From 33491bc4279481db8ae47213e34a6d695a0e8830 Mon Sep 17 00:00:00 2001 From: Michael Biebl Date: Sun, 6 Jul 2014 02:16:10 +0200 Subject: Imported Upstream version 0.9.10.0 --- src/Makefile.am | 604 +- src/Makefile.in | 1789 ++--- src/NetworkManagerUtils.c | 1151 ++- src/NetworkManagerUtils.h | 46 +- src/bluez-manager/Makefile.am | 44 - src/bluez-manager/Makefile.in | 786 -- src/bluez-manager/nm-bluez-common.h | 51 - src/bluez-manager/nm-bluez-device.c | 1223 --- src/bluez-manager/nm-bluez-device.h | 97 - src/bluez-manager/nm-bluez-manager.c | 438 -- src/bluez-manager/nm-bluez-manager.h | 69 - src/bluez-manager/nm-bluez4-adapter.c | 397 - src/bluez-manager/nm-bluez4-adapter.h | 69 - src/bluez-manager/nm-bluez4-manager.c | 386 - src/config/nm-config-device.c | 82 + src/config/nm-config-device.h | 47 + src/config/nm-config.c | 604 ++ src/config/nm-config.h | 78 + src/config/tests/Makefile.am | 30 + src/config/tests/Makefile.in | 864 +++ src/config/tests/NetworkManager.conf | 15 + src/config/tests/bad.conf | 1 + src/config/tests/conf.d/00-overrides.conf | 11 + src/config/tests/conf.d/10-more.conf | 11 + src/config/tests/conf.d/90-last.conf | 5 + src/config/tests/nm-test-device.c | 101 + src/config/tests/nm-test-device.h | 52 + src/config/tests/test-config.c | 305 + src/devices/adsl/Makefile.am | 63 + src/devices/adsl/Makefile.in | 847 +++ src/devices/adsl/exports.ver | 7 + src/devices/adsl/nm-adsl-enum-types.c | 12 + src/devices/adsl/nm-adsl-enum-types.h | 17 + src/devices/adsl/nm-atm-manager.c | 266 + src/devices/adsl/nm-atm-manager.h | 42 + src/devices/adsl/nm-device-adsl-glue.h | 73 + src/devices/adsl/nm-device-adsl.c | 640 ++ src/devices/adsl/nm-device-adsl.h | 56 + src/devices/bluetooth/Makefile.am | 74 + src/devices/bluetooth/Makefile.in | 864 +++ src/devices/bluetooth/exports.ver | 7 + src/devices/bluetooth/nm-bluez-common.h | 45 + src/devices/bluetooth/nm-bluez-device.c | 1212 +++ src/devices/bluetooth/nm-bluez-device.h | 98 + src/devices/bluetooth/nm-bluez-manager.c | 428 ++ src/devices/bluetooth/nm-bluez-manager.h | 44 + src/devices/bluetooth/nm-bluez4-adapter.c | 413 + src/devices/bluetooth/nm-bluez4-adapter.h | 69 + src/devices/bluetooth/nm-bluez4-manager.c | 361 + src/devices/bluetooth/nm-bluez4-manager.h | 62 + src/devices/bluetooth/nm-bluez5-manager.c | 421 ++ src/devices/bluetooth/nm-bluez5-manager.h | 62 + src/devices/bluetooth/nm-bt-enum-types.c | 32 + src/devices/bluetooth/nm-bt-enum-types.h | 19 + src/devices/bluetooth/nm-device-bt-glue.h | 73 + src/devices/bluetooth/nm-device-bt.c | 1278 ++++ src/devices/bluetooth/nm-device-bt.h | 74 + src/devices/nm-device-bond.c | 612 ++ src/devices/nm-device-bond.h | 62 + src/devices/nm-device-bridge.c | 588 ++ src/devices/nm-device-bridge.h | 64 + src/devices/nm-device-ethernet.c | 1770 +++++ src/devices/nm-device-ethernet.h | 65 + src/devices/nm-device-factory.c | 106 + src/devices/nm-device-factory.h | 136 + src/devices/nm-device-generic.c | 217 + src/devices/nm-device-generic.h | 61 + src/devices/nm-device-gre.c | 278 + src/devices/nm-device-gre.h | 63 + src/devices/nm-device-infiniband.c | 412 + src/devices/nm-device-infiniband.h | 61 + src/devices/nm-device-macvlan.c | 181 + src/devices/nm-device-macvlan.h | 56 + src/devices/nm-device-private.h | 102 + src/devices/nm-device-team.c | 894 +++ src/devices/nm-device-team.h | 64 + src/devices/nm-device-tun.c | 294 + src/devices/nm-device-tun.h | 59 + src/devices/nm-device-veth.c | 171 + src/devices/nm-device-veth.h | 54 + src/devices/nm-device-vlan.c | 659 ++ src/devices/nm-device-vlan.h | 65 + src/devices/nm-device-vxlan.c | 372 + src/devices/nm-device-vxlan.h | 69 + src/devices/nm-device.c | 7966 ++++++++++++++++++++ src/devices/nm-device.h | 363 + src/devices/wifi/Makefile.am | 78 + src/devices/wifi/Makefile.in | 983 +++ src/devices/wifi/exports.ver | 7 + src/devices/wifi/nm-device-olpc-mesh-glue.h | 73 + src/devices/wifi/nm-device-olpc-mesh.c | 585 ++ src/devices/wifi/nm-device-olpc-mesh.h | 82 + src/devices/wifi/nm-device-wifi-glue.h | 167 + src/devices/wifi/nm-device-wifi.c | 3502 +++++++++ src/devices/wifi/nm-device-wifi.h | 94 + src/devices/wifi/nm-wifi-ap-utils.c | 721 ++ src/devices/wifi/nm-wifi-ap-utils.h | 45 + src/devices/wifi/nm-wifi-ap.c | 1293 ++++ src/devices/wifi/nm-wifi-ap.h | 121 + src/devices/wifi/nm-wifi-enum-types.c | 58 + src/devices/wifi/nm-wifi-enum-types.h | 21 + src/devices/wifi/nm-wifi-factory.c | 89 + src/devices/wifi/tests/Makefile.am | 28 + src/devices/wifi/tests/Makefile.in | 891 +++ src/devices/wifi/tests/test-wifi-ap-utils.c | 1545 ++++ src/devices/wimax/Makefile.am | 63 + src/devices/wimax/Makefile.in | 850 +++ src/devices/wimax/exports.ver | 7 + src/devices/wimax/iwmxsdk.c | 1517 ++++ src/devices/wimax/iwmxsdk.h | 111 + src/devices/wimax/nm-device-wimax.c | 1445 ++++ src/devices/wimax/nm-device-wimax.h | 73 + src/devices/wimax/nm-wimax-factory.c | 89 + src/devices/wimax/nm-wimax-nsp.c | 242 + src/devices/wimax/nm-wimax-nsp.h | 63 + src/devices/wimax/nm-wimax-types.h | 31 + src/devices/wimax/nm-wimax-util.c | 82 + src/devices/wimax/nm-wimax-util.h | 38 + src/devices/wwan/Makefile.am | 95 + src/devices/wwan/Makefile.in | 886 +++ src/devices/wwan/README | 45 + src/devices/wwan/exports.ver | 7 + src/devices/wwan/nm-device-modem-glue.h | 73 + src/devices/wwan/nm-device-modem.c | 646 ++ src/devices/wwan/nm-device-modem.h | 54 + src/devices/wwan/nm-modem-broadband.c | 987 +++ src/devices/wwan/nm-modem-broadband.h | 58 + src/devices/wwan/nm-modem-enum-types.c | 64 + src/devices/wwan/nm-modem-enum-types.h | 21 + src/devices/wwan/nm-modem-manager.c | 757 ++ src/devices/wwan/nm-modem-manager.h | 49 + src/devices/wwan/nm-modem-old-types.h | 70 + src/devices/wwan/nm-modem-old.c | 1139 +++ src/devices/wwan/nm-modem-old.h | 53 + src/devices/wwan/nm-modem.c | 1119 +++ src/devices/wwan/nm-modem.h | 217 + src/devices/wwan/nm-wwan-factory.c | 136 + src/devices/wwan/nm-wwan-factory.h | 37 + src/devices/wwan/wwan-exports.ver | 28 + src/dhcp-manager/Makefile.am | 76 +- src/dhcp-manager/Makefile.in | 505 +- src/dhcp-manager/nm-dhcp-client.c | 424 +- src/dhcp-manager/nm-dhcp-client.h | 21 +- src/dhcp-manager/nm-dhcp-dhclient-utils.c | 313 +- src/dhcp-manager/nm-dhcp-dhclient-utils.h | 10 +- src/dhcp-manager/nm-dhcp-dhclient.c | 284 +- src/dhcp-manager/nm-dhcp-dhclient.h | 4 +- src/dhcp-manager/nm-dhcp-dhcpcd.c | 31 +- src/dhcp-manager/nm-dhcp-dhcpcd.h | 2 - src/dhcp-manager/nm-dhcp-helper.c | 345 + src/dhcp-manager/nm-dhcp-helper.conf | 13 + src/dhcp-manager/nm-dhcp-manager.c | 380 +- src/dhcp-manager/nm-dhcp-manager.h | 24 +- src/dhcp-manager/tests/Makefile.am | 29 +- src/dhcp-manager/tests/Makefile.in | 214 +- src/dhcp-manager/tests/leases/basic.leases | 31 + src/dhcp-manager/tests/leases/malformed1.leases | 15 + src/dhcp-manager/tests/leases/malformed2.leases | 15 + src/dhcp-manager/tests/leases/malformed3.leases | 15 + src/dhcp-manager/tests/test-dhcp-dhclient.c | 237 +- src/dns-manager/Makefile.am | 35 - src/dns-manager/Makefile.in | 775 -- src/dns-manager/nm-dns-dnsmasq.c | 73 +- src/dns-manager/nm-dns-dnsmasq.h | 2 +- src/dns-manager/nm-dns-manager.c | 325 +- src/dns-manager/nm-dns-manager.h | 28 +- src/dns-manager/nm-dns-plugin.h | 1 - src/dns-manager/nm-dns-unbound.c | 79 + src/dns-manager/nm-dns-unbound.h | 44 + src/dns-manager/nm-dns-utils.c | 13 +- src/dnsmasq-manager/Makefile.am | 19 - src/dnsmasq-manager/Makefile.in | 733 -- src/dnsmasq-manager/nm-dnsmasq-manager.c | 59 +- src/dnsmasq-manager/nm-dnsmasq-utils.c | 77 + src/dnsmasq-manager/nm-dnsmasq-utils.h | 32 + src/dnsmasq-manager/tests/Makefile.am | 23 + src/dnsmasq-manager/tests/Makefile.in | 856 +++ src/dnsmasq-manager/tests/test-dnsmasq-utils.c | 115 + src/firewall-manager/Makefile.am | 21 - src/firewall-manager/Makefile.in | 733 -- src/firewall-manager/nm-firewall-manager.c | 80 +- src/generated/Makefile.am | 91 - src/generated/Makefile.in | 788 -- src/generated/nm-enum-types.c | 1036 --- src/generated/nm-enum-types.h | 99 - src/generated/nm-marshal.c | 744 -- src/generated/nm-marshal.h | 159 - src/ip6-manager/Makefile.am | 27 - src/ip6-manager/Makefile.in | 740 -- src/ip6-manager/nm-ip6-manager.c | 1747 ----- src/ip6-manager/nm-ip6-manager.h | 88 - src/logging/Makefile.am | 14 - src/logging/Makefile.in | 723 -- src/logging/nm-logging.c | 358 +- src/logging/nm-logging.h | 101 +- src/main.c | 338 +- src/modem-manager/Makefile.am | 43 - src/modem-manager/Makefile.in | 789 -- src/modem-manager/README | 45 - src/modem-manager/nm-modem-broadband.c | 1013 --- src/modem-manager/nm-modem-broadband.h | 69 - src/modem-manager/nm-modem-cdma.c | 358 - src/modem-manager/nm-modem-cdma.h | 59 - src/modem-manager/nm-modem-generic.c | 445 -- src/modem-manager/nm-modem-generic.h | 69 - src/modem-manager/nm-modem-gsm.c | 644 -- src/modem-manager/nm-modem-gsm.h | 59 - src/modem-manager/nm-modem-manager.c | 859 --- src/modem-manager/nm-modem-manager.h | 58 - src/modem-manager/nm-modem-types.h | 106 - src/modem-manager/nm-modem.c | 953 --- src/modem-manager/nm-modem.h | 173 - src/nm-access-point-glue.h | 73 + src/nm-activation-request.c | 266 +- src/nm-activation-request.h | 14 +- src/nm-active-connection-glue.h | 73 + src/nm-active-connection.c | 668 +- src/nm-active-connection.h | 62 +- src/nm-agent-manager-glue.h | 170 + src/nm-auth-subject.c | 216 + src/nm-auth-subject.h | 70 + src/nm-call-store.c | 209 - src/nm-call-store.h | 47 - src/nm-config.c | 294 - src/nm-config.h | 59 - src/nm-connection-provider.c | 54 +- src/nm-connection-provider.h | 33 +- src/nm-connectivity.c | 15 +- src/nm-connectivity.h | 4 +- src/nm-dbus-manager.c | 652 +- src/nm-dbus-manager.h | 54 +- src/nm-dcb.c | 426 ++ src/nm-dcb.h | 100 + src/nm-device-adsl.c | 851 --- src/nm-device-adsl.h | 66 - src/nm-device-bond-glue.h | 73 + src/nm-device-bond.c | 526 -- src/nm-device-bond.h | 66 - src/nm-device-bridge-glue.h | 73 + src/nm-device-bridge.c | 579 -- src/nm-device-bridge.h | 66 - src/nm-device-bt.c | 1311 ---- src/nm-device-bt.h | 79 - src/nm-device-ethernet-glue.h | 73 + src/nm-device-ethernet.c | 1675 ---- src/nm-device-ethernet.h | 71 - src/nm-device-factory.h | 91 - src/nm-device-generic-glue.h | 73 + src/nm-device-glue.h | 78 + src/nm-device-gre-glue.h | 73 + src/nm-device-infiniband-glue.h | 73 + src/nm-device-infiniband.c | 509 -- src/nm-device-infiniband.h | 66 - src/nm-device-macvlan-glue.h | 73 + src/nm-device-modem.c | 544 -- src/nm-device-modem.h | 60 - src/nm-device-olpc-mesh.c | 773 -- src/nm-device-olpc-mesh.h | 88 - src/nm-device-private.h | 92 - src/nm-device-team-glue.h | 73 + src/nm-device-tun-glue.h | 73 + src/nm-device-veth-glue.h | 73 + src/nm-device-vlan-glue.h | 73 + src/nm-device-vlan.c | 777 -- src/nm-device-vlan.h | 67 - src/nm-device-vxlan-glue.h | 73 + src/nm-device-wifi.c | 3903 ---------- src/nm-device-wifi.h | 104 - src/nm-device-wired.c | 564 -- src/nm-device-wired.h | 57 - src/nm-device.c | 5706 -------------- src/nm-device.h | 311 - src/nm-dhcp4-config-glue.h | 73 + src/nm-dhcp4-config.c | 26 +- src/nm-dhcp4-config.h | 2 - src/nm-dhcp6-config-glue.h | 73 + src/nm-dhcp6-config.c | 26 +- src/nm-dhcp6-config.h | 2 - src/nm-dispatcher.c | 603 +- src/nm-dispatcher.h | 39 +- src/nm-enum-types.c | 1042 +++ src/nm-enum-types.h | 99 + src/nm-hostname-provider.c | 54 - src/nm-hostname-provider.h | 44 - src/nm-ip4-config-glue.h | 73 + src/nm-ip4-config.c | 1952 +++-- src/nm-ip4-config.h | 203 +- src/nm-ip6-config-glue.h | 73 + src/nm-ip6-config.c | 1772 +++-- src/nm-ip6-config.h | 167 +- src/nm-manager-auth.c | 339 +- src/nm-manager-auth.h | 26 +- src/nm-manager-glue.h | 416 + src/nm-manager.c | 4813 ++++++------ src/nm-manager.h | 22 +- src/nm-netlink-compat.c | 85 - src/nm-netlink-compat.h | 34 - src/nm-netlink-monitor.c | 943 --- src/nm-netlink-monitor.h | 102 - src/nm-netlink-utils.c | 465 -- src/nm-netlink-utils.h | 83 - src/nm-policy-hostname.c | 264 - src/nm-policy-hostname.h | 51 - src/nm-policy-hosts.c | 95 - src/nm-policy-hosts.h | 32 - src/nm-policy.c | 1232 ++- src/nm-ppp-manager-glue.h | 174 + src/nm-properties-changed-signal.c | 215 +- src/nm-properties-changed-signal.h | 7 +- src/nm-rfkill-manager.c | 422 ++ src/nm-rfkill-manager.h | 72 + src/nm-rfkill.h | 45 - src/nm-session-monitor-ck.c | 6 +- src/nm-session-monitor-null.c | 7 +- src/nm-session-monitor-systemd.c | 29 +- src/nm-settings-connection-glue.h | 171 + src/nm-settings-glue.h | 219 + src/nm-sleep-monitor-systemd.c | 146 +- src/nm-sleep-monitor-upower.c | 6 +- src/nm-system.c | 2603 ------- src/nm-system.h | 143 - src/nm-udev-manager.c | 674 -- src/nm-udev-manager.h | 74 - src/nm-vpn-connection-glue.h | 73 + src/nm-wifi-ap-utils.c | 728 -- src/nm-wifi-ap-utils.h | 45 - src/nm-wifi-ap.c | 1319 ---- src/nm-wifi-ap.h | 123 - src/org.freedesktop.NetworkManager.conf | 114 +- src/platform/Makefile.am | 1 + src/platform/Makefile.in | 753 ++ src/platform/nm-fake-platform.c | 1352 ++++ src/platform/nm-fake-platform.h | 49 + src/platform/nm-linux-platform.c | 4180 ++++++++++ src/platform/nm-linux-platform.h | 49 + src/platform/nm-platform.c | 2618 +++++++ src/platform/nm-platform.h | 634 ++ src/platform/tests/Makefile.am | 116 + src/platform/tests/Makefile.in | 1702 +++++ src/platform/tests/dump.c | 136 + src/platform/tests/monitor.c | 30 + src/platform/tests/platform.c | 897 +++ src/platform/tests/test-address.c | 265 + src/platform/tests/test-cleanup.c | 95 + src/platform/tests/test-common.c | 174 + src/platform/tests/test-common.h | 42 + src/platform/tests/test-link.c | 557 ++ src/platform/tests/test-route.c | 255 + src/platform/wifi/wifi-utils-nl80211.c | 971 +++ src/platform/wifi/wifi-utils-nl80211.h | 30 + src/platform/wifi/wifi-utils-private.h | 77 + src/platform/wifi/wifi-utils-wext.c | 671 ++ src/platform/wifi/wifi-utils-wext.h | 30 + src/platform/wifi/wifi-utils.c | 225 + src/platform/wifi/wifi-utils.h | 76 + src/posix-signals/Makefile.am | 14 - src/posix-signals/Makefile.in | 724 -- src/ppp-manager/Makefile.am | 46 +- src/ppp-manager/Makefile.in | 134 +- src/ppp-manager/nm-ppp-manager.c | 296 +- src/ppp-manager/nm-pppd-plugin.c | 24 +- src/rdisc/Makefile.am | 1 + src/rdisc/Makefile.in | 753 ++ src/rdisc/nm-fake-rdisc.c | 134 + src/rdisc/nm-fake-rdisc.h | 49 + src/rdisc/nm-lndp-rdisc.c | 700 ++ src/rdisc/nm-lndp-rdisc.h | 49 + src/rdisc/nm-rdisc.c | 191 + src/rdisc/nm-rdisc.h | 139 + src/rdisc/tests/Makefile.am | 36 + src/rdisc/tests/Makefile.in | 755 ++ src/rdisc/tests/rdisc.c | 80 + src/settings/Makefile.am | 86 - src/settings/Makefile.in | 1009 --- src/settings/nm-agent-manager.c | 1022 +-- src/settings/nm-agent-manager.h | 19 +- src/settings/nm-default-wired-connection.c | 197 - src/settings/nm-default-wired-connection.h | 56 - src/settings/nm-inotify-helper.c | 15 +- src/settings/nm-secret-agent.c | 141 +- src/settings/nm-secret-agent.h | 25 +- src/settings/nm-settings-connection.c | 793 +- src/settings/nm-settings-connection.h | 38 +- src/settings/nm-settings-error.h | 1 - src/settings/nm-settings.c | 1223 ++- src/settings/nm-settings.h | 28 +- src/settings/nm-system-config-interface.c | 57 +- src/settings/nm-system-config-interface.h | 62 +- src/settings/plugins/Makefile.am | 2 + src/settings/plugins/Makefile.in | 23 +- src/settings/plugins/example/Makefile.am | 15 +- src/settings/plugins/example/Makefile.in | 89 +- .../plugins/example/nm-example-connection.c | 8 +- src/settings/plugins/example/plugin.c | 147 +- src/settings/plugins/example/writer.c | 2 +- src/settings/plugins/ifcfg-rh/Makefile.am | 17 +- src/settings/plugins/ifcfg-rh/Makefile.in | 46 +- src/settings/plugins/ifcfg-rh/common.h | 30 +- .../plugins/ifcfg-rh/nm-ifcfg-connection.c | 286 +- .../plugins/ifcfg-rh/nm-ifcfg-connection.h | 11 +- src/settings/plugins/ifcfg-rh/plugin.c | 578 +- src/settings/plugins/ifcfg-rh/reader.c | 2169 ++++-- src/settings/plugins/ifcfg-rh/reader.h | 12 +- src/settings/plugins/ifcfg-rh/shvar.c | 612 +- src/settings/plugins/ifcfg-rh/shvar.h | 63 +- src/settings/plugins/ifcfg-rh/tests/Makefile.am | 56 +- src/settings/plugins/ifcfg-rh/tests/Makefile.in | 305 +- .../ifcfg-rh/tests/network-scripts/Makefile.am | 43 +- .../ifcfg-rh/tests/network-scripts/Makefile.in | 70 +- .../ifcfg-rh/tests/network-scripts/ifcfg-aliasem0 | 12 + .../tests/network-scripts/ifcfg-aliasem0:1 | 2 + .../tests/network-scripts/ifcfg-aliasem0:2 | 2 + .../tests/network-scripts/ifcfg-aliasem0:99 | 2 + .../ifcfg-rh/tests/network-scripts/ifcfg-aliasem1 | 12 + .../tests/network-scripts/ifcfg-aliasem1:1 | 2 + .../ifcfg-rh/tests/network-scripts/ifcfg-aliasem2 | 12 + .../tests/network-scripts/ifcfg-aliasem2:1 | 3 + .../tests/network-scripts/ifcfg-test-bridge-main | 1 + .../ifcfg-rh/tests/network-scripts/ifcfg-test-dcb | 43 + .../network-scripts/ifcfg-test-dcb-bad-booleans | 12 + .../network-scripts/ifcfg-test-dcb-bad-percent | 12 + .../tests/network-scripts/ifcfg-test-dcb-bad-uints | 12 + .../ifcfg-test-dcb-default-app-priorities | 7 + .../network-scripts/ifcfg-test-dcb-pgpct-not-100 | 12 + .../network-scripts/ifcfg-test-dcb-short-booleans | 12 + .../network-scripts/ifcfg-test-dcb-short-percent | 12 + .../network-scripts/ifcfg-test-dcb-short-uints | 12 + .../tests/network-scripts/ifcfg-test-fcoe-fabric | 6 + .../tests/network-scripts/ifcfg-test-fcoe-vn2vn | 6 + .../ifcfg-test-nm-controlled-unrecognized | 6 + .../ifcfg-rh/tests/network-scripts/ifcfg-test-noip | 3 + .../tests/network-scripts/ifcfg-test-team-master | 6 + .../tests/network-scripts/ifcfg-test-team-port | 5 + .../ifcfg-test-team-port-empty-config | 4 + .../tests/network-scripts/ifcfg-test-unrecognized | 7 + .../tests/network-scripts/ifcfg-test-wifi-hidden | 10 + .../ifcfg-test-wired-802-1X-subj-matches | 17 + .../ifcfg-test-wired-802-1x-ttls-eapgtc | 13 + .../network-scripts/ifcfg-test-wired-dhcp-plus-ip | 26 + .../ifcfg-test-wired-dhcp-send-hostname | 12 + .../route-test-static-routes-legacy | 1 + .../network-scripts/route6-test-wired-ipv6-manual | 3 + .../plugins/ifcfg-rh/tests/test-ifcfg-rh-utils.c | 7 +- .../plugins/ifcfg-rh/tests/test-ifcfg-rh.c | 6461 +++++++++------- src/settings/plugins/ifcfg-rh/utils.c | 144 +- src/settings/plugins/ifcfg-rh/utils.h | 7 +- src/settings/plugins/ifcfg-rh/writer.c | 729 +- src/settings/plugins/ifcfg-rh/writer.h | 3 + src/settings/plugins/ifcfg-suse/Makefile.am | 19 +- src/settings/plugins/ifcfg-suse/Makefile.in | 49 +- src/settings/plugins/ifcfg-suse/plugin.c | 2 +- src/settings/plugins/ifnet/Makefile.am | 28 +- src/settings/plugins/ifnet/Makefile.in | 76 +- src/settings/plugins/ifnet/connection_parser.c | 366 +- src/settings/plugins/ifnet/connection_parser.h | 13 +- src/settings/plugins/ifnet/errors.c | 35 + src/settings/plugins/ifnet/errors.h | 30 + src/settings/plugins/ifnet/net_parser.c | 95 +- src/settings/plugins/ifnet/net_parser.h | 1 - src/settings/plugins/ifnet/net_utils.c | 165 +- src/settings/plugins/ifnet/net_utils.h | 4 - src/settings/plugins/ifnet/nm-ifnet-connection.c | 118 +- src/settings/plugins/ifnet/nm-ifnet-connection.h | 6 +- src/settings/plugins/ifnet/plugin.c | 350 +- src/settings/plugins/ifnet/plugin.h | 2 - src/settings/plugins/ifnet/tests/Makefile.am | 32 +- src/settings/plugins/ifnet/tests/Makefile.in | 150 +- src/settings/plugins/ifnet/tests/net.all | 4 +- src/settings/plugins/ifnet/tests/test_all.c | 61 +- src/settings/plugins/ifnet/wpa_parser.c | 28 +- src/settings/plugins/ifupdown/Makefile.am | 13 +- src/settings/plugins/ifupdown/Makefile.in | 58 +- src/settings/plugins/ifupdown/interface_parser.c | 96 +- .../plugins/ifupdown/nm-ifupdown-connection.c | 17 +- src/settings/plugins/ifupdown/parser.c | 125 +- src/settings/plugins/ifupdown/plugin.c | 131 +- src/settings/plugins/ifupdown/tests/Makefile.am | 22 +- src/settings/plugins/ifupdown/tests/Makefile.in | 198 +- .../plugins/ifupdown/tests/test-ifupdown.c | 138 +- .../plugins/ifupdown/tests/test20-source-stanza | 1 + .../ifupdown/tests/test20-source-stanza.eth0 | 2 + .../ifupdown/tests/test20-source-stanza.eth1 | 2 + src/settings/plugins/keyfile/Makefile.am | 8 + src/settings/plugins/keyfile/Makefile.in | 29 +- src/settings/plugins/keyfile/common.h | 4 +- .../plugins/keyfile/nm-keyfile-connection.c | 38 +- .../plugins/keyfile/nm-keyfile-connection.h | 4 +- src/settings/plugins/keyfile/plugin.c | 603 +- src/settings/plugins/keyfile/plugin.h | 2 +- src/settings/plugins/keyfile/reader.c | 407 +- src/settings/plugins/keyfile/tests/Makefile.am | 28 +- src/settings/plugins/keyfile/tests/Makefile.in | 237 +- .../plugins/keyfile/tests/keyfiles/Makefile.am | 4 + .../plugins/keyfile/tests/keyfiles/Makefile.in | 25 +- .../keyfile/tests/keyfiles/Test_MAC_IB_Old_Format | 13 + .../keyfile/tests/keyfiles/Test_MAC_Old_Format | 10 + .../tests/keyfiles/Test_New_Wired_Group_Name | 13 + .../tests/keyfiles/Test_New_Wireless_Group_Names | 16 + .../keyfile/tests/keyfiles/Test_Wired_Connection | 22 + src/settings/plugins/keyfile/tests/test-keyfile.c | 545 +- src/settings/plugins/keyfile/utils.c | 176 + src/settings/plugins/keyfile/utils.h | 49 + src/settings/plugins/keyfile/writer.c | 337 +- src/settings/tests/Makefile.am | 13 +- src/settings/tests/Makefile.in | 188 +- src/settings/tests/test-wired-defname.c | 26 +- src/supplicant-manager/Makefile.am | 34 - src/supplicant-manager/Makefile.in | 889 --- src/supplicant-manager/nm-call-store.c | 111 + src/supplicant-manager/nm-call-store.h | 41 + src/supplicant-manager/nm-supplicant-config.c | 127 +- src/supplicant-manager/nm-supplicant-config.h | 4 +- src/supplicant-manager/nm-supplicant-interface.c | 507 +- src/supplicant-manager/nm-supplicant-interface.h | 2 +- src/supplicant-manager/nm-supplicant-manager.c | 3 +- .../nm-supplicant-settings-verify.c | 3 +- src/supplicant-manager/tests/Makefile.am | 19 +- src/supplicant-manager/tests/Makefile.in | 209 +- .../tests/test-supplicant-config.c | 117 +- src/tests/Makefile.am | 74 +- src/tests/Makefile.in | 342 +- src/tests/test-dcb.c | 357 + src/tests/test-dhcp-options.c | 296 +- src/tests/test-general.c | 614 ++ src/tests/test-ip4-config.c | 355 + src/tests/test-ip6-config.c | 338 + src/tests/test-policy-hosts.c | 176 - src/tests/test-resolvconf-capture.c | 226 + src/tests/test-wifi-ap-utils.c | 1440 ---- src/vpn-manager/Makefile.am | 49 - src/vpn-manager/Makefile.in | 784 -- src/vpn-manager/nm-vpn-connection.c | 1383 ++-- src/vpn-manager/nm-vpn-connection.h | 15 +- src/vpn-manager/nm-vpn-manager.c | 202 +- src/vpn-manager/nm-vpn-manager.h | 10 +- src/vpn-manager/nm-vpn-service.c | 390 +- src/vpn-manager/nm-vpn-service.h | 18 +- src/wifi/Makefile.am | 29 - src/wifi/Makefile.in | 755 -- src/wifi/wifi-utils-nl80211.c | 897 --- src/wifi/wifi-utils-nl80211.h | 30 - src/wifi/wifi-utils-private.h | 74 - src/wifi/wifi-utils-wext.c | 674 -- src/wifi/wifi-utils-wext.h | 30 - src/wifi/wifi-utils.c | 215 - src/wifi/wifi-utils.h | 72 - src/wimax/Makefile.am | 46 - src/wimax/Makefile.in | 860 --- src/wimax/iwmxsdk.c | 1518 ---- src/wimax/iwmxsdk.h | 111 - src/wimax/nm-device-wimax.c | 1589 ---- src/wimax/nm-device-wimax.h | 87 - src/wimax/nm-wimax-factory.c | 58 - src/wimax/nm-wimax-nsp.c | 265 - src/wimax/nm-wimax-nsp.h | 63 - src/wimax/nm-wimax-types.h | 31 - src/wimax/nm-wimax-util.c | 82 - src/wimax/nm-wimax-util.h | 38 - 558 files changed, 102794 insertions(+), 76798 deletions(-) delete mode 100644 src/bluez-manager/Makefile.am delete mode 100644 src/bluez-manager/Makefile.in delete mode 100644 src/bluez-manager/nm-bluez-common.h delete mode 100644 src/bluez-manager/nm-bluez-device.c delete mode 100644 src/bluez-manager/nm-bluez-device.h delete mode 100644 src/bluez-manager/nm-bluez-manager.c delete mode 100644 src/bluez-manager/nm-bluez-manager.h delete mode 100644 src/bluez-manager/nm-bluez4-adapter.c delete mode 100644 src/bluez-manager/nm-bluez4-adapter.h delete mode 100644 src/bluez-manager/nm-bluez4-manager.c create mode 100644 src/config/nm-config-device.c create mode 100644 src/config/nm-config-device.h create mode 100644 src/config/nm-config.c create mode 100644 src/config/nm-config.h create mode 100644 src/config/tests/Makefile.am create mode 100644 src/config/tests/Makefile.in create mode 100644 src/config/tests/NetworkManager.conf create mode 100644 src/config/tests/bad.conf create mode 100644 src/config/tests/conf.d/00-overrides.conf create mode 100644 src/config/tests/conf.d/10-more.conf create mode 100644 src/config/tests/conf.d/90-last.conf create mode 100644 src/config/tests/nm-test-device.c create mode 100644 src/config/tests/nm-test-device.h create mode 100644 src/config/tests/test-config.c create mode 100644 src/devices/adsl/Makefile.am create mode 100644 src/devices/adsl/Makefile.in create mode 100644 src/devices/adsl/exports.ver create mode 100644 src/devices/adsl/nm-adsl-enum-types.c create mode 100644 src/devices/adsl/nm-adsl-enum-types.h create mode 100644 src/devices/adsl/nm-atm-manager.c create mode 100644 src/devices/adsl/nm-atm-manager.h create mode 100644 src/devices/adsl/nm-device-adsl-glue.h create mode 100644 src/devices/adsl/nm-device-adsl.c create mode 100644 src/devices/adsl/nm-device-adsl.h create mode 100644 src/devices/bluetooth/Makefile.am create mode 100644 src/devices/bluetooth/Makefile.in create mode 100644 src/devices/bluetooth/exports.ver create mode 100644 src/devices/bluetooth/nm-bluez-common.h create mode 100644 src/devices/bluetooth/nm-bluez-device.c create mode 100644 src/devices/bluetooth/nm-bluez-device.h create mode 100644 src/devices/bluetooth/nm-bluez-manager.c create mode 100644 src/devices/bluetooth/nm-bluez-manager.h create mode 100644 src/devices/bluetooth/nm-bluez4-adapter.c create mode 100644 src/devices/bluetooth/nm-bluez4-adapter.h create mode 100644 src/devices/bluetooth/nm-bluez4-manager.c create mode 100644 src/devices/bluetooth/nm-bluez4-manager.h create mode 100644 src/devices/bluetooth/nm-bluez5-manager.c create mode 100644 src/devices/bluetooth/nm-bluez5-manager.h create mode 100644 src/devices/bluetooth/nm-bt-enum-types.c create mode 100644 src/devices/bluetooth/nm-bt-enum-types.h create mode 100644 src/devices/bluetooth/nm-device-bt-glue.h create mode 100644 src/devices/bluetooth/nm-device-bt.c create mode 100644 src/devices/bluetooth/nm-device-bt.h create mode 100644 src/devices/nm-device-bond.c create mode 100644 src/devices/nm-device-bond.h create mode 100644 src/devices/nm-device-bridge.c create mode 100644 src/devices/nm-device-bridge.h create mode 100644 src/devices/nm-device-ethernet.c create mode 100644 src/devices/nm-device-ethernet.h create mode 100644 src/devices/nm-device-factory.c create mode 100644 src/devices/nm-device-factory.h create mode 100644 src/devices/nm-device-generic.c create mode 100644 src/devices/nm-device-generic.h create mode 100644 src/devices/nm-device-gre.c create mode 100644 src/devices/nm-device-gre.h create mode 100644 src/devices/nm-device-infiniband.c create mode 100644 src/devices/nm-device-infiniband.h create mode 100644 src/devices/nm-device-macvlan.c create mode 100644 src/devices/nm-device-macvlan.h create mode 100644 src/devices/nm-device-private.h create mode 100644 src/devices/nm-device-team.c create mode 100644 src/devices/nm-device-team.h create mode 100644 src/devices/nm-device-tun.c create mode 100644 src/devices/nm-device-tun.h create mode 100644 src/devices/nm-device-veth.c create mode 100644 src/devices/nm-device-veth.h create mode 100644 src/devices/nm-device-vlan.c create mode 100644 src/devices/nm-device-vlan.h create mode 100644 src/devices/nm-device-vxlan.c create mode 100644 src/devices/nm-device-vxlan.h create mode 100644 src/devices/nm-device.c create mode 100644 src/devices/nm-device.h create mode 100644 src/devices/wifi/Makefile.am create mode 100644 src/devices/wifi/Makefile.in create mode 100644 src/devices/wifi/exports.ver create mode 100644 src/devices/wifi/nm-device-olpc-mesh-glue.h create mode 100644 src/devices/wifi/nm-device-olpc-mesh.c create mode 100644 src/devices/wifi/nm-device-olpc-mesh.h create mode 100644 src/devices/wifi/nm-device-wifi-glue.h create mode 100644 src/devices/wifi/nm-device-wifi.c create mode 100644 src/devices/wifi/nm-device-wifi.h create mode 100644 src/devices/wifi/nm-wifi-ap-utils.c create mode 100644 src/devices/wifi/nm-wifi-ap-utils.h create mode 100644 src/devices/wifi/nm-wifi-ap.c create mode 100644 src/devices/wifi/nm-wifi-ap.h create mode 100644 src/devices/wifi/nm-wifi-enum-types.c create mode 100644 src/devices/wifi/nm-wifi-enum-types.h create mode 100644 src/devices/wifi/nm-wifi-factory.c create mode 100644 src/devices/wifi/tests/Makefile.am create mode 100644 src/devices/wifi/tests/Makefile.in create mode 100644 src/devices/wifi/tests/test-wifi-ap-utils.c create mode 100644 src/devices/wimax/Makefile.am create mode 100644 src/devices/wimax/Makefile.in create mode 100644 src/devices/wimax/exports.ver create mode 100644 src/devices/wimax/iwmxsdk.c create mode 100644 src/devices/wimax/iwmxsdk.h create mode 100644 src/devices/wimax/nm-device-wimax.c create mode 100644 src/devices/wimax/nm-device-wimax.h create mode 100644 src/devices/wimax/nm-wimax-factory.c create mode 100644 src/devices/wimax/nm-wimax-nsp.c create mode 100644 src/devices/wimax/nm-wimax-nsp.h create mode 100644 src/devices/wimax/nm-wimax-types.h create mode 100644 src/devices/wimax/nm-wimax-util.c create mode 100644 src/devices/wimax/nm-wimax-util.h create mode 100644 src/devices/wwan/Makefile.am create mode 100644 src/devices/wwan/Makefile.in create mode 100644 src/devices/wwan/README create mode 100644 src/devices/wwan/exports.ver create mode 100644 src/devices/wwan/nm-device-modem-glue.h create mode 100644 src/devices/wwan/nm-device-modem.c create mode 100644 src/devices/wwan/nm-device-modem.h create mode 100644 src/devices/wwan/nm-modem-broadband.c create mode 100644 src/devices/wwan/nm-modem-broadband.h create mode 100644 src/devices/wwan/nm-modem-enum-types.c create mode 100644 src/devices/wwan/nm-modem-enum-types.h create mode 100644 src/devices/wwan/nm-modem-manager.c create mode 100644 src/devices/wwan/nm-modem-manager.h create mode 100644 src/devices/wwan/nm-modem-old-types.h create mode 100644 src/devices/wwan/nm-modem-old.c create mode 100644 src/devices/wwan/nm-modem-old.h create mode 100644 src/devices/wwan/nm-modem.c create mode 100644 src/devices/wwan/nm-modem.h create mode 100644 src/devices/wwan/nm-wwan-factory.c create mode 100644 src/devices/wwan/nm-wwan-factory.h create mode 100644 src/devices/wwan/wwan-exports.ver create mode 100644 src/dhcp-manager/nm-dhcp-helper.c create mode 100644 src/dhcp-manager/nm-dhcp-helper.conf create mode 100644 src/dhcp-manager/tests/leases/basic.leases create mode 100644 src/dhcp-manager/tests/leases/malformed1.leases create mode 100644 src/dhcp-manager/tests/leases/malformed2.leases create mode 100644 src/dhcp-manager/tests/leases/malformed3.leases delete mode 100644 src/dns-manager/Makefile.am delete mode 100644 src/dns-manager/Makefile.in create mode 100644 src/dns-manager/nm-dns-unbound.c create mode 100644 src/dns-manager/nm-dns-unbound.h delete mode 100644 src/dnsmasq-manager/Makefile.am delete mode 100644 src/dnsmasq-manager/Makefile.in create mode 100644 src/dnsmasq-manager/nm-dnsmasq-utils.c create mode 100644 src/dnsmasq-manager/nm-dnsmasq-utils.h create mode 100644 src/dnsmasq-manager/tests/Makefile.am create mode 100644 src/dnsmasq-manager/tests/Makefile.in create mode 100644 src/dnsmasq-manager/tests/test-dnsmasq-utils.c delete mode 100644 src/firewall-manager/Makefile.am delete mode 100644 src/firewall-manager/Makefile.in delete mode 100644 src/generated/Makefile.am delete mode 100644 src/generated/Makefile.in delete mode 100644 src/generated/nm-enum-types.c delete mode 100644 src/generated/nm-enum-types.h delete mode 100644 src/generated/nm-marshal.c delete mode 100644 src/generated/nm-marshal.h delete mode 100644 src/ip6-manager/Makefile.am delete mode 100644 src/ip6-manager/Makefile.in delete mode 100644 src/ip6-manager/nm-ip6-manager.c delete mode 100644 src/ip6-manager/nm-ip6-manager.h delete mode 100644 src/logging/Makefile.am delete mode 100644 src/logging/Makefile.in delete mode 100644 src/modem-manager/Makefile.am delete mode 100644 src/modem-manager/Makefile.in delete mode 100644 src/modem-manager/README delete mode 100644 src/modem-manager/nm-modem-broadband.c delete mode 100644 src/modem-manager/nm-modem-broadband.h delete mode 100644 src/modem-manager/nm-modem-cdma.c delete mode 100644 src/modem-manager/nm-modem-cdma.h delete mode 100644 src/modem-manager/nm-modem-generic.c delete mode 100644 src/modem-manager/nm-modem-generic.h delete mode 100644 src/modem-manager/nm-modem-gsm.c delete mode 100644 src/modem-manager/nm-modem-gsm.h delete mode 100644 src/modem-manager/nm-modem-manager.c delete mode 100644 src/modem-manager/nm-modem-manager.h delete mode 100644 src/modem-manager/nm-modem-types.h delete mode 100644 src/modem-manager/nm-modem.c delete mode 100644 src/modem-manager/nm-modem.h create mode 100644 src/nm-access-point-glue.h create mode 100644 src/nm-active-connection-glue.h create mode 100644 src/nm-agent-manager-glue.h create mode 100644 src/nm-auth-subject.c create mode 100644 src/nm-auth-subject.h delete mode 100644 src/nm-call-store.c delete mode 100644 src/nm-call-store.h delete mode 100644 src/nm-config.c delete mode 100644 src/nm-config.h create mode 100644 src/nm-dcb.c create mode 100644 src/nm-dcb.h delete mode 100644 src/nm-device-adsl.c delete mode 100644 src/nm-device-adsl.h create mode 100644 src/nm-device-bond-glue.h delete mode 100644 src/nm-device-bond.c delete mode 100644 src/nm-device-bond.h create mode 100644 src/nm-device-bridge-glue.h delete mode 100644 src/nm-device-bridge.c delete mode 100644 src/nm-device-bridge.h delete mode 100644 src/nm-device-bt.c delete mode 100644 src/nm-device-bt.h create mode 100644 src/nm-device-ethernet-glue.h delete mode 100644 src/nm-device-ethernet.c delete mode 100644 src/nm-device-ethernet.h delete mode 100644 src/nm-device-factory.h create mode 100644 src/nm-device-generic-glue.h create mode 100644 src/nm-device-glue.h create mode 100644 src/nm-device-gre-glue.h create mode 100644 src/nm-device-infiniband-glue.h delete mode 100644 src/nm-device-infiniband.c delete mode 100644 src/nm-device-infiniband.h create mode 100644 src/nm-device-macvlan-glue.h delete mode 100644 src/nm-device-modem.c delete mode 100644 src/nm-device-modem.h delete mode 100644 src/nm-device-olpc-mesh.c delete mode 100644 src/nm-device-olpc-mesh.h delete mode 100644 src/nm-device-private.h create mode 100644 src/nm-device-team-glue.h create mode 100644 src/nm-device-tun-glue.h create mode 100644 src/nm-device-veth-glue.h create mode 100644 src/nm-device-vlan-glue.h delete mode 100644 src/nm-device-vlan.c delete mode 100644 src/nm-device-vlan.h create mode 100644 src/nm-device-vxlan-glue.h delete mode 100644 src/nm-device-wifi.c delete mode 100644 src/nm-device-wifi.h delete mode 100644 src/nm-device-wired.c delete mode 100644 src/nm-device-wired.h delete mode 100644 src/nm-device.c delete mode 100644 src/nm-device.h create mode 100644 src/nm-dhcp4-config-glue.h create mode 100644 src/nm-dhcp6-config-glue.h create mode 100644 src/nm-enum-types.c create mode 100644 src/nm-enum-types.h delete mode 100644 src/nm-hostname-provider.c delete mode 100644 src/nm-hostname-provider.h create mode 100644 src/nm-ip4-config-glue.h create mode 100644 src/nm-ip6-config-glue.h create mode 100644 src/nm-manager-glue.h delete mode 100644 src/nm-netlink-compat.c delete mode 100644 src/nm-netlink-compat.h delete mode 100644 src/nm-netlink-monitor.c delete mode 100644 src/nm-netlink-monitor.h delete mode 100644 src/nm-netlink-utils.c delete mode 100644 src/nm-netlink-utils.h delete mode 100644 src/nm-policy-hostname.c delete mode 100644 src/nm-policy-hostname.h delete mode 100644 src/nm-policy-hosts.c delete mode 100644 src/nm-policy-hosts.h create mode 100644 src/nm-ppp-manager-glue.h create mode 100644 src/nm-rfkill-manager.c create mode 100644 src/nm-rfkill-manager.h delete mode 100644 src/nm-rfkill.h create mode 100644 src/nm-settings-connection-glue.h create mode 100644 src/nm-settings-glue.h delete mode 100644 src/nm-system.c delete mode 100644 src/nm-system.h delete mode 100644 src/nm-udev-manager.c delete mode 100644 src/nm-udev-manager.h create mode 100644 src/nm-vpn-connection-glue.h delete mode 100644 src/nm-wifi-ap-utils.c delete mode 100644 src/nm-wifi-ap-utils.h delete mode 100644 src/nm-wifi-ap.c delete mode 100644 src/nm-wifi-ap.h create mode 100644 src/platform/Makefile.am create mode 100644 src/platform/Makefile.in create mode 100644 src/platform/nm-fake-platform.c create mode 100644 src/platform/nm-fake-platform.h create mode 100644 src/platform/nm-linux-platform.c create mode 100644 src/platform/nm-linux-platform.h create mode 100644 src/platform/nm-platform.c create mode 100644 src/platform/nm-platform.h create mode 100644 src/platform/tests/Makefile.am create mode 100644 src/platform/tests/Makefile.in create mode 100644 src/platform/tests/dump.c create mode 100644 src/platform/tests/monitor.c create mode 100644 src/platform/tests/platform.c create mode 100644 src/platform/tests/test-address.c create mode 100644 src/platform/tests/test-cleanup.c create mode 100644 src/platform/tests/test-common.c create mode 100644 src/platform/tests/test-common.h create mode 100644 src/platform/tests/test-link.c create mode 100644 src/platform/tests/test-route.c create mode 100644 src/platform/wifi/wifi-utils-nl80211.c create mode 100644 src/platform/wifi/wifi-utils-nl80211.h create mode 100644 src/platform/wifi/wifi-utils-private.h create mode 100644 src/platform/wifi/wifi-utils-wext.c create mode 100644 src/platform/wifi/wifi-utils-wext.h create mode 100644 src/platform/wifi/wifi-utils.c create mode 100644 src/platform/wifi/wifi-utils.h delete mode 100644 src/posix-signals/Makefile.am delete mode 100644 src/posix-signals/Makefile.in create mode 100644 src/rdisc/Makefile.am create mode 100644 src/rdisc/Makefile.in create mode 100644 src/rdisc/nm-fake-rdisc.c create mode 100644 src/rdisc/nm-fake-rdisc.h create mode 100644 src/rdisc/nm-lndp-rdisc.c create mode 100644 src/rdisc/nm-lndp-rdisc.h create mode 100644 src/rdisc/nm-rdisc.c create mode 100644 src/rdisc/nm-rdisc.h create mode 100644 src/rdisc/tests/Makefile.am create mode 100644 src/rdisc/tests/Makefile.in create mode 100644 src/rdisc/tests/rdisc.c delete mode 100644 src/settings/Makefile.am delete mode 100644 src/settings/Makefile.in delete mode 100644 src/settings/nm-default-wired-connection.c delete mode 100644 src/settings/nm-default-wired-connection.h create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0 create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0:1 create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0:2 create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0:99 create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem1 create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem1:1 create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem2 create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem2:1 create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-bad-booleans create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-bad-percent create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-bad-uints create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-default-app-priorities create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-pgpct-not-100 create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-short-booleans create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-short-percent create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-short-uints create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-fcoe-fabric create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-fcoe-vn2vn create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-nm-controlled-unrecognized create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-noip create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-master create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-port create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-port-empty-config create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-unrecognized create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-hidden create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-802-1X-subj-matches create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-802-1x-ttls-eapgtc create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-dhcp-plus-ip create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-dhcp-send-hostname create mode 100644 src/settings/plugins/ifnet/errors.c create mode 100644 src/settings/plugins/ifnet/errors.h create mode 100644 src/settings/plugins/ifupdown/tests/test20-source-stanza create mode 100644 src/settings/plugins/ifupdown/tests/test20-source-stanza.eth0 create mode 100644 src/settings/plugins/ifupdown/tests/test20-source-stanza.eth1 create mode 100644 src/settings/plugins/keyfile/tests/keyfiles/Test_MAC_IB_Old_Format create mode 100644 src/settings/plugins/keyfile/tests/keyfiles/Test_MAC_Old_Format create mode 100644 src/settings/plugins/keyfile/tests/keyfiles/Test_New_Wired_Group_Name create mode 100644 src/settings/plugins/keyfile/tests/keyfiles/Test_New_Wireless_Group_Names delete mode 100644 src/supplicant-manager/Makefile.am delete mode 100644 src/supplicant-manager/Makefile.in create mode 100644 src/supplicant-manager/nm-call-store.c create mode 100644 src/supplicant-manager/nm-call-store.h create mode 100644 src/tests/test-dcb.c create mode 100644 src/tests/test-general.c create mode 100644 src/tests/test-ip4-config.c create mode 100644 src/tests/test-ip6-config.c delete mode 100644 src/tests/test-policy-hosts.c create mode 100644 src/tests/test-resolvconf-capture.c delete mode 100644 src/tests/test-wifi-ap-utils.c delete mode 100644 src/vpn-manager/Makefile.am delete mode 100644 src/vpn-manager/Makefile.in delete mode 100644 src/wifi/Makefile.am delete mode 100644 src/wifi/Makefile.in delete mode 100644 src/wifi/wifi-utils-nl80211.c delete mode 100644 src/wifi/wifi-utils-nl80211.h delete mode 100644 src/wifi/wifi-utils-private.h delete mode 100644 src/wifi/wifi-utils-wext.c delete mode 100644 src/wifi/wifi-utils-wext.h delete mode 100644 src/wifi/wifi-utils.c delete mode 100644 src/wifi/wifi-utils.h delete mode 100644 src/wimax/Makefile.am delete mode 100644 src/wimax/Makefile.in delete mode 100644 src/wimax/iwmxsdk.c delete mode 100644 src/wimax/iwmxsdk.h delete mode 100644 src/wimax/nm-device-wimax.c delete mode 100644 src/wimax/nm-device-wimax.h delete mode 100644 src/wimax/nm-wimax-factory.c delete mode 100644 src/wimax/nm-wimax-nsp.c delete mode 100644 src/wimax/nm-wimax-nsp.h delete mode 100644 src/wimax/nm-wimax-types.h delete mode 100644 src/wimax/nm-wimax-util.c delete mode 100644 src/wimax/nm-wimax-util.h (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index 3ea6241c..2929e18c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,115 +1,46 @@ -SUBDIRS= \ - generated \ - logging \ - posix-signals \ - dns-manager \ - vpn-manager \ - dhcp-manager \ - ip6-manager \ - supplicant-manager \ - ppp-manager \ - dnsmasq-manager \ - modem-manager \ - bluez-manager \ - firewall-manager \ - wifi \ - settings +include $(GLIB_MAKEFILE) -if WITH_WIMAX -SUBDIRS += wimax -endif - -SUBDIRS += . tests - -AM_CPPFLAGS = \ - -I${top_srcdir} \ - -I${top_builddir}/include \ - -I${top_srcdir}/include \ - -I${top_builddir}/src/generated \ - -I${top_srcdir}/src/generated \ - -I${top_srcdir}/src/logging \ - -I${top_srcdir}/src/posix-signals \ - -I${top_srcdir}/src/dns-manager \ - -I${top_srcdir}/src/vpn-manager \ - -I${top_srcdir}/src/dhcp-manager \ - -I${top_srcdir}/src/ip6-manager \ - -I${top_srcdir}/src/supplicant-manager \ - -I${top_srcdir}/src/dnsmasq-manager \ - -I${top_srcdir}/src/modem-manager \ - -I$(top_srcdir)/src/bluez-manager \ - -I$(top_srcdir)/src/firewall-manager \ - -I$(top_srcdir)/src/settings \ - -I$(top_srcdir)/src/wifi \ - -I${top_srcdir}/libnm-util \ - -I${top_builddir}/libnm-util \ - -I${top_srcdir}/callouts - -########################################### -# Test libraries -########################################### - -noinst_LTLIBRARIES = \ - libtest-dhcp.la \ - libtest-policy-hosts.la \ - libtest-wifi-ap-utils.la - -########################################### -# DHCP test library -########################################### - -libtest_dhcp_la_SOURCES = \ - nm-ip4-config.c \ - nm-ip6-config.c \ - nm-hostname-provider.c \ - nm-dbus-manager.c +@GNOME_CODE_COVERAGE_RULES@ -libtest_dhcp_la_CPPFLAGS = \ - $(GLIB_CFLAGS) \ - $(DBUS_CFLAGS) \ - $(LIBNL_CFLAGS) \ - $(AM_CPPFLAGS) +SUBDIRS = \ + . \ + devices/adsl \ + devices/wwan \ + devices/bluetooth \ + devices/wifi \ + dhcp-manager \ + ppp-manager \ + settings/plugins -libtest_dhcp_la_LIBADD = \ - $(top_builddir)/src/generated/libnm-generated.la \ - $(top_builddir)/libnm-util/libnm-util.la \ - $(GLIB_LIBS) \ - $(DBUS_LIBS) \ - $(LIBNL_LIBS) - -########################################### -# Hosts policy test library -########################################### - -libtest_policy_hosts_la_SOURCES = \ - nm-policy-hosts.c \ - nm-policy-hosts.h - -libtest_policy_hosts_la_CPPFLAGS = \ - -DSYSCONFDIR=\"$(sysconfdir)\" \ - $(GLIB_CFLAGS) \ - $(AM_CPPFLAGS) - -libtest_policy_hosts_la_LIBADD = \ - ${top_builddir}/src/logging/libnm-logging.la \ - $(GLIB_LIBS) - - -########################################### -# Wifi ap utils -########################################### - -libtest_wifi_ap_utils_la_SOURCES = \ - nm-wifi-ap-utils.c \ - nm-wifi-ap-utils.h +if WITH_WIMAX +SUBDIRS += devices/wimax +endif -libtest_wifi_ap_utils_la_CPPFLAGS = \ - $(GLIB_CFLAGS) \ - $(AM_CPPFLAGS) +if ENABLE_TESTS +SUBDIRS += \ + config/tests \ + dhcp-manager/tests \ + dnsmasq-manager/tests \ + platform \ + rdisc \ + settings/tests \ + supplicant-manager/tests \ + tests +endif -libtest_wifi_ap_utils_la_LIBADD = \ - ${top_builddir}/libnm-util/libnm-util.la \ - $(GLIB_LIBS) +AM_CPPFLAGS = \ + -I$(top_srcdir)/include \ + -I$(top_builddir)/include \ + -I${top_srcdir}/libgsystem \ + -I$(top_srcdir)/libnm-util \ + -I$(top_builddir)/libnm-util \ + -I$(top_srcdir)/callouts \ + -DG_LOG_DOMAIN=\""NetworkManager"\" \ + -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE +# add each subdirectory that contains a libNM source file. $(sort) is being used +# primarily for its side effect of removing duplicates. +AM_CPPFLAGS += $(foreach d,$(sort $(dir $(libNetworkManager_la_SOURCES))),-I$(top_srcdir)/src/$d) ########################################### # NetworkManager @@ -118,227 +49,314 @@ libtest_wifi_ap_utils_la_LIBADD = \ sbin_PROGRAMS = NetworkManager NetworkManager_SOURCES = \ - nm-types.h \ - nm-call-store.c \ - nm-call-store.h \ - nm-device.c \ - nm-device.h \ - nm-device-private.h \ - nm-device-ethernet.c \ - nm-device-ethernet.h \ - nm-device-adsl.c \ - nm-device-adsl.h \ - nm-device-wifi.c \ - nm-device-wifi.h \ - nm-device-wired.c \ - nm-device-wired.h \ - nm-device-olpc-mesh.c \ - nm-device-olpc-mesh.h \ - nm-device-bt.c \ - nm-device-bt.h \ - nm-device-modem.h \ - nm-device-modem.c \ - nm-device-infiniband.c \ - nm-device-infiniband.h \ - nm-device-bond.c \ - nm-device-bond.h \ - nm-device-bridge.c \ - nm-device-bridge.h \ - nm-device-vlan.c \ - nm-device-vlan.h \ - nm-wifi-ap.c \ - nm-wifi-ap.h \ - nm-wifi-ap-utils.c \ - nm-wifi-ap-utils.h \ - nm-dbus-manager.h \ - nm-dbus-manager.c \ - nm-udev-manager.c \ - nm-udev-manager.h \ - nm-device-factory.h \ - nm-hostname-provider.c \ - nm-hostname-provider.h \ - nm-ip4-config.c \ - nm-ip4-config.h \ - nm-ip6-config.c \ - nm-ip6-config.h \ - nm-active-connection.h \ - nm-active-connection.c \ - nm-config.h \ - nm-config.c \ - main.c \ - nm-policy.c \ - nm-policy.h \ - nm-policy-hosts.c \ - nm-policy-hosts.h \ - nm-policy-hostname.c \ - nm-policy-hostname.h \ - NetworkManagerUtils.c \ - NetworkManagerUtils.h \ - nm-system.c \ - nm-system.h \ - nm-manager.c \ - nm-manager.h \ - nm-manager-auth.c \ - nm-manager-auth.h \ - nm-netlink-monitor.c \ - nm-netlink-monitor.h \ - nm-netlink-utils.c \ - nm-netlink-utils.h \ - nm-netlink-compat.h \ - nm-netlink-compat.c \ - nm-activation-request.c \ - nm-activation-request.h \ - nm-properties-changed-signal.c \ - nm-properties-changed-signal.h \ - nm-dhcp4-config.c \ - nm-dhcp4-config.h \ - nm-dhcp6-config.c \ - nm-dhcp6-config.h \ - nm-rfkill.h \ - nm-session-monitor.h \ - nm-session-utils.c \ - nm-session-utils.h \ - nm-sleep-monitor.h \ - nm-connection-provider.h \ - nm-connection-provider.c \ - nm-dispatcher.c \ - nm-dispatcher.h \ - nm-connectivity.c \ - nm-connectivity.h + main.c + +NetworkManager_LDADD = libNetworkManager.la $(top_builddir)/libgsystem.la $(LIBNDP_LIBS) + +noinst_LTLIBRARIES = libNetworkManager.la + +nm_sources = \ + config/nm-config.c \ + config/nm-config.h \ + config/nm-config-device.c \ + config/nm-config-device.h \ + \ + devices/nm-device.c \ + devices/nm-device.h \ + devices/nm-device-bond.c \ + devices/nm-device-bond.h \ + devices/nm-device-bridge.c \ + devices/nm-device-bridge.h \ + devices/nm-device-ethernet.c \ + devices/nm-device-ethernet.h \ + devices/nm-device-factory.c \ + devices/nm-device-factory.h \ + devices/nm-device-generic.c \ + devices/nm-device-generic.h \ + devices/nm-device-gre.c \ + devices/nm-device-gre.h \ + devices/nm-device-infiniband.c \ + devices/nm-device-infiniband.h \ + devices/nm-device-macvlan.c \ + devices/nm-device-macvlan.h \ + devices/nm-device-private.h \ + devices/nm-device-team.c \ + devices/nm-device-team.h \ + devices/nm-device-tun.c \ + devices/nm-device-tun.h \ + devices/nm-device-veth.c \ + devices/nm-device-veth.h \ + devices/nm-device-vlan.c \ + devices/nm-device-vlan.h \ + devices/nm-device-vxlan.c \ + devices/nm-device-vxlan.h \ + \ + dhcp-manager/nm-dhcp-client.c \ + dhcp-manager/nm-dhcp-client.h \ + dhcp-manager/nm-dhcp-dhclient.c \ + dhcp-manager/nm-dhcp-dhclient.h \ + dhcp-manager/nm-dhcp-dhclient-utils.c \ + dhcp-manager/nm-dhcp-dhclient-utils.h \ + dhcp-manager/nm-dhcp-dhcpcd.c \ + dhcp-manager/nm-dhcp-dhcpcd.h \ + dhcp-manager/nm-dhcp-manager.c \ + dhcp-manager/nm-dhcp-manager.h \ + \ + dns-manager/nm-dns-dnsmasq.c \ + dns-manager/nm-dns-dnsmasq.h \ + dns-manager/nm-dns-unbound.c \ + dns-manager/nm-dns-unbound.h \ + dns-manager/nm-dns-manager.c \ + dns-manager/nm-dns-manager.h \ + dns-manager/nm-dns-plugin.c \ + dns-manager/nm-dns-plugin.h \ + dns-manager/nm-dns-utils.c \ + dns-manager/nm-dns-utils.h \ + \ + dnsmasq-manager/nm-dnsmasq-manager.c \ + dnsmasq-manager/nm-dnsmasq-manager.h \ + dnsmasq-manager/nm-dnsmasq-utils.c \ + dnsmasq-manager/nm-dnsmasq-utils.h \ + \ + firewall-manager/nm-firewall-manager.c \ + firewall-manager/nm-firewall-manager.h \ + \ + logging/nm-logging.c \ + logging/nm-logging.h \ + \ + platform/nm-fake-platform.c \ + platform/nm-fake-platform.h \ + platform/nm-linux-platform.c \ + platform/nm-linux-platform.h \ + platform/nm-platform.c \ + platform/nm-platform.h \ + platform/wifi/wifi-utils-nl80211.c \ + platform/wifi/wifi-utils-nl80211.h \ + platform/wifi/wifi-utils-private.h \ + platform/wifi/wifi-utils.c \ + platform/wifi/wifi-utils.h \ + \ + rdisc/nm-fake-rdisc.c \ + rdisc/nm-fake-rdisc.h \ + rdisc/nm-lndp-rdisc.c \ + rdisc/nm-lndp-rdisc.h \ + rdisc/nm-rdisc.c \ + rdisc/nm-rdisc.h \ + \ + posix-signals/nm-posix-signals.c \ + posix-signals/nm-posix-signals.h \ + \ + ppp-manager/nm-ppp-manager.c \ + ppp-manager/nm-ppp-manager.h \ + ppp-manager/nm-ppp-status.h \ + \ + settings/nm-agent-manager.c \ + settings/nm-agent-manager.h \ + settings/nm-inotify-helper.c \ + settings/nm-inotify-helper.h \ + settings/nm-secret-agent.c \ + settings/nm-secret-agent.h \ + settings/nm-settings-connection.c \ + settings/nm-settings-connection.h \ + settings/nm-settings-error.c \ + settings/nm-settings-error.h \ + settings/nm-settings-utils.c \ + settings/nm-settings-utils.h \ + settings/nm-settings.c \ + settings/nm-settings.h \ + settings/nm-system-config-interface.c \ + settings/nm-system-config-interface.h \ + \ + settings/plugins/keyfile/common.h \ + settings/plugins/keyfile/errors.c \ + settings/plugins/keyfile/nm-keyfile-connection.c \ + settings/plugins/keyfile/nm-keyfile-connection.h \ + settings/plugins/keyfile/plugin.c \ + settings/plugins/keyfile/plugin.h \ + settings/plugins/keyfile/reader.c \ + settings/plugins/keyfile/reader.h \ + settings/plugins/keyfile/utils.c \ + settings/plugins/keyfile/utils.h \ + settings/plugins/keyfile/writer.c \ + settings/plugins/keyfile/writer.h \ + \ + supplicant-manager/nm-supplicant-config.c \ + supplicant-manager/nm-supplicant-config.h \ + supplicant-manager/nm-supplicant-interface.c \ + supplicant-manager/nm-supplicant-interface.h \ + supplicant-manager/nm-supplicant-manager.c \ + supplicant-manager/nm-supplicant-manager.h \ + supplicant-manager/nm-supplicant-settings-verify.c \ + supplicant-manager/nm-supplicant-settings-verify.h \ + supplicant-manager/nm-supplicant-types.h \ + supplicant-manager/nm-call-store.c \ + supplicant-manager/nm-call-store.h \ + \ + vpn-manager/nm-vpn-connection.c \ + vpn-manager/nm-vpn-connection.h \ + vpn-manager/nm-vpn-manager.c \ + vpn-manager/nm-vpn-manager.h \ + vpn-manager/nm-vpn-service.c \ + vpn-manager/nm-vpn-service.h \ + \ + nm-activation-request.c \ + nm-activation-request.h \ + nm-active-connection.c \ + nm-active-connection.h \ + nm-connection-provider.c \ + nm-connection-provider.h \ + nm-connectivity.c \ + nm-connectivity.h \ + nm-dbus-manager.c \ + nm-dbus-manager.h \ + nm-dcb.c \ + nm-dcb.h \ + nm-dhcp4-config.c \ + nm-dhcp4-config.h \ + nm-dhcp6-config.c \ + nm-dhcp6-config.h \ + nm-dispatcher.c \ + nm-dispatcher.h \ + nm-enum-types.c \ + nm-enum-types.h \ + nm-ip4-config.c \ + nm-ip4-config.h \ + nm-ip6-config.c \ + nm-ip6-config.h \ + nm-manager-auth.c \ + nm-manager-auth.h \ + nm-auth-subject.c \ + nm-auth-subject.h \ + nm-manager.c \ + nm-manager.h \ + nm-policy.c \ + nm-policy.h \ + nm-properties-changed-signal.c \ + nm-properties-changed-signal.h \ + nm-rfkill-manager.c \ + nm-rfkill-manager.h \ + nm-session-monitor.h \ + nm-session-utils.c \ + nm-session-utils.h \ + nm-sleep-monitor.h \ + nm-types.h \ + NetworkManagerUtils.c \ + NetworkManagerUtils.h if SESSION_TRACKING_SYSTEMD -NetworkManager_SOURCES += nm-session-monitor-systemd.c +nm_sources += nm-session-monitor-systemd.c else if SESSION_TRACKING_CK -NetworkManager_SOURCES += nm-session-monitor-ck.c +nm_sources += nm-session-monitor-ck.c else -NetworkManager_SOURCES += nm-session-monitor-null.c +nm_sources += nm-session-monitor-null.c endif endif if SUSPEND_RESUME_SYSTEMD -NetworkManager_SOURCES += nm-sleep-monitor-systemd.c +nm_sources += nm-sleep-monitor-systemd.c else # UPower suspend/resume used whenever systemd is not enabled -NetworkManager_SOURCES += nm-sleep-monitor-upower.c +nm_sources += nm-sleep-monitor-upower.c endif -nm-access-point-glue.h: $(top_srcdir)/introspection/nm-access-point.xml - $(AM_V_GEN) dbus-binding-tool --prefix=nm_access_point --mode=glib-server --output=$@ $< - -nm-manager-glue.h: $(top_srcdir)/introspection/nm-manager.xml - $(AM_V_GEN) dbus-binding-tool --prefix=nm_manager --mode=glib-server --output=$@ $< - -nm-device-interface-glue.h: $(top_srcdir)/introspection/nm-device.xml - $(AM_V_GEN) dbus-binding-tool --prefix=nm_device_interface --mode=glib-server --output=$@ $< - -nm-device-ethernet-glue.h: $(top_srcdir)/introspection/nm-device-ethernet.xml - $(AM_V_GEN) dbus-binding-tool --prefix=nm_device_ethernet --mode=glib-server --output=$@ $< - -nm-device-infiniband-glue.h: $(top_srcdir)/introspection/nm-device-infiniband.xml - $(AM_V_GEN) dbus-binding-tool --prefix=nm_device_infiniband --mode=glib-server --output=$@ $< - -nm-device-adsl-glue.h: $(top_srcdir)/introspection/nm-device-adsl.xml - $(AM_V_GEN) dbus-binding-tool --prefix=nm_device_adsl --mode=glib-server --output=$@ $< - -nm-device-wifi-glue.h: $(top_srcdir)/introspection/nm-device-wifi.xml - $(AM_V_GEN) dbus-binding-tool --prefix=nm_device_wifi --mode=glib-server --output=$@ $< - -nm-device-bt-glue.h: $(top_srcdir)/introspection/nm-device-bt.xml - $(AM_V_GEN) dbus-binding-tool --prefix=nm_device_bt --mode=glib-server --output=$@ $< - -nm-device-olpc-mesh-glue.h: $(top_srcdir)/introspection/nm-device-olpc-mesh.xml - $(AM_V_GEN) dbus-binding-tool --prefix=nm_device_olpc_mesh --mode=glib-server --output=$@ $< - -nm-device-bond-glue.h: $(top_srcdir)/introspection/nm-device-bond.xml - $(AM_V_GEN) dbus-binding-tool --prefix=nm_device_bond --mode=glib-server --output=$@ $< - -nm-device-bridge-glue.h: $(top_srcdir)/introspection/nm-device-bridge.xml - $(AM_V_GEN) dbus-binding-tool --prefix=nm_device_bridge --mode=glib-server --output=$@ $< - -nm-device-vlan-glue.h: $(top_srcdir)/introspection/nm-device-vlan.xml - $(AM_V_GEN) dbus-binding-tool --prefix=nm_device_vlan --mode=glib-server --output=$@ $< - -nm-ip4-config-glue.h: $(top_srcdir)/introspection/nm-ip4-config.xml - $(AM_V_GEN) dbus-binding-tool --prefix=nm_ip4_config --mode=glib-server --output=$@ $< +if WITH_WEXT +nm_sources += \ + platform/wifi/wifi-utils-wext.c \ + platform/wifi/wifi-utils-wext.h +endif -nm-ip6-config-glue.h: $(top_srcdir)/introspection/nm-ip6-config.xml - $(AM_V_GEN) dbus-binding-tool --prefix=nm_ip6_config --mode=glib-server --output=$@ $< -nm-active-connection-glue.h: $(top_srcdir)/introspection/nm-active-connection.xml - $(AM_V_GEN) dbus-binding-tool --prefix=nm_active_connection --mode=glib-server --output=$@ $< +GLIB_GENERATED = nm-enum-types.h nm-enum-types.c +GLIB_MKENUMS_H_FLAGS = --identifier-prefix NM +GLIB_MKENUMS_C_FLAGS = --identifier-prefix NM +nm_enum_types_sources = $(nm_sources) -nm-dhcp4-config-glue.h: $(top_srcdir)/introspection/nm-dhcp4-config.xml - $(AM_V_GEN) dbus-binding-tool --prefix=nm_dhcp4_config --mode=glib-server --output=$@ $< +if WITH_WIMAX +nm_enum_types_sources += devices/wimax/nm-device-wimax.h +AM_CPPFLAGS += -I$(top_srcdir)/src/devices/wimax +endif -nm-dhcp6-config-glue.h: $(top_srcdir)/introspection/nm-dhcp6-config.xml - $(AM_V_GEN) dbus-binding-tool --prefix=nm_dhcp6_config --mode=glib-server --output=$@ $< +BUILT_SOURCES = $(GLIB_GENERATED) -nm-device-modem-glue.h: $(top_srcdir)/introspection/nm-device-modem.xml - $(AM_V_GEN) dbus-binding-tool --prefix=nm_device_modem --mode=glib-server --output=$@ $< -BUILT_SOURCES = \ +glue_sources = \ nm-access-point-glue.h \ - nm-manager-glue.h \ - nm-device-interface-glue.h \ - nm-device-ethernet-glue.h \ - nm-device-infiniband-glue.h \ + nm-active-connection-glue.h \ + nm-agent-manager-glue.h \ nm-device-bond-glue.h \ nm-device-bridge-glue.h \ + nm-device-ethernet-glue.h \ + nm-device-generic-glue.h \ + nm-device-glue.h \ + nm-device-gre-glue.h \ + nm-device-infiniband-glue.h \ + nm-device-macvlan-glue.h \ + nm-device-team-glue.h \ + nm-device-tun-glue.h \ + nm-device-veth-glue.h \ nm-device-vlan-glue.h \ - nm-device-adsl-glue.h \ - nm-device-wifi-glue.h \ - nm-device-olpc-mesh-glue.h \ - nm-device-bt-glue.h \ - nm-device-modem-glue.h \ + nm-device-vxlan-glue.h \ + nm-dhcp4-config-glue.h \ + nm-dhcp6-config-glue.h \ nm-ip4-config-glue.h \ nm-ip6-config-glue.h \ - nm-active-connection-glue.h \ - nm-dhcp4-config-glue.h \ - nm-dhcp6-config-glue.h + nm-manager-glue.h \ + nm-ppp-manager-glue.h \ + nm-settings-connection-glue.h \ + nm-settings-glue.h \ + nm-vpn-connection-glue.h -NetworkManager_CPPFLAGS = \ +BUILT_SOURCES += $(glue_sources) + +%-glue.h: $(top_srcdir)/introspection/%.xml + $(AM_V_GEN) dbus-binding-tool --prefix=$(subst -,_,$(subst -glue.h,,$@)) --mode=glib-server --output=$@ $< + + +AM_CPPFLAGS += \ $(DBUS_CFLAGS) \ $(GLIB_CFLAGS) \ $(GUDEV_CFLAGS) \ $(LIBNL_CFLAGS) \ + $(LIBNDP_CFLAGS) \ + $(LIBSOUP_CFLAGS) \ $(POLKIT_CFLAGS) \ $(SYSTEMD_LOGIN_CFLAGS) \ - $(LIBSOUP_CFLAGS) \ - $(AM_CPPFLAGS) \ + \ -DBINDIR=\"$(bindir)\" \ - -DSBINDIR=\"$(sbindir)\" \ - -DLIBEXECDIR=\"$(libexecdir)\" \ -DDATADIR=\"$(datadir)\" \ - -DSYSCONFDIR=\"$(sysconfdir)\" \ + -DLIBEXECDIR=\"$(libexecdir)\" \ -DLOCALSTATEDIR=\"$(localstatedir)\" \ + -DSBINDIR=\"$(sbindir)\" \ + -DSYSCONFDIR=\"$(sysconfdir)\" \ + -DRUNDIR=\"$(rundir)\" \ + \ + -DNMCONFDIR=\"$(nmconfdir)\" \ -DNMLOCALEDIR=\"$(datadir)/locale\" \ -DNMPLUGINDIR=\"$(pkglibdir)\" \ - -DNMCONFDIR=\"$(nmconfdir)\" \ -DNMRUNDIR=\"$(nmrundir)\" \ -DNMSTATEDIR=\"$(nmstatedir)\" \ - -DARP_DEBUG + \ + -DDHCLIENT_PATH=\"$(DHCLIENT_PATH)\" \ + -DDHCPCD_PATH=\"$(DHCPCD_PATH)\" \ + -DPPPD_PLUGIN_DIR=\"$(PPPD_PLUGIN_DIR)\" \ + \ + $(NULL) if SESSION_TRACKING_CK -NetworkManager_CPPFLAGS += -DCKDB_PATH=\"${CKDB_PATH}\" +AM_CPPFLAGS += -DCKDB_PATH=\"${CKDB_PATH}\" endif -NetworkManager_LDADD = \ - ./generated/libnm-generated.la \ - ./logging/libnm-logging.la \ - ./posix-signals/libnm-posix-signals.la \ - ./dns-manager/libdns-manager.la \ - ./vpn-manager/libvpn-manager.la \ - ./dhcp-manager/libdhcp-manager.la \ - ./ip6-manager/libip6-manager.la \ - ./supplicant-manager/libsupplicant-manager.la \ - ./dnsmasq-manager/libdnsmasq-manager.la \ - ./ppp-manager/libppp-manager.la \ - ./modem-manager/libmodem-manager.la \ - ./bluez-manager/libbluez-manager.la \ - ./wifi/libwifi-utils.la \ - ./firewall-manager/libfirewall-manager.la \ - ./settings/libsettings.la \ +if WITH_TEAMDCTL +AM_CPPFLAGS += ${LIBTEAMDCTL_CFLAGS} +endif + +libNetworkManager_la_SOURCES = \ + $(nm_sources) \ + $(glue_sources) + +libNetworkManager_la_LIBADD = \ + $(top_builddir)/libgsystem.la \ $(top_builddir)/libnm-util/libnm-util.la \ $(DBUS_LIBS) \ $(GLIB_LIBS) \ @@ -346,9 +364,16 @@ NetworkManager_LDADD = \ $(LIBNL_LIBS) \ $(POLKIT_LIBS) \ $(SYSTEMD_LOGIN_LIBS) \ - $(LIBSOUP_LIBS) \ - $(LIBM) \ - $(LIBDL) + $(LIBDL) \ + $(LIBM) + +if WITH_CONCHECK +libNetworkManager_la_LIBADD += $(LIBSOUP_LIBS) +endif + +if WITH_TEAMDCTL +libNetworkManager_la_LIBADD += $(LIBTEAMDCTL_LIBS) +endif NetworkManager_LDFLAGS = -rdynamic @@ -368,6 +393,7 @@ install-data-hook: CLEANFILES = \ $(BUILT_SOURCES) \ - nm-enum-types.c \ - nm-enum-types.h + settings/*-glue.h \ + devices/*-glue.h \ + devices/*/*-glue.h diff --git a/src/Makefile.in b/src/Makefile.in index 474ceb38..6aa8aa0a 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -80,20 +80,40 @@ PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ -@WITH_WIMAX_TRUE@am__append_1 = wimax +@WITH_WIMAX_TRUE@am__append_1 = devices/wimax +@ENABLE_TESTS_TRUE@am__append_2 = \ +@ENABLE_TESTS_TRUE@ config/tests \ +@ENABLE_TESTS_TRUE@ dhcp-manager/tests \ +@ENABLE_TESTS_TRUE@ dnsmasq-manager/tests \ +@ENABLE_TESTS_TRUE@ platform \ +@ENABLE_TESTS_TRUE@ rdisc \ +@ENABLE_TESTS_TRUE@ settings/tests \ +@ENABLE_TESTS_TRUE@ supplicant-manager/tests \ +@ENABLE_TESTS_TRUE@ tests + sbin_PROGRAMS = NetworkManager$(EXEEXT) -@SESSION_TRACKING_SYSTEMD_TRUE@am__append_2 = nm-session-monitor-systemd.c -@SESSION_TRACKING_CK_TRUE@@SESSION_TRACKING_SYSTEMD_FALSE@am__append_3 = nm-session-monitor-ck.c -@SESSION_TRACKING_CK_FALSE@@SESSION_TRACKING_SYSTEMD_FALSE@am__append_4 = nm-session-monitor-null.c -@SUSPEND_RESUME_SYSTEMD_TRUE@am__append_5 = nm-sleep-monitor-systemd.c +@SESSION_TRACKING_SYSTEMD_TRUE@am__append_3 = nm-session-monitor-systemd.c +@SESSION_TRACKING_CK_TRUE@@SESSION_TRACKING_SYSTEMD_FALSE@am__append_4 = nm-session-monitor-ck.c +@SESSION_TRACKING_CK_FALSE@@SESSION_TRACKING_SYSTEMD_FALSE@am__append_5 = nm-session-monitor-null.c +@SUSPEND_RESUME_SYSTEMD_TRUE@am__append_6 = nm-sleep-monitor-systemd.c # UPower suspend/resume used whenever systemd is not enabled -@SUSPEND_RESUME_SYSTEMD_FALSE@am__append_6 = nm-sleep-monitor-upower.c -@SESSION_TRACKING_CK_TRUE@am__append_7 = -DCKDB_PATH=\"${CKDB_PATH}\" +@SUSPEND_RESUME_SYSTEMD_FALSE@am__append_7 = nm-sleep-monitor-upower.c +@WITH_WEXT_TRUE@am__append_8 = \ +@WITH_WEXT_TRUE@ platform/wifi/wifi-utils-wext.c \ +@WITH_WEXT_TRUE@ platform/wifi/wifi-utils-wext.h + +@WITH_WIMAX_TRUE@am__append_9 = devices/wimax/nm-device-wimax.h +@WITH_WIMAX_TRUE@am__append_10 = -I$(top_srcdir)/src/devices/wimax +@SESSION_TRACKING_CK_TRUE@am__append_11 = -DCKDB_PATH=\"${CKDB_PATH}\" +@WITH_TEAMDCTL_TRUE@am__append_12 = ${LIBTEAMDCTL_CFLAGS} +@WITH_CONCHECK_TRUE@am__append_13 = $(LIBSOUP_LIBS) +@WITH_TEAMDCTL_TRUE@am__append_14 = $(LIBTEAMDCTL_LIBS) subdir = src DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/build-aux/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \ +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_lib_readline.m4 \ + $(top_srcdir)/m4/compiler_warnings.m4 \ $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/gnome-code-coverage.m4 \ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ @@ -113,134 +133,183 @@ CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) am__DEPENDENCIES_1 = -libtest_dhcp_la_DEPENDENCIES = \ - $(top_builddir)/src/generated/libnm-generated.la \ +@WITH_CONCHECK_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) +@WITH_TEAMDCTL_TRUE@am__DEPENDENCIES_3 = $(am__DEPENDENCIES_1) +libNetworkManager_la_DEPENDENCIES = $(top_builddir)/libgsystem.la \ $(top_builddir)/libnm-util/libnm-util.la $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) -am_libtest_dhcp_la_OBJECTS = libtest_dhcp_la-nm-ip4-config.lo \ - libtest_dhcp_la-nm-ip6-config.lo \ - libtest_dhcp_la-nm-hostname-provider.lo \ - libtest_dhcp_la-nm-dbus-manager.lo -libtest_dhcp_la_OBJECTS = $(am_libtest_dhcp_la_OBJECTS) + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) \ + $(am__DEPENDENCIES_3) +am__libNetworkManager_la_SOURCES_DIST = config/nm-config.c \ + config/nm-config.h config/nm-config-device.c \ + config/nm-config-device.h devices/nm-device.c \ + devices/nm-device.h devices/nm-device-bond.c \ + devices/nm-device-bond.h devices/nm-device-bridge.c \ + devices/nm-device-bridge.h devices/nm-device-ethernet.c \ + devices/nm-device-ethernet.h devices/nm-device-factory.c \ + devices/nm-device-factory.h devices/nm-device-generic.c \ + devices/nm-device-generic.h devices/nm-device-gre.c \ + devices/nm-device-gre.h devices/nm-device-infiniband.c \ + devices/nm-device-infiniband.h devices/nm-device-macvlan.c \ + devices/nm-device-macvlan.h devices/nm-device-private.h \ + devices/nm-device-team.c devices/nm-device-team.h \ + devices/nm-device-tun.c devices/nm-device-tun.h \ + devices/nm-device-veth.c devices/nm-device-veth.h \ + devices/nm-device-vlan.c devices/nm-device-vlan.h \ + devices/nm-device-vxlan.c devices/nm-device-vxlan.h \ + dhcp-manager/nm-dhcp-client.c dhcp-manager/nm-dhcp-client.h \ + dhcp-manager/nm-dhcp-dhclient.c \ + dhcp-manager/nm-dhcp-dhclient.h \ + dhcp-manager/nm-dhcp-dhclient-utils.c \ + dhcp-manager/nm-dhcp-dhclient-utils.h \ + dhcp-manager/nm-dhcp-dhcpcd.c dhcp-manager/nm-dhcp-dhcpcd.h \ + dhcp-manager/nm-dhcp-manager.c dhcp-manager/nm-dhcp-manager.h \ + dns-manager/nm-dns-dnsmasq.c dns-manager/nm-dns-dnsmasq.h \ + dns-manager/nm-dns-unbound.c dns-manager/nm-dns-unbound.h \ + dns-manager/nm-dns-manager.c dns-manager/nm-dns-manager.h \ + dns-manager/nm-dns-plugin.c dns-manager/nm-dns-plugin.h \ + dns-manager/nm-dns-utils.c dns-manager/nm-dns-utils.h \ + dnsmasq-manager/nm-dnsmasq-manager.c \ + dnsmasq-manager/nm-dnsmasq-manager.h \ + dnsmasq-manager/nm-dnsmasq-utils.c \ + dnsmasq-manager/nm-dnsmasq-utils.h \ + firewall-manager/nm-firewall-manager.c \ + firewall-manager/nm-firewall-manager.h logging/nm-logging.c \ + logging/nm-logging.h platform/nm-fake-platform.c \ + platform/nm-fake-platform.h platform/nm-linux-platform.c \ + platform/nm-linux-platform.h platform/nm-platform.c \ + platform/nm-platform.h platform/wifi/wifi-utils-nl80211.c \ + platform/wifi/wifi-utils-nl80211.h \ + platform/wifi/wifi-utils-private.h platform/wifi/wifi-utils.c \ + platform/wifi/wifi-utils.h rdisc/nm-fake-rdisc.c \ + rdisc/nm-fake-rdisc.h rdisc/nm-lndp-rdisc.c \ + rdisc/nm-lndp-rdisc.h rdisc/nm-rdisc.c rdisc/nm-rdisc.h \ + posix-signals/nm-posix-signals.c \ + posix-signals/nm-posix-signals.h ppp-manager/nm-ppp-manager.c \ + ppp-manager/nm-ppp-manager.h ppp-manager/nm-ppp-status.h \ + settings/nm-agent-manager.c settings/nm-agent-manager.h \ + settings/nm-inotify-helper.c settings/nm-inotify-helper.h \ + settings/nm-secret-agent.c settings/nm-secret-agent.h \ + settings/nm-settings-connection.c \ + settings/nm-settings-connection.h settings/nm-settings-error.c \ + settings/nm-settings-error.h settings/nm-settings-utils.c \ + settings/nm-settings-utils.h settings/nm-settings.c \ + settings/nm-settings.h settings/nm-system-config-interface.c \ + settings/nm-system-config-interface.h \ + settings/plugins/keyfile/common.h \ + settings/plugins/keyfile/errors.c \ + settings/plugins/keyfile/nm-keyfile-connection.c \ + settings/plugins/keyfile/nm-keyfile-connection.h \ + settings/plugins/keyfile/plugin.c \ + settings/plugins/keyfile/plugin.h \ + settings/plugins/keyfile/reader.c \ + settings/plugins/keyfile/reader.h \ + settings/plugins/keyfile/utils.c \ + settings/plugins/keyfile/utils.h \ + settings/plugins/keyfile/writer.c \ + settings/plugins/keyfile/writer.h \ + supplicant-manager/nm-supplicant-config.c \ + supplicant-manager/nm-supplicant-config.h \ + supplicant-manager/nm-supplicant-interface.c \ + supplicant-manager/nm-supplicant-interface.h \ + supplicant-manager/nm-supplicant-manager.c \ + supplicant-manager/nm-supplicant-manager.h \ + supplicant-manager/nm-supplicant-settings-verify.c \ + supplicant-manager/nm-supplicant-settings-verify.h \ + supplicant-manager/nm-supplicant-types.h \ + supplicant-manager/nm-call-store.c \ + supplicant-manager/nm-call-store.h \ + vpn-manager/nm-vpn-connection.c \ + vpn-manager/nm-vpn-connection.h vpn-manager/nm-vpn-manager.c \ + vpn-manager/nm-vpn-manager.h vpn-manager/nm-vpn-service.c \ + vpn-manager/nm-vpn-service.h nm-activation-request.c \ + nm-activation-request.h nm-active-connection.c \ + nm-active-connection.h nm-connection-provider.c \ + nm-connection-provider.h nm-connectivity.c nm-connectivity.h \ + nm-dbus-manager.c nm-dbus-manager.h nm-dcb.c nm-dcb.h \ + nm-dhcp4-config.c nm-dhcp4-config.h nm-dhcp6-config.c \ + nm-dhcp6-config.h nm-dispatcher.c nm-dispatcher.h \ + nm-enum-types.c nm-enum-types.h nm-ip4-config.c \ + nm-ip4-config.h nm-ip6-config.c nm-ip6-config.h \ + nm-manager-auth.c nm-manager-auth.h nm-auth-subject.c \ + nm-auth-subject.h nm-manager.c nm-manager.h nm-policy.c \ + nm-policy.h nm-properties-changed-signal.c \ + nm-properties-changed-signal.h nm-rfkill-manager.c \ + nm-rfkill-manager.h nm-session-monitor.h nm-session-utils.c \ + nm-session-utils.h nm-sleep-monitor.h nm-types.h \ + NetworkManagerUtils.c NetworkManagerUtils.h \ + nm-session-monitor-systemd.c nm-session-monitor-ck.c \ + nm-session-monitor-null.c nm-sleep-monitor-systemd.c \ + nm-sleep-monitor-upower.c platform/wifi/wifi-utils-wext.c \ + platform/wifi/wifi-utils-wext.h nm-access-point-glue.h \ + nm-active-connection-glue.h nm-agent-manager-glue.h \ + nm-device-bond-glue.h nm-device-bridge-glue.h \ + nm-device-ethernet-glue.h nm-device-generic-glue.h \ + nm-device-glue.h nm-device-gre-glue.h \ + nm-device-infiniband-glue.h nm-device-macvlan-glue.h \ + nm-device-team-glue.h nm-device-tun-glue.h \ + nm-device-veth-glue.h nm-device-vlan-glue.h \ + nm-device-vxlan-glue.h nm-dhcp4-config-glue.h \ + nm-dhcp6-config-glue.h nm-ip4-config-glue.h \ + nm-ip6-config-glue.h nm-manager-glue.h nm-ppp-manager-glue.h \ + nm-settings-connection-glue.h nm-settings-glue.h \ + nm-vpn-connection-glue.h +@SESSION_TRACKING_SYSTEMD_TRUE@am__objects_1 = \ +@SESSION_TRACKING_SYSTEMD_TRUE@ nm-session-monitor-systemd.lo +@SESSION_TRACKING_CK_TRUE@@SESSION_TRACKING_SYSTEMD_FALSE@am__objects_2 = nm-session-monitor-ck.lo +@SESSION_TRACKING_CK_FALSE@@SESSION_TRACKING_SYSTEMD_FALSE@am__objects_3 = nm-session-monitor-null.lo +@SUSPEND_RESUME_SYSTEMD_TRUE@am__objects_4 = \ +@SUSPEND_RESUME_SYSTEMD_TRUE@ nm-sleep-monitor-systemd.lo +@SUSPEND_RESUME_SYSTEMD_FALSE@am__objects_5 = \ +@SUSPEND_RESUME_SYSTEMD_FALSE@ nm-sleep-monitor-upower.lo +@WITH_WEXT_TRUE@am__objects_6 = wifi-utils-wext.lo +am__objects_7 = nm-config.lo nm-config-device.lo nm-device.lo \ + nm-device-bond.lo nm-device-bridge.lo nm-device-ethernet.lo \ + nm-device-factory.lo nm-device-generic.lo nm-device-gre.lo \ + nm-device-infiniband.lo nm-device-macvlan.lo nm-device-team.lo \ + nm-device-tun.lo nm-device-veth.lo nm-device-vlan.lo \ + nm-device-vxlan.lo nm-dhcp-client.lo nm-dhcp-dhclient.lo \ + nm-dhcp-dhclient-utils.lo nm-dhcp-dhcpcd.lo nm-dhcp-manager.lo \ + nm-dns-dnsmasq.lo nm-dns-unbound.lo nm-dns-manager.lo \ + nm-dns-plugin.lo nm-dns-utils.lo nm-dnsmasq-manager.lo \ + nm-dnsmasq-utils.lo nm-firewall-manager.lo nm-logging.lo \ + nm-fake-platform.lo nm-linux-platform.lo nm-platform.lo \ + wifi-utils-nl80211.lo wifi-utils.lo nm-fake-rdisc.lo \ + nm-lndp-rdisc.lo nm-rdisc.lo nm-posix-signals.lo \ + nm-ppp-manager.lo nm-agent-manager.lo nm-inotify-helper.lo \ + nm-secret-agent.lo nm-settings-connection.lo \ + nm-settings-error.lo nm-settings-utils.lo nm-settings.lo \ + nm-system-config-interface.lo errors.lo \ + nm-keyfile-connection.lo plugin.lo reader.lo utils.lo \ + writer.lo nm-supplicant-config.lo nm-supplicant-interface.lo \ + nm-supplicant-manager.lo nm-supplicant-settings-verify.lo \ + nm-call-store.lo nm-vpn-connection.lo nm-vpn-manager.lo \ + nm-vpn-service.lo nm-activation-request.lo \ + nm-active-connection.lo nm-connection-provider.lo \ + nm-connectivity.lo nm-dbus-manager.lo nm-dcb.lo \ + nm-dhcp4-config.lo nm-dhcp6-config.lo nm-dispatcher.lo \ + nm-enum-types.lo nm-ip4-config.lo nm-ip6-config.lo \ + nm-manager-auth.lo nm-auth-subject.lo nm-manager.lo \ + nm-policy.lo nm-properties-changed-signal.lo \ + nm-rfkill-manager.lo nm-session-utils.lo \ + NetworkManagerUtils.lo $(am__objects_1) $(am__objects_2) \ + $(am__objects_3) $(am__objects_4) $(am__objects_5) \ + $(am__objects_6) +am__objects_8 = +am_libNetworkManager_la_OBJECTS = $(am__objects_7) $(am__objects_8) +libNetworkManager_la_OBJECTS = $(am_libNetworkManager_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = -libtest_policy_hosts_la_DEPENDENCIES = \ - ${top_builddir}/src/logging/libnm-logging.la \ - $(am__DEPENDENCIES_1) -am_libtest_policy_hosts_la_OBJECTS = \ - libtest_policy_hosts_la-nm-policy-hosts.lo -libtest_policy_hosts_la_OBJECTS = \ - $(am_libtest_policy_hosts_la_OBJECTS) -libtest_wifi_ap_utils_la_DEPENDENCIES = \ - ${top_builddir}/libnm-util/libnm-util.la $(am__DEPENDENCIES_1) -am_libtest_wifi_ap_utils_la_OBJECTS = \ - libtest_wifi_ap_utils_la-nm-wifi-ap-utils.lo -libtest_wifi_ap_utils_la_OBJECTS = \ - $(am_libtest_wifi_ap_utils_la_OBJECTS) am__installdirs = "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(dbusservicedir)" PROGRAMS = $(sbin_PROGRAMS) -am__NetworkManager_SOURCES_DIST = nm-types.h nm-call-store.c \ - nm-call-store.h nm-device.c nm-device.h nm-device-private.h \ - nm-device-ethernet.c nm-device-ethernet.h nm-device-adsl.c \ - nm-device-adsl.h nm-device-wifi.c nm-device-wifi.h \ - nm-device-wired.c nm-device-wired.h nm-device-olpc-mesh.c \ - nm-device-olpc-mesh.h nm-device-bt.c nm-device-bt.h \ - nm-device-modem.h nm-device-modem.c nm-device-infiniband.c \ - nm-device-infiniband.h nm-device-bond.c nm-device-bond.h \ - nm-device-bridge.c nm-device-bridge.h nm-device-vlan.c \ - nm-device-vlan.h nm-wifi-ap.c nm-wifi-ap.h nm-wifi-ap-utils.c \ - nm-wifi-ap-utils.h nm-dbus-manager.h nm-dbus-manager.c \ - nm-udev-manager.c nm-udev-manager.h nm-device-factory.h \ - nm-hostname-provider.c nm-hostname-provider.h nm-ip4-config.c \ - nm-ip4-config.h nm-ip6-config.c nm-ip6-config.h \ - nm-active-connection.h nm-active-connection.c nm-config.h \ - nm-config.c main.c nm-policy.c nm-policy.h nm-policy-hosts.c \ - nm-policy-hosts.h nm-policy-hostname.c nm-policy-hostname.h \ - NetworkManagerUtils.c NetworkManagerUtils.h nm-system.c \ - nm-system.h nm-manager.c nm-manager.h nm-manager-auth.c \ - nm-manager-auth.h nm-netlink-monitor.c nm-netlink-monitor.h \ - nm-netlink-utils.c nm-netlink-utils.h nm-netlink-compat.h \ - nm-netlink-compat.c nm-activation-request.c \ - nm-activation-request.h nm-properties-changed-signal.c \ - nm-properties-changed-signal.h nm-dhcp4-config.c \ - nm-dhcp4-config.h nm-dhcp6-config.c nm-dhcp6-config.h \ - nm-rfkill.h nm-session-monitor.h nm-session-utils.c \ - nm-session-utils.h nm-sleep-monitor.h nm-connection-provider.h \ - nm-connection-provider.c nm-dispatcher.c nm-dispatcher.h \ - nm-connectivity.c nm-connectivity.h \ - nm-session-monitor-systemd.c nm-session-monitor-ck.c \ - nm-session-monitor-null.c nm-sleep-monitor-systemd.c \ - nm-sleep-monitor-upower.c -@SESSION_TRACKING_SYSTEMD_TRUE@am__objects_1 = NetworkManager-nm-session-monitor-systemd.$(OBJEXT) -@SESSION_TRACKING_CK_TRUE@@SESSION_TRACKING_SYSTEMD_FALSE@am__objects_2 = NetworkManager-nm-session-monitor-ck.$(OBJEXT) -@SESSION_TRACKING_CK_FALSE@@SESSION_TRACKING_SYSTEMD_FALSE@am__objects_3 = NetworkManager-nm-session-monitor-null.$(OBJEXT) -@SUSPEND_RESUME_SYSTEMD_TRUE@am__objects_4 = NetworkManager-nm-sleep-monitor-systemd.$(OBJEXT) -@SUSPEND_RESUME_SYSTEMD_FALSE@am__objects_5 = NetworkManager-nm-sleep-monitor-upower.$(OBJEXT) -am_NetworkManager_OBJECTS = NetworkManager-nm-call-store.$(OBJEXT) \ - NetworkManager-nm-device.$(OBJEXT) \ - NetworkManager-nm-device-ethernet.$(OBJEXT) \ - NetworkManager-nm-device-adsl.$(OBJEXT) \ - NetworkManager-nm-device-wifi.$(OBJEXT) \ - NetworkManager-nm-device-wired.$(OBJEXT) \ - NetworkManager-nm-device-olpc-mesh.$(OBJEXT) \ - NetworkManager-nm-device-bt.$(OBJEXT) \ - NetworkManager-nm-device-modem.$(OBJEXT) \ - NetworkManager-nm-device-infiniband.$(OBJEXT) \ - NetworkManager-nm-device-bond.$(OBJEXT) \ - NetworkManager-nm-device-bridge.$(OBJEXT) \ - NetworkManager-nm-device-vlan.$(OBJEXT) \ - NetworkManager-nm-wifi-ap.$(OBJEXT) \ - NetworkManager-nm-wifi-ap-utils.$(OBJEXT) \ - NetworkManager-nm-dbus-manager.$(OBJEXT) \ - NetworkManager-nm-udev-manager.$(OBJEXT) \ - NetworkManager-nm-hostname-provider.$(OBJEXT) \ - NetworkManager-nm-ip4-config.$(OBJEXT) \ - NetworkManager-nm-ip6-config.$(OBJEXT) \ - NetworkManager-nm-active-connection.$(OBJEXT) \ - NetworkManager-nm-config.$(OBJEXT) \ - NetworkManager-main.$(OBJEXT) \ - NetworkManager-nm-policy.$(OBJEXT) \ - NetworkManager-nm-policy-hosts.$(OBJEXT) \ - NetworkManager-nm-policy-hostname.$(OBJEXT) \ - NetworkManager-NetworkManagerUtils.$(OBJEXT) \ - NetworkManager-nm-system.$(OBJEXT) \ - NetworkManager-nm-manager.$(OBJEXT) \ - NetworkManager-nm-manager-auth.$(OBJEXT) \ - NetworkManager-nm-netlink-monitor.$(OBJEXT) \ - NetworkManager-nm-netlink-utils.$(OBJEXT) \ - NetworkManager-nm-netlink-compat.$(OBJEXT) \ - NetworkManager-nm-activation-request.$(OBJEXT) \ - NetworkManager-nm-properties-changed-signal.$(OBJEXT) \ - NetworkManager-nm-dhcp4-config.$(OBJEXT) \ - NetworkManager-nm-dhcp6-config.$(OBJEXT) \ - NetworkManager-nm-session-utils.$(OBJEXT) \ - NetworkManager-nm-connection-provider.$(OBJEXT) \ - NetworkManager-nm-dispatcher.$(OBJEXT) \ - NetworkManager-nm-connectivity.$(OBJEXT) $(am__objects_1) \ - $(am__objects_2) $(am__objects_3) $(am__objects_4) \ - $(am__objects_5) +am_NetworkManager_OBJECTS = main.$(OBJEXT) NetworkManager_OBJECTS = $(am_NetworkManager_OBJECTS) -NetworkManager_DEPENDENCIES = ./generated/libnm-generated.la \ - ./logging/libnm-logging.la \ - ./posix-signals/libnm-posix-signals.la \ - ./dns-manager/libdns-manager.la \ - ./vpn-manager/libvpn-manager.la \ - ./dhcp-manager/libdhcp-manager.la \ - ./ip6-manager/libip6-manager.la \ - ./supplicant-manager/libsupplicant-manager.la \ - ./dnsmasq-manager/libdnsmasq-manager.la \ - ./ppp-manager/libppp-manager.la \ - ./modem-manager/libmodem-manager.la \ - ./bluez-manager/libbluez-manager.la ./wifi/libwifi-utils.la \ - ./firewall-manager/libfirewall-manager.la \ - ./settings/libsettings.la \ - $(top_builddir)/libnm-util/libnm-util.la $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +NetworkManager_DEPENDENCIES = libNetworkManager.la \ + $(top_builddir)/libgsystem.la $(am__DEPENDENCIES_1) NetworkManager_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(NetworkManager_LDFLAGS) $(LDFLAGS) -o \ @@ -279,13 +348,9 @@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = -SOURCES = $(libtest_dhcp_la_SOURCES) \ - $(libtest_policy_hosts_la_SOURCES) \ - $(libtest_wifi_ap_utils_la_SOURCES) $(NetworkManager_SOURCES) -DIST_SOURCES = $(libtest_dhcp_la_SOURCES) \ - $(libtest_policy_hosts_la_SOURCES) \ - $(libtest_wifi_ap_utils_la_SOURCES) \ - $(am__NetworkManager_SOURCES_DIST) +SOURCES = $(libNetworkManager_la_SOURCES) $(NetworkManager_SOURCES) +DIST_SOURCES = $(am__libNetworkManager_la_SOURCES_DIST) \ + $(NetworkManager_SOURCES) RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ @@ -354,10 +419,11 @@ am__define_uniq_tagged_files = \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags -DIST_SUBDIRS = generated logging posix-signals dns-manager vpn-manager \ - dhcp-manager ip6-manager supplicant-manager ppp-manager \ - dnsmasq-manager modem-manager bluez-manager firewall-manager \ - wifi settings wimax . tests +DIST_SUBDIRS = . devices/adsl devices/wwan devices/bluetooth \ + devices/wifi dhcp-manager ppp-manager settings/plugins \ + devices/wimax config/tests dhcp-manager/tests \ + dnsmasq-manager/tests platform rdisc settings/tests \ + supplicant-manager/tests tests DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ @@ -409,12 +475,15 @@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIRNAME = @DATADIRNAME@ DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_100_CFLAGS = @DBUS_GLIB_100_CFLAGS@ +DBUS_GLIB_100_LIBS = @DBUS_GLIB_100_LIBS@ DBUS_LIBS = @DBUS_LIBS@ DBUS_SYS_DIR = @DBUS_SYS_DIR@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DHCLIENT_PATH = @DHCLIENT_PATH@ DHCPCD_PATH = @DHCPCD_PATH@ +DISTRO_NETWORK_SERVICE = @DISTRO_NETWORK_SERVICE@ DLLTOOL = @DLLTOOL@ DNSMASQ_PATH = @DNSMASQ_PATH@ DSYMUTIL = @DSYMUTIL@ @@ -439,7 +508,6 @@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ GTKDOC_CHECK = @GTKDOC_CHECK@ -GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ GTKDOC_MKPDF = @GTKDOC_MKPDF@ @@ -484,12 +552,16 @@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ +LIBNDP_CFLAGS = @LIBNDP_CFLAGS@ +LIBNDP_LIBS = @LIBNDP_LIBS@ LIBNL_CFLAGS = @LIBNL_CFLAGS@ LIBNL_LIBS = @LIBNL_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@ LIBSOUP_LIBS = @LIBSOUP_LIBS@ +LIBTEAMDCTL_CFLAGS = @LIBTEAMDCTL_CFLAGS@ +LIBTEAMDCTL_LIBS = @LIBTEAMDCTL_LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ @@ -506,6 +578,8 @@ MOC = @MOC@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ +NEWT_CFLAGS = @NEWT_CFLAGS@ +NEWT_LIBS = @NEWT_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ @@ -533,11 +607,16 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ POLKIT_CFLAGS = @POLKIT_CFLAGS@ POLKIT_LIBS = @POLKIT_LIBS@ POSUB = @POSUB@ +PPPD_PATH = @PPPD_PATH@ PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@ +PPPOE_PATH = @PPPOE_PATH@ QT_CFLAGS = @QT_CFLAGS@ QT_LIBS = @QT_LIBS@ RANLIB = @RANLIB@ +READLINE_LIBS = @READLINE_LIBS@ SED = @SED@ +SELINUX_CFLAGS = @SELINUX_CFLAGS@ +SELINUX_LIBS = @SELINUX_LIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ @@ -552,6 +631,7 @@ UDEV_BASE_DIR = @UDEV_BASE_DIR@ USE_NLS = @USE_NLS@ UUID_CFLAGS = @UUID_CFLAGS@ UUID_LIBS = @UUID_LIBS@ +VALGRIND_RULES = @VALGRIND_RULES@ VAPIGEN = @VAPIGEN@ VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ @@ -614,6 +694,7 @@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ +subdirs = @subdirs@ sysconfdir = @sysconfdir@ systemdsystemunitdir = @systemdsystemunitdir@ target_alias = @target_alias@ @@ -624,187 +705,180 @@ with_dhclient = @with_dhclient@ with_dhcpcd = @with_dhcpcd@ with_netconfig = @with_netconfig@ with_resolvconf = @with_resolvconf@ -SUBDIRS = generated logging posix-signals dns-manager vpn-manager \ - dhcp-manager ip6-manager supplicant-manager ppp-manager \ - dnsmasq-manager modem-manager bluez-manager firewall-manager \ - wifi settings $(am__append_1) . tests -AM_CPPFLAGS = \ - -I${top_srcdir} \ - -I${top_builddir}/include \ - -I${top_srcdir}/include \ - -I${top_builddir}/src/generated \ - -I${top_srcdir}/src/generated \ - -I${top_srcdir}/src/logging \ - -I${top_srcdir}/src/posix-signals \ - -I${top_srcdir}/src/dns-manager \ - -I${top_srcdir}/src/vpn-manager \ - -I${top_srcdir}/src/dhcp-manager \ - -I${top_srcdir}/src/ip6-manager \ - -I${top_srcdir}/src/supplicant-manager \ - -I${top_srcdir}/src/dnsmasq-manager \ - -I${top_srcdir}/src/modem-manager \ - -I$(top_srcdir)/src/bluez-manager \ - -I$(top_srcdir)/src/firewall-manager \ - -I$(top_srcdir)/src/settings \ - -I$(top_srcdir)/src/wifi \ - -I${top_srcdir}/libnm-util \ - -I${top_builddir}/libnm-util \ - -I${top_srcdir}/callouts - - -########################################### -# Test libraries -########################################### -noinst_LTLIBRARIES = \ - libtest-dhcp.la \ - libtest-policy-hosts.la \ - libtest-wifi-ap-utils.la - - -########################################### -# DHCP test library -########################################### -libtest_dhcp_la_SOURCES = \ - nm-ip4-config.c \ - nm-ip6-config.c \ - nm-hostname-provider.c \ - nm-dbus-manager.c - -libtest_dhcp_la_CPPFLAGS = \ - $(GLIB_CFLAGS) \ - $(DBUS_CFLAGS) \ - $(LIBNL_CFLAGS) \ - $(AM_CPPFLAGS) - -libtest_dhcp_la_LIBADD = \ - $(top_builddir)/src/generated/libnm-generated.la \ - $(top_builddir)/libnm-util/libnm-util.la \ - $(GLIB_LIBS) \ - $(DBUS_LIBS) \ - $(LIBNL_LIBS) - - -########################################### -# Hosts policy test library -########################################### -libtest_policy_hosts_la_SOURCES = \ - nm-policy-hosts.c \ - nm-policy-hosts.h - -libtest_policy_hosts_la_CPPFLAGS = \ - -DSYSCONFDIR=\"$(sysconfdir)\" \ - $(GLIB_CFLAGS) \ - $(AM_CPPFLAGS) - -libtest_policy_hosts_la_LIBADD = \ - ${top_builddir}/src/logging/libnm-logging.la \ - $(GLIB_LIBS) - - -########################################### -# Wifi ap utils -########################################### -libtest_wifi_ap_utils_la_SOURCES = \ - nm-wifi-ap-utils.c \ - nm-wifi-ap-utils.h - -libtest_wifi_ap_utils_la_CPPFLAGS = \ - $(GLIB_CFLAGS) \ - $(AM_CPPFLAGS) - -libtest_wifi_ap_utils_la_LIBADD = \ - ${top_builddir}/libnm-util/libnm-util.la \ - $(GLIB_LIBS) - -NetworkManager_SOURCES = nm-types.h nm-call-store.c nm-call-store.h \ - nm-device.c nm-device.h nm-device-private.h \ - nm-device-ethernet.c nm-device-ethernet.h nm-device-adsl.c \ - nm-device-adsl.h nm-device-wifi.c nm-device-wifi.h \ - nm-device-wired.c nm-device-wired.h nm-device-olpc-mesh.c \ - nm-device-olpc-mesh.h nm-device-bt.c nm-device-bt.h \ - nm-device-modem.h nm-device-modem.c nm-device-infiniband.c \ - nm-device-infiniband.h nm-device-bond.c nm-device-bond.h \ - nm-device-bridge.c nm-device-bridge.h nm-device-vlan.c \ - nm-device-vlan.h nm-wifi-ap.c nm-wifi-ap.h nm-wifi-ap-utils.c \ - nm-wifi-ap-utils.h nm-dbus-manager.h nm-dbus-manager.c \ - nm-udev-manager.c nm-udev-manager.h nm-device-factory.h \ - nm-hostname-provider.c nm-hostname-provider.h nm-ip4-config.c \ +with_valgrind = @with_valgrind@ +SUBDIRS = . devices/adsl devices/wwan devices/bluetooth devices/wifi \ + dhcp-manager ppp-manager settings/plugins $(am__append_1) \ + $(am__append_2) + +# add each subdirectory that contains a libNM source file. $(sort) is being used +# primarily for its side effect of removing duplicates. +AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include \ + -I${top_srcdir}/libgsystem -I$(top_srcdir)/libnm-util \ + -I$(top_builddir)/libnm-util -I$(top_srcdir)/callouts \ + -DG_LOG_DOMAIN=\""NetworkManager"\" \ + -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE $(foreach \ + d,$(sort $(dir \ + $(libNetworkManager_la_SOURCES))),-I$(top_srcdir)/src/$d) \ + $(am__append_10) $(DBUS_CFLAGS) $(GLIB_CFLAGS) $(GUDEV_CFLAGS) \ + $(LIBNL_CFLAGS) $(LIBNDP_CFLAGS) $(LIBSOUP_CFLAGS) \ + $(POLKIT_CFLAGS) $(SYSTEMD_LOGIN_CFLAGS) \ + -DBINDIR=\"$(bindir)\" -DDATADIR=\"$(datadir)\" \ + -DLIBEXECDIR=\"$(libexecdir)\" \ + -DLOCALSTATEDIR=\"$(localstatedir)\" -DSBINDIR=\"$(sbindir)\" \ + -DSYSCONFDIR=\"$(sysconfdir)\" -DRUNDIR=\"$(rundir)\" \ + -DNMCONFDIR=\"$(nmconfdir)\" \ + -DNMLOCALEDIR=\"$(datadir)/locale\" \ + -DNMPLUGINDIR=\"$(pkglibdir)\" -DNMRUNDIR=\"$(nmrundir)\" \ + -DNMSTATEDIR=\"$(nmstatedir)\" \ + -DDHCLIENT_PATH=\"$(DHCLIENT_PATH)\" \ + -DDHCPCD_PATH=\"$(DHCPCD_PATH)\" \ + -DPPPD_PLUGIN_DIR=\"$(PPPD_PLUGIN_DIR)\" $(NULL) \ + $(am__append_11) $(am__append_12) +NetworkManager_SOURCES = \ + main.c + +NetworkManager_LDADD = libNetworkManager.la $(top_builddir)/libgsystem.la $(LIBNDP_LIBS) +noinst_LTLIBRARIES = libNetworkManager.la +nm_sources = config/nm-config.c config/nm-config.h \ + config/nm-config-device.c config/nm-config-device.h \ + devices/nm-device.c devices/nm-device.h \ + devices/nm-device-bond.c devices/nm-device-bond.h \ + devices/nm-device-bridge.c devices/nm-device-bridge.h \ + devices/nm-device-ethernet.c devices/nm-device-ethernet.h \ + devices/nm-device-factory.c devices/nm-device-factory.h \ + devices/nm-device-generic.c devices/nm-device-generic.h \ + devices/nm-device-gre.c devices/nm-device-gre.h \ + devices/nm-device-infiniband.c devices/nm-device-infiniband.h \ + devices/nm-device-macvlan.c devices/nm-device-macvlan.h \ + devices/nm-device-private.h devices/nm-device-team.c \ + devices/nm-device-team.h devices/nm-device-tun.c \ + devices/nm-device-tun.h devices/nm-device-veth.c \ + devices/nm-device-veth.h devices/nm-device-vlan.c \ + devices/nm-device-vlan.h devices/nm-device-vxlan.c \ + devices/nm-device-vxlan.h dhcp-manager/nm-dhcp-client.c \ + dhcp-manager/nm-dhcp-client.h dhcp-manager/nm-dhcp-dhclient.c \ + dhcp-manager/nm-dhcp-dhclient.h \ + dhcp-manager/nm-dhcp-dhclient-utils.c \ + dhcp-manager/nm-dhcp-dhclient-utils.h \ + dhcp-manager/nm-dhcp-dhcpcd.c dhcp-manager/nm-dhcp-dhcpcd.h \ + dhcp-manager/nm-dhcp-manager.c dhcp-manager/nm-dhcp-manager.h \ + dns-manager/nm-dns-dnsmasq.c dns-manager/nm-dns-dnsmasq.h \ + dns-manager/nm-dns-unbound.c dns-manager/nm-dns-unbound.h \ + dns-manager/nm-dns-manager.c dns-manager/nm-dns-manager.h \ + dns-manager/nm-dns-plugin.c dns-manager/nm-dns-plugin.h \ + dns-manager/nm-dns-utils.c dns-manager/nm-dns-utils.h \ + dnsmasq-manager/nm-dnsmasq-manager.c \ + dnsmasq-manager/nm-dnsmasq-manager.h \ + dnsmasq-manager/nm-dnsmasq-utils.c \ + dnsmasq-manager/nm-dnsmasq-utils.h \ + firewall-manager/nm-firewall-manager.c \ + firewall-manager/nm-firewall-manager.h logging/nm-logging.c \ + logging/nm-logging.h platform/nm-fake-platform.c \ + platform/nm-fake-platform.h platform/nm-linux-platform.c \ + platform/nm-linux-platform.h platform/nm-platform.c \ + platform/nm-platform.h platform/wifi/wifi-utils-nl80211.c \ + platform/wifi/wifi-utils-nl80211.h \ + platform/wifi/wifi-utils-private.h platform/wifi/wifi-utils.c \ + platform/wifi/wifi-utils.h rdisc/nm-fake-rdisc.c \ + rdisc/nm-fake-rdisc.h rdisc/nm-lndp-rdisc.c \ + rdisc/nm-lndp-rdisc.h rdisc/nm-rdisc.c rdisc/nm-rdisc.h \ + posix-signals/nm-posix-signals.c \ + posix-signals/nm-posix-signals.h ppp-manager/nm-ppp-manager.c \ + ppp-manager/nm-ppp-manager.h ppp-manager/nm-ppp-status.h \ + settings/nm-agent-manager.c settings/nm-agent-manager.h \ + settings/nm-inotify-helper.c settings/nm-inotify-helper.h \ + settings/nm-secret-agent.c settings/nm-secret-agent.h \ + settings/nm-settings-connection.c \ + settings/nm-settings-connection.h settings/nm-settings-error.c \ + settings/nm-settings-error.h settings/nm-settings-utils.c \ + settings/nm-settings-utils.h settings/nm-settings.c \ + settings/nm-settings.h settings/nm-system-config-interface.c \ + settings/nm-system-config-interface.h \ + settings/plugins/keyfile/common.h \ + settings/plugins/keyfile/errors.c \ + settings/plugins/keyfile/nm-keyfile-connection.c \ + settings/plugins/keyfile/nm-keyfile-connection.h \ + settings/plugins/keyfile/plugin.c \ + settings/plugins/keyfile/plugin.h \ + settings/plugins/keyfile/reader.c \ + settings/plugins/keyfile/reader.h \ + settings/plugins/keyfile/utils.c \ + settings/plugins/keyfile/utils.h \ + settings/plugins/keyfile/writer.c \ + settings/plugins/keyfile/writer.h \ + supplicant-manager/nm-supplicant-config.c \ + supplicant-manager/nm-supplicant-config.h \ + supplicant-manager/nm-supplicant-interface.c \ + supplicant-manager/nm-supplicant-interface.h \ + supplicant-manager/nm-supplicant-manager.c \ + supplicant-manager/nm-supplicant-manager.h \ + supplicant-manager/nm-supplicant-settings-verify.c \ + supplicant-manager/nm-supplicant-settings-verify.h \ + supplicant-manager/nm-supplicant-types.h \ + supplicant-manager/nm-call-store.c \ + supplicant-manager/nm-call-store.h \ + vpn-manager/nm-vpn-connection.c \ + vpn-manager/nm-vpn-connection.h vpn-manager/nm-vpn-manager.c \ + vpn-manager/nm-vpn-manager.h vpn-manager/nm-vpn-service.c \ + vpn-manager/nm-vpn-service.h nm-activation-request.c \ + nm-activation-request.h nm-active-connection.c \ + nm-active-connection.h nm-connection-provider.c \ + nm-connection-provider.h nm-connectivity.c nm-connectivity.h \ + nm-dbus-manager.c nm-dbus-manager.h nm-dcb.c nm-dcb.h \ + nm-dhcp4-config.c nm-dhcp4-config.h nm-dhcp6-config.c \ + nm-dhcp6-config.h nm-dispatcher.c nm-dispatcher.h \ + nm-enum-types.c nm-enum-types.h nm-ip4-config.c \ nm-ip4-config.h nm-ip6-config.c nm-ip6-config.h \ - nm-active-connection.h nm-active-connection.c nm-config.h \ - nm-config.c main.c nm-policy.c nm-policy.h nm-policy-hosts.c \ - nm-policy-hosts.h nm-policy-hostname.c nm-policy-hostname.h \ - NetworkManagerUtils.c NetworkManagerUtils.h nm-system.c \ - nm-system.h nm-manager.c nm-manager.h nm-manager-auth.c \ - nm-manager-auth.h nm-netlink-monitor.c nm-netlink-monitor.h \ - nm-netlink-utils.c nm-netlink-utils.h nm-netlink-compat.h \ - nm-netlink-compat.c nm-activation-request.c \ - nm-activation-request.h nm-properties-changed-signal.c \ - nm-properties-changed-signal.h nm-dhcp4-config.c \ - nm-dhcp4-config.h nm-dhcp6-config.c nm-dhcp6-config.h \ - nm-rfkill.h nm-session-monitor.h nm-session-utils.c \ - nm-session-utils.h nm-sleep-monitor.h nm-connection-provider.h \ - nm-connection-provider.c nm-dispatcher.c nm-dispatcher.h \ - nm-connectivity.c nm-connectivity.h $(am__append_2) \ - $(am__append_3) $(am__append_4) $(am__append_5) \ - $(am__append_6) -BUILT_SOURCES = \ + nm-manager-auth.c nm-manager-auth.h nm-auth-subject.c \ + nm-auth-subject.h nm-manager.c nm-manager.h nm-policy.c \ + nm-policy.h nm-properties-changed-signal.c \ + nm-properties-changed-signal.h nm-rfkill-manager.c \ + nm-rfkill-manager.h nm-session-monitor.h nm-session-utils.c \ + nm-session-utils.h nm-sleep-monitor.h nm-types.h \ + NetworkManagerUtils.c NetworkManagerUtils.h $(am__append_3) \ + $(am__append_4) $(am__append_5) $(am__append_6) \ + $(am__append_7) $(am__append_8) +GLIB_GENERATED = nm-enum-types.h nm-enum-types.c +GLIB_MKENUMS_H_FLAGS = --identifier-prefix NM +GLIB_MKENUMS_C_FLAGS = --identifier-prefix NM +nm_enum_types_sources = $(nm_sources) $(am__append_9) +BUILT_SOURCES = $(GLIB_GENERATED) $(glue_sources) +glue_sources = \ nm-access-point-glue.h \ - nm-manager-glue.h \ - nm-device-interface-glue.h \ - nm-device-ethernet-glue.h \ - nm-device-infiniband-glue.h \ + nm-active-connection-glue.h \ + nm-agent-manager-glue.h \ nm-device-bond-glue.h \ nm-device-bridge-glue.h \ + nm-device-ethernet-glue.h \ + nm-device-generic-glue.h \ + nm-device-glue.h \ + nm-device-gre-glue.h \ + nm-device-infiniband-glue.h \ + nm-device-macvlan-glue.h \ + nm-device-team-glue.h \ + nm-device-tun-glue.h \ + nm-device-veth-glue.h \ nm-device-vlan-glue.h \ - nm-device-adsl-glue.h \ - nm-device-wifi-glue.h \ - nm-device-olpc-mesh-glue.h \ - nm-device-bt-glue.h \ - nm-device-modem-glue.h \ + nm-device-vxlan-glue.h \ + nm-dhcp4-config-glue.h \ + nm-dhcp6-config-glue.h \ nm-ip4-config-glue.h \ nm-ip6-config-glue.h \ - nm-active-connection-glue.h \ - nm-dhcp4-config-glue.h \ - nm-dhcp6-config-glue.h - -NetworkManager_CPPFLAGS = $(DBUS_CFLAGS) $(GLIB_CFLAGS) \ - $(GUDEV_CFLAGS) $(LIBNL_CFLAGS) $(POLKIT_CFLAGS) \ - $(SYSTEMD_LOGIN_CFLAGS) $(LIBSOUP_CFLAGS) $(AM_CPPFLAGS) \ - -DBINDIR=\"$(bindir)\" -DSBINDIR=\"$(sbindir)\" \ - -DLIBEXECDIR=\"$(libexecdir)\" -DDATADIR=\"$(datadir)\" \ - -DSYSCONFDIR=\"$(sysconfdir)\" \ - -DLOCALSTATEDIR=\"$(localstatedir)\" \ - -DNMLOCALEDIR=\"$(datadir)/locale\" \ - -DNMPLUGINDIR=\"$(pkglibdir)\" -DNMCONFDIR=\"$(nmconfdir)\" \ - -DNMRUNDIR=\"$(nmrundir)\" -DNMSTATEDIR=\"$(nmstatedir)\" \ - -DARP_DEBUG $(am__append_7) -NetworkManager_LDADD = \ - ./generated/libnm-generated.la \ - ./logging/libnm-logging.la \ - ./posix-signals/libnm-posix-signals.la \ - ./dns-manager/libdns-manager.la \ - ./vpn-manager/libvpn-manager.la \ - ./dhcp-manager/libdhcp-manager.la \ - ./ip6-manager/libip6-manager.la \ - ./supplicant-manager/libsupplicant-manager.la \ - ./dnsmasq-manager/libdnsmasq-manager.la \ - ./ppp-manager/libppp-manager.la \ - ./modem-manager/libmodem-manager.la \ - ./bluez-manager/libbluez-manager.la \ - ./wifi/libwifi-utils.la \ - ./firewall-manager/libfirewall-manager.la \ - ./settings/libsettings.la \ - $(top_builddir)/libnm-util/libnm-util.la \ - $(DBUS_LIBS) \ - $(GLIB_LIBS) \ - $(GUDEV_LIBS) \ - $(LIBNL_LIBS) \ - $(POLKIT_LIBS) \ - $(SYSTEMD_LOGIN_LIBS) \ - $(LIBSOUP_LIBS) \ - $(LIBM) \ - $(LIBDL) - + nm-manager-glue.h \ + nm-ppp-manager-glue.h \ + nm-settings-connection-glue.h \ + nm-settings-glue.h \ + nm-vpn-connection-glue.h + +libNetworkManager_la_SOURCES = \ + $(nm_sources) \ + $(glue_sources) + +libNetworkManager_la_LIBADD = $(top_builddir)/libgsystem.la \ + $(top_builddir)/libnm-util/libnm-util.la $(DBUS_LIBS) \ + $(GLIB_LIBS) $(GUDEV_LIBS) $(LIBNL_LIBS) $(POLKIT_LIBS) \ + $(SYSTEMD_LOGIN_LIBS) $(LIBDL) $(LIBM) $(am__append_13) \ + $(am__append_14) NetworkManager_LDFLAGS = -rdynamic dbusservicedir = $(DBUS_SYS_DIR) dbusservice_DATA = org.freedesktop.NetworkManager.conf @@ -816,8 +890,9 @@ rundir = $(localstatedir)/run/NetworkManager statedir = $(localstatedir)/lib/NetworkManager CLEANFILES = \ $(BUILT_SOURCES) \ - nm-enum-types.c \ - nm-enum-types.h + settings/*-glue.h \ + devices/*-glue.h \ + devices/*/*-glue.h all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-recursive @@ -866,14 +941,8 @@ clean-noinstLTLIBRARIES: rm -f $${locs}; \ } -libtest-dhcp.la: $(libtest_dhcp_la_OBJECTS) $(libtest_dhcp_la_DEPENDENCIES) $(EXTRA_libtest_dhcp_la_DEPENDENCIES) - $(AM_V_CCLD)$(LINK) $(libtest_dhcp_la_OBJECTS) $(libtest_dhcp_la_LIBADD) $(LIBS) - -libtest-policy-hosts.la: $(libtest_policy_hosts_la_OBJECTS) $(libtest_policy_hosts_la_DEPENDENCIES) $(EXTRA_libtest_policy_hosts_la_DEPENDENCIES) - $(AM_V_CCLD)$(LINK) $(libtest_policy_hosts_la_OBJECTS) $(libtest_policy_hosts_la_LIBADD) $(LIBS) - -libtest-wifi-ap-utils.la: $(libtest_wifi_ap_utils_la_OBJECTS) $(libtest_wifi_ap_utils_la_DEPENDENCIES) $(EXTRA_libtest_wifi_ap_utils_la_DEPENDENCIES) - $(AM_V_CCLD)$(LINK) $(libtest_wifi_ap_utils_la_OBJECTS) $(libtest_wifi_ap_utils_la_LIBADD) $(LIBS) +libNetworkManager.la: $(libNetworkManager_la_OBJECTS) $(libNetworkManager_la_DEPENDENCIES) $(EXTRA_libNetworkManager_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libNetworkManager_la_OBJECTS) $(libNetworkManager_la_LIBADD) $(LIBS) install-sbinPROGRAMS: $(sbin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ @@ -934,58 +1003,95 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-NetworkManagerUtils.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-main.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-activation-request.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-active-connection.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-call-store.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-config.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-connection-provider.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-connectivity.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-dbus-manager.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-device-adsl.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-device-bond.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-device-bridge.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-device-bt.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-device-ethernet.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-device-infiniband.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-device-modem.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-device-olpc-mesh.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-device-vlan.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-device-wifi.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-device-wired.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-device.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-dhcp4-config.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-dhcp6-config.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-dispatcher.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-hostname-provider.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-ip4-config.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-ip6-config.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-manager-auth.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-manager.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-netlink-compat.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-netlink-monitor.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-netlink-utils.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-policy-hostname.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-policy-hosts.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-policy.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-properties-changed-signal.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-session-monitor-ck.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-session-monitor-null.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-session-monitor-systemd.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-session-utils.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-sleep-monitor-systemd.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-sleep-monitor-upower.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-system.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-udev-manager.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-wifi-ap-utils.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-wifi-ap.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtest_dhcp_la-nm-dbus-manager.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtest_dhcp_la-nm-hostname-provider.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtest_dhcp_la-nm-ip4-config.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtest_dhcp_la-nm-ip6-config.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtest_policy_hosts_la-nm-policy-hosts.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtest_wifi_ap_utils_la-nm-wifi-ap-utils.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManagerUtils.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/errors.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-activation-request.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-active-connection.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-agent-manager.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-auth-subject.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-call-store.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-config-device.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-config.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-connection-provider.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-connectivity.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-dbus-manager.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-dcb.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-device-bond.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-device-bridge.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-device-ethernet.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-device-factory.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-device-generic.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-device-gre.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-device-infiniband.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-device-macvlan.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-device-team.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-device-tun.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-device-veth.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-device-vlan.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-device-vxlan.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-device.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-dhcp-client.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-dhcp-dhclient-utils.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-dhcp-dhclient.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-dhcp-dhcpcd.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-dhcp-manager.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-dhcp4-config.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-dhcp6-config.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-dispatcher.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-dns-dnsmasq.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-dns-manager.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-dns-plugin.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-dns-unbound.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-dns-utils.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-dnsmasq-manager.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-dnsmasq-utils.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-enum-types.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-fake-platform.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-fake-rdisc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-firewall-manager.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-inotify-helper.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-ip4-config.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-ip6-config.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-keyfile-connection.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-linux-platform.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-lndp-rdisc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-logging.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-manager-auth.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-manager.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-platform.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-policy.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-posix-signals.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-ppp-manager.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-properties-changed-signal.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-rdisc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-rfkill-manager.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-secret-agent.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-session-monitor-ck.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-session-monitor-null.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-session-monitor-systemd.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-session-utils.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-settings-connection.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-settings-error.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-settings-utils.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-settings.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-sleep-monitor-systemd.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-sleep-monitor-upower.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-supplicant-config.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-supplicant-interface.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-supplicant-manager.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-supplicant-settings-verify.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-system-config-interface.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-vpn-connection.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-vpn-manager.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-vpn-service.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/reader.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wifi-utils-nl80211.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wifi-utils-wext.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wifi-utils.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/writer.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @@ -1008,691 +1114,446 @@ distclean-compile: @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< -libtest_dhcp_la-nm-ip4-config.lo: nm-ip4-config.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtest_dhcp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libtest_dhcp_la-nm-ip4-config.lo -MD -MP -MF $(DEPDIR)/libtest_dhcp_la-nm-ip4-config.Tpo -c -o libtest_dhcp_la-nm-ip4-config.lo `test -f 'nm-ip4-config.c' || echo '$(srcdir)/'`nm-ip4-config.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libtest_dhcp_la-nm-ip4-config.Tpo $(DEPDIR)/libtest_dhcp_la-nm-ip4-config.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-ip4-config.c' object='libtest_dhcp_la-nm-ip4-config.lo' libtool=yes @AMDEPBACKSLASH@ +nm-config.lo: config/nm-config.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-config.lo -MD -MP -MF $(DEPDIR)/nm-config.Tpo -c -o nm-config.lo `test -f 'config/nm-config.c' || echo '$(srcdir)/'`config/nm-config.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-config.Tpo $(DEPDIR)/nm-config.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='config/nm-config.c' object='nm-config.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtest_dhcp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libtest_dhcp_la-nm-ip4-config.lo `test -f 'nm-ip4-config.c' || echo '$(srcdir)/'`nm-ip4-config.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-config.lo `test -f 'config/nm-config.c' || echo '$(srcdir)/'`config/nm-config.c -libtest_dhcp_la-nm-ip6-config.lo: nm-ip6-config.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtest_dhcp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libtest_dhcp_la-nm-ip6-config.lo -MD -MP -MF $(DEPDIR)/libtest_dhcp_la-nm-ip6-config.Tpo -c -o libtest_dhcp_la-nm-ip6-config.lo `test -f 'nm-ip6-config.c' || echo '$(srcdir)/'`nm-ip6-config.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libtest_dhcp_la-nm-ip6-config.Tpo $(DEPDIR)/libtest_dhcp_la-nm-ip6-config.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-ip6-config.c' object='libtest_dhcp_la-nm-ip6-config.lo' libtool=yes @AMDEPBACKSLASH@ +nm-config-device.lo: config/nm-config-device.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-config-device.lo -MD -MP -MF $(DEPDIR)/nm-config-device.Tpo -c -o nm-config-device.lo `test -f 'config/nm-config-device.c' || echo '$(srcdir)/'`config/nm-config-device.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-config-device.Tpo $(DEPDIR)/nm-config-device.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='config/nm-config-device.c' object='nm-config-device.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtest_dhcp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libtest_dhcp_la-nm-ip6-config.lo `test -f 'nm-ip6-config.c' || echo '$(srcdir)/'`nm-ip6-config.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-config-device.lo `test -f 'config/nm-config-device.c' || echo '$(srcdir)/'`config/nm-config-device.c -libtest_dhcp_la-nm-hostname-provider.lo: nm-hostname-provider.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtest_dhcp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libtest_dhcp_la-nm-hostname-provider.lo -MD -MP -MF $(DEPDIR)/libtest_dhcp_la-nm-hostname-provider.Tpo -c -o libtest_dhcp_la-nm-hostname-provider.lo `test -f 'nm-hostname-provider.c' || echo '$(srcdir)/'`nm-hostname-provider.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libtest_dhcp_la-nm-hostname-provider.Tpo $(DEPDIR)/libtest_dhcp_la-nm-hostname-provider.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-hostname-provider.c' object='libtest_dhcp_la-nm-hostname-provider.lo' libtool=yes @AMDEPBACKSLASH@ +nm-device.lo: devices/nm-device.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-device.lo -MD -MP -MF $(DEPDIR)/nm-device.Tpo -c -o nm-device.lo `test -f 'devices/nm-device.c' || echo '$(srcdir)/'`devices/nm-device.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-device.Tpo $(DEPDIR)/nm-device.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='devices/nm-device.c' object='nm-device.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtest_dhcp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libtest_dhcp_la-nm-hostname-provider.lo `test -f 'nm-hostname-provider.c' || echo '$(srcdir)/'`nm-hostname-provider.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-device.lo `test -f 'devices/nm-device.c' || echo '$(srcdir)/'`devices/nm-device.c -libtest_dhcp_la-nm-dbus-manager.lo: nm-dbus-manager.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtest_dhcp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libtest_dhcp_la-nm-dbus-manager.lo -MD -MP -MF $(DEPDIR)/libtest_dhcp_la-nm-dbus-manager.Tpo -c -o libtest_dhcp_la-nm-dbus-manager.lo `test -f 'nm-dbus-manager.c' || echo '$(srcdir)/'`nm-dbus-manager.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libtest_dhcp_la-nm-dbus-manager.Tpo $(DEPDIR)/libtest_dhcp_la-nm-dbus-manager.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-dbus-manager.c' object='libtest_dhcp_la-nm-dbus-manager.lo' libtool=yes @AMDEPBACKSLASH@ +nm-device-bond.lo: devices/nm-device-bond.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-device-bond.lo -MD -MP -MF $(DEPDIR)/nm-device-bond.Tpo -c -o nm-device-bond.lo `test -f 'devices/nm-device-bond.c' || echo '$(srcdir)/'`devices/nm-device-bond.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-device-bond.Tpo $(DEPDIR)/nm-device-bond.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='devices/nm-device-bond.c' object='nm-device-bond.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtest_dhcp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libtest_dhcp_la-nm-dbus-manager.lo `test -f 'nm-dbus-manager.c' || echo '$(srcdir)/'`nm-dbus-manager.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-device-bond.lo `test -f 'devices/nm-device-bond.c' || echo '$(srcdir)/'`devices/nm-device-bond.c -libtest_policy_hosts_la-nm-policy-hosts.lo: nm-policy-hosts.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtest_policy_hosts_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libtest_policy_hosts_la-nm-policy-hosts.lo -MD -MP -MF $(DEPDIR)/libtest_policy_hosts_la-nm-policy-hosts.Tpo -c -o libtest_policy_hosts_la-nm-policy-hosts.lo `test -f 'nm-policy-hosts.c' || echo '$(srcdir)/'`nm-policy-hosts.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libtest_policy_hosts_la-nm-policy-hosts.Tpo $(DEPDIR)/libtest_policy_hosts_la-nm-policy-hosts.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-policy-hosts.c' object='libtest_policy_hosts_la-nm-policy-hosts.lo' libtool=yes @AMDEPBACKSLASH@ +nm-device-bridge.lo: devices/nm-device-bridge.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-device-bridge.lo -MD -MP -MF $(DEPDIR)/nm-device-bridge.Tpo -c -o nm-device-bridge.lo `test -f 'devices/nm-device-bridge.c' || echo '$(srcdir)/'`devices/nm-device-bridge.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-device-bridge.Tpo $(DEPDIR)/nm-device-bridge.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='devices/nm-device-bridge.c' object='nm-device-bridge.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtest_policy_hosts_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libtest_policy_hosts_la-nm-policy-hosts.lo `test -f 'nm-policy-hosts.c' || echo '$(srcdir)/'`nm-policy-hosts.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-device-bridge.lo `test -f 'devices/nm-device-bridge.c' || echo '$(srcdir)/'`devices/nm-device-bridge.c -libtest_wifi_ap_utils_la-nm-wifi-ap-utils.lo: nm-wifi-ap-utils.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtest_wifi_ap_utils_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libtest_wifi_ap_utils_la-nm-wifi-ap-utils.lo -MD -MP -MF $(DEPDIR)/libtest_wifi_ap_utils_la-nm-wifi-ap-utils.Tpo -c -o libtest_wifi_ap_utils_la-nm-wifi-ap-utils.lo `test -f 'nm-wifi-ap-utils.c' || echo '$(srcdir)/'`nm-wifi-ap-utils.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libtest_wifi_ap_utils_la-nm-wifi-ap-utils.Tpo $(DEPDIR)/libtest_wifi_ap_utils_la-nm-wifi-ap-utils.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-wifi-ap-utils.c' object='libtest_wifi_ap_utils_la-nm-wifi-ap-utils.lo' libtool=yes @AMDEPBACKSLASH@ +nm-device-ethernet.lo: devices/nm-device-ethernet.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-device-ethernet.lo -MD -MP -MF $(DEPDIR)/nm-device-ethernet.Tpo -c -o nm-device-ethernet.lo `test -f 'devices/nm-device-ethernet.c' || echo '$(srcdir)/'`devices/nm-device-ethernet.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-device-ethernet.Tpo $(DEPDIR)/nm-device-ethernet.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='devices/nm-device-ethernet.c' object='nm-device-ethernet.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtest_wifi_ap_utils_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libtest_wifi_ap_utils_la-nm-wifi-ap-utils.lo `test -f 'nm-wifi-ap-utils.c' || echo '$(srcdir)/'`nm-wifi-ap-utils.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-device-ethernet.lo `test -f 'devices/nm-device-ethernet.c' || echo '$(srcdir)/'`devices/nm-device-ethernet.c -NetworkManager-nm-call-store.o: nm-call-store.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-call-store.o -MD -MP -MF $(DEPDIR)/NetworkManager-nm-call-store.Tpo -c -o NetworkManager-nm-call-store.o `test -f 'nm-call-store.c' || echo '$(srcdir)/'`nm-call-store.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-call-store.Tpo $(DEPDIR)/NetworkManager-nm-call-store.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-call-store.c' object='NetworkManager-nm-call-store.o' libtool=no @AMDEPBACKSLASH@ +nm-device-factory.lo: devices/nm-device-factory.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-device-factory.lo -MD -MP -MF $(DEPDIR)/nm-device-factory.Tpo -c -o nm-device-factory.lo `test -f 'devices/nm-device-factory.c' || echo '$(srcdir)/'`devices/nm-device-factory.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-device-factory.Tpo $(DEPDIR)/nm-device-factory.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='devices/nm-device-factory.c' object='nm-device-factory.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-call-store.o `test -f 'nm-call-store.c' || echo '$(srcdir)/'`nm-call-store.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-device-factory.lo `test -f 'devices/nm-device-factory.c' || echo '$(srcdir)/'`devices/nm-device-factory.c -NetworkManager-nm-call-store.obj: nm-call-store.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-call-store.obj -MD -MP -MF $(DEPDIR)/NetworkManager-nm-call-store.Tpo -c -o NetworkManager-nm-call-store.obj `if test -f 'nm-call-store.c'; then $(CYGPATH_W) 'nm-call-store.c'; else $(CYGPATH_W) '$(srcdir)/nm-call-store.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-call-store.Tpo $(DEPDIR)/NetworkManager-nm-call-store.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-call-store.c' object='NetworkManager-nm-call-store.obj' libtool=no @AMDEPBACKSLASH@ +nm-device-generic.lo: devices/nm-device-generic.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-device-generic.lo -MD -MP -MF $(DEPDIR)/nm-device-generic.Tpo -c -o nm-device-generic.lo `test -f 'devices/nm-device-generic.c' || echo '$(srcdir)/'`devices/nm-device-generic.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-device-generic.Tpo $(DEPDIR)/nm-device-generic.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='devices/nm-device-generic.c' object='nm-device-generic.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-call-store.obj `if test -f 'nm-call-store.c'; then $(CYGPATH_W) 'nm-call-store.c'; else $(CYGPATH_W) '$(srcdir)/nm-call-store.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-device-generic.lo `test -f 'devices/nm-device-generic.c' || echo '$(srcdir)/'`devices/nm-device-generic.c -NetworkManager-nm-device.o: nm-device.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-device.o -MD -MP -MF $(DEPDIR)/NetworkManager-nm-device.Tpo -c -o NetworkManager-nm-device.o `test -f 'nm-device.c' || echo '$(srcdir)/'`nm-device.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-device.Tpo $(DEPDIR)/NetworkManager-nm-device.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-device.c' object='NetworkManager-nm-device.o' libtool=no @AMDEPBACKSLASH@ +nm-device-gre.lo: devices/nm-device-gre.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-device-gre.lo -MD -MP -MF $(DEPDIR)/nm-device-gre.Tpo -c -o nm-device-gre.lo `test -f 'devices/nm-device-gre.c' || echo '$(srcdir)/'`devices/nm-device-gre.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-device-gre.Tpo $(DEPDIR)/nm-device-gre.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='devices/nm-device-gre.c' object='nm-device-gre.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-device.o `test -f 'nm-device.c' || echo '$(srcdir)/'`nm-device.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-device-gre.lo `test -f 'devices/nm-device-gre.c' || echo '$(srcdir)/'`devices/nm-device-gre.c -NetworkManager-nm-device.obj: nm-device.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-device.obj -MD -MP -MF $(DEPDIR)/NetworkManager-nm-device.Tpo -c -o NetworkManager-nm-device.obj `if test -f 'nm-device.c'; then $(CYGPATH_W) 'nm-device.c'; else $(CYGPATH_W) '$(srcdir)/nm-device.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-device.Tpo $(DEPDIR)/NetworkManager-nm-device.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-device.c' object='NetworkManager-nm-device.obj' libtool=no @AMDEPBACKSLASH@ +nm-device-infiniband.lo: devices/nm-device-infiniband.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-device-infiniband.lo -MD -MP -MF $(DEPDIR)/nm-device-infiniband.Tpo -c -o nm-device-infiniband.lo `test -f 'devices/nm-device-infiniband.c' || echo '$(srcdir)/'`devices/nm-device-infiniband.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-device-infiniband.Tpo $(DEPDIR)/nm-device-infiniband.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='devices/nm-device-infiniband.c' object='nm-device-infiniband.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-device.obj `if test -f 'nm-device.c'; then $(CYGPATH_W) 'nm-device.c'; else $(CYGPATH_W) '$(srcdir)/nm-device.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-device-infiniband.lo `test -f 'devices/nm-device-infiniband.c' || echo '$(srcdir)/'`devices/nm-device-infiniband.c -NetworkManager-nm-device-ethernet.o: nm-device-ethernet.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-device-ethernet.o -MD -MP -MF $(DEPDIR)/NetworkManager-nm-device-ethernet.Tpo -c -o NetworkManager-nm-device-ethernet.o `test -f 'nm-device-ethernet.c' || echo '$(srcdir)/'`nm-device-ethernet.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-device-ethernet.Tpo $(DEPDIR)/NetworkManager-nm-device-ethernet.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-device-ethernet.c' object='NetworkManager-nm-device-ethernet.o' libtool=no @AMDEPBACKSLASH@ +nm-device-macvlan.lo: devices/nm-device-macvlan.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-device-macvlan.lo -MD -MP -MF $(DEPDIR)/nm-device-macvlan.Tpo -c -o nm-device-macvlan.lo `test -f 'devices/nm-device-macvlan.c' || echo '$(srcdir)/'`devices/nm-device-macvlan.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-device-macvlan.Tpo $(DEPDIR)/nm-device-macvlan.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='devices/nm-device-macvlan.c' object='nm-device-macvlan.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-device-ethernet.o `test -f 'nm-device-ethernet.c' || echo '$(srcdir)/'`nm-device-ethernet.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-device-macvlan.lo `test -f 'devices/nm-device-macvlan.c' || echo '$(srcdir)/'`devices/nm-device-macvlan.c -NetworkManager-nm-device-ethernet.obj: nm-device-ethernet.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-device-ethernet.obj -MD -MP -MF $(DEPDIR)/NetworkManager-nm-device-ethernet.Tpo -c -o NetworkManager-nm-device-ethernet.obj `if test -f 'nm-device-ethernet.c'; then $(CYGPATH_W) 'nm-device-ethernet.c'; else $(CYGPATH_W) '$(srcdir)/nm-device-ethernet.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-device-ethernet.Tpo $(DEPDIR)/NetworkManager-nm-device-ethernet.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-device-ethernet.c' object='NetworkManager-nm-device-ethernet.obj' libtool=no @AMDEPBACKSLASH@ +nm-device-team.lo: devices/nm-device-team.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-device-team.lo -MD -MP -MF $(DEPDIR)/nm-device-team.Tpo -c -o nm-device-team.lo `test -f 'devices/nm-device-team.c' || echo '$(srcdir)/'`devices/nm-device-team.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-device-team.Tpo $(DEPDIR)/nm-device-team.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='devices/nm-device-team.c' object='nm-device-team.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-device-ethernet.obj `if test -f 'nm-device-ethernet.c'; then $(CYGPATH_W) 'nm-device-ethernet.c'; else $(CYGPATH_W) '$(srcdir)/nm-device-ethernet.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-device-team.lo `test -f 'devices/nm-device-team.c' || echo '$(srcdir)/'`devices/nm-device-team.c -NetworkManager-nm-device-adsl.o: nm-device-adsl.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-device-adsl.o -MD -MP -MF $(DEPDIR)/NetworkManager-nm-device-adsl.Tpo -c -o NetworkManager-nm-device-adsl.o `test -f 'nm-device-adsl.c' || echo '$(srcdir)/'`nm-device-adsl.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-device-adsl.Tpo $(DEPDIR)/NetworkManager-nm-device-adsl.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-device-adsl.c' object='NetworkManager-nm-device-adsl.o' libtool=no @AMDEPBACKSLASH@ +nm-device-tun.lo: devices/nm-device-tun.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-device-tun.lo -MD -MP -MF $(DEPDIR)/nm-device-tun.Tpo -c -o nm-device-tun.lo `test -f 'devices/nm-device-tun.c' || echo '$(srcdir)/'`devices/nm-device-tun.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-device-tun.Tpo $(DEPDIR)/nm-device-tun.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='devices/nm-device-tun.c' object='nm-device-tun.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-device-adsl.o `test -f 'nm-device-adsl.c' || echo '$(srcdir)/'`nm-device-adsl.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-device-tun.lo `test -f 'devices/nm-device-tun.c' || echo '$(srcdir)/'`devices/nm-device-tun.c -NetworkManager-nm-device-adsl.obj: nm-device-adsl.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-device-adsl.obj -MD -MP -MF $(DEPDIR)/NetworkManager-nm-device-adsl.Tpo -c -o NetworkManager-nm-device-adsl.obj `if test -f 'nm-device-adsl.c'; then $(CYGPATH_W) 'nm-device-adsl.c'; else $(CYGPATH_W) '$(srcdir)/nm-device-adsl.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-device-adsl.Tpo $(DEPDIR)/NetworkManager-nm-device-adsl.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-device-adsl.c' object='NetworkManager-nm-device-adsl.obj' libtool=no @AMDEPBACKSLASH@ +nm-device-veth.lo: devices/nm-device-veth.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-device-veth.lo -MD -MP -MF $(DEPDIR)/nm-device-veth.Tpo -c -o nm-device-veth.lo `test -f 'devices/nm-device-veth.c' || echo '$(srcdir)/'`devices/nm-device-veth.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-device-veth.Tpo $(DEPDIR)/nm-device-veth.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='devices/nm-device-veth.c' object='nm-device-veth.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-device-adsl.obj `if test -f 'nm-device-adsl.c'; then $(CYGPATH_W) 'nm-device-adsl.c'; else $(CYGPATH_W) '$(srcdir)/nm-device-adsl.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-device-veth.lo `test -f 'devices/nm-device-veth.c' || echo '$(srcdir)/'`devices/nm-device-veth.c -NetworkManager-nm-device-wifi.o: nm-device-wifi.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-device-wifi.o -MD -MP -MF $(DEPDIR)/NetworkManager-nm-device-wifi.Tpo -c -o NetworkManager-nm-device-wifi.o `test -f 'nm-device-wifi.c' || echo '$(srcdir)/'`nm-device-wifi.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-device-wifi.Tpo $(DEPDIR)/NetworkManager-nm-device-wifi.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-device-wifi.c' object='NetworkManager-nm-device-wifi.o' libtool=no @AMDEPBACKSLASH@ +nm-device-vlan.lo: devices/nm-device-vlan.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-device-vlan.lo -MD -MP -MF $(DEPDIR)/nm-device-vlan.Tpo -c -o nm-device-vlan.lo `test -f 'devices/nm-device-vlan.c' || echo '$(srcdir)/'`devices/nm-device-vlan.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-device-vlan.Tpo $(DEPDIR)/nm-device-vlan.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='devices/nm-device-vlan.c' object='nm-device-vlan.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-device-wifi.o `test -f 'nm-device-wifi.c' || echo '$(srcdir)/'`nm-device-wifi.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-device-vlan.lo `test -f 'devices/nm-device-vlan.c' || echo '$(srcdir)/'`devices/nm-device-vlan.c -NetworkManager-nm-device-wifi.obj: nm-device-wifi.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-device-wifi.obj -MD -MP -MF $(DEPDIR)/NetworkManager-nm-device-wifi.Tpo -c -o NetworkManager-nm-device-wifi.obj `if test -f 'nm-device-wifi.c'; then $(CYGPATH_W) 'nm-device-wifi.c'; else $(CYGPATH_W) '$(srcdir)/nm-device-wifi.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-device-wifi.Tpo $(DEPDIR)/NetworkManager-nm-device-wifi.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-device-wifi.c' object='NetworkManager-nm-device-wifi.obj' libtool=no @AMDEPBACKSLASH@ +nm-device-vxlan.lo: devices/nm-device-vxlan.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-device-vxlan.lo -MD -MP -MF $(DEPDIR)/nm-device-vxlan.Tpo -c -o nm-device-vxlan.lo `test -f 'devices/nm-device-vxlan.c' || echo '$(srcdir)/'`devices/nm-device-vxlan.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-device-vxlan.Tpo $(DEPDIR)/nm-device-vxlan.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='devices/nm-device-vxlan.c' object='nm-device-vxlan.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-device-wifi.obj `if test -f 'nm-device-wifi.c'; then $(CYGPATH_W) 'nm-device-wifi.c'; else $(CYGPATH_W) '$(srcdir)/nm-device-wifi.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-device-vxlan.lo `test -f 'devices/nm-device-vxlan.c' || echo '$(srcdir)/'`devices/nm-device-vxlan.c -NetworkManager-nm-device-wired.o: nm-device-wired.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-device-wired.o -MD -MP -MF $(DEPDIR)/NetworkManager-nm-device-wired.Tpo -c -o NetworkManager-nm-device-wired.o `test -f 'nm-device-wired.c' || echo '$(srcdir)/'`nm-device-wired.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-device-wired.Tpo $(DEPDIR)/NetworkManager-nm-device-wired.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-device-wired.c' object='NetworkManager-nm-device-wired.o' libtool=no @AMDEPBACKSLASH@ +nm-dhcp-client.lo: dhcp-manager/nm-dhcp-client.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-dhcp-client.lo -MD -MP -MF $(DEPDIR)/nm-dhcp-client.Tpo -c -o nm-dhcp-client.lo `test -f 'dhcp-manager/nm-dhcp-client.c' || echo '$(srcdir)/'`dhcp-manager/nm-dhcp-client.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-dhcp-client.Tpo $(DEPDIR)/nm-dhcp-client.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dhcp-manager/nm-dhcp-client.c' object='nm-dhcp-client.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-device-wired.o `test -f 'nm-device-wired.c' || echo '$(srcdir)/'`nm-device-wired.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-dhcp-client.lo `test -f 'dhcp-manager/nm-dhcp-client.c' || echo '$(srcdir)/'`dhcp-manager/nm-dhcp-client.c -NetworkManager-nm-device-wired.obj: nm-device-wired.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-device-wired.obj -MD -MP -MF $(DEPDIR)/NetworkManager-nm-device-wired.Tpo -c -o NetworkManager-nm-device-wired.obj `if test -f 'nm-device-wired.c'; then $(CYGPATH_W) 'nm-device-wired.c'; else $(CYGPATH_W) '$(srcdir)/nm-device-wired.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-device-wired.Tpo $(DEPDIR)/NetworkManager-nm-device-wired.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-device-wired.c' object='NetworkManager-nm-device-wired.obj' libtool=no @AMDEPBACKSLASH@ +nm-dhcp-dhclient.lo: dhcp-manager/nm-dhcp-dhclient.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-dhcp-dhclient.lo -MD -MP -MF $(DEPDIR)/nm-dhcp-dhclient.Tpo -c -o nm-dhcp-dhclient.lo `test -f 'dhcp-manager/nm-dhcp-dhclient.c' || echo '$(srcdir)/'`dhcp-manager/nm-dhcp-dhclient.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-dhcp-dhclient.Tpo $(DEPDIR)/nm-dhcp-dhclient.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dhcp-manager/nm-dhcp-dhclient.c' object='nm-dhcp-dhclient.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-device-wired.obj `if test -f 'nm-device-wired.c'; then $(CYGPATH_W) 'nm-device-wired.c'; else $(CYGPATH_W) '$(srcdir)/nm-device-wired.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-dhcp-dhclient.lo `test -f 'dhcp-manager/nm-dhcp-dhclient.c' || echo '$(srcdir)/'`dhcp-manager/nm-dhcp-dhclient.c -NetworkManager-nm-device-olpc-mesh.o: nm-device-olpc-mesh.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-device-olpc-mesh.o -MD -MP -MF $(DEPDIR)/NetworkManager-nm-device-olpc-mesh.Tpo -c -o NetworkManager-nm-device-olpc-mesh.o `test -f 'nm-device-olpc-mesh.c' || echo '$(srcdir)/'`nm-device-olpc-mesh.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-device-olpc-mesh.Tpo $(DEPDIR)/NetworkManager-nm-device-olpc-mesh.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-device-olpc-mesh.c' object='NetworkManager-nm-device-olpc-mesh.o' libtool=no @AMDEPBACKSLASH@ +nm-dhcp-dhclient-utils.lo: dhcp-manager/nm-dhcp-dhclient-utils.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-dhcp-dhclient-utils.lo -MD -MP -MF $(DEPDIR)/nm-dhcp-dhclient-utils.Tpo -c -o nm-dhcp-dhclient-utils.lo `test -f 'dhcp-manager/nm-dhcp-dhclient-utils.c' || echo '$(srcdir)/'`dhcp-manager/nm-dhcp-dhclient-utils.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-dhcp-dhclient-utils.Tpo $(DEPDIR)/nm-dhcp-dhclient-utils.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dhcp-manager/nm-dhcp-dhclient-utils.c' object='nm-dhcp-dhclient-utils.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-device-olpc-mesh.o `test -f 'nm-device-olpc-mesh.c' || echo '$(srcdir)/'`nm-device-olpc-mesh.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-dhcp-dhclient-utils.lo `test -f 'dhcp-manager/nm-dhcp-dhclient-utils.c' || echo '$(srcdir)/'`dhcp-manager/nm-dhcp-dhclient-utils.c -NetworkManager-nm-device-olpc-mesh.obj: nm-device-olpc-mesh.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-device-olpc-mesh.obj -MD -MP -MF $(DEPDIR)/NetworkManager-nm-device-olpc-mesh.Tpo -c -o NetworkManager-nm-device-olpc-mesh.obj `if test -f 'nm-device-olpc-mesh.c'; then $(CYGPATH_W) 'nm-device-olpc-mesh.c'; else $(CYGPATH_W) '$(srcdir)/nm-device-olpc-mesh.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-device-olpc-mesh.Tpo $(DEPDIR)/NetworkManager-nm-device-olpc-mesh.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-device-olpc-mesh.c' object='NetworkManager-nm-device-olpc-mesh.obj' libtool=no @AMDEPBACKSLASH@ +nm-dhcp-dhcpcd.lo: dhcp-manager/nm-dhcp-dhcpcd.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-dhcp-dhcpcd.lo -MD -MP -MF $(DEPDIR)/nm-dhcp-dhcpcd.Tpo -c -o nm-dhcp-dhcpcd.lo `test -f 'dhcp-manager/nm-dhcp-dhcpcd.c' || echo '$(srcdir)/'`dhcp-manager/nm-dhcp-dhcpcd.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-dhcp-dhcpcd.Tpo $(DEPDIR)/nm-dhcp-dhcpcd.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dhcp-manager/nm-dhcp-dhcpcd.c' object='nm-dhcp-dhcpcd.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-device-olpc-mesh.obj `if test -f 'nm-device-olpc-mesh.c'; then $(CYGPATH_W) 'nm-device-olpc-mesh.c'; else $(CYGPATH_W) '$(srcdir)/nm-device-olpc-mesh.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-dhcp-dhcpcd.lo `test -f 'dhcp-manager/nm-dhcp-dhcpcd.c' || echo '$(srcdir)/'`dhcp-manager/nm-dhcp-dhcpcd.c -NetworkManager-nm-device-bt.o: nm-device-bt.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-device-bt.o -MD -MP -MF $(DEPDIR)/NetworkManager-nm-device-bt.Tpo -c -o NetworkManager-nm-device-bt.o `test -f 'nm-device-bt.c' || echo '$(srcdir)/'`nm-device-bt.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-device-bt.Tpo $(DEPDIR)/NetworkManager-nm-device-bt.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-device-bt.c' object='NetworkManager-nm-device-bt.o' libtool=no @AMDEPBACKSLASH@ +nm-dhcp-manager.lo: dhcp-manager/nm-dhcp-manager.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-dhcp-manager.lo -MD -MP -MF $(DEPDIR)/nm-dhcp-manager.Tpo -c -o nm-dhcp-manager.lo `test -f 'dhcp-manager/nm-dhcp-manager.c' || echo '$(srcdir)/'`dhcp-manager/nm-dhcp-manager.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-dhcp-manager.Tpo $(DEPDIR)/nm-dhcp-manager.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dhcp-manager/nm-dhcp-manager.c' object='nm-dhcp-manager.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-device-bt.o `test -f 'nm-device-bt.c' || echo '$(srcdir)/'`nm-device-bt.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-dhcp-manager.lo `test -f 'dhcp-manager/nm-dhcp-manager.c' || echo '$(srcdir)/'`dhcp-manager/nm-dhcp-manager.c -NetworkManager-nm-device-bt.obj: nm-device-bt.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-device-bt.obj -MD -MP -MF $(DEPDIR)/NetworkManager-nm-device-bt.Tpo -c -o NetworkManager-nm-device-bt.obj `if test -f 'nm-device-bt.c'; then $(CYGPATH_W) 'nm-device-bt.c'; else $(CYGPATH_W) '$(srcdir)/nm-device-bt.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-device-bt.Tpo $(DEPDIR)/NetworkManager-nm-device-bt.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-device-bt.c' object='NetworkManager-nm-device-bt.obj' libtool=no @AMDEPBACKSLASH@ +nm-dns-dnsmasq.lo: dns-manager/nm-dns-dnsmasq.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-dns-dnsmasq.lo -MD -MP -MF $(DEPDIR)/nm-dns-dnsmasq.Tpo -c -o nm-dns-dnsmasq.lo `test -f 'dns-manager/nm-dns-dnsmasq.c' || echo '$(srcdir)/'`dns-manager/nm-dns-dnsmasq.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-dns-dnsmasq.Tpo $(DEPDIR)/nm-dns-dnsmasq.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dns-manager/nm-dns-dnsmasq.c' object='nm-dns-dnsmasq.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-device-bt.obj `if test -f 'nm-device-bt.c'; then $(CYGPATH_W) 'nm-device-bt.c'; else $(CYGPATH_W) '$(srcdir)/nm-device-bt.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-dns-dnsmasq.lo `test -f 'dns-manager/nm-dns-dnsmasq.c' || echo '$(srcdir)/'`dns-manager/nm-dns-dnsmasq.c -NetworkManager-nm-device-modem.o: nm-device-modem.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-device-modem.o -MD -MP -MF $(DEPDIR)/NetworkManager-nm-device-modem.Tpo -c -o NetworkManager-nm-device-modem.o `test -f 'nm-device-modem.c' || echo '$(srcdir)/'`nm-device-modem.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-device-modem.Tpo $(DEPDIR)/NetworkManager-nm-device-modem.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-device-modem.c' object='NetworkManager-nm-device-modem.o' libtool=no @AMDEPBACKSLASH@ +nm-dns-unbound.lo: dns-manager/nm-dns-unbound.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-dns-unbound.lo -MD -MP -MF $(DEPDIR)/nm-dns-unbound.Tpo -c -o nm-dns-unbound.lo `test -f 'dns-manager/nm-dns-unbound.c' || echo '$(srcdir)/'`dns-manager/nm-dns-unbound.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-dns-unbound.Tpo $(DEPDIR)/nm-dns-unbound.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dns-manager/nm-dns-unbound.c' object='nm-dns-unbound.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-device-modem.o `test -f 'nm-device-modem.c' || echo '$(srcdir)/'`nm-device-modem.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-dns-unbound.lo `test -f 'dns-manager/nm-dns-unbound.c' || echo '$(srcdir)/'`dns-manager/nm-dns-unbound.c -NetworkManager-nm-device-modem.obj: nm-device-modem.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-device-modem.obj -MD -MP -MF $(DEPDIR)/NetworkManager-nm-device-modem.Tpo -c -o NetworkManager-nm-device-modem.obj `if test -f 'nm-device-modem.c'; then $(CYGPATH_W) 'nm-device-modem.c'; else $(CYGPATH_W) '$(srcdir)/nm-device-modem.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-device-modem.Tpo $(DEPDIR)/NetworkManager-nm-device-modem.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-device-modem.c' object='NetworkManager-nm-device-modem.obj' libtool=no @AMDEPBACKSLASH@ +nm-dns-manager.lo: dns-manager/nm-dns-manager.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-dns-manager.lo -MD -MP -MF $(DEPDIR)/nm-dns-manager.Tpo -c -o nm-dns-manager.lo `test -f 'dns-manager/nm-dns-manager.c' || echo '$(srcdir)/'`dns-manager/nm-dns-manager.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-dns-manager.Tpo $(DEPDIR)/nm-dns-manager.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dns-manager/nm-dns-manager.c' object='nm-dns-manager.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-device-modem.obj `if test -f 'nm-device-modem.c'; then $(CYGPATH_W) 'nm-device-modem.c'; else $(CYGPATH_W) '$(srcdir)/nm-device-modem.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-dns-manager.lo `test -f 'dns-manager/nm-dns-manager.c' || echo '$(srcdir)/'`dns-manager/nm-dns-manager.c -NetworkManager-nm-device-infiniband.o: nm-device-infiniband.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-device-infiniband.o -MD -MP -MF $(DEPDIR)/NetworkManager-nm-device-infiniband.Tpo -c -o NetworkManager-nm-device-infiniband.o `test -f 'nm-device-infiniband.c' || echo '$(srcdir)/'`nm-device-infiniband.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-device-infiniband.Tpo $(DEPDIR)/NetworkManager-nm-device-infiniband.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-device-infiniband.c' object='NetworkManager-nm-device-infiniband.o' libtool=no @AMDEPBACKSLASH@ +nm-dns-plugin.lo: dns-manager/nm-dns-plugin.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-dns-plugin.lo -MD -MP -MF $(DEPDIR)/nm-dns-plugin.Tpo -c -o nm-dns-plugin.lo `test -f 'dns-manager/nm-dns-plugin.c' || echo '$(srcdir)/'`dns-manager/nm-dns-plugin.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-dns-plugin.Tpo $(DEPDIR)/nm-dns-plugin.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dns-manager/nm-dns-plugin.c' object='nm-dns-plugin.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-device-infiniband.o `test -f 'nm-device-infiniband.c' || echo '$(srcdir)/'`nm-device-infiniband.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-dns-plugin.lo `test -f 'dns-manager/nm-dns-plugin.c' || echo '$(srcdir)/'`dns-manager/nm-dns-plugin.c -NetworkManager-nm-device-infiniband.obj: nm-device-infiniband.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-device-infiniband.obj -MD -MP -MF $(DEPDIR)/NetworkManager-nm-device-infiniband.Tpo -c -o NetworkManager-nm-device-infiniband.obj `if test -f 'nm-device-infiniband.c'; then $(CYGPATH_W) 'nm-device-infiniband.c'; else $(CYGPATH_W) '$(srcdir)/nm-device-infiniband.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-device-infiniband.Tpo $(DEPDIR)/NetworkManager-nm-device-infiniband.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-device-infiniband.c' object='NetworkManager-nm-device-infiniband.obj' libtool=no @AMDEPBACKSLASH@ +nm-dns-utils.lo: dns-manager/nm-dns-utils.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-dns-utils.lo -MD -MP -MF $(DEPDIR)/nm-dns-utils.Tpo -c -o nm-dns-utils.lo `test -f 'dns-manager/nm-dns-utils.c' || echo '$(srcdir)/'`dns-manager/nm-dns-utils.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-dns-utils.Tpo $(DEPDIR)/nm-dns-utils.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dns-manager/nm-dns-utils.c' object='nm-dns-utils.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-device-infiniband.obj `if test -f 'nm-device-infiniband.c'; then $(CYGPATH_W) 'nm-device-infiniband.c'; else $(CYGPATH_W) '$(srcdir)/nm-device-infiniband.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-dns-utils.lo `test -f 'dns-manager/nm-dns-utils.c' || echo '$(srcdir)/'`dns-manager/nm-dns-utils.c -NetworkManager-nm-device-bond.o: nm-device-bond.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-device-bond.o -MD -MP -MF $(DEPDIR)/NetworkManager-nm-device-bond.Tpo -c -o NetworkManager-nm-device-bond.o `test -f 'nm-device-bond.c' || echo '$(srcdir)/'`nm-device-bond.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-device-bond.Tpo $(DEPDIR)/NetworkManager-nm-device-bond.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-device-bond.c' object='NetworkManager-nm-device-bond.o' libtool=no @AMDEPBACKSLASH@ +nm-dnsmasq-manager.lo: dnsmasq-manager/nm-dnsmasq-manager.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-dnsmasq-manager.lo -MD -MP -MF $(DEPDIR)/nm-dnsmasq-manager.Tpo -c -o nm-dnsmasq-manager.lo `test -f 'dnsmasq-manager/nm-dnsmasq-manager.c' || echo '$(srcdir)/'`dnsmasq-manager/nm-dnsmasq-manager.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-dnsmasq-manager.Tpo $(DEPDIR)/nm-dnsmasq-manager.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dnsmasq-manager/nm-dnsmasq-manager.c' object='nm-dnsmasq-manager.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-device-bond.o `test -f 'nm-device-bond.c' || echo '$(srcdir)/'`nm-device-bond.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-dnsmasq-manager.lo `test -f 'dnsmasq-manager/nm-dnsmasq-manager.c' || echo '$(srcdir)/'`dnsmasq-manager/nm-dnsmasq-manager.c -NetworkManager-nm-device-bond.obj: nm-device-bond.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-device-bond.obj -MD -MP -MF $(DEPDIR)/NetworkManager-nm-device-bond.Tpo -c -o NetworkManager-nm-device-bond.obj `if test -f 'nm-device-bond.c'; then $(CYGPATH_W) 'nm-device-bond.c'; else $(CYGPATH_W) '$(srcdir)/nm-device-bond.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-device-bond.Tpo $(DEPDIR)/NetworkManager-nm-device-bond.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-device-bond.c' object='NetworkManager-nm-device-bond.obj' libtool=no @AMDEPBACKSLASH@ +nm-dnsmasq-utils.lo: dnsmasq-manager/nm-dnsmasq-utils.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-dnsmasq-utils.lo -MD -MP -MF $(DEPDIR)/nm-dnsmasq-utils.Tpo -c -o nm-dnsmasq-utils.lo `test -f 'dnsmasq-manager/nm-dnsmasq-utils.c' || echo '$(srcdir)/'`dnsmasq-manager/nm-dnsmasq-utils.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-dnsmasq-utils.Tpo $(DEPDIR)/nm-dnsmasq-utils.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dnsmasq-manager/nm-dnsmasq-utils.c' object='nm-dnsmasq-utils.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-device-bond.obj `if test -f 'nm-device-bond.c'; then $(CYGPATH_W) 'nm-device-bond.c'; else $(CYGPATH_W) '$(srcdir)/nm-device-bond.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-dnsmasq-utils.lo `test -f 'dnsmasq-manager/nm-dnsmasq-utils.c' || echo '$(srcdir)/'`dnsmasq-manager/nm-dnsmasq-utils.c -NetworkManager-nm-device-bridge.o: nm-device-bridge.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-device-bridge.o -MD -MP -MF $(DEPDIR)/NetworkManager-nm-device-bridge.Tpo -c -o NetworkManager-nm-device-bridge.o `test -f 'nm-device-bridge.c' || echo '$(srcdir)/'`nm-device-bridge.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-device-bridge.Tpo $(DEPDIR)/NetworkManager-nm-device-bridge.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-device-bridge.c' object='NetworkManager-nm-device-bridge.o' libtool=no @AMDEPBACKSLASH@ +nm-firewall-manager.lo: firewall-manager/nm-firewall-manager.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-firewall-manager.lo -MD -MP -MF $(DEPDIR)/nm-firewall-manager.Tpo -c -o nm-firewall-manager.lo `test -f 'firewall-manager/nm-firewall-manager.c' || echo '$(srcdir)/'`firewall-manager/nm-firewall-manager.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-firewall-manager.Tpo $(DEPDIR)/nm-firewall-manager.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='firewall-manager/nm-firewall-manager.c' object='nm-firewall-manager.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-device-bridge.o `test -f 'nm-device-bridge.c' || echo '$(srcdir)/'`nm-device-bridge.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-firewall-manager.lo `test -f 'firewall-manager/nm-firewall-manager.c' || echo '$(srcdir)/'`firewall-manager/nm-firewall-manager.c -NetworkManager-nm-device-bridge.obj: nm-device-bridge.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-device-bridge.obj -MD -MP -MF $(DEPDIR)/NetworkManager-nm-device-bridge.Tpo -c -o NetworkManager-nm-device-bridge.obj `if test -f 'nm-device-bridge.c'; then $(CYGPATH_W) 'nm-device-bridge.c'; else $(CYGPATH_W) '$(srcdir)/nm-device-bridge.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-device-bridge.Tpo $(DEPDIR)/NetworkManager-nm-device-bridge.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-device-bridge.c' object='NetworkManager-nm-device-bridge.obj' libtool=no @AMDEPBACKSLASH@ +nm-logging.lo: logging/nm-logging.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-logging.lo -MD -MP -MF $(DEPDIR)/nm-logging.Tpo -c -o nm-logging.lo `test -f 'logging/nm-logging.c' || echo '$(srcdir)/'`logging/nm-logging.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-logging.Tpo $(DEPDIR)/nm-logging.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='logging/nm-logging.c' object='nm-logging.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-device-bridge.obj `if test -f 'nm-device-bridge.c'; then $(CYGPATH_W) 'nm-device-bridge.c'; else $(CYGPATH_W) '$(srcdir)/nm-device-bridge.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-logging.lo `test -f 'logging/nm-logging.c' || echo '$(srcdir)/'`logging/nm-logging.c -NetworkManager-nm-device-vlan.o: nm-device-vlan.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-device-vlan.o -MD -MP -MF $(DEPDIR)/NetworkManager-nm-device-vlan.Tpo -c -o NetworkManager-nm-device-vlan.o `test -f 'nm-device-vlan.c' || echo '$(srcdir)/'`nm-device-vlan.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-device-vlan.Tpo $(DEPDIR)/NetworkManager-nm-device-vlan.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-device-vlan.c' object='NetworkManager-nm-device-vlan.o' libtool=no @AMDEPBACKSLASH@ +nm-fake-platform.lo: platform/nm-fake-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-fake-platform.lo -MD -MP -MF $(DEPDIR)/nm-fake-platform.Tpo -c -o nm-fake-platform.lo `test -f 'platform/nm-fake-platform.c' || echo '$(srcdir)/'`platform/nm-fake-platform.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-fake-platform.Tpo $(DEPDIR)/nm-fake-platform.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='platform/nm-fake-platform.c' object='nm-fake-platform.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-device-vlan.o `test -f 'nm-device-vlan.c' || echo '$(srcdir)/'`nm-device-vlan.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-fake-platform.lo `test -f 'platform/nm-fake-platform.c' || echo '$(srcdir)/'`platform/nm-fake-platform.c -NetworkManager-nm-device-vlan.obj: nm-device-vlan.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-device-vlan.obj -MD -MP -MF $(DEPDIR)/NetworkManager-nm-device-vlan.Tpo -c -o NetworkManager-nm-device-vlan.obj `if test -f 'nm-device-vlan.c'; then $(CYGPATH_W) 'nm-device-vlan.c'; else $(CYGPATH_W) '$(srcdir)/nm-device-vlan.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-device-vlan.Tpo $(DEPDIR)/NetworkManager-nm-device-vlan.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-device-vlan.c' object='NetworkManager-nm-device-vlan.obj' libtool=no @AMDEPBACKSLASH@ +nm-linux-platform.lo: platform/nm-linux-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-linux-platform.lo -MD -MP -MF $(DEPDIR)/nm-linux-platform.Tpo -c -o nm-linux-platform.lo `test -f 'platform/nm-linux-platform.c' || echo '$(srcdir)/'`platform/nm-linux-platform.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-linux-platform.Tpo $(DEPDIR)/nm-linux-platform.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='platform/nm-linux-platform.c' object='nm-linux-platform.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-device-vlan.obj `if test -f 'nm-device-vlan.c'; then $(CYGPATH_W) 'nm-device-vlan.c'; else $(CYGPATH_W) '$(srcdir)/nm-device-vlan.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-linux-platform.lo `test -f 'platform/nm-linux-platform.c' || echo '$(srcdir)/'`platform/nm-linux-platform.c -NetworkManager-nm-wifi-ap.o: nm-wifi-ap.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-wifi-ap.o -MD -MP -MF $(DEPDIR)/NetworkManager-nm-wifi-ap.Tpo -c -o NetworkManager-nm-wifi-ap.o `test -f 'nm-wifi-ap.c' || echo '$(srcdir)/'`nm-wifi-ap.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-wifi-ap.Tpo $(DEPDIR)/NetworkManager-nm-wifi-ap.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-wifi-ap.c' object='NetworkManager-nm-wifi-ap.o' libtool=no @AMDEPBACKSLASH@ +nm-platform.lo: platform/nm-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-platform.lo -MD -MP -MF $(DEPDIR)/nm-platform.Tpo -c -o nm-platform.lo `test -f 'platform/nm-platform.c' || echo '$(srcdir)/'`platform/nm-platform.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-platform.Tpo $(DEPDIR)/nm-platform.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='platform/nm-platform.c' object='nm-platform.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-wifi-ap.o `test -f 'nm-wifi-ap.c' || echo '$(srcdir)/'`nm-wifi-ap.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-platform.lo `test -f 'platform/nm-platform.c' || echo '$(srcdir)/'`platform/nm-platform.c -NetworkManager-nm-wifi-ap.obj: nm-wifi-ap.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-wifi-ap.obj -MD -MP -MF $(DEPDIR)/NetworkManager-nm-wifi-ap.Tpo -c -o NetworkManager-nm-wifi-ap.obj `if test -f 'nm-wifi-ap.c'; then $(CYGPATH_W) 'nm-wifi-ap.c'; else $(CYGPATH_W) '$(srcdir)/nm-wifi-ap.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-wifi-ap.Tpo $(DEPDIR)/NetworkManager-nm-wifi-ap.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-wifi-ap.c' object='NetworkManager-nm-wifi-ap.obj' libtool=no @AMDEPBACKSLASH@ +wifi-utils-nl80211.lo: platform/wifi/wifi-utils-nl80211.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT wifi-utils-nl80211.lo -MD -MP -MF $(DEPDIR)/wifi-utils-nl80211.Tpo -c -o wifi-utils-nl80211.lo `test -f 'platform/wifi/wifi-utils-nl80211.c' || echo '$(srcdir)/'`platform/wifi/wifi-utils-nl80211.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/wifi-utils-nl80211.Tpo $(DEPDIR)/wifi-utils-nl80211.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='platform/wifi/wifi-utils-nl80211.c' object='wifi-utils-nl80211.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-wifi-ap.obj `if test -f 'nm-wifi-ap.c'; then $(CYGPATH_W) 'nm-wifi-ap.c'; else $(CYGPATH_W) '$(srcdir)/nm-wifi-ap.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o wifi-utils-nl80211.lo `test -f 'platform/wifi/wifi-utils-nl80211.c' || echo '$(srcdir)/'`platform/wifi/wifi-utils-nl80211.c -NetworkManager-nm-wifi-ap-utils.o: nm-wifi-ap-utils.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-wifi-ap-utils.o -MD -MP -MF $(DEPDIR)/NetworkManager-nm-wifi-ap-utils.Tpo -c -o NetworkManager-nm-wifi-ap-utils.o `test -f 'nm-wifi-ap-utils.c' || echo '$(srcdir)/'`nm-wifi-ap-utils.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-wifi-ap-utils.Tpo $(DEPDIR)/NetworkManager-nm-wifi-ap-utils.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-wifi-ap-utils.c' object='NetworkManager-nm-wifi-ap-utils.o' libtool=no @AMDEPBACKSLASH@ +wifi-utils.lo: platform/wifi/wifi-utils.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT wifi-utils.lo -MD -MP -MF $(DEPDIR)/wifi-utils.Tpo -c -o wifi-utils.lo `test -f 'platform/wifi/wifi-utils.c' || echo '$(srcdir)/'`platform/wifi/wifi-utils.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/wifi-utils.Tpo $(DEPDIR)/wifi-utils.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='platform/wifi/wifi-utils.c' object='wifi-utils.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-wifi-ap-utils.o `test -f 'nm-wifi-ap-utils.c' || echo '$(srcdir)/'`nm-wifi-ap-utils.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o wifi-utils.lo `test -f 'platform/wifi/wifi-utils.c' || echo '$(srcdir)/'`platform/wifi/wifi-utils.c -NetworkManager-nm-wifi-ap-utils.obj: nm-wifi-ap-utils.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-wifi-ap-utils.obj -MD -MP -MF $(DEPDIR)/NetworkManager-nm-wifi-ap-utils.Tpo -c -o NetworkManager-nm-wifi-ap-utils.obj `if test -f 'nm-wifi-ap-utils.c'; then $(CYGPATH_W) 'nm-wifi-ap-utils.c'; else $(CYGPATH_W) '$(srcdir)/nm-wifi-ap-utils.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-wifi-ap-utils.Tpo $(DEPDIR)/NetworkManager-nm-wifi-ap-utils.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-wifi-ap-utils.c' object='NetworkManager-nm-wifi-ap-utils.obj' libtool=no @AMDEPBACKSLASH@ +nm-fake-rdisc.lo: rdisc/nm-fake-rdisc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-fake-rdisc.lo -MD -MP -MF $(DEPDIR)/nm-fake-rdisc.Tpo -c -o nm-fake-rdisc.lo `test -f 'rdisc/nm-fake-rdisc.c' || echo '$(srcdir)/'`rdisc/nm-fake-rdisc.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-fake-rdisc.Tpo $(DEPDIR)/nm-fake-rdisc.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rdisc/nm-fake-rdisc.c' object='nm-fake-rdisc.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-wifi-ap-utils.obj `if test -f 'nm-wifi-ap-utils.c'; then $(CYGPATH_W) 'nm-wifi-ap-utils.c'; else $(CYGPATH_W) '$(srcdir)/nm-wifi-ap-utils.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-fake-rdisc.lo `test -f 'rdisc/nm-fake-rdisc.c' || echo '$(srcdir)/'`rdisc/nm-fake-rdisc.c -NetworkManager-nm-dbus-manager.o: nm-dbus-manager.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-dbus-manager.o -MD -MP -MF $(DEPDIR)/NetworkManager-nm-dbus-manager.Tpo -c -o NetworkManager-nm-dbus-manager.o `test -f 'nm-dbus-manager.c' || echo '$(srcdir)/'`nm-dbus-manager.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-dbus-manager.Tpo $(DEPDIR)/NetworkManager-nm-dbus-manager.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-dbus-manager.c' object='NetworkManager-nm-dbus-manager.o' libtool=no @AMDEPBACKSLASH@ +nm-lndp-rdisc.lo: rdisc/nm-lndp-rdisc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-lndp-rdisc.lo -MD -MP -MF $(DEPDIR)/nm-lndp-rdisc.Tpo -c -o nm-lndp-rdisc.lo `test -f 'rdisc/nm-lndp-rdisc.c' || echo '$(srcdir)/'`rdisc/nm-lndp-rdisc.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-lndp-rdisc.Tpo $(DEPDIR)/nm-lndp-rdisc.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rdisc/nm-lndp-rdisc.c' object='nm-lndp-rdisc.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-dbus-manager.o `test -f 'nm-dbus-manager.c' || echo '$(srcdir)/'`nm-dbus-manager.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-lndp-rdisc.lo `test -f 'rdisc/nm-lndp-rdisc.c' || echo '$(srcdir)/'`rdisc/nm-lndp-rdisc.c -NetworkManager-nm-dbus-manager.obj: nm-dbus-manager.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-dbus-manager.obj -MD -MP -MF $(DEPDIR)/NetworkManager-nm-dbus-manager.Tpo -c -o NetworkManager-nm-dbus-manager.obj `if test -f 'nm-dbus-manager.c'; then $(CYGPATH_W) 'nm-dbus-manager.c'; else $(CYGPATH_W) '$(srcdir)/nm-dbus-manager.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-dbus-manager.Tpo $(DEPDIR)/NetworkManager-nm-dbus-manager.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-dbus-manager.c' object='NetworkManager-nm-dbus-manager.obj' libtool=no @AMDEPBACKSLASH@ +nm-rdisc.lo: rdisc/nm-rdisc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-rdisc.lo -MD -MP -MF $(DEPDIR)/nm-rdisc.Tpo -c -o nm-rdisc.lo `test -f 'rdisc/nm-rdisc.c' || echo '$(srcdir)/'`rdisc/nm-rdisc.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-rdisc.Tpo $(DEPDIR)/nm-rdisc.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rdisc/nm-rdisc.c' object='nm-rdisc.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-dbus-manager.obj `if test -f 'nm-dbus-manager.c'; then $(CYGPATH_W) 'nm-dbus-manager.c'; else $(CYGPATH_W) '$(srcdir)/nm-dbus-manager.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-rdisc.lo `test -f 'rdisc/nm-rdisc.c' || echo '$(srcdir)/'`rdisc/nm-rdisc.c -NetworkManager-nm-udev-manager.o: nm-udev-manager.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-udev-manager.o -MD -MP -MF $(DEPDIR)/NetworkManager-nm-udev-manager.Tpo -c -o NetworkManager-nm-udev-manager.o `test -f 'nm-udev-manager.c' || echo '$(srcdir)/'`nm-udev-manager.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-udev-manager.Tpo $(DEPDIR)/NetworkManager-nm-udev-manager.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-udev-manager.c' object='NetworkManager-nm-udev-manager.o' libtool=no @AMDEPBACKSLASH@ +nm-posix-signals.lo: posix-signals/nm-posix-signals.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-posix-signals.lo -MD -MP -MF $(DEPDIR)/nm-posix-signals.Tpo -c -o nm-posix-signals.lo `test -f 'posix-signals/nm-posix-signals.c' || echo '$(srcdir)/'`posix-signals/nm-posix-signals.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-posix-signals.Tpo $(DEPDIR)/nm-posix-signals.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='posix-signals/nm-posix-signals.c' object='nm-posix-signals.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-udev-manager.o `test -f 'nm-udev-manager.c' || echo '$(srcdir)/'`nm-udev-manager.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-posix-signals.lo `test -f 'posix-signals/nm-posix-signals.c' || echo '$(srcdir)/'`posix-signals/nm-posix-signals.c -NetworkManager-nm-udev-manager.obj: nm-udev-manager.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-udev-manager.obj -MD -MP -MF $(DEPDIR)/NetworkManager-nm-udev-manager.Tpo -c -o NetworkManager-nm-udev-manager.obj `if test -f 'nm-udev-manager.c'; then $(CYGPATH_W) 'nm-udev-manager.c'; else $(CYGPATH_W) '$(srcdir)/nm-udev-manager.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-udev-manager.Tpo $(DEPDIR)/NetworkManager-nm-udev-manager.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-udev-manager.c' object='NetworkManager-nm-udev-manager.obj' libtool=no @AMDEPBACKSLASH@ +nm-ppp-manager.lo: ppp-manager/nm-ppp-manager.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-ppp-manager.lo -MD -MP -MF $(DEPDIR)/nm-ppp-manager.Tpo -c -o nm-ppp-manager.lo `test -f 'ppp-manager/nm-ppp-manager.c' || echo '$(srcdir)/'`ppp-manager/nm-ppp-manager.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-ppp-manager.Tpo $(DEPDIR)/nm-ppp-manager.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ppp-manager/nm-ppp-manager.c' object='nm-ppp-manager.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-udev-manager.obj `if test -f 'nm-udev-manager.c'; then $(CYGPATH_W) 'nm-udev-manager.c'; else $(CYGPATH_W) '$(srcdir)/nm-udev-manager.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-ppp-manager.lo `test -f 'ppp-manager/nm-ppp-manager.c' || echo '$(srcdir)/'`ppp-manager/nm-ppp-manager.c -NetworkManager-nm-hostname-provider.o: nm-hostname-provider.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-hostname-provider.o -MD -MP -MF $(DEPDIR)/NetworkManager-nm-hostname-provider.Tpo -c -o NetworkManager-nm-hostname-provider.o `test -f 'nm-hostname-provider.c' || echo '$(srcdir)/'`nm-hostname-provider.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-hostname-provider.Tpo $(DEPDIR)/NetworkManager-nm-hostname-provider.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-hostname-provider.c' object='NetworkManager-nm-hostname-provider.o' libtool=no @AMDEPBACKSLASH@ +nm-agent-manager.lo: settings/nm-agent-manager.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-agent-manager.lo -MD -MP -MF $(DEPDIR)/nm-agent-manager.Tpo -c -o nm-agent-manager.lo `test -f 'settings/nm-agent-manager.c' || echo '$(srcdir)/'`settings/nm-agent-manager.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-agent-manager.Tpo $(DEPDIR)/nm-agent-manager.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='settings/nm-agent-manager.c' object='nm-agent-manager.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-hostname-provider.o `test -f 'nm-hostname-provider.c' || echo '$(srcdir)/'`nm-hostname-provider.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-agent-manager.lo `test -f 'settings/nm-agent-manager.c' || echo '$(srcdir)/'`settings/nm-agent-manager.c -NetworkManager-nm-hostname-provider.obj: nm-hostname-provider.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-hostname-provider.obj -MD -MP -MF $(DEPDIR)/NetworkManager-nm-hostname-provider.Tpo -c -o NetworkManager-nm-hostname-provider.obj `if test -f 'nm-hostname-provider.c'; then $(CYGPATH_W) 'nm-hostname-provider.c'; else $(CYGPATH_W) '$(srcdir)/nm-hostname-provider.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-hostname-provider.Tpo $(DEPDIR)/NetworkManager-nm-hostname-provider.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-hostname-provider.c' object='NetworkManager-nm-hostname-provider.obj' libtool=no @AMDEPBACKSLASH@ +nm-inotify-helper.lo: settings/nm-inotify-helper.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-inotify-helper.lo -MD -MP -MF $(DEPDIR)/nm-inotify-helper.Tpo -c -o nm-inotify-helper.lo `test -f 'settings/nm-inotify-helper.c' || echo '$(srcdir)/'`settings/nm-inotify-helper.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-inotify-helper.Tpo $(DEPDIR)/nm-inotify-helper.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='settings/nm-inotify-helper.c' object='nm-inotify-helper.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-hostname-provider.obj `if test -f 'nm-hostname-provider.c'; then $(CYGPATH_W) 'nm-hostname-provider.c'; else $(CYGPATH_W) '$(srcdir)/nm-hostname-provider.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-inotify-helper.lo `test -f 'settings/nm-inotify-helper.c' || echo '$(srcdir)/'`settings/nm-inotify-helper.c -NetworkManager-nm-ip4-config.o: nm-ip4-config.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-ip4-config.o -MD -MP -MF $(DEPDIR)/NetworkManager-nm-ip4-config.Tpo -c -o NetworkManager-nm-ip4-config.o `test -f 'nm-ip4-config.c' || echo '$(srcdir)/'`nm-ip4-config.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-ip4-config.Tpo $(DEPDIR)/NetworkManager-nm-ip4-config.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-ip4-config.c' object='NetworkManager-nm-ip4-config.o' libtool=no @AMDEPBACKSLASH@ +nm-secret-agent.lo: settings/nm-secret-agent.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-secret-agent.lo -MD -MP -MF $(DEPDIR)/nm-secret-agent.Tpo -c -o nm-secret-agent.lo `test -f 'settings/nm-secret-agent.c' || echo '$(srcdir)/'`settings/nm-secret-agent.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-secret-agent.Tpo $(DEPDIR)/nm-secret-agent.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='settings/nm-secret-agent.c' object='nm-secret-agent.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-ip4-config.o `test -f 'nm-ip4-config.c' || echo '$(srcdir)/'`nm-ip4-config.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-secret-agent.lo `test -f 'settings/nm-secret-agent.c' || echo '$(srcdir)/'`settings/nm-secret-agent.c -NetworkManager-nm-ip4-config.obj: nm-ip4-config.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-ip4-config.obj -MD -MP -MF $(DEPDIR)/NetworkManager-nm-ip4-config.Tpo -c -o NetworkManager-nm-ip4-config.obj `if test -f 'nm-ip4-config.c'; then $(CYGPATH_W) 'nm-ip4-config.c'; else $(CYGPATH_W) '$(srcdir)/nm-ip4-config.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-ip4-config.Tpo $(DEPDIR)/NetworkManager-nm-ip4-config.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-ip4-config.c' object='NetworkManager-nm-ip4-config.obj' libtool=no @AMDEPBACKSLASH@ +nm-settings-connection.lo: settings/nm-settings-connection.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-settings-connection.lo -MD -MP -MF $(DEPDIR)/nm-settings-connection.Tpo -c -o nm-settings-connection.lo `test -f 'settings/nm-settings-connection.c' || echo '$(srcdir)/'`settings/nm-settings-connection.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-settings-connection.Tpo $(DEPDIR)/nm-settings-connection.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='settings/nm-settings-connection.c' object='nm-settings-connection.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-ip4-config.obj `if test -f 'nm-ip4-config.c'; then $(CYGPATH_W) 'nm-ip4-config.c'; else $(CYGPATH_W) '$(srcdir)/nm-ip4-config.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-settings-connection.lo `test -f 'settings/nm-settings-connection.c' || echo '$(srcdir)/'`settings/nm-settings-connection.c -NetworkManager-nm-ip6-config.o: nm-ip6-config.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-ip6-config.o -MD -MP -MF $(DEPDIR)/NetworkManager-nm-ip6-config.Tpo -c -o NetworkManager-nm-ip6-config.o `test -f 'nm-ip6-config.c' || echo '$(srcdir)/'`nm-ip6-config.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-ip6-config.Tpo $(DEPDIR)/NetworkManager-nm-ip6-config.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-ip6-config.c' object='NetworkManager-nm-ip6-config.o' libtool=no @AMDEPBACKSLASH@ +nm-settings-error.lo: settings/nm-settings-error.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-settings-error.lo -MD -MP -MF $(DEPDIR)/nm-settings-error.Tpo -c -o nm-settings-error.lo `test -f 'settings/nm-settings-error.c' || echo '$(srcdir)/'`settings/nm-settings-error.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-settings-error.Tpo $(DEPDIR)/nm-settings-error.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='settings/nm-settings-error.c' object='nm-settings-error.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-ip6-config.o `test -f 'nm-ip6-config.c' || echo '$(srcdir)/'`nm-ip6-config.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-settings-error.lo `test -f 'settings/nm-settings-error.c' || echo '$(srcdir)/'`settings/nm-settings-error.c -NetworkManager-nm-ip6-config.obj: nm-ip6-config.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-ip6-config.obj -MD -MP -MF $(DEPDIR)/NetworkManager-nm-ip6-config.Tpo -c -o NetworkManager-nm-ip6-config.obj `if test -f 'nm-ip6-config.c'; then $(CYGPATH_W) 'nm-ip6-config.c'; else $(CYGPATH_W) '$(srcdir)/nm-ip6-config.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-ip6-config.Tpo $(DEPDIR)/NetworkManager-nm-ip6-config.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-ip6-config.c' object='NetworkManager-nm-ip6-config.obj' libtool=no @AMDEPBACKSLASH@ +nm-settings-utils.lo: settings/nm-settings-utils.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-settings-utils.lo -MD -MP -MF $(DEPDIR)/nm-settings-utils.Tpo -c -o nm-settings-utils.lo `test -f 'settings/nm-settings-utils.c' || echo '$(srcdir)/'`settings/nm-settings-utils.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-settings-utils.Tpo $(DEPDIR)/nm-settings-utils.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='settings/nm-settings-utils.c' object='nm-settings-utils.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-ip6-config.obj `if test -f 'nm-ip6-config.c'; then $(CYGPATH_W) 'nm-ip6-config.c'; else $(CYGPATH_W) '$(srcdir)/nm-ip6-config.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-settings-utils.lo `test -f 'settings/nm-settings-utils.c' || echo '$(srcdir)/'`settings/nm-settings-utils.c -NetworkManager-nm-active-connection.o: nm-active-connection.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-active-connection.o -MD -MP -MF $(DEPDIR)/NetworkManager-nm-active-connection.Tpo -c -o NetworkManager-nm-active-connection.o `test -f 'nm-active-connection.c' || echo '$(srcdir)/'`nm-active-connection.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-active-connection.Tpo $(DEPDIR)/NetworkManager-nm-active-connection.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-active-connection.c' object='NetworkManager-nm-active-connection.o' libtool=no @AMDEPBACKSLASH@ +nm-settings.lo: settings/nm-settings.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-settings.lo -MD -MP -MF $(DEPDIR)/nm-settings.Tpo -c -o nm-settings.lo `test -f 'settings/nm-settings.c' || echo '$(srcdir)/'`settings/nm-settings.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-settings.Tpo $(DEPDIR)/nm-settings.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='settings/nm-settings.c' object='nm-settings.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-active-connection.o `test -f 'nm-active-connection.c' || echo '$(srcdir)/'`nm-active-connection.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-settings.lo `test -f 'settings/nm-settings.c' || echo '$(srcdir)/'`settings/nm-settings.c -NetworkManager-nm-active-connection.obj: nm-active-connection.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-active-connection.obj -MD -MP -MF $(DEPDIR)/NetworkManager-nm-active-connection.Tpo -c -o NetworkManager-nm-active-connection.obj `if test -f 'nm-active-connection.c'; then $(CYGPATH_W) 'nm-active-connection.c'; else $(CYGPATH_W) '$(srcdir)/nm-active-connection.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-active-connection.Tpo $(DEPDIR)/NetworkManager-nm-active-connection.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-active-connection.c' object='NetworkManager-nm-active-connection.obj' libtool=no @AMDEPBACKSLASH@ +nm-system-config-interface.lo: settings/nm-system-config-interface.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-system-config-interface.lo -MD -MP -MF $(DEPDIR)/nm-system-config-interface.Tpo -c -o nm-system-config-interface.lo `test -f 'settings/nm-system-config-interface.c' || echo '$(srcdir)/'`settings/nm-system-config-interface.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-system-config-interface.Tpo $(DEPDIR)/nm-system-config-interface.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='settings/nm-system-config-interface.c' object='nm-system-config-interface.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-active-connection.obj `if test -f 'nm-active-connection.c'; then $(CYGPATH_W) 'nm-active-connection.c'; else $(CYGPATH_W) '$(srcdir)/nm-active-connection.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-system-config-interface.lo `test -f 'settings/nm-system-config-interface.c' || echo '$(srcdir)/'`settings/nm-system-config-interface.c -NetworkManager-nm-config.o: nm-config.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-config.o -MD -MP -MF $(DEPDIR)/NetworkManager-nm-config.Tpo -c -o NetworkManager-nm-config.o `test -f 'nm-config.c' || echo '$(srcdir)/'`nm-config.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-config.Tpo $(DEPDIR)/NetworkManager-nm-config.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-config.c' object='NetworkManager-nm-config.o' libtool=no @AMDEPBACKSLASH@ +errors.lo: settings/plugins/keyfile/errors.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT errors.lo -MD -MP -MF $(DEPDIR)/errors.Tpo -c -o errors.lo `test -f 'settings/plugins/keyfile/errors.c' || echo '$(srcdir)/'`settings/plugins/keyfile/errors.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/errors.Tpo $(DEPDIR)/errors.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='settings/plugins/keyfile/errors.c' object='errors.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-config.o `test -f 'nm-config.c' || echo '$(srcdir)/'`nm-config.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o errors.lo `test -f 'settings/plugins/keyfile/errors.c' || echo '$(srcdir)/'`settings/plugins/keyfile/errors.c -NetworkManager-nm-config.obj: nm-config.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-config.obj -MD -MP -MF $(DEPDIR)/NetworkManager-nm-config.Tpo -c -o NetworkManager-nm-config.obj `if test -f 'nm-config.c'; then $(CYGPATH_W) 'nm-config.c'; else $(CYGPATH_W) '$(srcdir)/nm-config.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-config.Tpo $(DEPDIR)/NetworkManager-nm-config.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-config.c' object='NetworkManager-nm-config.obj' libtool=no @AMDEPBACKSLASH@ +nm-keyfile-connection.lo: settings/plugins/keyfile/nm-keyfile-connection.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-keyfile-connection.lo -MD -MP -MF $(DEPDIR)/nm-keyfile-connection.Tpo -c -o nm-keyfile-connection.lo `test -f 'settings/plugins/keyfile/nm-keyfile-connection.c' || echo '$(srcdir)/'`settings/plugins/keyfile/nm-keyfile-connection.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-keyfile-connection.Tpo $(DEPDIR)/nm-keyfile-connection.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='settings/plugins/keyfile/nm-keyfile-connection.c' object='nm-keyfile-connection.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-config.obj `if test -f 'nm-config.c'; then $(CYGPATH_W) 'nm-config.c'; else $(CYGPATH_W) '$(srcdir)/nm-config.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-keyfile-connection.lo `test -f 'settings/plugins/keyfile/nm-keyfile-connection.c' || echo '$(srcdir)/'`settings/plugins/keyfile/nm-keyfile-connection.c -NetworkManager-main.o: main.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-main.o -MD -MP -MF $(DEPDIR)/NetworkManager-main.Tpo -c -o NetworkManager-main.o `test -f 'main.c' || echo '$(srcdir)/'`main.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-main.Tpo $(DEPDIR)/NetworkManager-main.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='main.c' object='NetworkManager-main.o' libtool=no @AMDEPBACKSLASH@ +plugin.lo: settings/plugins/keyfile/plugin.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT plugin.lo -MD -MP -MF $(DEPDIR)/plugin.Tpo -c -o plugin.lo `test -f 'settings/plugins/keyfile/plugin.c' || echo '$(srcdir)/'`settings/plugins/keyfile/plugin.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/plugin.Tpo $(DEPDIR)/plugin.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='settings/plugins/keyfile/plugin.c' object='plugin.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-main.o `test -f 'main.c' || echo '$(srcdir)/'`main.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o plugin.lo `test -f 'settings/plugins/keyfile/plugin.c' || echo '$(srcdir)/'`settings/plugins/keyfile/plugin.c -NetworkManager-main.obj: main.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-main.obj -MD -MP -MF $(DEPDIR)/NetworkManager-main.Tpo -c -o NetworkManager-main.obj `if test -f 'main.c'; then $(CYGPATH_W) 'main.c'; else $(CYGPATH_W) '$(srcdir)/main.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-main.Tpo $(DEPDIR)/NetworkManager-main.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='main.c' object='NetworkManager-main.obj' libtool=no @AMDEPBACKSLASH@ +reader.lo: settings/plugins/keyfile/reader.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT reader.lo -MD -MP -MF $(DEPDIR)/reader.Tpo -c -o reader.lo `test -f 'settings/plugins/keyfile/reader.c' || echo '$(srcdir)/'`settings/plugins/keyfile/reader.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/reader.Tpo $(DEPDIR)/reader.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='settings/plugins/keyfile/reader.c' object='reader.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-main.obj `if test -f 'main.c'; then $(CYGPATH_W) 'main.c'; else $(CYGPATH_W) '$(srcdir)/main.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o reader.lo `test -f 'settings/plugins/keyfile/reader.c' || echo '$(srcdir)/'`settings/plugins/keyfile/reader.c -NetworkManager-nm-policy.o: nm-policy.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-policy.o -MD -MP -MF $(DEPDIR)/NetworkManager-nm-policy.Tpo -c -o NetworkManager-nm-policy.o `test -f 'nm-policy.c' || echo '$(srcdir)/'`nm-policy.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-policy.Tpo $(DEPDIR)/NetworkManager-nm-policy.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-policy.c' object='NetworkManager-nm-policy.o' libtool=no @AMDEPBACKSLASH@ +utils.lo: settings/plugins/keyfile/utils.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT utils.lo -MD -MP -MF $(DEPDIR)/utils.Tpo -c -o utils.lo `test -f 'settings/plugins/keyfile/utils.c' || echo '$(srcdir)/'`settings/plugins/keyfile/utils.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/utils.Tpo $(DEPDIR)/utils.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='settings/plugins/keyfile/utils.c' object='utils.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-policy.o `test -f 'nm-policy.c' || echo '$(srcdir)/'`nm-policy.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o utils.lo `test -f 'settings/plugins/keyfile/utils.c' || echo '$(srcdir)/'`settings/plugins/keyfile/utils.c -NetworkManager-nm-policy.obj: nm-policy.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-policy.obj -MD -MP -MF $(DEPDIR)/NetworkManager-nm-policy.Tpo -c -o NetworkManager-nm-policy.obj `if test -f 'nm-policy.c'; then $(CYGPATH_W) 'nm-policy.c'; else $(CYGPATH_W) '$(srcdir)/nm-policy.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-policy.Tpo $(DEPDIR)/NetworkManager-nm-policy.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-policy.c' object='NetworkManager-nm-policy.obj' libtool=no @AMDEPBACKSLASH@ +writer.lo: settings/plugins/keyfile/writer.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT writer.lo -MD -MP -MF $(DEPDIR)/writer.Tpo -c -o writer.lo `test -f 'settings/plugins/keyfile/writer.c' || echo '$(srcdir)/'`settings/plugins/keyfile/writer.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/writer.Tpo $(DEPDIR)/writer.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='settings/plugins/keyfile/writer.c' object='writer.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-policy.obj `if test -f 'nm-policy.c'; then $(CYGPATH_W) 'nm-policy.c'; else $(CYGPATH_W) '$(srcdir)/nm-policy.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o writer.lo `test -f 'settings/plugins/keyfile/writer.c' || echo '$(srcdir)/'`settings/plugins/keyfile/writer.c -NetworkManager-nm-policy-hosts.o: nm-policy-hosts.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-policy-hosts.o -MD -MP -MF $(DEPDIR)/NetworkManager-nm-policy-hosts.Tpo -c -o NetworkManager-nm-policy-hosts.o `test -f 'nm-policy-hosts.c' || echo '$(srcdir)/'`nm-policy-hosts.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-policy-hosts.Tpo $(DEPDIR)/NetworkManager-nm-policy-hosts.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-policy-hosts.c' object='NetworkManager-nm-policy-hosts.o' libtool=no @AMDEPBACKSLASH@ +nm-supplicant-config.lo: supplicant-manager/nm-supplicant-config.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-supplicant-config.lo -MD -MP -MF $(DEPDIR)/nm-supplicant-config.Tpo -c -o nm-supplicant-config.lo `test -f 'supplicant-manager/nm-supplicant-config.c' || echo '$(srcdir)/'`supplicant-manager/nm-supplicant-config.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-supplicant-config.Tpo $(DEPDIR)/nm-supplicant-config.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='supplicant-manager/nm-supplicant-config.c' object='nm-supplicant-config.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-policy-hosts.o `test -f 'nm-policy-hosts.c' || echo '$(srcdir)/'`nm-policy-hosts.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-supplicant-config.lo `test -f 'supplicant-manager/nm-supplicant-config.c' || echo '$(srcdir)/'`supplicant-manager/nm-supplicant-config.c -NetworkManager-nm-policy-hosts.obj: nm-policy-hosts.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-policy-hosts.obj -MD -MP -MF $(DEPDIR)/NetworkManager-nm-policy-hosts.Tpo -c -o NetworkManager-nm-policy-hosts.obj `if test -f 'nm-policy-hosts.c'; then $(CYGPATH_W) 'nm-policy-hosts.c'; else $(CYGPATH_W) '$(srcdir)/nm-policy-hosts.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-policy-hosts.Tpo $(DEPDIR)/NetworkManager-nm-policy-hosts.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-policy-hosts.c' object='NetworkManager-nm-policy-hosts.obj' libtool=no @AMDEPBACKSLASH@ +nm-supplicant-interface.lo: supplicant-manager/nm-supplicant-interface.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-supplicant-interface.lo -MD -MP -MF $(DEPDIR)/nm-supplicant-interface.Tpo -c -o nm-supplicant-interface.lo `test -f 'supplicant-manager/nm-supplicant-interface.c' || echo '$(srcdir)/'`supplicant-manager/nm-supplicant-interface.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-supplicant-interface.Tpo $(DEPDIR)/nm-supplicant-interface.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='supplicant-manager/nm-supplicant-interface.c' object='nm-supplicant-interface.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-policy-hosts.obj `if test -f 'nm-policy-hosts.c'; then $(CYGPATH_W) 'nm-policy-hosts.c'; else $(CYGPATH_W) '$(srcdir)/nm-policy-hosts.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-supplicant-interface.lo `test -f 'supplicant-manager/nm-supplicant-interface.c' || echo '$(srcdir)/'`supplicant-manager/nm-supplicant-interface.c -NetworkManager-nm-policy-hostname.o: nm-policy-hostname.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-policy-hostname.o -MD -MP -MF $(DEPDIR)/NetworkManager-nm-policy-hostname.Tpo -c -o NetworkManager-nm-policy-hostname.o `test -f 'nm-policy-hostname.c' || echo '$(srcdir)/'`nm-policy-hostname.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-policy-hostname.Tpo $(DEPDIR)/NetworkManager-nm-policy-hostname.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-policy-hostname.c' object='NetworkManager-nm-policy-hostname.o' libtool=no @AMDEPBACKSLASH@ +nm-supplicant-manager.lo: supplicant-manager/nm-supplicant-manager.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-supplicant-manager.lo -MD -MP -MF $(DEPDIR)/nm-supplicant-manager.Tpo -c -o nm-supplicant-manager.lo `test -f 'supplicant-manager/nm-supplicant-manager.c' || echo '$(srcdir)/'`supplicant-manager/nm-supplicant-manager.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-supplicant-manager.Tpo $(DEPDIR)/nm-supplicant-manager.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='supplicant-manager/nm-supplicant-manager.c' object='nm-supplicant-manager.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-policy-hostname.o `test -f 'nm-policy-hostname.c' || echo '$(srcdir)/'`nm-policy-hostname.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-supplicant-manager.lo `test -f 'supplicant-manager/nm-supplicant-manager.c' || echo '$(srcdir)/'`supplicant-manager/nm-supplicant-manager.c -NetworkManager-nm-policy-hostname.obj: nm-policy-hostname.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-policy-hostname.obj -MD -MP -MF $(DEPDIR)/NetworkManager-nm-policy-hostname.Tpo -c -o NetworkManager-nm-policy-hostname.obj `if test -f 'nm-policy-hostname.c'; then $(CYGPATH_W) 'nm-policy-hostname.c'; else $(CYGPATH_W) '$(srcdir)/nm-policy-hostname.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-policy-hostname.Tpo $(DEPDIR)/NetworkManager-nm-policy-hostname.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-policy-hostname.c' object='NetworkManager-nm-policy-hostname.obj' libtool=no @AMDEPBACKSLASH@ +nm-supplicant-settings-verify.lo: supplicant-manager/nm-supplicant-settings-verify.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-supplicant-settings-verify.lo -MD -MP -MF $(DEPDIR)/nm-supplicant-settings-verify.Tpo -c -o nm-supplicant-settings-verify.lo `test -f 'supplicant-manager/nm-supplicant-settings-verify.c' || echo '$(srcdir)/'`supplicant-manager/nm-supplicant-settings-verify.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-supplicant-settings-verify.Tpo $(DEPDIR)/nm-supplicant-settings-verify.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='supplicant-manager/nm-supplicant-settings-verify.c' object='nm-supplicant-settings-verify.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-policy-hostname.obj `if test -f 'nm-policy-hostname.c'; then $(CYGPATH_W) 'nm-policy-hostname.c'; else $(CYGPATH_W) '$(srcdir)/nm-policy-hostname.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-supplicant-settings-verify.lo `test -f 'supplicant-manager/nm-supplicant-settings-verify.c' || echo '$(srcdir)/'`supplicant-manager/nm-supplicant-settings-verify.c -NetworkManager-NetworkManagerUtils.o: NetworkManagerUtils.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-NetworkManagerUtils.o -MD -MP -MF $(DEPDIR)/NetworkManager-NetworkManagerUtils.Tpo -c -o NetworkManager-NetworkManagerUtils.o `test -f 'NetworkManagerUtils.c' || echo '$(srcdir)/'`NetworkManagerUtils.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-NetworkManagerUtils.Tpo $(DEPDIR)/NetworkManager-NetworkManagerUtils.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='NetworkManagerUtils.c' object='NetworkManager-NetworkManagerUtils.o' libtool=no @AMDEPBACKSLASH@ +nm-call-store.lo: supplicant-manager/nm-call-store.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-call-store.lo -MD -MP -MF $(DEPDIR)/nm-call-store.Tpo -c -o nm-call-store.lo `test -f 'supplicant-manager/nm-call-store.c' || echo '$(srcdir)/'`supplicant-manager/nm-call-store.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-call-store.Tpo $(DEPDIR)/nm-call-store.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='supplicant-manager/nm-call-store.c' object='nm-call-store.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-NetworkManagerUtils.o `test -f 'NetworkManagerUtils.c' || echo '$(srcdir)/'`NetworkManagerUtils.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-call-store.lo `test -f 'supplicant-manager/nm-call-store.c' || echo '$(srcdir)/'`supplicant-manager/nm-call-store.c -NetworkManager-NetworkManagerUtils.obj: NetworkManagerUtils.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-NetworkManagerUtils.obj -MD -MP -MF $(DEPDIR)/NetworkManager-NetworkManagerUtils.Tpo -c -o NetworkManager-NetworkManagerUtils.obj `if test -f 'NetworkManagerUtils.c'; then $(CYGPATH_W) 'NetworkManagerUtils.c'; else $(CYGPATH_W) '$(srcdir)/NetworkManagerUtils.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-NetworkManagerUtils.Tpo $(DEPDIR)/NetworkManager-NetworkManagerUtils.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='NetworkManagerUtils.c' object='NetworkManager-NetworkManagerUtils.obj' libtool=no @AMDEPBACKSLASH@ +nm-vpn-connection.lo: vpn-manager/nm-vpn-connection.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-vpn-connection.lo -MD -MP -MF $(DEPDIR)/nm-vpn-connection.Tpo -c -o nm-vpn-connection.lo `test -f 'vpn-manager/nm-vpn-connection.c' || echo '$(srcdir)/'`vpn-manager/nm-vpn-connection.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-vpn-connection.Tpo $(DEPDIR)/nm-vpn-connection.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vpn-manager/nm-vpn-connection.c' object='nm-vpn-connection.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-NetworkManagerUtils.obj `if test -f 'NetworkManagerUtils.c'; then $(CYGPATH_W) 'NetworkManagerUtils.c'; else $(CYGPATH_W) '$(srcdir)/NetworkManagerUtils.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-vpn-connection.lo `test -f 'vpn-manager/nm-vpn-connection.c' || echo '$(srcdir)/'`vpn-manager/nm-vpn-connection.c -NetworkManager-nm-system.o: nm-system.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-system.o -MD -MP -MF $(DEPDIR)/NetworkManager-nm-system.Tpo -c -o NetworkManager-nm-system.o `test -f 'nm-system.c' || echo '$(srcdir)/'`nm-system.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-system.Tpo $(DEPDIR)/NetworkManager-nm-system.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-system.c' object='NetworkManager-nm-system.o' libtool=no @AMDEPBACKSLASH@ +nm-vpn-manager.lo: vpn-manager/nm-vpn-manager.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-vpn-manager.lo -MD -MP -MF $(DEPDIR)/nm-vpn-manager.Tpo -c -o nm-vpn-manager.lo `test -f 'vpn-manager/nm-vpn-manager.c' || echo '$(srcdir)/'`vpn-manager/nm-vpn-manager.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-vpn-manager.Tpo $(DEPDIR)/nm-vpn-manager.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vpn-manager/nm-vpn-manager.c' object='nm-vpn-manager.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-system.o `test -f 'nm-system.c' || echo '$(srcdir)/'`nm-system.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-vpn-manager.lo `test -f 'vpn-manager/nm-vpn-manager.c' || echo '$(srcdir)/'`vpn-manager/nm-vpn-manager.c -NetworkManager-nm-system.obj: nm-system.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-system.obj -MD -MP -MF $(DEPDIR)/NetworkManager-nm-system.Tpo -c -o NetworkManager-nm-system.obj `if test -f 'nm-system.c'; then $(CYGPATH_W) 'nm-system.c'; else $(CYGPATH_W) '$(srcdir)/nm-system.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-system.Tpo $(DEPDIR)/NetworkManager-nm-system.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-system.c' object='NetworkManager-nm-system.obj' libtool=no @AMDEPBACKSLASH@ +nm-vpn-service.lo: vpn-manager/nm-vpn-service.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-vpn-service.lo -MD -MP -MF $(DEPDIR)/nm-vpn-service.Tpo -c -o nm-vpn-service.lo `test -f 'vpn-manager/nm-vpn-service.c' || echo '$(srcdir)/'`vpn-manager/nm-vpn-service.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-vpn-service.Tpo $(DEPDIR)/nm-vpn-service.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vpn-manager/nm-vpn-service.c' object='nm-vpn-service.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-system.obj `if test -f 'nm-system.c'; then $(CYGPATH_W) 'nm-system.c'; else $(CYGPATH_W) '$(srcdir)/nm-system.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-vpn-service.lo `test -f 'vpn-manager/nm-vpn-service.c' || echo '$(srcdir)/'`vpn-manager/nm-vpn-service.c -NetworkManager-nm-manager.o: nm-manager.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-manager.o -MD -MP -MF $(DEPDIR)/NetworkManager-nm-manager.Tpo -c -o NetworkManager-nm-manager.o `test -f 'nm-manager.c' || echo '$(srcdir)/'`nm-manager.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-manager.Tpo $(DEPDIR)/NetworkManager-nm-manager.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-manager.c' object='NetworkManager-nm-manager.o' libtool=no @AMDEPBACKSLASH@ +wifi-utils-wext.lo: platform/wifi/wifi-utils-wext.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT wifi-utils-wext.lo -MD -MP -MF $(DEPDIR)/wifi-utils-wext.Tpo -c -o wifi-utils-wext.lo `test -f 'platform/wifi/wifi-utils-wext.c' || echo '$(srcdir)/'`platform/wifi/wifi-utils-wext.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/wifi-utils-wext.Tpo $(DEPDIR)/wifi-utils-wext.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='platform/wifi/wifi-utils-wext.c' object='wifi-utils-wext.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-manager.o `test -f 'nm-manager.c' || echo '$(srcdir)/'`nm-manager.c - -NetworkManager-nm-manager.obj: nm-manager.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-manager.obj -MD -MP -MF $(DEPDIR)/NetworkManager-nm-manager.Tpo -c -o NetworkManager-nm-manager.obj `if test -f 'nm-manager.c'; then $(CYGPATH_W) 'nm-manager.c'; else $(CYGPATH_W) '$(srcdir)/nm-manager.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-manager.Tpo $(DEPDIR)/NetworkManager-nm-manager.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-manager.c' object='NetworkManager-nm-manager.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-manager.obj `if test -f 'nm-manager.c'; then $(CYGPATH_W) 'nm-manager.c'; else $(CYGPATH_W) '$(srcdir)/nm-manager.c'; fi` - -NetworkManager-nm-manager-auth.o: nm-manager-auth.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-manager-auth.o -MD -MP -MF $(DEPDIR)/NetworkManager-nm-manager-auth.Tpo -c -o NetworkManager-nm-manager-auth.o `test -f 'nm-manager-auth.c' || echo '$(srcdir)/'`nm-manager-auth.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-manager-auth.Tpo $(DEPDIR)/NetworkManager-nm-manager-auth.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-manager-auth.c' object='NetworkManager-nm-manager-auth.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-manager-auth.o `test -f 'nm-manager-auth.c' || echo '$(srcdir)/'`nm-manager-auth.c - -NetworkManager-nm-manager-auth.obj: nm-manager-auth.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-manager-auth.obj -MD -MP -MF $(DEPDIR)/NetworkManager-nm-manager-auth.Tpo -c -o NetworkManager-nm-manager-auth.obj `if test -f 'nm-manager-auth.c'; then $(CYGPATH_W) 'nm-manager-auth.c'; else $(CYGPATH_W) '$(srcdir)/nm-manager-auth.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-manager-auth.Tpo $(DEPDIR)/NetworkManager-nm-manager-auth.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-manager-auth.c' object='NetworkManager-nm-manager-auth.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-manager-auth.obj `if test -f 'nm-manager-auth.c'; then $(CYGPATH_W) 'nm-manager-auth.c'; else $(CYGPATH_W) '$(srcdir)/nm-manager-auth.c'; fi` - -NetworkManager-nm-netlink-monitor.o: nm-netlink-monitor.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-netlink-monitor.o -MD -MP -MF $(DEPDIR)/NetworkManager-nm-netlink-monitor.Tpo -c -o NetworkManager-nm-netlink-monitor.o `test -f 'nm-netlink-monitor.c' || echo '$(srcdir)/'`nm-netlink-monitor.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-netlink-monitor.Tpo $(DEPDIR)/NetworkManager-nm-netlink-monitor.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-netlink-monitor.c' object='NetworkManager-nm-netlink-monitor.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-netlink-monitor.o `test -f 'nm-netlink-monitor.c' || echo '$(srcdir)/'`nm-netlink-monitor.c - -NetworkManager-nm-netlink-monitor.obj: nm-netlink-monitor.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-netlink-monitor.obj -MD -MP -MF $(DEPDIR)/NetworkManager-nm-netlink-monitor.Tpo -c -o NetworkManager-nm-netlink-monitor.obj `if test -f 'nm-netlink-monitor.c'; then $(CYGPATH_W) 'nm-netlink-monitor.c'; else $(CYGPATH_W) '$(srcdir)/nm-netlink-monitor.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-netlink-monitor.Tpo $(DEPDIR)/NetworkManager-nm-netlink-monitor.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-netlink-monitor.c' object='NetworkManager-nm-netlink-monitor.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-netlink-monitor.obj `if test -f 'nm-netlink-monitor.c'; then $(CYGPATH_W) 'nm-netlink-monitor.c'; else $(CYGPATH_W) '$(srcdir)/nm-netlink-monitor.c'; fi` - -NetworkManager-nm-netlink-utils.o: nm-netlink-utils.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-netlink-utils.o -MD -MP -MF $(DEPDIR)/NetworkManager-nm-netlink-utils.Tpo -c -o NetworkManager-nm-netlink-utils.o `test -f 'nm-netlink-utils.c' || echo '$(srcdir)/'`nm-netlink-utils.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-netlink-utils.Tpo $(DEPDIR)/NetworkManager-nm-netlink-utils.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-netlink-utils.c' object='NetworkManager-nm-netlink-utils.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-netlink-utils.o `test -f 'nm-netlink-utils.c' || echo '$(srcdir)/'`nm-netlink-utils.c - -NetworkManager-nm-netlink-utils.obj: nm-netlink-utils.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-netlink-utils.obj -MD -MP -MF $(DEPDIR)/NetworkManager-nm-netlink-utils.Tpo -c -o NetworkManager-nm-netlink-utils.obj `if test -f 'nm-netlink-utils.c'; then $(CYGPATH_W) 'nm-netlink-utils.c'; else $(CYGPATH_W) '$(srcdir)/nm-netlink-utils.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-netlink-utils.Tpo $(DEPDIR)/NetworkManager-nm-netlink-utils.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-netlink-utils.c' object='NetworkManager-nm-netlink-utils.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-netlink-utils.obj `if test -f 'nm-netlink-utils.c'; then $(CYGPATH_W) 'nm-netlink-utils.c'; else $(CYGPATH_W) '$(srcdir)/nm-netlink-utils.c'; fi` - -NetworkManager-nm-netlink-compat.o: nm-netlink-compat.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-netlink-compat.o -MD -MP -MF $(DEPDIR)/NetworkManager-nm-netlink-compat.Tpo -c -o NetworkManager-nm-netlink-compat.o `test -f 'nm-netlink-compat.c' || echo '$(srcdir)/'`nm-netlink-compat.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-netlink-compat.Tpo $(DEPDIR)/NetworkManager-nm-netlink-compat.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-netlink-compat.c' object='NetworkManager-nm-netlink-compat.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-netlink-compat.o `test -f 'nm-netlink-compat.c' || echo '$(srcdir)/'`nm-netlink-compat.c - -NetworkManager-nm-netlink-compat.obj: nm-netlink-compat.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-netlink-compat.obj -MD -MP -MF $(DEPDIR)/NetworkManager-nm-netlink-compat.Tpo -c -o NetworkManager-nm-netlink-compat.obj `if test -f 'nm-netlink-compat.c'; then $(CYGPATH_W) 'nm-netlink-compat.c'; else $(CYGPATH_W) '$(srcdir)/nm-netlink-compat.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-netlink-compat.Tpo $(DEPDIR)/NetworkManager-nm-netlink-compat.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-netlink-compat.c' object='NetworkManager-nm-netlink-compat.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-netlink-compat.obj `if test -f 'nm-netlink-compat.c'; then $(CYGPATH_W) 'nm-netlink-compat.c'; else $(CYGPATH_W) '$(srcdir)/nm-netlink-compat.c'; fi` - -NetworkManager-nm-activation-request.o: nm-activation-request.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-activation-request.o -MD -MP -MF $(DEPDIR)/NetworkManager-nm-activation-request.Tpo -c -o NetworkManager-nm-activation-request.o `test -f 'nm-activation-request.c' || echo '$(srcdir)/'`nm-activation-request.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-activation-request.Tpo $(DEPDIR)/NetworkManager-nm-activation-request.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-activation-request.c' object='NetworkManager-nm-activation-request.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-activation-request.o `test -f 'nm-activation-request.c' || echo '$(srcdir)/'`nm-activation-request.c - -NetworkManager-nm-activation-request.obj: nm-activation-request.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-activation-request.obj -MD -MP -MF $(DEPDIR)/NetworkManager-nm-activation-request.Tpo -c -o NetworkManager-nm-activation-request.obj `if test -f 'nm-activation-request.c'; then $(CYGPATH_W) 'nm-activation-request.c'; else $(CYGPATH_W) '$(srcdir)/nm-activation-request.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-activation-request.Tpo $(DEPDIR)/NetworkManager-nm-activation-request.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-activation-request.c' object='NetworkManager-nm-activation-request.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-activation-request.obj `if test -f 'nm-activation-request.c'; then $(CYGPATH_W) 'nm-activation-request.c'; else $(CYGPATH_W) '$(srcdir)/nm-activation-request.c'; fi` - -NetworkManager-nm-properties-changed-signal.o: nm-properties-changed-signal.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-properties-changed-signal.o -MD -MP -MF $(DEPDIR)/NetworkManager-nm-properties-changed-signal.Tpo -c -o NetworkManager-nm-properties-changed-signal.o `test -f 'nm-properties-changed-signal.c' || echo '$(srcdir)/'`nm-properties-changed-signal.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-properties-changed-signal.Tpo $(DEPDIR)/NetworkManager-nm-properties-changed-signal.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-properties-changed-signal.c' object='NetworkManager-nm-properties-changed-signal.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-properties-changed-signal.o `test -f 'nm-properties-changed-signal.c' || echo '$(srcdir)/'`nm-properties-changed-signal.c - -NetworkManager-nm-properties-changed-signal.obj: nm-properties-changed-signal.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-properties-changed-signal.obj -MD -MP -MF $(DEPDIR)/NetworkManager-nm-properties-changed-signal.Tpo -c -o NetworkManager-nm-properties-changed-signal.obj `if test -f 'nm-properties-changed-signal.c'; then $(CYGPATH_W) 'nm-properties-changed-signal.c'; else $(CYGPATH_W) '$(srcdir)/nm-properties-changed-signal.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-properties-changed-signal.Tpo $(DEPDIR)/NetworkManager-nm-properties-changed-signal.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-properties-changed-signal.c' object='NetworkManager-nm-properties-changed-signal.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-properties-changed-signal.obj `if test -f 'nm-properties-changed-signal.c'; then $(CYGPATH_W) 'nm-properties-changed-signal.c'; else $(CYGPATH_W) '$(srcdir)/nm-properties-changed-signal.c'; fi` - -NetworkManager-nm-dhcp4-config.o: nm-dhcp4-config.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-dhcp4-config.o -MD -MP -MF $(DEPDIR)/NetworkManager-nm-dhcp4-config.Tpo -c -o NetworkManager-nm-dhcp4-config.o `test -f 'nm-dhcp4-config.c' || echo '$(srcdir)/'`nm-dhcp4-config.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-dhcp4-config.Tpo $(DEPDIR)/NetworkManager-nm-dhcp4-config.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-dhcp4-config.c' object='NetworkManager-nm-dhcp4-config.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-dhcp4-config.o `test -f 'nm-dhcp4-config.c' || echo '$(srcdir)/'`nm-dhcp4-config.c - -NetworkManager-nm-dhcp4-config.obj: nm-dhcp4-config.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-dhcp4-config.obj -MD -MP -MF $(DEPDIR)/NetworkManager-nm-dhcp4-config.Tpo -c -o NetworkManager-nm-dhcp4-config.obj `if test -f 'nm-dhcp4-config.c'; then $(CYGPATH_W) 'nm-dhcp4-config.c'; else $(CYGPATH_W) '$(srcdir)/nm-dhcp4-config.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-dhcp4-config.Tpo $(DEPDIR)/NetworkManager-nm-dhcp4-config.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-dhcp4-config.c' object='NetworkManager-nm-dhcp4-config.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-dhcp4-config.obj `if test -f 'nm-dhcp4-config.c'; then $(CYGPATH_W) 'nm-dhcp4-config.c'; else $(CYGPATH_W) '$(srcdir)/nm-dhcp4-config.c'; fi` - -NetworkManager-nm-dhcp6-config.o: nm-dhcp6-config.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-dhcp6-config.o -MD -MP -MF $(DEPDIR)/NetworkManager-nm-dhcp6-config.Tpo -c -o NetworkManager-nm-dhcp6-config.o `test -f 'nm-dhcp6-config.c' || echo '$(srcdir)/'`nm-dhcp6-config.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-dhcp6-config.Tpo $(DEPDIR)/NetworkManager-nm-dhcp6-config.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-dhcp6-config.c' object='NetworkManager-nm-dhcp6-config.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-dhcp6-config.o `test -f 'nm-dhcp6-config.c' || echo '$(srcdir)/'`nm-dhcp6-config.c - -NetworkManager-nm-dhcp6-config.obj: nm-dhcp6-config.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-dhcp6-config.obj -MD -MP -MF $(DEPDIR)/NetworkManager-nm-dhcp6-config.Tpo -c -o NetworkManager-nm-dhcp6-config.obj `if test -f 'nm-dhcp6-config.c'; then $(CYGPATH_W) 'nm-dhcp6-config.c'; else $(CYGPATH_W) '$(srcdir)/nm-dhcp6-config.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-dhcp6-config.Tpo $(DEPDIR)/NetworkManager-nm-dhcp6-config.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-dhcp6-config.c' object='NetworkManager-nm-dhcp6-config.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-dhcp6-config.obj `if test -f 'nm-dhcp6-config.c'; then $(CYGPATH_W) 'nm-dhcp6-config.c'; else $(CYGPATH_W) '$(srcdir)/nm-dhcp6-config.c'; fi` - -NetworkManager-nm-session-utils.o: nm-session-utils.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-session-utils.o -MD -MP -MF $(DEPDIR)/NetworkManager-nm-session-utils.Tpo -c -o NetworkManager-nm-session-utils.o `test -f 'nm-session-utils.c' || echo '$(srcdir)/'`nm-session-utils.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-session-utils.Tpo $(DEPDIR)/NetworkManager-nm-session-utils.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-session-utils.c' object='NetworkManager-nm-session-utils.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-session-utils.o `test -f 'nm-session-utils.c' || echo '$(srcdir)/'`nm-session-utils.c - -NetworkManager-nm-session-utils.obj: nm-session-utils.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-session-utils.obj -MD -MP -MF $(DEPDIR)/NetworkManager-nm-session-utils.Tpo -c -o NetworkManager-nm-session-utils.obj `if test -f 'nm-session-utils.c'; then $(CYGPATH_W) 'nm-session-utils.c'; else $(CYGPATH_W) '$(srcdir)/nm-session-utils.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-session-utils.Tpo $(DEPDIR)/NetworkManager-nm-session-utils.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-session-utils.c' object='NetworkManager-nm-session-utils.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-session-utils.obj `if test -f 'nm-session-utils.c'; then $(CYGPATH_W) 'nm-session-utils.c'; else $(CYGPATH_W) '$(srcdir)/nm-session-utils.c'; fi` - -NetworkManager-nm-connection-provider.o: nm-connection-provider.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-connection-provider.o -MD -MP -MF $(DEPDIR)/NetworkManager-nm-connection-provider.Tpo -c -o NetworkManager-nm-connection-provider.o `test -f 'nm-connection-provider.c' || echo '$(srcdir)/'`nm-connection-provider.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-connection-provider.Tpo $(DEPDIR)/NetworkManager-nm-connection-provider.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-connection-provider.c' object='NetworkManager-nm-connection-provider.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-connection-provider.o `test -f 'nm-connection-provider.c' || echo '$(srcdir)/'`nm-connection-provider.c - -NetworkManager-nm-connection-provider.obj: nm-connection-provider.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-connection-provider.obj -MD -MP -MF $(DEPDIR)/NetworkManager-nm-connection-provider.Tpo -c -o NetworkManager-nm-connection-provider.obj `if test -f 'nm-connection-provider.c'; then $(CYGPATH_W) 'nm-connection-provider.c'; else $(CYGPATH_W) '$(srcdir)/nm-connection-provider.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-connection-provider.Tpo $(DEPDIR)/NetworkManager-nm-connection-provider.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-connection-provider.c' object='NetworkManager-nm-connection-provider.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-connection-provider.obj `if test -f 'nm-connection-provider.c'; then $(CYGPATH_W) 'nm-connection-provider.c'; else $(CYGPATH_W) '$(srcdir)/nm-connection-provider.c'; fi` - -NetworkManager-nm-dispatcher.o: nm-dispatcher.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-dispatcher.o -MD -MP -MF $(DEPDIR)/NetworkManager-nm-dispatcher.Tpo -c -o NetworkManager-nm-dispatcher.o `test -f 'nm-dispatcher.c' || echo '$(srcdir)/'`nm-dispatcher.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-dispatcher.Tpo $(DEPDIR)/NetworkManager-nm-dispatcher.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-dispatcher.c' object='NetworkManager-nm-dispatcher.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-dispatcher.o `test -f 'nm-dispatcher.c' || echo '$(srcdir)/'`nm-dispatcher.c - -NetworkManager-nm-dispatcher.obj: nm-dispatcher.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-dispatcher.obj -MD -MP -MF $(DEPDIR)/NetworkManager-nm-dispatcher.Tpo -c -o NetworkManager-nm-dispatcher.obj `if test -f 'nm-dispatcher.c'; then $(CYGPATH_W) 'nm-dispatcher.c'; else $(CYGPATH_W) '$(srcdir)/nm-dispatcher.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-dispatcher.Tpo $(DEPDIR)/NetworkManager-nm-dispatcher.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-dispatcher.c' object='NetworkManager-nm-dispatcher.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-dispatcher.obj `if test -f 'nm-dispatcher.c'; then $(CYGPATH_W) 'nm-dispatcher.c'; else $(CYGPATH_W) '$(srcdir)/nm-dispatcher.c'; fi` - -NetworkManager-nm-connectivity.o: nm-connectivity.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-connectivity.o -MD -MP -MF $(DEPDIR)/NetworkManager-nm-connectivity.Tpo -c -o NetworkManager-nm-connectivity.o `test -f 'nm-connectivity.c' || echo '$(srcdir)/'`nm-connectivity.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-connectivity.Tpo $(DEPDIR)/NetworkManager-nm-connectivity.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-connectivity.c' object='NetworkManager-nm-connectivity.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-connectivity.o `test -f 'nm-connectivity.c' || echo '$(srcdir)/'`nm-connectivity.c - -NetworkManager-nm-connectivity.obj: nm-connectivity.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-connectivity.obj -MD -MP -MF $(DEPDIR)/NetworkManager-nm-connectivity.Tpo -c -o NetworkManager-nm-connectivity.obj `if test -f 'nm-connectivity.c'; then $(CYGPATH_W) 'nm-connectivity.c'; else $(CYGPATH_W) '$(srcdir)/nm-connectivity.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-connectivity.Tpo $(DEPDIR)/NetworkManager-nm-connectivity.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-connectivity.c' object='NetworkManager-nm-connectivity.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-connectivity.obj `if test -f 'nm-connectivity.c'; then $(CYGPATH_W) 'nm-connectivity.c'; else $(CYGPATH_W) '$(srcdir)/nm-connectivity.c'; fi` - -NetworkManager-nm-session-monitor-systemd.o: nm-session-monitor-systemd.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-session-monitor-systemd.o -MD -MP -MF $(DEPDIR)/NetworkManager-nm-session-monitor-systemd.Tpo -c -o NetworkManager-nm-session-monitor-systemd.o `test -f 'nm-session-monitor-systemd.c' || echo '$(srcdir)/'`nm-session-monitor-systemd.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-session-monitor-systemd.Tpo $(DEPDIR)/NetworkManager-nm-session-monitor-systemd.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-session-monitor-systemd.c' object='NetworkManager-nm-session-monitor-systemd.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-session-monitor-systemd.o `test -f 'nm-session-monitor-systemd.c' || echo '$(srcdir)/'`nm-session-monitor-systemd.c - -NetworkManager-nm-session-monitor-systemd.obj: nm-session-monitor-systemd.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-session-monitor-systemd.obj -MD -MP -MF $(DEPDIR)/NetworkManager-nm-session-monitor-systemd.Tpo -c -o NetworkManager-nm-session-monitor-systemd.obj `if test -f 'nm-session-monitor-systemd.c'; then $(CYGPATH_W) 'nm-session-monitor-systemd.c'; else $(CYGPATH_W) '$(srcdir)/nm-session-monitor-systemd.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-session-monitor-systemd.Tpo $(DEPDIR)/NetworkManager-nm-session-monitor-systemd.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-session-monitor-systemd.c' object='NetworkManager-nm-session-monitor-systemd.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-session-monitor-systemd.obj `if test -f 'nm-session-monitor-systemd.c'; then $(CYGPATH_W) 'nm-session-monitor-systemd.c'; else $(CYGPATH_W) '$(srcdir)/nm-session-monitor-systemd.c'; fi` - -NetworkManager-nm-session-monitor-ck.o: nm-session-monitor-ck.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-session-monitor-ck.o -MD -MP -MF $(DEPDIR)/NetworkManager-nm-session-monitor-ck.Tpo -c -o NetworkManager-nm-session-monitor-ck.o `test -f 'nm-session-monitor-ck.c' || echo '$(srcdir)/'`nm-session-monitor-ck.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-session-monitor-ck.Tpo $(DEPDIR)/NetworkManager-nm-session-monitor-ck.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-session-monitor-ck.c' object='NetworkManager-nm-session-monitor-ck.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-session-monitor-ck.o `test -f 'nm-session-monitor-ck.c' || echo '$(srcdir)/'`nm-session-monitor-ck.c - -NetworkManager-nm-session-monitor-ck.obj: nm-session-monitor-ck.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-session-monitor-ck.obj -MD -MP -MF $(DEPDIR)/NetworkManager-nm-session-monitor-ck.Tpo -c -o NetworkManager-nm-session-monitor-ck.obj `if test -f 'nm-session-monitor-ck.c'; then $(CYGPATH_W) 'nm-session-monitor-ck.c'; else $(CYGPATH_W) '$(srcdir)/nm-session-monitor-ck.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-session-monitor-ck.Tpo $(DEPDIR)/NetworkManager-nm-session-monitor-ck.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-session-monitor-ck.c' object='NetworkManager-nm-session-monitor-ck.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-session-monitor-ck.obj `if test -f 'nm-session-monitor-ck.c'; then $(CYGPATH_W) 'nm-session-monitor-ck.c'; else $(CYGPATH_W) '$(srcdir)/nm-session-monitor-ck.c'; fi` - -NetworkManager-nm-session-monitor-null.o: nm-session-monitor-null.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-session-monitor-null.o -MD -MP -MF $(DEPDIR)/NetworkManager-nm-session-monitor-null.Tpo -c -o NetworkManager-nm-session-monitor-null.o `test -f 'nm-session-monitor-null.c' || echo '$(srcdir)/'`nm-session-monitor-null.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-session-monitor-null.Tpo $(DEPDIR)/NetworkManager-nm-session-monitor-null.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-session-monitor-null.c' object='NetworkManager-nm-session-monitor-null.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-session-monitor-null.o `test -f 'nm-session-monitor-null.c' || echo '$(srcdir)/'`nm-session-monitor-null.c - -NetworkManager-nm-session-monitor-null.obj: nm-session-monitor-null.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-session-monitor-null.obj -MD -MP -MF $(DEPDIR)/NetworkManager-nm-session-monitor-null.Tpo -c -o NetworkManager-nm-session-monitor-null.obj `if test -f 'nm-session-monitor-null.c'; then $(CYGPATH_W) 'nm-session-monitor-null.c'; else $(CYGPATH_W) '$(srcdir)/nm-session-monitor-null.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-session-monitor-null.Tpo $(DEPDIR)/NetworkManager-nm-session-monitor-null.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-session-monitor-null.c' object='NetworkManager-nm-session-monitor-null.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-session-monitor-null.obj `if test -f 'nm-session-monitor-null.c'; then $(CYGPATH_W) 'nm-session-monitor-null.c'; else $(CYGPATH_W) '$(srcdir)/nm-session-monitor-null.c'; fi` - -NetworkManager-nm-sleep-monitor-systemd.o: nm-sleep-monitor-systemd.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-sleep-monitor-systemd.o -MD -MP -MF $(DEPDIR)/NetworkManager-nm-sleep-monitor-systemd.Tpo -c -o NetworkManager-nm-sleep-monitor-systemd.o `test -f 'nm-sleep-monitor-systemd.c' || echo '$(srcdir)/'`nm-sleep-monitor-systemd.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-sleep-monitor-systemd.Tpo $(DEPDIR)/NetworkManager-nm-sleep-monitor-systemd.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-sleep-monitor-systemd.c' object='NetworkManager-nm-sleep-monitor-systemd.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-sleep-monitor-systemd.o `test -f 'nm-sleep-monitor-systemd.c' || echo '$(srcdir)/'`nm-sleep-monitor-systemd.c - -NetworkManager-nm-sleep-monitor-systemd.obj: nm-sleep-monitor-systemd.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-sleep-monitor-systemd.obj -MD -MP -MF $(DEPDIR)/NetworkManager-nm-sleep-monitor-systemd.Tpo -c -o NetworkManager-nm-sleep-monitor-systemd.obj `if test -f 'nm-sleep-monitor-systemd.c'; then $(CYGPATH_W) 'nm-sleep-monitor-systemd.c'; else $(CYGPATH_W) '$(srcdir)/nm-sleep-monitor-systemd.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-sleep-monitor-systemd.Tpo $(DEPDIR)/NetworkManager-nm-sleep-monitor-systemd.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-sleep-monitor-systemd.c' object='NetworkManager-nm-sleep-monitor-systemd.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-sleep-monitor-systemd.obj `if test -f 'nm-sleep-monitor-systemd.c'; then $(CYGPATH_W) 'nm-sleep-monitor-systemd.c'; else $(CYGPATH_W) '$(srcdir)/nm-sleep-monitor-systemd.c'; fi` - -NetworkManager-nm-sleep-monitor-upower.o: nm-sleep-monitor-upower.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-sleep-monitor-upower.o -MD -MP -MF $(DEPDIR)/NetworkManager-nm-sleep-monitor-upower.Tpo -c -o NetworkManager-nm-sleep-monitor-upower.o `test -f 'nm-sleep-monitor-upower.c' || echo '$(srcdir)/'`nm-sleep-monitor-upower.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-sleep-monitor-upower.Tpo $(DEPDIR)/NetworkManager-nm-sleep-monitor-upower.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-sleep-monitor-upower.c' object='NetworkManager-nm-sleep-monitor-upower.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-sleep-monitor-upower.o `test -f 'nm-sleep-monitor-upower.c' || echo '$(srcdir)/'`nm-sleep-monitor-upower.c - -NetworkManager-nm-sleep-monitor-upower.obj: nm-sleep-monitor-upower.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-sleep-monitor-upower.obj -MD -MP -MF $(DEPDIR)/NetworkManager-nm-sleep-monitor-upower.Tpo -c -o NetworkManager-nm-sleep-monitor-upower.obj `if test -f 'nm-sleep-monitor-upower.c'; then $(CYGPATH_W) 'nm-sleep-monitor-upower.c'; else $(CYGPATH_W) '$(srcdir)/nm-sleep-monitor-upower.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-sleep-monitor-upower.Tpo $(DEPDIR)/NetworkManager-nm-sleep-monitor-upower.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-sleep-monitor-upower.c' object='NetworkManager-nm-sleep-monitor-upower.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-sleep-monitor-upower.obj `if test -f 'nm-sleep-monitor-upower.c'; then $(CYGPATH_W) 'nm-sleep-monitor-upower.c'; else $(CYGPATH_W) '$(srcdir)/nm-sleep-monitor-upower.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o wifi-utils-wext.lo `test -f 'platform/wifi/wifi-utils-wext.c' || echo '$(srcdir)/'`platform/wifi/wifi-utils-wext.c mostlyclean-libtool: -rm -f *.lo @@ -2009,60 +1870,12 @@ uninstall-am: uninstall-dbusserviceDATA uninstall-sbinPROGRAMS tags tags-am uninstall uninstall-am uninstall-dbusserviceDATA \ uninstall-sbinPROGRAMS +include $(GLIB_MAKEFILE) -nm-access-point-glue.h: $(top_srcdir)/introspection/nm-access-point.xml - $(AM_V_GEN) dbus-binding-tool --prefix=nm_access_point --mode=glib-server --output=$@ $< - -nm-manager-glue.h: $(top_srcdir)/introspection/nm-manager.xml - $(AM_V_GEN) dbus-binding-tool --prefix=nm_manager --mode=glib-server --output=$@ $< - -nm-device-interface-glue.h: $(top_srcdir)/introspection/nm-device.xml - $(AM_V_GEN) dbus-binding-tool --prefix=nm_device_interface --mode=glib-server --output=$@ $< - -nm-device-ethernet-glue.h: $(top_srcdir)/introspection/nm-device-ethernet.xml - $(AM_V_GEN) dbus-binding-tool --prefix=nm_device_ethernet --mode=glib-server --output=$@ $< - -nm-device-infiniband-glue.h: $(top_srcdir)/introspection/nm-device-infiniband.xml - $(AM_V_GEN) dbus-binding-tool --prefix=nm_device_infiniband --mode=glib-server --output=$@ $< - -nm-device-adsl-glue.h: $(top_srcdir)/introspection/nm-device-adsl.xml - $(AM_V_GEN) dbus-binding-tool --prefix=nm_device_adsl --mode=glib-server --output=$@ $< - -nm-device-wifi-glue.h: $(top_srcdir)/introspection/nm-device-wifi.xml - $(AM_V_GEN) dbus-binding-tool --prefix=nm_device_wifi --mode=glib-server --output=$@ $< - -nm-device-bt-glue.h: $(top_srcdir)/introspection/nm-device-bt.xml - $(AM_V_GEN) dbus-binding-tool --prefix=nm_device_bt --mode=glib-server --output=$@ $< - -nm-device-olpc-mesh-glue.h: $(top_srcdir)/introspection/nm-device-olpc-mesh.xml - $(AM_V_GEN) dbus-binding-tool --prefix=nm_device_olpc_mesh --mode=glib-server --output=$@ $< - -nm-device-bond-glue.h: $(top_srcdir)/introspection/nm-device-bond.xml - $(AM_V_GEN) dbus-binding-tool --prefix=nm_device_bond --mode=glib-server --output=$@ $< - -nm-device-bridge-glue.h: $(top_srcdir)/introspection/nm-device-bridge.xml - $(AM_V_GEN) dbus-binding-tool --prefix=nm_device_bridge --mode=glib-server --output=$@ $< - -nm-device-vlan-glue.h: $(top_srcdir)/introspection/nm-device-vlan.xml - $(AM_V_GEN) dbus-binding-tool --prefix=nm_device_vlan --mode=glib-server --output=$@ $< - -nm-ip4-config-glue.h: $(top_srcdir)/introspection/nm-ip4-config.xml - $(AM_V_GEN) dbus-binding-tool --prefix=nm_ip4_config --mode=glib-server --output=$@ $< - -nm-ip6-config-glue.h: $(top_srcdir)/introspection/nm-ip6-config.xml - $(AM_V_GEN) dbus-binding-tool --prefix=nm_ip6_config --mode=glib-server --output=$@ $< - -nm-active-connection-glue.h: $(top_srcdir)/introspection/nm-active-connection.xml - $(AM_V_GEN) dbus-binding-tool --prefix=nm_active_connection --mode=glib-server --output=$@ $< - -nm-dhcp4-config-glue.h: $(top_srcdir)/introspection/nm-dhcp4-config.xml - $(AM_V_GEN) dbus-binding-tool --prefix=nm_dhcp4_config --mode=glib-server --output=$@ $< - -nm-dhcp6-config-glue.h: $(top_srcdir)/introspection/nm-dhcp6-config.xml - $(AM_V_GEN) dbus-binding-tool --prefix=nm_dhcp6_config --mode=glib-server --output=$@ $< +@GNOME_CODE_COVERAGE_RULES@ -nm-device-modem-glue.h: $(top_srcdir)/introspection/nm-device-modem.xml - $(AM_V_GEN) dbus-binding-tool --prefix=nm_device_modem --mode=glib-server --output=$@ $< +%-glue.h: $(top_srcdir)/introspection/%.xml + $(AM_V_GEN) dbus-binding-tool --prefix=$(subst -,_,$(subst -glue.h,,$@)) --mode=glib-server --output=$@ $< install-data-hook: $(mkinstalldirs) -m 0700 $(DESTDIR)$(rundir) $(mkinstalldirs) -m 0700 $(DESTDIR)$(statedir) diff --git a/src/NetworkManagerUtils.c b/src/NetworkManagerUtils.c index 2f369d68..0aaa344f 100644 --- a/src/NetworkManagerUtils.c +++ b/src/NetworkManagerUtils.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "NetworkManagerUtils.h" #include "nm-utils.h" @@ -74,6 +75,50 @@ nm_ethernet_address_is_valid (const struct ether_addr *test_addr) } +/* nm_utils_ip4_address_clear_host_address: + * @addr: source ip6 address + * @plen: prefix length of network + * + * returns: the input address, with the host address set to 0. + */ +in_addr_t +nm_utils_ip4_address_clear_host_address (in_addr_t addr, guint8 plen) +{ + return addr & nm_utils_ip4_prefix_to_netmask (plen); +} + +/* nm_utils_ip6_address_clear_host_address: + * @dst: destination output buffer, will contain the network part of the @src address + * @src: source ip6 address + * @plen: prefix length of network + * + * Note: this function is self assignment save, to update @src inplace, set both + * @dst and @src to the same destination. + */ +void +nm_utils_ip6_address_clear_host_address (struct in6_addr *dst, const struct in6_addr *src, guint8 plen) +{ + g_return_if_fail (plen <= 128); + g_return_if_fail (src); + g_return_if_fail (dst); + + if (plen < 128) { + guint nbytes = plen / 8; + guint nbits = plen % 8; + + if (nbytes && dst != src) + memcpy (dst, src, nbytes); + if (nbits) { + dst->s6_addr[nbytes] = (src->s6_addr[nbytes] & (0xFF << (8 - nbits))); + nbytes++; + } + if (nbytes <= 15) + memset (&dst->s6_addr[nbytes], 0, 16 - nbytes); + } else if (src != dst) + *dst = *src; +} + + int nm_spawn_process (const char *args) { @@ -99,240 +144,45 @@ nm_spawn_process (const char *args) return status; } -void -nm_utils_merge_ip4_config (NMIP4Config *ip4_config, NMSettingIP4Config *setting) -{ - int i, j; - gboolean setting_never_default; - - if (!setting) - return; /* Defaults are just fine */ - - if (nm_setting_ip4_config_get_ignore_auto_dns (setting)) { - nm_ip4_config_reset_nameservers (ip4_config); - nm_ip4_config_reset_domains (ip4_config); - nm_ip4_config_reset_searches (ip4_config); - } - - if (nm_setting_ip4_config_get_ignore_auto_routes (setting)) - nm_ip4_config_reset_routes (ip4_config); - - for (i = 0; i < nm_setting_ip4_config_get_num_dns (setting); i++) { - guint32 ns; - gboolean found = FALSE; - - /* Avoid dupes */ - ns = nm_setting_ip4_config_get_dns (setting, i); - for (j = 0; j < nm_ip4_config_get_num_nameservers (ip4_config); j++) { - if (nm_ip4_config_get_nameserver (ip4_config, j) == ns) { - found = TRUE; - break; - } - } - - if (!found) - nm_ip4_config_add_nameserver (ip4_config, ns); - } - - /* DNS search domains */ - for (i = 0; i < nm_setting_ip4_config_get_num_dns_searches (setting); i++) { - const char *search = nm_setting_ip4_config_get_dns_search (setting, i); - gboolean found = FALSE; - - /* Avoid dupes */ - for (j = 0; j < nm_ip4_config_get_num_searches (ip4_config); j++) { - if (!strcmp (search, nm_ip4_config_get_search (ip4_config, j))) { - found = TRUE; - break; - } - } - - if (!found) - nm_ip4_config_add_search (ip4_config, search); - } - - /* IPv4 addresses */ - for (i = 0; i < nm_setting_ip4_config_get_num_addresses (setting); i++) { - NMIP4Address *setting_addr = nm_setting_ip4_config_get_address (setting, i); - guint32 num; - - num = nm_ip4_config_get_num_addresses (ip4_config); - for (j = 0; j < num; j++) { - NMIP4Address *cfg_addr = nm_ip4_config_get_address (ip4_config, j); - - /* Dupe, override with user-specified address */ - if (nm_ip4_address_get_address (cfg_addr) == nm_ip4_address_get_address (setting_addr)) { - nm_ip4_config_replace_address (ip4_config, j, setting_addr); - break; - } - } - - if (j == num) - nm_ip4_config_add_address (ip4_config, setting_addr); - } - - /* IPv4 routes */ - for (i = 0; i < nm_setting_ip4_config_get_num_routes (setting); i++) { - NMIP4Route *setting_route = nm_setting_ip4_config_get_route (setting, i); - guint32 num; - - num = nm_ip4_config_get_num_routes (ip4_config); - for (j = 0; j < num; j++) { - NMIP4Route *cfg_route = nm_ip4_config_get_route (ip4_config, j); - - /* Dupe, override with user-specified route */ - if ( (nm_ip4_route_get_dest (cfg_route) == nm_ip4_route_get_dest (setting_route)) - && (nm_ip4_route_get_prefix (cfg_route) == nm_ip4_route_get_prefix (setting_route)) - && (nm_ip4_route_get_next_hop (cfg_route) == nm_ip4_route_get_next_hop (setting_route))) { - nm_ip4_config_replace_route (ip4_config, j, setting_route); - break; - } - } - - if (j == num) - nm_ip4_config_add_route (ip4_config, setting_route); - } - - setting_never_default = nm_setting_ip4_config_get_never_default (setting); - - if (nm_setting_ip4_config_get_ignore_auto_routes (setting)) - nm_ip4_config_set_never_default (ip4_config, setting_never_default); - else { - if (setting_never_default) - nm_ip4_config_set_never_default (ip4_config, TRUE); - } -} - -static inline gboolean -ip6_addresses_equal (const struct in6_addr *a, const struct in6_addr *b) -{ - return memcmp (a, b, sizeof (struct in6_addr)) == 0; -} - -/* This is exactly identical to nm_utils_merge_ip4_config, with s/4/6/, - * except that we can't compare addresses with ==. - */ -void -nm_utils_merge_ip6_config (NMIP6Config *ip6_config, NMSettingIP6Config *setting) +gboolean +nm_match_spec_string (const GSList *specs, const char *match) { - int i, j; - - if (!setting) - return; /* Defaults are just fine */ - - if (nm_setting_ip6_config_get_ignore_auto_dns (setting)) { - nm_ip6_config_reset_nameservers (ip6_config); - nm_ip6_config_reset_domains (ip6_config); - nm_ip6_config_reset_searches (ip6_config); - } - - if (nm_setting_ip6_config_get_ignore_auto_routes (setting)) - nm_ip6_config_reset_routes (ip6_config); - - for (i = 0; i < nm_setting_ip6_config_get_num_dns (setting); i++) { - const struct in6_addr *ns; - gboolean found = FALSE; - - /* Avoid dupes */ - ns = nm_setting_ip6_config_get_dns (setting, i); - for (j = 0; j < nm_ip6_config_get_num_nameservers (ip6_config); j++) { - if (ip6_addresses_equal (nm_ip6_config_get_nameserver (ip6_config, j), ns)) { - found = TRUE; - break; - } - } - - if (!found) - nm_ip6_config_add_nameserver (ip6_config, ns); - } - - /* DNS search domains */ - for (i = 0; i < nm_setting_ip6_config_get_num_dns_searches (setting); i++) { - const char *search = nm_setting_ip6_config_get_dns_search (setting, i); - gboolean found = FALSE; - - /* Avoid dupes */ - for (j = 0; j < nm_ip6_config_get_num_searches (ip6_config); j++) { - if (!strcmp (search, nm_ip6_config_get_search (ip6_config, j))) { - found = TRUE; - break; - } - } - - if (!found) - nm_ip6_config_add_search (ip6_config, search); - } - - /* IPv6 addresses */ - for (i = 0; i < nm_setting_ip6_config_get_num_addresses (setting); i++) { - NMIP6Address *setting_addr = nm_setting_ip6_config_get_address (setting, i); - guint32 num; - - num = nm_ip6_config_get_num_addresses (ip6_config); - for (j = 0; j < num; j++) { - NMIP6Address *cfg_addr = nm_ip6_config_get_address (ip6_config, j); - - /* Dupe, override with user-specified address */ - if (ip6_addresses_equal (nm_ip6_address_get_address (cfg_addr), nm_ip6_address_get_address (setting_addr))) { - nm_ip6_config_replace_address (ip6_config, j, setting_addr); - break; - } - } - - if (j == num) - nm_ip6_config_add_address (ip6_config, setting_addr); - } - - /* IPv6 routes */ - for (i = 0; i < nm_setting_ip6_config_get_num_routes (setting); i++) { - NMIP6Route *setting_route = nm_setting_ip6_config_get_route (setting, i); - guint32 num; - - num = nm_ip6_config_get_num_routes (ip6_config); - for (j = 0; j < num; j++) { - NMIP6Route *cfg_route = nm_ip6_config_get_route (ip6_config, j); - - /* Dupe, override with user-specified route */ - if ( ip6_addresses_equal (nm_ip6_route_get_dest (cfg_route), nm_ip6_route_get_dest (setting_route)) - && (nm_ip6_route_get_prefix (cfg_route) == nm_ip6_route_get_prefix (setting_route)) - && ip6_addresses_equal (nm_ip6_route_get_next_hop (cfg_route), nm_ip6_route_get_next_hop (setting_route))) { - nm_ip6_config_replace_route (ip6_config, j, setting_route); - break; - } - } + const GSList *iter; - if (j == num) - nm_ip6_config_add_route (ip6_config, setting_route); + for (iter = specs; iter; iter = g_slist_next (iter)) { + if (!g_ascii_strcasecmp ((const char *) iter->data, match)) + return TRUE; } - if (nm_setting_ip6_config_get_never_default (setting)) - nm_ip6_config_set_never_default (ip6_config, TRUE); + return FALSE; } gboolean nm_match_spec_hwaddr (const GSList *specs, const char *hwaddr) { - const GSList *iter; - char *hwaddr_match, *p; + char *hwaddr_match; + gboolean matched; g_return_val_if_fail (hwaddr != NULL, FALSE); - p = hwaddr_match = g_strdup_printf ("mac:%s", hwaddr); + hwaddr_match = g_strdup_printf ("mac:%s", hwaddr); + matched = nm_match_spec_string (specs, hwaddr_match); + g_free (hwaddr_match); + return matched; +} - while (*p) { - *p = g_ascii_tolower (*p); - p++; - } +gboolean +nm_match_spec_interface_name (const GSList *specs, const char *interface_name) +{ + char *iface_match; + gboolean matched; - for (iter = specs; iter; iter = g_slist_next (iter)) { - if (!strcmp ((const char *) iter->data, hwaddr_match)) { - g_free (hwaddr_match); - return TRUE; - } - } + g_return_val_if_fail (interface_name != NULL, FALSE); - g_free (hwaddr_match); - return FALSE; + iface_match = g_strdup_printf ("interface-name:%s", interface_name); + matched = nm_match_spec_string (specs, iface_match); + g_free (iface_match); + return matched; } #define BUFSIZE 10 @@ -435,20 +285,16 @@ nm_utils_get_shared_wifi_permission (NMConnection *connection) { NMSettingWireless *s_wifi; NMSettingWirelessSecurity *s_wsec; - NMSettingIP4Config *s_ip4; const char *method = NULL; - s_ip4 = nm_connection_get_setting_ip4_config (connection); - if (s_ip4) - method = nm_setting_ip4_config_get_method (s_ip4); - - if (g_strcmp0 (method, NM_SETTING_IP4_CONFIG_METHOD_SHARED) != 0) + method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP4_CONFIG); + if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_SHARED) != 0) return NULL; /* Not shared */ s_wifi = nm_connection_get_setting_wireless (connection); if (s_wifi) { s_wsec = nm_connection_get_setting_wireless_security (connection); - if (nm_setting_wireless_get_security (s_wifi) || s_wsec) + if (s_wsec) return NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED; else return NM_AUTH_PERMISSION_WIFI_SHARE_OPEN; @@ -553,116 +399,6 @@ value_hash_add_object_property (GHashTable *hash, value_hash_add (hash, key, value); } -/** - * nm_utils_do_sysctl: - * @path: path to write @value to - * @value: value to write to @path - * - * Writes @value to the file at @path, trying 3 times on failure. - * - * Returns: %TRUE on success. On failure, returns %FALSE and sets errno. - */ -gboolean -nm_utils_do_sysctl (const char *path, const char *value) -{ - int fd, len, nwrote, tries, saved_errno = 0; - char *actual; - - g_return_val_if_fail (path != NULL, FALSE); - g_return_val_if_fail (value != NULL, FALSE); - - fd = open (path, O_WRONLY | O_TRUNC); - if (fd == -1) { - saved_errno = errno; - nm_log_warn (LOGD_CORE, "sysctl: failed to open '%s': (%d) %s", - path, saved_errno, strerror (saved_errno)); - errno = saved_errno; - return FALSE; - } - - nm_log_dbg (LOGD_CORE, "sysctl: setting '%s' to '%s'", path, value); - - /* Most sysfs and sysctl options don't care about a trailing CR, while some - * (like infiniband) do. So always add the CR. Also, neither sysfs nor - * sysctl support partial writes so the CR must be added to the string we're - * about to write. - */ - actual = g_strdup_printf ("%s\n", value); - - /* Try to write the entire value three times if a partial write occurs */ - len = strlen (actual); - for (tries = 0, nwrote = 0; tries < 3 && nwrote != len; tries++) { - errno = 0; - nwrote = write (fd, actual, len); - if (nwrote == -1) { - if (errno == EINTR) - continue; - saved_errno = errno; - break; - } - } - g_free (actual); - close (fd); - - if (nwrote != len && saved_errno != EEXIST) { - nm_log_warn (LOGD_CORE, "sysctl: failed to set '%s' to '%s': (%d) %s", - path, value, saved_errno, strerror (saved_errno)); - } - - errno = saved_errno; - return (nwrote == len); -} - -gboolean -nm_utils_get_proc_sys_net_value (const char *path, - const char *iface, - gint32 *out_value) -{ - GError *error = NULL; - char *contents = NULL; - gboolean success = FALSE; - long int tmp; - - if (!g_file_get_contents (path, &contents, NULL, &error)) { - nm_log_dbg (LOGD_DEVICE, "(%s): error reading %s: (%d) %s", - iface, path, - error ? error->code : -1, - error && error->message ? error->message : "(unknown)"); - g_clear_error (&error); - } else { - errno = 0; - tmp = strtol (contents, NULL, 10); - if (errno == 0) { - *out_value = (gint32) tmp; - success = TRUE; - } - g_free (contents); - } - - return success; -} - -gboolean -nm_utils_get_proc_sys_net_value_with_bounds (const char *path, - const char *iface, - gint32 *out_value, - gint32 valid_min, - gint32 valid_max) -{ - gboolean result; - gint32 val; - - result = nm_utils_get_proc_sys_net_value (path, iface, &val); - - if (result) { - if (val >= valid_min && val <= valid_max) - *out_value = val; - else - result = FALSE; - } - - return result; -} static char * get_new_connection_name (const GSList *existing, @@ -717,6 +453,113 @@ get_new_connection_name (const GSList *existing, return cname; } +void +nm_utils_normalize_connection (NMConnection *connection, + gboolean default_enable_ipv6) +{ + NMSettingConnection *s_con = nm_connection_get_setting_connection (connection); + const char *default_ip4_method = NM_SETTING_IP4_CONFIG_METHOD_AUTO; + const char *default_ip6_method = + default_enable_ipv6 ? NM_SETTING_IP6_CONFIG_METHOD_AUTO : NM_SETTING_IP6_CONFIG_METHOD_IGNORE; + NMSettingIP4Config *s_ip4; + NMSettingIP6Config *s_ip6; + NMSetting *setting; + const char *method; + + s_ip4 = nm_connection_get_setting_ip4_config (connection); + s_ip6 = nm_connection_get_setting_ip6_config (connection); + + if (nm_setting_connection_get_master (s_con)) { + /* Slave connections don't have IP configuration. */ + + if (s_ip4) { + method = nm_setting_ip4_config_get_method (s_ip4); + if (g_strcmp0 (method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED) != 0) { + nm_log_warn (LOGD_SETTINGS, "ignoring IP4 config on slave '%s'", + nm_connection_get_id (connection)); + } + nm_connection_remove_setting (connection, NM_TYPE_SETTING_IP4_CONFIG); + s_ip4 = NULL; + } + + if (s_ip6) { + method = nm_setting_ip6_config_get_method (s_ip6); + if (g_strcmp0 (method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE) != 0) { + nm_log_warn (LOGD_SETTINGS, "ignoring IP6 config on slave '%s'", + nm_connection_get_id (connection)); + } + nm_connection_remove_setting (connection, NM_TYPE_SETTING_IP6_CONFIG); + s_ip6 = NULL; + } + } else { + /* Ensure all non-slave connections have IP4 and IP6 settings objects. If no + * IP6 setting was specified, then assume that means IP6 config is allowed + * to fail. But if no IP4 setting was specified, assume the caller was just + * being lazy. + */ + if (!s_ip4) { + setting = nm_setting_ip4_config_new (); + nm_connection_add_setting (connection, setting); + + g_object_set (setting, + NM_SETTING_IP4_CONFIG_METHOD, default_ip4_method, + NULL); + } + if (!s_ip6) { + setting = nm_setting_ip6_config_new (); + nm_connection_add_setting (connection, setting); + + g_object_set (setting, + NM_SETTING_IP6_CONFIG_METHOD, default_ip6_method, + NM_SETTING_IP6_CONFIG_MAY_FAIL, TRUE, + NULL); + } + } +} + +const char * +nm_utils_get_ip_config_method (NMConnection *connection, + GType ip_setting_type) +{ + NMSettingConnection *s_con; + NMSettingIP4Config *s_ip4; + NMSettingIP6Config *s_ip6; + const char *method; + + s_con = nm_connection_get_setting_connection (connection); + + if (ip_setting_type == NM_TYPE_SETTING_IP4_CONFIG) { + g_return_val_if_fail (s_con != NULL, NM_SETTING_IP4_CONFIG_METHOD_AUTO); + + if (nm_setting_connection_get_master (s_con)) + return NM_SETTING_IP4_CONFIG_METHOD_DISABLED; + else { + s_ip4 = nm_connection_get_setting_ip4_config (connection); + g_return_val_if_fail (s_ip4 != NULL, NM_SETTING_IP4_CONFIG_METHOD_AUTO); + method = nm_setting_ip4_config_get_method (s_ip4); + g_return_val_if_fail (method != NULL, NM_SETTING_IP4_CONFIG_METHOD_AUTO); + + return method; + } + + } else if (ip_setting_type == NM_TYPE_SETTING_IP6_CONFIG) { + g_return_val_if_fail (s_con != NULL, NM_SETTING_IP6_CONFIG_METHOD_AUTO); + + if (nm_setting_connection_get_master (s_con)) + return NM_SETTING_IP6_CONFIG_METHOD_IGNORE; + else { + s_ip6 = nm_connection_get_setting_ip6_config (connection); + g_return_val_if_fail (s_ip6 != NULL, NM_SETTING_IP6_CONFIG_METHOD_AUTO); + method = nm_setting_ip6_config_get_method (s_ip6); + g_return_val_if_fail (method != NULL, NM_SETTING_IP6_CONFIG_METHOD_AUTO); + + return method; + } + + } else + g_assert_not_reached (); +} + void nm_utils_complete_generic (NMConnection *connection, const char *ctype, @@ -726,9 +569,6 @@ nm_utils_complete_generic (NMConnection *connection, gboolean default_enable_ipv6) { NMSettingConnection *s_con; - NMSettingIP4Config *s_ip4; - NMSettingIP6Config *s_ip6; - const char *method; char *id, *uuid; s_con = nm_connection_get_setting_connection (connection); @@ -751,37 +591,622 @@ nm_utils_complete_generic (NMConnection *connection, g_free (id); } - /* Add an 'auto' IPv4 connection if present */ - s_ip4 = nm_connection_get_setting_ip4_config (connection); - if (!s_ip4) { - s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new (); - nm_connection_add_setting (connection, NM_SETTING (s_ip4)); + /* Normalize */ + nm_utils_normalize_connection (connection, default_enable_ipv6); +} + +char * +nm_utils_new_vlan_name (const char *parent_iface, guint32 vlan_id) +{ + /* Basically VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD */ + return g_strdup_printf ("%s.%d", parent_iface, vlan_id); +} + +/** + * nm_utils_read_resolv_conf_nameservers(): + * @rc_contents: contents of a resolv.conf; or %NULL to read /etc/resolv.conf + * + * Reads all nameservers out of @rc_contents or /etc/resolv.conf and returns + * them. + * + * Returns: a #GPtrArray of 'char *' elements of each nameserver line from + * @contents or resolv.conf + */ +GPtrArray * +nm_utils_read_resolv_conf_nameservers (const char *rc_contents) +{ + GPtrArray *nameservers = NULL; + char *contents = NULL; + char **lines, **iter; + char *p; + + if (rc_contents) + contents = g_strdup (rc_contents); + else { + if (!g_file_get_contents (_PATH_RESCONF, &contents, NULL, NULL)) + return NULL; } - method = nm_setting_ip4_config_get_method (s_ip4); - if (!method) { - g_object_set (G_OBJECT (s_ip4), - NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, - NULL); + + nameservers = g_ptr_array_new_full (3, g_free); + + lines = g_strsplit_set (contents, "\r\n", -1); + for (iter = lines; *iter; iter++) { + if (!g_str_has_prefix (*iter, "nameserver")) + continue; + p = *iter + strlen ("nameserver"); + if (!g_ascii_isspace (*p++)) + continue; + /* Skip intermediate whitespace */ + while (g_ascii_isspace (*p)) + p++; + g_strchomp (p); + + g_ptr_array_add (nameservers, g_strdup (p)); } + g_strfreev (lines); + g_free (contents); - /* Add an 'auto' IPv6 setting if allowed and not preset */ - s_ip6 = nm_connection_get_setting_ip6_config (connection); - if (!s_ip6 && default_enable_ipv6) { - s_ip6 = (NMSettingIP6Config *) nm_setting_ip6_config_new (); - nm_connection_add_setting (connection, NM_SETTING (s_ip6)); + return nameservers; +} + +static GHashTable * +check_property_in_hash (GHashTable *hash, + const char *s_name, + const char *p_name) +{ + GHashTable *props; + + props = g_hash_table_lookup (hash, s_name); + if ( !props + || !g_hash_table_lookup (props, p_name)) { + return NULL; } - if (s_ip6 && !nm_setting_ip6_config_get_method (s_ip6)) { - g_object_set (G_OBJECT (s_ip6), - NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO, - NM_SETTING_IP6_CONFIG_MAY_FAIL, TRUE, - NULL); + return props; +} + +static void +remove_from_hash (GHashTable *s_hash, + GHashTable *p_hash, + const char *s_name, + const char *p_name) +{ + g_hash_table_remove (p_hash, p_name); + if (g_hash_table_size (p_hash) == 0) + g_hash_table_remove (s_hash, s_name); +} + +static gboolean +check_ip6_method (NMConnection *orig, + NMConnection *candidate, + GHashTable *settings) +{ + GHashTable *props; + const char *orig_ip6_method, *candidate_ip6_method; + NMSettingIP6Config *candidate_ip6; + gboolean allow = FALSE; + + props = check_property_in_hash (settings, + NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_IP6_CONFIG_METHOD); + if (!props) + return TRUE; + + /* If the generated connection is 'link-local' and the candidate is both 'auto' + * and may-fail=TRUE, then the candidate is OK to use. may-fail is included + * in the decision because if the candidate is 'auto' but may-fail=FALSE, then + * the connection could not possibly have been previously activated on the + * device if the device has no non-link-local IPv6 address. + */ + orig_ip6_method = nm_utils_get_ip_config_method (orig, NM_TYPE_SETTING_IP6_CONFIG); + candidate_ip6_method = nm_utils_get_ip_config_method (candidate, NM_TYPE_SETTING_IP6_CONFIG); + candidate_ip6 = nm_connection_get_setting_ip6_config (candidate); + + if ( strcmp (orig_ip6_method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL) == 0 + && strcmp (candidate_ip6_method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) == 0 + && (!candidate_ip6 || nm_setting_ip6_config_get_may_fail (candidate_ip6))) { + allow = TRUE; } + + /* If the generated connection method is 'link-local' or 'auto' and the candidate + * method is 'ignore' we can take the connection, because NM didn't simply take care + * of IPv6. + */ + if ( ( strcmp (orig_ip6_method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL) == 0 + || strcmp (orig_ip6_method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) == 0) + && strcmp (candidate_ip6_method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE) == 0) { + allow = TRUE; + } + + if (allow) { + remove_from_hash (settings, props, + NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_IP6_CONFIG_METHOD); + } + return allow; } -char * -nm_utils_new_vlan_name (const char *parent_iface, guint32 vlan_id) +static gboolean +check_ip4_method (NMConnection *orig, + NMConnection *candidate, + GHashTable *settings, + gboolean device_has_carrier) { - /* Basically VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD */ - return g_strdup_printf ("%s.%d", parent_iface, vlan_id); + GHashTable *props; + const char *orig_ip4_method, *candidate_ip4_method; + NMSettingIP4Config *candidate_ip4; + + props = check_property_in_hash (settings, + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP4_CONFIG_METHOD); + if (!props) + return TRUE; + + /* If the generated connection is 'disabled' (device had no IP addresses) + * but it has no carrier, that most likely means that IP addressing could + * not complete and thus no IP addresses were assigned. In that case, allow + * matching to the "auto" method. + */ + orig_ip4_method = nm_utils_get_ip_config_method (orig, NM_TYPE_SETTING_IP4_CONFIG); + candidate_ip4_method = nm_utils_get_ip_config_method (candidate, NM_TYPE_SETTING_IP4_CONFIG); + candidate_ip4 = nm_connection_get_setting_ip4_config (candidate); + + if ( strcmp (orig_ip4_method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED) == 0 + && strcmp (candidate_ip4_method, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0 + && (!candidate_ip4 || nm_setting_ip4_config_get_may_fail (candidate_ip4)) + && (device_has_carrier == FALSE)) { + remove_from_hash (settings, props, + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP4_CONFIG_METHOD); + return TRUE; + } + return FALSE; +} + +static gboolean +check_connection_interface_name (NMConnection *orig, + NMConnection *candidate, + GHashTable *settings) +{ + GHashTable *props; + const char *orig_ifname, *cand_ifname; + NMSettingConnection *s_con_orig, *s_con_cand; + + props = check_property_in_hash (settings, + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_INTERFACE_NAME); + if (!props) + return TRUE; + + /* If one of the interface names is NULL, we accept that connection */ + s_con_orig = nm_connection_get_setting_connection (orig); + s_con_cand = nm_connection_get_setting_connection (candidate); + orig_ifname = nm_setting_connection_get_interface_name (s_con_orig); + cand_ifname = nm_setting_connection_get_interface_name (s_con_cand); + + if (!orig_ifname || !cand_ifname) { + remove_from_hash (settings, props, + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_INTERFACE_NAME); + return TRUE; + } + return FALSE; +} + +static gboolean +check_connection_mac_address (NMConnection *orig, + NMConnection *candidate, + GHashTable *settings) +{ + GHashTable *props; + const GByteArray *orig_mac = NULL, *cand_mac = NULL; + NMSettingWired *s_wired_orig, *s_wired_cand; + + props = check_property_in_hash (settings, + NM_SETTING_WIRED_SETTING_NAME, + NM_SETTING_WIRED_MAC_ADDRESS); + if (!props) + return TRUE; + + /* If one of the MAC addresses is NULL, we accept that connection */ + s_wired_orig = nm_connection_get_setting_wired (orig); + if (s_wired_orig) + orig_mac = nm_setting_wired_get_mac_address (s_wired_orig); + + s_wired_cand = nm_connection_get_setting_wired (candidate); + if (s_wired_cand) + cand_mac = nm_setting_wired_get_mac_address (s_wired_cand); + + if (!orig_mac || !cand_mac) { + remove_from_hash (settings, props, + NM_SETTING_WIRED_SETTING_NAME, + NM_SETTING_WIRED_MAC_ADDRESS); + return TRUE; + } + return FALSE; +} + +static NMConnection * +check_possible_match (NMConnection *orig, + NMConnection *candidate, + GHashTable *settings, + gboolean device_has_carrier) +{ + g_return_val_if_fail (settings != NULL, NULL); + + if (!check_ip6_method (orig, candidate, settings)) + return NULL; + + if (!check_ip4_method (orig, candidate, settings, device_has_carrier)) + return NULL; + + if (!check_connection_interface_name (orig, candidate, settings)) + return NULL; + + if (!check_connection_mac_address (orig, candidate, settings)) + return NULL; + + if (g_hash_table_size (settings) == 0) + return candidate; + else + return NULL; +} + +/** + * nm_utils_match_connection: + * @connections: a (optionally pre-sorted) list of connections from which to + * find a matching connection to @original based on "inferrable" properties + * @original: the #NMConnection to find a match for from @connections + * @device_has_carrier: pass %TRUE if the device that generated @original has + * a carrier, %FALSE if not + * @match_filter_func: a function to check whether each connection from @connections + * should be considered for matching. This function should return %TRUE if the + * connection should be considered, %FALSE if the connection should be ignored + * @match_compat_data: data pointer passed to @match_filter_func + * + * Checks each connection from @connections until a matching connection is found + * considering only setting properties marked with %NM_SETTING_PARAM_INFERRABLE + * and checking a few other characteristics like IPv6 method. If the caller + * desires some priority order of the connections, @connections should be + * sorted before calling this function. + * + * Returns: the best #NMConnection matching @original, or %NULL if no connection + * matches well enough. + */ +NMConnection * +nm_utils_match_connection (GSList *connections, + NMConnection *original, + gboolean device_has_carrier, + NMUtilsMatchFilterFunc match_filter_func, + gpointer match_filter_data) +{ + NMConnection *best_match = NULL; + GSList *iter; + + for (iter = connections; iter; iter = iter->next) { + NMConnection *candidate = NM_CONNECTION (iter->data); + GHashTable *diffs = NULL; + + if (match_filter_func) { + if (!match_filter_func (candidate, match_filter_data)) + continue; + } + + if (!nm_connection_diff (original, candidate, NM_SETTING_COMPARE_FLAG_INFERRABLE, &diffs)) { + if (!best_match) + best_match = check_possible_match (original, candidate, diffs, device_has_carrier); + + if (!best_match && nm_logging_enabled (LOGL_DEBUG, LOGD_CORE)) { + GString *diff_string; + GHashTableIter s_iter, p_iter; + gpointer setting_name, setting; + gpointer property_name, value; + + diff_string = g_string_new (NULL); + g_hash_table_iter_init (&s_iter, diffs); + while (g_hash_table_iter_next (&s_iter, &setting_name, &setting)) { + g_hash_table_iter_init (&p_iter, setting); + while (g_hash_table_iter_next (&p_iter, &property_name, &value)) { + if (diff_string->len) + g_string_append (diff_string, ", "); + g_string_append_printf (diff_string, "%s.%s", + (char *) setting_name, + (char *) property_name); + } + } + + nm_log_dbg (LOGD_CORE, "Connection '%s' differs from candidate '%s' in %s", + nm_connection_get_id (original), + nm_connection_get_id (candidate), + diff_string->str); + g_string_free (diff_string, TRUE); + } + + g_hash_table_unref (diffs); + continue; + } + + /* Exact match */ + return candidate; + } + + /* Best match (if any) */ + return best_match; +} + +/* nm_utils_ascii_str_to_int64: + * + * A wrapper for g_ascii_strtoll, that checks whether the whole string + * can be successfully converted to a number and is within a given + * range. On any error, @fallback will be returned and %errno will be set + * to a non-zero value. On success, %errno will be set to zero, check %errno + * for errors. Any trailing or leading (ascii) white space is ignored and the + * functions is locale independent. + * + * The function is guaranteed to return a value between @min and @max + * (inclusive) or @fallback. Also, the parsing is rather strict, it does + * not allow for any unrecognized characters, except leading and trailing + * white space. + **/ +gint64 +nm_utils_ascii_str_to_int64 (const char *str, guint base, gint64 min, gint64 max, gint64 fallback) +{ + gint64 v; + size_t len; + char buf[64], *s, *str_free = NULL; + + if (str) { + while (g_ascii_isspace (str[0])) + str++; + } + if (!str || !str[0]) { + errno = EINVAL; + return fallback; + } + + len = strlen (str); + if (g_ascii_isspace (str[--len])) { + /* backward search the first non-ws character. + * We already know that str[0] is non-ws. */ + while (g_ascii_isspace (str[--len])) + ; + + /* str[len] is now the last non-ws character... */ + len++; + + if (len >= sizeof (buf)) + s = str_free = g_malloc (len + 1); + else + s = buf; + + memcpy (s, str, len); + s[len] = 0; + + /* + g_assert (len > 0 && len < strlen (str) && len == strlen (s)); + g_assert (!g_ascii_isspace (str[len-1]) && g_ascii_isspace (str[len])); + g_assert (strncmp (str, s, len) == 0); + */ + + str = s; + } + + errno = 0; + v = g_ascii_strtoll (str, &s, base); + + if (errno != 0) + v = fallback; + else if (s[0] != 0) { + errno = EINVAL; + v = fallback; + } else if (v > max || v < min) { + errno = ERANGE; + v = fallback; + } + + if (G_UNLIKELY (str_free)) + g_free (str_free); + return v; +} + + +static gint64 monotonic_timestamp_offset_sec; + +static void +monotonic_timestamp_get (struct timespec *tp) +{ + static gboolean initialized = FALSE; + int err; + + err = clock_gettime (CLOCK_BOOTTIME, tp); + + g_assert (err == 0); (void)err; + g_assert (tp->tv_nsec >= 0 && tp->tv_nsec < NM_UTILS_NS_PER_SECOND); + + if (G_LIKELY (initialized)) + return; + + /* Calculate an offset for the time stamp. + * + * We always want positive values, because then we can initialize + * a timestamp with 0 and be sure, that it will be less then any + * value nm_utils_get_monotonic_timestamp_*() might return. + * For this to be true also for nm_utils_get_monotonic_timestamp_s() at + * early boot, we have to shift the timestamp to start counting at + * least from 1 second onward. + * + * Another advantage of shifting is, that this way we make use of the whole 31 bit + * range of signed int, before the time stamp for nm_utils_get_monotonic_timestamp_s() + * wraps (~68 years). + **/ + monotonic_timestamp_offset_sec = (- ((gint64) tp->tv_sec)) + 1; + initialized = TRUE; + + if (nm_logging_enabled (LOGL_DEBUG, LOGD_CORE)) { + time_t now = time (NULL); + struct tm tm; + char s[255]; + + strftime (s, sizeof (s), "%Y-%m-%d %H:%M:%S", localtime_r (&now, &tm)); + nm_log_dbg (LOGD_CORE, "monotonic timestamp started counting 1.%09ld seconds ago with " + "an offset of %lld.0 seconds to CLOCK_BOOTTIME (local time is %s)", + tp->tv_nsec, (long long) -monotonic_timestamp_offset_sec, s); + } +} + +/** + * nm_utils_get_monotonic_timestamp_ns: + * + * Returns: a monotonically increasing time stamp in nanoseconds, + * starting at an unspecified offset. See clock_gettime(), %CLOCK_BOOTTIME. + * + * The returned value will start counting at an undefined point + * in the past and will always be positive. + * + * All the nm_utils_get_monotonic_timestamp_*s functions return the same + * timestamp but in different scales (nsec, usec, msec, sec). + **/ +gint64 +nm_utils_get_monotonic_timestamp_ns (void) +{ + struct timespec tp; + + monotonic_timestamp_get (&tp); + + /* Although the result will always be positive, we return a signed + * integer, which makes it easier to calculate time differences (when + * you want to subtract signed values). + **/ + return (((gint64) tp.tv_sec) + monotonic_timestamp_offset_sec) * NM_UTILS_NS_PER_SECOND + + tp.tv_nsec; +} + +/** + * nm_utils_get_monotonic_timestamp_us: + * + * Returns: a monotonically increasing time stamp in microseconds, + * starting at an unspecified offset. See clock_gettime(), %CLOCK_BOOTTIME. + * + * The returned value will start counting at an undefined point + * in the past and will always be positive. + * + * All the nm_utils_get_monotonic_timestamp_*s functions return the same + * timestamp but in different scales (nsec, usec, msec, sec). + **/ +gint64 +nm_utils_get_monotonic_timestamp_us (void) +{ + struct timespec tp; + + monotonic_timestamp_get (&tp); + + /* Although the result will always be positive, we return a signed + * integer, which makes it easier to calculate time differences (when + * you want to subtract signed values). + **/ + return (((gint64) tp.tv_sec) + monotonic_timestamp_offset_sec) * ((gint64) G_USEC_PER_SEC) + + (tp.tv_nsec / (NM_UTILS_NS_PER_SECOND/G_USEC_PER_SEC)); +} + +/** + * nm_utils_get_monotonic_timestamp_ms: + * + * Returns: a monotonically increasing time stamp in milliseconds, + * starting at an unspecified offset. See clock_gettime(), %CLOCK_BOOTTIME. + * + * The returned value will start counting at an undefined point + * in the past and will always be positive. + * + * All the nm_utils_get_monotonic_timestamp_*s functions return the same + * timestamp but in different scales (nsec, usec, msec, sec). + **/ +gint64 +nm_utils_get_monotonic_timestamp_ms (void) +{ + struct timespec tp; + + monotonic_timestamp_get (&tp); + + /* Although the result will always be positive, we return a signed + * integer, which makes it easier to calculate time differences (when + * you want to subtract signed values). + **/ + return (((gint64) tp.tv_sec) + monotonic_timestamp_offset_sec) * ((gint64) 1000) + + (tp.tv_nsec / (NM_UTILS_NS_PER_SECOND/1000)); +} + +/** + * nm_utils_get_monotonic_timestamp_s: + * + * Returns: nm_utils_get_monotonic_timestamp_ms() in seconds (throwing + * away sub second parts). The returned value will always be positive. + * + * This value wraps after roughly 68 years which should be fine for any + * practical purpose. + * + * All the nm_utils_get_monotonic_timestamp_*s functions return the same + * timestamp but in different scales (nsec, usec, msec, sec). + **/ +gint32 +nm_utils_get_monotonic_timestamp_s (void) +{ + struct timespec tp; + + monotonic_timestamp_get (&tp); + return (((gint64) tp.tv_sec) + monotonic_timestamp_offset_sec); +} + + +/** + * nm_utils_ip6_property_path: + * @ifname: an interface name + * @property: a property name + * + * Returns the path to IPv6 property @property on @ifname. Note that + * this uses a static buffer. + */ +const char * +nm_utils_ip6_property_path (const char *ifname, const char *property) +{ +#define IPV6_PROPERTY_DIR "/proc/sys/net/ipv6/conf/" + static char path[sizeof (IPV6_PROPERTY_DIR) + IFNAMSIZ + 32]; + int len; + + ifname = ASSERT_VALID_PATH_COMPONENT (ifname); + property = ASSERT_VALID_PATH_COMPONENT (property); + + len = g_snprintf (path, sizeof (path), IPV6_PROPERTY_DIR "%s/%s", + ifname, property); + g_assert (len < sizeof (path) - 1); + + return path; +} + +const char * +ASSERT_VALID_PATH_COMPONENT (const char *name) +{ + const char *n; + + if (name == NULL || name[0] == '\0') + goto fail; + + if (name[0] == '.') { + if (name[1] == '\0') + goto fail; + if (name[1] == '.' && name[2] == '\0') + goto fail; + } + n = name; + do { + if (*n == '/') + goto fail; + } while (*(++n) != '\0'); + + return name; +fail: + if (name) + nm_log_err (LOGD_CORE, "Failed asserting path component: NULL"); + else + nm_log_err (LOGD_CORE, "Failed asserting path component: \"%s\"", name); + g_error ("FATAL: Failed asserting path component: %s", name ? name : "(null)"); } diff --git a/src/NetworkManagerUtils.h b/src/NetworkManagerUtils.h index 057ad283..a09a30e2 100644 --- a/src/NetworkManagerUtils.h +++ b/src/NetworkManagerUtils.h @@ -31,16 +31,22 @@ #include "nm-ip6-config.h" #include "nm-setting-ip6-config.h" #include "nm-connection.h" +#include "nm-setting-private.h" gboolean nm_ethernet_address_is_valid (const struct ether_addr *test_addr); +in_addr_t nm_utils_ip4_address_clear_host_address (in_addr_t addr, guint8 plen); +void nm_utils_ip6_address_clear_host_address (struct in6_addr *dst, const struct in6_addr *src, guint8 plen); + int nm_spawn_process (const char *args); -void nm_utils_merge_ip4_config (NMIP4Config *ip4_config, NMSettingIP4Config *setting); -void nm_utils_merge_ip6_config (NMIP6Config *ip6_config, NMSettingIP6Config *setting); +/* macro to return strlen() of a compile time string. */ +#define STRLEN(str) ( sizeof ("" str) - 1 ) +gboolean nm_match_spec_string (const GSList *specs, const char *string); gboolean nm_match_spec_hwaddr (const GSList *specs, const char *hwaddr); gboolean nm_match_spec_s390_subchannels (const GSList *specs, const char *subchannels); +gboolean nm_match_spec_interface_name (const GSList *specs, const char *interface_name); const char *nm_utils_get_shared_wifi_permission (NMConnection *connection); @@ -71,17 +77,10 @@ void value_hash_add_object_property (GHashTable *hash, const char *prop, GType val_type); -gboolean nm_utils_do_sysctl (const char *path, const char *value); - -gboolean nm_utils_get_proc_sys_net_value (const char *path, - const char *iface, - gint32 *out_value); - -gboolean nm_utils_get_proc_sys_net_value_with_bounds (const char *path, - const char *iface, - gint32 *out_value, - gint32 valid_min, - gint32 valid_max); +void nm_utils_normalize_connection (NMConnection *connection, + gboolean default_enable_ipv6); +const char *nm_utils_get_ip_config_method (NMConnection *connection, + GType ip_setting_type); void nm_utils_complete_generic (NMConnection *connection, const char *ctype, @@ -92,4 +91,25 @@ void nm_utils_complete_generic (NMConnection *connection, char *nm_utils_new_vlan_name (const char *parent_iface, guint32 vlan_id); +GPtrArray *nm_utils_read_resolv_conf_nameservers (const char *rc_contents); + +typedef gboolean (NMUtilsMatchFilterFunc) (NMConnection *connection, gpointer user_data); + +NMConnection *nm_utils_match_connection (GSList *connections, + NMConnection *original, + gboolean device_has_carrier, + NMUtilsMatchFilterFunc match_filter_func, + gpointer match_filter_data); + +gint64 nm_utils_ascii_str_to_int64 (const char *str, guint base, gint64 min, gint64 max, gint64 fallback); + +#define NM_UTILS_NS_PER_SECOND ((gint64) 1000000000) +gint64 nm_utils_get_monotonic_timestamp_ns (void); +gint64 nm_utils_get_monotonic_timestamp_us (void); +gint64 nm_utils_get_monotonic_timestamp_ms (void); +gint32 nm_utils_get_monotonic_timestamp_s (void); + +const char *ASSERT_VALID_PATH_COMPONENT (const char *name) G_GNUC_WARN_UNUSED_RESULT; +const char *nm_utils_ip6_property_path (const char *ifname, const char *property); + #endif /* NETWORK_MANAGER_UTILS_H */ diff --git a/src/bluez-manager/Makefile.am b/src/bluez-manager/Makefile.am deleted file mode 100644 index fb836abf..00000000 --- a/src/bluez-manager/Makefile.am +++ /dev/null @@ -1,44 +0,0 @@ -noinst_LTLIBRARIES = libbluez-manager.la - -libbluez_manager_la_CPPFLAGS = \ - -I${top_srcdir} \ - -I${top_builddir}/include \ - -I${top_srcdir}/include \ - -I${top_builddir}/libnm-util \ - -I${top_srcdir}/libnm-util \ - -I${top_srcdir}/src \ - -I${top_builddir}/src/generated \ - -I${top_srcdir}/src/generated \ - -I${top_srcdir}/src/logging \ - $(DBUS_CFLAGS) \ - $(GLIB_CFLAGS) \ - $(BLUEZ_CFLAGS) \ - -DBINDIR=\"$(bindir)\" \ - -DDATADIR=\"$(datadir)\" \ - -DSYSCONFDIR=\"$(sysconfdir)\" \ - -DLIBEXECDIR=\"$(libexecdir)\" \ - -DLOCALSTATEDIR=\"$(localstatedir)\" - -libbluez_manager_la_SOURCES = \ - nm-bluez-common.h \ - nm-bluez-device.c \ - nm-bluez-device.h \ - nm-bluez-manager.h - -if WITH_BLUEZ4 -libbluez_manager_la_SOURCES += \ - nm-bluez4-adapter.h \ - nm-bluez4-adapter.c \ - nm-bluez4-manager.c -else -libbluez_manager_la_SOURCES += \ - nm-bluez-manager.c -endif - -libbluez_manager_la_LIBADD = \ - $(top_builddir)/src/generated/libnm-generated.la \ - $(top_builddir)/src/logging/libnm-logging.la \ - $(DBUS_LIBS) \ - $(GLIB_LIBS) \ - $(BLUEZ_LIBS) - diff --git a/src/bluez-manager/Makefile.in b/src/bluez-manager/Makefile.in deleted file mode 100644 index f72768a6..00000000 --- a/src/bluez-manager/Makefile.in +++ /dev/null @@ -1,786 +0,0 @@ -# Makefile.in generated by automake 1.13.4 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994-2013 Free Software Foundation, Inc. - -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ - -VPATH = @srcdir@ -am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' -am__make_running_with_option = \ - case $${target_option-} in \ - ?) ;; \ - *) echo "am__make_running_with_option: internal error: invalid" \ - "target option '$${target_option-}' specified" >&2; \ - exit 1;; \ - esac; \ - has_opt=no; \ - sane_makeflags=$$MAKEFLAGS; \ - if $(am__is_gnu_make); then \ - sane_makeflags=$$MFLAGS; \ - else \ - case $$MAKEFLAGS in \ - *\\[\ \ ]*) \ - bs=\\; \ - sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ - | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ - esac; \ - fi; \ - skip_next=no; \ - strip_trailopt () \ - { \ - flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ - }; \ - for flg in $$sane_makeflags; do \ - test $$skip_next = yes && { skip_next=no; continue; }; \ - case $$flg in \ - *=*|--*) continue;; \ - -*I) strip_trailopt 'I'; skip_next=yes;; \ - -*I?*) strip_trailopt 'I';; \ - -*O) strip_trailopt 'O'; skip_next=yes;; \ - -*O?*) strip_trailopt 'O';; \ - -*l) strip_trailopt 'l'; skip_next=yes;; \ - -*l?*) strip_trailopt 'l';; \ - -[dEDm]) skip_next=yes;; \ - -[JT]) skip_next=yes;; \ - esac; \ - case $$flg in \ - *$$target_option*) has_opt=yes; break;; \ - esac; \ - done; \ - test $$has_opt = yes -am__make_dryrun = (target_option=n; $(am__make_running_with_option)) -am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) -pkgdatadir = $(datadir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkglibexecdir = $(libexecdir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = @build@ -host_triplet = @host@ -@WITH_BLUEZ4_TRUE@am__append_1 = \ -@WITH_BLUEZ4_TRUE@ nm-bluez4-adapter.h \ -@WITH_BLUEZ4_TRUE@ nm-bluez4-adapter.c \ -@WITH_BLUEZ4_TRUE@ nm-bluez4-manager.c - -@WITH_BLUEZ4_FALSE@am__append_2 = \ -@WITH_BLUEZ4_FALSE@ nm-bluez-manager.c - -subdir = src/bluez-manager -DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ - $(top_srcdir)/build-aux/depcomp -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \ - $(top_srcdir)/m4/gettext.m4 \ - $(top_srcdir)/m4/gnome-code-coverage.m4 \ - $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ - $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \ - $(top_srcdir)/m4/introspection.m4 $(top_srcdir)/m4/lib-ld.m4 \ - $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ - $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ - $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ - $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ - $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ - $(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -mkinstalldirs = $(install_sh) -d -CONFIG_HEADER = $(top_builddir)/config.h -CONFIG_CLEAN_FILES = -CONFIG_CLEAN_VPATH_FILES = -LTLIBRARIES = $(noinst_LTLIBRARIES) -am__DEPENDENCIES_1 = -libbluez_manager_la_DEPENDENCIES = \ - $(top_builddir)/src/generated/libnm-generated.la \ - $(top_builddir)/src/logging/libnm-logging.la \ - $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) -am__libbluez_manager_la_SOURCES_DIST = nm-bluez-common.h \ - nm-bluez-device.c nm-bluez-device.h nm-bluez-manager.h \ - nm-bluez4-adapter.h nm-bluez4-adapter.c nm-bluez4-manager.c \ - nm-bluez-manager.c -@WITH_BLUEZ4_TRUE@am__objects_1 = \ -@WITH_BLUEZ4_TRUE@ libbluez_manager_la-nm-bluez4-adapter.lo \ -@WITH_BLUEZ4_TRUE@ libbluez_manager_la-nm-bluez4-manager.lo -@WITH_BLUEZ4_FALSE@am__objects_2 = \ -@WITH_BLUEZ4_FALSE@ libbluez_manager_la-nm-bluez-manager.lo -am_libbluez_manager_la_OBJECTS = \ - libbluez_manager_la-nm-bluez-device.lo $(am__objects_1) \ - $(am__objects_2) -libbluez_manager_la_OBJECTS = $(am_libbluez_manager_la_OBJECTS) -AM_V_lt = $(am__v_lt_@AM_V@) -am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) -am__v_lt_0 = --silent -am__v_lt_1 = -AM_V_P = $(am__v_P_@AM_V@) -am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) -am__v_P_0 = false -am__v_P_1 = : -AM_V_GEN = $(am__v_GEN_@AM_V@) -am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) -am__v_GEN_0 = @echo " GEN " $@; -am__v_GEN_1 = -AM_V_at = $(am__v_at_@AM_V@) -am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) -am__v_at_0 = @ -am__v_at_1 = -DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) -depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp -am__depfiles_maybe = depfiles -am__mv = mv -f -COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ - $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ - $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ - $(AM_CFLAGS) $(CFLAGS) -AM_V_CC = $(am__v_CC_@AM_V@) -am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) -am__v_CC_0 = @echo " CC " $@; -am__v_CC_1 = -CCLD = $(CC) -LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(AM_LDFLAGS) $(LDFLAGS) -o $@ -AM_V_CCLD = $(am__v_CCLD_@AM_V@) -am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) -am__v_CCLD_0 = @echo " CCLD " $@; -am__v_CCLD_1 = -SOURCES = $(libbluez_manager_la_SOURCES) -DIST_SOURCES = $(am__libbluez_manager_la_SOURCES_DIST) -am__can_run_installinfo = \ - case $$AM_UPDATE_INFO_DIR in \ - n|no|NO) false;; \ - *) (install-info --version) >/dev/null 2>&1;; \ - esac -am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) -# Read a list of newline-separated strings from the standard input, -# and print each of them once, without duplicates. Input order is -# *not* preserved. -am__uniquify_input = $(AWK) '\ - BEGIN { nonempty = 0; } \ - { items[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in items) print i; }; } \ -' -# Make sure the list of sources is unique. This is necessary because, -# e.g., the same source file might be shared among _SOURCES variables -# for different programs/libraries. -am__define_uniq_tagged_files = \ - list='$(am__tagged_files)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | $(am__uniquify_input)` -ETAGS = etags -CTAGS = ctags -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -ALL_LINGUAS = @ALL_LINGUAS@ -AMTAR = @AMTAR@ -AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -AR = @AR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CKDB_PATH = @CKDB_PATH@ -CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@ -CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@ -CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CXX = @CXX@ -CXXCPP = @CXXCPP@ -CXXDEPMODE = @CXXDEPMODE@ -CXXFLAGS = @CXXFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DATADIRNAME = @DATADIRNAME@ -DBUS_CFLAGS = @DBUS_CFLAGS@ -DBUS_LIBS = @DBUS_LIBS@ -DBUS_SYS_DIR = @DBUS_SYS_DIR@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -DHCLIENT_PATH = @DHCLIENT_PATH@ -DHCPCD_PATH = @DHCPCD_PATH@ -DLLTOOL = @DLLTOOL@ -DNSMASQ_PATH = @DNSMASQ_PATH@ -DSYMUTIL = @DSYMUTIL@ -DUMPBIN = @DUMPBIN@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -FGREP = @FGREP@ -GENHTML = @GENHTML@ -GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ -GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ -GLIB_CFLAGS = @GLIB_CFLAGS@ -GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ -GLIB_LIBS = @GLIB_LIBS@ -GLIB_MAKEFILE = @GLIB_MAKEFILE@ -GLIB_MKENUMS = @GLIB_MKENUMS@ -GMSGFMT = @GMSGFMT@ -GMSGFMT_015 = @GMSGFMT_015@ -GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ -GNUTLS_LIBS = @GNUTLS_LIBS@ -GREP = @GREP@ -GTKDOC_CHECK = @GTKDOC_CHECK@ -GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ -GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ -GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ -GTKDOC_MKPDF = @GTKDOC_MKPDF@ -GTKDOC_REBASE = @GTKDOC_REBASE@ -GUDEV_CFLAGS = @GUDEV_CFLAGS@ -GUDEV_LIBS = @GUDEV_LIBS@ -HTML_DIR = @HTML_DIR@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -INTLLIBS = @INTLLIBS@ -INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ -INTLTOOL_MERGE = @INTLTOOL_MERGE@ -INTLTOOL_PERL = @INTLTOOL_PERL@ -INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ -INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ -INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ -INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ -INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ -INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ -INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ -INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ -INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ -INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ -INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ -INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ -INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ -INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ -IPTABLES_PATH = @IPTABLES_PATH@ -IWMX_SDK_CFLAGS = @IWMX_SDK_CFLAGS@ -IWMX_SDK_LIBS = @IWMX_SDK_LIBS@ -KERNEL_FIRMWARE_DIR = @KERNEL_FIRMWARE_DIR@ -LCOV = @LCOV@ -LD = @LD@ -LDFLAGS = @LDFLAGS@ -LIBDL = @LIBDL@ -LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ -LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ -LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ -LIBICONV = @LIBICONV@ -LIBINTL = @LIBINTL@ -LIBM = @LIBM@ -LIBNL_CFLAGS = @LIBNL_CFLAGS@ -LIBNL_LIBS = @LIBNL_LIBS@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@ -LIBSOUP_LIBS = @LIBSOUP_LIBS@ -LIBTOOL = @LIBTOOL@ -LIPO = @LIPO@ -LN_S = @LN_S@ -LTLIBICONV = @LTLIBICONV@ -LTLIBINTL = @LTLIBINTL@ -LTLIBOBJS = @LTLIBOBJS@ -MAINT = @MAINT@ -MAKEINFO = @MAKEINFO@ -MANIFEST_TOOL = @MANIFEST_TOOL@ -MKDIR_P = @MKDIR_P@ -MM_GLIB_CFLAGS = @MM_GLIB_CFLAGS@ -MM_GLIB_LIBS = @MM_GLIB_LIBS@ -MOC = @MOC@ -MSGFMT = @MSGFMT@ -MSGFMT_015 = @MSGFMT_015@ -MSGMERGE = @MSGMERGE@ -NM = @NM@ -NMEDIT = @NMEDIT@ -NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ -NM_MICRO_VERSION = @NM_MICRO_VERSION@ -NM_MINOR_VERSION = @NM_MINOR_VERSION@ -NM_MODIFY_SYSTEM_POLICY = @NM_MODIFY_SYSTEM_POLICY@ -NM_VERSION = @NM_VERSION@ -NSS_CFLAGS = @NSS_CFLAGS@ -NSS_LIBS = @NSS_LIBS@ -OBJDUMP = @OBJDUMP@ -OBJEXT = @OBJEXT@ -OTOOL = @OTOOL@ -OTOOL64 = @OTOOL64@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_URL = @PACKAGE_URL@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PKG_CONFIG = @PKG_CONFIG@ -PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ -PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ -POLKIT_CFLAGS = @POLKIT_CFLAGS@ -POLKIT_LIBS = @POLKIT_LIBS@ -POSUB = @POSUB@ -PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@ -QT_CFLAGS = @QT_CFLAGS@ -QT_LIBS = @QT_LIBS@ -RANLIB = @RANLIB@ -SED = @SED@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -STRIP = @STRIP@ -SYSTEMD_200_CFLAGS = @SYSTEMD_200_CFLAGS@ -SYSTEMD_200_LIBS = @SYSTEMD_200_LIBS@ -SYSTEMD_INHIBIT_CFLAGS = @SYSTEMD_INHIBIT_CFLAGS@ -SYSTEMD_INHIBIT_LIBS = @SYSTEMD_INHIBIT_LIBS@ -SYSTEMD_LOGIN_CFLAGS = @SYSTEMD_LOGIN_CFLAGS@ -SYSTEMD_LOGIN_LIBS = @SYSTEMD_LOGIN_LIBS@ -SYSTEM_CA_PATH = @SYSTEM_CA_PATH@ -UDEV_BASE_DIR = @UDEV_BASE_DIR@ -USE_NLS = @USE_NLS@ -UUID_CFLAGS = @UUID_CFLAGS@ -UUID_LIBS = @UUID_LIBS@ -VAPIGEN = @VAPIGEN@ -VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ -VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ -VERSION = @VERSION@ -XGETTEXT = @XGETTEXT@ -XGETTEXT_015 = @XGETTEXT_015@ -XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_AR = @ac_ct_AR@ -ac_ct_CC = @ac_ct_CC@ -ac_ct_CXX = @ac_ct_CXX@ -ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -intltool__v_merge_options_ = @intltool__v_merge_options_@ -intltool__v_merge_options_0 = @intltool__v_merge_options_0@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -nmbinary = @nmbinary@ -nmconfdir = @nmconfdir@ -nmdatadir = @nmdatadir@ -nmrundir = @nmrundir@ -nmstatedir = @nmstatedir@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -sysconfdir = @sysconfdir@ -systemdsystemunitdir = @systemdsystemunitdir@ -target_alias = @target_alias@ -top_build_prefix = @top_build_prefix@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -with_dhclient = @with_dhclient@ -with_dhcpcd = @with_dhcpcd@ -with_netconfig = @with_netconfig@ -with_resolvconf = @with_resolvconf@ -noinst_LTLIBRARIES = libbluez-manager.la -libbluez_manager_la_CPPFLAGS = \ - -I${top_srcdir} \ - -I${top_builddir}/include \ - -I${top_srcdir}/include \ - -I${top_builddir}/libnm-util \ - -I${top_srcdir}/libnm-util \ - -I${top_srcdir}/src \ - -I${top_builddir}/src/generated \ - -I${top_srcdir}/src/generated \ - -I${top_srcdir}/src/logging \ - $(DBUS_CFLAGS) \ - $(GLIB_CFLAGS) \ - $(BLUEZ_CFLAGS) \ - -DBINDIR=\"$(bindir)\" \ - -DDATADIR=\"$(datadir)\" \ - -DSYSCONFDIR=\"$(sysconfdir)\" \ - -DLIBEXECDIR=\"$(libexecdir)\" \ - -DLOCALSTATEDIR=\"$(localstatedir)\" - -libbluez_manager_la_SOURCES = nm-bluez-common.h nm-bluez-device.c \ - nm-bluez-device.h nm-bluez-manager.h $(am__append_1) \ - $(am__append_2) -libbluez_manager_la_LIBADD = \ - $(top_builddir)/src/generated/libnm-generated.la \ - $(top_builddir)/src/logging/libnm-logging.la \ - $(DBUS_LIBS) \ - $(GLIB_LIBS) \ - $(BLUEZ_LIBS) - -all: all-am - -.SUFFIXES: -.SUFFIXES: .c .lo .o .obj -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ - && { if test -f $@; then exit 0; else break; fi; }; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/bluez-manager/Makefile'; \ - $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --gnu src/bluez-manager/Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(am__aclocal_m4_deps): - -clean-noinstLTLIBRARIES: - -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) - @list='$(noinst_LTLIBRARIES)'; \ - locs=`for p in $$list; do echo $$p; done | \ - sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ - sort -u`; \ - test -z "$$locs" || { \ - echo rm -f $${locs}; \ - rm -f $${locs}; \ - } - -libbluez-manager.la: $(libbluez_manager_la_OBJECTS) $(libbluez_manager_la_DEPENDENCIES) $(EXTRA_libbluez_manager_la_DEPENDENCIES) - $(AM_V_CCLD)$(LINK) $(libbluez_manager_la_OBJECTS) $(libbluez_manager_la_LIBADD) $(LIBS) - -mostlyclean-compile: - -rm -f *.$(OBJEXT) - -distclean-compile: - -rm -f *.tab.c - -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libbluez_manager_la-nm-bluez-device.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libbluez_manager_la-nm-bluez-manager.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libbluez_manager_la-nm-bluez4-adapter.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libbluez_manager_la-nm-bluez4-manager.Plo@am__quote@ - -.c.o: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< - -.c.obj: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` - -.c.lo: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< - -libbluez_manager_la-nm-bluez-device.lo: nm-bluez-device.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libbluez_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libbluez_manager_la-nm-bluez-device.lo -MD -MP -MF $(DEPDIR)/libbluez_manager_la-nm-bluez-device.Tpo -c -o libbluez_manager_la-nm-bluez-device.lo `test -f 'nm-bluez-device.c' || echo '$(srcdir)/'`nm-bluez-device.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libbluez_manager_la-nm-bluez-device.Tpo $(DEPDIR)/libbluez_manager_la-nm-bluez-device.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-bluez-device.c' object='libbluez_manager_la-nm-bluez-device.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libbluez_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libbluez_manager_la-nm-bluez-device.lo `test -f 'nm-bluez-device.c' || echo '$(srcdir)/'`nm-bluez-device.c - -libbluez_manager_la-nm-bluez4-adapter.lo: nm-bluez4-adapter.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libbluez_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libbluez_manager_la-nm-bluez4-adapter.lo -MD -MP -MF $(DEPDIR)/libbluez_manager_la-nm-bluez4-adapter.Tpo -c -o libbluez_manager_la-nm-bluez4-adapter.lo `test -f 'nm-bluez4-adapter.c' || echo '$(srcdir)/'`nm-bluez4-adapter.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libbluez_manager_la-nm-bluez4-adapter.Tpo $(DEPDIR)/libbluez_manager_la-nm-bluez4-adapter.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-bluez4-adapter.c' object='libbluez_manager_la-nm-bluez4-adapter.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libbluez_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libbluez_manager_la-nm-bluez4-adapter.lo `test -f 'nm-bluez4-adapter.c' || echo '$(srcdir)/'`nm-bluez4-adapter.c - -libbluez_manager_la-nm-bluez4-manager.lo: nm-bluez4-manager.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libbluez_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libbluez_manager_la-nm-bluez4-manager.lo -MD -MP -MF $(DEPDIR)/libbluez_manager_la-nm-bluez4-manager.Tpo -c -o libbluez_manager_la-nm-bluez4-manager.lo `test -f 'nm-bluez4-manager.c' || echo '$(srcdir)/'`nm-bluez4-manager.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libbluez_manager_la-nm-bluez4-manager.Tpo $(DEPDIR)/libbluez_manager_la-nm-bluez4-manager.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-bluez4-manager.c' object='libbluez_manager_la-nm-bluez4-manager.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libbluez_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libbluez_manager_la-nm-bluez4-manager.lo `test -f 'nm-bluez4-manager.c' || echo '$(srcdir)/'`nm-bluez4-manager.c - -libbluez_manager_la-nm-bluez-manager.lo: nm-bluez-manager.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libbluez_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libbluez_manager_la-nm-bluez-manager.lo -MD -MP -MF $(DEPDIR)/libbluez_manager_la-nm-bluez-manager.Tpo -c -o libbluez_manager_la-nm-bluez-manager.lo `test -f 'nm-bluez-manager.c' || echo '$(srcdir)/'`nm-bluez-manager.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libbluez_manager_la-nm-bluez-manager.Tpo $(DEPDIR)/libbluez_manager_la-nm-bluez-manager.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-bluez-manager.c' object='libbluez_manager_la-nm-bluez-manager.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libbluez_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libbluez_manager_la-nm-bluez-manager.lo `test -f 'nm-bluez-manager.c' || echo '$(srcdir)/'`nm-bluez-manager.c - -mostlyclean-libtool: - -rm -f *.lo - -clean-libtool: - -rm -rf .libs _libs - -ID: $(am__tagged_files) - $(am__define_uniq_tagged_files); mkid -fID $$unique -tags: tags-am -TAGS: tags - -tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) - set x; \ - here=`pwd`; \ - $(am__define_uniq_tagged_files); \ - shift; \ - if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ - test -n "$$unique" || unique=$$empty_fix; \ - if test $$# -gt 0; then \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - "$$@" $$unique; \ - else \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$unique; \ - fi; \ - fi -ctags: ctags-am - -CTAGS: ctags -ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) - $(am__define_uniq_tagged_files); \ - test -z "$(CTAGS_ARGS)$$unique" \ - || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$unique - -GTAGS: - here=`$(am__cd) $(top_builddir) && pwd` \ - && $(am__cd) $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) "$$here" -cscopelist: cscopelist-am - -cscopelist-am: $(am__tagged_files) - list='$(am__tagged_files)'; \ - case "$(srcdir)" in \ - [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ - *) sdir=$(subdir)/$(srcdir) ;; \ - esac; \ - for i in $$list; do \ - if test -f "$$i"; then \ - echo "$(subdir)/$$i"; \ - else \ - echo "$$sdir/$$i"; \ - fi; \ - done >> $(top_builddir)/cscope.files - -distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags - -distdir: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d "$(distdir)/$$file"; then \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ - else \ - test -f "$(distdir)/$$file" \ - || cp -p $$d/$$file "$(distdir)/$$file" \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: check-am -all-am: Makefile $(LTLIBRARIES) -installdirs: -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - if test -z '$(STRIP)'; then \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - install; \ - else \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ - fi -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." -clean: clean-am - -clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ - mostlyclean-am - -distclean: distclean-am - -rm -rf ./$(DEPDIR) - -rm -f Makefile -distclean-am: clean-am distclean-compile distclean-generic \ - distclean-tags - -dvi: dvi-am - -dvi-am: - -html: html-am - -html-am: - -info: info-am - -info-am: - -install-data-am: - -install-dvi: install-dvi-am - -install-dvi-am: - -install-exec-am: - -install-html: install-html-am - -install-html-am: - -install-info: install-info-am - -install-info-am: - -install-man: - -install-pdf: install-pdf-am - -install-pdf-am: - -install-ps: install-ps-am - -install-ps-am: - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -rf ./$(DEPDIR) - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-compile mostlyclean-generic \ - mostlyclean-libtool - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: - -.MAKE: install-am install-strip - -.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ - clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ - ctags-am distclean distclean-compile distclean-generic \ - distclean-libtool distclean-tags distdir dvi dvi-am html \ - html-am info info-am install install-am install-data \ - install-data-am install-dvi install-dvi-am install-exec \ - install-exec-am install-html install-html-am install-info \ - install-info-am install-man install-pdf install-pdf-am \ - install-ps install-ps-am install-strip installcheck \ - installcheck-am installdirs maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-compile \ - mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ - tags tags-am uninstall uninstall-am - - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/src/bluez-manager/nm-bluez-common.h b/src/bluez-manager/nm-bluez-common.h deleted file mode 100644 index ecc4d709..00000000 --- a/src/bluez-manager/nm-bluez-common.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2009 Red Hat, Inc. - */ - -#ifndef NM_BLUEZ_COMMON_H -#define NM_BLUEZ_COMMON_H - -#include - -#define BLUETOOTH_CONNECT_DUN "dun" -#define BLUETOOTH_CONNECT_NAP "nap" - -#define BLUEZ_SERVICE "org.bluez" - -#define BLUEZ_MANAGER_PATH "/" -#define OBJECT_MANAGER_INTERFACE "org.freedesktop.DBus.ObjectManager" - -#if ! WITH_BLUEZ4 - -#define BLUEZ_ADAPTER_INTERFACE "org.bluez.Adapter1" -#define BLUEZ_DEVICE_INTERFACE "org.bluez.Device1" -#define BLUEZ_NETWORK_INTERFACE "org.bluez.Network1" - -#else - -#define BLUEZ_MANAGER_INTERFACE "org.bluez.Manager" -#define BLUEZ_ADAPTER_INTERFACE "org.bluez.Adapter" -#define BLUEZ_DEVICE_INTERFACE "org.bluez.Device" -#define BLUEZ_SERIAL_INTERFACE "org.bluez.Serial" -#define BLUEZ_NETWORK_INTERFACE "org.bluez.Network" - -#endif /* WITH_BLUEZ */ - -#endif /* NM_BLUEZ_COMMON_H */ - diff --git a/src/bluez-manager/nm-bluez-device.c b/src/bluez-manager/nm-bluez-device.c deleted file mode 100644 index ed5e345d..00000000 --- a/src/bluez-manager/nm-bluez-device.c +++ /dev/null @@ -1,1223 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2009 - 2012 Red Hat, Inc. - * Copyright (C) 2013 Intel Corporation. - */ - -#include -#include -#include -#include -#include -#include - -#include "NetworkManager.h" -#include "nm-setting-bluetooth.h" - -#include "nm-bluez-common.h" -#if WITH_BLUEZ4 -#include "nm-dbus-manager.h" -#include "nm-dbus-glib-types.h" -#endif -#include "nm-bluez-device.h" -#include "nm-logging.h" -#include "nm-marshal.h" -#include "nm-utils.h" - - -G_DEFINE_TYPE (NMBluezDevice, nm_bluez_device, G_TYPE_OBJECT) - -#define NM_BLUEZ_DEVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_BLUEZ_DEVICE, NMBluezDevicePrivate)) - -typedef struct { - char *path; - GDBusConnection *dbus_connection; -#if ! WITH_BLUEZ4 - GDBusProxy *proxy5; - GDBusProxy *adapter; - gboolean adapter_powered; -#else - DBusGProxy *proxy4; -#endif - - gboolean initialized; - gboolean usable; - NMBluetoothCapabilities connection_bt_type; - - char *address; - guint8 bin_address[ETH_ALEN]; - char *name; - guint32 capabilities; - gint rssi; - gboolean connected; - - char *bt_iface; - - NMConnectionProvider *provider; - GSList *connections; - - NMConnection *pan_connection; - gboolean pan_connection_no_autocreate; -} NMBluezDevicePrivate; - - -enum { - PROP_0, - PROP_PATH, - PROP_ADDRESS, - PROP_NAME, - PROP_CAPABILITIES, - PROP_RSSI, - PROP_USABLE, - PROP_CONNECTED, - - LAST_PROP -}; - -/* Signals */ -enum { - INITIALIZED, - LAST_SIGNAL -}; -static guint signals[LAST_SIGNAL] = { 0 }; - - -static void cp_connection_added (NMConnectionProvider *provider, - NMConnection *connection, NMBluezDevice *self); -static gboolean connection_compatible (NMBluezDevice *self, NMConnection *connection); - - -/***********************************************************/ - -const char * -nm_bluez_device_get_path (NMBluezDevice *self) -{ - g_return_val_if_fail (NM_IS_BLUEZ_DEVICE (self), NULL); - - return NM_BLUEZ_DEVICE_GET_PRIVATE (self)->path; -} - -const char * -nm_bluez_device_get_address (NMBluezDevice *self) -{ - g_return_val_if_fail (NM_IS_BLUEZ_DEVICE (self), NULL); - - return NM_BLUEZ_DEVICE_GET_PRIVATE (self)->address; -} - -gboolean -nm_bluez_device_get_initialized (NMBluezDevice *self) -{ - g_return_val_if_fail (NM_IS_BLUEZ_DEVICE (self), FALSE); - - return NM_BLUEZ_DEVICE_GET_PRIVATE (self)->initialized; -} - -gboolean -nm_bluez_device_get_usable (NMBluezDevice *self) -{ - g_return_val_if_fail (NM_IS_BLUEZ_DEVICE (self), FALSE); - - return NM_BLUEZ_DEVICE_GET_PRIVATE (self)->usable; -} - -const char * -nm_bluez_device_get_name (NMBluezDevice *self) -{ - g_return_val_if_fail (NM_IS_BLUEZ_DEVICE (self), NULL); - - return NM_BLUEZ_DEVICE_GET_PRIVATE (self)->name; -} - -guint32 -nm_bluez_device_get_capabilities (NMBluezDevice *self) -{ - g_return_val_if_fail (NM_IS_BLUEZ_DEVICE (self), 0); - - return NM_BLUEZ_DEVICE_GET_PRIVATE (self)->capabilities; -} - -gint -nm_bluez_device_get_rssi (NMBluezDevice *self) -{ - g_return_val_if_fail (NM_IS_BLUEZ_DEVICE (self), 0); - - return NM_BLUEZ_DEVICE_GET_PRIVATE (self)->rssi; -} - -gboolean -nm_bluez_device_get_connected (NMBluezDevice *self) -{ - g_return_val_if_fail (NM_IS_BLUEZ_DEVICE (self), FALSE); - - return NM_BLUEZ_DEVICE_GET_PRIVATE (self)->connected; -} - -static void -pan_connection_check_create (NMBluezDevice *self) -{ - NMConnection *connection; - NMConnection *added; - NMSetting *setting; - char *uuid, *id; - GByteArray *bdaddr_array; - GError *error = NULL; - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - - g_return_if_fail (priv->capabilities & NM_BT_CAPABILITY_NAP); - g_return_if_fail (priv->connections == NULL); - g_return_if_fail (priv->name); - - if (priv->pan_connection || priv->pan_connection_no_autocreate) { - /* already have a connection or we don't want to create one, nothing to do. */ - return; - } - - if (!nm_connection_provider_has_connections_loaded (priv->provider)) { - /* do not try to create any connections until the connection provider is ready. */ - return; - } - - /* Only try once to create a connection. If it does not succeed, we do not try again. Also, - * if the connection gets deleted later, do not create another one for this device. */ - priv->pan_connection_no_autocreate = TRUE; - - /* create a new connection */ - - connection = nm_connection_new (); - - /* Setting: Connection */ - uuid = nm_utils_uuid_generate (); - id = g_strdup_printf (_("%s Network"), priv->name); - setting = nm_setting_connection_new (); - g_object_set (setting, - NM_SETTING_CONNECTION_ID, id, - NM_SETTING_CONNECTION_UUID, uuid, - NM_SETTING_CONNECTION_AUTOCONNECT, FALSE, - NM_SETTING_CONNECTION_TYPE, NM_SETTING_BLUETOOTH_SETTING_NAME, - NULL); - nm_connection_add_setting (connection, setting); - - /* Setting: Bluetooth */ - bdaddr_array = g_byte_array_sized_new (sizeof (priv->bin_address)); - g_byte_array_append (bdaddr_array, priv->bin_address, sizeof (priv->bin_address)); - setting = nm_setting_bluetooth_new (); - g_object_set (G_OBJECT (setting), - NM_SETTING_BLUETOOTH_BDADDR, bdaddr_array, - NM_SETTING_BLUETOOTH_TYPE, NM_SETTING_BLUETOOTH_TYPE_PANU, - NULL); - nm_connection_add_setting (connection, setting); - g_byte_array_free (bdaddr_array, TRUE); - - /* Setting: IPv4 */ - setting = nm_setting_ip4_config_new (); - g_object_set (G_OBJECT (setting), - NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, - NM_SETTING_IP4_CONFIG_MAY_FAIL, FALSE, - NULL); - nm_connection_add_setting (connection, setting); - - /* Setting: IPv6 */ - setting = nm_setting_ip6_config_new (); - g_object_set (G_OBJECT (setting), - NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO, - NM_SETTING_IP6_CONFIG_MAY_FAIL, TRUE, - NULL); - nm_connection_add_setting (connection, setting); - - /* Adding a new connection raises a signal which eventually calls check_emit_usable (again) - * which then already finds the suitable connection in priv->connections. This is confusing, - * so block the signal. check_emit_usable will succeed after this function call returns. */ - g_signal_handlers_block_by_func (priv->provider, cp_connection_added, self); - added = nm_connection_provider_add_connection (priv->provider, connection, &error); - g_signal_handlers_unblock_by_func (priv->provider, cp_connection_added, self); - - if (added) { - g_assert (!g_slist_find (priv->connections, added)); - g_assert (connection_compatible (self, added)); - - priv->connections = g_slist_prepend (priv->connections, g_object_ref (added)); - priv->pan_connection = added; - nm_log_dbg (LOGD_SETTINGS, "added new Bluetooth connection for NAP device '%s': '%s' (%s)", priv->path, id, uuid); - } else { - nm_log_warn (LOGD_SETTINGS, "couldn't add new Bluetooth connection for NAP device '%s': '%s' (%s): %d / %s", - priv->path, id, uuid, error ? error->code : -1, - (error && error->message) ? error->message : "(unknown)"); - g_clear_error (&error); - } - - g_object_unref (connection); - g_free (id); - g_free (uuid); -} - -static void -check_emit_usable (NMBluezDevice *self) -{ - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - gboolean new_usable; - - /* only expect the supported capabilities set. */ - g_assert ((priv->capabilities & ~( NM_BT_CAPABILITY_NAP -#if WITH_BLUEZ4 - | NM_BT_CAPABILITY_DUN -#endif - )) == NM_BT_CAPABILITY_NONE); - - new_usable = (priv->initialized && priv->capabilities && priv->name && -#if ! WITH_BLUEZ4 - priv->adapter && priv->adapter_powered && -#endif - priv->dbus_connection && priv->address); - - if (!new_usable) - goto END; - - if (priv->connections) - goto END; - - if (!(priv->capabilities & NM_BT_CAPABILITY_NAP)) { - /* non NAP devices are only usable, if they already have a connection. */ - new_usable = FALSE; - goto END; - } - - pan_connection_check_create (self); - new_usable = !!priv->pan_connection; - -END: - if (new_usable != priv->usable) { - priv->usable = new_usable; - g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_USABLE); - } -} - -/********************************************************************/ - -static gboolean -connection_compatible (NMBluezDevice *self, NMConnection *connection) -{ - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - NMSettingBluetooth *s_bt; - const char *bt_type; - const GByteArray *bdaddr; - - if (!nm_connection_is_type (connection, NM_SETTING_BLUETOOTH_SETTING_NAME)) - return FALSE; - - s_bt = nm_connection_get_setting_bluetooth (connection); - if (!s_bt) - return FALSE; - - if (!priv->address) { - /* unless address is set, bin_address is not initialized. */ - return FALSE; - } - bdaddr = nm_setting_bluetooth_get_bdaddr (s_bt); - if (!bdaddr || bdaddr->len != ETH_ALEN) - return FALSE; - if (memcmp (bdaddr->data, priv->bin_address, ETH_ALEN) != 0) - return FALSE; - - bt_type = nm_setting_bluetooth_get_connection_type (s_bt); - if ( g_str_equal (bt_type, NM_SETTING_BLUETOOTH_TYPE_DUN) - && !(priv->capabilities & NM_BT_CAPABILITY_DUN)) - return FALSE; - - if ( g_str_equal (bt_type, NM_SETTING_BLUETOOTH_TYPE_PANU) - && !(priv->capabilities & NM_BT_CAPABILITY_NAP)) - return FALSE; - - return TRUE; -} - -static void -_internal_add_connection (NMBluezDevice *self, NMConnection *connection) -{ - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - - if (!g_slist_find (priv->connections, connection)) { - priv->connections = g_slist_prepend (priv->connections, g_object_ref (connection)); - check_emit_usable (self); - } -} - -static void -cp_connection_added (NMConnectionProvider *provider, - NMConnection *connection, - NMBluezDevice *self) -{ - if (connection_compatible (self, connection)) - _internal_add_connection (self, connection); -} - -static void -cp_connection_removed (NMConnectionProvider *provider, - NMConnection *connection, - NMBluezDevice *self) -{ - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - - if (g_slist_find (priv->connections, connection)) { - priv->connections = g_slist_remove (priv->connections, connection); - if (priv->pan_connection == connection) { - priv->pan_connection = NULL; - } - g_object_unref (connection); - check_emit_usable (self); - } -} - -static void -cp_connection_updated (NMConnectionProvider *provider, - NMConnection *connection, - NMBluezDevice *self) -{ - if (connection_compatible (self, connection)) - _internal_add_connection (self, connection); - else - cp_connection_removed (provider, connection, self); -} - -static void -cp_connections_loaded (NMConnectionProvider *provider, NMBluezDevice *self) -{ - const GSList *connections, *iter; - - connections = nm_connection_provider_get_connections (provider); - for (iter = connections; iter; iter = g_slist_next (iter)) - cp_connection_added (provider, NM_CONNECTION (iter->data), self); -} - -/***********************************************************/ - -static void -bluez_disconnect_cb (GDBusConnection *dbus_connection, - GAsyncResult *res, - gpointer user_data) -{ - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (user_data); - GError *error = NULL; - GVariant *variant; - - variant = g_dbus_connection_call_finish (dbus_connection, res, &error); - if (!variant) { - nm_log_warn (LOGD_BT, "%s: failed to disconnect: %s", priv->address, error->message); - g_error_free (error); - } else - g_variant_unref (variant); -} - -void -nm_bluez_device_disconnect (NMBluezDevice *self) -{ - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - GVariant *args = NULL; - const char *dbus_iface = BLUEZ_NETWORK_INTERFACE; - - g_return_if_fail (priv->dbus_connection); - -#if ! WITH_BLUEZ4 - g_return_if_fail (priv->connection_bt_type == NM_BT_CAPABILITY_NAP); -#else - g_return_if_fail (priv->connection_bt_type == NM_BT_CAPABILITY_NAP || priv->connection_bt_type == NM_BT_CAPABILITY_DUN); - - if (priv->connection_bt_type == NM_BT_CAPABILITY_DUN) { - /* Can't pass a NULL interface name through dbus to bluez, so just - * ignore the disconnect if the interface isn't known. - */ - if (!priv->bt_iface) - return; - - args = g_variant_new ("(s)", priv->bt_iface), - dbus_iface = BLUEZ_SERIAL_INTERFACE; - } -#endif - - g_dbus_connection_call (priv->dbus_connection, - BLUEZ_SERVICE, - priv->path, - dbus_iface, - "Disconnect", - args ? args : g_variant_new ("()"), - NULL, - G_DBUS_CALL_FLAGS_NONE, - 10000, - NULL, - (GAsyncReadyCallback) bluez_disconnect_cb, - self); - - priv->connection_bt_type = NM_BT_CAPABILITY_NONE; -} - -static void -bluez_connect_cb (GDBusConnection *dbus_connection, - GAsyncResult *res, - gpointer user_data) -{ - GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (user_data); - GObject *result_object = g_async_result_get_source_object (G_ASYNC_RESULT (result)); - NMBluezDevice *self = NM_BLUEZ_DEVICE (result_object); - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - GError *error = NULL; - char *device; - GVariant *variant; - - variant = g_dbus_connection_call_finish (dbus_connection, res, &error); - - if (!variant) { - g_simple_async_result_take_error (result, error); - } else { - g_variant_get (variant, "(s)", &device); - - g_simple_async_result_set_op_res_gpointer (result, - g_strdup (device), - g_free); - priv->bt_iface = device; - g_variant_unref (variant); - } - - g_simple_async_result_complete (result); - g_object_unref (result); - g_object_unref (result_object); -} - -void -nm_bluez_device_connect_async (NMBluezDevice *self, - NMBluetoothCapabilities connection_bt_type, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GSimpleAsyncResult *simple; - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - const char *dbus_iface = BLUEZ_NETWORK_INTERFACE; - const char *connect_type = BLUETOOTH_CONNECT_NAP; - - g_return_if_fail (priv->capabilities & connection_bt_type & (NM_BT_CAPABILITY_DUN | NM_BT_CAPABILITY_NAP)); -#if ! WITH_BLUEZ4 - g_return_if_fail (connection_bt_type == NM_BT_CAPABILITY_NAP); -#else - g_return_if_fail (connection_bt_type == NM_BT_CAPABILITY_NAP || connection_bt_type == NM_BT_CAPABILITY_DUN); - - if (connection_bt_type == NM_BT_CAPABILITY_DUN) { - dbus_iface = BLUEZ_SERIAL_INTERFACE; - connect_type = BLUETOOTH_CONNECT_DUN; - } -#endif - - simple = g_simple_async_result_new (G_OBJECT (self), - callback, - user_data, - nm_bluez_device_connect_async); - - g_dbus_connection_call (priv->dbus_connection, - BLUEZ_SERVICE, - priv->path, - dbus_iface, - "Connect", - g_variant_new ("(s)", connect_type), - NULL, - G_DBUS_CALL_FLAGS_NONE, - 20000, - NULL, - (GAsyncReadyCallback) bluez_connect_cb, - simple); - - priv->connection_bt_type = connection_bt_type; -} - -const char * -nm_bluez_device_connect_finish (NMBluezDevice *self, - GAsyncResult *result, - GError **error) -{ - GSimpleAsyncResult *simple; - const char *device; - - g_return_val_if_fail (g_simple_async_result_is_valid (result, - G_OBJECT (self), - nm_bluez_device_connect_async), - NULL); - - simple = (GSimpleAsyncResult *) result; - - if (g_simple_async_result_propagate_error (simple, error)) - return NULL; - - device = (const char *) g_simple_async_result_get_op_res_gpointer (simple); - return device; -} - -/***********************************************************/ - -static guint32 -convert_uuids_to_capabilities (const char **strings) -{ - const char **iter; - guint32 capabilities = 0; - - for (iter = strings; iter && *iter; iter++) { - char **parts; - - parts = g_strsplit (*iter, "-", -1); - if (parts && parts[0]) { - switch (g_ascii_strtoull (parts[0], NULL, 16)) { -#if WITH_BLUEZ4 - case 0x1103: - capabilities |= NM_BT_CAPABILITY_DUN; - break; -#endif - case 0x1116: - capabilities |= NM_BT_CAPABILITY_NAP; - break; - default: - break; - } - } - g_strfreev (parts); - } - - return capabilities; -} - -static void -_set_property_capabilities (NMBluezDevice *self, const char **uuids, gboolean notify) -{ - guint32 uint_val; - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - - uint_val = convert_uuids_to_capabilities (uuids); - if (priv->capabilities != uint_val) { - if (priv->capabilities) { - /* changing (relevant) capabilities is not supported and ignored -- except setting initially */ - nm_log_warn (LOGD_BT, "ignore change of capabilities for Bluetooth device %s from %u to %u", - priv->path, priv->capabilities, uint_val); - return; - } - nm_log_dbg (LOGD_BT, "set capabilities for Bluetooth device %s: %s%s%s", priv->path, - uint_val & NM_BT_CAPABILITY_NAP ? "NAP" : "", - ((uint_val & NM_BT_CAPABILITY_DUN) && (uint_val &NM_BT_CAPABILITY_NAP)) ? " | " : "", - uint_val & NM_BT_CAPABILITY_DUN ? "DUN" : ""); - priv->capabilities = uint_val; - if (notify) - g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_CAPABILITIES); - } -} - -/** - * priv->address can only be set one to a certain (non NULL) value. Every later attempt - * to reset it to another value will be ignored and a warning will be logged. - * - * When setting the address for the first time, we also set bin_address. - **/ -static void -_set_property_address (NMBluezDevice *self, const char *addr) -{ - struct ether_addr *tmp; - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - - if (g_strcmp0 (priv->address, addr) == 0) - return; - - if (!addr) { - nm_log_warn (LOGD_BT, "[%s] cannot reset address from '%s' to NULL", priv->path, priv->address); - return; - } - - if (priv->address != NULL) { - nm_log_warn (LOGD_BT, "[%s] cannot reset address from '%s' to '%s'", priv->path, priv->address, addr); - return; - } - - tmp = ether_aton (addr); - if (!tmp) { - if (priv->address) - nm_log_warn (LOGD_BT, "[%s] cannot reset address from '%s' to '%s' (invalid value)", priv->path, priv->address, addr); - else - nm_log_warn (LOGD_BT, "[%s] cannot reset address from NULL to '%s' (invalid value)", priv->path, addr); - return; - } - memcpy (priv->bin_address, tmp->ether_addr_octet, ETH_ALEN); - priv->address = g_strdup (addr); - return; -} - -#if ! WITH_BLUEZ4 -static void -adapter_properties_changed (GDBusProxy *proxy5, - GVariant *changed_properties, - GStrv invalidated_properties, - gpointer user_data) -{ - NMBluezDevice *self = NM_BLUEZ_DEVICE (user_data); - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - GVariantIter i; - const char *property; - GVariant *v; - - g_variant_iter_init (&i, changed_properties); - while (g_variant_iter_next (&i, "{&sv}", &property, &v)) { - if (!strcmp (property, "Powered")) { - gboolean powered = g_variant_get_boolean (v); - if (priv->adapter_powered != powered) - priv->adapter_powered = powered; - } - g_variant_unref (v); - } - - check_emit_usable (self); -} - -static void -on_adapter_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self) -{ - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - GError *error; - GVariant *v; - - priv->adapter = g_dbus_proxy_new_for_bus_finish (res, &error); - if (!priv->adapter) { - nm_log_warn (LOGD_BT, "failed to acquire adapter proxy: %s.", error->message); - g_clear_error (&error); - g_signal_emit (self, signals[INITIALIZED], 0, FALSE); - } else { - g_signal_connect (priv->adapter, "g-properties-changed", - G_CALLBACK (adapter_properties_changed), self); - - /* Check adapter's powered state */ - v = g_dbus_proxy_get_cached_property (priv->adapter, "Powered"); - priv->adapter_powered = v ? g_variant_get_boolean (v) : FALSE; - if (v) - g_variant_unref (v); - - priv->initialized = TRUE; - g_signal_emit (self, signals[INITIALIZED], 0, TRUE); - - check_emit_usable (self); - } - - g_object_unref (self); -} - -static void -properties_changed (GDBusProxy *proxy5, - GVariant *changed_properties, - GStrv invalidated_properties, - gpointer user_data) -{ - NMBluezDevice *self = NM_BLUEZ_DEVICE (user_data); - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - GVariantIter i; - const char *property; - const char *str; - GVariant *v; - gint int_val; - const char **strv; - - g_object_freeze_notify (G_OBJECT (self)); - g_variant_iter_init (&i, changed_properties); - while (g_variant_iter_next (&i, "{&sv}", &property, &v)) { - if (!strcmp (property, "Name")) { - str = g_variant_get_string (v, NULL); - if (g_strcmp0 (priv->name, str)) { - g_free (priv->name); - priv->name = g_strdup (str); - g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_NAME); - } - } else if (!strcmp (property, "RSSI")) { - int_val = g_variant_get_int16 (v); - if (priv->rssi != int_val) { - priv->rssi = int_val; - g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_RSSI); - } - } else if (!strcmp (property, "UUIDs")) { - strv = g_variant_get_strv (v, NULL); - _set_property_capabilities (self, strv, TRUE); - g_free (strv); - } else if (!strcmp (property, "Connected")) { - gboolean connected = g_variant_get_boolean (v); - if (priv->connected != connected) { - priv->connected = connected; - g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_CONNECTED); - } - } - g_variant_unref (v); - } - g_object_thaw_notify (G_OBJECT (self)); - - check_emit_usable (self); -} -#else -static void -property_changed (DBusGProxy *proxy4, - const char *property, - GValue *value, - gpointer user_data) -{ - NMBluezDevice *self = NM_BLUEZ_DEVICE (user_data); - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - const char *str; - gint int_val; - - g_object_freeze_notify (G_OBJECT (self)); - { - if (!strcmp (property, "Name")) { - str = g_value_get_string (value); - if ( (!priv->name && str) - || (priv->name && !str) - || (priv->name && str && strcmp (priv->name, str))) { - g_free (priv->name); - priv->name = g_strdup (str); - g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_NAME); - } - } else if (!strcmp (property, "RSSI")) { - int_val = g_value_get_int (value); - if (priv->rssi != int_val) { - priv->rssi = int_val; - g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_RSSI); - } - } else if (!strcmp (property, "UUIDs")) { - _set_property_capabilities (self, (const char **) g_value_get_boxed (value), TRUE); - } else if (!strcmp (property, "Connected")) { - gboolean connected = g_value_get_boolean (value); - if (priv->connected != connected) { - priv->connected = connected; - g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_CONNECTED); - } - } - } - g_object_thaw_notify (G_OBJECT (self)); - - check_emit_usable (self); -} -#endif - -#if ! WITH_BLUEZ4 -static void -query_properties (NMBluezDevice *self) -{ - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - GVariant *v; - const char **uuids; - - v = g_dbus_proxy_get_cached_property (priv->proxy5, "Address"); - _set_property_address (self, v ? g_variant_get_string (v, NULL) : NULL); - if (v) - g_variant_unref (v); - - v = g_dbus_proxy_get_cached_property (priv->proxy5, "Name"); - priv->name = v ? g_variant_dup_string (v, NULL) : NULL; - if (v) - g_variant_unref (v); - - v = g_dbus_proxy_get_cached_property (priv->proxy5, "RSSI"); - priv->rssi = v ? g_variant_get_int16 (v) : 0; - if (v) - g_variant_unref (v); - - v = g_dbus_proxy_get_cached_property (priv->proxy5, "UUIDs"); - if (v) { - uuids = g_variant_get_strv (v, NULL); - _set_property_capabilities (self, uuids, FALSE); - g_variant_unref (v); - } else - priv->capabilities = NM_BT_CAPABILITY_NONE; - - v = g_dbus_proxy_get_cached_property (priv->proxy5, "Adapter"); - if (v) { - g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - BLUEZ_SERVICE, - g_variant_get_string (v, NULL), - BLUEZ_ADAPTER_INTERFACE, - NULL, - (GAsyncReadyCallback) on_adapter_acquired, - g_object_ref (self)); - g_variant_unref (v); - } - - /* Check if any connections match this device */ - cp_connections_loaded (priv->provider, self); -} -#else -static void -get_properties_cb (DBusGProxy *proxy4, DBusGProxyCall *call, gpointer user_data) -{ - NMBluezDevice *self = NM_BLUEZ_DEVICE (user_data); - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - GHashTable *properties = NULL; - GError *err = NULL; - GValue *value; - - if (!dbus_g_proxy_end_call (proxy4, call, &err, - DBUS_TYPE_G_MAP_OF_VARIANT, &properties, - G_TYPE_INVALID)) { - nm_log_warn (LOGD_BT, "bluez error getting device properties: %s", - err && err->message ? err->message : "(unknown)"); - g_error_free (err); - g_signal_emit (self, signals[INITIALIZED], 0, FALSE); - return; - } - - value = g_hash_table_lookup (properties, "Address"); - _set_property_address (self, value ? g_value_get_string (value) : NULL); - - value = g_hash_table_lookup (properties, "Name"); - priv->name = value ? g_value_dup_string (value) : NULL; - - value = g_hash_table_lookup (properties, "RSSI"); - priv->rssi = value ? g_value_get_int (value) : 0; - - value = g_hash_table_lookup (properties, "UUIDs"); - if (value) { - _set_property_capabilities (self, (const char **) g_value_get_boxed (value), FALSE); - } else - priv->capabilities = NM_BT_CAPABILITY_NONE; - - g_hash_table_unref (properties); - - /* Check if any connections match this device */ - cp_connections_loaded (priv->provider, self); - - priv->initialized = TRUE; - g_signal_emit (self, signals[INITIALIZED], 0, TRUE); - - check_emit_usable (self); -} - -static void -query_properties (NMBluezDevice *self) -{ - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - DBusGProxyCall *call; - - call = dbus_g_proxy_begin_call (priv->proxy4, "GetProperties", - get_properties_cb, - self, - NULL, G_TYPE_INVALID); - if (!call) { - nm_log_warn (LOGD_BT, "failed to request Bluetooth device properties for %s.", - priv->path); - } -} -#endif - - -#if ! WITH_BLUEZ4 -static void -on_proxy_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self) -{ - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - GError *error; - - priv->proxy5 = g_dbus_proxy_new_for_bus_finish (res, &error); - - if (!priv->proxy5) { - nm_log_warn (LOGD_BT, "failed to acquire device proxy: %s.", error->message); - g_clear_error (&error); - g_signal_emit (self, signals[INITIALIZED], 0, FALSE); - } else { - g_signal_connect (priv->proxy5, "g-properties-changed", - G_CALLBACK (properties_changed), self); - - query_properties (self); - } - g_object_unref (self); -} -#endif - -static void -on_bus_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self) -{ - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - GError *error = NULL; - - priv->dbus_connection = g_bus_get_finish (res, &error); - - if (!priv->dbus_connection) { - nm_log_warn (LOGD_BT, "failed to acquire bus connection: %s.", error->message); - g_clear_error (&error); - g_signal_emit (self, signals[INITIALIZED], 0, FALSE); - return; - } - - check_emit_usable (self); -} - -/********************************************************************/ - -NMBluezDevice * -nm_bluez_device_new (const char *path, NMConnectionProvider *provider) -{ - NMBluezDevice *self; - NMBluezDevicePrivate *priv; -#if WITH_BLUEZ4 - NMDBusManager *dbus_mgr; - DBusGConnection *connection; -#endif - - g_return_val_if_fail (path != NULL, NULL); - g_return_val_if_fail (provider != NULL, NULL); - - self = (NMBluezDevice *) g_object_new (NM_TYPE_BLUEZ_DEVICE, - NM_BLUEZ_DEVICE_PATH, path, - NULL); - if (!self) - return NULL; - - priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - - priv->provider = provider; - - g_signal_connect (priv->provider, - NM_CP_SIGNAL_CONNECTION_ADDED, - G_CALLBACK (cp_connection_added), - self); - - g_signal_connect (priv->provider, - NM_CP_SIGNAL_CONNECTION_REMOVED, - G_CALLBACK (cp_connection_removed), - self); - - g_signal_connect (priv->provider, - NM_CP_SIGNAL_CONNECTION_UPDATED, - G_CALLBACK (cp_connection_updated), - self); - - g_signal_connect (priv->provider, - NM_CP_SIGNAL_CONNECTIONS_LOADED, - G_CALLBACK (cp_connections_loaded), - self); - - g_bus_get (G_BUS_TYPE_SYSTEM, - NULL, - (GAsyncReadyCallback) on_bus_acquired, - self); - -#if ! WITH_BLUEZ4 - g_object_ref (self); - g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - BLUEZ_SERVICE, - priv->path, - BLUEZ_DEVICE_INTERFACE, - NULL, - (GAsyncReadyCallback) on_proxy_acquired, - self); -#else - dbus_mgr = nm_dbus_manager_get (); - connection = nm_dbus_manager_get_connection (dbus_mgr); - - priv->proxy4 = dbus_g_proxy_new_for_name (connection, - BLUEZ_SERVICE, - priv->path, - BLUEZ_DEVICE_INTERFACE); - g_object_unref (dbus_mgr); - - dbus_g_object_register_marshaller (_nm_marshal_VOID__STRING_BOXED, - G_TYPE_NONE, - G_TYPE_STRING, G_TYPE_VALUE, - G_TYPE_INVALID); - dbus_g_proxy_add_signal (priv->proxy4, "PropertyChanged", - G_TYPE_STRING, G_TYPE_VALUE, G_TYPE_INVALID); - dbus_g_proxy_connect_signal (priv->proxy4, "PropertyChanged", - G_CALLBACK (property_changed), self, NULL); - - query_properties (self); -#endif - return self; -} - -static void -nm_bluez_device_init (NMBluezDevice *self) -{ -} - -static void -dispose (GObject *object) -{ - NMBluezDevice *self = NM_BLUEZ_DEVICE (object); - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - - g_slist_foreach (priv->connections, (GFunc) g_object_unref, NULL); - g_slist_free (priv->connections); - priv->connections = NULL; - - g_signal_handlers_disconnect_by_func (priv->provider, cp_connection_added, self); - g_signal_handlers_disconnect_by_func (priv->provider, cp_connection_removed, self); - g_signal_handlers_disconnect_by_func (priv->provider, cp_connection_updated, self); - g_signal_handlers_disconnect_by_func (priv->provider, cp_connections_loaded, self); - -#if ! WITH_BLUEZ4 - g_clear_object (&priv->adapter); -#endif - g_clear_object (&priv->dbus_connection); - - G_OBJECT_CLASS (nm_bluez_device_parent_class)->dispose (object); -} - -static void -finalize (GObject *object) -{ - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (object); - - g_free (priv->path); - g_free (priv->address); - g_free (priv->name); - g_free (priv->bt_iface); -#if ! WITH_BLUEZ4 - g_object_unref (priv->proxy5); -#else - g_object_unref (priv->proxy4); -#endif - - G_OBJECT_CLASS (nm_bluez_device_parent_class)->finalize (object); -} - -static void -get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) -{ - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (object); - - switch (prop_id) { - case PROP_PATH: - g_value_set_string (value, priv->path); - break; - case PROP_ADDRESS: - g_value_set_string (value, priv->address); - break; - case PROP_NAME: - g_value_set_string (value, priv->name); - break; - case PROP_CAPABILITIES: - g_value_set_uint (value, priv->capabilities); - break; - case PROP_RSSI: - g_value_set_int (value, priv->rssi); - break; - case PROP_USABLE: - g_value_set_boolean (value, priv->usable); - break; - case PROP_CONNECTED: - g_value_set_boolean (value, priv->connected); - 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) -{ - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (object); - - switch (prop_id) { - case PROP_PATH: - /* construct only */ - priv->path = g_value_dup_string (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -nm_bluez_device_class_init (NMBluezDeviceClass *config_class) -{ - GObjectClass *object_class = G_OBJECT_CLASS (config_class); - - g_type_class_add_private (config_class, sizeof (NMBluezDevicePrivate)); - - /* virtual methods */ - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->dispose = dispose; - object_class->finalize = finalize; - - /* Properties */ - g_object_class_install_property - (object_class, PROP_PATH, - g_param_spec_string (NM_BLUEZ_DEVICE_PATH, - "DBus Path", - "DBus Path", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - g_object_class_install_property - (object_class, PROP_ADDRESS, - g_param_spec_string (NM_BLUEZ_DEVICE_ADDRESS, - "Address", - "Address", - NULL, - G_PARAM_READABLE)); - - g_object_class_install_property - (object_class, PROP_NAME, - g_param_spec_string (NM_BLUEZ_DEVICE_NAME, - "Name", - "Name", - NULL, - G_PARAM_READABLE)); - - g_object_class_install_property - (object_class, PROP_CAPABILITIES, - g_param_spec_uint (NM_BLUEZ_DEVICE_CAPABILITIES, - "Capabilities", - "Capabilities", - 0, G_MAXUINT, 0, - G_PARAM_READABLE)); - - g_object_class_install_property - (object_class, PROP_RSSI, - g_param_spec_int (NM_BLUEZ_DEVICE_RSSI, - "RSSI", - "RSSI", - G_MININT, G_MAXINT, 0, - G_PARAM_READABLE)); - - g_object_class_install_property - (object_class, PROP_USABLE, - g_param_spec_boolean (NM_BLUEZ_DEVICE_USABLE, - "Usable", - "Usable", - FALSE, - G_PARAM_READABLE)); - - g_object_class_install_property - (object_class, PROP_CONNECTED, - g_param_spec_boolean (NM_BLUEZ_DEVICE_CONNECTED, - "Connected", - "Connected", - FALSE, - G_PARAM_READABLE)); - - /* Signals */ - signals[INITIALIZED] = g_signal_new ("initialized", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMBluezDeviceClass, initialized), - NULL, NULL, NULL, - G_TYPE_NONE, 1, G_TYPE_BOOLEAN); -} - diff --git a/src/bluez-manager/nm-bluez-device.h b/src/bluez-manager/nm-bluez-device.h deleted file mode 100644 index 11add389..00000000 --- a/src/bluez-manager/nm-bluez-device.h +++ /dev/null @@ -1,97 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2009 - 2012 Red Hat, Inc. - */ - -#ifndef NM_BLUEZ_DEVICE_H -#define NM_BLUEZ_DEVICE_H - -#include -#include -#include - -#include -#include "nm-connection.h" -#include "nm-connection-provider.h" - -#define NM_TYPE_BLUEZ_DEVICE (nm_bluez_device_get_type ()) -#define NM_BLUEZ_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_BLUEZ_DEVICE, NMBluezDevice)) -#define NM_BLUEZ_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_BLUEZ_DEVICE, NMBluezDeviceClass)) -#define NM_IS_BLUEZ_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_BLUEZ_DEVICE)) -#define NM_IS_BLUEZ_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_BLUEZ_DEVICE)) -#define NM_BLUEZ_DEVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_BLUEZ_DEVICE, NMBluezDeviceClass)) - -#define NM_BLUEZ_DEVICE_PATH "path" -#define NM_BLUEZ_DEVICE_ADDRESS "address" -#define NM_BLUEZ_DEVICE_NAME "name" -#define NM_BLUEZ_DEVICE_CAPABILITIES "capabilities" -#define NM_BLUEZ_DEVICE_RSSI "rssi" -#define NM_BLUEZ_DEVICE_USABLE "usable" -#define NM_BLUEZ_DEVICE_CONNECTED "connected" - -typedef struct { - GObject parent; -} NMBluezDevice; - -typedef struct { - GObjectClass parent; - - /* virtual functions */ - void (*initialized) (NMBluezDevice *self, gboolean success); - - void (*invalid) (NMBluezDevice *self); -} NMBluezDeviceClass; - -GType nm_bluez_device_get_type (void); - -NMBluezDevice *nm_bluez_device_new (const char *path, NMConnectionProvider *provider); - -const char *nm_bluez_device_get_path (NMBluezDevice *self); - -gboolean nm_bluez_device_get_initialized (NMBluezDevice *self); - -gboolean nm_bluez_device_get_usable (NMBluezDevice *self); - -const char *nm_bluez_device_get_address (NMBluezDevice *self); - -const char *nm_bluez_device_get_name (NMBluezDevice *self); - -guint32 nm_bluez_device_get_class (NMBluezDevice *self); - -guint32 nm_bluez_device_get_capabilities (NMBluezDevice *self); - -gint nm_bluez_device_get_rssi (NMBluezDevice *self); - -gboolean nm_bluez_device_get_connected (NMBluezDevice *self); - -void -nm_bluez_device_connect_async (NMBluezDevice *self, - NMBluetoothCapabilities connection_bt_type, - GAsyncReadyCallback callback, - gpointer user_data); - -const char * -nm_bluez_device_connect_finish (NMBluezDevice *self, - GAsyncResult *result, - GError **error); - -void -nm_bluez_device_disconnect (NMBluezDevice *self); - -#endif /* NM_BLUEZ_DEVICE_H */ - diff --git a/src/bluez-manager/nm-bluez-manager.c b/src/bluez-manager/nm-bluez-manager.c deleted file mode 100644 index 3801d5ee..00000000 --- a/src/bluez-manager/nm-bluez-manager.c +++ /dev/null @@ -1,438 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2007 - 2008 Novell, Inc. - * Copyright (C) 2007 - 2012 Red Hat, Inc. - * Copyright (C) 2013 Intel Corporation. - */ - -#include -#include -#include -#include - -#include "nm-logging.h" -#include "nm-bluez-manager.h" -#include "nm-bluez-device.h" -#include "nm-bluez-common.h" - -#include "nm-dbus-manager.h" - -typedef struct { - NMDBusManager *dbus_mgr; - gulong name_owner_changed_id; - - NMConnectionProvider *provider; - - GDBusProxy *proxy; - - GHashTable *devices; -} NMBluezManagerPrivate; - -#define NM_BLUEZ_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_BLUEZ_MANAGER, NMBluezManagerPrivate)) - -G_DEFINE_TYPE (NMBluezManager, nm_bluez_manager, G_TYPE_OBJECT) - -enum { - BDADDR_ADDED, - BDADDR_REMOVED, - - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -static void device_initialized (NMBluezDevice *device, gboolean success, NMBluezManager *self); -static void device_usable (NMBluezDevice *device, GParamSpec *pspec, NMBluezManager *self); - -static void -emit_bdaddr_added (NMBluezManager *self, NMBluezDevice *device) -{ - g_signal_emit (self, signals[BDADDR_ADDED], 0, - device, - nm_bluez_device_get_address (device), - nm_bluez_device_get_name (device), - nm_bluez_device_get_path (device), - nm_bluez_device_get_capabilities (device)); -} - -void -nm_bluez_manager_query_devices (NMBluezManager *self) -{ - NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); - NMBluezDevice *device; - GHashTableIter iter; - - g_hash_table_iter_init (&iter, priv->devices); - while (g_hash_table_iter_next (&iter, NULL, (gpointer) &device)) { - if (nm_bluez_device_get_usable (device)) - emit_bdaddr_added (self, device); - } -} - -static void -remove_device (NMBluezManager *self, NMBluezDevice *device) -{ - if (nm_bluez_device_get_usable (device)) { - g_signal_emit (self, signals[BDADDR_REMOVED], 0, - nm_bluez_device_get_address (device), - nm_bluez_device_get_path (device)); - } - g_signal_handlers_disconnect_by_func (device, G_CALLBACK (device_initialized), self); - g_signal_handlers_disconnect_by_func (device, G_CALLBACK (device_usable), self); -} - -static void -remove_all_devices (NMBluezManager *self) -{ - GHashTableIter iter; - NMBluezDevice *device; - NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); - - g_hash_table_iter_init (&iter, priv->devices); - while (g_hash_table_iter_next (&iter, NULL, (gpointer) &device)) { - g_hash_table_iter_steal (&iter); - remove_device (self, device); - g_object_unref (device); - } -} - -static void -device_usable (NMBluezDevice *device, GParamSpec *pspec, NMBluezManager *self) -{ - gboolean usable = nm_bluez_device_get_usable (device); - - nm_log_dbg (LOGD_BT, "(%s): bluez device now %s", - nm_bluez_device_get_path (device), - usable ? "usable" : "unusable"); - - if (usable) { - nm_log_dbg (LOGD_BT, "(%s): bluez device address %s", - nm_bluez_device_get_path (device), - nm_bluez_device_get_address (device)); - emit_bdaddr_added (self, device); - } else - g_signal_emit (self, signals[BDADDR_REMOVED], 0, - nm_bluez_device_get_address (device), - nm_bluez_device_get_path (device)); -} - -static void -device_initialized (NMBluezDevice *device, gboolean success, NMBluezManager *self) -{ - NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); - - nm_log_dbg (LOGD_BT, "(%s): bluez device %s", - nm_bluez_device_get_path (device), - success ? "initialized" : "failed to initialize"); - if (!success) - g_hash_table_remove (priv->devices, nm_bluez_device_get_path (device)); -} - -static void -device_added (GDBusProxy *proxy, const gchar *path, NMBluezManager *self) -{ - NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); - NMBluezDevice *device; - - device = nm_bluez_device_new (path, priv->provider); - g_signal_connect (device, "initialized", G_CALLBACK (device_initialized), self); - g_signal_connect (device, "notify::usable", G_CALLBACK (device_usable), self); - g_hash_table_insert (priv->devices, (gpointer) nm_bluez_device_get_path (device), device); - - nm_log_dbg (LOGD_BT, "(%s): new bluez device found", path); -} - -static void -device_removed (GDBusProxy *proxy, const gchar *path, NMBluezManager *self) -{ - NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); - NMBluezDevice *device; - - nm_log_dbg (LOGD_BT, "(%s): bluez device removed", path); - - device = g_hash_table_lookup (priv->devices, path); - if (device) { - g_hash_table_steal (priv->devices, nm_bluez_device_get_path (device)); - remove_device (NM_BLUEZ_MANAGER (self), device); - g_object_unref (device); - } -} - -static void -object_manager_g_signal (GDBusProxy *proxy, - gchar *sender_name, - gchar *signal_name, - GVariant *parameters, - NMBluezManager *self) -{ - GVariant *variant; - const gchar *path; - - if (!strcmp (signal_name, "InterfacesRemoved")) { - const gchar **ifaces; - gsize i, length; - - g_variant_get (parameters, "(&o*)", &path, &variant); - - ifaces = g_variant_get_strv (variant, &length); - - for (i = 0; i < length; i++) { - if (!strcmp (ifaces[i], BLUEZ_DEVICE_INTERFACE)) { - device_removed (proxy, path, self); - break; - } - } - - g_free (ifaces); - - } else if (!strcmp (signal_name, "InterfacesAdded")) { - g_variant_get (parameters, "(&o*)", &path, &variant); - - if (g_variant_lookup_value (variant, BLUEZ_DEVICE_INTERFACE, - G_VARIANT_TYPE_DICTIONARY)) - device_added (proxy, path, self); - } -} - -static void -get_managed_objects_cb (GDBusProxy *proxy, - GAsyncResult *res, - NMBluezManager *self) -{ - GVariant *variant, *ifaces; - GVariantIter i; - GError *error = NULL; - const char *path; - - variant = g_dbus_proxy_call_finish (proxy, res, &error); - - if (!variant) { - nm_log_warn (LOGD_BT, "Couldn't get managed objects: %s", - error && error->message ? error->message : "(unknown)"); - g_clear_error (&error); - return; - } - g_variant_iter_init (&i, g_variant_get_child_value (variant, 0)); - while ((g_variant_iter_next (&i, "{&o*}", &path, &ifaces))) { - if (g_variant_lookup_value (ifaces, BLUEZ_DEVICE_INTERFACE, - G_VARIANT_TYPE_DICTIONARY)) { - device_added (proxy, path, self); - } - } - - g_variant_unref (variant); -} - -static void -on_proxy_acquired (GObject *object, - GAsyncResult *res, - NMBluezManager *self) -{ - NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); - GError *error = NULL; - - priv->proxy = g_dbus_proxy_new_for_bus_finish (res, &error); - - if (!priv->proxy) { - nm_log_warn (LOGD_BT, "Couldn't acquire object manager proxy: %s", - error && error->message ? error->message : "(unknown)"); - g_clear_error (&error); - return; - } - - /* Get already managed devices. */ - g_dbus_proxy_call (priv->proxy, "GetManagedObjects", - NULL, - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, - (GAsyncReadyCallback) get_managed_objects_cb, - self); - - g_signal_connect (priv->proxy, "g-signal", - G_CALLBACK (object_manager_g_signal), self); -} - -static void -bluez_connect (NMBluezManager *self) -{ - NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); - - g_return_if_fail (priv->proxy == NULL); - - g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - BLUEZ_SERVICE, - BLUEZ_MANAGER_PATH, - OBJECT_MANAGER_INTERFACE, - NULL, - (GAsyncReadyCallback) on_proxy_acquired, - self); -} - -static void -name_owner_changed_cb (NMDBusManager *dbus_mgr, - const char *name, - const char *old_owner, - const char *new_owner, - gpointer user_data) -{ - NMBluezManager *self = NM_BLUEZ_MANAGER (user_data); - NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); - gboolean old_owner_good = (old_owner && strlen (old_owner)); - gboolean new_owner_good = (new_owner && strlen (new_owner)); - - /* Can't handle the signal if its not from the Bluez */ - if (strcmp (BLUEZ_SERVICE, name)) - return; - - if (old_owner_good && !new_owner_good) { - if (priv->devices) - remove_all_devices (self); - } -} - -static void -bluez_cleanup (NMBluezManager *self, gboolean do_signal) -{ - NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); - - if (priv->proxy) { - g_object_unref (priv->proxy); - priv->proxy = NULL; - } - - if (do_signal) - remove_all_devices (self); - else - g_hash_table_remove_all (priv->devices); -} - -static void -dbus_connection_changed_cb (NMDBusManager *dbus_mgr, - DBusGConnection *connection, - gpointer user_data) -{ - NMBluezManager *self = NM_BLUEZ_MANAGER (user_data); - - if (!connection) - bluez_cleanup (self, TRUE); - else - bluez_connect (self); -} - -/****************************************************************/ - -NMBluezManager * -nm_bluez_manager_get (NMConnectionProvider *provider) -{ - static NMBluezManager *singleton = NULL; - - if (singleton) - return g_object_ref (singleton); - - singleton = (NMBluezManager *) g_object_new (NM_TYPE_BLUEZ_MANAGER, NULL); - g_assert (singleton); - - /* Cache the connection provider for NMBluezAdapter objects */ - NM_BLUEZ_MANAGER_GET_PRIVATE (singleton)->provider = provider; - - return singleton; -} - -static void -nm_bluez_manager_init (NMBluezManager *self) -{ - NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); - - priv->dbus_mgr = nm_dbus_manager_get (); - g_assert (priv->dbus_mgr); - - g_signal_connect (priv->dbus_mgr, - NM_DBUS_MANAGER_NAME_OWNER_CHANGED, - G_CALLBACK (name_owner_changed_cb), - self); - - g_signal_connect (priv->dbus_mgr, - NM_DBUS_MANAGER_DBUS_CONNECTION_CHANGED, - G_CALLBACK (dbus_connection_changed_cb), - self); - - bluez_connect (self); - - priv->devices = g_hash_table_new_full (g_str_hash, g_str_equal, - NULL, g_object_unref); -} - -static void -dispose (GObject *object) -{ - NMBluezManager *self = NM_BLUEZ_MANAGER (object); - NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); - - bluez_cleanup (self, FALSE); - - if (priv->dbus_mgr) { - g_signal_handlers_disconnect_by_func (priv->dbus_mgr, name_owner_changed_cb, self); - g_signal_handlers_disconnect_by_func (priv->dbus_mgr, dbus_connection_changed_cb, self); - priv->dbus_mgr = NULL; - } - - G_OBJECT_CLASS (nm_bluez_manager_parent_class)->dispose (object); -} - -static void -finalize (GObject *object) -{ - NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (object); - - g_hash_table_destroy (priv->devices); - - G_OBJECT_CLASS (nm_bluez_manager_parent_class)->finalize (object); -} - -static void -nm_bluez_manager_class_init (NMBluezManagerClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - g_type_class_add_private (klass, sizeof (NMBluezManagerPrivate)); - - /* virtual methods */ - object_class->dispose = dispose; - object_class->finalize = finalize; - - /* Signals */ - signals[BDADDR_ADDED] = - g_signal_new (NM_BLUEZ_MANAGER_BDADDR_ADDED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMBluezManagerClass, bdaddr_added), - NULL, NULL, NULL, - G_TYPE_NONE, 5, G_TYPE_OBJECT, G_TYPE_STRING, - G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT); - - signals[BDADDR_REMOVED] = - g_signal_new (NM_BLUEZ_MANAGER_BDADDR_REMOVED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMBluezManagerClass, bdaddr_removed), - NULL, NULL, NULL, - G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_STRING); -} diff --git a/src/bluez-manager/nm-bluez-manager.h b/src/bluez-manager/nm-bluez-manager.h deleted file mode 100644 index 95e319c5..00000000 --- a/src/bluez-manager/nm-bluez-manager.h +++ /dev/null @@ -1,69 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2007 - 2008 Novell, Inc. - * Copyright (C) 2007 - 2012 Red Hat, Inc. - */ - -#ifndef NM_BLUEZ_MANAGER_H -#define NM_BLUEZ_MANAGER_H - -#include -#include - -#include -#include "nm-connection-provider.h" - -G_BEGIN_DECLS - -#define NM_TYPE_BLUEZ_MANAGER (nm_bluez_manager_get_type ()) -#define NM_BLUEZ_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_BLUEZ_MANAGER, NMBluezManager)) -#define NM_BLUEZ_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_BLUEZ_MANAGER, NMBluezManagerClass)) -#define NM_IS_BLUEZ_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_BLUEZ_MANAGER)) -#define NM_IS_BLUEZ_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_BLUEZ_MANAGER)) -#define NM_BLUEZ_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_BLUEZ_MANAGER, NMBluezManagerClass)) - -#define NM_BLUEZ_MANAGER_BDADDR_ADDED "bdaddr-added" -#define NM_BLUEZ_MANAGER_BDADDR_REMOVED "bdaddr-removed" - -typedef struct { - GObject parent; -} NMBluezManager; - -typedef struct { - GObjectClass parent; - - /* Virtual functions */ - void (*bdaddr_added) (NMBluezManager *manager, - const char *bdaddr, - const char *name, - const char *object_path, - guint uuids); - - void (*bdaddr_removed) (NMBluezManager *manager, - const char *bdaddr, - const char *object_path); -} NMBluezManagerClass; - -GType nm_bluez_manager_get_type (void); - -NMBluezManager *nm_bluez_manager_get (NMConnectionProvider *provider); - -void nm_bluez_manager_query_devices (NMBluezManager *manager); - -#endif /* NM_BLUEZ_MANAGER_H */ - diff --git a/src/bluez-manager/nm-bluez4-adapter.c b/src/bluez-manager/nm-bluez4-adapter.c deleted file mode 100644 index 817df73d..00000000 --- a/src/bluez-manager/nm-bluez4-adapter.c +++ /dev/null @@ -1,397 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2009 - 2012 Red Hat, Inc. - */ - -#include -#include - -#include "NetworkManager.h" -#include "nm-dbus-manager.h" -#include "nm-bluez4-adapter.h" -#include "nm-bluez-device.h" -#include "nm-bluez-common.h" -#include "nm-dbus-glib-types.h" -#include "nm-logging.h" - - -G_DEFINE_TYPE (NMBluezAdapter, nm_bluez_adapter, G_TYPE_OBJECT) - -#define NM_BLUEZ_ADAPTER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_BLUEZ_ADAPTER, NMBluezAdapterPrivate)) - -typedef struct { - char *path; - DBusGProxy *proxy; - gboolean initialized; - - char *address; - GHashTable *devices; - - /* Cached for devices */ - NMConnectionProvider *provider; -} NMBluezAdapterPrivate; - - -enum { - PROP_0, - PROP_PATH, - PROP_ADDRESS, - - LAST_PROP -}; - -/* Signals */ -enum { - INITIALIZED, - DEVICE_ADDED, - DEVICE_REMOVED, - LAST_SIGNAL -}; -static guint signals[LAST_SIGNAL] = { 0 }; - -const char * -nm_bluez_adapter_get_path (NMBluezAdapter *self) -{ - g_return_val_if_fail (NM_IS_BLUEZ_ADAPTER (self), NULL); - - return NM_BLUEZ_ADAPTER_GET_PRIVATE (self)->path; -} - -const char * -nm_bluez_adapter_get_address (NMBluezAdapter *self) -{ - g_return_val_if_fail (NM_IS_BLUEZ_ADAPTER (self), NULL); - - return NM_BLUEZ_ADAPTER_GET_PRIVATE (self)->address; -} - -gboolean -nm_bluez_adapter_get_initialized (NMBluezAdapter *self) -{ - g_return_val_if_fail (NM_IS_BLUEZ_ADAPTER (self), FALSE); - - return NM_BLUEZ_ADAPTER_GET_PRIVATE (self)->initialized; -} - -GSList * -nm_bluez_adapter_get_devices (NMBluezAdapter *self) -{ - GSList *devices = NULL; - GHashTableIter iter; - NMBluezDevice *device; - - g_hash_table_iter_init (&iter, NM_BLUEZ_ADAPTER_GET_PRIVATE (self)->devices); - while (g_hash_table_iter_next (&iter, NULL, (gpointer) &device)) { - if (nm_bluez_device_get_usable (device)) - devices = g_slist_append (devices, device); - } - return devices; -} - -static void -device_usable (NMBluezDevice *device, GParamSpec *pspec, gpointer user_data) -{ - NMBluezAdapter *self = NM_BLUEZ_ADAPTER (user_data); - gboolean usable = nm_bluez_device_get_usable (device); - - nm_log_dbg (LOGD_BT, "(%s): bluez device now %s", - nm_bluez_device_get_path (device), - usable ? "usable" : "unusable"); - - if (usable) { - nm_log_dbg (LOGD_BT, "(%s): bluez device address %s", - nm_bluez_device_get_path (device), - nm_bluez_device_get_address (device)); - g_signal_emit (self, signals[DEVICE_ADDED], 0, device); - } else - g_signal_emit (self, signals[DEVICE_REMOVED], 0, device); -} - -static void -device_initialized (NMBluezDevice *device, gboolean success, gpointer user_data) -{ - NMBluezAdapter *self = NM_BLUEZ_ADAPTER (user_data); - NMBluezAdapterPrivate *priv = NM_BLUEZ_ADAPTER_GET_PRIVATE (self); - - nm_log_dbg (LOGD_BT, "(%s): bluez device %s", - nm_bluez_device_get_path (device), - success ? "initialized" : "failed to initialize"); - if (!success) - g_hash_table_remove (priv->devices, nm_bluez_device_get_path (device)); -} - -static void -device_created (DBusGProxy *proxy, const char *path, gpointer user_data) -{ - NMBluezAdapter *self = NM_BLUEZ_ADAPTER (user_data); - NMBluezAdapterPrivate *priv = NM_BLUEZ_ADAPTER_GET_PRIVATE (self); - NMBluezDevice *device; - - device = nm_bluez_device_new (path, priv->provider); - g_signal_connect (device, "initialized", G_CALLBACK (device_initialized), self); - g_signal_connect (device, "notify::usable", G_CALLBACK (device_usable), self); - g_hash_table_insert (priv->devices, (gpointer) nm_bluez_device_get_path (device), device); - - nm_log_dbg (LOGD_BT, "(%s): new bluez device found", path); -} - -static void -device_removed (DBusGProxy *proxy, const char *path, gpointer user_data) -{ - NMBluezAdapter *self = NM_BLUEZ_ADAPTER (user_data); - NMBluezAdapterPrivate *priv = NM_BLUEZ_ADAPTER_GET_PRIVATE (self); - NMBluezDevice *device; - - nm_log_dbg (LOGD_BT, "(%s): bluez device removed", path); - - device = g_hash_table_lookup (priv->devices, path); - if (device) { - g_object_ref (device); - g_hash_table_remove (priv->devices, nm_bluez_device_get_path (device)); - g_signal_emit (self, signals[DEVICE_REMOVED], 0, device); - g_object_unref (device); - } -} - - -static void -get_properties_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) -{ - NMBluezAdapter *self = NM_BLUEZ_ADAPTER (user_data); - NMBluezAdapterPrivate *priv = NM_BLUEZ_ADAPTER_GET_PRIVATE (self); - GHashTable *properties = NULL; - GError *err = NULL; - GValue *value; - GPtrArray *devices; - int i; - - if (!dbus_g_proxy_end_call (proxy, call, &err, - DBUS_TYPE_G_MAP_OF_VARIANT, &properties, - G_TYPE_INVALID)) { - nm_log_warn (LOGD_BT, "bluez error getting adapter properties: %s", - err && err->message ? err->message : "(unknown)"); - g_error_free (err); - goto done; - } - - value = g_hash_table_lookup (properties, "Address"); - priv->address = value ? g_value_dup_string (value) : NULL; - - value = g_hash_table_lookup (properties, "Devices"); - devices = value ? g_value_get_boxed (value) : NULL; - - for (i = 0; devices && i < devices->len; i++) - device_created (priv->proxy, g_ptr_array_index (devices, i), self); - - g_hash_table_unref (properties); - - priv->initialized = TRUE; - -done: - g_signal_emit (self, signals[INITIALIZED], 0, priv->initialized); -} - -static void -query_properties (NMBluezAdapter *self) -{ - NMBluezAdapterPrivate *priv = NM_BLUEZ_ADAPTER_GET_PRIVATE (self); - DBusGProxyCall *call; - - call = dbus_g_proxy_begin_call (priv->proxy, "GetProperties", - get_properties_cb, - self, - NULL, G_TYPE_INVALID); - if (!call) { - nm_log_warn (LOGD_BT, "failed to request Bluetooth adapter properties for %s.", - priv->path); - } -} - -/***********************************************************/ - -NMBluezAdapter * -nm_bluez_adapter_new (const char *path, NMConnectionProvider *provider) -{ - NMBluezAdapter *self; - NMBluezAdapterPrivate *priv; - NMDBusManager *dbus_mgr; - DBusGConnection *connection; - - self = (NMBluezAdapter *) g_object_new (NM_TYPE_BLUEZ_ADAPTER, - NM_BLUEZ_ADAPTER_PATH, path, - NULL); - if (!self) - return NULL; - - priv = NM_BLUEZ_ADAPTER_GET_PRIVATE (self); - - priv->provider = provider; - - dbus_mgr = nm_dbus_manager_get (); - connection = nm_dbus_manager_get_connection (dbus_mgr); - - priv->proxy = dbus_g_proxy_new_for_name (connection, - BLUEZ_SERVICE, - priv->path, - BLUEZ_ADAPTER_INTERFACE); - g_object_unref (dbus_mgr); - - dbus_g_proxy_add_signal (priv->proxy, "DeviceCreated", - DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID); - dbus_g_proxy_connect_signal (priv->proxy, "DeviceCreated", - G_CALLBACK (device_created), self, NULL); - - dbus_g_proxy_add_signal (priv->proxy, "DeviceRemoved", - DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID); - dbus_g_proxy_connect_signal (priv->proxy, "DeviceRemoved", - G_CALLBACK (device_removed), self, NULL); - - query_properties (self); - return self; -} - -static void -nm_bluez_adapter_init (NMBluezAdapter *self) -{ - NMBluezAdapterPrivate *priv = NM_BLUEZ_ADAPTER_GET_PRIVATE (self); - - priv->devices = g_hash_table_new_full (g_str_hash, g_str_equal, - NULL, g_object_unref); -} - -static void -dispose (GObject *object) -{ - NMBluezAdapter *self = NM_BLUEZ_ADAPTER (object); - NMBluezAdapterPrivate *priv = NM_BLUEZ_ADAPTER_GET_PRIVATE (self); - GHashTableIter iter; - NMBluezDevice *device; - - g_hash_table_iter_init (&iter, priv->devices); - while (g_hash_table_iter_next (&iter, NULL, (gpointer) &device)) - g_signal_emit (self, signals[DEVICE_REMOVED], 0, device); - g_hash_table_remove_all (priv->devices); - - G_OBJECT_CLASS (nm_bluez_adapter_parent_class)->dispose (object); -} - -static void -finalize (GObject *object) -{ - NMBluezAdapterPrivate *priv = NM_BLUEZ_ADAPTER_GET_PRIVATE (object); - - g_hash_table_destroy (priv->devices); - g_free (priv->address); - g_free (priv->path); - g_object_unref (priv->proxy); - - G_OBJECT_CLASS (nm_bluez_adapter_parent_class)->finalize (object); -} - -static void -get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) -{ - NMBluezAdapterPrivate *priv = NM_BLUEZ_ADAPTER_GET_PRIVATE (object); - - switch (prop_id) { - case PROP_PATH: - g_value_set_string (value, priv->path); - break; - case PROP_ADDRESS: - g_value_set_string (value, priv->address); - 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) -{ - NMBluezAdapterPrivate *priv = NM_BLUEZ_ADAPTER_GET_PRIVATE (object); - - switch (prop_id) { - case PROP_PATH: - /* construct only */ - priv->path = g_value_dup_string (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -nm_bluez_adapter_class_init (NMBluezAdapterClass *config_class) -{ - GObjectClass *object_class = G_OBJECT_CLASS (config_class); - - g_type_class_add_private (config_class, sizeof (NMBluezAdapterPrivate)); - - /* virtual methods */ - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->dispose = dispose; - object_class->finalize = finalize; - - /* Properties */ - g_object_class_install_property - (object_class, PROP_PATH, - g_param_spec_string (NM_BLUEZ_ADAPTER_PATH, - "DBus Path", - "DBus Path", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - g_object_class_install_property - (object_class, PROP_ADDRESS, - g_param_spec_string (NM_BLUEZ_ADAPTER_ADDRESS, - "Address", - "Address", - NULL, - G_PARAM_READABLE)); - - /* Signals */ - signals[INITIALIZED] = g_signal_new ("initialized", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMBluezAdapterClass, initialized), - NULL, NULL, - g_cclosure_marshal_VOID__BOOLEAN, - G_TYPE_NONE, 1, G_TYPE_BOOLEAN); - - signals[DEVICE_ADDED] = g_signal_new ("device-added", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMBluezAdapterClass, device_added), - NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, G_TYPE_OBJECT); - - signals[DEVICE_REMOVED] = g_signal_new ("device-removed", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMBluezAdapterClass, device_removed), - NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, G_TYPE_OBJECT); -} - diff --git a/src/bluez-manager/nm-bluez4-adapter.h b/src/bluez-manager/nm-bluez4-adapter.h deleted file mode 100644 index 8e53b40d..00000000 --- a/src/bluez-manager/nm-bluez4-adapter.h +++ /dev/null @@ -1,69 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2009 - 2012 Red Hat, Inc. - */ - -#ifndef NM_BLUEZ_ADAPTER_H -#define NM_BLUEZ_ADAPTER_H - -#include -#include - -#include "nm-bluez-device.h" -#include "nm-connection-provider.h" - -#define NM_TYPE_BLUEZ_ADAPTER (nm_bluez_adapter_get_type ()) -#define NM_BLUEZ_ADAPTER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_BLUEZ_ADAPTER, NMBluezAdapter)) -#define NM_BLUEZ_ADAPTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_BLUEZ_ADAPTER, NMBluezAdapterClass)) -#define NM_IS_BLUEZ_ADAPTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_BLUEZ_ADAPTER)) -#define NM_IS_BLUEZ_ADAPTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_BLUEZ_ADAPTER)) -#define NM_BLUEZ_ADAPTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_BLUEZ_ADAPTER, NMBluezAdapterClass)) - -#define NM_BLUEZ_ADAPTER_PATH "path" -#define NM_BLUEZ_ADAPTER_ADDRESS "address" - -typedef struct { - GObject parent; -} NMBluezAdapter; - -typedef struct { - GObjectClass parent; - - /* virtual functions */ - void (*initialized) (NMBluezAdapter *self, gboolean success); - - void (*device_added) (NMBluezAdapter *self, NMBluezDevice *device); - - void (*device_removed) (NMBluezAdapter *self, NMBluezDevice *device); -} NMBluezAdapterClass; - -GType nm_bluez_adapter_get_type (void); - -NMBluezAdapter *nm_bluez_adapter_new (const char *path, - NMConnectionProvider *provider); - -const char *nm_bluez_adapter_get_path (NMBluezAdapter *self); - -const char *nm_bluez_adapter_get_address (NMBluezAdapter *self); - -gboolean nm_bluez_adapter_get_initialized (NMBluezAdapter *self); - -GSList *nm_bluez_adapter_get_devices (NMBluezAdapter *self); - -#endif /* NM_BLUEZ_ADAPTER_H */ - diff --git a/src/bluez-manager/nm-bluez4-manager.c b/src/bluez-manager/nm-bluez4-manager.c deleted file mode 100644 index bd1d251a..00000000 --- a/src/bluez-manager/nm-bluez4-manager.c +++ /dev/null @@ -1,386 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2007 - 2008 Novell, Inc. - * Copyright (C) 2007 - 2012 Red Hat, Inc. - */ - -#include -#include -#include -#include - -#include "nm-logging.h" -#include "nm-dbus-glib-types.h" -#include "nm-marshal.h" -#include "nm-bluez-manager.h" -#include "nm-bluez4-adapter.h" -#include "nm-dbus-manager.h" -#include "nm-bluez-common.h" - - -typedef struct { - NMDBusManager *dbus_mgr; - gulong name_owner_changed_id; - - NMConnectionProvider *provider; - - DBusGProxy *proxy; - - NMBluezAdapter *adapter; -} NMBluezManagerPrivate; - -#define NM_BLUEZ_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_BLUEZ_MANAGER, NMBluezManagerPrivate)) - -G_DEFINE_TYPE (NMBluezManager, nm_bluez_manager, G_TYPE_OBJECT) - -enum { - BDADDR_ADDED, - BDADDR_REMOVED, - - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -static void - -emit_bdaddr_added (NMBluezManager *self, NMBluezDevice *device) -{ - g_signal_emit (self, signals[BDADDR_ADDED], 0, - device, - nm_bluez_device_get_address (device), - nm_bluez_device_get_name (device), - nm_bluez_device_get_path (device), - nm_bluez_device_get_capabilities (device)); -} - -void -nm_bluez_manager_query_devices (NMBluezManager *self) -{ - NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); - GSList *devices, *iter; - - if (!priv->adapter) - return; - - devices = nm_bluez_adapter_get_devices (priv->adapter); - for (iter = devices; iter; iter = g_slist_next (iter)) - emit_bdaddr_added (self, NM_BLUEZ_DEVICE (iter->data)); - g_slist_free (devices); -} - -static void -device_added (NMBluezAdapter *adapter, NMBluezDevice *device, gpointer user_data) -{ - emit_bdaddr_added (NM_BLUEZ_MANAGER (user_data), device); -} - -static void -device_removed (NMBluezAdapter *adapter, NMBluezDevice *device, gpointer user_data) -{ - NMBluezManager *self = NM_BLUEZ_MANAGER (user_data); - - g_signal_emit (self, signals[BDADDR_REMOVED], 0, - nm_bluez_device_get_address (device), - nm_bluez_device_get_path (device)); -} - -static void -adapter_initialized (NMBluezAdapter *adapter, gboolean success, gpointer user_data) -{ - NMBluezManager *self = NM_BLUEZ_MANAGER (user_data); - NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); - - if (success) { - GSList *devices, *iter; - - devices = nm_bluez_adapter_get_devices (adapter); - for (iter = devices; iter; iter = g_slist_next (iter)) - emit_bdaddr_added (self, NM_BLUEZ_DEVICE (iter->data)); - g_slist_free (devices); - - g_signal_connect (adapter, "device-added", G_CALLBACK (device_added), self); - g_signal_connect (adapter, "device-removed", G_CALLBACK (device_removed), self); - } else { - g_object_unref (priv->adapter); - priv->adapter = NULL; - } -} - -static void -adapter_removed (DBusGProxy *proxy, const char *path, NMBluezManager *self) -{ - NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); - - if (priv->adapter && !strcmp (path, nm_bluez_adapter_get_path (priv->adapter))) { - if (nm_bluez_adapter_get_initialized (priv->adapter)) { - GSList *devices, *iter; - - devices = nm_bluez_adapter_get_devices (priv->adapter); - for (iter = devices; iter; iter = g_slist_next (iter)) { - NMBluezDevice *device = NM_BLUEZ_DEVICE (iter->data); - - g_signal_emit (self, signals[BDADDR_REMOVED], 0, - nm_bluez_device_get_address (device), - nm_bluez_device_get_path (device)); - } - g_slist_free (devices); - } - - g_object_unref (priv->adapter); - priv->adapter = NULL; - } -} - -static void -default_adapter_changed (DBusGProxy *proxy, const char *path, NMBluezManager *self) -{ - NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); - const char *cur_path = NULL; - - if (priv->adapter) - cur_path = nm_bluez_adapter_get_path (priv->adapter); - - if (cur_path) { - if (!path || strcmp (path, cur_path)) { - /* Default adapter changed */ - adapter_removed (priv->proxy, cur_path, self); - } else { - /* This adapter is already the default */ - return; - } - } - - /* Add the new default adapter */ - if (path) { - priv->adapter = nm_bluez_adapter_new (path, priv->provider); - g_signal_connect (priv->adapter, "initialized", G_CALLBACK (adapter_initialized), self); - } -} - -static void -default_adapter_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) -{ - NMBluezManager *self = NM_BLUEZ_MANAGER (user_data); - NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); - const char *default_adapter = NULL; - GError *err = NULL; - - if (!dbus_g_proxy_end_call (proxy, call, &err, - DBUS_TYPE_G_OBJECT_PATH, &default_adapter, - G_TYPE_INVALID)) { - /* Ignore "No such adapter" errors; just means bluetooth isn't active */ - if ( !dbus_g_error_has_name (err, "org.bluez.Error.NoSuchAdapter") - && !dbus_g_error_has_name (err, "org.freedesktop.systemd1.LoadFailed") - && !g_error_matches (err, DBUS_GERROR, DBUS_GERROR_SERVICE_UNKNOWN)) { - nm_log_warn (LOGD_BT, "bluez error getting default adapter: %s", - err && err->message ? err->message : "(unknown)"); - } - g_error_free (err); - return; - } - - default_adapter_changed (priv->proxy, default_adapter, self); -} - -static void -query_default_adapter (NMBluezManager *self) -{ - NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); - DBusGProxyCall *call; - - call = dbus_g_proxy_begin_call (priv->proxy, "DefaultAdapter", - default_adapter_cb, - self, - NULL, G_TYPE_INVALID); - if (!call) - nm_log_warn (LOGD_BT, "failed to request default Bluetooth adapter."); -} - -static void -bluez_connect (NMBluezManager *self) -{ - NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); - DBusGConnection *connection; - - g_return_if_fail (priv->proxy == NULL); - - connection = nm_dbus_manager_get_connection (priv->dbus_mgr); - if (!connection) - return; - - priv->proxy = dbus_g_proxy_new_for_name (connection, - BLUEZ_SERVICE, - BLUEZ_MANAGER_PATH, - BLUEZ_MANAGER_INTERFACE); - - dbus_g_proxy_add_signal (priv->proxy, "AdapterRemoved", - DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID); - dbus_g_proxy_connect_signal (priv->proxy, "AdapterRemoved", - G_CALLBACK (adapter_removed), self, NULL); - - dbus_g_proxy_add_signal (priv->proxy, "DefaultAdapterChanged", - DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID); - dbus_g_proxy_connect_signal (priv->proxy, "DefaultAdapterChanged", - G_CALLBACK (default_adapter_changed), self, NULL); - - query_default_adapter (self); -} - -static void -name_owner_changed_cb (NMDBusManager *dbus_mgr, - const char *name, - const char *old_owner, - const char *new_owner, - gpointer user_data) -{ - NMBluezManager *self = NM_BLUEZ_MANAGER (user_data); - NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); - gboolean old_owner_good = (old_owner && strlen (old_owner)); - gboolean new_owner_good = (new_owner && strlen (new_owner)); - - /* Can't handle the signal if its not from the Bluez */ - if (strcmp (BLUEZ_SERVICE, name)) - return; - - if (!old_owner_good && new_owner_good) - query_default_adapter (self); - else if (old_owner_good && !new_owner_good) { - /* Throwing away the adapter removes all devices too */ - if (priv->adapter) { - g_object_unref (priv->adapter); - priv->adapter = NULL; - } - } -} - -static void -bluez_cleanup (NMBluezManager *self, gboolean do_signal) -{ - NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); - - if (priv->proxy) { - g_object_unref (priv->proxy); - priv->proxy = NULL; - } - - if (priv->adapter) { - g_object_unref (priv->adapter); - priv->adapter = NULL; - } -} - -static void -dbus_connection_changed_cb (NMDBusManager *dbus_mgr, - DBusGConnection *connection, - gpointer user_data) -{ - NMBluezManager *self = NM_BLUEZ_MANAGER (user_data); - - if (!connection) - bluez_cleanup (self, TRUE); - else - bluez_connect (self); -} - -/****************************************************************/ - -NMBluezManager * -nm_bluez_manager_get (NMConnectionProvider *provider) -{ - static NMBluezManager *singleton = NULL; - - if (singleton) - return g_object_ref (singleton); - - singleton = (NMBluezManager *) g_object_new (NM_TYPE_BLUEZ_MANAGER, NULL); - g_assert (singleton); - - /* Cache the connection provider for NMBluezAdapter objects */ - NM_BLUEZ_MANAGER_GET_PRIVATE (singleton)->provider = provider; - - return singleton; -} - -static void -nm_bluez_manager_init (NMBluezManager *self) -{ - NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); - - priv->dbus_mgr = nm_dbus_manager_get (); - g_assert (priv->dbus_mgr); - - g_signal_connect (priv->dbus_mgr, - NM_DBUS_MANAGER_NAME_OWNER_CHANGED, - G_CALLBACK (name_owner_changed_cb), - self); - - g_signal_connect (priv->dbus_mgr, - NM_DBUS_MANAGER_DBUS_CONNECTION_CHANGED, - G_CALLBACK (dbus_connection_changed_cb), - self); - - bluez_connect (self); -} - -static void -dispose (GObject *object) -{ - NMBluezManager *self = NM_BLUEZ_MANAGER (object); - NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); - - bluez_cleanup (self, FALSE); - - if (priv->dbus_mgr) { - g_signal_handlers_disconnect_by_func (priv->dbus_mgr, name_owner_changed_cb, self); - g_signal_handlers_disconnect_by_func (priv->dbus_mgr, dbus_connection_changed_cb, self); - g_object_unref (priv->dbus_mgr); - } - - G_OBJECT_CLASS (nm_bluez_manager_parent_class)->dispose (object); -} - -static void -nm_bluez_manager_class_init (NMBluezManagerClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - g_type_class_add_private (klass, sizeof (NMBluezManagerPrivate)); - - /* virtual methods */ - object_class->dispose = dispose; - - /* Signals */ - signals[BDADDR_ADDED] = - g_signal_new (NM_BLUEZ_MANAGER_BDADDR_ADDED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMBluezManagerClass, bdaddr_added), - NULL, NULL, NULL, - G_TYPE_NONE, 5, G_TYPE_OBJECT, G_TYPE_STRING, - G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT); - - signals[BDADDR_REMOVED] = - g_signal_new (NM_BLUEZ_MANAGER_BDADDR_REMOVED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMBluezManagerClass, bdaddr_removed), - NULL, NULL, NULL, - G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_STRING); -} - diff --git a/src/config/nm-config-device.c b/src/config/nm-config-device.c new file mode 100644 index 00000000..6914f033 --- /dev/null +++ b/src/config/nm-config-device.c @@ -0,0 +1,82 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright 2013 Red Hat, Inc. + */ + +#include "config.h" + +#include "nm-config-device.h" + +#include + +#include + +G_DEFINE_INTERFACE (NMConfigDevice, nm_config_device, G_TYPE_OBJECT) + +static void +nm_config_device_default_init (NMConfigDeviceInterface *iface) +{ +} + +gboolean +nm_config_device_spec_match_list (NMConfigDevice *self, const char **config_specs) +{ + GSList *specs = NULL; + gboolean match; + char buf[NM_UTILS_HWADDR_LEN_MAX + 1], *tmp; + int i; + + g_return_val_if_fail (NM_IS_CONFIG_DEVICE (self), FALSE); + + if (!config_specs) + return FALSE; + + /* For compatibility, we allow an untagged MAC address, and for convenience, + * we allow untagged interface names as well. + */ + for (i = 0; config_specs[i]; i++) { + if (g_strcmp0 (config_specs[i], "*") == 0) + specs = g_slist_prepend (specs, g_strdup (config_specs[i])); + else if (nm_utils_iface_valid_name (config_specs[i])) + specs = g_slist_prepend (specs, g_strdup_printf ("interface-name:%s", config_specs[i])); + else if ( nm_utils_hwaddr_aton (config_specs[i], ARPHRD_ETHER, buf) + || nm_utils_hwaddr_aton (config_specs[i], ARPHRD_INFINIBAND, buf)) { + tmp = g_ascii_strdown (config_specs[i], -1); + specs = g_slist_prepend (specs, g_strdup_printf ("mac:%s", tmp)); + g_free (tmp); + } else + specs = g_slist_prepend (specs, g_strdup (config_specs[i])); + } + + specs = g_slist_reverse (specs); + + match = NM_CONFIG_DEVICE_GET_INTERFACE (self)->spec_match_list (self, specs); + + g_slist_free_full (specs, g_free); + return match; +} + +char * +nm_config_device_get_hwaddr (NMConfigDevice *self) +{ + const guint8 *bytes; + guint len = 0; + + bytes = NM_CONFIG_DEVICE_GET_INTERFACE (self)->get_hw_address (self, &len); + return nm_utils_hwaddr_ntoa_len (bytes, len); +} diff --git a/src/config/nm-config-device.h b/src/config/nm-config-device.h new file mode 100644 index 00000000..8b5409a0 --- /dev/null +++ b/src/config/nm-config-device.h @@ -0,0 +1,47 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright 2013 Red Hat, Inc. + */ + +#ifndef NM_CONFIG_DEVICE_H +#define NM_CONFIG_DEVICE_H + +#include + +#define NM_TYPE_CONFIG_DEVICE (nm_config_device_get_type ()) +#define NM_CONFIG_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_CONFIG_DEVICE, NMConfigDevice)) +#define NM_IS_CONFIG_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_CONFIG_DEVICE)) +#define NM_CONFIG_DEVICE_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), NM_TYPE_CONFIG_DEVICE, NMConfigDeviceInterface)) + +typedef struct _NMConfigDevice NMConfigDevice; +typedef struct _NMConfigDeviceInterface NMConfigDeviceInterface; + +struct _NMConfigDeviceInterface { + GTypeInterface g_iface; + + /* Methods */ + gboolean (*spec_match_list) (NMConfigDevice *device, const GSList *specs); + const guint8 * (* get_hw_address) (NMConfigDevice *device, guint *out_len); +}; + +GType nm_config_device_get_type (void); + +gboolean nm_config_device_spec_match_list (NMConfigDevice *device, const char **config_specs); +char *nm_config_device_get_hwaddr (NMConfigDevice *device); + +#endif /* NM_CONFIG_DEVICE_H */ diff --git a/src/config/nm-config.c b/src/config/nm-config.c new file mode 100644 index 00000000..f6688b75 --- /dev/null +++ b/src/config/nm-config.c @@ -0,0 +1,604 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2011 Red Hat, Inc. + * Copyright (C) 2013 Thomas Bechtold + */ + +#include +#include +#include + +#include "nm-config.h" +#include "nm-logging.h" +#include "nm-utils.h" +#include "nm-glib-compat.h" + +#include +#include + +#define NM_DEFAULT_SYSTEM_CONF_FILE NMCONFDIR "/NetworkManager.conf" +#define NM_DEFAULT_SYSTEM_CONF_DIR NMCONFDIR "/conf.d" +#define NM_OLD_SYSTEM_CONF_FILE NMCONFDIR "/nm-system-settings.conf" +#define NM_NO_AUTO_DEFAULT_STATE_FILE NMSTATEDIR "/no-auto-default.state" + +typedef struct { + char *nm_conf_path; + char *config_dir; + char *config_description; + char *no_auto_default_file; + GKeyFile *keyfile; + + char **plugins; + gboolean monitor_connection_files; + char *dhcp_client; + char *dns_mode; + + char *log_level; + char *log_domains; + + char *debug; + + char *connectivity_uri; + gint connectivity_interval; + char *connectivity_response; + + char **no_auto_default; + char **ignore_carrier; +} NMConfigPrivate; + +static NMConfig *singleton = NULL; + +G_DEFINE_TYPE (NMConfig, nm_config, G_TYPE_OBJECT) + +#define NM_CONFIG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_CONFIG, NMConfigPrivate)) + +/************************************************************************/ + +const char * +nm_config_get_path (NMConfig *config) +{ + g_return_val_if_fail (config != NULL, NULL); + + return NM_CONFIG_GET_PRIVATE (config)->nm_conf_path; +} + +const char * +nm_config_get_description (NMConfig *config) +{ + g_return_val_if_fail (config != NULL, NULL); + + return NM_CONFIG_GET_PRIVATE (config)->config_description; +} + +const char ** +nm_config_get_plugins (NMConfig *config) +{ + g_return_val_if_fail (config != NULL, NULL); + + return (const char **) NM_CONFIG_GET_PRIVATE (config)->plugins; +} + +gboolean +nm_config_get_monitor_connection_files (NMConfig *config) +{ + g_return_val_if_fail (config != NULL, FALSE); + + return NM_CONFIG_GET_PRIVATE (config)->monitor_connection_files; +} + +const char * +nm_config_get_dhcp_client (NMConfig *config) +{ + g_return_val_if_fail (config != NULL, NULL); + + return NM_CONFIG_GET_PRIVATE (config)->dhcp_client; +} + +const char * +nm_config_get_dns_mode (NMConfig *config) +{ + g_return_val_if_fail (config != NULL, NULL); + + return NM_CONFIG_GET_PRIVATE (config)->dns_mode; +} + +const char * +nm_config_get_log_level (NMConfig *config) +{ + g_return_val_if_fail (config != NULL, NULL); + + return NM_CONFIG_GET_PRIVATE (config)->log_level; +} + +const char * +nm_config_get_log_domains (NMConfig *config) +{ + g_return_val_if_fail (config != NULL, NULL); + + return NM_CONFIG_GET_PRIVATE (config)->log_domains; +} + +const char * +nm_config_get_debug (NMConfig *config) +{ + g_return_val_if_fail (config != NULL, NULL); + + return NM_CONFIG_GET_PRIVATE (config)->debug; +} + +const char * +nm_config_get_connectivity_uri (NMConfig *config) +{ + g_return_val_if_fail (config != NULL, NULL); + + return NM_CONFIG_GET_PRIVATE (config)->connectivity_uri; +} + +const guint +nm_config_get_connectivity_interval (NMConfig *config) +{ + g_return_val_if_fail (config != NULL, 0); + + /* We store interval as signed internally to track whether it's + * set or not, but report as unsigned to callers. + */ + return MAX (NM_CONFIG_GET_PRIVATE (config)->connectivity_interval, 0); +} + +const char * +nm_config_get_connectivity_response (NMConfig *config) +{ + g_return_val_if_fail (config != NULL, NULL); + + return NM_CONFIG_GET_PRIVATE (config)->connectivity_response; +} + +char * +nm_config_get_value (NMConfig *config, const char *group, const char *key, GError **error) +{ + NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (config); + + return g_key_file_get_string (priv->keyfile, group, key, error); +} + +gboolean +nm_config_get_ignore_carrier (NMConfig *config, NMConfigDevice *device) +{ + NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (config); + + return nm_config_device_spec_match_list (device, (const char **) priv->ignore_carrier); +} + +/************************************************************************/ + +static void +merge_no_auto_default_state (NMConfig *config) +{ + NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (config); + GPtrArray *updated; + char **list; + int i, j; + char *data; + + /* If the config already matches everything, we don't need to do anything else. */ + if (priv->no_auto_default && !g_strcmp0 (priv->no_auto_default[0], "*")) + return; + + updated = g_ptr_array_new (); + if (priv->no_auto_default) { + for (i = 0; priv->no_auto_default[i]; i++) + g_ptr_array_add (updated, priv->no_auto_default[i]); + g_free (priv->no_auto_default); + } + + if (g_file_get_contents (priv->no_auto_default_file, &data, NULL, NULL)) { + list = g_strsplit (data, "\n", -1); + for (i = 0; list[i]; i++) { + if (!*list[i]) + continue; + for (j = 0; j < updated->len; j++) { + if (!strcmp (list[i], updated->pdata[j])) + break; + } + if (j == updated->len) + g_ptr_array_add (updated, list[i]); + } + g_free (list); + g_free (data); + } + + g_ptr_array_add (updated, NULL); + priv->no_auto_default = (char **) g_ptr_array_free (updated, FALSE); +} + +gboolean +nm_config_get_ethernet_can_auto_default (NMConfig *config, NMConfigDevice *device) +{ + NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (config); + + return !nm_config_device_spec_match_list (device, (const char **) priv->no_auto_default); +} + +void +nm_config_set_ethernet_no_auto_default (NMConfig *config, NMConfigDevice *device) +{ + NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (config); + char *current; + GString *updated; + GError *error = NULL; + + if (!nm_config_get_ethernet_can_auto_default (config, device)) + return; + + updated = g_string_new (NULL); + if (g_file_get_contents (priv->no_auto_default_file, ¤t, NULL, NULL)) { + g_string_append (updated, current); + g_free (current); + if (updated->str[updated->len - 1] != '\n') + g_string_append_c (updated, '\n'); + } + + g_string_append (updated, nm_config_device_get_hwaddr (device)); + g_string_append_c (updated, '\n'); + + if (!g_file_set_contents (priv->no_auto_default_file, updated->str, updated->len, &error)) { + nm_log_warn (LOGD_SETTINGS, "Could not update no-auto-default.state file: %s", + error->message); + g_error_free (error); + } + + g_string_free (updated, TRUE); + + merge_no_auto_default_state (config); +} + +/************************************************************************/ + +static char *cli_config_path; +static char *cli_config_dir; +static char *cli_no_auto_default_file; +static char *cli_plugins; +static char *cli_connectivity_uri; +static int cli_connectivity_interval = -1; +static char *cli_connectivity_response; + +static GOptionEntry config_options[] = { + { "config", 0, 0, G_OPTION_ARG_FILENAME, &cli_config_path, N_("Config file location"), N_("/path/to/config.file") }, + { "config-dir", 0, 0, G_OPTION_ARG_FILENAME, &cli_config_dir, N_("Config directory location"), N_("/path/to/config/dir") }, + { "no-auto-default", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_FILENAME, &cli_no_auto_default_file, "no-auto-default.state location", NULL }, + { "plugins", 0, 0, G_OPTION_ARG_STRING, &cli_plugins, N_("List of plugins separated by ','"), N_("plugin1,plugin2") }, + + /* These three are hidden for now, and should eventually just go away. */ + { "connectivity-uri", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, &cli_connectivity_uri, N_("An http(s) address for checking internet connectivity"), "http://example.com" }, + { "connectivity-interval", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_INT, &cli_connectivity_interval, N_("The interval between connectivity checks (in seconds)"), "60" }, + { "connectivity-response", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, &cli_connectivity_response, N_("The expected start of the response"), N_("Bingo!") }, + {NULL} +}; +GOptionEntry * +nm_config_get_options (void) +{ + return config_options; +} + +/************************************************************************/ + +static gboolean +read_config (NMConfig *config, const char *path, GError **error) +{ + NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (config); + GKeyFile *kf; + char **groups, **keys; + gsize ngroups, nkeys; + int g, k; + + if (g_file_test (path, G_FILE_TEST_EXISTS) == FALSE) { + g_set_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_NOT_FOUND, "file %s not found", path); + return FALSE; + } + + nm_log_dbg (LOGD_SETTINGS, "Reading config file '%s'", path); + + kf = g_key_file_new (); + g_key_file_set_list_separator (kf, ','); + if (!g_key_file_load_from_file (kf, path, G_KEY_FILE_NONE, error)) { + g_key_file_free (kf); + return FALSE; + } + + /* Override the current settings with the new ones */ + groups = g_key_file_get_groups (kf, &ngroups); + for (g = 0; groups[g]; g++) { + keys = g_key_file_get_keys (kf, groups[g], &nkeys, NULL); + if (!keys) + continue; + for (k = 0; keys[k]; k++) { + int len = strlen (keys[k]); + if (keys[k][len - 1] == '+') { + char *base_key = g_strndup (keys[k], len - 1); + const char *old_val = g_key_file_get_value (priv->keyfile, groups[g], base_key, NULL); + const char *new_val = g_key_file_get_value (kf, groups[g], keys[k], NULL); + + if (old_val && *old_val) { + char *combined = g_strconcat (old_val, ",", new_val, NULL); + + g_key_file_set_value (priv->keyfile, groups[g], base_key, combined); + g_free (combined); + } else + g_key_file_set_value (priv->keyfile, groups[g], base_key, new_val); + + g_free (base_key); + continue; + } + + g_key_file_set_value (priv->keyfile, groups[g], keys[k], + g_key_file_get_value (kf, groups[g], keys[k], NULL)); + } + } + g_key_file_free (kf); + + return TRUE; +} + +static gboolean +find_base_config (NMConfig *config, GError **error) +{ + NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (config); + GError *my_error = NULL; + + /* Try a user-specified config file first */ + if (cli_config_path) { + /* Bad user-specific config file path is a hard error */ + if (read_config (config, cli_config_path, error)) { + priv->nm_conf_path = g_strdup (cli_config_path); + return TRUE; + } else + return FALSE; + } + + /* Even though we prefer NetworkManager.conf, we need to check the + * old nm-system-settings.conf first to preserve compat with older + * setups. In package managed systems dropping a NetworkManager.conf + * onto the system would make NM use it instead of nm-system-settings.conf, + * changing behavior during an upgrade. We don't want that. + */ + + /* Try deprecated nm-system-settings.conf first */ + if (read_config (config, NM_OLD_SYSTEM_CONF_FILE, &my_error)) { + priv->nm_conf_path = g_strdup (NM_OLD_SYSTEM_CONF_FILE); + return TRUE; + } + + if (!g_error_matches (my_error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_NOT_FOUND)) { + g_warning ("Default config file %s invalid: %s\n", + NM_OLD_SYSTEM_CONF_FILE, + my_error->message); + } + g_clear_error (&my_error); + + /* Try the standard config file location next */ + if (read_config (config, NM_DEFAULT_SYSTEM_CONF_FILE, &my_error)) { + priv->nm_conf_path = g_strdup (NM_DEFAULT_SYSTEM_CONF_FILE); + return TRUE; + } + + if (!g_error_matches (my_error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_NOT_FOUND)) { + g_warning ("Default config file %s invalid: %s\n", + NM_DEFAULT_SYSTEM_CONF_FILE, + my_error->message); + g_propagate_error (error, my_error); + return FALSE; + } + + /* If for some reason no config file exists, use the default + * config file path. + */ + priv->nm_conf_path = g_strdup (NM_DEFAULT_SYSTEM_CONF_FILE); + g_warning ("No config file found or given; using %s\n", + NM_DEFAULT_SYSTEM_CONF_FILE); + return TRUE; +} + +/************************************************************************/ + +NMConfig * +nm_config_get (void) +{ + g_assert (singleton); + return singleton; +} + +static int +sort_asciibetically (gconstpointer a, gconstpointer b) +{ + const char *s1 = *(const char **)a; + const char *s2 = *(const char **)b; + + return strcmp (s1, s2); +} + +/* call this function only once! */ +NMConfig * +nm_config_new (GError **error) +{ + NMConfigPrivate *priv = NULL; + GFile *dir; + GFileEnumerator *direnum; + GFileInfo *info; + GPtrArray *confs; + const char *name; + char *value; + int i; + GString *config_description; + + g_assert (!singleton); + singleton = NM_CONFIG (g_object_new (NM_TYPE_CONFIG, NULL)); + priv = NM_CONFIG_GET_PRIVATE (singleton); + + /* First read the base config file */ + if (!find_base_config (singleton, error)) { + g_object_unref (singleton); + singleton = NULL; + return NULL; + } + + /* Now read the overrides in the config dir */ + if (cli_config_dir) + priv->config_dir = g_strdup (cli_config_dir); + else + priv->config_dir = g_strdup (NM_DEFAULT_SYSTEM_CONF_DIR); + + confs = g_ptr_array_new_with_free_func (g_free); + config_description = g_string_new (priv->nm_conf_path); + dir = g_file_new_for_path (priv->config_dir); + direnum = g_file_enumerate_children (dir, G_FILE_ATTRIBUTE_STANDARD_NAME, 0, NULL, NULL); + if (direnum) { + while ((info = g_file_enumerator_next_file (direnum, NULL, NULL))) { + name = g_file_info_get_name (info); + if (g_str_has_suffix (name, ".conf")) { + g_ptr_array_add (confs, g_build_filename (priv->config_dir, name, NULL)); + if (confs->len == 1) + g_string_append (config_description, " and conf.d: "); + else + g_string_append (config_description, ", "); + g_string_append (config_description, name); + } + g_object_unref (info); + } + g_object_unref (direnum); + } + g_object_unref (dir); + + g_ptr_array_sort (confs, sort_asciibetically); + priv->config_description = g_string_free (config_description, FALSE); + for (i = 0; i < confs->len; i++) { + if (!read_config (singleton, confs->pdata[i], error)) { + g_object_unref (singleton); + singleton = NULL; + break; + } + } + g_ptr_array_unref (confs); + if (!singleton) + return FALSE; + + /* Handle no-auto-default key and state file */ + priv->no_auto_default = g_key_file_get_string_list (priv->keyfile, "main", "no-auto-default", NULL, NULL); + if (cli_no_auto_default_file) + priv->no_auto_default_file = g_strdup (cli_no_auto_default_file); + else + priv->no_auto_default_file = g_strdup (NM_NO_AUTO_DEFAULT_STATE_FILE); + merge_no_auto_default_state (singleton); + + /* Now let command-line options override the config files, and fill in priv. */ + if (cli_plugins && cli_plugins[0]) + g_key_file_set_value (priv->keyfile, "main", "plugins", cli_plugins); + priv->plugins = g_key_file_get_string_list (priv->keyfile, "main", "plugins", NULL, NULL); + + value = g_key_file_get_value (priv->keyfile, "main", "monitor-connection-files", NULL); + if (value) { + if (!strcmp (value, "true") || !strcmp (value, "yes") || !strcmp (value, "on")) + priv->monitor_connection_files = TRUE; + else if (!strcmp (value, "false") || !strcmp (value, "no") || !strcmp (value, "off")) + priv->monitor_connection_files = FALSE; + else { + g_warning ("Unrecognized value for main.monitor-connection-files: %s. Assuming 'false'", value); + priv->monitor_connection_files = FALSE; + } + g_free (value); + } else + priv->monitor_connection_files = FALSE; + + priv->dhcp_client = g_key_file_get_value (priv->keyfile, "main", "dhcp", NULL); + priv->dns_mode = g_key_file_get_value (priv->keyfile, "main", "dns", NULL); + + priv->log_level = g_key_file_get_value (priv->keyfile, "logging", "level", NULL); + priv->log_domains = g_key_file_get_value (priv->keyfile, "logging", "domains", NULL); + + priv->debug = g_key_file_get_value (priv->keyfile, "main", "debug", NULL); + + if (cli_connectivity_uri && cli_connectivity_uri[0]) + g_key_file_set_value (priv->keyfile, "connectivity", "uri", cli_connectivity_uri); + priv->connectivity_uri = g_key_file_get_value (priv->keyfile, "connectivity", "uri", NULL); + + if (cli_connectivity_interval >= 0) + g_key_file_set_integer (priv->keyfile, "connectivity", "interval", cli_connectivity_interval); + priv->connectivity_interval = g_key_file_get_integer (priv->keyfile, "connectivity", "interval", NULL); + + if (cli_connectivity_response && cli_connectivity_response[0]) + g_key_file_set_value (priv->keyfile, "connectivity", "response", cli_connectivity_response); + priv->connectivity_response = g_key_file_get_value (priv->keyfile, "connectivity", "response", NULL); + + priv->ignore_carrier = g_key_file_get_string_list (priv->keyfile, "main", "ignore-carrier", NULL, NULL); + + return singleton; +} + +static void +nm_config_init (NMConfig *config) +{ + NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (config); + + priv->keyfile = g_key_file_new (); + g_key_file_set_list_separator (priv->keyfile, ','); + + priv->connectivity_interval = -1; +} + +static void +finalize (GObject *gobject) +{ + NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (gobject); + + g_free (priv->nm_conf_path); + g_free (priv->config_dir); + g_free (priv->config_description); + g_free (priv->no_auto_default_file); + g_clear_pointer (&priv->keyfile, g_key_file_unref); + g_strfreev (priv->plugins); + g_free (priv->dhcp_client); + g_free (priv->dns_mode); + g_free (priv->log_level); + g_free (priv->log_domains); + g_free (priv->debug); + g_free (priv->connectivity_uri); + g_free (priv->connectivity_response); + g_strfreev (priv->no_auto_default); + g_strfreev (priv->ignore_carrier); + + singleton = NULL; + + g_clear_pointer (&cli_config_path, g_free); + g_clear_pointer (&cli_config_dir, g_free); + g_clear_pointer (&cli_no_auto_default_file, g_free); + g_clear_pointer (&cli_plugins, g_free); + g_clear_pointer (&cli_connectivity_uri, g_free); + g_clear_pointer (&cli_connectivity_response, g_free); + + G_OBJECT_CLASS (nm_config_parent_class)->finalize (gobject); +} + + +static void +nm_config_class_init (NMConfigClass *config_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (config_class); + + g_type_class_add_private (config_class, sizeof (NMConfigPrivate)); + object_class->finalize = finalize; +} + diff --git a/src/config/nm-config.h b/src/config/nm-config.h new file mode 100644 index 00000000..2e335c71 --- /dev/null +++ b/src/config/nm-config.h @@ -0,0 +1,78 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2011 Red Hat, Inc. + * Copyright (C) 2013 Thomas Bechtold + */ + +#ifndef NM_CONFIG_H +#define NM_CONFIG_H + +#include +#include + +#include "nm-config-device.h" + +G_BEGIN_DECLS + +#define NM_TYPE_CONFIG (nm_config_get_type ()) +#define NM_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_CONFIG, NMConfig)) +#define NM_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_CONFIG, NMConfigClass)) +#define NM_IS_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_CONFIG)) +#define NM_IS_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_CONFIG)) +#define NM_CONFIG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_CONFIG, NMConfigClass)) + +typedef struct { + GObject parent; +} NMConfig; + +typedef struct { + GObjectClass parent; +} NMConfigClass; + +GType nm_config_get_type (void); + +NMConfig *nm_config_get (void); + +const char *nm_config_get_path (NMConfig *config); +const char *nm_config_get_description (NMConfig *config); +const char **nm_config_get_plugins (NMConfig *config); +gboolean nm_config_get_monitor_connection_files (NMConfig *config); +const char *nm_config_get_dhcp_client (NMConfig *config); +const char *nm_config_get_dns_mode (NMConfig *config); +const char *nm_config_get_log_level (NMConfig *config); +const char *nm_config_get_log_domains (NMConfig *config); +const char *nm_config_get_debug (NMConfig *config); +const char *nm_config_get_connectivity_uri (NMConfig *config); +const guint nm_config_get_connectivity_interval (NMConfig *config); +const char *nm_config_get_connectivity_response (NMConfig *config); + +gboolean nm_config_get_ethernet_can_auto_default (NMConfig *config, NMConfigDevice *device); +void nm_config_set_ethernet_no_auto_default (NMConfig *config, NMConfigDevice *device); + +gboolean nm_config_get_ignore_carrier (NMConfig *config, NMConfigDevice *device); + +char *nm_config_get_value (NMConfig *config, const char *group, const char *key, GError **error); + +/* for main.c only */ +GOptionEntry *nm_config_get_options (void); +NMConfig *nm_config_new (GError **error); + +G_END_DECLS + +#endif /* NM_CONFIG_H */ + diff --git a/src/config/tests/Makefile.am b/src/config/tests/Makefile.am new file mode 100644 index 00000000..6e64812b --- /dev/null +++ b/src/config/tests/Makefile.am @@ -0,0 +1,30 @@ +AM_CPPFLAGS = \ + -I$(top_srcdir)/include \ + -I$(top_builddir)/include \ + -I$(top_srcdir)/libnm-util \ + -I$(top_builddir)/libnm-util \ + -I$(top_srcdir)/src/config \ + -DG_LOG_DOMAIN=\""NetworkManager"\" \ + -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \ + $(GLIB_CFLAGS) \ + -DSRCDIR=\""$(srcdir)"\" + +noinst_PROGRAMS = \ + test-config + +test_config_SOURCES = \ + nm-test-device.c \ + nm-test-device.h \ + test-config.c + +test_config_LDADD = \ + $(top_builddir)/src/libNetworkManager.la + +TESTS = test-config + +EXTRA_DIST = \ + NetworkManager.conf \ + bad.conf \ + conf.d/00-overrides.conf \ + conf.d/10-more.conf \ + conf.d/90-last.conf diff --git a/src/config/tests/Makefile.in b/src/config/tests/Makefile.in new file mode 100644 index 00000000..4ac0ce15 --- /dev/null +++ b/src/config/tests/Makefile.in @@ -0,0 +1,864 @@ +# Makefile.in generated by automake 1.13.4 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +noinst_PROGRAMS = test-config$(EXEEXT) +TESTS = test-config$(EXEEXT) +subdir = src/config/tests +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(top_srcdir)/build-aux/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_lib_readline.m4 \ + $(top_srcdir)/m4/compiler_warnings.m4 \ + $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/gnome-code-coverage.m4 \ + $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ + $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \ + $(top_srcdir)/m4/introspection.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ + $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ + $(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +PROGRAMS = $(noinst_PROGRAMS) +am_test_config_OBJECTS = nm-test-device.$(OBJEXT) \ + test-config.$(OBJEXT) +test_config_OBJECTS = $(am_test_config_OBJECTS) +test_config_DEPENDENCIES = $(top_builddir)/src/libNetworkManager.la +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(test_config_SOURCES) +DIST_SOURCES = $(test_config_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__tty_colors_dummy = \ + mgn= red= grn= lgn= blu= brg= std=; \ + am__color_tests=no +am__tty_colors = { \ + $(am__tty_colors_dummy); \ + if test "X$(AM_COLOR_TESTS)" = Xno; then \ + am__color_tests=no; \ + elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ + am__color_tests=yes; \ + elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ + am__color_tests=yes; \ + fi; \ + if test $$am__color_tests = yes; then \ + red=''; \ + grn=''; \ + lgn=''; \ + blu=''; \ + mgn=''; \ + brg=''; \ + std=''; \ + fi; \ +} +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALL_LINGUAS = @ALL_LINGUAS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CKDB_PATH = @CKDB_PATH@ +CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@ +CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@ +CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIRNAME = @DATADIRNAME@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_100_CFLAGS = @DBUS_GLIB_100_CFLAGS@ +DBUS_GLIB_100_LIBS = @DBUS_GLIB_100_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DHCLIENT_PATH = @DHCLIENT_PATH@ +DHCPCD_PATH = @DHCPCD_PATH@ +DISTRO_NETWORK_SERVICE = @DISTRO_NETWORK_SERVICE@ +DLLTOOL = @DLLTOOL@ +DNSMASQ_PATH = @DNSMASQ_PATH@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GENHTML = @GENHTML@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MAKEFILE = @GLIB_MAKEFILE@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ +GNUTLS_LIBS = @GNUTLS_LIBS@ +GREP = @GREP@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GUDEV_CFLAGS = @GUDEV_CFLAGS@ +GUDEV_LIBS = @GUDEV_LIBS@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_PERL = @INTLTOOL_PERL@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ +INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ +INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ +INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +IPTABLES_PATH = @IPTABLES_PATH@ +IWMX_SDK_CFLAGS = @IWMX_SDK_CFLAGS@ +IWMX_SDK_LIBS = @IWMX_SDK_LIBS@ +KERNEL_FIRMWARE_DIR = @KERNEL_FIRMWARE_DIR@ +LCOV = @LCOV@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDL = @LIBDL@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBM = @LIBM@ +LIBNDP_CFLAGS = @LIBNDP_CFLAGS@ +LIBNDP_LIBS = @LIBNDP_LIBS@ +LIBNL_CFLAGS = @LIBNL_CFLAGS@ +LIBNL_LIBS = @LIBNL_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@ +LIBSOUP_LIBS = @LIBSOUP_LIBS@ +LIBTEAMDCTL_CFLAGS = @LIBTEAMDCTL_CFLAGS@ +LIBTEAMDCTL_LIBS = @LIBTEAMDCTL_LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MM_GLIB_CFLAGS = @MM_GLIB_CFLAGS@ +MM_GLIB_LIBS = @MM_GLIB_LIBS@ +MOC = @MOC@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NEWT_CFLAGS = @NEWT_CFLAGS@ +NEWT_LIBS = @NEWT_LIBS@ +NM = @NM@ +NMEDIT = @NMEDIT@ +NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ +NM_MICRO_VERSION = @NM_MICRO_VERSION@ +NM_MINOR_VERSION = @NM_MINOR_VERSION@ +NM_MODIFY_SYSTEM_POLICY = @NM_MODIFY_SYSTEM_POLICY@ +NM_VERSION = @NM_VERSION@ +NSS_CFLAGS = @NSS_CFLAGS@ +NSS_LIBS = @NSS_LIBS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +POLKIT_CFLAGS = @POLKIT_CFLAGS@ +POLKIT_LIBS = @POLKIT_LIBS@ +POSUB = @POSUB@ +PPPD_PATH = @PPPD_PATH@ +PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@ +PPPOE_PATH = @PPPOE_PATH@ +QT_CFLAGS = @QT_CFLAGS@ +QT_LIBS = @QT_LIBS@ +RANLIB = @RANLIB@ +READLINE_LIBS = @READLINE_LIBS@ +SED = @SED@ +SELINUX_CFLAGS = @SELINUX_CFLAGS@ +SELINUX_LIBS = @SELINUX_LIBS@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SYSTEMD_200_CFLAGS = @SYSTEMD_200_CFLAGS@ +SYSTEMD_200_LIBS = @SYSTEMD_200_LIBS@ +SYSTEMD_INHIBIT_CFLAGS = @SYSTEMD_INHIBIT_CFLAGS@ +SYSTEMD_INHIBIT_LIBS = @SYSTEMD_INHIBIT_LIBS@ +SYSTEMD_LOGIN_CFLAGS = @SYSTEMD_LOGIN_CFLAGS@ +SYSTEMD_LOGIN_LIBS = @SYSTEMD_LOGIN_LIBS@ +SYSTEM_CA_PATH = @SYSTEM_CA_PATH@ +UDEV_BASE_DIR = @UDEV_BASE_DIR@ +USE_NLS = @USE_NLS@ +UUID_CFLAGS = @UUID_CFLAGS@ +UUID_LIBS = @UUID_LIBS@ +VALGRIND_RULES = @VALGRIND_RULES@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ +VERSION = @VERSION@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +intltool__v_merge_options_ = @intltool__v_merge_options_@ +intltool__v_merge_options_0 = @intltool__v_merge_options_0@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +nmbinary = @nmbinary@ +nmconfdir = @nmconfdir@ +nmdatadir = @nmdatadir@ +nmrundir = @nmrundir@ +nmstatedir = @nmstatedir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +with_dhclient = @with_dhclient@ +with_dhcpcd = @with_dhcpcd@ +with_netconfig = @with_netconfig@ +with_resolvconf = @with_resolvconf@ +with_valgrind = @with_valgrind@ +AM_CPPFLAGS = \ + -I$(top_srcdir)/include \ + -I$(top_builddir)/include \ + -I$(top_srcdir)/libnm-util \ + -I$(top_builddir)/libnm-util \ + -I$(top_srcdir)/src/config \ + -DG_LOG_DOMAIN=\""NetworkManager"\" \ + -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \ + $(GLIB_CFLAGS) \ + -DSRCDIR=\""$(srcdir)"\" + +test_config_SOURCES = \ + nm-test-device.c \ + nm-test-device.h \ + test-config.c + +test_config_LDADD = \ + $(top_builddir)/src/libNetworkManager.la + +EXTRA_DIST = \ + NetworkManager.conf \ + bad.conf \ + conf.d/00-overrides.conf \ + conf.d/10-more.conf \ + conf.d/90-last.conf + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/config/tests/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/config/tests/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +test-config$(EXEEXT): $(test_config_OBJECTS) $(test_config_DEPENDENCIES) $(EXTRA_test_config_DEPENDENCIES) + @rm -f test-config$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_config_OBJECTS) $(test_config_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-test-device.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-config.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +check-TESTS: $(TESTS) + @failed=0; all=0; xfail=0; xpass=0; skip=0; \ + srcdir=$(srcdir); export srcdir; \ + list=' $(TESTS) '; \ + $(am__tty_colors); \ + if test -n "$$list"; then \ + for tst in $$list; do \ + if test -f ./$$tst; then dir=./; \ + elif test -f $$tst; then dir=; \ + else dir="$(srcdir)/"; fi; \ + if $(TESTS_ENVIRONMENT) $${dir}$$tst $(AM_TESTS_FD_REDIRECT); then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$tst[\ \ ]*) \ + xpass=`expr $$xpass + 1`; \ + failed=`expr $$failed + 1`; \ + col=$$red; res=XPASS; \ + ;; \ + *) \ + col=$$grn; res=PASS; \ + ;; \ + esac; \ + elif test $$? -ne 77; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$tst[\ \ ]*) \ + xfail=`expr $$xfail + 1`; \ + col=$$lgn; res=XFAIL; \ + ;; \ + *) \ + failed=`expr $$failed + 1`; \ + col=$$red; res=FAIL; \ + ;; \ + esac; \ + else \ + skip=`expr $$skip + 1`; \ + col=$$blu; res=SKIP; \ + fi; \ + echo "$${col}$$res$${std}: $$tst"; \ + done; \ + if test "$$all" -eq 1; then \ + tests="test"; \ + All=""; \ + else \ + tests="tests"; \ + All="All "; \ + fi; \ + if test "$$failed" -eq 0; then \ + if test "$$xfail" -eq 0; then \ + banner="$$All$$all $$tests passed"; \ + else \ + if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \ + banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \ + fi; \ + else \ + if test "$$xpass" -eq 0; then \ + banner="$$failed of $$all $$tests failed"; \ + else \ + if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \ + banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \ + fi; \ + fi; \ + dashes="$$banner"; \ + skipped=""; \ + if test "$$skip" -ne 0; then \ + if test "$$skip" -eq 1; then \ + skipped="($$skip test was not run)"; \ + else \ + skipped="($$skip tests were not run)"; \ + fi; \ + test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$skipped"; \ + fi; \ + report=""; \ + if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ + report="Please report to $(PACKAGE_BUGREPORT)"; \ + test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$report"; \ + fi; \ + dashes=`echo "$$dashes" | sed s/./=/g`; \ + if test "$$failed" -eq 0; then \ + col="$$grn"; \ + else \ + col="$$red"; \ + fi; \ + echo "$${col}$$dashes$${std}"; \ + echo "$${col}$$banner$${std}"; \ + test -z "$$skipped" || echo "$${col}$$skipped$${std}"; \ + test -z "$$report" || echo "$${col}$$report$${std}"; \ + echo "$${col}$$dashes$${std}"; \ + test "$$failed" -eq 0; \ + else :; fi + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: check-am install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ + clean-generic clean-libtool clean-noinstPROGRAMS cscopelist-am \ + ctags ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/config/tests/NetworkManager.conf b/src/config/tests/NetworkManager.conf new file mode 100644 index 00000000..401ba48a --- /dev/null +++ b/src/config/tests/NetworkManager.conf @@ -0,0 +1,15 @@ +[main] +dhcp=dhclient +plugins=foo,bar,baz +no-auto-default=11:11:11:11:11:11 + +[logging] +level=INFO + +[connectivity] +uri=http://example.com +interval=100 +response=Hello + +[extra-section] +extra-key=some value diff --git a/src/config/tests/bad.conf b/src/config/tests/bad.conf new file mode 100644 index 00000000..20d6a67a --- /dev/null +++ b/src/config/tests/bad.conf @@ -0,0 +1 @@ +This is not a keyfile. diff --git a/src/config/tests/conf.d/00-overrides.conf b/src/config/tests/conf.d/00-overrides.conf new file mode 100644 index 00000000..0aa19d48 --- /dev/null +++ b/src/config/tests/conf.d/00-overrides.conf @@ -0,0 +1,11 @@ +[main] +dhcp=dhcpcd + +[logging] +domains=PLATFORM,DNS,WIFI + +[order] +a=0 +b=0 +c=0 + diff --git a/src/config/tests/conf.d/10-more.conf b/src/config/tests/conf.d/10-more.conf new file mode 100644 index 00000000..b1424a4b --- /dev/null +++ b/src/config/tests/conf.d/10-more.conf @@ -0,0 +1,11 @@ +[main] +extra=hello +new+=something + +[connectivity] +uri=http://example.net + +[order] +a=10 +b=10 + diff --git a/src/config/tests/conf.d/90-last.conf b/src/config/tests/conf.d/90-last.conf new file mode 100644 index 00000000..dc1de394 --- /dev/null +++ b/src/config/tests/conf.d/90-last.conf @@ -0,0 +1,5 @@ +[main] +plugins+=one,two + +[order] +a=90 diff --git a/src/config/tests/nm-test-device.c b/src/config/tests/nm-test-device.c new file mode 100644 index 00000000..b671f255 --- /dev/null +++ b/src/config/tests/nm-test-device.c @@ -0,0 +1,101 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright 2013 Red Hat, Inc. + */ + +#include "config.h" + +#include +#include + +#include "nm-test-device.h" +#include "nm-config-device.h" +#include "nm-utils.h" + +static void nm_test_device_config_device_interface_init (NMConfigDeviceInterface *iface); + +G_DEFINE_TYPE_WITH_CODE (NMTestDevice, nm_test_device, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (NM_TYPE_CONFIG_DEVICE, nm_test_device_config_device_interface_init)) + +static void +nm_test_device_init (NMTestDevice *self) +{ +} + +static void +finalize (GObject *object) +{ + NMTestDevice *self = NM_TEST_DEVICE (object); + + g_free (self->hwaddr); + g_free (self->hwaddr_bytes); + + G_OBJECT_CLASS (nm_test_device_parent_class)->finalize (object); +} + +static void +nm_test_device_class_init (NMTestDeviceClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = finalize; +} + +static gboolean +spec_match_list (NMConfigDevice *device, const GSList *specs) +{ + NMTestDevice *self = NM_TEST_DEVICE (device); + const GSList *iter; + const char *spec; + + for (iter = specs; iter; iter = iter->next) { + spec = iter->data; + if (g_str_has_prefix (spec, "mac:") && !strcmp (spec + 4, self->hwaddr)) + return TRUE; + } + return FALSE; +} + +static const guint8 * +get_hw_address (NMConfigDevice *device, guint *out_len) +{ + NMTestDevice *self = NM_TEST_DEVICE (device); + + if (out_len) + *out_len = ETH_ALEN; + return self->hwaddr_bytes; +} + +static void +nm_test_device_config_device_interface_init (NMConfigDeviceInterface *iface) +{ + iface->spec_match_list = spec_match_list; + iface->get_hw_address = get_hw_address; +} + +NMTestDevice * +nm_test_device_new (const char *hwaddr) +{ + NMTestDevice *self = g_object_new (NM_TYPE_TEST_DEVICE, NULL); + + self->hwaddr = g_strdup (hwaddr); + self->hwaddr_bytes = g_malloc (ETH_ALEN); + nm_utils_hwaddr_aton (hwaddr, ARPHRD_ETHER, self->hwaddr_bytes); + + return self; +} diff --git a/src/config/tests/nm-test-device.h b/src/config/tests/nm-test-device.h new file mode 100644 index 00000000..ad63bf5f --- /dev/null +++ b/src/config/tests/nm-test-device.h @@ -0,0 +1,52 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright 2013 Red Hat, Inc. + */ + +#ifndef NM_TEST_DEVICE_H +#define NM_TEST_DEVICE_H + +#include + +G_BEGIN_DECLS + +#define NM_TYPE_TEST_DEVICE (nm_test_device_get_type ()) +#define NM_TEST_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_TEST_DEVICE, NMTestDevice)) +#define NM_TEST_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_TEST_DEVICE, NMTestDeviceClass)) +#define NM_IS_TEST_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_TEST_DEVICE)) +#define NM_IS_TEST_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_TEST_DEVICE)) +#define NM_TEST_DEVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_TEST_DEVICE, NMTestDeviceClass)) + +typedef struct { + GObject parent; + + char *hwaddr; + guint8 *hwaddr_bytes; +} NMTestDevice; + +typedef struct { + GObjectClass parent; +} NMTestDeviceClass; + +GType nm_test_device_get_type (void); + +NMTestDevice *nm_test_device_new (const char *hwaddr); + +G_END_DECLS + +#endif /* NM_DEVICE_H */ diff --git a/src/config/tests/test-config.c b/src/config/tests/test-config.c new file mode 100644 index 00000000..fb6baacc --- /dev/null +++ b/src/config/tests/test-config.c @@ -0,0 +1,305 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright 2013 Red Hat, Inc. + * + */ + +#include "config.h" + +#include + +#include + +#include +#include "nm-test-device.h" + +static void +setup_config (const char *config_file, const char *config_dir, ...) +{ + va_list ap; + GPtrArray *args; + char **argv, *arg; + int argc; + GOptionContext *context; + gboolean success; + + args = g_ptr_array_new (); + g_ptr_array_add (args, "test-config"); + g_ptr_array_add (args, "--config"); + g_ptr_array_add (args, (char *)config_file); + g_ptr_array_add (args, "--config-dir"); + g_ptr_array_add (args, (char *)config_dir); + + va_start (ap, config_dir); + while ((arg = va_arg (ap, char *))) + g_ptr_array_add (args, arg); + va_end (ap); + + argv = (char **)args->pdata; + argc = args->len; + + context = g_option_context_new (NULL); + g_option_context_add_main_entries (context, nm_config_get_options (), NULL); + success = g_option_context_parse (context, &argc, &argv, NULL); + g_option_context_free (context); + + if (!success) + g_printerr ("Invalid options.\n"); + + g_ptr_array_free (args, TRUE); +} + +static void +test_config_simple (void) +{ + NMConfig *config; + GError *error = NULL; + const char **plugins; + char *value; + + setup_config (SRCDIR "/NetworkManager.conf", "/no/such/dir", NULL); + config = nm_config_new (&error); + g_assert_no_error (error); + + g_assert_cmpstr (nm_config_get_path (config), ==, SRCDIR "/NetworkManager.conf"); + g_assert_cmpstr (nm_config_get_dhcp_client (config), ==, "dhclient"); + g_assert_cmpstr (nm_config_get_log_level (config), ==, "INFO"); + g_assert_cmpint (nm_config_get_connectivity_interval (config), ==, 100); + + plugins = nm_config_get_plugins (config); + g_assert_cmpint (g_strv_length ((char **)plugins), ==, 3); + g_assert_cmpstr (plugins[0], ==, "foo"); + g_assert_cmpstr (plugins[1], ==, "bar"); + g_assert_cmpstr (plugins[2], ==, "baz"); + + value = nm_config_get_value (config, "extra-section", "extra-key", NULL); + g_assert_cmpstr (value, ==, "some value"); + g_free (value); + + value = nm_config_get_value (config, "extra-section", "no-key", &error); + g_assert (!value); + g_assert_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND); + g_clear_error (&error); + + value = nm_config_get_value (config, "no-section", "no-key", &error); + g_assert (!value); + g_assert_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND); + g_clear_error (&error); + + g_object_unref (config); +} + +static void +test_config_non_existent (void) +{ + NMConfig *config; + GError *error = NULL; + + setup_config (SRCDIR "/no-such-file", "/no/such/dir", NULL); + config = nm_config_new (&error); + g_assert (!config); + g_assert_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_NOT_FOUND); +} + +static void +test_config_parse_error (void) +{ + NMConfig *config; + GError *error = NULL; + + setup_config (SRCDIR "/bad.conf", "/no/such/dir", NULL); + config = nm_config_new (&error); + g_assert (!config); + g_assert_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_PARSE); +} + +static void +test_config_override (void) +{ + NMConfig *config; + GError *error = NULL; + const char **plugins; + + setup_config (SRCDIR "/NetworkManager.conf", "/no/such/dir", + "--plugins", "alpha,beta,gamma,delta", + "--connectivity-interval", "12", + NULL); + config = nm_config_new (&error); + g_assert_no_error (error); + + g_assert_cmpstr (nm_config_get_path (config), ==, SRCDIR "/NetworkManager.conf"); + g_assert_cmpstr (nm_config_get_dhcp_client (config), ==, "dhclient"); + g_assert_cmpstr (nm_config_get_log_level (config), ==, "INFO"); + g_assert_cmpint (nm_config_get_connectivity_interval (config), ==, 12); + + plugins = nm_config_get_plugins (config); + g_assert_cmpint (g_strv_length ((char **)plugins), ==, 4); + g_assert_cmpstr (plugins[0], ==, "alpha"); + g_assert_cmpstr (plugins[1], ==, "beta"); + g_assert_cmpstr (plugins[2], ==, "gamma"); + g_assert_cmpstr (plugins[3], ==, "delta"); + + g_object_unref (config); +} + +static void +test_config_no_auto_default (void) +{ + NMConfig *config; + GError *error = NULL; + int fd, nwrote; + char *state_file; + NMTestDevice *dev1, *dev2, *dev3, *dev4; + + fd = g_file_open_tmp (NULL, &state_file, &error); + g_assert_no_error (error); + + nwrote = write (fd, "22:22:22:22:22:22\n", 18); + g_assert_cmpint (nwrote, ==, 18); + nwrote = write (fd, "44:44:44:44:44:44\n", 18); + g_assert_cmpint (nwrote, ==, 18); + close (fd); + + setup_config (SRCDIR "/NetworkManager.conf", "/no/such/dir", + "--no-auto-default", state_file, + NULL); + config = nm_config_new (&error); + g_assert_no_error (error); + + dev1 = nm_test_device_new ("11:11:11:11:11:11"); + dev2 = nm_test_device_new ("22:22:22:22:22:22"); + dev3 = nm_test_device_new ("33:33:33:33:33:33"); + dev4 = nm_test_device_new ("44:44:44:44:44:44"); + + g_assert (!nm_config_get_ethernet_can_auto_default (config, NM_CONFIG_DEVICE (dev1))); + g_assert (!nm_config_get_ethernet_can_auto_default (config, NM_CONFIG_DEVICE (dev2))); + g_assert (nm_config_get_ethernet_can_auto_default (config, NM_CONFIG_DEVICE (dev3))); + g_assert (!nm_config_get_ethernet_can_auto_default (config, NM_CONFIG_DEVICE (dev4))); + + nm_config_set_ethernet_no_auto_default (config, NM_CONFIG_DEVICE (dev3)); + g_assert (!nm_config_get_ethernet_can_auto_default (config, NM_CONFIG_DEVICE (dev3))); + + g_object_unref (config); + + setup_config (SRCDIR "/NetworkManager.conf", "/no/such/dir", + "--no-auto-default", state_file, + NULL); + config = nm_config_new (&error); + g_assert_no_error (error); + + g_assert (!nm_config_get_ethernet_can_auto_default (config, NM_CONFIG_DEVICE (dev1))); + g_assert (!nm_config_get_ethernet_can_auto_default (config, NM_CONFIG_DEVICE (dev2))); + g_assert (!nm_config_get_ethernet_can_auto_default (config, NM_CONFIG_DEVICE (dev3))); + g_assert (!nm_config_get_ethernet_can_auto_default (config, NM_CONFIG_DEVICE (dev4))); + + g_object_unref (config); + + g_object_unref (dev1); + g_object_unref (dev2); + g_object_unref (dev3); + g_object_unref (dev4); + + unlink (state_file); + g_free (state_file); +} + +static void +test_config_confdir (void) +{ + NMConfig *config; + GError *error = NULL; + const char **plugins; + char *value; + + setup_config (SRCDIR "/NetworkManager.conf", SRCDIR "/conf.d", NULL); + config = nm_config_new (&error); + g_assert_no_error (error); + + g_assert_cmpstr (nm_config_get_path (config), ==, SRCDIR "/NetworkManager.conf"); + g_assert_cmpstr (nm_config_get_dhcp_client (config), ==, "dhcpcd"); + g_assert_cmpstr (nm_config_get_log_level (config), ==, "INFO"); + g_assert_cmpstr (nm_config_get_log_domains (config), ==, "PLATFORM,DNS,WIFI"); + g_assert_cmpstr (nm_config_get_connectivity_uri (config), ==, "http://example.net"); + g_assert_cmpint (nm_config_get_connectivity_interval (config), ==, 100); + + plugins = nm_config_get_plugins (config); + g_assert_cmpint (g_strv_length ((char **)plugins), ==, 5); + g_assert_cmpstr (plugins[0], ==, "foo"); + g_assert_cmpstr (plugins[1], ==, "bar"); + g_assert_cmpstr (plugins[2], ==, "baz"); + g_assert_cmpstr (plugins[3], ==, "one"); + g_assert_cmpstr (plugins[4], ==, "two"); + + value = nm_config_get_value (config, "main", "extra", NULL); + g_assert_cmpstr (value, ==, "hello"); + g_free (value); + + value = nm_config_get_value (config, "main", "new", NULL); + g_assert_cmpstr (value, ==, "something"); /* not ",something" */ + g_free (value); + + value = nm_config_get_value (config, "order", "a", NULL); + g_assert_cmpstr (value, ==, "90"); + g_free (value); + value = nm_config_get_value (config, "order", "b", NULL); + g_assert_cmpstr (value, ==, "10"); + g_free (value); + value = nm_config_get_value (config, "order", "c", NULL); + g_assert_cmpstr (value, ==, "0"); + g_free (value); + + g_object_unref (config); +} + +static void +test_config_confdir_parse_error (void) +{ + NMConfig *config; + GError *error = NULL; + + /* Using SRCDIR as the conf dir will pick up bad.conf */ + setup_config (SRCDIR "/NetworkManager.conf", SRCDIR, NULL); + config = nm_config_new (&error); + g_assert (!config); + g_assert_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_PARSE); +} + +int +main (int argc, char **argv) +{ +#if !GLIB_CHECK_VERSION (2, 35, 0) + g_type_init (); +#endif + + g_test_init (&argc, &argv, NULL); + + g_test_add_func ("/config/simple", test_config_simple); + g_test_add_func ("/config/non-existent", test_config_non_existent); + g_test_add_func ("/config/parse-error", test_config_parse_error); + g_test_add_func ("/config/no-auto-default", test_config_no_auto_default); + g_test_add_func ("/config/confdir", test_config_confdir); + g_test_add_func ("/config/confdir-parse-error", test_config_confdir_parse_error); + + /* This one has to come last, because it leaves its values in + * nm-config.c's global variables, and there's no way to reset + * those to NULL. + */ + g_test_add_func ("/config/override", test_config_override); + + return g_test_run (); +} + diff --git a/src/devices/adsl/Makefile.am b/src/devices/adsl/Makefile.am new file mode 100644 index 00000000..0430f47d --- /dev/null +++ b/src/devices/adsl/Makefile.am @@ -0,0 +1,63 @@ +include $(GLIB_MAKEFILE) + +@GNOME_CODE_COVERAGE_RULES@ + +AM_CPPFLAGS = \ + -I${top_srcdir}/src \ + -I${top_builddir}/src \ + -I${top_srcdir}/src/logging \ + -I${top_srcdir}/src/devices \ + -I${top_srcdir}/src/settings \ + -I${top_srcdir}/src/platform \ + -I${top_srcdir}/src/ppp-manager \ + -I${top_builddir}/include \ + -I${top_srcdir}/include \ + -I${top_builddir}/libnm-util \ + -I${top_srcdir}/libnm-util \ + -DG_LOG_DOMAIN=\""NetworkManager-adsl"\" \ + -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \ + $(DBUS_CFLAGS) \ + $(POLKIT_CFLAGS) \ + $(LIBNL_CFLAGS) \ + $(GUDEV_CFLAGS) + +GLIB_GENERATED = nm-adsl-enum-types.h nm-adsl-enum-types.c +GLIB_MKENUMS_H_FLAGS = --identifier-prefix NM +GLIB_MKENUMS_C_FLAGS = --identifier-prefix NM +nm_adsl_enum_types_sources = $(srcdir)/nm-device-adsl.h + +nm-device-adsl-glue.h: $(top_srcdir)/introspection/nm-device-adsl.xml + dbus-binding-tool --prefix=nm_device_adsl --mode=glib-server --output=$@ $< + +BUILT_SOURCES = $(GLIB_GENERATED) nm-device-adsl-glue.h + +pkglib_LTLIBRARIES = libnm-device-plugin-adsl.la + +SYMBOL_VIS_FILE=$(srcdir)/exports.ver + +libnm_device_plugin_adsl_la_SOURCES = \ + nm-atm-manager.c \ + nm-atm-manager.h \ + nm-device-adsl.c \ + nm-device-adsl.h \ + \ + $(BUILT_SOURCES) + +libnm_device_plugin_adsl_la_LDFLAGS = \ + -module -avoid-version \ + -Wl,--version-script=$(SYMBOL_VIS_FILE) + +libnm_device_plugin_adsl_la_LIBADD = \ + $(DBUS_LIBS) \ + $(GUDEV_LIBS) + +CLEANFILES = $(BUILT_SOURCES) +EXTRA_DIST = $(SYMBOL_VIS_FILE) + +if ENABLE_TESTS + +check-local: + $(top_srcdir)/tools/check-exports.sh $(builddir)/.libs/libnm-device-plugin-adsl.so $(SYMBOL_VIS_FILE) + +endif + diff --git a/src/devices/adsl/Makefile.in b/src/devices/adsl/Makefile.in new file mode 100644 index 00000000..708a45d2 --- /dev/null +++ b/src/devices/adsl/Makefile.in @@ -0,0 +1,847 @@ +# Makefile.in generated by automake 1.13.4 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/devices/adsl +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(top_srcdir)/build-aux/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_lib_readline.m4 \ + $(top_srcdir)/m4/compiler_warnings.m4 \ + $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/gnome-code-coverage.m4 \ + $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ + $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \ + $(top_srcdir)/m4/introspection.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ + $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ + $(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(pkglibdir)" +LTLIBRARIES = $(pkglib_LTLIBRARIES) +am__DEPENDENCIES_1 = +libnm_device_plugin_adsl_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +am__objects_1 = nm-adsl-enum-types.lo +am__objects_2 = $(am__objects_1) +am_libnm_device_plugin_adsl_la_OBJECTS = nm-atm-manager.lo \ + nm-device-adsl.lo $(am__objects_2) +libnm_device_plugin_adsl_la_OBJECTS = \ + $(am_libnm_device_plugin_adsl_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libnm_device_plugin_adsl_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(libnm_device_plugin_adsl_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libnm_device_plugin_adsl_la_SOURCES) +DIST_SOURCES = $(libnm_device_plugin_adsl_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALL_LINGUAS = @ALL_LINGUAS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CKDB_PATH = @CKDB_PATH@ +CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@ +CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@ +CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIRNAME = @DATADIRNAME@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_100_CFLAGS = @DBUS_GLIB_100_CFLAGS@ +DBUS_GLIB_100_LIBS = @DBUS_GLIB_100_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DHCLIENT_PATH = @DHCLIENT_PATH@ +DHCPCD_PATH = @DHCPCD_PATH@ +DISTRO_NETWORK_SERVICE = @DISTRO_NETWORK_SERVICE@ +DLLTOOL = @DLLTOOL@ +DNSMASQ_PATH = @DNSMASQ_PATH@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GENHTML = @GENHTML@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MAKEFILE = @GLIB_MAKEFILE@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ +GNUTLS_LIBS = @GNUTLS_LIBS@ +GREP = @GREP@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GUDEV_CFLAGS = @GUDEV_CFLAGS@ +GUDEV_LIBS = @GUDEV_LIBS@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_PERL = @INTLTOOL_PERL@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ +INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ +INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ +INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +IPTABLES_PATH = @IPTABLES_PATH@ +IWMX_SDK_CFLAGS = @IWMX_SDK_CFLAGS@ +IWMX_SDK_LIBS = @IWMX_SDK_LIBS@ +KERNEL_FIRMWARE_DIR = @KERNEL_FIRMWARE_DIR@ +LCOV = @LCOV@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDL = @LIBDL@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBM = @LIBM@ +LIBNDP_CFLAGS = @LIBNDP_CFLAGS@ +LIBNDP_LIBS = @LIBNDP_LIBS@ +LIBNL_CFLAGS = @LIBNL_CFLAGS@ +LIBNL_LIBS = @LIBNL_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@ +LIBSOUP_LIBS = @LIBSOUP_LIBS@ +LIBTEAMDCTL_CFLAGS = @LIBTEAMDCTL_CFLAGS@ +LIBTEAMDCTL_LIBS = @LIBTEAMDCTL_LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MM_GLIB_CFLAGS = @MM_GLIB_CFLAGS@ +MM_GLIB_LIBS = @MM_GLIB_LIBS@ +MOC = @MOC@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NEWT_CFLAGS = @NEWT_CFLAGS@ +NEWT_LIBS = @NEWT_LIBS@ +NM = @NM@ +NMEDIT = @NMEDIT@ +NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ +NM_MICRO_VERSION = @NM_MICRO_VERSION@ +NM_MINOR_VERSION = @NM_MINOR_VERSION@ +NM_MODIFY_SYSTEM_POLICY = @NM_MODIFY_SYSTEM_POLICY@ +NM_VERSION = @NM_VERSION@ +NSS_CFLAGS = @NSS_CFLAGS@ +NSS_LIBS = @NSS_LIBS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +POLKIT_CFLAGS = @POLKIT_CFLAGS@ +POLKIT_LIBS = @POLKIT_LIBS@ +POSUB = @POSUB@ +PPPD_PATH = @PPPD_PATH@ +PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@ +PPPOE_PATH = @PPPOE_PATH@ +QT_CFLAGS = @QT_CFLAGS@ +QT_LIBS = @QT_LIBS@ +RANLIB = @RANLIB@ +READLINE_LIBS = @READLINE_LIBS@ +SED = @SED@ +SELINUX_CFLAGS = @SELINUX_CFLAGS@ +SELINUX_LIBS = @SELINUX_LIBS@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SYSTEMD_200_CFLAGS = @SYSTEMD_200_CFLAGS@ +SYSTEMD_200_LIBS = @SYSTEMD_200_LIBS@ +SYSTEMD_INHIBIT_CFLAGS = @SYSTEMD_INHIBIT_CFLAGS@ +SYSTEMD_INHIBIT_LIBS = @SYSTEMD_INHIBIT_LIBS@ +SYSTEMD_LOGIN_CFLAGS = @SYSTEMD_LOGIN_CFLAGS@ +SYSTEMD_LOGIN_LIBS = @SYSTEMD_LOGIN_LIBS@ +SYSTEM_CA_PATH = @SYSTEM_CA_PATH@ +UDEV_BASE_DIR = @UDEV_BASE_DIR@ +USE_NLS = @USE_NLS@ +UUID_CFLAGS = @UUID_CFLAGS@ +UUID_LIBS = @UUID_LIBS@ +VALGRIND_RULES = @VALGRIND_RULES@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ +VERSION = @VERSION@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +intltool__v_merge_options_ = @intltool__v_merge_options_@ +intltool__v_merge_options_0 = @intltool__v_merge_options_0@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +nmbinary = @nmbinary@ +nmconfdir = @nmconfdir@ +nmdatadir = @nmdatadir@ +nmrundir = @nmrundir@ +nmstatedir = @nmstatedir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +with_dhclient = @with_dhclient@ +with_dhcpcd = @with_dhcpcd@ +with_netconfig = @with_netconfig@ +with_resolvconf = @with_resolvconf@ +with_valgrind = @with_valgrind@ +AM_CPPFLAGS = \ + -I${top_srcdir}/src \ + -I${top_builddir}/src \ + -I${top_srcdir}/src/logging \ + -I${top_srcdir}/src/devices \ + -I${top_srcdir}/src/settings \ + -I${top_srcdir}/src/platform \ + -I${top_srcdir}/src/ppp-manager \ + -I${top_builddir}/include \ + -I${top_srcdir}/include \ + -I${top_builddir}/libnm-util \ + -I${top_srcdir}/libnm-util \ + -DG_LOG_DOMAIN=\""NetworkManager-adsl"\" \ + -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \ + $(DBUS_CFLAGS) \ + $(POLKIT_CFLAGS) \ + $(LIBNL_CFLAGS) \ + $(GUDEV_CFLAGS) + +GLIB_GENERATED = nm-adsl-enum-types.h nm-adsl-enum-types.c +GLIB_MKENUMS_H_FLAGS = --identifier-prefix NM +GLIB_MKENUMS_C_FLAGS = --identifier-prefix NM +nm_adsl_enum_types_sources = $(srcdir)/nm-device-adsl.h +BUILT_SOURCES = $(GLIB_GENERATED) nm-device-adsl-glue.h +pkglib_LTLIBRARIES = libnm-device-plugin-adsl.la +SYMBOL_VIS_FILE = $(srcdir)/exports.ver +libnm_device_plugin_adsl_la_SOURCES = \ + nm-atm-manager.c \ + nm-atm-manager.h \ + nm-device-adsl.c \ + nm-device-adsl.h \ + \ + $(BUILT_SOURCES) + +libnm_device_plugin_adsl_la_LDFLAGS = \ + -module -avoid-version \ + -Wl,--version-script=$(SYMBOL_VIS_FILE) + +libnm_device_plugin_adsl_la_LIBADD = \ + $(DBUS_LIBS) \ + $(GUDEV_LIBS) + +CLEANFILES = $(BUILT_SOURCES) +EXTRA_DIST = $(SYMBOL_VIS_FILE) +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/devices/adsl/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/devices/adsl/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +install-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkglibdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ + } + +uninstall-pkglibLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ + done + +clean-pkglibLTLIBRARIES: + -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) + @list='$(pkglib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libnm-device-plugin-adsl.la: $(libnm_device_plugin_adsl_la_OBJECTS) $(libnm_device_plugin_adsl_la_DEPENDENCIES) $(EXTRA_libnm_device_plugin_adsl_la_DEPENDENCIES) + $(AM_V_CCLD)$(libnm_device_plugin_adsl_la_LINK) -rpath $(pkglibdir) $(libnm_device_plugin_adsl_la_OBJECTS) $(libnm_device_plugin_adsl_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-adsl-enum-types.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-atm-manager.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-device-adsl.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +@ENABLE_TESTS_FALSE@check-local: +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) check-local +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(pkglibdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-am + +clean-am: clean-generic clean-libtool clean-pkglibLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-pkglibLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pkglibLTLIBRARIES + +.MAKE: all check check-am install install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am check-local clean \ + clean-generic clean-libtool clean-pkglibLTLIBRARIES \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-pkglibLTLIBRARIES install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am uninstall-pkglibLTLIBRARIES + +include $(GLIB_MAKEFILE) + +@GNOME_CODE_COVERAGE_RULES@ + +nm-device-adsl-glue.h: $(top_srcdir)/introspection/nm-device-adsl.xml + dbus-binding-tool --prefix=nm_device_adsl --mode=glib-server --output=$@ $< + +@ENABLE_TESTS_TRUE@check-local: +@ENABLE_TESTS_TRUE@ $(top_srcdir)/tools/check-exports.sh $(builddir)/.libs/libnm-device-plugin-adsl.so $(SYMBOL_VIS_FILE) + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/devices/adsl/exports.ver b/src/devices/adsl/exports.ver new file mode 100644 index 00000000..d2c45124 --- /dev/null +++ b/src/devices/adsl/exports.ver @@ -0,0 +1,7 @@ +{ +global: + nm_device_factory_create; + nm_device_factory_get_device_type; +local: + *; +}; diff --git a/src/devices/adsl/nm-adsl-enum-types.c b/src/devices/adsl/nm-adsl-enum-types.c new file mode 100644 index 00000000..08565331 --- /dev/null +++ b/src/devices/adsl/nm-adsl-enum-types.c @@ -0,0 +1,12 @@ + + + +/* Generated by glib-mkenums. Do not edit */ + +#include "nm-adsl-enum-types.h" + +#include "nm-device-adsl.h" + + + + diff --git a/src/devices/adsl/nm-adsl-enum-types.h b/src/devices/adsl/nm-adsl-enum-types.h new file mode 100644 index 00000000..88e1fe84 --- /dev/null +++ b/src/devices/adsl/nm-adsl-enum-types.h @@ -0,0 +1,17 @@ + + + +/* Generated by glib-mkenums. Do not edit */ + +#ifndef __NM_ADSL_ENUM_TYPES_H__ +#define __NM_ADSL_ENUM_TYPES_H__ + +#include + +G_BEGIN_DECLS +G_END_DECLS + +#endif /* __NM_ADSL_ENUM_TYPES_H__ */ + + + diff --git a/src/devices/adsl/nm-atm-manager.c b/src/devices/adsl/nm-atm-manager.c new file mode 100644 index 00000000..e8db3596 --- /dev/null +++ b/src/devices/adsl/nm-atm-manager.c @@ -0,0 +1,266 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2009 - 2013 Red Hat, Inc. + */ + +#include + +#include +#include +#include + +#include "nm-atm-manager.h" +#include "nm-device-adsl.h" +#include "nm-device-factory.h" +#include "nm-logging.h" + +typedef struct { + GUdevClient *client; + GSList *devices; + guint start_id; +} NMAtmManagerPrivate; + +#define NM_ATM_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_ATM_MANAGER, NMAtmManagerPrivate)) + +static GType nm_atm_manager_get_type (void); + +static void device_factory_interface_init (NMDeviceFactory *factory_iface); + +G_DEFINE_TYPE_EXTENDED (NMAtmManager, nm_atm_manager, G_TYPE_OBJECT, 0, + G_IMPLEMENT_INTERFACE (NM_TYPE_DEVICE_FACTORY, device_factory_interface_init)) + +/**************************************************************************/ + +#define PLUGIN_TYPE NM_DEVICE_TYPE_ADSL + +G_MODULE_EXPORT NMDeviceFactory * +nm_device_factory_create (GError **error) +{ + return (NMDeviceFactory *) g_object_new (NM_TYPE_ATM_MANAGER, NULL); +} + +G_MODULE_EXPORT NMDeviceType +nm_device_factory_get_device_type (void) +{ + return PLUGIN_TYPE; +} + +/************************************************************************/ + +static gboolean +dev_get_attrs (GUdevDevice *udev_device, + const char **out_path, + char **out_driver) +{ + GUdevDevice *parent = NULL; + const char *driver, *path; + + g_return_val_if_fail (udev_device != NULL, FALSE); + g_return_val_if_fail (out_path != NULL, FALSE); + g_return_val_if_fail (out_driver != NULL, FALSE); + + path = g_udev_device_get_sysfs_path (udev_device); + if (!path) { + nm_log_warn (LOGD_HW, "couldn't determine device path; ignoring..."); + return FALSE; + } + + driver = g_udev_device_get_driver (udev_device); + if (!driver) { + /* Try the parent */ + parent = g_udev_device_get_parent (udev_device); + if (parent) + driver = g_udev_device_get_driver (parent); + } + + *out_path = path; + *out_driver = g_strdup (driver); + + g_clear_object (&parent); + return TRUE; +} + +static void +device_destroyed (gpointer user_data, GObject *dead) +{ + NMAtmManager *self = NM_ATM_MANAGER (user_data); + NMAtmManagerPrivate *priv = NM_ATM_MANAGER_GET_PRIVATE (self); + + priv->devices = g_slist_remove (priv->devices, dead); +} + +static void +adsl_add (NMAtmManager *self, GUdevDevice *udev_device) +{ + NMAtmManagerPrivate *priv = NM_ATM_MANAGER_GET_PRIVATE (self); + const char *ifname, *sysfs_path = NULL; + char *driver = NULL; + NMDevice *device; + + g_return_if_fail (udev_device != NULL); + + ifname = g_udev_device_get_name (udev_device); + if (!ifname) { + nm_log_warn (LOGD_HW, "failed to get device's interface name"); + return; + } + + nm_log_dbg (LOGD_HW, "(%s): found ATM device", ifname); + + if (dev_get_attrs (udev_device, &sysfs_path, &driver)) { + g_assert (sysfs_path); + + device = nm_device_adsl_new (sysfs_path, ifname, driver); + g_assert (device); + + priv->devices = g_slist_prepend (priv->devices, device); + g_object_weak_ref (G_OBJECT (device), device_destroyed, self); + + g_signal_emit_by_name (self, NM_DEVICE_FACTORY_DEVICE_ADDED, device); + g_object_unref (device); + + g_free (driver); + } +} + +static void +adsl_remove (NMAtmManager *self, GUdevDevice *udev_device) +{ + NMAtmManagerPrivate *priv = NM_ATM_MANAGER_GET_PRIVATE (self); + const char *iface = g_udev_device_get_name (udev_device); + GSList *iter; + + nm_log_dbg (LOGD_HW, "(%s): removing ATM device", iface); + + for (iter = priv->devices; iter; iter = iter->next) { + NMDevice *device = iter->data; + + /* Match 'iface' not 'ip_iface' to the ATM device instead of the + * NAS bridge interface or PPPoE interface. + */ + if (g_strcmp0 (nm_device_get_iface (device), iface) != 0) + continue; + + g_object_weak_unref (G_OBJECT (iter->data), device_destroyed, self); + priv->devices = g_slist_remove (priv->devices, device); + g_signal_emit_by_name (device, NM_DEVICE_REMOVED); + break; + } +} + +static gboolean +query_devices (NMAtmManager *self) +{ + NMAtmManagerPrivate *priv = NM_ATM_MANAGER_GET_PRIVATE (self); + GUdevEnumerator *enumerator; + GList *devices, *iter; + + enumerator = g_udev_enumerator_new (priv->client); + g_udev_enumerator_add_match_subsystem (enumerator, "atm"); + g_udev_enumerator_add_match_is_initialized (enumerator); + devices = g_udev_enumerator_execute (enumerator); + for (iter = devices; iter; iter = g_list_next (iter)) { + adsl_add (self, G_UDEV_DEVICE (iter->data)); + g_object_unref (G_UDEV_DEVICE (iter->data)); + } + g_list_free (devices); + g_object_unref (enumerator); + + return G_SOURCE_REMOVE; +} + +static void +handle_uevent (GUdevClient *client, + const char *action, + GUdevDevice *device, + gpointer user_data) +{ + NMAtmManager *self = NM_ATM_MANAGER (user_data); + const char *subsys; + const char *ifindex; + guint64 seqnum; + + g_return_if_fail (action != NULL); + + /* A bit paranoid */ + subsys = g_udev_device_get_subsystem (device); + g_return_if_fail (!g_strcmp0 (subsys, "atm")); + + ifindex = g_udev_device_get_property (device, "IFINDEX"); + seqnum = g_udev_device_get_seqnum (device); + nm_log_dbg (LOGD_HW, "UDEV event: action '%s' subsys '%s' device '%s' (%s); seqnum=%" G_GUINT64_FORMAT, + action, subsys, g_udev_device_get_name (device), ifindex ? ifindex : "unknown", seqnum); + + if (!strcmp (action, "add")) + adsl_add (self, device); + else if (!strcmp (action, "remove")) + adsl_remove (self, device); +} + +/*********************************************************************/ + +static void +nm_atm_manager_init (NMAtmManager *self) +{ + NMAtmManagerPrivate *priv = NM_ATM_MANAGER_GET_PRIVATE (self); + const char *subsys[] = { "atm", NULL }; + + priv->client = g_udev_client_new (subsys); + g_signal_connect (priv->client, "uevent", G_CALLBACK (handle_uevent), self); + + priv->start_id = g_idle_add ((GSourceFunc) query_devices, self); +} + +static void +device_factory_interface_init (NMDeviceFactory *factory_iface) +{ +} + +static void +dispose (GObject *object) +{ + NMAtmManager *self = NM_ATM_MANAGER (object); + NMAtmManagerPrivate *priv = NM_ATM_MANAGER_GET_PRIVATE (self); + GSList *iter; + + if (priv->client) + g_signal_handlers_disconnect_by_func (priv->client, handle_uevent, self); + g_clear_object (&priv->client); + + if (priv->start_id) { + g_source_remove (priv->start_id); + priv->start_id = 0; + } + + for (iter = priv->devices; iter; iter = iter->next) + g_object_weak_unref (G_OBJECT (iter->data), device_destroyed, self); + g_clear_pointer (&priv->devices, g_slist_free); + + G_OBJECT_CLASS (nm_atm_manager_parent_class)->dispose (object); +} + +static void +nm_atm_manager_class_init (NMAtmManagerClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (NMAtmManagerPrivate)); + + /* virtual methods */ + object_class->dispose = dispose; +} diff --git a/src/devices/adsl/nm-atm-manager.h b/src/devices/adsl/nm-atm-manager.h new file mode 100644 index 00000000..00525220 --- /dev/null +++ b/src/devices/adsl/nm-atm-manager.h @@ -0,0 +1,42 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2007 - 2008 Novell, Inc. + * Copyright (C) 2007 - 2014 Red Hat, Inc. + */ + +#ifndef NM_ATM_MANAGER_H +#define NM_ATM_MANAGER_H + +#include +#include + +G_BEGIN_DECLS + +#define NM_TYPE_ATM_MANAGER (nm_atm_manager_get_type ()) +#define NM_ATM_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_ATM_MANAGER, NMAtmManager)) + +typedef struct { + GObject parent; +} NMAtmManager; + +typedef struct { + GObjectClass parent; +} NMAtmManagerClass; + +#endif /* NM_ATM_MANAGER_H */ + diff --git a/src/devices/adsl/nm-device-adsl-glue.h b/src/devices/adsl/nm-device-adsl-glue.h new file mode 100644 index 00000000..3a1b9108 --- /dev/null +++ b/src/devices/adsl/nm-device-adsl-glue.h @@ -0,0 +1,73 @@ +/* Generated by dbus-binding-tool; do not edit! */ + + +#ifndef __dbus_glib_marshal_nm_device_adsl_MARSHAL_H__ +#define __dbus_glib_marshal_nm_device_adsl_MARSHAL_H__ + +#include + +G_BEGIN_DECLS + +#ifdef G_ENABLE_DEBUG +#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v) +#define g_marshal_value_peek_char(v) g_value_get_schar (v) +#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v) +#define g_marshal_value_peek_int(v) g_value_get_int (v) +#define g_marshal_value_peek_uint(v) g_value_get_uint (v) +#define g_marshal_value_peek_long(v) g_value_get_long (v) +#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v) +#define g_marshal_value_peek_int64(v) g_value_get_int64 (v) +#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v) +#define g_marshal_value_peek_enum(v) g_value_get_enum (v) +#define g_marshal_value_peek_flags(v) g_value_get_flags (v) +#define g_marshal_value_peek_float(v) g_value_get_float (v) +#define g_marshal_value_peek_double(v) g_value_get_double (v) +#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v) +#define g_marshal_value_peek_param(v) g_value_get_param (v) +#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v) +#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v) +#define g_marshal_value_peek_object(v) g_value_get_object (v) +#define g_marshal_value_peek_variant(v) g_value_get_variant (v) +#else /* !G_ENABLE_DEBUG */ +/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API. + * Do not access GValues directly in your code. Instead, use the + * g_value_get_*() functions + */ +#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int +#define g_marshal_value_peek_char(v) (v)->data[0].v_int +#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint +#define g_marshal_value_peek_int(v) (v)->data[0].v_int +#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint +#define g_marshal_value_peek_long(v) (v)->data[0].v_long +#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 +#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 +#define g_marshal_value_peek_enum(v) (v)->data[0].v_long +#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_float(v) (v)->data[0].v_float +#define g_marshal_value_peek_double(v) (v)->data[0].v_double +#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer +#endif /* !G_ENABLE_DEBUG */ + + +G_END_DECLS + +#endif /* __dbus_glib_marshal_nm_device_adsl_MARSHAL_H__ */ + +#include +static const DBusGMethodInfo dbus_glib_nm_device_adsl_methods[] = { +}; + +const DBusGObjectInfo dbus_glib_nm_device_adsl_object_info = { 1, + dbus_glib_nm_device_adsl_methods, + 0, +"\0", +"org.freedesktop.NetworkManager.Device.Adsl\0PropertiesChanged\0\0", +"org.freedesktop.NetworkManager.Device.Adsl\0Carrier\0carrier\0read\0\0" +}; + diff --git a/src/devices/adsl/nm-device-adsl.c b/src/devices/adsl/nm-device-adsl.c new file mode 100644 index 00000000..0c35bb7a --- /dev/null +++ b/src/devices/adsl/nm-device-adsl.c @@ -0,0 +1,640 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Pantelis Koukousoulas + */ + +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "nm-device-adsl.h" +#include "nm-device-private.h" +#include "NetworkManagerUtils.h" +#include "nm-logging.h" +#include "nm-enum-types.h" +#include "nm-dbus-manager.h" +#include "nm-platform.h" + +#include "ppp-manager/nm-ppp-manager.h" +#include "nm-setting-adsl.h" + +#include "nm-device-adsl-glue.h" + +G_DEFINE_TYPE (NMDeviceAdsl, nm_device_adsl, NM_TYPE_DEVICE) + +#define NM_DEVICE_ADSL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_ADSL, NMDeviceAdslPrivate)) + +/**********************************************/ + +typedef struct { + gboolean disposed; + guint carrier_poll_id; + int atm_index; + + /* PPP */ + NMPPPManager *ppp_manager; + + /* RFC 2684 bridging (PPPoE over ATM) */ + int brfd; + int nas_ifindex; + char * nas_ifname; +} NMDeviceAdslPrivate; + +/**************************************************************/ + +static guint32 +get_generic_capabilities (NMDevice *dev) +{ + return (NM_DEVICE_CAP_CARRIER_DETECT | NM_DEVICE_CAP_NONSTANDARD_CARRIER); +} + +static gboolean +check_connection_compatible (NMDevice *device, NMConnection *connection) +{ + NMSettingAdsl *s_adsl; + const char *protocol; + + if (!NM_DEVICE_CLASS (nm_device_adsl_parent_class)->check_connection_compatible (device, connection)) + return FALSE; + + if (!nm_connection_is_type (connection, NM_SETTING_ADSL_SETTING_NAME)) + return FALSE; + + s_adsl = nm_connection_get_setting_adsl (connection); + if (!s_adsl) + return FALSE; + + /* FIXME: we don't yet support IPoATM */ + protocol = nm_setting_adsl_get_protocol (s_adsl); + if (g_strcmp0 (protocol, NM_SETTING_ADSL_PROTOCOL_IPOATM) == 0) + return FALSE; + + return TRUE; +} + +static gboolean +complete_connection (NMDevice *device, + NMConnection *connection, + const char *specific_object, + const GSList *existing_connections, + GError **error) +{ + NMSettingAdsl *s_adsl; + + /* + * We can't telepathically figure out the username, so if + * it wasn't given, we can't complete the connection. + */ + s_adsl = nm_connection_get_setting_adsl (connection); + if (s_adsl && !nm_setting_verify (NM_SETTING (s_adsl), NULL, error)) + return FALSE; + + nm_utils_complete_generic (connection, + NM_SETTING_ADSL_SETTING_NAME, + existing_connections, + _("ADSL connection %d"), + NULL, + FALSE); /* No IPv6 yet by default */ + + + return TRUE; +} + +/**************************************************************/ + +static void +set_nas_iface (NMDeviceAdsl *self, int idx, const char *name) +{ + NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (self); + + g_return_if_fail (name != NULL); + + g_warn_if_fail (priv->nas_ifindex <= 0); + priv->nas_ifindex = idx > 0 ? idx : nm_platform_link_get_ifindex (name); + g_warn_if_fail (priv->nas_ifindex > 0); + + g_warn_if_fail (priv->nas_ifname == NULL); + priv->nas_ifname = g_strdup (name); + + /* Update NAS interface's MAC address */ + nm_device_update_hw_address (NM_DEVICE (self)); +} + +static gboolean +br2684_create_iface (NMDeviceAdsl *self, NMSettingAdsl *s_adsl) +{ + NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (self); + const char *iface = nm_device_get_iface (NM_DEVICE (self)); + struct atm_newif_br2684 ni; + int err, fd; + gboolean success = FALSE; + guint num = 0; + + g_return_val_if_fail (s_adsl != NULL, FALSE); + + fd = socket (PF_ATMPVC, SOCK_DGRAM, ATM_AAL5); + if (fd < 0) { + nm_log_err (LOGD_ADSL, "(%s): failed to open ATM control socket (%d)", + iface, errno); + return FALSE; + } + + memset (&ni, 0, sizeof (ni)); + ni.backend_num = ATM_BACKEND_BR2684; + ni.media = BR2684_MEDIA_ETHERNET; + ni.mtu = 1500; + + /* Loop attempting to create an interface that doesn't exist yet. The + * kernel can create one for us automatically, but due to API issues it + * cannot return that name to us. Since we want to know the name right + * away, just brute-force it. + */ + while (num < 10000) { + memset (&ni.ifname, 0, sizeof (ni.ifname)); + g_snprintf (ni.ifname, sizeof (ni.ifname), "nas%d", num); + + err = ioctl (fd, ATM_NEWBACKENDIF, &ni); + if (err == 0) { + set_nas_iface (self, -1, ni.ifname); + nm_log_info (LOGD_ADSL, "(%s): using NAS interface %s (%d)", + iface, priv->nas_ifname, priv->nas_ifindex); + success = TRUE; + break; + } else if (errno == -EEXIST) { + /* Try again */ + num++; + } else { + nm_log_warn (LOGD_ADSL, "(%s): failed to create br2684 interface (%d)", + iface, errno); + break; + } + } + + close (fd); + return success; +} + +static gboolean +br2684_assign_vcc (NMDeviceAdsl *self, NMSettingAdsl *s_adsl) +{ + NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (self); + const char *iface = nm_device_get_iface (NM_DEVICE (self)); + struct sockaddr_atmpvc addr; + struct atm_backend_br2684 be; + struct atm_qos qos; + int err, bufsize = 8192; + const char *encapsulation; + gboolean is_llc; + + g_return_val_if_fail (priv->brfd == -1, FALSE); + g_return_val_if_fail (priv->nas_ifname != NULL, FALSE); + + priv->brfd = socket (PF_ATMPVC, SOCK_DGRAM, ATM_AAL5); + if (priv->brfd < 0) { + nm_log_err (LOGD_ADSL, "(%s): failed to open ATM control socket (%d)", + iface, errno); + return FALSE; + } + + err = setsockopt (priv->brfd, SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof (bufsize)); + if (err != 0) { + nm_log_err (LOGD_ADSL, "(%s): failed to set SNDBUF option (%d)", + iface, errno); + goto error; + } + + /* QoS */ + memset (&qos, 0, sizeof (qos)); + qos.aal = ATM_AAL5; + qos.txtp.traffic_class = ATM_UBR; + qos.txtp.max_sdu = 1524; + qos.txtp.pcr = ATM_MAX_PCR; + qos.rxtp = qos.txtp; + + err = setsockopt (priv->brfd, SOL_ATM, SO_ATMQOS, &qos, sizeof (qos)); + if (err != 0) { + nm_log_err (LOGD_ADSL, "(%s): failed to set QoS (%d)", + iface, errno); + goto error; + } + + encapsulation = nm_setting_adsl_get_encapsulation (s_adsl); + + /* VPI/VCI */ + memset (&addr, 0, sizeof (addr)); + addr.sap_family = AF_ATMPVC; + addr.sap_addr.itf = priv->atm_index; + addr.sap_addr.vpi = (guint16) nm_setting_adsl_get_vpi (s_adsl); + addr.sap_addr.vci = (int) nm_setting_adsl_get_vci (s_adsl); + + nm_log_dbg (LOGD_ADSL, "(%s): assigning address %d.%d.%d encapsulation %s", + nm_device_get_iface (NM_DEVICE (self)), + priv->atm_index, addr.sap_addr.vpi, addr.sap_addr.vci, + encapsulation); + + err = connect (priv->brfd, (struct sockaddr*) &addr, sizeof (addr)); + if (err != 0) { + nm_log_err (LOGD_ADSL, "(%s): failed to set VPI/VCI (%d)", + iface, errno); + goto error; + } + + /* And last attach the VCC to the interface */ + is_llc = (g_strcmp0 (encapsulation, "llc") == 0); + + memset (&be, 0, sizeof (be)); + be.backend_num = ATM_BACKEND_BR2684; + be.ifspec.method = BR2684_FIND_BYIFNAME; + strcpy (be.ifspec.spec.ifname, priv->nas_ifname); + be.fcs_in = BR2684_FCSIN_NO; + be.fcs_out = BR2684_FCSOUT_NO; + be.encaps = is_llc ? BR2684_ENCAPS_LLC : BR2684_ENCAPS_VC; + err = ioctl (priv->brfd, ATM_SETBACKEND, &be); + if (err != 0) { + nm_log_err (LOGD_ADSL, "(%s): failed to attach VCC (%d)", + iface, errno); + goto error; + } + + return TRUE; + +error: + close (priv->brfd); + priv->brfd = -1; + return FALSE; +} + +static void +link_changed_cb (NMPlatform *platform, int ifindex, NMPlatformLink *info, NMPlatformSignalChangeType change_type, NMPlatformReason reason, NMDeviceAdsl *device_adsl) +{ + if (change_type == NM_PLATFORM_SIGNAL_REMOVED) { + NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (device_adsl); + NMDevice *device = NM_DEVICE (device_adsl); + + /* This only gets called for PPPoE connections and "nas" interfaces */ + + if (priv->nas_ifindex >= 0 && ifindex == priv->nas_ifindex) { + /* NAS device went away for some reason; kill the connection */ + nm_log_dbg (LOGD_ADSL, "(%s): NAS interface disappeared", + nm_device_get_iface (device)); + nm_device_state_changed (device, + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_BR2684_FAILED); + } + } +} + +static NMActStageReturn +act_stage2_config (NMDevice *device, NMDeviceStateReason *out_reason) +{ + NMDeviceAdsl *self = NM_DEVICE_ADSL (device); + NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (self); + NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; + NMSettingAdsl *s_adsl; + const char *protocol; + + g_assert (out_reason); + + s_adsl = nm_connection_get_setting_adsl (nm_device_get_connection (device)); + g_assert (s_adsl); + + protocol = nm_setting_adsl_get_protocol (s_adsl); + nm_log_dbg (LOGD_ADSL, "(%s): using ADSL protocol '%s'", + nm_device_get_iface (device), protocol); + + if (g_strcmp0 (protocol, NM_SETTING_ADSL_PROTOCOL_PPPOE) == 0) { + + /* PPPoE needs RFC2684 bridging before we can do PPP over it */ + if (!br2684_create_iface (self, s_adsl)) { + *out_reason = NM_DEVICE_STATE_REASON_BR2684_FAILED; + goto done; + } + + /* Set up the VCC */ + if (!br2684_assign_vcc (self, s_adsl)) { + *out_reason = NM_DEVICE_STATE_REASON_BR2684_FAILED; + goto done; + } + + /* Watch for the 'nas' interface going away */ + g_signal_connect (nm_platform_get (), NM_PLATFORM_SIGNAL_LINK_CHANGED, + G_CALLBACK (link_changed_cb), + self); + + nm_log_dbg (LOGD_ADSL, "(%s): ATM setup successful", nm_device_get_iface (device)); + + /* otherwise we're good for stage3 */ + nm_platform_link_set_up (priv->nas_ifindex); + ret = NM_ACT_STAGE_RETURN_SUCCESS; + + } else if (g_strcmp0 (protocol, NM_SETTING_ADSL_PROTOCOL_PPPOA) == 0) { + /* PPPoA doesn't need anything special */ + ret = NM_ACT_STAGE_RETURN_SUCCESS; + } else { + nm_log_warn (LOGD_ADSL, "(%s): unhandled ADSL protocol '%s'", + nm_device_get_iface (device), protocol); + } + +done: + return ret; +} + +static void +ppp_state_changed (NMPPPManager *ppp_manager, NMPPPStatus status, gpointer user_data) +{ + NMDevice *device = NM_DEVICE (user_data); + + switch (status) { + case NM_PPP_STATUS_DISCONNECT: + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_PPP_DISCONNECT); + break; + case NM_PPP_STATUS_DEAD: + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_PPP_FAILED); + break; + default: + break; + } +} + +static void +ppp_ip4_config (NMPPPManager *ppp_manager, + const char *iface, + NMIP4Config *config, + gpointer user_data) +{ + NMDevice *device = NM_DEVICE (user_data); + + /* Ignore PPP IP4 events that come in after initial configuration */ + if (nm_device_activate_ip4_state_in_conf (device)) { + nm_device_set_ip_iface (device, iface); + nm_device_activate_schedule_ip4_config_result (device, config); + } +} + +static NMActStageReturn +act_stage3_ip4_config_start (NMDevice *device, + NMIP4Config **out_config, + NMDeviceStateReason *reason) +{ + NMDeviceAdsl *self = NM_DEVICE_ADSL (device); + NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (self); + NMConnection *connection; + NMSettingAdsl *s_adsl; + NMActRequest *req; + GError *err = NULL; + NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; + const char *iface = nm_device_get_iface (device); + const char *ppp_iface; + + req = nm_device_get_act_request (device); + g_assert (req); + + connection = nm_act_request_get_connection (req); + g_assert (req); + + s_adsl = nm_connection_get_setting_adsl (connection); + g_assert (s_adsl); + + /* PPPoE uses the NAS interface, not the ATM interface */ + if (g_strcmp0 (nm_setting_adsl_get_protocol (s_adsl), NM_SETTING_ADSL_PROTOCOL_PPPOE) == 0) { + g_assert (priv->nas_ifname); + ppp_iface = priv->nas_ifname; + + nm_log_dbg (LOGD_ADSL, "(%s): starting PPPoE on NAS interface %s", + iface, priv->nas_ifname); + } else { + ppp_iface = iface; + nm_log_dbg (LOGD_ADSL, "(%s): starting PPPoA", iface); + } + + priv->ppp_manager = nm_ppp_manager_new (ppp_iface); + if (nm_ppp_manager_start (priv->ppp_manager, req, nm_setting_adsl_get_username (s_adsl), 30, &err)) { + g_signal_connect (priv->ppp_manager, "state-changed", + G_CALLBACK (ppp_state_changed), + self); + g_signal_connect (priv->ppp_manager, "ip4-config", + G_CALLBACK (ppp_ip4_config), + self); + ret = NM_ACT_STAGE_RETURN_POSTPONE; + } else { + nm_log_warn (LOGD_ADSL, "(%s): PPP failed to start: %s", iface, err->message); + g_error_free (err); + + g_object_unref (priv->ppp_manager); + priv->ppp_manager = NULL; + + *reason = NM_DEVICE_STATE_REASON_PPP_START_FAILED; + } + + return ret; +} + +static void +deactivate (NMDevice *device) +{ + NMDeviceAdsl *self = NM_DEVICE_ADSL (device); + NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (self); + + if (priv->ppp_manager) { + g_object_unref (priv->ppp_manager); + priv->ppp_manager = NULL; + } + + g_signal_handlers_disconnect_by_func (nm_platform_get (), G_CALLBACK (link_changed_cb), device); + + if (priv->brfd >= 0) { + close (priv->brfd); + priv->brfd = -1; + } + + /* FIXME: kernel has no way of explicitly deleting the 'nasX' interface yet, + * so it gets leaked. It does get destroyed when it's no longer in use, + * but we have no control over that. + */ + if (priv->nas_ifindex >= 0) + priv->nas_ifindex = -1; + g_free (priv->nas_ifname); + priv->nas_ifname = NULL; + + /* Poke NMDevice to notice that our hw_address is no longer valid */ + nm_device_update_hw_address (NM_DEVICE (self)); +} + +/**************************************************************/ + +static guint +get_hw_address_length (NMDevice *device, gboolean *out_permanent) +{ + NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (device); + + return priv->nas_ifname ? ETH_ALEN : 0; +} + +static gboolean +carrier_update_cb (gpointer user_data) +{ + NMDeviceAdsl *self = NM_DEVICE_ADSL (user_data); + int carrier; + char *path; + const char *iface; + + iface = nm_device_get_iface (NM_DEVICE (self)); + + path = g_strdup_printf ("/sys/class/atm/%s/carrier", + ASSERT_VALID_PATH_COMPONENT (iface)); + carrier = (int) nm_platform_sysctl_get_int_checked (path, 10, 0, 1, -1); + g_free (path); + + if (carrier != -1) + nm_device_set_carrier (NM_DEVICE (self), carrier); + return TRUE; +} + +/**************************************************************/ + +NMDevice * +nm_device_adsl_new (const char *udi, + const char *iface, + const char *driver) +{ + g_return_val_if_fail (udi != NULL, NULL); + + return (NMDevice *) g_object_new (NM_TYPE_DEVICE_ADSL, + NM_DEVICE_UDI, udi, + NM_DEVICE_IFACE, iface, + NM_DEVICE_DRIVER, driver, + NM_DEVICE_TYPE_DESC, "ADSL", + NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_ADSL, + NULL); +} + +static int +get_atm_index (const char *iface) +{ + char *path; + int idx; + + path = g_strdup_printf ("/sys/class/atm/%s/atmindex", + ASSERT_VALID_PATH_COMPONENT (iface)); + idx = (int) nm_platform_sysctl_get_int_checked (path, 10, 0, G_MAXINT, -1); + g_free (path); + + return idx; +} + +static GObject* +constructor (GType type, + guint n_construct_params, + GObjectConstructParam *construct_params) +{ + GObject *object; + NMDeviceAdslPrivate *priv; + + object = G_OBJECT_CLASS (nm_device_adsl_parent_class)->constructor (type, + n_construct_params, + construct_params); + if (!object) + return NULL; + + priv = NM_DEVICE_ADSL_GET_PRIVATE (object); + + priv->atm_index = get_atm_index (nm_device_get_iface (NM_DEVICE (object))); + if (priv->atm_index < 0) { + nm_log_err (LOGD_ADSL, "(%s): error reading ATM device index", + nm_device_get_iface (NM_DEVICE (object))); + g_object_unref (object); + return NULL; + } else { + nm_log_dbg (LOGD_ADSL, "(%s): ATM device index %d", + nm_device_get_iface (NM_DEVICE (object)), priv->atm_index); + } + + /* Poll the carrier */ + priv->carrier_poll_id = g_timeout_add_seconds (5, carrier_update_cb, object); + + return object; +} + +static void +dispose (GObject *object) +{ + NMDeviceAdsl *self = NM_DEVICE_ADSL (object); + NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (self); + + if (priv->disposed) { + G_OBJECT_CLASS (nm_device_adsl_parent_class)->dispose (object); + return; + } + + priv->disposed = TRUE; + + if (priv->carrier_poll_id) { + g_source_remove (priv->carrier_poll_id); + priv->carrier_poll_id = 0; + } + + g_signal_handlers_disconnect_by_func (nm_platform_get (), G_CALLBACK (link_changed_cb), self); + + g_free (priv->nas_ifname); + priv->nas_ifname = NULL; + + G_OBJECT_CLASS (nm_device_adsl_parent_class)->dispose (object); +} + +static void +nm_device_adsl_init (NMDeviceAdsl *self) +{ +} + +static void +nm_device_adsl_class_init (NMDeviceAdslClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (NMDeviceAdslPrivate)); + + object_class->constructor = constructor; + object_class->dispose = dispose; + + parent_class->get_generic_capabilities = get_generic_capabilities; + + parent_class->check_connection_compatible = check_connection_compatible; + parent_class->complete_connection = complete_connection; + + parent_class->get_hw_address_length = get_hw_address_length; + parent_class->act_stage2_config = act_stage2_config; + parent_class->act_stage3_ip4_config_start = act_stage3_ip4_config_start; + parent_class->deactivate = deactivate; + + nm_dbus_manager_register_exported_type (nm_dbus_manager_get (), + G_TYPE_FROM_CLASS (klass), + &dbus_glib_nm_device_adsl_object_info); +} diff --git a/src/devices/adsl/nm-device-adsl.h b/src/devices/adsl/nm-device-adsl.h new file mode 100644 index 00000000..bbd0e63f --- /dev/null +++ b/src/devices/adsl/nm-device-adsl.h @@ -0,0 +1,56 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Author: Pantelis Koukousoulas + * Copyright (C) 2009 - 2011 Red Hat Inc. + */ + +#ifndef NM_DEVICE_ADSL_H +#define NM_DEVICE_ADSL_H + +#include + +// Parent class +#include "nm-device.h" + +G_BEGIN_DECLS + +#define NM_TYPE_DEVICE_ADSL (nm_device_adsl_get_type ()) +#define NM_DEVICE_ADSL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_ADSL, NMDeviceAdsl)) +#define NM_DEVICE_ADSL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_ADSL, NMDeviceAdslClass)) +#define NM_IS_DEVICE_ADSL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_ADSL)) +#define NM_IS_DEVICE_ADSL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_ADSL)) +#define NM_DEVICE_ADSL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_ADSL, NMDeviceAdslClass)) + +typedef struct { + NMDevice parent; +} NMDeviceAdsl; + +typedef struct { + NMDeviceClass parent; + +} NMDeviceAdslClass; + +GType nm_device_adsl_get_type (void); + +NMDevice *nm_device_adsl_new (const char *udi, + const char *iface, + const char *driver); + +G_END_DECLS + +#endif /* NM_DEVICE_ADSL_H */ diff --git a/src/devices/bluetooth/Makefile.am b/src/devices/bluetooth/Makefile.am new file mode 100644 index 00000000..639a1ad7 --- /dev/null +++ b/src/devices/bluetooth/Makefile.am @@ -0,0 +1,74 @@ +include $(GLIB_MAKEFILE) + +@GNOME_CODE_COVERAGE_RULES@ + +AM_CPPFLAGS = \ + -I${top_srcdir}/src \ + -I${top_builddir}/src \ + -I${top_srcdir}/src/logging \ + -I${top_srcdir}/src/devices \ + -I${top_srcdir}/src/settings \ + -I${top_srcdir}/src/platform \ + -I${top_srcdir}/src/devices/wwan \ + -I${top_builddir}/include \ + -I${top_srcdir}/include \ + -I${top_builddir}/libnm-util \ + -I${top_srcdir}/libnm-util \ + -DG_LOG_DOMAIN=\""NetworkManager-bluetooth"\" \ + -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \ + $(DBUS_CFLAGS) \ + $(POLKIT_CFLAGS) \ + $(LIBNL_CFLAGS) \ + $(GUDEV_CFLAGS) + +GLIB_GENERATED = nm-bt-enum-types.h nm-bt-enum-types.c +GLIB_MKENUMS_H_FLAGS = --identifier-prefix NM +GLIB_MKENUMS_C_FLAGS = --identifier-prefix NM +nm_bt_enum_types_sources = $(srcdir)/nm-device-bt.h + +nm-device-bt-glue.h: $(top_srcdir)/introspection/nm-device-bt.xml + dbus-binding-tool --prefix=nm_device_bt --mode=glib-server --output=$@ $< + +BUILT_SOURCES = $(GLIB_GENERATED) nm-device-bt-glue.h + +pkglib_LTLIBRARIES = libnm-device-plugin-bluetooth.la + +SYMBOL_VIS_FILE=$(srcdir)/exports.ver + +libnm_device_plugin_bluetooth_la_SOURCES = \ + nm-bluez-manager.c \ + nm-bluez-manager.h \ + nm-bluez-common.h \ + nm-bluez-device.c \ + nm-bluez-device.h \ + nm-bluez4-adapter.c \ + nm-bluez4-adapter.h \ + nm-bluez4-manager.c \ + nm-bluez4-manager.h \ + nm-bluez5-manager.c \ + nm-bluez5-manager.h \ + \ + nm-device-bt.c \ + nm-device-bt.h \ + \ + $(BUILT_SOURCES) + +libnm_device_plugin_bluetooth_la_LDFLAGS = \ + -module -avoid-version \ + -Wl,--version-script=$(SYMBOL_VIS_FILE) + +libnm_device_plugin_bluetooth_la_LIBADD = \ + $(top_builddir)/src/devices/wwan/libnm-wwan.la \ + $(DBUS_LIBS) \ + $(GUDEV_LIBS) + +CLEANFILES = $(BUILT_SOURCES) +EXTRA_DIST = $(SYMBOL_VIS_FILE) + +if ENABLE_TESTS + +check-local: + $(top_srcdir)/tools/check-exports.sh $(builddir)/.libs/libnm-device-plugin-bluetooth.so $(SYMBOL_VIS_FILE) + +endif + diff --git a/src/devices/bluetooth/Makefile.in b/src/devices/bluetooth/Makefile.in new file mode 100644 index 00000000..3145c52d --- /dev/null +++ b/src/devices/bluetooth/Makefile.in @@ -0,0 +1,864 @@ +# Makefile.in generated by automake 1.13.4 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/devices/bluetooth +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(top_srcdir)/build-aux/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_lib_readline.m4 \ + $(top_srcdir)/m4/compiler_warnings.m4 \ + $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/gnome-code-coverage.m4 \ + $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ + $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \ + $(top_srcdir)/m4/introspection.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ + $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ + $(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(pkglibdir)" +LTLIBRARIES = $(pkglib_LTLIBRARIES) +am__DEPENDENCIES_1 = +libnm_device_plugin_bluetooth_la_DEPENDENCIES = \ + $(top_builddir)/src/devices/wwan/libnm-wwan.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +am__objects_1 = nm-bt-enum-types.lo +am__objects_2 = $(am__objects_1) +am_libnm_device_plugin_bluetooth_la_OBJECTS = nm-bluez-manager.lo \ + nm-bluez-device.lo nm-bluez4-adapter.lo nm-bluez4-manager.lo \ + nm-bluez5-manager.lo nm-device-bt.lo $(am__objects_2) +libnm_device_plugin_bluetooth_la_OBJECTS = \ + $(am_libnm_device_plugin_bluetooth_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libnm_device_plugin_bluetooth_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) \ + $(libnm_device_plugin_bluetooth_la_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libnm_device_plugin_bluetooth_la_SOURCES) +DIST_SOURCES = $(libnm_device_plugin_bluetooth_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALL_LINGUAS = @ALL_LINGUAS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CKDB_PATH = @CKDB_PATH@ +CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@ +CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@ +CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIRNAME = @DATADIRNAME@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_100_CFLAGS = @DBUS_GLIB_100_CFLAGS@ +DBUS_GLIB_100_LIBS = @DBUS_GLIB_100_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DHCLIENT_PATH = @DHCLIENT_PATH@ +DHCPCD_PATH = @DHCPCD_PATH@ +DISTRO_NETWORK_SERVICE = @DISTRO_NETWORK_SERVICE@ +DLLTOOL = @DLLTOOL@ +DNSMASQ_PATH = @DNSMASQ_PATH@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GENHTML = @GENHTML@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MAKEFILE = @GLIB_MAKEFILE@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ +GNUTLS_LIBS = @GNUTLS_LIBS@ +GREP = @GREP@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GUDEV_CFLAGS = @GUDEV_CFLAGS@ +GUDEV_LIBS = @GUDEV_LIBS@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_PERL = @INTLTOOL_PERL@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ +INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ +INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ +INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +IPTABLES_PATH = @IPTABLES_PATH@ +IWMX_SDK_CFLAGS = @IWMX_SDK_CFLAGS@ +IWMX_SDK_LIBS = @IWMX_SDK_LIBS@ +KERNEL_FIRMWARE_DIR = @KERNEL_FIRMWARE_DIR@ +LCOV = @LCOV@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDL = @LIBDL@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBM = @LIBM@ +LIBNDP_CFLAGS = @LIBNDP_CFLAGS@ +LIBNDP_LIBS = @LIBNDP_LIBS@ +LIBNL_CFLAGS = @LIBNL_CFLAGS@ +LIBNL_LIBS = @LIBNL_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@ +LIBSOUP_LIBS = @LIBSOUP_LIBS@ +LIBTEAMDCTL_CFLAGS = @LIBTEAMDCTL_CFLAGS@ +LIBTEAMDCTL_LIBS = @LIBTEAMDCTL_LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MM_GLIB_CFLAGS = @MM_GLIB_CFLAGS@ +MM_GLIB_LIBS = @MM_GLIB_LIBS@ +MOC = @MOC@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NEWT_CFLAGS = @NEWT_CFLAGS@ +NEWT_LIBS = @NEWT_LIBS@ +NM = @NM@ +NMEDIT = @NMEDIT@ +NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ +NM_MICRO_VERSION = @NM_MICRO_VERSION@ +NM_MINOR_VERSION = @NM_MINOR_VERSION@ +NM_MODIFY_SYSTEM_POLICY = @NM_MODIFY_SYSTEM_POLICY@ +NM_VERSION = @NM_VERSION@ +NSS_CFLAGS = @NSS_CFLAGS@ +NSS_LIBS = @NSS_LIBS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +POLKIT_CFLAGS = @POLKIT_CFLAGS@ +POLKIT_LIBS = @POLKIT_LIBS@ +POSUB = @POSUB@ +PPPD_PATH = @PPPD_PATH@ +PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@ +PPPOE_PATH = @PPPOE_PATH@ +QT_CFLAGS = @QT_CFLAGS@ +QT_LIBS = @QT_LIBS@ +RANLIB = @RANLIB@ +READLINE_LIBS = @READLINE_LIBS@ +SED = @SED@ +SELINUX_CFLAGS = @SELINUX_CFLAGS@ +SELINUX_LIBS = @SELINUX_LIBS@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SYSTEMD_200_CFLAGS = @SYSTEMD_200_CFLAGS@ +SYSTEMD_200_LIBS = @SYSTEMD_200_LIBS@ +SYSTEMD_INHIBIT_CFLAGS = @SYSTEMD_INHIBIT_CFLAGS@ +SYSTEMD_INHIBIT_LIBS = @SYSTEMD_INHIBIT_LIBS@ +SYSTEMD_LOGIN_CFLAGS = @SYSTEMD_LOGIN_CFLAGS@ +SYSTEMD_LOGIN_LIBS = @SYSTEMD_LOGIN_LIBS@ +SYSTEM_CA_PATH = @SYSTEM_CA_PATH@ +UDEV_BASE_DIR = @UDEV_BASE_DIR@ +USE_NLS = @USE_NLS@ +UUID_CFLAGS = @UUID_CFLAGS@ +UUID_LIBS = @UUID_LIBS@ +VALGRIND_RULES = @VALGRIND_RULES@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ +VERSION = @VERSION@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +intltool__v_merge_options_ = @intltool__v_merge_options_@ +intltool__v_merge_options_0 = @intltool__v_merge_options_0@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +nmbinary = @nmbinary@ +nmconfdir = @nmconfdir@ +nmdatadir = @nmdatadir@ +nmrundir = @nmrundir@ +nmstatedir = @nmstatedir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +with_dhclient = @with_dhclient@ +with_dhcpcd = @with_dhcpcd@ +with_netconfig = @with_netconfig@ +with_resolvconf = @with_resolvconf@ +with_valgrind = @with_valgrind@ +AM_CPPFLAGS = \ + -I${top_srcdir}/src \ + -I${top_builddir}/src \ + -I${top_srcdir}/src/logging \ + -I${top_srcdir}/src/devices \ + -I${top_srcdir}/src/settings \ + -I${top_srcdir}/src/platform \ + -I${top_srcdir}/src/devices/wwan \ + -I${top_builddir}/include \ + -I${top_srcdir}/include \ + -I${top_builddir}/libnm-util \ + -I${top_srcdir}/libnm-util \ + -DG_LOG_DOMAIN=\""NetworkManager-bluetooth"\" \ + -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \ + $(DBUS_CFLAGS) \ + $(POLKIT_CFLAGS) \ + $(LIBNL_CFLAGS) \ + $(GUDEV_CFLAGS) + +GLIB_GENERATED = nm-bt-enum-types.h nm-bt-enum-types.c +GLIB_MKENUMS_H_FLAGS = --identifier-prefix NM +GLIB_MKENUMS_C_FLAGS = --identifier-prefix NM +nm_bt_enum_types_sources = $(srcdir)/nm-device-bt.h +BUILT_SOURCES = $(GLIB_GENERATED) nm-device-bt-glue.h +pkglib_LTLIBRARIES = libnm-device-plugin-bluetooth.la +SYMBOL_VIS_FILE = $(srcdir)/exports.ver +libnm_device_plugin_bluetooth_la_SOURCES = \ + nm-bluez-manager.c \ + nm-bluez-manager.h \ + nm-bluez-common.h \ + nm-bluez-device.c \ + nm-bluez-device.h \ + nm-bluez4-adapter.c \ + nm-bluez4-adapter.h \ + nm-bluez4-manager.c \ + nm-bluez4-manager.h \ + nm-bluez5-manager.c \ + nm-bluez5-manager.h \ + \ + nm-device-bt.c \ + nm-device-bt.h \ + \ + $(BUILT_SOURCES) + +libnm_device_plugin_bluetooth_la_LDFLAGS = \ + -module -avoid-version \ + -Wl,--version-script=$(SYMBOL_VIS_FILE) + +libnm_device_plugin_bluetooth_la_LIBADD = \ + $(top_builddir)/src/devices/wwan/libnm-wwan.la \ + $(DBUS_LIBS) \ + $(GUDEV_LIBS) + +CLEANFILES = $(BUILT_SOURCES) +EXTRA_DIST = $(SYMBOL_VIS_FILE) +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/devices/bluetooth/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/devices/bluetooth/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +install-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkglibdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ + } + +uninstall-pkglibLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ + done + +clean-pkglibLTLIBRARIES: + -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) + @list='$(pkglib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libnm-device-plugin-bluetooth.la: $(libnm_device_plugin_bluetooth_la_OBJECTS) $(libnm_device_plugin_bluetooth_la_DEPENDENCIES) $(EXTRA_libnm_device_plugin_bluetooth_la_DEPENDENCIES) + $(AM_V_CCLD)$(libnm_device_plugin_bluetooth_la_LINK) -rpath $(pkglibdir) $(libnm_device_plugin_bluetooth_la_OBJECTS) $(libnm_device_plugin_bluetooth_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-bluez-device.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-bluez-manager.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-bluez4-adapter.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-bluez4-manager.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-bluez5-manager.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-bt-enum-types.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-device-bt.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +@ENABLE_TESTS_FALSE@check-local: +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) check-local +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(pkglibdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-am + +clean-am: clean-generic clean-libtool clean-pkglibLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-pkglibLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pkglibLTLIBRARIES + +.MAKE: all check check-am install install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am check-local clean \ + clean-generic clean-libtool clean-pkglibLTLIBRARIES \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-pkglibLTLIBRARIES install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am uninstall-pkglibLTLIBRARIES + +include $(GLIB_MAKEFILE) + +@GNOME_CODE_COVERAGE_RULES@ + +nm-device-bt-glue.h: $(top_srcdir)/introspection/nm-device-bt.xml + dbus-binding-tool --prefix=nm_device_bt --mode=glib-server --output=$@ $< + +@ENABLE_TESTS_TRUE@check-local: +@ENABLE_TESTS_TRUE@ $(top_srcdir)/tools/check-exports.sh $(builddir)/.libs/libnm-device-plugin-bluetooth.so $(SYMBOL_VIS_FILE) + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/devices/bluetooth/exports.ver b/src/devices/bluetooth/exports.ver new file mode 100644 index 00000000..d2c45124 --- /dev/null +++ b/src/devices/bluetooth/exports.ver @@ -0,0 +1,7 @@ +{ +global: + nm_device_factory_create; + nm_device_factory_get_device_type; +local: + *; +}; diff --git a/src/devices/bluetooth/nm-bluez-common.h b/src/devices/bluetooth/nm-bluez-common.h new file mode 100644 index 00000000..f80cfc2e --- /dev/null +++ b/src/devices/bluetooth/nm-bluez-common.h @@ -0,0 +1,45 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2009 Red Hat, Inc. + */ + +#ifndef NM_BLUEZ_COMMON_H +#define NM_BLUEZ_COMMON_H + +#include + +#define BLUETOOTH_CONNECT_DUN "dun" +#define BLUETOOTH_CONNECT_NAP "nap" + +#define BLUEZ_SERVICE "org.bluez" + +#define BLUEZ_MANAGER_PATH "/" +#define OBJECT_MANAGER_INTERFACE "org.freedesktop.DBus.ObjectManager" + +#define BLUEZ5_ADAPTER_INTERFACE "org.bluez.Adapter1" +#define BLUEZ5_DEVICE_INTERFACE "org.bluez.Device1" +#define BLUEZ5_NETWORK_INTERFACE "org.bluez.Network1" + +#define BLUEZ4_MANAGER_INTERFACE "org.bluez.Manager" +#define BLUEZ4_ADAPTER_INTERFACE "org.bluez.Adapter" +#define BLUEZ4_DEVICE_INTERFACE "org.bluez.Device" +#define BLUEZ4_SERIAL_INTERFACE "org.bluez.Serial" +#define BLUEZ4_NETWORK_INTERFACE "org.bluez.Network" + +#endif /* NM_BLUEZ_COMMON_H */ + diff --git a/src/devices/bluetooth/nm-bluez-device.c b/src/devices/bluetooth/nm-bluez-device.c new file mode 100644 index 00000000..4c448a37 --- /dev/null +++ b/src/devices/bluetooth/nm-bluez-device.c @@ -0,0 +1,1212 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2009 - 2012 Red Hat, Inc. + * Copyright (C) 2013 Intel Corporation. + */ + +#include +#include +#include +#include +#include +#include + +#include "NetworkManager.h" +#include "nm-setting-bluetooth.h" + +#include "nm-bluez-common.h" +#include "nm-bluez-device.h" +#include "nm-logging.h" +#include "nm-utils.h" +#include "nm-settings-connection.h" + + +G_DEFINE_TYPE (NMBluezDevice, nm_bluez_device, G_TYPE_OBJECT) + +#define NM_BLUEZ_DEVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_BLUEZ_DEVICE, NMBluezDevicePrivate)) + +typedef struct { + char *path; + GDBusConnection *dbus_connection; + + GDBusProxy *proxy; + + GDBusProxy *adapter5; + gboolean adapter_powered; + + int bluez_version; + + gboolean initialized; + gboolean usable; + NMBluetoothCapabilities connection_bt_type; + + char *address; + guint8 bin_address[ETH_ALEN]; + char *name; + guint32 capabilities; + gboolean connected; + + char *bt_iface; + + NMConnectionProvider *provider; + GSList *connections; + + NMConnection *pan_connection; + NMConnection *pan_connection_original; + gboolean pan_connection_no_autocreate; +} NMBluezDevicePrivate; + + +enum { + PROP_0, + PROP_PATH, + PROP_ADDRESS, + PROP_NAME, + PROP_CAPABILITIES, + PROP_USABLE, + PROP_CONNECTED, + + LAST_PROP +}; + +/* Signals */ +enum { + INITIALIZED, + REMOVED, + LAST_SIGNAL +}; +static guint signals[LAST_SIGNAL] = { 0 }; + + +static void cp_connection_added (NMConnectionProvider *provider, + NMConnection *connection, NMBluezDevice *self); +static gboolean connection_compatible (NMBluezDevice *self, NMConnection *connection); + + +#define VARIANT_IS_OF_TYPE_BOOLEAN(v) ((v) != NULL && ( g_variant_is_of_type ((v), G_VARIANT_TYPE_BOOLEAN) )) +#define VARIANT_IS_OF_TYPE_STRING(v) ((v) != NULL && ( g_variant_is_of_type ((v), G_VARIANT_TYPE_STRING) )) +#define VARIANT_IS_OF_TYPE_OBJECT_PATH(v) ((v) != NULL && ( g_variant_is_of_type ((v), G_VARIANT_TYPE_OBJECT_PATH) )) +#define VARIANT_IS_OF_TYPE_STRING_ARRAY(v) ((v) != NULL && ( g_variant_is_of_type ((v), G_VARIANT_TYPE_STRING_ARRAY) )) + +/***********************************************************/ + +const char * +nm_bluez_device_get_path (NMBluezDevice *self) +{ + g_return_val_if_fail (NM_IS_BLUEZ_DEVICE (self), NULL); + + return NM_BLUEZ_DEVICE_GET_PRIVATE (self)->path; +} + +const char * +nm_bluez_device_get_address (NMBluezDevice *self) +{ + g_return_val_if_fail (NM_IS_BLUEZ_DEVICE (self), NULL); + + return NM_BLUEZ_DEVICE_GET_PRIVATE (self)->address; +} + +gboolean +nm_bluez_device_get_initialized (NMBluezDevice *self) +{ + g_return_val_if_fail (NM_IS_BLUEZ_DEVICE (self), FALSE); + + return NM_BLUEZ_DEVICE_GET_PRIVATE (self)->initialized; +} + +gboolean +nm_bluez_device_get_usable (NMBluezDevice *self) +{ + g_return_val_if_fail (NM_IS_BLUEZ_DEVICE (self), FALSE); + + return NM_BLUEZ_DEVICE_GET_PRIVATE (self)->usable; +} + +const char * +nm_bluez_device_get_name (NMBluezDevice *self) +{ + g_return_val_if_fail (NM_IS_BLUEZ_DEVICE (self), NULL); + + return NM_BLUEZ_DEVICE_GET_PRIVATE (self)->name; +} + +guint32 +nm_bluez_device_get_capabilities (NMBluezDevice *self) +{ + g_return_val_if_fail (NM_IS_BLUEZ_DEVICE (self), 0); + + return NM_BLUEZ_DEVICE_GET_PRIVATE (self)->capabilities; +} + +gboolean +nm_bluez_device_get_connected (NMBluezDevice *self) +{ + g_return_val_if_fail (NM_IS_BLUEZ_DEVICE (self), FALSE); + + return NM_BLUEZ_DEVICE_GET_PRIVATE (self)->connected; +} + +static void +pan_connection_check_create (NMBluezDevice *self) +{ + NMConnection *connection; + NMConnection *added; + NMSetting *setting; + char *uuid, *id; + GByteArray *bdaddr_array; + GError *error = NULL; + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + + g_return_if_fail (priv->capabilities & NM_BT_CAPABILITY_NAP); + g_return_if_fail (priv->connections == NULL); + g_return_if_fail (priv->name); + + if (priv->pan_connection || priv->pan_connection_no_autocreate) { + /* already have a connection or we don't want to create one, nothing to do. */ + return; + } + + /* Only try once to create a connection. If it does not succeed, we do not try again. Also, + * if the connection gets deleted later, do not create another one for this device. */ + priv->pan_connection_no_autocreate = TRUE; + + /* create a new connection */ + + connection = nm_connection_new (); + + /* Setting: Connection */ + uuid = nm_utils_uuid_generate (); + id = g_strdup_printf (_("%s Network"), priv->name); + setting = nm_setting_connection_new (); + g_object_set (setting, + NM_SETTING_CONNECTION_ID, id, + NM_SETTING_CONNECTION_UUID, uuid, + NM_SETTING_CONNECTION_AUTOCONNECT, FALSE, + NM_SETTING_CONNECTION_TYPE, NM_SETTING_BLUETOOTH_SETTING_NAME, + NULL); + nm_connection_add_setting (connection, setting); + + /* Setting: Bluetooth */ + bdaddr_array = g_byte_array_sized_new (sizeof (priv->bin_address)); + g_byte_array_append (bdaddr_array, priv->bin_address, sizeof (priv->bin_address)); + setting = nm_setting_bluetooth_new (); + g_object_set (G_OBJECT (setting), + NM_SETTING_BLUETOOTH_BDADDR, bdaddr_array, + NM_SETTING_BLUETOOTH_TYPE, NM_SETTING_BLUETOOTH_TYPE_PANU, + NULL); + nm_connection_add_setting (connection, setting); + g_byte_array_free (bdaddr_array, TRUE); + + /* Setting: IPv4 */ + setting = nm_setting_ip4_config_new (); + g_object_set (G_OBJECT (setting), + NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, + NM_SETTING_IP4_CONFIG_MAY_FAIL, FALSE, + NULL); + nm_connection_add_setting (connection, setting); + + /* Setting: IPv6 */ + setting = nm_setting_ip6_config_new (); + g_object_set (G_OBJECT (setting), + NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO, + NM_SETTING_IP6_CONFIG_MAY_FAIL, TRUE, + NULL); + nm_connection_add_setting (connection, setting); + + /* Adding a new connection raises a signal which eventually calls check_emit_usable (again) + * which then already finds the suitable connection in priv->connections. This is confusing, + * so block the signal. check_emit_usable will succeed after this function call returns. */ + g_signal_handlers_block_by_func (priv->provider, cp_connection_added, self); + added = nm_connection_provider_add_connection (priv->provider, connection, FALSE, &error); + g_signal_handlers_unblock_by_func (priv->provider, cp_connection_added, self); + + if (added) { + g_assert (!g_slist_find (priv->connections, added)); + g_assert (connection_compatible (self, added)); + g_assert (nm_connection_compare (added, connection, NM_SETTING_COMPARE_FLAG_EXACT)); + + priv->connections = g_slist_prepend (priv->connections, g_object_ref (added)); + priv->pan_connection = added; + priv->pan_connection_original = connection; + nm_log_dbg (LOGD_BT, "bluez[%s] added new Bluetooth connection for NAP device: '%s' (%s)", priv->path, id, uuid); + } else { + nm_log_warn (LOGD_BT, "bluez[%s] couldn't add new Bluetooth connection for NAP device: '%s' (%s): %d / %s", + priv->path, id, uuid, error ? error->code : -1, + (error && error->message) ? error->message : "(unknown)"); + g_clear_error (&error); + + g_object_unref (connection); + } + + g_free (id); + g_free (uuid); +} + +static void +check_emit_usable (NMBluezDevice *self) +{ + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + gboolean new_usable; + + /* only expect the supported capabilities set. */ + g_assert (priv->bluez_version != 4 || ((priv->capabilities & ~(NM_BT_CAPABILITY_NAP | NM_BT_CAPABILITY_DUN)) == NM_BT_CAPABILITY_NONE )); + g_assert (priv->bluez_version != 5 || ((priv->capabilities & ~(NM_BT_CAPABILITY_NAP )) == NM_BT_CAPABILITY_NONE )); + + new_usable = (priv->initialized && priv->capabilities && priv->name && + ((priv->bluez_version == 4) || + (priv->bluez_version == 5 && priv->adapter5 && priv->adapter_powered) ) && + priv->dbus_connection && priv->address); + + if (!new_usable) + goto END; + + if (priv->connections) + goto END; + + if (!(priv->capabilities & NM_BT_CAPABILITY_NAP)) { + /* non NAP devices are only usable, if they already have a connection. */ + new_usable = FALSE; + goto END; + } + + pan_connection_check_create (self); + new_usable = !!priv->pan_connection; + +END: + if (new_usable != priv->usable) { + priv->usable = new_usable; + g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_USABLE); + } +} + +/********************************************************************/ + +static gboolean +connection_compatible (NMBluezDevice *self, NMConnection *connection) +{ + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + NMSettingBluetooth *s_bt; + const char *bt_type; + const GByteArray *bdaddr; + + if (!nm_connection_is_type (connection, NM_SETTING_BLUETOOTH_SETTING_NAME)) + return FALSE; + + s_bt = nm_connection_get_setting_bluetooth (connection); + if (!s_bt) + return FALSE; + + if (!priv->address) { + /* unless address is set, bin_address is not initialized. */ + return FALSE; + } + bdaddr = nm_setting_bluetooth_get_bdaddr (s_bt); + if (!bdaddr || bdaddr->len != ETH_ALEN) + return FALSE; + if (memcmp (bdaddr->data, priv->bin_address, ETH_ALEN) != 0) + return FALSE; + + bt_type = nm_setting_bluetooth_get_connection_type (s_bt); + if ( g_str_equal (bt_type, NM_SETTING_BLUETOOTH_TYPE_DUN) + && !(priv->capabilities & NM_BT_CAPABILITY_DUN)) + return FALSE; + + if ( g_str_equal (bt_type, NM_SETTING_BLUETOOTH_TYPE_PANU) + && !(priv->capabilities & NM_BT_CAPABILITY_NAP)) + return FALSE; + + return TRUE; +} + +static void +_internal_add_connection (NMBluezDevice *self, NMConnection *connection) +{ + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + + if (!g_slist_find (priv->connections, connection)) { + priv->connections = g_slist_prepend (priv->connections, g_object_ref (connection)); + check_emit_usable (self); + } +} + +static void +cp_connection_added (NMConnectionProvider *provider, + NMConnection *connection, + NMBluezDevice *self) +{ + if (connection_compatible (self, connection)) + _internal_add_connection (self, connection); +} + +static void +cp_connection_removed (NMConnectionProvider *provider, + NMConnection *connection, + NMBluezDevice *self) +{ + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + + if (g_slist_find (priv->connections, connection)) { + priv->connections = g_slist_remove (priv->connections, connection); + if (priv->pan_connection == connection) { + priv->pan_connection = NULL; + g_clear_object (&priv->pan_connection_original); + } + g_object_unref (connection); + check_emit_usable (self); + } +} + +static void +cp_connection_updated (NMConnectionProvider *provider, + NMConnection *connection, + NMBluezDevice *self) +{ + if (connection_compatible (self, connection)) + _internal_add_connection (self, connection); + else + cp_connection_removed (provider, connection, self); +} + +static void +load_connections (NMBluezDevice *self) +{ + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + const GSList *connections, *iter; + + connections = nm_connection_provider_get_connections (priv->provider); + for (iter = connections; iter; iter = g_slist_next (iter)) + cp_connection_added (priv->provider, NM_CONNECTION (iter->data), self); +} + +/***********************************************************/ + +static void +bluez_disconnect_cb (GDBusConnection *dbus_connection, + GAsyncResult *res, + gpointer user_data) +{ + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (user_data); + GError *error = NULL; + GVariant *variant; + + variant = g_dbus_connection_call_finish (dbus_connection, res, &error); + if (!variant) { + if (!strstr (error->message, "org.bluez.Error.NotConnected")) + nm_log_warn (LOGD_BT, "bluez[%s]: failed to disconnect: %s", priv->path, error->message); + g_error_free (error); + } else + g_variant_unref (variant); + + g_object_unref (NM_BLUEZ_DEVICE (user_data)); +} + +void +nm_bluez_device_disconnect (NMBluezDevice *self) +{ + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + GVariant *args = NULL; + const char *dbus_iface; + + g_return_if_fail (priv->dbus_connection); + + if (priv->bluez_version == 5) { + g_return_if_fail (priv->connection_bt_type == NM_BT_CAPABILITY_NAP); + dbus_iface = BLUEZ5_NETWORK_INTERFACE; + } else if (priv->bluez_version == 4 && priv->connection_bt_type == NM_BT_CAPABILITY_DUN) { + /* Can't pass a NULL interface name through dbus to bluez, so just + * ignore the disconnect if the interface isn't known. + */ + if (!priv->bt_iface) + return; + + args = g_variant_new ("(s)", priv->bt_iface), + dbus_iface = BLUEZ4_SERIAL_INTERFACE; + } else { + g_return_if_fail (priv->bluez_version == 4 && priv->connection_bt_type == NM_BT_CAPABILITY_NAP); + dbus_iface = BLUEZ4_NETWORK_INTERFACE; + } + + g_dbus_connection_call (priv->dbus_connection, + BLUEZ_SERVICE, + priv->path, + dbus_iface, + "Disconnect", + args ? args : g_variant_new ("()"), + NULL, + G_DBUS_CALL_FLAGS_NONE, + 10000, + NULL, + (GAsyncReadyCallback) bluez_disconnect_cb, + g_object_ref (self)); + + priv->connection_bt_type = NM_BT_CAPABILITY_NONE; +} + +static void +bluez_connect_cb (GDBusConnection *dbus_connection, + GAsyncResult *res, + gpointer user_data) +{ + GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (user_data); + GObject *result_object = g_async_result_get_source_object (G_ASYNC_RESULT (result)); + NMBluezDevice *self = NM_BLUEZ_DEVICE (result_object); + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + GError *error = NULL; + char *device; + GVariant *variant; + + variant = g_dbus_connection_call_finish (dbus_connection, res, &error); + + if (!variant) { + g_simple_async_result_take_error (result, error); + } else { + g_variant_get (variant, "(s)", &device); + + g_simple_async_result_set_op_res_gpointer (result, + g_strdup (device), + g_free); + priv->bt_iface = device; + g_variant_unref (variant); + } + + g_simple_async_result_complete (result); + g_object_unref (result); + g_object_unref (result_object); +} + +void +nm_bluez_device_connect_async (NMBluezDevice *self, + NMBluetoothCapabilities connection_bt_type, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *simple; + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + const char *dbus_iface; + const char *connect_type = BLUETOOTH_CONNECT_NAP; + + g_return_if_fail (priv->capabilities & connection_bt_type & (NM_BT_CAPABILITY_DUN | NM_BT_CAPABILITY_NAP)); + + if (priv->bluez_version == 5) { + g_return_if_fail (connection_bt_type == NM_BT_CAPABILITY_NAP); + dbus_iface = BLUEZ5_NETWORK_INTERFACE; + } else if (priv->bluez_version == 4 && connection_bt_type == NM_BT_CAPABILITY_DUN) { + dbus_iface = BLUEZ4_SERIAL_INTERFACE; + connect_type = BLUETOOTH_CONNECT_DUN; + } else { + g_return_if_fail (priv->bluez_version == 4 && connection_bt_type == NM_BT_CAPABILITY_NAP); + dbus_iface = BLUEZ4_NETWORK_INTERFACE; + } + + simple = g_simple_async_result_new (G_OBJECT (self), + callback, + user_data, + nm_bluez_device_connect_async); + + g_dbus_connection_call (priv->dbus_connection, + BLUEZ_SERVICE, + priv->path, + dbus_iface, + "Connect", + g_variant_new ("(s)", connect_type), + NULL, + G_DBUS_CALL_FLAGS_NONE, + 20000, + NULL, + (GAsyncReadyCallback) bluez_connect_cb, + simple); + + priv->connection_bt_type = connection_bt_type; +} + +const char * +nm_bluez_device_connect_finish (NMBluezDevice *self, + GAsyncResult *result, + GError **error) +{ + GSimpleAsyncResult *simple; + const char *device; + + g_return_val_if_fail (g_simple_async_result_is_valid (result, + G_OBJECT (self), + nm_bluez_device_connect_async), + NULL); + + simple = (GSimpleAsyncResult *) result; + + if (g_simple_async_result_propagate_error (simple, error)) + return NULL; + + device = (const char *) g_simple_async_result_get_op_res_gpointer (simple); + return device; +} + +/***********************************************************/ + +static guint32 +convert_uuids_to_capabilities (const char **strings, int bluez_version) +{ + const char **iter; + guint32 capabilities = 0; + + for (iter = strings; iter && *iter; iter++) { + char **parts; + + parts = g_strsplit (*iter, "-", -1); + if (parts && parts[0]) { + switch (g_ascii_strtoull (parts[0], NULL, 16)) { + case 0x1103: + if (bluez_version == 4) + capabilities |= NM_BT_CAPABILITY_DUN; + break; + case 0x1116: + capabilities |= NM_BT_CAPABILITY_NAP; + break; + default: + break; + } + } + g_strfreev (parts); + } + + return capabilities; +} + +static void +_set_property_capabilities (NMBluezDevice *self, const char **uuids) +{ + guint32 uint_val; + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + + uint_val = convert_uuids_to_capabilities (uuids, priv->bluez_version); + if (priv->capabilities != uint_val) { + if (priv->capabilities) { + /* changing (relevant) capabilities is not supported and ignored -- except setting initially */ + nm_log_warn (LOGD_BT, "bluez[%s] ignore change of capabilities for Bluetooth device from %u to %u", + priv->path, priv->capabilities, uint_val); + return; + } + nm_log_dbg (LOGD_BT, "bluez[%s] set capabilities for Bluetooth device: %s%s%s", priv->path, + uint_val & NM_BT_CAPABILITY_NAP ? "NAP" : "", + ((uint_val & NM_BT_CAPABILITY_DUN) && (uint_val &NM_BT_CAPABILITY_NAP)) ? " | " : "", + uint_val & NM_BT_CAPABILITY_DUN ? "DUN" : ""); + priv->capabilities = uint_val; + g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_CAPABILITIES); + } +} + +/** + * priv->address can only be set one to a certain (non NULL) value. Every later attempt + * to reset it to another value will be ignored and a warning will be logged. + * + * When setting the address for the first time, we also set bin_address. + **/ +static void +_set_property_address (NMBluezDevice *self, const char *addr) +{ + struct ether_addr *tmp; + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + + if (g_strcmp0 (priv->address, addr) == 0) + return; + + if (!addr) { + nm_log_warn (LOGD_BT, "bluez[%s] cannot reset address from '%s' to NULL", priv->path, priv->address); + return; + } + + if (priv->address != NULL) { + nm_log_warn (LOGD_BT, "bluez[%s] cannot reset address from '%s' to '%s'", priv->path, priv->address, addr); + return; + } + + tmp = ether_aton (addr); + if (!tmp) { + if (priv->address) + nm_log_warn (LOGD_BT, "bluez[%s] cannot reset address from '%s' to '%s' (invalid value)", priv->path, priv->address, addr); + else + nm_log_warn (LOGD_BT, "bluez[%s] cannot reset address from NULL to '%s' (invalid value)", priv->path, addr); + return; + } + memcpy (priv->bin_address, tmp->ether_addr_octet, ETH_ALEN); + priv->address = g_strdup (addr); + g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_ADDRESS); +} + +static void +_take_variant_property_address (NMBluezDevice *self, GVariant *v) +{ + _set_property_address (self, VARIANT_IS_OF_TYPE_STRING (v) ? g_variant_get_string (v, NULL) : NULL); + if (v) + g_variant_unref (v); +} + +static void +_take_variant_property_name (NMBluezDevice *self, GVariant *v) +{ + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + const char *str; + + if (VARIANT_IS_OF_TYPE_STRING (v)) { + str = g_variant_get_string (v, NULL); + if (g_strcmp0 (priv->name, str)) { + g_free (priv->name); + priv->name = g_strdup (str); + g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_NAME); + } + } + if (v) + g_variant_unref (v); +} + +static void +_take_variant_property_uuids (NMBluezDevice *self, GVariant *v) +{ + if (VARIANT_IS_OF_TYPE_STRING_ARRAY (v)) { + const char **uuids = g_variant_get_strv (v, NULL); + + _set_property_capabilities (self, uuids); + g_free (uuids); + } + if (v) + g_variant_unref (v); +} + +static void +_take_variant_property_connected (NMBluezDevice *self, GVariant *v) +{ + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + + if (VARIANT_IS_OF_TYPE_BOOLEAN (v)) { + gboolean connected = g_variant_get_boolean (v); + + if (priv->connected != connected) { + priv->connected = connected; + g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_CONNECTED); + } + } + if (v) + g_variant_unref (v); +} + + +static void +adapter5_on_properties_changed (GDBusProxy *proxy, + GVariant *changed_properties, + GStrv invalidated_properties, + gpointer user_data) +{ + NMBluezDevice *self = NM_BLUEZ_DEVICE (user_data); + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + GVariantIter i; + const char *property; + GVariant *v; + + g_variant_iter_init (&i, changed_properties); + while (g_variant_iter_next (&i, "{&sv}", &property, &v)) { + if (!strcmp (property, "Powered") && VARIANT_IS_OF_TYPE_BOOLEAN (v)) { + gboolean powered = g_variant_get_boolean (v); + if (priv->adapter_powered != powered) + priv->adapter_powered = powered; + } + g_variant_unref (v); + } + + check_emit_usable (self); +} + +static void +adapter5_on_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self) +{ + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + GError *error; + GVariant *v; + + priv->adapter5 = g_dbus_proxy_new_for_bus_finish (res, &error); + if (!priv->adapter5) { + nm_log_warn (LOGD_BT, "bluez[%s] failed to acquire adapter proxy: %s.", priv->path, error->message); + g_clear_error (&error); + g_signal_emit (self, signals[INITIALIZED], 0, FALSE); + } else { + g_signal_connect (priv->adapter5, "g-properties-changed", + G_CALLBACK (adapter5_on_properties_changed), self); + + /* Check adapter's powered state */ + v = g_dbus_proxy_get_cached_property (priv->adapter5, "Powered"); + priv->adapter_powered = VARIANT_IS_OF_TYPE_BOOLEAN (v) ? g_variant_get_boolean (v) : FALSE; + if (v) + g_variant_unref (v); + + priv->initialized = TRUE; + g_signal_emit (self, signals[INITIALIZED], 0, TRUE); + + check_emit_usable (self); + } + + g_object_unref (self); +} + +static void +_take_one_variant_property (NMBluezDevice *self, const char *property, GVariant *v) +{ + if (v) { + if (!g_strcmp0 (property, "Address")) + _take_variant_property_address (self, v); + else if (!g_strcmp0 (property, "Connected")) + _take_variant_property_connected (self, v); + else if (!g_strcmp0 (property, "Name")) + _take_variant_property_name (self, v); + else if (!g_strcmp0 (property, "UUIDs")) + _take_variant_property_uuids (self, v); + else + g_variant_unref (v); + } +} + +static void +_set_properties (NMBluezDevice *self, GVariant *properties) +{ + GVariantIter i; + const char *property; + GVariant *v; + + g_object_freeze_notify (G_OBJECT (self)); + g_variant_iter_init (&i, properties); + while (g_variant_iter_next (&i, "{&sv}", &property, &v)) + _take_one_variant_property (self, property, v); + g_object_thaw_notify (G_OBJECT (self)); +} + +static void +properties_changed (GDBusProxy *proxy, + GVariant *changed_properties, + GStrv invalidated_properties, + gpointer user_data) +{ + NMBluezDevice *self = NM_BLUEZ_DEVICE (user_data); + + _set_properties (self, changed_properties); + check_emit_usable (self); +} + +static void +bluez4_property_changed (GDBusProxy *proxy, + const char *sender, + const char *signal_name, + GVariant *parameters, + gpointer user_data) +{ + NMBluezDevice *self = NM_BLUEZ_DEVICE (user_data); + + if (g_strcmp0 (signal_name, "PropertyChanged") == 0) { + const char *property = NULL; + GVariant *v = NULL; + + g_variant_get (parameters, "(&sv)", &property, &v); + _take_one_variant_property (self, property, v); + check_emit_usable (self); + } +} + +static void +get_properties_cb_4 (GObject *source_object, GAsyncResult *res, gpointer user_data) +{ + NMBluezDevice *self = NM_BLUEZ_DEVICE (user_data); + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + GError *err = NULL; + GVariant *v_properties, *v_dict; + GVariantType *v_type; + + v_properties = g_dbus_proxy_call_finish (priv->proxy, res, &err); + if (!v_properties) { + nm_log_warn (LOGD_BT, "bluez[%s] error getting device properties: %s", + priv->path, err && err->message ? err->message : "(unknown)"); + g_error_free (err); + g_signal_emit (self, signals[INITIALIZED], 0, FALSE); + goto END; + } + + v_type = g_variant_type_new ("(a{sv})"); + if (g_variant_is_of_type (v_properties, v_type)) { + v_dict = g_variant_get_child_value (v_properties, 0); + _set_properties (self, v_dict); + g_variant_unref (v_dict); + } else { + nm_log_warn (LOGD_BT, "bluez[%s] GetProperties returns unexpected result of type %s", priv->path, g_variant_get_type_string (v_properties)); + } + g_variant_type_free (v_type); + + g_variant_unref (v_properties); + + /* Check if any connections match this device */ + load_connections (self); + + priv->initialized = TRUE; + g_signal_emit (self, signals[INITIALIZED], 0, TRUE); + + + check_emit_usable (self); + +END: + g_object_unref (self); +} + +static void +query_properties (NMBluezDevice *self) +{ + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + GVariant *v; + + switch (priv->bluez_version) { + case 4: + g_dbus_proxy_call (priv->proxy, "GetProperties", NULL, G_DBUS_CALL_FLAGS_NO_AUTO_START, 3000, + NULL, get_properties_cb_4, g_object_ref (self)); + break; + case 5: + g_object_freeze_notify (G_OBJECT (self)); + _take_variant_property_address (self, g_dbus_proxy_get_cached_property (priv->proxy, "Address")); + _take_variant_property_connected (self, g_dbus_proxy_get_cached_property (priv->proxy, "Connected")); + _take_variant_property_name (self, g_dbus_proxy_get_cached_property (priv->proxy, "Name")); + _take_variant_property_uuids (self, g_dbus_proxy_get_cached_property (priv->proxy, "UUIDs")); + g_object_thaw_notify (G_OBJECT (self)); + + v = g_dbus_proxy_get_cached_property (priv->proxy, "Adapter"); + if (VARIANT_IS_OF_TYPE_OBJECT_PATH (v)) { + g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + BLUEZ_SERVICE, + g_variant_get_string (v, NULL), + BLUEZ5_ADAPTER_INTERFACE, + NULL, + (GAsyncReadyCallback) adapter5_on_acquired, + g_object_ref (self)); + g_variant_unref (v); + } else { + /* If the Adapter property is unset at this point, we won't try to acquire the adapter later on + * and the device stays unusable. This should not happen, but if it does, log a debug message. */ + nm_log_dbg (LOGD_BT, "bluez[%s] device has no adapter property and cannot be used.", priv->path); + } + + /* Check if any connections match this device */ + load_connections (self); + + break; + } +} + +static void +on_proxy_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self) +{ + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + GError *error = NULL; + + priv->proxy = g_dbus_proxy_new_for_bus_finish (res, &error); + + if (!priv->proxy) { + nm_log_warn (LOGD_BT, "bluez[%s] failed to acquire device proxy: %s.", priv->path, error->message); + g_clear_error (&error); + g_signal_emit (self, signals[INITIALIZED], 0, FALSE); + } else { + g_signal_connect (priv->proxy, "g-properties-changed", + G_CALLBACK (properties_changed), self); + if (priv->bluez_version == 4) { + /* Watch for custom Bluez4 PropertyChanged signals */ + g_signal_connect (priv->proxy, "g-signal", + G_CALLBACK (bluez4_property_changed), self); + } + + query_properties (self); + } + g_object_unref (self); +} + +static void +on_bus_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self) +{ + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + GError *error = NULL; + + priv->dbus_connection = g_bus_get_finish (res, &error); + + if (!priv->dbus_connection) { + nm_log_warn (LOGD_BT, "bluez[%s] failed to acquire bus connection: %s.", priv->path, error->message); + g_clear_error (&error); + g_signal_emit (self, signals[INITIALIZED], 0, FALSE); + } else + check_emit_usable (self); + + g_object_unref (self); +} + +/********************************************************************/ + +NMBluezDevice * +nm_bluez_device_new (const char *path, NMConnectionProvider *provider, int bluez_version) +{ + NMBluezDevice *self; + NMBluezDevicePrivate *priv; + const char *interface_name = NULL; + + g_return_val_if_fail (path != NULL, NULL); + g_return_val_if_fail (provider != NULL, NULL); + g_return_val_if_fail (bluez_version == 4 || bluez_version == 5, NULL); + + self = (NMBluezDevice *) g_object_new (NM_TYPE_BLUEZ_DEVICE, + NM_BLUEZ_DEVICE_PATH, path, + NULL); + if (!self) + return NULL; + + nm_log_dbg (LOGD_BT, "bluez[%s] create NMBluezDevice", path); + + priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + + priv->bluez_version = bluez_version; + + priv->provider = provider; + + g_signal_connect (priv->provider, + NM_CP_SIGNAL_CONNECTION_ADDED, + G_CALLBACK (cp_connection_added), + self); + + g_signal_connect (priv->provider, + NM_CP_SIGNAL_CONNECTION_REMOVED, + G_CALLBACK (cp_connection_removed), + self); + + g_signal_connect (priv->provider, + NM_CP_SIGNAL_CONNECTION_UPDATED, + G_CALLBACK (cp_connection_updated), + self); + + g_bus_get (G_BUS_TYPE_SYSTEM, + NULL, + (GAsyncReadyCallback) on_bus_acquired, + g_object_ref (self)); + + switch (priv->bluez_version) { + case 4: + interface_name = BLUEZ4_DEVICE_INTERFACE; + break; + case 5: + interface_name = BLUEZ5_DEVICE_INTERFACE; + break; + } + + g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + BLUEZ_SERVICE, + priv->path, + interface_name, + NULL, + (GAsyncReadyCallback) on_proxy_acquired, + g_object_ref (self)); + return self; +} + +static void +nm_bluez_device_init (NMBluezDevice *self) +{ +} + +static void +dispose (GObject *object) +{ + NMBluezDevice *self = NM_BLUEZ_DEVICE (object); + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + NMConnection *to_delete = NULL; + + if (priv->pan_connection) { + /* Check whether we want to remove the created connection. If so, we take a reference + * and delete it at the end of dispose(). */ + if ( nm_settings_connection_get_unsaved (NM_SETTINGS_CONNECTION (priv->pan_connection)) + && nm_connection_compare (priv->pan_connection, priv->pan_connection_original, NM_SETTING_COMPARE_FLAG_EXACT)) + to_delete = g_object_ref (priv->pan_connection); + + priv->pan_connection = NULL; + g_clear_object (&priv->pan_connection_original); + } + + g_signal_handlers_disconnect_by_func (priv->provider, cp_connection_added, self); + g_signal_handlers_disconnect_by_func (priv->provider, cp_connection_removed, self); + g_signal_handlers_disconnect_by_func (priv->provider, cp_connection_updated, self); + + g_slist_free_full (priv->connections, g_object_unref); + priv->connections = NULL; + + g_clear_object (&priv->adapter5); + g_clear_object (&priv->dbus_connection); + + G_OBJECT_CLASS (nm_bluez_device_parent_class)->dispose (object); + + if (to_delete) { + nm_log_dbg (LOGD_BT, "bluez[%s] removing Bluetooth connection for NAP device: '%s' (%s)", priv->path, + nm_connection_get_id (to_delete), nm_connection_get_uuid (to_delete)); + nm_settings_connection_delete (NM_SETTINGS_CONNECTION (to_delete), NULL, NULL); + g_object_unref (to_delete); + } +} + +static void +finalize (GObject *object) +{ + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (object); + + nm_log_dbg (LOGD_BT, "bluez[%s]: finalize NMBluezDevice", priv->path); + + g_free (priv->path); + g_free (priv->address); + g_free (priv->name); + g_free (priv->bt_iface); + + if (priv->proxy) + g_signal_handlers_disconnect_by_data (priv->proxy, object); + g_clear_object (&priv->proxy); + + G_OBJECT_CLASS (nm_bluez_device_parent_class)->finalize (object); +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (object); + + switch (prop_id) { + case PROP_PATH: + g_value_set_string (value, priv->path); + break; + case PROP_ADDRESS: + g_value_set_string (value, priv->address); + break; + case PROP_NAME: + g_value_set_string (value, priv->name); + break; + case PROP_CAPABILITIES: + g_value_set_uint (value, priv->capabilities); + break; + case PROP_USABLE: + g_value_set_boolean (value, priv->usable); + break; + case PROP_CONNECTED: + g_value_set_boolean (value, priv->connected); + 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) +{ + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (object); + + switch (prop_id) { + case PROP_PATH: + /* construct only */ + priv->path = g_value_dup_string (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_bluez_device_class_init (NMBluezDeviceClass *config_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (config_class); + + g_type_class_add_private (config_class, sizeof (NMBluezDevicePrivate)); + + /* virtual methods */ + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->dispose = dispose; + object_class->finalize = finalize; + + /* Properties */ + g_object_class_install_property + (object_class, PROP_PATH, + g_param_spec_string (NM_BLUEZ_DEVICE_PATH, + "DBus Path", + "DBus Path", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property + (object_class, PROP_ADDRESS, + g_param_spec_string (NM_BLUEZ_DEVICE_ADDRESS, + "Address", + "Address", + NULL, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_NAME, + g_param_spec_string (NM_BLUEZ_DEVICE_NAME, + "Name", + "Name", + NULL, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_CAPABILITIES, + g_param_spec_uint (NM_BLUEZ_DEVICE_CAPABILITIES, + "Capabilities", + "Capabilities", + 0, G_MAXUINT, 0, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_USABLE, + g_param_spec_boolean (NM_BLUEZ_DEVICE_USABLE, + "Usable", + "Usable", + FALSE, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_CONNECTED, + g_param_spec_boolean (NM_BLUEZ_DEVICE_CONNECTED, + "Connected", + "Connected", + FALSE, + G_PARAM_READABLE)); + + /* Signals */ + signals[INITIALIZED] = g_signal_new ("initialized", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (NMBluezDeviceClass, initialized), + NULL, NULL, NULL, + G_TYPE_NONE, 1, G_TYPE_BOOLEAN); + + signals[REMOVED] = g_signal_new (NM_BLUEZ_DEVICE_REMOVED, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (NMBluezDeviceClass, removed), + NULL, NULL, NULL, + G_TYPE_NONE, 0); +} + diff --git a/src/devices/bluetooth/nm-bluez-device.h b/src/devices/bluetooth/nm-bluez-device.h new file mode 100644 index 00000000..0bf7d898 --- /dev/null +++ b/src/devices/bluetooth/nm-bluez-device.h @@ -0,0 +1,98 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2009 - 2014 Red Hat, Inc. + */ + +#ifndef NM_BLUEZ_DEVICE_H +#define NM_BLUEZ_DEVICE_H + +#include +#include +#include + +#include +#include "nm-connection.h" +#include "nm-connection-provider.h" + +#define NM_TYPE_BLUEZ_DEVICE (nm_bluez_device_get_type ()) +#define NM_BLUEZ_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_BLUEZ_DEVICE, NMBluezDevice)) +#define NM_BLUEZ_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_BLUEZ_DEVICE, NMBluezDeviceClass)) +#define NM_IS_BLUEZ_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_BLUEZ_DEVICE)) +#define NM_IS_BLUEZ_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_BLUEZ_DEVICE)) +#define NM_BLUEZ_DEVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_BLUEZ_DEVICE, NMBluezDeviceClass)) + +/* Properties */ +#define NM_BLUEZ_DEVICE_PATH "path" +#define NM_BLUEZ_DEVICE_ADDRESS "address" +#define NM_BLUEZ_DEVICE_NAME "name" +#define NM_BLUEZ_DEVICE_CAPABILITIES "capabilities" +#define NM_BLUEZ_DEVICE_USABLE "usable" +#define NM_BLUEZ_DEVICE_CONNECTED "connected" + +/* Signals */ +#define NM_BLUEZ_DEVICE_REMOVED "removed" + +typedef struct { + GObject parent; +} NMBluezDevice; + +typedef struct { + GObjectClass parent; + + /* virtual functions */ + void (*initialized) (NMBluezDevice *self, gboolean success); + + void (*removed) (NMBluezDevice *self); +} NMBluezDeviceClass; + +GType nm_bluez_device_get_type (void); + +NMBluezDevice *nm_bluez_device_new (const char *path, NMConnectionProvider *provider, int bluez_version); + +const char *nm_bluez_device_get_path (NMBluezDevice *self); + +gboolean nm_bluez_device_get_initialized (NMBluezDevice *self); + +gboolean nm_bluez_device_get_usable (NMBluezDevice *self); + +const char *nm_bluez_device_get_address (NMBluezDevice *self); + +const char *nm_bluez_device_get_name (NMBluezDevice *self); + +guint32 nm_bluez_device_get_class (NMBluezDevice *self); + +guint32 nm_bluez_device_get_capabilities (NMBluezDevice *self); + +gboolean nm_bluez_device_get_connected (NMBluezDevice *self); + +void +nm_bluez_device_connect_async (NMBluezDevice *self, + NMBluetoothCapabilities connection_bt_type, + GAsyncReadyCallback callback, + gpointer user_data); + +const char * +nm_bluez_device_connect_finish (NMBluezDevice *self, + GAsyncResult *result, + GError **error); + +void +nm_bluez_device_disconnect (NMBluezDevice *self); + +#endif /* NM_BLUEZ_DEVICE_H */ + diff --git a/src/devices/bluetooth/nm-bluez-manager.c b/src/devices/bluetooth/nm-bluez-manager.c new file mode 100644 index 00000000..04ffb0a4 --- /dev/null +++ b/src/devices/bluetooth/nm-bluez-manager.c @@ -0,0 +1,428 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2013 - 2014 Red Hat, Inc. + */ + +#include +#include +#include +#include +#include + +#include "nm-logging.h" +#include "nm-bluez-manager.h" +#include "nm-device-factory.h" +#include "nm-bluez4-manager.h" +#include "nm-bluez5-manager.h" +#include "nm-bluez-device.h" +#include "nm-bluez-common.h" +#include "nm-connection-provider.h" +#include "nm-device-bt.h" + +#include "nm-dbus-manager.h" + +typedef struct { + int bluez_version; + + NMConnectionProvider *provider; + NMBluez4Manager *manager4; + NMBluez5Manager *manager5; + + guint watch_name_id; + + GDBusProxy *introspect_proxy; + GCancellable *async_cancellable; +} NMBluezManagerPrivate; + +#define NM_BLUEZ_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_BLUEZ_MANAGER, NMBluezManagerPrivate)) + +static GType nm_bluez_manager_get_type (void); + +static void device_factory_interface_init (NMDeviceFactory *factory_iface); + +G_DEFINE_TYPE_EXTENDED (NMBluezManager, nm_bluez_manager, G_TYPE_OBJECT, 0, + G_IMPLEMENT_INTERFACE (NM_TYPE_DEVICE_FACTORY, device_factory_interface_init)) + +static void check_bluez_and_try_setup (NMBluezManager *self); + +/**************************************************************************/ + +#define PLUGIN_TYPE NM_DEVICE_TYPE_BT + +G_MODULE_EXPORT NMDeviceFactory * +nm_device_factory_create (GError **error) +{ + return (NMDeviceFactory *) g_object_new (NM_TYPE_BLUEZ_MANAGER, NULL); +} + +G_MODULE_EXPORT NMDeviceType +nm_device_factory_get_device_type (void) +{ + return PLUGIN_TYPE; +} + +/************************************************************************/ + +struct AsyncData { + NMBluezManager *self; + GCancellable *async_cancellable; +}; + +static struct AsyncData * +async_data_pack (NMBluezManager *self) +{ + struct AsyncData *data = g_new (struct AsyncData, 1); + + data->self = self; + data->async_cancellable = g_object_ref (NM_BLUEZ_MANAGER_GET_PRIVATE (self)->async_cancellable); + return data; +} + +static NMBluezManager * +async_data_unpack (struct AsyncData *async_data) +{ + NMBluezManager *self = g_cancellable_is_cancelled (async_data->async_cancellable) + ? NULL : async_data->self; + + g_object_unref (async_data->async_cancellable); + g_free (async_data); + return self; +} + + +/** + * Cancel any current attempt to detect the version and cleanup + * the related fields. + **/ +static void +cleanup_checking (NMBluezManager *self, gboolean do_unwatch_name) +{ + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + + if (priv->async_cancellable) { + g_cancellable_cancel (priv->async_cancellable); + g_clear_object (&priv->async_cancellable); + } + + g_clear_object (&priv->introspect_proxy); + + if (do_unwatch_name && priv->watch_name_id) { + g_bus_unwatch_name (priv->watch_name_id); + priv->watch_name_id = 0; + } +} + + +static void +manager_bdaddr_added_cb (NMBluez4Manager *bluez_mgr, + NMBluezDevice *bt_device, + const char *bdaddr, + const char *name, + const char *object_path, + guint32 capabilities, + gpointer user_data) +{ + NMBluezManager *self = NM_BLUEZ_MANAGER (user_data); + NMDevice *device; + gboolean has_dun = (capabilities & NM_BT_CAPABILITY_DUN); + gboolean has_nap = (capabilities & NM_BT_CAPABILITY_NAP); + + g_return_if_fail (bdaddr != NULL); + g_return_if_fail (name != NULL); + g_return_if_fail (object_path != NULL); + g_return_if_fail (capabilities != NM_BT_CAPABILITY_NONE); + g_return_if_fail (NM_IS_BLUEZ_DEVICE (bt_device)); + + device = nm_device_bt_new (bt_device, object_path, bdaddr, name, capabilities); + if (!device) + return; + + nm_log_info (LOGD_BT, "BT device %s (%s) added (%s%s%s)", + name, + bdaddr, + has_dun ? "DUN" : "", + has_dun && has_nap ? " " : "", + has_nap ? "NAP" : ""); + g_signal_emit_by_name (self, NM_DEVICE_FACTORY_DEVICE_ADDED, device); + g_object_unref (device); +} + +static void +setup_version_number (NMBluezManager *self, int bluez_version) +{ + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + + g_return_if_fail (!priv->bluez_version); + + nm_log_info (LOGD_BT, "use BlueZ version %d", bluez_version); + + priv->bluez_version = bluez_version; + + /* Just detected the version. Cleanup the ongoing checking/detection. */ + cleanup_checking (self, TRUE); +} + +static void +setup_bluez4 (NMBluezManager *self) +{ + NMBluez4Manager *manager; + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + + g_return_if_fail (!priv->manager4 && !priv->manager5 && !priv->bluez_version); + + setup_version_number (self, 4); + priv->manager4 = manager = nm_bluez4_manager_new (priv->provider); + + g_signal_connect (manager, + NM_BLUEZ_MANAGER_BDADDR_ADDED, + G_CALLBACK (manager_bdaddr_added_cb), + self); + + nm_bluez4_manager_query_devices (manager); +} + +static void +setup_bluez5 (NMBluezManager *self) +{ + NMBluez5Manager *manager; + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + + g_return_if_fail (!priv->manager4 && !priv->manager5 && !priv->bluez_version); + + setup_version_number (self, 5); + priv->manager5 = manager = nm_bluez5_manager_new (priv->provider); + + g_signal_connect (manager, + NM_BLUEZ_MANAGER_BDADDR_ADDED, + G_CALLBACK (manager_bdaddr_added_cb), + self); + + nm_bluez5_manager_query_devices (manager); +} + + +static void +watch_name_on_appeared (GDBusConnection *connection, + const gchar *name, + const gchar *name_owner, + gpointer user_data) +{ + check_bluez_and_try_setup (NM_BLUEZ_MANAGER (user_data)); +} + + +static void +check_bluez_and_try_setup_final_step (NMBluezManager *self, int bluez_version, const char *reason) +{ + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + + g_return_if_fail (!priv->bluez_version); + + switch (bluez_version) { + case 4: + setup_bluez4 (self); + break; + case 5: + setup_bluez5 (self); + break; + default: + nm_log_dbg (LOGD_BT, "detecting BlueZ version failed: %s", reason); + + /* cancel current attempts to detect the version. */ + cleanup_checking (self, FALSE); + if (!priv->watch_name_id) { + priv->watch_name_id = g_bus_watch_name (G_BUS_TYPE_SYSTEM, + BLUEZ_SERVICE, + G_BUS_NAME_WATCHER_FLAGS_NONE, + watch_name_on_appeared, + NULL, + self, + NULL); + } + break; + } +} + +static void +check_bluez_and_try_setup_do_introspect (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + NMBluezManager *self = async_data_unpack (user_data); + NMBluezManagerPrivate *priv; + GError *error = NULL; + GVariant *result; + const char *xml_data; + int bluez_version = 0; + const char *reason = NULL; + + if (!self) + return; + + priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + + g_return_if_fail (priv->introspect_proxy); + g_return_if_fail (!g_cancellable_is_cancelled (priv->async_cancellable)); + g_return_if_fail (!priv->bluez_version); + + g_clear_object (&priv->async_cancellable); + + result = g_dbus_proxy_call_finish (priv->introspect_proxy, res, &error); + + if (!result) { + char *reason2 = g_strdup_printf ("introspect failed with %s", error->message); + check_bluez_and_try_setup_final_step (self, 0, reason2); + g_error_free (error); + g_free (reason2); + return; + } + + g_variant_get (result, "(&s)", &xml_data); + + /* might not be the best approach to detect the version, but it's good enough in practice. */ + if (strstr (xml_data, "org.freedesktop.DBus.ObjectManager")) + bluez_version = 5; + else if (strstr (xml_data, BLUEZ4_MANAGER_INTERFACE)) + bluez_version = 4; + else + reason = "unexpected introspect result"; + + g_variant_unref (result); + + check_bluez_and_try_setup_final_step (self, bluez_version, reason); +} + +static void +check_bluez_and_try_setup_on_new_proxy (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + NMBluezManager *self = async_data_unpack (user_data); + NMBluezManagerPrivate *priv; + GError *error = NULL; + + if (!self) + return; + + priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + + g_return_if_fail (!priv->introspect_proxy); + g_return_if_fail (!g_cancellable_is_cancelled (priv->async_cancellable)); + g_return_if_fail (!priv->bluez_version); + + priv->introspect_proxy = g_dbus_proxy_new_for_bus_finish (res, &error); + + if (!priv->introspect_proxy) { + char *reason = g_strdup_printf ("bluez error creating dbus proxy: %s", error->message); + check_bluez_and_try_setup_final_step (self, 0, reason); + g_error_free (error); + g_free (reason); + return; + } + + g_dbus_proxy_call (priv->introspect_proxy, + "Introspect", + NULL, + G_DBUS_CALL_FLAGS_NO_AUTO_START, + 3000, + priv->async_cancellable, + check_bluez_and_try_setup_do_introspect, + async_data_pack (self)); +} + +static void +check_bluez_and_try_setup (NMBluezManager *self) +{ + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + + g_return_if_fail (!priv->bluez_version); + + /* there should be no ongoing detection. Anyway, cleanup_checking. */ + cleanup_checking (self, FALSE); + + priv->async_cancellable = g_cancellable_new (); + + g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, + NULL, + BLUEZ_SERVICE, + "/", + DBUS_INTERFACE_INTROSPECTABLE, + priv->async_cancellable, + check_bluez_and_try_setup_on_new_proxy, + async_data_pack (self)); +} + +/*********************************************************************/ + +static void +dispose (GObject *object) +{ + NMBluezManager *self = NM_BLUEZ_MANAGER (object); + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + + if (priv->manager4) { + g_signal_handlers_disconnect_by_func (priv->manager4, manager_bdaddr_added_cb, self); + g_clear_object (&priv->manager4); + } + if (priv->manager5) { + g_signal_handlers_disconnect_by_func (priv->manager5, manager_bdaddr_added_cb, self); + g_clear_object (&priv->manager5); + } + + cleanup_checking (self, TRUE); + + priv->bluez_version = 0; +} + +static void +constructed (GObject *object) +{ + NMBluezManager *self = NM_BLUEZ_MANAGER (object); + + G_OBJECT_CLASS (nm_bluez_manager_parent_class)->constructed (object); + + check_bluez_and_try_setup (self); +} + +static void +nm_bluez_manager_init (NMBluezManager *self) +{ + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + + priv->provider = nm_connection_provider_get (); + g_assert (priv->provider); +} + +static void +device_factory_interface_init (NMDeviceFactory *factory_iface) +{ +} + +static void +nm_bluez_manager_class_init (NMBluezManagerClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (NMBluezManagerPrivate)); + + /* virtual methods */ + object_class->dispose = dispose; + object_class->constructed = constructed; +} + diff --git a/src/devices/bluetooth/nm-bluez-manager.h b/src/devices/bluetooth/nm-bluez-manager.h new file mode 100644 index 00000000..68d6dbe5 --- /dev/null +++ b/src/devices/bluetooth/nm-bluez-manager.h @@ -0,0 +1,44 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2007 - 2008 Novell, Inc. + * Copyright (C) 2007 - 2014 Red Hat, Inc. + */ + +#ifndef NM_BLUEZ_MANAGER_H +#define NM_BLUEZ_MANAGER_H + +#include +#include + +G_BEGIN_DECLS + +#define NM_TYPE_BLUEZ_MANAGER (nm_bluez_manager_get_type ()) +#define NM_BLUEZ_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_BLUEZ_MANAGER, NMBluezManager)) + +#define NM_BLUEZ_MANAGER_BDADDR_ADDED "bdaddr-added" + +typedef struct { + GObject parent; +} NMBluezManager; + +typedef struct { + GObjectClass parent; +} NMBluezManagerClass; + +#endif /* NM_BLUEZ_MANAGER_H */ + diff --git a/src/devices/bluetooth/nm-bluez4-adapter.c b/src/devices/bluetooth/nm-bluez4-adapter.c new file mode 100644 index 00000000..ad1786f0 --- /dev/null +++ b/src/devices/bluetooth/nm-bluez4-adapter.c @@ -0,0 +1,413 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2009 - 2012 Red Hat, Inc. + */ + +#include +#include + +#include "NetworkManager.h" +#include "nm-dbus-manager.h" +#include "nm-bluez4-adapter.h" +#include "nm-bluez-device.h" +#include "nm-bluez-common.h" +#include "nm-dbus-glib-types.h" +#include "nm-logging.h" + + +G_DEFINE_TYPE (NMBluez4Adapter, nm_bluez4_adapter, G_TYPE_OBJECT) + +#define NM_BLUEZ4_ADAPTER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_BLUEZ4_ADAPTER, NMBluez4AdapterPrivate)) + +typedef struct { + char *path; + DBusGProxy *proxy; + gboolean initialized; + + char *address; + GHashTable *devices; + + /* Cached for devices */ + NMConnectionProvider *provider; +} NMBluez4AdapterPrivate; + + +enum { + PROP_0, + PROP_PATH, + PROP_ADDRESS, + + LAST_PROP +}; + +/* Signals */ +enum { + INITIALIZED, + DEVICE_ADDED, + DEVICE_REMOVED, + LAST_SIGNAL +}; +static guint signals[LAST_SIGNAL] = { 0 }; + +static void device_do_remove (NMBluez4Adapter *self, NMBluezDevice *device); + +const char * +nm_bluez4_adapter_get_path (NMBluez4Adapter *self) +{ + g_return_val_if_fail (NM_IS_BLUEZ4_ADAPTER (self), NULL); + + return NM_BLUEZ4_ADAPTER_GET_PRIVATE (self)->path; +} + +const char * +nm_bluez4_adapter_get_address (NMBluez4Adapter *self) +{ + g_return_val_if_fail (NM_IS_BLUEZ4_ADAPTER (self), NULL); + + return NM_BLUEZ4_ADAPTER_GET_PRIVATE (self)->address; +} + +gboolean +nm_bluez4_adapter_get_initialized (NMBluez4Adapter *self) +{ + g_return_val_if_fail (NM_IS_BLUEZ4_ADAPTER (self), FALSE); + + return NM_BLUEZ4_ADAPTER_GET_PRIVATE (self)->initialized; +} + +GSList * +nm_bluez4_adapter_get_devices (NMBluez4Adapter *self) +{ + GSList *devices = NULL; + GHashTableIter iter; + NMBluezDevice *device; + + g_hash_table_iter_init (&iter, NM_BLUEZ4_ADAPTER_GET_PRIVATE (self)->devices); + while (g_hash_table_iter_next (&iter, NULL, (gpointer) &device)) { + if (nm_bluez_device_get_usable (device)) + devices = g_slist_append (devices, device); + } + return devices; +} + +static void +emit_device_removed (NMBluez4Adapter *self, NMBluezDevice *device) +{ + nm_log_dbg (LOGD_BT, "(%s): bluez device now unusable", + nm_bluez_device_get_path (device)); + g_signal_emit (self, signals[DEVICE_REMOVED], 0, device); +} + +static void +device_usable (NMBluezDevice *device, GParamSpec *pspec, gpointer user_data) +{ + NMBluez4Adapter *self = NM_BLUEZ4_ADAPTER (user_data); + + if (nm_bluez_device_get_usable (device)) { + nm_log_dbg (LOGD_BT, "(%s): bluez device now usable (device address is %s)", + nm_bluez_device_get_path (device), + nm_bluez_device_get_address (device)); + g_signal_emit (self, signals[DEVICE_ADDED], 0, device); + } else + emit_device_removed (self, device); +} + +static void +device_initialized (NMBluezDevice *device, gboolean success, gpointer user_data) +{ + NMBluez4Adapter *self = NM_BLUEZ4_ADAPTER (user_data); + + nm_log_dbg (LOGD_BT, "(%s): bluez device %s", + nm_bluez_device_get_path (device), + success ? "initialized" : "failed to initialize"); + if (!success) + device_do_remove (self, device); +} + +static void +device_do_remove (NMBluez4Adapter *self, NMBluezDevice *device) +{ + NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self); + + if (g_hash_table_remove (priv->devices, nm_bluez_device_get_path (device))) { + g_signal_handlers_disconnect_by_func (device, G_CALLBACK (device_initialized), self); + g_signal_handlers_disconnect_by_func (device, G_CALLBACK (device_usable), self); + + if (nm_bluez_device_get_usable (device)) + emit_device_removed (self, device); + + g_object_unref (device); + } +} + +static void +device_created (DBusGProxy *proxy, const char *path, gpointer user_data) +{ + NMBluez4Adapter *self = NM_BLUEZ4_ADAPTER (user_data); + NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self); + NMBluezDevice *device; + + device = nm_bluez_device_new (path, priv->provider, 4); + g_signal_connect (device, "initialized", G_CALLBACK (device_initialized), self); + g_signal_connect (device, "notify::usable", G_CALLBACK (device_usable), self); + g_hash_table_insert (priv->devices, (gpointer) nm_bluez_device_get_path (device), device); + + nm_log_dbg (LOGD_BT, "(%s): new bluez device found", path); +} + +static void +device_removed (DBusGProxy *proxy, const char *path, gpointer user_data) +{ + NMBluez4Adapter *self = NM_BLUEZ4_ADAPTER (user_data); + NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self); + NMBluezDevice *device; + + nm_log_dbg (LOGD_BT, "(%s): bluez device removed", path); + + device = g_hash_table_lookup (priv->devices, path); + if (device) + device_do_remove (self, device); +} + + +static void +get_properties_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) +{ + NMBluez4Adapter *self = NM_BLUEZ4_ADAPTER (user_data); + NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self); + GHashTable *properties = NULL; + GError *err = NULL; + GValue *value; + GPtrArray *devices; + int i; + + if (!dbus_g_proxy_end_call (proxy, call, &err, + DBUS_TYPE_G_MAP_OF_VARIANT, &properties, + G_TYPE_INVALID)) { + nm_log_warn (LOGD_BT, "bluez error getting adapter properties: %s", + err && err->message ? err->message : "(unknown)"); + g_error_free (err); + goto done; + } + + value = g_hash_table_lookup (properties, "Address"); + priv->address = value ? g_value_dup_string (value) : NULL; + + value = g_hash_table_lookup (properties, "Devices"); + devices = value ? g_value_get_boxed (value) : NULL; + + for (i = 0; devices && i < devices->len; i++) + device_created (priv->proxy, g_ptr_array_index (devices, i), self); + + g_hash_table_unref (properties); + + priv->initialized = TRUE; + +done: + g_signal_emit (self, signals[INITIALIZED], 0, priv->initialized); +} + +static void +query_properties (NMBluez4Adapter *self) +{ + NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self); + DBusGProxyCall *call; + + call = dbus_g_proxy_begin_call (priv->proxy, "GetProperties", + get_properties_cb, + self, + NULL, G_TYPE_INVALID); + if (!call) { + nm_log_warn (LOGD_BT, "failed to request Bluetooth adapter properties for %s.", + priv->path); + } +} + +/***********************************************************/ + +NMBluez4Adapter * +nm_bluez4_adapter_new (const char *path, NMConnectionProvider *provider) +{ + NMBluez4Adapter *self; + NMBluez4AdapterPrivate *priv; + DBusGConnection *connection; + + self = (NMBluez4Adapter *) g_object_new (NM_TYPE_BLUEZ4_ADAPTER, + NM_BLUEZ4_ADAPTER_PATH, path, + NULL); + if (!self) + return NULL; + + priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self); + + priv->provider = provider; + + connection = nm_dbus_manager_get_connection (nm_dbus_manager_get ()); + + priv->proxy = dbus_g_proxy_new_for_name (connection, + BLUEZ_SERVICE, + priv->path, + BLUEZ4_ADAPTER_INTERFACE); + + dbus_g_proxy_add_signal (priv->proxy, "DeviceCreated", + DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID); + dbus_g_proxy_connect_signal (priv->proxy, "DeviceCreated", + G_CALLBACK (device_created), self, NULL); + + dbus_g_proxy_add_signal (priv->proxy, "DeviceRemoved", + DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID); + dbus_g_proxy_connect_signal (priv->proxy, "DeviceRemoved", + G_CALLBACK (device_removed), self, NULL); + + query_properties (self); + return self; +} + +static void +nm_bluez4_adapter_init (NMBluez4Adapter *self) +{ + NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self); + + priv->devices = g_hash_table_new_full (g_str_hash, g_str_equal, + NULL, NULL); +} + +static gboolean +_find_all (gpointer key, gpointer value, gpointer user_data) +{ + return TRUE; +} + +static void +dispose (GObject *object) +{ + NMBluez4Adapter *self = NM_BLUEZ4_ADAPTER (object); + NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self); + NMBluezDevice *device; + + while ((device = g_hash_table_find (priv->devices, _find_all, NULL))) + device_do_remove (self, device); + + G_OBJECT_CLASS (nm_bluez4_adapter_parent_class)->dispose (object); +} + +static void +finalize (GObject *object) +{ + NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (object); + + g_hash_table_destroy (priv->devices); + g_free (priv->address); + g_free (priv->path); + g_object_unref (priv->proxy); + + G_OBJECT_CLASS (nm_bluez4_adapter_parent_class)->finalize (object); +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (object); + + switch (prop_id) { + case PROP_PATH: + g_value_set_string (value, priv->path); + break; + case PROP_ADDRESS: + g_value_set_string (value, priv->address); + 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) +{ + NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (object); + + switch (prop_id) { + case PROP_PATH: + /* construct only */ + priv->path = g_value_dup_string (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_bluez4_adapter_class_init (NMBluez4AdapterClass *config_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (config_class); + + g_type_class_add_private (config_class, sizeof (NMBluez4AdapterPrivate)); + + /* virtual methods */ + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->dispose = dispose; + object_class->finalize = finalize; + + /* Properties */ + g_object_class_install_property + (object_class, PROP_PATH, + g_param_spec_string (NM_BLUEZ4_ADAPTER_PATH, + "DBus Path", + "DBus Path", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property + (object_class, PROP_ADDRESS, + g_param_spec_string (NM_BLUEZ4_ADAPTER_ADDRESS, + "Address", + "Address", + NULL, + G_PARAM_READABLE)); + + /* Signals */ + signals[INITIALIZED] = g_signal_new ("initialized", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (NMBluez4AdapterClass, initialized), + NULL, NULL, + g_cclosure_marshal_VOID__BOOLEAN, + G_TYPE_NONE, 1, G_TYPE_BOOLEAN); + + signals[DEVICE_ADDED] = g_signal_new ("device-added", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (NMBluez4AdapterClass, device_added), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, G_TYPE_OBJECT); + + signals[DEVICE_REMOVED] = g_signal_new ("device-removed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (NMBluez4AdapterClass, device_removed), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, G_TYPE_OBJECT); +} + diff --git a/src/devices/bluetooth/nm-bluez4-adapter.h b/src/devices/bluetooth/nm-bluez4-adapter.h new file mode 100644 index 00000000..454ca557 --- /dev/null +++ b/src/devices/bluetooth/nm-bluez4-adapter.h @@ -0,0 +1,69 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2009 - 2012 Red Hat, Inc. + */ + +#ifndef NM_BLUEZ4_ADAPTER_H +#define NM_BLUEZ4_ADAPTER_H + +#include +#include + +#include "nm-bluez-device.h" +#include "nm-connection-provider.h" + +#define NM_TYPE_BLUEZ4_ADAPTER (nm_bluez4_adapter_get_type ()) +#define NM_BLUEZ4_ADAPTER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_BLUEZ4_ADAPTER, NMBluez4Adapter)) +#define NM_BLUEZ4_ADAPTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_BLUEZ4_ADAPTER, NMBluez4AdapterClass)) +#define NM_IS_BLUEZ4_ADAPTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_BLUEZ4_ADAPTER)) +#define NM_IS_BLUEZ4_ADAPTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_BLUEZ4_ADAPTER)) +#define NM_BLUEZ4_ADAPTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_BLUEZ4_ADAPTER, NMBluez4AdapterClass)) + +#define NM_BLUEZ4_ADAPTER_PATH "path" +#define NM_BLUEZ4_ADAPTER_ADDRESS "address" + +typedef struct { + GObject parent; +} NMBluez4Adapter; + +typedef struct { + GObjectClass parent; + + /* virtual functions */ + void (*initialized) (NMBluez4Adapter *self, gboolean success); + + void (*device_added) (NMBluez4Adapter *self, NMBluezDevice *device); + + void (*device_removed) (NMBluez4Adapter *self, NMBluezDevice *device); +} NMBluez4AdapterClass; + +GType nm_bluez4_adapter_get_type (void); + +NMBluez4Adapter *nm_bluez4_adapter_new (const char *path, + NMConnectionProvider *provider); + +const char *nm_bluez4_adapter_get_path (NMBluez4Adapter *self); + +const char *nm_bluez4_adapter_get_address (NMBluez4Adapter *self); + +gboolean nm_bluez4_adapter_get_initialized (NMBluez4Adapter *self); + +GSList *nm_bluez4_adapter_get_devices (NMBluez4Adapter *self); + +#endif /* NM_BLUEZ4_ADAPTER_H */ + diff --git a/src/devices/bluetooth/nm-bluez4-manager.c b/src/devices/bluetooth/nm-bluez4-manager.c new file mode 100644 index 00000000..2660cbd9 --- /dev/null +++ b/src/devices/bluetooth/nm-bluez4-manager.c @@ -0,0 +1,361 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2007 - 2008 Novell, Inc. + * Copyright (C) 2007 - 2013 Red Hat, Inc. + */ + +#include +#include +#include +#include + +#include "nm-logging.h" +#include "nm-dbus-glib-types.h" +#include "nm-bluez-manager.h" +#include "nm-bluez4-manager.h" +#include "nm-bluez4-adapter.h" +#include "nm-dbus-manager.h" +#include "nm-bluez-common.h" + + +typedef struct { + NMDBusManager *dbus_mgr; + gulong name_owner_changed_id; + + NMConnectionProvider *provider; + + DBusGProxy *proxy; + + NMBluez4Adapter *adapter; +} NMBluez4ManagerPrivate; + +#define NM_BLUEZ4_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_BLUEZ4_MANAGER, NMBluez4ManagerPrivate)) + +G_DEFINE_TYPE (NMBluez4Manager, nm_bluez4_manager, G_TYPE_OBJECT) + +enum { + BDADDR_ADDED, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +static void + +emit_bdaddr_added (NMBluez4Manager *self, NMBluezDevice *device) +{ + g_signal_emit (self, signals[BDADDR_ADDED], 0, + device, + nm_bluez_device_get_address (device), + nm_bluez_device_get_name (device), + nm_bluez_device_get_path (device), + nm_bluez_device_get_capabilities (device)); +} + +void +nm_bluez4_manager_query_devices (NMBluez4Manager *self) +{ + NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); + GSList *devices, *iter; + + if (!priv->adapter) + return; + + devices = nm_bluez4_adapter_get_devices (priv->adapter); + for (iter = devices; iter; iter = g_slist_next (iter)) + emit_bdaddr_added (self, NM_BLUEZ_DEVICE (iter->data)); + g_slist_free (devices); +} + +static void +device_added (NMBluez4Adapter *adapter, NMBluezDevice *device, gpointer user_data) +{ + emit_bdaddr_added (NM_BLUEZ4_MANAGER (user_data), device); +} + +static void +device_removed (NMBluez4Adapter *adapter, NMBluezDevice *device, gpointer user_data) +{ + /* Re-emit the signal on the device for now; flatten this later */ + g_signal_emit_by_name (device, NM_BLUEZ_DEVICE_REMOVED); +} + +static void +adapter_initialized (NMBluez4Adapter *adapter, gboolean success, gpointer user_data) +{ + NMBluez4Manager *self = NM_BLUEZ4_MANAGER (user_data); + NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); + + if (success) { + GSList *devices, *iter; + + devices = nm_bluez4_adapter_get_devices (adapter); + for (iter = devices; iter; iter = g_slist_next (iter)) + emit_bdaddr_added (self, NM_BLUEZ_DEVICE (iter->data)); + g_slist_free (devices); + + g_signal_connect (adapter, "device-added", G_CALLBACK (device_added), self); + g_signal_connect (adapter, "device-removed", G_CALLBACK (device_removed), self); + } else { + g_object_unref (priv->adapter); + priv->adapter = NULL; + } +} + +static void +adapter_removed (DBusGProxy *proxy, const char *path, NMBluez4Manager *self) +{ + NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); + + if (priv->adapter && !strcmp (path, nm_bluez4_adapter_get_path (priv->adapter))) { + if (nm_bluez4_adapter_get_initialized (priv->adapter)) { + GSList *devices, *iter; + + devices = nm_bluez4_adapter_get_devices (priv->adapter); + for (iter = devices; iter; iter = g_slist_next (iter)) + g_signal_emit_by_name (NM_BLUEZ_DEVICE (iter->data), NM_BLUEZ_DEVICE_REMOVED); + g_slist_free (devices); + } + + g_object_unref (priv->adapter); + priv->adapter = NULL; + } +} + +static void +default_adapter_changed (DBusGProxy *proxy, const char *path, NMBluez4Manager *self) +{ + NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); + const char *cur_path = NULL; + + if (priv->adapter) + cur_path = nm_bluez4_adapter_get_path (priv->adapter); + + if (cur_path) { + if (!path || strcmp (path, cur_path)) { + /* Default adapter changed */ + adapter_removed (priv->proxy, cur_path, self); + } else { + /* This adapter is already the default */ + return; + } + } + + /* Add the new default adapter */ + if (path) { + priv->adapter = nm_bluez4_adapter_new (path, priv->provider); + g_signal_connect (priv->adapter, "initialized", G_CALLBACK (adapter_initialized), self); + } +} + +static void +default_adapter_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) +{ + NMBluez4Manager *self = NM_BLUEZ4_MANAGER (user_data); + NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); + const char *default_adapter = NULL; + GError *err = NULL; + + if (!dbus_g_proxy_end_call (proxy, call, &err, + DBUS_TYPE_G_OBJECT_PATH, &default_adapter, + G_TYPE_INVALID)) { + /* Ignore "No such adapter" errors; just means bluetooth isn't active */ + if ( !dbus_g_error_has_name (err, "org.bluez.Error.NoSuchAdapter") + && !dbus_g_error_has_name (err, "org.freedesktop.systemd1.LoadFailed") + && !g_error_matches (err, DBUS_GERROR, DBUS_GERROR_SERVICE_UNKNOWN)) { + nm_log_warn (LOGD_BT, "bluez error getting default adapter: %s", + err && err->message ? err->message : "(unknown)"); + } + g_error_free (err); + return; + } + + default_adapter_changed (priv->proxy, default_adapter, self); +} + +static void +query_default_adapter (NMBluez4Manager *self) +{ + NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); + DBusGProxyCall *call; + + call = dbus_g_proxy_begin_call (priv->proxy, "DefaultAdapter", + default_adapter_cb, + self, + NULL, G_TYPE_INVALID); + if (!call) + nm_log_warn (LOGD_BT, "failed to request default Bluetooth adapter."); +} + +static void +bluez_connect (NMBluez4Manager *self) +{ + NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); + DBusGConnection *connection; + + g_return_if_fail (priv->proxy == NULL); + + connection = nm_dbus_manager_get_connection (priv->dbus_mgr); + if (!connection) + return; + + priv->proxy = dbus_g_proxy_new_for_name (connection, + BLUEZ_SERVICE, + BLUEZ_MANAGER_PATH, + BLUEZ4_MANAGER_INTERFACE); + + dbus_g_proxy_add_signal (priv->proxy, "AdapterRemoved", + DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID); + dbus_g_proxy_connect_signal (priv->proxy, "AdapterRemoved", + G_CALLBACK (adapter_removed), self, NULL); + + dbus_g_proxy_add_signal (priv->proxy, "DefaultAdapterChanged", + DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID); + dbus_g_proxy_connect_signal (priv->proxy, "DefaultAdapterChanged", + G_CALLBACK (default_adapter_changed), self, NULL); + + query_default_adapter (self); +} + +static void +name_owner_changed_cb (NMDBusManager *dbus_mgr, + const char *name, + const char *old_owner, + const char *new_owner, + gpointer user_data) +{ + NMBluez4Manager *self = NM_BLUEZ4_MANAGER (user_data); + NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); + gboolean old_owner_good = (old_owner && strlen (old_owner)); + gboolean new_owner_good = (new_owner && strlen (new_owner)); + + /* Can't handle the signal if its not from the Bluez */ + if (strcmp (BLUEZ_SERVICE, name)) + return; + + if (!old_owner_good && new_owner_good) + query_default_adapter (self); + else if (old_owner_good && !new_owner_good) { + /* Throwing away the adapter removes all devices too */ + if (priv->adapter) { + g_object_unref (priv->adapter); + priv->adapter = NULL; + } + } +} + +static void +bluez_cleanup (NMBluez4Manager *self, gboolean do_signal) +{ + NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); + + if (priv->proxy) { + g_object_unref (priv->proxy); + priv->proxy = NULL; + } + + if (priv->adapter) { + g_object_unref (priv->adapter); + priv->adapter = NULL; + } +} + +static void +dbus_connection_changed_cb (NMDBusManager *dbus_mgr, + DBusGConnection *connection, + gpointer user_data) +{ + NMBluez4Manager *self = NM_BLUEZ4_MANAGER (user_data); + + if (!connection) + bluez_cleanup (self, TRUE); + else + bluez_connect (self); +} + +/****************************************************************/ + +NMBluez4Manager * +nm_bluez4_manager_new (NMConnectionProvider *provider) +{ + NMBluez4Manager *instance; + + instance = g_object_new (NM_TYPE_BLUEZ4_MANAGER, NULL); + NM_BLUEZ4_MANAGER_GET_PRIVATE (instance)->provider = provider; + return instance; +} + +static void +nm_bluez4_manager_init (NMBluez4Manager *self) +{ + NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); + + priv->dbus_mgr = nm_dbus_manager_get (); + g_assert (priv->dbus_mgr); + + g_signal_connect (priv->dbus_mgr, + NM_DBUS_MANAGER_NAME_OWNER_CHANGED, + G_CALLBACK (name_owner_changed_cb), + self); + + g_signal_connect (priv->dbus_mgr, + NM_DBUS_MANAGER_DBUS_CONNECTION_CHANGED, + G_CALLBACK (dbus_connection_changed_cb), + self); + + bluez_connect (self); +} + +static void +dispose (GObject *object) +{ + NMBluez4Manager *self = NM_BLUEZ4_MANAGER (object); + NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); + + bluez_cleanup (self, FALSE); + + if (priv->dbus_mgr) { + g_signal_handlers_disconnect_by_func (priv->dbus_mgr, name_owner_changed_cb, self); + g_signal_handlers_disconnect_by_func (priv->dbus_mgr, dbus_connection_changed_cb, self); + priv->dbus_mgr = NULL; + } + + G_OBJECT_CLASS (nm_bluez4_manager_parent_class)->dispose (object); +} + +static void +nm_bluez4_manager_class_init (NMBluez4ManagerClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (NMBluez4ManagerPrivate)); + + /* virtual methods */ + object_class->dispose = dispose; + + /* Signals */ + signals[BDADDR_ADDED] = + g_signal_new (NM_BLUEZ_MANAGER_BDADDR_ADDED, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMBluez4ManagerClass, bdaddr_added), + NULL, NULL, NULL, + G_TYPE_NONE, 5, G_TYPE_OBJECT, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT); +} + diff --git a/src/devices/bluetooth/nm-bluez4-manager.h b/src/devices/bluetooth/nm-bluez4-manager.h new file mode 100644 index 00000000..19b1c65a --- /dev/null +++ b/src/devices/bluetooth/nm-bluez4-manager.h @@ -0,0 +1,62 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2007 - 2008 Novell, Inc. + * Copyright (C) 2007 - 2013 Red Hat, Inc. + */ + +#ifndef NM_BLUEZ4_MANAGER_H +#define NM_BLUEZ4_MANAGER_H + +#include +#include + +#include +#include "nm-connection-provider.h" + +G_BEGIN_DECLS + +#define NM_TYPE_BLUEZ4_MANAGER (nm_bluez4_manager_get_type ()) +#define NM_BLUEZ4_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_BLUEZ4_MANAGER, NMBluez4Manager)) +#define NM_BLUEZ4_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_BLUEZ4_MANAGER, NMBluez4ManagerClass)) +#define NM_IS_BLUEZ4_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_BLUEZ4_MANAGER)) +#define NM_IS_BLUEZ4_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_BLUEZ4_MANAGER)) +#define NM_BLUEZ4_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_BLUEZ4_MANAGER, NMBluez4ManagerClass)) + +typedef struct { + GObject parent; +} NMBluez4Manager; + +typedef struct { + GObjectClass parent; + + /* Signals */ + void (*bdaddr_added) (NMBluez4Manager *manager, + const char *bdaddr, + const char *name, + const char *object_path, + guint uuids); +} NMBluez4ManagerClass; + +GType nm_bluez4_manager_get_type (void); + +NMBluez4Manager *nm_bluez4_manager_new (NMConnectionProvider *provider); + +void nm_bluez4_manager_query_devices (NMBluez4Manager *manager); + +#endif /* NM_BLUEZ4_MANAGER_H */ + diff --git a/src/devices/bluetooth/nm-bluez5-manager.c b/src/devices/bluetooth/nm-bluez5-manager.c new file mode 100644 index 00000000..63006b3a --- /dev/null +++ b/src/devices/bluetooth/nm-bluez5-manager.c @@ -0,0 +1,421 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2007 - 2008 Novell, Inc. + * Copyright (C) 2007 - 2013 Red Hat, Inc. + * Copyright (C) 2013 Intel Corporation. + */ + +#include +#include +#include +#include + +#include "nm-logging.h" +#include "nm-bluez-manager.h" +#include "nm-bluez5-manager.h" +#include "nm-bluez-device.h" +#include "nm-bluez-common.h" + +#include "nm-dbus-manager.h" + +typedef struct { + NMDBusManager *dbus_mgr; + gulong name_owner_changed_id; + + NMConnectionProvider *provider; + + GDBusProxy *proxy; + + GHashTable *devices; +} NMBluez5ManagerPrivate; + +#define NM_BLUEZ5_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_BLUEZ5_MANAGER, NMBluez5ManagerPrivate)) + +G_DEFINE_TYPE (NMBluez5Manager, nm_bluez5_manager, G_TYPE_OBJECT) + +enum { + BDADDR_ADDED, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +static void device_initialized (NMBluezDevice *device, gboolean success, NMBluez5Manager *self); +static void device_usable (NMBluezDevice *device, GParamSpec *pspec, NMBluez5Manager *self); + +static void +emit_bdaddr_added (NMBluez5Manager *self, NMBluezDevice *device) +{ + g_signal_emit (self, signals[BDADDR_ADDED], 0, + device, + nm_bluez_device_get_address (device), + nm_bluez_device_get_name (device), + nm_bluez_device_get_path (device), + nm_bluez_device_get_capabilities (device)); +} + +void +nm_bluez5_manager_query_devices (NMBluez5Manager *self) +{ + NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (self); + NMBluezDevice *device; + GHashTableIter iter; + + g_hash_table_iter_init (&iter, priv->devices); + while (g_hash_table_iter_next (&iter, NULL, (gpointer) &device)) { + if (nm_bluez_device_get_usable (device)) + emit_bdaddr_added (self, device); + } +} + +static void +remove_device (NMBluez5Manager *self, NMBluezDevice *device) +{ + g_signal_handlers_disconnect_by_func (device, G_CALLBACK (device_initialized), self); + g_signal_handlers_disconnect_by_func (device, G_CALLBACK (device_usable), self); + if (nm_bluez_device_get_usable (device)) + g_signal_emit_by_name (device, NM_BLUEZ_DEVICE_REMOVED); +} + +static void +remove_all_devices (NMBluez5Manager *self) +{ + GHashTableIter iter; + NMBluezDevice *device; + NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (self); + + g_hash_table_iter_init (&iter, priv->devices); + while (g_hash_table_iter_next (&iter, NULL, (gpointer) &device)) { + g_hash_table_iter_steal (&iter); + remove_device (self, device); + g_object_unref (device); + } +} + +static void +device_usable (NMBluezDevice *device, GParamSpec *pspec, NMBluez5Manager *self) +{ + gboolean usable = nm_bluez_device_get_usable (device); + + nm_log_dbg (LOGD_BT, "(%s): bluez device now %s", + nm_bluez_device_get_path (device), + usable ? "usable" : "unusable"); + + if (usable) { + nm_log_dbg (LOGD_BT, "(%s): bluez device address %s", + nm_bluez_device_get_path (device), + nm_bluez_device_get_address (device)); + emit_bdaddr_added (self, device); + } else + g_signal_emit_by_name (device, NM_BLUEZ_DEVICE_REMOVED); +} + +static void +device_initialized (NMBluezDevice *device, gboolean success, NMBluez5Manager *self) +{ + NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (self); + + nm_log_dbg (LOGD_BT, "(%s): bluez device %s", + nm_bluez_device_get_path (device), + success ? "initialized" : "failed to initialize"); + if (!success) + g_hash_table_remove (priv->devices, nm_bluez_device_get_path (device)); +} + +static void +device_added (GDBusProxy *proxy, const gchar *path, NMBluez5Manager *self) +{ + NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (self); + NMBluezDevice *device; + + device = nm_bluez_device_new (path, priv->provider, 5); + g_signal_connect (device, "initialized", G_CALLBACK (device_initialized), self); + g_signal_connect (device, "notify::usable", G_CALLBACK (device_usable), self); + g_hash_table_insert (priv->devices, (gpointer) nm_bluez_device_get_path (device), device); + + nm_log_dbg (LOGD_BT, "(%s): new bluez device found", path); +} + +static void +device_removed (GDBusProxy *proxy, const gchar *path, NMBluez5Manager *self) +{ + NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (self); + NMBluezDevice *device; + + nm_log_dbg (LOGD_BT, "(%s): bluez device removed", path); + + device = g_hash_table_lookup (priv->devices, path); + if (device) { + g_hash_table_steal (priv->devices, nm_bluez_device_get_path (device)); + remove_device (NM_BLUEZ5_MANAGER (self), device); + g_object_unref (device); + } +} + +static void +object_manager_g_signal (GDBusProxy *proxy, + gchar *sender_name, + gchar *signal_name, + GVariant *parameters, + NMBluez5Manager *self) +{ + GVariant *variant; + const gchar *path; + + if (!strcmp (signal_name, "InterfacesRemoved")) { + const gchar **ifaces; + gsize i, length; + + g_variant_get (parameters, "(&o*)", &path, &variant); + + ifaces = g_variant_get_strv (variant, &length); + + for (i = 0; i < length; i++) { + if (!strcmp (ifaces[i], BLUEZ5_DEVICE_INTERFACE)) { + device_removed (proxy, path, self); + break; + } + } + + g_free (ifaces); + + } else if (!strcmp (signal_name, "InterfacesAdded")) { + g_variant_get (parameters, "(&o*)", &path, &variant); + + if (g_variant_lookup_value (variant, BLUEZ5_DEVICE_INTERFACE, + G_VARIANT_TYPE_DICTIONARY)) + device_added (proxy, path, self); + } +} + +static void +get_managed_objects_cb (GDBusProxy *proxy, + GAsyncResult *res, + NMBluez5Manager *self) +{ + GVariant *variant, *ifaces; + GVariantIter i; + GError *error = NULL; + const char *path; + + variant = g_dbus_proxy_call_finish (proxy, res, &error); + + if (!variant) { + if (g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD)) + nm_log_warn (LOGD_BT, "Couldn't get managed objects: not running Bluez5?"); + else { + nm_log_warn (LOGD_BT, "Couldn't get managed objects: %s", + error && error->message ? error->message : "(unknown)"); + } + g_clear_error (&error); + return; + } + g_variant_iter_init (&i, g_variant_get_child_value (variant, 0)); + while ((g_variant_iter_next (&i, "{&o*}", &path, &ifaces))) { + if (g_variant_lookup_value (ifaces, BLUEZ5_DEVICE_INTERFACE, + G_VARIANT_TYPE_DICTIONARY)) { + device_added (proxy, path, self); + } + } + + g_variant_unref (variant); +} + +static void +on_proxy_acquired (GObject *object, + GAsyncResult *res, + NMBluez5Manager *self) +{ + NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (self); + GError *error = NULL; + + priv->proxy = g_dbus_proxy_new_for_bus_finish (res, &error); + + if (!priv->proxy) { + nm_log_warn (LOGD_BT, "Couldn't acquire object manager proxy: %s", + error && error->message ? error->message : "(unknown)"); + g_clear_error (&error); + return; + } + + /* Get already managed devices. */ + g_dbus_proxy_call (priv->proxy, "GetManagedObjects", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + (GAsyncReadyCallback) get_managed_objects_cb, + self); + + g_signal_connect (priv->proxy, "g-signal", + G_CALLBACK (object_manager_g_signal), self); +} + +static void +bluez_connect (NMBluez5Manager *self) +{ + NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (self); + + g_return_if_fail (priv->proxy == NULL); + + g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + BLUEZ_SERVICE, + BLUEZ_MANAGER_PATH, + OBJECT_MANAGER_INTERFACE, + NULL, + (GAsyncReadyCallback) on_proxy_acquired, + self); +} + +static void +name_owner_changed_cb (NMDBusManager *dbus_mgr, + const char *name, + const char *old_owner, + const char *new_owner, + gpointer user_data) +{ + NMBluez5Manager *self = NM_BLUEZ5_MANAGER (user_data); + NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (self); + gboolean old_owner_good = (old_owner && strlen (old_owner)); + gboolean new_owner_good = (new_owner && strlen (new_owner)); + + /* Can't handle the signal if its not from the Bluez */ + if (strcmp (BLUEZ_SERVICE, name)) + return; + + if (old_owner_good && !new_owner_good) { + if (priv->devices) + remove_all_devices (self); + } +} + +static void +bluez_cleanup (NMBluez5Manager *self, gboolean do_signal) +{ + NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (self); + + if (priv->proxy) { + g_object_unref (priv->proxy); + priv->proxy = NULL; + } + + if (do_signal) + remove_all_devices (self); + else + g_hash_table_remove_all (priv->devices); +} + +static void +dbus_connection_changed_cb (NMDBusManager *dbus_mgr, + DBusGConnection *connection, + gpointer user_data) +{ + NMBluez5Manager *self = NM_BLUEZ5_MANAGER (user_data); + + if (!connection) + bluez_cleanup (self, TRUE); + else + bluez_connect (self); +} + +/****************************************************************/ + +NMBluez5Manager * +nm_bluez5_manager_new (NMConnectionProvider *provider) +{ + NMBluez5Manager *instance = NULL; + + instance = g_object_new (NM_TYPE_BLUEZ5_MANAGER, NULL); + NM_BLUEZ5_MANAGER_GET_PRIVATE (instance)->provider = provider; + return instance; +} + +static void +nm_bluez5_manager_init (NMBluez5Manager *self) +{ + NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (self); + + priv->dbus_mgr = nm_dbus_manager_get (); + g_assert (priv->dbus_mgr); + + g_signal_connect (priv->dbus_mgr, + NM_DBUS_MANAGER_NAME_OWNER_CHANGED, + G_CALLBACK (name_owner_changed_cb), + self); + + g_signal_connect (priv->dbus_mgr, + NM_DBUS_MANAGER_DBUS_CONNECTION_CHANGED, + G_CALLBACK (dbus_connection_changed_cb), + self); + + bluez_connect (self); + + priv->devices = g_hash_table_new_full (g_str_hash, g_str_equal, + NULL, g_object_unref); +} + +static void +dispose (GObject *object) +{ + NMBluez5Manager *self = NM_BLUEZ5_MANAGER (object); + NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (self); + + bluez_cleanup (self, FALSE); + + if (priv->dbus_mgr) { + g_signal_handlers_disconnect_by_func (priv->dbus_mgr, name_owner_changed_cb, self); + g_signal_handlers_disconnect_by_func (priv->dbus_mgr, dbus_connection_changed_cb, self); + priv->dbus_mgr = NULL; + } + + G_OBJECT_CLASS (nm_bluez5_manager_parent_class)->dispose (object); +} + +static void +finalize (GObject *object) +{ + NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (object); + + g_hash_table_destroy (priv->devices); + + G_OBJECT_CLASS (nm_bluez5_manager_parent_class)->finalize (object); +} + +static void +nm_bluez5_manager_class_init (NMBluez5ManagerClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (NMBluez5ManagerPrivate)); + + /* virtual methods */ + object_class->dispose = dispose; + object_class->finalize = finalize; + + /* Signals */ + signals[BDADDR_ADDED] = + g_signal_new (NM_BLUEZ_MANAGER_BDADDR_ADDED, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMBluez5ManagerClass, bdaddr_added), + NULL, NULL, NULL, + G_TYPE_NONE, 5, G_TYPE_OBJECT, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT); +} diff --git a/src/devices/bluetooth/nm-bluez5-manager.h b/src/devices/bluetooth/nm-bluez5-manager.h new file mode 100644 index 00000000..79f347bc --- /dev/null +++ b/src/devices/bluetooth/nm-bluez5-manager.h @@ -0,0 +1,62 @@ +/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2007 - 2008 Novell, Inc. + * Copyright (C) 2007 - 2013 Red Hat, Inc. + */ + +#ifndef NM_BLUEZ5_MANAGER_H +#define NM_BLUEZ5_MANAGER_H + +#include +#include + +#include +#include "nm-connection-provider.h" + +G_BEGIN_DECLS + +#define NM_TYPE_BLUEZ5_MANAGER (nm_bluez5_manager_get_type ()) +#define NM_BLUEZ5_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_BLUEZ5_MANAGER, NMBluez5Manager)) +#define NM_BLUEZ5_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_BLUEZ5_MANAGER, NMBluez5ManagerClass)) +#define NM_IS_BLUEZ5_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_BLUEZ5_MANAGER)) +#define NM_IS_BLUEZ5_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_BLUEZ5_MANAGER)) +#define NM_BLUEZ5_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_BLUEZ5_MANAGER, NMBluez5ManagerClass)) + +typedef struct { + GObject parent; +} NMBluez5Manager; + +typedef struct { + GObjectClass parent; + + /* Signals */ + void (*bdaddr_added) (NMBluez5Manager *manager, + const char *bdaddr, + const char *name, + const char *object_path, + guint uuids); +} NMBluez5ManagerClass; + +GType nm_bluez5_manager_get_type (void); + +NMBluez5Manager *nm_bluez5_manager_new (NMConnectionProvider *provider); + +void nm_bluez5_manager_query_devices (NMBluez5Manager *manager); + +#endif /* NM_BLUEZ5_MANAGER_H */ + diff --git a/src/devices/bluetooth/nm-bt-enum-types.c b/src/devices/bluetooth/nm-bt-enum-types.c new file mode 100644 index 00000000..2595caeb --- /dev/null +++ b/src/devices/bluetooth/nm-bt-enum-types.c @@ -0,0 +1,32 @@ + + + +/* Generated by glib-mkenums. Do not edit */ + +#include "nm-bt-enum-types.h" + +#include "nm-device-bt.h" + +GType +nm_bt_error_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { NM_BT_ERROR_CONNECTION_NOT_BT, "NM_BT_ERROR_CONNECTION_NOT_BT", "ConnectionNotBt" }, + { NM_BT_ERROR_CONNECTION_INVALID, "NM_BT_ERROR_CONNECTION_INVALID", "ConnectionInvalid" }, + { NM_BT_ERROR_CONNECTION_INCOMPATIBLE, "NM_BT_ERROR_CONNECTION_INCOMPATIBLE", "ConnectionIncompatible" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("NMBtError"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} + + + diff --git a/src/devices/bluetooth/nm-bt-enum-types.h b/src/devices/bluetooth/nm-bt-enum-types.h new file mode 100644 index 00000000..af887929 --- /dev/null +++ b/src/devices/bluetooth/nm-bt-enum-types.h @@ -0,0 +1,19 @@ + + + +/* Generated by glib-mkenums. Do not edit */ + +#ifndef __NM_BT_ENUM_TYPES_H__ +#define __NM_BT_ENUM_TYPES_H__ + +#include + +G_BEGIN_DECLS +GType nm_bt_error_get_type (void) G_GNUC_CONST; +#define NM_TYPE_BT_ERROR (nm_bt_error_get_type ()) +G_END_DECLS + +#endif /* __NM_BT_ENUM_TYPES_H__ */ + + + diff --git a/src/devices/bluetooth/nm-device-bt-glue.h b/src/devices/bluetooth/nm-device-bt-glue.h new file mode 100644 index 00000000..b6f851b2 --- /dev/null +++ b/src/devices/bluetooth/nm-device-bt-glue.h @@ -0,0 +1,73 @@ +/* Generated by dbus-binding-tool; do not edit! */ + + +#ifndef __dbus_glib_marshal_nm_device_bt_MARSHAL_H__ +#define __dbus_glib_marshal_nm_device_bt_MARSHAL_H__ + +#include + +G_BEGIN_DECLS + +#ifdef G_ENABLE_DEBUG +#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v) +#define g_marshal_value_peek_char(v) g_value_get_schar (v) +#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v) +#define g_marshal_value_peek_int(v) g_value_get_int (v) +#define g_marshal_value_peek_uint(v) g_value_get_uint (v) +#define g_marshal_value_peek_long(v) g_value_get_long (v) +#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v) +#define g_marshal_value_peek_int64(v) g_value_get_int64 (v) +#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v) +#define g_marshal_value_peek_enum(v) g_value_get_enum (v) +#define g_marshal_value_peek_flags(v) g_value_get_flags (v) +#define g_marshal_value_peek_float(v) g_value_get_float (v) +#define g_marshal_value_peek_double(v) g_value_get_double (v) +#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v) +#define g_marshal_value_peek_param(v) g_value_get_param (v) +#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v) +#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v) +#define g_marshal_value_peek_object(v) g_value_get_object (v) +#define g_marshal_value_peek_variant(v) g_value_get_variant (v) +#else /* !G_ENABLE_DEBUG */ +/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API. + * Do not access GValues directly in your code. Instead, use the + * g_value_get_*() functions + */ +#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int +#define g_marshal_value_peek_char(v) (v)->data[0].v_int +#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint +#define g_marshal_value_peek_int(v) (v)->data[0].v_int +#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint +#define g_marshal_value_peek_long(v) (v)->data[0].v_long +#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 +#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 +#define g_marshal_value_peek_enum(v) (v)->data[0].v_long +#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_float(v) (v)->data[0].v_float +#define g_marshal_value_peek_double(v) (v)->data[0].v_double +#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer +#endif /* !G_ENABLE_DEBUG */ + + +G_END_DECLS + +#endif /* __dbus_glib_marshal_nm_device_bt_MARSHAL_H__ */ + +#include +static const DBusGMethodInfo dbus_glib_nm_device_bt_methods[] = { +}; + +const DBusGObjectInfo dbus_glib_nm_device_bt_object_info = { 1, + dbus_glib_nm_device_bt_methods, + 0, +"\0", +"org.freedesktop.NetworkManager.Device.Bluetooth\0PropertiesChanged\0\0", +"org.freedesktop.NetworkManager.Device.Bluetooth\0HwAddress\0hw_address\0read\0org.freedesktop.NetworkManager.Device.Bluetooth\0Name\0name\0read\0org.freedesktop.NetworkManager.Device.Bluetooth\0BtCapabilities\0bt_capabilities\0read\0\0" +}; + diff --git a/src/devices/bluetooth/nm-device-bt.c b/src/devices/bluetooth/nm-device-bt.c new file mode 100644 index 00000000..0bd2f17d --- /dev/null +++ b/src/devices/bluetooth/nm-device-bt.c @@ -0,0 +1,1278 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2009 - 2011 Red Hat, Inc. + */ + +#include "config.h" + +#include +#include +#include +#include + +#include +#include + +#include "nm-glib-compat.h" +#include "nm-bluez-common.h" +#include "nm-bluez-device.h" +#include "nm-dbus-manager.h" +#include "nm-device-bt.h" +#include "nm-device-private.h" +#include "nm-logging.h" +#include "ppp-manager/nm-ppp-manager.h" +#include "nm-setting-connection.h" +#include "nm-setting-bluetooth.h" +#include "nm-setting-cdma.h" +#include "nm-setting-gsm.h" +#include "nm-setting-serial.h" +#include "nm-setting-ppp.h" +#include "nm-device-bt-glue.h" +#include "NetworkManagerUtils.h" +#include "nm-bt-enum-types.h" +#include "nm-utils.h" + +#define MM_OLD_DBUS_SERVICE "org.freedesktop.ModemManager" +#define MM_NEW_DBUS_SERVICE "org.freedesktop.ModemManager1" + +G_DEFINE_TYPE (NMDeviceBt, nm_device_bt, NM_TYPE_DEVICE) + +#define NM_DEVICE_BT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_BT, NMDeviceBtPrivate)) + +static gboolean modem_stage1 (NMDeviceBt *self, NMModem *modem, NMDeviceStateReason *reason); + +typedef struct { + NMDBusManager *dbus_mgr; + guint mm_watch_id; + gboolean mm_running; + + NMBluezDevice *bt_device; + + guint8 bdaddr[ETH_ALEN]; + char *name; + guint32 capabilities; + + gboolean connected; + gboolean have_iface; + + char *rfcomm_iface; + NMModem *modem; + guint32 timeout_id; + + guint32 bt_type; /* BT type of the current connection */ +} NMDeviceBtPrivate; + +enum { + PROP_0, + PROP_BT_NAME, + PROP_BT_CAPABILITIES, + PROP_BT_DEVICE, + + LAST_PROP +}; + +enum { + PPP_STATS, + + LAST_SIGNAL +}; +static guint signals[LAST_SIGNAL] = { 0 }; + + +#define NM_BT_ERROR (nm_bt_error_quark ()) + +static GQuark +nm_bt_error_quark (void) +{ + static GQuark quark = 0; + if (!quark) + quark = g_quark_from_static_string ("nm-bt-error"); + return quark; +} + +guint32 nm_device_bt_get_capabilities (NMDeviceBt *self) +{ + g_return_val_if_fail (NM_IS_DEVICE_BT (self), NM_BT_CAPABILITY_NONE); + + return NM_DEVICE_BT_GET_PRIVATE (self)->capabilities; +} + +static guint +get_hw_address_length (NMDevice *device, gboolean *out_permanent) +{ + /* HW address is the Bluetooth HW address of the remote device */ + if (out_permanent) + *out_permanent = TRUE; /* the bdaddr of the remote device will never change */ + return ETH_ALEN; +} + +static guint32 +get_connection_bt_type (NMConnection *connection) +{ + NMSettingBluetooth *s_bt; + const char *bt_type; + + s_bt = nm_connection_get_setting_bluetooth (connection); + if (!s_bt) + return NM_BT_CAPABILITY_NONE; + + bt_type = nm_setting_bluetooth_get_connection_type (s_bt); + g_assert (bt_type); + + if (!strcmp (bt_type, NM_SETTING_BLUETOOTH_TYPE_DUN)) + return NM_BT_CAPABILITY_DUN; + else if (!strcmp (bt_type, NM_SETTING_BLUETOOTH_TYPE_PANU)) + return NM_BT_CAPABILITY_NAP; + + return NM_BT_CAPABILITY_NONE; +} + +static gboolean +can_auto_connect (NMDevice *device, + NMConnection *connection, + char **specific_object) +{ + NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device); + guint32 bt_type; + + if (!NM_DEVICE_CLASS (nm_device_bt_parent_class)->can_auto_connect (device, connection, specific_object)) + return FALSE; + + /* Can't auto-activate a DUN connection without ModemManager */ + bt_type = get_connection_bt_type (connection); + if (bt_type == NM_BT_CAPABILITY_DUN && priv->mm_running == FALSE) + return FALSE; + + return TRUE; +} + +static gboolean +check_connection_compatible (NMDevice *device, NMConnection *connection) +{ + NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device); + NMSettingConnection *s_con; + NMSettingBluetooth *s_bt; + const GByteArray *array; + guint32 bt_type; + + if (!NM_DEVICE_CLASS (nm_device_bt_parent_class)->check_connection_compatible (device, connection)) + return FALSE; + + s_con = nm_connection_get_setting_connection (connection); + g_assert (s_con); + + if (strcmp (nm_setting_connection_get_connection_type (s_con), NM_SETTING_BLUETOOTH_SETTING_NAME)) + return FALSE; + + s_bt = nm_connection_get_setting_bluetooth (connection); + if (!s_bt) + return FALSE; + + bt_type = get_connection_bt_type (connection); + if (!(bt_type & priv->capabilities)) + return FALSE; + + array = nm_setting_bluetooth_get_bdaddr (s_bt); + if (!array || (array->len != ETH_ALEN)) + return FALSE; + + if (memcmp (priv->bdaddr, array->data, ETH_ALEN) != 0) + return FALSE; + + return TRUE; +} + +static gboolean +check_connection_available (NMDevice *device, + NMConnection *connection, + const char *specific_object) +{ + NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device); + guint32 bt_type; + + bt_type = get_connection_bt_type (connection); + if (!(bt_type & priv->capabilities)) + return FALSE; + + /* DUN connections aren't available without ModemManager */ + if (bt_type == NM_BT_CAPABILITY_DUN && priv->mm_running == FALSE) + return FALSE; + + return TRUE; +} + +static gboolean +complete_connection (NMDevice *device, + NMConnection *connection, + const char *specific_object, + const GSList *existing_connections, + GError **error) +{ + NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device); + NMSettingBluetooth *s_bt; + const GByteArray *setting_bdaddr; + const char *ctype; + gboolean is_dun = FALSE, is_pan = FALSE; + NMSettingGsm *s_gsm; + NMSettingCdma *s_cdma; + NMSettingSerial *s_serial; + NMSettingPPP *s_ppp; + const char *format = NULL, *preferred = NULL; + + s_gsm = nm_connection_get_setting_gsm (connection); + s_cdma = nm_connection_get_setting_cdma (connection); + s_serial = nm_connection_get_setting_serial (connection); + s_ppp = nm_connection_get_setting_ppp (connection); + + s_bt = nm_connection_get_setting_bluetooth (connection); + if (!s_bt) { + s_bt = (NMSettingBluetooth *) nm_setting_bluetooth_new (); + nm_connection_add_setting (connection, NM_SETTING (s_bt)); + } + + ctype = nm_setting_bluetooth_get_connection_type (s_bt); + if (ctype) { + if (!strcmp (ctype, NM_SETTING_BLUETOOTH_TYPE_DUN)) + is_dun = TRUE; + else if (!strcmp (ctype, NM_SETTING_BLUETOOTH_TYPE_PANU)) + is_pan = TRUE; + } else { + if (s_gsm || s_cdma) + is_dun = TRUE; + else if (priv->capabilities & NM_BT_CAPABILITY_NAP) + is_pan = TRUE; + } + + if (is_pan) { + /* Make sure the device supports PAN */ + if (!(priv->capabilities & NM_BT_CAPABILITY_NAP)) { + g_set_error_literal (error, + NM_SETTING_BLUETOOTH_ERROR, + NM_SETTING_BLUETOOTH_ERROR_INVALID_PROPERTY, + "PAN required but Bluetooth device does not support NAP"); + return FALSE; + } + + /* PAN can't use any DUN-related settings */ + if (s_gsm || s_cdma || s_serial || s_ppp) { + g_set_error_literal (error, + NM_SETTING_BLUETOOTH_ERROR, + NM_SETTING_BLUETOOTH_ERROR_INVALID_PROPERTY, + "PAN incompatible with GSM, CDMA, or serial settings"); + return FALSE; + } + + g_object_set (G_OBJECT (s_bt), + NM_SETTING_BLUETOOTH_TYPE, NM_SETTING_BLUETOOTH_TYPE_PANU, + NULL); + + format = _("PAN connection %d"); + } else if (is_dun) { + /* Make sure the device supports PAN */ + if (!(priv->capabilities & NM_BT_CAPABILITY_DUN)) { + g_set_error_literal (error, + NM_SETTING_BLUETOOTH_ERROR, + NM_SETTING_BLUETOOTH_ERROR_INVALID_PROPERTY, + "DUN required but Bluetooth device does not support DUN"); + return FALSE; + } + + /* Need at least a GSM or a CDMA setting */ + if (!s_gsm && !s_cdma) { + g_set_error_literal (error, + NM_SETTING_BLUETOOTH_ERROR, + NM_SETTING_BLUETOOTH_ERROR_INVALID_PROPERTY, + "Setting requires DUN but no GSM or CDMA setting is present"); + return FALSE; + } + + g_object_set (G_OBJECT (s_bt), + NM_SETTING_BLUETOOTH_TYPE, NM_SETTING_BLUETOOTH_TYPE_DUN, + NULL); + + if (s_gsm) { + format = _("GSM connection %d"); + if (!nm_setting_gsm_get_number (s_gsm)) + g_object_set (G_OBJECT (s_gsm), NM_SETTING_GSM_NUMBER, "*99#", NULL); + } else if (s_cdma) { + format = _("CDMA connection %d"); + if (!nm_setting_cdma_get_number (s_cdma)) + g_object_set (G_OBJECT (s_cdma), NM_SETTING_GSM_NUMBER, "#777", NULL); + } else + format = _("DUN connection %d"); + } else { + g_set_error_literal (error, + NM_SETTING_BLUETOOTH_ERROR, + NM_SETTING_BLUETOOTH_ERROR_INVALID_PROPERTY, + "Unknown/unhandled Bluetooth connection type"); + return FALSE; + } + + nm_utils_complete_generic (connection, + NM_SETTING_BLUETOOTH_SETTING_NAME, + existing_connections, + format, + preferred, + is_dun ? FALSE : TRUE); /* No IPv6 yet for DUN */ + + setting_bdaddr = nm_setting_bluetooth_get_bdaddr (s_bt); + if (setting_bdaddr) { + /* Make sure the setting BT Address (if any) matches the device's */ + if (memcmp (setting_bdaddr->data, priv->bdaddr, ETH_ALEN)) { + g_set_error_literal (error, + NM_SETTING_BLUETOOTH_ERROR, + NM_SETTING_BLUETOOTH_ERROR_INVALID_PROPERTY, + NM_SETTING_BLUETOOTH_BDADDR); + return FALSE; + } + } else { + GByteArray *bdaddr; + const guint8 null_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; + + /* Lock the connection to this device by default */ + if (memcmp (priv->bdaddr, null_mac, ETH_ALEN)) { + bdaddr = g_byte_array_sized_new (ETH_ALEN); + g_byte_array_append (bdaddr, priv->bdaddr, ETH_ALEN); + g_object_set (G_OBJECT (s_bt), NM_SETTING_BLUETOOTH_BDADDR, bdaddr, NULL); + g_byte_array_free (bdaddr, TRUE); + } + } + + return TRUE; +} + +/*****************************************************************************/ +/* IP method PPP */ + +static void +ppp_stats (NMModem *modem, + guint32 in_bytes, + guint32 out_bytes, + gpointer user_data) +{ + g_signal_emit (NM_DEVICE_BT (user_data), signals[PPP_STATS], 0, in_bytes, out_bytes); +} + +static void +ppp_failed (NMModem *modem, NMDeviceStateReason reason, gpointer user_data) +{ + NMDevice *device = NM_DEVICE (user_data); + + switch (nm_device_get_state (device)) { + case NM_DEVICE_STATE_PREPARE: + case NM_DEVICE_STATE_CONFIG: + case NM_DEVICE_STATE_NEED_AUTH: + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, reason); + break; + case NM_DEVICE_STATE_IP_CONFIG: + case NM_DEVICE_STATE_IP_CHECK: + case NM_DEVICE_STATE_SECONDARIES: + case NM_DEVICE_STATE_ACTIVATED: + if (nm_device_activate_ip4_state_in_conf (device)) + nm_device_activate_schedule_ip4_config_timeout (device); + else { + nm_device_state_changed (device, + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); + } + break; + default: + break; + } +} + +static void +modem_auth_requested (NMModem *modem, gpointer user_data) +{ + NMDevice *device = NM_DEVICE (user_data); + + /* Auth requests (PIN, PAP/CHAP passwords, etc) only get handled + * during activation. + */ + if (!nm_device_is_activating (device)) + return; + + nm_device_state_changed (device, + NM_DEVICE_STATE_NEED_AUTH, + NM_DEVICE_STATE_REASON_NONE); +} + +static void +modem_auth_result (NMModem *modem, GError *error, gpointer user_data) +{ + NMDevice *device = NM_DEVICE (user_data); + NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device); + NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; + + if (error) { + nm_device_state_changed (device, + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_NO_SECRETS); + } else { + /* Otherwise, on success for GSM/CDMA secrets we need to schedule modem stage1 again */ + g_return_if_fail (nm_device_get_state (device) == NM_DEVICE_STATE_NEED_AUTH); + if (!modem_stage1 (NM_DEVICE_BT (device), priv->modem, &reason)) + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, reason); + } +} + +static void +modem_prepare_result (NMModem *modem, + gboolean success, + NMDeviceStateReason reason, + gpointer user_data) +{ + NMDevice *device = NM_DEVICE (user_data); + NMDeviceState state; + + state = nm_device_get_state (device); + g_return_if_fail (state == NM_DEVICE_STATE_CONFIG || state == NM_DEVICE_STATE_NEED_AUTH); + + if (success) { + NMActRequest *req; + NMActStageReturn ret; + NMDeviceStateReason stage2_reason = NM_DEVICE_STATE_REASON_NONE; + + req = nm_device_get_act_request (device); + g_assert (req); + + ret = nm_modem_act_stage2_config (modem, req, &stage2_reason); + switch (ret) { + case NM_ACT_STAGE_RETURN_POSTPONE: + break; + case NM_ACT_STAGE_RETURN_SUCCESS: + nm_device_activate_schedule_stage3_ip_config_start (device); + break; + case NM_ACT_STAGE_RETURN_FAILURE: + default: + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, stage2_reason); + break; + } + } else { + if (reason == NM_DEVICE_STATE_REASON_SIM_PIN_INCORRECT) { + /* If the connect failed because the SIM PIN was wrong don't allow + * the device to be auto-activated anymore, which would risk locking + * the SIM if the incorrect PIN continues to be used. + */ + g_object_set (G_OBJECT (device), NM_DEVICE_AUTOCONNECT, FALSE, NULL); + nm_log_info (LOGD_MB, "(%s): disabling autoconnect due to failed SIM PIN", + nm_device_get_iface (device)); + } + + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, reason); + } +} + +static void +device_state_changed (NMDevice *device, + NMDeviceState new_state, + NMDeviceState old_state, + NMDeviceStateReason reason) +{ + NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device); + + if (priv->modem) + nm_modem_device_state_changed (priv->modem, new_state, old_state, reason); +} + +static void +modem_ip4_config_result (NMModem *self, + NMIP4Config *config, + GError *error, + gpointer user_data) +{ + NMDevice *device = NM_DEVICE (user_data); + + g_return_if_fail (nm_device_activate_ip4_state_in_conf (device) == TRUE); + + if (error) { + nm_log_warn (LOGD_MB | LOGD_IP4 | LOGD_BT, + "(%s): retrieving IP4 configuration failed: (%d) %s", + nm_device_get_ip_iface (device), + error ? error->code : -1, + error && error->message ? error->message : "(unknown)"); + + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); + } else + nm_device_activate_schedule_ip4_config_result (device, config); +} + +static void +data_port_changed_cb (NMModem *modem, GParamSpec *pspec, gpointer user_data) +{ + NMDevice *self = NM_DEVICE (user_data); + + nm_device_set_ip_iface (self, nm_modem_get_data_port (modem)); +} + +static gboolean +modem_stage1 (NMDeviceBt *self, NMModem *modem, NMDeviceStateReason *reason) +{ + NMActRequest *req; + NMActStageReturn ret; + + g_return_val_if_fail (reason != NULL, FALSE); + + req = nm_device_get_act_request (NM_DEVICE (self)); + g_assert (req); + + ret = nm_modem_act_stage1_prepare (modem, req, reason); + switch (ret) { + case NM_ACT_STAGE_RETURN_POSTPONE: + case NM_ACT_STAGE_RETURN_SUCCESS: + /* Success, wait for the 'prepare-result' signal */ + return TRUE; + case NM_ACT_STAGE_RETURN_FAILURE: + default: + break; + } + + return FALSE; +} + +/*****************************************************************************/ + +static void +modem_cleanup (NMDeviceBt *self) +{ + NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self); + + if (priv->modem) { + g_signal_handlers_disconnect_matched (priv->modem, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, self); + g_clear_object (&priv->modem); + } +} + +static void +modem_state_cb (NMModem *modem, + NMModemState new_state, + NMModemState old_state, + gpointer user_data) +{ + NMDevice *device = NM_DEVICE (user_data); + NMDeviceState dev_state = nm_device_get_state (device); + + if (new_state <= NM_MODEM_STATE_DISABLING && old_state > NM_MODEM_STATE_DISABLING) { + /* Will be called whenever something external to NM disables the + * modem directly through ModemManager. + */ + if (nm_device_is_activating (device) || dev_state == NM_DEVICE_STATE_ACTIVATED) { + nm_device_state_changed (device, + NM_DEVICE_STATE_DISCONNECTED, + NM_DEVICE_STATE_REASON_USER_REQUESTED); + return; + } + } + + if (new_state < NM_MODEM_STATE_CONNECTING && + old_state >= NM_MODEM_STATE_CONNECTING && + dev_state >= NM_DEVICE_STATE_NEED_AUTH && + dev_state <= NM_DEVICE_STATE_ACTIVATED) { + /* Fail the device if the modem disconnects unexpectedly while the + * device is activating/activated. */ + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER); + return; + } +} + +static void +modem_removed_cb (NMModem *modem, gpointer user_data) +{ + NMDeviceBt *self = NM_DEVICE_BT (user_data); + NMDeviceState state; + + /* Fail the device if the modem was removed while active */ + state = nm_device_get_state (NM_DEVICE (self)); + if ( state == NM_DEVICE_STATE_ACTIVATED + || nm_device_is_activating (NM_DEVICE (self))) { + nm_device_state_changed (NM_DEVICE (self), + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_BT_FAILED); + } else + modem_cleanup (self); +} + +static gboolean +component_added (NMDevice *device, GObject *component) +{ + NMDeviceBt *self = NM_DEVICE_BT (device); + NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self); + NMModem *modem; + const gchar *modem_data_port; + const gchar *modem_control_port; + char *base; + NMDeviceState state; + NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; + + if (!NM_IS_MODEM (component)) + return FALSE; + modem = NM_MODEM (component); + + modem_data_port = nm_modem_get_data_port (modem); + modem_control_port = nm_modem_get_control_port (modem); + g_return_val_if_fail (modem_data_port != NULL || modem_control_port != NULL, FALSE); + + if (!priv->rfcomm_iface) + return FALSE; + + base = g_path_get_basename (priv->rfcomm_iface); + if (g_strcmp0 (base, modem_data_port) && g_strcmp0 (base, modem_control_port)) { + g_free (base); + return FALSE; + } + g_free (base); + + /* Got the modem */ + if (priv->timeout_id) { + g_source_remove (priv->timeout_id); + priv->timeout_id = 0; + } + + /* Can only accept the modem in stage2, but since the interface matched + * what we were expecting, don't let anything else claim the modem either. + */ + state = nm_device_get_state (NM_DEVICE (self)); + if (state != NM_DEVICE_STATE_CONFIG) { + nm_log_warn (LOGD_BT | LOGD_MB, + "(%s): modem found but device not in correct state (%d)", + nm_device_get_iface (NM_DEVICE (self)), + nm_device_get_state (NM_DEVICE (self))); + return TRUE; + } + + nm_log_info (LOGD_BT | LOGD_MB, + "Activation (%s/bluetooth) Stage 2 of 5 (Device Configure) modem found.", + nm_device_get_iface (NM_DEVICE (self))); + + if (priv->modem) { + g_warn_if_reached (); + modem_cleanup (self); + } + + priv->modem = g_object_ref (modem); + g_signal_connect (modem, NM_MODEM_PPP_STATS, G_CALLBACK (ppp_stats), self); + g_signal_connect (modem, NM_MODEM_PPP_FAILED, G_CALLBACK (ppp_failed), self); + g_signal_connect (modem, NM_MODEM_PREPARE_RESULT, G_CALLBACK (modem_prepare_result), self); + g_signal_connect (modem, NM_MODEM_IP4_CONFIG_RESULT, G_CALLBACK (modem_ip4_config_result), self); + g_signal_connect (modem, NM_MODEM_AUTH_REQUESTED, G_CALLBACK (modem_auth_requested), self); + g_signal_connect (modem, NM_MODEM_AUTH_RESULT, G_CALLBACK (modem_auth_result), self); + g_signal_connect (modem, NM_MODEM_STATE_CHANGED, G_CALLBACK (modem_state_cb), self); + g_signal_connect (modem, NM_MODEM_REMOVED, G_CALLBACK (modem_removed_cb), self); + + /* In the old ModemManager the data port is known from the very beginning; + * while in the new ModemManager the data port is set afterwards when the bearer gets + * created */ + if (modem_data_port) + nm_device_set_ip_iface (NM_DEVICE (self), modem_data_port); + g_signal_connect (modem, "notify::" NM_MODEM_DATA_PORT, G_CALLBACK (data_port_changed_cb), self); + + /* Kick off the modem connection */ + if (!modem_stage1 (self, modem, &reason)) + nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_FAILED, reason); + + return TRUE; +} + +static gboolean +modem_find_timeout (gpointer user_data) +{ + NMDeviceBt *self = NM_DEVICE_BT (user_data); + + NM_DEVICE_BT_GET_PRIVATE (self)->timeout_id = 0; + nm_device_state_changed (NM_DEVICE (self), + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_MODEM_NOT_FOUND); + return FALSE; +} + +static void +check_connect_continue (NMDeviceBt *self) +{ + NMDevice *device = NM_DEVICE (self); + NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self); + gboolean pan = (priv->bt_type == NM_BT_CAPABILITY_NAP); + gboolean dun = (priv->bt_type == NM_BT_CAPABILITY_DUN); + + if (!priv->connected || !priv->have_iface) + return; + + nm_log_info (LOGD_BT, "Activation (%s %s/bluetooth) Stage 2 of 5 (Device Configure) " + "successful. Will connect via %s.", + nm_device_get_iface (device), + nm_device_get_ip_iface (device), + dun ? "DUN" : (pan ? "PAN" : "unknown")); + + /* Kill the connect timeout since we're connected now */ + if (priv->timeout_id) { + g_source_remove (priv->timeout_id); + priv->timeout_id = 0; + } + + if (pan) { + /* Bluez says we're connected now. Start IP config. */ + nm_device_activate_schedule_stage3_ip_config_start (device); + } else if (dun) { + /* Wait for ModemManager to find the modem */ + priv->timeout_id = g_timeout_add_seconds (30, modem_find_timeout, self); + + nm_log_info (LOGD_BT | LOGD_MB, "Activation (%s/bluetooth) Stage 2 of 5 (Device Configure) " + "waiting for modem to appear.", + nm_device_get_iface (device)); + } else + g_assert_not_reached (); +} + +static void +bluez_connect_cb (GObject *object, + GAsyncResult *res, + void *user_data) +{ + NMDeviceBt *self = NM_DEVICE_BT (user_data); + NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self); + GError *error = NULL; + const char *device; + + device = nm_bluez_device_connect_finish (NM_BLUEZ_DEVICE (object), + res, &error); + + if (!device) { + nm_log_warn (LOGD_BT, "Error connecting with bluez: %s", + error && error->message ? error->message : "(unknown)"); + g_clear_error (&error); + + nm_device_state_changed (NM_DEVICE (self), + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_BT_FAILED); + return; + } + + if (priv->bt_type == NM_BT_CAPABILITY_DUN) { + g_free (priv->rfcomm_iface); + priv->rfcomm_iface = g_strdup (device); + } else if (priv->bt_type == NM_BT_CAPABILITY_NAP) { + nm_device_set_ip_iface (NM_DEVICE (self), device); + } + + nm_log_dbg (LOGD_BT, "(%s): connect request successful", + nm_device_get_iface (NM_DEVICE (self))); + + /* Stage 3 gets scheduled when Bluez says we're connected */ + priv->have_iface = TRUE; + check_connect_continue (self); +} + +static void +bluez_connected_changed (NMBluezDevice *bt_device, + GParamSpec *pspec, + NMDevice *device) +{ + NMDeviceBt *self = NM_DEVICE_BT (device); + NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self); + gboolean connected; + NMDeviceState state; + + state = nm_device_get_state (device); + connected = nm_bluez_device_get_connected (bt_device); + if (connected) { + if (state == NM_DEVICE_STATE_CONFIG) { + nm_log_dbg (LOGD_BT, "(%s): connected to the device", + nm_device_get_iface (device)); + + priv->connected = TRUE; + check_connect_continue (self); + } + } else { + gboolean fail = FALSE; + + /* Bluez says we're disconnected from the device. Suck. */ + + if (nm_device_is_activating (device)) { + nm_log_info (LOGD_BT, + "Activation (%s/bluetooth): bluetooth link disconnected.", + nm_device_get_iface (device)); + fail = TRUE; + } else if (state == NM_DEVICE_STATE_ACTIVATED) { + nm_log_info (LOGD_BT, "(%s): bluetooth link disconnected.", + nm_device_get_iface (device)); + fail = TRUE; + } + + if (fail) { + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_CARRIER); + priv->connected = FALSE; + } + } +} + +static gboolean +bt_connect_timeout (gpointer user_data) +{ + NMDeviceBt *self = NM_DEVICE_BT (user_data); + + nm_log_dbg (LOGD_BT, "(%s): initial connection timed out", + nm_device_get_iface (NM_DEVICE (self))); + + NM_DEVICE_BT_GET_PRIVATE (self)->timeout_id = 0; + nm_device_state_changed (NM_DEVICE (self), + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_BT_FAILED); + return FALSE; +} + +static NMActStageReturn +act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) +{ + NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device); + NMConnection *connection; + + connection = nm_device_get_connection (device); + g_assert (connection); + priv->bt_type = get_connection_bt_type (connection); + if (priv->bt_type == NM_BT_CAPABILITY_NONE) { + // FIXME: set a reason code + return NM_ACT_STAGE_RETURN_FAILURE; + } + + if (priv->bt_type == NM_BT_CAPABILITY_DUN && !priv->mm_running) { + *reason = NM_DEVICE_STATE_REASON_MODEM_MANAGER_UNAVAILABLE; + return NM_ACT_STAGE_RETURN_FAILURE; + } + + nm_log_dbg (LOGD_BT, "(%s): requesting connection to the device", + nm_device_get_iface (device)); + + /* Connect to the BT device */ + nm_bluez_device_connect_async (priv->bt_device, + priv->bt_type & (NM_BT_CAPABILITY_DUN | NM_BT_CAPABILITY_NAP), + bluez_connect_cb, device); + + if (priv->timeout_id) + g_source_remove (priv->timeout_id); + priv->timeout_id = g_timeout_add_seconds (30, bt_connect_timeout, device); + + return NM_ACT_STAGE_RETURN_POSTPONE; +} + +static NMActStageReturn +act_stage3_ip4_config_start (NMDevice *device, + NMIP4Config **out_config, + NMDeviceStateReason *reason) +{ + NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device); + NMActStageReturn ret; + + if (priv->bt_type == NM_BT_CAPABILITY_DUN) { + ret = nm_modem_stage3_ip4_config_start (NM_DEVICE_BT_GET_PRIVATE (device)->modem, + device, + NM_DEVICE_CLASS (nm_device_bt_parent_class), + reason); + } else + ret = NM_DEVICE_CLASS (nm_device_bt_parent_class)->act_stage3_ip4_config_start (device, out_config, reason); + + return ret; +} + +static NMActStageReturn +act_stage3_ip6_config_start (NMDevice *device, + NMIP6Config **out_config, + NMDeviceStateReason *reason) +{ + NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device); + NMActStageReturn ret; + + if (priv->bt_type == NM_BT_CAPABILITY_DUN) { + ret = nm_modem_stage3_ip6_config_start (NM_DEVICE_BT_GET_PRIVATE (device)->modem, + device, + NM_DEVICE_CLASS (nm_device_bt_parent_class), + reason); + } else + ret = NM_DEVICE_CLASS (nm_device_bt_parent_class)->act_stage3_ip6_config_start (device, out_config, reason); + + return ret; +} + +static void +deactivate (NMDevice *device) +{ + NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device); + + priv->have_iface = FALSE; + priv->connected = FALSE; + + if (priv->bt_type == NM_BT_CAPABILITY_DUN) { + if (priv->modem) { + nm_modem_deactivate (priv->modem, device); + + /* Since we're killing the Modem object before it'll get the + * state change signal, simulate the state change here. + */ + nm_modem_device_state_changed (priv->modem, + NM_DEVICE_STATE_DISCONNECTED, + NM_DEVICE_STATE_ACTIVATED, + NM_DEVICE_STATE_REASON_USER_REQUESTED); + modem_cleanup (NM_DEVICE_BT (device)); + } + } + + if (priv->bt_type != NM_BT_CAPABILITY_NONE) + nm_bluez_device_disconnect (priv->bt_device); + + if (priv->timeout_id) { + g_source_remove (priv->timeout_id); + priv->timeout_id = 0; + } + + priv->bt_type = NM_BT_CAPABILITY_NONE; + + g_free (priv->rfcomm_iface); + priv->rfcomm_iface = NULL; + + if (NM_DEVICE_CLASS (nm_device_bt_parent_class)->deactivate) + NM_DEVICE_CLASS (nm_device_bt_parent_class)->deactivate (device); +} + +static void +bluez_device_removed (NMBluezDevice *bdev, gpointer user_data) +{ + g_signal_emit_by_name (NM_DEVICE_BT (user_data), NM_DEVICE_REMOVED); +} + +/*****************************************************************************/ + +static gboolean +is_available (NMDevice *dev) +{ + NMDeviceBt *self = NM_DEVICE_BT (dev); + NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self); + + /* PAN doesn't need ModemManager, so devices that support it are always available */ + if (priv->capabilities & NM_BT_CAPABILITY_NAP) + return TRUE; + + /* DUN requires ModemManager */ + return priv->mm_running; +} + +static void +handle_availability_change (NMDeviceBt *self, + gboolean old_available, + NMDeviceStateReason unavailable_reason) +{ + NMDevice *device = NM_DEVICE (self); + NMDeviceState state; + gboolean available; + + state = nm_device_get_state (device); + if (state < NM_DEVICE_STATE_UNAVAILABLE) { + nm_log_dbg (LOGD_BT, "(%s): availability blocked by UNMANAGED state", + nm_device_get_iface (device)); + return; + } + + available = nm_device_is_available (device); + if (available == old_available) + return; + + if (available) { + if (state != NM_DEVICE_STATE_UNAVAILABLE) + nm_log_warn (LOGD_CORE | LOGD_BT, "not in expected unavailable state!"); + + nm_device_state_changed (device, + NM_DEVICE_STATE_DISCONNECTED, + NM_DEVICE_STATE_REASON_NONE); + } else { + nm_device_state_changed (device, + NM_DEVICE_STATE_UNAVAILABLE, + unavailable_reason); + } +} + +static void +set_mm_running (NMDeviceBt *self, gboolean running) +{ + NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self); + gboolean old_available; + + if (priv->mm_running == running) + return; + + nm_log_dbg (LOGD_BT, "(%s): ModemManager now %s", + nm_device_get_iface (NM_DEVICE (self)), + running ? "available" : "unavailable"); + + old_available = nm_device_is_available (NM_DEVICE (self)); + priv->mm_running = running; + handle_availability_change (self, old_available, NM_DEVICE_STATE_REASON_MODEM_MANAGER_UNAVAILABLE); + + /* Need to recheck available connections whenever MM appears or disappears, + * since the device could be both DUN and NAP capable and thus may not + * change state (which rechecks available connections) when MM comes and goes. + */ + if (priv->capabilities & NM_BT_CAPABILITY_DUN) + nm_device_recheck_available_connections (NM_DEVICE (self)); +} + +static void +mm_name_owner_changed (NMDBusManager *dbus_mgr, + const char *name, + const char *old_owner, + const char *new_owner, + NMDeviceBt *self) +{ + gboolean old_owner_good; + gboolean new_owner_good; + + /* Can't handle the signal if its not from the modem service */ + if ( strcmp (MM_OLD_DBUS_SERVICE, name) != 0 +#if WITH_MODEM_MANAGER_1 + && strcmp (MM_NEW_DBUS_SERVICE, name) != 0 +#endif + ) + return; + + old_owner_good = (old_owner && strlen (old_owner)); + new_owner_good = (new_owner && strlen (new_owner)); + + if (!old_owner_good && new_owner_good) + set_mm_running (self, TRUE); + else if (old_owner_good && !new_owner_good) + set_mm_running (self, FALSE); +} + +/*****************************************************************************/ + +NMDevice * +nm_device_bt_new (NMBluezDevice *bt_device, + const char *udi, + const char *bdaddr, + const char *name, + guint32 capabilities) +{ + g_return_val_if_fail (udi != NULL, NULL); + g_return_val_if_fail (bdaddr != NULL, NULL); + g_return_val_if_fail (name != NULL, NULL); + g_return_val_if_fail (capabilities != NM_BT_CAPABILITY_NONE, NULL); + g_return_val_if_fail (NM_IS_BLUEZ_DEVICE (bt_device), NULL); + + return (NMDevice *) g_object_new (NM_TYPE_DEVICE_BT, + NM_DEVICE_UDI, udi, + NM_DEVICE_IFACE, bdaddr, + NM_DEVICE_DRIVER, "bluez", + NM_DEVICE_HW_ADDRESS, bdaddr, + NM_DEVICE_BT_DEVICE, bt_device, + NM_DEVICE_BT_NAME, name, + NM_DEVICE_BT_CAPABILITIES, capabilities, + NM_DEVICE_TYPE_DESC, "Bluetooth", + NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_BT, + NULL); +} + +static void +nm_device_bt_init (NMDeviceBt *self) +{ + NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self); + gboolean mm_running; + + priv->dbus_mgr = nm_dbus_manager_get (); + + priv->mm_watch_id = g_signal_connect (priv->dbus_mgr, + NM_DBUS_MANAGER_NAME_OWNER_CHANGED, + G_CALLBACK (mm_name_owner_changed), + self); + + /* Initial check to see if ModemManager is running */ + mm_running = nm_dbus_manager_name_has_owner (priv->dbus_mgr, MM_OLD_DBUS_SERVICE); +#if WITH_MODEM_MANAGER_1 + if (!mm_running) + mm_running = nm_dbus_manager_name_has_owner (priv->dbus_mgr, MM_NEW_DBUS_SERVICE); +#endif + set_mm_running (self, mm_running); +} + +static void +constructed (GObject *object) +{ + NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (object); + const guint8 *my_hwaddr; + guint my_hwaddr_len = 0; + + G_OBJECT_CLASS (nm_device_bt_parent_class)->constructed (object); + + my_hwaddr = nm_device_get_hw_address (NM_DEVICE (object), &my_hwaddr_len); + g_assert (my_hwaddr); + g_assert_cmpint (my_hwaddr_len, ==, ETH_ALEN); + memcpy (priv->bdaddr, my_hwaddr, ETH_ALEN); + + /* Watch for BT device property changes */ + g_signal_connect (priv->bt_device, "notify::" NM_BLUEZ_DEVICE_CONNECTED, + G_CALLBACK (bluez_connected_changed), + object); +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (object); + + switch (prop_id) { + case PROP_BT_NAME: + /* Construct only */ + priv->name = g_value_dup_string (value); + break; + case PROP_BT_CAPABILITIES: + /* Construct only */ + priv->capabilities = g_value_get_uint (value); + break; + case PROP_BT_DEVICE: + /* Construct only */ + priv->bt_device = g_value_dup_object (value); + g_signal_connect (priv->bt_device, "removed", G_CALLBACK (bluez_device_removed), object); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (object); + + switch (prop_id) { + case PROP_BT_NAME: + g_value_set_string (value, priv->name); + break; + case PROP_BT_CAPABILITIES: + g_value_set_uint (value, priv->capabilities); + break; + case PROP_BT_DEVICE: + g_value_set_object (value, priv->bt_device); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +dispose (GObject *object) +{ + NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (object); + + if (priv->timeout_id) { + g_source_remove (priv->timeout_id); + priv->timeout_id = 0; + } + + g_signal_handlers_disconnect_matched (priv->bt_device, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, object); + + if (priv->dbus_mgr && priv->mm_watch_id) { + g_signal_handler_disconnect (priv->dbus_mgr, priv->mm_watch_id); + priv->mm_watch_id = 0; + } + priv->dbus_mgr = NULL; + + modem_cleanup (NM_DEVICE_BT (object)); + g_clear_object (&priv->bt_device); + + G_OBJECT_CLASS (nm_device_bt_parent_class)->dispose (object); +} + +static void +finalize (GObject *object) +{ + NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (object); + + g_free (priv->rfcomm_iface); + g_free (priv->name); + + G_OBJECT_CLASS (nm_device_bt_parent_class)->finalize (object); +} + +static void +nm_device_bt_class_init (NMDeviceBtClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (NMDeviceBtPrivate)); + + object_class->constructed = constructed; + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->dispose = dispose; + object_class->finalize = finalize; + + device_class->get_hw_address_length = get_hw_address_length; + device_class->can_auto_connect = can_auto_connect; + device_class->deactivate = deactivate; + device_class->act_stage2_config = act_stage2_config; + device_class->act_stage3_ip4_config_start = act_stage3_ip4_config_start; + device_class->act_stage3_ip6_config_start = act_stage3_ip6_config_start; + device_class->check_connection_compatible = check_connection_compatible; + device_class->check_connection_available = check_connection_available; + device_class->complete_connection = complete_connection; + device_class->is_available = is_available; + device_class->component_added = component_added; + + device_class->state_changed = device_state_changed; + + /* Properties */ + g_object_class_install_property + (object_class, PROP_BT_NAME, + g_param_spec_string (NM_DEVICE_BT_NAME, + "Bluetooth device name", + "Bluetooth device name", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property + (object_class, PROP_BT_CAPABILITIES, + g_param_spec_uint (NM_DEVICE_BT_CAPABILITIES, + "Bluetooth device capabilities", + "Bluetooth device capabilities", + NM_BT_CAPABILITY_NONE, G_MAXUINT, NM_BT_CAPABILITY_NONE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property + (object_class, PROP_BT_DEVICE, + g_param_spec_object (NM_DEVICE_BT_DEVICE, + "NMBluezDevice object for the Device", + "NMBluezDevice object for the Device", + NM_TYPE_BLUEZ_DEVICE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + /* Signals */ + signals[PPP_STATS] = + g_signal_new ("ppp-stats", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMDeviceBtClass, ppp_stats), + NULL, NULL, NULL, + G_TYPE_NONE, 2, + G_TYPE_UINT, G_TYPE_UINT); + + nm_dbus_manager_register_exported_type (nm_dbus_manager_get (), + G_TYPE_FROM_CLASS (klass), + &dbus_glib_nm_device_bt_object_info); + + dbus_g_error_domain_register (NM_BT_ERROR, NULL, NM_TYPE_BT_ERROR); +} diff --git a/src/devices/bluetooth/nm-device-bt.h b/src/devices/bluetooth/nm-device-bt.h new file mode 100644 index 00000000..83732bc0 --- /dev/null +++ b/src/devices/bluetooth/nm-device-bt.h @@ -0,0 +1,74 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2009 Red Hat, Inc. + */ + +#ifndef NM_DEVICE_BT_H +#define NM_DEVICE_BT_H + +#include +#include "nm-bluez-device.h" +#include "nm-modem.h" + +G_BEGIN_DECLS + +#define NM_TYPE_DEVICE_BT (nm_device_bt_get_type ()) +#define NM_DEVICE_BT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_BT, NMDeviceBt)) +#define NM_DEVICE_BT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_BT, NMDeviceBtClass)) +#define NM_IS_DEVICE_BT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_BT)) +#define NM_IS_DEVICE_BT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_BT)) +#define NM_DEVICE_BT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_BT, NMDeviceBtClass)) + +typedef enum { + NM_BT_ERROR_CONNECTION_NOT_BT = 0, /*< nick=ConnectionNotBt >*/ + NM_BT_ERROR_CONNECTION_INVALID, /*< nick=ConnectionInvalid >*/ + NM_BT_ERROR_CONNECTION_INCOMPATIBLE, /*< nick=ConnectionIncompatible >*/ +} NMBtError; + +#define NM_DEVICE_BT_NAME "name" +#define NM_DEVICE_BT_CAPABILITIES "bt-capabilities" +#define NM_DEVICE_BT_DEVICE "bt-device" + +typedef struct { + NMDevice parent; +} NMDeviceBt; + +typedef struct { + NMDeviceClass parent; + + /* Signals */ + void (*ppp_stats) (NMDeviceBt *device, guint32 in_bytes, guint32 out_bytes); +} NMDeviceBtClass; + +GType nm_device_bt_get_type (void); + +NMDevice *nm_device_bt_new (NMBluezDevice *bt_device, + const char *udi, + const char *bdaddr, + const char *name, + guint32 capabilities); + +guint32 nm_device_bt_get_capabilities (NMDeviceBt *device); + +gboolean nm_device_bt_modem_added (NMDeviceBt *device, + NMModem *modem, + const char *driver); + +G_END_DECLS + +#endif /* NM_DEVICE_BT_H */ diff --git a/src/devices/nm-device-bond.c b/src/devices/nm-device-bond.c new file mode 100644 index 00000000..6f8caeb4 --- /dev/null +++ b/src/devices/nm-device-bond.c @@ -0,0 +1,612 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright 2011 - 2012 Red Hat, Inc. + */ + +#include "config.h" + +#include +#include + +#include +#include +#include + +#include "gsystem-local-alloc.h" +#include "nm-device-bond.h" +#include "nm-logging.h" +#include "nm-utils.h" +#include "NetworkManagerUtils.h" +#include "nm-device-private.h" +#include "nm-platform.h" +#include "nm-dbus-glib-types.h" +#include "nm-dbus-manager.h" +#include "nm-enum-types.h" + +#include "nm-device-bond-glue.h" + + +G_DEFINE_TYPE (NMDeviceBond, nm_device_bond, NM_TYPE_DEVICE) + +#define NM_DEVICE_BOND_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_BOND, NMDeviceBondPrivate)) + +#define NM_BOND_ERROR (nm_bond_error_quark ()) + +typedef struct { + int dummy; +} NMDeviceBondPrivate; + +enum { + PROP_0, + PROP_SLAVES, + + LAST_PROP +}; + +/******************************************************************/ + +static GQuark +nm_bond_error_quark (void) +{ + static GQuark quark = 0; + if (!quark) + quark = g_quark_from_static_string ("nm-bond-error"); + return quark; +} + +/******************************************************************/ + +static guint32 +get_generic_capabilities (NMDevice *dev) +{ + return NM_DEVICE_CAP_CARRIER_DETECT; +} + +static gboolean +is_available (NMDevice *dev) +{ + if (NM_DEVICE_GET_CLASS (dev)->is_up) + return NM_DEVICE_GET_CLASS (dev)->is_up (dev); + return FALSE; +} + +static gboolean +check_connection_available (NMDevice *device, + NMConnection *connection, + const char *specific_object) +{ + /* Connections are always available because the carrier state is determined + * by the slave carrier states, not the bonds's state. + */ + return TRUE; +} + +static gboolean +check_connection_compatible (NMDevice *device, NMConnection *connection) +{ + const char *iface; + NMSettingBond *s_bond; + + if (!NM_DEVICE_CLASS (nm_device_bond_parent_class)->check_connection_compatible (device, connection)) + return FALSE; + + s_bond = nm_connection_get_setting_bond (connection); + if (!s_bond || !nm_connection_is_type (connection, NM_SETTING_BOND_SETTING_NAME)) + return FALSE; + + /* Bond connections must specify the virtual interface name */ + iface = nm_connection_get_virtual_iface_name (connection); + if (!iface || strcmp (nm_device_get_iface (device), iface)) + return FALSE; + + /* FIXME: match bond properties like mode, etc? */ + + return TRUE; +} + +static gboolean +complete_connection (NMDevice *device, + NMConnection *connection, + const char *specific_object, + const GSList *existing_connections, + GError **error) +{ + NMSettingBond *s_bond, *tmp; + guint32 i = 0; + char *name; + const GSList *iter; + gboolean found; + + nm_utils_complete_generic (connection, + NM_SETTING_BOND_SETTING_NAME, + existing_connections, + _("Bond connection %d"), + NULL, + TRUE); + + s_bond = nm_connection_get_setting_bond (connection); + if (!s_bond) { + s_bond = (NMSettingBond *) nm_setting_bond_new (); + nm_connection_add_setting (connection, NM_SETTING (s_bond)); + } + + /* Grab the first name that doesn't exist in either our connections + * or a device on the system. + */ + while (i < 500 && !nm_setting_bond_get_interface_name (s_bond)) { + name = g_strdup_printf ("bond%u", i); + /* check interface names */ + if (!nm_platform_link_exists (name)) { + /* check existing bond connections */ + for (iter = existing_connections, found = FALSE; iter; iter = g_slist_next (iter)) { + NMConnection *candidate = iter->data; + + tmp = nm_connection_get_setting_bond (candidate); + if (tmp && nm_connection_is_type (candidate, NM_SETTING_BOND_SETTING_NAME)) { + if (g_strcmp0 (nm_setting_bond_get_interface_name (tmp), name) == 0) { + found = TRUE; + break; + } + } + } + + if (!found) + g_object_set (G_OBJECT (s_bond), NM_SETTING_BOND_INTERFACE_NAME, name, NULL); + } + + g_free (name); + i++; + } + + return TRUE; +} + +/******************************************************************/ + +static gboolean +set_bond_attr (NMDevice *device, const char *attr, const char *value) +{ + gboolean ret; + int ifindex = nm_device_get_ifindex (device); + + ret = nm_platform_master_set_option (ifindex, attr, value); + if (!ret) { + nm_log_warn (LOGD_HW, "(%s): failed to set bonding attribute " + "'%s' to '%s'", nm_device_get_ip_iface (device), attr, value); + } + return ret; +} + +/* Ignore certain bond options if they are zero (off/disabled) */ +static gboolean +ignore_if_zero (const char *option, const char *value) +{ + if (strcmp (option, "arp_interval") && + strcmp (option, "miimon") && + strcmp (option, "downdelay") && + strcmp (option, "updelay")) + return FALSE; + + return g_strcmp0 (value, "0") == 0 ? TRUE : FALSE; +} + +static void +update_connection (NMDevice *device, NMConnection *connection) +{ + NMSettingBond *s_bond = nm_connection_get_setting_bond (connection); + const char *ifname = nm_device_get_iface (device); + int ifindex = nm_device_get_ifindex (device); + const char **options; + + if (!s_bond) { + s_bond = (NMSettingBond *) nm_setting_bond_new (); + nm_connection_add_setting (connection, (NMSetting *) s_bond); + g_object_set (s_bond, NM_SETTING_BOND_INTERFACE_NAME, ifname, NULL); + } + + /* Read bond options from sysfs and update the Bond setting to match */ + options = nm_setting_bond_get_valid_options (s_bond); + while (options && *options) { + gs_free char *value = nm_platform_master_get_option (ifindex, *options); + const char *defvalue = nm_setting_bond_get_option_default (s_bond, *options); + + if (value && !ignore_if_zero (*options, value) && (g_strcmp0 (value, defvalue) != 0)) { + /* Replace " " with "," for arp_ip_targets from the kernel */ + if (strcmp (*options, "arp_ip_target") == 0) { + char *p = value; + + while (p && *p) { + if (*p == ' ') + *p = ','; + p++; + } + } + + nm_setting_bond_add_option (s_bond, *options, value); + } + options++; + } +} + +static void +set_arp_targets (NMDevice *device, + const char *value, + const char *delim, + const char *prefix) +{ + char **items, **iter, *tmp; + + if (!value || !*value) + return; + + items = g_strsplit_set (value, delim, 0); + for (iter = items; iter && *iter; iter++) { + if (*iter[0]) { + tmp = g_strdup_printf ("%s%s", prefix, *iter); + set_bond_attr (device, "arp_ip_target", tmp); + g_free (tmp); + } + } + g_strfreev (items); +} + +static void +set_simple_option (NMDevice *device, + const char *attr, + NMSettingBond *s_bond, + const char *opt) +{ + const char *value; + + value = nm_setting_bond_get_option_by_name (s_bond, opt); + if (!value) + value = nm_setting_bond_get_option_default (s_bond, opt); + set_bond_attr (device, attr, value); +} + +static NMActStageReturn +apply_bonding_config (NMDevice *device) +{ + NMConnection *connection; + NMSettingBond *s_bond; + int ifindex = nm_device_get_ifindex (device); + const char *mode, *value; + char *contents; + gboolean set_arp_interval = TRUE; + + /* Option restrictions: + * + * arp_interval conflicts miimon > 0 + * arp_interval conflicts [ alb, tlb ] + * arp_validate needs [ active-backup ] + * downdelay needs miimon + * updelay needs miimon + * primary needs [ active-backup, tlb, alb ] + * + * clearing miimon requires that arp_interval be 0, but clearing + * arp_interval doesn't require miimon to be 0 + */ + + connection = nm_device_get_connection (device); + g_assert (connection); + s_bond = nm_connection_get_setting_bond (connection); + g_assert (s_bond); + + mode = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_MODE); + if (mode == NULL) + mode = "balance-rr"; + + value = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_MIIMON); + if (value && atoi (value)) { + /* clear arp interval */ + set_bond_attr (device, "arp_interval", "0"); + set_arp_interval = FALSE; + + set_bond_attr (device, "miimon", value); + set_simple_option (device, "updelay", s_bond, NM_SETTING_BOND_OPTION_UPDELAY); + set_simple_option (device, "downdelay", s_bond, NM_SETTING_BOND_OPTION_DOWNDELAY); + } else if (!value) { + /* If not given, and arp_interval is not given, default to 100 */ + long int val_int; + char *end; + + value = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_ARP_INTERVAL); + errno = 0; + val_int = strtol (value ? value : "0", &end, 10); + if (!value || (val_int == 0 && errno == 0 && *end == '\0')) + set_bond_attr (device, "miimon", "100"); + } + + /* The stuff after 'mode' requires the given mode or doesn't care */ + set_bond_attr (device, "mode", mode); + + /* arp_interval not compatible with ALB, TLB */ + if (g_strcmp0 (mode, "balance-alb") == 0 || g_strcmp0 (mode, "balance-tlb") == 0) + set_arp_interval = FALSE; + + if (set_arp_interval) { + set_simple_option (device, "arp_interval", s_bond, NM_SETTING_BOND_OPTION_ARP_INTERVAL); + + /* Just let miimon get cleared automatically; even setting miimon to + * 0 (disabled) clears arp_interval. + */ + } + + value = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_ARP_VALIDATE); + /* arp_validate > 0 only valid in active-backup mode */ + if ( value + && g_strcmp0 (value, "0") != 0 + && g_strcmp0 (value, "none") != 0 + && g_strcmp0 (mode, "active-backup") == 0) + set_bond_attr (device, "arp_validate", value); + else + set_bond_attr (device, "arp_validate", "0"); + + if ( g_strcmp0 (mode, "active-backup") == 0 + || g_strcmp0 (mode, "balance-alb") == 0 + || g_strcmp0 (mode, "balance-tlb") == 0) { + value = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_PRIMARY); + set_bond_attr (device, "primary", value ? value : ""); + } + + /* Clear ARP targets */ + contents = nm_platform_master_get_option (ifindex, "arp_ip_target"); + set_arp_targets (device, contents, " \n", "-"); + g_free (contents); + + /* Add new ARP targets */ + value = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_ARP_IP_TARGET); + set_arp_targets (device, value, ",", "+"); + + set_simple_option (device, "primary_reselect", s_bond, NM_SETTING_BOND_OPTION_PRIMARY_RESELECT); + set_simple_option (device, "fail_over_mac", s_bond, NM_SETTING_BOND_OPTION_FAIL_OVER_MAC); + set_simple_option (device, "use_carrier", s_bond, NM_SETTING_BOND_OPTION_USE_CARRIER); + set_simple_option (device, "ad_select", s_bond, NM_SETTING_BOND_OPTION_AD_SELECT); + set_simple_option (device, "xmit_hash_policy", s_bond, NM_SETTING_BOND_OPTION_XMIT_HASH_POLICY); + set_simple_option (device, "resend_igmp", s_bond, NM_SETTING_BOND_OPTION_RESEND_IGMP); + + return NM_ACT_STAGE_RETURN_SUCCESS; +} + + +static NMActStageReturn +act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason) +{ + NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS; + gboolean no_firmware = FALSE; + + g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); + + ret = NM_DEVICE_CLASS (nm_device_bond_parent_class)->act_stage1_prepare (dev, reason); + if (ret != NM_ACT_STAGE_RETURN_SUCCESS) + return ret; + + /* Interface must be down to set bond options */ + nm_device_take_down (dev, TRUE); + ret = apply_bonding_config (dev); + nm_device_bring_up (dev, TRUE, &no_firmware); + + return ret; +} + +static gboolean +enslave_slave (NMDevice *device, + NMDevice *slave, + NMConnection *connection, + gboolean configure) +{ + gboolean success = TRUE, no_firmware = FALSE; + const char *iface = nm_device_get_ip_iface (device); + const char *slave_iface = nm_device_get_ip_iface (slave); + + nm_device_master_check_slave_physical_port (device, slave, LOGD_BOND); + + if (configure) { + nm_device_take_down (slave, TRUE); + success = nm_platform_link_enslave (nm_device_get_ip_ifindex (device), + nm_device_get_ip_ifindex (slave)); + nm_device_bring_up (slave, TRUE, &no_firmware); + + if (!success) + return FALSE; + + nm_log_info (LOGD_BOND, "(%s): enslaved bond slave %s", iface, slave_iface); + } else + nm_log_info (LOGD_BOND, "(%s): bond slave %s was enslaved", iface, slave_iface); + + g_object_notify (G_OBJECT (device), NM_DEVICE_BOND_SLAVES); + return TRUE; +} + +static gboolean +release_slave (NMDevice *device, + NMDevice *slave, + gboolean configure) +{ + gboolean success = TRUE, no_firmware = FALSE; + + if (configure) { + success = nm_platform_link_release (nm_device_get_ip_ifindex (device), + nm_device_get_ip_ifindex (slave)); + + if (success) { + nm_log_info (LOGD_BOND, "(%s): released bond slave %s", + nm_device_get_ip_iface (device), + nm_device_get_ip_iface (slave)); + } else { + nm_log_warn (LOGD_BOND, "(%s): failed to release bond slave %s", + nm_device_get_ip_iface (device), + nm_device_get_ip_iface (slave)); + } + } else { + nm_log_info (LOGD_BOND, "(%s): bond slave %s was released", + nm_device_get_ip_iface (device), + nm_device_get_ip_iface (slave)); + } + + if (success) + g_object_notify (G_OBJECT (device), NM_DEVICE_BOND_SLAVES); + + if (configure) { + /* Kernel bonding code "closes" the slave when releasing it, (which clears + * IFF_UP), so we must bring it back up here to ensure carrier changes and + * other state is noticed by the now-released slave. + */ + if (!nm_device_bring_up (slave, TRUE, &no_firmware)) { + nm_log_warn (LOGD_BOND, "(%s): released bond slave could not be brought up.", + nm_device_get_iface (slave)); + } + } + + return success; +} + +/******************************************************************/ + +NMDevice * +nm_device_bond_new (NMPlatformLink *platform_device) +{ + g_return_val_if_fail (platform_device != NULL, NULL); + + return (NMDevice *) g_object_new (NM_TYPE_DEVICE_BOND, + NM_DEVICE_PLATFORM_DEVICE, platform_device, + NM_DEVICE_DRIVER, "bonding", + NM_DEVICE_TYPE_DESC, "Bond", + NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_BOND, + NM_DEVICE_IS_MASTER, TRUE, + NULL); +} + +NMDevice * +nm_device_bond_new_for_connection (NMConnection *connection) +{ + const char *iface; + + g_return_val_if_fail (connection != NULL, NULL); + + iface = nm_connection_get_virtual_iface_name (connection); + g_return_val_if_fail (iface != NULL, NULL); + + if ( !nm_platform_bond_add (iface) + && nm_platform_get_error () != NM_PLATFORM_ERROR_EXISTS) { + nm_log_warn (LOGD_DEVICE | LOGD_BOND, "(%s): failed to create bonding master interface for '%s': %s", + iface, nm_connection_get_id (connection), + nm_platform_get_error_msg ()); + return NULL; + } + + return (NMDevice *) g_object_new (NM_TYPE_DEVICE_BOND, + NM_DEVICE_IFACE, iface, + NM_DEVICE_DRIVER, "bonding", + NM_DEVICE_TYPE_DESC, "Bond", + NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_BOND, + NM_DEVICE_IS_MASTER, TRUE, + NULL); +} + +static void +constructed (GObject *object) +{ + G_OBJECT_CLASS (nm_device_bond_parent_class)->constructed (object); + + nm_log_dbg (LOGD_HW | LOGD_BOND, "(%s): kernel ifindex %d", + nm_device_get_iface (NM_DEVICE (object)), + nm_device_get_ifindex (NM_DEVICE (object))); +} + +static void +nm_device_bond_init (NMDeviceBond * self) +{ +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + GPtrArray *slaves; + GSList *list, *iter; + + switch (prop_id) { + break; + case PROP_SLAVES: + slaves = g_ptr_array_new (); + list = nm_device_master_get_slaves (NM_DEVICE (object)); + for (iter = list; iter; iter = iter->next) + g_ptr_array_add (slaves, g_strdup (nm_device_get_path (NM_DEVICE (iter->data)))); + g_slist_free (list); + g_value_take_boxed (value, slaves); + 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) +{ + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_device_bond_class_init (NMDeviceBondClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (NMDeviceBondPrivate)); + + parent_class->connection_type = NM_SETTING_BOND_SETTING_NAME; + + /* virtual methods */ + object_class->constructed = constructed; + object_class->get_property = get_property; + object_class->set_property = set_property; + + parent_class->get_generic_capabilities = get_generic_capabilities; + parent_class->is_available = is_available; + parent_class->check_connection_compatible = check_connection_compatible; + parent_class->check_connection_available = check_connection_available; + parent_class->complete_connection = complete_connection; + + parent_class->update_connection = update_connection; + + parent_class->act_stage1_prepare = act_stage1_prepare; + parent_class->enslave_slave = enslave_slave; + parent_class->release_slave = release_slave; + + /* properties */ + g_object_class_install_property + (object_class, PROP_SLAVES, + g_param_spec_boxed (NM_DEVICE_BOND_SLAVES, + "Slaves", + "Slaves", + DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH, + G_PARAM_READABLE)); + + nm_dbus_manager_register_exported_type (nm_dbus_manager_get (), + G_TYPE_FROM_CLASS (klass), + &dbus_glib_nm_device_bond_object_info); + + dbus_g_error_domain_register (NM_BOND_ERROR, NULL, NM_TYPE_BOND_ERROR); +} diff --git a/src/devices/nm-device-bond.h b/src/devices/nm-device-bond.h new file mode 100644 index 00000000..f4683ad8 --- /dev/null +++ b/src/devices/nm-device-bond.h @@ -0,0 +1,62 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright 2012 Red Hat, Inc. + */ + +#ifndef NM_DEVICE_BOND_H +#define NM_DEVICE_BOND_H + +#include + +#include "nm-device.h" + +G_BEGIN_DECLS + +#define NM_TYPE_DEVICE_BOND (nm_device_bond_get_type ()) +#define NM_DEVICE_BOND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_BOND, NMDeviceBond)) +#define NM_DEVICE_BOND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_BOND, NMDeviceBondClass)) +#define NM_IS_DEVICE_BOND(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_BOND)) +#define NM_IS_DEVICE_BOND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_BOND)) +#define NM_DEVICE_BOND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_BOND, NMDeviceBondClass)) + +typedef enum { + NM_BOND_ERROR_CONNECTION_NOT_BOND = 0, /*< nick=ConnectionNotBond >*/ + NM_BOND_ERROR_CONNECTION_INVALID, /*< nick=ConnectionInvalid >*/ + NM_BOND_ERROR_CONNECTION_INCOMPATIBLE, /*< nick=ConnectionIncompatible >*/ +} NMBondError; + +#define NM_DEVICE_BOND_SLAVES "slaves" + +typedef struct { + NMDevice parent; +} NMDeviceBond; + +typedef struct { + NMDeviceClass parent; + +} NMDeviceBondClass; + + +GType nm_device_bond_get_type (void); + +NMDevice *nm_device_bond_new (NMPlatformLink *platform_device); +NMDevice *nm_device_bond_new_for_connection (NMConnection *connection); + +G_END_DECLS + +#endif /* NM_DEVICE_BOND_H */ diff --git a/src/devices/nm-device-bridge.c b/src/devices/nm-device-bridge.c new file mode 100644 index 00000000..edc41838 --- /dev/null +++ b/src/devices/nm-device-bridge.c @@ -0,0 +1,588 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright 2011 - 2012 Red Hat, Inc. + */ + +#include "config.h" + +#include +#include + +#include +#include + +#include "gsystem-local-alloc.h" +#include "nm-device-bridge.h" +#include "nm-logging.h" +#include "nm-utils.h" +#include "NetworkManagerUtils.h" +#include "nm-device-private.h" +#include "nm-dbus-glib-types.h" +#include "nm-dbus-manager.h" +#include "nm-enum-types.h" +#include "nm-platform.h" + +#include "nm-device-bridge-glue.h" + + +G_DEFINE_TYPE (NMDeviceBridge, nm_device_bridge, NM_TYPE_DEVICE) + +#define NM_DEVICE_BRIDGE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_BRIDGE, NMDeviceBridgePrivate)) + +#define NM_BRIDGE_ERROR (nm_bridge_error_quark ()) + +typedef struct { + int dummy; +} NMDeviceBridgePrivate; + +enum { + PROP_0, + PROP_SLAVES, + + LAST_PROP +}; + +/******************************************************************/ + +static GQuark +nm_bridge_error_quark (void) +{ + static GQuark quark = 0; + if (!quark) + quark = g_quark_from_static_string ("nm-bridge-error"); + return quark; +} + +/******************************************************************/ + +static guint32 +get_generic_capabilities (NMDevice *dev) +{ + return NM_DEVICE_CAP_CARRIER_DETECT; +} + +static gboolean +is_available (NMDevice *dev) +{ + if (NM_DEVICE_GET_CLASS (dev)->is_up) + return NM_DEVICE_GET_CLASS (dev)->is_up (dev); + return FALSE; +} + +static gboolean +check_connection_available (NMDevice *device, + NMConnection *connection, + const char *specific_object) +{ + /* Connections are always available because the carrier state is determined + * by the bridge port carrier states, not the bridge's state. + */ + return TRUE; +} + +static gboolean +check_connection_compatible (NMDevice *device, NMConnection *connection) +{ + const char *iface; + NMSettingBridge *s_bridge; + const GByteArray *mac_address; + + if (!NM_DEVICE_CLASS (nm_device_bridge_parent_class)->check_connection_compatible (device, connection)) + return FALSE; + + s_bridge = nm_connection_get_setting_bridge (connection); + if (!s_bridge || !nm_connection_is_type (connection, NM_SETTING_BRIDGE_SETTING_NAME)) + return FALSE; + + /* Bridge connections must specify the virtual interface name */ + iface = nm_connection_get_virtual_iface_name (connection); + if (!iface || strcmp (nm_device_get_iface (device), iface)) + return FALSE; + + mac_address = nm_setting_bridge_get_mac_address (s_bridge); + if (mac_address) { + guint hw_len; + const guint8 *hw_addr; + + hw_addr = nm_device_get_hw_address (device, &hw_len); + if ( !hw_addr + || hw_len != mac_address->len + || memcmp (mac_address->data, hw_addr, hw_len) != 0) + return FALSE; + } + + return TRUE; +} + +static gboolean +complete_connection (NMDevice *device, + NMConnection *connection, + const char *specific_object, + const GSList *existing_connections, + GError **error) +{ + NMSettingBridge *s_bridge, *tmp; + guint32 i = 0; + char *name; + const GSList *iter; + gboolean found; + + nm_utils_complete_generic (connection, + NM_SETTING_BRIDGE_SETTING_NAME, + existing_connections, + _("Bridge connection %d"), + NULL, + TRUE); + + s_bridge = nm_connection_get_setting_bridge (connection); + if (!s_bridge) { + s_bridge = (NMSettingBridge *) nm_setting_bridge_new (); + nm_connection_add_setting (connection, NM_SETTING (s_bridge)); + } + + /* Grab the first name that doesn't exist in either our connections + * or a device on the system. + */ + while (i < 500 && !nm_setting_bridge_get_interface_name (s_bridge)) { + name = g_strdup_printf ("br%u", i); + /* check interface names */ + if (!nm_platform_link_exists (name)) { + /* check existing bridge connections */ + for (iter = existing_connections, found = FALSE; iter; iter = g_slist_next (iter)) { + NMConnection *candidate = iter->data; + + tmp = nm_connection_get_setting_bridge (candidate); + if (tmp && nm_connection_is_type (candidate, NM_SETTING_BRIDGE_SETTING_NAME)) { + if (g_strcmp0 (nm_setting_bridge_get_interface_name (tmp), name) == 0) { + found = TRUE; + break; + } + } + } + + if (!found) + g_object_set (G_OBJECT (s_bridge), NM_SETTING_BRIDGE_INTERFACE_NAME, name, NULL); + } + + g_free (name); + i++; + } + + return TRUE; +} + +/******************************************************************/ + +typedef struct { + const char *name; + const char *sysname; + gboolean default_if_zero; + gboolean user_hz_compensate; +} Option; + +static const Option master_options[] = { + { NM_SETTING_BRIDGE_STP, "stp_state", FALSE, FALSE }, + { NM_SETTING_BRIDGE_PRIORITY, "priority", TRUE, FALSE }, + { NM_SETTING_BRIDGE_FORWARD_DELAY, "forward_delay", TRUE, TRUE }, + { NM_SETTING_BRIDGE_HELLO_TIME, "hello_time", TRUE, TRUE }, + { NM_SETTING_BRIDGE_MAX_AGE, "max_age", TRUE, TRUE }, + { NM_SETTING_BRIDGE_AGEING_TIME, "ageing_time", TRUE, TRUE }, + { NULL, NULL } +}; + +static const Option slave_options[] = { + { NM_SETTING_BRIDGE_PORT_PRIORITY, "priority", TRUE, FALSE }, + { NM_SETTING_BRIDGE_PORT_PATH_COST, "path_cost", TRUE, FALSE }, + { NM_SETTING_BRIDGE_PORT_HAIRPIN_MODE, "hairpin_mode", FALSE, FALSE }, + { NULL, NULL } +}; + +static void +commit_option (NMDevice *device, NMSetting *setting, const Option *option, gboolean slave) +{ + int ifindex = nm_device_get_ifindex (device); + GParamSpec *pspec; + GValue val = G_VALUE_INIT; + guint32 uval = 0; + gs_free char *value = NULL; + + g_assert (setting); + + pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (setting), option->name); + g_assert (pspec); + + /* Get the property's value */ + g_value_init (&val, G_PARAM_SPEC_VALUE_TYPE (pspec)); + g_object_get_property ((GObject *) setting, option->name, &val); + if (G_VALUE_HOLDS_BOOLEAN (&val)) + uval = g_value_get_boolean (&val) ? 1 : 0; + else if (G_VALUE_HOLDS_UINT (&val)) { + uval = g_value_get_uint (&val); + + /* zero means "unspecified" for some NM properties but isn't in the + * allowed kernel range, so reset the property to the default value. + */ + if (option->default_if_zero && uval == 0) { + g_value_unset (&val); + g_value_init (&val, G_PARAM_SPEC_VALUE_TYPE (pspec)); + g_param_value_set_default (pspec, &val); + uval = g_value_get_uint (&val); + } + + /* Linux kernel bridge interfaces use 'centiseconds' for time-based values. + * In reality it's not centiseconds, but depends on HZ and USER_HZ, which + * is almost always works out to be a multiplier of 100, so we can assume + * centiseconds. See clock_t_to_jiffies(). + */ + if (option->user_hz_compensate) + uval *= 100; + } else + g_assert_not_reached (); + g_value_unset (&val); + + value = g_strdup_printf ("%u", uval); + if (slave) + nm_platform_slave_set_option (ifindex, option->sysname, value); + else + nm_platform_master_set_option (ifindex, option->sysname, value); +} + +static void +commit_master_options (NMDevice *device, NMSettingBridge *setting) +{ + const Option *option; + NMSetting *s = NM_SETTING (setting); + + for (option = master_options; option->name; option++) + commit_option (device, s, option, FALSE); +} + +static void +commit_slave_options (NMDevice *device, NMSettingBridgePort *setting) +{ + const Option *option; + NMSetting *s, *s_clear = NULL; + + if (setting) + s = NM_SETTING (setting); + else + s = s_clear = nm_setting_bridge_port_new (); + + for (option = slave_options; option->name; option++) + commit_option (device, s, option, TRUE); + + g_clear_object (&s_clear); +} + +static void +update_connection (NMDevice *device, NMConnection *connection) +{ + NMSettingBridge *s_bridge = nm_connection_get_setting_bridge (connection); + const char *ifname = nm_device_get_iface (device); + int ifindex = nm_device_get_ifindex (device); + const Option *option; + + if (!s_bridge) { + s_bridge = (NMSettingBridge *) nm_setting_bridge_new (); + nm_connection_add_setting (connection, (NMSetting *) s_bridge); + g_object_set (s_bridge, NM_SETTING_BRIDGE_INTERFACE_NAME, ifname, NULL); + } + + for (option = master_options; option->name; option++) { + gs_free char *str = nm_platform_master_get_option (ifindex, option->sysname); + int value; + + if (str) { + value = strtol (str, NULL, 10); + + /* See comments in set_sysfs_uint() about centiseconds. */ + if (option->user_hz_compensate) + value /= 100; + + g_object_set (s_bridge, option->name, value, NULL); + } else { + nm_log_warn (LOGD_BRIDGE, "(%s): failed to read bridge setting '%s'", + nm_device_get_iface (device), option->sysname); + } + } +} + +/** + * nm_bridge_update_slave_connection: + * @slave: the slave #NMDevice, is *not* necessarily a bridge interface + * @connection: the #NMConnection to update with the bridge port settings + * + * Reads bridge port configuration and updates @connection with those + * properties. + * + * Returns: %TRUE if the port configuration was read and @connection updated, + * %FALSE if not. + */ +gboolean +nm_bridge_update_slave_connection (NMDevice *slave, NMConnection *connection) +{ + NMSettingBridgePort *s_port; + int ifindex = nm_device_get_ifindex (slave); + const Option *option; + + g_return_val_if_fail (NM_IS_DEVICE (slave), FALSE); + g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE); + + s_port = nm_connection_get_setting_bridge_port (connection); + if (!s_port) { + s_port = (NMSettingBridgePort *) nm_setting_bridge_port_new (); + nm_connection_add_setting (connection, NM_SETTING (s_port)); + } + + for (option = slave_options; option->name; option++) { + gs_free char *str = nm_platform_slave_get_option (ifindex, option->sysname); + int value; + + if (str) { + value = strtol (str, NULL, 10); + + /* See comments in set_sysfs_uint() about centiseconds. */ + if (option->user_hz_compensate) + value /= 100; + + g_object_set (s_port, option->name, value, NULL); + } else { + nm_log_warn (LOGD_BRIDGE, "(%s): failed to read bridge port setting '%s'", + nm_device_get_iface (slave), option->sysname); + } + } + + return TRUE; +} + +static NMActStageReturn +act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) +{ + NMActStageReturn ret; + NMConnection *connection = nm_device_get_connection (device); + + g_assert (connection); + + ret = NM_DEVICE_CLASS (nm_device_bridge_parent_class)->act_stage1_prepare (device, reason); + if (ret != NM_ACT_STAGE_RETURN_SUCCESS) + return ret; + + commit_master_options (device, nm_connection_get_setting_bridge (connection)); + + return NM_ACT_STAGE_RETURN_SUCCESS; +} + +static gboolean +enslave_slave (NMDevice *device, + NMDevice *slave, + NMConnection *connection, + gboolean configure) +{ + if (configure) { + if (!nm_platform_link_enslave (nm_device_get_ip_ifindex (device), nm_device_get_ip_ifindex (slave))) + return FALSE; + + commit_slave_options (slave, nm_connection_get_setting_bridge_port (connection)); + + nm_log_info (LOGD_BRIDGE, "(%s): attached bridge port %s", + nm_device_get_ip_iface (device), + nm_device_get_ip_iface (slave)); + } else { + nm_log_info (LOGD_BRIDGE, "(%s): bridge port %s was attached", + nm_device_get_ip_iface (device), + nm_device_get_ip_iface (slave)); + } + + g_object_notify (G_OBJECT (device), NM_DEVICE_BRIDGE_SLAVES); + + return TRUE; +} + +static gboolean +release_slave (NMDevice *device, + NMDevice *slave, + gboolean configure) +{ + gboolean success = TRUE; + + if (configure) { + success = nm_platform_link_release (nm_device_get_ip_ifindex (device), + nm_device_get_ip_ifindex (slave)); + + if (success) { + nm_log_info (LOGD_BRIDGE, "(%s): detached bridge port %s", + nm_device_get_ip_iface (device), + nm_device_get_ip_iface (slave)); + } else { + nm_log_warn (LOGD_BRIDGE, "(%s): failed to detach bridge port %s", + nm_device_get_ip_iface (device), + nm_device_get_ip_iface (slave)); + } + } else { + nm_log_info (LOGD_BRIDGE, "(%s): bridge port %s was detached", + nm_device_get_ip_iface (device), + nm_device_get_ip_iface (slave)); + } + + g_object_notify (G_OBJECT (device), NM_DEVICE_BRIDGE_SLAVES); + return success; +} + +/******************************************************************/ + +NMDevice * +nm_device_bridge_new (NMPlatformLink *platform_device) +{ + g_return_val_if_fail (platform_device != NULL, NULL); + + return (NMDevice *) g_object_new (NM_TYPE_DEVICE_BRIDGE, + NM_DEVICE_PLATFORM_DEVICE, platform_device, + NM_DEVICE_DRIVER, "bridge", + NM_DEVICE_TYPE_DESC, "Bridge", + NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_BRIDGE, + NM_DEVICE_IS_MASTER, TRUE, + NULL); +} + +NMDevice * +nm_device_bridge_new_for_connection (NMConnection *connection) +{ + const char *iface; + NMSettingBridge *s_bridge; + const GByteArray *mac_address; + + g_return_val_if_fail (connection != NULL, NULL); + + iface = nm_connection_get_virtual_iface_name (connection); + g_return_val_if_fail (iface != NULL, NULL); + + s_bridge = nm_connection_get_setting_bridge (connection); + g_return_val_if_fail (s_bridge, NULL); + + mac_address = nm_setting_bridge_get_mac_address (s_bridge); + + if ( !nm_platform_bridge_add (iface, + mac_address ? mac_address->data : NULL, + mac_address ? mac_address->len : 0) + && nm_platform_get_error () != NM_PLATFORM_ERROR_EXISTS) { + nm_log_warn (LOGD_DEVICE | LOGD_BRIDGE, "(%s): failed to create bridge master interface for '%s': %s", + iface, nm_connection_get_id (connection), + nm_platform_get_error_msg ()); + return NULL; + } + + return (NMDevice *) g_object_new (NM_TYPE_DEVICE_BRIDGE, + NM_DEVICE_IFACE, iface, + NM_DEVICE_DRIVER, "bridge", + NM_DEVICE_TYPE_DESC, "Bridge", + NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_BRIDGE, + NM_DEVICE_IS_MASTER, TRUE, + NULL); +} + +static void +constructed (GObject *object) +{ + G_OBJECT_CLASS (nm_device_bridge_parent_class)->constructed (object); + + nm_log_dbg (LOGD_HW | LOGD_BRIDGE, "(%s): kernel ifindex %d", + nm_device_get_iface (NM_DEVICE (object)), + nm_device_get_ifindex (NM_DEVICE (object))); +} + +static void +nm_device_bridge_init (NMDeviceBridge * self) +{ +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + GPtrArray *slaves; + GSList *list, *iter; + + switch (prop_id) { + break; + case PROP_SLAVES: + slaves = g_ptr_array_new (); + list = nm_device_master_get_slaves (NM_DEVICE (object)); + for (iter = list; iter; iter = iter->next) + g_ptr_array_add (slaves, g_strdup (nm_device_get_path (NM_DEVICE (iter->data)))); + g_slist_free (list); + g_value_take_boxed (value, slaves); + 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) +{ + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_device_bridge_class_init (NMDeviceBridgeClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (NMDeviceBridgePrivate)); + + parent_class->connection_type = NM_SETTING_BRIDGE_SETTING_NAME; + + /* virtual methods */ + object_class->constructed = constructed; + object_class->get_property = get_property; + object_class->set_property = set_property; + + parent_class->get_generic_capabilities = get_generic_capabilities; + parent_class->is_available = is_available; + parent_class->check_connection_compatible = check_connection_compatible; + parent_class->check_connection_available = check_connection_available; + parent_class->complete_connection = complete_connection; + + parent_class->update_connection = update_connection; + + parent_class->act_stage1_prepare = act_stage1_prepare; + parent_class->enslave_slave = enslave_slave; + parent_class->release_slave = release_slave; + + /* properties */ + g_object_class_install_property + (object_class, PROP_SLAVES, + g_param_spec_boxed (NM_DEVICE_BRIDGE_SLAVES, + "Slaves", + "Slaves", + DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH, + G_PARAM_READABLE)); + + nm_dbus_manager_register_exported_type (nm_dbus_manager_get (), + G_TYPE_FROM_CLASS (klass), + &dbus_glib_nm_device_bridge_object_info); + + dbus_g_error_domain_register (NM_BRIDGE_ERROR, NULL, NM_TYPE_BRIDGE_ERROR); +} diff --git a/src/devices/nm-device-bridge.h b/src/devices/nm-device-bridge.h new file mode 100644 index 00000000..4194f5a4 --- /dev/null +++ b/src/devices/nm-device-bridge.h @@ -0,0 +1,64 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright 2012 Red Hat, Inc. + */ + +#ifndef NM_DEVICE_BRIDGE_H +#define NM_DEVICE_BRIDGE_H + +#include + +#include "nm-device.h" + +G_BEGIN_DECLS + +#define NM_TYPE_DEVICE_BRIDGE (nm_device_bridge_get_type ()) +#define NM_DEVICE_BRIDGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_BRIDGE, NMDeviceBridge)) +#define NM_DEVICE_BRIDGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_BRIDGE, NMDeviceBridgeClass)) +#define NM_IS_DEVICE_BRIDGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_BRIDGE)) +#define NM_IS_DEVICE_BRIDGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_BRIDGE)) +#define NM_DEVICE_BRIDGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_BRIDGE, NMDeviceBridgeClass)) + +typedef enum { + NM_BRIDGE_ERROR_CONNECTION_NOT_BRIDGE = 0, /*< nick=ConnectionNotBridge >*/ + NM_BRIDGE_ERROR_CONNECTION_INVALID, /*< nick=ConnectionInvalid >*/ + NM_BRIDGE_ERROR_CONNECTION_INCOMPATIBLE, /*< nick=ConnectionIncompatible >*/ +} NMBridgeError; + +#define NM_DEVICE_BRIDGE_SLAVES "slaves" + +typedef struct { + NMDevice parent; +} NMDeviceBridge; + +typedef struct { + NMDeviceClass parent; + +} NMDeviceBridgeClass; + + +GType nm_device_bridge_get_type (void); + +NMDevice *nm_device_bridge_new (NMPlatformLink *platform_device); +NMDevice *nm_device_bridge_new_for_connection (NMConnection *connection); + +gboolean nm_bridge_update_slave_connection (NMDevice *slave, NMConnection *connection); + +G_END_DECLS + +#endif /* NM_DEVICE_BRIDGE_H */ diff --git a/src/devices/nm-device-ethernet.c b/src/devices/nm-device-ethernet.c new file mode 100644 index 00000000..f4a90c74 --- /dev/null +++ b/src/devices/nm-device-ethernet.c @@ -0,0 +1,1770 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2005 - 2014 Red Hat, Inc. + * Copyright (C) 2006 - 2008 Novell, Inc. + */ + +#include "config.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "nm-glib-compat.h" +#include "nm-device-ethernet.h" +#include "nm-device-private.h" +#include "nm-activation-request.h" +#include "NetworkManagerUtils.h" +#include "nm-supplicant-manager.h" +#include "nm-supplicant-interface.h" +#include "nm-supplicant-config.h" +#include "nm-setting-connection.h" +#include "nm-setting-wired.h" +#include "nm-setting-8021x.h" +#include "nm-setting-pppoe.h" +#include "nm-setting-bond.h" +#include "ppp-manager/nm-ppp-manager.h" +#include "nm-logging.h" +#include "nm-utils.h" +#include "nm-enum-types.h" +#include "nm-dbus-manager.h" +#include "nm-platform.h" +#include "nm-dcb.h" +#include "nm-settings-connection.h" + +#include "nm-device-ethernet-glue.h" + + +G_DEFINE_TYPE (NMDeviceEthernet, nm_device_ethernet, NM_TYPE_DEVICE) + +#define NM_DEVICE_ETHERNET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_ETHERNET, NMDeviceEthernetPrivate)) + +#define WIRED_SECRETS_TRIES "wired-secrets-tries" + +#define PPPOE_RECONNECT_DELAY 7 + +#define NM_ETHERNET_ERROR (nm_ethernet_error_quark ()) + +static NMSetting *device_get_setting (NMDevice *device, GType setting_type); + +typedef struct Supplicant { + NMSupplicantManager *mgr; + NMSupplicantInterface *iface; + + /* signal handler ids */ + guint iface_error_id; + guint iface_state_id; + + /* Timeouts and idles */ + guint iface_con_error_cb_id; + guint con_timeout_id; +} Supplicant; + +typedef enum { + DCB_WAIT_UNKNOWN = 0, + /* Ensure carrier is up before enabling DCB */ + DCB_WAIT_CARRIER_PREENABLE_UP, + /* Wait for carrier down when device starts enabling */ + DCB_WAIT_CARRIER_PRECONFIG_DOWN, + /* Wait for carrier up when device has finished enabling */ + DCB_WAIT_CARRIER_PRECONFIG_UP, + /* Wait carrier down when device starts configuring */ + DCB_WAIT_CARRIER_POSTCONFIG_DOWN, + /* Wait carrier up when device has finished configuring */ + DCB_WAIT_CARRIER_POSTCONFIG_UP, +} DcbWait; + +typedef struct { + guint8 perm_hw_addr[ETH_ALEN]; /* Permanent MAC address */ + guint8 initial_hw_addr[ETH_ALEN]; /* Initial MAC address (as seen when NM starts) */ + + guint32 speed; + + Supplicant supplicant; + guint supplicant_timeout_id; + + /* s390 */ + char * subchan1; + char * subchan2; + char * subchan3; + char * subchannels; /* Composite used for checking unmanaged specs */ + char * s390_nettype; + GHashTable * s390_options; + + /* PPPoE */ + NMPPPManager *ppp_manager; + NMIP4Config *pending_ip4_config; + gint32 last_pppoe_time; + guint pppoe_wait_id; + + /* DCB */ + DcbWait dcb_wait; + guint dcb_timeout_id; + guint dcb_carrier_id; +} NMDeviceEthernetPrivate; + +enum { + PROP_0, + PROP_PERM_HW_ADDRESS, + PROP_SPEED, + + LAST_PROP +}; + + +static GQuark +nm_ethernet_error_quark (void) +{ + static GQuark quark = 0; + if (!quark) + quark = g_quark_from_static_string ("nm-ethernet-error"); + return quark; +} + +static char * +get_link_basename (const char *parent_path, const char *name, GError **error) +{ + char *link_dest, *path; + char *result = NULL; + + path = g_strdup_printf ("%s/%s", parent_path, name); + link_dest = g_file_read_link (path, error); + if (link_dest) { + result = g_path_get_basename (link_dest); + g_free (link_dest); + } + g_free (path); + return result; +} + +static void +_update_s390_subchannels (NMDeviceEthernet *self) +{ + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); + const char *iface; + GUdevClient *client; + GUdevDevice *dev; + GUdevDevice *parent = NULL; + const char *parent_path, *item, *driver; + const char *subsystems[] = { "net", NULL }; + GDir *dir; + GError *error = NULL; + + iface = nm_device_get_iface (NM_DEVICE (self)); + + client = g_udev_client_new (subsystems); + if (!client) { + nm_log_warn (LOGD_DEVICE | LOGD_HW, "(%s): failed to initialize GUdev client", iface); + return; + } + + dev = g_udev_client_query_by_subsystem_and_name (client, "net", iface); + if (!dev) { + nm_log_warn (LOGD_DEVICE | LOGD_HW, "(%s): failed to find device with udev", iface); + goto out; + } + + /* Try for the "ccwgroup" parent */ + parent = g_udev_device_get_parent_with_subsystem (dev, "ccwgroup", NULL); + if (!parent) { + /* FIXME: whatever 'lcs' devices' subsystem is here... */ + if (!parent) { + /* Not an s390 device */ + goto out; + } + } + + parent_path = g_udev_device_get_sysfs_path (parent); + dir = g_dir_open (parent_path, 0, &error); + if (!dir) { + nm_log_warn (LOGD_DEVICE | LOGD_HW, "(%s): failed to open directory '%s': %s", + iface, parent_path, + error && error->message ? error->message : "(unknown)"); + g_clear_error (&error); + goto out; + } + + while ((item = g_dir_read_name (dir))) { + if (!strcmp (item, "cdev0")) { + priv->subchan1 = get_link_basename (parent_path, "cdev0", &error); + } else if (!strcmp (item, "cdev1")) { + priv->subchan2 = get_link_basename (parent_path, "cdev1", &error); + } else if (!strcmp (item, "cdev2")) { + priv->subchan3 = get_link_basename (parent_path, "cdev2", &error); + } else if (!strcmp (item, "driver")) { + priv->s390_nettype = get_link_basename (parent_path, "driver", &error); + } else if ( !strcmp (item, "layer2") + || !strcmp (item, "portname") + || !strcmp (item, "portno")) { + char *path, *value; + path = g_strdup_printf ("%s/%s", parent_path, item); + value = nm_platform_sysctl_get (path); + if (value && *value) + g_hash_table_insert (priv->s390_options, g_strdup (item), g_strdup (value)); + else + nm_log_warn (LOGD_DEVICE | LOGD_HW, "(%s): error reading %s", iface, path); + g_free (path); + g_free (value); + } + if (error) { + nm_log_warn (LOGD_DEVICE | LOGD_HW, "(%s): %s", iface, error->message); + g_clear_error (&error); + } + } + + g_dir_close (dir); + + if (priv->subchan3) { + priv->subchannels = g_strdup_printf ("%s,%s,%s", + priv->subchan1, + priv->subchan2, + priv->subchan3); + } else if (priv->subchan2) { + priv->subchannels = g_strdup_printf ("%s,%s", + priv->subchan1, + priv->subchan2); + } else + priv->subchannels = g_strdup (priv->subchan1); + + driver = nm_device_get_driver (NM_DEVICE (self)); + nm_log_info (LOGD_DEVICE | LOGD_HW, + "(%s): found s390 '%s' subchannels [%s]", + iface, driver ? driver : "(unknown driver)", priv->subchannels); + +out: + if (parent) + g_object_unref (parent); + if (dev) + g_object_unref (dev); + g_object_unref (client); +} + +static GObject* +constructor (GType type, + guint n_construct_params, + GObjectConstructParam *construct_params) +{ + GObject *object; + NMDevice *self; + int ifindex; + + object = G_OBJECT_CLASS (nm_device_ethernet_parent_class)->constructor (type, + n_construct_params, + construct_params); + if (object) { + self = NM_DEVICE (object); + ifindex = nm_device_get_ifindex (self); + + g_assert ( nm_platform_link_get_type (ifindex) == NM_LINK_TYPE_ETHERNET + || nm_platform_link_get_type (ifindex) == NM_LINK_TYPE_VETH); + + nm_log_dbg (LOGD_HW | LOGD_ETHER, "(%s): kernel ifindex %d", + nm_device_get_iface (NM_DEVICE (self)), + nm_device_get_ifindex (NM_DEVICE (self))); + + /* s390 stuff */ + _update_s390_subchannels (NM_DEVICE_ETHERNET (self)); + } + + return object; +} + +static void +clear_secrets_tries (NMDevice *device) +{ + NMActRequest *req; + NMConnection *connection; + + req = nm_device_get_act_request (device); + if (req) { + connection = nm_act_request_get_connection (req); + /* Clear wired secrets tries on success, failure, or when deactivating */ + g_object_set_data (G_OBJECT (connection), WIRED_SECRETS_TRIES, NULL); + } +} + +static void +device_state_changed (NMDevice *device, + NMDeviceState new_state, + NMDeviceState old_state, + NMDeviceStateReason reason) +{ + if ( new_state == NM_DEVICE_STATE_ACTIVATED + || new_state == NM_DEVICE_STATE_FAILED + || new_state == NM_DEVICE_STATE_DISCONNECTED) + clear_secrets_tries (device); +} + +static void +nm_device_ethernet_init (NMDeviceEthernet *self) +{ + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); + priv->s390_options = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); +} + +NMDevice * +nm_device_ethernet_new (NMPlatformLink *platform_device) +{ + g_return_val_if_fail (platform_device != NULL, NULL); + + return (NMDevice *) g_object_new (NM_TYPE_DEVICE_ETHERNET, + NM_DEVICE_PLATFORM_DEVICE, platform_device, + NM_DEVICE_TYPE_DESC, "Ethernet", + NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_ETHERNET, + NULL); +} + +static void +update_permanent_hw_address (NMDevice *dev) +{ + NMDeviceEthernet *self = NM_DEVICE_ETHERNET (dev); + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); + struct ifreq req; + struct ethtool_perm_addr *epaddr = NULL; + int fd, ret; + const guint8 *mac; + + fd = socket (PF_INET, SOCK_DGRAM, 0); + if (fd < 0) { + nm_log_warn (LOGD_HW, "couldn't open control socket."); + return; + } + + /* Get permanent MAC address */ + memset (&req, 0, sizeof (struct ifreq)); + strncpy (req.ifr_name, nm_device_get_iface (dev), IFNAMSIZ); + + epaddr = g_malloc0 (sizeof (struct ethtool_perm_addr) + ETH_ALEN); + epaddr->cmd = ETHTOOL_GPERMADDR; + epaddr->size = ETH_ALEN; + req.ifr_data = (void *) epaddr; + + errno = 0; + ret = ioctl (fd, SIOCETHTOOL, &req); + if ((ret < 0) || !nm_ethernet_address_is_valid ((struct ether_addr *) epaddr->data)) { + nm_log_dbg (LOGD_HW | LOGD_ETHER, "(%s): unable to read permanent MAC address (error %d)", + nm_device_get_iface (dev), errno); + /* Fall back to current address */ + mac = nm_device_get_hw_address (dev, NULL); + if (mac) + memcpy (epaddr->data, mac, ETH_ALEN); + else + memset (epaddr->data, 0, ETH_ALEN); + } + + if (memcmp (&priv->perm_hw_addr, epaddr->data, ETH_ALEN)) { + memcpy (&priv->perm_hw_addr, epaddr->data, ETH_ALEN); + g_object_notify (G_OBJECT (dev), NM_DEVICE_ETHERNET_PERMANENT_HW_ADDRESS); + } + + g_free (epaddr); + close (fd); +} + +static void +update_initial_hw_address (NMDevice *dev) +{ + NMDeviceEthernet *self = NM_DEVICE_ETHERNET (dev); + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); + char *mac_str; + const guint8 *mac; + + /* This sets initial MAC address from current MAC address. It should only + * be called from NMDevice constructor() to really get the initial address. + */ + mac = nm_device_get_hw_address (dev, NULL); + if (mac) + memcpy (priv->initial_hw_addr, mac, ETH_ALEN); + + mac_str = nm_utils_hwaddr_ntoa (priv->initial_hw_addr, ARPHRD_ETHER); + nm_log_dbg (LOGD_DEVICE | LOGD_ETHER, "(%s): read initial MAC address %s", + nm_device_get_iface (dev), mac_str); + g_free (mac_str); +} + +static guint32 +get_generic_capabilities (NMDevice *dev) +{ + if (nm_platform_link_supports_carrier_detect (nm_device_get_ifindex (dev))) + return NM_DEVICE_CAP_CARRIER_DETECT; + else { + nm_log_info (LOGD_HW, + "(%s): driver '%s' does not support carrier detection.", + nm_device_get_iface (dev), + nm_device_get_driver (dev)); + return NM_DEVICE_CAP_NONE; + } +} + +static gboolean +match_subchans (NMDeviceEthernet *self, NMSettingWired *s_wired, gboolean *try_mac) +{ + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); + const GPtrArray *subchans; + int i; + + *try_mac = TRUE; + + subchans = nm_setting_wired_get_s390_subchannels (s_wired); + if (!subchans) + return TRUE; + + /* connection requires subchannels but the device has none */ + if (!priv->subchannels) + return FALSE; + + /* Make sure each subchannel in the connection is a subchannel of this device */ + for (i = 0; i < subchans->len; i++) { + const char *candidate = g_ptr_array_index (subchans, i); + + if ( (priv->subchan1 && !strcmp (priv->subchan1, candidate)) + || (priv->subchan2 && !strcmp (priv->subchan2, candidate)) + || (priv->subchan3 && !strcmp (priv->subchan3, candidate))) + continue; + + return FALSE; /* a subchannel was not found */ + } + + *try_mac = FALSE; + return TRUE; +} + +static gboolean +check_connection_compatible (NMDevice *device, NMConnection *connection) +{ + NMDeviceEthernet *self = NM_DEVICE_ETHERNET (device); + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); + NMSettingWired *s_wired; + + if (!NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->check_connection_compatible (device, connection)) + return FALSE; + + s_wired = nm_connection_get_setting_wired (connection); + + if (nm_connection_is_type (connection, NM_SETTING_PPPOE_SETTING_NAME)) { + /* NOP */ + } else if (nm_connection_is_type (connection, NM_SETTING_WIRED_SETTING_NAME)) { + if (!s_wired) + return FALSE; + } else + return FALSE; + + if (s_wired) { + const GByteArray *mac; + gboolean try_mac = TRUE; + const GSList *mac_blacklist, *mac_blacklist_iter; + + if (!match_subchans (self, s_wired, &try_mac)) + return FALSE; + + mac = nm_setting_wired_get_mac_address (s_wired); + if (try_mac && mac && memcmp (mac->data, &priv->perm_hw_addr, ETH_ALEN)) + return FALSE; + + /* Check for MAC address blacklist */ + mac_blacklist = nm_setting_wired_get_mac_address_blacklist (s_wired); + for (mac_blacklist_iter = mac_blacklist; mac_blacklist_iter; + mac_blacklist_iter = g_slist_next (mac_blacklist_iter)) { + struct ether_addr addr; + + if (!ether_aton_r (mac_blacklist_iter->data, &addr)) { + g_warn_if_reached (); + return FALSE; + } + + if (memcmp (&addr, &priv->perm_hw_addr, ETH_ALEN) == 0) + return FALSE; + } + } + + return TRUE; +} + +/* FIXME: Move it to nm-device.c and then get rid of all foo_device_get_setting() all around. + It's here now to keep the patch short. */ +static NMSetting * +device_get_setting (NMDevice *device, GType setting_type) +{ + NMActRequest *req; + NMSetting *setting = NULL; + + req = nm_device_get_act_request (device); + if (req) { + NMConnection *connection; + + connection = nm_act_request_get_connection (req); + if (connection) + setting = nm_connection_get_setting (connection, setting_type); + } + + return setting; +} + +/*****************************************************************************/ +/* 802.1X */ + +static void +remove_supplicant_timeouts (NMDeviceEthernet *self) +{ + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); + + if (priv->supplicant.con_timeout_id) { + g_source_remove (priv->supplicant.con_timeout_id); + priv->supplicant.con_timeout_id = 0; + } + + if (priv->supplicant_timeout_id) { + g_source_remove (priv->supplicant_timeout_id); + priv->supplicant_timeout_id = 0; + } +} + +static void +remove_supplicant_interface_error_handler (NMDeviceEthernet *self) +{ + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); + + if (priv->supplicant.iface_error_id != 0) { + g_signal_handler_disconnect (priv->supplicant.iface, priv->supplicant.iface_error_id); + priv->supplicant.iface_error_id = 0; + } + + if (priv->supplicant.iface_con_error_cb_id > 0) { + g_source_remove (priv->supplicant.iface_con_error_cb_id); + priv->supplicant.iface_con_error_cb_id = 0; + } +} + +static void +supplicant_interface_release (NMDeviceEthernet *self) +{ + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); + + remove_supplicant_timeouts (self); + remove_supplicant_interface_error_handler (self); + + if (priv->supplicant.iface_state_id > 0) { + g_signal_handler_disconnect (priv->supplicant.iface, priv->supplicant.iface_state_id); + priv->supplicant.iface_state_id = 0; + } + + if (priv->supplicant.iface) { + nm_supplicant_interface_disconnect (priv->supplicant.iface); + nm_supplicant_manager_iface_release (priv->supplicant.mgr, priv->supplicant.iface); + priv->supplicant.iface = NULL; + } +} + +static void +wired_secrets_cb (NMActRequest *req, + guint32 call_id, + NMConnection *connection, + GError *error, + gpointer user_data) +{ + NMDevice *dev = NM_DEVICE (user_data); + + g_return_if_fail (req == nm_device_get_act_request (dev)); + g_return_if_fail (nm_device_get_state (dev) == NM_DEVICE_STATE_NEED_AUTH); + g_return_if_fail (nm_act_request_get_connection (req) == connection); + + if (error) { + nm_log_warn (LOGD_ETHER, "%s", error->message); + nm_device_state_changed (dev, + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_NO_SECRETS); + } else + nm_device_activate_schedule_stage1_device_prepare (dev); +} + +static gboolean +link_timeout_cb (gpointer user_data) +{ + NMDeviceEthernet *self = NM_DEVICE_ETHERNET (user_data); + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); + NMDevice *dev = NM_DEVICE (self); + NMActRequest *req; + NMConnection *connection; + const char *setting_name; + + priv->supplicant_timeout_id = 0; + + req = nm_device_get_act_request (dev); + + if (nm_device_get_state (dev) == NM_DEVICE_STATE_ACTIVATED) { + nm_device_state_changed (dev, + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT); + return FALSE; + } + + /* Disconnect event during initial authentication and credentials + * ARE checked - we are likely to have wrong key. Ask the user for + * another one. + */ + if (nm_device_get_state (dev) != NM_DEVICE_STATE_CONFIG) + goto time_out; + + connection = nm_act_request_get_connection (req); + nm_connection_clear_secrets (connection); + setting_name = nm_connection_need_secrets (connection, NULL); + if (!setting_name) + goto time_out; + + nm_log_info (LOGD_DEVICE | LOGD_ETHER, + "Activation (%s/wired): disconnected during authentication," + " asking for new key.", + nm_device_get_iface (dev)); + supplicant_interface_release (self); + + nm_device_state_changed (dev, NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT); + nm_act_request_get_secrets (req, + setting_name, + NM_SETTINGS_GET_SECRETS_FLAG_REQUEST_NEW, + NULL, + wired_secrets_cb, + self); + + return FALSE; + +time_out: + nm_log_warn (LOGD_DEVICE | LOGD_ETHER, + "(%s): link timed out.", nm_device_get_iface (dev)); + nm_device_state_changed (dev, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT); + + return FALSE; +} + +static NMSupplicantConfig * +build_supplicant_config (NMDeviceEthernet *self) +{ + const char *con_uuid; + NMSupplicantConfig *config = NULL; + NMSetting8021x *security; + NMConnection *connection; + + connection = nm_device_get_connection (NM_DEVICE (self)); + g_assert (connection); + con_uuid = nm_connection_get_uuid (connection); + + config = nm_supplicant_config_new (); + + security = nm_connection_get_setting_802_1x (connection); + if (!nm_supplicant_config_add_setting_8021x (config, security, con_uuid, TRUE)) { + nm_log_warn (LOGD_DEVICE, "Couldn't add 802.1X security setting to supplicant config."); + g_object_unref (config); + config = NULL; + } + + return config; +} + +static void +supplicant_iface_state_cb (NMSupplicantInterface *iface, + guint32 new_state, + guint32 old_state, + int disconnect_reason, + gpointer user_data) +{ + NMDeviceEthernet *self = NM_DEVICE_ETHERNET (user_data); + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); + NMDevice *device = NM_DEVICE (self); + NMSupplicantConfig *config; + gboolean success = FALSE; + NMDeviceState devstate; + + if (new_state == old_state) + return; + + nm_log_info (LOGD_DEVICE | LOGD_ETHER, + "(%s): supplicant interface state: %s -> %s", + nm_device_get_iface (device), + nm_supplicant_interface_state_to_string (old_state), + nm_supplicant_interface_state_to_string (new_state)); + + devstate = nm_device_get_state (device); + + switch (new_state) { + case NM_SUPPLICANT_INTERFACE_STATE_READY: + config = build_supplicant_config (self); + if (config) { + success = nm_supplicant_interface_set_config (priv->supplicant.iface, config); + g_object_unref (config); + + if (!success) { + nm_log_err (LOGD_DEVICE | LOGD_ETHER, + "Activation (%s/wired): couldn't send security " + "configuration to the supplicant.", + nm_device_get_iface (device)); + } + } else { + nm_log_warn (LOGD_DEVICE | LOGD_ETHER, + "Activation (%s/wired): couldn't build security configuration.", + nm_device_get_iface (device)); + } + + if (!success) { + nm_device_state_changed (device, + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED); + } + break; + case NM_SUPPLICANT_INTERFACE_STATE_COMPLETED: + remove_supplicant_interface_error_handler (self); + remove_supplicant_timeouts (self); + + /* If this is the initial association during device activation, + * schedule the next activation stage. + */ + if (devstate == NM_DEVICE_STATE_CONFIG) { + nm_log_info (LOGD_DEVICE | LOGD_ETHER, + "Activation (%s/wired) Stage 2 of 5 (Device Configure) successful.", + nm_device_get_iface (device)); + nm_device_activate_schedule_stage3_ip_config_start (device); + } + break; + case NM_SUPPLICANT_INTERFACE_STATE_DISCONNECTED: + if ((devstate == NM_DEVICE_STATE_ACTIVATED) || nm_device_is_activating (device)) { + /* Start the link timeout so we allow some time for reauthentication */ + if (!priv->supplicant_timeout_id) + priv->supplicant_timeout_id = g_timeout_add_seconds (15, link_timeout_cb, device); + } + break; + case NM_SUPPLICANT_INTERFACE_STATE_DOWN: + supplicant_interface_release (self); + remove_supplicant_timeouts (self); + + if ((devstate == NM_DEVICE_STATE_ACTIVATED) || nm_device_is_activating (device)) { + nm_device_state_changed (device, + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); + } + break; + default: + break; + } +} + +static gboolean +supplicant_iface_connection_error_cb_handler (gpointer user_data) +{ + NMDeviceEthernet *self = NM_DEVICE_ETHERNET (user_data); + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); + + supplicant_interface_release (self); + nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED); + + priv->supplicant.iface_con_error_cb_id = 0; + return FALSE; +} + +static void +supplicant_iface_connection_error_cb (NMSupplicantInterface *iface, + const char *name, + const char *message, + gpointer user_data) +{ + NMDeviceEthernet *self = NM_DEVICE_ETHERNET (user_data); + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); + guint id; + + nm_log_warn (LOGD_DEVICE | LOGD_ETHER, + "Activation (%s/wired): association request to the supplicant failed: %s - %s", + nm_device_get_iface (NM_DEVICE (self)), name, message); + + if (priv->supplicant.iface_con_error_cb_id) + g_source_remove (priv->supplicant.iface_con_error_cb_id); + + id = g_idle_add (supplicant_iface_connection_error_cb_handler, self); + priv->supplicant.iface_con_error_cb_id = id; +} + +static NMActStageReturn +handle_auth_or_fail (NMDeviceEthernet *self, + NMActRequest *req, + gboolean new_secrets) +{ + const char *setting_name; + guint32 tries; + NMConnection *connection; + + connection = nm_act_request_get_connection (req); + g_assert (connection); + + tries = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (connection), WIRED_SECRETS_TRIES)); + if (tries > 3) + return NM_ACT_STAGE_RETURN_FAILURE; + + nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_NONE); + + nm_connection_clear_secrets (connection); + setting_name = nm_connection_need_secrets (connection, NULL); + if (setting_name) { + NMSettingsGetSecretsFlags flags = NM_SETTINGS_GET_SECRETS_FLAG_ALLOW_INTERACTION; + + if (new_secrets) + flags |= NM_SETTINGS_GET_SECRETS_FLAG_REQUEST_NEW; + nm_act_request_get_secrets (req, setting_name, flags, NULL, wired_secrets_cb, self); + + g_object_set_data (G_OBJECT (connection), WIRED_SECRETS_TRIES, GUINT_TO_POINTER (++tries)); + } else { + nm_log_info (LOGD_DEVICE, "Cleared secrets, but setting didn't need any secrets."); + } + + return NM_ACT_STAGE_RETURN_POSTPONE; +} + +static gboolean +supplicant_connection_timeout_cb (gpointer user_data) +{ + NMDeviceEthernet *self = NM_DEVICE_ETHERNET (user_data); + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); + NMDevice *device = NM_DEVICE (self); + NMActRequest *req; + NMConnection *connection; + const char *iface; + guint64 timestamp = 0; + gboolean new_secrets = TRUE; + + priv->supplicant.con_timeout_id = 0; + + iface = nm_device_get_iface (device); + + /* Authentication failed; either driver problems, the encryption key is + * wrong, the passwords or certificates were wrong or the Ethernet switch's + * port is not configured for 802.1x. */ + nm_log_warn (LOGD_DEVICE | LOGD_ETHER, + "Activation (%s/wired): association took too long.", iface); + + supplicant_interface_release (self); + req = nm_device_get_act_request (device); + g_assert (req); + + connection = nm_act_request_get_connection (req); + g_assert (connection); + + /* Ask for new secrets only if we've never activated this connection + * before. If we've connected before, don't bother the user with dialogs, + * just retry or fail, and if we never connect the user can fix the + * password somewhere else. */ + if (nm_settings_connection_get_timestamp (NM_SETTINGS_CONNECTION (connection), ×tamp)) + new_secrets = !timestamp; + + if (handle_auth_or_fail (self, req, new_secrets) == NM_ACT_STAGE_RETURN_POSTPONE) { + nm_log_info (LOGD_DEVICE | LOGD_ETHER, + "Activation (%s/wired): asking for new secrets", iface); + } else + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_NO_SECRETS); + + return FALSE; +} + +static gboolean +supplicant_interface_init (NMDeviceEthernet *self) +{ + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); + const char *iface; + + iface = nm_device_get_iface (NM_DEVICE (self)); + + /* Create supplicant interface */ + priv->supplicant.iface = nm_supplicant_manager_iface_get (priv->supplicant.mgr, iface, FALSE); + if (!priv->supplicant.iface) { + nm_log_err (LOGD_DEVICE | LOGD_ETHER, + "Couldn't initialize supplicant interface for %s.", + iface); + supplicant_interface_release (self); + return FALSE; + } + + /* Listen for it's state signals */ + priv->supplicant.iface_state_id = g_signal_connect (priv->supplicant.iface, + NM_SUPPLICANT_INTERFACE_STATE, + G_CALLBACK (supplicant_iface_state_cb), + self); + + /* Hook up error signal handler to capture association errors */ + priv->supplicant.iface_error_id = g_signal_connect (priv->supplicant.iface, + "connection-error", + G_CALLBACK (supplicant_iface_connection_error_cb), + self); + + /* Set up a timeout on the connection attempt to fail it after 25 seconds */ + priv->supplicant.con_timeout_id = g_timeout_add_seconds (25, supplicant_connection_timeout_cb, self); + + return TRUE; +} + +static gboolean +pppoe_reconnect_delay (gpointer user_data) +{ + NMDevice *device = NM_DEVICE (user_data); + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (device); + + priv->pppoe_wait_id = 0; + nm_log_info (LOGD_DEVICE, "(%s) PPPoE reconnect delay complete, resuming connection...", + nm_device_get_iface (device)); + nm_device_activate_schedule_stage2_device_config (device); + return FALSE; +} + +static NMActStageReturn +act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason) +{ + NMDeviceEthernet *self = NM_DEVICE_ETHERNET (dev); + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); + NMActRequest *req; + NMSettingWired *s_wired; + const GByteArray *cloned_mac; + NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS; + + g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); + + ret = NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->act_stage1_prepare (dev, reason); + if (ret == NM_ACT_STAGE_RETURN_SUCCESS) { + req = nm_device_get_act_request (NM_DEVICE (self)); + g_return_val_if_fail (req != NULL, NM_ACT_STAGE_RETURN_FAILURE); + + s_wired = (NMSettingWired *) device_get_setting (dev, NM_TYPE_SETTING_WIRED); + if (s_wired) { + /* Set device MAC address if the connection wants to change it */ + cloned_mac = nm_setting_wired_get_cloned_mac_address (s_wired); + if (cloned_mac && (cloned_mac->len == ETH_ALEN)) + nm_device_set_hw_addr (dev, cloned_mac->data, "set", LOGD_ETHER); + } + + /* If we're re-activating a PPPoE connection a short while after + * a previous PPPoE connection was torn down, wait a bit to allow the + * remote side to handle the disconnection. Otherwise the peer may + * get confused and fail to negotiate the new connection. (rh #1023503) + */ + if (priv->last_pppoe_time) { + gint32 delay = nm_utils_get_monotonic_timestamp_s () - priv->last_pppoe_time; + + if (delay < PPPOE_RECONNECT_DELAY && device_get_setting (dev, NM_TYPE_SETTING_PPPOE)) { + nm_log_info (LOGD_DEVICE, "(%s) delaying PPPoE reconnect for %d seconds to ensure peer is ready...", + nm_device_get_iface (dev), delay); + g_assert (!priv->pppoe_wait_id); + priv->pppoe_wait_id = g_timeout_add_seconds (delay, + pppoe_reconnect_delay, + self); + ret = NM_ACT_STAGE_RETURN_POSTPONE; + } else + priv->last_pppoe_time = 0; + } + } + + return ret; +} + +static NMActStageReturn +nm_8021x_stage2_config (NMDeviceEthernet *self, NMDeviceStateReason *reason) +{ + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); + NMConnection *connection; + NMSetting8021x *security; + const char *setting_name; + const char *iface; + NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; + + connection = nm_device_get_connection (NM_DEVICE (self)); + g_assert (connection); + security = nm_connection_get_setting_802_1x (connection); + if (!security) { + nm_log_err (LOGD_DEVICE, "Invalid or missing 802.1X security"); + *reason = NM_DEVICE_STATE_REASON_CONFIG_FAILED; + return ret; + } + + if (!priv->supplicant.mgr) + priv->supplicant.mgr = nm_supplicant_manager_get (); + + iface = nm_device_get_iface (NM_DEVICE (self)); + + /* If we need secrets, get them */ + setting_name = nm_connection_need_secrets (connection, NULL); + if (setting_name) { + NMActRequest *req = nm_device_get_act_request (NM_DEVICE (self)); + + nm_log_info (LOGD_DEVICE | LOGD_ETHER, + "Activation (%s/wired): connection '%s' has security, but secrets are required.", + iface, nm_connection_get_id (connection)); + + ret = handle_auth_or_fail (self, req, FALSE); + if (ret != NM_ACT_STAGE_RETURN_POSTPONE) + *reason = NM_DEVICE_STATE_REASON_NO_SECRETS; + } else { + nm_log_info (LOGD_DEVICE | LOGD_ETHER, + "Activation (%s/wired): connection '%s' requires no security. No secrets needed.", + iface, nm_connection_get_id (connection)); + + if (supplicant_interface_init (self)) + ret = NM_ACT_STAGE_RETURN_POSTPONE; + else + *reason = NM_DEVICE_STATE_REASON_CONFIG_FAILED; + } + + return ret; +} + +/*****************************************************************************/ +/* PPPoE */ + +static void +ppp_state_changed (NMPPPManager *ppp_manager, NMPPPStatus status, gpointer user_data) +{ + NMDevice *device = NM_DEVICE (user_data); + + switch (status) { + case NM_PPP_STATUS_DISCONNECT: + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_PPP_DISCONNECT); + break; + case NM_PPP_STATUS_DEAD: + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_PPP_FAILED); + break; + default: + break; + } +} + +static void +ppp_ip4_config (NMPPPManager *ppp_manager, + const char *iface, + NMIP4Config *config, + gpointer user_data) +{ + NMDevice *device = NM_DEVICE (user_data); + + /* Ignore PPP IP4 events that come in after initial configuration */ + if (nm_device_activate_ip4_state_in_conf (device)) { + nm_device_set_ip_iface (device, iface); + nm_device_activate_schedule_ip4_config_result (device, config); + } +} + +static NMActStageReturn +pppoe_stage3_ip4_config_start (NMDeviceEthernet *self, NMDeviceStateReason *reason) +{ + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); + NMConnection *connection; + NMSettingPPPOE *s_pppoe; + NMActRequest *req; + GError *err = NULL; + NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; + + req = nm_device_get_act_request (NM_DEVICE (self)); + g_assert (req); + + connection = nm_act_request_get_connection (req); + g_assert (req); + + s_pppoe = nm_connection_get_setting_pppoe (connection); + g_assert (s_pppoe); + + priv->ppp_manager = nm_ppp_manager_new (nm_device_get_iface (NM_DEVICE (self))); + if (nm_ppp_manager_start (priv->ppp_manager, req, nm_setting_pppoe_get_username (s_pppoe), 30, &err)) { + g_signal_connect (priv->ppp_manager, "state-changed", + G_CALLBACK (ppp_state_changed), + self); + g_signal_connect (priv->ppp_manager, "ip4-config", + G_CALLBACK (ppp_ip4_config), + self); + ret = NM_ACT_STAGE_RETURN_POSTPONE; + } else { + nm_log_warn (LOGD_DEVICE, "(%s): PPPoE failed to start: %s", + nm_device_get_iface (NM_DEVICE (self)), err->message); + g_error_free (err); + + g_object_unref (priv->ppp_manager); + priv->ppp_manager = NULL; + + *reason = NM_DEVICE_STATE_REASON_PPP_START_FAILED; + } + + return ret; +} + +/****************************************************************/ + +static void +dcb_timeout_cleanup (NMDevice *device) +{ + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (device); + + if (priv->dcb_timeout_id) { + g_source_remove (priv->dcb_timeout_id); + priv->dcb_timeout_id = 0; + } +} + +static void +dcb_carrier_cleanup (NMDevice *device) +{ + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (device); + + if (priv->dcb_carrier_id) { + g_signal_handler_disconnect (device, priv->dcb_carrier_id); + priv->dcb_carrier_id = 0; + } +} + +static void dcb_state (NMDevice *device, gboolean timeout); + +static gboolean +dcb_carrier_timeout (gpointer user_data) +{ + NMDevice *device = NM_DEVICE (user_data); + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (device); + + g_return_val_if_fail (nm_device_get_state (device) == NM_DEVICE_STATE_CONFIG, G_SOURCE_REMOVE); + + priv->dcb_timeout_id = 0; + if (priv->dcb_wait != DCB_WAIT_CARRIER_POSTCONFIG_DOWN) { + nm_log_warn (LOGD_DCB, + "(%s): DCB: timed out waiting for carrier (step %d)", + nm_device_get_iface (device), + priv->dcb_wait); + } + dcb_state (device, TRUE); + return G_SOURCE_REMOVE; +} + +static gboolean +dcb_configure (NMDevice *device) +{ + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (device); + NMSettingDcb *s_dcb; + const char *iface = nm_device_get_iface (device); + GError *error = NULL; + + dcb_timeout_cleanup (device); + + s_dcb = (NMSettingDcb *) device_get_setting (device, NM_TYPE_SETTING_DCB); + g_assert (s_dcb); + if (!nm_dcb_setup (iface, s_dcb, &error)) { + nm_log_warn (LOGD_DCB, + "Activation (%s/wired) failed to enable DCB/FCoE: %s", + iface, error->message); + g_clear_error (&error); + return FALSE; + } + + /* Pause again just in case the device takes the carrier down when + * setting specific DCB attributes. + */ + nm_log_dbg (LOGD_DCB, "(%s): waiting for carrier (postconfig down)", iface); + priv->dcb_wait = DCB_WAIT_CARRIER_POSTCONFIG_DOWN; + priv->dcb_timeout_id = g_timeout_add_seconds (3, dcb_carrier_timeout, device); + return TRUE; +} + +static gboolean +dcb_enable (NMDevice *device) +{ + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (device); + const char *iface = nm_device_get_iface (device); + GError *error = NULL; + + dcb_timeout_cleanup (device); + if (!nm_dcb_enable (iface, TRUE, &error)) { + nm_log_warn (LOGD_DCB, + "Activation (%s/wired) failed to enable DCB/FCoE: %s", + iface, error->message); + g_clear_error (&error); + return FALSE; + } + + /* Pause for 3 seconds after enabling DCB to let the card reconfigure + * itself. Drivers will often re-initialize internal settings which + * takes the carrier down for 2 or more seconds. During this time, + * lldpad will refuse to do anything else with the card since the carrier + * is down. But NM might get the carrier-down signal long after calling + * "dcbtool dcb on", so we have to first wait for the carrier to go down. + */ + nm_log_dbg (LOGD_DCB, "(%s): waiting for carrier (preconfig down)", iface); + priv->dcb_wait = DCB_WAIT_CARRIER_PRECONFIG_DOWN; + priv->dcb_timeout_id = g_timeout_add_seconds (3, dcb_carrier_timeout, device); + return TRUE; +} + +static void +dcb_state (NMDevice *device, gboolean timeout) +{ + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (device); + const char *iface = nm_device_get_iface (device); + gboolean carrier; + + g_return_if_fail (nm_device_get_state (device) == NM_DEVICE_STATE_CONFIG); + + + carrier = nm_platform_link_is_connected (nm_device_get_ifindex (device)); + nm_log_dbg (LOGD_DCB, "(%s): dcb_state() wait %d carrier %d timeout %d", iface, priv->dcb_wait, carrier, timeout); + + switch (priv->dcb_wait) { + case DCB_WAIT_CARRIER_PREENABLE_UP: + if (timeout || carrier) { + nm_log_dbg (LOGD_DCB, "(%s): dcb_state() enabling DCB", iface); + dcb_timeout_cleanup (device); + if (!dcb_enable (device)) { + dcb_carrier_cleanup (device); + nm_device_state_changed (device, + NM_ACT_STAGE_RETURN_FAILURE, + NM_DEVICE_STATE_REASON_DCB_FCOE_FAILED); + } + } + break; + case DCB_WAIT_CARRIER_PRECONFIG_DOWN: + dcb_timeout_cleanup (device); + priv->dcb_wait = DCB_WAIT_CARRIER_PRECONFIG_UP; + + if (!carrier) { + /* Wait for the carrier to come back up */ + nm_log_dbg (LOGD_DCB, "(%s): waiting for carrier (preconfig up)", iface); + priv->dcb_timeout_id = g_timeout_add_seconds (5, dcb_carrier_timeout, device); + break; + } + nm_log_dbg (LOGD_DCB, "(%s): dcb_state() preconfig down falling through", iface); + /* carrier never went down? fall through */ + case DCB_WAIT_CARRIER_PRECONFIG_UP: + if (timeout || carrier) { + nm_log_dbg (LOGD_DCB, "(%s): dcb_state() preconfig up configuring DCB", iface); + dcb_timeout_cleanup (device); + if (!dcb_configure (device)) { + dcb_carrier_cleanup (device); + nm_device_state_changed (device, + NM_ACT_STAGE_RETURN_FAILURE, + NM_DEVICE_STATE_REASON_DCB_FCOE_FAILED); + } + } + break; + case DCB_WAIT_CARRIER_POSTCONFIG_DOWN: + dcb_timeout_cleanup (device); + priv->dcb_wait = DCB_WAIT_CARRIER_POSTCONFIG_UP; + + if (!carrier) { + /* Wait for the carrier to come back up */ + nm_log_dbg (LOGD_DCB, "(%s): waiting for carrier (postconfig up)", iface); + priv->dcb_timeout_id = g_timeout_add_seconds (5, dcb_carrier_timeout, device); + break; + } + nm_log_dbg (LOGD_DCB, "(%s): dcb_state() postconfig down falling through", iface); + /* carrier never went down? fall through */ + case DCB_WAIT_CARRIER_POSTCONFIG_UP: + if (timeout || carrier) { + nm_log_dbg (LOGD_DCB, "(%s): dcb_state() postconfig up starting IP", iface); + dcb_timeout_cleanup (device); + dcb_carrier_cleanup (device); + priv->dcb_wait = DCB_WAIT_UNKNOWN; + nm_device_activate_schedule_stage3_ip_config_start (device); + } + break; + default: + g_assert_not_reached (); + } +} + +static void +dcb_carrier_changed (NMDevice *device, GParamSpec *pspec, gpointer unused) +{ + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (device); + + g_return_if_fail (nm_device_get_state (device) == NM_DEVICE_STATE_CONFIG); + + if (priv->dcb_timeout_id) { + nm_log_dbg (LOGD_DCB, "(%s): carrier_changed() calling dcb_state()", nm_device_get_iface (device)); + dcb_state (device, FALSE); + } +} + +/****************************************************************/ + +static NMActStageReturn +act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) +{ + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (device); + NMSettingConnection *s_con; + const char *connection_type; + NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS; + NMSettingDcb *s_dcb; + + g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); + + s_con = NM_SETTING_CONNECTION (device_get_setting (device, NM_TYPE_SETTING_CONNECTION)); + g_assert (s_con); + + dcb_timeout_cleanup (device); + dcb_carrier_cleanup (device); + + /* 802.1x has to run before any IP configuration since the 802.1x auth + * process opens the port up for normal traffic. + */ + connection_type = nm_setting_connection_get_connection_type (s_con); + if (!strcmp (connection_type, NM_SETTING_WIRED_SETTING_NAME)) { + NMSetting8021x *security; + + security = (NMSetting8021x *) device_get_setting (device, NM_TYPE_SETTING_802_1X); + if (security) { + /* FIXME: for now 802.1x is mutually exclusive with DCB */ + return nm_8021x_stage2_config (NM_DEVICE_ETHERNET (device), reason); + } + } + + /* DCB and FCoE setup */ + s_dcb = (NMSettingDcb *) device_get_setting (device, NM_TYPE_SETTING_DCB); + if (s_dcb) { + /* lldpad really really wants the carrier to be up */ + if (nm_platform_link_is_connected (nm_device_get_ifindex (device))) { + if (!dcb_enable (device)) { + *reason = NM_DEVICE_STATE_REASON_DCB_FCOE_FAILED; + return NM_ACT_STAGE_RETURN_FAILURE; + } + } else { + nm_log_dbg (LOGD_DCB, "(%s): waiting for carrier (preenable up)", + nm_device_get_iface (device)); + priv->dcb_wait = DCB_WAIT_CARRIER_PREENABLE_UP; + priv->dcb_timeout_id = g_timeout_add_seconds (4, dcb_carrier_timeout, device); + } + + /* Watch carrier independently of NMDeviceClass::carrier_changed so + * we get instant notifications of disconnection that aren't deferred. + */ + priv->dcb_carrier_id = g_signal_connect (device, + "notify::" NM_DEVICE_CARRIER, + G_CALLBACK (dcb_carrier_changed), + NULL); + ret = NM_ACT_STAGE_RETURN_POSTPONE; + } + + return ret; +} + +static NMActStageReturn +act_stage3_ip4_config_start (NMDevice *device, + NMIP4Config **out_config, + NMDeviceStateReason *reason) +{ + NMSettingConnection *s_con; + const char *connection_type; + + g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); + + s_con = NM_SETTING_CONNECTION (device_get_setting (device, NM_TYPE_SETTING_CONNECTION)); + g_assert (s_con); + + connection_type = nm_setting_connection_get_connection_type (s_con); + if (!strcmp (connection_type, NM_SETTING_PPPOE_SETTING_NAME)) + return pppoe_stage3_ip4_config_start (NM_DEVICE_ETHERNET (device), reason); + + return NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->act_stage3_ip4_config_start (device, out_config, reason); +} + +static void +ip4_config_pre_commit (NMDevice *device, NMIP4Config *config) +{ + NMConnection *connection; + NMSettingWired *s_wired; + guint32 mtu; + + /* MTU only set for plain ethernet */ + if (NM_DEVICE_ETHERNET_GET_PRIVATE (device)->ppp_manager) + return; + + connection = nm_device_get_connection (device); + g_assert (connection); + s_wired = nm_connection_get_setting_wired (connection); + g_assert (s_wired); + + /* MTU override */ + mtu = nm_setting_wired_get_mtu (s_wired); + if (mtu) + nm_ip4_config_set_mtu (config, mtu); +} + +static void +deactivate (NMDevice *device) +{ + NMDeviceEthernet *self = NM_DEVICE_ETHERNET (device); + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); + NMSettingDcb *s_dcb; + GError *error = NULL; + + /* Clear wired secrets tries when deactivating */ + clear_secrets_tries (device); + + if (priv->pppoe_wait_id) { + g_source_remove (priv->pppoe_wait_id); + priv->pppoe_wait_id = 0; + } + + if (priv->pending_ip4_config) { + g_object_unref (priv->pending_ip4_config); + priv->pending_ip4_config = NULL; + } + + if (priv->ppp_manager) { + g_object_unref (priv->ppp_manager); + priv->ppp_manager = NULL; + } + + supplicant_interface_release (self); + + priv->dcb_wait = DCB_WAIT_UNKNOWN; + dcb_timeout_cleanup (device); + dcb_carrier_cleanup (device); + + /* Tear down DCB/FCoE if it was enabled */ + s_dcb = (NMSettingDcb *) device_get_setting (device, NM_TYPE_SETTING_DCB); + if (s_dcb) { + if (!nm_dcb_cleanup (nm_device_get_iface (device), &error)) { + nm_log_warn (LOGD_DEVICE | LOGD_HW, + "(%s) failed to disable DCB/FCoE: %s", + nm_device_get_iface (device), error->message); + g_clear_error (&error); + } + } + + /* Set last PPPoE connection time */ + if (device_get_setting (device, NM_TYPE_SETTING_PPPOE)) + NM_DEVICE_ETHERNET_GET_PRIVATE (device)->last_pppoe_time = nm_utils_get_monotonic_timestamp_s (); + + /* Reset MAC address back to initial address */ + nm_device_set_hw_addr (device, priv->initial_hw_addr, "reset", LOGD_ETHER); +} + +static gboolean +complete_connection (NMDevice *device, + NMConnection *connection, + const char *specific_object, + const GSList *existing_connections, + GError **error) +{ + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (device); + NMSettingWired *s_wired; + NMSettingPPPOE *s_pppoe; + const GByteArray *setting_mac; + + s_pppoe = nm_connection_get_setting_pppoe (connection); + + /* We can't telepathically figure out the service name or username, so if + * those weren't given, we can't complete the connection. + */ + if (s_pppoe && !nm_setting_verify (NM_SETTING (s_pppoe), NULL, error)) + return FALSE; + + /* Default to an ethernet-only connection, but if a PPPoE setting was given + * then PPPoE should be our connection type. + */ + nm_utils_complete_generic (connection, + s_pppoe ? NM_SETTING_PPPOE_SETTING_NAME : NM_SETTING_WIRED_SETTING_NAME, + existing_connections, + s_pppoe ? _("PPPoE connection %d") : _("Wired connection %d"), + NULL, + s_pppoe ? FALSE : TRUE); /* No IPv6 by default yet for PPPoE */ + + s_wired = nm_connection_get_setting_wired (connection); + if (!s_wired) { + s_wired = (NMSettingWired *) nm_setting_wired_new (); + nm_connection_add_setting (connection, NM_SETTING (s_wired)); + } + + setting_mac = nm_setting_wired_get_mac_address (s_wired); + if (setting_mac) { + /* Make sure the setting MAC (if any) matches the device's permanent MAC */ + if (memcmp (setting_mac->data, priv->perm_hw_addr, ETH_ALEN)) { + g_set_error_literal (error, + NM_SETTING_WIRED_ERROR, + NM_SETTING_WIRED_ERROR_INVALID_PROPERTY, + NM_SETTING_WIRED_MAC_ADDRESS); + return FALSE; + } + } else { + GByteArray *mac; + const guint8 null_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; + + /* Lock the connection to this device by default */ + if (memcmp (priv->perm_hw_addr, null_mac, ETH_ALEN)) { + mac = g_byte_array_sized_new (ETH_ALEN); + g_byte_array_append (mac, priv->perm_hw_addr, ETH_ALEN); + g_object_set (G_OBJECT (s_wired), NM_SETTING_WIRED_MAC_ADDRESS, mac, NULL); + g_byte_array_free (mac, TRUE); + } + } + + return TRUE; +} + +static gboolean +spec_match_list (NMDevice *device, const GSList *specs) +{ + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (device); + + if (priv->subchannels && nm_match_spec_s390_subchannels (specs, priv->subchannels)) + return TRUE; + + return NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->spec_match_list (device, specs); +} + +static void +update_connection (NMDevice *device, NMConnection *connection) +{ + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (device); + NMSettingWired *s_wired = nm_connection_get_setting_wired (connection); + guint maclen; + const guint8 *mac = nm_device_get_hw_address (device, &maclen); + static const guint8 null_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; + const char *mac_prop = NM_SETTING_WIRED_MAC_ADDRESS; + GByteArray *array; + GHashTableIter iter; + gpointer key, value; + + if (!s_wired) { + s_wired = (NMSettingWired *) nm_setting_wired_new (); + nm_connection_add_setting (connection, (NMSetting *) s_wired); + } + + /* If the device reports a permanent address, use that for the MAC address + * and the current MAC, if different, is the cloned MAC. + */ + if (memcmp (priv->perm_hw_addr, null_mac, ETH_ALEN)) { + array = g_byte_array_sized_new (ETH_ALEN); + g_byte_array_append (array, priv->perm_hw_addr, ETH_ALEN); + g_object_set (s_wired, NM_SETTING_WIRED_MAC_ADDRESS, array, NULL); + g_byte_array_unref (array); + + mac_prop = NULL; + if (mac && memcmp (priv->perm_hw_addr, mac, ETH_ALEN)) + mac_prop = NM_SETTING_WIRED_CLONED_MAC_ADDRESS; + } + + if (mac_prop && mac && maclen == ETH_ALEN) { + array = g_byte_array_sized_new (ETH_ALEN); + g_byte_array_append (array, (guint8 *) mac, maclen); + g_object_set (s_wired, mac_prop, array, NULL); + g_byte_array_unref (array); + } + + /* We don't set the MTU as we don't know whether it was set explicitly */ + + /* s390 */ + if (priv->subchannels) { + GPtrArray *subchan_arr = g_ptr_array_sized_new (3); + if (priv->subchan1) + g_ptr_array_add (subchan_arr, priv->subchan1); + if (priv->subchan2) + g_ptr_array_add (subchan_arr, priv->subchan2); + if (priv->subchan3) + g_ptr_array_add (subchan_arr, priv->subchan3); + g_object_set (s_wired, NM_SETTING_WIRED_S390_SUBCHANNELS, subchan_arr, NULL); + g_ptr_array_free (subchan_arr, TRUE); + } + if (priv->s390_nettype) + g_object_set (s_wired, NM_SETTING_WIRED_S390_NETTYPE, priv->s390_nettype, NULL); + g_hash_table_iter_init (&iter, priv->s390_options); + while (g_hash_table_iter_next (&iter, &key, &value)) { + nm_setting_wired_add_s390_option (s_wired, (const char *) key, (const char *) value); + } + +} + +static void +get_link_speed (NMDevice *device) +{ + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (device); + struct ifreq ifr; + struct ethtool_cmd edata = { + .cmd = ETHTOOL_GSET, + }; + guint32 speed; + int fd; + + fd = socket (PF_INET, SOCK_DGRAM, 0); + if (fd < 0) { + nm_log_warn (LOGD_HW | LOGD_ETHER, "couldn't open ethtool control socket."); + return; + } + + memset (&ifr, 0, sizeof (struct ifreq)); + strncpy (ifr.ifr_name, nm_device_get_iface (device), IFNAMSIZ); + ifr.ifr_data = (char *) &edata; + + if (ioctl (fd, SIOCETHTOOL, &ifr) < 0) { + close (fd); + return; + } + close (fd); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) + speed = edata.speed; +#else + speed = ethtool_cmd_speed (&edata); +#endif + if (speed == G_MAXUINT16 || speed == G_MAXUINT32) + speed = 0; + + if (priv->speed == speed) + return; + + priv->speed = speed; + g_object_notify (G_OBJECT (device), "speed"); + + nm_log_dbg (LOGD_HW | LOGD_ETHER, "(%s): speed is now %d Mb/s", + nm_device_get_iface (device), speed); +} + +static void +carrier_changed (NMDevice *device, gboolean carrier) +{ + if (carrier) + get_link_speed (device); + + NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->carrier_changed (device, carrier); +} + +static void +dispose (GObject *object) +{ + NMDeviceEthernet *self = NM_DEVICE_ETHERNET (object); + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); + + if (priv->pppoe_wait_id) { + g_source_remove (priv->pppoe_wait_id); + priv->pppoe_wait_id = 0; + } + + dcb_timeout_cleanup (NM_DEVICE (self)); + dcb_carrier_cleanup (NM_DEVICE (self)); + + G_OBJECT_CLASS (nm_device_ethernet_parent_class)->dispose (object); +} + +static void +finalize (GObject *object) +{ + NMDeviceEthernet *self = NM_DEVICE_ETHERNET (object); + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); + + g_clear_object (&priv->supplicant.mgr); + g_free (priv->subchan1); + g_free (priv->subchan2); + g_free (priv->subchan3); + g_free (priv->subchannels); + g_free (priv->s390_nettype); + g_hash_table_destroy (priv->s390_options); + + G_OBJECT_CLASS (nm_device_ethernet_parent_class)->finalize (object); +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMDeviceEthernet *self = NM_DEVICE_ETHERNET (object); + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); + + switch (prop_id) { + case PROP_PERM_HW_ADDRESS: + g_value_take_string (value, nm_utils_hwaddr_ntoa (&priv->perm_hw_addr, ARPHRD_ETHER)); + break; + case PROP_SPEED: + g_value_set_uint (value, priv->speed); + 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) +{ + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_device_ethernet_class_init (NMDeviceEthernetClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (NMDeviceEthernetPrivate)); + + parent_class->connection_type = NM_SETTING_WIRED_SETTING_NAME; + + /* virtual methods */ + object_class->constructor = constructor; + object_class->dispose = dispose; + object_class->finalize = finalize; + object_class->get_property = get_property; + object_class->set_property = set_property; + + parent_class->get_generic_capabilities = get_generic_capabilities; + parent_class->update_permanent_hw_address = update_permanent_hw_address; + parent_class->update_initial_hw_address = update_initial_hw_address; + parent_class->check_connection_compatible = check_connection_compatible; + parent_class->complete_connection = complete_connection; + + parent_class->act_stage1_prepare = act_stage1_prepare; + parent_class->act_stage2_config = act_stage2_config; + parent_class->act_stage3_ip4_config_start = act_stage3_ip4_config_start; + parent_class->ip4_config_pre_commit = ip4_config_pre_commit; + parent_class->deactivate = deactivate; + parent_class->spec_match_list = spec_match_list; + parent_class->update_connection = update_connection; + parent_class->carrier_changed = carrier_changed; + + parent_class->state_changed = device_state_changed; + + /* properties */ + g_object_class_install_property + (object_class, PROP_PERM_HW_ADDRESS, + g_param_spec_string (NM_DEVICE_ETHERNET_PERMANENT_HW_ADDRESS, + "Permanent MAC Address", + "Permanent hardware MAC address", + NULL, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_SPEED, + g_param_spec_uint (NM_DEVICE_ETHERNET_SPEED, + "Speed", + "Speed", + 0, G_MAXUINT32, 0, + G_PARAM_READABLE)); + + nm_dbus_manager_register_exported_type (nm_dbus_manager_get (), + G_TYPE_FROM_CLASS (klass), + &dbus_glib_nm_device_ethernet_object_info); + + dbus_g_error_domain_register (NM_ETHERNET_ERROR, NULL, NM_TYPE_ETHERNET_ERROR); +} diff --git a/src/devices/nm-device-ethernet.h b/src/devices/nm-device-ethernet.h new file mode 100644 index 00000000..bcaf270a --- /dev/null +++ b/src/devices/nm-device-ethernet.h @@ -0,0 +1,65 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2005 - 2010 Red Hat, Inc. + * Copyright (C) 2006 - 2008 Novell, Inc. + */ + +#ifndef NM_DEVICE_ETHERNET_H +#define NM_DEVICE_ETHERNET_H + +#include + +#include "nm-device.h" + +G_BEGIN_DECLS + +#define NM_TYPE_DEVICE_ETHERNET (nm_device_ethernet_get_type ()) +#define NM_DEVICE_ETHERNET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_ETHERNET, NMDeviceEthernet)) +#define NM_DEVICE_ETHERNET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_ETHERNET, NMDeviceEthernetClass)) +#define NM_IS_DEVICE_ETHERNET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_ETHERNET)) +#define NM_IS_DEVICE_ETHERNET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_ETHERNET)) +#define NM_DEVICE_ETHERNET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_ETHERNET, NMDeviceEthernetClass)) + +typedef enum +{ + NM_ETHERNET_ERROR_CONNECTION_NOT_WIRED = 0, /*< nick=ConnectionNotWired >*/ + NM_ETHERNET_ERROR_CONNECTION_INVALID, /*< nick=ConnectionInvalid >*/ + NM_ETHERNET_ERROR_CONNECTION_INCOMPATIBLE, /*< nick=ConnectionIncompatible >*/ +} NMEthernetError; + +#define NM_DEVICE_ETHERNET_PERMANENT_HW_ADDRESS "perm-hw-address" +#define NM_DEVICE_ETHERNET_SPEED "speed" + +typedef struct { + NMDevice parent; +} NMDeviceEthernet; + +typedef struct { + NMDeviceClass parent; + +} NMDeviceEthernetClass; + + +GType nm_device_ethernet_get_type (void); + + +NMDevice *nm_device_ethernet_new (NMPlatformLink *platform_device); + +G_END_DECLS + +#endif /* NM_DEVICE_ETHERNET_H */ diff --git a/src/devices/nm-device-factory.c b/src/devices/nm-device-factory.c new file mode 100644 index 00000000..fc4d1c24 --- /dev/null +++ b/src/devices/nm-device-factory.c @@ -0,0 +1,106 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2014 Red Hat, Inc. + */ + +#include "nm-device-factory.h" + +enum { + DEVICE_ADDED, + COMPONENT_ADDED, + LAST_SIGNAL +}; +static guint signals[LAST_SIGNAL] = { 0 }; + +gboolean +nm_device_factory_emit_component_added (NMDeviceFactory *factory, GObject *component) +{ + gboolean consumed = FALSE; + + g_signal_emit (factory, signals[COMPONENT_ADDED], 0, component, &consumed); + return consumed; +} + +static void +interface_init (gpointer g_iface) +{ + GType iface_type = G_TYPE_FROM_INTERFACE (g_iface); + static gboolean initialized = FALSE; + + if (G_LIKELY (initialized)) + return; + + /* Signals */ + signals[DEVICE_ADDED] = g_signal_new (NM_DEVICE_FACTORY_DEVICE_ADDED, + iface_type, + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMDeviceFactory, device_added), + NULL, NULL, NULL, + G_TYPE_NONE, 1, NM_TYPE_DEVICE); + + signals[COMPONENT_ADDED] = g_signal_new (NM_DEVICE_FACTORY_COMPONENT_ADDED, + iface_type, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (NMDeviceFactory, component_added), + g_signal_accumulator_true_handled, NULL, NULL, + G_TYPE_BOOLEAN, 1, G_TYPE_OBJECT); + + initialized = TRUE; +} + +GType +nm_device_factory_get_type (void) +{ + static GType device_factory_type = 0; + + if (!device_factory_type) { + const GTypeInfo device_factory_info = { + sizeof (NMDeviceFactory), /* class_size */ + interface_init, /* base_init */ + NULL, /* base_finalize */ + NULL, + NULL, /* class_finalize */ + NULL, /* class_data */ + 0, + 0, /* n_preallocs */ + NULL + }; + + device_factory_type = g_type_register_static (G_TYPE_INTERFACE, + "NMDeviceFactory", + &device_factory_info, + 0); + g_type_interface_add_prerequisite (device_factory_type, G_TYPE_OBJECT); + } + + return device_factory_type; +} + +NMDevice * +nm_device_factory_new_link (NMDeviceFactory *factory, + NMPlatformLink *plink, + GError **error) +{ + g_return_val_if_fail (factory != NULL, NULL); + g_return_val_if_fail (plink != NULL, NULL); + + if (NM_DEVICE_FACTORY_GET_INTERFACE (factory)->new_link) + return NM_DEVICE_FACTORY_GET_INTERFACE (factory)->new_link (factory, plink, error); + return NULL; +} + diff --git a/src/devices/nm-device-factory.h b/src/devices/nm-device-factory.h new file mode 100644 index 00000000..f0e3dc19 --- /dev/null +++ b/src/devices/nm-device-factory.h @@ -0,0 +1,136 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2007 - 2014 Red Hat, Inc. + */ + +#ifndef NM_DEVICE_FACTORY_H +#define NM_DEVICE_FACTORY_H + +#include +#include + +#include "NetworkManager.h" +#include "nm-platform.h" +#include "nm-device.h" + +/* WARNING: this file is private API between NetworkManager and its internal + * device plugins. Its API can change at any time and is not guaranteed to be + * stable. NM and device plugins are distributed together and this API is + * not meant to enable third-party plugins. + */ + +typedef struct _NMDeviceFactory NMDeviceFactory; + +/** + * nm_device_factory_create: + * @error: an error if creation of the factory failed, or %NULL + * + * Creates a #GObject that implements the #NMDeviceFactory interface. This + * function must not emit any signals or perform any actions that would cause + * devices or components to be created immediately. Instead these should be + * deferred to an idle handler. + * + * Returns: the #GObject implementing #NMDeviceFactory or %NULL + */ +NMDeviceFactory *nm_device_factory_create (GError **error); + +/* Should match nm_device_factory_create() */ +typedef NMDeviceFactory * (*NMDeviceFactoryCreateFunc) (GError **error); + +/** + * nm_device_factory_get_device_type: + * + * Returns: the #NMDeviceType that this plugin creates + */ +NMDeviceType nm_device_factory_get_device_type (void); + +/* Should match nm_device_factory_get_device_type() */ +typedef NMDeviceType (*NMDeviceFactoryDeviceTypeFunc) (void); + +/********************************************************************/ + +#define NM_TYPE_DEVICE_FACTORY (nm_device_factory_get_type ()) +#define NM_DEVICE_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_FACTORY, NMDeviceFactory)) +#define NM_IS_DEVICE_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_FACTORY)) +#define NM_DEVICE_FACTORY_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), NM_TYPE_DEVICE_FACTORY, NMDeviceFactory)) + +/* signals */ +#define NM_DEVICE_FACTORY_COMPONENT_ADDED "component-added" +#define NM_DEVICE_FACTORY_DEVICE_ADDED "device-added" + +struct _NMDeviceFactory { + GTypeInterface g_iface; + + /** + * new_link: + * @factory: the #NMDeviceFactory + * @link: the new link + * @error: error if the link could be claimed but an error occurred + * + * The NetworkManager core was notified of a new link which the plugin + * may want to claim and create a #NMDevice subclass for. If the link + * represents a device the factory is capable of claiming, but the device + * could not be created, %NULL should be returned and @error should be set. + * %NULL should always be returned and @error should never be set if the + * factory cannot create devices for the type which @link represents. + * + * Returns: the #NMDevice if the link was claimed and created, %NULL if not + */ + NMDevice * (*new_link) (NMDeviceFactory *factory, + NMPlatformLink *plink, + GError **error); + + /* Signals */ + + /** + * device_added: + * @factory: the #NMDeviceFactory + * @device: the new #NMDevice subclass + * + * The factory emits this signal if it finds a new device by itself. + */ + void (*device_added) (NMDeviceFactory *factory, NMDevice *device); + + /** + * component_added: + * @factory: the #NMDeviceFactory + * @component: a new component which existing devices may wish to claim + * + * The factory emits this signal when it finds a new component. For example, + * the WWAN factory may indicate that a new modem is available, which an + * existing Bluetooth device may wish to claim. If no device claims the + * component, the plugin is allowed to create a new #NMDevice instance for + * that component and emit the "device-added" signal. + * + * Returns: %TRUE if the component was claimed by a device, %FALSE if not + */ + gboolean (*component_added) (NMDeviceFactory *factory, GObject *component); +}; + +GType nm_device_factory_get_type (void); + +NMDevice * nm_device_factory_new_link (NMDeviceFactory *factory, + NMPlatformLink *plink, + GError **error); + +/* For use by implementations */ +gboolean nm_device_factory_emit_component_added (NMDeviceFactory *factory, + GObject *component); + +#endif /* NM_DEVICE_FACTORY_H */ + diff --git a/src/devices/nm-device-generic.c b/src/devices/nm-device-generic.c new file mode 100644 index 00000000..5261c133 --- /dev/null +++ b/src/devices/nm-device-generic.c @@ -0,0 +1,217 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright 2013 Red Hat, Inc. + */ + +#include "config.h" + +#include "nm-device-generic.h" +#include "nm-device-private.h" +#include "nm-enum-types.h" +#include "nm-platform.h" +#include "nm-utils.h" +#include "nm-glib-compat.h" +#include "nm-dbus-manager.h" + +#include "nm-device-generic-glue.h" + +G_DEFINE_TYPE (NMDeviceGeneric, nm_device_generic, NM_TYPE_DEVICE) + +#define NM_DEVICE_GENERIC_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_GENERIC, NMDeviceGenericPrivate)) + +typedef struct { + char *type_description; +} NMDeviceGenericPrivate; + +enum { + PROP_0, + PROP_TYPE_DESCRIPTION, + + LAST_PROP +}; + +#define NM_DEVICE_GENERIC_ERROR (nm_device_generic_error_quark ()) + +static GQuark +nm_device_generic_error_quark (void) +{ + static GQuark quark = 0; + if (!quark) + quark = g_quark_from_static_string ("nm-device-generic-error"); + return quark; +} + +/**************************************************************/ + +static guint32 +get_generic_capabilities (NMDevice *dev) +{ + if (nm_platform_link_supports_carrier_detect (nm_device_get_ifindex (dev))) + return NM_DEVICE_CAP_CARRIER_DETECT; + else + return NM_DEVICE_CAP_NONE; +} + +static gboolean +check_connection_compatible (NMDevice *device, NMConnection *connection) +{ + NMSettingConnection *s_con; + + if (!NM_DEVICE_CLASS (nm_device_generic_parent_class)->check_connection_compatible (device, connection)) + return FALSE; + + if (!nm_connection_is_type (connection, NM_SETTING_GENERIC_SETTING_NAME)) + return FALSE; + + s_con = nm_connection_get_setting_connection (connection); + if (!nm_setting_connection_get_interface_name (s_con)) + return FALSE; + + return TRUE; +} + +static void +update_connection (NMDevice *device, NMConnection *connection) +{ + NMSettingConnection *s_con; + + if (!nm_connection_get_setting_generic (connection)) + nm_connection_add_setting (connection, nm_setting_generic_new ()); + + s_con = nm_connection_get_setting_connection (connection); + g_assert (s_con); + g_object_set (G_OBJECT (s_con), + NM_SETTING_CONNECTION_INTERFACE_NAME, nm_device_get_iface (device), + NULL); +} + +/**************************************************************/ + +NMDevice * +nm_device_generic_new (NMPlatformLink *platform_device) +{ + g_return_val_if_fail (platform_device != NULL, NULL); + + return (NMDevice *) g_object_new (NM_TYPE_DEVICE_GENERIC, + NM_DEVICE_PLATFORM_DEVICE, platform_device, + NM_DEVICE_TYPE_DESC, "Generic", + NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_GENERIC, + NULL); +} + +static void +nm_device_generic_init (NMDeviceGeneric *self) +{ + nm_device_set_initial_unmanaged_flag (NM_DEVICE (self), NM_UNMANAGED_DEFAULT, TRUE); +} + +static void +constructed (GObject *object) +{ + NMDeviceGeneric *self = NM_DEVICE_GENERIC (object); + NMDeviceGenericPrivate *priv = NM_DEVICE_GENERIC_GET_PRIVATE (self); + + if (!priv->type_description) { + int ifindex = nm_device_get_ip_ifindex (NM_DEVICE (self)); + + if (ifindex != 0) + priv->type_description = g_strdup (nm_platform_link_get_type_name (ifindex)); + } + + G_OBJECT_CLASS (nm_device_generic_parent_class)->constructed (object); +} + +static void +dispose (GObject *object) +{ + NMDeviceGeneric *self = NM_DEVICE_GENERIC (object); + NMDeviceGenericPrivate *priv = NM_DEVICE_GENERIC_GET_PRIVATE (self); + + g_clear_pointer (&priv->type_description, g_free); + + G_OBJECT_CLASS (nm_device_generic_parent_class)->dispose (object); +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMDeviceGeneric *self = NM_DEVICE_GENERIC (object); + NMDeviceGenericPrivate *priv = NM_DEVICE_GENERIC_GET_PRIVATE (self); + + switch (prop_id) { + case PROP_TYPE_DESCRIPTION: + g_value_set_string (value, priv->type_description); + 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) +{ + NMDeviceGeneric *self = NM_DEVICE_GENERIC (object); + NMDeviceGenericPrivate *priv = NM_DEVICE_GENERIC_GET_PRIVATE (self); + + switch (prop_id) { + case PROP_TYPE_DESCRIPTION: + priv->type_description = g_value_dup_string (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_device_generic_class_init (NMDeviceGenericClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass); + + g_type_class_add_private (klass, sizeof (NMDeviceGenericPrivate)); + + parent_class->connection_type = NM_SETTING_GENERIC_SETTING_NAME; + + object_class->constructed = constructed; + object_class->dispose = dispose; + object_class->get_property = get_property; + object_class->set_property = set_property; + + parent_class->get_generic_capabilities = get_generic_capabilities; + parent_class->check_connection_compatible = check_connection_compatible; + parent_class->update_connection = update_connection; + + /* properties */ + g_object_class_install_property + (object_class, PROP_TYPE_DESCRIPTION, + g_param_spec_string (NM_DEVICE_GENERIC_TYPE_DESCRIPTION, + "Type Description", + "Type description", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + nm_dbus_manager_register_exported_type (nm_dbus_manager_get (), + G_TYPE_FROM_CLASS (klass), + &dbus_glib_nm_device_generic_object_info); + + dbus_g_error_domain_register (NM_DEVICE_GENERIC_ERROR, NULL, NM_TYPE_DEVICE_GENERIC_ERROR); +} diff --git a/src/devices/nm-device-generic.h b/src/devices/nm-device-generic.h new file mode 100644 index 00000000..e7b7090b --- /dev/null +++ b/src/devices/nm-device-generic.h @@ -0,0 +1,61 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright 2013 Red Hat, Inc. + */ + +#ifndef NM_DEVICE_GENERIC_H +#define NM_DEVICE_GENERIC_H + +#include + +#include "nm-device.h" + +G_BEGIN_DECLS + +#define NM_TYPE_DEVICE_GENERIC (nm_device_generic_get_type ()) +#define NM_DEVICE_GENERIC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_GENERIC, NMDeviceGeneric)) +#define NM_DEVICE_GENERIC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_GENERIC, NMDeviceGenericClass)) +#define NM_IS_DEVICE_GENERIC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_GENERIC)) +#define NM_IS_DEVICE_GENERIC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_GENERIC)) +#define NM_DEVICE_GENERIC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_GENERIC, NMDeviceGenericClass)) + +typedef enum +{ + NM_DEVICE_GENERIC_ERROR_CONNECTION_NOT_GENERIC = 0, /*< nick=ConnectionNotGeneric >*/ + NM_DEVICE_GENERIC_ERROR_CONNECTION_INVALID, /*< nick=ConnectionInvalid >*/ + NM_DEVICE_GENERIC_ERROR_CONNECTION_INCOMPATIBLE, /*< nick=ConnectionIncompatible >*/ +} NMDeviceGenericError; + +#define NM_DEVICE_GENERIC_TYPE_DESCRIPTION "type-description" + +typedef struct { + NMDevice parent; +} NMDeviceGeneric; + +typedef struct { + NMDeviceClass parent; + +} NMDeviceGenericClass; + +GType nm_device_generic_get_type (void); + +NMDevice *nm_device_generic_new (NMPlatformLink *platform_device); + +G_END_DECLS + +#endif /* NM_DEVICE_GENERIC_H */ diff --git a/src/devices/nm-device-gre.c b/src/devices/nm-device-gre.c new file mode 100644 index 00000000..0412e993 --- /dev/null +++ b/src/devices/nm-device-gre.c @@ -0,0 +1,278 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright 2013 Red Hat, Inc. + */ + +#include "config.h" + +#include + +#include "nm-device-gre.h" +#include "nm-device-private.h" +#include "nm-dbus-manager.h" +#include "nm-logging.h" +#include "nm-manager.h" +#include "nm-platform.h" + +#include "nm-device-gre-glue.h" + +G_DEFINE_TYPE (NMDeviceGre, nm_device_gre, NM_TYPE_DEVICE_GENERIC) + +#define NM_DEVICE_GRE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_GRE, NMDeviceGrePrivate)) + +typedef struct { + NMPlatformGreProperties props; +} NMDeviceGrePrivate; + +enum { + PROP_0, + PROP_PARENT, + PROP_INPUT_FLAGS, + PROP_OUTPUT_FLAGS, + PROP_INPUT_KEY, + PROP_OUTPUT_KEY, + PROP_LOCAL, + PROP_REMOTE, + PROP_TTL, + PROP_TOS, + PROP_PATH_MTU_DISCOVERY, + + LAST_PROP +}; + +/**************************************************************/ + +static void +update_properties (NMDevice *device) +{ + NMDeviceGrePrivate *priv = NM_DEVICE_GRE_GET_PRIVATE (device); + GObject *object = G_OBJECT (device); + NMPlatformGreProperties props; + + if (!nm_platform_gre_get_properties (nm_device_get_ifindex (device), &props)) { + nm_log_warn (LOGD_HW, "(%s): could not read gre properties", + nm_device_get_iface (device)); + return; + } + + g_object_freeze_notify (object); + + if (priv->props.parent_ifindex != props.parent_ifindex) + g_object_notify (object, NM_DEVICE_GRE_PARENT); + if (priv->props.input_flags != props.input_flags) + g_object_notify (object, NM_DEVICE_GRE_INPUT_FLAGS); + if (priv->props.output_flags != props.output_flags) + g_object_notify (object, NM_DEVICE_GRE_OUTPUT_FLAGS); + if (priv->props.input_key != props.input_key) + g_object_notify (object, NM_DEVICE_GRE_INPUT_KEY); + if (priv->props.output_key != props.output_key) + g_object_notify (object, NM_DEVICE_GRE_OUTPUT_KEY); + if (priv->props.local != props.local) + g_object_notify (object, NM_DEVICE_GRE_LOCAL); + if (priv->props.remote != props.remote) + g_object_notify (object, NM_DEVICE_GRE_REMOTE); + if (priv->props.ttl != props.ttl) + g_object_notify (object, NM_DEVICE_GRE_TTL); + if (priv->props.tos != props.tos) + g_object_notify (object, NM_DEVICE_GRE_TOS); + if (priv->props.path_mtu_discovery != props.path_mtu_discovery) + g_object_notify (object, NM_DEVICE_GRE_PATH_MTU_DISCOVERY); + + memcpy (&priv->props, &props, sizeof (NMPlatformGreProperties)); + + g_object_thaw_notify (object); +} + +static void +link_changed (NMDevice *device, NMPlatformLink *info) +{ + NM_DEVICE_CLASS (nm_device_gre_parent_class)->link_changed (device, info); + update_properties (device); +} + +/**************************************************************/ + +NMDevice * +nm_device_gre_new (NMPlatformLink *platform_device) +{ + g_return_val_if_fail (platform_device != NULL, NULL); + + return (NMDevice *) g_object_new (NM_TYPE_DEVICE_GRE, + NM_DEVICE_PLATFORM_DEVICE, platform_device, + NM_DEVICE_TYPE_DESC, "Gre", + NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_GENERIC, + NULL); +} + +static void +nm_device_gre_init (NMDeviceGre *self) +{ +} + +static void +constructed (GObject *object) +{ + update_properties (NM_DEVICE (object)); + + G_OBJECT_CLASS (nm_device_gre_parent_class)->constructed (object); +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMDeviceGrePrivate *priv = NM_DEVICE_GRE_GET_PRIVATE (object); + char buf[INET_ADDRSTRLEN]; + NMDevice *parent; + + switch (prop_id) { + case PROP_PARENT: + parent = nm_manager_get_device_by_ifindex (nm_manager_get (), priv->props.parent_ifindex); + g_value_set_boxed (value, parent ? nm_device_get_path (parent) : "/"); + break; + case PROP_INPUT_FLAGS: + g_value_set_uint (value, priv->props.input_flags); + break; + case PROP_OUTPUT_FLAGS: + g_value_set_uint (value, priv->props.output_flags); + break; + case PROP_INPUT_KEY: + g_value_set_uint (value, priv->props.input_key); + break; + case PROP_OUTPUT_KEY: + g_value_set_uint (value, priv->props.output_key); + break; + case PROP_LOCAL: + g_value_set_string (value, inet_ntop (AF_INET, &priv->props.local, buf, sizeof (buf))); + break; + case PROP_REMOTE: + g_value_set_string (value, inet_ntop (AF_INET, &priv->props.remote, buf, sizeof (buf))); + break; + case PROP_TTL: + g_value_set_uchar (value, priv->props.ttl); + break; + case PROP_TOS: + g_value_set_uchar (value, priv->props.tos); + break; + case PROP_PATH_MTU_DISCOVERY: + g_value_set_boolean (value, priv->props.path_mtu_discovery); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_device_gre_class_init (NMDeviceGreClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); + + g_type_class_add_private (klass, sizeof (NMDeviceGrePrivate)); + + object_class->constructed = constructed; + object_class->get_property = get_property; + + device_class->link_changed = link_changed; + + /* properties */ + g_object_class_install_property + (object_class, PROP_PARENT, + g_param_spec_boxed (NM_DEVICE_GRE_PARENT, + "Parent", + "Parent device", + DBUS_TYPE_G_OBJECT_PATH, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_INPUT_FLAGS, + g_param_spec_uint (NM_DEVICE_GRE_INPUT_FLAGS, + "Input flags", + "Input flags", + 0, G_MAXUINT16, 0, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_OUTPUT_FLAGS, + g_param_spec_uint (NM_DEVICE_GRE_OUTPUT_FLAGS, + "Output flags", + "Output flags", + 0, G_MAXUINT16, 0, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_INPUT_KEY, + g_param_spec_uint (NM_DEVICE_GRE_INPUT_KEY, + "Input key", + "Input key", + 0, G_MAXUINT32, 0, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_OUTPUT_KEY, + g_param_spec_uint (NM_DEVICE_GRE_OUTPUT_KEY, + "Output key", + "Output key", + 0, G_MAXUINT32, 0, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_LOCAL, + g_param_spec_string (NM_DEVICE_GRE_LOCAL, + "Local", + "Local", + NULL, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_REMOTE, + g_param_spec_string (NM_DEVICE_GRE_REMOTE, + "Remote", + "Remote", + NULL, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_TTL, + g_param_spec_uchar (NM_DEVICE_GRE_TTL, + "TTL", + "TTL", + 0, 255, 0, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_TOS, + g_param_spec_uchar (NM_DEVICE_GRE_TOS, + "ToS", + "ToS", + 0, 255, 0, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_PATH_MTU_DISCOVERY, + g_param_spec_boolean (NM_DEVICE_GRE_PATH_MTU_DISCOVERY, + "Path MTU Discovery", + "Path MTU Discovery", + FALSE, + G_PARAM_READABLE)); + + nm_dbus_manager_register_exported_type (nm_dbus_manager_get (), + G_TYPE_FROM_CLASS (klass), + &dbus_glib_nm_device_gre_object_info); +} diff --git a/src/devices/nm-device-gre.h b/src/devices/nm-device-gre.h new file mode 100644 index 00000000..610b3805 --- /dev/null +++ b/src/devices/nm-device-gre.h @@ -0,0 +1,63 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright 2013 Red Hat, Inc. + */ + +#ifndef NM_DEVICE_GRE_H +#define NM_DEVICE_GRE_H + +#include + +#include "nm-device-generic.h" + +G_BEGIN_DECLS + +#define NM_TYPE_DEVICE_GRE (nm_device_gre_get_type ()) +#define NM_DEVICE_GRE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_GRE, NMDeviceGre)) +#define NM_DEVICE_GRE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_GRE, NMDeviceGreClass)) +#define NM_IS_DEVICE_GRE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_GRE)) +#define NM_IS_DEVICE_GRE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_GRE)) +#define NM_DEVICE_GRE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_GRE, NMDeviceGreClass)) + +#define NM_DEVICE_GRE_PARENT "parent" +#define NM_DEVICE_GRE_INPUT_FLAGS "input-flags" +#define NM_DEVICE_GRE_OUTPUT_FLAGS "output-flags" +#define NM_DEVICE_GRE_INPUT_KEY "input-key" +#define NM_DEVICE_GRE_OUTPUT_KEY "output-key" +#define NM_DEVICE_GRE_LOCAL "local" +#define NM_DEVICE_GRE_REMOTE "remote" +#define NM_DEVICE_GRE_TTL "ttl" +#define NM_DEVICE_GRE_TOS "tos" +#define NM_DEVICE_GRE_PATH_MTU_DISCOVERY "path-mtu-discovery" + +typedef struct { + NMDeviceGeneric parent; +} NMDeviceGre; + +typedef struct { + NMDeviceGenericClass parent; + +} NMDeviceGreClass; + +GType nm_device_gre_get_type (void); + +NMDevice *nm_device_gre_new (NMPlatformLink *platform_device); + +G_END_DECLS + +#endif /* NM_DEVICE_GRE_H */ diff --git a/src/devices/nm-device-infiniband.c b/src/devices/nm-device-infiniband.c new file mode 100644 index 00000000..8ec79157 --- /dev/null +++ b/src/devices/nm-device-infiniband.c @@ -0,0 +1,412 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright 2011 Red Hat, Inc. + */ + +#include "config.h" + +#include +#include + +#include +#include + +#include "nm-device-infiniband.h" +#include "nm-logging.h" +#include "nm-utils.h" +#include "NetworkManagerUtils.h" +#include "nm-device-private.h" +#include "nm-enum-types.h" +#include "nm-dbus-manager.h" + +#include "nm-device-infiniband-glue.h" + + +G_DEFINE_TYPE (NMDeviceInfiniband, nm_device_infiniband, NM_TYPE_DEVICE) + +#define NM_DEVICE_INFINIBAND_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_INFINIBAND, NMDeviceInfinibandPrivate)) + +#define NM_INFINIBAND_ERROR (nm_infiniband_error_quark ()) + +typedef struct { + int dummy; +} NMDeviceInfinibandPrivate; + +enum { + PROP_0, + + LAST_PROP +}; + +static GQuark +nm_infiniband_error_quark (void) +{ + static GQuark quark = 0; + if (!quark) + quark = g_quark_from_static_string ("nm-infiniband-error"); + return quark; +} + +static GObject* +constructor (GType type, + guint n_construct_params, + GObjectConstructParam *construct_params) +{ + GObject *object; + NMDevice *self; + + object = G_OBJECT_CLASS (nm_device_infiniband_parent_class)->constructor (type, + n_construct_params, + construct_params); + if (!object) + return NULL; + + self = NM_DEVICE (object); + + nm_log_dbg (LOGD_HW | LOGD_INFINIBAND, "(%s): kernel ifindex %d", + nm_device_get_iface (self), + nm_device_get_ifindex (self)); + return object; +} + +static void +nm_device_infiniband_init (NMDeviceInfiniband * self) +{ +} + +NMDevice * +nm_device_infiniband_new (NMPlatformLink *platform_device) +{ + g_return_val_if_fail (platform_device != NULL, NULL); + + return (NMDevice *) g_object_new (NM_TYPE_DEVICE_INFINIBAND, + NM_DEVICE_PLATFORM_DEVICE, platform_device, + NM_DEVICE_TYPE_DESC, "InfiniBand", + NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_INFINIBAND, + NULL); +} + +NMDevice * +nm_device_infiniband_new_partition (NMConnection *connection, + NMDevice *parent) +{ + NMSettingInfiniband *s_infiniband; + int p_key, parent_ifindex; + const char *iface; + + g_return_val_if_fail (connection != NULL, NULL); + g_return_val_if_fail (NM_IS_DEVICE_INFINIBAND (parent), NULL); + + iface = nm_connection_get_virtual_iface_name (connection); + g_return_val_if_fail (iface != NULL, NULL); + + parent_ifindex = nm_device_get_ifindex (parent); + s_infiniband = nm_connection_get_setting_infiniband (connection); + p_key = nm_setting_infiniband_get_p_key (s_infiniband); + + if ( !nm_platform_infiniband_partition_add (parent_ifindex, p_key) + && nm_platform_get_error () != NM_PLATFORM_ERROR_EXISTS) { + nm_log_warn (LOGD_DEVICE | LOGD_INFINIBAND, "(%s): failed to add InfiniBand P_Key interface for '%s': %s", + iface, nm_connection_get_id (connection), + nm_platform_get_error_msg ()); + return NULL; + } + + return (NMDevice *) g_object_new (NM_TYPE_DEVICE_INFINIBAND, + NM_DEVICE_IFACE, iface, + NM_DEVICE_DRIVER, nm_device_get_driver (parent), + NM_DEVICE_TYPE_DESC, "InfiniBand", + NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_INFINIBAND, + NULL); +} + +static guint32 +get_generic_capabilities (NMDevice *dev) +{ + return NM_DEVICE_CAP_CARRIER_DETECT; +} + +static NMActStageReturn +act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason) +{ + NMActStageReturn ret; + NMActRequest *req; + NMConnection *connection; + NMSettingInfiniband *s_infiniband; + const char *transport_mode; + char *mode_path; + gboolean ok; + + g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); + + ret = NM_DEVICE_CLASS (nm_device_infiniband_parent_class)->act_stage1_prepare (dev, reason); + if (ret != NM_ACT_STAGE_RETURN_SUCCESS) + return ret; + + req = nm_device_get_act_request (dev); + g_return_val_if_fail (req != NULL, NM_ACT_STAGE_RETURN_FAILURE); + + connection = nm_act_request_get_connection (req); + g_assert (connection); + s_infiniband = nm_connection_get_setting_infiniband (connection); + g_assert (s_infiniband); + + transport_mode = nm_setting_infiniband_get_transport_mode (s_infiniband); + + mode_path = g_strdup_printf ("/sys/class/net/%s/mode", + ASSERT_VALID_PATH_COMPONENT (nm_device_get_iface (dev))); + if (!g_file_test (mode_path, G_FILE_TEST_EXISTS)) { + g_free (mode_path); + + if (!strcmp (transport_mode, "datagram")) + return NM_ACT_STAGE_RETURN_SUCCESS; + else { + *reason = NM_DEVICE_STATE_REASON_INFINIBAND_MODE; + return NM_ACT_STAGE_RETURN_FAILURE; + } + } + + ok = nm_platform_sysctl_set (mode_path, transport_mode); + g_free (mode_path); + + if (!ok) { + *reason = NM_DEVICE_STATE_REASON_CONFIG_FAILED; + return NM_ACT_STAGE_RETURN_FAILURE; + } + + return NM_ACT_STAGE_RETURN_SUCCESS; +} + +static void +ip4_config_pre_commit (NMDevice *self, NMIP4Config *config) +{ + NMConnection *connection; + NMSettingInfiniband *s_infiniband; + guint32 mtu; + + connection = nm_device_get_connection (self); + g_assert (connection); + s_infiniband = nm_connection_get_setting_infiniband (connection); + g_assert (s_infiniband); + + /* MTU override */ + mtu = nm_setting_infiniband_get_mtu (s_infiniband); + if (mtu) + nm_ip4_config_set_mtu (config, mtu); +} + +static gboolean +check_connection_compatible (NMDevice *device, NMConnection *connection) +{ + NMSettingInfiniband *s_infiniband; + const GByteArray *mac; + + if (!NM_DEVICE_CLASS (nm_device_infiniband_parent_class)->check_connection_compatible (device, connection)) + return FALSE; + + if (!nm_connection_is_type (connection, NM_SETTING_INFINIBAND_SETTING_NAME)) + return FALSE; + + s_infiniband = nm_connection_get_setting_infiniband (connection); + if (!s_infiniband) + return FALSE; + + if (s_infiniband) { + mac = nm_setting_infiniband_get_mac_address (s_infiniband); + /* We only compare the last 8 bytes */ + if (mac && memcmp (mac->data + INFINIBAND_ALEN - 8, + nm_device_get_hw_address (device, NULL) + INFINIBAND_ALEN - 8, + 8)) + return FALSE; + } + + return TRUE; +} + +static gboolean +complete_connection (NMDevice *device, + NMConnection *connection, + const char *specific_object, + const GSList *existing_connections, + GError **error) +{ + NMSettingInfiniband *s_infiniband; + const GByteArray *setting_mac; + const guint8 *hw_address; + + nm_utils_complete_generic (connection, + NM_SETTING_INFINIBAND_SETTING_NAME, + existing_connections, + _("InfiniBand connection %d"), + NULL, + TRUE); + + s_infiniband = nm_connection_get_setting_infiniband (connection); + if (!s_infiniband) { + s_infiniband = (NMSettingInfiniband *) nm_setting_infiniband_new (); + nm_connection_add_setting (connection, NM_SETTING (s_infiniband)); + } + + setting_mac = nm_setting_infiniband_get_mac_address (s_infiniband); + hw_address = nm_device_get_hw_address (device, NULL); + if (setting_mac) { + /* Make sure the setting MAC (if any) matches the device's MAC */ + if (memcmp (setting_mac->data, hw_address, INFINIBAND_ALEN)) { + g_set_error_literal (error, + NM_SETTING_INFINIBAND_ERROR, + NM_SETTING_INFINIBAND_ERROR_INVALID_PROPERTY, + NM_SETTING_INFINIBAND_MAC_ADDRESS); + return FALSE; + } + } else { + GByteArray *mac; + + /* Lock the connection to this device by default */ + mac = g_byte_array_sized_new (INFINIBAND_ALEN); + g_byte_array_append (mac, hw_address, INFINIBAND_ALEN); + g_object_set (G_OBJECT (s_infiniband), NM_SETTING_INFINIBAND_MAC_ADDRESS, mac, NULL); + g_byte_array_free (mac, TRUE); + } + + if (!nm_setting_infiniband_get_transport_mode (s_infiniband)) + g_object_set (G_OBJECT (s_infiniband), NM_SETTING_INFINIBAND_TRANSPORT_MODE, "datagram", NULL); + + return TRUE; +} + +static void +update_connection (NMDevice *device, NMConnection *connection) +{ + NMSettingInfiniband *s_infiniband = nm_connection_get_setting_infiniband (connection); + guint maclen; + gconstpointer mac = nm_device_get_hw_address (device, &maclen); + static const guint8 null_mac[INFINIBAND_ALEN] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + GByteArray *array; + char *mode_path, *contents = NULL; + const char *transport_mode = "datagram"; + + if (!s_infiniband) { + s_infiniband = (NMSettingInfiniband *) nm_setting_infiniband_new (); + nm_connection_add_setting (connection, (NMSetting *) s_infiniband); + } + + if (mac && (maclen == INFINIBAND_ALEN) && (memcmp (mac, null_mac, maclen) != 0)) { + array = g_byte_array_sized_new (maclen); + g_byte_array_append (array, (guint8 *) mac, maclen); + g_object_set (s_infiniband, NM_SETTING_INFINIBAND_MAC_ADDRESS, array, NULL); + g_byte_array_unref (array); + } + + mode_path = g_strdup_printf ("/sys/class/net/%s/mode", + ASSERT_VALID_PATH_COMPONENT (nm_device_get_iface (device))); + contents = nm_platform_sysctl_get (mode_path); + g_free (mode_path); + if (contents) { + if (strstr (contents, "datagram")) + transport_mode = "datagram"; + else if (strstr (contents, "connected")) + transport_mode = "connected"; + g_free (contents); + } + g_object_set (G_OBJECT (s_infiniband), NM_SETTING_INFINIBAND_TRANSPORT_MODE, transport_mode, NULL); +} + +static gboolean +spec_match_list (NMDevice *device, const GSList *specs) +{ + char *hwaddr_str, *spec_str; + const GSList *iter; + + if (NM_DEVICE_CLASS (nm_device_infiniband_parent_class)->spec_match_list (device, specs)) + return TRUE; + + hwaddr_str = nm_utils_hwaddr_ntoa (nm_device_get_hw_address (device, NULL), + ARPHRD_INFINIBAND); + + /* InfiniBand hardware address matches only need to match the last + * 8 bytes. In string format, that means we skip the first 36 + * characters of hwaddr_str, and the first 40 of the spec (to skip + * "mac:" too). + */ + for (iter = specs; iter; iter = g_slist_next (iter)) { + spec_str = iter->data; + + if ( !g_ascii_strncasecmp (spec_str, "mac:", 4) + && strlen (spec_str) > 40 + && !g_ascii_strcasecmp (spec_str + 40, hwaddr_str + 36)) { + g_free (hwaddr_str); + return TRUE; + } + } + + g_free (hwaddr_str); + return FALSE; +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + switch (prop_id) { + 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) +{ + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_device_infiniband_class_init (NMDeviceInfinibandClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (NMDeviceInfinibandPrivate)); + + /* virtual methods */ + object_class->constructor = constructor; + object_class->get_property = get_property; + object_class->set_property = set_property; + + parent_class->get_generic_capabilities = get_generic_capabilities; + parent_class->check_connection_compatible = check_connection_compatible; + parent_class->complete_connection = complete_connection; + parent_class->update_connection = update_connection; + parent_class->spec_match_list = spec_match_list; + + parent_class->act_stage1_prepare = act_stage1_prepare; + parent_class->ip4_config_pre_commit = ip4_config_pre_commit; + + /* properties */ + + nm_dbus_manager_register_exported_type (nm_dbus_manager_get (), + G_TYPE_FROM_CLASS (klass), + &dbus_glib_nm_device_infiniband_object_info); + + dbus_g_error_domain_register (NM_INFINIBAND_ERROR, NULL, NM_TYPE_INFINIBAND_ERROR); +} diff --git a/src/devices/nm-device-infiniband.h b/src/devices/nm-device-infiniband.h new file mode 100644 index 00000000..45dc1ab6 --- /dev/null +++ b/src/devices/nm-device-infiniband.h @@ -0,0 +1,61 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright 2011 Red Hat, Inc. + */ + +#ifndef NM_DEVICE_INFINIBAND_H +#define NM_DEVICE_INFINIBAND_H + +#include + +#include "nm-device.h" + +G_BEGIN_DECLS + +#define NM_TYPE_DEVICE_INFINIBAND (nm_device_infiniband_get_type ()) +#define NM_DEVICE_INFINIBAND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_INFINIBAND, NMDeviceInfiniband)) +#define NM_DEVICE_INFINIBAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_INFINIBAND, NMDeviceInfinibandClass)) +#define NM_IS_DEVICE_INFINIBAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_INFINIBAND)) +#define NM_IS_DEVICE_INFINIBAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_INFINIBAND)) +#define NM_DEVICE_INFINIBAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_INFINIBAND, NMDeviceInfinibandClass)) + +typedef enum { + NM_INFINIBAND_ERROR_CONNECTION_NOT_INFINIBAND = 0, /*< nick=ConnectionNotInfiniband >*/ + NM_INFINIBAND_ERROR_CONNECTION_INVALID, /*< nick=ConnectionInvalid >*/ + NM_INFINIBAND_ERROR_CONNECTION_INCOMPATIBLE, /*< nick=ConnectionIncompatible >*/ +} NMInfinibandError; + +typedef struct { + NMDevice parent; +} NMDeviceInfiniband; + +typedef struct { + NMDeviceClass parent; + +} NMDeviceInfinibandClass; + + +GType nm_device_infiniband_get_type (void); + +NMDevice *nm_device_infiniband_new (NMPlatformLink *platform_device); +NMDevice *nm_device_infiniband_new_partition (NMConnection *connection, + NMDevice *parent); + +G_END_DECLS + +#endif /* NM_DEVICE_INFINIBAND_H */ diff --git a/src/devices/nm-device-macvlan.c b/src/devices/nm-device-macvlan.c new file mode 100644 index 00000000..22848fe7 --- /dev/null +++ b/src/devices/nm-device-macvlan.c @@ -0,0 +1,181 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright 2013 Red Hat, Inc. + */ + +#include "config.h" + +#include + +#include "nm-device-macvlan.h" +#include "nm-device-private.h" +#include "nm-dbus-manager.h" +#include "nm-logging.h" +#include "nm-manager.h" +#include "nm-platform.h" + +#include "nm-device-macvlan-glue.h" + +G_DEFINE_TYPE (NMDeviceMacvlan, nm_device_macvlan, NM_TYPE_DEVICE_GENERIC) + +#define NM_DEVICE_MACVLAN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_MACVLAN, NMDeviceMacvlanPrivate)) + +typedef struct { + NMPlatformMacvlanProperties props; +} NMDeviceMacvlanPrivate; + +enum { + PROP_0, + PROP_PARENT, + PROP_MODE, + PROP_NO_PROMISC, + + LAST_PROP +}; + +/**************************************************************/ + +/**************************************************************/ + +static void +update_properties (NMDevice *device) +{ + NMDeviceMacvlanPrivate *priv = NM_DEVICE_MACVLAN_GET_PRIVATE (device); + GObject *object = G_OBJECT (device); + NMPlatformMacvlanProperties props; + + if (!nm_platform_macvlan_get_properties (nm_device_get_ifindex (device), &props)) { + nm_log_warn (LOGD_HW, "(%s): could not read macvlan properties", + nm_device_get_iface (device)); + return; + } + + g_object_freeze_notify (object); + + if (priv->props.parent_ifindex != props.parent_ifindex) + g_object_notify (object, NM_DEVICE_MACVLAN_PARENT); + if (g_strcmp0 (priv->props.mode, props.mode) != 0) + g_object_notify (object, NM_DEVICE_MACVLAN_MODE); + if (priv->props.no_promisc != props.no_promisc) + g_object_notify (object, NM_DEVICE_MACVLAN_NO_PROMISC); + + memcpy (&priv->props, &props, sizeof (NMPlatformMacvlanProperties)); + + g_object_thaw_notify (object); +} + +static void +link_changed (NMDevice *device, NMPlatformLink *info) +{ + NM_DEVICE_CLASS (nm_device_macvlan_parent_class)->link_changed (device, info); + update_properties (device); +} + +/**************************************************************/ + +NMDevice * +nm_device_macvlan_new (NMPlatformLink *platform_device) +{ + g_return_val_if_fail (platform_device != NULL, NULL); + + return (NMDevice *) g_object_new (NM_TYPE_DEVICE_MACVLAN, + NM_DEVICE_PLATFORM_DEVICE, platform_device, + NM_DEVICE_TYPE_DESC, "Macvlan", + NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_GENERIC, + NULL); +} + +static void +nm_device_macvlan_init (NMDeviceMacvlan *self) +{ +} + +static void +constructed (GObject *object) +{ + update_properties (NM_DEVICE (object)); + + G_OBJECT_CLASS (nm_device_macvlan_parent_class)->constructed (object); +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMDeviceMacvlanPrivate *priv = NM_DEVICE_MACVLAN_GET_PRIVATE (object); + NMDevice *parent; + + switch (prop_id) { + case PROP_PARENT: + parent = nm_manager_get_device_by_ifindex (nm_manager_get (), priv->props.parent_ifindex); + g_value_set_boxed (value, parent ? nm_device_get_path (parent) : "/"); + break; + case PROP_MODE: + g_value_set_string (value, priv->props.mode); + break; + case PROP_NO_PROMISC: + g_value_set_boolean (value, priv->props.no_promisc); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_device_macvlan_class_init (NMDeviceMacvlanClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); + + g_type_class_add_private (klass, sizeof (NMDeviceMacvlanPrivate)); + + object_class->constructed = constructed; + object_class->get_property = get_property; + + device_class->link_changed = link_changed; + + /* properties */ + g_object_class_install_property + (object_class, PROP_PARENT, + g_param_spec_boxed (NM_DEVICE_MACVLAN_PARENT, + "Parent", + "Parent device", + DBUS_TYPE_G_OBJECT_PATH, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_MODE, + g_param_spec_string (NM_DEVICE_MACVLAN_MODE, + "Mode", + "Mode: 'private', 'vepa', 'bridge', or 'passthru'", + NULL, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_NO_PROMISC, + g_param_spec_boolean (NM_DEVICE_MACVLAN_NO_PROMISC, + "No-promisc", + "No promiscuous mode", + FALSE, + G_PARAM_READABLE)); + + nm_dbus_manager_register_exported_type (nm_dbus_manager_get (), + G_TYPE_FROM_CLASS (klass), + &dbus_glib_nm_device_macvlan_object_info); +} diff --git a/src/devices/nm-device-macvlan.h b/src/devices/nm-device-macvlan.h new file mode 100644 index 00000000..348ed2f9 --- /dev/null +++ b/src/devices/nm-device-macvlan.h @@ -0,0 +1,56 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright 2013 Red Hat, Inc. + */ + +#ifndef NM_DEVICE_MACVLAN_H +#define NM_DEVICE_MACVLAN_H + +#include + +#include "nm-device-generic.h" + +G_BEGIN_DECLS + +#define NM_TYPE_DEVICE_MACVLAN (nm_device_macvlan_get_type ()) +#define NM_DEVICE_MACVLAN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_MACVLAN, NMDeviceMacvlan)) +#define NM_DEVICE_MACVLAN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_MACVLAN, NMDeviceMacvlanClass)) +#define NM_IS_DEVICE_MACVLAN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_MACVLAN)) +#define NM_IS_DEVICE_MACVLAN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_MACVLAN)) +#define NM_DEVICE_MACVLAN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_MACVLAN, NMDeviceMacvlanClass)) + +#define NM_DEVICE_MACVLAN_PARENT "parent" +#define NM_DEVICE_MACVLAN_MODE "mode" +#define NM_DEVICE_MACVLAN_NO_PROMISC "no-promisc" + +typedef struct { + NMDeviceGeneric parent; +} NMDeviceMacvlan; + +typedef struct { + NMDeviceGenericClass parent; + +} NMDeviceMacvlanClass; + +GType nm_device_macvlan_get_type (void); + +NMDevice *nm_device_macvlan_new (NMPlatformLink *platform_device); + +G_END_DECLS + +#endif /* NM_DEVICE_MACVLAN_H */ diff --git a/src/devices/nm-device-private.h b/src/devices/nm-device-private.h new file mode 100644 index 00000000..24bb0b33 --- /dev/null +++ b/src/devices/nm-device-private.h @@ -0,0 +1,102 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2007 - 2008 Novell, Inc. + * Copyright (C) 2007 - 2011 Red Hat, Inc. + */ + +#ifndef NM_DEVICE_PRIVATE_H +#define NM_DEVICE_PRIVATE_H + +#include "nm-device.h" + +/* This file should only be used by subclasses of NMDevice */ + +#define NM_DEVICE_PLATFORM_DEVICE "platform-device" + +enum NMActStageReturn { + NM_ACT_STAGE_RETURN_FAILURE = 0, + NM_ACT_STAGE_RETURN_SUCCESS, /* Activation stage done */ + NM_ACT_STAGE_RETURN_POSTPONE, /* Long-running operation in progress */ + NM_ACT_STAGE_RETURN_WAIT, /* Not ready to start stage; wait */ + NM_ACT_STAGE_RETURN_STOP /* Activation stage done; nothing to do */ +}; + +#define NM_DEVICE_CAP_NONSTANDARD_CARRIER 0x80000000 + +#define NM_DEVICE_CAP_INTERNAL_MASK 0x80000000 + +void nm_device_set_ip_iface (NMDevice *self, const char *iface); + +void nm_device_activate_schedule_stage3_ip_config_start (NMDevice *device); + +gboolean nm_device_activate_stage3_ip4_start (NMDevice *self); + +gboolean nm_device_activate_stage3_ip6_start (NMDevice *self); + +gboolean nm_device_bring_up (NMDevice *self, gboolean wait, gboolean *no_firmware); + +void nm_device_take_down (NMDevice *self, gboolean block); + +gboolean nm_device_update_hw_address (NMDevice *self); +gboolean nm_device_set_hw_addr (NMDevice *device, const guint8 *addr, + const char *detail, guint64 hw_log_domain); + +gboolean nm_device_ip_config_should_fail (NMDevice *self, gboolean ip6); + +void nm_device_set_firmware_missing (NMDevice *self, gboolean missing); + +void nm_device_activate_schedule_stage1_device_prepare (NMDevice *device); +void nm_device_activate_schedule_stage2_device_config (NMDevice *device); + +void nm_device_activate_schedule_ip4_config_result(NMDevice *device, NMIP4Config *config); +void nm_device_activate_schedule_ip4_config_timeout (NMDevice *device); + +void nm_device_activate_schedule_ip6_config_result (NMDevice *device); +void nm_device_activate_schedule_ip6_config_timeout (NMDevice *device); + +gboolean nm_device_activate_ip4_state_in_conf (NMDevice *device); +gboolean nm_device_activate_ip4_state_in_wait (NMDevice *device); + +gboolean nm_device_activate_ip6_state_in_conf (NMDevice *device); +gboolean nm_device_activate_ip6_state_in_wait (NMDevice *device); + +void nm_device_set_dhcp_timeout (NMDevice *device, guint32 timeout); +void nm_device_set_dhcp_anycast_address (NMDevice *device, guint8 *addr); + +gboolean nm_device_dhcp4_renew (NMDevice *device, gboolean release); +gboolean nm_device_dhcp6_renew (NMDevice *device, gboolean release); + +void nm_device_recheck_available_connections (NMDevice *device); + +void nm_device_queued_state_clear (NMDevice *device); + +NMDeviceState nm_device_queued_state_peek (NMDevice *device); + +gboolean nm_device_get_enslaved (NMDevice *device); + +NMDevice *nm_device_master_get_slave_by_ifindex (NMDevice *dev, int ifindex); + +void nm_device_master_check_slave_physical_port (NMDevice *dev, NMDevice *slave, + guint64 log_domain); + +void nm_device_set_carrier (NMDevice *device, gboolean carrier); + +void nm_device_emit_recheck_auto_activate (NMDevice *device); +void nm_device_queue_recheck_assume (NMDevice *device); + +#endif /* NM_DEVICE_PRIVATE_H */ diff --git a/src/devices/nm-device-team.c b/src/devices/nm-device-team.c new file mode 100644 index 00000000..f3b25e3b --- /dev/null +++ b/src/devices/nm-device-team.c @@ -0,0 +1,894 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * Copyright (C) 2013 Jiri Pirko + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#if WITH_TEAMDCTL +#include +#endif +#include + +#include "nm-device-team.h" +#include "nm-logging.h" +#include "nm-utils.h" +#include "NetworkManagerUtils.h" +#include "nm-device-private.h" +#include "nm-platform.h" +#include "nm-dbus-glib-types.h" +#include "nm-dbus-manager.h" +#include "nm-enum-types.h" +#include "nm-posix-signals.h" + +#include "nm-device-team-glue.h" + + +G_DEFINE_TYPE (NMDeviceTeam, nm_device_team, NM_TYPE_DEVICE) + +#define NM_DEVICE_TEAM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_TEAM, NMDeviceTeamPrivate)) + +#define NM_TEAM_ERROR (nm_team_error_quark ()) + +static gboolean teamd_start (NMDevice *dev, NMSettingTeam *s_team); + +typedef struct { +#if WITH_TEAMDCTL + struct teamdctl *tdc; +#endif + GPid teamd_pid; + guint teamd_process_watch; + guint teamd_timeout; + guint teamd_dbus_watch; +} NMDeviceTeamPrivate; + +enum { + PROP_0, + PROP_SLAVES, + + LAST_PROP +}; + +/******************************************************************/ + +static GQuark +nm_team_error_quark (void) +{ + static GQuark quark = 0; + if (!quark) + quark = g_quark_from_static_string ("nm-team-error"); + return quark; +} + +/******************************************************************/ + +static guint32 +get_generic_capabilities (NMDevice *dev) +{ + return NM_DEVICE_CAP_CARRIER_DETECT; +} + +static gboolean +is_available (NMDevice *dev) +{ + if (NM_DEVICE_GET_CLASS (dev)->is_up) + return NM_DEVICE_GET_CLASS (dev)->is_up (dev); + return FALSE; +} + +static gboolean +check_connection_available (NMDevice *device, + NMConnection *connection, + const char *specific_object) +{ + /* Connections are always available because the carrier state is determined + * by the team port carrier states, not the team's state. + */ + return TRUE; +} + +static gboolean +check_connection_compatible (NMDevice *device, NMConnection *connection) +{ + const char *iface; + NMSettingTeam *s_team; + + if (!NM_DEVICE_CLASS (nm_device_team_parent_class)->check_connection_compatible (device, connection)) + return FALSE; + + s_team = nm_connection_get_setting_team (connection); + if (!s_team || !nm_connection_is_type (connection, NM_SETTING_TEAM_SETTING_NAME)) + return FALSE; + + /* Team connections must specify the virtual interface name */ + iface = nm_connection_get_virtual_iface_name (connection); + if (!iface || strcmp (nm_device_get_iface (device), iface)) + return FALSE; + + /* FIXME: match team properties like mode, etc? */ + + return TRUE; +} + +static gboolean +complete_connection (NMDevice *device, + NMConnection *connection, + const char *specific_object, + const GSList *existing_connections, + GError **error) +{ + NMSettingTeam *s_team, *tmp; + guint32 i = 0; + char *name; + const GSList *iter; + gboolean found; + + nm_utils_complete_generic (connection, + NM_SETTING_TEAM_SETTING_NAME, + existing_connections, + _("Team connection %d"), + NULL, + TRUE); + + s_team = nm_connection_get_setting_team (connection); + if (!s_team) { + s_team = (NMSettingTeam *) nm_setting_team_new (); + nm_connection_add_setting (connection, NM_SETTING (s_team)); + } + + /* Grab the first name that doesn't exist in either our connections + * or a device on the system. + */ + while (i < 500 && !nm_setting_team_get_interface_name (s_team)) { + name = g_strdup_printf ("team%u", i); + /* check interface names */ + if (!nm_platform_link_exists (name)) { + /* check existing team connections */ + for (iter = existing_connections, found = FALSE; iter; iter = g_slist_next (iter)) { + NMConnection *candidate = iter->data; + + tmp = nm_connection_get_setting_team (candidate); + if (tmp && nm_connection_is_type (candidate, NM_SETTING_TEAM_SETTING_NAME)) { + if (g_strcmp0 (nm_setting_team_get_interface_name (tmp), name) == 0) { + found = TRUE; + break; + } + } + } + + if (!found) + g_object_set (G_OBJECT (s_team), NM_SETTING_TEAM_INTERFACE_NAME, name, NULL); + } + + g_free (name); + i++; + } + + return TRUE; +} + +#if WITH_TEAMDCTL +static gboolean +ensure_teamd_connection (NMDevice *self) +{ + NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE (self); + int err; + + if (priv->tdc) + return TRUE; + + priv->tdc = teamdctl_alloc (); + g_assert (priv->tdc); + err = teamdctl_connect (priv->tdc, nm_device_get_iface (self), NULL, NULL); + if (err != 0) { + nm_log_err (LOGD_TEAM, "(%s): failed to connect to teamd (err=%d)", + nm_device_get_iface (self), err); + teamdctl_free (priv->tdc); + priv->tdc = NULL; + } + + return !!priv->tdc; +} +#endif + +static void +update_connection (NMDevice *device, NMConnection *connection) +{ + NMSettingTeam *s_team = nm_connection_get_setting_team (connection); + const char *iface = nm_device_get_iface (device); + + if (!s_team) { + s_team = (NMSettingTeam *) nm_setting_team_new (); + nm_connection_add_setting (connection, (NMSetting *) s_team); + g_object_set (G_OBJECT (s_team), NM_SETTING_TEAM_INTERFACE_NAME, iface, NULL); + } + g_object_set (G_OBJECT (s_team), NM_SETTING_TEAM_CONFIG, NULL, NULL); + +#if WITH_TEAMDCTL + teamd_start (device, s_team); + if (NM_DEVICE_TEAM_GET_PRIVATE (device)->teamd_pid > 0 && ensure_teamd_connection (device)) { + const char *config = NULL; + int err; + + err = teamdctl_config_get_raw_direct (NM_DEVICE_TEAM_GET_PRIVATE (device)->tdc, + (char **)&config); + if (err == 0) + g_object_set (G_OBJECT (s_team), NM_SETTING_TEAM_CONFIG, config, NULL); + else + nm_log_err (LOGD_TEAM, "(%s): failed to read teamd config (err=%d)", iface, err); + } +#endif +} + +/******************************************************************/ + +gboolean +nm_team_update_slave_connection (NMDevice *slave, NMConnection *connection) +{ + NMSettingTeamPort *s_port; + const char *iface = nm_device_get_iface (slave); + char *port_config = NULL; + gboolean with_teamdctl = FALSE; + int err = 0; +#if WITH_TEAMDCTL + const char *master_iface; + int master_ifindex; + struct teamdctl *tdc; + const char *team_port_config = NULL; +#endif + + g_return_val_if_fail (NM_IS_DEVICE (slave), FALSE); + g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE); + +#if WITH_TEAMDCTL + master_ifindex = nm_platform_link_get_master (nm_device_get_ifindex (slave)); + g_assert (master_ifindex > 0); + master_iface = nm_platform_link_get_name (master_ifindex); + g_assert (master_iface); + + tdc = teamdctl_alloc (); + g_assert (tdc); + err = teamdctl_connect (tdc, master_iface, NULL, NULL); + if (err) { + nm_log_err (LOGD_TEAM, "(%s): failed to connect to teamd for master %s (err=%d)", + iface, master_iface, err); + teamdctl_free (tdc); + return FALSE; + } + err = teamdctl_port_config_get_raw_direct (tdc, iface, (char **)&team_port_config); + port_config = g_strdup (team_port_config); + teamdctl_free (tdc); + with_teamdctl = TRUE; +#endif + + s_port = nm_connection_get_setting_team_port (connection); + if (!s_port) { + s_port = (NMSettingTeamPort *) nm_setting_team_port_new (); + nm_connection_add_setting (connection, NM_SETTING (s_port)); + } + + g_object_set (G_OBJECT (s_port), NM_SETTING_TEAM_PORT_CONFIG, port_config, NULL); + g_free (port_config); + + if (!with_teamdctl || err != 0) { + if (!with_teamdctl) + nm_log_err (LOGD_TEAM, "(%s): failed to read teamd port configuration " + " (compiled without libteamdctl support)", iface); + else + nm_log_err (LOGD_TEAM, "(%s): failed to read teamd port configuration (err=%d)", + iface, err); + return FALSE; + } + + return TRUE; +} + +/******************************************************************/ + +static gboolean +ensure_killed (gpointer data) +{ + int pid = GPOINTER_TO_INT (data); + + if (kill (pid, 0) == 0) + kill (pid, SIGKILL); + + /* ensure the child is reaped */ + nm_log_dbg (LOGD_TEAM, "waiting for teamd pid %d to exit", pid); + waitpid (pid, NULL, 0); + nm_log_dbg (LOGD_TEAM, "teamd pid %d cleaned up", pid); + + return FALSE; +} + +static void +service_kill (int pid) +{ + if (kill (pid, SIGTERM) == 0) + g_timeout_add_seconds (2, ensure_killed, GINT_TO_POINTER (pid)); + else { + kill (pid, SIGKILL); + + /* ensure the child is reaped */ + nm_log_dbg (LOGD_TEAM, "waiting for teamd pid %d to exit", pid); + waitpid (pid, NULL, 0); + nm_log_dbg (LOGD_TEAM, "teamd pid %d cleaned up", pid); + } +} + +static void +teamd_timeout_remove (NMDevice *dev) +{ + NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE (dev); + + if (priv->teamd_timeout) { + g_source_remove (priv->teamd_timeout); + priv->teamd_timeout = 0; + } +} + +static void +teamd_cleanup (NMDevice *dev, gboolean device_state_failed) +{ + NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE (dev); + + if (priv->teamd_dbus_watch) { + g_bus_unwatch_name (priv->teamd_dbus_watch); + priv->teamd_dbus_watch = 0; + } + + if (priv->teamd_process_watch) { + g_source_remove (priv->teamd_process_watch); + priv->teamd_process_watch = 0; + } + + if (priv->teamd_pid > 0) { + service_kill (priv->teamd_pid); + priv->teamd_pid = 0; + } + +#if WITH_TEAMDCTL + if (priv->tdc) { + teamdctl_disconnect (priv->tdc); + teamdctl_free (priv->tdc); + priv->tdc = NULL; + } +#endif + + teamd_timeout_remove (dev); + + if (device_state_failed) { + if (nm_device_is_activating (dev) || + (nm_device_get_state (dev) == NM_DEVICE_STATE_ACTIVATED)) + nm_device_state_changed (dev, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED); + } +} + +static gboolean +teamd_timeout_cb (gpointer user_data) +{ + NMDevice *dev = NM_DEVICE (user_data); + NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE (dev); + + g_return_val_if_fail (priv->teamd_timeout, FALSE); + + nm_log_info (LOGD_TEAM, "(%s): teamd timed out.", nm_device_get_iface (dev)); + teamd_cleanup (dev, TRUE); + + return FALSE; +} + +static void +teamd_dbus_appeared (GDBusConnection *connection, + const gchar *name, + const gchar *name_owner, + gpointer user_data) +{ + NMDevice *dev = NM_DEVICE (user_data); + NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE (dev); + + g_return_if_fail (priv->teamd_dbus_watch); + + nm_log_info (LOGD_TEAM, "(%s): teamd appeared on D-Bus", nm_device_get_iface (dev)); + teamd_timeout_remove (dev); +#if WITH_TEAMDCTL + if (!ensure_teamd_connection (dev)) { + nm_device_state_changed (dev, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED); + return; + } +#endif + nm_device_activate_schedule_stage2_device_config (dev); +} + +static void +teamd_dbus_vanished (GDBusConnection *connection, + const gchar *name, + gpointer user_data) +{ + NMDevice *dev = NM_DEVICE (user_data); + NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE (dev); + + g_return_if_fail (priv->teamd_dbus_watch); + + if (priv->teamd_timeout) { + /* g_bus_watch_name will always raise an initial signal, to indicate whether the + * name exists/not exists initially. Do not take this as a failure, until the + * startup timeout is over. + * + * Note that g_bus_watch_name is guaranteed to alternate vanished/appeared signals, + * so we won't hit this condition again (because the next signal is either 'appeared' + * or 'timeout'). */ + nm_log_dbg (LOGD_TEAM, "(%s): teamd vanished from D-Bus (ignored)", nm_device_get_iface (dev)); + return; + } + + nm_log_info (LOGD_TEAM, "(%s): teamd vanished from D-Bus", nm_device_get_iface (dev)); + teamd_cleanup (dev, TRUE); +} + +static void +teamd_process_watch_cb (GPid pid, gint status, gpointer user_data) +{ + NMDevice *dev = NM_DEVICE (user_data); + NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE (dev); + + g_return_if_fail (priv->teamd_process_watch); + + nm_log_info (LOGD_TEAM, "(%s): teamd died", nm_device_get_iface (dev)); + priv->teamd_process_watch = 0; + priv->teamd_pid = 0; + teamd_cleanup (dev, TRUE); +} + +static void +teamd_child_setup (gpointer user_data G_GNUC_UNUSED) +{ + /* We are in the child process at this point. + * Give child it's own program group for signal + * separation. + */ + pid_t pid = getpid (); + setpgid (pid, pid); + + /* + * We blocked signals in main(). We need to restore original signal + * mask for avahi-autoipd here so that it can receive signals. + */ + nm_unblock_posix_signals (NULL); +} + +static gboolean +teamd_start (NMDevice *dev, NMSettingTeam *s_team) +{ + NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE (dev); + const char *iface = nm_device_get_ip_iface (dev); + char *tmp_str; + const char *config; + const char **teamd_binary = NULL; + static const char *teamd_paths[] = { + "/usr/bin/teamd", + "/usr/local/bin/teamd", + NULL + }; + GPtrArray *argv; + GError *error = NULL; + gboolean ret; + int status; + + if (priv->teamd_dbus_watch || + priv->teamd_process_watch || + priv->teamd_pid > 0 || +#if WITH_TEAMDCTL + priv->tdc || +#endif + priv->teamd_timeout) + { + /* Just return if teamd_start() was already called */ + return TRUE; + } + + teamd_binary = teamd_paths; + while (*teamd_binary != NULL) { + if (g_file_test (*teamd_binary, G_FILE_TEST_EXISTS)) + break; + teamd_binary++; + } + + if (!*teamd_binary) { + nm_log_warn (LOGD_TEAM, + "Activation (%s) failed to start teamd: teamd binary not found", + iface); + return FALSE; + } + + /* Kill teamd for same named device first if it is there */ + argv = g_ptr_array_new (); + g_ptr_array_add (argv, (gpointer) *teamd_binary); + g_ptr_array_add (argv, (gpointer) "-k"); + g_ptr_array_add (argv, (gpointer) "-t"); + g_ptr_array_add (argv, (gpointer) iface); + g_ptr_array_add (argv, NULL); + + tmp_str = g_strjoinv (" ", (gchar **) argv->pdata); + nm_log_dbg (LOGD_TEAM, "running: %s", tmp_str); + g_free (tmp_str); + + ret = g_spawn_sync ("/", (char **) argv->pdata, NULL, 0, nm_unblock_posix_signals, NULL, NULL, NULL, &status, &error); + g_ptr_array_free (argv, TRUE); + + /* Start teamd now */ + argv = g_ptr_array_new (); + g_ptr_array_add (argv, (gpointer) *teamd_binary); + g_ptr_array_add (argv, (gpointer) "-o"); + g_ptr_array_add (argv, (gpointer) "-n"); + g_ptr_array_add (argv, (gpointer) "-U"); + g_ptr_array_add (argv, (gpointer) "-D"); + g_ptr_array_add (argv, (gpointer) "-t"); + g_ptr_array_add (argv, (gpointer) iface); + + config = nm_setting_team_get_config(s_team); + if (config) { + g_ptr_array_add (argv, (gpointer) "-c"); + g_ptr_array_add (argv, (gpointer) config); + } + + if (nm_logging_enabled (LOGL_DEBUG, LOGD_TEAM)) + g_ptr_array_add (argv, (gpointer) "-gg"); + g_ptr_array_add (argv, NULL); + + tmp_str = g_strjoinv (" ", (gchar **) argv->pdata); + nm_log_dbg (LOGD_TEAM, "running: %s", tmp_str); + g_free (tmp_str); + + /* Start a timeout for teamd to appear at D-Bus */ + priv->teamd_timeout = g_timeout_add_seconds (5, teamd_timeout_cb, dev); + + /* Register D-Bus name watcher */ + tmp_str = g_strdup_printf ("org.libteam.teamd.%s", iface); + priv->teamd_dbus_watch = g_bus_watch_name (G_BUS_TYPE_SYSTEM, + tmp_str, + G_BUS_NAME_WATCHER_FLAGS_NONE, + teamd_dbus_appeared, + teamd_dbus_vanished, + dev, + NULL); + g_free (tmp_str); + + ret = g_spawn_async ("/", (char **) argv->pdata, NULL, G_SPAWN_DO_NOT_REAP_CHILD, + &teamd_child_setup, NULL, &priv->teamd_pid, &error); + g_ptr_array_free (argv, TRUE); + if (!ret) { + nm_log_warn (LOGD_TEAM, + "Activation (%s) failed to start teamd: %s", + iface, error->message); + g_clear_error (&error); + teamd_cleanup (dev, FALSE); + return FALSE; + } + + /* Monitor the child process so we know when it dies */ + priv->teamd_process_watch = g_child_watch_add (priv->teamd_pid, + teamd_process_watch_cb, + dev); + + nm_log_info (LOGD_TEAM, + "Activation (%s) started teamd...", iface); + return TRUE; +} + +static void +teamd_stop (NMDevice *dev) +{ + NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE (dev); + + if (priv->teamd_pid > 0) { + nm_log_info (LOGD_TEAM, "Deactivation (%s) stopping teamd...", + nm_device_get_ip_iface (dev)); + } else { + nm_log_dbg (LOGD_TEAM, "Deactivation (%s) stopping teamd (not started)...", + nm_device_get_ip_iface (dev)); + } + teamd_cleanup (dev, FALSE); +} + +static NMActStageReturn +act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason) +{ + NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS; + NMConnection *connection; + NMSettingTeam *s_team; + + g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); + + ret = NM_DEVICE_CLASS (nm_device_team_parent_class)->act_stage1_prepare (dev, reason); + if (ret == NM_ACT_STAGE_RETURN_SUCCESS) { + connection = nm_device_get_connection (dev); + g_assert (connection); + s_team = nm_connection_get_setting_team (connection); + g_assert (s_team); + if (teamd_start (dev, s_team)) + ret = NM_ACT_STAGE_RETURN_POSTPONE; + else + ret = NM_ACT_STAGE_RETURN_FAILURE; + } + return ret; +} + +static void +deactivate (NMDevice *dev) +{ + teamd_stop (dev); +} + +static gboolean +enslave_slave (NMDevice *device, + NMDevice *slave, + NMConnection *connection, + gboolean configure) +{ +#if WITH_TEAMDCTL + NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE (device); +#endif + gboolean success = TRUE, no_firmware = FALSE; + const char *iface = nm_device_get_ip_iface (device); + const char *slave_iface = nm_device_get_ip_iface (slave); + NMSettingTeamPort *s_team_port; + + nm_device_master_check_slave_physical_port (device, slave, LOGD_TEAM); + + if (configure) { + nm_device_take_down (slave, TRUE); + + s_team_port = nm_connection_get_setting_team_port (connection); + if (s_team_port) { + const char *config = nm_setting_team_port_get_config (s_team_port); + + if (config) { +#if WITH_TEAMDCTL + if (!priv->tdc) { + nm_log_warn (LOGD_TEAM, "(%s): enslaved team port %s config not changed, not connected to teamd", + iface, slave_iface); + } else { + int err; + char *sanitized_config; + + sanitized_config = g_strdelimit (g_strdup (config), "\r\n", ' '); + err = teamdctl_port_config_update_raw (priv->tdc, slave_iface, sanitized_config); + g_free (sanitized_config); + if (err != 0) { + nm_log_err (LOGD_TEAM, "(%s): failed to update config for port %s (err=%d)", + iface, slave_iface, err); + return FALSE; + } + } +#else + nm_log_warn (LOGD_TEAM, "(%s): enslaved team port %s config not changed due to lack of Teamd control support", + iface, slave_iface); +#endif + } + } + success = nm_platform_link_enslave (nm_device_get_ip_ifindex (device), + nm_device_get_ip_ifindex (slave)); + nm_device_bring_up (slave, TRUE, &no_firmware); + + if (!success) + return FALSE; + + nm_log_info (LOGD_TEAM, "(%s): enslaved team port %s", iface, slave_iface); + } else + nm_log_info (LOGD_TEAM, "(%s): team port %s was enslaved", iface, slave_iface); + + g_object_notify (G_OBJECT (device), NM_DEVICE_TEAM_SLAVES); + + return TRUE; +} + +static gboolean +release_slave (NMDevice *device, + NMDevice *slave, + gboolean configure) +{ + gboolean success = TRUE, no_firmware = FALSE; + + if (configure) { + success = nm_platform_link_release (nm_device_get_ip_ifindex (device), + nm_device_get_ip_ifindex (slave)); + + if (success) { + nm_log_info (LOGD_TEAM, "(%s): released team port %s", + nm_device_get_ip_iface (device), + nm_device_get_ip_iface (slave)); + } else { + nm_log_warn (LOGD_TEAM, "(%s): failed to release team port %s", + nm_device_get_ip_iface (device), + nm_device_get_ip_iface (slave)); + } + } else { + nm_log_info (LOGD_TEAM, "(%s): team port %s was released", + nm_device_get_ip_iface (device), + nm_device_get_ip_iface (slave)); + } + + if (success) + g_object_notify (G_OBJECT (device), NM_DEVICE_TEAM_SLAVES); + + if (configure) { + /* Kernel team code "closes" the port when releasing it, (which clears + * IFF_UP), so we must bring it back up here to ensure carrier changes and + * other state is noticed by the now-released port. + */ + if (!nm_device_bring_up (slave, TRUE, &no_firmware)) { + nm_log_warn (LOGD_TEAM, "(%s): released team port could not be brought up.", + nm_device_get_iface (slave)); + } + } + + return success; +} + +/******************************************************************/ + +NMDevice * +nm_device_team_new (NMPlatformLink *platform_device) +{ + g_return_val_if_fail (platform_device != NULL, NULL); + + return (NMDevice *) g_object_new (NM_TYPE_DEVICE_TEAM, + NM_DEVICE_PLATFORM_DEVICE, platform_device, + NM_DEVICE_DRIVER, "team", + NM_DEVICE_TYPE_DESC, "Team", + NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_TEAM, + NM_DEVICE_IS_MASTER, TRUE, + NULL); +} + +NMDevice * +nm_device_team_new_for_connection (NMConnection *connection) +{ + const char *iface; + + g_return_val_if_fail (connection != NULL, NULL); + + iface = nm_connection_get_virtual_iface_name (connection); + g_return_val_if_fail (iface != NULL, NULL); + + if ( !nm_platform_team_add (iface) + && nm_platform_get_error () != NM_PLATFORM_ERROR_EXISTS) { + nm_log_warn (LOGD_DEVICE | LOGD_TEAM, "(%s): failed to create team master interface for '%s': %s", + iface, nm_connection_get_id (connection), + nm_platform_get_error_msg ()); + return NULL; + } + + return (NMDevice *) g_object_new (NM_TYPE_DEVICE_TEAM, + NM_DEVICE_IFACE, iface, + NM_DEVICE_DRIVER, "team", + NM_DEVICE_TYPE_DESC, "Team", + NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_TEAM, + NM_DEVICE_IS_MASTER, TRUE, + NULL); +} + +static void +constructed (GObject *object) +{ + G_OBJECT_CLASS (nm_device_team_parent_class)->constructed (object); + + nm_log_dbg (LOGD_HW | LOGD_TEAM, "(%s): kernel ifindex %d", + nm_device_get_iface (NM_DEVICE (object)), + nm_device_get_ifindex (NM_DEVICE (object))); +} + +static void +nm_device_team_init (NMDeviceTeam * self) +{ +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + GPtrArray *slaves; + GSList *list, *iter; + + switch (prop_id) { + break; + case PROP_SLAVES: + slaves = g_ptr_array_new (); + list = nm_device_master_get_slaves (NM_DEVICE (object)); + for (iter = list; iter; iter = iter->next) + g_ptr_array_add (slaves, g_strdup (nm_device_get_path (NM_DEVICE (iter->data)))); + g_slist_free (list); + g_value_take_boxed (value, slaves); + 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) +{ + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +dispose (GObject *object) +{ + teamd_cleanup (NM_DEVICE (object), FALSE); + + G_OBJECT_CLASS (nm_device_team_parent_class)->dispose (object); +} + +static void +nm_device_team_class_init (NMDeviceTeamClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (NMDeviceTeamPrivate)); + + parent_class->connection_type = NM_SETTING_TEAM_SETTING_NAME; + + /* virtual methods */ + object_class->constructed = constructed; + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->dispose = dispose; + + parent_class->get_generic_capabilities = get_generic_capabilities; + parent_class->is_available = is_available; + parent_class->check_connection_compatible = check_connection_compatible; + parent_class->check_connection_available = check_connection_available; + parent_class->complete_connection = complete_connection; + parent_class->update_connection = update_connection; + + parent_class->act_stage1_prepare = act_stage1_prepare; + parent_class->deactivate = deactivate; + parent_class->enslave_slave = enslave_slave; + parent_class->release_slave = release_slave; + + /* properties */ + g_object_class_install_property + (object_class, PROP_SLAVES, + g_param_spec_boxed (NM_DEVICE_TEAM_SLAVES, + "Slaves", + "Slaves", + DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH, + G_PARAM_READABLE)); + + nm_dbus_manager_register_exported_type (nm_dbus_manager_get (), + G_TYPE_FROM_CLASS (klass), + &dbus_glib_nm_device_team_object_info); + + dbus_g_error_domain_register (NM_TEAM_ERROR, NULL, NM_TYPE_TEAM_ERROR); +} diff --git a/src/devices/nm-device-team.h b/src/devices/nm-device-team.h new file mode 100644 index 00000000..fe1275c6 --- /dev/null +++ b/src/devices/nm-device-team.h @@ -0,0 +1,64 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * Copyright (C) 2013 Jiri Pirko + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef NM_DEVICE_TEAM_H +#define NM_DEVICE_TEAM_H + +#include + +#include "nm-device.h" + +G_BEGIN_DECLS + +#define NM_TYPE_DEVICE_TEAM (nm_device_team_get_type ()) +#define NM_DEVICE_TEAM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_TEAM, NMDeviceTeam)) +#define NM_DEVICE_TEAM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_TEAM, NMDeviceTeamClass)) +#define NM_IS_DEVICE_TEAM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_TEAM)) +#define NM_IS_DEVICE_TEAM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_TEAM)) +#define NM_DEVICE_TEAM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_TEAM, NMDeviceTeamClass)) + +typedef enum { + NM_TEAM_ERROR_CONNECTION_NOT_TEAM = 0, /*< nick=ConnectionNotTeam >*/ + NM_TEAM_ERROR_CONNECTION_INVALID, /*< nick=ConnectionInvalid >*/ + NM_TEAM_ERROR_CONNECTION_INCOMPATIBLE, /*< nick=ConnectionIncompatible >*/ +} NMTeamError; + +#define NM_DEVICE_TEAM_SLAVES "slaves" + +typedef struct { + NMDevice parent; +} NMDeviceTeam; + +typedef struct { + NMDeviceClass parent; + +} NMDeviceTeamClass; + + +GType nm_device_team_get_type (void); + +NMDevice *nm_device_team_new (NMPlatformLink *platform_device); +NMDevice *nm_device_team_new_for_connection (NMConnection *connection); + +gboolean nm_team_update_slave_connection (NMDevice *slave, NMConnection *connection); + +G_END_DECLS + +#endif /* NM_DEVICE_TEAM_H */ diff --git a/src/devices/nm-device-tun.c b/src/devices/nm-device-tun.c new file mode 100644 index 00000000..d52228f9 --- /dev/null +++ b/src/devices/nm-device-tun.c @@ -0,0 +1,294 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright 2013 Red Hat, Inc. + */ + +#include "config.h" + +#include +#include + +#include "nm-device-tun.h" +#include "nm-device-private.h" +#include "nm-dbus-manager.h" +#include "nm-logging.h" +#include "nm-platform.h" + +#include "nm-device-tun-glue.h" + +G_DEFINE_TYPE (NMDeviceTun, nm_device_tun, NM_TYPE_DEVICE_GENERIC) + +#define NM_DEVICE_TUN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_TUN, NMDeviceTunPrivate)) + +typedef struct { + NMPlatformTunProperties props; + const char *mode; + guint delay_tun_get_properties_id; +} NMDeviceTunPrivate; + +enum { + PROP_0, + PROP_OWNER, + PROP_GROUP, + PROP_FLAGS, + PROP_MODE, + PROP_NO_PI, + PROP_VNET_HDR, + PROP_MULTI_QUEUE, + + LAST_PROP +}; + +static void +reload_tun_properties (NMDeviceTun *device) +{ + NMDeviceTunPrivate *priv = NM_DEVICE_TUN_GET_PRIVATE (device); + GObject *object = G_OBJECT (device); + NMPlatformTunProperties props; + + if (!nm_platform_tun_get_properties (nm_device_get_ifindex (NM_DEVICE (device)), &props)) { + nm_log_warn (LOGD_HW, "(%s): could not read tun properties", + nm_device_get_iface (NM_DEVICE (device))); + return; + } + + g_object_freeze_notify (object); + + if (priv->props.owner != props.owner) + g_object_notify (object, NM_DEVICE_TUN_OWNER); + if (priv->props.group != props.group) + g_object_notify (object, NM_DEVICE_TUN_GROUP); + if (priv->props.no_pi != props.no_pi) + g_object_notify (object, NM_DEVICE_TUN_NO_PI); + if (priv->props.vnet_hdr != props.vnet_hdr) + g_object_notify (object, NM_DEVICE_TUN_VNET_HDR); + if (priv->props.multi_queue != props.multi_queue) + g_object_notify (object, NM_DEVICE_TUN_MULTI_QUEUE); + + memcpy (&priv->props, &props, sizeof (NMPlatformTunProperties)); + + g_object_thaw_notify (object); +} + +static void +link_changed (NMDevice *device, NMPlatformLink *info) +{ + NM_DEVICE_CLASS (nm_device_tun_parent_class)->link_changed (device, info); + + reload_tun_properties (NM_DEVICE_TUN (device)); +} + +static gboolean +delay_tun_get_properties_cb (gpointer user_data) +{ + NMDeviceTun *self = user_data; + NMDeviceTunPrivate *priv = NM_DEVICE_TUN_GET_PRIVATE (self); + + priv->delay_tun_get_properties_id = 0; + + reload_tun_properties (self); + + return G_SOURCE_REMOVE; +} + +/**************************************************************/ + +NMDevice * +nm_device_tun_new (NMPlatformLink *platform_device) +{ + const char *mode = NULL; + + g_return_val_if_fail (platform_device != NULL, NULL); + + if (platform_device->type == NM_LINK_TYPE_TUN) + mode = "tun"; + else if (platform_device->type == NM_LINK_TYPE_TAP) + mode = "tap"; + g_return_val_if_fail (mode != NULL, NULL); + + return (NMDevice *) g_object_new (NM_TYPE_DEVICE_TUN, + NM_DEVICE_PLATFORM_DEVICE, platform_device, + NM_DEVICE_TYPE_DESC, "Tun", + NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_GENERIC, + NM_DEVICE_TUN_MODE, mode, + NULL); +} + +static void +nm_device_tun_init (NMDeviceTun *self) +{ +} + +static void +constructed (GObject *object) +{ + gboolean properties_read; + NMDeviceTunPrivate *priv = NM_DEVICE_TUN_GET_PRIVATE (object); + + properties_read = nm_platform_tun_get_properties (nm_device_get_ifindex (NM_DEVICE (object)), &priv->props); + + G_OBJECT_CLASS (nm_device_tun_parent_class)->constructed (object); + + if (!properties_read) { + /* Error reading the tun properties. Maybe this was due to a race. Try again a bit later. */ + nm_log_dbg (LOGD_HW, "(%s): could not read tun properties (retry)", + nm_device_get_iface (NM_DEVICE (object))); + priv->delay_tun_get_properties_id = g_timeout_add_seconds (1, delay_tun_get_properties_cb, object); + } +} + +static void +dispose (GObject *object) +{ + NMDeviceTunPrivate *priv = NM_DEVICE_TUN_GET_PRIVATE (object); + + if (priv->delay_tun_get_properties_id) { + g_source_remove (priv->delay_tun_get_properties_id); + priv->delay_tun_get_properties_id = 0; + } + + G_OBJECT_CLASS (nm_device_tun_parent_class)->dispose (object); +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMDeviceTun *self = NM_DEVICE_TUN (object); + NMDeviceTunPrivate *priv = NM_DEVICE_TUN_GET_PRIVATE (self); + + switch (prop_id) { + case PROP_OWNER: + g_value_set_uint (value, priv->props.owner); + break; + case PROP_GROUP: + g_value_set_uint (value, priv->props.group); + break; + case PROP_MODE: + g_value_set_string (value, priv->mode); + break; + case PROP_NO_PI: + g_value_set_boolean (value, priv->props.no_pi); + break; + case PROP_VNET_HDR: + g_value_set_boolean (value, priv->props.vnet_hdr); + break; + case PROP_MULTI_QUEUE: + g_value_set_boolean (value, priv->props.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) +{ + NMDeviceTun *self = NM_DEVICE_TUN (object); + NMDeviceTunPrivate *priv = NM_DEVICE_TUN_GET_PRIVATE (self); + const char *str; + + switch (prop_id) { + case PROP_MODE: + /* construct-only */ + str = g_value_get_string (value); + + /* mode is G_PARAM_STATIC_STRINGS */ + if (g_strcmp0 (str, "tun") == 0) + priv->mode = "tun"; + else if (g_strcmp0 (str, "tap") == 0) + priv->mode = "tap"; + else + g_return_if_fail (FALSE); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_device_tun_class_init (NMDeviceTunClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); + + g_type_class_add_private (klass, sizeof (NMDeviceTunPrivate)); + + object_class->constructed = constructed; + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->dispose = dispose; + + device_class->link_changed = link_changed; + + /* properties */ + g_object_class_install_property + (object_class, PROP_OWNER, + g_param_spec_int64 (NM_DEVICE_TUN_OWNER, + "Owner", + "Owner", + -1, G_MAXUINT32, -1, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (object_class, PROP_GROUP, + g_param_spec_int64 (NM_DEVICE_TUN_GROUP, + "Group", + "Group", + -1, G_MAXUINT32, -1, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (object_class, PROP_MODE, + g_param_spec_string (NM_DEVICE_TUN_MODE, + "Mode", + "Mode", + "tun", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (object_class, PROP_NO_PI, + g_param_spec_boolean (NM_DEVICE_TUN_NO_PI, + "No Protocol Info", + "No Protocol Info", + FALSE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (object_class, PROP_VNET_HDR, + g_param_spec_boolean (NM_DEVICE_TUN_VNET_HDR, + "Virtio networking header", + "Virtio networking header", + FALSE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (object_class, PROP_MULTI_QUEUE, + g_param_spec_boolean (NM_DEVICE_TUN_MULTI_QUEUE, + "Multi-queue", + "Multi-queue", + FALSE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + nm_dbus_manager_register_exported_type (nm_dbus_manager_get (), + G_TYPE_FROM_CLASS (klass), + &dbus_glib_nm_device_tun_object_info); +} diff --git a/src/devices/nm-device-tun.h b/src/devices/nm-device-tun.h new file mode 100644 index 00000000..cfcf4d7b --- /dev/null +++ b/src/devices/nm-device-tun.h @@ -0,0 +1,59 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright 2013 Red Hat, Inc. + */ + +#ifndef NM_DEVICE_TUN_H +#define NM_DEVICE_TUN_H + +#include + +#include "nm-device-generic.h" + +G_BEGIN_DECLS + +#define NM_TYPE_DEVICE_TUN (nm_device_tun_get_type ()) +#define NM_DEVICE_TUN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_TUN, NMDeviceTun)) +#define NM_DEVICE_TUN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_TUN, NMDeviceTunClass)) +#define NM_IS_DEVICE_TUN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_TUN)) +#define NM_IS_DEVICE_TUN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_TUN)) +#define NM_DEVICE_TUN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_TUN, NMDeviceTunClass)) + +#define NM_DEVICE_TUN_OWNER "owner" +#define NM_DEVICE_TUN_GROUP "group" +#define NM_DEVICE_TUN_MODE "mode" +#define NM_DEVICE_TUN_NO_PI "no-pi" +#define NM_DEVICE_TUN_VNET_HDR "vnet-hdr" +#define NM_DEVICE_TUN_MULTI_QUEUE "multi-queue" + +typedef struct { + NMDeviceGeneric parent; +} NMDeviceTun; + +typedef struct { + NMDeviceGenericClass parent; + +} NMDeviceTunClass; + +GType nm_device_tun_get_type (void); + +NMDevice *nm_device_tun_new (NMPlatformLink *platform_device); + +G_END_DECLS + +#endif /* NM_DEVICE_TUN_H */ diff --git a/src/devices/nm-device-veth.c b/src/devices/nm-device-veth.c new file mode 100644 index 00000000..df107523 --- /dev/null +++ b/src/devices/nm-device-veth.c @@ -0,0 +1,171 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright 2013 Red Hat, Inc. + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include + +#include "nm-device-veth.h" +#include "nm-device-private.h" +#include "nm-logging.h" +#include "nm-manager.h" +#include "nm-platform.h" +#include "nm-dbus-manager.h" + +#include "nm-device-veth-glue.h" + +G_DEFINE_TYPE (NMDeviceVeth, nm_device_veth, NM_TYPE_DEVICE_ETHERNET) + +#define NM_DEVICE_VETH_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_VETH, NMDeviceVethPrivate)) + +typedef struct { + NMDevice *peer; + gboolean ever_had_peer; +} NMDeviceVethPrivate; + +enum { + PROP_0, + PROP_PEER, + + LAST_PROP +}; + +/**************************************************************/ + +static void +set_peer (NMDeviceVeth *self, NMDevice *peer) +{ + NMDeviceVethPrivate *priv = NM_DEVICE_VETH_GET_PRIVATE (self); + + if (!priv->peer) { + priv->ever_had_peer = TRUE; + priv->peer = peer; + g_object_add_weak_pointer (G_OBJECT (peer), (gpointer *) &priv->peer); + + g_object_notify (G_OBJECT (self), NM_DEVICE_VETH_PEER); + } +} + +static NMDevice * +get_peer (NMDeviceVeth *self) +{ + NMDeviceVethPrivate *priv = NM_DEVICE_VETH_GET_PRIVATE (self); + NMDevice *device = NM_DEVICE (self), *peer = NULL; + NMPlatformVethProperties props; + + if (priv->ever_had_peer) + return priv->peer; + + if (!nm_platform_veth_get_properties (nm_device_get_ifindex (device), &props)) { + nm_log_warn (LOGD_HW, "(%s): could not read veth properties", + nm_device_get_iface (device)); + return NULL; + } + + peer = nm_manager_get_device_by_ifindex (nm_manager_get (), props.peer); + if (peer && NM_IS_DEVICE_VETH (peer)) { + set_peer (self, peer); + set_peer (NM_DEVICE_VETH (peer), device); + } + + return priv->peer; +} + + +/**************************************************************/ + +NMDevice * +nm_device_veth_new (NMPlatformLink *platform_device) +{ + g_return_val_if_fail (platform_device != NULL, NULL); + + return (NMDevice *) g_object_new (NM_TYPE_DEVICE_VETH, + NM_DEVICE_PLATFORM_DEVICE, platform_device, + NM_DEVICE_TYPE_DESC, "Veth", + NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_ETHERNET, + NULL); +} + +static void +nm_device_veth_init (NMDeviceVeth *self) +{ + nm_device_set_initial_unmanaged_flag (NM_DEVICE (self), NM_UNMANAGED_DEFAULT, TRUE); +} + +static void +dispose (GObject *object) +{ + NMDeviceVeth *self = NM_DEVICE_VETH (object); + NMDeviceVethPrivate *priv = NM_DEVICE_VETH_GET_PRIVATE (self); + + if (priv->peer) { + g_object_remove_weak_pointer (G_OBJECT (priv->peer), (gpointer *) &priv->peer); + priv->peer = NULL; + } + + G_OBJECT_CLASS (nm_device_veth_parent_class)->dispose (object); +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMDeviceVeth *self = NM_DEVICE_VETH (object); + NMDevice *peer; + + switch (prop_id) { + case PROP_PEER: + peer = get_peer (self); + g_value_set_boxed (value, peer ? nm_device_get_path (peer) : "/"); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_device_veth_class_init (NMDeviceVethClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (NMDeviceVethPrivate)); + + object_class->get_property = get_property; + object_class->dispose = dispose; + + /* properties */ + g_object_class_install_property + (object_class, PROP_PEER, + g_param_spec_boxed (NM_DEVICE_VETH_PEER, + "Peer", + "Peer device", + DBUS_TYPE_G_OBJECT_PATH, + G_PARAM_READABLE)); + + nm_dbus_manager_register_exported_type (nm_dbus_manager_get (), + G_TYPE_FROM_CLASS (klass), + &dbus_glib_nm_device_veth_object_info); +} diff --git a/src/devices/nm-device-veth.h b/src/devices/nm-device-veth.h new file mode 100644 index 00000000..bc8fedff --- /dev/null +++ b/src/devices/nm-device-veth.h @@ -0,0 +1,54 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright 2013 Red Hat, Inc. + */ + +#ifndef NM_DEVICE_VETH_H +#define NM_DEVICE_VETH_H + +#include + +#include "nm-device-ethernet.h" + +G_BEGIN_DECLS + +#define NM_TYPE_DEVICE_VETH (nm_device_veth_get_type ()) +#define NM_DEVICE_VETH(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_VETH, NMDeviceVeth)) +#define NM_DEVICE_VETH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_VETH, NMDeviceVethClass)) +#define NM_IS_DEVICE_VETH(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_VETH)) +#define NM_IS_DEVICE_VETH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_VETH)) +#define NM_DEVICE_VETH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_VETH, NMDeviceVethClass)) + +#define NM_DEVICE_VETH_PEER "peer" + +typedef struct { + NMDeviceEthernet parent; +} NMDeviceVeth; + +typedef struct { + NMDeviceEthernetClass parent; + +} NMDeviceVethClass; + +GType nm_device_veth_get_type (void); + +NMDevice *nm_device_veth_new (NMPlatformLink *platform_device); + +G_END_DECLS + +#endif /* NM_DEVICE_VETH_H */ diff --git a/src/devices/nm-device-vlan.c b/src/devices/nm-device-vlan.c new file mode 100644 index 00000000..348be352 --- /dev/null +++ b/src/devices/nm-device-vlan.c @@ -0,0 +1,659 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright 2011 - 2012 Red Hat, Inc. + */ + +#include "config.h" + +#include +#include + +#include +#include +#include + +#include "nm-device-vlan.h" +#include "nm-manager.h" +#include "nm-logging.h" +#include "nm-utils.h" +#include "NetworkManagerUtils.h" +#include "nm-device-private.h" +#include "nm-enum-types.h" +#include "nm-dbus-manager.h" +#include "nm-platform.h" +#include "nm-utils.h" + +#include "nm-device-vlan-glue.h" + + +G_DEFINE_TYPE (NMDeviceVlan, nm_device_vlan, NM_TYPE_DEVICE) + +#define NM_DEVICE_VLAN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_VLAN, NMDeviceVlanPrivate)) + +#define NM_VLAN_ERROR (nm_vlan_error_quark ()) + +typedef struct { + guint8 initial_hw_addr[ETH_ALEN]; + + gboolean disposed; + gboolean invalid; + + NMDevice *parent; + guint parent_state_id; + + int vlan_id; +} NMDeviceVlanPrivate; + +enum { + PROP_0, + PROP_PARENT, + PROP_VLAN_ID, + + LAST_PROP +}; + +/******************************************************************/ + +static GQuark +nm_vlan_error_quark (void) +{ + static GQuark quark = 0; + if (!quark) + quark = g_quark_from_static_string ("nm-vlan-error"); + return quark; +} + +/******************************************************************/ + +static void +update_initial_hw_address (NMDevice *dev) +{ + NMDeviceVlan *self = NM_DEVICE_VLAN (dev); + NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (self); + char *mac_str; + + memcpy (priv->initial_hw_addr, nm_device_get_hw_address (dev, NULL), ETH_ALEN); + + mac_str = nm_utils_hwaddr_ntoa (priv->initial_hw_addr, ARPHRD_ETHER); + nm_log_dbg (LOGD_DEVICE | LOGD_VLAN, "(%s): read initial MAC address %s", + nm_device_get_iface (dev), mac_str); + g_free (mac_str); +} + +static guint32 +get_generic_capabilities (NMDevice *dev) +{ + /* We assume VLAN interfaces always support carrier detect */ + return NM_DEVICE_CAP_CARRIER_DETECT; +} + +static gboolean +bring_up (NMDevice *dev, gboolean *no_firmware) +{ + gboolean success = FALSE; + guint i = 20; + + while (i-- > 0 && !success) { + success = NM_DEVICE_CLASS (nm_device_vlan_parent_class)->bring_up (dev, no_firmware); + g_usleep (50); + } + + return success; +} + +/******************************************************************/ + +static gboolean +match_parent (NMDeviceVlan *self, const char *parent) +{ + NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (self); + + g_return_val_if_fail (parent != NULL, FALSE); + + if (nm_utils_is_uuid (parent)) { + NMActRequest *parent_req; + NMConnection *parent_connection; + + /* If the parent is a UUID, the connection matches if our parent + * device has that connection activated. + */ + + parent_req = nm_device_get_act_request (priv->parent); + if (!parent_req) + return FALSE; + + parent_connection = nm_active_connection_get_connection (NM_ACTIVE_CONNECTION (parent_req)); + if (!parent_connection) + return FALSE; + + if (g_strcmp0 (parent, nm_connection_get_uuid (parent_connection)) != 0) + return FALSE; + } else { + /* interface name */ + if (g_strcmp0 (parent, nm_device_get_ip_iface (priv->parent)) != 0) + return FALSE; + } + + return TRUE; +} + +static gboolean +match_hwaddr (NMDevice *device, NMConnection *connection, gboolean fail_if_no_hwaddr) +{ + NMSettingWired *s_wired; + const GByteArray *mac; + const guint8 *device_mac; + guint device_mac_len; + + s_wired = nm_connection_get_setting_wired (connection); + if (!s_wired) + return !fail_if_no_hwaddr; + + mac = nm_setting_wired_get_mac_address (s_wired); + if (!mac) + return !fail_if_no_hwaddr; + + device_mac = nm_device_get_hw_address (device, &device_mac_len); + + return ( mac->len == device_mac_len + && memcmp (mac->data, device_mac, device_mac_len) == 0); +} + +static gboolean +check_connection_compatible (NMDevice *device, NMConnection *connection) +{ + NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (device); + NMSettingVlan *s_vlan; + const char *parent, *iface = NULL; + + if (!NM_DEVICE_CLASS (nm_device_vlan_parent_class)->check_connection_compatible (device, connection)) + return FALSE; + + s_vlan = nm_connection_get_setting_vlan (connection); + if (!s_vlan) + return FALSE; + + if (nm_setting_vlan_get_id (s_vlan) != priv->vlan_id) + return FALSE; + + /* Check parent interface; could be an interface name or a UUID */ + parent = nm_setting_vlan_get_parent (s_vlan); + if (parent) { + if (!match_parent (NM_DEVICE_VLAN (device), parent)) + return FALSE; + } else { + /* Parent could be a MAC address in an NMSettingWired */ + if (!match_hwaddr (device, connection, TRUE)) + return FALSE; + } + + /* Ensure the interface name matches. If not specified we assume a match + * since both the parent interface and the VLAN ID matched by the time we + * get here. + */ + iface = nm_connection_get_virtual_iface_name (connection); + if (iface) { + if (g_strcmp0 (nm_device_get_ip_iface (device), iface) != 0) + return FALSE; + } + + return TRUE; +} + +static gboolean +complete_connection (NMDevice *device, + NMConnection *connection, + const char *specific_object, + const GSList *existing_connections, + GError **error) +{ + NMSettingVlan *s_vlan; + + nm_utils_complete_generic (connection, + NM_SETTING_VLAN_SETTING_NAME, + existing_connections, + _("VLAN connection %d"), + NULL, + TRUE); + + s_vlan = nm_connection_get_setting_vlan (connection); + if (!s_vlan) { + g_set_error_literal (error, NM_VLAN_ERROR, NM_VLAN_ERROR_CONNECTION_INVALID, + "A 'vlan' setting is required."); + return FALSE; + } + + /* If there's no VLAN interface, no parent, and no hardware address in the + * settings, then there's not enough information to complete the setting. + */ + if ( !nm_setting_vlan_get_parent (s_vlan) + && !match_hwaddr (device, connection, TRUE)) { + g_set_error_literal (error, NM_VLAN_ERROR, NM_VLAN_ERROR_CONNECTION_INVALID, + "The 'vlan' setting had no interface name, parent, or hardware address."); + return FALSE; + } + + return TRUE; +} + +static void parent_state_changed (NMDevice *parent, NMDeviceState new_state, + NMDeviceState old_state, + NMDeviceStateReason reason, + gpointer user_data); + +static void +nm_device_vlan_set_parent (NMDeviceVlan *device, NMDevice *parent) +{ + NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (device); + + if (priv->parent_state_id) { + g_signal_handler_disconnect (priv->parent, priv->parent_state_id); + priv->parent_state_id = 0; + } + g_clear_object (&priv->parent); + + if (parent) { + priv->parent = g_object_ref (parent); + priv->parent_state_id = g_signal_connect (priv->parent, + "state-changed", + G_CALLBACK (parent_state_changed), + device); + } + g_object_notify (G_OBJECT (device), NM_DEVICE_VLAN_PARENT); +} + +static void +update_connection (NMDevice *device, NMConnection *connection) +{ + NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (device); + NMSettingVlan *s_vlan = nm_connection_get_setting_vlan (connection); + int ifindex = nm_device_get_ifindex (device); + int parent_ifindex = -1, vlan_id = -1; + NMDevice *parent; + const char *setting_parent, *new_parent; + + if (!s_vlan) { + s_vlan = (NMSettingVlan *) nm_setting_vlan_new (); + nm_connection_add_setting (connection, (NMSetting *) s_vlan); + g_object_set (s_vlan, NM_SETTING_VLAN_INTERFACE_NAME, nm_device_get_iface (device), NULL); + } + + if (!nm_platform_vlan_get_info (ifindex, &parent_ifindex, &vlan_id)) { + nm_log_warn (LOGD_VLAN, "(%s): failed to get VLAN interface info while updating connection.", + nm_device_get_iface (device)); + return; + } + + if (priv->vlan_id != vlan_id) { + priv->vlan_id = vlan_id; + g_object_notify (G_OBJECT (device), NM_DEVICE_VLAN_ID); + } + + if (vlan_id != nm_setting_vlan_get_id (s_vlan)) + g_object_set (s_vlan, NM_SETTING_VLAN_ID, priv->vlan_id, NULL); + + parent = nm_manager_get_device_by_ifindex (nm_manager_get (), parent_ifindex); + g_assert (parent); + if (priv->parent != parent) + nm_device_vlan_set_parent (NM_DEVICE_VLAN (device), parent); + + /* Update parent in the connection; default to parent's interface name */ + new_parent = nm_device_get_iface (parent); + setting_parent = nm_setting_vlan_get_parent (s_vlan); + if (setting_parent && nm_utils_is_uuid (setting_parent)) { + NMConnection *parent_connection; + + /* Don't change a parent specified by UUID if it's still valid */ + parent_connection = nm_connection_provider_get_connection_by_uuid (nm_connection_provider_get (), setting_parent); + if (parent_connection && nm_device_check_connection_compatible (parent, parent_connection)) + new_parent = NULL; + } + if (new_parent) + g_object_set (s_vlan, NM_SETTING_VLAN_PARENT, new_parent, NULL); +} + +static NMActStageReturn +act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason) +{ + NMActRequest *req; + NMConnection *connection; + NMSettingVlan *s_vlan; + NMSettingWired *s_wired; + const GByteArray *cloned_mac; + NMActStageReturn ret; + + g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); + + ret = NM_DEVICE_CLASS (nm_device_vlan_parent_class)->act_stage1_prepare (dev, reason); + if (ret != NM_ACT_STAGE_RETURN_SUCCESS) + return ret; + + req = nm_device_get_act_request (dev); + g_return_val_if_fail (req != NULL, NM_ACT_STAGE_RETURN_FAILURE); + + connection = nm_act_request_get_connection (req); + g_return_val_if_fail (connection != NULL, NM_ACT_STAGE_RETURN_FAILURE); + + s_wired = nm_connection_get_setting_wired (connection); + if (s_wired) { + /* Set device MAC address if the connection wants to change it */ + cloned_mac = nm_setting_wired_get_cloned_mac_address (s_wired); + if (cloned_mac && (cloned_mac->len == ETH_ALEN)) + nm_device_set_hw_addr (dev, (const guint8 *) cloned_mac->data, "set", LOGD_VLAN); + } + + s_vlan = nm_connection_get_setting_vlan (connection); + if (s_vlan) { + int ifindex = nm_device_get_ifindex (dev); + int num, i; + guint32 from, to; + + num = nm_setting_vlan_get_num_priorities (s_vlan, NM_VLAN_INGRESS_MAP); + for (i = 0; i < num; i++) { + if (nm_setting_vlan_get_priority (s_vlan, NM_VLAN_INGRESS_MAP, i, &from, &to)) + nm_platform_vlan_set_ingress_map (ifindex, from, to); + } + num = nm_setting_vlan_get_num_priorities (s_vlan, NM_VLAN_EGRESS_MAP); + for (i = 0; i < num; i++) { + if (nm_setting_vlan_get_priority (s_vlan, NM_VLAN_EGRESS_MAP, i, &from, &to)) + nm_platform_vlan_set_egress_map (ifindex, from, to); + } + } + + return ret; +} + +static void +ip4_config_pre_commit (NMDevice *device, NMIP4Config *config) +{ + NMConnection *connection; + NMSettingWired *s_wired; + guint32 mtu; + + connection = nm_device_get_connection (device); + g_assert (connection); + + s_wired = nm_connection_get_setting_wired (connection); + if (s_wired) { + mtu = nm_setting_wired_get_mtu (s_wired); + if (mtu) + nm_ip4_config_set_mtu (config, mtu); + } +} + +static void +deactivate (NMDevice *device) +{ + NMDeviceVlan *self = NM_DEVICE_VLAN (device); + NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (self); + + /* Reset MAC address back to initial address */ + nm_device_set_hw_addr (device, priv->initial_hw_addr, "reset", LOGD_VLAN); +} + +/******************************************************************/ + +static void +parent_state_changed (NMDevice *parent, + NMDeviceState new_state, + NMDeviceState old_state, + NMDeviceStateReason reason, + gpointer user_data) +{ + NMDeviceVlan *self = NM_DEVICE_VLAN (user_data); + + /* We'll react to our own carrier state notifications. Ignore the parent's. */ + if (reason == NM_DEVICE_STATE_REASON_CARRIER) + return; + + if (new_state < NM_DEVICE_STATE_DISCONNECTED) { + /* If the parent becomes unavailable or unmanaged so does the VLAN */ + nm_device_state_changed (NM_DEVICE (self), new_state, reason); + } else if ( new_state == NM_DEVICE_STATE_DISCONNECTED + && old_state < NM_DEVICE_STATE_DISCONNECTED) { + /* Mark VLAN interface as available/disconnected when the parent + * becomes available as a result of becoming initialized. + */ + nm_device_state_changed (NM_DEVICE (self), new_state, reason); + } +} + +/******************************************************************/ + +NMDevice * +nm_device_vlan_new (NMPlatformLink *platform_device, NMDevice *parent) +{ + NMDevice *device; + + g_return_val_if_fail (platform_device != NULL, NULL); + g_return_val_if_fail (NM_IS_DEVICE (parent), NULL); + + device = (NMDevice *) g_object_new (NM_TYPE_DEVICE_VLAN, + NM_DEVICE_PLATFORM_DEVICE, platform_device, + NM_DEVICE_VLAN_PARENT, parent, + NM_DEVICE_DRIVER, "8021q", + NM_DEVICE_TYPE_DESC, "VLAN", + NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_VLAN, + NULL); + if (NM_DEVICE_VLAN_GET_PRIVATE (device)->invalid) { + g_object_unref (device); + device = NULL; + } + + return device; +} + +NMDevice * +nm_device_vlan_new_for_connection (NMConnection *connection, NMDevice *parent) +{ + NMDevice *device; + NMSettingVlan *s_vlan; + char *iface; + + g_return_val_if_fail (connection != NULL, NULL); + g_return_val_if_fail (NM_IS_DEVICE (parent), NULL); + + s_vlan = nm_connection_get_setting_vlan (connection); + g_return_val_if_fail (s_vlan != NULL, NULL); + + iface = g_strdup (nm_connection_get_virtual_iface_name (connection)); + if (!iface) { + iface = nm_utils_new_vlan_name (nm_device_get_ip_iface (parent), + nm_setting_vlan_get_id (s_vlan)); + } + + if ( !nm_platform_vlan_add (iface, + nm_device_get_ifindex (parent), + nm_setting_vlan_get_id (s_vlan), + nm_setting_vlan_get_flags (s_vlan)) + && nm_platform_get_error () != NM_PLATFORM_ERROR_EXISTS) { + nm_log_warn (LOGD_DEVICE | LOGD_VLAN, "(%s): failed to add VLAN interface for '%s'", + iface, nm_connection_get_id (connection)); + g_free (iface); + return NULL; + } + + device = (NMDevice *) g_object_new (NM_TYPE_DEVICE_VLAN, + NM_DEVICE_IFACE, iface, + NM_DEVICE_VLAN_PARENT, parent, + NM_DEVICE_DRIVER, "8021q", + NM_DEVICE_TYPE_DESC, "VLAN", + NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_VLAN, + NULL); + g_free (iface); + if (NM_DEVICE_VLAN_GET_PRIVATE (device)->invalid) { + g_object_unref (device); + device = NULL; + } + + return device; +} + +static void +nm_device_vlan_init (NMDeviceVlan * self) +{ +} + +static void +constructed (GObject *object) +{ + NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (object); + NMDevice *device = NM_DEVICE (object); + const char *iface = nm_device_get_iface (device); + int ifindex = nm_device_get_ifindex (device); + int parent_ifindex = -1, itype; + int vlan_id; + + if (G_OBJECT_CLASS (nm_device_vlan_parent_class)->constructed) + G_OBJECT_CLASS (nm_device_vlan_parent_class)->constructed (object); + + if (!priv->parent) { + nm_log_err (LOGD_VLAN, "(%s): no parent specified.", iface); + priv->invalid = TRUE; + return; + } + + itype = nm_platform_link_get_type (ifindex); + if (itype != NM_LINK_TYPE_VLAN) { + nm_log_err (LOGD_VLAN, "(%s): failed to get VLAN interface type.", iface); + priv->invalid = TRUE; + return; + } + + if (!nm_platform_vlan_get_info (ifindex, &parent_ifindex, &vlan_id)) { + nm_log_warn (LOGD_VLAN, "(%s): failed to get VLAN interface info.", iface); + priv->invalid = TRUE; + return; + } + + if ( parent_ifindex < 0 + || parent_ifindex != nm_device_get_ip_ifindex (priv->parent) + || vlan_id < 0) { + nm_log_warn (LOGD_VLAN, "(%s): VLAN parent ifindex (%d) or VLAN ID (%d) invalid.", + iface, parent_ifindex, priv->vlan_id); + priv->invalid = TRUE; + return; + } + + priv->vlan_id = vlan_id; + nm_log_dbg (LOGD_HW | LOGD_VLAN, "(%s): kernel ifindex %d", iface, ifindex); + nm_log_info (LOGD_HW | LOGD_VLAN, "(%s): VLAN ID %d with parent %s", + iface, priv->vlan_id, nm_device_get_iface (priv->parent)); +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (object); + + switch (prop_id) { + case PROP_VLAN_ID: + g_value_set_uint (value, priv->vlan_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) +{ + NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (object); + + switch (prop_id) { + case PROP_PARENT: + nm_device_vlan_set_parent (NM_DEVICE_VLAN (object), g_value_get_object (value)); + break; + case PROP_VLAN_ID: + priv->vlan_id = g_value_get_uint (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +dispose (GObject *object) +{ + NMDeviceVlan *self = NM_DEVICE_VLAN (object); + NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (self); + + if (priv->disposed) { + G_OBJECT_CLASS (nm_device_vlan_parent_class)->dispose (object); + return; + } + priv->disposed = TRUE; + + nm_device_vlan_set_parent (self, NULL); + + G_OBJECT_CLASS (nm_device_vlan_parent_class)->dispose (object); +} + +static void +nm_device_vlan_class_init (NMDeviceVlanClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass); + + parent_class->connection_type = NM_SETTING_VLAN_SETTING_NAME; + + g_type_class_add_private (object_class, sizeof (NMDeviceVlanPrivate)); + + /* virtual methods */ + object_class->constructed = constructed; + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->dispose = dispose; + + parent_class->update_initial_hw_address = update_initial_hw_address; + parent_class->get_generic_capabilities = get_generic_capabilities; + parent_class->bring_up = bring_up; + parent_class->act_stage1_prepare = act_stage1_prepare; + parent_class->ip4_config_pre_commit = ip4_config_pre_commit; + parent_class->deactivate = deactivate; + + parent_class->check_connection_compatible = check_connection_compatible; + parent_class->complete_connection = complete_connection; + parent_class->update_connection = update_connection; + + /* properties */ + g_object_class_install_property + (object_class, PROP_PARENT, + g_param_spec_object (NM_DEVICE_VLAN_PARENT, + "Parent", + "Parent", + NM_TYPE_DEVICE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + g_object_class_install_property + (object_class, PROP_VLAN_ID, + g_param_spec_uint (NM_DEVICE_VLAN_ID, + "VLAN ID", + "VLAN ID", + 0, 4095, 0, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + nm_dbus_manager_register_exported_type (nm_dbus_manager_get (), + G_TYPE_FROM_CLASS (klass), + &dbus_glib_nm_device_vlan_object_info); + + dbus_g_error_domain_register (NM_VLAN_ERROR, NULL, NM_TYPE_VLAN_ERROR); +} diff --git a/src/devices/nm-device-vlan.h b/src/devices/nm-device-vlan.h new file mode 100644 index 00000000..0f2ac70d --- /dev/null +++ b/src/devices/nm-device-vlan.h @@ -0,0 +1,65 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright 2012 Red Hat, Inc. + */ + +#ifndef NM_DEVICE_VLAN_H +#define NM_DEVICE_VLAN_H + +#include + +#include "nm-device.h" + +G_BEGIN_DECLS + +#define NM_TYPE_DEVICE_VLAN (nm_device_vlan_get_type ()) +#define NM_DEVICE_VLAN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_VLAN, NMDeviceVlan)) +#define NM_DEVICE_VLAN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_VLAN, NMDeviceVlanClass)) +#define NM_IS_DEVICE_VLAN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_VLAN)) +#define NM_IS_DEVICE_VLAN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_VLAN)) +#define NM_DEVICE_VLAN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_VLAN, NMDeviceVlanClass)) + +typedef enum { + NM_VLAN_ERROR_CONNECTION_NOT_VLAN = 0, /*< nick=ConnectionNotVlan >*/ + NM_VLAN_ERROR_CONNECTION_INVALID, /*< nick=ConnectionInvalid >*/ + NM_VLAN_ERROR_CONNECTION_INCOMPATIBLE, /*< nick=ConnectionIncompatible >*/ +} NMVlanError; + +#define NM_DEVICE_VLAN_PARENT "parent" +#define NM_DEVICE_VLAN_ID "vlan-id" + +typedef struct { + NMDevice parent; +} NMDeviceVlan; + +typedef struct { + NMDeviceClass parent; + +} NMDeviceVlanClass; + + +GType nm_device_vlan_get_type (void); + +NMDevice *nm_device_vlan_new (NMPlatformLink *platform_link, + NMDevice *parent); +NMDevice *nm_device_vlan_new_for_connection (NMConnection *connection, + NMDevice *parent); + +G_END_DECLS + +#endif /* NM_DEVICE_VLAN_H */ diff --git a/src/devices/nm-device-vxlan.c b/src/devices/nm-device-vxlan.c new file mode 100644 index 00000000..0be57106 --- /dev/null +++ b/src/devices/nm-device-vxlan.c @@ -0,0 +1,372 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright 2013, 2014 Red Hat, Inc. + */ + +#include "config.h" + +#include + +#include "nm-device-vxlan.h" +#include "nm-device-private.h" +#include "nm-dbus-manager.h" +#include "nm-logging.h" +#include "nm-manager.h" +#include "nm-platform.h" +#include "nm-utils.h" + +#include "nm-device-vxlan-glue.h" + +G_DEFINE_TYPE (NMDeviceVxlan, nm_device_vxlan, NM_TYPE_DEVICE_GENERIC) + +#define NM_DEVICE_VXLAN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_VXLAN, NMDeviceVxlanPrivate)) + +typedef struct { + NMPlatformVxlanProperties props; +} NMDeviceVxlanPrivate; + +enum { + PROP_0, + PROP_PARENT, + PROP_ID, + PROP_GROUP, + PROP_LOCAL, + PROP_TOS, + PROP_TTL, + PROP_LEARNING, + PROP_AGEING, + PROP_LIMIT, + PROP_DST_PORT, + PROP_SRC_PORT_MIN, + PROP_SRC_PORT_MAX, + PROP_PROXY, + PROP_RSC, + PROP_L2MISS, + PROP_L3MISS, + + LAST_PROP +}; + +/**************************************************************/ + +static void +update_properties (NMDevice *device) +{ + NMDeviceVxlanPrivate *priv = NM_DEVICE_VXLAN_GET_PRIVATE (device); + GObject *object = G_OBJECT (device); + NMPlatformVxlanProperties props; + + if (!nm_platform_vxlan_get_properties (nm_device_get_ifindex (device), &props)) { + nm_log_warn (LOGD_HW, "(%s): could not read vxlan properties", + nm_device_get_iface (device)); + return; + } + + g_object_freeze_notify (object); + + if (priv->props.parent_ifindex != props.parent_ifindex) + g_object_notify (object, NM_DEVICE_VXLAN_PARENT); + if (priv->props.id != props.id) + g_object_notify (object, NM_DEVICE_VXLAN_ID); + if (priv->props.group != props.group) + g_object_notify (object, NM_DEVICE_VXLAN_GROUP); + if (priv->props.local != props.local) + g_object_notify (object, NM_DEVICE_VXLAN_LOCAL); + if (memcmp (&priv->props.group6, &props.group6, sizeof (props.group6)) != 0) + g_object_notify (object, NM_DEVICE_VXLAN_GROUP); + if (memcmp (&priv->props.local6, &props.local6, sizeof (props.local6)) != 0) + g_object_notify (object, NM_DEVICE_VXLAN_LOCAL); + if (priv->props.tos != props.tos) + g_object_notify (object, NM_DEVICE_VXLAN_TOS); + if (priv->props.ttl != props.ttl) + g_object_notify (object, NM_DEVICE_VXLAN_TTL); + if (priv->props.learning != props.learning) + g_object_notify (object, NM_DEVICE_VXLAN_LEARNING); + if (priv->props.ageing != props.ageing) + g_object_notify (object, NM_DEVICE_VXLAN_AGEING); + if (priv->props.limit != props.limit) + g_object_notify (object, NM_DEVICE_VXLAN_LIMIT); + if (priv->props.dst_port != props.dst_port) + g_object_notify (object, NM_DEVICE_VXLAN_DST_PORT); + if (priv->props.src_port_min != props.src_port_min) + g_object_notify (object, NM_DEVICE_VXLAN_SRC_PORT_MIN); + if (priv->props.src_port_max != props.src_port_max) + g_object_notify (object, NM_DEVICE_VXLAN_SRC_PORT_MAX); + if (priv->props.proxy != props.proxy) + g_object_notify (object, NM_DEVICE_VXLAN_PROXY); + if (priv->props.rsc != props.rsc) + g_object_notify (object, NM_DEVICE_VXLAN_RSC); + if (priv->props.l2miss != props.l2miss) + g_object_notify (object, NM_DEVICE_VXLAN_L2MISS); + if (priv->props.l3miss != props.l3miss) + g_object_notify (object, NM_DEVICE_VXLAN_L3MISS); + + memcpy (&priv->props, &props, sizeof (NMPlatformVxlanProperties)); + + g_object_thaw_notify (object); +} + +static void +link_changed (NMDevice *device, NMPlatformLink *info) +{ + NM_DEVICE_CLASS (nm_device_vxlan_parent_class)->link_changed (device, info); + update_properties (device); +} + +/**************************************************************/ + +NMDevice * +nm_device_vxlan_new (NMPlatformLink *platform_device) +{ + g_return_val_if_fail (platform_device != NULL, NULL); + + return (NMDevice *) g_object_new (NM_TYPE_DEVICE_VXLAN, + NM_DEVICE_PLATFORM_DEVICE, platform_device, + NM_DEVICE_TYPE_DESC, "Vxlan", + NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_GENERIC, + NULL); +} + +static void +nm_device_vxlan_init (NMDeviceVxlan *self) +{ +} + +static void +constructed (GObject *object) +{ + update_properties (NM_DEVICE (object)); + + G_OBJECT_CLASS (nm_device_vxlan_parent_class)->constructed (object); +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMDeviceVxlanPrivate *priv = NM_DEVICE_VXLAN_GET_PRIVATE (object); + NMDevice *parent; + + switch (prop_id) { + case PROP_PARENT: + parent = nm_manager_get_device_by_ifindex (nm_manager_get (), priv->props.parent_ifindex); + g_value_set_boxed (value, parent ? nm_device_get_path (parent) : "/"); + break; + case PROP_ID: + g_value_set_uint (value, priv->props.id); + break; + case PROP_GROUP: + if (priv->props.group) + g_value_set_string (value, nm_utils_inet4_ntop (priv->props.group, NULL)); + else if (!IN6_IS_ADDR_UNSPECIFIED (&priv->props.group6)) + g_value_set_string (value, nm_utils_inet6_ntop (&priv->props.group6, NULL)); + break; + case PROP_LOCAL: + if (priv->props.local) + g_value_set_string (value, nm_utils_inet4_ntop (priv->props.local, NULL)); + else if (!IN6_IS_ADDR_UNSPECIFIED (&priv->props.local6)) + g_value_set_string (value, nm_utils_inet6_ntop (&priv->props.local6, NULL)); + break; + case PROP_TOS: + g_value_set_uchar (value, priv->props.tos); + break; + case PROP_TTL: + g_value_set_uchar (value, priv->props.ttl); + break; + case PROP_LEARNING: + g_value_set_boolean (value, priv->props.learning); + break; + case PROP_AGEING: + g_value_set_uint (value, priv->props.ageing); + break; + case PROP_LIMIT: + g_value_set_uint (value, priv->props.limit); + break; + case PROP_DST_PORT: + g_value_set_uint (value, priv->props.dst_port); + break; + case PROP_SRC_PORT_MIN: + g_value_set_uint (value, priv->props.src_port_min); + break; + case PROP_SRC_PORT_MAX: + g_value_set_uint (value, priv->props.src_port_max); + break; + case PROP_PROXY: + g_value_set_uint (value, priv->props.proxy); + break; + case PROP_RSC: + g_value_set_boolean (value, priv->props.rsc); + break; + case PROP_L2MISS: + g_value_set_boolean (value, priv->props.l2miss); + break; + case PROP_L3MISS: + g_value_set_boolean (value, priv->props.l3miss); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_device_vxlan_class_init (NMDeviceVxlanClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); + + g_type_class_add_private (klass, sizeof (NMDeviceVxlanPrivate)); + + object_class->constructed = constructed; + object_class->get_property = get_property; + + device_class->link_changed = link_changed; + + /* properties */ + g_object_class_install_property + (object_class, PROP_PARENT, + g_param_spec_boxed (NM_DEVICE_VXLAN_PARENT, + "Parent", + "Parent device", + DBUS_TYPE_G_OBJECT_PATH, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_ID, + g_param_spec_uint (NM_DEVICE_VXLAN_ID, + "Id", + "Id", + 0, G_MAXUINT32, 0, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_GROUP, + g_param_spec_string (NM_DEVICE_VXLAN_GROUP, + "Group", + "Group", + NULL, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_LOCAL, + g_param_spec_string (NM_DEVICE_VXLAN_LOCAL, + "Local", + "Local", + NULL, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_TOS, + g_param_spec_uchar (NM_DEVICE_VXLAN_TOS, + "ToS", + "ToS", + 0, 255, 0, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_TTL, + g_param_spec_uchar (NM_DEVICE_VXLAN_TTL, + "TTL", + "TTL", + 0, 255, 0, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_LEARNING, + g_param_spec_boolean (NM_DEVICE_VXLAN_LEARNING, + "Learning", + "Learning", + FALSE, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_AGEING, + g_param_spec_uint (NM_DEVICE_VXLAN_AGEING, + "Ageing", + "Ageing", + 0, G_MAXUINT32, 0, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_LIMIT, + g_param_spec_uint (NM_DEVICE_VXLAN_LIMIT, + "Limit", + "Limit", + 0, G_MAXUINT32, 0, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_DST_PORT, + g_param_spec_uint (NM_DEVICE_VXLAN_DST_PORT, + "Destination port", + "Destination port", + 0, 65535, 0, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_SRC_PORT_MIN, + g_param_spec_uint (NM_DEVICE_VXLAN_SRC_PORT_MIN, + "Source port min", + "Minimum source port", + 0, 65535, 0, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_SRC_PORT_MAX, + g_param_spec_uint (NM_DEVICE_VXLAN_SRC_PORT_MAX, + "Source port max", + "Maximum source port", + 0, 65535, 0, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_PROXY, + g_param_spec_boolean (NM_DEVICE_VXLAN_PROXY, + "Proxy", + "Proxy", + FALSE, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_RSC, + g_param_spec_boolean (NM_DEVICE_VXLAN_RSC, + "RSC", + "RSC", + FALSE, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_L2MISS, + g_param_spec_boolean (NM_DEVICE_VXLAN_L2MISS, + "L2miss", + "L2miss", + FALSE, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_L3MISS, + g_param_spec_boolean (NM_DEVICE_VXLAN_L3MISS, + "L3miss", + "L3miss", + FALSE, + G_PARAM_READABLE)); + + nm_dbus_manager_register_exported_type (nm_dbus_manager_get (), + G_TYPE_FROM_CLASS (klass), + &dbus_glib_nm_device_vxlan_object_info); +} diff --git a/src/devices/nm-device-vxlan.h b/src/devices/nm-device-vxlan.h new file mode 100644 index 00000000..14b158de --- /dev/null +++ b/src/devices/nm-device-vxlan.h @@ -0,0 +1,69 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright 2013, 2014 Red Hat, Inc. + */ + +#ifndef NM_DEVICE_VXLAN_H +#define NM_DEVICE_VXLAN_H + +#include + +#include "nm-device-generic.h" + +G_BEGIN_DECLS + +#define NM_TYPE_DEVICE_VXLAN (nm_device_vxlan_get_type ()) +#define NM_DEVICE_VXLAN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_VXLAN, NMDeviceVxlan)) +#define NM_DEVICE_VXLAN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_VXLAN, NMDeviceVxlanClass)) +#define NM_IS_DEVICE_VXLAN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_VXLAN)) +#define NM_IS_DEVICE_VXLAN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_VXLAN)) +#define NM_DEVICE_VXLAN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_VXLAN, NMDeviceVxlanClass)) + +#define NM_DEVICE_VXLAN_PARENT "parent" +#define NM_DEVICE_VXLAN_ID "id" +#define NM_DEVICE_VXLAN_GROUP "group" +#define NM_DEVICE_VXLAN_LOCAL "local" +#define NM_DEVICE_VXLAN_TOS "tos" +#define NM_DEVICE_VXLAN_TTL "ttl" +#define NM_DEVICE_VXLAN_LEARNING "learning" +#define NM_DEVICE_VXLAN_AGEING "ageing" +#define NM_DEVICE_VXLAN_LIMIT "limit" +#define NM_DEVICE_VXLAN_DST_PORT "dst-port" +#define NM_DEVICE_VXLAN_SRC_PORT_MIN "src-port-min" +#define NM_DEVICE_VXLAN_SRC_PORT_MAX "src-port-max" +#define NM_DEVICE_VXLAN_PROXY "proxy" +#define NM_DEVICE_VXLAN_RSC "rsc" +#define NM_DEVICE_VXLAN_L2MISS "l2miss" +#define NM_DEVICE_VXLAN_L3MISS "l3miss" + +typedef struct { + NMDeviceGeneric parent; +} NMDeviceVxlan; + +typedef struct { + NMDeviceGenericClass parent; + +} NMDeviceVxlanClass; + +GType nm_device_vxlan_get_type (void); + +NMDevice *nm_device_vxlan_new (NMPlatformLink *platform_device); + +G_END_DECLS + +#endif /* NM_DEVICE_VXLAN_H */ diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c new file mode 100644 index 00000000..4788a604 --- /dev/null +++ b/src/devices/nm-device.c @@ -0,0 +1,7966 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2005 - 2013 Red Hat, Inc. + * Copyright (C) 2006 - 2008 Novell, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "libgsystem.h" +#include "nm-glib-compat.h" +#include "nm-device.h" +#include "nm-device-private.h" +#include "NetworkManagerUtils.h" +#include "nm-manager.h" +#include "nm-platform.h" +#include "nm-rdisc.h" +#include "nm-lndp-rdisc.h" +#include "nm-dhcp-manager.h" +#include "nm-dbus-manager.h" +#include "nm-utils.h" +#include "nm-logging.h" +#include "nm-setting-ip4-config.h" +#include "nm-setting-ip6-config.h" +#include "nm-setting-connection.h" +#include "nm-dnsmasq-manager.h" +#include "nm-dhcp4-config.h" +#include "nm-rfkill-manager.h" +#include "nm-firewall-manager.h" +#include "nm-properties-changed-signal.h" +#include "nm-enum-types.h" +#include "nm-settings-connection.h" +#include "nm-connection-provider.h" +#include "nm-posix-signals.h" +#include "nm-manager-auth.h" +#include "nm-dbus-glib-types.h" +#include "nm-dispatcher.h" +#include "nm-config-device.h" +#include "nm-config.h" +#include "nm-dns-manager.h" + +#include "nm-device-bridge.h" +#include "nm-device-bond.h" +#include "nm-device-team.h" + +static void impl_device_disconnect (NMDevice *device, DBusGMethodInvocation *context); + +#include "nm-device-glue.h" + +static void nm_device_config_device_interface_init (NMConfigDeviceInterface *iface); + +G_DEFINE_ABSTRACT_TYPE_WITH_CODE (NMDevice, nm_device, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (NM_TYPE_CONFIG_DEVICE, nm_device_config_device_interface_init)) + +#define NM_DEVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE, NMDevicePrivate)) + +enum { + STATE_CHANGED, + AUTOCONNECT_ALLOWED, + AUTH_REQUEST, + IP4_CONFIG_CHANGED, + IP6_CONFIG_CHANGED, + REMOVED, + RECHECK_AUTO_ACTIVATE, + RECHECK_ASSUME, + LAST_SIGNAL, +}; +static guint signals[LAST_SIGNAL] = { 0 }; + +enum { + PROP_0, + PROP_PLATFORM_DEVICE, + PROP_UDI, + PROP_IFACE, + PROP_IP_IFACE, + PROP_DRIVER, + PROP_DRIVER_VERSION, + PROP_FIRMWARE_VERSION, + PROP_CAPABILITIES, + PROP_CARRIER, + PROP_MTU, + PROP_IP4_ADDRESS, + PROP_IP4_CONFIG, + PROP_DHCP4_CONFIG, + PROP_IP6_CONFIG, + PROP_DHCP6_CONFIG, + PROP_STATE, + PROP_STATE_REASON, + PROP_ACTIVE_CONNECTION, + PROP_DEVICE_TYPE, + PROP_MANAGED, + PROP_AUTOCONNECT, + PROP_FIRMWARE_MISSING, + PROP_TYPE_DESC, + PROP_RFKILL_TYPE, + PROP_IFINDEX, + PROP_AVAILABLE_CONNECTIONS, + PROP_PHYSICAL_PORT_ID, + PROP_IS_MASTER, + PROP_MASTER, + PROP_HW_ADDRESS, + PROP_HAS_PENDING_ACTION, + LAST_PROP +}; + +/***********************************************************/ + +#define PENDING_ACTION_DHCP4 "dhcp4" +#define PENDING_ACTION_DHCP6 "dhcp6" +#define PENDING_ACTION_AUTOCONF6 "autoconf6" + +typedef enum { + IP_NONE = 0, + IP_WAIT, + IP_CONF, + IP_DONE, + IP_FAIL +} IpState; + +typedef struct { + NMDeviceState state; + NMDeviceStateReason reason; + guint id; +} QueuedState; + +typedef struct { + NMDevice *slave; + gboolean enslaved; + gboolean configure; + guint watch_id; +} SlaveInfo; + +typedef struct { + guint log_domain; + guint timeout; + guint watch; + GPid pid; +} PingInfo; + +typedef struct { + NMDevice *device; + guint idle_add_id; + int ifindex; +} DeleteOnDeactivateData; + +typedef struct { + gboolean in_state_changed; + + NMDeviceState state; + NMDeviceStateReason state_reason; + QueuedState queued_state; + guint queued_ip_config_id; + GSList *pending_actions; + + char * udi; + char * path; + char * iface; /* may change, could be renamed by user */ + int ifindex; + gboolean is_software; + char * ip_iface; + int ip_ifindex; + NMDeviceType type; + char * type_desc; + guint32 capabilities; + char * driver; + char * driver_version; + char * firmware_version; + RfKillType rfkill_type; + gboolean firmware_missing; + GHashTable * available_connections; + guint8 hw_addr[NM_UTILS_HWADDR_LEN_MAX]; + guint hw_addr_len; + char * physical_port_id; + + NMUnmanagedFlags unmanaged_flags; + gboolean is_nm_owned; /* whether the device is a device owned and created by NM */ + DeleteOnDeactivateData *delete_on_deactivate_data; /* data for scheduled cleanup when deleting link (g_idle_add) */ + + guint32 ip4_address; + + NMActRequest * queued_act_request; + NMActRequest * act_request; + guint act_source_id; + gpointer act_source_func; + guint act_source6_id; + gpointer act_source6_func; + guint recheck_assume_id; + struct { + guint call_id; + NMDeviceState post_state; + NMDeviceStateReason post_state_reason; + } dispatcher; + + /* Link stuff */ + guint link_connected_id; + guint link_disconnected_id; + guint carrier_defer_id; + gboolean carrier; + guint carrier_wait_id; + gboolean ignore_carrier; + guint32 mtu; + + /* Generic DHCP stuff */ + guint32 dhcp_timeout; + GByteArray * dhcp_anycast_address; + + /* IP4 configuration info */ + NMIP4Config * ip4_config; /* Combined config from VPN, settings, and device */ + IpState ip4_state; + NMIP4Config * dev_ip4_config; /* Config from DHCP, PPP, LLv4, etc */ + NMIP4Config * ext_ip4_config; /* Stuff added outside NM */ + + /* DHCPv4 tracking */ + NMDHCPClient * dhcp4_client; + gulong dhcp4_state_sigid; + gulong dhcp4_timeout_sigid; + NMDHCP4Config * dhcp4_config; + NMIP4Config * vpn4_config; /* routes added by a VPN which uses this device */ + + guint arp_round2_id; + PingInfo gw_ping; + + /* dnsmasq stuff for shared connections */ + NMDnsMasqManager *dnsmasq_manager; + gulong dnsmasq_state_id; + + /* Firewall Manager */ + NMFirewallManager *fw_manager; + DBusGProxyCall *fw_call; + + /* avahi-autoipd stuff */ + GPid aipd_pid; + guint aipd_watch; + guint aipd_timeout; + + /* IP6 configuration info */ + NMIP6Config * ip6_config; + IpState ip6_state; + NMIP6Config * vpn6_config; /* routes added by a VPN which uses this device */ + NMIP6Config * ext_ip6_config; /* Stuff added outside NM */ + + NMRDisc * rdisc; + gulong rdisc_config_changed_sigid; + NMSettingIP6ConfigPrivacy rdisc_use_tempaddr; + /* IP6 config from autoconf */ + NMIP6Config * ac_ip6_config; + + guint linklocal6_timeout_id; + + GHashTable * ip6_saved_properties; + + NMDHCPClient * dhcp6_client; + NMRDiscDHCPLevel dhcp6_mode; + gulong dhcp6_state_sigid; + gulong dhcp6_timeout_sigid; + NMDHCP6Config * dhcp6_config; + /* IP6 config from DHCP */ + NMIP6Config * dhcp6_ip6_config; + + /* allow autoconnect feature */ + gboolean autoconnect; + + /* master interface for bridge/bond/team slave */ + NMDevice * master; + gboolean enslaved; + guint master_ready_id; + + /* slave management */ + gboolean is_master; + GSList * slaves; /* list of SlaveInfo */ + + NMConnectionProvider *con_provider; +} NMDevicePrivate; + +static gboolean nm_device_set_ip4_config (NMDevice *dev, + NMIP4Config *config, + gboolean commit, + NMDeviceStateReason *reason); +static gboolean ip4_config_merge_and_apply (NMDevice *self, + NMIP4Config *config, + gboolean commit, + NMDeviceStateReason *out_reason); + +static gboolean nm_device_set_ip6_config (NMDevice *dev, + NMIP6Config *config, + gboolean commit, + NMDeviceStateReason *reason); + +static gboolean nm_device_master_add_slave (NMDevice *dev, NMDevice *slave, gboolean configure); +static void nm_device_slave_notify_enslave (NMDevice *dev, gboolean success); +static void nm_device_slave_notify_release (NMDevice *dev, NMDeviceStateReason reason); + +static void addrconf6_start_with_link_ready (NMDevice *self); + +static gboolean nm_device_get_default_unmanaged (NMDevice *device); + +static void _set_state_full (NMDevice *device, + NMDeviceState state, + NMDeviceStateReason reason, + gboolean quitting); + +/***********************************************************/ + +static GQuark +nm_device_error_quark (void) +{ + static GQuark quark = 0; + if (!quark) + quark = g_quark_from_static_string ("nm-device-error"); + return quark; +} + +#define NM_DEVICE_ERROR (nm_device_error_quark ()) + +/***********************************************************/ + +#define QUEUED_PREFIX "queued state change to " + +static const char *state_table[] = { + [NM_DEVICE_STATE_UNKNOWN] = QUEUED_PREFIX "unknown", + [NM_DEVICE_STATE_UNMANAGED] = QUEUED_PREFIX "unmanaged", + [NM_DEVICE_STATE_UNAVAILABLE] = QUEUED_PREFIX "unavailable", + [NM_DEVICE_STATE_DISCONNECTED] = QUEUED_PREFIX "disconnected", + [NM_DEVICE_STATE_PREPARE] = QUEUED_PREFIX "prepare", + [NM_DEVICE_STATE_CONFIG] = QUEUED_PREFIX "config", + [NM_DEVICE_STATE_NEED_AUTH] = QUEUED_PREFIX "need-auth", + [NM_DEVICE_STATE_IP_CONFIG] = QUEUED_PREFIX "ip-config", + [NM_DEVICE_STATE_IP_CHECK] = QUEUED_PREFIX "ip-check", + [NM_DEVICE_STATE_SECONDARIES] = QUEUED_PREFIX "secondaries", + [NM_DEVICE_STATE_ACTIVATED] = QUEUED_PREFIX "activated", + [NM_DEVICE_STATE_DEACTIVATING] = QUEUED_PREFIX "deactivating", + [NM_DEVICE_STATE_FAILED] = QUEUED_PREFIX "failed", +}; + +static const char * +queued_state_to_string (NMDeviceState state) +{ + if (state >= 0 && state < G_N_ELEMENTS (state_table)) + return state_table[state]; + return state_table[NM_DEVICE_STATE_UNKNOWN]; +} + +static const char * +state_to_string (NMDeviceState state) +{ + return queued_state_to_string (state) + strlen (QUEUED_PREFIX); +} + +static const char *reason_table[] = { + [NM_DEVICE_STATE_REASON_NONE] = "none", + [NM_DEVICE_STATE_REASON_NOW_MANAGED] = "managed", + [NM_DEVICE_STATE_REASON_NOW_UNMANAGED] = "unmanaged", + [NM_DEVICE_STATE_REASON_CONFIG_FAILED] = "config-failed", + [NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE] = "ip-config-unavailable", + [NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED] = "ip-config-expired", + [NM_DEVICE_STATE_REASON_NO_SECRETS] = "no-secrets", + [NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT] = "supplicant-disconnect", + [NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED] = "supplicant-config-failed", + [NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED] = "supplicant-failed", + [NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT] = "supplicant-timeout", + [NM_DEVICE_STATE_REASON_PPP_START_FAILED] = "ppp-start-failed", + [NM_DEVICE_STATE_REASON_PPP_DISCONNECT] = "ppp-disconnect", + [NM_DEVICE_STATE_REASON_PPP_FAILED] = "ppp-failed", + [NM_DEVICE_STATE_REASON_DHCP_START_FAILED] = "dhcp-start-failed", + [NM_DEVICE_STATE_REASON_DHCP_ERROR] = "dhcp-error", + [NM_DEVICE_STATE_REASON_DHCP_FAILED] = "dhcp-failed", + [NM_DEVICE_STATE_REASON_SHARED_START_FAILED] = "sharing-start-failed", + [NM_DEVICE_STATE_REASON_SHARED_FAILED] = "sharing-failed", + [NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED] = "autoip-start-failed", + [NM_DEVICE_STATE_REASON_AUTOIP_ERROR] = "autoip-error", + [NM_DEVICE_STATE_REASON_AUTOIP_FAILED] = "autoip-failed", + [NM_DEVICE_STATE_REASON_MODEM_BUSY] = "modem-busy", + [NM_DEVICE_STATE_REASON_MODEM_NO_DIAL_TONE] = "modem-no-dialtone", + [NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER] = "modem-no-carrier", + [NM_DEVICE_STATE_REASON_MODEM_DIAL_TIMEOUT] = "modem-dial-timeout", + [NM_DEVICE_STATE_REASON_MODEM_DIAL_FAILED] = "modem-dial-failed", + [NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED] = "modem-init-failed", + [NM_DEVICE_STATE_REASON_GSM_APN_FAILED] = "gsm-apn-failed", + [NM_DEVICE_STATE_REASON_GSM_REGISTRATION_NOT_SEARCHING] = "gsm-registration-idle", + [NM_DEVICE_STATE_REASON_GSM_REGISTRATION_DENIED] = "gsm-registration-denied", + [NM_DEVICE_STATE_REASON_GSM_REGISTRATION_TIMEOUT] = "gsm-registration-timeout", + [NM_DEVICE_STATE_REASON_GSM_REGISTRATION_FAILED] = "gsm-registration-failed", + [NM_DEVICE_STATE_REASON_GSM_PIN_CHECK_FAILED] = "gsm-pin-check-failed", + [NM_DEVICE_STATE_REASON_FIRMWARE_MISSING] = "firmware-missing", + [NM_DEVICE_STATE_REASON_REMOVED] = "removed", + [NM_DEVICE_STATE_REASON_SLEEPING] = "sleeping", + [NM_DEVICE_STATE_REASON_CONNECTION_REMOVED] = "connection-removed", + [NM_DEVICE_STATE_REASON_USER_REQUESTED] = "user-requested", + [NM_DEVICE_STATE_REASON_CARRIER] = "carrier-changed", + [NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED] = "connection-assumed", + [NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE] = "supplicant-available", + [NM_DEVICE_STATE_REASON_MODEM_NOT_FOUND] = "modem-not-found", + [NM_DEVICE_STATE_REASON_BT_FAILED] = "bluetooth-failed", + [NM_DEVICE_STATE_REASON_GSM_SIM_NOT_INSERTED] = "gsm-sim-not-inserted", + [NM_DEVICE_STATE_REASON_GSM_SIM_PIN_REQUIRED] = "gsm-sim-pin-required", + [NM_DEVICE_STATE_REASON_GSM_SIM_PUK_REQUIRED] = "gsm-sim-puk-required", + [NM_DEVICE_STATE_REASON_GSM_SIM_WRONG] = "gsm-sim-wrong", + [NM_DEVICE_STATE_REASON_INFINIBAND_MODE] = "infiniband-mode", + [NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED] = "dependency-failed", + [NM_DEVICE_STATE_REASON_BR2684_FAILED] = "br2684-bridge-failed", + [NM_DEVICE_STATE_REASON_MODEM_MANAGER_UNAVAILABLE] = "modem-manager-unavailable", + [NM_DEVICE_STATE_REASON_SSID_NOT_FOUND] = "ssid-not-found", + [NM_DEVICE_STATE_REASON_SECONDARY_CONNECTION_FAILED] = "secondary-connection-failed", + [NM_DEVICE_STATE_REASON_DCB_FCOE_FAILED] = "dcb-fcoe-failed", + [NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED] = "teamd-control-failed", + [NM_DEVICE_STATE_REASON_MODEM_FAILED] = "modem-failed", + [NM_DEVICE_STATE_REASON_MODEM_AVAILABLE] = "modem-available", + [NM_DEVICE_STATE_REASON_SIM_PIN_INCORRECT] = "sim-pin-incorrect", +}; + +static const char * +reason_to_string (NMDeviceStateReason reason) +{ + if (reason >= 0 && reason < G_N_ELEMENTS (reason_table)) + return reason_table[reason]; + return reason_table[NM_DEVICE_STATE_REASON_UNKNOWN]; +} + +/***********************************************************/ + +static inline gboolean +nm_device_ipv6_sysctl_set (NMDevice *self, const char *property, const char *value) +{ + return nm_platform_sysctl_set (nm_utils_ip6_property_path (nm_device_get_ip_iface (self), property), value); +} + +static gboolean +device_has_capability (NMDevice *device, NMDeviceCapabilities caps) +{ + return !!(NM_DEVICE_GET_PRIVATE (device)->capabilities & caps); +} + +/***********************************************************/ + +void +nm_device_dbus_export (NMDevice *device) +{ + static guint32 devcount = 0; + NMDevicePrivate *priv; + + g_return_if_fail (NM_IS_DEVICE (device)); + + priv = NM_DEVICE_GET_PRIVATE (device); + g_return_if_fail (priv->path == NULL); + + priv->path = g_strdup_printf ("/org/freedesktop/NetworkManager/Devices/%d", devcount++); + nm_log_info (LOGD_DEVICE, "(%s): exported as %s", priv->iface, priv->path); + nm_dbus_manager_register_object (nm_dbus_manager_get (), priv->path, device); +} + +const char * +nm_device_get_path (NMDevice *self) +{ + g_return_val_if_fail (self != NULL, NULL); + + return NM_DEVICE_GET_PRIVATE (self)->path; +} + +const char * +nm_device_get_udi (NMDevice *self) +{ + g_return_val_if_fail (self != NULL, NULL); + + return NM_DEVICE_GET_PRIVATE (self)->udi; +} + +const char * +nm_device_get_iface (NMDevice *self) +{ + g_return_val_if_fail (self != NULL, NULL); + + return NM_DEVICE_GET_PRIVATE (self)->iface; +} + +int +nm_device_get_ifindex (NMDevice *self) +{ + g_return_val_if_fail (self != NULL, 0); + + return NM_DEVICE_GET_PRIVATE (self)->ifindex; +} + +gboolean +nm_device_is_software (NMDevice *device) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); + + return priv->is_software; +} + +const char * +nm_device_get_ip_iface (NMDevice *self) +{ + NMDevicePrivate *priv; + + g_return_val_if_fail (self != NULL, NULL); + + priv = NM_DEVICE_GET_PRIVATE (self); + /* If it's not set, default to iface */ + return priv->ip_iface ? priv->ip_iface : priv->iface; +} + +int +nm_device_get_ip_ifindex (NMDevice *self) +{ + NMDevicePrivate *priv; + + g_return_val_if_fail (self != NULL, 0); + + priv = NM_DEVICE_GET_PRIVATE (self); + /* If it's not set, default to iface */ + return priv->ip_iface ? priv->ip_ifindex : priv->ifindex; +} + +void +nm_device_set_ip_iface (NMDevice *self, const char *iface) +{ + NMDevicePrivate *priv; + char *old_ip_iface; + + g_return_if_fail (NM_IS_DEVICE (self)); + + priv = NM_DEVICE_GET_PRIVATE (self); + if (!g_strcmp0 (iface, priv->ip_iface)) + return; + + old_ip_iface = priv->ip_iface; + priv->ip_ifindex = 0; + + priv->ip_iface = g_strdup (iface); + if (priv->ip_iface) { + priv->ip_ifindex = nm_platform_link_get_ifindex (priv->ip_iface); + if (priv->ip_ifindex > 0) { + if (!nm_platform_link_is_up (priv->ip_ifindex)) + nm_platform_link_set_up (priv->ip_ifindex); + } else { + /* Device IP interface must always be a kernel network interface */ + nm_log_warn (LOGD_HW, "(%s): failed to look up interface index", iface); + } + } + + /* We don't care about any saved values from the old iface */ + g_hash_table_remove_all (priv->ip6_saved_properties); + + /* Emit change notification */ + if (g_strcmp0 (old_ip_iface, priv->ip_iface)) + g_object_notify (G_OBJECT (self), NM_DEVICE_IP_IFACE); + g_free (old_ip_iface); +} + +const char * +nm_device_get_driver (NMDevice *self) +{ + g_return_val_if_fail (self != NULL, NULL); + + return NM_DEVICE_GET_PRIVATE (self)->driver; +} + +const char * +nm_device_get_driver_version (NMDevice *self) +{ + g_return_val_if_fail (self != NULL, NULL); + + return NM_DEVICE_GET_PRIVATE (self)->driver_version; +} + +NMDeviceType +nm_device_get_device_type (NMDevice *self) +{ + g_return_val_if_fail (NM_IS_DEVICE (self), NM_DEVICE_TYPE_UNKNOWN); + + return NM_DEVICE_GET_PRIVATE (self)->type; +} + + +/** + * nm_device_get_priority(): + * @dev: the #NMDevice + * + * Returns: the device's routing priority. Lower numbers means a "better" + * device, eg higher priority. + */ +int +nm_device_get_priority (NMDevice *dev) +{ + g_return_val_if_fail (NM_IS_DEVICE (dev), 100); + + /* Device 'priority' is used for two things: + * + * a) two devices on the same IP subnet: the "better" (ie, lower number) + * device is the default outgoing device for that subnet + * b) default route: the "better" device gets the default route. This can + * always be modified by setting a connection to never-default=TRUE, in + * which case that device will never take the default route when + * it's using that connection. + */ + + switch (nm_device_get_device_type (dev)) { + case NM_DEVICE_TYPE_ETHERNET: + return 1; + case NM_DEVICE_TYPE_INFINIBAND: + return 2; + case NM_DEVICE_TYPE_ADSL: + return 3; + case NM_DEVICE_TYPE_WIMAX: + return 4; + case NM_DEVICE_TYPE_BOND: + return 5; + case NM_DEVICE_TYPE_TEAM: + return 6; + case NM_DEVICE_TYPE_VLAN: + return 7; + case NM_DEVICE_TYPE_MODEM: + return 8; + case NM_DEVICE_TYPE_BT: + return 9; + case NM_DEVICE_TYPE_WIFI: + return 10; + case NM_DEVICE_TYPE_OLPC_MESH: + return 11; + default: + return 20; + } +} + +const char * +nm_device_get_type_desc (NMDevice *self) +{ + g_return_val_if_fail (self != NULL, NULL); + + return NM_DEVICE_GET_PRIVATE (self)->type_desc; +} + +gboolean +nm_device_has_carrier (NMDevice *device) +{ + return NM_DEVICE_GET_PRIVATE (device)->carrier; +} + +NMActRequest * +nm_device_get_act_request (NMDevice *self) +{ + g_return_val_if_fail (self != NULL, NULL); + + return NM_DEVICE_GET_PRIVATE (self)->act_request; +} + +NMConnection * +nm_device_get_connection (NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + + return priv->act_request ? nm_act_request_get_connection (priv->act_request) : NULL; +} + +RfKillType +nm_device_get_rfkill_type (NMDevice *self) +{ + g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); + + return NM_DEVICE_GET_PRIVATE (self)->rfkill_type; +} + +static const char * +nm_device_get_physical_port_id (NMDevice *device) +{ + return NM_DEVICE_GET_PRIVATE (device)->physical_port_id; +} + +/***********************************************************/ + +static gboolean +nm_device_uses_generated_connection (NMDevice *self) +{ + NMConnection *connection; + + connection = nm_device_get_connection (self); + if (!connection) + return FALSE; + return nm_settings_connection_get_nm_generated (NM_SETTINGS_CONNECTION (connection)); +} + +static SlaveInfo * +find_slave_info (NMDevice *self, NMDevice *slave) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + SlaveInfo *info; + GSList *iter; + + for (iter = priv->slaves; iter; iter = g_slist_next (iter)) { + info = iter->data; + if (info->slave == slave) + return info; + } + return NULL; +} + +static void +free_slave_info (SlaveInfo *info) +{ + g_signal_handler_disconnect (info->slave, info->watch_id); + g_clear_object (&info->slave); + memset (info, 0, sizeof (*info)); + g_free (info); +} + +/** + * nm_device_enslave_slave: + * @dev: the master device + * @slave: the slave device to enslave + * @connection: (allow-none): the slave device's connection + * + * If @dev is capable of enslaving other devices (ie it's a bridge, bond, team, + * etc) then this function enslaves @slave. + * + * Returns: %TRUE on success, %FALSE on failure or if this device cannot enslave + * other devices. + */ +static gboolean +nm_device_enslave_slave (NMDevice *dev, NMDevice *slave, NMConnection *connection) +{ + SlaveInfo *info; + gboolean success = FALSE; + gboolean configure; + + g_return_val_if_fail (dev != NULL, FALSE); + g_return_val_if_fail (slave != NULL, FALSE); + g_return_val_if_fail (NM_DEVICE_GET_CLASS (dev)->enslave_slave != NULL, FALSE); + + info = find_slave_info (dev, slave); + if (!info) + return FALSE; + + if (info->enslaved) + success = TRUE; + else { + configure = (info->configure && connection != NULL); + if (configure) + g_return_val_if_fail (nm_device_get_state (slave) >= NM_DEVICE_STATE_DISCONNECTED, FALSE); + + success = NM_DEVICE_GET_CLASS (dev)->enslave_slave (dev, slave, connection, configure); + info->enslaved = success; + } + + nm_device_slave_notify_enslave (info->slave, success); + + /* Ensure the device's hardware address is up-to-date; it often changes + * when slaves change. + */ + nm_device_update_hw_address (dev); + + /* Restart IP configuration if we're waiting for slaves. Do this + * after updating the hardware address as IP config may need the + * new address. + */ + if (success) { + if (NM_DEVICE_GET_PRIVATE (dev)->ip4_state == IP_WAIT) + nm_device_activate_stage3_ip4_start (dev); + + if (NM_DEVICE_GET_PRIVATE (dev)->ip6_state == IP_WAIT) + nm_device_activate_stage3_ip6_start (dev); + } + + return success; +} + +/** + * nm_device_release_one_slave: + * @dev: the master device + * @slave: the slave device to release + * @configure: whether @dev needs to actually release @slave + * @reason: the state change reason for the @slave + * + * If @dev is capable of enslaving other devices (ie it's a bridge, bond, team, + * etc) then this function releases the previously enslaved @slave and/or + * updates the state of @dev and @slave to reflect its release. + * + * Returns: %TRUE on success, %FALSE on failure, if this device cannot enslave + * other devices, or if @slave was never enslaved. + */ +static gboolean +nm_device_release_one_slave (NMDevice *dev, NMDevice *slave, gboolean configure, NMDeviceStateReason reason) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (dev); + SlaveInfo *info; + gboolean success = FALSE; + + g_return_val_if_fail (slave != NULL, FALSE); + g_return_val_if_fail (NM_DEVICE_GET_CLASS (dev)->release_slave != NULL, FALSE); + + info = find_slave_info (dev, slave); + if (!info) + return FALSE; + priv->slaves = g_slist_remove (priv->slaves, info); + + if (info->enslaved) { + success = NM_DEVICE_GET_CLASS (dev)->release_slave (dev, slave, configure); + /* The release_slave() implementation logs success/failure (in the + * correct device-specific log domain), so we don't have to do anything. + */ + } + + if (!configure) { + g_warn_if_fail (reason == NM_DEVICE_STATE_REASON_NONE); + reason = NM_DEVICE_STATE_REASON_NONE; + } else if (reason == NM_DEVICE_STATE_REASON_NONE) { + g_warn_if_reached (); + reason = NM_DEVICE_STATE_REASON_UNKNOWN; + } + nm_device_slave_notify_release (info->slave, reason); + + free_slave_info (info); + + /* Ensure the device's hardware address is up-to-date; it often changes + * when slaves change. + */ + nm_device_update_hw_address (dev); + + return success; +} + +static void +carrier_changed (NMDevice *device, gboolean carrier) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); + + if (!nm_device_get_managed (device)) + return; + + nm_device_recheck_available_connections (device); + + /* ignore-carrier devices ignore all carrier-down events */ + if (priv->ignore_carrier && !carrier) + return; + + if (priv->is_master) { + /* Bridge/bond/team carrier does not affect its own activation, + * but when carrier comes on, if there are slaves waiting, + * it will restart them. + */ + if (!carrier) + return; + + if (nm_device_activate_ip4_state_in_wait (device)) + nm_device_activate_stage3_ip4_start (device); + if (nm_device_activate_ip6_state_in_wait (device)) + nm_device_activate_stage3_ip6_start (device); + + return; + } else if (nm_device_get_enslaved (device) && !carrier) { + /* Slaves don't deactivate when they lose carrier; for + * bonds/teams in particular that would be actively + * counterproductive. + */ + return; + } + + if (carrier) { + g_warn_if_fail (priv->state >= NM_DEVICE_STATE_UNAVAILABLE); + + if (priv->state == NM_DEVICE_STATE_UNAVAILABLE) { + nm_device_queue_state (device, NM_DEVICE_STATE_DISCONNECTED, + NM_DEVICE_STATE_REASON_CARRIER); + } else if (priv->state == NM_DEVICE_STATE_DISCONNECTED) { + /* If the device is already in DISCONNECTED state without a carrier + * (probably because it is tagged for carrier ignore) ensure that + * when the carrier appears, auto connections are rechecked for + * the device. + */ + nm_device_emit_recheck_auto_activate (device); + } + } else { + if (priv->state == NM_DEVICE_STATE_UNAVAILABLE) { + if (nm_device_queued_state_peek (device) >= NM_DEVICE_STATE_DISCONNECTED) + nm_device_queued_state_clear (device); + } else if (priv->state >= NM_DEVICE_STATE_DISCONNECTED) { + nm_device_queue_state (device, NM_DEVICE_STATE_UNAVAILABLE, + NM_DEVICE_STATE_REASON_CARRIER); + } + } +} + +#define LINK_DISCONNECT_DELAY 4 + +static gboolean +link_disconnect_action_cb (gpointer user_data) +{ + NMDevice *device = NM_DEVICE (user_data); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); + + nm_log_dbg (LOGD_DEVICE, "(%s): link disconnected (calling deferred action) (id=%u)", + nm_device_get_iface (device), priv->carrier_defer_id); + + priv->carrier_defer_id = 0; + + nm_log_info (LOGD_DEVICE, "(%s): link disconnected (calling deferred action)", + nm_device_get_iface (device)); + + NM_DEVICE_GET_CLASS (device)->carrier_changed (device, FALSE); + + return FALSE; +} + +static void +link_disconnect_action_cancel (NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + + if (priv->carrier_defer_id) { + g_source_remove (priv->carrier_defer_id); + nm_log_dbg (LOGD_DEVICE, "(%s): link disconnected (canceling deferred action) (id=%u)", + nm_device_get_iface (self), priv->carrier_defer_id); + priv->carrier_defer_id = 0; + } +} + +void +nm_device_set_carrier (NMDevice *device, gboolean carrier) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); + NMDeviceClass *klass = NM_DEVICE_GET_CLASS (device); + NMDeviceState state = nm_device_get_state (device); + const char *iface = nm_device_get_iface (device); + + if (priv->carrier == carrier) + return; + + priv->carrier = carrier; + g_object_notify (G_OBJECT (device), NM_DEVICE_CARRIER); + + if (priv->carrier) { + nm_log_info (LOGD_DEVICE, "(%s): link connected", iface); + link_disconnect_action_cancel (device); + klass->carrier_changed (device, TRUE); + + if (priv->carrier_wait_id) { + g_source_remove (priv->carrier_wait_id); + priv->carrier_wait_id = 0; + nm_device_remove_pending_action (device, "carrier wait", TRUE); + } + } else if (state <= NM_DEVICE_STATE_DISCONNECTED) { + nm_log_info (LOGD_DEVICE, "(%s): link disconnected", iface); + klass->carrier_changed (device, FALSE); + } else { + nm_log_info (LOGD_DEVICE, "(%s): link disconnected (deferring action for %d seconds)", + iface, LINK_DISCONNECT_DELAY); + priv->carrier_defer_id = g_timeout_add_seconds (LINK_DISCONNECT_DELAY, + link_disconnect_action_cb, device); + nm_log_dbg (LOGD_DEVICE, "(%s): link disconnected (deferring action for %d seconds) (id=%u)", + iface, LINK_DISCONNECT_DELAY, priv->carrier_defer_id); + } +} + +static void +update_for_ip_ifname_change (NMDevice *device) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); + + g_hash_table_remove_all (priv->ip6_saved_properties); + + if (priv->dhcp4_client) { + if (!nm_device_dhcp4_renew (device, FALSE)) { + nm_device_state_changed (device, + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_DHCP_FAILED); + return; + } + } + if (priv->dhcp6_client) { + if (!nm_device_dhcp6_renew (device, FALSE)) { + nm_device_state_changed (device, + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_DHCP_FAILED); + return; + } + } + if (priv->rdisc) { + /* FIXME: todo */ + } + if (priv->dnsmasq_manager) { + /* FIXME: todo */ + } +} + +static void +device_link_changed (NMDevice *device, NMPlatformLink *info) +{ + NMDeviceClass *klass = NM_DEVICE_GET_CLASS (device); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); + gboolean ip_ifname_changed = FALSE; + + if (info->udi && g_strcmp0 (info->udi, priv->udi)) { + /* Update UDI to what udev gives us */ + g_free (priv->udi); + priv->udi = g_strdup (info->udi); + g_object_notify (G_OBJECT (device), NM_DEVICE_UDI); + } + + /* Update MTU if it has changed. */ + if (priv->mtu != info->mtu) { + priv->mtu = info->mtu; + g_object_notify (G_OBJECT (device), NM_DEVICE_MTU); + } + + if (info->name[0] && strcmp (priv->iface, info->name) != 0) { + nm_log_info (LOGD_DEVICE, "(%s): interface index %d renamed iface from '%s' to '%s'", + priv->iface, priv->ifindex, priv->iface, info->name); + g_free (priv->iface); + priv->iface = g_strdup (info->name); + + /* If the device has no explicit ip_iface, then changing iface changes ip_iface too. */ + ip_ifname_changed = !priv->ip_iface; + + g_object_notify (G_OBJECT (device), NM_DEVICE_IFACE); + if (ip_ifname_changed) + g_object_notify (G_OBJECT (device), NM_DEVICE_IP_IFACE); + + /* Re-match available connections against the new interface name */ + nm_device_recheck_available_connections (device); + + /* Let any connections that use the new interface name have a chance + * to auto-activate on the device. + */ + nm_device_emit_recheck_auto_activate (device); + } + + /* Update slave status for external changes */ + if (info->master && !priv->enslaved) { + NMDevice *master; + + master = nm_manager_get_device_by_ifindex (nm_manager_get (), info->master); + if (master && NM_DEVICE_GET_CLASS (master)->enslave_slave) { + g_clear_object (&priv->master); + priv->master = g_object_ref (master); + nm_device_master_add_slave (master, device, FALSE); + nm_device_enslave_slave (master, device, NULL); + } else if (master) { + nm_log_info (LOGD_DEVICE, "(%s): enslaved to non-master-type device %s; ignoring", + nm_device_get_iface (device), + nm_device_get_iface (master)); + } else { + nm_log_warn (LOGD_DEVICE, "(%s): enslaved to unknown device %d %s", + nm_device_get_iface (device), + info->master, + nm_platform_link_get_name (info->master)); + } + } else if (priv->enslaved && !info->master) + nm_device_release_one_slave (priv->master, device, FALSE, NM_DEVICE_STATE_REASON_NONE); + + if (klass->link_changed) + klass->link_changed (device, info); + + + /* Update DHCP, etc, if needed */ + if (ip_ifname_changed) + update_for_ip_ifname_change (device); +} + +static void +device_ip_link_changed (NMDevice *device, NMPlatformLink *info) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); + + if (info->name[0] && g_strcmp0 (priv->ip_iface, info->name)) { + nm_log_info (LOGD_DEVICE, "(%s): interface index %d renamed ip_iface (%d) from '%s' to '%s'", + priv->iface, priv->ifindex, nm_device_get_ip_ifindex (device), + priv->ip_iface, info->name); + g_free (priv->ip_iface); + priv->ip_iface = g_strdup (info->name); + + g_object_notify (G_OBJECT (device), NM_DEVICE_IP_IFACE); + update_for_ip_ifname_change (device); + } +} + +static void +link_changed_cb (NMPlatform *platform, int ifindex, NMPlatformLink *info, NMPlatformSignalChangeType change_type, NMPlatformReason reason, NMDevice *device) +{ + if (change_type != NM_PLATFORM_SIGNAL_CHANGED) + return; + + /* We don't filter by 'reason' because we are interested in *all* link + * changes. For example a call to nm_platform_link_set_up() may result + * in an internal carrier change (i.e. we ask the kernel to set IFF_UP + * and it results in also setting IFF_LOWER_UP. + */ + + if (ifindex == nm_device_get_ifindex (device)) + device_link_changed (device, info); + else if (ifindex == nm_device_get_ip_ifindex (device)) + device_ip_link_changed (device, info); +} + +static void +link_changed (NMDevice *device, NMPlatformLink *info) +{ + /* Update carrier from link event if applicable. */ + if ( device_has_capability (device, NM_DEVICE_CAP_CARRIER_DETECT) + && !device_has_capability (device, NM_DEVICE_CAP_NONSTANDARD_CARRIER)) + nm_device_set_carrier (device, info->connected); +} + +/** + * nm_device_notify_component_added(): + * @device: the #NMDevice + * @component: the component being added by a plugin + * + * Called by the manager to notify the device that a new component has + * been found. The device implementation should return %TRUE if it + * wishes to claim the component, or %FALSE if it cannot. + * + * Returns: %TRUE to claim the component, %FALSE if the component cannot be + * claimed. + */ +gboolean +nm_device_notify_component_added (NMDevice *device, GObject *component) +{ + if (NM_DEVICE_GET_CLASS (device)->component_added) + return NM_DEVICE_GET_CLASS (device)->component_added (device, component); + return FALSE; +} + +/** + * nm_device_owns_iface(): + * @device: the #NMDevice + * @iface: an interface name + * + * Called by the manager to ask if the device or any of its components owns + * @iface. For example, a WWAN implementation would return %TRUE for an + * ethernet interface name that was owned by the WWAN device's modem component, + * because that ethernet interface is controlled by the WWAN device and cannot + * be used independently of the WWAN device. + * + * Returns: %TRUE if @device or it's components owns the interface name, + * %FALSE if not + */ +gboolean +nm_device_owns_iface (NMDevice *device, const char *iface) +{ + if (NM_DEVICE_GET_CLASS (device)->owns_iface) + return NM_DEVICE_GET_CLASS (device)->owns_iface (device, iface); + return FALSE; +} + +static void +slave_state_changed (NMDevice *slave, + NMDeviceState slave_new_state, + NMDeviceState slave_old_state, + NMDeviceStateReason reason, + NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + gboolean release = FALSE; + + nm_log_dbg (LOGD_DEVICE, "(%s): slave %s state change %d (%s) -> %d (%s)", + nm_device_get_iface (self), + nm_device_get_iface (slave), + slave_old_state, + state_to_string (slave_old_state), + slave_new_state, + state_to_string (slave_new_state)); + + /* Don't try to enslave slaves until the master is ready */ + if (priv->state < NM_DEVICE_STATE_CONFIG) + return; + + if (slave_new_state == NM_DEVICE_STATE_IP_CONFIG) + nm_device_enslave_slave (self, slave, nm_device_get_connection (slave)); + else if (slave_new_state > NM_DEVICE_STATE_ACTIVATED) + release = TRUE; + else if ( slave_new_state <= NM_DEVICE_STATE_DISCONNECTED + && slave_old_state > NM_DEVICE_STATE_DISCONNECTED) { + /* Catch failures due to unavailable or unmanaged */ + release = TRUE; + } + + if (release) { + nm_device_release_one_slave (self, slave, TRUE, reason); + /* Bridge/bond/team interfaces are left up until manually deactivated */ + if (priv->slaves == NULL && priv->state == NM_DEVICE_STATE_ACTIVATED) { + nm_log_dbg (LOGD_DEVICE, "(%s): last slave removed; remaining activated", + nm_device_get_iface (self)); + } + } +} + +/** + * nm_device_master_add_slave: + * @dev: the master device + * @slave: the slave device to enslave + * @configure: pass %TRUE if the slave should be configured by the master, or + * %FALSE if it is already configured outside NetworkManager + * + * If @dev is capable of enslaving other devices (ie it's a bridge, bond, team, + * etc) then this function adds @slave to the slave list for later enslavement. + * + * Returns: %TRUE on success, %FALSE on failure + */ +static gboolean +nm_device_master_add_slave (NMDevice *dev, NMDevice *slave, gboolean configure) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (dev); + SlaveInfo *info; + + g_return_val_if_fail (dev != NULL, FALSE); + g_return_val_if_fail (slave != NULL, FALSE); + g_return_val_if_fail (NM_DEVICE_GET_CLASS (dev)->enslave_slave != NULL, FALSE); + + if (configure) + g_return_val_if_fail (nm_device_get_state (slave) >= NM_DEVICE_STATE_DISCONNECTED, FALSE); + + if (!find_slave_info (dev, slave)) { + info = g_malloc0 (sizeof (SlaveInfo)); + info->slave = g_object_ref (slave); + info->configure = configure; + info->watch_id = g_signal_connect (slave, "state-changed", + G_CALLBACK (slave_state_changed), dev); + priv->slaves = g_slist_append (priv->slaves, info); + } + + return TRUE; +} + + +/** + * nm_device_master_get_slaves: + * @dev: the master device + * + * Returns: any slaves of which @device is the master. Caller owns returned list. + */ +GSList * +nm_device_master_get_slaves (NMDevice *dev) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (dev); + GSList *slaves = NULL, *iter; + + for (iter = priv->slaves; iter; iter = g_slist_next (iter)) + slaves = g_slist_prepend (slaves, ((SlaveInfo *) iter->data)->slave); + + return slaves; +} + +/** + * nm_device_master_get_slave_by_ifindex: + * @dev: the master device + * @ifindex: the slave's interface index + * + * Returns: the slave with the given @ifindex of which @device is the master, + * or %NULL if no device with @ifindex is a slave of @device. + */ +NMDevice * +nm_device_master_get_slave_by_ifindex (NMDevice *dev, int ifindex) +{ + GSList *iter; + + for (iter = NM_DEVICE_GET_PRIVATE (dev)->slaves; iter; iter = g_slist_next (iter)) { + SlaveInfo *info = iter->data; + + if (nm_device_get_ip_ifindex (info->slave) == ifindex) + return info->slave; + } + return NULL; +} + +/** + * nm_device_master_check_slave_physical_port: + * @dev: the master device + * @slave: a slave device + * @log_domain: domain to log a warning in + * + * Checks if @dev already has a slave with the same #NMDevice:physical-port-id + * as @slave, and logs a warning if so. + */ +void +nm_device_master_check_slave_physical_port (NMDevice *dev, NMDevice *slave, + guint64 log_domain) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (dev); + const char *slave_physical_port_id, *existing_physical_port_id; + SlaveInfo *info; + GSList *iter; + + slave_physical_port_id = nm_device_get_physical_port_id (slave); + if (!slave_physical_port_id) + return; + + for (iter = priv->slaves; iter; iter = iter->next) { + info = iter->data; + if (info->slave == slave) + continue; + + existing_physical_port_id = nm_device_get_physical_port_id (info->slave); + if (!g_strcmp0 (slave_physical_port_id, existing_physical_port_id)) { + nm_log_warn (log_domain, "(%s): slave %s shares a physical port with existing slave %s", + nm_device_get_ip_iface (dev), + nm_device_get_ip_iface (slave), + nm_device_get_ip_iface (info->slave)); + /* Since this function will get called for every slave, we only have + * to warn about the first match we find; if there are other matches + * later in the list, we will have already warned about them matching + * @existing earlier. + */ + return; + } + } +} + +/* release all slaves */ +static void +nm_device_master_release_slaves (NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMDeviceStateReason reason; + + /* Don't release the slaves if this connection doesn't belong to NM. */ + if (nm_device_uses_generated_connection (self)) + return; + + reason = priv->state_reason; + if (priv->state == NM_DEVICE_STATE_FAILED) + reason = NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED; + + while (priv->slaves) { + SlaveInfo *info = priv->slaves->data; + + nm_device_release_one_slave (self, info->slave, TRUE, reason); + } +} + +/** + * nm_device_get_master: + * @dev: the device + * + * If @dev has been enslaved by another device, this returns that + * device. Otherwise it returns %NULL. (In particular, note that if + * @dev is in the process of activating as a slave, but has not yet + * been enslaved by its master, this will return %NULL.) + * + * Returns: (transfer none): @dev's master, or %NULL + */ +NMDevice * +nm_device_get_master (NMDevice *dev) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (dev); + + if (priv->enslaved) + return priv->master; + else + return NULL; +} + +/** + * nm_device_slave_notify_enslave: + * @dev: the slave device + * @success: whether the enslaving operation succeeded + * + * Notifies a slave that either it has been enslaved, or else its master tried + * to enslave it and failed. + */ +static void +nm_device_slave_notify_enslave (NMDevice *dev, gboolean success) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (dev); + NMConnection *connection = nm_device_get_connection (dev); + gboolean activating = (priv->state == NM_DEVICE_STATE_IP_CONFIG); + + g_assert (priv->master); + + if (!priv->enslaved) { + if (success) { + if (activating) { + nm_log_info (LOGD_DEVICE, + "Activation (%s) connection '%s' enslaved, continuing activation", + nm_device_get_iface (dev), + nm_connection_get_id (connection)); + } else { + nm_log_info (LOGD_DEVICE, + "(%s): enslaved to %s", + nm_device_get_iface (dev), + nm_device_get_iface (priv->master)); + } + + priv->enslaved = TRUE; + g_object_notify (G_OBJECT (dev), NM_DEVICE_MASTER); + } else if (activating) { + nm_log_warn (LOGD_DEVICE, + "Activation (%s) connection '%s' could not be enslaved", + nm_device_get_iface (dev), + nm_connection_get_id (connection)); + } + } + + if (activating) { + priv->ip4_state = IP_DONE; + priv->ip6_state = IP_DONE; + nm_device_queue_state (dev, + success ? NM_DEVICE_STATE_SECONDARIES : NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_NONE); + } else + nm_device_queue_recheck_assume (dev); +} + +/** + * nm_device_slave_notify_release: + * @dev: the slave device + * @reason: the reason associated with the state change + * + * Notifies a slave that it has been released, and why. + */ +static void +nm_device_slave_notify_release (NMDevice *dev, NMDeviceStateReason reason) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (dev); + NMConnection *connection = nm_device_get_connection (dev); + NMDeviceState new_state; + const char *master_status; + + if ( reason != NM_DEVICE_STATE_REASON_NONE + && priv->state > NM_DEVICE_STATE_DISCONNECTED + && priv->state <= NM_DEVICE_STATE_ACTIVATED) { + if (reason == NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED) { + new_state = NM_DEVICE_STATE_FAILED; + master_status = "failed"; + } else if (reason == NM_DEVICE_STATE_REASON_USER_REQUESTED) { + new_state = NM_DEVICE_STATE_DEACTIVATING; + master_status = "deactivated by user request"; + } else { + new_state = NM_DEVICE_STATE_DISCONNECTED; + master_status = "deactivated"; + } + + nm_log_dbg (LOGD_DEVICE, + "Activation (%s) connection '%s' master %s", + nm_device_get_iface (dev), + nm_connection_get_id (connection), + master_status); + + nm_device_queue_state (dev, new_state, reason); + } else { + nm_log_info (LOGD_DEVICE, + "(%s): released from master %s", + nm_device_get_iface (dev), + nm_device_get_iface (priv->master)); + } + + if (priv->enslaved) { + priv->enslaved = FALSE; + g_object_notify (G_OBJECT (dev), NM_DEVICE_MASTER); + } +} + +/** + * nm_device_get_enslaved: + * @device: the #NMDevice + * + * Returns: %TRUE if the device is enslaved to a master device (eg bridge or + * bond or team), %FALSE if not + */ +gboolean +nm_device_get_enslaved (NMDevice *device) +{ + return NM_DEVICE_GET_PRIVATE (device)->enslaved; +} + +static gboolean +is_available (NMDevice *device) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); + + return priv->carrier || priv->ignore_carrier; +} + +/** + * nm_device_is_available: + * @self: the #NMDevice + * + * Checks if @self would currently be capable of activating a + * connection. In particular, it checks that the device is ready (eg, + * is not missing firmware), that it has carrier (if necessary), and + * that any necessary external software (eg, ModemManager, + * wpa_supplicant) is available. + * + * @self can only be in a state higher than + * %NM_DEVICE_STATE_UNAVAILABLE when nm_device_is_available() returns + * %TRUE. (But note that it can still be %NM_DEVICE_STATE_UNMANAGED + * when it is available.) + * + * Returns: %TRUE or %FALSE + */ +gboolean +nm_device_is_available (NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + + if (priv->firmware_missing) + return FALSE; + + return NM_DEVICE_GET_CLASS (self)->is_available (self); +} + +gboolean +nm_device_get_enabled (NMDevice *self) +{ + g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); + + if (NM_DEVICE_GET_CLASS (self)->get_enabled) + return NM_DEVICE_GET_CLASS (self)->get_enabled (self); + return TRUE; +} + +void +nm_device_set_enabled (NMDevice *self, gboolean enabled) +{ + g_return_if_fail (NM_IS_DEVICE (self)); + + if (NM_DEVICE_GET_CLASS (self)->set_enabled) + NM_DEVICE_GET_CLASS (self)->set_enabled (self, enabled); +} + +gboolean +nm_device_get_autoconnect (NMDevice *device) +{ + g_return_val_if_fail (NM_IS_DEVICE (device), FALSE); + + return NM_DEVICE_GET_PRIVATE (device)->autoconnect; +} + +static gboolean +autoconnect_allowed_accumulator (GSignalInvocationHint *ihint, + GValue *return_accu, + const GValue *handler_return, gpointer data) +{ + if (!g_value_get_boolean (handler_return)) + g_value_set_boolean (return_accu, FALSE); + return TRUE; +} + +gboolean +nm_device_autoconnect_allowed (NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + GValue instance = G_VALUE_INIT; + GValue retval = G_VALUE_INIT; + + g_value_init (&instance, G_TYPE_OBJECT); + g_value_set_object (&instance, self); + + g_value_init (&retval, G_TYPE_BOOLEAN); + if (priv->autoconnect) + g_value_set_boolean (&retval, TRUE); + else + g_value_set_boolean (&retval, FALSE); + + /* Use g_signal_emitv() rather than g_signal_emit() to avoid the return + * value being changed if no handlers are connected */ + g_signal_emitv (&instance, signals[AUTOCONNECT_ALLOWED], 0, &retval); + g_value_unset (&instance); + return g_value_get_boolean (&retval); +} + +static gboolean +can_auto_connect (NMDevice *device, + NMConnection *connection, + char **specific_object) +{ + NMSettingConnection *s_con; + + s_con = nm_connection_get_setting_connection (connection); + if (!nm_setting_connection_get_autoconnect (s_con)) + return FALSE; + + return nm_device_connection_is_available (device, connection, FALSE); +} + +static gboolean +device_has_config (NMDevice *device) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); + + /* Check for IP configuration. */ + if (priv->ip4_config && nm_ip4_config_get_num_addresses (priv->ip4_config)) + return TRUE; + if (priv->ip6_config && nm_ip6_config_get_num_addresses (priv->ip6_config)) + return TRUE; + + /* The existence of a software device is good enough. */ + if (nm_device_is_software (device)) + return TRUE; + + /* Slaves are also configured by definition */ + if (nm_platform_link_get_master (priv->ifindex) > 0) + return TRUE; + + return FALSE; +} + +NMConnection * +nm_device_generate_connection (NMDevice *device) +{ + NMDeviceClass *klass = NM_DEVICE_GET_CLASS (device); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); + const char *ifname = nm_device_get_iface (device); + int ifindex = nm_device_get_ifindex (device); + NMConnection *connection; + NMSetting *s_con; + NMSetting *s_ip4; + NMSetting *s_ip6; + gs_free char *uuid = NULL; + gs_free char *name = NULL; + int master_ifindex = 0; + const char *ip4_method, *ip6_method; + GError *error = NULL; + + /* If update_connection() is not implemented, just fail. */ + if (!klass->update_connection) + return NULL; + + /* Return NULL if device is unconfigured. */ + if (!device_has_config (device)) { + nm_log_dbg (LOGD_DEVICE, "(%s): device has no existing configuration", ifname); + return NULL; + } + + if (ifindex) + master_ifindex = nm_platform_link_get_master (ifindex); + if (master_ifindex) { + NMDevice *master; + + master = nm_manager_get_device_by_ifindex (nm_manager_get (), master_ifindex); + if (!master || !nm_device_get_act_request (master)) { + nm_log_dbg (LOGD_DEVICE, "(%s): cannot generate connection for slave before its master (%s)", + ifname, nm_platform_link_get_name (master_ifindex)); + return NULL; + } + } + + connection = nm_connection_new (); + s_con = nm_setting_connection_new (); + uuid = nm_utils_uuid_generate (); + name = g_strdup_printf ("%s", ifname); + + g_object_set (s_con, + NM_SETTING_CONNECTION_UUID, uuid, + NM_SETTING_CONNECTION_ID, name, + NM_SETTING_CONNECTION_AUTOCONNECT, FALSE, + NM_SETTING_CONNECTION_INTERFACE_NAME, ifname, + NM_SETTING_CONNECTION_TIMESTAMP, (guint64) time (NULL), + NULL); + if (klass->connection_type) + g_object_set (s_con, NM_SETTING_CONNECTION_TYPE, klass->connection_type, NULL); + nm_connection_add_setting (connection, s_con); + + /* If the device is a slave, update various slave settings */ + if (master_ifindex) { + const char *master_iface = nm_platform_link_get_name (master_ifindex); + const char *slave_type = NULL; + gboolean success = FALSE; + + switch (nm_platform_link_get_type (master_ifindex)) { + case NM_LINK_TYPE_BRIDGE: + slave_type = NM_SETTING_BRIDGE_SETTING_NAME; + success = nm_bridge_update_slave_connection (device, connection); + break; + case NM_LINK_TYPE_BOND: + slave_type = NM_SETTING_BOND_SETTING_NAME; + success = TRUE; + break; + case NM_LINK_TYPE_TEAM: + slave_type = NM_SETTING_TEAM_SETTING_NAME; + success = nm_team_update_slave_connection (device, connection); + break; + default: + g_warn_if_reached (); + break; + } + + if (!success) + nm_log_err (LOGD_DEVICE, "(%s): failed to read slave configuration", ifname); + + g_object_set (s_con, + NM_SETTING_CONNECTION_MASTER, master_iface, + NM_SETTING_CONNECTION_SLAVE_TYPE, slave_type, + NULL); + } else { + /* Only regular and master devices get IP configuration; slaves do not */ + s_ip4 = nm_ip4_config_create_setting (priv->ip4_config); + nm_connection_add_setting (connection, s_ip4); + + s_ip6 = nm_ip6_config_create_setting (priv->ip6_config); + nm_connection_add_setting (connection, s_ip6); + } + + klass->update_connection (device, connection); + + /* Check the connection in case of update_connection() bug. */ + if (!nm_connection_verify (connection, &error)) { + nm_log_err (LOGD_DEVICE, "(%s): Generated connection does not verify: %s", + nm_device_get_iface (device), error->message); + g_clear_error (&error); + g_object_unref (connection); + return NULL; + } + + /* Ignore the connection if it has no IP configuration, + * no slave configuration, and is not a master interface. + */ + ip4_method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP4_CONFIG); + ip6_method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP6_CONFIG); + if ( g_strcmp0 (ip4_method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED) == 0 + && g_strcmp0 (ip6_method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE) == 0 + && !nm_setting_connection_get_master (NM_SETTING_CONNECTION (s_con))) { + nm_log_dbg (LOGD_DEVICE, "(%s): ignoring generated connection (no IP and not slave)", ifname); + g_object_unref (connection); + connection = NULL; + } + + return connection; +} + +/** + * nm_device_get_best_auto_connection: + * @dev: an #NMDevice + * @connections: (element-type #NMConnection): a list of connections + * @specific_object: (out) (transfer full): on output, the path of an + * object associated with the returned connection, to be passed to + * nm_manager_activate_connection(), or %NULL. + * + * Looks through @connections to see if there is a connection that can + * be auto-activated on @dev right now. This requires, at a minimum, + * that the connection be compatible with @dev, and that it have the + * #NMSettingConnection:autoconnect property set. Some devices impose + * additional requirements. (Eg, a Wi-Fi connection can only be + * activated if its SSID was seen in the last scan.) + * + * Returns: an auto-activatable #NMConnection, or %NULL if none are + * available. + */ + +NMConnection * +nm_device_get_best_auto_connection (NMDevice *dev, + GSList *connections, + char **specific_object) +{ + GSList *iter; + + g_return_val_if_fail (NM_IS_DEVICE (dev), NULL); + g_return_val_if_fail (specific_object != NULL, NULL); + g_return_val_if_fail (*specific_object == NULL, NULL); + + for (iter = connections; iter; iter = iter->next) { + NMConnection *connection = NM_CONNECTION (iter->data); + + if (NM_DEVICE_GET_CLASS (dev)->can_auto_connect (dev, connection, specific_object)) + return connection; + } + + return NULL; +} + +gboolean +nm_device_complete_connection (NMDevice *self, + NMConnection *connection, + const char *specific_object, + const GSList *existing_connections, + GError **error) +{ + gboolean success = FALSE; + + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (connection != NULL, FALSE); + + if (!NM_DEVICE_GET_CLASS (self)->complete_connection) { + g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CONNECTION_INVALID, + "Device class %s had no complete_connection method", + G_OBJECT_TYPE_NAME (self)); + return FALSE; + } + + success = NM_DEVICE_GET_CLASS (self)->complete_connection (self, + connection, + specific_object, + existing_connections, + error); + if (success) + success = nm_connection_verify (connection, error); + + return success; +} + +static gboolean +check_connection_compatible (NMDevice *device, NMConnection *connection) +{ + NMSettingConnection *s_con; + const char *config_iface, *device_iface; + + s_con = nm_connection_get_setting_connection (connection); + g_assert (s_con); + + config_iface = nm_setting_connection_get_interface_name (s_con); + device_iface = nm_device_get_iface (device); + if (config_iface && strcmp (config_iface, device_iface) != 0) + return FALSE; + + return TRUE; +} + +/** + * nm_device_check_connection_compatible: + * @device: an #NMDevice + * @connection: an #NMConnection + * + * Checks if @connection could potentially be activated on @device. + * This means only that @device has the proper capabilities, and that + * @connection is not locked to some other device. It does not + * necessarily mean that @connection could be activated on @device + * right now. (Eg, it might refer to a Wi-Fi network that is not + * currently available.) + * + * Returns: #TRUE if @connection could potentially be activated on + * @device. + */ +gboolean +nm_device_check_connection_compatible (NMDevice *device, NMConnection *connection) +{ + g_return_val_if_fail (NM_IS_DEVICE (device), FALSE); + g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE); + + return NM_DEVICE_GET_CLASS (device)->check_connection_compatible (device, connection); +} + +static gboolean +string_in_list (const char *str, const char **array, gsize array_len) +{ + gsize i; + + for (i = 0; i < array_len; i++) { + if (strcmp (str, array[i]) == 0) + return TRUE; + } + return FALSE; +} + +/** + * nm_device_can_assume_connections: + * @device: #NMDevice instance + * + * This is a convenience function to determine whether connection assumption + * is available for this device. + * + * Returns: %TRUE if the device is capable of assuming connections, %FALSE if not + */ +static gboolean +nm_device_can_assume_connections (NMDevice *device) +{ + return !!NM_DEVICE_GET_CLASS (device)->update_connection; +} + +/** + * nm_device_can_assume_active_connection: + * @device: #NMDevice instance + * + * This is a convenience function to determine whether the device's active + * connection can be assumed if NetworkManager restarts. This method returns + * %TRUE if and only if the device can assume connections, and the device has + * an active connection, and that active connection can be assumed. + * + * Returns: %TRUE if the device's active connection can be assumed, or %FALSE + * if there is no active connection or the active connection cannot be + * assumed. + */ +gboolean +nm_device_can_assume_active_connection (NMDevice *device) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); + NMConnection *connection; + const char *method; + const char *assumable_ip6_methods[] = { + NM_SETTING_IP6_CONFIG_METHOD_IGNORE, + NM_SETTING_IP6_CONFIG_METHOD_AUTO, + NM_SETTING_IP6_CONFIG_METHOD_DHCP, + NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL, + NM_SETTING_IP6_CONFIG_METHOD_MANUAL, + }; + const char *assumable_ip4_methods[] = { + NM_SETTING_IP4_CONFIG_METHOD_DISABLED, + NM_SETTING_IP6_CONFIG_METHOD_AUTO, + NM_SETTING_IP6_CONFIG_METHOD_MANUAL, + }; + + if (!nm_device_can_assume_connections (device)) + return FALSE; + + connection = nm_device_get_connection (device); + if (!connection) + return FALSE; + + /* Can't assume connections that aren't yet configured + * FIXME: what about bridges/bonds waiting for slaves? + */ + if (priv->state < NM_DEVICE_STATE_IP_CONFIG) + return FALSE; + if (priv->ip4_state != IP_DONE && priv->ip6_state != IP_DONE) + return FALSE; + + method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP6_CONFIG); + if (!string_in_list (method, assumable_ip6_methods, G_N_ELEMENTS (assumable_ip6_methods))) + return FALSE; + + method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP4_CONFIG); + if (!string_in_list (method, assumable_ip4_methods, G_N_ELEMENTS (assumable_ip4_methods))) + return FALSE; + + return TRUE; +} + +static gboolean +nm_device_emit_recheck_assume (gpointer self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + + priv->recheck_assume_id = 0; + if (!nm_device_get_act_request (self) && (priv->ip4_config || priv->ip6_config)) + g_signal_emit (self, signals[RECHECK_ASSUME], 0); + return G_SOURCE_REMOVE; +} + +void +nm_device_queue_recheck_assume (NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + + if (nm_device_can_assume_connections (self) && !priv->recheck_assume_id) + priv->recheck_assume_id = g_idle_add (nm_device_emit_recheck_assume, self); +} + +void +nm_device_emit_recheck_auto_activate (NMDevice *self) +{ + g_signal_emit (self, signals[RECHECK_AUTO_ACTIVATE], 0); +} + +static void +dnsmasq_state_changed_cb (NMDnsMasqManager *manager, guint32 status, gpointer user_data) +{ + NMDevice *self = NM_DEVICE (user_data); + + switch (status) { + case NM_DNSMASQ_STATUS_DEAD: + nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_SHARED_START_FAILED); + break; + default: + break; + } +} + +static void +activation_source_clear (NMDevice *self, gboolean remove_source, int family) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + guint *act_source_id; + gpointer *act_source_func; + + if (family == AF_INET6) { + act_source_id = &priv->act_source6_id; + act_source_func = &priv->act_source6_func; + } else { + act_source_id = &priv->act_source_id; + act_source_func = &priv->act_source_func; + } + + if (*act_source_id) { + if (remove_source) + g_source_remove (*act_source_id); + *act_source_id = 0; + *act_source_func = NULL; + } +} + +static void +activation_source_schedule (NMDevice *self, GSourceFunc func, int family) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + guint *act_source_id; + gpointer *act_source_func; + + if (family == AF_INET6) { + act_source_id = &priv->act_source6_id; + act_source_func = &priv->act_source6_func; + } else { + act_source_id = &priv->act_source_id; + act_source_func = &priv->act_source_func; + } + + if (*act_source_id) { + nm_log_err (LOGD_DEVICE, "activation stage already scheduled"); + } + + /* Don't bother rescheduling the same function that's about to + * run anyway. Fixes issues with crappy wireless drivers sending + * streams of associate events before NM has had a chance to process + * the first one. + */ + if (!*act_source_id || (*act_source_func != func)) { + activation_source_clear (self, TRUE, family); + *act_source_id = g_idle_add (func, self); + *act_source_func = func; + } +} + +gboolean +nm_device_ip_config_should_fail (NMDevice *self, gboolean ip6) +{ + NMConnection *connection; + NMSettingIP4Config *s_ip4; + NMSettingIP6Config *s_ip6; + + g_return_val_if_fail (self != NULL, TRUE); + + connection = nm_device_get_connection (self); + g_assert (connection); + + /* Fail the connection if the failed IP method is required to complete */ + if (ip6) { + s_ip6 = nm_connection_get_setting_ip6_config (connection); + if (!nm_setting_ip6_config_get_may_fail (s_ip6)) + return TRUE; + } else { + s_ip4 = nm_connection_get_setting_ip4_config (connection); + if (!nm_setting_ip4_config_get_may_fail (s_ip4)) + return TRUE; + } + + return FALSE; +} + +static void +master_ready_cb (NMActiveConnection *active, + GParamSpec *pspec, + NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMActiveConnection *master; + + g_assert (priv->state == NM_DEVICE_STATE_PREPARE); + + /* Notify a master device that it has a new slave */ + g_assert (nm_active_connection_get_master_ready (active)); + master = nm_active_connection_get_master (active); + + priv->master = g_object_ref (nm_active_connection_get_device (master)); + nm_device_master_add_slave (priv->master, + self, + nm_active_connection_get_assumed (active) ? FALSE : TRUE); + + nm_log_dbg (LOGD_DEVICE, "(%s): master connection ready; master device %s", + nm_device_get_iface (self), + nm_device_get_iface (priv->master)); + + if (priv->master_ready_id) { + g_signal_handler_disconnect (active, priv->master_ready_id); + priv->master_ready_id = 0; + } + + nm_device_activate_schedule_stage2_device_config (self); +} + +static NMActStageReturn +act_stage1_prepare (NMDevice *self, NMDeviceStateReason *reason) +{ + return NM_ACT_STAGE_RETURN_SUCCESS; +} + +/* + * nm_device_activate_stage1_device_prepare + * + * Prepare for device activation + * + */ +static gboolean +nm_device_activate_stage1_device_prepare (gpointer user_data) +{ + NMDevice *self = NM_DEVICE (user_data); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + const char *iface; + NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS; + NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; + NMActiveConnection *active = NM_ACTIVE_CONNECTION (priv->act_request); + + /* Clear the activation source ID now that this stage has run */ + activation_source_clear (self, FALSE, 0); + + priv->ip4_state = priv->ip6_state = IP_NONE; + + /* Notify the new ActiveConnection along with the state change */ + g_object_notify (G_OBJECT (self), NM_DEVICE_ACTIVE_CONNECTION); + + iface = nm_device_get_iface (self); + nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 1 of 5 (Device Prepare) started...", iface); + nm_device_state_changed (self, NM_DEVICE_STATE_PREPARE, NM_DEVICE_STATE_REASON_NONE); + + /* Assumed connections were already set up outside NetworkManager */ + if (!nm_active_connection_get_assumed (active)) { + ret = NM_DEVICE_GET_CLASS (self)->act_stage1_prepare (self, &reason); + if (ret == NM_ACT_STAGE_RETURN_POSTPONE) { + goto out; + } else if (ret == NM_ACT_STAGE_RETURN_FAILURE) { + nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); + goto out; + } + g_assert (ret == NM_ACT_STAGE_RETURN_SUCCESS); + } + + if (nm_active_connection_get_master (active)) { + /* If the master connection is ready for slaves, attach ourselves */ + if (nm_active_connection_get_master_ready (active)) + master_ready_cb (active, NULL, self); + else { + nm_log_dbg (LOGD_DEVICE, "(%s): waiting for master connection to become ready", + nm_device_get_iface (self)); + + /* Attach a signal handler and wait for the master connection to begin activating */ + g_assert (priv->master_ready_id == 0); + priv->master_ready_id = g_signal_connect (active, + "notify::" NM_ACTIVE_CONNECTION_INT_MASTER_READY, + (GCallback) master_ready_cb, + self); + /* Postpone */ + } + } else + nm_device_activate_schedule_stage2_device_config (self); + +out: + nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 1 of 5 (Device Prepare) complete.", iface); + return FALSE; +} + + +/* + * nm_device_activate_schedule_stage1_device_prepare + * + * Prepare a device for activation + * + */ +void +nm_device_activate_schedule_stage1_device_prepare (NMDevice *self) +{ + NMDevicePrivate *priv; + + g_return_if_fail (NM_IS_DEVICE (self)); + + priv = NM_DEVICE_GET_PRIVATE (self); + g_return_if_fail (priv->act_request); + + activation_source_schedule (self, nm_device_activate_stage1_device_prepare, 0); + + nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 1 of 5 (Device Prepare) scheduled...", + nm_device_get_iface (self)); +} + +static NMActStageReturn +act_stage2_config (NMDevice *dev, NMDeviceStateReason *reason) +{ + /* Nothing to do */ + return NM_ACT_STAGE_RETURN_SUCCESS; +} + +/* + * nm_device_activate_stage2_device_config + * + * Determine device parameters and set those on the device, ie + * for wireless devices, set SSID, keys, etc. + * + */ +static gboolean +nm_device_activate_stage2_device_config (gpointer user_data) +{ + NMDevice *self = NM_DEVICE (user_data); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + const char *iface; + NMActStageReturn ret; + NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; + gboolean no_firmware = FALSE; + NMActiveConnection *active = NM_ACTIVE_CONNECTION (priv->act_request); + GSList *iter; + + /* Clear the activation source ID now that this stage has run */ + activation_source_clear (self, FALSE, 0); + + iface = nm_device_get_iface (self); + nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 2 of 5 (Device Configure) starting...", iface); + nm_device_state_changed (self, NM_DEVICE_STATE_CONFIG, NM_DEVICE_STATE_REASON_NONE); + + /* Assumed connections were already set up outside NetworkManager */ + if (!nm_active_connection_get_assumed (active)) { + if (!nm_device_bring_up (self, FALSE, &no_firmware)) { + if (no_firmware) + nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_FIRMWARE_MISSING); + else + nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_CONFIG_FAILED); + goto out; + } + + ret = NM_DEVICE_GET_CLASS (self)->act_stage2_config (self, &reason); + if (ret == NM_ACT_STAGE_RETURN_POSTPONE) + goto out; + else if (ret == NM_ACT_STAGE_RETURN_FAILURE) { + nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); + goto out; + } + g_assert (ret == NM_ACT_STAGE_RETURN_SUCCESS); + } + + /* If we have slaves that aren't yet enslaved, do that now */ + for (iter = priv->slaves; iter; iter = g_slist_next (iter)) { + SlaveInfo *info = iter->data; + NMDeviceState slave_state = nm_device_get_state (info->slave); + + if (slave_state == NM_DEVICE_STATE_IP_CONFIG) + nm_device_enslave_slave (self, info->slave, nm_device_get_connection (info->slave)); + else if ( nm_device_uses_generated_connection (self) + && slave_state <= NM_DEVICE_STATE_DISCONNECTED) + nm_device_queue_recheck_assume (info->slave); + } + + nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 2 of 5 (Device Configure) successful.", iface); + + nm_device_activate_schedule_stage3_ip_config_start (self); + +out: + nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 2 of 5 (Device Configure) complete.", iface); + return FALSE; +} + + +/* + * nm_device_activate_schedule_stage2_device_config + * + * Schedule setup of the hardware device + * + */ +void +nm_device_activate_schedule_stage2_device_config (NMDevice *self) +{ + NMDevicePrivate *priv; + + g_return_if_fail (NM_IS_DEVICE (self)); + + priv = NM_DEVICE_GET_PRIVATE (self); + g_return_if_fail (priv->act_request); + + activation_source_schedule (self, nm_device_activate_stage2_device_config, 0); + + nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 2 of 5 (Device Configure) scheduled...", + nm_device_get_iface (self)); +} + +/*********************************************/ +/* avahi-autoipd stuff */ + +static void +aipd_timeout_remove (NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + + if (priv->aipd_timeout) { + g_source_remove (priv->aipd_timeout); + priv->aipd_timeout = 0; + } +} + +static void +aipd_cleanup (NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + + if (priv->aipd_watch) { + g_source_remove (priv->aipd_watch); + priv->aipd_watch = 0; + } + + if (priv->aipd_pid > 0) { + kill (priv->aipd_pid, SIGKILL); + + /* ensure the child is reaped */ + nm_log_dbg (LOGD_AUTOIP4, "waiting for avahi-autoipd pid %d to exit", priv->aipd_pid); + waitpid (priv->aipd_pid, NULL, 0); + nm_log_dbg (LOGD_AUTOIP4, "avahi-autoip pid %d cleaned up", priv->aipd_pid); + + priv->aipd_pid = -1; + } + + aipd_timeout_remove (self); +} + +static NMIP4Config * +aipd_get_ip4_config (NMDevice *self, guint32 lla) +{ + NMIP4Config *config = NULL; + NMPlatformIP4Address address; + NMPlatformIP4Route route; + + config = nm_ip4_config_new (); + g_assert (config); + + memset (&address, 0, sizeof (address)); + address.address = lla; + address.plen = 16; + address.source = NM_PLATFORM_SOURCE_IP4LL; + nm_ip4_config_add_address (config, &address); + + /* Add a multicast route for link-local connections: destination= 224.0.0.0, netmask=240.0.0.0 */ + memset (&route, 0, sizeof (route)); + route.network = htonl (0xE0000000L); + route.plen = 4; + route.source = NM_PLATFORM_SOURCE_IP4LL; + route.metric = nm_device_get_priority (self); + nm_ip4_config_add_route (config, &route); + + return config; +} + +#define IPV4LL_NETWORK (htonl (0xA9FE0000L)) +#define IPV4LL_NETMASK (htonl (0xFFFF0000L)) + +void +nm_device_handle_autoip4_event (NMDevice *self, + const char *event, + const char *address) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMConnection *connection = NULL; + const char *iface, *method; + NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; + + g_return_if_fail (event != NULL); + + if (priv->act_request == NULL) + return; + + connection = nm_act_request_get_connection (priv->act_request); + g_assert (connection); + + /* Ignore if the connection isn't an AutoIP connection */ + method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP4_CONFIG); + if (g_strcmp0 (method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL) != 0) + return; + + iface = nm_device_get_iface (self); + + if (strcmp (event, "BIND") == 0) { + guint32 lla; + NMIP4Config *config; + + if (inet_pton (AF_INET, address, &lla) <= 0) { + nm_log_err (LOGD_AUTOIP4, "(%s): invalid address %s received from avahi-autoipd.", + iface, address); + nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_AUTOIP_ERROR); + return; + } + + if ((lla & IPV4LL_NETMASK) != IPV4LL_NETWORK) { + nm_log_err (LOGD_AUTOIP4, "(%s): invalid address %s received from avahi-autoipd (not link-local).", + iface, address); + nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_AUTOIP_ERROR); + return; + } + + config = aipd_get_ip4_config (self, lla); + if (config == NULL) { + nm_log_err (LOGD_AUTOIP4, "failed to get autoip config"); + nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); + return; + } + + if (priv->ip4_state == IP_CONF) { + aipd_timeout_remove (self); + nm_device_activate_schedule_ip4_config_result (self, config); + } else if (priv->ip4_state == IP_DONE) { + if (!ip4_config_merge_and_apply (self, config, TRUE, &reason)) { + nm_log_err (LOGD_AUTOIP4, "(%s): failed to update IP4 config for autoip change.", + nm_device_get_iface (self)); + nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); + } + } else + g_assert_not_reached (); + + g_object_unref (config); + } else { + nm_log_warn (LOGD_AUTOIP4, "(%s): autoip address %s no longer valid because '%s'.", + iface, address, event); + + /* The address is gone; terminate the connection or fail activation */ + nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED); + } +} + +static void +aipd_watch_cb (GPid pid, gint status, gpointer user_data) +{ + NMDevice *self = NM_DEVICE (user_data); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMDeviceState state; + const char *iface; + + if (!priv->aipd_watch) + return; + priv->aipd_watch = 0; + + iface = nm_device_get_iface (self); + + if (WIFEXITED (status)) { + nm_log_dbg (LOGD_AUTOIP4, "(%s): avahi-autoipd exited with error code %d", + iface, WEXITSTATUS (status)); + } else if (WIFSTOPPED (status)) { + nm_log_warn (LOGD_AUTOIP4, "(%s): avahi-autoipd stopped unexpectedly with signal %d", + iface, WSTOPSIG (status)); + } else if (WIFSIGNALED (status)) { + nm_log_warn (LOGD_AUTOIP4, "(%s): avahi-autoipd died with signal %d", + iface, WTERMSIG (status)); + } else { + nm_log_warn (LOGD_AUTOIP4, "(%s): avahi-autoipd died from an unknown cause", iface); + } + + aipd_cleanup (self); + + state = nm_device_get_state (self); + if (nm_device_is_activating (self) || (state == NM_DEVICE_STATE_ACTIVATED)) + nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_AUTOIP_FAILED); +} + +static gboolean +aipd_timeout_cb (gpointer user_data) +{ + NMDevice *self = NM_DEVICE (user_data); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + + if (priv->aipd_timeout) { + nm_log_info (LOGD_AUTOIP4, "(%s): avahi-autoipd timed out.", nm_device_get_iface (self)); + priv->aipd_timeout = 0; + aipd_cleanup (self); + + if (priv->ip4_state == IP_CONF) + nm_device_activate_schedule_ip4_config_timeout (self); + } + + return FALSE; +} + +static void +aipd_child_setup (gpointer user_data G_GNUC_UNUSED) +{ + /* We are in the child process at this point. + * Give child it's own program group for signal + * separation. + */ + pid_t pid = getpid (); + setpgid (pid, pid); + + /* + * We blocked signals in main(). We need to restore original signal + * mask for avahi-autoipd here so that it can receive signals. + */ + nm_unblock_posix_signals (NULL); +} + +/* default to installed helper, but can be modified for testing */ +const char *nm_device_autoipd_helper_path = LIBEXECDIR "/nm-avahi-autoipd.action"; + +static NMActStageReturn +aipd_start (NMDevice *self, NMDeviceStateReason *reason) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + const char *iface = nm_device_get_iface (self); + char *argv[6], *cmdline; + const char **aipd_binary = NULL; + static const char *aipd_paths[] = { + "/usr/sbin/avahi-autoipd", + "/usr/local/sbin/avahi-autoipd", + NULL + }; + int i = 0; + GError *error = NULL; + + aipd_cleanup (self); + + /* Find avahi-autoipd */ + aipd_binary = aipd_paths; + while (*aipd_binary != NULL) { + if (g_file_test (*aipd_binary, G_FILE_TEST_EXISTS)) + break; + aipd_binary++; + } + + if (!*aipd_binary) { + nm_log_warn (LOGD_DEVICE | LOGD_AUTOIP4, + "Activation (%s) Stage 3 of 5 (IP Configure Start) failed" + " to start avahi-autoipd: not found", iface); + *reason = NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED; + return NM_ACT_STAGE_RETURN_FAILURE; + } + + argv[i++] = (char *) (*aipd_binary); + argv[i++] = "--script"; + argv[i++] = (char *) nm_device_autoipd_helper_path; + + if (nm_logging_enabled (LOGL_DEBUG, LOGD_AUTOIP4)) + argv[i++] = "--debug"; + argv[i++] = (char *) nm_device_get_ip_iface (self); + argv[i++] = NULL; + + cmdline = g_strjoinv (" ", argv); + nm_log_dbg (LOGD_AUTOIP4, "running: %s", cmdline); + g_free (cmdline); + + if (!g_spawn_async ("/", argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD, + &aipd_child_setup, NULL, &(priv->aipd_pid), &error)) { + nm_log_warn (LOGD_DEVICE | LOGD_AUTOIP4, + "Activation (%s) Stage 3 of 5 (IP Configure Start) failed" + " to start avahi-autoipd: %s", + iface, + error && error->message ? error->message : "(unknown)"); + g_clear_error (&error); + aipd_cleanup (self); + return NM_ACT_STAGE_RETURN_FAILURE; + } + + nm_log_info (LOGD_DEVICE | LOGD_AUTOIP4, + "Activation (%s) Stage 3 of 5 (IP Configure Start) started" + " avahi-autoipd...", iface); + + /* Monitor the child process so we know when it dies */ + priv->aipd_watch = g_child_watch_add (priv->aipd_pid, aipd_watch_cb, self); + + /* Start a timeout to bound the address attempt */ + priv->aipd_timeout = g_timeout_add_seconds (20, aipd_timeout_cb, self); + + return NM_ACT_STAGE_RETURN_POSTPONE; +} + +/*********************************************/ +/* DHCPv4 stuff */ + +static void +dhcp4_cleanup (NMDevice *self, gboolean stop, gboolean release) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + + if (priv->dhcp4_client) { + /* Stop any ongoing DHCP transaction on this device */ + if (priv->dhcp4_state_sigid) { + g_signal_handler_disconnect (priv->dhcp4_client, priv->dhcp4_state_sigid); + priv->dhcp4_state_sigid = 0; + } + + if (priv->dhcp4_timeout_sigid) { + g_signal_handler_disconnect (priv->dhcp4_client, priv->dhcp4_timeout_sigid); + priv->dhcp4_timeout_sigid = 0; + } + + nm_device_remove_pending_action (self, PENDING_ACTION_DHCP4, FALSE); + + if (stop) + nm_dhcp_client_stop (priv->dhcp4_client, release); + + g_clear_object (&priv->dhcp4_client); + } + + if (priv->dhcp4_config) { + g_clear_object (&priv->dhcp4_config); + g_object_notify (G_OBJECT (self), NM_DEVICE_DHCP4_CONFIG); + } +} + +static void +dhcp4_add_option_cb (gpointer key, gpointer value, gpointer user_data) +{ + nm_dhcp4_config_add_option (NM_DHCP4_CONFIG (user_data), + (const char *) key, + (const char *) value); +} + +static gboolean +ip4_config_merge_and_apply (NMDevice *self, + NMIP4Config *config, + gboolean commit, + NMDeviceStateReason *out_reason) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMConnection *connection; + gboolean success; + NMIP4Config *composite; + + /* Merge all the configs into the composite config */ + if (config) { + g_clear_object (&priv->dev_ip4_config); + priv->dev_ip4_config = g_object_ref (config); + } + + composite = nm_ip4_config_new (); + if (priv->dev_ip4_config) + nm_ip4_config_merge (composite, priv->dev_ip4_config); + if (priv->vpn4_config) + nm_ip4_config_merge (composite, priv->vpn4_config); + if (priv->ext_ip4_config) + nm_ip4_config_merge (composite, priv->ext_ip4_config); + + /* Merge user overrides into the composite config */ + connection = nm_device_get_connection (self); + if (connection) { + nm_ip4_config_merge_setting (composite, + nm_connection_get_setting_ip4_config (connection), + nm_device_get_priority (self)); + } + + /* Allow setting MTU etc */ + if (commit) { + if (NM_DEVICE_GET_CLASS (self)->ip4_config_pre_commit) + NM_DEVICE_GET_CLASS (self)->ip4_config_pre_commit (self, composite); + } + + success = nm_device_set_ip4_config (self, composite, commit, out_reason); + g_object_unref (composite); + return success; +} + +static void +dhcp4_lease_change (NMDevice *self, NMIP4Config *config) +{ + NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; + + g_return_if_fail (config != NULL); + + if (!ip4_config_merge_and_apply (self, config, TRUE, &reason)) { + nm_log_warn (LOGD_DHCP4, "(%s): failed to update IPv4 config for DHCP change.", + nm_device_get_ip_iface (self)); + nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); + } else { + /* Notify dispatcher scripts of new DHCP4 config */ + nm_dispatcher_call (DISPATCHER_ACTION_DHCP4_CHANGE, + nm_device_get_connection (self), + self, + NULL, + NULL, + NULL); + } +} + +static void +dhcp4_fail (NMDevice *device, gboolean timeout) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); + + nm_dhcp4_config_reset (priv->dhcp4_config); + + if (timeout || (priv->ip4_state == IP_CONF)) + nm_device_activate_schedule_ip4_config_timeout (device); + else if (priv->ip4_state == IP_FAIL) + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED); +} + +static void +dhcp4_state_changed (NMDHCPClient *client, + NMDHCPState state, + gpointer user_data) +{ + NMDevice *device = NM_DEVICE (user_data); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); + NMIP4Config *config; + + g_return_if_fail (nm_dhcp_client_get_ipv6 (client) == FALSE); + + nm_log_dbg (LOGD_DHCP4, "(%s): new DHCPv4 client state %d", + nm_device_get_iface (device), state); + + switch (state) { + case DHC_BOUND4: /* lease obtained */ + case DHC_RENEW4: /* lease renewed */ + case DHC_REBOOT: /* have valid lease, but now obtained a different one */ + case DHC_REBIND4: /* new, different lease */ + config = nm_dhcp_client_get_ip4_config (priv->dhcp4_client, FALSE); + if (!config) { + nm_log_warn (LOGD_DHCP4, "(%s): failed to get IPv4 config in response to DHCP event.", + nm_device_get_ip_iface (device)); + nm_device_state_changed (device, + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); + break; + } + + /* Update the DHCP4 config object with new DHCP options */ + nm_dhcp4_config_reset (priv->dhcp4_config); + nm_dhcp_client_foreach_option (priv->dhcp4_client, + dhcp4_add_option_cb, + priv->dhcp4_config); + g_object_notify (G_OBJECT (device), NM_DEVICE_DHCP4_CONFIG); + + if (priv->ip4_state == IP_CONF) + nm_device_activate_schedule_ip4_config_result (device, config); + else if (priv->ip4_state == IP_DONE) + dhcp4_lease_change (device, config); + g_object_unref (config); + + break; + case DHC_TIMEOUT: /* timed out contacting DHCP server */ + dhcp4_fail (device, TRUE); + break; + case DHC_END: /* dhclient exited normally */ + case DHC_FAIL: /* all attempts to contact server timed out, sleeping */ + case DHC_ABEND: /* dhclient exited abnormally */ + /* dhclient quit and can't get/renew a lease; so kill the connection */ + dhcp4_fail (device, FALSE); + break; + default: + break; + } +} + +static void +dhcp4_timeout (NMDHCPClient *client, gpointer user_data) +{ + NMDevice *device = NM_DEVICE (user_data); + + g_return_if_fail (nm_device_get_act_request (device) != NULL); + g_return_if_fail (nm_dhcp_client_get_ipv6 (client) == FALSE); + + nm_dhcp_client_stop (client, FALSE); + dhcp4_fail (device, TRUE); +} + +static NMActStageReturn +dhcp4_start (NMDevice *self, + NMConnection *connection, + NMDeviceStateReason *reason) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMSettingIP4Config *s_ip4; + GByteArray *tmp = NULL; + + s_ip4 = nm_connection_get_setting_ip4_config (connection); + + /* Clear old exported DHCP options */ + if (priv->dhcp4_config) + g_object_unref (priv->dhcp4_config); + priv->dhcp4_config = nm_dhcp4_config_new (); + + if (priv->hw_addr_len) { + tmp = g_byte_array_sized_new (priv->hw_addr_len); + g_byte_array_append (tmp, priv->hw_addr, priv->hw_addr_len); + } + + /* Begin DHCP on the interface */ + g_warn_if_fail (priv->dhcp4_client == NULL); + priv->dhcp4_client = nm_dhcp_manager_start_ip4 (nm_dhcp_manager_get (), + nm_device_get_ip_iface (self), + tmp, + nm_connection_get_uuid (connection), + nm_device_get_priority (self), + s_ip4, + priv->dhcp_timeout, + priv->dhcp_anycast_address); + + if (tmp) + g_byte_array_free (tmp, TRUE); + + if (!priv->dhcp4_client) { + *reason = NM_DEVICE_STATE_REASON_DHCP_START_FAILED; + return NM_ACT_STAGE_RETURN_FAILURE; + } + + priv->dhcp4_state_sigid = g_signal_connect (priv->dhcp4_client, + NM_DHCP_CLIENT_SIGNAL_STATE_CHANGED, + G_CALLBACK (dhcp4_state_changed), + self); + priv->dhcp4_timeout_sigid = g_signal_connect (priv->dhcp4_client, + NM_DHCP_CLIENT_SIGNAL_TIMEOUT, + G_CALLBACK (dhcp4_timeout), + self); + + nm_device_add_pending_action (self, PENDING_ACTION_DHCP4, TRUE); + + /* DHCP devices will be notified by the DHCP manager when stuff happens */ + return NM_ACT_STAGE_RETURN_POSTPONE; +} + +gboolean +nm_device_dhcp4_renew (NMDevice *self, gboolean release) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMActStageReturn ret; + NMDeviceStateReason reason; + NMConnection *connection; + + g_return_val_if_fail (priv->dhcp4_client != NULL, FALSE); + + nm_log_info (LOGD_DHCP4, "(%s): DHCPv4 lease renewal requested", + nm_device_get_iface (self)); + + /* Terminate old DHCP instance and release the old lease */ + dhcp4_cleanup (self, TRUE, release); + + connection = nm_device_get_connection (self); + g_assert (connection); + + /* Start DHCP again on the interface */ + ret = dhcp4_start (self, connection, &reason); + + return (ret != NM_ACT_STAGE_RETURN_FAILURE); +} + +/*********************************************/ + +static GHashTable *shared_ips = NULL; + +static void +release_shared_ip (gpointer data) +{ + g_hash_table_remove (shared_ips, data); +} + +static gboolean +reserve_shared_ip (NMSettingIP4Config *s_ip4, NMPlatformIP4Address *address) +{ + if (G_UNLIKELY (shared_ips == NULL)) + shared_ips = g_hash_table_new (g_direct_hash, g_direct_equal); + + memset (address, 0, sizeof (*address)); + + if (s_ip4 && nm_setting_ip4_config_get_num_addresses (s_ip4)) { + /* Use the first user-supplied address */ + NMIP4Address *user = nm_setting_ip4_config_get_address (s_ip4, 0); + + g_assert (user); + address->address = nm_ip4_address_get_address (user); + address->plen = nm_ip4_address_get_prefix (user); + } else { + /* Find an unused address in the 10.42.x.x range */ + guint32 start = (guint32) ntohl (0x0a2a0001); /* 10.42.0.1 */ + guint32 count = 0; + + while (g_hash_table_lookup (shared_ips, GUINT_TO_POINTER (start + count))) { + count += ntohl (0x100); + if (count > ntohl (0xFE00)) { + nm_log_err (LOGD_SHARING, "ran out of shared IP addresses!"); + return FALSE; + } + } + address->address = start + count; + address->plen = 24; + + g_hash_table_insert (shared_ips, + GUINT_TO_POINTER (address->address), + GUINT_TO_POINTER (TRUE)); + } + + return TRUE; +} + +static NMIP4Config * +shared4_new_config (NMDevice *self, NMConnection *connection, NMDeviceStateReason *reason) +{ + NMIP4Config *config = NULL; + NMPlatformIP4Address address; + + g_return_val_if_fail (self != NULL, NULL); + + if (!reserve_shared_ip (nm_connection_get_setting_ip4_config (connection), &address)) { + *reason = NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE; + return NULL; + } + + config = nm_ip4_config_new (); + address.source = NM_PLATFORM_SOURCE_SHARED; + nm_ip4_config_add_address (config, &address); + + /* Remove the address lock when the object gets disposed */ + g_object_set_data_full (G_OBJECT (config), "shared-ip", + GUINT_TO_POINTER (address.address), + release_shared_ip); + + return config; +} + +/*********************************************/ + +static gboolean +have_any_ready_slaves (NMDevice *device, const GSList *slaves) +{ + const GSList *iter; + + /* Any enslaved slave is "ready" in the generic case as it's + * at least >= NM_DEVCIE_STATE_IP_CONFIG and has had Layer 2 + * properties set up. + */ + for (iter = slaves; iter; iter = g_slist_next (iter)) { + if (nm_device_get_enslaved (iter->data)) + return TRUE; + } + return FALSE; +} + +static gboolean +ip4_requires_slaves (NMConnection *connection) +{ + const char *method; + + method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP4_CONFIG); + return strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0; +} + +static NMActStageReturn +act_stage3_ip4_config_start (NMDevice *self, + NMIP4Config **out_config, + NMDeviceStateReason *reason) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMConnection *connection; + NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; + const char *method; + GSList *slaves; + gboolean ready_slaves; + + g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); + + connection = nm_device_get_connection (self); + g_assert (connection); + + method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP4_CONFIG); + if (priv->master) + g_assert_cmpstr (method, ==, NM_SETTING_IP4_CONFIG_METHOD_DISABLED); + + if ( strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL) != 0 + && priv->is_master + && !priv->carrier) { + nm_log_info (LOGD_IP4 | LOGD_DEVICE, + "(%s): IPv4 config waiting until carrier is on", + nm_device_get_ip_iface (self)); + return NM_ACT_STAGE_RETURN_WAIT; + } + + if (priv->is_master && ip4_requires_slaves (connection)) { + /* If the master has no ready slaves, and depends on slaves for + * a successful IPv4 attempt, then postpone IPv4 addressing. + */ + slaves = nm_device_master_get_slaves (self); + ready_slaves = NM_DEVICE_GET_CLASS (self)->have_any_ready_slaves (self, slaves); + g_slist_free (slaves); + + if (ready_slaves == FALSE) { + nm_log_info (LOGD_DEVICE | LOGD_IP4, + "(%s): IPv4 config waiting until slaves are ready", + nm_device_get_ip_iface (self)); + return NM_ACT_STAGE_RETURN_WAIT; + } + } + + /* Start IPv4 addressing based on the method requested */ + if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0) + ret = dhcp4_start (self, connection, reason); + else if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL) == 0) + ret = aipd_start (self, reason); + else if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL) == 0) { + /* Use only IPv4 config from the connection data */ + *out_config = nm_ip4_config_new (); + g_assert (*out_config); + ret = NM_ACT_STAGE_RETURN_SUCCESS; + } else if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_SHARED) == 0) { + *out_config = shared4_new_config (self, connection, reason); + if (*out_config) { + priv->dnsmasq_manager = nm_dnsmasq_manager_new (nm_device_get_ip_iface (self)); + ret = NM_ACT_STAGE_RETURN_SUCCESS; + } else + ret = NM_ACT_STAGE_RETURN_FAILURE; + } else if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED) == 0) { + /* Nothing to do... */ + ret = NM_ACT_STAGE_RETURN_STOP; + } else { + nm_log_warn (LOGD_IP4, "(%s): unhandled IPv4 config method '%s'; will fail", + nm_device_get_ip_iface (self), method); + } + + return ret; +} + +/*********************************************/ +/* DHCPv6 stuff */ + +static void +dhcp6_cleanup (NMDevice *self, gboolean stop, gboolean release) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + + priv->dhcp6_mode = NM_RDISC_DHCP_LEVEL_NONE; + g_clear_object (&priv->dhcp6_ip6_config); + + if (priv->dhcp6_client) { + if (priv->dhcp6_state_sigid) { + g_signal_handler_disconnect (priv->dhcp6_client, priv->dhcp6_state_sigid); + priv->dhcp6_state_sigid = 0; + } + + if (priv->dhcp6_timeout_sigid) { + g_signal_handler_disconnect (priv->dhcp6_client, priv->dhcp6_timeout_sigid); + priv->dhcp6_timeout_sigid = 0; + } + + nm_device_remove_pending_action (self, PENDING_ACTION_DHCP6, FALSE); + + if (stop) + nm_dhcp_client_stop (priv->dhcp6_client, release); + + g_clear_object (&priv->dhcp6_client); + } + + if (priv->dhcp6_config) { + g_clear_object (&priv->dhcp6_config); + g_object_notify (G_OBJECT (self), NM_DEVICE_DHCP6_CONFIG); + } +} + +static void +dhcp6_add_option_cb (gpointer key, gpointer value, gpointer user_data) +{ + nm_dhcp6_config_add_option (NM_DHCP6_CONFIG (user_data), + (const char *) key, + (const char *) value); +} + +static gboolean +ip6_config_merge_and_apply (NMDevice *self, + gboolean commit, + NMDeviceStateReason *out_reason) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMConnection *connection; + gboolean success; + NMIP6Config *composite; + + /* If no config was passed in, create a new one */ + composite = nm_ip6_config_new (); + g_assert (composite); + + /* Merge all the IP configs into the composite config */ + if (priv->ac_ip6_config) + nm_ip6_config_merge (composite, priv->ac_ip6_config); + if (priv->dhcp6_ip6_config) + nm_ip6_config_merge (composite, priv->dhcp6_ip6_config); + if (priv->vpn6_config) + nm_ip6_config_merge (composite, priv->vpn6_config); + if (priv->ext_ip6_config) + nm_ip6_config_merge (composite, priv->ext_ip6_config); + + /* Merge user overrides into the composite config */ + connection = nm_device_get_connection (self); + if (connection) { + nm_ip6_config_merge_setting (composite, + nm_connection_get_setting_ip6_config (connection), + nm_device_get_priority (self)); + } + + nm_ip6_config_addresses_sort (composite, + priv->rdisc ? priv->rdisc_use_tempaddr : NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN); + + success = nm_device_set_ip6_config (self, composite, commit, out_reason); + g_object_unref (composite); + return success; +} + +static void +dhcp6_lease_change (NMDevice *device) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); + NMConnection *connection; + NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; + + if (priv->dhcp6_ip6_config == NULL) { + nm_log_warn (LOGD_DHCP6, "(%s): failed to get DHCPv6 config for rebind", + nm_device_get_ip_iface (device)); + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED); + return; + } + + g_assert (priv->dhcp6_client); /* sanity check */ + + connection = nm_device_get_connection (device); + g_assert (connection); + + /* Apply the updated config */ + if (ip6_config_merge_and_apply (device, TRUE, &reason) == FALSE) { + nm_log_warn (LOGD_DHCP6, "(%s): failed to update IPv6 config in response to DHCP event.", + nm_device_get_ip_iface (device)); + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, reason); + } else { + /* Notify dispatcher scripts of new DHCPv6 config */ + nm_dispatcher_call (DISPATCHER_ACTION_DHCP6_CHANGE, connection, device, NULL, NULL, NULL); + } +} + +static void +dhcp6_fail (NMDevice *device, gboolean timeout) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); + + nm_dhcp6_config_reset (priv->dhcp6_config); + + if (timeout || (priv->ip6_state == IP_CONF)) + nm_device_activate_schedule_ip6_config_timeout (device); + else if (priv->ip6_state == IP_FAIL) + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED); +} + +static void +dhcp6_state_changed (NMDHCPClient *client, + NMDHCPState state, + gpointer user_data) +{ + NMDevice *device = NM_DEVICE (user_data); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); + + g_return_if_fail (nm_dhcp_client_get_ipv6 (client) == TRUE); + + nm_log_dbg (LOGD_DHCP6, "(%s): new DHCPv6 client state %d", + nm_device_get_iface (device), state); + + switch (state) { + case DHC_BOUND6: + case DHC_RENEW6: /* lease renewed */ + case DHC_REBOOT: /* have valid lease, but now obtained a different one */ + case DHC_REBIND6: /* new, different lease */ + g_clear_object (&priv->dhcp6_ip6_config); + priv->dhcp6_ip6_config = nm_dhcp_client_get_ip6_config (priv->dhcp6_client, FALSE); + + /* Update the DHCP6 config object with new DHCP options */ + nm_dhcp6_config_reset (priv->dhcp6_config); + if (priv->dhcp6_ip6_config) { + nm_dhcp_client_foreach_option (priv->dhcp6_client, + dhcp6_add_option_cb, + priv->dhcp6_config); + } + g_object_notify (G_OBJECT (device), NM_DEVICE_DHCP6_CONFIG); + + if (priv->ip6_state == IP_CONF) { + if (priv->dhcp6_ip6_config == NULL) { + /* FIXME: Initial DHCP failed; should we fail IPv6 entirely then? */ + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_DHCP_FAILED); + break; + } + nm_device_activate_schedule_ip6_config_result (device); + } else if (priv->ip6_state == IP_DONE) + dhcp6_lease_change (device); + break; + case DHC_TIMEOUT: /* timed out contacting DHCP server */ + dhcp6_fail (device, TRUE); + break; + case DHC_END: /* dhclient exited normally */ + /* In IPv6 info-only mode, the client doesn't handle leases so it + * may exit right after getting a response from the server. That's + * normal. In that case we just ignore the exit. + */ + if (priv->dhcp6_mode == NM_RDISC_DHCP_LEVEL_OTHERCONF) + break; + /* Otherwise, fall through */ + case DHC_FAIL: /* all attempts to contact server timed out, sleeping */ + case DHC_ABEND: /* dhclient exited abnormally */ + /* dhclient quit and can't get/renew a lease; so kill the connection */ + dhcp6_fail (device, FALSE); + break; + default: + break; + } +} + +static void +dhcp6_timeout (NMDHCPClient *client, gpointer user_data) +{ + NMDevice *device = NM_DEVICE (user_data); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); + + g_return_if_fail (nm_device_get_act_request (device) != NULL); + g_return_if_fail (nm_dhcp_client_get_ipv6 (client) == TRUE); + + nm_dhcp_client_stop (client, FALSE); + if (priv->dhcp6_mode == NM_RDISC_DHCP_LEVEL_MANAGED) + dhcp6_fail (device, TRUE); + else { + /* not a hard failure; just live with the RA info */ + nm_dhcp6_config_reset (priv->dhcp6_config); + if (priv->dhcp6_ip6_config) + g_object_unref (priv->dhcp6_ip6_config); + priv->dhcp6_ip6_config = NULL; + + if (priv->ip6_state == IP_CONF) + nm_device_activate_schedule_ip6_config_result (device); + } +} + +static NMActStageReturn +dhcp6_start (NMDevice *self, + NMConnection *connection, + guint32 dhcp_opt, + NMDeviceStateReason *reason) +{ + NMSettingIP6Config *s_ip6; + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; + GByteArray *tmp = NULL; + + if (!connection) { + connection = nm_device_get_connection (self); + g_assert (connection); + } + + /* Begin a DHCP transaction on the interface */ + + /* Clear old exported DHCP options */ + if (priv->dhcp6_config) + g_object_unref (priv->dhcp6_config); + priv->dhcp6_config = nm_dhcp6_config_new (); + + g_warn_if_fail (priv->dhcp6_ip6_config == NULL); + if (priv->dhcp6_ip6_config) { + g_object_unref (priv->dhcp6_ip6_config); + priv->dhcp6_ip6_config = NULL; + } + + if (priv->hw_addr_len) { + tmp = g_byte_array_sized_new (priv->hw_addr_len); + g_byte_array_append (tmp, priv->hw_addr, priv->hw_addr_len); + } + + priv->dhcp6_client = nm_dhcp_manager_start_ip6 (nm_dhcp_manager_get (), + nm_device_get_ip_iface (self), + tmp, + nm_connection_get_uuid (connection), + nm_device_get_priority (self), + nm_connection_get_setting_ip6_config (connection), + priv->dhcp_timeout, + priv->dhcp_anycast_address, + (dhcp_opt == NM_RDISC_DHCP_LEVEL_OTHERCONF) ? TRUE : FALSE); + if (tmp) + g_byte_array_free (tmp, TRUE); + + if (priv->dhcp6_client) { + priv->dhcp6_state_sigid = g_signal_connect (priv->dhcp6_client, + NM_DHCP_CLIENT_SIGNAL_STATE_CHANGED, + G_CALLBACK (dhcp6_state_changed), + self); + priv->dhcp6_timeout_sigid = g_signal_connect (priv->dhcp6_client, + NM_DHCP_CLIENT_SIGNAL_TIMEOUT, + G_CALLBACK (dhcp6_timeout), + self); + + s_ip6 = nm_connection_get_setting_ip6_config (connection); + if (!nm_setting_ip6_config_get_may_fail (s_ip6) || + !strcmp (nm_setting_ip6_config_get_method (s_ip6), NM_SETTING_IP6_CONFIG_METHOD_DHCP)) + nm_device_add_pending_action (self, PENDING_ACTION_DHCP6, TRUE); + + /* DHCP devices will be notified by the DHCP manager when stuff happens */ + ret = NM_ACT_STAGE_RETURN_POSTPONE; + } else { + *reason = NM_DEVICE_STATE_REASON_DHCP_START_FAILED; + ret = NM_ACT_STAGE_RETURN_FAILURE; + } + + return ret; +} + +gboolean +nm_device_dhcp6_renew (NMDevice *self, gboolean release) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMActStageReturn ret; + NMDeviceStateReason reason; + NMConnection *connection; + + g_return_val_if_fail (priv->dhcp6_client != NULL, FALSE); + + nm_log_info (LOGD_DHCP6, "(%s): DHCPv6 lease renewal requested", + nm_device_get_iface (self)); + + /* Terminate old DHCP instance and release the old lease */ + dhcp6_cleanup (self, TRUE, release); + + connection = nm_device_get_connection (self); + g_assert (connection); + + /* Start DHCP again on the interface */ + ret = dhcp6_start (self, connection, priv->dhcp6_mode, &reason); + + return (ret != NM_ACT_STAGE_RETURN_FAILURE); +} + +/******************************************/ + +static gboolean +linklocal6_config_is_ready (const NMIP6Config *ip6_config) +{ + int i; + + if (!ip6_config) + return FALSE; + + for (i = 0; i < nm_ip6_config_get_num_addresses (ip6_config); i++) { + const NMPlatformIP6Address *addr = nm_ip6_config_get_address (ip6_config, i); + + if (IN6_IS_ADDR_LINKLOCAL (&addr->address) && + !(addr->flags & IFA_F_TENTATIVE)) + return TRUE; + } + + return FALSE; +} + +static void +linklocal6_cleanup (NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + + if (priv->linklocal6_timeout_id) { + g_source_remove (priv->linklocal6_timeout_id); + priv->linklocal6_timeout_id = 0; + } +} + +static gboolean +linklocal6_timeout_cb (gpointer user_data) +{ + NMDevice *self = user_data; + + linklocal6_cleanup (self); + + nm_log_dbg (LOGD_DEVICE, "[%s] linklocal6: waiting for link-local addresses failed due to timeout", + nm_device_get_iface (self)); + + nm_device_activate_schedule_ip6_config_timeout (self); + return G_SOURCE_REMOVE; +} + +static void +linklocal6_complete (NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMConnection *connection; + const char *method; + + g_assert (priv->linklocal6_timeout_id); + g_assert (linklocal6_config_is_ready (priv->ip6_config)); + + linklocal6_cleanup (self); + + connection = nm_device_get_connection (self); + g_assert (connection); + + method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP6_CONFIG); + + nm_log_dbg (LOGD_DEVICE, "[%s] linklocal6: waiting for link-local addresses successful, continue with method %s", + nm_device_get_iface (self), method); + + if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) == 0) + addrconf6_start_with_link_ready (self); + else if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL) == 0) + nm_device_activate_schedule_ip6_config_result (self); + else + g_return_if_fail (FALSE); +} + +static NMActStageReturn +linklocal6_start (NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMConnection *connection; + const char *method; + + linklocal6_cleanup (self); + + if (linklocal6_config_is_ready (priv->ip6_config)) + return NM_ACT_STAGE_RETURN_SUCCESS; + + connection = nm_device_get_connection (self); + g_assert (connection); + + method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP6_CONFIG); + nm_log_dbg (LOGD_DEVICE, "[%s] linklocal6: starting IPv6 with method '%s', but the device has no link-local addresses configured. Wait.", + nm_device_get_iface (self), method); + + priv->linklocal6_timeout_id = g_timeout_add_seconds (5, linklocal6_timeout_cb, self); + + return NM_ACT_STAGE_RETURN_POSTPONE; +} + +/******************************************/ + +static void +print_support_extended_ifa_flags (NMSettingIP6ConfigPrivacy use_tempaddr) +{ + static gint8 warn = 0; + static gint8 s_libnl = -1, s_kernel; + + if (warn >= 2) + return; + + if (s_libnl == -1) { + s_libnl = !!nm_platform_check_support_libnl_extended_ifa_flags (); + s_kernel = !!nm_platform_check_support_kernel_extended_ifa_flags (); + + if (s_libnl && s_kernel) { + nm_log_dbg (LOGD_IP6, "kernel and libnl support extended IFA_FLAGS (needed by NM for IPv6 private addresses)"); + warn = 2; + return; + } + } + + if ( use_tempaddr != NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR + && use_tempaddr != NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR) { + if (warn == 0) { + nm_log_dbg (LOGD_IP6, "%s%s%s %s not support extended IFA_FLAGS (needed by NM for IPv6 private addresses)", + !s_kernel ? "kernel" : "", + !s_kernel && !s_libnl ? " and " : "", + !s_libnl ? "libnl" : "", + !s_kernel && !s_libnl ? "do" : "does"); + warn = 1; + } + return; + } + + if (!s_libnl && !s_kernel) { + nm_log_warn (LOGD_IP6, "libnl and the kernel do not support extended IFA_FLAGS needed by NM for " + "IPv6 private addresses. This feature is not available"); + } else if (!s_libnl) { + nm_log_warn (LOGD_IP6, "libnl does not support extended IFA_FLAGS needed by NM for " + "IPv6 private addresses. This feature is not available"); + } else if (!s_kernel) { + nm_log_warn (LOGD_IP6, "The kernel does not support extended IFA_FLAGS needed by NM for " + "IPv6 private addresses. This feature is not available"); + } + + warn = 2; +} + +static void +rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, NMDevice *device) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); + NMConnection *connection; + int i; + NMDeviceStateReason reason; + static int system_support = -1; + guint ifa_flags = 0x00; + + if (system_support == -1) { + /* + * Check, if both libnl and the kernel are recent enough, + * to help user space handling RA. If it's not supported, + * we have no ipv6-privacy and must add autoconf addresses + * as /128. The reason for the /128 is to prevent the kernel + * from adding a prefix route for this address. + **/ + system_support = nm_platform_check_support_libnl_extended_ifa_flags () && + nm_platform_check_support_kernel_extended_ifa_flags (); + } + + if (system_support) + ifa_flags = IFA_F_NOPREFIXROUTE; + if (priv->rdisc_use_tempaddr == NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR + || priv->rdisc_use_tempaddr == NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR) + { + /* without system_support, this flag will be ignored. Still set it, doesn't seem to do any harm. */ + ifa_flags |= IFA_F_MANAGETEMPADDR; + } + + g_return_if_fail (priv->act_request); + connection = nm_device_get_connection (device); + g_assert (connection); + + if (!priv->ac_ip6_config) + priv->ac_ip6_config = nm_ip6_config_new (); + + if (changed & NM_RDISC_CONFIG_GATEWAYS) { + /* Use the first gateway as ordered in router discovery cache. */ + if (rdisc->gateways->len) { + NMRDiscGateway *gateway = &g_array_index (rdisc->gateways, NMRDiscGateway, 0); + + nm_ip6_config_set_gateway (priv->ac_ip6_config, &gateway->address); + } else + nm_ip6_config_set_gateway (priv->ac_ip6_config, NULL); + } + + if (changed & NM_RDISC_CONFIG_ADDRESSES) { + /* Rebuild address list from router discovery cache. */ + nm_ip6_config_reset_addresses (priv->ac_ip6_config); + + /* rdisc->addresses contains at most max_addresses entries. + * This is different from what the kernel does, which + * also counts static and temporary addresses when checking + * max_addresses. + **/ + for (i = 0; i < rdisc->addresses->len; i++) { + NMRDiscAddress *discovered_address = &g_array_index (rdisc->addresses, NMRDiscAddress, i); + NMPlatformIP6Address address; + + memset (&address, 0, sizeof (address)); + address.address = discovered_address->address; + address.plen = system_support ? 64 : 128; + address.timestamp = discovered_address->timestamp; + address.lifetime = discovered_address->lifetime; + address.preferred = discovered_address->preferred; + if (address.preferred > address.lifetime) + address.preferred = address.lifetime; + address.source = NM_PLATFORM_SOURCE_RDISC; + address.flags = ifa_flags; + + nm_ip6_config_add_address (priv->ac_ip6_config, &address); + } + } + + if (changed & NM_RDISC_CONFIG_ROUTES) { + /* Rebuild route list from router discovery cache. */ + nm_ip6_config_reset_routes (priv->ac_ip6_config); + + for (i = 0; i < rdisc->routes->len; i++) { + NMRDiscRoute *discovered_route = &g_array_index (rdisc->routes, NMRDiscRoute, i); + NMPlatformIP6Route route; + + /* Only accept non-default routes. The router has no idea what the + * local configuration or user preferences are, so sending routes + * with a prefix length of 0 is quite rude and thus ignored. + */ + if (discovered_route->plen > 0) { + memset (&route, 0, sizeof (route)); + route.network = discovered_route->network; + route.plen = discovered_route->plen; + route.gateway = discovered_route->gateway; + route.source = NM_PLATFORM_SOURCE_RDISC; + route.metric = nm_device_get_priority (device); + + nm_ip6_config_add_route (priv->ac_ip6_config, &route); + } + } + } + + if (changed & NM_RDISC_CONFIG_DNS_SERVERS) { + /* Rebuild DNS server list from router discovery cache. */ + nm_ip6_config_reset_nameservers (priv->ac_ip6_config); + + for (i = 0; i < rdisc->dns_servers->len; i++) { + NMRDiscDNSServer *discovered_server = &g_array_index (rdisc->dns_servers, NMRDiscDNSServer, i); + + nm_ip6_config_add_nameserver (priv->ac_ip6_config, &discovered_server->address); + } + } + + if (changed & NM_RDISC_CONFIG_DNS_DOMAINS) { + /* Rebuild domain list from router discovery cache. */ + nm_ip6_config_reset_domains (priv->ac_ip6_config); + + for (i = 0; i < rdisc->dns_domains->len; i++) { + NMRDiscDNSDomain *discovered_domain = &g_array_index (rdisc->dns_domains, NMRDiscDNSDomain, i); + + nm_ip6_config_add_domain (priv->ac_ip6_config, discovered_domain->domain); + } + } + + if (changed & NM_RDISC_CONFIG_DHCP_LEVEL) { + dhcp6_cleanup (device, TRUE, TRUE); + + priv->dhcp6_mode = rdisc->dhcp_level; + + switch (priv->dhcp6_mode) { + case NM_RDISC_DHCP_LEVEL_NONE: + break; + default: + nm_log_info (LOGD_DEVICE | LOGD_DHCP6, + "Activation (%s) Stage 3 of 5 (IP Configure Start) starting DHCPv6" + " as requested by IPv6 router...", + priv->iface); + switch (dhcp6_start (device, connection, priv->dhcp6_mode, &reason)) { + case NM_ACT_STAGE_RETURN_SUCCESS: + g_warn_if_reached (); + break; + case NM_ACT_STAGE_RETURN_POSTPONE: + return; + default: + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, reason); + return; + } + } + } + + if (changed & NM_RDISC_CONFIG_HOP_LIMIT) { + char val[16]; + + g_snprintf (val, sizeof (val), "%d", rdisc->hop_limit); + nm_device_ipv6_sysctl_set (device, "hop_limit", val); + } + + nm_device_activate_schedule_ip6_config_result (device); +} + +static gboolean +addrconf6_start (NMDevice *self, NMSettingIP6ConfigPrivacy use_tempaddr) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMConnection *connection; + NMActStageReturn ret; + const char *ip_iface = nm_device_get_ip_iface (self); + + connection = nm_device_get_connection (self); + g_assert (connection); + + g_warn_if_fail (priv->ac_ip6_config == NULL); + if (priv->ac_ip6_config) { + g_object_unref (priv->ac_ip6_config); + priv->ac_ip6_config = NULL; + } + + priv->rdisc = nm_lndp_rdisc_new (nm_device_get_ip_ifindex (self), ip_iface); + if (!priv->rdisc) { + nm_log_err (LOGD_IP6, "(%s): failed to start router discovery.", ip_iface); + return FALSE; + } + + priv->rdisc_use_tempaddr = use_tempaddr; + print_support_extended_ifa_flags (use_tempaddr); + + if (!nm_setting_ip6_config_get_may_fail (nm_connection_get_setting_ip6_config (connection))) + nm_device_add_pending_action (self, PENDING_ACTION_AUTOCONF6, TRUE); + + /* ensure link local is ready... */ + ret = linklocal6_start (self); + if (ret == NM_ACT_STAGE_RETURN_SUCCESS) + addrconf6_start_with_link_ready (self); + else + g_return_val_if_fail (ret == NM_ACT_STAGE_RETURN_POSTPONE, TRUE); + + return TRUE; +} + +static void +addrconf6_start_with_link_ready (NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + + g_assert (priv->rdisc); + + /* FIXME: what if interface has no lladdr, like PPP? */ + if (priv->hw_addr_len) + nm_rdisc_set_lladdr (priv->rdisc, (const char *) priv->hw_addr, priv->hw_addr_len); + + nm_device_ipv6_sysctl_set (self, "accept_ra", "1"); + nm_device_ipv6_sysctl_set (self, "accept_ra_defrtr", "0"); + nm_device_ipv6_sysctl_set (self, "accept_ra_pinfo", "0"); + nm_device_ipv6_sysctl_set (self, "accept_ra_rtr_pref", "0"); + + priv->rdisc_config_changed_sigid = g_signal_connect (priv->rdisc, NM_RDISC_CONFIG_CHANGED, + G_CALLBACK (rdisc_config_changed), self); + + nm_rdisc_start (priv->rdisc); +} + +static void +addrconf6_cleanup (NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + + if (priv->rdisc_config_changed_sigid) { + g_signal_handler_disconnect (priv->rdisc, + priv->rdisc_config_changed_sigid); + priv->rdisc_config_changed_sigid = 0; + } + + nm_device_remove_pending_action (self, PENDING_ACTION_AUTOCONF6, FALSE); + + g_clear_object (&priv->ac_ip6_config); + g_clear_object (&priv->rdisc); +} + +/******************************************/ + +static const char *ip6_properties_to_save[] = { + "accept_ra", + "accept_ra_defrtr", + "accept_ra_pinfo", + "accept_ra_rtr_pref", + "disable_ipv6", + "hop_limit", + "use_tempaddr", +}; + +static void +save_ip6_properties (NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + const char *ifname = nm_device_get_ip_iface (self); + char *value; + int i; + + g_hash_table_remove_all (priv->ip6_saved_properties); + + for (i = 0; i < G_N_ELEMENTS (ip6_properties_to_save); i++) { + value = nm_platform_sysctl_get (nm_utils_ip6_property_path (ifname, ip6_properties_to_save[i])); + if (value) { + g_hash_table_insert (priv->ip6_saved_properties, + (char *) ip6_properties_to_save[i], + value); + } + } +} + +static void +restore_ip6_properties (NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + GHashTableIter iter; + gpointer key, value; + + g_hash_table_iter_init (&iter, priv->ip6_saved_properties); + while (g_hash_table_iter_next (&iter, &key, &value)) + nm_device_ipv6_sysctl_set (self, key, value); +} + +static NMSettingIP6ConfigPrivacy +use_tempaddr_clamp (NMSettingIP6ConfigPrivacy use_tempaddr) +{ + switch (use_tempaddr) { + case NM_SETTING_IP6_CONFIG_PRIVACY_DISABLED: + case NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR: + case NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR: + return use_tempaddr; + default: + return NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN; + } +} + +/* Get net.ipv6.conf.default.use_tempaddr value from /etc/sysctl.conf or + * /lib/sysctl.d/sysctl.conf + */ +static NMSettingIP6ConfigPrivacy +ip6_use_tempaddr (void) +{ + char *contents = NULL; + const char *group_name = "[forged_group]\n"; + char *sysctl_data = NULL; + GKeyFile *keyfile; + GError *error = NULL; + gint tmp; + NMSettingIP6ConfigPrivacy ret = NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN; + + /* Read file contents to a string. */ + if (!g_file_get_contents ("/etc/sysctl.conf", &contents, NULL, NULL)) + if (!g_file_get_contents ("/lib/sysctl.d/sysctl.conf", &contents, NULL, NULL)) + return NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN; + + /* Prepend a group so that we can use GKeyFile parser. */ + sysctl_data = g_strdup_printf ("%s%s", group_name, contents); + + keyfile = g_key_file_new (); + if (!g_key_file_load_from_data (keyfile, sysctl_data, -1, G_KEY_FILE_NONE, NULL)) + goto done; + + tmp = g_key_file_get_integer (keyfile, "forged_group", "net.ipv6.conf.default.use_tempaddr", &error); + if (error == NULL) + ret = use_tempaddr_clamp (tmp); + +done: + g_free (contents); + g_free (sysctl_data); + g_clear_error (&error); + g_key_file_free (keyfile); + + return ret; +} + +static gboolean +ip6_requires_slaves (NMConnection *connection) +{ + const char *method; + + method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP6_CONFIG); + + /* SLAAC, DHCP, and Link-Local depend on connectivity (and thus slaves) + * to complete addressing. SLAAC and DHCP obviously need a peer to + * provide a prefix, while Link-Local must perform DAD on the local link. + */ + return strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) == 0 + || strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_DHCP) == 0 + || strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL) == 0; +} + +static NMActStageReturn +act_stage3_ip6_config_start (NMDevice *self, + NMIP6Config **out_config, + NMDeviceStateReason *reason) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + const char *ip_iface; + NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; + NMConnection *connection; + const char *method; + NMSettingIP6ConfigPrivacy ip6_privacy = NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN; + const char *ip6_privacy_str = "0\n"; + GSList *slaves; + gboolean ready_slaves; + + g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); + + ip_iface = nm_device_get_ip_iface (self); + + connection = nm_device_get_connection (self); + g_assert (connection); + + method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP6_CONFIG); + if (priv->master) + g_assert_cmpstr (method, ==, NM_SETTING_IP6_CONFIG_METHOD_IGNORE); + + if ( strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_MANUAL) != 0 + && priv->is_master + && !priv->carrier) { + nm_log_info (LOGD_IP6 | LOGD_DEVICE, + "(%s): IPv6 config waiting until carrier is on", ip_iface); + return NM_ACT_STAGE_RETURN_WAIT; + } + + if (priv->is_master && ip6_requires_slaves (connection)) { + /* If the master has no ready slaves, and depends on slaves for + * a successful IPv6 attempt, then postpone IPv6 addressing. + */ + slaves = nm_device_master_get_slaves (self); + ready_slaves = NM_DEVICE_GET_CLASS (self)->have_any_ready_slaves (self, slaves); + g_slist_free (slaves); + + if (ready_slaves == FALSE) { + nm_log_info (LOGD_DEVICE | LOGD_IP6, + "(%s): IPv6 config waiting until slaves are ready", + ip_iface); + return NM_ACT_STAGE_RETURN_WAIT; + } + } + + priv->dhcp6_mode = NM_RDISC_DHCP_LEVEL_NONE; + + if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE) == 0) { + if (!priv->master) + restore_ip6_properties (self); + return NM_ACT_STAGE_RETURN_STOP; + } + + /* Re-enable IPv6 on the interface */ + nm_device_ipv6_sysctl_set (self, "disable_ipv6", "0"); + + /* Enable/disable IPv6 Privacy Extensions. + * If a global value is configured by sysadmin (e.g. /etc/sysctl.conf), + * use that value instead of per-connection value. + */ + ip6_privacy = ip6_use_tempaddr (); + if (ip6_privacy == NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN) { + NMSettingIP6Config *s_ip6 = nm_connection_get_setting_ip6_config (connection); + + if (s_ip6) + ip6_privacy = nm_setting_ip6_config_get_ip6_privacy (s_ip6); + } + ip6_privacy = use_tempaddr_clamp (ip6_privacy); + + if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) == 0) { + if (!addrconf6_start (self, ip6_privacy)) { + /* IPv6 might be disabled; allow IPv4 to proceed */ + ret = NM_ACT_STAGE_RETURN_STOP; + } else + ret = NM_ACT_STAGE_RETURN_POSTPONE; + } else if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL) == 0) { + ret = linklocal6_start (self); + if (ret == NM_ACT_STAGE_RETURN_SUCCESS) { + /* New blank config; LL address is already in priv->ext_ip6_config */ + *out_config = nm_ip6_config_new (); + g_assert (*out_config); + } + } else if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_DHCP) == 0) { + priv->dhcp6_mode = NM_RDISC_DHCP_LEVEL_MANAGED; + ret = dhcp6_start (self, connection, priv->dhcp6_mode, reason); + } else if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_MANUAL) == 0) { + /* New blank config */ + *out_config = nm_ip6_config_new (); + g_assert (*out_config); + + ret = NM_ACT_STAGE_RETURN_SUCCESS; + } else { + nm_log_warn (LOGD_IP6, "(%s): unhandled IPv6 config method '%s'; will fail", + nm_device_get_ip_iface (self), method); + } + + /* Other methods (shared) aren't implemented yet */ + + switch (ip6_privacy) { + case NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN: + case NM_SETTING_IP6_CONFIG_PRIVACY_DISABLED: + ip6_privacy_str = "0"; + break; + case NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR: + ip6_privacy_str = "1"; + break; + case NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR: + ip6_privacy_str = "2"; + break; + } + nm_device_ipv6_sysctl_set (self, "use_tempaddr", ip6_privacy_str); + + return ret; +} + +/** + * nm_device_activate_stage3_ip4_start: + * @self: the device + * + * Try starting IPv4 configuration. + */ +gboolean +nm_device_activate_stage3_ip4_start (NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMActStageReturn ret; + NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; + NMIP4Config *ip4_config = NULL; + + g_assert (priv->ip4_state == IP_WAIT); + + priv->ip4_state = IP_CONF; + ret = NM_DEVICE_GET_CLASS (self)->act_stage3_ip4_config_start (self, &ip4_config, &reason); + if (ret == NM_ACT_STAGE_RETURN_SUCCESS) { + g_assert (ip4_config); + nm_device_activate_schedule_ip4_config_result (self, ip4_config); + g_object_unref (ip4_config); + } else if (ret == NM_ACT_STAGE_RETURN_FAILURE) { + nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); + return FALSE; + } else if (ret == NM_ACT_STAGE_RETURN_STOP) { + /* Early finish */ + priv->ip4_state = IP_FAIL; + } else if (ret == NM_ACT_STAGE_RETURN_WAIT) { + /* Wait for something to try IP config again */ + priv->ip4_state = IP_WAIT; + } else + g_assert (ret == NM_ACT_STAGE_RETURN_POSTPONE); + + return TRUE; +} + +/** + * nm_device_activate_stage3_ip6_start: + * @self: the device + * + * Try starting IPv6 configuration. + */ +gboolean +nm_device_activate_stage3_ip6_start (NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMActStageReturn ret; + NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; + NMIP6Config *ip6_config = NULL; + + g_assert (priv->ip6_state == IP_WAIT); + + priv->ip6_state = IP_CONF; + ret = NM_DEVICE_GET_CLASS (self)->act_stage3_ip6_config_start (self, &ip6_config, &reason); + if (ret == NM_ACT_STAGE_RETURN_SUCCESS) { + g_assert (ip6_config); + /* Here we get a static IPv6 config, like for Shared where it's + * autogenerated or from modems where it comes from ModemManager. + */ + g_warn_if_fail (priv->ac_ip6_config == NULL); + priv->ac_ip6_config = ip6_config; + nm_device_activate_schedule_ip6_config_result (self); + } else if (ret == NM_ACT_STAGE_RETURN_FAILURE) { + nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); + return FALSE; + } else if (ret == NM_ACT_STAGE_RETURN_STOP) { + /* Early finish */ + priv->ip6_state = IP_FAIL; + } else if (ret == NM_ACT_STAGE_RETURN_WAIT) { + /* Wait for something to try IP config again */ + priv->ip6_state = IP_WAIT; + } else + g_assert (ret == NM_ACT_STAGE_RETURN_POSTPONE); + + return TRUE; +} + +/* + * nm_device_activate_stage3_ip_config_start + * + * Begin automatic/manual IP configuration + * + */ +static gboolean +nm_device_activate_stage3_ip_config_start (gpointer user_data) +{ + NMDevice *self = NM_DEVICE (user_data); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + const char *iface; + NMActiveConnection *master; + NMDevice *master_device; + + /* Clear the activation source ID now that this stage has run */ + activation_source_clear (self, FALSE, 0); + + priv->ip4_state = priv->ip6_state = IP_WAIT; + + iface = nm_device_get_iface (self); + nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 3 of 5 (IP Configure Start) started...", iface); + nm_device_state_changed (self, NM_DEVICE_STATE_IP_CONFIG, NM_DEVICE_STATE_REASON_NONE); + + /* Device should be up before we can do anything with it */ + if (!nm_platform_link_is_up (nm_device_get_ip_ifindex (self))) { + nm_log_warn (LOGD_DEVICE, "(%s): interface %s not up for IP configuration", + iface, nm_device_get_ip_iface (self)); + } + + /* If the device is a slave, then we don't do any IP configuration but we + * use the IP config stage to indicate to the master we're ready for + * enslavement. If the master is already activating, it will have tried to + * enslave us when we changed state to IP_CONFIG, causing us to queue a + * transition to SECONDARIES (or FAILED if the enslavement failed), with + * our IP states set to IP_DONE either way. If the master isn't yet + * activating, then they'll still be in IP_WAIT. Either way, we bail out + * of IP config here. + */ + master = nm_active_connection_get_master (NM_ACTIVE_CONNECTION (priv->act_request)); + if (master) { + master_device = nm_active_connection_get_device (master); + if (priv->ip4_state == IP_WAIT && priv->ip6_state == IP_WAIT) { + nm_log_info (LOGD_DEVICE, "Activation (%s) connection '%s' waiting on master '%s'", + nm_device_get_iface (self), + nm_connection_get_id (nm_device_get_connection (self)), + master_device ? nm_device_get_iface (master_device) : "(unknown)"); + } + goto out; + } + + /* IPv4 */ + if (!nm_device_activate_stage3_ip4_start (self)) + goto out; + + /* IPv6 */ + if (!nm_device_activate_stage3_ip6_start (self)) + goto out; + + if (priv->ip4_state == IP_FAIL && priv->ip6_state == IP_FAIL) { + nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); + } + +out: + nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 3 of 5 (IP Configure Start) complete.", iface); + return FALSE; +} + + +static void +fw_change_zone_cb (GError *error, gpointer user_data) +{ + NMDevice *self = NM_DEVICE (user_data); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + + priv->fw_call = NULL; + + if (error) { + /* FIXME: fail the device activation? */ + } + + activation_source_schedule (self, nm_device_activate_stage3_ip_config_start, 0); + + nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 3 of 5 (IP Configure Start) scheduled.", + nm_device_get_iface (self)); +} + +/* + * nm_device_activate_schedule_stage3_ip_config_start + * + * Schedule IP configuration start + */ +void +nm_device_activate_schedule_stage3_ip_config_start (NMDevice *self) +{ + NMDevicePrivate *priv; + NMConnection *connection; + NMSettingConnection *s_con = NULL; + const char *zone; + + g_return_if_fail (NM_IS_DEVICE (self)); + + priv = NM_DEVICE_GET_PRIVATE (self); + g_return_if_fail (priv->act_request); + + /* Add the interface to the specified firewall zone */ + connection = nm_device_get_connection (self); + g_assert (connection); + s_con = nm_connection_get_setting_connection (connection); + + zone = nm_setting_connection_get_zone (s_con); + nm_log_dbg (LOGD_DEVICE, "Activation (%s) setting firewall zone '%s'", + nm_device_get_iface (self), zone ? zone : "default"); + priv->fw_call = nm_firewall_manager_add_or_change_zone (priv->fw_manager, + nm_device_get_ip_iface (self), + zone, + FALSE, + fw_change_zone_cb, + self); +} + +static NMActStageReturn +act_stage4_ip4_config_timeout (NMDevice *self, NMDeviceStateReason *reason) +{ + if (nm_device_ip_config_should_fail (self, FALSE)) { + *reason = NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE; + return NM_ACT_STAGE_RETURN_FAILURE; + } + return NM_ACT_STAGE_RETURN_SUCCESS; +} + + +/* + * nm_device_activate_stage4_ip4_config_timeout + * + * Time out on retrieving the IPv4 config. + * + */ +static gboolean +nm_device_activate_ip4_config_timeout (gpointer user_data) +{ + NMDevice *self = NM_DEVICE (user_data); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + const char *iface; + NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; + NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; + + /* Clear the activation source ID now that this stage has run */ + activation_source_clear (self, FALSE, AF_INET); + + iface = nm_device_get_iface (self); + nm_log_info (LOGD_DEVICE | LOGD_IP4, + "Activation (%s) Stage 4 of 5 (IPv4 Configure Timeout) started...", + iface); + + ret = NM_DEVICE_GET_CLASS (self)->act_stage4_ip4_config_timeout (self, &reason); + if (ret == NM_ACT_STAGE_RETURN_POSTPONE) + goto out; + else if (ret == NM_ACT_STAGE_RETURN_FAILURE) { + nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); + goto out; + } + g_assert (ret == NM_ACT_STAGE_RETURN_SUCCESS); + + priv->ip4_state = IP_FAIL; + + /* If IPv4 failed and IPv6 failed, the activation fails */ + if (priv->ip6_state == IP_FAIL) + nm_device_state_changed (self, + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); + +out: + nm_log_info (LOGD_DEVICE | LOGD_IP4, + "Activation (%s) Stage 4 of 5 (IPv4 Configure Timeout) complete.", + iface); + return FALSE; +} + + +/* + * nm_device_activate_schedule_ip4_config_timeout + * + * Deal with a timeout of the IPv4 configuration + * + */ +void +nm_device_activate_schedule_ip4_config_timeout (NMDevice *self) +{ + NMDevicePrivate *priv; + + g_return_if_fail (NM_IS_DEVICE (self)); + + priv = NM_DEVICE_GET_PRIVATE (self); + g_return_if_fail (priv->act_request); + + activation_source_schedule (self, nm_device_activate_ip4_config_timeout, AF_INET); + + nm_log_info (LOGD_DEVICE | LOGD_IP4, + "Activation (%s) Stage 4 of 5 (IPv4 Configure Timeout) scheduled...", + nm_device_get_iface (self)); +} + + +static NMActStageReturn +act_stage4_ip6_config_timeout (NMDevice *self, NMDeviceStateReason *reason) +{ + if (nm_device_ip_config_should_fail (self, TRUE)) { + *reason = NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE; + return NM_ACT_STAGE_RETURN_FAILURE; + } + + return NM_ACT_STAGE_RETURN_SUCCESS; +} + + +/* + * nm_device_activate_ip6_config_timeout + * + * Time out on retrieving the IPv6 config. + * + */ +static gboolean +nm_device_activate_ip6_config_timeout (gpointer user_data) +{ + NMDevice *self = NM_DEVICE (user_data); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + const char *iface; + NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; + NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; + + /* Clear the activation source ID now that this stage has run */ + activation_source_clear (self, FALSE, AF_INET6); + + iface = nm_device_get_iface (self); + nm_log_info (LOGD_DEVICE | LOGD_IP6, + "Activation (%s) Stage 4 of 5 (IPv6 Configure Timeout) started...", + iface); + + ret = NM_DEVICE_GET_CLASS (self)->act_stage4_ip6_config_timeout (self, &reason); + if (ret == NM_ACT_STAGE_RETURN_POSTPONE) + goto out; + else if (ret == NM_ACT_STAGE_RETURN_FAILURE) { + nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); + goto out; + } + g_assert (ret == NM_ACT_STAGE_RETURN_SUCCESS); + + priv->ip6_state = IP_FAIL; + + /* If IPv6 failed and IPv4 failed, the activation fails */ + if (priv->ip4_state == IP_FAIL) + nm_device_state_changed (self, + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); + +out: + nm_log_info (LOGD_DEVICE | LOGD_IP6, + "Activation (%s) Stage 4 of 5 (IPv6 Configure Timeout) complete.", + iface); + return FALSE; +} + + +/* + * nm_device_activate_schedule_ip6_config_timeout + * + * Deal with a timeout of the IPv6 configuration + * + */ +void +nm_device_activate_schedule_ip6_config_timeout (NMDevice *self) +{ + NMDevicePrivate *priv; + + g_return_if_fail (NM_IS_DEVICE (self)); + + priv = NM_DEVICE_GET_PRIVATE (self); + g_return_if_fail (priv->act_request); + + activation_source_schedule (self, nm_device_activate_ip6_config_timeout, AF_INET6); + + nm_log_info (LOGD_DEVICE | LOGD_IP6, + "Activation (%s) Stage 4 of 5 (IPv6 Configure Timeout) scheduled...", + nm_device_get_iface (self)); +} + +static void +share_child_setup (gpointer user_data G_GNUC_UNUSED) +{ + /* We are in the child process at this point */ + pid_t pid = getpid (); + setpgid (pid, pid); + + nm_unblock_posix_signals (NULL); +} + +static gboolean +share_init (void) +{ + int status; + char *modules[] = { "ip_tables", "iptable_nat", "nf_nat_ftp", "nf_nat_irc", + "nf_nat_sip", "nf_nat_tftp", "nf_nat_pptp", "nf_nat_h323", + NULL }; + char **iter; + + if (!nm_platform_sysctl_set ("/proc/sys/net/ipv4/ip_forward", "1")) { + nm_log_err (LOGD_SHARING, "Error starting IP forwarding: (%d) %s", + errno, strerror (errno)); + return FALSE; + } + + if (!nm_platform_sysctl_set ("/proc/sys/net/ipv4/ip_dynaddr", "1")) { + nm_log_err (LOGD_SHARING, "error starting IP forwarding: (%d) %s", + errno, strerror (errno)); + } + + for (iter = modules; *iter; iter++) { + char *argv[3] = { "/sbin/modprobe", *iter, NULL }; + char *envp[1] = { NULL }; + GError *error = NULL; + + if (!g_spawn_sync ("/", argv, envp, G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL, + share_child_setup, NULL, NULL, NULL, &status, &error)) { + nm_log_err (LOGD_SHARING, "error loading NAT module %s: (%d) %s", + *iter, error ? error->code : 0, + (error && error->message) ? error->message : "unknown"); + if (error) + g_error_free (error); + } + } + + return TRUE; +} + +static void +add_share_rule (NMActRequest *req, const char *table, const char *fmt, ...) +{ + va_list args; + char *cmd; + + va_start (args, fmt); + cmd = g_strdup_vprintf (fmt, args); + va_end (args); + + nm_act_request_add_share_rule (req, table, cmd); + g_free (cmd); +} + +static gboolean +start_sharing (NMDevice *self, NMIP4Config *config) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMActRequest *req; + GError *error = NULL; + char str_addr[INET_ADDRSTRLEN + 1]; + char str_mask[INET_ADDRSTRLEN + 1]; + guint32 netmask, network; + const NMPlatformIP4Address *ip4_addr; + const char *ip_iface; + + g_return_val_if_fail (config != NULL, FALSE); + + ip_iface = nm_device_get_ip_iface (self); + + ip4_addr = nm_ip4_config_get_address (config, 0); + if (!ip4_addr || !ip4_addr->address) + return FALSE; + + netmask = nm_utils_ip4_prefix_to_netmask (ip4_addr->plen); + if (!inet_ntop (AF_INET, &netmask, str_mask, sizeof (str_mask))) + return FALSE; + + network = ip4_addr->address & netmask; + if (!inet_ntop (AF_INET, &network, str_addr, sizeof (str_addr))) + return FALSE; + + if (!share_init ()) + return FALSE; + + req = nm_device_get_act_request (self); + g_assert (req); + + add_share_rule (req, "filter", "INPUT --in-interface %s --protocol tcp --destination-port 53 --jump ACCEPT", ip_iface); + add_share_rule (req, "filter", "INPUT --in-interface %s --protocol udp --destination-port 53 --jump ACCEPT", ip_iface); + add_share_rule (req, "filter", "INPUT --in-interface %s --protocol tcp --destination-port 67 --jump ACCEPT", ip_iface); + add_share_rule (req, "filter", "INPUT --in-interface %s --protocol udp --destination-port 67 --jump ACCEPT", ip_iface); + add_share_rule (req, "filter", "FORWARD --in-interface %s --jump REJECT", ip_iface); + add_share_rule (req, "filter", "FORWARD --out-interface %s --jump REJECT", ip_iface); + add_share_rule (req, "filter", "FORWARD --in-interface %s --out-interface %s --jump ACCEPT", ip_iface, ip_iface); + add_share_rule (req, "filter", "FORWARD --source %s/%s --in-interface %s --jump ACCEPT", str_addr, str_mask, ip_iface); + add_share_rule (req, "filter", "FORWARD --destination %s/%s --out-interface %s --match state --state ESTABLISHED,RELATED --jump ACCEPT", str_addr, str_mask, ip_iface); + add_share_rule (req, "nat", "POSTROUTING --source %s/%s ! --destination %s/%s --jump MASQUERADE", str_addr, str_mask, str_addr, str_mask); + + nm_act_request_set_shared (req, TRUE); + + if (!nm_dnsmasq_manager_start (priv->dnsmasq_manager, config, &error)) { + nm_log_err (LOGD_SHARING, "(%s/%s): failed to start dnsmasq: %s", + nm_device_get_iface (self), ip_iface, + (error && error->message) ? error->message : "(unknown)"); + g_error_free (error); + nm_act_request_set_shared (req, FALSE); + return FALSE; + } + + priv->dnsmasq_state_id = g_signal_connect (priv->dnsmasq_manager, "state-changed", + G_CALLBACK (dnsmasq_state_changed_cb), + self); + return TRUE; +} + +static void +send_arps (NMDevice *self, const char *mode_arg) +{ + const char *argv[] = { "/sbin/arping", mode_arg, "-q", "-I", nm_device_get_ip_iface (self), "-c", "1", NULL, NULL }; + int ip_arg = G_N_ELEMENTS (argv) - 2; + NMConnection *connection; + NMSettingIP4Config *s_ip4; + int i, num; + NMIP4Address *addr; + guint32 ipaddr; + GError *error = NULL; + + connection = nm_device_get_connection (self); + if (!connection) + return; + s_ip4 = nm_connection_get_setting_ip4_config (connection); + if (!s_ip4) + return; + num = nm_setting_ip4_config_get_num_addresses (s_ip4); + + for (i = 0; i < num; i++) { + addr = nm_setting_ip4_config_get_address (s_ip4, i); + ipaddr = nm_ip4_address_get_address (addr); + argv[ip_arg] = (char *) nm_utils_inet4_ntop (ipaddr, NULL); + + nm_log_dbg (LOGD_DEVICE | LOGD_IP4, + "Running arping %s -I %s %s", + mode_arg, nm_device_get_iface (self), argv[ip_arg]); + g_spawn_async (NULL, (char **) argv, NULL, + G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL, + nm_unblock_posix_signals, + NULL, NULL, &error); + if (error) { + nm_log_warn (LOGD_DEVICE | LOGD_IP4, + "Could not send ARP for local address %s: %s", + argv[ip_arg], error->message); + g_clear_error (&error); + } + } +} + +static gboolean +arp_announce_round2 (gpointer self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + + priv->arp_round2_id = 0; + + if ( priv->state >= NM_DEVICE_STATE_IP_CONFIG + && priv->state <= NM_DEVICE_STATE_ACTIVATED) + send_arps (self, "-U"); + + return G_SOURCE_REMOVE; +} + +static void +arp_cleanup (NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + + if (priv->arp_round2_id) { + g_source_remove (priv->arp_round2_id); + priv->arp_round2_id = 0; + } +} + +static void +arp_announce (NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMConnection *connection; + NMSettingIP4Config *s_ip4; + int num; + + arp_cleanup (self); + + /* We only care about manually-configured addresses; DHCP- and autoip-configured + * ones should already have been seen on the network at this point. + */ + connection = nm_device_get_connection (self); + if (!connection) + return; + s_ip4 = nm_connection_get_setting_ip4_config (connection); + if (!s_ip4) + return; + num = nm_setting_ip4_config_get_num_addresses (s_ip4); + if (num == 0) + return; + + send_arps (self, "-A"); + priv->arp_round2_id = g_timeout_add_seconds (2, arp_announce_round2, self); +} + +static gboolean +nm_device_activate_ip4_config_commit (gpointer user_data) +{ + NMDevice *self = NM_DEVICE (user_data); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMActRequest *req; + const char *iface, *method; + NMConnection *connection; + NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; + + /* Clear the activation source ID now that this stage has run */ + activation_source_clear (self, FALSE, AF_INET); + + iface = nm_device_get_iface (self); + nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 5 of 5 (IPv4 Commit) started...", + iface); + + req = nm_device_get_act_request (self); + g_assert (req); + connection = nm_act_request_get_connection (req); + g_assert (connection); + + /* Device should be up before we can do anything with it */ + if (!nm_platform_link_is_up (nm_device_get_ip_ifindex (self))) { + nm_log_warn (LOGD_DEVICE, "(%s): interface %s not up for IP configuration", + iface, nm_device_get_ip_iface (self)); + } + + /* NULL to use the existing priv->dev_ip4_config */ + if (!ip4_config_merge_and_apply (self, NULL, TRUE, &reason)) { + nm_log_info (LOGD_DEVICE | LOGD_IP4, + "Activation (%s) Stage 5 of 5 (IPv4 Commit) failed", + iface); + nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); + goto out; + } + + /* Start IPv4 sharing if we need it */ + method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP4_CONFIG); + + if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_SHARED) == 0) { + if (!start_sharing (self, priv->ip4_config)) { + nm_log_warn (LOGD_SHARING, "Activation (%s) Stage 5 of 5 (IPv4 Commit) start sharing failed.", iface); + nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_SHARED_START_FAILED); + goto out; + } + } + + /* If IPv4 wasn't the first to complete, and DHCP was used, then ensure + * dispatcher scripts get the DHCP lease information. + */ + if ( priv->dhcp4_client + && nm_device_activate_ip4_state_in_conf (self) + && (nm_device_get_state (self) > NM_DEVICE_STATE_IP_CONFIG)) { + /* Notify dispatcher scripts of new DHCP4 config */ + nm_dispatcher_call (DISPATCHER_ACTION_DHCP4_CHANGE, + nm_device_get_connection (self), + self, + NULL, + NULL, + NULL); + } + + arp_announce (self); + + /* Enter the IP_CHECK state if this is the first method to complete */ + priv->ip4_state = IP_DONE; + + nm_device_remove_pending_action (self, PENDING_ACTION_DHCP4, FALSE); + + if (nm_device_get_state (self) == NM_DEVICE_STATE_IP_CONFIG) + nm_device_state_changed (self, NM_DEVICE_STATE_IP_CHECK, NM_DEVICE_STATE_REASON_NONE); + +out: + nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 5 of 5 (IPv4 Commit) complete.", + iface); + + return FALSE; +} + +void +nm_device_activate_schedule_ip4_config_result (NMDevice *self, NMIP4Config *config) +{ + NMDevicePrivate *priv; + + g_return_if_fail (NM_IS_DEVICE (self)); + g_return_if_fail (NM_IS_IP4_CONFIG (config)); + priv = NM_DEVICE_GET_PRIVATE (self); + + g_clear_object (&priv->dev_ip4_config); + priv->dev_ip4_config = g_object_ref (config); + + activation_source_schedule (self, nm_device_activate_ip4_config_commit, AF_INET); + + nm_log_info (LOGD_DEVICE | LOGD_IP4, + "Activation (%s) Stage 5 of 5 (IPv4 Configure Commit) scheduled...", + nm_device_get_iface (self)); +} + +gboolean +nm_device_activate_ip4_state_in_conf (NMDevice *self) +{ + g_return_val_if_fail (self != NULL, FALSE); + return NM_DEVICE_GET_PRIVATE (self)->ip4_state == IP_CONF; +} + +gboolean +nm_device_activate_ip4_state_in_wait (NMDevice *self) +{ + g_return_val_if_fail (self != NULL, FALSE); + return NM_DEVICE_GET_PRIVATE (self)->ip4_state == IP_WAIT; +} + +static gboolean +nm_device_activate_ip6_config_commit (gpointer user_data) +{ + NMDevice *self = NM_DEVICE (user_data); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + guint level = (priv->ip6_state == IP_DONE) ? LOGL_DEBUG : LOGL_INFO; + NMActRequest *req; + const char *iface; + NMConnection *connection; + NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; + + /* Clear the activation source ID now that this stage has run */ + activation_source_clear (self, FALSE, AF_INET6); + + iface = nm_device_get_iface (self); + nm_log (LOGD_DEVICE, level, "Activation (%s) Stage 5 of 5 (IPv6 Commit) started...", iface); + + req = nm_device_get_act_request (self); + g_assert (req); + connection = nm_act_request_get_connection (req); + g_assert (connection); + + /* Device should be up before we can do anything with it */ + g_warn_if_fail (nm_platform_link_is_up (nm_device_get_ip_ifindex (self))); + + /* Allow setting MTU etc */ + if (NM_DEVICE_GET_CLASS (self)->ip6_config_pre_commit) + NM_DEVICE_GET_CLASS (self)->ip6_config_pre_commit (self); + + if (ip6_config_merge_and_apply (self, TRUE, &reason)) { + /* If IPv6 wasn't the first IP to complete, and DHCP was used, + * then ensure dispatcher scripts get the DHCP lease information. + */ + if ( priv->dhcp6_client + && nm_device_activate_ip6_state_in_conf (self) + && (nm_device_get_state (self) > NM_DEVICE_STATE_IP_CONFIG)) { + /* Notify dispatcher scripts of new DHCP6 config */ + nm_dispatcher_call (DISPATCHER_ACTION_DHCP6_CHANGE, + nm_device_get_connection (self), + self, + NULL, + NULL, + NULL); + } + + /* Enter the IP_CHECK state if this is the first method to complete */ + priv->ip6_state = IP_DONE; + + nm_device_remove_pending_action (self, PENDING_ACTION_DHCP6, FALSE); + nm_device_remove_pending_action (self, PENDING_ACTION_AUTOCONF6, FALSE); + + if (nm_device_get_state (self) == NM_DEVICE_STATE_IP_CONFIG) + nm_device_state_changed (self, NM_DEVICE_STATE_IP_CHECK, NM_DEVICE_STATE_REASON_NONE); + } else { + nm_log_warn (LOGD_DEVICE | LOGD_IP6, + "Activation (%s) Stage 5 of 5 (IPv6 Commit) failed", + iface); + nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); + } + + nm_log (LOGD_DEVICE, level, "Activation (%s) Stage 5 of 5 (IPv6 Commit) complete.", iface); + + return FALSE; +} + +void +nm_device_activate_schedule_ip6_config_result (NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + guint level = (priv->ip6_state == IP_DONE) ? LOGL_DEBUG : LOGL_INFO; + + g_return_if_fail (NM_IS_DEVICE (self)); + + activation_source_schedule (self, nm_device_activate_ip6_config_commit, AF_INET6); + + nm_log (LOGD_DEVICE | LOGD_IP6, level, + "Activation (%s) Stage 5 of 5 (IPv6 Commit) scheduled...", + nm_device_get_iface (self)); +} + +gboolean +nm_device_activate_ip6_state_in_conf (NMDevice *self) +{ + g_return_val_if_fail (self != NULL, FALSE); + return NM_DEVICE_GET_PRIVATE (self)->ip6_state == IP_CONF; +} + +gboolean +nm_device_activate_ip6_state_in_wait (NMDevice *self) +{ + g_return_val_if_fail (self != NULL, FALSE); + return NM_DEVICE_GET_PRIVATE (self)->ip6_state == IP_WAIT; +} + +static void +clear_act_request (NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + + if (!priv->act_request) + return; + + nm_active_connection_set_default (NM_ACTIVE_CONNECTION (priv->act_request), FALSE); + + if (priv->master_ready_id) { + g_signal_handler_disconnect (priv->act_request, priv->master_ready_id); + priv->master_ready_id = 0; + } + + g_clear_object (&priv->act_request); + g_object_notify (G_OBJECT (self), NM_DEVICE_ACTIVE_CONNECTION); +} + +static void +dnsmasq_cleanup (NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + + if (!priv->dnsmasq_manager) + return; + + if (priv->dnsmasq_state_id) { + g_signal_handler_disconnect (priv->dnsmasq_manager, priv->dnsmasq_state_id); + priv->dnsmasq_state_id = 0; + } + + nm_dnsmasq_manager_stop (priv->dnsmasq_manager); + g_object_unref (priv->dnsmasq_manager); + priv->dnsmasq_manager = NULL; +} + +static void +_update_ip4_address (NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + struct ifreq req; + guint32 new_address; + int fd; + + g_return_if_fail (self != NULL); + + fd = socket (PF_INET, SOCK_DGRAM, 0); + if (fd < 0) { + nm_log_err (LOGD_IP4, "couldn't open control socket."); + return; + } + + memset (&req, 0, sizeof (struct ifreq)); + strncpy (req.ifr_name, nm_device_get_ip_iface (self), IFNAMSIZ); + if (ioctl (fd, SIOCGIFADDR, &req) == 0) { + new_address = ((struct sockaddr_in *)(&req.ifr_addr))->sin_addr.s_addr; + if (new_address != priv->ip4_address) + priv->ip4_address = new_address; + } + close (fd); +} + +gboolean +nm_device_get_is_nm_owned (NMDevice *device) +{ + return NM_DEVICE_GET_PRIVATE (device)->is_nm_owned; +} + +void +nm_device_set_nm_owned (NMDevice *device) +{ + g_return_if_fail (NM_IS_DEVICE (device)); + + NM_DEVICE_GET_PRIVATE (device)->is_nm_owned = TRUE; +} + +/* + * delete_on_deactivate_link_delete + * + * Function will be queued with g_idle_add to call + * nm_platform_link_delete for the underlying resources + * of the device. + */ +static gboolean +delete_on_deactivate_link_delete (gpointer user_data) +{ + DeleteOnDeactivateData *data = user_data; + + if (data->device) { + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (data->device); + + g_object_remove_weak_pointer (G_OBJECT (data->device), (void **) &data->device); + priv->delete_on_deactivate_data = NULL; + } + + nm_log_dbg (LOGD_DEVICE, "delete_on_deactivate: cleanup and delete virtual link #%d (id=%u)", + data->ifindex, data->idle_add_id); + nm_platform_link_delete (data->ifindex); + g_free (data); + return FALSE; +} + +static void +delete_on_deactivate_unschedule (NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + + if (priv->delete_on_deactivate_data) { + DeleteOnDeactivateData *data = priv->delete_on_deactivate_data; + + priv->delete_on_deactivate_data = NULL; + + g_source_remove (data->idle_add_id); + g_object_remove_weak_pointer (G_OBJECT (self), (void **) &data->device); + nm_log_dbg (LOGD_DEVICE, "delete_on_deactivate: cancel cleanup and delete virtual link #%d (id=%u)", + data->ifindex, data->idle_add_id); + g_free (data); + } +} + +static void +delete_on_deactivate_check_and_schedule (NMDevice *self, int ifindex) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + DeleteOnDeactivateData *data; + + if (ifindex <= 0) + return; + if (!priv->is_nm_owned) + return; + if (!nm_device_is_software (self)) + return; + if (nm_device_get_state (self) == NM_DEVICE_STATE_UNMANAGED) + return; + if (nm_device_get_state (self) == NM_DEVICE_STATE_UNAVAILABLE) + return; + delete_on_deactivate_unschedule (self); /* always cancel and reschedule */ + + data = g_new (DeleteOnDeactivateData, 1); + g_object_add_weak_pointer (G_OBJECT (self), (void **) &data->device); + data->device = self; + data->ifindex = ifindex; + data->idle_add_id = g_idle_add (delete_on_deactivate_link_delete, data); + priv->delete_on_deactivate_data = data; + + nm_log_dbg (LOGD_DEVICE, "delete_on_deactivate: schedule cleanup and delete virtual link #%d for [%s] (id=%u)", + ifindex, nm_device_get_iface (self), data->idle_add_id); +} + +static void +disconnect_cb (NMDevice *device, + DBusGMethodInvocation *context, + GError *error, + gpointer user_data) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); + GError *local = NULL; + + if (error) { + dbus_g_method_return_error (context, error); + return; + } + + /* Authorized */ + if (priv->state <= NM_DEVICE_STATE_DISCONNECTED) { + local = g_error_new_literal (NM_DEVICE_ERROR, + NM_DEVICE_ERROR_NOT_ACTIVE, + "Device is not active"); + dbus_g_method_return_error (context, local); + g_error_free (local); + } else { + priv->autoconnect = FALSE; + + nm_device_state_changed (device, + NM_DEVICE_STATE_DEACTIVATING, + NM_DEVICE_STATE_REASON_USER_REQUESTED); + dbus_g_method_return (context); + } +} + +static void +impl_device_disconnect (NMDevice *device, DBusGMethodInvocation *context) +{ + NMConnection *connection; + GError *error = NULL; + + if (NM_DEVICE_GET_PRIVATE (device)->act_request == NULL) { + error = g_error_new_literal (NM_DEVICE_ERROR, + NM_DEVICE_ERROR_NOT_ACTIVE, + "This device is not active"); + dbus_g_method_return_error (context, error); + g_error_free (error); + return; + } + + connection = nm_device_get_connection (device); + g_assert (connection); + + /* Ask the manager to authenticate this request for us */ + g_signal_emit (device, signals[AUTH_REQUEST], 0, + context, + connection, + NM_AUTH_PERMISSION_NETWORK_CONTROL, + TRUE, + disconnect_cb, + NULL); +} + +static void +_device_activate (NMDevice *self, NMActRequest *req) +{ + NMDevicePrivate *priv; + NMConnection *connection; + + g_return_if_fail (NM_IS_DEVICE (self)); + g_return_if_fail (NM_IS_ACT_REQUEST (req)); + + priv = NM_DEVICE_GET_PRIVATE (self); + + connection = nm_act_request_get_connection (req); + g_assert (connection); + + nm_log_info (LOGD_DEVICE, "Activation (%s) starting connection '%s'", + nm_device_get_iface (self), + nm_connection_get_id (connection)); + + delete_on_deactivate_unschedule (self); + + /* Move default unmanaged devices to DISCONNECTED state here */ + if (nm_device_get_default_unmanaged (self) && priv->state == NM_DEVICE_STATE_UNMANAGED) { + nm_device_state_changed (self, + NM_DEVICE_STATE_DISCONNECTED, + NM_DEVICE_STATE_REASON_NOW_MANAGED); + } + + /* note: don't notify D-Bus of the new AC here, but do it later when + * changing state to PREPARE so that the two properties change together. + */ + priv->act_request = g_object_ref (req); + + nm_device_activate_schedule_stage1_device_prepare (self); +} + +void +nm_device_queue_activation (NMDevice *self, NMActRequest *req) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + + if (!priv->act_request) { + /* Just activate immediately */ + _device_activate (self, req); + return; + } + + /* supercede any already-queued request */ + g_clear_object (&priv->queued_act_request); + priv->queued_act_request = g_object_ref (req); + + /* Deactivate existing activation request first */ + nm_log_info (LOGD_DEVICE, "(%s): disconnecting for new activation request.", + nm_device_get_iface (self)); + nm_device_state_changed (self, + NM_DEVICE_STATE_DEACTIVATING, + NM_DEVICE_STATE_REASON_NONE); +} + +/* + * nm_device_is_activating + * + * Return whether or not the device is currently activating itself. + * + */ +gboolean +nm_device_is_activating (NMDevice *device) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); + NMDeviceState state; + + g_return_val_if_fail (NM_IS_DEVICE (device), FALSE); + + state = nm_device_get_state (device); + if (state >= NM_DEVICE_STATE_PREPARE && state <= NM_DEVICE_STATE_SECONDARIES) + return TRUE; + + /* There's a small race between the time when stage 1 is scheduled + * and when the device actually sets STATE_PREPARE when the activation + * handler is actually run. If there's an activation handler scheduled + * we're activating anyway. + */ + return priv->act_source_id ? TRUE : FALSE; +} + +/* IP Configuration stuff */ + +NMDHCP4Config * +nm_device_get_dhcp4_config (NMDevice *self) +{ + g_return_val_if_fail (NM_IS_DEVICE (self), NULL); + + return NM_DEVICE_GET_PRIVATE (self)->dhcp4_config; +} + +NMIP4Config * +nm_device_get_ip4_config (NMDevice *self) +{ + g_return_val_if_fail (NM_IS_DEVICE (self), NULL); + + return NM_DEVICE_GET_PRIVATE (self)->ip4_config; +} + + +static gboolean +nm_device_set_ip4_config (NMDevice *self, + NMIP4Config *new_config, + gboolean commit, + NMDeviceStateReason *reason) +{ + NMDevicePrivate *priv; + const char *ip_iface; + NMIP4Config *old_config = NULL; + gboolean has_changes = FALSE; + gboolean success = TRUE; + NMDeviceStateReason reason_local = NM_DEVICE_STATE_REASON_NONE; + int ip_ifindex; + + g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); + + priv = NM_DEVICE_GET_PRIVATE (self); + ip_iface = nm_device_get_ip_iface (self); + ip_ifindex = nm_device_get_ip_ifindex (self); + + old_config = priv->ip4_config; + + /* Always commit to nm-platform to update lifetimes */ + if (commit && new_config) { + success = nm_ip4_config_commit (new_config, ip_ifindex); + if (!success) + reason_local = NM_DEVICE_STATE_REASON_CONFIG_FAILED; + } + + if (new_config) { + if (old_config) { + /* has_changes is set only on relevant changes, because when the configuration changes, + * this causes a re-read and reset. This should only happen for relevant changes */ + nm_ip4_config_replace (old_config, new_config, &has_changes); + if (has_changes) { + nm_log_dbg (LOGD_IP4, "(%s): update IP4Config instance (%s)", + ip_iface, nm_ip4_config_get_dbus_path (old_config)); + } + } else { + has_changes = TRUE; + priv->ip4_config = g_object_ref (new_config); + + if (success && !nm_ip4_config_get_dbus_path (new_config)) { + /* Export over D-Bus */ + nm_ip4_config_export (new_config); + } + + nm_log_dbg (LOGD_IP4, "(%s): set IP4Config instance (%s)", + ip_iface, nm_ip4_config_get_dbus_path (new_config)); + } + } else if (old_config) { + has_changes = TRUE; + priv->ip4_config = NULL; + nm_log_dbg (LOGD_IP4, "(%s): clear IP4Config instance (%s)", + ip_iface, nm_ip4_config_get_dbus_path (old_config)); + /* Device config is invalid if combined config is invalid */ + g_clear_object (&priv->dev_ip4_config); + } + + if (has_changes) { + _update_ip4_address (self); + + if (old_config != priv->ip4_config) + g_object_notify (G_OBJECT (self), NM_DEVICE_IP4_CONFIG); + g_signal_emit (self, signals[IP4_CONFIG_CHANGED], 0, priv->ip4_config, old_config); + + if (old_config != priv->ip4_config && old_config) + g_object_unref (old_config); + + if (nm_device_uses_generated_connection (self)) { + NMConnection *connection = nm_device_get_connection (self); + NMSetting *s_ip4; + + g_object_freeze_notify (G_OBJECT (connection)); + nm_connection_remove_setting (connection, NM_TYPE_SETTING_IP4_CONFIG); + s_ip4 = nm_ip4_config_create_setting (priv->ip4_config); + nm_connection_add_setting (connection, s_ip4); + g_object_thaw_notify (G_OBJECT (connection)); + } + + nm_device_queue_recheck_assume (self); + } + + if (reason) + *reason = reason_local; + + return success; +} + +void +nm_device_set_vpn4_config (NMDevice *device, NMIP4Config *config) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); + + if (priv->vpn4_config == config) + return; + + g_clear_object (&priv->vpn4_config); + if (config) + priv->vpn4_config = g_object_ref (config); + + /* NULL to use existing configs */ + if (!ip4_config_merge_and_apply (device, NULL, TRUE, NULL)) { + nm_log_warn (LOGD_IP4, "(%s): failed to set VPN routes for device", + nm_device_get_ip_iface (device)); + } +} + +static gboolean +nm_device_set_ip6_config (NMDevice *self, + NMIP6Config *new_config, + gboolean commit, + NMDeviceStateReason *reason) +{ + NMDevicePrivate *priv; + const char *ip_iface; + NMIP6Config *old_config = NULL; + gboolean has_changes = FALSE; + gboolean success = TRUE; + NMDeviceStateReason reason_local = NM_DEVICE_STATE_REASON_NONE; + int ip_ifindex; + + g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); + + priv = NM_DEVICE_GET_PRIVATE (self); + ip_iface = nm_device_get_ip_iface (self); + ip_ifindex = nm_device_get_ip_ifindex (self); + + old_config = priv->ip6_config; + + /* Always commit to nm-platform to update lifetimes */ + if (commit && new_config) { + success = nm_ip6_config_commit (new_config, ip_ifindex); + if (!success) + reason_local = NM_DEVICE_STATE_REASON_CONFIG_FAILED; + } + + if (new_config) { + if (old_config) { + /* has_changes is set only on relevant changes, because when the configuration changes, + * this causes a re-read and reset. This should only happen for relevant changes */ + nm_ip6_config_replace (old_config, new_config, &has_changes); + if (has_changes) { + nm_log_dbg (LOGD_IP6, "(%s): update IP6Config instance (%s)", + ip_iface, nm_ip6_config_get_dbus_path (old_config)); + } + } else { + has_changes = TRUE; + priv->ip6_config = g_object_ref (new_config); + + if (success && !nm_ip6_config_get_dbus_path (new_config)) { + /* Export over D-Bus */ + nm_ip6_config_export (new_config); + } + + nm_log_dbg (LOGD_IP4, "(%s): set IP6Config instance (%s)", + ip_iface, nm_ip6_config_get_dbus_path (new_config)); + } + } else if (old_config) { + has_changes = TRUE; + priv->ip6_config = NULL; + nm_log_dbg (LOGD_IP6, "(%s): clear IP6Config instance (%s)", + ip_iface, nm_ip6_config_get_dbus_path (old_config)); + } + + if (has_changes) { + if (old_config != priv->ip6_config) + g_object_notify (G_OBJECT (self), NM_DEVICE_IP6_CONFIG); + g_signal_emit (self, signals[IP6_CONFIG_CHANGED], 0, priv->ip6_config, old_config); + + if (old_config != priv->ip6_config && old_config) + g_object_unref (old_config); + + if (nm_device_uses_generated_connection (self)) { + NMConnection *connection = nm_device_get_connection (self); + NMSetting *s_ip6; + + g_object_freeze_notify (G_OBJECT (connection)); + nm_connection_remove_setting (connection, NM_TYPE_SETTING_IP6_CONFIG); + s_ip6 = nm_ip6_config_create_setting (priv->ip6_config); + nm_connection_add_setting (connection, s_ip6); + g_object_thaw_notify (G_OBJECT (connection)); + } + + nm_device_queue_recheck_assume (self); + } + + if (reason) + *reason = reason_local; + + return success; +} + +void +nm_device_set_vpn6_config (NMDevice *device, NMIP6Config *config) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); + + if (priv->vpn6_config == config) + return; + + g_clear_object (&priv->vpn6_config); + if (config) + priv->vpn6_config = g_object_ref (config); + + /* NULL to use existing configs */ + if (!ip6_config_merge_and_apply (device, TRUE, NULL)) { + nm_log_warn (LOGD_IP6, "(%s): failed to set VPN routes for device", + nm_device_get_ip_iface (device)); + } +} + +NMDHCP6Config * +nm_device_get_dhcp6_config (NMDevice *self) +{ + g_return_val_if_fail (NM_IS_DEVICE (self), NULL); + + return NM_DEVICE_GET_PRIVATE (self)->dhcp6_config; +} + +NMIP6Config * +nm_device_get_ip6_config (NMDevice *self) +{ + g_return_val_if_fail (NM_IS_DEVICE (self), NULL); + + return NM_DEVICE_GET_PRIVATE (self)->ip6_config; +} + +/****************************************************************/ + +static void +dispatcher_cleanup (NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + + if (priv->dispatcher.call_id) { + nm_dispatcher_call_cancel (priv->dispatcher.call_id); + priv->dispatcher.call_id = 0; + priv->dispatcher.post_state = NM_DEVICE_STATE_UNKNOWN; + priv->dispatcher.post_state_reason = NM_DEVICE_STATE_REASON_NONE; + } +} + +static void +dispatcher_complete_proceed_state (guint call_id, gpointer user_data) +{ + NMDevice *self = NM_DEVICE (user_data); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + + g_return_if_fail (call_id == priv->dispatcher.call_id); + + priv->dispatcher.call_id = 0; + nm_device_queue_state (self, priv->dispatcher.post_state, + priv->dispatcher.post_state_reason); + priv->dispatcher.post_state = NM_DEVICE_STATE_UNKNOWN; + priv->dispatcher.post_state_reason = NM_DEVICE_STATE_REASON_NONE; +} + +/****************************************************************/ + +static void +ip_check_pre_up (NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + + if (priv->dispatcher.call_id != 0) { + g_warn_if_reached (); + dispatcher_cleanup (self); + } + + priv->dispatcher.post_state = NM_DEVICE_STATE_SECONDARIES; + priv->dispatcher.post_state_reason = NM_DEVICE_STATE_REASON_NONE; + if (!nm_dispatcher_call (DISPATCHER_ACTION_PRE_UP, + nm_device_get_connection (self), + self, + dispatcher_complete_proceed_state, + self, + &priv->dispatcher.call_id)) { + /* Just proceed on errors */ + dispatcher_complete_proceed_state (0, self); + } +} + +static void +ip_check_gw_ping_cleanup (NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + + if (priv->gw_ping.watch) { + g_source_remove (priv->gw_ping.watch); + priv->gw_ping.watch = 0; + } + if (priv->gw_ping.timeout) { + g_source_remove (priv->gw_ping.timeout); + priv->gw_ping.timeout = 0; + } + + if (priv->gw_ping.pid) { + guint count = 20; + int status; + + kill (priv->gw_ping.pid, SIGKILL); + do { + if (waitpid (priv->gw_ping.pid, &status, WNOHANG) != 0) + break; + g_usleep (G_USEC_PER_SEC / 20); + } while (count--); + + priv->gw_ping.pid = 0; + } +} + +static void +ip_check_ping_watch_cb (GPid pid, gint status, gpointer user_data) +{ + NMDevice *self = NM_DEVICE (user_data); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + const char *iface; + guint log_domain = priv->gw_ping.log_domain; + + if (!priv->gw_ping.watch) + return; + priv->gw_ping.watch = 0; + priv->gw_ping.pid = 0; + + iface = nm_device_get_iface (self); + + if (WIFEXITED (status)) { + if (WEXITSTATUS (status) == 0) + nm_log_dbg (log_domain, "(%s): gateway ping succeeded", iface); + else { + nm_log_warn (log_domain, "(%s): gateway ping failed with error code %d", + iface, WEXITSTATUS (status)); + } + } else + nm_log_warn (log_domain, "(%s): ping stopped unexpectedly with status %d", iface, status); + + /* We've got connectivity, proceed to pre_up */ + ip_check_gw_ping_cleanup (self); + ip_check_pre_up (self); +} + +static gboolean +ip_check_ping_timeout_cb (gpointer user_data) +{ + NMDevice *self = NM_DEVICE (user_data); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + + priv->gw_ping.timeout = 0; + + nm_log_warn (priv->gw_ping.log_domain, "(%s): gateway ping timed out", + nm_device_get_iface (self)); + + ip_check_gw_ping_cleanup (self); + ip_check_pre_up (self); + return FALSE; +} + +static gboolean +spawn_ping (NMDevice *self, + guint log_domain, + const char *binary, + const char *address, + guint timeout) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + const char *args[] = { binary, "-I", nm_device_get_ip_iface (self), "-c", "1", "-w", NULL, address, NULL }; + GError *error = NULL; + char *str_timeout, *cmd; + gboolean success; + + g_return_val_if_fail (priv->gw_ping.watch == 0, FALSE); + g_return_val_if_fail (priv->gw_ping.timeout == 0, FALSE); + + args[6] = str_timeout = g_strdup_printf ("%u", timeout); + + if (nm_logging_enabled (LOGL_DEBUG, log_domain)) { + cmd = g_strjoinv (" ", (gchar **) args); + nm_log_dbg (log_domain, "(%s): running '%s'", + nm_device_get_iface (self), + cmd); + g_free (cmd); + } + + success = g_spawn_async ("/", + (gchar **) args, + NULL, + G_SPAWN_DO_NOT_REAP_CHILD, + nm_unblock_posix_signals, + NULL, + &priv->gw_ping.pid, + &error); + if (success) { + priv->gw_ping.log_domain = log_domain; + priv->gw_ping.watch = g_child_watch_add (priv->gw_ping.pid, ip_check_ping_watch_cb, self); + priv->gw_ping.timeout = g_timeout_add_seconds (timeout + 1, ip_check_ping_timeout_cb, self); + } else { + nm_log_warn (log_domain, "could not spawn %s: %s", binary, error->message); + g_clear_error (&error); + } + + g_free (str_timeout); + return success; +} + +static void +nm_device_start_ip_check (NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMConnection *connection; + NMSettingConnection *s_con; + guint timeout = 0; + const char *ping_binary = NULL; + char buf[INET6_ADDRSTRLEN] = { 0 }; + guint log_domain = LOGD_IP4; + + /* Shouldn't be any active ping here, since IP_CHECK happens after the + * first IP method completes. Any subsequently completing IP method doesn't + * get checked. + */ + g_assert (!priv->gw_ping.watch); + g_assert (!priv->gw_ping.timeout); + g_assert (!priv->gw_ping.pid); + g_assert (priv->ip4_state == IP_DONE || priv->ip6_state == IP_DONE); + + connection = nm_device_get_connection (self); + g_assert (connection); + + s_con = nm_connection_get_setting_connection (connection); + g_assert (s_con); + timeout = nm_setting_connection_get_gateway_ping_timeout (s_con); + + if (timeout) { + if (priv->ip4_state == IP_DONE) { + guint gw = 0; + + ping_binary = "/usr/bin/ping"; + log_domain = LOGD_IP4; + + gw = nm_ip4_config_get_gateway (priv->ip4_config); + if (gw && !inet_ntop (AF_INET, &gw, buf, sizeof (buf))) + buf[0] = '\0'; + } else if (priv->ip6_config && priv->ip6_state == IP_DONE) { + const struct in6_addr *gw = NULL; + + ping_binary = "/usr/bin/ping6"; + log_domain = LOGD_IP6; + + gw = nm_ip6_config_get_gateway (priv->ip6_config); + if (gw && !inet_ntop (AF_INET6, gw, buf, sizeof (buf))) + buf[0] = '\0'; + } + } + + if (buf[0]) + spawn_ping (self, log_domain, ping_binary, buf, timeout); + + /* If no ping was started, just advance to pre_up */ + if (!priv->gw_ping.pid) + ip_check_pre_up (self); +} + +/****************************************************************/ + +static gboolean +carrier_wait_timeout (gpointer user_data) +{ + NMDevice *self = NM_DEVICE (user_data); + + NM_DEVICE_GET_PRIVATE (self)->carrier_wait_id = 0; + nm_device_remove_pending_action (self, "carrier wait", TRUE); + return G_SOURCE_REMOVE; +} + +static gboolean +nm_device_is_up (NMDevice *self) +{ + g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); + + if (NM_DEVICE_GET_CLASS (self)->is_up) + return NM_DEVICE_GET_CLASS (self)->is_up (self); + + return TRUE; +} + +static gboolean +is_up (NMDevice *device) +{ + int ifindex = nm_device_get_ip_ifindex (device); + + return ifindex > 0 ? nm_platform_link_is_up (ifindex) : TRUE; +} + +gboolean +nm_device_bring_up (NMDevice *self, gboolean block, gboolean *no_firmware) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + gboolean device_is_up = FALSE; + + g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); + + nm_log_dbg (LOGD_HW, "(%s): bringing up device.", nm_device_get_iface (self)); + + if (NM_DEVICE_GET_CLASS (self)->bring_up) { + if (!NM_DEVICE_GET_CLASS (self)->bring_up (self, no_firmware)) + return FALSE; + } + + device_is_up = nm_device_is_up (self); + if (block && !device_is_up) { + int ifindex = nm_device_get_ip_ifindex (self); + gint64 wait_until = nm_utils_get_monotonic_timestamp_us () + 10000 /* microseconds */; + + do { + g_usleep (200); + if (!nm_platform_link_refresh (ifindex)) + return FALSE; + device_is_up = nm_device_is_up (self); + } while (!device_is_up && nm_utils_get_monotonic_timestamp_us () < wait_until); + } + + if (!device_is_up) { + if (block) + nm_log_warn (LOGD_HW, "(%s): device not up after timeout!", nm_device_get_iface (self)); + else + nm_log_dbg (LOGD_HW, "(%s): device not up immediately", nm_device_get_iface (self)); + return FALSE; + } + + /* Devices that support carrier detect must be IFF_UP to report carrier + * changes; so after setting the device IFF_UP we must suppress startup + * complete (via a pending action) until either the carrier turns on, or + * a timeout is reached. + */ + if (device_has_capability (self, NM_DEVICE_CAP_CARRIER_DETECT)) { + if (priv->carrier_wait_id) { + g_source_remove (priv->carrier_wait_id); + nm_device_remove_pending_action (self, "carrier wait", TRUE); + } + priv->carrier_wait_id = g_timeout_add_seconds (5, carrier_wait_timeout, self); + nm_device_add_pending_action (self, "carrier wait", TRUE); + } + + /* Can only get HW address of some devices when they are up */ + nm_device_update_hw_address (self); + + _update_ip4_address (self); + return TRUE; +} + +static void +check_carrier (NMDevice *device) +{ + int ifindex = nm_device_get_ip_ifindex (device); + + if (!device_has_capability (device, NM_DEVICE_CAP_NONSTANDARD_CARRIER)) + nm_device_set_carrier (device, nm_platform_link_is_connected (ifindex)); +} + +static gboolean +bring_up (NMDevice *device, gboolean *no_firmware) +{ + int ifindex = nm_device_get_ip_ifindex (device); + gboolean result; + + if (ifindex <= 0) { + if (no_firmware) + *no_firmware = FALSE; + return TRUE; + } + + result = nm_platform_link_set_up (ifindex); + if (no_firmware) + *no_firmware = nm_platform_get_error () == NM_PLATFORM_ERROR_NO_FIRMWARE; + + /* Store carrier immediately. */ + if (result && device_has_capability (device, NM_DEVICE_CAP_CARRIER_DETECT)) + check_carrier (device); + + return result; +} + +void +nm_device_take_down (NMDevice *self, gboolean block) +{ + gboolean device_is_up; + + g_return_if_fail (NM_IS_DEVICE (self)); + + nm_log_dbg (LOGD_HW, "(%s): taking down device.", nm_device_get_iface (self)); + + if (NM_DEVICE_GET_CLASS (self)->take_down) { + if (!NM_DEVICE_GET_CLASS (self)->take_down (self)) + return; + } + + device_is_up = nm_device_is_up (self); + if (block && device_is_up) { + int ifindex = nm_device_get_ip_ifindex (self); + gint64 wait_until = nm_utils_get_monotonic_timestamp_us () + 10000 /* microseconds */; + + do { + g_usleep (200); + if (!nm_platform_link_refresh (ifindex)) + return; + device_is_up = nm_device_is_up (self); + } while (device_is_up && nm_utils_get_monotonic_timestamp_us () < wait_until); + } + + if (device_is_up) { + if (block) + nm_log_warn (LOGD_HW, "(%s): device not down after timeout!", nm_device_get_iface (self)); + else + nm_log_dbg (LOGD_HW, "(%s): device not down immediately", nm_device_get_iface (self)); + } +} + +static gboolean +take_down (NMDevice *device) +{ + int ifindex = nm_device_get_ip_ifindex (device); + + if (ifindex > 0) + return nm_platform_link_set_down (ifindex); + + /* devices without ifindex are always up. */ + nm_log_dbg (LOGD_HW, "(%s): cannot take down device without ifindex", nm_device_get_iface (device)); + return FALSE; +} + +void +nm_device_set_firmware_missing (NMDevice *self, gboolean new_missing) +{ + NMDevicePrivate *priv; + + g_return_if_fail (NM_IS_DEVICE (self)); + + priv = NM_DEVICE_GET_PRIVATE (self); + if (priv->firmware_missing != new_missing) { + priv->firmware_missing = new_missing; + g_object_notify (G_OBJECT (self), NM_DEVICE_FIRMWARE_MISSING); + } +} + +gboolean +nm_device_get_firmware_missing (NMDevice *self) +{ + return NM_DEVICE_GET_PRIVATE (self)->firmware_missing; +} + +static NMIP4Config * +find_ip4_lease_config (NMDevice *device, + NMConnection *connection, + NMIP4Config *ext_ip4_config) +{ + const char *ip_iface = nm_device_get_ip_iface (device); + GSList *leases, *liter; + NMIP4Config *found = NULL; + + g_return_val_if_fail (NM_IS_IP4_CONFIG (ext_ip4_config), NULL); + g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); + + leases = nm_dhcp_manager_get_lease_ip_configs (nm_dhcp_manager_get (), + ip_iface, + nm_connection_get_uuid (connection), + FALSE); + for (liter = leases; liter && !found; liter = liter->next) { + NMIP4Config *lease_config = liter->data; + const NMPlatformIP4Address *address = nm_ip4_config_get_address (lease_config, 0); + guint32 gateway = nm_ip4_config_get_gateway (lease_config); + + g_assert (address); + if (!nm_ip4_config_address_exists (ext_ip4_config, address)) + continue; + if (gateway != nm_ip4_config_get_gateway (ext_ip4_config)) + continue; + found = g_object_ref (lease_config); + } + + g_slist_free_full (leases, g_object_unref); + return found; +} + +static void +capture_lease_config (NMDevice *device, + NMIP4Config *ext_ip4_config, + NMIP4Config **out_ip4_config, + NMIP6Config *ext_ip6_config, + NMIP6Config **out_ip6_config) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); + const GSList *connections, *citer; + guint i; + gboolean dhcp_used = FALSE; + + /* Ensure at least one address on the device has a non-infinite lifetime, + * otherwise DHCP cannot possibly be active on the device right now. + */ + if (ext_ip4_config && out_ip4_config) { + for (i = 0; i < nm_ip4_config_get_num_addresses (ext_ip4_config); i++) { + const NMPlatformIP4Address *addr = nm_ip4_config_get_address (ext_ip4_config, i); + + if (addr->lifetime != NM_PLATFORM_LIFETIME_PERMANENT) { + dhcp_used = TRUE; + break; + } + } + } else if (ext_ip6_config && out_ip6_config) { + for (i = 0; i < nm_ip6_config_get_num_addresses (ext_ip6_config); i++) { + const NMPlatformIP6Address *addr = nm_ip6_config_get_address (ext_ip6_config, i); + + if (addr->lifetime != NM_PLATFORM_LIFETIME_PERMANENT) { + dhcp_used = TRUE; + break; + } + } + } else { + g_return_if_fail ( (ext_ip6_config && out_ip6_config) + || (ext_ip4_config && out_ip4_config)); + } + + if (!dhcp_used) + return; + + connections = nm_connection_provider_get_connections (priv->con_provider); + for (citer = connections; citer; citer = citer->next) { + NMConnection *candidate = citer->data; + const char *method; + + if (!nm_device_check_connection_compatible (device, candidate)) + continue; + + /* IPv4 leases */ + method = nm_utils_get_ip_config_method (candidate, NM_TYPE_SETTING_IP4_CONFIG); + if (out_ip4_config && strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0) { + *out_ip4_config = find_ip4_lease_config (device, candidate, ext_ip4_config); + if (*out_ip4_config) + return; + } + + /* IPv6 leases */ + method = nm_utils_get_ip_config_method (candidate, NM_TYPE_SETTING_IP6_CONFIG); + if (out_ip6_config && strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) == 0) { + /* FIXME: implement find_ip6_lease_config() */ + } + } +} + +static void +update_ip_config (NMDevice *self, gboolean initial) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + int ifindex; + gboolean linklocal6_just_completed = FALSE; + gboolean capture_resolv_conf; + NMDnsManagerResolvConfMode resolv_conf_mode; + + ifindex = nm_device_get_ip_ifindex (self); + if (!ifindex) + return; + + resolv_conf_mode = nm_dns_manager_get_resolv_conf_mode (nm_dns_manager_get ()); + capture_resolv_conf = initial && (resolv_conf_mode == NM_DNS_MANAGER_RESOLV_CONF_EXPLICIT); + + /* IPv4 */ + g_clear_object (&priv->ext_ip4_config); + priv->ext_ip4_config = nm_ip4_config_capture (ifindex, capture_resolv_conf); + + if (priv->ext_ip4_config) { + if (initial) { + g_clear_object (&priv->dev_ip4_config); + capture_lease_config (self, priv->ext_ip4_config, &priv->dev_ip4_config, NULL, NULL); + } + if (priv->dev_ip4_config) + nm_ip4_config_subtract (priv->ext_ip4_config, priv->dev_ip4_config); + if (priv->vpn4_config) + nm_ip4_config_subtract (priv->ext_ip4_config, priv->vpn4_config); + + ip4_config_merge_and_apply (self, NULL, FALSE, NULL); + } + + /* IPv6 */ + g_clear_object (&priv->ext_ip6_config); + priv->ext_ip6_config = nm_ip6_config_capture (ifindex, capture_resolv_conf, NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN); + if (priv->ext_ip6_config) { + + /* Check this before modifying ext_ip6_config */ + linklocal6_just_completed = priv->linklocal6_timeout_id && + linklocal6_config_is_ready (priv->ext_ip6_config); + + if (priv->ac_ip6_config) + nm_ip6_config_subtract (priv->ext_ip6_config, priv->ac_ip6_config); + if (priv->dhcp6_ip6_config) + nm_ip6_config_subtract (priv->ext_ip6_config, priv->dhcp6_ip6_config); + if (priv->vpn6_config) + nm_ip6_config_subtract (priv->ext_ip6_config, priv->vpn6_config); + + ip6_config_merge_and_apply (self, FALSE, NULL); + } + + if (linklocal6_just_completed) { + /* linklocal6 is ready now, do the state transition... we are also + * invoked as g_idle_add, so no problems with reentrance doing it now. + */ + linklocal6_complete (self); + } +} + +void +nm_device_capture_initial_config (NMDevice *dev) +{ + update_ip_config (dev, TRUE); +} + +static gboolean +queued_ip_config_change (gpointer user_data) +{ + NMDevice *self = NM_DEVICE (user_data); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + + /* Wait for any queued state changes */ + if (priv->queued_state.id) + return TRUE; + + priv->queued_ip_config_id = 0; + update_ip_config (self, FALSE); + return FALSE; +} + +static void +device_ip_changed (NMPlatform *platform, int ifindex, gpointer platform_object, NMPlatformSignalChangeType change_type, NMPlatformReason reason, gpointer user_data) +{ + NMDevice *self = user_data; + + if (nm_device_get_ip_ifindex (self) == ifindex) { + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + + if (!priv->queued_ip_config_id) + priv->queued_ip_config_id = g_idle_add (queued_ip_config_change, self); + + nm_log_dbg (LOGD_DEVICE, "(%s): queued IP config change", + nm_device_get_iface (self)); + } +} + +static void +nm_device_queued_ip_config_change_clear (NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + + if (priv->queued_ip_config_id) { + nm_log_dbg (LOGD_DEVICE, "(%s): clearing queued IP config change", + nm_device_get_iface (self)); + g_source_remove (priv->queued_ip_config_id); + priv->queued_ip_config_id = 0; + } +} + +/** + * nm_device_get_managed(): + * @device: the #NMDevice + * + * Returns: %TRUE if the device is managed + */ +gboolean +nm_device_get_managed (NMDevice *device) +{ + NMDevicePrivate *priv; + gboolean managed; + + g_return_val_if_fail (NM_IS_DEVICE (device), FALSE); + + priv = NM_DEVICE_GET_PRIVATE (device); + + /* Return the composite of all managed flags. However, if the device + * is a default-unmanaged device, and would be managed except for the + * default-unmanaged flag (eg, only NM_UNMANAGED_DEFAULT is set) then + * the device is managed whenever it's not in the UNMANAGED state. + */ + managed = !(priv->unmanaged_flags & ~NM_UNMANAGED_DEFAULT); + if (managed && (priv->unmanaged_flags & NM_UNMANAGED_DEFAULT)) + managed = (priv->state > NM_DEVICE_STATE_UNMANAGED); + + return managed; +} + +/** + * nm_device_get_unmanaged_flag(): + * @device: the #NMDevice + * + * Returns: %TRUE if the device is unmanaged for @flag. + */ +gboolean +nm_device_get_unmanaged_flag (NMDevice *device, NMUnmanagedFlags flag) +{ + return NM_DEVICE_GET_PRIVATE (device)->unmanaged_flags & flag; +} + +/** + * nm_device_get_default_unmanaged(): + * @device: the #NMDevice + * + * Returns: %TRUE if the device is by default unmanaged + */ +static gboolean +nm_device_get_default_unmanaged (NMDevice *device) +{ + return nm_device_get_unmanaged_flag (device, NM_UNMANAGED_DEFAULT); +} + +void +nm_device_set_unmanaged (NMDevice *device, + NMUnmanagedFlags flag, + gboolean unmanaged, + NMDeviceStateReason reason) +{ + NMDevicePrivate *priv; + gboolean was_managed, now_managed; + + g_return_if_fail (NM_IS_DEVICE (device)); + g_return_if_fail (flag <= NM_UNMANAGED_LAST); + + priv = NM_DEVICE_GET_PRIVATE (device); + + was_managed = nm_device_get_managed (device); + if (unmanaged) + priv->unmanaged_flags |= flag; + else + priv->unmanaged_flags &= ~flag; + now_managed = nm_device_get_managed (device); + + if (was_managed != now_managed) { + nm_log_dbg (LOGD_DEVICE, "(%s): now %s", + nm_device_get_iface (device), + unmanaged ? "unmanaged" : "managed"); + + g_object_notify (G_OBJECT (device), NM_DEVICE_MANAGED); + + if (unmanaged) + nm_device_state_changed (device, NM_DEVICE_STATE_UNMANAGED, reason); + else + nm_device_state_changed (device, NM_DEVICE_STATE_UNAVAILABLE, reason); + } +} + +void +nm_device_set_unmanaged_quitting (NMDevice *device) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); + + /* It's OK to block here because we're quitting */ + if (nm_device_is_activating (device) || priv->state == NM_DEVICE_STATE_ACTIVATED) + _set_state_full (device, NM_DEVICE_STATE_DEACTIVATING, NM_DEVICE_STATE_REASON_REMOVED, TRUE); + + nm_device_set_unmanaged (device, + NM_UNMANAGED_INTERNAL, + TRUE, + NM_DEVICE_STATE_REASON_REMOVED); +} + +/** + * nm_device_set_initial_unmanaged_flag(): + * @device: the #NMDevice + * @flag: an #NMUnmanagedFlag + * @unmanaged: %TRUE or %FALSE to set or clear @flag + * + * Like nm_device_set_unmanaged() but must be set before the device is exported + * and does not trigger state changes. Should only be used when initializing + * a device. + */ +void +nm_device_set_initial_unmanaged_flag (NMDevice *device, + NMUnmanagedFlags flag, + gboolean unmanaged) +{ + NMDevicePrivate *priv; + + g_return_if_fail (NM_IS_DEVICE (device)); + g_return_if_fail (flag <= NM_UNMANAGED_LAST); + + priv = NM_DEVICE_GET_PRIVATE (device); + g_return_if_fail (priv->path == NULL); + + if (unmanaged) + priv->unmanaged_flags |= flag; + else + priv->unmanaged_flags &= ~flag; +} + +void +nm_device_set_dhcp_timeout (NMDevice *device, guint32 timeout) +{ + g_return_if_fail (NM_IS_DEVICE (device)); + + NM_DEVICE_GET_PRIVATE (device)->dhcp_timeout = timeout; +} + +void +nm_device_set_dhcp_anycast_address (NMDevice *device, guint8 *addr) +{ + NMDevicePrivate *priv; + + g_return_if_fail (NM_IS_DEVICE (device)); + + priv = NM_DEVICE_GET_PRIVATE (device); + + if (priv->dhcp_anycast_address) { + g_byte_array_free (priv->dhcp_anycast_address, TRUE); + priv->dhcp_anycast_address = NULL; + } + + if (addr) { + priv->dhcp_anycast_address = g_byte_array_sized_new (ETH_ALEN); + g_byte_array_append (priv->dhcp_anycast_address, addr, ETH_ALEN); + } +} + +/** + * nm_device_connection_is_available(): + * @device: the #NMDevice + * @connection: the #NMConnection to check for availability + * @allow_device_override: set to %TRUE to let the device do specific checks + * + * Check if @connection is available to be activated on @device. Normally this + * only checks if the connection is in @device's AvailableConnections property. + * If @allow_device_override is %TRUE then the device is asked to do specific + * checks that may bypass the AvailableConnections property. + * + * Returns: %TRUE if @connection can be activated on @device + */ +gboolean +nm_device_connection_is_available (NMDevice *device, + NMConnection *connection, + gboolean allow_device_override) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); + gboolean available = FALSE; + + if (nm_device_get_default_unmanaged (device) && (priv->state == NM_DEVICE_STATE_UNMANAGED)) { + /* default-unmanaged devices in UNMANAGED state have no available connections + * so we must manually check whether the connection is available here. + */ + if ( nm_device_check_connection_compatible (device, connection) + && NM_DEVICE_GET_CLASS (device)->check_connection_available (device, connection, NULL)) + return TRUE; + } + + available = !!g_hash_table_lookup (priv->available_connections, connection); + if (!available && allow_device_override) { + /* FIXME: hack for hidden WiFi becuase clients didn't consistently + * set the 'hidden' property to indicate hidden SSID networks. If + * activating but the network isn't available let the device recheck + * availability. + */ + if ( nm_device_check_connection_compatible (device, connection) + && NM_DEVICE_GET_CLASS (device)->check_connection_available_wifi_hidden) + available = NM_DEVICE_GET_CLASS (device)->check_connection_available_wifi_hidden (device, connection); + } + + return available; +} + +static void +_signal_available_connections_changed (NMDevice *device) +{ + g_object_notify (G_OBJECT (device), NM_DEVICE_AVAILABLE_CONNECTIONS); +} + +static void +_clear_available_connections (NMDevice *device, gboolean do_signal) +{ + g_hash_table_remove_all (NM_DEVICE_GET_PRIVATE (device)->available_connections); + if (do_signal == TRUE) + _signal_available_connections_changed (device); +} + +static gboolean +_try_add_available_connection (NMDevice *self, NMConnection *connection) +{ + if (nm_device_get_state (self) < NM_DEVICE_STATE_DISCONNECTED) + return FALSE; + + if (nm_device_check_connection_compatible (self, connection)) { + if (NM_DEVICE_GET_CLASS (self)->check_connection_available (self, connection, NULL)) { + g_hash_table_insert (NM_DEVICE_GET_PRIVATE (self)->available_connections, + g_object_ref (connection), + GUINT_TO_POINTER (1)); + return TRUE; + } + } + return FALSE; +} + +static gboolean +_del_available_connection (NMDevice *device, NMConnection *connection) +{ + return g_hash_table_remove (NM_DEVICE_GET_PRIVATE (device)->available_connections, connection); +} + +static gboolean +connection_requires_carrier (NMConnection *connection) +{ + NMSettingIP4Config *s_ip4; + NMSettingIP6Config *s_ip6; + const char *method; + gboolean ip4_carrier_wanted = FALSE, ip6_carrier_wanted = FALSE; + gboolean ip4_used = FALSE, ip6_used = FALSE; + + method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP4_CONFIG); + if ( strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL) != 0 + && strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED) != 0) { + ip4_carrier_wanted = TRUE; + + /* If IPv4 wants a carrier and cannot fail, the whole connection + * requires a carrier regardless of the IPv6 method. + */ + s_ip4 = nm_connection_get_setting_ip4_config (connection); + if (s_ip4 && !nm_setting_ip4_config_get_may_fail (s_ip4)) + return TRUE; + } + ip4_used = (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED) != 0); + + method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP6_CONFIG); + if ( strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_MANUAL) != 0 + && strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE) != 0) { + ip6_carrier_wanted = TRUE; + + /* If IPv6 wants a carrier and cannot fail, the whole connection + * requires a carrier regardless of the IPv4 method. + */ + s_ip6 = nm_connection_get_setting_ip6_config (connection); + if (s_ip6 && !nm_setting_ip6_config_get_may_fail (s_ip6)) + return TRUE; + } + ip6_used = (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE) != 0); + + /* If an IP version wants a carrier and and the other IP version isn't + * used, the connection requires carrier since it will just fail without one. + */ + if (ip4_carrier_wanted && !ip6_used) + return TRUE; + if (ip6_carrier_wanted && !ip4_used) + return TRUE; + + /* If both want a carrier, the whole connection wants a carrier */ + return ip4_carrier_wanted && ip6_carrier_wanted; +} + +static gboolean +check_connection_available (NMDevice *device, + NMConnection *connection, + const char *specific_object) +{ + /* Connections which require a network connection are not available when + * the device has no carrier, even with ignore-carrer=TRUE. + */ + if (NM_DEVICE_GET_PRIVATE (device)->carrier == FALSE) + return connection_requires_carrier (connection) ? FALSE : TRUE; + + return TRUE; +} + +void +nm_device_recheck_available_connections (NMDevice *device) +{ + NMDevicePrivate *priv; + const GSList *connections, *iter; + + g_return_if_fail (NM_IS_DEVICE (device)); + + priv = NM_DEVICE_GET_PRIVATE(device); + + if (priv->con_provider) { + _clear_available_connections (device, FALSE); + + connections = nm_connection_provider_get_connections (priv->con_provider); + for (iter = connections; iter; iter = g_slist_next (iter)) + _try_add_available_connection (device, NM_CONNECTION (iter->data)); + + _signal_available_connections_changed (device); + } +} + +/** + * nm_device_get_available_connections: + * @device: the #NMDevice + * @specific_object: a specific object path if any + * + * Returns a list of connections available to activate on the device, taking + * into account any device-specific details given by @specific_object (like + * WiFi access point path). + * + * Returns: caller-owned #GPtrArray of #NMConnections + */ +GPtrArray * +nm_device_get_available_connections (NMDevice *device, const char *specific_object) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); + GHashTableIter iter; + guint num_available; + NMConnection *connection = NULL; + GPtrArray *array = NULL; + + num_available = g_hash_table_size (priv->available_connections); + if (num_available > 0) { + array = g_ptr_array_sized_new (num_available); + g_hash_table_iter_init (&iter, priv->available_connections); + while (g_hash_table_iter_next (&iter, (gpointer) &connection, NULL)) { + /* If a specific object is given, only include connections that are + * compatible with it. + */ + if ( !specific_object + || NM_DEVICE_GET_CLASS (device)->check_connection_available (device, connection, specific_object)) + g_ptr_array_add (array, connection); + } + } + return array; +} + +static void +cp_connection_added (NMConnectionProvider *cp, NMConnection *connection, gpointer user_data) +{ + if (_try_add_available_connection (NM_DEVICE (user_data), connection)) + _signal_available_connections_changed (NM_DEVICE (user_data)); +} + +static void +cp_connection_removed (NMConnectionProvider *cp, NMConnection *connection, gpointer user_data) +{ + if (_del_available_connection (NM_DEVICE (user_data), connection)) + _signal_available_connections_changed (NM_DEVICE (user_data)); +} + +static void +cp_connection_updated (NMConnectionProvider *cp, NMConnection *connection, gpointer user_data) +{ + gboolean added, deleted; + + /* FIXME: don't remove it from the hash if it's just going to get re-added */ + deleted = _del_available_connection (NM_DEVICE (user_data), connection); + added = _try_add_available_connection (NM_DEVICE (user_data), connection); + + /* Only signal if the connection was removed OR added, but not both */ + if (added != deleted) + _signal_available_connections_changed (NM_DEVICE (user_data)); +} + +gboolean +nm_device_supports_vlans (NMDevice *device) +{ + return nm_platform_link_supports_vlans (nm_device_get_ifindex (device)); +} + +/** + * nm_device_add_pending_action(): + * @device: the #NMDevice to add the pending action to + * @action: a static string that identifies the action + * @assert_not_yet_pending: if %TRUE, assert that the @action is currently not yet pending. + * Otherwise, ignore duplicate scheduling of the same action silently. + * + * Adds a pending action to the device. + * + * Returns: %TRUE if the action was added (and not already added before). %FALSE + * if the same action is already scheduled. In the latter case, the action was not scheduled + * a second time. + */ +gboolean +nm_device_add_pending_action (NMDevice *device, const char *action, gboolean assert_not_yet_pending) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); + GSList *iter; + guint count = 0; + + g_return_val_if_fail (action, FALSE); + + /* Check if the action is already pending. Cannot add duplicate actions */ + for (iter = priv->pending_actions; iter; iter = iter->next) { + if (!strcmp (action, iter->data)) { + if (assert_not_yet_pending) { + nm_log_warn (LOGD_DEVICE, "(%s): add_pending_action (%d): '%s' already pending", + nm_device_get_iface (device), + count + g_slist_length (iter), + action); + g_return_val_if_reached (FALSE); + } else { + nm_log_dbg (LOGD_DEVICE, "(%s): add_pending_action (%d): '%s' already pending (expected)", + nm_device_get_iface (device), + count + g_slist_length (iter), + action); + } + return FALSE; + } + count++; + } + + priv->pending_actions = g_slist_append (priv->pending_actions, g_strdup (action)); + count++; + + nm_log_dbg (LOGD_DEVICE, "(%s): add_pending_action (%d): '%s'", + nm_device_get_iface (device), + count, + action); + + if (count == 1) + g_object_notify (G_OBJECT (device), NM_DEVICE_HAS_PENDING_ACTION); + + return TRUE; +} + +/** + * nm_device_remove_pending_action(): + * @device: the #NMDevice to remove the pending action from + * @action: a static string that identifies the action + * @assert_is_pending: if %TRUE, assert that the @action is pending. + * If %FALSE, don't do anything if the current action is not pending and + * return %FALSE. + * + * Removes a pending action previously added by nm_device_add_pending_action(). + * + * Returns: whether the @action was pending and is now removed. + */ +gboolean +nm_device_remove_pending_action (NMDevice *device, const char *action, gboolean assert_is_pending) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); + GSList *iter; + guint count = 0; + + g_return_val_if_fail (action, FALSE); + + for (iter = priv->pending_actions; iter; iter = iter->next) { + if (!strcmp (action, iter->data)) { + nm_log_dbg (LOGD_DEVICE, "(%s): remove_pending_action (%d): '%s'", + nm_device_get_iface (device), + count + g_slist_length (iter->next), /* length excluding 'iter' */ + action); + g_free (iter->data); + priv->pending_actions = g_slist_delete_link (priv->pending_actions, iter); + if (priv->pending_actions == NULL) + g_object_notify (G_OBJECT (device), NM_DEVICE_HAS_PENDING_ACTION); + return TRUE; + } + count++; + } + + if (assert_is_pending) { + nm_log_warn (LOGD_DEVICE, "(%s): remove_pending_action (%d): '%s' not pending", + nm_device_get_iface (device), + count, + action); + g_return_val_if_reached (FALSE); + } else { + nm_log_dbg (LOGD_DEVICE, "(%s): remove_pending_action (%d): '%s' not pending (expected)", + nm_device_get_iface (device), + count, + action); + } + return FALSE; +} + +gboolean +nm_device_has_pending_action (NMDevice *device) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); + + return !!priv->pending_actions; +} + +/***********************************************************/ + +static void +_cleanup_generic_pre (NMDevice *self, gboolean deconfigure) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + + /* Clean up when device was deactivated during call to firewall */ + if (priv->fw_manager) { + NMConnection *connection; + + if (priv->fw_call) { + nm_firewall_manager_cancel_call (priv->fw_manager, priv->fw_call); + priv->fw_call = NULL; + } + + connection = nm_device_get_connection (self); + if (deconfigure && connection) { + nm_firewall_manager_remove_from_zone (priv->fw_manager, + nm_device_get_ip_iface (self), + NULL); + } + } + + ip_check_gw_ping_cleanup (self); + + /* Break the activation chain */ + activation_source_clear (self, TRUE, AF_INET); + activation_source_clear (self, TRUE, AF_INET6); + + /* Clear any queued transitions */ + nm_device_queued_state_clear (self); + nm_device_queued_ip_config_change_clear (self); + + priv->ip4_state = priv->ip6_state = IP_NONE; + + dhcp4_cleanup (self, deconfigure, FALSE); + arp_cleanup (self); + dhcp6_cleanup (self, deconfigure, FALSE); + linklocal6_cleanup (self); + addrconf6_cleanup (self); + dnsmasq_cleanup (self); + aipd_cleanup (self); +} + +static void +_cleanup_generic_post (NMDevice *self, gboolean deconfigure) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMDeviceStateReason ignored = NM_DEVICE_STATE_REASON_NONE; + + /* Clean up IP configs; this does not actually deconfigure the + * interface; the caller must flush routes and addresses explicitly. + */ + nm_device_set_ip4_config (self, NULL, TRUE, &ignored); + nm_device_set_ip6_config (self, NULL, TRUE, &ignored); + g_clear_object (&priv->dev_ip4_config); + g_clear_object (&priv->ext_ip4_config); + g_clear_object (&priv->vpn4_config); + g_clear_object (&priv->ip4_config); + g_clear_object (&priv->ac_ip6_config); + g_clear_object (&priv->ext_ip6_config); + g_clear_object (&priv->vpn6_config); + g_clear_object (&priv->ip6_config); + + clear_act_request (self); + + /* Clear legacy IPv4 address property */ + if (priv->ip4_address) { + priv->ip4_address = 0; + g_object_notify (G_OBJECT (self), NM_DEVICE_IP4_ADDRESS); + } + + if (deconfigure) { + /* Check if the device was deactivated, and if so, delete_link. + * Don't call delete_link synchronously because we are currently + * handling a state change -- which is not reentrant. */ + delete_on_deactivate_check_and_schedule (self, nm_device_get_ip_ifindex (self)); + } + + /* ip_iface should be cleared after flushing all routes and addreses, since + * those are identified by ip_iface, not by iface (which might be a tty + * or ATM device). + */ + nm_device_set_ip_iface (self, NULL); +} + +/* + * nm_device_cleanup + * + * Remove a device's routing table entries and IP addresses. + * + */ +static void +nm_device_cleanup (NMDevice *self, NMDeviceStateReason reason) +{ + NMDevicePrivate *priv; + int ifindex; + + g_return_if_fail (NM_IS_DEVICE (self)); + + if (reason == NM_DEVICE_STATE_REASON_NOW_MANAGED) { + nm_log_info (LOGD_DEVICE, "(%s): preparing device", + nm_device_get_iface (self)); + } else { + nm_log_info (LOGD_DEVICE, "(%s): deactivating device (reason '%s') [%d]", + nm_device_get_iface (self), reason_to_string (reason), reason); + } + + /* Save whether or not we tried IPv6 for later */ + priv = NM_DEVICE_GET_PRIVATE (self); + + _cleanup_generic_pre (self, TRUE); + + /* Turn off kernel IPv6 */ + nm_device_ipv6_sysctl_set (self, "disable_ipv6", "1"); + nm_device_ipv6_sysctl_set (self, "accept_ra", "0"); + nm_device_ipv6_sysctl_set (self, "use_tempaddr", "0"); + + /* Call device type-specific deactivation */ + if (NM_DEVICE_GET_CLASS (self)->deactivate) + NM_DEVICE_GET_CLASS (self)->deactivate (self); + + /* master: release slaves */ + nm_device_master_release_slaves (self); + + /* slave: mark no longer enslaved */ + g_clear_object (&priv->master); + priv->enslaved = FALSE; + g_object_notify (G_OBJECT (self), NM_DEVICE_MASTER); + + /* Take out any entries in the routing table and any IP address the device had. */ + ifindex = nm_device_get_ip_ifindex (self); + if (ifindex > 0) { + nm_platform_route_flush (ifindex); + nm_platform_address_flush (ifindex); + } + + _cleanup_generic_post (self, TRUE); +} + +/***********************************************************/ + +static gboolean +ip_config_valid (NMDeviceState state) +{ + return (state == NM_DEVICE_STATE_UNMANAGED) || + (state >= NM_DEVICE_STATE_IP_CHECK && + state <= NM_DEVICE_STATE_DEACTIVATING); +} + +static void +notify_ip_properties (NMDevice *device) +{ + g_object_notify (G_OBJECT (device), NM_DEVICE_IP_IFACE); + g_object_notify (G_OBJECT (device), NM_DEVICE_IP4_CONFIG); + g_object_notify (G_OBJECT (device), NM_DEVICE_DHCP4_CONFIG); + g_object_notify (G_OBJECT (device), NM_DEVICE_IP6_CONFIG); + g_object_notify (G_OBJECT (device), NM_DEVICE_DHCP6_CONFIG); +} + +static void +_set_state_full (NMDevice *device, + NMDeviceState state, + NMDeviceStateReason reason, + gboolean quitting) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); + NMDeviceState old_state; + NMActRequest *req; + gboolean no_firmware = FALSE; + NMConnection *connection; + + /* Track re-entry */ + g_warn_if_fail (priv->in_state_changed == FALSE); + priv->in_state_changed = TRUE; + + g_return_if_fail (NM_IS_DEVICE (device)); + + /* Do nothing if state isn't changing, but as a special case allow + * re-setting UNAVAILABLE if the device is missing firmware so that we + * can retry device initialization. + */ + if ( (priv->state == state) + && !(state == NM_DEVICE_STATE_UNAVAILABLE && priv->firmware_missing)) { + priv->in_state_changed = FALSE; + return; + } + + old_state = priv->state; + priv->state = state; + priv->state_reason = reason; + + nm_log_info (LOGD_DEVICE, "(%s): device state change: %s -> %s (reason '%s') [%d %d %d]", + nm_device_get_iface (device), + state_to_string (old_state), + state_to_string (state), + reason_to_string (reason), + old_state, + state, + reason); + + /* Clear any queued transitions */ + nm_device_queued_state_clear (device); + + dispatcher_cleanup (device); + + /* Cache the activation request for the dispatcher */ + req = priv->act_request ? g_object_ref (priv->act_request) : NULL; + + if (state <= NM_DEVICE_STATE_UNAVAILABLE) { + _clear_available_connections (device, TRUE); + g_clear_object (&priv->queued_act_request); + } + + /* Update the available connections list when a device first becomes available */ + if ( state >= NM_DEVICE_STATE_DISCONNECTED + && old_state < NM_DEVICE_STATE_DISCONNECTED) + nm_device_recheck_available_connections (device); + + /* Handle the new state here; but anything that could trigger + * another state change should be done below. + */ + switch (state) { + case NM_DEVICE_STATE_UNMANAGED: + nm_device_set_firmware_missing (device, FALSE); + if (old_state > NM_DEVICE_STATE_UNMANAGED) { + /* Clean up if the device is now unmanaged but was activated */ + if (nm_device_get_act_request (device)) + nm_device_cleanup (device, reason); + nm_device_take_down (device, TRUE); + restore_ip6_properties (device); + } + break; + case NM_DEVICE_STATE_UNAVAILABLE: + if (old_state == NM_DEVICE_STATE_UNMANAGED) { + save_ip6_properties (device); + if (reason != NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED) { + nm_device_ipv6_sysctl_set (device, "disable_ipv6", "1"); + nm_device_ipv6_sysctl_set (device, "accept_ra_defrtr", "0"); + nm_device_ipv6_sysctl_set (device, "accept_ra_pinfo", "0"); + nm_device_ipv6_sysctl_set (device, "accept_ra_rtr_pref", "0"); + nm_device_ipv6_sysctl_set (device, "use_tempaddr", "0"); + } + } + + if (old_state == NM_DEVICE_STATE_UNMANAGED || priv->firmware_missing) { + if (!nm_device_bring_up (device, TRUE, &no_firmware) && no_firmware) + nm_log_warn (LOGD_HW, "(%s): firmware may be missing.", nm_device_get_iface (device)); + nm_device_set_firmware_missing (device, no_firmware ? TRUE : FALSE); + } + /* Ensure the device gets deactivated in response to stuff like + * carrier changes or rfkill. But don't deactivate devices that are + * about to assume a connection since that defeats the purpose of + * assuming the device's existing connection. + * + * Note that we "deactivate" the device even when coming from + * UNMANAGED, to ensure that it's in a clean state. + */ + if (reason != NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED) + nm_device_cleanup (device, reason); + break; + case NM_DEVICE_STATE_DISCONNECTED: + if (old_state > NM_DEVICE_STATE_UNAVAILABLE) + nm_device_cleanup (device, reason); + break; + default: + break; + } + + /* Reset autoconnect flag when the device is activating or connected. */ + if ( state >= NM_DEVICE_STATE_PREPARE + && state <= NM_DEVICE_STATE_ACTIVATED) + priv->autoconnect = TRUE; + + g_object_notify (G_OBJECT (device), NM_DEVICE_STATE); + g_object_notify (G_OBJECT (device), NM_DEVICE_STATE_REASON); + g_signal_emit_by_name (device, "state-changed", state, old_state, reason); + + /* Post-process the event after internal notification */ + + switch (state) { + case NM_DEVICE_STATE_UNAVAILABLE: + /* If the device can activate now (ie, it's got a carrier, the supplicant + * is active, or whatever) schedule a delayed transition to DISCONNECTED + * to get things rolling. The device can't transition immediately because + * we can't change states again from the state handler for a variety of + * reasons. + */ + if (nm_device_is_available (device)) { + nm_log_dbg (LOGD_DEVICE, "(%s): device is available, will transition to DISCONNECTED", + nm_device_get_iface (device)); + nm_device_queue_state (device, NM_DEVICE_STATE_DISCONNECTED, NM_DEVICE_STATE_REASON_NONE); + } else { + if (old_state == NM_DEVICE_STATE_UNMANAGED) { + nm_log_dbg (LOGD_DEVICE, "(%s): device not yet available for transition to DISCONNECTED", + nm_device_get_iface (device)); + } else if ( old_state > NM_DEVICE_STATE_UNAVAILABLE + && nm_device_get_default_unmanaged (device)) + nm_device_queue_state (device, NM_DEVICE_STATE_UNMANAGED, NM_DEVICE_STATE_REASON_NONE); + } + break; + case NM_DEVICE_STATE_DEACTIVATING: + if (quitting) { + nm_dispatcher_call_sync (DISPATCHER_ACTION_PRE_DOWN, + nm_act_request_get_connection (req), + device); + } else { + priv->dispatcher.post_state = NM_DEVICE_STATE_DISCONNECTED; + priv->dispatcher.post_state_reason = reason; + if (!nm_dispatcher_call (DISPATCHER_ACTION_PRE_DOWN, + nm_act_request_get_connection (req), + device, + dispatcher_complete_proceed_state, + device, + &priv->dispatcher.call_id)) { + /* Just proceed on errors */ + dispatcher_complete_proceed_state (0, device); + } + } + break; + case NM_DEVICE_STATE_DISCONNECTED: + if (priv->queued_act_request) { + NMActRequest *queued_req; + + queued_req = priv->queued_act_request; + priv->queued_act_request = NULL; + _device_activate (device, queued_req); + g_object_unref (queued_req); + } else if ( old_state > NM_DEVICE_STATE_DISCONNECTED + && nm_device_get_default_unmanaged (device)) + nm_device_queue_state (device, NM_DEVICE_STATE_UNMANAGED, NM_DEVICE_STATE_REASON_NONE); + break; + case NM_DEVICE_STATE_ACTIVATED: + nm_log_info (LOGD_DEVICE, "Activation (%s) successful, device activated.", + nm_device_get_iface (device)); + nm_dispatcher_call (DISPATCHER_ACTION_UP, nm_act_request_get_connection (req), device, NULL, NULL, NULL); + break; + case NM_DEVICE_STATE_FAILED: + connection = nm_device_get_connection (device); + nm_log_warn (LOGD_DEVICE | LOGD_WIFI, + "Activation (%s) failed for connection '%s'", + nm_device_get_iface (device), + connection ? nm_connection_get_id (connection) : ""); + + /* Notify any slaves of the unexpected failure */ + nm_device_master_release_slaves (device); + + /* If the connection doesn't yet have a timestamp, set it to zero so that + * we can distinguish between connections we've tried to activate and have + * failed (zero timestamp), connections that succeeded (non-zero timestamp), + * and those we haven't tried yet (no timestamp). + */ + if (connection && !nm_settings_connection_get_timestamp (NM_SETTINGS_CONNECTION (connection), NULL)) { + nm_settings_connection_update_timestamp (NM_SETTINGS_CONNECTION (connection), + (guint64) 0, + TRUE); + } + + /* Schedule the transition to DISCONNECTED. The device can't transition + * immediately because we can't change states again from the state + * handler for a variety of reasons. + */ + nm_device_queue_state (device, NM_DEVICE_STATE_DISCONNECTED, NM_DEVICE_STATE_REASON_NONE); + break; + case NM_DEVICE_STATE_IP_CHECK: + nm_device_start_ip_check (device); + + /* IP-related properties are only valid when the device has IP configuration; + * now that it does, ensure their change notifications are emitted. + */ + notify_ip_properties (device); + break; + case NM_DEVICE_STATE_SECONDARIES: + ip_check_gw_ping_cleanup (device); + nm_log_dbg (LOGD_DEVICE, "(%s): device entered SECONDARIES state", + nm_device_get_iface (device)); + break; + default: + break; + } + + if (state > NM_DEVICE_STATE_DISCONNECTED) + delete_on_deactivate_unschedule (device); + + if ( (old_state == NM_DEVICE_STATE_ACTIVATED || old_state == NM_DEVICE_STATE_DEACTIVATING) + && (state != NM_DEVICE_STATE_DEACTIVATING)) { + if (quitting) + nm_dispatcher_call_sync (DISPATCHER_ACTION_DOWN, nm_act_request_get_connection (req), device); + else + nm_dispatcher_call (DISPATCHER_ACTION_DOWN, nm_act_request_get_connection (req), device, NULL, NULL, NULL); + } + + /* IP-related properties are only valid when the device has IP configuration. + * If it no longer does, ensure their change notifications are emitted. + */ + if (ip_config_valid (old_state) && !ip_config_valid (state)) + notify_ip_properties (device); + + /* Dispose of the cached activation request */ + if (req) + g_object_unref (req); + + priv->in_state_changed = FALSE; +} + +void +nm_device_state_changed (NMDevice *device, + NMDeviceState state, + NMDeviceStateReason reason) +{ + _set_state_full (device, state, reason, FALSE); +} + +static gboolean +queued_set_state (gpointer user_data) +{ + NMDevice *self = NM_DEVICE (user_data); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMDeviceState new_state; + NMDeviceStateReason new_reason; + + if (priv->queued_state.id) { + nm_log_dbg (LOGD_DEVICE, "(%s): running queued state change to %s (id %d)", + nm_device_get_iface (self), + state_to_string (priv->queued_state.state), + priv->queued_state.id); + + /* Clear queued state struct before triggering state change, since + * the state change may queue another state. + */ + priv->queued_state.id = 0; + new_state = priv->queued_state.state; + new_reason = priv->queued_state.reason; + nm_device_queued_state_clear (self); + + nm_device_state_changed (self, new_state, new_reason); + nm_device_remove_pending_action (self, queued_state_to_string (new_state), TRUE); + } else { + g_warn_if_fail (priv->queued_state.state == NM_DEVICE_STATE_UNKNOWN); + g_warn_if_fail (priv->queued_state.reason == NM_DEVICE_STATE_REASON_NONE); + } + return FALSE; +} + +void +nm_device_queue_state (NMDevice *self, + NMDeviceState state, + NMDeviceStateReason reason) +{ + NMDevicePrivate *priv; + + g_return_if_fail (NM_IS_DEVICE (self)); + + priv = NM_DEVICE_GET_PRIVATE (self); + + if (priv->queued_state.id && priv->queued_state.state == state) + return; + + /* Add pending action for the new state before clearing the queued states, so + * that we don't accidently pop all pending states and reach 'startup complete' */ + nm_device_add_pending_action (self, queued_state_to_string (state), TRUE); + + /* We should only ever have one delayed state transition at a time */ + if (priv->queued_state.id) { + nm_log_warn (LOGD_DEVICE, "(%s): overwriting previously queued state change to %s (%s)", + nm_device_get_iface (self), + state_to_string (priv->queued_state.state), + reason_to_string (priv->queued_state.reason)); + nm_device_queued_state_clear (self); + } + + priv->queued_state.state = state; + priv->queued_state.reason = reason; + priv->queued_state.id = g_idle_add (queued_set_state, self); + + nm_log_dbg (LOGD_DEVICE, "(%s): queued state change to %s due to %s (id %d)", + nm_device_get_iface (self), state_to_string (state), reason_to_string (reason), + priv->queued_state.id); +} + +NMDeviceState +nm_device_queued_state_peek (NMDevice *self) +{ + NMDevicePrivate *priv; + + g_return_val_if_fail (NM_IS_DEVICE (self), NM_DEVICE_STATE_UNKNOWN); + + priv = NM_DEVICE_GET_PRIVATE (self); + + return priv->queued_state.id ? priv->queued_state.state : NM_DEVICE_STATE_UNKNOWN; +} + +void +nm_device_queued_state_clear (NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + + if (priv->queued_state.id) { + nm_log_dbg (LOGD_DEVICE, "(%s): clearing queued state transition (id %d)", + nm_device_get_iface (self), priv->queued_state.id); + g_source_remove (priv->queued_state.id); + nm_device_remove_pending_action (self, queued_state_to_string (priv->queued_state.state), TRUE); + } + memset (&priv->queued_state, 0, sizeof (priv->queued_state)); +} + +NMDeviceState +nm_device_get_state (NMDevice *device) +{ + g_return_val_if_fail (NM_IS_DEVICE (device), NM_DEVICE_STATE_UNKNOWN); + + return NM_DEVICE_GET_PRIVATE (device)->state; +} + +/***********************************************************/ +/* NMConfigDevice interface related stuff */ + +static guint +nm_device_get_hw_address_length (NMDevice *dev, gboolean *out_permanent) +{ + return NM_DEVICE_GET_CLASS (dev)->get_hw_address_length (dev, out_permanent); +} + +const guint8 * +nm_device_get_hw_address (NMDevice *dev, guint *out_len) +{ + NMDevicePrivate *priv; + + g_return_val_if_fail (NM_IS_DEVICE (dev), NULL); + priv = NM_DEVICE_GET_PRIVATE (dev); + + if (out_len) + *out_len = priv->hw_addr_len; + + if (priv->hw_addr_len == 0) + return NULL; + else + return priv->hw_addr; +} + +gboolean +nm_device_update_hw_address (NMDevice *dev) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (dev); + gboolean changed = FALSE, permanent = FALSE; + + priv->hw_addr_len = nm_device_get_hw_address_length (dev, &permanent); + + /* If the address can't be changed, don't bother trying */ + if (permanent) + return FALSE; + + if (priv->hw_addr_len) { + int ifindex = nm_device_get_ip_ifindex (dev); + gsize addrlen; + const guint8 *binaddr; + + g_return_val_if_fail (ifindex > 0, FALSE); + + binaddr = nm_platform_link_get_address (ifindex, &addrlen); + + if (addrlen != priv->hw_addr_len) { + nm_log_err (LOGD_HW | LOGD_DEVICE, + "(%s): hardware address is wrong length (got %zd, expected %d)", + nm_device_get_iface (dev), addrlen, priv->hw_addr_len); + } else { + changed = !!memcmp (priv->hw_addr, binaddr, addrlen); + if (changed) { + char *addrstr = nm_utils_hwaddr_ntoa_len (binaddr, priv->hw_addr_len); + + memcpy (priv->hw_addr, binaddr, addrlen); + nm_log_dbg (LOGD_HW | LOGD_DEVICE, + "(%s): hardware address is %s", + nm_device_get_iface (dev), addrstr); + g_free (addrstr); + g_object_notify (G_OBJECT (dev), NM_DEVICE_HW_ADDRESS); + } + } + } else { + int i; + + /* hw_addr_len is now 0; see if hw_addr was already empty */ + for (i = 0; i < sizeof (priv->hw_addr) && !changed; i++) { + if (priv->hw_addr[i]) + changed = TRUE; + } + if (changed) { + memset (priv->hw_addr, 0, sizeof (priv->hw_addr)); + nm_log_dbg (LOGD_HW | LOGD_DEVICE, + "(%s): previous hardware address is no longer valid", + nm_device_get_iface (dev)); + g_object_notify (G_OBJECT (dev), NM_DEVICE_HW_ADDRESS); + } + } + + return changed; +} + +gboolean +nm_device_set_hw_addr (NMDevice *device, const guint8 *addr, + const char *detail, guint64 hw_log_domain) +{ + const char *iface; + char *mac_str = NULL; + gboolean success = FALSE; + guint len; + const guint8 *cur_addr = nm_device_get_hw_address (device, &len); + + g_return_val_if_fail (addr != NULL, FALSE); + + iface = nm_device_get_iface (device); + + /* Do nothing if current MAC is same */ + if (cur_addr && !memcmp (cur_addr, addr, len)) { + nm_log_dbg (LOGD_DEVICE | hw_log_domain, "(%s): no MAC address change needed", iface); + return TRUE; + } + + mac_str = nm_utils_hwaddr_ntoa_len (addr, len); + + /* Can't change MAC address while device is up */ + nm_device_take_down (device, FALSE); + + success = nm_platform_link_set_address (nm_device_get_ip_ifindex (device), addr, len); + if (success) { + /* MAC address succesfully changed; update the current MAC to match */ + nm_device_update_hw_address (device); + cur_addr = nm_device_get_hw_address (device, NULL); + if (memcmp (cur_addr, addr, len) == 0) { + nm_log_info (LOGD_DEVICE | hw_log_domain, "(%s): %s MAC address to %s", + iface, detail, mac_str); + } else { + nm_log_warn (LOGD_DEVICE | hw_log_domain, "(%s): new MAC address %s " + "not successfully set", + iface, mac_str); + success = FALSE; + } + } else { + nm_log_warn (LOGD_DEVICE | hw_log_domain, "(%s): failed to %s MAC address to %s", + iface, detail, mac_str); + } + nm_device_bring_up (device, TRUE, NULL); + g_free (mac_str); + + return success; +} + +/** + * nm_device_spec_match_list: + * @device: an #NMDevice + * @specs: (element-type utf8): a list of device specs + * + * Checks if @device matches any of the specifications in @specs. The + * currently-supported spec types are: + * + * "mac:00:11:22:33:44:55" - matches a device with the given + * hardware address + * + * "interface-name:foo0" - matches a device with the given + * interface name + * + * "s390-subchannels:00.11.22" - matches a device with the given + * z/VM / s390 subchannels. + * + * "*" - matches any device + * + * Returns: #TRUE if @device matches one of the specs in @specs + */ +gboolean +nm_device_spec_match_list (NMDevice *device, const GSList *specs) +{ + g_return_val_if_fail (NM_IS_DEVICE (device), FALSE); + + if (!specs) + return FALSE; + + return NM_DEVICE_GET_CLASS (device)->spec_match_list (device, specs); +} + +static gboolean +spec_match_list (NMDevice *device, const GSList *specs) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); + char *hwaddr_str; + gboolean matched = FALSE; + + if (nm_match_spec_string (specs, "*")) + return TRUE; + + if (priv->hw_addr_len) { + hwaddr_str = nm_utils_hwaddr_ntoa_len (priv->hw_addr, priv->hw_addr_len); + matched = nm_match_spec_hwaddr (specs, hwaddr_str); + g_free (hwaddr_str); + } + + if (!matched) + matched = nm_match_spec_interface_name (specs, nm_device_get_iface (device)); + + return matched; +} + +static guint +get_hw_address_length (NMDevice *dev, gboolean *out_permanent) +{ + size_t len; + + if (nm_platform_link_get_address (nm_device_get_ip_ifindex (dev), &len)) + return len; + else + return 0; +} + +/***********************************************************/ + +#define DEFAULT_AUTOCONNECT TRUE + +static void +nm_device_init (NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + + priv->type = NM_DEVICE_TYPE_UNKNOWN; + priv->capabilities = NM_DEVICE_CAP_NM_SUPPORTED; + priv->state = NM_DEVICE_STATE_UNMANAGED; + priv->state_reason = NM_DEVICE_STATE_REASON_NONE; + priv->dhcp_timeout = 0; + priv->rfkill_type = RFKILL_TYPE_UNKNOWN; + priv->autoconnect = DEFAULT_AUTOCONNECT; + priv->unmanaged_flags = NM_UNMANAGED_INTERNAL; + priv->available_connections = g_hash_table_new_full (g_direct_hash, g_direct_equal, g_object_unref, NULL); + priv->ip6_saved_properties = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free); +} + +static void +nm_device_config_device_interface_init (NMConfigDeviceInterface *iface) +{ + iface->spec_match_list = (gboolean (*) (NMConfigDevice *, const GSList *)) nm_device_spec_match_list; + iface->get_hw_address = (const guint8 * (*) (NMConfigDevice *, guint *)) nm_device_get_hw_address; +} + +/* + * Get driver info from SIOCETHTOOL ioctl() for 'iface' + * Returns driver and firmware versions to 'driver_version and' 'firmware_version' + */ +static gboolean +device_get_driver_info (const char *iface, char **driver_version, char **firmware_version) +{ + struct ethtool_drvinfo drvinfo; + struct ifreq req; + int fd; + + fd = socket (PF_INET, SOCK_DGRAM, 0); + if (fd < 0) { + nm_log_warn (LOGD_HW, "couldn't open control socket."); + return FALSE; + } + + /* Get driver and firmware version info */ + memset (&drvinfo, 0, sizeof (drvinfo)); + memset (&req, 0, sizeof (struct ifreq)); + strncpy (req.ifr_name, iface, IFNAMSIZ); + drvinfo.cmd = ETHTOOL_GDRVINFO; + req.ifr_data = &drvinfo; + + errno = 0; + if (ioctl (fd, SIOCETHTOOL, &req) < 0) { + nm_log_dbg (LOGD_HW, "SIOCETHTOOL ioctl() failed: cmd=ETHTOOL_GDRVINFO, iface=%s, errno=%d", + iface, errno); + close (fd); + return FALSE; + } + if (driver_version) + *driver_version = g_strdup (drvinfo.version); + if (firmware_version) + *firmware_version = g_strdup (drvinfo.fw_version); + + close (fd); + return TRUE; +} + +static GObject* +constructor (GType type, + guint n_construct_params, + GObjectConstructParam *construct_params) +{ + GObject *object; + NMDevice *dev; + NMDevicePrivate *priv; + NMPlatform *platform; + static guint32 id = 0; + + object = G_OBJECT_CLASS (nm_device_parent_class)->constructor (type, + n_construct_params, + construct_params); + if (!object) + return NULL; + + dev = NM_DEVICE (object); + priv = NM_DEVICE_GET_PRIVATE (dev); + + if (!priv->iface) { + nm_log_err (LOGD_DEVICE, "No device interface provided, ignoring"); + goto error; + } + + if (!priv->udi) { + /* Use a placeholder UDI until we get a real one */ + priv->udi = g_strdup_printf ("/virtual/device/placeholder/%d", id++); + } + + if (NM_DEVICE_GET_CLASS (dev)->get_generic_capabilities) + priv->capabilities |= NM_DEVICE_GET_CLASS (dev)->get_generic_capabilities (dev); + + priv->fw_manager = nm_firewall_manager_get (); + + device_get_driver_info (priv->iface, &priv->driver_version, &priv->firmware_version); + + /* Watch for external IP config changes */ + platform = nm_platform_get (); + g_signal_connect (platform, NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED, G_CALLBACK (device_ip_changed), dev); + g_signal_connect (platform, NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED, G_CALLBACK (device_ip_changed), dev); + g_signal_connect (platform, NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, G_CALLBACK (device_ip_changed), dev); + g_signal_connect (platform, NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, G_CALLBACK (device_ip_changed), dev); + g_signal_connect (platform, NM_PLATFORM_SIGNAL_LINK_CHANGED, G_CALLBACK (link_changed_cb), dev); + + return object; + +error: + g_object_unref (dev); + return NULL; +} + +static void +constructed (GObject *object) +{ + NMDevice *dev = NM_DEVICE (object); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (dev); + + nm_device_update_hw_address (dev); + + if (NM_DEVICE_GET_CLASS (dev)->update_permanent_hw_address) + NM_DEVICE_GET_CLASS (dev)->update_permanent_hw_address (dev); + + if (NM_DEVICE_GET_CLASS (dev)->update_initial_hw_address) + NM_DEVICE_GET_CLASS (dev)->update_initial_hw_address (dev); + + /* Have to call update_initial_hw_address() before calling get_ignore_carrier() */ + if (device_has_capability (dev, NM_DEVICE_CAP_CARRIER_DETECT)) { + priv->ignore_carrier = nm_config_get_ignore_carrier (nm_config_get (), NM_CONFIG_DEVICE (dev)); + + check_carrier (dev); + nm_log_info (LOGD_HW, + "(%s): carrier is %s%s", + nm_device_get_iface (NM_DEVICE (dev)), + priv->carrier ? "ON" : "OFF", + priv->ignore_carrier ? " (but ignored)" : ""); + } else { + /* Fake online link when carrier detection is not available. */ + priv->carrier = TRUE; + } + + if (priv->ifindex > 0) { + priv->is_software = nm_platform_link_is_software (priv->ifindex); + priv->physical_port_id = nm_platform_link_get_physical_port_id (priv->ifindex); + } + + if (priv->ifindex > 0) + priv->mtu = nm_platform_link_get_mtu (priv->ifindex); + + priv->con_provider = nm_connection_provider_get (); + g_assert (priv->con_provider); + g_signal_connect (priv->con_provider, + NM_CP_SIGNAL_CONNECTION_ADDED, + G_CALLBACK (cp_connection_added), + dev); + + g_signal_connect (priv->con_provider, + NM_CP_SIGNAL_CONNECTION_REMOVED, + G_CALLBACK (cp_connection_removed), + dev); + + g_signal_connect (priv->con_provider, + NM_CP_SIGNAL_CONNECTION_UPDATED, + G_CALLBACK (cp_connection_updated), + dev); + + G_OBJECT_CLASS (nm_device_parent_class)->constructed (object); +} + +static void +dispose (GObject *object) +{ + NMDevice *self = NM_DEVICE (object); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMPlatform *platform; + + dispatcher_cleanup (self); + + _cleanup_generic_pre (self, FALSE); + + g_warn_if_fail (priv->slaves == NULL); + g_assert (priv->master_ready_id == 0); + + _cleanup_generic_post (self, FALSE); + + g_clear_pointer (&priv->ip6_saved_properties, g_hash_table_unref); + + if (priv->recheck_assume_id) { + g_source_remove (priv->recheck_assume_id); + priv->recheck_assume_id = 0; + } + + link_disconnect_action_cancel (self); + + if (priv->con_provider) { + g_signal_handlers_disconnect_by_func (priv->con_provider, cp_connection_added, self); + g_signal_handlers_disconnect_by_func (priv->con_provider, cp_connection_removed, self); + g_signal_handlers_disconnect_by_func (priv->con_provider, cp_connection_updated, self); + priv->con_provider = NULL; + } + + g_hash_table_unref (priv->available_connections); + priv->available_connections = NULL; + + if (priv->carrier_wait_id) { + g_source_remove (priv->carrier_wait_id); + priv->carrier_wait_id = 0; + } + + g_clear_object (&priv->queued_act_request); + + platform = nm_platform_get (); + g_signal_handlers_disconnect_by_func (platform, G_CALLBACK (device_ip_changed), self); + g_signal_handlers_disconnect_by_func (platform, G_CALLBACK (link_changed_cb), self); + + g_clear_object (&priv->fw_manager); + + G_OBJECT_CLASS (nm_device_parent_class)->dispose (object); +} + +static void +finalize (GObject *object) +{ + NMDevice *self = NM_DEVICE (object); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + + g_slist_free_full (priv->pending_actions, g_free); + g_clear_pointer (&priv->physical_port_id, g_free); + g_free (priv->udi); + g_free (priv->path); + g_free (priv->iface); + g_free (priv->ip_iface); + g_free (priv->driver); + g_free (priv->driver_version); + g_free (priv->firmware_version); + g_free (priv->type_desc); + if (priv->dhcp_anycast_address) + g_byte_array_free (priv->dhcp_anycast_address, TRUE); + + G_OBJECT_CLASS (nm_device_parent_class)->finalize (object); +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (object); + NMPlatformLink *platform_device; + const char *hw_addr; + + switch (prop_id) { + case PROP_PLATFORM_DEVICE: + platform_device = g_value_get_pointer (value); + if (platform_device) { + g_free (priv->udi); + priv->udi = g_strdup (platform_device->udi); + g_free (priv->iface); + priv->iface = g_strdup (platform_device->name); + priv->ifindex = platform_device->ifindex; + g_free (priv->driver); + priv->driver = g_strdup (platform_device->driver); + } + break; + case PROP_UDI: + if (g_value_get_string (value)) { + g_free (priv->udi); + priv->udi = g_value_dup_string (value); + } + break; + case PROP_IFACE: + if (g_value_get_string (value)) { + g_free (priv->iface); + priv->ifindex = 0; + priv->iface = g_value_dup_string (value); + + /* Only look up the ifindex if it appears to be an actual kernel + * interface name. eg Bluetooth devices won't have one until we know + * the IP interface. + */ + if (priv->iface && !strchr (priv->iface, ':')) { + priv->ifindex = nm_platform_link_get_ifindex (priv->iface); + if (priv->ifindex <= 0) + nm_log_warn (LOGD_HW, "(%s): failed to look up interface index", priv->iface); + } + } + break; + case PROP_DRIVER: + if (g_value_get_string (value)) { + g_free (priv->driver); + priv->driver = g_value_dup_string (value); + } + break; + case PROP_DRIVER_VERSION: + g_free (priv->driver_version); + priv->driver_version = g_strdup (g_value_get_string (value)); + break; + case PROP_FIRMWARE_VERSION: + g_free (priv->firmware_version); + priv->firmware_version = g_strdup (g_value_get_string (value)); + break; + case PROP_MTU: + priv->mtu = g_value_get_uint (value); + break; + case PROP_IP4_ADDRESS: + priv->ip4_address = g_value_get_uint (value); + break; + case PROP_AUTOCONNECT: + priv->autoconnect = g_value_get_boolean (value); + break; + case PROP_FIRMWARE_MISSING: + priv->firmware_missing = g_value_get_boolean (value); + break; + case PROP_DEVICE_TYPE: + g_return_if_fail (priv->type == NM_DEVICE_TYPE_UNKNOWN); + priv->type = g_value_get_uint (value); + break; + case PROP_TYPE_DESC: + g_free (priv->type_desc); + priv->type_desc = g_value_dup_string (value); + break; + case PROP_RFKILL_TYPE: + priv->rfkill_type = g_value_get_uint (value); + break; + case PROP_IS_MASTER: + priv->is_master = g_value_get_boolean (value); + break; + case PROP_HW_ADDRESS: + priv->hw_addr_len = nm_device_get_hw_address_length (NM_DEVICE (object), NULL); + + hw_addr = g_value_get_string (value); + if (!hw_addr) + break; + if (priv->hw_addr_len == 0) { + g_warn_if_fail (*hw_addr == '\0'); + break; + } + + if (!nm_utils_hwaddr_aton_len (hw_addr, priv->hw_addr, priv->hw_addr_len)) { + g_warning ("Could not parse hw-address '%s'", hw_addr); + memset (priv->hw_addr, 0, sizeof (priv->hw_addr)); + } + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +#define DBUS_TYPE_STATE_REASON_STRUCT (dbus_g_type_get_struct ("GValueArray", G_TYPE_UINT, G_TYPE_UINT, G_TYPE_INVALID)) + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMDevice *self = NM_DEVICE (object); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + const char *ac_path = NULL; + GPtrArray *array; + GHashTableIter iter; + NMConnection *connection; + + switch (prop_id) { + case PROP_UDI: + g_value_set_string (value, priv->udi); + break; + case PROP_IFACE: + g_value_set_string (value, priv->iface); + break; + case PROP_IP_IFACE: + if (ip_config_valid (priv->state)) + g_value_set_string (value, nm_device_get_ip_iface (self)); + else + g_value_set_string (value, NULL); + break; + case PROP_IFINDEX: + g_value_set_int (value, priv->ifindex); + break; + case PROP_DRIVER: + g_value_set_string (value, priv->driver); + break; + case PROP_DRIVER_VERSION: + g_value_set_string (value, priv->driver_version); + break; + case PROP_FIRMWARE_VERSION: + g_value_set_string (value, priv->firmware_version); + break; + case PROP_CAPABILITIES: + g_value_set_uint (value, (priv->capabilities & ~NM_DEVICE_CAP_INTERNAL_MASK)); + break; + case PROP_IP4_ADDRESS: + g_value_set_uint (value, priv->ip4_address); + break; + case PROP_CARRIER: + g_value_set_boolean (value, priv->carrier); + break; + case PROP_MTU: + g_value_set_uint (value, priv->mtu); + break; + case PROP_IP4_CONFIG: + if (ip_config_valid (priv->state) && priv->ip4_config) + g_value_set_boxed (value, nm_ip4_config_get_dbus_path (priv->ip4_config)); + else + g_value_set_boxed (value, "/"); + break; + case PROP_DHCP4_CONFIG: + if (ip_config_valid (priv->state) && priv->dhcp4_config) + g_value_set_boxed (value, nm_dhcp4_config_get_dbus_path (priv->dhcp4_config)); + else + g_value_set_boxed (value, "/"); + break; + case PROP_IP6_CONFIG: + if (ip_config_valid (priv->state) && priv->ip6_config) + g_value_set_boxed (value, nm_ip6_config_get_dbus_path (priv->ip6_config)); + else + g_value_set_boxed (value, "/"); + break; + case PROP_DHCP6_CONFIG: + if (ip_config_valid (priv->state) && priv->dhcp6_config) + g_value_set_boxed (value, nm_dhcp6_config_get_dbus_path (priv->dhcp6_config)); + else + g_value_set_boxed (value, "/"); + break; + case PROP_STATE: + g_value_set_uint (value, priv->state); + break; + case PROP_STATE_REASON: + g_value_take_boxed (value, dbus_g_type_specialized_construct (DBUS_TYPE_STATE_REASON_STRUCT)); + dbus_g_type_struct_set (value, 0, priv->state, 1, priv->state_reason, G_MAXUINT); + break; + case PROP_ACTIVE_CONNECTION: + if (priv->act_request) + ac_path = nm_active_connection_get_path (NM_ACTIVE_CONNECTION (priv->act_request)); + g_value_set_boxed (value, ac_path ? ac_path : "/"); + break; + case PROP_DEVICE_TYPE: + g_value_set_uint (value, priv->type); + break; + case PROP_MANAGED: + g_value_set_boolean (value, nm_device_get_managed (self)); + break; + case PROP_AUTOCONNECT: + g_value_set_boolean (value, priv->autoconnect); + break; + case PROP_FIRMWARE_MISSING: + g_value_set_boolean (value, priv->firmware_missing); + break; + case PROP_TYPE_DESC: + g_value_set_string (value, priv->type_desc); + break; + case PROP_RFKILL_TYPE: + g_value_set_uint (value, priv->rfkill_type); + break; + case PROP_AVAILABLE_CONNECTIONS: + array = g_ptr_array_sized_new (g_hash_table_size (priv->available_connections)); + g_hash_table_iter_init (&iter, priv->available_connections); + while (g_hash_table_iter_next (&iter, (gpointer) &connection, NULL)) + g_ptr_array_add (array, g_strdup (nm_connection_get_path (connection))); + g_value_take_boxed (value, array); + break; + case PROP_PHYSICAL_PORT_ID: + g_value_set_string (value, priv->physical_port_id); + break; + case PROP_IS_MASTER: + g_value_set_boolean (value, priv->is_master); + break; + case PROP_MASTER: + g_value_set_object (value, priv->master); + break; + case PROP_HW_ADDRESS: + if (priv->hw_addr_len) + g_value_take_string (value, nm_utils_hwaddr_ntoa_len (priv->hw_addr, priv->hw_addr_len)); + else + g_value_set_string (value, NULL); + break; + case PROP_HAS_PENDING_ACTION: + g_value_set_boolean (value, nm_device_has_pending_action (self)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_device_class_init (NMDeviceClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (NMDevicePrivate)); + + /* Virtual methods */ + object_class->dispose = dispose; + object_class->finalize = finalize; + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->constructor = constructor; + object_class->constructed = constructed; + + klass->link_changed = link_changed; + + klass->is_available = is_available; + klass->act_stage1_prepare = act_stage1_prepare; + klass->act_stage2_config = act_stage2_config; + klass->act_stage3_ip4_config_start = act_stage3_ip4_config_start; + klass->act_stage3_ip6_config_start = act_stage3_ip6_config_start; + klass->act_stage4_ip4_config_timeout = act_stage4_ip4_config_timeout; + klass->act_stage4_ip6_config_timeout = act_stage4_ip6_config_timeout; + klass->have_any_ready_slaves = have_any_ready_slaves; + + klass->spec_match_list = spec_match_list; + klass->can_auto_connect = can_auto_connect; + klass->check_connection_compatible = check_connection_compatible; + klass->check_connection_available = check_connection_available; + klass->is_up = is_up; + klass->bring_up = bring_up; + klass->take_down = take_down; + klass->carrier_changed = carrier_changed; + klass->get_hw_address_length = get_hw_address_length; + + /* Properties */ + g_object_class_install_property + (object_class, PROP_PLATFORM_DEVICE, + g_param_spec_pointer (NM_DEVICE_PLATFORM_DEVICE, + "Platform Device", + "NMPlatform device object", + G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property + (object_class, PROP_UDI, + g_param_spec_string (NM_DEVICE_UDI, + "UDI", + "Unique Device Identifier", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + g_object_class_install_property + (object_class, PROP_IFACE, + g_param_spec_string (NM_DEVICE_IFACE, + "Interface", + "Interface", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property + (object_class, PROP_IP_IFACE, + g_param_spec_string (NM_DEVICE_IP_IFACE, + "IP Interface", + "IP Interface", + NULL, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_DRIVER, + g_param_spec_string (NM_DEVICE_DRIVER, + "Driver", + "Driver", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property + (object_class, PROP_DRIVER_VERSION, + g_param_spec_string (NM_DEVICE_DRIVER_VERSION, + "Driver Version", + "Driver Version", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property + (object_class, PROP_FIRMWARE_VERSION, + g_param_spec_string (NM_DEVICE_FIRMWARE_VERSION, + "Firmware Version", + "Firmware Version", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property + (object_class, PROP_CAPABILITIES, + g_param_spec_uint (NM_DEVICE_CAPABILITIES, + "Capabilities", + "Capabilities", + 0, G_MAXUINT32, NM_DEVICE_CAP_NONE, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_CARRIER, + g_param_spec_boolean (NM_DEVICE_CARRIER, + "Carrier", + "Carrier", + FALSE, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_MTU, + g_param_spec_uint (NM_DEVICE_MTU, + "MTU", + "MTU", + 0, G_MAXUINT32, 1500, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_IP4_ADDRESS, + g_param_spec_uint (NM_DEVICE_IP4_ADDRESS, + "IP4 address", + "IP4 address", + 0, G_MAXUINT32, 0, /* FIXME */ + G_PARAM_READWRITE)); + + g_object_class_install_property + (object_class, PROP_IP4_CONFIG, + g_param_spec_boxed (NM_DEVICE_IP4_CONFIG, + "IP4 Config", + "IP4 Config", + DBUS_TYPE_G_OBJECT_PATH, + G_PARAM_READWRITE)); + + g_object_class_install_property + (object_class, PROP_DHCP4_CONFIG, + g_param_spec_boxed (NM_DEVICE_DHCP4_CONFIG, + "DHCP4 Config", + "DHCP4 Config", + DBUS_TYPE_G_OBJECT_PATH, + G_PARAM_READWRITE)); + + g_object_class_install_property + (object_class, PROP_IP6_CONFIG, + g_param_spec_boxed (NM_DEVICE_IP6_CONFIG, + "IP6 Config", + "IP6 Config", + DBUS_TYPE_G_OBJECT_PATH, + G_PARAM_READWRITE)); + + g_object_class_install_property + (object_class, PROP_DHCP6_CONFIG, + g_param_spec_boxed (NM_DEVICE_DHCP6_CONFIG, + "DHCP6 Config", + "DHCP6 Config", + DBUS_TYPE_G_OBJECT_PATH, + G_PARAM_READWRITE)); + + g_object_class_install_property + (object_class, PROP_STATE, + g_param_spec_uint (NM_DEVICE_STATE, + "State", + "State", + 0, G_MAXUINT32, NM_DEVICE_STATE_UNKNOWN, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_STATE_REASON, + g_param_spec_boxed (NM_DEVICE_STATE_REASON, + "StateReason", + "StateReason", + DBUS_TYPE_STATE_REASON_STRUCT, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_ACTIVE_CONNECTION, + g_param_spec_boxed (NM_DEVICE_ACTIVE_CONNECTION, + "ActiveConnection", + "ActiveConnection", + DBUS_TYPE_G_OBJECT_PATH, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_DEVICE_TYPE, + g_param_spec_uint (NM_DEVICE_DEVICE_TYPE, + "DeviceType", + "DeviceType", + 0, G_MAXUINT32, NM_DEVICE_TYPE_UNKNOWN, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property + (object_class, PROP_MANAGED, + g_param_spec_boolean (NM_DEVICE_MANAGED, + "Managed", + "Managed", + FALSE, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_AUTOCONNECT, + g_param_spec_boolean (NM_DEVICE_AUTOCONNECT, + "Autoconnect", + "Autoconnect", + DEFAULT_AUTOCONNECT, + G_PARAM_READWRITE)); + + g_object_class_install_property + (object_class, PROP_FIRMWARE_MISSING, + g_param_spec_boolean (NM_DEVICE_FIRMWARE_MISSING, + "FirmwareMissing", + "Firmware missing", + FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property + (object_class, PROP_TYPE_DESC, + g_param_spec_string (NM_DEVICE_TYPE_DESC, + "Type Description", + "Device type description", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property + (object_class, PROP_RFKILL_TYPE, + g_param_spec_uint (NM_DEVICE_RFKILL_TYPE, + "Rfkill Type", + "Type of rfkill switch (if any) supported by this device", + RFKILL_TYPE_WLAN, + RFKILL_TYPE_MAX, + RFKILL_TYPE_UNKNOWN, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property + (object_class, PROP_IFINDEX, + g_param_spec_int (NM_DEVICE_IFINDEX, + "Ifindex", + "Ifindex", + 0, G_MAXINT, 0, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_AVAILABLE_CONNECTIONS, + g_param_spec_boxed (NM_DEVICE_AVAILABLE_CONNECTIONS, + "AvailableConnections", + "AvailableConnections", + DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_PHYSICAL_PORT_ID, + g_param_spec_string (NM_DEVICE_PHYSICAL_PORT_ID, + "PhysicalPortId", + "PhysicalPortId", + NULL, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_IS_MASTER, + g_param_spec_boolean (NM_DEVICE_IS_MASTER, + "IsMaster", + "IsMaster", + FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property + (object_class, PROP_MASTER, + g_param_spec_object (NM_DEVICE_MASTER, + "Master", + "Master", + NM_TYPE_DEVICE, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_HW_ADDRESS, + g_param_spec_string (NM_DEVICE_HW_ADDRESS, + "Hardware Address", + "Hardware address", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property + (object_class, PROP_HAS_PENDING_ACTION, + g_param_spec_boolean (NM_DEVICE_HAS_PENDING_ACTION, + "Has pending action", + "Has pending action", + FALSE, + G_PARAM_READABLE)); + + /* Signals */ + signals[STATE_CHANGED] = + g_signal_new ("state-changed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (NMDeviceClass, state_changed), + NULL, NULL, NULL, + G_TYPE_NONE, 3, + G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT); + + signals[AUTOCONNECT_ALLOWED] = + g_signal_new ("autoconnect-allowed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + 0, + autoconnect_allowed_accumulator, NULL, NULL, + G_TYPE_BOOLEAN, 0); + + signals[AUTH_REQUEST] = + g_signal_new (NM_DEVICE_AUTH_REQUEST, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, NULL, + /* dbus-glib context, connection, permission, allow_interaction, callback, user_data */ + G_TYPE_NONE, 6, G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_POINTER, G_TYPE_POINTER); + + signals[IP4_CONFIG_CHANGED] = + g_signal_new (NM_DEVICE_IP4_CONFIG_CHANGED, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, NULL, + G_TYPE_NONE, 2, G_TYPE_OBJECT, G_TYPE_OBJECT); + + signals[IP6_CONFIG_CHANGED] = + g_signal_new (NM_DEVICE_IP6_CONFIG_CHANGED, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, NULL, + G_TYPE_NONE, 2, G_TYPE_OBJECT, G_TYPE_OBJECT); + + signals[REMOVED] = + g_signal_new (NM_DEVICE_REMOVED, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, NULL, + G_TYPE_NONE, 0); + + signals[RECHECK_AUTO_ACTIVATE] = + g_signal_new (NM_DEVICE_RECHECK_AUTO_ACTIVATE, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, NULL, + G_TYPE_NONE, 0); + + signals[RECHECK_ASSUME] = + g_signal_new (NM_DEVICE_RECHECK_ASSUME, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, NULL, + G_TYPE_NONE, 0); + + nm_dbus_manager_register_exported_type (nm_dbus_manager_get (), + G_TYPE_FROM_CLASS (klass), + &dbus_glib_nm_device_object_info); + + dbus_g_error_domain_register (NM_DEVICE_ERROR, NULL, NM_TYPE_DEVICE_ERROR); +} + diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h new file mode 100644 index 00000000..f74486e6 --- /dev/null +++ b/src/devices/nm-device.h @@ -0,0 +1,363 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2005 - 2013 Red Hat, Inc. + * Copyright (C) 2006 - 2008 Novell, Inc. + */ + +#ifndef NM_DEVICE_H +#define NM_DEVICE_H + +#include +#include +#include + +#include "NetworkManager.h" +#include "nm-types.h" +#include "nm-activation-request.h" +#include "nm-ip4-config.h" +#include "nm-ip6-config.h" +#include "nm-dhcp4-config.h" +#include "nm-dhcp6-config.h" +#include "nm-connection.h" +#include "nm-rfkill-manager.h" +#include "nm-connection-provider.h" +#include "nm-platform.h" + +/* Properties */ +#define NM_DEVICE_UDI "udi" +#define NM_DEVICE_IFACE "interface" +#define NM_DEVICE_IP_IFACE "ip-interface" +#define NM_DEVICE_DRIVER "driver" +#define NM_DEVICE_DRIVER_VERSION "driver-version" +#define NM_DEVICE_FIRMWARE_VERSION "firmware-version" +#define NM_DEVICE_CAPABILITIES "capabilities" +#define NM_DEVICE_CARRIER "carrier" +#define NM_DEVICE_IP4_ADDRESS "ip4-address" +#define NM_DEVICE_IP4_CONFIG "ip4-config" +#define NM_DEVICE_DHCP4_CONFIG "dhcp4-config" +#define NM_DEVICE_IP6_CONFIG "ip6-config" +#define NM_DEVICE_DHCP6_CONFIG "dhcp6-config" +#define NM_DEVICE_STATE "state" +#define NM_DEVICE_STATE_REASON "state-reason" +#define NM_DEVICE_ACTIVE_CONNECTION "active-connection" +#define NM_DEVICE_DEVICE_TYPE "device-type" /* ugh */ +#define NM_DEVICE_MANAGED "managed" +#define NM_DEVICE_AUTOCONNECT "autoconnect" +#define NM_DEVICE_FIRMWARE_MISSING "firmware-missing" +#define NM_DEVICE_AVAILABLE_CONNECTIONS "available-connections" +#define NM_DEVICE_PHYSICAL_PORT_ID "physical-port-id" +#define NM_DEVICE_MTU "mtu" +#define NM_DEVICE_TYPE_DESC "type-desc" /* Internal only */ +#define NM_DEVICE_RFKILL_TYPE "rfkill-type" /* Internal only */ +#define NM_DEVICE_IFINDEX "ifindex" /* Internal only */ +#define NM_DEVICE_IS_MASTER "is-master" /* Internal only */ +#define NM_DEVICE_MASTER "master" /* Internal only */ +#define NM_DEVICE_HW_ADDRESS "hw-address" /* Internal only */ +#define NM_DEVICE_HAS_PENDING_ACTION "has-pending-action" /* Internal only */ + +/* Internal signals */ +#define NM_DEVICE_AUTH_REQUEST "auth-request" +#define NM_DEVICE_IP4_CONFIG_CHANGED "ip4-config-changed" +#define NM_DEVICE_IP6_CONFIG_CHANGED "ip6-config-changed" +#define NM_DEVICE_REMOVED "removed" +#define NM_DEVICE_RECHECK_AUTO_ACTIVATE "recheck-auto-activate" +#define NM_DEVICE_RECHECK_ASSUME "recheck-assume" + + +G_BEGIN_DECLS + +#define NM_TYPE_DEVICE (nm_device_get_type ()) +#define NM_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE, NMDevice)) +#define NM_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE, NMDeviceClass)) +#define NM_IS_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE)) +#define NM_IS_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE)) +#define NM_DEVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE, NMDeviceClass)) + +typedef enum NMActStageReturn NMActStageReturn; + +typedef enum { + NM_DEVICE_ERROR_CONNECTION_ACTIVATING = 0, /*< nick=ConnectionActivating >*/ + NM_DEVICE_ERROR_CONNECTION_INVALID, /*< nick=ConnectionInvalid >*/ + NM_DEVICE_ERROR_NOT_ACTIVE, /*< nick=NotActive >*/ +} NMDeviceError; + +struct _NMDevice { + GObject parent; +}; + +typedef struct { + GObjectClass parent; + + const char *connection_type; + + void (*state_changed) (NMDevice *device, + NMDeviceState new_state, + NMDeviceState old_state, + NMDeviceStateReason reason); + + void (* link_changed) (NMDevice *self, NMPlatformLink *info); + + /* Hardware state (IFF_UP) */ + gboolean (*is_up) (NMDevice *self); + gboolean (*bring_up) (NMDevice *self, gboolean *no_firmware); + gboolean (*take_down) (NMDevice *self); + + /* Carrier state (IFF_LOWER_UP) */ + void (*carrier_changed) (NMDevice *, gboolean carrier); + + void (* update_hw_address) (NMDevice *self); + void (* update_permanent_hw_address) (NMDevice *self); + void (* update_initial_hw_address) (NMDevice *self); + guint (* get_hw_address_length) (NMDevice *self, gboolean *out_permanent); + + guint32 (* get_generic_capabilities) (NMDevice *self); + + gboolean (* is_available) (NMDevice *self); + + gboolean (* get_enabled) (NMDevice *self); + + void (* set_enabled) (NMDevice *self, gboolean enabled); + + gboolean (* can_auto_connect) (NMDevice *self, + NMConnection *connection, + char **specific_object); + + /* Checks whether the connection is compatible with the device using + * only the devices type and characteristics. Does not use any live + * network information like WiFi/WiMAX scan lists etc. + */ + gboolean (* check_connection_compatible) (NMDevice *self, NMConnection *connection); + + /* Checks whether the connection is likely available to be activated, + * including any live network information like scan lists. The connection + * is checked against the object defined by @specific_object, if given. + * Returns TRUE if the connection is available; FALSE if not. + */ + gboolean (* check_connection_available) (NMDevice *self, + NMConnection *connection, + const char *specific_object); + + /* Same as check_connection_available() but called if the connection + * is not present in the activating-connections array during activation, + * to give the device a chance to allow/deny the activation. This is a + * hack only meant for hidden WiFi networks. + */ + gboolean (* check_connection_available_wifi_hidden) (NMDevice *self, + NMConnection *connection); + + gboolean (* complete_connection) (NMDevice *self, + NMConnection *connection, + const char *specific_object, + const GSList *existing_connections, + GError **error); + + NMActStageReturn (* act_stage1_prepare) (NMDevice *self, + NMDeviceStateReason *reason); + NMActStageReturn (* act_stage2_config) (NMDevice *self, + NMDeviceStateReason *reason); + NMActStageReturn (* act_stage3_ip4_config_start) (NMDevice *self, + NMIP4Config **out_config, + NMDeviceStateReason *reason); + NMActStageReturn (* act_stage3_ip6_config_start) (NMDevice *self, + NMIP6Config **out_config, + NMDeviceStateReason *reason); + NMActStageReturn (* act_stage4_ip4_config_timeout) (NMDevice *self, + NMDeviceStateReason *reason); + NMActStageReturn (* act_stage4_ip6_config_timeout) (NMDevice *self, + NMDeviceStateReason *reason); + + /* Called right before IP config is set; use for setting MTU etc */ + void (* ip4_config_pre_commit) (NMDevice *self, NMIP4Config *config); + void (* ip6_config_pre_commit) (NMDevice *self); + + void (* deactivate) (NMDevice *self); + + gboolean (* spec_match_list) (NMDevice *self, const GSList *specs); + + /* Update the connection with currently configured L2 settings */ + void (* update_connection) (NMDevice *device, NMConnection *connection); + + gboolean (* enslave_slave) (NMDevice *self, + NMDevice *slave, + NMConnection *connection, + gboolean configure); + + gboolean (* release_slave) (NMDevice *self, + NMDevice *slave, + gboolean configure); + + gboolean (* have_any_ready_slaves) (NMDevice *self, + const GSList *slaves); + + gboolean (* component_added) (NMDevice *self, GObject *component); + + gboolean (* owns_iface) (NMDevice *self, const char *iface); +} NMDeviceClass; + + +typedef void (*NMDeviceAuthRequestFunc) (NMDevice *device, + DBusGMethodInvocation *context, + GError *error, + gpointer user_data); + +GType nm_device_get_type (void); + +const char * nm_device_get_path (NMDevice *dev); +void nm_device_dbus_export (NMDevice *device); + +const char * nm_device_get_udi (NMDevice *dev); +const char * nm_device_get_iface (NMDevice *dev); +int nm_device_get_ifindex (NMDevice *dev); +gboolean nm_device_is_software (NMDevice *dev); +const char * nm_device_get_ip_iface (NMDevice *dev); +int nm_device_get_ip_ifindex(NMDevice *dev); +const char * nm_device_get_driver (NMDevice *dev); +const char * nm_device_get_driver_version (NMDevice *dev); +const char * nm_device_get_type_desc (NMDevice *dev); +NMDeviceType nm_device_get_device_type (NMDevice *dev); + +int nm_device_get_priority (NMDevice *dev); + +const guint8 * nm_device_get_hw_address (NMDevice *dev, guint *out_len); + +NMDHCP4Config * nm_device_get_dhcp4_config (NMDevice *dev); +NMDHCP6Config * nm_device_get_dhcp6_config (NMDevice *dev); + +NMIP4Config * nm_device_get_ip4_config (NMDevice *dev); +void nm_device_set_vpn4_config (NMDevice *dev, NMIP4Config *config); + +NMIP6Config * nm_device_get_ip6_config (NMDevice *dev); +void nm_device_set_vpn6_config (NMDevice *dev, NMIP6Config *config); + +void nm_device_capture_initial_config (NMDevice *dev); + +/* Master */ +GSList * nm_device_master_get_slaves (NMDevice *dev); + +/* Slave */ +NMDevice * nm_device_get_master (NMDevice *dev); + +NMActRequest * nm_device_get_act_request (NMDevice *dev); +NMConnection * nm_device_get_connection (NMDevice *dev); + +gboolean nm_device_is_available (NMDevice *dev); +gboolean nm_device_has_carrier (NMDevice *dev); + +NMConnection * nm_device_generate_connection (NMDevice *device); + +NMConnection * nm_device_get_best_auto_connection (NMDevice *dev, + GSList *connections, + char **specific_object); + +gboolean nm_device_complete_connection (NMDevice *device, + NMConnection *connection, + const char *specific_object, + const GSList *existing_connection, + GError **error); + +gboolean nm_device_check_connection_compatible (NMDevice *device, NMConnection *connection); + +gboolean nm_device_can_assume_active_connection (NMDevice *device); + +gboolean nm_device_spec_match_list (NMDevice *device, const GSList *specs); + +gboolean nm_device_is_activating (NMDevice *dev); +gboolean nm_device_autoconnect_allowed (NMDevice *self); + +NMDeviceState nm_device_get_state (NMDevice *device); + +gboolean nm_device_get_enabled (NMDevice *device); + +void nm_device_set_enabled (NMDevice *device, gboolean enabled); + +RfKillType nm_device_get_rfkill_type (NMDevice *device); + +/** + * NMUnmanagedFlags: + * @NM_UNMANAGED_NONE: placeholder value + * @NM_UNMANAGED_DEFAULT: %TRUE when unmanaged by default (ie, Generic devices) + * @NM_UNMANAGED_INTERNAL: %TRUE when unmanaged by internal decision (ie, + * because NM is sleeping or not managed for some other reason) + * @NM_UNMANAGED_USER: %TRUE when unmanaged by user decision (via unmanaged-specs) + */ +typedef enum { + NM_UNMANAGED_NONE = 0x00, + NM_UNMANAGED_DEFAULT = 0x01, + NM_UNMANAGED_INTERNAL = 0x02, + NM_UNMANAGED_USER = 0x04, + + /* Boundary value */ + __NM_UNMANAGED_LAST, + NM_UNMANAGED_LAST = __NM_UNMANAGED_LAST - 1, +} NMUnmanagedFlags; + +gboolean nm_device_get_managed (NMDevice *device); +gboolean nm_device_get_unmanaged_flag (NMDevice *device, NMUnmanagedFlags flag); +void nm_device_set_unmanaged (NMDevice *device, + NMUnmanagedFlags flag, + gboolean unmanaged, + NMDeviceStateReason reason); +void nm_device_set_unmanaged_quitting (NMDevice *device); +void nm_device_set_initial_unmanaged_flag (NMDevice *device, + NMUnmanagedFlags flag, + gboolean unmanaged); + +gboolean nm_device_get_is_nm_owned (NMDevice *device); +void nm_device_set_nm_owned (NMDevice *device); + +gboolean nm_device_get_autoconnect (NMDevice *device); + +void nm_device_handle_autoip4_event (NMDevice *self, + const char *event, + const char *address); + +void nm_device_state_changed (NMDevice *device, + NMDeviceState state, + NMDeviceStateReason reason); + +void nm_device_queue_state (NMDevice *self, + NMDeviceState state, + NMDeviceStateReason reason); + +gboolean nm_device_get_firmware_missing (NMDevice *self); + +void nm_device_queue_activation (NMDevice *device, NMActRequest *req); + +gboolean nm_device_supports_vlans (NMDevice *device); + +gboolean nm_device_add_pending_action (NMDevice *device, const char *action, gboolean assert_not_yet_pending); +gboolean nm_device_remove_pending_action (NMDevice *device, const char *action, gboolean assert_is_pending); +gboolean nm_device_has_pending_action (NMDevice *device); + +GPtrArray *nm_device_get_available_connections (NMDevice *device, + const char *specific_object); + +gboolean nm_device_connection_is_available (NMDevice *device, + NMConnection *connection, + gboolean allow_device_override); + +gboolean nm_device_notify_component_added (NMDevice *device, GObject *component); + +gboolean nm_device_owns_iface (NMDevice *device, const char *iface); + +G_END_DECLS + +/* For testing only */ +extern const char* nm_device_autoipd_helper_path; + +#endif /* NM_DEVICE_H */ diff --git a/src/devices/wifi/Makefile.am b/src/devices/wifi/Makefile.am new file mode 100644 index 00000000..5f3ce286 --- /dev/null +++ b/src/devices/wifi/Makefile.am @@ -0,0 +1,78 @@ +include $(GLIB_MAKEFILE) + +@GNOME_CODE_COVERAGE_RULES@ + +SUBDIRS=. tests + +AM_CPPFLAGS = \ + -I${top_srcdir}/src \ + -I${top_builddir}/src \ + -I${top_srcdir}/src/logging \ + -I${top_srcdir}/src/devices \ + -I${top_srcdir}/src/settings \ + -I${top_srcdir}/src/platform \ + -I${top_srcdir}/src/supplicant-manager \ + -I${top_builddir}/include \ + -I${top_srcdir}/include \ + -I${top_builddir}/libnm-util \ + -I${top_srcdir}/libnm-util \ + -DG_LOG_DOMAIN=\""NetworkManager-wifi"\" \ + -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \ + $(DBUS_CFLAGS) \ + $(POLKIT_CFLAGS) \ + $(LIBNL_CFLAGS) \ + $(GUDEV_CFLAGS) + +GLIB_GENERATED = nm-wifi-enum-types.h nm-wifi-enum-types.c +GLIB_MKENUMS_H_FLAGS = --identifier-prefix NM +GLIB_MKENUMS_C_FLAGS = --identifier-prefix NM +nm_wifi_enum_types_sources = \ + $(srcdir)/nm-device-wifi.h \ + $(srcdir)/nm-wifi-ap.h \ + $(srcdir)/nm-device-olpc-mesh.h + +glue_sources = \ + nm-device-wifi-glue.h \ + nm-device-olpc-mesh-glue.h + +%-glue.h: $(top_srcdir)/introspection/%.xml + $(AM_V_GEN) dbus-binding-tool --prefix=$(subst -,_,$(subst -glue.h,,$@)) --mode=glib-server --output=$@ $< + +BUILT_SOURCES = $(GLIB_GENERATED) $(glue_sources) + +pkglib_LTLIBRARIES = libnm-device-plugin-wifi.la + +libnm_device_plugin_wifi_la_SOURCES = \ + nm-wifi-factory.c \ + nm-device-wifi.c \ + nm-device-wifi.h \ + nm-wifi-ap.c \ + nm-wifi-ap.h \ + nm-wifi-ap-utils.c \ + nm-wifi-ap-utils.h \ + nm-device-olpc-mesh.c \ + nm-device-olpc-mesh.h \ + \ + $(BUILT_SOURCES) + +SYMBOL_VIS_FILE=$(srcdir)/exports.ver + +libnm_device_plugin_wifi_la_LDFLAGS = \ + -module -avoid-version \ + -Wl,--version-script=$(SYMBOL_VIS_FILE) + +libnm_device_plugin_wifi_la_LIBADD = \ + $(DBUS_LIBS) \ + $(GUDEV_LIBS) + +CLEANFILES = $(BUILT_SOURCES) + +EXTRA_DIST = $(SYMBOL_VIS_FILE) + +if ENABLE_TESTS + +check-local: + $(top_srcdir)/tools/check-exports.sh $(builddir)/.libs/libnm-device-plugin-wifi.so $(SYMBOL_VIS_FILE) + +endif + diff --git a/src/devices/wifi/Makefile.in b/src/devices/wifi/Makefile.in new file mode 100644 index 00000000..cbf6826b --- /dev/null +++ b/src/devices/wifi/Makefile.in @@ -0,0 +1,983 @@ +# Makefile.in generated by automake 1.13.4 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/devices/wifi +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(top_srcdir)/build-aux/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_lib_readline.m4 \ + $(top_srcdir)/m4/compiler_warnings.m4 \ + $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/gnome-code-coverage.m4 \ + $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ + $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \ + $(top_srcdir)/m4/introspection.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ + $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ + $(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(pkglibdir)" +LTLIBRARIES = $(pkglib_LTLIBRARIES) +am__DEPENDENCIES_1 = +libnm_device_plugin_wifi_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +am__objects_1 = nm-wifi-enum-types.lo +am__objects_2 = +am__objects_3 = $(am__objects_1) $(am__objects_2) +am_libnm_device_plugin_wifi_la_OBJECTS = nm-wifi-factory.lo \ + nm-device-wifi.lo nm-wifi-ap.lo nm-wifi-ap-utils.lo \ + nm-device-olpc-mesh.lo $(am__objects_3) +libnm_device_plugin_wifi_la_OBJECTS = \ + $(am_libnm_device_plugin_wifi_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libnm_device_plugin_wifi_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(libnm_device_plugin_wifi_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libnm_device_plugin_wifi_la_SOURCES) +DIST_SOURCES = $(libnm_device_plugin_wifi_la_SOURCES) +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +ALL_LINGUAS = @ALL_LINGUAS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CKDB_PATH = @CKDB_PATH@ +CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@ +CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@ +CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIRNAME = @DATADIRNAME@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_100_CFLAGS = @DBUS_GLIB_100_CFLAGS@ +DBUS_GLIB_100_LIBS = @DBUS_GLIB_100_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DHCLIENT_PATH = @DHCLIENT_PATH@ +DHCPCD_PATH = @DHCPCD_PATH@ +DISTRO_NETWORK_SERVICE = @DISTRO_NETWORK_SERVICE@ +DLLTOOL = @DLLTOOL@ +DNSMASQ_PATH = @DNSMASQ_PATH@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GENHTML = @GENHTML@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MAKEFILE = @GLIB_MAKEFILE@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ +GNUTLS_LIBS = @GNUTLS_LIBS@ +GREP = @GREP@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GUDEV_CFLAGS = @GUDEV_CFLAGS@ +GUDEV_LIBS = @GUDEV_LIBS@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_PERL = @INTLTOOL_PERL@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ +INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ +INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ +INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +IPTABLES_PATH = @IPTABLES_PATH@ +IWMX_SDK_CFLAGS = @IWMX_SDK_CFLAGS@ +IWMX_SDK_LIBS = @IWMX_SDK_LIBS@ +KERNEL_FIRMWARE_DIR = @KERNEL_FIRMWARE_DIR@ +LCOV = @LCOV@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDL = @LIBDL@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBM = @LIBM@ +LIBNDP_CFLAGS = @LIBNDP_CFLAGS@ +LIBNDP_LIBS = @LIBNDP_LIBS@ +LIBNL_CFLAGS = @LIBNL_CFLAGS@ +LIBNL_LIBS = @LIBNL_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@ +LIBSOUP_LIBS = @LIBSOUP_LIBS@ +LIBTEAMDCTL_CFLAGS = @LIBTEAMDCTL_CFLAGS@ +LIBTEAMDCTL_LIBS = @LIBTEAMDCTL_LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MM_GLIB_CFLAGS = @MM_GLIB_CFLAGS@ +MM_GLIB_LIBS = @MM_GLIB_LIBS@ +MOC = @MOC@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NEWT_CFLAGS = @NEWT_CFLAGS@ +NEWT_LIBS = @NEWT_LIBS@ +NM = @NM@ +NMEDIT = @NMEDIT@ +NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ +NM_MICRO_VERSION = @NM_MICRO_VERSION@ +NM_MINOR_VERSION = @NM_MINOR_VERSION@ +NM_MODIFY_SYSTEM_POLICY = @NM_MODIFY_SYSTEM_POLICY@ +NM_VERSION = @NM_VERSION@ +NSS_CFLAGS = @NSS_CFLAGS@ +NSS_LIBS = @NSS_LIBS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +POLKIT_CFLAGS = @POLKIT_CFLAGS@ +POLKIT_LIBS = @POLKIT_LIBS@ +POSUB = @POSUB@ +PPPD_PATH = @PPPD_PATH@ +PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@ +PPPOE_PATH = @PPPOE_PATH@ +QT_CFLAGS = @QT_CFLAGS@ +QT_LIBS = @QT_LIBS@ +RANLIB = @RANLIB@ +READLINE_LIBS = @READLINE_LIBS@ +SED = @SED@ +SELINUX_CFLAGS = @SELINUX_CFLAGS@ +SELINUX_LIBS = @SELINUX_LIBS@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SYSTEMD_200_CFLAGS = @SYSTEMD_200_CFLAGS@ +SYSTEMD_200_LIBS = @SYSTEMD_200_LIBS@ +SYSTEMD_INHIBIT_CFLAGS = @SYSTEMD_INHIBIT_CFLAGS@ +SYSTEMD_INHIBIT_LIBS = @SYSTEMD_INHIBIT_LIBS@ +SYSTEMD_LOGIN_CFLAGS = @SYSTEMD_LOGIN_CFLAGS@ +SYSTEMD_LOGIN_LIBS = @SYSTEMD_LOGIN_LIBS@ +SYSTEM_CA_PATH = @SYSTEM_CA_PATH@ +UDEV_BASE_DIR = @UDEV_BASE_DIR@ +USE_NLS = @USE_NLS@ +UUID_CFLAGS = @UUID_CFLAGS@ +UUID_LIBS = @UUID_LIBS@ +VALGRIND_RULES = @VALGRIND_RULES@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ +VERSION = @VERSION@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +intltool__v_merge_options_ = @intltool__v_merge_options_@ +intltool__v_merge_options_0 = @intltool__v_merge_options_0@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +nmbinary = @nmbinary@ +nmconfdir = @nmconfdir@ +nmdatadir = @nmdatadir@ +nmrundir = @nmrundir@ +nmstatedir = @nmstatedir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +with_dhclient = @with_dhclient@ +with_dhcpcd = @with_dhcpcd@ +with_netconfig = @with_netconfig@ +with_resolvconf = @with_resolvconf@ +with_valgrind = @with_valgrind@ +SUBDIRS = . tests +AM_CPPFLAGS = \ + -I${top_srcdir}/src \ + -I${top_builddir}/src \ + -I${top_srcdir}/src/logging \ + -I${top_srcdir}/src/devices \ + -I${top_srcdir}/src/settings \ + -I${top_srcdir}/src/platform \ + -I${top_srcdir}/src/supplicant-manager \ + -I${top_builddir}/include \ + -I${top_srcdir}/include \ + -I${top_builddir}/libnm-util \ + -I${top_srcdir}/libnm-util \ + -DG_LOG_DOMAIN=\""NetworkManager-wifi"\" \ + -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \ + $(DBUS_CFLAGS) \ + $(POLKIT_CFLAGS) \ + $(LIBNL_CFLAGS) \ + $(GUDEV_CFLAGS) + +GLIB_GENERATED = nm-wifi-enum-types.h nm-wifi-enum-types.c +GLIB_MKENUMS_H_FLAGS = --identifier-prefix NM +GLIB_MKENUMS_C_FLAGS = --identifier-prefix NM +nm_wifi_enum_types_sources = \ + $(srcdir)/nm-device-wifi.h \ + $(srcdir)/nm-wifi-ap.h \ + $(srcdir)/nm-device-olpc-mesh.h + +glue_sources = \ + nm-device-wifi-glue.h \ + nm-device-olpc-mesh-glue.h + +BUILT_SOURCES = $(GLIB_GENERATED) $(glue_sources) +pkglib_LTLIBRARIES = libnm-device-plugin-wifi.la +libnm_device_plugin_wifi_la_SOURCES = \ + nm-wifi-factory.c \ + nm-device-wifi.c \ + nm-device-wifi.h \ + nm-wifi-ap.c \ + nm-wifi-ap.h \ + nm-wifi-ap-utils.c \ + nm-wifi-ap-utils.h \ + nm-device-olpc-mesh.c \ + nm-device-olpc-mesh.h \ + \ + $(BUILT_SOURCES) + +SYMBOL_VIS_FILE = $(srcdir)/exports.ver +libnm_device_plugin_wifi_la_LDFLAGS = \ + -module -avoid-version \ + -Wl,--version-script=$(SYMBOL_VIS_FILE) + +libnm_device_plugin_wifi_la_LIBADD = \ + $(DBUS_LIBS) \ + $(GUDEV_LIBS) + +CLEANFILES = $(BUILT_SOURCES) +EXTRA_DIST = $(SYMBOL_VIS_FILE) +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-recursive + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/devices/wifi/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/devices/wifi/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +install-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkglibdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ + } + +uninstall-pkglibLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ + done + +clean-pkglibLTLIBRARIES: + -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) + @list='$(pkglib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libnm-device-plugin-wifi.la: $(libnm_device_plugin_wifi_la_OBJECTS) $(libnm_device_plugin_wifi_la_DEPENDENCIES) $(EXTRA_libnm_device_plugin_wifi_la_DEPENDENCIES) + $(AM_V_CCLD)$(libnm_device_plugin_wifi_la_LINK) -rpath $(pkglibdir) $(libnm_device_plugin_wifi_la_OBJECTS) $(libnm_device_plugin_wifi_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-device-olpc-mesh.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-device-wifi.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-wifi-ap-utils.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-wifi-ap.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-wifi-enum-types.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-wifi-factory.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +@ENABLE_TESTS_FALSE@check-local: +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) check-local +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-recursive +all-am: Makefile $(LTLIBRARIES) +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(pkglibdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-recursive + +clean-am: clean-generic clean-libtool clean-pkglibLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-recursive + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: install-pkglibLTLIBRARIES + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-pkglibLTLIBRARIES + +.MAKE: $(am__recursive_targets) all check check-am install install-am \ + install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am check-local clean clean-generic clean-libtool \ + clean-pkglibLTLIBRARIES cscopelist-am ctags ctags-am distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-pkglibLTLIBRARIES \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am \ + uninstall-pkglibLTLIBRARIES + +include $(GLIB_MAKEFILE) + +@GNOME_CODE_COVERAGE_RULES@ + +%-glue.h: $(top_srcdir)/introspection/%.xml + $(AM_V_GEN) dbus-binding-tool --prefix=$(subst -,_,$(subst -glue.h,,$@)) --mode=glib-server --output=$@ $< + +@ENABLE_TESTS_TRUE@check-local: +@ENABLE_TESTS_TRUE@ $(top_srcdir)/tools/check-exports.sh $(builddir)/.libs/libnm-device-plugin-wifi.so $(SYMBOL_VIS_FILE) + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/devices/wifi/exports.ver b/src/devices/wifi/exports.ver new file mode 100644 index 00000000..d2c45124 --- /dev/null +++ b/src/devices/wifi/exports.ver @@ -0,0 +1,7 @@ +{ +global: + nm_device_factory_create; + nm_device_factory_get_device_type; +local: + *; +}; diff --git a/src/devices/wifi/nm-device-olpc-mesh-glue.h b/src/devices/wifi/nm-device-olpc-mesh-glue.h new file mode 100644 index 00000000..04b5e83f --- /dev/null +++ b/src/devices/wifi/nm-device-olpc-mesh-glue.h @@ -0,0 +1,73 @@ +/* Generated by dbus-binding-tool; do not edit! */ + + +#ifndef __dbus_glib_marshal_nm_device_olpc_mesh_MARSHAL_H__ +#define __dbus_glib_marshal_nm_device_olpc_mesh_MARSHAL_H__ + +#include + +G_BEGIN_DECLS + +#ifdef G_ENABLE_DEBUG +#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v) +#define g_marshal_value_peek_char(v) g_value_get_schar (v) +#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v) +#define g_marshal_value_peek_int(v) g_value_get_int (v) +#define g_marshal_value_peek_uint(v) g_value_get_uint (v) +#define g_marshal_value_peek_long(v) g_value_get_long (v) +#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v) +#define g_marshal_value_peek_int64(v) g_value_get_int64 (v) +#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v) +#define g_marshal_value_peek_enum(v) g_value_get_enum (v) +#define g_marshal_value_peek_flags(v) g_value_get_flags (v) +#define g_marshal_value_peek_float(v) g_value_get_float (v) +#define g_marshal_value_peek_double(v) g_value_get_double (v) +#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v) +#define g_marshal_value_peek_param(v) g_value_get_param (v) +#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v) +#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v) +#define g_marshal_value_peek_object(v) g_value_get_object (v) +#define g_marshal_value_peek_variant(v) g_value_get_variant (v) +#else /* !G_ENABLE_DEBUG */ +/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API. + * Do not access GValues directly in your code. Instead, use the + * g_value_get_*() functions + */ +#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int +#define g_marshal_value_peek_char(v) (v)->data[0].v_int +#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint +#define g_marshal_value_peek_int(v) (v)->data[0].v_int +#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint +#define g_marshal_value_peek_long(v) (v)->data[0].v_long +#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 +#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 +#define g_marshal_value_peek_enum(v) (v)->data[0].v_long +#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_float(v) (v)->data[0].v_float +#define g_marshal_value_peek_double(v) (v)->data[0].v_double +#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer +#endif /* !G_ENABLE_DEBUG */ + + +G_END_DECLS + +#endif /* __dbus_glib_marshal_nm_device_olpc_mesh_MARSHAL_H__ */ + +#include +static const DBusGMethodInfo dbus_glib_nm_device_olpc_mesh_methods[] = { +}; + +const DBusGObjectInfo dbus_glib_nm_device_olpc_mesh_object_info = { 1, + dbus_glib_nm_device_olpc_mesh_methods, + 0, +"\0", +"org.freedesktop.NetworkManager.Device.OlpcMesh\0PropertiesChanged\0\0", +"org.freedesktop.NetworkManager.Device.OlpcMesh\0HwAddress\0hw_address\0read\0org.freedesktop.NetworkManager.Device.OlpcMesh\0Companion\0companion\0read\0org.freedesktop.NetworkManager.Device.OlpcMesh\0ActiveChannel\0active_channel\0read\0\0" +}; + diff --git a/src/devices/wifi/nm-device-olpc-mesh.c b/src/devices/wifi/nm-device-olpc-mesh.c new file mode 100644 index 00000000..85214a70 --- /dev/null +++ b/src/devices/wifi/nm-device-olpc-mesh.c @@ -0,0 +1,585 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * Dan Williams + * Sjoerd Simons + * Daniel Drake + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * (C) Copyright 2005 - 2014 Red Hat, Inc. + * (C) Copyright 2008 Collabora Ltd. + * (C) Copyright 2009 One Laptop per Child + */ + +#include "config.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "nm-device.h" +#include "nm-device-wifi.h" +#include "nm-device-olpc-mesh.h" +#include "nm-device-private.h" +#include "nm-utils.h" +#include "nm-logging.h" +#include "NetworkManagerUtils.h" +#include "nm-activation-request.h" +#include "nm-setting-connection.h" +#include "nm-setting-olpc-mesh.h" +#include "nm-manager.h" +#include "nm-enum-types.h" +#include "nm-dbus-manager.h" +#include "nm-wifi-enum-types.h" + +/* This is a bug; but we can't really change API now... */ +#include "NetworkManagerVPN.h" + + +#include "nm-device-olpc-mesh-glue.h" + +G_DEFINE_TYPE (NMDeviceOlpcMesh, nm_device_olpc_mesh, NM_TYPE_DEVICE) + +#define NM_DEVICE_OLPC_MESH_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_OLPC_MESH, NMDeviceOlpcMeshPrivate)) + +enum { + PROP_0, + PROP_COMPANION, + PROP_ACTIVE_CHANNEL, + + LAST_PROP +}; + +struct _NMDeviceOlpcMeshPrivate { + NMDevice *companion; + gboolean stage1_waiting; +}; + +/*******************************************************************/ + +static GQuark +nm_olpc_mesh_error_quark (void) +{ + static GQuark quark = 0; + if (!quark) + quark = g_quark_from_static_string ("nm-mesh-error"); + return quark; +} + +#define NM_OLPC_MESH_ERROR (nm_olpc_mesh_error_quark ()) + +/*******************************************************************/ + +static gboolean +check_connection_compatible (NMDevice *device, NMConnection *connection) +{ + NMSettingConnection *s_con; + NMSettingOlpcMesh *s_mesh; + + if (!NM_DEVICE_CLASS (nm_device_olpc_mesh_parent_class)->check_connection_compatible (device, connection)) + return FALSE; + + s_con = nm_connection_get_setting_connection (connection); + g_assert (s_con); + + if (strcmp (nm_setting_connection_get_connection_type (s_con), NM_SETTING_OLPC_MESH_SETTING_NAME)) + return FALSE; + + s_mesh = nm_connection_get_setting_olpc_mesh (connection); + if (!s_mesh) + return FALSE; + + return TRUE; +} + +static gboolean +can_auto_connect (NMDevice *device, + NMConnection *connection, + char **specific_object) +{ + return FALSE; +} + +#define DEFAULT_SSID "olpc-mesh" + +static gboolean +complete_connection (NMDevice *device, + NMConnection *connection, + const char *specific_object, + const GSList *existing_connections, + GError **error) +{ + NMSettingOlpcMesh *s_mesh; + GByteArray *tmp; + + s_mesh = nm_connection_get_setting_olpc_mesh (connection); + if (!s_mesh) { + s_mesh = (NMSettingOlpcMesh *) nm_setting_olpc_mesh_new (); + nm_connection_add_setting (connection, NM_SETTING (s_mesh)); + } + + if (!nm_setting_olpc_mesh_get_ssid (s_mesh)) { + tmp = g_byte_array_sized_new (strlen (DEFAULT_SSID)); + g_byte_array_append (tmp, (const guint8 *) DEFAULT_SSID, strlen (DEFAULT_SSID)); + g_object_set (G_OBJECT (s_mesh), NM_SETTING_OLPC_MESH_SSID, tmp, NULL); + g_byte_array_free (tmp, TRUE); + } + + if (!nm_setting_olpc_mesh_get_dhcp_anycast_address (s_mesh)) { + const guint8 anycast[ETH_ALEN] = { 0xC0, 0x27, 0xC0, 0x27, 0xC0, 0x27 }; + + tmp = g_byte_array_sized_new (ETH_ALEN); + g_byte_array_append (tmp, anycast, sizeof (anycast)); + g_object_set (G_OBJECT (s_mesh), NM_SETTING_OLPC_MESH_DHCP_ANYCAST_ADDRESS, tmp, NULL); + g_byte_array_free (tmp, TRUE); + + } + + nm_utils_complete_generic (connection, + NM_SETTING_OLPC_MESH_SETTING_NAME, + existing_connections, + _("Mesh %d"), + NULL, + FALSE); /* No IPv6 by default */ + + return TRUE; +} + +/****************************************************************************/ + +static NMActStageReturn +act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason) +{ + NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (dev); + NMActStageReturn ret; + gboolean scanning; + + ret = NM_DEVICE_CLASS (nm_device_olpc_mesh_parent_class)->act_stage1_prepare (dev, reason); + if (ret != NM_ACT_STAGE_RETURN_SUCCESS) + return ret; + + /* disconnect companion device, if it is connected */ + if (nm_device_get_act_request (NM_DEVICE (priv->companion))) { + nm_log_info (LOGD_OLPC, "(%s): disconnecting companion device %s", + nm_device_get_iface (dev), + nm_device_get_iface (priv->companion)); + /* FIXME: VPN stuff here is a bug; but we can't really change API now... */ + nm_device_state_changed (NM_DEVICE (priv->companion), + NM_DEVICE_STATE_DISCONNECTED, + NM_VPN_CONNECTION_STATE_REASON_USER_DISCONNECTED); + nm_log_info (LOGD_OLPC, "(%s): companion %s disconnected", + nm_device_get_iface (dev), + nm_device_get_iface (priv->companion)); + } + + + /* wait with continuing configuration untill the companion device is done scanning */ + g_object_get (priv->companion, "scanning", &scanning, NULL); + if (scanning) { + priv->stage1_waiting = TRUE; + return NM_ACT_STAGE_RETURN_POSTPONE; + } + + return NM_ACT_STAGE_RETURN_SUCCESS; +} + +static void +_mesh_set_channel (NMDeviceOlpcMesh *self, guint32 channel) +{ + int ifindex = nm_device_get_ifindex (NM_DEVICE (self)); + + if (nm_platform_mesh_get_channel (ifindex) != channel) { + if (nm_platform_mesh_set_channel (ifindex, channel)) + g_object_notify (G_OBJECT (self), NM_DEVICE_OLPC_MESH_ACTIVE_CHANNEL); + } +} + +static NMActStageReturn +act_stage2_config (NMDevice *dev, NMDeviceStateReason *reason) +{ + NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (dev); + NMConnection *connection; + NMSettingOlpcMesh *s_mesh; + guint32 channel; + const GByteArray *anycast_addr_array; + guint8 *anycast_addr = NULL; + + connection = nm_device_get_connection (dev); + g_assert (connection); + + s_mesh = nm_connection_get_setting_olpc_mesh (connection); + g_assert (s_mesh); + + channel = nm_setting_olpc_mesh_get_channel (s_mesh); + if (channel != 0) + _mesh_set_channel (self, channel); + nm_platform_mesh_set_ssid (nm_device_get_ifindex (dev), + nm_setting_olpc_mesh_get_ssid (s_mesh)); + + anycast_addr_array = nm_setting_olpc_mesh_get_dhcp_anycast_address (s_mesh); + if (anycast_addr_array) + anycast_addr = anycast_addr_array->data; + + nm_device_set_dhcp_anycast_address (dev, anycast_addr); + return NM_ACT_STAGE_RETURN_SUCCESS; +} + +static gboolean +is_available (NMDevice *dev) +{ + NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (dev); + + if (!NM_DEVICE_OLPC_MESH_GET_PRIVATE (self)->companion) { + nm_log_dbg (LOGD_WIFI, "(%s): not available because companion not found", + nm_device_get_iface (dev)); + return FALSE; + } + + return TRUE; +} + +/*******************************************************************/ + +static void +companion_cleanup (NMDeviceOlpcMesh *self) +{ + NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); + + if (priv->companion) { + g_signal_handlers_disconnect_by_data (priv->companion, self); + g_clear_object (&priv->companion); + } + g_object_notify (G_OBJECT (self), NM_DEVICE_OLPC_MESH_COMPANION); +} + +static void +companion_notify_cb (NMDeviceWifi *companion, GParamSpec *pspec, gpointer user_data) +{ + NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (user_data); + NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); + gboolean scanning; + + if (!priv->stage1_waiting) + return; + + g_object_get (companion, "scanning", &scanning, NULL); + + if (!scanning) { + priv->stage1_waiting = FALSE; + nm_device_activate_schedule_stage2_device_config (NM_DEVICE (self)); + } +} + +/* disconnect from mesh if someone starts using the companion */ +static void +companion_state_changed_cb (NMDeviceWifi *companion, + NMDeviceState state, + NMDeviceState old_state, + NMDeviceStateReason reason, + gpointer user_data) +{ + NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (user_data); + NMDeviceState self_state = nm_device_get_state (NM_DEVICE (self)); + + if ( self_state < NM_DEVICE_STATE_PREPARE + || self_state > NM_DEVICE_STATE_ACTIVATED + || state < NM_DEVICE_STATE_PREPARE + || state > NM_DEVICE_STATE_ACTIVATED) + return; + + nm_log_dbg (LOGD_OLPC, "(%s): disconnecting mesh due to companion connectivity", + nm_device_get_iface (NM_DEVICE (self))); + /* FIXME: VPN stuff here is a bug; but we can't really change API now... */ + nm_device_state_changed (NM_DEVICE (self), + NM_DEVICE_STATE_DISCONNECTED, + NM_VPN_CONNECTION_STATE_REASON_USER_DISCONNECTED); +} + +static gboolean +companion_scan_allowed_cb (NMDeviceWifi *companion, gpointer user_data) +{ + NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (user_data); + NMDeviceState state = nm_device_get_state (NM_DEVICE (self)); + + /* Don't allow the companion to scan while configuring the mesh interface */ + return (state < NM_DEVICE_STATE_PREPARE) || (state > NM_DEVICE_STATE_IP_CONFIG); +} + +static gboolean +companion_autoconnect_allowed_cb (NMDeviceWifi *companion, gpointer user_data) +{ + NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (user_data); + NMDeviceState state = nm_device_get_state (NM_DEVICE (self)); + + /* Don't allow the companion to autoconnect while a mesh connection is + * active */ + return (state < NM_DEVICE_STATE_PREPARE) || (state > NM_DEVICE_STATE_ACTIVATED); +} + +static gboolean +check_companion (NMDeviceOlpcMesh *self, NMDevice *other) +{ + NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); + const guint8 *my_addr, *their_addr; + guint their_addr_len; + + if (!NM_IS_DEVICE_WIFI (other)) + return FALSE; + + my_addr = nm_device_get_hw_address (NM_DEVICE (self), NULL); + their_addr = nm_device_get_hw_address (other, &their_addr_len); + if ( (their_addr_len != ETH_ALEN) + || (memcmp (my_addr, their_addr, ETH_ALEN) != 0)) + return FALSE; + + g_assert (priv->companion == NULL); + priv->companion = g_object_ref (other); + + nm_log_info (LOGD_OLPC, "(%s): found companion WiFi device %s", + nm_device_get_iface (NM_DEVICE (self)), + nm_device_get_iface (other)); + + g_signal_connect (G_OBJECT (other), "state-changed", + G_CALLBACK (companion_state_changed_cb), self); + + g_signal_connect (G_OBJECT (other), "notify::scanning", + G_CALLBACK (companion_notify_cb), self); + + g_signal_connect (G_OBJECT (other), "scanning-allowed", + G_CALLBACK (companion_scan_allowed_cb), self); + + g_signal_connect (G_OBJECT (other), "autoconnect-allowed", + G_CALLBACK (companion_autoconnect_allowed_cb), self); + + g_object_notify (G_OBJECT (self), NM_DEVICE_OLPC_MESH_COMPANION); + + return TRUE; +} + +static void +device_added_cb (NMManager *manager, NMDevice *other, gpointer user_data) +{ + NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (user_data); + NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); + + if (!priv->companion && check_companion (self, other)) { + nm_device_state_changed (NM_DEVICE (self), + NM_DEVICE_STATE_DISCONNECTED, + NM_DEVICE_STATE_REASON_NONE); + nm_device_remove_pending_action (NM_DEVICE (self), "waiting for companion", TRUE); + } +} + +static void +device_removed_cb (NMManager *manager, NMDevice *other, gpointer user_data) +{ + NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (user_data); + + if (other == NM_DEVICE_OLPC_MESH_GET_PRIVATE (self)->companion) + companion_cleanup (self); +} + +static void +find_companion (NMDeviceOlpcMesh *self) +{ + NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); + const GSList *list; + + if (priv->companion) + return; + + nm_device_add_pending_action (NM_DEVICE (self), "waiting for companion", TRUE); + + /* Try to find the companion if it's already known to the NMManager */ + for (list = nm_manager_get_devices (nm_manager_get ()); list ; list = g_slist_next (list)) { + if (check_companion (self, NM_DEVICE (list->data))) { + nm_device_queue_state (NM_DEVICE (self), + NM_DEVICE_STATE_DISCONNECTED, + NM_DEVICE_STATE_REASON_NONE); + nm_device_remove_pending_action (NM_DEVICE (self), "waiting for companion", TRUE); + break; + } + } +} + +static void +state_changed (NMDevice *device, + NMDeviceState new_state, + NMDeviceState old_state, + NMDeviceStateReason reason) +{ + if (new_state == NM_DEVICE_STATE_UNAVAILABLE) + find_companion (NM_DEVICE_OLPC_MESH (device)); +} + +/*******************************************************************/ + +NMDevice * +nm_device_olpc_mesh_new (NMPlatformLink *platform_device) +{ + g_return_val_if_fail (platform_device != NULL, NULL); + + return (NMDevice *) g_object_new (NM_TYPE_DEVICE_OLPC_MESH, + NM_DEVICE_PLATFORM_DEVICE, platform_device, + NM_DEVICE_TYPE_DESC, "802.11 OLPC Mesh", + NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_OLPC_MESH, + NULL); +} + +static void +nm_device_olpc_mesh_init (NMDeviceOlpcMesh * self) +{ +} + +static GObject* +constructor (GType type, + guint n_construct_params, + GObjectConstructParam *construct_params) +{ + GObject *object; + GObjectClass *klass; + NMDeviceOlpcMesh *self; + NMDeviceWifiCapabilities caps; + + klass = G_OBJECT_CLASS (nm_device_olpc_mesh_parent_class); + object = klass->constructor (type, n_construct_params, construct_params); + if (!object) + return NULL; + + self = NM_DEVICE_OLPC_MESH (object); + + nm_log_dbg (LOGD_HW | LOGD_OLPC, "(%s): kernel ifindex %d", + nm_device_get_iface (NM_DEVICE (self)), + nm_device_get_ifindex (NM_DEVICE (self))); + + if (!nm_platform_wifi_get_capabilities (nm_device_get_ifindex (NM_DEVICE (self)), &caps)) { + nm_log_warn (LOGD_HW | LOGD_OLPC, "(%s): failed to initialize WiFi driver", + nm_device_get_iface (NM_DEVICE (self))); + g_object_unref (object); + return NULL; + } + + g_signal_connect (nm_manager_get (), "device-added", G_CALLBACK (device_added_cb), self); + g_signal_connect (nm_manager_get (), "device-removed", G_CALLBACK (device_removed_cb), self); + + /* shorter timeout for mesh connectivity */ + nm_device_set_dhcp_timeout (NM_DEVICE (self), 20); + return object; +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMDeviceOlpcMesh *device = NM_DEVICE_OLPC_MESH (object); + NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (device); + + switch (prop_id) { + case PROP_COMPANION: + if (priv->companion) + g_value_set_boxed (value, nm_device_get_path (priv->companion)); + else + g_value_set_boxed (value, "/"); + break; + case PROP_ACTIVE_CHANNEL: + g_value_set_uint (value, nm_platform_mesh_get_channel (nm_device_get_ifindex (NM_DEVICE (device)))); + 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) +{ + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +dispose (GObject *object) +{ + NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (object); + + companion_cleanup (self); + g_signal_handlers_disconnect_by_func (nm_manager_get (), G_CALLBACK (device_added_cb), self); + g_signal_handlers_disconnect_by_func (nm_manager_get (), G_CALLBACK (device_removed_cb), self); + + G_OBJECT_CLASS (nm_device_olpc_mesh_parent_class)->dispose (object); +} + +static void +nm_device_olpc_mesh_class_init (NMDeviceOlpcMeshClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (NMDeviceOlpcMeshPrivate)); + + object_class->constructor = constructor; + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->dispose = dispose; + + parent_class->check_connection_compatible = check_connection_compatible; + parent_class->can_auto_connect = can_auto_connect; + parent_class->complete_connection = complete_connection; + + parent_class->is_available = is_available; + parent_class->act_stage1_prepare = act_stage1_prepare; + parent_class->act_stage2_config = act_stage2_config; + + parent_class->state_changed = state_changed; + + /* Properties */ + g_object_class_install_property + (object_class, PROP_COMPANION, + g_param_spec_boxed (NM_DEVICE_OLPC_MESH_COMPANION, + "Companion device", + "Companion device object path", + DBUS_TYPE_G_OBJECT_PATH, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_ACTIVE_CHANNEL, + g_param_spec_uint (NM_DEVICE_OLPC_MESH_ACTIVE_CHANNEL, + "Active channel", + "Active channel", + 0, G_MAXUINT32, 0, + G_PARAM_READABLE)); + + nm_dbus_manager_register_exported_type (nm_dbus_manager_get (), + G_TYPE_FROM_CLASS (klass), + &dbus_glib_nm_device_olpc_mesh_object_info); + + dbus_g_error_domain_register (NM_OLPC_MESH_ERROR, NULL, NM_TYPE_OLPC_MESH_ERROR); +} + diff --git a/src/devices/wifi/nm-device-olpc-mesh.h b/src/devices/wifi/nm-device-olpc-mesh.h new file mode 100644 index 00000000..c25dd8e5 --- /dev/null +++ b/src/devices/wifi/nm-device-olpc-mesh.h @@ -0,0 +1,82 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* NetworkManager -- Network link manager + * + * Dan Williams + * Sjoerd Simons + * Daniel Drake + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * (C) Copyright 2005 Red Hat, Inc. + * (C) Copyright 2008 Collabora Ltd. + * (C) Copyright 2009 One Laptop per Child + */ + +#ifndef NM_DEVICE_OLPC_MESH_H +#define NM_DEVICE_OLPC_MESH_H + +#include +#include + +#include "nm-device.h" + +G_BEGIN_DECLS + +#define NM_TYPE_DEVICE_OLPC_MESH (nm_device_olpc_mesh_get_type ()) +#define NM_DEVICE_OLPC_MESH(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_OLPC_MESH, NMDeviceOlpcMesh)) +#define NM_DEVICE_OLPC_MESH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_OLPC_MESH, NMDeviceOlpcMeshClass)) +#define NM_IS_DEVICE_OLPC_MESH(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_OLPC_MESH)) +#define NM_IS_DEVICE_OLPC_MESH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_OLPC_MESH)) +#define NM_DEVICE_OLPC_MESH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_OLPC_MESH, NMDeviceOlpcMeshClass)) + +typedef enum +{ + NM_OLPC_MESH_ERROR_CONNECTION_NOT_MESH = 0, /*< nick=ConnectionNotMesh >*/ + NM_OLPC_MESH_ERROR_CONNECTION_INVALID, /*< nick=ConnectionInvalid >*/ + NM_OLPC_MESH_ERROR_CONNECTION_INCOMPATIBLE, /*< nick=ConnectionIncompatible >*/ +} NMOlpcMeshError; + +#define NM_DEVICE_OLPC_MESH_COMPANION "companion" +#define NM_DEVICE_OLPC_MESH_BITRATE "bitrate" +#define NM_DEVICE_OLPC_MESH_ACTIVE_CHANNEL "active-channel" + +#ifndef NM_DEVICE_OLPC_MESH_DEFINED +#define NM_DEVICE_OLPC_MESH_DEFINED +typedef struct _NMDeviceOlpcMesh NMDeviceOlpcMesh; +#endif + +typedef struct _NMDeviceOlpcMeshClass NMDeviceOlpcMeshClass; +typedef struct _NMDeviceOlpcMeshPrivate NMDeviceOlpcMeshPrivate; + +struct _NMDeviceOlpcMesh +{ + NMDevice parent; +}; + +struct _NMDeviceOlpcMeshClass +{ + NMDeviceClass parent; + +}; + + +GType nm_device_olpc_mesh_get_type (void); + +NMDevice *nm_device_olpc_mesh_new (NMPlatformLink *platform_device); + +G_END_DECLS + +#endif /* NM_DEVICE_OLPC_MESH_H */ diff --git a/src/devices/wifi/nm-device-wifi-glue.h b/src/devices/wifi/nm-device-wifi-glue.h new file mode 100644 index 00000000..3d0f63db --- /dev/null +++ b/src/devices/wifi/nm-device-wifi-glue.h @@ -0,0 +1,167 @@ +/* Generated by dbus-binding-tool; do not edit! */ + + +#ifndef __dbus_glib_marshal_nm_device_wifi_MARSHAL_H__ +#define __dbus_glib_marshal_nm_device_wifi_MARSHAL_H__ + +#include + +G_BEGIN_DECLS + +#ifdef G_ENABLE_DEBUG +#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v) +#define g_marshal_value_peek_char(v) g_value_get_schar (v) +#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v) +#define g_marshal_value_peek_int(v) g_value_get_int (v) +#define g_marshal_value_peek_uint(v) g_value_get_uint (v) +#define g_marshal_value_peek_long(v) g_value_get_long (v) +#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v) +#define g_marshal_value_peek_int64(v) g_value_get_int64 (v) +#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v) +#define g_marshal_value_peek_enum(v) g_value_get_enum (v) +#define g_marshal_value_peek_flags(v) g_value_get_flags (v) +#define g_marshal_value_peek_float(v) g_value_get_float (v) +#define g_marshal_value_peek_double(v) g_value_get_double (v) +#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v) +#define g_marshal_value_peek_param(v) g_value_get_param (v) +#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v) +#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v) +#define g_marshal_value_peek_object(v) g_value_get_object (v) +#define g_marshal_value_peek_variant(v) g_value_get_variant (v) +#else /* !G_ENABLE_DEBUG */ +/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API. + * Do not access GValues directly in your code. Instead, use the + * g_value_get_*() functions + */ +#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int +#define g_marshal_value_peek_char(v) (v)->data[0].v_int +#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint +#define g_marshal_value_peek_int(v) (v)->data[0].v_int +#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint +#define g_marshal_value_peek_long(v) (v)->data[0].v_long +#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 +#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 +#define g_marshal_value_peek_enum(v) (v)->data[0].v_long +#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_float(v) (v)->data[0].v_float +#define g_marshal_value_peek_double(v) (v)->data[0].v_double +#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer +#endif /* !G_ENABLE_DEBUG */ + + +/* BOOLEAN:POINTER,POINTER */ +extern void dbus_glib_marshal_nm_device_wifi_BOOLEAN__POINTER_POINTER (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); +void +dbus_glib_marshal_nm_device_wifi_BOOLEAN__POINTER_POINTER (GClosure *closure, + GValue *return_value G_GNUC_UNUSED, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint G_GNUC_UNUSED, + gpointer marshal_data) +{ + typedef gboolean (*GMarshalFunc_BOOLEAN__POINTER_POINTER) (gpointer data1, + gpointer arg_1, + gpointer arg_2, + gpointer data2); + register GMarshalFunc_BOOLEAN__POINTER_POINTER callback; + register GCClosure *cc = (GCClosure*) closure; + register gpointer data1, data2; + gboolean v_return; + + g_return_if_fail (return_value != NULL); + g_return_if_fail (n_param_values == 3); + + if (G_CCLOSURE_SWAP_DATA (closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer (param_values + 0); + } + else + { + data1 = g_value_peek_pointer (param_values + 0); + data2 = closure->data; + } + callback = (GMarshalFunc_BOOLEAN__POINTER_POINTER) (marshal_data ? marshal_data : cc->callback); + + v_return = callback (data1, + g_marshal_value_peek_pointer (param_values + 1), + g_marshal_value_peek_pointer (param_values + 2), + data2); + + g_value_set_boolean (return_value, v_return); +} + +/* NONE:BOXED,POINTER */ +extern void dbus_glib_marshal_nm_device_wifi_VOID__BOXED_POINTER (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); +void +dbus_glib_marshal_nm_device_wifi_VOID__BOXED_POINTER (GClosure *closure, + GValue *return_value G_GNUC_UNUSED, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint G_GNUC_UNUSED, + gpointer marshal_data) +{ + typedef void (*GMarshalFunc_VOID__BOXED_POINTER) (gpointer data1, + gpointer arg_1, + gpointer arg_2, + gpointer data2); + register GMarshalFunc_VOID__BOXED_POINTER callback; + register GCClosure *cc = (GCClosure*) closure; + register gpointer data1, data2; + + g_return_if_fail (n_param_values == 3); + + if (G_CCLOSURE_SWAP_DATA (closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer (param_values + 0); + } + else + { + data1 = g_value_peek_pointer (param_values + 0); + data2 = closure->data; + } + callback = (GMarshalFunc_VOID__BOXED_POINTER) (marshal_data ? marshal_data : cc->callback); + + callback (data1, + g_marshal_value_peek_boxed (param_values + 1), + g_marshal_value_peek_pointer (param_values + 2), + data2); +} +#define dbus_glib_marshal_nm_device_wifi_NONE__BOXED_POINTER dbus_glib_marshal_nm_device_wifi_VOID__BOXED_POINTER + +G_END_DECLS + +#endif /* __dbus_glib_marshal_nm_device_wifi_MARSHAL_H__ */ + +#include +static const DBusGMethodInfo dbus_glib_nm_device_wifi_methods[] = { + { (GCallback) impl_device_get_access_points, dbus_glib_marshal_nm_device_wifi_BOOLEAN__POINTER_POINTER, 0 }, + { (GCallback) impl_device_get_all_access_points, dbus_glib_marshal_nm_device_wifi_BOOLEAN__POINTER_POINTER, 89 }, + { (GCallback) impl_device_request_scan, dbus_glib_marshal_nm_device_wifi_NONE__BOXED_POINTER, 181 }, +}; + +const DBusGObjectInfo dbus_glib_nm_device_wifi_object_info = { 1, + dbus_glib_nm_device_wifi_methods, + 3, +"org.freedesktop.NetworkManager.Device.Wireless\0GetAccessPoints\0S\0access_points\0O\0F\0N\0ao\0\0org.freedesktop.NetworkManager.Device.Wireless\0GetAllAccessPoints\0S\0access_points\0O\0F\0N\0ao\0\0org.freedesktop.NetworkManager.Device.Wireless\0RequestScan\0A\0options\0I\0a{sv}\0\0\0", +"org.freedesktop.NetworkManager.Device.Wireless\0PropertiesChanged\0org.freedesktop.NetworkManager.Device.Wireless\0AccessPointAdded\0org.freedesktop.NetworkManager.Device.Wireless\0AccessPointRemoved\0\0", +"org.freedesktop.NetworkManager.Device.Wireless\0HwAddress\0hw_address\0read\0org.freedesktop.NetworkManager.Device.Wireless\0PermHwAddress\0perm_hw_address\0read\0org.freedesktop.NetworkManager.Device.Wireless\0Mode\0mode\0read\0org.freedesktop.NetworkManager.Device.Wireless\0Bitrate\0bitrate\0read\0org.freedesktop.NetworkManager.Device.Wireless\0AccessPoints\0access_points\0read\0org.freedesktop.NetworkManager.Device.Wireless\0ActiveAccessPoint\0active_access_point\0read\0org.freedesktop.NetworkManager.Device.Wireless\0WirelessCapabilities\0wireless_capabilities\0read\0\0" +}; + diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c new file mode 100644 index 00000000..95173cf4 --- /dev/null +++ b/src/devices/wifi/nm-device-wifi.c @@ -0,0 +1,3502 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2005 - 2012 Red Hat, Inc. + * Copyright (C) 2006 - 2008 Novell, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "nm-glib-compat.h" +#include "nm-dbus-manager.h" +#include "nm-device.h" +#include "nm-device-wifi.h" +#include "nm-device-private.h" +#include "nm-utils.h" +#include "nm-logging.h" +#include "NetworkManagerUtils.h" +#include "nm-activation-request.h" +#include "nm-supplicant-manager.h" +#include "nm-supplicant-interface.h" +#include "nm-supplicant-config.h" +#include "nm-setting-connection.h" +#include "nm-setting-wireless.h" +#include "nm-setting-wireless-security.h" +#include "nm-setting-8021x.h" +#include "nm-setting-ip4-config.h" +#include "nm-setting-ip6-config.h" +#include "nm-platform.h" +#include "nm-manager-auth.h" +#include "nm-settings-connection.h" +#include "nm-enum-types.h" +#include "nm-dbus-glib-types.h" +#include "nm-wifi-enum-types.h" +#include "nm-connection-provider.h" + + +static gboolean impl_device_get_access_points (NMDeviceWifi *device, + GPtrArray **aps, + GError **err); + +static gboolean impl_device_get_all_access_points (NMDeviceWifi *device, + GPtrArray **aps, + GError **err); + +static void impl_device_request_scan (NMDeviceWifi *device, + GHashTable *options, + DBusGMethodInvocation *context); + +#include "nm-device-wifi-glue.h" + + +/* All of these are in seconds */ +#define SCAN_INTERVAL_MIN 3 +#define SCAN_INTERVAL_STEP 20 +#define SCAN_INTERVAL_MAX 120 + +#define WIRELESS_SECRETS_TRIES "wireless-secrets-tries" + +G_DEFINE_TYPE (NMDeviceWifi, nm_device_wifi, NM_TYPE_DEVICE) + +#define NM_DEVICE_WIFI_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_WIFI, NMDeviceWifiPrivate)) + + +enum { + PROP_0, + PROP_PERM_HW_ADDRESS, + PROP_MODE, + PROP_BITRATE, + PROP_ACCESS_POINTS, + PROP_ACTIVE_ACCESS_POINT, + PROP_CAPABILITIES, + PROP_SCANNING, + + LAST_PROP +}; + +enum { + ACCESS_POINT_ADDED, + ACCESS_POINT_REMOVED, + SCANNING_ALLOWED, + + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +struct _NMDeviceWifiPrivate { + gboolean disposed; + + guint8 perm_hw_addr[ETH_ALEN]; /* Permanent MAC address */ + guint8 initial_hw_addr[ETH_ALEN]; /* Initial MAC address (as seen when NM starts) */ + + gint8 invalid_strength_counter; + + GSList * ap_list; + NMAccessPoint * current_ap; + guint32 rate; + gboolean enabled; /* rfkilled or not */ + + gint32 scheduled_scan_time; + guint8 scan_interval; /* seconds */ + guint pending_scan_id; + guint scanlist_cull_id; + gboolean requested_scan; + + NMSupplicantManager *sup_mgr; + NMSupplicantInterface *sup_iface; + guint sup_timeout_id; /* supplicant association timeout */ + + gboolean ssid_found; + NM80211Mode mode; + + guint32 failed_link_count; + guint periodic_source_id; + guint link_timeout_id; + + NMDeviceWifiCapabilities capabilities; +}; + +static gboolean check_scanning_allowed (NMDeviceWifi *self); + +static void schedule_scan (NMDeviceWifi *self, gboolean backoff); + +static void cancel_pending_scan (NMDeviceWifi *self); + +static void cleanup_association_attempt (NMDeviceWifi * self, + gboolean disconnect); + +static void supplicant_iface_state_cb (NMSupplicantInterface *iface, + guint32 new_state, + guint32 old_state, + int disconnect_reason, + gpointer user_data); + +static void supplicant_iface_new_bss_cb (NMSupplicantInterface * iface, + const char *object_path, + GHashTable *properties, + NMDeviceWifi * self); + +static void supplicant_iface_bss_updated_cb (NMSupplicantInterface *iface, + const char *object_path, + GHashTable *properties, + NMDeviceWifi *self); + +static void supplicant_iface_bss_removed_cb (NMSupplicantInterface *iface, + const char *object_path, + NMDeviceWifi *self); + +static void supplicant_iface_scan_done_cb (NMSupplicantInterface * iface, + gboolean success, + NMDeviceWifi * self); + +static void supplicant_iface_notify_scanning_cb (NMSupplicantInterface * iface, + GParamSpec * pspec, + NMDeviceWifi * self); + +static void schedule_scanlist_cull (NMDeviceWifi *self); + +static gboolean request_wireless_scan (gpointer user_data); + +static void remove_access_point (NMDeviceWifi *device, NMAccessPoint *ap); + +static void remove_supplicant_interface_error_handler (NMDeviceWifi *self); + +/*****************************************************************/ + +#define NM_WIFI_ERROR (nm_wifi_error_quark ()) + +static GQuark +nm_wifi_error_quark (void) +{ + static GQuark quark = 0; + if (!quark) + quark = g_quark_from_static_string ("nm-wifi-error"); + return quark; +} + +/*****************************************************************/ + +static GObject* +constructor (GType type, + guint n_construct_params, + GObjectConstructParam *construct_params) +{ + GObject *object; + GObjectClass *klass; + NMDeviceWifi *self; + NMDeviceWifiPrivate *priv; + + klass = G_OBJECT_CLASS (nm_device_wifi_parent_class); + object = klass->constructor (type, n_construct_params, construct_params); + if (!object) + return NULL; + + self = NM_DEVICE_WIFI (object); + priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + + nm_log_dbg (LOGD_HW | LOGD_WIFI, "(%s): kernel ifindex %d", + nm_device_get_iface (NM_DEVICE (self)), + nm_device_get_ifindex (NM_DEVICE (self))); + + if (!nm_platform_wifi_get_capabilities (nm_device_get_ifindex (NM_DEVICE (self)), + &priv->capabilities)) { + nm_log_warn (LOGD_HW | LOGD_WIFI, "(%s): failed to initialize WiFi driver", + nm_device_get_iface (NM_DEVICE (self))); + g_object_unref (object); + return NULL; + } + + if (priv->capabilities & NM_WIFI_DEVICE_CAP_AP) { + nm_log_info (LOGD_HW | LOGD_WIFI, "(%s): driver supports Access Point (AP) mode", + nm_device_get_iface (NM_DEVICE (self))); + } + + /* Connect to the supplicant manager */ + priv->sup_mgr = nm_supplicant_manager_get (); + g_assert (priv->sup_mgr); + + return object; +} + +static gboolean +supplicant_interface_acquire (NMDeviceWifi *self) +{ + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + + g_return_val_if_fail (self != NULL, FALSE); + /* interface already acquired? */ + g_return_val_if_fail (priv->sup_iface == NULL, TRUE); + + priv->sup_iface = nm_supplicant_manager_iface_get (priv->sup_mgr, + nm_device_get_iface (NM_DEVICE (self)), + TRUE); + if (priv->sup_iface == NULL) { + nm_log_err (LOGD_WIFI, "Couldn't initialize supplicant interface for %s.", + nm_device_get_iface (NM_DEVICE (self))); + return FALSE; + } + + if (nm_supplicant_interface_get_state (priv->sup_iface) < NM_SUPPLICANT_INTERFACE_STATE_READY) + nm_device_add_pending_action (NM_DEVICE (self), "waiting for supplicant", TRUE); + + g_signal_connect (priv->sup_iface, + NM_SUPPLICANT_INTERFACE_STATE, + G_CALLBACK (supplicant_iface_state_cb), + self); + g_signal_connect (priv->sup_iface, + NM_SUPPLICANT_INTERFACE_NEW_BSS, + G_CALLBACK (supplicant_iface_new_bss_cb), + self); + g_signal_connect (priv->sup_iface, + NM_SUPPLICANT_INTERFACE_BSS_UPDATED, + G_CALLBACK (supplicant_iface_bss_updated_cb), + self); + g_signal_connect (priv->sup_iface, + NM_SUPPLICANT_INTERFACE_BSS_REMOVED, + G_CALLBACK (supplicant_iface_bss_removed_cb), + self); + g_signal_connect (priv->sup_iface, + NM_SUPPLICANT_INTERFACE_SCAN_DONE, + G_CALLBACK (supplicant_iface_scan_done_cb), + self); + g_signal_connect (priv->sup_iface, + "notify::scanning", + G_CALLBACK (supplicant_iface_notify_scanning_cb), + self); + + return TRUE; +} + +static void +supplicant_interface_release (NMDeviceWifi *self) +{ + NMDeviceWifiPrivate *priv; + + g_return_if_fail (self != NULL); + + priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + + cancel_pending_scan (self); + + /* Reset the scan interval to be pretty frequent when disconnected */ + priv->scan_interval = SCAN_INTERVAL_MIN + SCAN_INTERVAL_STEP; + nm_log_dbg (LOGD_WIFI_SCAN, "(%s): reset scanning interval to %d seconds", + nm_device_get_iface (NM_DEVICE (self)), + priv->scan_interval); + + if (priv->scanlist_cull_id) { + g_source_remove (priv->scanlist_cull_id); + priv->scanlist_cull_id = 0; + } + + if (priv->sup_iface) { + remove_supplicant_interface_error_handler (self); + + /* Clear supplicant interface signal handlers */ + g_signal_handlers_disconnect_by_data (priv->sup_iface, self); + + /* Tell the supplicant to disconnect from the current AP */ + nm_supplicant_interface_disconnect (priv->sup_iface); + + nm_supplicant_manager_iface_release (priv->sup_mgr, priv->sup_iface); + priv->sup_iface = NULL; + } +} + +static NMAccessPoint * +get_ap_by_path (NMDeviceWifi *self, const char *path) +{ + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + GSList *iter; + + if (!path) + return NULL; + + for (iter = priv->ap_list; iter; iter = g_slist_next (iter)) { + if (g_strcmp0 (path, nm_ap_get_dbus_path (NM_AP (iter->data))) == 0) + return NM_AP (iter->data); + } + return NULL; +} + +static NMAccessPoint * +get_ap_by_supplicant_path (NMDeviceWifi *self, const char *path) +{ + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + GSList *iter; + + if (!path) + return NULL; + + for (iter = priv->ap_list; iter; iter = g_slist_next (iter)) { + if (g_strcmp0 (path, nm_ap_get_supplicant_path (NM_AP (iter->data))) == 0) + return NM_AP (iter->data); + } + return NULL; +} + +static NMAccessPoint * +find_active_ap (NMDeviceWifi *self, + NMAccessPoint *ignore_ap, + gboolean match_hidden) +{ + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + const char *iface = nm_device_get_iface (NM_DEVICE (self)); + int ifindex = nm_device_get_ifindex (NM_DEVICE (self)); + struct ether_addr bssid; + GByteArray *ssid; + GSList *iter; + int i = 0; + NMAccessPoint *match_nofreq = NULL, *active_ap = NULL; + gboolean found_a_band = FALSE; + gboolean found_bg_band = FALSE; + NM80211Mode devmode; + guint32 devfreq; + + nm_platform_wifi_get_bssid (ifindex, &bssid); + nm_log_dbg (LOGD_WIFI, "(%s): active BSSID: %02x:%02x:%02x:%02x:%02x:%02x", + iface, + bssid.ether_addr_octet[0], bssid.ether_addr_octet[1], + bssid.ether_addr_octet[2], bssid.ether_addr_octet[3], + bssid.ether_addr_octet[4], bssid.ether_addr_octet[5]); + + if (!nm_ethernet_address_is_valid (&bssid)) + return NULL; + + ssid = nm_platform_wifi_get_ssid (ifindex); + nm_log_dbg (LOGD_WIFI, "(%s): active SSID: %s%s%s", + iface, + ssid ? "'" : "", + ssid ? nm_utils_escape_ssid (ssid->data, ssid->len) : "(none)", + ssid ? "'" : ""); + + devmode = nm_platform_wifi_get_mode (ifindex); + devfreq = nm_platform_wifi_get_frequency (ifindex); + + /* When matching hidden APs, do a second pass that ignores the SSID check, + * because NM might not yet know the SSID of the hidden AP in the scan list + * and therefore it won't get matched the first time around. + */ + while (i++ < (match_hidden ? 2 : 1)) { + nm_log_dbg (LOGD_WIFI, " Pass #%d %s", i, i > 1 ? "(ignoring SSID)" : ""); + + /* Find this SSID + BSSID in the device's AP list */ + for (iter = priv->ap_list; iter; iter = g_slist_next (iter)) { + NMAccessPoint *ap = NM_AP (iter->data); + const struct ether_addr *ap_bssid = nm_ap_get_address (ap); + const GByteArray *ap_ssid = nm_ap_get_ssid (ap); + NM80211Mode apmode; + guint32 apfreq; + + nm_log_dbg (LOGD_WIFI, " AP: %s%s%s %02x:%02x:%02x:%02x:%02x:%02x", + ap_ssid ? "'" : "", + ap_ssid ? nm_utils_escape_ssid (ap_ssid->data, ap_ssid->len) : "(none)", + ap_ssid ? "'" : "", + ap_bssid->ether_addr_octet[0], ap_bssid->ether_addr_octet[1], + ap_bssid->ether_addr_octet[2], ap_bssid->ether_addr_octet[3], + ap_bssid->ether_addr_octet[4], ap_bssid->ether_addr_octet[5]); + + if (ap == ignore_ap) { + nm_log_dbg (LOGD_WIFI, " ignored"); + continue; + } + + if (memcmp (bssid.ether_addr_octet, ap_bssid->ether_addr_octet, ETH_ALEN)) { + nm_log_dbg (LOGD_WIFI, " BSSID mismatch"); + continue; + } + + if ((i == 0) && !nm_utils_same_ssid (ssid, ap_ssid, TRUE)) { + nm_log_dbg (LOGD_WIFI, " SSID mismatch"); + continue; + } + + apmode = nm_ap_get_mode (ap); + if (devmode != apmode) { + nm_log_dbg (LOGD_WIFI, " mode mismatch (device %d, ap %d)", + devmode, apmode); + continue; + } + + apfreq = nm_ap_get_freq (ap); + if (devfreq != apfreq) { + nm_log_dbg (LOGD_WIFI, " frequency mismatch (device %u, ap %u)", + devfreq, apfreq); + + if (match_nofreq == NULL) + match_nofreq = ap; + + if (apfreq > 4000) + found_a_band = TRUE; + else if (apfreq > 2000) + found_bg_band = TRUE; + continue; + } + + // FIXME: handle security settings here too + nm_log_dbg (LOGD_WIFI, " matched"); + active_ap = ap; + goto done; + } + } + + /* Some proprietary drivers (wl.o) report tuned frequency (like when + * scanning) instead of the associated AP's frequency. This is a great + * example of how WEXT is underspecified. We use frequency to find the + * active AP in the scan list because some configurations use the same + * SSID/BSSID on the 2GHz and 5GHz bands simultaneously, and we need to + * make sure we get the right AP in the right band. This configuration + * is uncommon though, and the frequency check penalizes closed drivers we + * can't fix. Because we're not total dicks, ignore the frequency condition + * if the associated BSSID/SSID exists only in one band since that's most + * likely the AP we want. Sometimes wl.o returns a frequency of 0, so if + * we can't match the AP based on frequency at all, just give up. + */ + if (match_nofreq && ((found_a_band != found_bg_band) || (devfreq == 0))) { + const struct ether_addr *ap_bssid = nm_ap_get_address (match_nofreq); + const GByteArray *ap_ssid = nm_ap_get_ssid (match_nofreq); + + nm_log_dbg (LOGD_WIFI, " matched %s%s%s %02x:%02x:%02x:%02x:%02x:%02x", + ap_ssid ? "'" : "", + ap_ssid ? nm_utils_escape_ssid (ap_ssid->data, ap_ssid->len) : "(none)", + ap_ssid ? "'" : "", + ap_bssid->ether_addr_octet[0], ap_bssid->ether_addr_octet[1], + ap_bssid->ether_addr_octet[2], ap_bssid->ether_addr_octet[3], + ap_bssid->ether_addr_octet[4], ap_bssid->ether_addr_octet[5]); + + active_ap = match_nofreq; + goto done; + } + + nm_log_dbg (LOGD_WIFI, " No matching AP found."); + +done: + if (ssid) + g_byte_array_free (ssid, TRUE); + return active_ap; +} + +static void +update_seen_bssids_cache (NMDeviceWifi *self, NMAccessPoint *ap) +{ + NMConnection *connection; + + g_return_if_fail (NM_IS_DEVICE_WIFI (self)); + + if (ap == NULL) + return; + + /* Don't cache the BSSID for Ad-Hoc APs */ + if (nm_ap_get_mode (ap) != NM_802_11_MODE_INFRA) + return; + + if (nm_device_get_state (NM_DEVICE (self)) == NM_DEVICE_STATE_ACTIVATED) { + connection = nm_device_get_connection (NM_DEVICE (self)); + if (connection) { + nm_settings_connection_add_seen_bssid (NM_SETTINGS_CONNECTION (connection), + nm_ap_get_address (ap)); + } + } +} + +static void +set_current_ap (NMDeviceWifi *self, NMAccessPoint *new_ap, gboolean recheck_available_connections, gboolean force_remove_old_ap) +{ + NMDeviceWifiPrivate *priv; + NMAccessPoint *old_ap; + + g_return_if_fail (NM_IS_DEVICE_WIFI (self)); + + priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + old_ap = priv->current_ap; + + if (old_ap == new_ap) + return; + + if (new_ap) { + priv->current_ap = g_object_ref (new_ap); + + /* Move the current AP to the front of the scan list. Since we + * do a lot of searches looking for the current AP, it saves + * time to have it in front. + */ + priv->ap_list = g_slist_remove (priv->ap_list, new_ap); + priv->ap_list = g_slist_prepend (priv->ap_list, new_ap); + + /* Update seen BSSIDs cache */ + update_seen_bssids_cache (self, priv->current_ap); + } else + priv->current_ap = NULL; + + if (old_ap) { + NM80211Mode mode = nm_ap_get_mode (old_ap); + + if (force_remove_old_ap || mode == NM_802_11_MODE_ADHOC || mode == NM_802_11_MODE_AP || nm_ap_get_fake (old_ap)) { + remove_access_point (self, old_ap); + if (recheck_available_connections) + nm_device_recheck_available_connections (NM_DEVICE (self)); + } + g_object_unref (old_ap); + } + + g_object_notify (G_OBJECT (self), NM_DEVICE_WIFI_ACTIVE_ACCESS_POINT); +} + +static void +periodic_update (NMDeviceWifi *self, NMAccessPoint *ignore_ap) +{ + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + int ifindex = nm_device_get_ifindex (NM_DEVICE (self)); + NMAccessPoint *new_ap; + guint32 new_rate; + int percent; + NMDeviceState state; + guint32 supplicant_state; + + /* BSSID and signal strength have meaningful values only if the device + * is activated and not scanning. + */ + state = nm_device_get_state (NM_DEVICE (self)); + if (state != NM_DEVICE_STATE_ACTIVATED) + return; + + /* Only update current AP if we're actually talking to something, otherwise + * assume the old one (if any) is still valid until we're told otherwise or + * the connection fails. + */ + supplicant_state = nm_supplicant_interface_get_state (priv->sup_iface); + if ( supplicant_state < NM_SUPPLICANT_INTERFACE_STATE_AUTHENTICATING + || supplicant_state > NM_SUPPLICANT_INTERFACE_STATE_COMPLETED + || nm_supplicant_interface_get_scanning (priv->sup_iface)) + return; + + /* In AP mode we currently have nothing to do. */ + if (priv->mode == NM_802_11_MODE_AP) + return; + + /* In IBSS mode, most newer firmware/drivers do "BSS coalescing" where + * multiple IBSS stations using the same SSID will eventually switch to + * using the same BSSID to avoid network segmentation. When this happens, + * the card's reported BSSID will change, but the new BSS may not + * be in the scan list, since scanning isn't done in ad-hoc mode for + * various reasons. So pull the BSSID from the card and update the + * current AP with it, if the current AP is adhoc. + */ + if (priv->current_ap && (nm_ap_get_mode (priv->current_ap) == NM_802_11_MODE_ADHOC)) { + struct ether_addr bssid = { {0x0, 0x0, 0x0, 0x0, 0x0, 0x0} }; + + nm_platform_wifi_get_bssid (ifindex, &bssid); + /* 0x02 means "locally administered" and should be OR-ed into + * the first byte of IBSS BSSIDs. + */ + if ( (bssid.ether_addr_octet[0] & 0x02) + && nm_ethernet_address_is_valid (&bssid)) + nm_ap_set_address (priv->current_ap, &bssid); + } + + new_ap = find_active_ap (self, ignore_ap, FALSE); + if (new_ap) { + /* Try to smooth out the strength. Atmel cards, for example, will give no strength + * one second and normal strength the next. + */ + percent = nm_platform_wifi_get_quality (ifindex); + if (percent >= 0 || ++priv->invalid_strength_counter > 3) { + nm_ap_set_strength (new_ap, (gint8) percent); + priv->invalid_strength_counter = 0; + } + } + + if (new_ap != priv->current_ap) { + const struct ether_addr *new_bssid = NULL; + const GByteArray *new_ssid = NULL; + const struct ether_addr *old_bssid = NULL; + const GByteArray *old_ssid = NULL; + char *old_addr = NULL, *new_addr = NULL; + + if (new_ap) { + new_bssid = nm_ap_get_address (new_ap); + new_addr = nm_utils_hwaddr_ntoa (new_bssid, ARPHRD_ETHER); + new_ssid = nm_ap_get_ssid (new_ap); + } + + if (priv->current_ap) { + old_bssid = nm_ap_get_address (priv->current_ap); + old_addr = nm_utils_hwaddr_ntoa (old_bssid, ARPHRD_ETHER); + old_ssid = nm_ap_get_ssid (priv->current_ap); + } + + nm_log_info (LOGD_WIFI, "(%s): roamed from BSSID %s (%s) to %s (%s)", + nm_device_get_iface (NM_DEVICE (self)), + old_addr ? old_addr : "(none)", + old_ssid ? nm_utils_escape_ssid (old_ssid->data, old_ssid->len) : "(none)", + new_addr ? new_addr : "(none)", + new_ssid ? nm_utils_escape_ssid (new_ssid->data, new_ssid->len) : "(none)"); + g_free (old_addr); + g_free (new_addr); + + set_current_ap (self, new_ap, TRUE, FALSE); + } + + new_rate = nm_platform_wifi_get_rate (ifindex); + if (new_rate != priv->rate) { + priv->rate = new_rate; + g_object_notify (G_OBJECT (self), NM_DEVICE_WIFI_BITRATE); + } +} + +static gboolean +periodic_update_cb (gpointer user_data) +{ + periodic_update (NM_DEVICE_WIFI (user_data), NULL); + return TRUE; +} + +static gboolean +bring_up (NMDevice *device, gboolean *no_firmware) +{ + if (!NM_DEVICE_WIFI_GET_PRIVATE (device)->enabled) + return FALSE; + + return NM_DEVICE_CLASS (nm_device_wifi_parent_class)->bring_up (device, no_firmware); +} + +static void +emit_ap_added_removed (NMDeviceWifi *self, + guint signum, + NMAccessPoint *ap, + gboolean recheck_available_connections) +{ + g_signal_emit (self, signals[signum], 0, ap); + g_object_notify (G_OBJECT (self), NM_DEVICE_WIFI_ACCESS_POINTS); + nm_device_emit_recheck_auto_activate (NM_DEVICE (self)); + if (recheck_available_connections) + nm_device_recheck_available_connections (NM_DEVICE (self)); +} + +static void +remove_access_point (NMDeviceWifi *device, + NMAccessPoint *ap) +{ + NMDeviceWifi *self = NM_DEVICE_WIFI (device); + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + + g_return_if_fail (ap); + g_return_if_fail (ap != priv->current_ap); + g_return_if_fail (g_slist_find (priv->ap_list, ap)); + + priv->ap_list = g_slist_remove (priv->ap_list, ap); + emit_ap_added_removed (self, ACCESS_POINT_REMOVED, ap, FALSE); + g_object_unref (ap); +} + +static void +remove_all_aps (NMDeviceWifi *self) +{ + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + + if (priv->ap_list) { + set_current_ap (self, NULL, FALSE, FALSE); + + while (priv->ap_list) + remove_access_point (self, NM_AP (priv->ap_list->data)); + + nm_device_recheck_available_connections (NM_DEVICE (self)); + } +} + +static void +deactivate (NMDevice *dev) +{ + NMDeviceWifi *self = NM_DEVICE_WIFI (dev); + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + int ifindex = nm_device_get_ifindex (dev); + NMConnection *connection; + NM80211Mode old_mode = priv->mode; + + connection = nm_device_get_connection (dev); + if (connection) { + /* Clear wireless secrets tries when deactivating */ + g_object_set_data (G_OBJECT (connection), WIRELESS_SECRETS_TRIES, NULL); + } + + if (priv->periodic_source_id) { + g_source_remove (priv->periodic_source_id); + priv->periodic_source_id = 0; + } + + cleanup_association_attempt (self, TRUE); + + priv->rate = 0; + + /* If the AP is 'fake', i.e. it wasn't actually found from + * a scan but the user tried to connect to it manually (maybe it + * was non-broadcasting or something) get rid of it, because 'fake' + * APs should only live for as long as we're connected to them. + **/ + set_current_ap (self, NULL, TRUE, FALSE); + + /* Clear any critical protocol notification in the Wi-Fi stack */ + nm_platform_wifi_indicate_addressing_running (ifindex, FALSE); + + /* Reset MAC address back to initial address */ + nm_device_set_hw_addr (dev, priv->initial_hw_addr, "reset", LOGD_WIFI); + + /* Ensure we're in infrastructure mode after deactivation; some devices + * (usually older ones) don't scan well in adhoc mode. + */ + if (nm_platform_wifi_get_mode (ifindex) != NM_802_11_MODE_INFRA) { + nm_device_take_down (NM_DEVICE (self), TRUE); + nm_platform_wifi_set_mode (ifindex, NM_802_11_MODE_INFRA); + nm_device_bring_up (NM_DEVICE (self), TRUE, NULL); + } + + if (priv->mode != NM_802_11_MODE_INFRA) { + priv->mode = NM_802_11_MODE_INFRA; + g_object_notify (G_OBJECT (self), NM_DEVICE_WIFI_MODE); + } + + /* Ensure we trigger a scan after deactivating a Hotspot */ + if (old_mode == NM_802_11_MODE_AP) { + cancel_pending_scan (self); + request_wireless_scan (self); + } +} + +static gboolean +is_adhoc_wpa (NMConnection *connection) +{ + NMSettingWireless *s_wifi; + NMSettingWirelessSecurity *s_wsec; + const char *mode, *key_mgmt; + + /* The kernel doesn't support Ad-Hoc WPA connections well at this time, + * and turns them into open networks. It's been this way since at least + * 2.6.30 or so; until that's fixed, disable WPA-protected Ad-Hoc networks. + */ + + s_wifi = nm_connection_get_setting_wireless (connection); + g_return_val_if_fail (s_wifi != NULL, FALSE); + + mode = nm_setting_wireless_get_mode (s_wifi); + if (g_strcmp0 (mode, NM_SETTING_WIRELESS_MODE_ADHOC) != 0) + return FALSE; + + s_wsec = nm_connection_get_setting_wireless_security (connection); + if (!s_wsec) + return FALSE; + + key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wsec); + if (g_strcmp0 (key_mgmt, "wpa-none") != 0) + return FALSE; + + return TRUE; +} + +static gboolean +check_connection_compatible (NMDevice *device, NMConnection *connection) +{ + NMDeviceWifi *self = NM_DEVICE_WIFI (device); + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + NMSettingConnection *s_con; + NMSettingWireless *s_wireless; + const GByteArray *mac; + const GSList *mac_blacklist, *mac_blacklist_iter; + const char *mode; + + if (!NM_DEVICE_CLASS (nm_device_wifi_parent_class)->check_connection_compatible (device, connection)) + return FALSE; + + s_con = nm_connection_get_setting_connection (connection); + g_assert (s_con); + + if (strcmp (nm_setting_connection_get_connection_type (s_con), NM_SETTING_WIRELESS_SETTING_NAME)) + return FALSE; + + s_wireless = nm_connection_get_setting_wireless (connection); + if (!s_wireless) + return FALSE; + + mac = nm_setting_wireless_get_mac_address (s_wireless); + if (mac && memcmp (mac->data, &priv->perm_hw_addr, ETH_ALEN)) + return FALSE; + + /* Check for MAC address blacklist */ + mac_blacklist = nm_setting_wireless_get_mac_address_blacklist (s_wireless); + for (mac_blacklist_iter = mac_blacklist; mac_blacklist_iter; + mac_blacklist_iter = g_slist_next (mac_blacklist_iter)) { + struct ether_addr addr; + + if (!ether_aton_r (mac_blacklist_iter->data, &addr)) { + g_warn_if_reached (); + continue; + } + + if (memcmp (&addr, &priv->perm_hw_addr, ETH_ALEN) == 0) + return FALSE; + } + + if (is_adhoc_wpa (connection)) + return FALSE; + + /* Early exit if supplicant or device doesn't support requested mode */ + mode = nm_setting_wireless_get_mode (s_wireless); + if (g_strcmp0 (mode, NM_SETTING_WIRELESS_MODE_ADHOC) == 0) { + if (!(priv->capabilities & NM_WIFI_DEVICE_CAP_ADHOC)) + return FALSE; + } else if (g_strcmp0 (mode, NM_SETTING_WIRELESS_MODE_AP) == 0) { + if (!(priv->capabilities & NM_WIFI_DEVICE_CAP_AP)) + return FALSE; + + if (priv->sup_iface) { + if (nm_supplicant_interface_get_ap_support (priv->sup_iface) == AP_SUPPORT_NO) + return FALSE; + } + } + + // FIXME: check channel/freq/band against bands the hardware supports + // FIXME: check encryption against device capabilities + // FIXME: check bitrate against device capabilities + + return TRUE; +} + + +static gboolean +_internal_check_connection_available (NMDevice *device, + NMConnection *connection, + const char *specific_object, + gboolean ignore_ap_list) +{ + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (device); + NMSettingWireless *s_wifi; + const char *mode; + GSList *ap_iter = NULL; + + s_wifi = nm_connection_get_setting_wireless (connection); + g_return_val_if_fail (s_wifi, FALSE); + + if (specific_object) { + NMAccessPoint *ap; + + ap = get_ap_by_path (NM_DEVICE_WIFI (device), specific_object); + return ap ? nm_ap_check_compatible (ap, connection) : FALSE; + } + + /* Ad-Hoc and AP connections are always available because they may be + * started at any time. + */ + mode = nm_setting_wireless_get_mode (s_wifi); + if ( g_strcmp0 (mode, NM_SETTING_WIRELESS_MODE_ADHOC) == 0 + || g_strcmp0 (mode, NM_SETTING_WIRELESS_MODE_AP) == 0) + return TRUE; + + /* Hidden SSIDs obviously don't always appear in the scan list either */ + if (nm_setting_wireless_get_hidden (s_wifi) || ignore_ap_list) + return TRUE; + + /* check if its visible */ + for (ap_iter = priv->ap_list; ap_iter; ap_iter = g_slist_next (ap_iter)) { + if (nm_ap_check_compatible (NM_AP (ap_iter->data), connection)) + return TRUE; + } + + return FALSE; +} + +static gboolean +check_connection_available (NMDevice *device, + NMConnection *connection, + const char *specific_object) +{ + return _internal_check_connection_available (device, connection, specific_object, FALSE); +} + +/* FIXME: remove this function when we require the 'hidden' property to be + * set before a hidden connection can be activated. + */ +static gboolean +check_connection_available_wifi_hidden (NMDevice *device, + NMConnection *connection) +{ + return _internal_check_connection_available (device, connection, NULL, TRUE); +} + +/* + * List of manufacturer default SSIDs that are often unchanged by users. + * + * NOTE: this list should *not* contain networks that you would like to + * automatically roam to like "Starbucks" or "AT&T" or "T-Mobile HotSpot". + */ +static const char * +manf_defaults[] = { + "linksys", + "linksys-a", + "linksys-g", + "default", + "belkin54g", + "NETGEAR", + "o2DSL", + "WLAN", + "ALICE-WLAN", + "Speedport W 501V", +}; + +#define ARRAY_SIZE(a) (sizeof (a) / sizeof (a[0])) + +static gboolean +is_manf_default_ssid (const GByteArray *ssid) +{ + int i; + + for (i = 0; i < ARRAY_SIZE (manf_defaults); i++) { + if (ssid->len == strlen (manf_defaults[i])) { + if (memcmp (manf_defaults[i], ssid->data, ssid->len) == 0) + return TRUE; + } + } + return FALSE; +} + +static gboolean +complete_connection (NMDevice *device, + NMConnection *connection, + const char *specific_object, + const GSList *existing_connections, + GError **error) +{ + NMDeviceWifi *self = NM_DEVICE_WIFI (device); + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + NMSettingWireless *s_wifi; + NMSettingWirelessSecurity *s_wsec; + NMSetting8021x *s_8021x; + const GByteArray *setting_mac; + char *format, *str_ssid = NULL; + NMAccessPoint *ap = NULL; + const GByteArray *ssid = NULL; + GSList *iter; + gboolean hidden = FALSE; + + s_wifi = nm_connection_get_setting_wireless (connection); + s_wsec = nm_connection_get_setting_wireless_security (connection); + s_8021x = nm_connection_get_setting_802_1x (connection); + + if (!specific_object) { + /* If not given a specific object, we need at minimum an SSID */ + if (!s_wifi) { + g_set_error_literal (error, + NM_WIFI_ERROR, + NM_WIFI_ERROR_CONNECTION_INVALID, + "A 'wireless' setting is required if no AP path was given."); + return FALSE; + } + + ssid = nm_setting_wireless_get_ssid (s_wifi); + if (!ssid || !ssid->len) { + g_set_error_literal (error, + NM_WIFI_ERROR, + NM_WIFI_ERROR_CONNECTION_INVALID, + "A 'wireless' setting with a valid SSID is required if no AP path was given."); + return FALSE; + } + + /* Find a compatible AP in the scan list */ + for (iter = priv->ap_list; iter; iter = g_slist_next (iter)) { + if (nm_ap_check_compatible (NM_AP (iter->data), connection)) { + ap = NM_AP (iter->data); + break; + } + } + + /* If we still don't have an AP, then the WiFI settings needs to be + * fully specified by the client. Might not be able to find an AP + * if the network isn't broadcasting the SSID for example. + */ + if (!ap) { + GSList *settings = NULL; + gboolean valid; + + settings = g_slist_prepend (settings, s_wifi); + if (s_wsec) + settings = g_slist_prepend (settings, s_wsec); + if (s_8021x) + settings = g_slist_prepend (settings, s_8021x); + valid = nm_setting_verify (NM_SETTING (s_wifi), settings, error); + g_slist_free (settings); + if (!valid) + return FALSE; + + hidden = TRUE; + } + } else { + ap = get_ap_by_path (self, specific_object); + if (!ap) { + g_set_error (error, + NM_WIFI_ERROR, + NM_WIFI_ERROR_ACCESS_POINT_NOT_FOUND, + "The access point %s was not in the scan list.", + specific_object); + return FALSE; + } + } + + /* Add a wifi setting if one doesn't exist yet */ + if (!s_wifi) { + s_wifi = (NMSettingWireless *) nm_setting_wireless_new (); + nm_connection_add_setting (connection, NM_SETTING (s_wifi)); + } + + if (ap) { + ssid = nm_ap_get_ssid (ap); + + if (ssid == NULL) { + /* The AP must be hidden. Connecting to a WiFi AP requires the SSID + * as part of the initial handshake, so check the connection details + * for the SSID. The AP object will still be used for encryption + * settings and such. + */ + ssid = nm_setting_wireless_get_ssid (s_wifi); + } + + if (ssid == NULL) { + /* If there's no SSID on the AP itself, and no SSID in the + * connection data, then we cannot connect at all. Return an error. + */ + g_set_error_literal (error, + NM_WIFI_ERROR, + NM_WIFI_ERROR_CONNECTION_INVALID, + "A 'wireless' setting with a valid SSID is required for hidden access points."); + return FALSE; + } + + /* If the SSID is a well-known SSID, lock the connection to the AP's + * specific BSSID so NM doesn't autoconnect to some random wifi net. + */ + if (!nm_ap_complete_connection (ap, + connection, + is_manf_default_ssid (ssid), + error)) + return FALSE; + } + + /* The kernel doesn't support Ad-Hoc WPA connections well at this time, + * and turns them into open networks. It's been this way since at least + * 2.6.30 or so; until that's fixed, disable WPA-protected Ad-Hoc networks. + */ + if (is_adhoc_wpa (connection)) { + g_set_error_literal (error, + NM_SETTING_WIRELESS_ERROR, + NM_SETTING_WIRELESS_ERROR_INVALID_PROPERTY, + "WPA Ad-Hoc disabled due to kernel bugs"); + return FALSE; + } + + g_assert (ssid); + str_ssid = nm_utils_ssid_to_utf8 (ssid); + format = g_strdup_printf ("%s %%d", str_ssid); + + nm_utils_complete_generic (connection, + NM_SETTING_WIRELESS_SETTING_NAME, + existing_connections, + format, + str_ssid, + TRUE); + g_free (str_ssid); + g_free (format); + + if (hidden) + g_object_set (s_wifi, NM_SETTING_WIRELESS_HIDDEN, TRUE, NULL); + + setting_mac = nm_setting_wireless_get_mac_address (s_wifi); + if (setting_mac) { + /* Make sure the setting MAC (if any) matches the device's permanent MAC */ + if (memcmp (setting_mac->data, priv->perm_hw_addr, ETH_ALEN)) { + g_set_error (error, + NM_SETTING_WIRELESS_ERROR, + NM_SETTING_WIRELESS_ERROR_INVALID_PROPERTY, + NM_SETTING_WIRELESS_MAC_ADDRESS); + return FALSE; + } + } else { + GByteArray *mac; + const guint8 null_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; + + /* Lock the connection to this device by default if it uses a + * permanent MAC address (ie not a 'locally administered' one) + */ + if ( !(priv->perm_hw_addr[0] & 0x02) + && memcmp (priv->perm_hw_addr, null_mac, ETH_ALEN)) { + mac = g_byte_array_sized_new (ETH_ALEN); + g_byte_array_append (mac, priv->perm_hw_addr, ETH_ALEN); + g_object_set (G_OBJECT (s_wifi), NM_SETTING_WIRELESS_MAC_ADDRESS, mac, NULL); + g_byte_array_free (mac, TRUE); + } + } + + return TRUE; +} + +static gboolean +is_available (NMDevice *dev) +{ + NMDeviceWifi *self = NM_DEVICE_WIFI (dev); + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + NMSupplicantInterface *sup_iface; + guint32 state; + + if (!priv->enabled) { + nm_log_dbg (LOGD_WIFI, "(%s): not available because not enabled", + nm_device_get_iface (dev)); + return FALSE; + } + + sup_iface = priv->sup_iface; + if (!sup_iface) { + nm_log_dbg (LOGD_WIFI, "(%s): not available because supplicant not running", + nm_device_get_iface (dev)); + return FALSE; + } + + state = nm_supplicant_interface_get_state (sup_iface); + if ( state < NM_SUPPLICANT_INTERFACE_STATE_READY + || state > NM_SUPPLICANT_INTERFACE_STATE_COMPLETED) { + nm_log_dbg (LOGD_WIFI, "(%s): not available because supplicant interface not ready", + nm_device_get_iface (dev)); + return FALSE; + } + + return TRUE; +} + +static gboolean +can_auto_connect (NMDevice *dev, + NMConnection *connection, + char **specific_object) +{ + NMDeviceWifi *self = NM_DEVICE_WIFI (dev); + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + GSList *ap_iter; + const char *method = NULL; + guint64 timestamp = 0; + + if (!NM_DEVICE_CLASS (nm_device_wifi_parent_class)->can_auto_connect (dev, connection, specific_object)) + return FALSE; + + /* Don't autoconnect to networks that have been tried at least once + * but haven't been successful, since these are often accidental choices + * from the menu and the user may not know the password. + */ + if (nm_settings_connection_get_timestamp (NM_SETTINGS_CONNECTION (connection), ×tamp)) { + if (timestamp == 0) + return FALSE; + } + + /* Use the connection if it's a shared connection */ + method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP4_CONFIG); + if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_SHARED)) + return TRUE; + + for (ap_iter = priv->ap_list; ap_iter; ap_iter = g_slist_next (ap_iter)) { + NMAccessPoint *ap = NM_AP (ap_iter->data); + + if (nm_ap_check_compatible (ap, connection)) { + /* All good; connection is usable */ + *specific_object = (char *) nm_ap_get_dbus_path (ap); + return TRUE; + } + } + + return FALSE; +} + +static void +ap_list_dump (NMDeviceWifi *self) +{ + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + GSList * elt; + int i = 0; + + g_return_if_fail (NM_IS_DEVICE_WIFI (self)); + + nm_log_dbg (LOGD_WIFI_SCAN, "Current AP list:"); + for (elt = priv->ap_list; elt; elt = g_slist_next (elt), i++) { + NMAccessPoint * ap = NM_AP (elt->data); + nm_ap_dump (ap, "List AP: "); + } + nm_log_dbg (LOGD_WIFI_SCAN, "Current AP list: done"); +} + +static gboolean +impl_device_get_access_points (NMDeviceWifi *self, + GPtrArray **aps, + GError **err) +{ + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + GSList *elt; + + *aps = g_ptr_array_new (); + for (elt = priv->ap_list; elt; elt = g_slist_next (elt)) { + NMAccessPoint *ap = NM_AP (elt->data); + + if (nm_ap_get_ssid (ap)) + g_ptr_array_add (*aps, g_strdup (nm_ap_get_dbus_path (ap))); + } + return TRUE; +} + +static gboolean +impl_device_get_all_access_points (NMDeviceWifi *self, + GPtrArray **aps, + GError **err) +{ + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + GSList *elt; + + *aps = g_ptr_array_new (); + for (elt = priv->ap_list; elt; elt = g_slist_next (elt)) + g_ptr_array_add (*aps, g_strdup (nm_ap_get_dbus_path (NM_AP (elt->data)))); + return TRUE; +} + +static void +request_scan_cb (NMDevice *device, + DBusGMethodInvocation *context, + GError *error, + gpointer user_data) +{ + NMDeviceWifi *self = NM_DEVICE_WIFI (device); + GError *local = NULL; + + if (error) { + dbus_g_method_return_error (context, error); + return; + } + + if (!check_scanning_allowed (self)) { + local = g_error_new_literal (NM_WIFI_ERROR, + NM_WIFI_ERROR_SCAN_NOT_ALLOWED, + "Scanning not allowed at this time"); + dbus_g_method_return_error (context, local); + g_error_free (local); + return; + } + + cancel_pending_scan (self); + request_wireless_scan (self); + dbus_g_method_return (context); +} + +static void +impl_device_request_scan (NMDeviceWifi *self, + GHashTable *options, + DBusGMethodInvocation *context) +{ + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + NMDevice *device = NM_DEVICE (self); + gint32 last_scan; + GError *error; + + if ( !priv->enabled + || !priv->sup_iface + || nm_device_get_state (device) < NM_DEVICE_STATE_DISCONNECTED + || nm_device_is_activating (device)) { + error = g_error_new_literal (NM_WIFI_ERROR, + NM_WIFI_ERROR_SCAN_NOT_ALLOWED, + "Scanning not allowed while unavailable or activating"); + goto error; + } + + if (nm_supplicant_interface_get_scanning (priv->sup_iface)) { + error = g_error_new_literal (NM_WIFI_ERROR, + NM_WIFI_ERROR_SCAN_NOT_ALLOWED, + "Scanning not allowed while already scanning"); + goto error; + } + + last_scan = nm_supplicant_interface_get_last_scan_time (priv->sup_iface); + if (last_scan && (nm_utils_get_monotonic_timestamp_s () - last_scan) < 10) { + error = g_error_new_literal (NM_WIFI_ERROR, + NM_WIFI_ERROR_SCAN_NOT_ALLOWED, + "Scanning not allowed immediately following previous scan"); + goto error; + } + + /* Ask the manager to authenticate this request for us */ + g_signal_emit_by_name (device, + NM_DEVICE_AUTH_REQUEST, + context, + NULL, + NM_AUTH_PERMISSION_NETWORK_CONTROL, + TRUE, + request_scan_cb, + NULL); + return; + +error: + dbus_g_method_return_error (context, error); + g_error_free (error); +} + +static gboolean +scanning_allowed (NMDeviceWifi *self) +{ + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + guint32 sup_state; + NMConnection *connection; + + g_return_val_if_fail (priv->sup_iface != NULL, FALSE); + + /* Scanning not done in AP mode */ + if (priv->mode == NM_802_11_MODE_AP) + return FALSE; + + switch (nm_device_get_state (NM_DEVICE (self))) { + case NM_DEVICE_STATE_UNKNOWN: + case NM_DEVICE_STATE_UNMANAGED: + case NM_DEVICE_STATE_UNAVAILABLE: + case NM_DEVICE_STATE_PREPARE: + case NM_DEVICE_STATE_CONFIG: + case NM_DEVICE_STATE_NEED_AUTH: + case NM_DEVICE_STATE_IP_CONFIG: + case NM_DEVICE_STATE_IP_CHECK: + case NM_DEVICE_STATE_SECONDARIES: + case NM_DEVICE_STATE_DEACTIVATING: + /* Don't scan when unusable or activating */ + return FALSE; + case NM_DEVICE_STATE_DISCONNECTED: + case NM_DEVICE_STATE_FAILED: + /* Can always scan when disconnected */ + return TRUE; + case NM_DEVICE_STATE_ACTIVATED: + /* Need to do further checks when activated */ + break; + } + + /* Don't scan if the supplicant is busy */ + sup_state = nm_supplicant_interface_get_state (priv->sup_iface); + if ( sup_state == NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATING + || sup_state == NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATED + || sup_state == NM_SUPPLICANT_INTERFACE_STATE_4WAY_HANDSHAKE + || sup_state == NM_SUPPLICANT_INTERFACE_STATE_GROUP_HANDSHAKE + || nm_supplicant_interface_get_scanning (priv->sup_iface)) + return FALSE; + + connection = nm_device_get_connection (NM_DEVICE (self)); + if (connection) { + NMSettingWireless *s_wifi; + const char *ip4_method = NULL; + const GByteArray *bssid; + + /* Don't scan when a shared connection is active; it makes drivers mad */ + ip4_method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP4_CONFIG); + + if (!strcmp (ip4_method, NM_SETTING_IP4_CONFIG_METHOD_SHARED)) + return FALSE; + + /* Don't scan when the connection is locked to a specifc AP, since + * intra-ESS roaming (which requires periodic scanning) isn't being + * used due to the specific AP lock. (bgo #513820) + */ + s_wifi = nm_connection_get_setting_wireless (connection); + g_assert (s_wifi); + bssid = nm_setting_wireless_get_bssid (s_wifi); + if (bssid && bssid->len == ETH_ALEN) + return FALSE; + } + + return TRUE; +} + +static gboolean +scanning_allowed_accumulator (GSignalInvocationHint *ihint, + GValue *return_accu, + const GValue *handler_return, + gpointer data) +{ + if (!g_value_get_boolean (handler_return)) + g_value_set_boolean (return_accu, FALSE); + return TRUE; +} + +static gboolean +check_scanning_allowed (NMDeviceWifi *self) +{ + GValue instance = G_VALUE_INIT; + GValue retval = G_VALUE_INIT; + + g_value_init (&instance, G_TYPE_OBJECT); + g_value_take_object (&instance, self); + + g_value_init (&retval, G_TYPE_BOOLEAN); + g_value_set_boolean (&retval, TRUE); + + /* Use g_signal_emitv() rather than g_signal_emit() to avoid the return + * value being changed if no handlers are connected */ + g_signal_emitv (&instance, signals[SCANNING_ALLOWED], 0, &retval); + + return g_value_get_boolean (&retval); +} + +static gboolean +hidden_filter_func (NMConnectionProvider *provider, + NMConnection *connection, + gpointer user_data) +{ + NMSettingWireless *s_wifi; + + s_wifi = (NMSettingWireless *) nm_connection_get_setting_wireless (connection); + return s_wifi ? nm_setting_wireless_get_hidden (s_wifi) : FALSE; +} + +static GPtrArray * +build_hidden_probe_list (NMDeviceWifi *self) +{ + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + guint max_scan_ssids = nm_supplicant_interface_get_max_scan_ssids (priv->sup_iface); + GSList *connections, *iter; + GPtrArray *ssids = NULL; + static GByteArray *nullssid = NULL; + + /* Need at least two: wildcard SSID and one or more hidden SSIDs */ + if (max_scan_ssids < 2) + return NULL; + + /* Static wildcard SSID used for every scan */ + if (G_UNLIKELY (nullssid == NULL)) + nullssid = g_byte_array_new (); + + connections = nm_connection_provider_get_best_connections (nm_connection_provider_get (), + max_scan_ssids - 1, + NM_SETTING_WIRELESS_SETTING_NAME, + NULL, + hidden_filter_func, + NULL); + if (connections && connections->data) { + ssids = g_ptr_array_sized_new (max_scan_ssids - 1); + g_ptr_array_add (ssids, nullssid); /* Add wildcard SSID */ + } + + for (iter = connections; iter; iter = g_slist_next (iter)) { + NMConnection *connection = iter->data; + NMSettingWireless *s_wifi; + const GByteArray *ssid; + + s_wifi = (NMSettingWireless *) nm_connection_get_setting_wireless (connection); + g_assert (s_wifi); + ssid = nm_setting_wireless_get_ssid (s_wifi); + g_assert (ssid); + g_ptr_array_add (ssids, (gpointer) ssid); + } + g_slist_free (connections); + + return ssids; +} + +static gboolean +request_wireless_scan (gpointer user_data) +{ + NMDeviceWifi *self = NM_DEVICE_WIFI (user_data); + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + gboolean backoff = FALSE; + GPtrArray *ssids = NULL; + + if (priv->requested_scan) { + /* There's already a scan in progress */ + return FALSE; + } + + if (check_scanning_allowed (self)) { + nm_log_dbg (LOGD_WIFI_SCAN, "(%s): scanning requested", + nm_device_get_iface (NM_DEVICE (self))); + + ssids = build_hidden_probe_list (self); + + if (nm_logging_enabled (LOGL_DEBUG, LOGD_WIFI_SCAN)) { + if (ssids) { + guint i; + char *foo; + + for (i = 0; i < ssids->len; i++) { + foo = nm_utils_ssid_to_utf8 (g_ptr_array_index (ssids, i)); + nm_log_dbg (LOGD_WIFI_SCAN, "(%s): (%d) probe scanning SSID '%s'", + nm_device_get_iface (NM_DEVICE (self)), + i, foo ? foo : ""); + g_free (foo); + } + } else { + nm_log_dbg (LOGD_WIFI_SCAN, "(%s): no SSIDs to probe scan", + nm_device_get_iface (NM_DEVICE (self))); + } + } + + if (nm_supplicant_interface_request_scan (priv->sup_iface, ssids)) { + /* success */ + backoff = TRUE; + priv->requested_scan = TRUE; + nm_device_add_pending_action (NM_DEVICE (self), "scan", TRUE); + } + + if (ssids) { + /* Elements owned by the connections, so we don't free them here */ + g_ptr_array_free (ssids, TRUE); + } + } else { + nm_log_dbg (LOGD_WIFI_SCAN, "(%s): scan requested but not allowed at this time", + nm_device_get_iface (NM_DEVICE (self))); + } + + priv->pending_scan_id = 0; + schedule_scan (self, backoff); + return FALSE; +} + + +/* + * schedule_scan + * + * Schedule a wireless scan. + * + */ +static void +schedule_scan (NMDeviceWifi *self, gboolean backoff) +{ + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + gint32 now = nm_utils_get_monotonic_timestamp_s (); + + /* Cancel the pending scan if it would happen later than (now + the scan_interval) */ + if (priv->pending_scan_id) { + if (now + priv->scan_interval < priv->scheduled_scan_time) + cancel_pending_scan (self); + } + + if (!priv->pending_scan_id) { + guint factor = 2, next_scan = priv->scan_interval; + + if ( nm_device_is_activating (NM_DEVICE (self)) + || (nm_device_get_state (NM_DEVICE (self)) == NM_DEVICE_STATE_ACTIVATED)) + factor = 1; + + priv->pending_scan_id = g_timeout_add_seconds (next_scan, + request_wireless_scan, + self); + + priv->scheduled_scan_time = now + priv->scan_interval; + if (backoff && (priv->scan_interval < (SCAN_INTERVAL_MAX / factor))) { + priv->scan_interval += (SCAN_INTERVAL_STEP / factor); + /* Ensure the scan interval will never be less than 20s... */ + priv->scan_interval = MAX(priv->scan_interval, SCAN_INTERVAL_MIN + SCAN_INTERVAL_STEP); + /* ... or more than 120s */ + priv->scan_interval = MIN(priv->scan_interval, SCAN_INTERVAL_MAX); + } else if (!backoff && (priv->scan_interval == 0)) { + /* Invalid combination; would cause continual rescheduling of + * the scan and hog CPU. Reset to something minimally sane. + */ + priv->scan_interval = 5; + } + + nm_log_dbg (LOGD_WIFI_SCAN, "(%s): scheduled scan in %d seconds (interval now %d seconds)", + nm_device_get_iface (NM_DEVICE (self)), + next_scan, + priv->scan_interval); + + } +} + + +static void +cancel_pending_scan (NMDeviceWifi *self) +{ + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + + if (priv->pending_scan_id) { + g_source_remove (priv->pending_scan_id); + priv->pending_scan_id = 0; + } +} + +static void +supplicant_iface_scan_done_cb (NMSupplicantInterface *iface, + gboolean success, + NMDeviceWifi *self) +{ + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + + nm_log_dbg (LOGD_WIFI_SCAN, "(%s): scan %s", + nm_device_get_iface (NM_DEVICE (self)), + success ? "successful" : "failed"); + + schedule_scan (self, success); + + /* Ensure that old APs get removed, which otherwise only + * happens when there are new BSSes. + */ + schedule_scanlist_cull (self); + + if (priv->requested_scan) { + priv->requested_scan = FALSE; + nm_device_remove_pending_action (NM_DEVICE (self), "scan", TRUE); + } +} + +/**************************************************************************** + * WPA Supplicant control stuff + * + */ + +static void +try_fill_ssid_for_hidden_ap (NMAccessPoint *ap) +{ + const struct ether_addr *bssid; + const GSList *connections, *iter; + + g_return_if_fail (nm_ap_get_ssid (ap) == NULL); + + bssid = nm_ap_get_address (ap); + g_assert (bssid); + + /* Look for this AP's BSSID in the seen-bssids list of a connection, + * and if a match is found, copy over the SSID */ + connections = nm_connection_provider_get_connections (nm_connection_provider_get ()); + for (iter = connections; iter; iter = g_slist_next (iter)) { + NMConnection *connection = NM_CONNECTION (iter->data); + NMSettingWireless *s_wifi; + + s_wifi = nm_connection_get_setting_wireless (connection); + if (s_wifi) { + if (nm_settings_connection_has_seen_bssid (NM_SETTINGS_CONNECTION (connection), bssid)) { + nm_ap_set_ssid (ap, nm_setting_wireless_get_ssid (s_wifi)); + break; + } + } + } +} + +#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x" +#define MAC_ARG(x) ((guint8*)(x))[0],((guint8*)(x))[1],((guint8*)(x))[2],((guint8*)(x))[3],((guint8*)(x))[4],((guint8*)(x))[5] + +/* + * merge_scanned_ap + * + * If there is already an entry that matches the BSSID and ESSID of the + * AP to merge, replace that entry with the scanned AP. Otherwise, add + * the scanned AP to the list. + * + * TODO: possibly need to differentiate entries based on security too; i.e. if + * there are two scan results with the same BSSID and SSID but different + * security options? + * + */ +static void +merge_scanned_ap (NMDeviceWifi *self, + NMAccessPoint *merge_ap) +{ + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + NMAccessPoint *found_ap = NULL; + const GByteArray *ssid; + const struct ether_addr *bssid; + gboolean strict_match = TRUE; + + /* Let the manager try to fill in the SSID from seen-bssids lists */ + bssid = nm_ap_get_address (merge_ap); + ssid = nm_ap_get_ssid (merge_ap); + if (!ssid || nm_utils_is_empty_ssid (ssid->data, ssid->len)) { + /* Try to fill the SSID from the AP database */ + try_fill_ssid_for_hidden_ap (merge_ap); + + ssid = nm_ap_get_ssid (merge_ap); + if (ssid && (nm_utils_is_empty_ssid (ssid->data, ssid->len) == FALSE)) { + /* Yay, matched it, no longer treat as hidden */ + nm_log_dbg (LOGD_WIFI_SCAN, "(%s): matched hidden AP " MAC_FMT " => '%s'", + nm_device_get_iface (NM_DEVICE (self)), + MAC_ARG (bssid->ether_addr_octet), + nm_utils_escape_ssid (ssid->data, ssid->len)); + nm_ap_set_broadcast (merge_ap, FALSE); + } else { + /* Didn't have an entry for this AP in the database */ + nm_log_dbg (LOGD_WIFI_SCAN, "(%s): failed to match hidden AP " MAC_FMT, + nm_device_get_iface (NM_DEVICE (self)), + MAC_ARG (bssid->ether_addr_octet)); + } + } + + /* If the incoming scan result matches the hidden AP that NM is currently + * connected to but hasn't been seen in the scan list yet, don't use + * strict matching. Because the capabilities of the fake AP have to be + * constructed from the NMConnection of the activation request, they won't + * always be the same as the capabilities of the real AP from the scan. + */ + if (priv->current_ap && nm_ap_get_fake (priv->current_ap)) + strict_match = FALSE; + + found_ap = get_ap_by_supplicant_path (self, nm_ap_get_supplicant_path (merge_ap)); + if (!found_ap) + found_ap = nm_ap_match_in_list (merge_ap, priv->ap_list, strict_match); + if (found_ap) { + nm_log_dbg (LOGD_WIFI_SCAN, "(%s): merging AP '%s' " MAC_FMT " (%p) with existing (%p)", + nm_device_get_iface (NM_DEVICE (self)), + ssid ? nm_utils_escape_ssid (ssid->data, ssid->len) : "(none)", + MAC_ARG (bssid->ether_addr_octet), + merge_ap, + found_ap); + + nm_ap_set_supplicant_path (found_ap, nm_ap_get_supplicant_path (merge_ap)); + nm_ap_set_flags (found_ap, nm_ap_get_flags (merge_ap)); + nm_ap_set_wpa_flags (found_ap, nm_ap_get_wpa_flags (merge_ap)); + nm_ap_set_rsn_flags (found_ap, nm_ap_get_rsn_flags (merge_ap)); + nm_ap_set_strength (found_ap, nm_ap_get_strength (merge_ap)); + nm_ap_set_last_seen (found_ap, nm_ap_get_last_seen (merge_ap)); + nm_ap_set_broadcast (found_ap, nm_ap_get_broadcast (merge_ap)); + nm_ap_set_freq (found_ap, nm_ap_get_freq (merge_ap)); + nm_ap_set_max_bitrate (found_ap, nm_ap_get_max_bitrate (merge_ap)); + + /* If the AP is noticed in a scan, it's automatically no longer + * fake, since it clearly exists somewhere. + */ + nm_ap_set_fake (found_ap, FALSE); + } else { + /* New entry in the list */ + nm_log_dbg (LOGD_WIFI_SCAN, "(%s): adding new AP '%s' " MAC_FMT " (%p)", + nm_device_get_iface (NM_DEVICE (self)), + ssid ? nm_utils_escape_ssid (ssid->data, ssid->len) : "(none)", + MAC_ARG (bssid->ether_addr_octet), + merge_ap); + + g_object_ref (merge_ap); + priv->ap_list = g_slist_prepend (priv->ap_list, merge_ap); + nm_ap_export_to_dbus (merge_ap); + emit_ap_added_removed (self, ACCESS_POINT_ADDED, merge_ap, TRUE); + } +} + +#define WPAS_REMOVED_TAG "supplicant-removed" + +static gboolean +cull_scan_list (NMDeviceWifi *self) +{ + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + gint32 now = nm_utils_get_monotonic_timestamp_s (); + GSList *outdated_list = NULL; + GSList *elt; + guint32 removed = 0, total = 0; + + priv->scanlist_cull_id = 0; + + nm_log_dbg (LOGD_WIFI_SCAN, "(%s): checking scan list for outdated APs", + nm_device_get_iface (NM_DEVICE (self))); + + /* Walk the access point list and remove any access points older than + * three times the inactive scan interval. + */ + for (elt = priv->ap_list; elt; elt = g_slist_next (elt), total++) { + NMAccessPoint *ap = elt->data; + const guint prune_interval_s = SCAN_INTERVAL_MAX * 3; + gint32 last_seen; + + /* Don't cull the associated AP or manually created APs */ + if (ap == priv->current_ap) + continue; + g_assert (!nm_ap_get_fake (ap)); /* only the current_ap can be fake */ + + /* Don't cull APs still known to the supplicant. Since the supplicant + * doesn't yet emit property updates for "last seen" we have to rely + * on changing signal strength for updating "last seen". But if the + * AP's strength doesn't change we won't get any updates for the AP, + * and we'll end up here even if the AP was still found by the + * supplicant in the last scan. + */ + if ( nm_ap_get_supplicant_path (ap) + && g_object_get_data (G_OBJECT (ap), WPAS_REMOVED_TAG) == NULL) + continue; + + last_seen = nm_ap_get_last_seen (ap); + if (!last_seen || last_seen + prune_interval_s < now) + outdated_list = g_slist_prepend (outdated_list, ap); + } + + /* Remove outdated APs */ + for (elt = outdated_list; elt; elt = g_slist_next (elt)) { + NMAccessPoint *outdated_ap = NM_AP (elt->data); + const struct ether_addr *bssid; + const GByteArray *ssid; + + bssid = nm_ap_get_address (outdated_ap); + ssid = nm_ap_get_ssid (outdated_ap); + nm_log_dbg (LOGD_WIFI_SCAN, + " removing %02x:%02x:%02x:%02x:%02x:%02x (%s%s%s)", + bssid->ether_addr_octet[0], bssid->ether_addr_octet[1], + bssid->ether_addr_octet[2], bssid->ether_addr_octet[3], + bssid->ether_addr_octet[4], bssid->ether_addr_octet[5], + ssid ? "'" : "", + ssid ? nm_utils_escape_ssid (ssid->data, ssid->len) : "(none)", + ssid ? "'" : ""); + + remove_access_point (self, outdated_ap); + removed++; + } + g_slist_free (outdated_list); + + nm_log_dbg (LOGD_WIFI_SCAN, "(%s): removed %d APs (of %d)", + nm_device_get_iface (NM_DEVICE (self)), + removed, total); + + ap_list_dump (self); + + if(removed > 0) + nm_device_recheck_available_connections (NM_DEVICE (self)); + + return FALSE; +} + +static void +schedule_scanlist_cull (NMDeviceWifi *self) +{ + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + + /* Cull the scan list after the last request for it has come in */ + if (priv->scanlist_cull_id) + g_source_remove (priv->scanlist_cull_id); + priv->scanlist_cull_id = g_timeout_add_seconds (4, (GSourceFunc) cull_scan_list, self); +} + +static void +supplicant_iface_new_bss_cb (NMSupplicantInterface *iface, + const char *object_path, + GHashTable *properties, + NMDeviceWifi *self) +{ + NMDeviceState state; + NMAccessPoint *ap; + + g_return_if_fail (self != NULL); + g_return_if_fail (properties != NULL); + g_return_if_fail (iface != NULL); + + /* Ignore new APs when unavailable, unmanaged, or in AP mode */ + state = nm_device_get_state (NM_DEVICE (self)); + if (state <= NM_DEVICE_STATE_UNAVAILABLE) + return; + if (NM_DEVICE_WIFI_GET_PRIVATE (self)->mode == NM_802_11_MODE_AP) + return; + + ap = nm_ap_new_from_properties (object_path, properties); + if (ap) { + nm_ap_dump (ap, "New AP: "); + + /* Add the AP to the device's AP list */ + merge_scanned_ap (self, ap); + g_object_unref (ap); + } else { + nm_log_warn (LOGD_WIFI_SCAN, "(%s): invalid AP properties received", + nm_device_get_iface (NM_DEVICE (self))); + } + + /* Remove outdated access points */ + schedule_scanlist_cull (self); +} + +static void +supplicant_iface_bss_updated_cb (NMSupplicantInterface *iface, + const char *object_path, + GHashTable *properties, + NMDeviceWifi *self) +{ + NMDeviceState state; + NMAccessPoint *ap; + + g_return_if_fail (self != NULL); + g_return_if_fail (object_path != NULL); + g_return_if_fail (properties != NULL); + + /* Ignore new APs when unavailable or unamnaged */ + state = nm_device_get_state (NM_DEVICE (self)); + if (state <= NM_DEVICE_STATE_UNAVAILABLE) + return; + + /* Update the AP's last-seen property */ + ap = get_ap_by_supplicant_path (self, object_path); + if (ap) + nm_ap_set_last_seen (ap, nm_utils_get_monotonic_timestamp_s ()); + + /* Remove outdated access points */ + schedule_scanlist_cull (self); +} + +static void +supplicant_iface_bss_removed_cb (NMSupplicantInterface *iface, + const char *object_path, + NMDeviceWifi *self) +{ + NMAccessPoint *ap; + + g_return_if_fail (self != NULL); + g_return_if_fail (object_path != NULL); + + ap = get_ap_by_supplicant_path (self, object_path); + if (ap) + g_object_set_data (G_OBJECT (ap), WPAS_REMOVED_TAG, GUINT_TO_POINTER (TRUE)); +} + +static void +remove_supplicant_timeouts (NMDeviceWifi *self) +{ + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + + if (priv->sup_timeout_id) { + g_source_remove (priv->sup_timeout_id); + priv->sup_timeout_id = 0; + } + + if (priv->link_timeout_id) { + g_source_remove (priv->link_timeout_id); + priv->link_timeout_id = 0; + } +} + +static void +cleanup_association_attempt (NMDeviceWifi *self, gboolean disconnect) +{ + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + + remove_supplicant_interface_error_handler (self); + remove_supplicant_timeouts (self); + if (disconnect && priv->sup_iface) + nm_supplicant_interface_disconnect (priv->sup_iface); +} + +static void +wifi_secrets_cb (NMActRequest *req, + guint32 call_id, + NMConnection *connection, + GError *error, + gpointer user_data) +{ + NMDevice *dev = NM_DEVICE (user_data); + + g_return_if_fail (req == nm_device_get_act_request (dev)); + g_return_if_fail (nm_device_get_state (dev) == NM_DEVICE_STATE_NEED_AUTH); + g_return_if_fail (nm_act_request_get_connection (req) == connection); + + if (error) { + nm_log_warn (LOGD_WIFI, "%s", error->message); + nm_device_state_changed (dev, + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_NO_SECRETS); + } else + nm_device_activate_schedule_stage1_device_prepare (dev); +} + +/* + * link_timeout_cb + * + * Called when the link to the access point has been down for a specified + * period of time. + */ +static gboolean +link_timeout_cb (gpointer user_data) +{ + NMDevice *dev = NM_DEVICE (user_data); + NMDeviceWifi *self = NM_DEVICE_WIFI (dev); + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + + nm_log_warn (LOGD_WIFI, "(%s): link timed out.", nm_device_get_iface (dev)); + + priv->link_timeout_id = 0; + + /* Disconnect event while activated; the supplicant hasn't been able + * to reassociate within the timeout period, so the connection must + * fail. + */ + if (nm_device_get_state (dev) != NM_DEVICE_STATE_ACTIVATED) + return FALSE; + + /* If the access point failed, and wasn't found by the supplicant when it + * attempted to reconnect, then it's probably out of range or turned off. + * Remove it from the list and if it's actually still present, it'll be + * found in the next scan. + */ + if (priv->ssid_found == FALSE && priv->current_ap) + set_current_ap (self, NULL, TRUE, TRUE); + + nm_device_state_changed (dev, + NM_DEVICE_STATE_FAILED, + priv->ssid_found ? NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT : + NM_DEVICE_STATE_REASON_SSID_NOT_FOUND); + return FALSE; +} + +static gboolean +need_new_8021x_secrets (NMDeviceWifi *self, + guint32 old_state, + const char **setting_name) +{ + NMSetting8021x *s_8021x; + NMSettingWirelessSecurity *s_wsec; + NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE; + NMConnection *connection; + + g_assert (setting_name != NULL); + + connection = nm_device_get_connection (NM_DEVICE (self)); + g_return_val_if_fail (connection != NULL, FALSE); + + /* 802.1x stuff only happens in the supplicant's ASSOCIATED state when it's + * attempting to authenticate with the AP. + */ + if (old_state != NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATED) + return FALSE; + + /* If it's an 802.1x or LEAP connection with "always ask"/unsaved secrets + * then we need to ask again because it might be an OTP token and the PIN + * may have changed. + */ + + s_8021x = nm_connection_get_setting_802_1x (connection); + if (s_8021x) { + nm_setting_get_secret_flags (NM_SETTING (s_8021x), + NM_SETTING_802_1X_PASSWORD, + &secret_flags, + NULL); + if (secret_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED) + *setting_name = NM_SETTING_802_1X_SETTING_NAME; + return *setting_name ? TRUE : FALSE; + } + + s_wsec = nm_connection_get_setting_wireless_security (connection); + if (s_wsec) { + nm_setting_get_secret_flags (NM_SETTING (s_wsec), + NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD, + &secret_flags, + NULL); + if (secret_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED) + *setting_name = NM_SETTING_WIRELESS_SECURITY_SETTING_NAME; + return *setting_name ? TRUE : FALSE; + } + + /* Not a LEAP or 802.1x connection */ + return FALSE; +} + +static gboolean +need_new_wpa_psk (NMDeviceWifi *self, + guint32 old_state, + const char **setting_name) +{ + NMSettingWirelessSecurity *s_wsec; + NMConnection *connection; + const char *key_mgmt = NULL; + + g_assert (setting_name != NULL); + + connection = nm_device_get_connection (NM_DEVICE (self)); + g_return_val_if_fail (connection != NULL, FALSE); + + /* A bad PSK will cause the supplicant to disconnect during the 4-way handshake */ + if (old_state != NM_SUPPLICANT_INTERFACE_STATE_4WAY_HANDSHAKE) + return FALSE; + + s_wsec = nm_connection_get_setting_wireless_security (connection); + if (s_wsec) + key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wsec); + + if (g_strcmp0 (key_mgmt, "wpa-psk") == 0) { + *setting_name = NM_SETTING_WIRELESS_SECURITY_SETTING_NAME; + return TRUE; + } + + /* Not a WPA-PSK connection */ + return FALSE; +} + +static gboolean +handle_8021x_or_psk_auth_fail (NMDeviceWifi *self, + guint32 new_state, + guint32 old_state, + int disconnect_reason) +{ + NMDevice *device = NM_DEVICE (self); + NMActRequest *req; + NMConnection *connection; + const char *setting_name = NULL; + gboolean handled = FALSE; + + g_return_val_if_fail (new_state == NM_SUPPLICANT_INTERFACE_STATE_DISCONNECTED, FALSE); + + req = nm_device_get_act_request (NM_DEVICE (self)); + g_return_val_if_fail (req != NULL, FALSE); + + connection = nm_act_request_get_connection (req); + g_assert (connection); + + if ( need_new_8021x_secrets (self, old_state, &setting_name) + || need_new_wpa_psk (self, old_state, &setting_name)) { + + nm_connection_clear_secrets (connection); + + nm_log_info (LOGD_DEVICE | LOGD_WIFI, + "Activation (%s/wireless): disconnected during association," + " asking for new key.", nm_device_get_iface (device)); + + cleanup_association_attempt (self, TRUE); + nm_device_state_changed (device, NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT); + nm_act_request_get_secrets (req, + setting_name, + NM_SETTINGS_GET_SECRETS_FLAG_ALLOW_INTERACTION + | NM_SETTINGS_GET_SECRETS_FLAG_REQUEST_NEW, + NULL, + wifi_secrets_cb, + self); + handled = TRUE; + } + + return handled; +} + +static void +supplicant_iface_state_cb (NMSupplicantInterface *iface, + guint32 new_state, + guint32 old_state, + int disconnect_reason, + gpointer user_data) +{ + NMDeviceWifi *self = NM_DEVICE_WIFI (user_data); + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + NMDevice *device = NM_DEVICE (self); + NMDeviceState devstate; + gboolean scanning; + + if (new_state == old_state) + return; + + nm_log_info (LOGD_DEVICE | LOGD_WIFI, + "(%s): supplicant interface state: %s -> %s", + nm_device_get_iface (device), + nm_supplicant_interface_state_to_string (old_state), + nm_supplicant_interface_state_to_string (new_state)); + + devstate = nm_device_get_state (device); + scanning = nm_supplicant_interface_get_scanning (iface); + + /* In these states we know the supplicant is actually talking to something */ + if ( new_state >= NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATING + && new_state <= NM_SUPPLICANT_INTERFACE_STATE_COMPLETED) + priv->ssid_found = TRUE; + + switch (new_state) { + case NM_SUPPLICANT_INTERFACE_STATE_READY: + priv->scan_interval = SCAN_INTERVAL_MIN; + + /* If the interface can now be activated because the supplicant is now + * available, transition to DISCONNECTED. + */ + if ((devstate == NM_DEVICE_STATE_UNAVAILABLE) && nm_device_is_available (device)) { + nm_device_state_changed (device, + NM_DEVICE_STATE_DISCONNECTED, + NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE); + } + + nm_log_dbg (LOGD_WIFI_SCAN, + "(%s): supplicant ready, requesting initial scan", + nm_device_get_iface (device)); + + /* Request a scan to get latest results */ + cancel_pending_scan (self); + request_wireless_scan (self); + + if (old_state < NM_SUPPLICANT_INTERFACE_STATE_READY) + nm_device_remove_pending_action (device, "waiting for supplicant", TRUE); + break; + case NM_SUPPLICANT_INTERFACE_STATE_COMPLETED: + remove_supplicant_interface_error_handler (self); + remove_supplicant_timeouts (self); + + /* If this is the initial association during device activation, + * schedule the next activation stage. + */ + if (devstate == NM_DEVICE_STATE_CONFIG) { + NMConnection *connection; + NMSettingWireless *s_wifi; + const GByteArray *ssid; + + connection = nm_device_get_connection (NM_DEVICE (self)); + g_return_if_fail (connection); + + s_wifi = nm_connection_get_setting_wireless (connection); + g_return_if_fail (s_wifi); + + ssid = nm_setting_wireless_get_ssid (s_wifi); + g_return_if_fail (ssid); + + nm_log_info (LOGD_DEVICE | LOGD_WIFI, + "Activation (%s/wireless) Stage 2 of 5 (Device Configure) " + "successful. %s '%s'.", + nm_device_get_iface (device), + priv->mode == NM_802_11_MODE_AP ? "Started Wi-Fi Hotspot" : + "Connected to wireless network", + ssid ? nm_utils_escape_ssid (ssid->data, ssid->len) : "(none)"); + nm_device_activate_schedule_stage3_ip_config_start (device); + } else if (devstate == NM_DEVICE_STATE_ACTIVATED) + periodic_update (self, NULL); + break; + case NM_SUPPLICANT_INTERFACE_STATE_DISCONNECTED: + if ((devstate == NM_DEVICE_STATE_ACTIVATED) || nm_device_is_activating (device)) { + /* Disconnect of an 802.1x/LEAP connection during authentication, + * or disconnect of a WPA-PSK connection during the 4-way handshake, + * often means secrets are wrong. Not always the case, but until we + * have more information from wpa_supplicant about why the + * disconnect happened this is the best we can do. + */ + if (handle_8021x_or_psk_auth_fail (self, new_state, old_state, disconnect_reason)) + break; + } + + /* Otherwise it might be a stupid driver or some transient error, so + * let the supplicant try to reconnect a few more times. Give it more + * time if a scan is in progress since the link might be dropped during + * the scan but will be re-established when the scan is done. + */ + if (devstate == NM_DEVICE_STATE_ACTIVATED) { + if (priv->link_timeout_id == 0) { + priv->link_timeout_id = g_timeout_add_seconds (scanning ? 30 : 15, link_timeout_cb, self); + priv->ssid_found = FALSE; + } + } + break; + case NM_SUPPLICANT_INTERFACE_STATE_DOWN: + cleanup_association_attempt (self, FALSE); + + if (old_state < NM_SUPPLICANT_INTERFACE_STATE_READY) + nm_device_remove_pending_action (device, "waiting for supplicant", TRUE); + + /* If the device is already in UNAVAILABLE state then the state change + * is a NOP and the interface won't be re-acquired in the device state + * change handler. So ensure we have a new one here so that we're + * ready if the supplicant comes back. + */ + supplicant_interface_release (self); + supplicant_interface_acquire (self); + + nm_device_state_changed (device, + NM_DEVICE_STATE_UNAVAILABLE, + NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); + break; + default: + break; + } + + /* Signal scanning state changes */ + if ( new_state == NM_SUPPLICANT_INTERFACE_STATE_SCANNING + || old_state == NM_SUPPLICANT_INTERFACE_STATE_SCANNING) + g_object_notify (G_OBJECT (self), "scanning"); +} + +static void +supplicant_iface_connection_error_cb (NMSupplicantInterface *iface, + const char *name, + const char *message, + NMDeviceWifi *self) +{ + NMDevice *device = NM_DEVICE (self); + + if (nm_device_is_activating (device)) { + nm_log_warn (LOGD_DEVICE | LOGD_WIFI, + "Activation (%s/wireless): supplicant association failed: %s - %s", + nm_device_get_iface (device), name, message); + + cleanup_association_attempt (self, TRUE); + nm_device_queue_state (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); + } +} + +static void +remove_supplicant_interface_error_handler (NMDeviceWifi *self) +{ + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + + if (priv->sup_iface) { + g_signal_handlers_disconnect_by_func (priv->sup_iface, + supplicant_iface_connection_error_cb, + self); + } +} + +static void +supplicant_iface_notify_scanning_cb (NMSupplicantInterface *iface, + GParamSpec *pspec, + NMDeviceWifi *self) +{ + NMDeviceState state; + gboolean scanning; + + scanning = nm_supplicant_interface_get_scanning (iface); + nm_log_dbg (LOGD_WIFI_SCAN, "(%s): now %s", + nm_device_get_iface (NM_DEVICE (self)), + scanning ? "scanning" : "idle"); + + g_object_notify (G_OBJECT (self), "scanning"); + + /* Run a quick update of current AP when coming out of a scan */ + state = nm_device_get_state (NM_DEVICE (self)); + if (!scanning && state == NM_DEVICE_STATE_ACTIVATED) + periodic_update (self, NULL); +} + +static NMActStageReturn +handle_auth_or_fail (NMDeviceWifi *self, + NMActRequest *req, + gboolean new_secrets) +{ + const char *setting_name; + guint32 tries; + NMConnection *connection; + NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; + + g_return_val_if_fail (NM_IS_DEVICE_WIFI (self), NM_ACT_STAGE_RETURN_FAILURE); + + if (!req) { + req = nm_device_get_act_request (NM_DEVICE (self)); + g_assert (req); + } + + connection = nm_act_request_get_connection (req); + g_assert (connection); + + tries = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (connection), WIRELESS_SECRETS_TRIES)); + if (tries > 3) + return NM_ACT_STAGE_RETURN_FAILURE; + + nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_NONE); + + nm_connection_clear_secrets (connection); + setting_name = nm_connection_need_secrets (connection, NULL); + if (setting_name) { + NMSettingsGetSecretsFlags flags = NM_SETTINGS_GET_SECRETS_FLAG_ALLOW_INTERACTION; + + if (new_secrets) + flags |= NM_SETTINGS_GET_SECRETS_FLAG_REQUEST_NEW; + nm_act_request_get_secrets (req, setting_name, flags, NULL, wifi_secrets_cb, self); + + g_object_set_data (G_OBJECT (connection), WIRELESS_SECRETS_TRIES, GUINT_TO_POINTER (++tries)); + ret = NM_ACT_STAGE_RETURN_POSTPONE; + } else + nm_log_warn (LOGD_DEVICE, "Cleared secrets, but setting didn't need any secrets."); + + return ret; +} + +/* + * supplicant_connection_timeout_cb + * + * Called when the supplicant has been unable to connect to an access point + * within a specified period of time. + */ +static gboolean +supplicant_connection_timeout_cb (gpointer user_data) +{ + NMDevice *dev = NM_DEVICE (user_data); + NMDeviceWifi *self = NM_DEVICE_WIFI (user_data); + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + NMActRequest *req; + NMConnection *connection; + + cleanup_association_attempt (self, TRUE); + + if (!nm_device_is_activating (dev)) + return FALSE; + + /* Timed out waiting for a successful connection to the AP; if the AP's + * security requires network-side authentication (like WPA or 802.1x) + * and the connection attempt timed out then it's likely the authentication + * information (passwords, pin codes, etc) are wrong. + */ + + req = nm_device_get_act_request (dev); + g_assert (req); + + connection = nm_act_request_get_connection (req); + g_assert (connection); + + if ( priv->mode == NM_802_11_MODE_ADHOC + || priv->mode == NM_802_11_MODE_AP) { + /* In Ad-Hoc and AP modes there's nothing to check the encryption key + * (if any), so supplicant timeouts here are almost certainly the wifi + * driver being really stupid. + */ + nm_log_warn (LOGD_DEVICE | LOGD_WIFI, + "Activation (%s/wireless): %s network creation took " + "too long, failing activation.", + nm_device_get_iface (dev), + priv->mode == NM_802_11_MODE_ADHOC ? "Ad-Hoc" : "Hotspot"); + nm_device_state_changed (dev, NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT); + return FALSE; + } + + g_assert (priv->mode == NM_802_11_MODE_INFRA); + + if (priv->ssid_found && nm_connection_get_setting_wireless_security (connection)) { + guint64 timestamp = 0; + gboolean new_secrets = TRUE; + + /* Connection failed; either driver problems, the encryption key is + * wrong, or the passwords or certificates were wrong. + */ + nm_log_warn (LOGD_DEVICE | LOGD_WIFI, + "Activation (%s/wireless): association took too long.", + nm_device_get_iface (dev)); + + /* Ask for new secrets only if we've never activated this connection + * before. If we've connected before, don't bother the user with + * dialogs, just retry or fail, and if we never connect the user can + * fix the password somewhere else. + */ + if (nm_settings_connection_get_timestamp (NM_SETTINGS_CONNECTION (connection), ×tamp)) + new_secrets = !timestamp; + + if (handle_auth_or_fail (self, req, new_secrets) == NM_ACT_STAGE_RETURN_POSTPONE) { + nm_log_warn (LOGD_DEVICE | LOGD_WIFI, + "Activation (%s/wireless): asking for new secrets", + nm_device_get_iface (dev)); + } else { + nm_device_state_changed (dev, NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_NO_SECRETS); + } + } else { + nm_log_warn (LOGD_DEVICE | LOGD_WIFI, + "Activation (%s/wireless): association took too long, " + "failing activation.", + nm_device_get_iface (dev)); + nm_device_state_changed (dev, NM_DEVICE_STATE_FAILED, + priv->ssid_found ? NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT : + NM_DEVICE_STATE_REASON_SSID_NOT_FOUND); + } + + return FALSE; +} + +static NMSupplicantConfig * +build_supplicant_config (NMDeviceWifi *self, + NMConnection *connection, + guint32 fixed_freq) +{ + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + NMSupplicantConfig *config = NULL; + NMSettingWireless *s_wireless; + NMSettingWirelessSecurity *s_wireless_sec; + + g_return_val_if_fail (self != NULL, NULL); + + s_wireless = nm_connection_get_setting_wireless (connection); + g_return_val_if_fail (s_wireless != NULL, NULL); + + config = nm_supplicant_config_new (); + if (!config) + return NULL; + + /* Warn if AP mode may not be supported */ + if ( g_strcmp0 (nm_setting_wireless_get_mode (s_wireless), NM_SETTING_WIRELESS_MODE_AP) == 0 + && nm_supplicant_interface_get_ap_support (priv->sup_iface) == AP_SUPPORT_UNKNOWN) { + nm_log_warn (LOGD_WIFI, "Supplicant may not support AP mode; connection may time out."); + } + + if (!nm_supplicant_config_add_setting_wireless (config, + s_wireless, + fixed_freq)) { + nm_log_err (LOGD_WIFI, "Couldn't add 802-11-wireless setting to supplicant config."); + goto error; + } + + s_wireless_sec = nm_connection_get_setting_wireless_security (connection); + if (s_wireless_sec) { + NMSetting8021x *s_8021x; + const char *con_uuid = nm_connection_get_uuid (connection); + + g_assert (con_uuid); + s_8021x = nm_connection_get_setting_802_1x (connection); + if (!nm_supplicant_config_add_setting_wireless_security (config, + s_wireless_sec, + s_8021x, + con_uuid)) { + nm_log_err (LOGD_WIFI, "Couldn't add 802-11-wireless-security setting to " + "supplicant config."); + goto error; + } + } else { + if (!nm_supplicant_config_add_no_security (config)) { + nm_log_err (LOGD_WIFI, "Couldn't add unsecured option to supplicant config."); + goto error; + } + } + + return config; + +error: + g_object_unref (config); + return NULL; +} + +/****************************************************************************/ + +static void +update_permanent_hw_address (NMDevice *dev) +{ + NMDeviceWifi *self = NM_DEVICE_WIFI (dev); + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + struct ifreq req; + struct ethtool_perm_addr *epaddr = NULL; + int fd, ret; + + fd = socket (PF_INET, SOCK_DGRAM, 0); + if (fd < 0) { + nm_log_err (LOGD_HW, "could not open control socket."); + return; + } + + /* Get permanent MAC address */ + memset (&req, 0, sizeof (struct ifreq)); + strncpy (req.ifr_name, nm_device_get_iface (dev), IFNAMSIZ); + + epaddr = g_malloc0 (sizeof (struct ethtool_perm_addr) + ETH_ALEN); + epaddr->cmd = ETHTOOL_GPERMADDR; + epaddr->size = ETH_ALEN; + req.ifr_data = (void *) epaddr; + + errno = 0; + ret = ioctl (fd, SIOCETHTOOL, &req); + if ((ret < 0) || !nm_ethernet_address_is_valid ((struct ether_addr *) epaddr->data)) { + nm_log_dbg (LOGD_HW | LOGD_ETHER, "(%s): unable to read permanent MAC address (error %d)", + nm_device_get_iface (dev), errno); + /* Fall back to current address */ + memcpy (epaddr->data, nm_device_get_hw_address (dev, NULL), ETH_ALEN); + } + + if (memcmp (&priv->perm_hw_addr, epaddr->data, ETH_ALEN)) { + memcpy (&priv->perm_hw_addr, epaddr->data, ETH_ALEN); + g_object_notify (G_OBJECT (dev), NM_DEVICE_WIFI_PERMANENT_HW_ADDRESS); + } + + g_free (epaddr); + close (fd); +} + +static void +update_initial_hw_address (NMDevice *dev) +{ + NMDeviceWifi *self = NM_DEVICE_WIFI (dev); + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + char *mac_str; + + /* This sets initial MAC address from current MAC address. It should only + * be called from NMDevice constructor() to really get the initial address. + */ + memcpy (priv->initial_hw_addr, nm_device_get_hw_address (dev, NULL), ETH_ALEN); + + mac_str = nm_utils_hwaddr_ntoa (priv->initial_hw_addr, ARPHRD_ETHER); + nm_log_dbg (LOGD_DEVICE | LOGD_ETHER, "(%s): read initial MAC address %s", + nm_device_get_iface (dev), mac_str); + g_free (mac_str); +} + +static NMActStageReturn +act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason) +{ + NMDeviceWifi *self = NM_DEVICE_WIFI (dev); + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + NMActStageReturn ret; + NMAccessPoint *ap = NULL; + NMActRequest *req; + NMConnection *connection; + NMSettingWireless *s_wireless; + const GByteArray *cloned_mac; + GSList *iter; + const char *mode; + const char *ap_path; + + ret = NM_DEVICE_CLASS (nm_device_wifi_parent_class)->act_stage1_prepare (dev, reason); + if (ret != NM_ACT_STAGE_RETURN_SUCCESS) + return ret; + + req = nm_device_get_act_request (NM_DEVICE (self)); + g_return_val_if_fail (req != NULL, NM_ACT_STAGE_RETURN_FAILURE); + + connection = nm_act_request_get_connection (req); + g_return_val_if_fail (connection != NULL, NM_ACT_STAGE_RETURN_FAILURE); + + s_wireless = nm_connection_get_setting_wireless (connection); + g_assert (s_wireless); + + mode = nm_setting_wireless_get_mode (s_wireless); + if (g_strcmp0 (mode, NM_SETTING_WIRELESS_MODE_INFRA) == 0) + priv->mode = NM_802_11_MODE_INFRA; + else if (g_strcmp0 (mode, NM_SETTING_WIRELESS_MODE_ADHOC) == 0) + priv->mode = NM_802_11_MODE_ADHOC; + else if (g_strcmp0 (mode, NM_SETTING_WIRELESS_MODE_AP) == 0) { + priv->mode = NM_802_11_MODE_AP; + + /* Scanning not done in AP mode; clear the scan list */ + remove_all_aps (self); + } + g_object_notify (G_OBJECT (self), NM_DEVICE_WIFI_MODE); + + /* The kernel doesn't support Ad-Hoc WPA connections well at this time, + * and turns them into open networks. It's been this way since at least + * 2.6.30 or so; until that's fixed, disable WPA-protected Ad-Hoc networks. + */ + if (is_adhoc_wpa (connection)) { + nm_log_warn (LOGD_WIFI, "Ad-Hoc WPA disabled due to kernel bugs"); + *reason = NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED; + return NM_ACT_STAGE_RETURN_FAILURE; + } + + /* Set spoof MAC to the interface */ + cloned_mac = nm_setting_wireless_get_cloned_mac_address (s_wireless); + if (cloned_mac && (cloned_mac->len == ETH_ALEN)) + nm_device_set_hw_addr (dev, (const guint8 *) cloned_mac->data, "set", LOGD_WIFI); + + /* AP mode never uses a specific object or existing scanned AP */ + if (priv->mode != NM_802_11_MODE_AP) { + + ap_path = nm_active_connection_get_specific_object (NM_ACTIVE_CONNECTION (req)); + ap = ap_path ? get_ap_by_path (self, ap_path) : NULL; + if (ap) + goto done; + + /* Find a compatible AP in the scan list */ + for (iter = priv->ap_list; iter; iter = g_slist_next (iter)) { + NMAccessPoint *candidate = NM_AP (iter->data); + + if (nm_ap_check_compatible (candidate, connection)) { + ap = candidate; + break; + } + } + } + + if (ap) { + nm_active_connection_set_specific_object (NM_ACTIVE_CONNECTION (req), nm_ap_get_dbus_path (ap)); + goto done; + } + + /* If the user is trying to connect to an AP that NM doesn't yet know about + * (hidden network or something) or starting a Hotspot, create an fake AP + * from the security settings in the connection. This "fake" AP gets used + * until the real one is found in the scan list (Ad-Hoc or Hidden), or until + * the device is deactivated (Hotspot). + */ + ap = nm_ap_new_fake_from_connection (connection); + g_return_val_if_fail (ap != NULL, NM_ACT_STAGE_RETURN_FAILURE); + + if (nm_ap_get_mode (ap) == NM_802_11_MODE_INFRA) + nm_ap_set_broadcast (ap, FALSE); + else if (nm_ap_is_hotspot (ap)) + nm_ap_set_address (ap, (const struct ether_addr *) nm_device_get_hw_address (dev, NULL)); + + priv->ap_list = g_slist_prepend (priv->ap_list, ap); + nm_ap_export_to_dbus (ap); + g_object_freeze_notify (G_OBJECT (self)); + set_current_ap (self, ap, FALSE, FALSE); + emit_ap_added_removed (self, ACCESS_POINT_ADDED, ap, TRUE); + g_object_thaw_notify (G_OBJECT (self)); + nm_active_connection_set_specific_object (NM_ACTIVE_CONNECTION (req), nm_ap_get_dbus_path (ap)); + return NM_ACT_STAGE_RETURN_SUCCESS; + +done: + set_current_ap (self, ap, TRUE, FALSE); + return NM_ACT_STAGE_RETURN_SUCCESS; +} + +static void +ensure_hotspot_frequency (NMDeviceWifi *self, + NMSettingWireless *s_wifi, + NMAccessPoint *ap) +{ + const char *band = nm_setting_wireless_get_band (s_wifi); + const guint32 a_freqs[] = { 5180, 5200, 5220, 5745, 5765, 5785, 5805, 0 }; + const guint32 bg_freqs[] = { 2412, 2437, 2462, 2472, 0 }; + guint32 freq = 0; + + g_assert (ap); + + if (nm_ap_get_freq (ap)) + return; + + if (g_strcmp0 (band, "a") == 0) + freq = nm_platform_wifi_find_frequency (nm_device_get_ifindex (NM_DEVICE (self)), a_freqs); + else + freq = nm_platform_wifi_find_frequency (nm_device_get_ifindex (NM_DEVICE (self)), bg_freqs); + + if (!freq) + freq = (g_strcmp0 (band, "a") == 0) ? 5180 : 2462; + + nm_ap_set_freq (ap, freq); +} + +static NMActStageReturn +act_stage2_config (NMDevice *dev, NMDeviceStateReason *reason) +{ + NMDeviceWifi *self = NM_DEVICE_WIFI (dev); + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; + const char *iface = nm_device_get_iface (dev); + NMSupplicantConfig *config = NULL; + NMActRequest *req; + NMAccessPoint *ap; + NMConnection *connection; + const char *setting_name; + NMSettingWireless *s_wireless; + + g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); + + remove_supplicant_timeouts (self); + + req = nm_device_get_act_request (dev); + g_assert (req); + + ap = priv->current_ap; + if (!ap) { + *reason = NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED; + goto out; + } + + connection = nm_act_request_get_connection (req); + g_assert (connection); + + s_wireless = nm_connection_get_setting_wireless (connection); + g_assert (s_wireless); + + /* If we need secrets, get them */ + setting_name = nm_connection_need_secrets (connection, NULL); + if (setting_name) { + nm_log_info (LOGD_DEVICE | LOGD_WIFI, + "Activation (%s/wireless): access point '%s' has security," + " but secrets are required.", + iface, nm_connection_get_id (connection)); + + ret = handle_auth_or_fail (self, req, FALSE); + if (ret == NM_ACT_STAGE_RETURN_FAILURE) + *reason = NM_DEVICE_STATE_REASON_NO_SECRETS; + goto out; + } + + /* have secrets, or no secrets required */ + if (nm_connection_get_setting_wireless_security (connection)) { + nm_log_info (LOGD_DEVICE | LOGD_WIFI, + "Activation (%s/wireless): connection '%s' has security" + ", and secrets exist. No new secrets needed.", + iface, nm_connection_get_id (connection)); + } else { + nm_log_info (LOGD_DEVICE | LOGD_WIFI, + "Activation (%s/wireless): connection '%s' requires no " + "security. No secrets needed.", + iface, nm_connection_get_id (connection)); + } + + priv->ssid_found = FALSE; + + /* Supplicant requires an initial frequency for Ad-Hoc and Hotspot; if the user + * didn't specify one and we didn't find an AP that matched the connection, + * just pick a frequency the device supports. + */ + if ((nm_ap_get_mode (ap) == NM_802_11_MODE_ADHOC) || nm_ap_is_hotspot (ap)) + ensure_hotspot_frequency (self, s_wireless, ap); + + /* Build up the supplicant configuration */ + config = build_supplicant_config (self, connection, nm_ap_get_freq (ap)); + if (config == NULL) { + nm_log_err (LOGD_DEVICE | LOGD_WIFI, + "Activation (%s/wireless): couldn't build wireless configuration.", + iface); + *reason = NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED; + goto out; + } + + /* Hook up error signal handler to capture association errors */ + g_signal_connect (priv->sup_iface, + NM_SUPPLICANT_INTERFACE_CONNECTION_ERROR, + G_CALLBACK (supplicant_iface_connection_error_cb), + self); + + if (!nm_supplicant_interface_set_config (priv->sup_iface, config)) { + nm_log_err (LOGD_DEVICE | LOGD_WIFI, + "Activation (%s/wireless): couldn't send wireless " + "configuration to the supplicant.", iface); + *reason = NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED; + goto out; + } + + /* Set up a timeout on the association attempt to fail after 25 seconds */ + priv->sup_timeout_id = g_timeout_add_seconds (25, supplicant_connection_timeout_cb, self); + + if (!priv->periodic_source_id) + priv->periodic_source_id = g_timeout_add_seconds (6, periodic_update_cb, self); + + /* We'll get stage3 started when the supplicant connects */ + ret = NM_ACT_STAGE_RETURN_POSTPONE; + +out: + if (ret == NM_ACT_STAGE_RETURN_FAILURE) + cleanup_association_attempt (self, TRUE); + + if (config) { + /* Supplicant interface object refs the config; we no longer care about + * it after this function. + */ + g_object_unref (config); + } + return ret; +} + +static NMActStageReturn +act_stage3_ip4_config_start (NMDevice *device, + NMIP4Config **out_config, + NMDeviceStateReason *reason) +{ + NMConnection *connection; + NMSettingIP4Config *s_ip4; + const char *method = NM_SETTING_IP4_CONFIG_METHOD_AUTO; + + connection = nm_device_get_connection (device); + g_assert (connection); + s_ip4 = nm_connection_get_setting_ip4_config (connection); + if (s_ip4) + method = nm_setting_ip4_config_get_method (s_ip4); + + /* Indicate that a critical protocol is about to start */ + if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0) + nm_platform_wifi_indicate_addressing_running (nm_device_get_ifindex (device), TRUE); + + return NM_DEVICE_CLASS (nm_device_wifi_parent_class)->act_stage3_ip4_config_start (device, out_config, reason); +} + +static NMActStageReturn +act_stage3_ip6_config_start (NMDevice *device, + NMIP6Config **out_config, + NMDeviceStateReason *reason) +{ + NMConnection *connection; + NMSettingIP6Config *s_ip6; + const char *method = NM_SETTING_IP6_CONFIG_METHOD_AUTO; + + connection = nm_device_get_connection (device); + g_assert (connection); + s_ip6 = nm_connection_get_setting_ip6_config (connection); + if (s_ip6) + method = nm_setting_ip6_config_get_method (s_ip6); + + /* Indicate that a critical protocol is about to start */ + if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) == 0 || + strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_DHCP) == 0) + nm_platform_wifi_indicate_addressing_running (nm_device_get_ifindex (device), TRUE); + + return NM_DEVICE_CLASS (nm_device_wifi_parent_class)->act_stage3_ip6_config_start (device, out_config, reason); +} + +static void +ip4_config_pre_commit (NMDevice *device, NMIP4Config *config) +{ + NMConnection *connection; + NMSettingWireless *s_wifi; + guint32 mtu; + + connection = nm_device_get_connection (device); + g_assert (connection); + s_wifi = nm_connection_get_setting_wireless (connection); + g_assert (s_wifi); + + /* MTU override */ + mtu = nm_setting_wireless_get_mtu (s_wifi); + if (mtu) + nm_ip4_config_set_mtu (config, mtu); +} + +static gboolean +is_static_wep (NMConnection *connection) +{ + NMSettingWirelessSecurity *s_wsec; + const char *str; + + g_return_val_if_fail (connection != NULL, FALSE); + + s_wsec = nm_connection_get_setting_wireless_security (connection); + if (!s_wsec) + return FALSE; + + str = nm_setting_wireless_security_get_key_mgmt (s_wsec); + if (g_strcmp0 (str, "none") != 0) + return FALSE; + + str = nm_setting_wireless_security_get_auth_alg (s_wsec); + if (g_strcmp0 (str, "leap") == 0) + return FALSE; + + return TRUE; +} + +static NMActStageReturn +handle_ip_config_timeout (NMDeviceWifi *self, + NMConnection *connection, + gboolean may_fail, + gboolean *chain_up, + NMDeviceStateReason *reason) +{ + NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; + + g_return_val_if_fail (connection != NULL, NM_ACT_STAGE_RETURN_FAILURE); + + if (NM_DEVICE_WIFI_GET_PRIVATE (self)->mode == NM_802_11_MODE_AP) { + *chain_up = TRUE; + return ret; + } + + /* If IP configuration times out and it's a static WEP connection, that + * usually means the WEP key is wrong. WEP's Open System auth mode has + * no provision for figuring out if the WEP key is wrong, so you just have + * to wait for DHCP to fail to figure it out. For all other WiFi security + * types (open, WPA, 802.1x, etc) if the secrets/certs were wrong the + * connection would have failed before IP configuration. + */ + if (!may_fail && is_static_wep (connection)) { + /* Activation failed, we must have bad encryption key */ + nm_log_warn (LOGD_DEVICE | LOGD_WIFI, + "Activation (%s/wireless): could not get IP configuration for " + "connection '%s'.", + nm_device_get_iface (NM_DEVICE (self)), + nm_connection_get_id (connection)); + + ret = handle_auth_or_fail (self, NULL, TRUE); + if (ret == NM_ACT_STAGE_RETURN_POSTPONE) { + nm_log_info (LOGD_DEVICE | LOGD_WIFI, + "Activation (%s/wireless): asking for new secrets", + nm_device_get_iface (NM_DEVICE (self))); + } else { + *reason = NM_DEVICE_STATE_REASON_NO_SECRETS; + } + } else { + /* Not static WEP or failure allowed; let superclass handle it */ + *chain_up = TRUE; + } + + return ret; +} + + +static NMActStageReturn +act_stage4_ip4_config_timeout (NMDevice *dev, NMDeviceStateReason *reason) +{ + NMConnection *connection; + NMSettingIP4Config *s_ip4; + gboolean may_fail = FALSE, chain_up = FALSE; + NMActStageReturn ret; + + connection = nm_device_get_connection (dev); + g_assert (connection); + + s_ip4 = nm_connection_get_setting_ip4_config (connection); + may_fail = nm_setting_ip4_config_get_may_fail (s_ip4); + + ret = handle_ip_config_timeout (NM_DEVICE_WIFI (dev), connection, may_fail, &chain_up, reason); + if (chain_up) + ret = NM_DEVICE_CLASS (nm_device_wifi_parent_class)->act_stage4_ip4_config_timeout (dev, reason); + + return ret; +} + +static NMActStageReturn +act_stage4_ip6_config_timeout (NMDevice *dev, NMDeviceStateReason *reason) +{ + NMConnection *connection; + NMSettingIP6Config *s_ip6; + gboolean may_fail = FALSE, chain_up = FALSE; + NMActStageReturn ret; + + connection = nm_device_get_connection (dev); + g_assert (connection); + + s_ip6 = nm_connection_get_setting_ip6_config (connection); + may_fail = nm_setting_ip6_config_get_may_fail (s_ip6); + + ret = handle_ip_config_timeout (NM_DEVICE_WIFI (dev), connection, may_fail, &chain_up, reason); + if (chain_up) + ret = NM_DEVICE_CLASS (nm_device_wifi_parent_class)->act_stage4_ip6_config_timeout (dev, reason); + + return ret; +} + +static void +activation_success_handler (NMDevice *dev) +{ + NMDeviceWifi *self = NM_DEVICE_WIFI (dev); + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + int ifindex = nm_device_get_ifindex (dev); + NMAccessPoint *ap; + struct ether_addr bssid = { {0x0, 0x0, 0x0, 0x0, 0x0, 0x0} }; + NMAccessPoint *tmp_ap = NULL; + NMActRequest *req; + NMConnection *connection; + + req = nm_device_get_act_request (dev); + g_assert (req); + + connection = nm_act_request_get_connection (req); + g_assert (connection); + + /* Clear any critical protocol notification in the wifi stack */ + nm_platform_wifi_indicate_addressing_running (ifindex, FALSE); + + /* Clear wireless secrets tries on success */ + g_object_set_data (G_OBJECT (connection), WIRELESS_SECRETS_TRIES, NULL); + + ap = priv->current_ap; + + /* If the AP isn't fake, it was found in the scan list and all its + * details are known. + */ + if (!ap || !nm_ap_get_fake (ap)){ + ap = NULL; + goto done; + } + + /* If the activate AP was fake, it probably won't have a BSSID at all. + * But if activation was successful, the card will know the BSSID. Grab + * the BSSID off the card and fill in the BSSID of the activation AP. + */ + nm_platform_wifi_get_bssid (ifindex, &bssid); + if (!nm_ethernet_address_is_valid (nm_ap_get_address (ap))) + nm_ap_set_address (ap, &bssid); + if (!nm_ap_get_freq (ap)) + nm_ap_set_freq (ap, nm_platform_wifi_get_frequency (ifindex)); + if (!nm_ap_get_max_bitrate (ap)) + nm_ap_set_max_bitrate (ap, nm_platform_wifi_get_rate (ifindex)); + + tmp_ap = find_active_ap (self, ap, TRUE); + if (tmp_ap) { + const GByteArray *ssid = nm_ap_get_ssid (tmp_ap); + + /* Found a better match in the scan list than the fake AP. Use it + * instead. + */ + + /* If the better match was a hidden AP, update it's SSID */ + if (!ssid || nm_utils_is_empty_ssid (ssid->data, ssid->len)) + nm_ap_set_ssid (tmp_ap, nm_ap_get_ssid (ap)); + + nm_active_connection_set_specific_object (NM_ACTIVE_CONNECTION (req), + nm_ap_get_dbus_path (tmp_ap)); + } + +done: + periodic_update (self, ap); + + /* ap might be already unrefed, because it was a fake_ap. But we don't touch it... */ + if (tmp_ap && ap == priv->current_ap) { + /* Strange, we would expect periodic_update() to find a better AP + * then the fake one and reset it. Reset the fake current_ap to NULL + * now, which will remove the fake ap. + **/ + set_current_ap (self, NULL, TRUE, FALSE); + } + + /* No need to update seen BSSIDs cache, that is done by set_current_ap() already */ + + /* Reset scan interval to something reasonable */ + priv->scan_interval = SCAN_INTERVAL_MIN + (SCAN_INTERVAL_STEP * 2); +} + +static void +activation_failure_handler (NMDevice *dev) +{ + NMConnection *connection; + + connection = nm_device_get_connection (dev); + g_assert (connection); + + /* Clear wireless secrets tries on failure */ + g_object_set_data (G_OBJECT (connection), WIRELESS_SECRETS_TRIES, NULL); + + /* Clear any critical protocol notification in the wifi stack */ + nm_platform_wifi_indicate_addressing_running (nm_device_get_ifindex (dev), FALSE); +} + +static void +device_state_changed (NMDevice *device, + NMDeviceState new_state, + NMDeviceState old_state, + NMDeviceStateReason reason) +{ + NMDeviceWifi *self = NM_DEVICE_WIFI (device); + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + gboolean clear_aps = FALSE; + + if (new_state <= NM_DEVICE_STATE_UNAVAILABLE) { + /* Clean up the supplicant interface because in these states the + * device cannot be used. + */ + if (priv->sup_iface) + supplicant_interface_release (self); + + if (priv->periodic_source_id) { + g_source_remove (priv->periodic_source_id); + priv->periodic_source_id = 0; + } + + cleanup_association_attempt (self, TRUE); + remove_all_aps (self); + } + + switch (new_state) { + case NM_DEVICE_STATE_UNMANAGED: + clear_aps = TRUE; + break; + case NM_DEVICE_STATE_UNAVAILABLE: + /* If the device is enabled and the supplicant manager is ready, + * acquire a supplicant interface and transition to DISCONNECTED because + * the device is now ready to use. + */ + if (priv->enabled && (nm_device_get_firmware_missing (device) == FALSE)) { + if (!priv->sup_iface) + supplicant_interface_acquire (self); + } + clear_aps = TRUE; + break; + case NM_DEVICE_STATE_NEED_AUTH: + if (priv->sup_iface) + nm_supplicant_interface_disconnect (priv->sup_iface); + break; + case NM_DEVICE_STATE_IP_CHECK: + /* Clear any critical protocol notification in the wifi stack */ + nm_platform_wifi_indicate_addressing_running (nm_device_get_ifindex (device), FALSE); + break; + case NM_DEVICE_STATE_ACTIVATED: + activation_success_handler (device); + break; + case NM_DEVICE_STATE_FAILED: + activation_failure_handler (device); + break; + case NM_DEVICE_STATE_DISCONNECTED: + /* Kick off a scan to get latest results */ + priv->scan_interval = SCAN_INTERVAL_MIN; + cancel_pending_scan (self); + request_wireless_scan (self); + break; + default: + break; + } + + if (clear_aps) + remove_all_aps (self); +} + +static void +set_enabled (NMDevice *device, gboolean enabled) +{ + NMDeviceWifi *self = NM_DEVICE_WIFI (device); + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + NMDeviceState state; + + if (priv->enabled == enabled) + return; + + priv->enabled = enabled; + + nm_log_dbg (LOGD_WIFI, "(%s): device now %s", + nm_device_get_iface (NM_DEVICE (device)), + enabled ? "enabled" : "disabled"); + + state = nm_device_get_state (NM_DEVICE (self)); + if (state < NM_DEVICE_STATE_UNAVAILABLE) { + nm_log_dbg (LOGD_WIFI, "(%s): %s blocked by UNMANAGED state", + enabled ? "enable" : "disable", + nm_device_get_iface (NM_DEVICE (device))); + return; + } + + if (enabled) { + gboolean no_firmware = FALSE; + + if (state != NM_DEVICE_STATE_UNAVAILABLE) + nm_log_warn (LOGD_CORE, "not in expected unavailable state!"); + + if (!nm_device_bring_up (NM_DEVICE (self), TRUE, &no_firmware)) { + nm_log_dbg (LOGD_WIFI, "(%s): enable blocked by failure to bring device up", + nm_device_get_iface (NM_DEVICE (device))); + + if (no_firmware) + nm_device_set_firmware_missing (NM_DEVICE (device), TRUE); + else { + /* The device sucks, or the kernel was lying to us about the killswitch state */ + priv->enabled = FALSE; + } + return; + } + + /* Re-initialize the supplicant interface and wait for it to be ready */ + if (priv->sup_iface) + supplicant_interface_release (self); + supplicant_interface_acquire (self); + + nm_log_dbg (LOGD_WIFI, "(%s): enable waiting on supplicant state", + nm_device_get_iface (NM_DEVICE (device))); + } else { + nm_device_state_changed (NM_DEVICE (self), + NM_DEVICE_STATE_UNAVAILABLE, + NM_DEVICE_STATE_REASON_NONE); + nm_device_take_down (NM_DEVICE (self), TRUE); + } +} + +/********************************************************************/ + +NMDevice * +nm_device_wifi_new (NMPlatformLink *platform_device) +{ + g_return_val_if_fail (platform_device != NULL, NULL); + + return (NMDevice *) g_object_new (NM_TYPE_DEVICE_WIFI, + NM_DEVICE_PLATFORM_DEVICE, platform_device, + NM_DEVICE_TYPE_DESC, "802.11 WiFi", + NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_WIFI, + NM_DEVICE_RFKILL_TYPE, RFKILL_TYPE_WLAN, + NULL); +} + +static void +nm_device_wifi_init (NMDeviceWifi *self) +{ + NM_DEVICE_WIFI_GET_PRIVATE (self)->mode = NM_802_11_MODE_INFRA; +} + +static void +dispose (GObject *object) +{ + NMDeviceWifi *self = NM_DEVICE_WIFI (object); + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + + if (priv->disposed) { + G_OBJECT_CLASS (nm_device_wifi_parent_class)->dispose (object); + return; + } + + priv->disposed = TRUE; + + if (priv->periodic_source_id) { + g_source_remove (priv->periodic_source_id); + priv->periodic_source_id = 0; + } + + cleanup_association_attempt (self, TRUE); + supplicant_interface_release (self); + + g_clear_object (&priv->sup_mgr); + + remove_all_aps (self); + + G_OBJECT_CLASS (nm_device_wifi_parent_class)->dispose (object); +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMDeviceWifi *device = NM_DEVICE_WIFI (object); + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (device); + GPtrArray *array; + GSList *iter; + + switch (prop_id) { + case PROP_PERM_HW_ADDRESS: + g_value_take_string (value, nm_utils_hwaddr_ntoa (&priv->perm_hw_addr, ARPHRD_ETHER)); + break; + case PROP_MODE: + g_value_set_uint (value, priv->mode); + break; + case PROP_BITRATE: + g_value_set_uint (value, priv->rate); + break; + case PROP_CAPABILITIES: + g_value_set_uint (value, priv->capabilities); + break; + case PROP_ACCESS_POINTS: + array = g_ptr_array_sized_new (4); + for (iter = priv->ap_list; iter; iter = g_slist_next (iter)) + g_ptr_array_add (array, g_strdup (nm_ap_get_dbus_path (NM_AP (iter->data)))); + g_value_take_boxed (value, array); + break; + case PROP_ACTIVE_ACCESS_POINT: + if (priv->current_ap) + g_value_set_boxed (value, nm_ap_get_dbus_path (priv->current_ap)); + else + g_value_set_boxed (value, "/"); + break; + case PROP_SCANNING: + g_value_set_boolean (value, nm_supplicant_interface_get_scanning (priv->sup_iface)); + 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) +{ + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + + +static void +nm_device_wifi_class_init (NMDeviceWifiClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (NMDeviceWifiPrivate)); + + object_class->constructor = constructor; + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->dispose = dispose; + + parent_class->bring_up = bring_up; + parent_class->update_permanent_hw_address = update_permanent_hw_address; + parent_class->update_initial_hw_address = update_initial_hw_address; + parent_class->can_auto_connect = can_auto_connect; + parent_class->is_available = is_available; + parent_class->check_connection_compatible = check_connection_compatible; + parent_class->check_connection_available = check_connection_available; + parent_class->check_connection_available_wifi_hidden = check_connection_available_wifi_hidden; + parent_class->complete_connection = complete_connection; + parent_class->set_enabled = set_enabled; + + parent_class->act_stage1_prepare = act_stage1_prepare; + parent_class->act_stage2_config = act_stage2_config; + parent_class->ip4_config_pre_commit = ip4_config_pre_commit; + parent_class->act_stage3_ip4_config_start = act_stage3_ip4_config_start; + parent_class->act_stage3_ip6_config_start = act_stage3_ip6_config_start; + parent_class->act_stage4_ip4_config_timeout = act_stage4_ip4_config_timeout; + parent_class->act_stage4_ip6_config_timeout = act_stage4_ip6_config_timeout; + parent_class->deactivate = deactivate; + + parent_class->state_changed = device_state_changed; + + klass->scanning_allowed = scanning_allowed; + + /* Properties */ + g_object_class_install_property (object_class, PROP_PERM_HW_ADDRESS, + g_param_spec_string (NM_DEVICE_WIFI_PERMANENT_HW_ADDRESS, + "Permanent MAC Address", + "Permanent hardware MAC address", + NULL, + G_PARAM_READABLE)); + + g_object_class_install_property (object_class, PROP_MODE, + g_param_spec_uint (NM_DEVICE_WIFI_MODE, + "Mode", + "Mode", + NM_802_11_MODE_UNKNOWN, + NM_802_11_MODE_AP, + NM_802_11_MODE_INFRA, + G_PARAM_READABLE)); + + g_object_class_install_property (object_class, PROP_BITRATE, + g_param_spec_uint (NM_DEVICE_WIFI_BITRATE, + "Bitrate", + "Bitrate", + 0, G_MAXUINT32, 0, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_ACCESS_POINTS, + g_param_spec_boxed (NM_DEVICE_WIFI_ACCESS_POINTS, + "Access points", + "Access points", + DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH, + G_PARAM_READABLE)); + + g_object_class_install_property (object_class, PROP_ACTIVE_ACCESS_POINT, + g_param_spec_boxed (NM_DEVICE_WIFI_ACTIVE_ACCESS_POINT, + "Active access point", + "Currently active access point", + DBUS_TYPE_G_OBJECT_PATH, + G_PARAM_READABLE)); + + g_object_class_install_property (object_class, PROP_CAPABILITIES, + g_param_spec_uint (NM_DEVICE_WIFI_CAPABILITIES, + "Wireless Capabilities", + "Wireless Capabilities", + 0, G_MAXUINT32, NM_WIFI_DEVICE_CAP_NONE, + G_PARAM_READABLE)); + + g_object_class_install_property (object_class, PROP_SCANNING, + g_param_spec_boolean (NM_DEVICE_WIFI_SCANNING, + "Scanning", + "Scanning", + FALSE, + G_PARAM_READABLE)); + + /* Signals */ + signals[ACCESS_POINT_ADDED] = + g_signal_new ("access-point-added", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMDeviceWifiClass, access_point_added), + NULL, NULL, NULL, + G_TYPE_NONE, 1, + G_TYPE_OBJECT); + + signals[ACCESS_POINT_REMOVED] = + g_signal_new ("access-point-removed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, + NULL, NULL, NULL, + G_TYPE_NONE, 1, + G_TYPE_OBJECT); + + signals[SCANNING_ALLOWED] = + g_signal_new ("scanning-allowed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (NMDeviceWifiClass, scanning_allowed), + scanning_allowed_accumulator, NULL, NULL, + G_TYPE_BOOLEAN, 0); + + nm_dbus_manager_register_exported_type (nm_dbus_manager_get (), + G_TYPE_FROM_CLASS (klass), + &dbus_glib_nm_device_wifi_object_info); + + dbus_g_error_domain_register (NM_WIFI_ERROR, NULL, NM_TYPE_WIFI_ERROR); +} + + diff --git a/src/devices/wifi/nm-device-wifi.h b/src/devices/wifi/nm-device-wifi.h new file mode 100644 index 00000000..f0a1beac --- /dev/null +++ b/src/devices/wifi/nm-device-wifi.h @@ -0,0 +1,94 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2005 - 2010 Red Hat, Inc. + * Copyright (C) 2006 - 2008 Novell, Inc. + */ + +#ifndef NM_DEVICE_WIFI_H +#define NM_DEVICE_WIFI_H + +#include +#include +#include + +#include "nm-device.h" +#include "nm-wifi-ap.h" + +struct NMAccessPointList; + +G_BEGIN_DECLS + +#define NM_TYPE_DEVICE_WIFI (nm_device_wifi_get_type ()) +#define NM_DEVICE_WIFI(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_WIFI, NMDeviceWifi)) +#define NM_DEVICE_WIFI_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_WIFI, NMDeviceWifiClass)) +#define NM_IS_DEVICE_WIFI(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_WIFI)) +#define NM_IS_DEVICE_WIFI_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_WIFI)) +#define NM_DEVICE_WIFI_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_WIFI, NMDeviceWifiClass)) + +typedef enum { + NM_WIFI_ERROR_CONNECTION_NOT_WIRELESS = 0, /*< nick=ConnectionNotWireless >*/ + NM_WIFI_ERROR_CONNECTION_INVALID, /*< nick=ConnectionInvalid >*/ + NM_WIFI_ERROR_CONNECTION_INCOMPATIBLE, /*< nick=ConnectionIncompatible >*/ + NM_WIFI_ERROR_ACCESS_POINT_NOT_FOUND, /*< nick=AccessPointNotFound >*/ + NM_WIFI_ERROR_SCAN_NOT_ALLOWED, /*< nick=ScanNotAllowed >*/ + NM_WIFI_ERROR_AP_MODE_UNSUPPORTED, /*< nick=ApModeUnsupported >*/ + NM_WIFI_ERROR_ADHOC_MODE_UNSUPPORTED, /*< nick=AdhocModeUnsupported >*/ +} NMWifiError; + +#define NM_DEVICE_WIFI_PERMANENT_HW_ADDRESS "perm-hw-address" +#define NM_DEVICE_WIFI_MODE "mode" +#define NM_DEVICE_WIFI_BITRATE "bitrate" +#define NM_DEVICE_WIFI_ACCESS_POINTS "access-points" +#define NM_DEVICE_WIFI_ACTIVE_ACCESS_POINT "active-access-point" +#define NM_DEVICE_WIFI_CAPABILITIES "wireless-capabilities" +#define NM_DEVICE_WIFI_SCANNING "scanning" + +#ifndef NM_DEVICE_WIFI_DEFINED +#define NM_DEVICE_WIFI_DEFINED +typedef struct _NMDeviceWifi NMDeviceWifi; +#endif + +typedef struct _NMDeviceWifiClass NMDeviceWifiClass; +typedef struct _NMDeviceWifiPrivate NMDeviceWifiPrivate; + +struct _NMDeviceWifi +{ + NMDevice parent; + + /*< private >*/ + NMDeviceWifiPrivate *priv; +}; + +struct _NMDeviceWifiClass +{ + NMDeviceClass parent; + + /* Signals */ + void (*access_point_added) (NMDeviceWifi *device, NMAccessPoint *ap); + void (*access_point_removed) (NMDeviceWifi *device, NMAccessPoint *ap); + gboolean (*scanning_allowed) (NMDeviceWifi *device); +}; + + +GType nm_device_wifi_get_type (void); + +NMDevice *nm_device_wifi_new (NMPlatformLink *platform_device); + +G_END_DECLS + +#endif /* NM_DEVICE_WIFI_H */ diff --git a/src/devices/wifi/nm-wifi-ap-utils.c b/src/devices/wifi/nm-wifi-ap-utils.c new file mode 100644 index 00000000..9b03cbd4 --- /dev/null +++ b/src/devices/wifi/nm-wifi-ap-utils.c @@ -0,0 +1,721 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * (C) Copyright 2011 Red Hat, Inc. + */ + +#include +#include +#include + +#include "nm-wifi-ap-utils.h" + +static gboolean +verify_no_wep (NMSettingWirelessSecurity *s_wsec, const char *tag, GError **error) +{ + if ( nm_setting_wireless_security_get_wep_key (s_wsec, 0) + || nm_setting_wireless_security_get_wep_key (s_wsec, 1) + || nm_setting_wireless_security_get_wep_key (s_wsec, 2) + || nm_setting_wireless_security_get_wep_key (s_wsec, 3) + || nm_setting_wireless_security_get_wep_tx_keyidx (s_wsec) + || nm_setting_wireless_security_get_wep_key_type (s_wsec)) { + /* Dynamic WEP cannot have any WEP keys set */ + g_set_error (error, + NM_SETTING_WIRELESS_SECURITY_ERROR, + NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, + "%s is incompatible with static WEP keys", tag); + return FALSE; + } + + return TRUE; +} + +static gboolean +verify_leap (NMSettingWirelessSecurity *s_wsec, + NMSetting8021x *s_8021x, + gboolean adhoc, + GError **error) +{ + const char *key_mgmt, *auth_alg, *leap_username; + + key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wsec); + auth_alg = nm_setting_wireless_security_get_auth_alg (s_wsec); + leap_username = nm_setting_wireless_security_get_leap_username (s_wsec); + + /* One (or both) of two things indicates we want LEAP: + * 1) auth_alg == 'leap' + * 2) valid leap_username + * + * LEAP always requires a LEAP username. + */ + + if (auth_alg) { + if (!strcmp (auth_alg, "leap")) { + /* LEAP authentication requires at least a LEAP username */ + if (!leap_username) { + g_set_error_literal (error, + NM_SETTING_WIRELESS_SECURITY_ERROR, + NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_USERNAME, + "LEAP requires a LEAP username"); + return FALSE; + } + } else if (leap_username) { + /* Leap username requires 'leap' auth */ + g_set_error_literal (error, + NM_SETTING_WIRELESS_SECURITY_ERROR, + NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, + "LEAP requires 'leap' authentication"); + return FALSE; + } + } + + if (leap_username) { + if (key_mgmt && strcmp (key_mgmt, "ieee8021x")) { + /* LEAP requires ieee8021x key management */ + g_set_error_literal (error, + NM_SETTING_WIRELESS_SECURITY_ERROR, + NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_802_1X, + "LEAP requires IEEE 802.1x key management"); + return FALSE; + } + } + + /* At this point if auth_alg is set it must be 'leap', and if key_mgmt + * is set it must be 'ieee8021x'. + */ + if (leap_username) { + if (auth_alg) + g_assert (strcmp (auth_alg, "leap") == 0); + if (key_mgmt) + g_assert (strcmp (key_mgmt, "ieee8021x") == 0); + + if (adhoc) { + g_set_error_literal (error, + NM_SETTING_WIRELESS_SECURITY_ERROR, + NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, + "LEAP incompatible with Ad-Hoc mode"); + return FALSE; + } + + if (!verify_no_wep (s_wsec, "LEAP", error)) + return FALSE; + + if (s_8021x) { + g_set_error_literal (error, + NM_SETTING_WIRELESS_SECURITY_ERROR, + NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_USERNAME, + "LEAP incompatible with 802.1x setting"); + return FALSE; + } + } + + return TRUE; +} + +static gboolean +verify_no_wpa (NMSettingWirelessSecurity *s_wsec, + const char *tag, + GError **error) +{ + const char *key_mgmt; + int n, i; + + key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wsec); + if (key_mgmt && !strncmp (key_mgmt, "wpa", 3)) { + g_set_error (error, + NM_SETTING_WIRELESS_SECURITY_ERROR, + NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, + "%s incompatible with any WPA key management", tag); + return FALSE; + } + + if (nm_setting_wireless_security_get_num_protos (s_wsec)) { + g_set_error (error, + NM_SETTING_WIRELESS_SECURITY_ERROR, + NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, + "%s incompatible with any 'proto' setting", tag); + return FALSE; + } + + n = nm_setting_wireless_security_get_num_pairwise (s_wsec); + for (i = 0; i < n; i++) { + const char *pw; + + pw = nm_setting_wireless_security_get_pairwise (s_wsec, i); + if (!strcmp (pw, "tkip") || !strcmp (pw, "ccmp")) { + g_set_error (error, + NM_SETTING_WIRELESS_SECURITY_ERROR, + NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, + "%s is incompatible with WPA pairwise ciphers", tag); + return FALSE; + } + } + + n = nm_setting_wireless_security_get_num_groups (s_wsec); + for (i = 0; i < n; i++) { + const char *gr; + + gr = nm_setting_wireless_security_get_group (s_wsec, i); + if (strcmp (gr, "wep40") && strcmp (gr, "wep104")) { + g_set_error (error, + NM_SETTING_WIRELESS_SECURITY_ERROR, + NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, + "%s is incompatible with WPA group ciphers", tag); + return FALSE; + } + } + + if (nm_setting_wireless_security_get_psk (s_wsec)) { + g_set_error (error, + NM_SETTING_WIRELESS_SECURITY_ERROR, + NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, + "%s is incompatible with a WPA Pre-Shared Key", tag); + return FALSE; + } + + return TRUE; +} + +static gboolean +verify_dynamic_wep (NMSettingWirelessSecurity *s_wsec, + NMSetting8021x *s_8021x, + gboolean adhoc, + GError **error) +{ + const char *key_mgmt, *auth_alg, *leap_username; + + key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wsec); + auth_alg = nm_setting_wireless_security_get_auth_alg (s_wsec); + leap_username = nm_setting_wireless_security_get_leap_username (s_wsec); + + g_return_val_if_fail (leap_username == NULL, TRUE); + + if (key_mgmt) { + if (!strcmp (key_mgmt, "ieee8021x")) { + if (!s_8021x) { + /* 802.1x key management requires an 802.1x setting */ + g_set_error_literal (error, + NM_SETTING_WIRELESS_SECURITY_ERROR, + NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, + "Dynamic WEP requires an 802.1x setting"); + return FALSE; + } + + if (auth_alg && strcmp (auth_alg, "open")) { + /* 802.1x key management must use "open" authentication */ + g_set_error_literal (error, + NM_SETTING_WIRELESS_SECURITY_ERROR, + NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, + "Dynamic WEP requires 'open' authentication"); + return FALSE; + } + + /* Dynamic WEP incompatible with anything static WEP related */ + if (!verify_no_wep (s_wsec, "Dynamic WEP", error)) + return FALSE; + } else if (!strcmp (key_mgmt, "none")) { + if (s_8021x) { + /* 802.1x setting requires 802.1x key management */ + g_set_error_literal (error, + NM_SETTING_WIRELESS_SECURITY_ERROR, + NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, + "Dynamic WEP requires 'ieee8021x' key management"); + return FALSE; + } + } + } else if (s_8021x) { + /* 802.1x setting incompatible with anything but 'open' auth */ + if (auth_alg && strcmp (auth_alg, "open")) { + /* 802.1x key management must use "open" authentication */ + g_set_error_literal (error, + NM_SETTING_WIRELESS_SECURITY_ERROR, + NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, + "Dynamic WEP requires 'open' authentication"); + return FALSE; + } + + /* Dynamic WEP incompatible with anything static WEP related */ + if (!verify_no_wep (s_wsec, "Dynamic WEP", error)) + return FALSE; + } + + return TRUE; +} + +static gboolean +verify_wpa_psk (NMSettingWirelessSecurity *s_wsec, + NMSetting8021x *s_8021x, + gboolean adhoc, + guint32 wpa_flags, + guint32 rsn_flags, + GError **error) +{ + const char *key_mgmt, *auth_alg, *tmp; + int n; + + key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wsec); + auth_alg = nm_setting_wireless_security_get_auth_alg (s_wsec); + + if (key_mgmt) { + if (!strcmp (key_mgmt, "wpa-psk") || !strcmp (key_mgmt, "wpa-none")) { + if (s_8021x) { + g_set_error_literal (error, + NM_SETTING_WIRELESS_SECURITY_ERROR, + NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, + "WPA-PSK incompatible with 802.1x"); + return FALSE; + } + + if (auth_alg && strcmp (auth_alg, "open")) { + /* WPA must use "open" authentication */ + g_set_error_literal (error, + NM_SETTING_WIRELESS_SECURITY_ERROR, + NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, + "WPA-PSK requires 'open' authentication"); + return FALSE; + } + } + + if (!strcmp (key_mgmt, "wpa-none")) { + if (!adhoc) { + g_set_error_literal (error, + NM_SETTING_WIRELESS_SECURITY_ERROR, + NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, + "WPA Ad-Hoc requires an Ad-Hoc mode AP"); + return FALSE; + } + + /* Ad-Hoc WPA requires 'wpa' proto, 'none' pairwise, and 'tkip' group */ + n = nm_setting_wireless_security_get_num_protos (s_wsec); + tmp = (n > 0) ? nm_setting_wireless_security_get_proto (s_wsec, 0) : NULL; + if (n > 1 || !tmp || strcmp (tmp, "wpa")) { + g_set_error_literal (error, + NM_SETTING_WIRELESS_SECURITY_ERROR, + NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, + "WPA Ad-Hoc requires 'wpa' proto"); + return FALSE; + } + + n = nm_setting_wireless_security_get_num_pairwise (s_wsec); + tmp = (n > 0) ? nm_setting_wireless_security_get_pairwise (s_wsec, 0) : NULL; + if (n > 1 || g_strcmp0 (tmp, "none")) { + g_set_error_literal (error, + NM_SETTING_WIRELESS_SECURITY_ERROR, + NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, + "WPA Ad-Hoc requires 'none' pairwise cipher"); + return FALSE; + } + + n = nm_setting_wireless_security_get_num_groups (s_wsec); + tmp = (n > 0) ? nm_setting_wireless_security_get_group (s_wsec, 0) : NULL; + if (n > 1 || !tmp || strcmp (tmp, "tkip")) { + g_set_error_literal (error, + NM_SETTING_WIRELESS_SECURITY_ERROR, + NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, + "WPA Ad-Hoc requires 'tkip' group cipher"); + return FALSE; + } + } + + if (!strcmp (key_mgmt, "wpa-psk")) { + /* Make sure the AP's capabilities support WPA-PSK */ + if ( !(wpa_flags & NM_802_11_AP_SEC_KEY_MGMT_PSK) + && !(rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_PSK)) { + g_set_error_literal (error, + NM_SETTING_WIRELESS_SECURITY_ERROR, + NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, + "AP does not support PSK but setting requires it"); + return FALSE; + } + } + } + + return TRUE; +} + +static gboolean +verify_wpa_eap (NMSettingWirelessSecurity *s_wsec, + NMSetting8021x *s_8021x, + guint32 wpa_flags, + guint32 rsn_flags, + GError **error) +{ + const char *key_mgmt, *auth_alg; + gboolean is_wpa_eap = FALSE; + + key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wsec); + auth_alg = nm_setting_wireless_security_get_auth_alg (s_wsec); + + if (key_mgmt) { + if (!strcmp (key_mgmt, "wpa-eap")) { + if (!s_8021x) { + g_set_error_literal (error, + NM_SETTING_WIRELESS_SECURITY_ERROR, + NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, + "WPA-EAP requires an 802.1x setting"); + return FALSE; + } + + if (auth_alg && strcmp (auth_alg, "open")) { + /* WPA must use "open" authentication */ + g_set_error_literal (error, + NM_SETTING_WIRELESS_SECURITY_ERROR, + NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, + "WPA-EAP requires 'open' authentication"); + return FALSE; + } + + is_wpa_eap = TRUE; + } else if (s_8021x) { + g_set_error_literal (error, + NM_SETTING_WIRELESS_SECURITY_ERROR, + NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, + "Setting requires 802.1x but does not use 'wpa-eap' key management"); + return FALSE; + } + } + + if (is_wpa_eap || s_8021x) { + /* Make sure the AP's capabilities support WPA-EAP */ + if ( !(wpa_flags & NM_802_11_AP_SEC_KEY_MGMT_802_1X) + && !(rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) { + g_set_error_literal (error, + NM_SETTING_WIRELESS_SECURITY_ERROR, + NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, + "AP does not support 802.1x but setting requires it"); + return FALSE; + } + } + + return TRUE; +} + +static gboolean +verify_adhoc (NMSettingWirelessSecurity *s_wsec, + NMSetting8021x *s_8021x, + gboolean adhoc, + GError **error) +{ + const char *key_mgmt = NULL, *leap_username = NULL, *auth_alg = NULL; + + if (s_wsec) { + key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wsec); + auth_alg = nm_setting_wireless_security_get_auth_alg (s_wsec); + leap_username = nm_setting_wireless_security_get_leap_username (s_wsec); + } + + if (adhoc) { + if (key_mgmt && strcmp (key_mgmt, "wpa-none") && strcmp (key_mgmt, "none")) { + g_set_error_literal (error, + NM_SETTING_WIRELESS_SECURITY_ERROR, + NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, + "AP mode is Ad-Hoc but setting requires Infrastructure security"); + return FALSE; + } + + if (s_8021x) { + g_set_error_literal (error, + NM_SETTING_WIRELESS_SECURITY_ERROR, + NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, + "Ad-Hoc mode incompatible with 802.1x security"); + return FALSE; + } + + if (leap_username) { + g_set_error_literal (error, + NM_SETTING_WIRELESS_SECURITY_ERROR, + NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, + "Ad-Hoc mode incompatible with LEAP security"); + return FALSE; + } + + if (auth_alg && strcmp (auth_alg, "open")) { + g_set_error_literal (error, + NM_SETTING_WIRELESS_SECURITY_ERROR, + NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, + "Ad-Hoc mode requires 'open' authentication"); + return FALSE; + } + } else { + if (key_mgmt && !strcmp (key_mgmt, "wpa-none")) { + g_set_error_literal (error, + NM_SETTING_WIRELESS_SECURITY_ERROR, + NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, + "AP mode is Infrastructure but setting requires Ad-Hoc security"); + return FALSE; + } + } + + return TRUE; +} + +gboolean +nm_ap_utils_complete_connection (const GByteArray *ap_ssid, + const guint8 ap_bssid[ETH_ALEN], + NM80211Mode ap_mode, + guint32 ap_flags, + guint32 ap_wpa_flags, + guint32 ap_rsn_flags, + NMConnection *connection, + gboolean lock_bssid, + GError **error) +{ + NMSettingWireless *s_wifi; + NMSettingWirelessSecurity *s_wsec; + NMSetting8021x *s_8021x; + const GByteArray *ssid; + const char *mode, *key_mgmt, *auth_alg, *leap_username; + gboolean adhoc = FALSE; + + s_wifi = nm_connection_get_setting_wireless (connection); + g_assert (s_wifi); + s_wsec = nm_connection_get_setting_wireless_security (connection); + s_8021x = nm_connection_get_setting_802_1x (connection); + + /* Fill in missing SSID */ + ssid = nm_setting_wireless_get_ssid (s_wifi); + if (!ssid) + g_object_set (G_OBJECT (s_wifi), NM_SETTING_WIRELESS_SSID, ap_ssid, NULL); + else if ( ssid->len != ap_ssid->len + || memcmp (ssid->data, ap_ssid->data, ssid->len)) { + g_set_error_literal (error, + NM_SETTING_WIRELESS_ERROR, + NM_SETTING_WIRELESS_ERROR_INVALID_PROPERTY, + "Setting SSID did not match AP SSID"); + return FALSE; + } + + if (lock_bssid && !nm_setting_wireless_get_bssid (s_wifi)) { + GByteArray *bssid; + + bssid = g_byte_array_sized_new (ETH_ALEN); + g_byte_array_append (bssid, ap_bssid, ETH_ALEN); + g_object_set (G_OBJECT (s_wifi), NM_SETTING_WIRELESS_BSSID, bssid, NULL); + g_byte_array_free (bssid, TRUE); + } + + /* And mode */ + mode = nm_setting_wireless_get_mode (s_wifi); + if (mode) { + gboolean valid = FALSE; + + /* Make sure the supplied mode matches the AP's */ + if ( !strcmp (mode, NM_SETTING_WIRELESS_MODE_INFRA) + || !strcmp (mode, NM_SETTING_WIRELESS_MODE_AP)) { + if (ap_mode == NM_802_11_MODE_INFRA) + valid = TRUE; + } else if (!strcmp (mode, NM_SETTING_WIRELESS_MODE_ADHOC)) { + if (ap_mode == NM_802_11_MODE_ADHOC) + valid = TRUE; + adhoc = TRUE; + } + + if (valid == FALSE) { + g_set_error (error, + NM_SETTING_WIRELESS_ERROR, + NM_SETTING_WIRELESS_ERROR_INVALID_PROPERTY, + NM_SETTING_WIRELESS_MODE); + return FALSE; + } + } else { + mode = NM_SETTING_WIRELESS_MODE_INFRA; + if (ap_mode == NM_802_11_MODE_ADHOC) { + mode = NM_SETTING_WIRELESS_MODE_ADHOC; + adhoc = TRUE; + } + g_object_set (G_OBJECT (s_wifi), NM_SETTING_WIRELESS_MODE, mode, NULL); + } + + /* Security */ + + /* Open */ + if ( !(ap_flags & NM_802_11_AP_FLAGS_PRIVACY) + && (ap_wpa_flags == NM_802_11_AP_SEC_NONE) + && (ap_rsn_flags == NM_802_11_AP_SEC_NONE)) { + /* Make sure the connection doesn't specify security */ + if (s_wsec || s_8021x) { + g_set_error_literal (error, + NM_SETTING_WIRELESS_SECURITY_ERROR, + NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, + "AP is unencrypted but setting specifies security"); + return FALSE; + } + return TRUE; + } + + /* Everything else requires security */ + if (!s_wsec) { + s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new (); + nm_connection_add_setting (connection, NM_SETTING (s_wsec)); + } + + key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wsec); + auth_alg = nm_setting_wireless_security_get_auth_alg (s_wsec); + leap_username = nm_setting_wireless_security_get_leap_username (s_wsec); + + /* Ad-Hoc checks */ + if (!verify_adhoc (s_wsec, s_8021x, adhoc, error)) + return FALSE; + + /* Static WEP, Dynamic WEP, or LEAP */ + if ( (ap_flags & NM_802_11_AP_FLAGS_PRIVACY) + && (ap_wpa_flags == NM_802_11_AP_SEC_NONE) + && (ap_rsn_flags == NM_802_11_AP_SEC_NONE)) { + const char *tag = "WEP"; + gboolean is_dynamic_wep = FALSE; + + if (!verify_leap (s_wsec, s_8021x, adhoc, error)) + return FALSE; + + if (leap_username) { + tag = "LEAP"; + } else { + /* Static or Dynamic WEP */ + if (!verify_dynamic_wep (s_wsec, s_8021x, adhoc, error)) + return FALSE; + + if (s_8021x || (key_mgmt && !strcmp (key_mgmt, "ieee8021x"))) { + is_dynamic_wep = TRUE; + tag = "Dynamic WEP"; + } + } + + /* Nothing WPA-related can be set */ + if (!verify_no_wpa (s_wsec, tag, error)) + return FALSE; + + if (leap_username) { + /* LEAP */ + g_object_set (s_wsec, + NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x", + NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "leap", + NULL); + } else if (is_dynamic_wep) { + /* Dynamic WEP */ + g_object_set (s_wsec, + NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x", + NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "open", + NULL); + + if (s_8021x) { + /* Dynamic WEP requires a valid 802.1x setting since we can't + * autocomplete 802.1x. + */ + if (!nm_setting_verify (NM_SETTING (s_8021x), NULL, error)) + return FALSE; + } + } else { + /* Static WEP */ + g_object_set (s_wsec, + NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "none", + NULL); + } + + return TRUE; + } + + /* WPA/RSN */ + g_assert (ap_wpa_flags || ap_rsn_flags); + + /* Ensure key management is valid for WPA */ + if ((key_mgmt && !strcmp (key_mgmt, "ieee8021x")) || leap_username) { + g_set_error_literal (error, + NM_SETTING_WIRELESS_SECURITY_ERROR, + NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, + "WPA incompatible with non-EAP (original) LEAP or Dynamic WEP"); + return FALSE; + } + + /* 'shared' auth incompatible with any type of WPA */ + if (auth_alg && strcmp (auth_alg, "open")) { + g_set_error_literal (error, + NM_SETTING_WIRELESS_SECURITY_ERROR, + NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, + "WPA incompatible with Shared Key authentication"); + return FALSE; + } + + if (!verify_no_wep (s_wsec, "WPA", error)) + return FALSE; + + if (!verify_wpa_psk (s_wsec, s_8021x, adhoc, ap_wpa_flags, ap_rsn_flags, error)) + return FALSE; + + if (!adhoc && !verify_wpa_eap (s_wsec, s_8021x, ap_wpa_flags, ap_rsn_flags, error)) + return FALSE; + + if (adhoc) { + g_object_set (s_wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-none", NULL); + /* Ad-Hoc does not support RSN/WPA2 */ + nm_setting_wireless_security_add_proto (s_wsec, "wpa"); + nm_setting_wireless_security_add_pairwise (s_wsec, "none"); + nm_setting_wireless_security_add_group (s_wsec, "tkip"); + } else if (s_8021x) { + g_object_set (s_wsec, + NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-eap", + NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "open", + NULL); + /* Leave proto/pairwise/group as client set them; if they are unset the + * supplicant will figure out the best combination at connect time. + */ + + /* 802.1x also requires the client to completely fill in the 8021x + * setting. Since there's so much configuration required for it, there's + * no way it can be automatically completed. + */ + } else if ( (key_mgmt && !strcmp (key_mgmt, "wpa-psk")) + || (ap_wpa_flags & NM_802_11_AP_SEC_KEY_MGMT_PSK) + || (ap_rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_PSK)) { + g_object_set (s_wsec, + NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-psk", + NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "open", + NULL); + /* Leave proto/pairwise/group as client set them; if they are unset the + * supplicant will figure out the best combination at connect time. + */ + } else { + g_set_error_literal (error, + NM_SETTING_WIRELESS_SECURITY_ERROR, + NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, + "Failed to determine AP security information"); + return FALSE; + } + + return TRUE; +} + +guint32 +nm_ap_utils_level_to_quality (gint val) +{ + if (val < 0) { + /* Assume dBm already; rough conversion: best = -40, worst = -100 */ + val = abs (CLAMP (val, -100, -40) + 40); /* normalize to 0 */ + val = 100 - (int) ((100.0 * (double) val) / 60.0); + } else if (val > 110 && val < 256) { + /* assume old-style WEXT 8-bit unsigned signal level */ + val -= 256; /* subtract 256 to convert to dBm */ + val = abs (CLAMP (val, -100, -40) + 40); /* normalize to 0 */ + val = 100 - (int) ((100.0 * (double) val) / 60.0); + } else { + /* Assume signal is a "quality" percentage */ + val = CLAMP (val, 0, 100); + } + g_assert (val >= 0); + + return (guint32) val; +} + diff --git a/src/devices/wifi/nm-wifi-ap-utils.h b/src/devices/wifi/nm-wifi-ap-utils.h new file mode 100644 index 00000000..992b839d --- /dev/null +++ b/src/devices/wifi/nm-wifi-ap-utils.h @@ -0,0 +1,45 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * (C) Copyright 2011 Red Hat, Inc. + */ + +#ifndef NM_WIFI_AP_UTILS_H +#define NM_WIFI_AP_UTILS_H + +#include + +#include +#include +#include +#include +#include + +gboolean nm_ap_utils_complete_connection (const GByteArray *ssid, + const guint8 bssid[ETH_ALEN], + NM80211Mode mode, + guint32 flags, + guint32 wpa_flags, + guint32 rsn_flags, + NMConnection *connection, + gboolean lock_bssid, + GError **error); + +guint32 nm_ap_utils_level_to_quality (gint val); + +#endif /* NM_WIFI_AP_UTILS_H */ + diff --git a/src/devices/wifi/nm-wifi-ap.c b/src/devices/wifi/nm-wifi-ap.c new file mode 100644 index 00000000..363be2e3 --- /dev/null +++ b/src/devices/wifi/nm-wifi-ap.c @@ -0,0 +1,1293 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2004 - 2011 Red Hat, Inc. + * Copyright (C) 2006 - 2008 Novell, Inc. + */ + +#include +#include +#include + +#include "nm-wifi-ap.h" +#include "nm-wifi-ap-utils.h" +#include "NetworkManagerUtils.h" +#include "nm-utils.h" +#include "nm-logging.h" +#include "nm-dbus-manager.h" + +#include "nm-setting-wireless.h" +#include "nm-glib-compat.h" + +#include "nm-access-point-glue.h" + +/* + * Encapsulates Access Point information + */ +typedef struct +{ + char *dbus_path; + char *supplicant_path; /* D-Bus object path of this AP from wpa_supplicant */ + + /* Scanned or cached values */ + GByteArray * ssid; + struct ether_addr address; + NM80211Mode mode; + gint8 strength; + guint32 freq; /* Frequency in MHz; ie 2412 (== 2.412 GHz) */ + guint32 max_bitrate;/* Maximum bitrate of the AP in Kbit/s (ie 54000 Kb/s == 54Mbit/s) */ + + NM80211ApFlags flags; /* General flags */ + NM80211ApSecurityFlags wpa_flags; /* WPA-related flags */ + NM80211ApSecurityFlags rsn_flags; /* RSN (WPA2) -related flags */ + + /* Non-scanned attributes */ + gboolean fake; /* Whether or not the AP is from a scan */ + gboolean hotspot; /* Whether the AP is a local device's hotspot network */ + gboolean broadcast; /* Whether or not the AP is broadcasting (hidden) */ + gint32 last_seen; /* Timestamp when the AP was seen lastly (obtained via nm_utils_get_monotonic_timestamp_s()) */ +} NMAccessPointPrivate; + +#define NM_AP_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_AP, NMAccessPointPrivate)) + +G_DEFINE_TYPE (NMAccessPoint, nm_ap, G_TYPE_OBJECT) + +enum { + PROP_0, + PROP_FLAGS, + PROP_WPA_FLAGS, + PROP_RSN_FLAGS, + PROP_SSID, + PROP_FREQUENCY, + PROP_HW_ADDRESS, + PROP_MODE, + PROP_MAX_BITRATE, + PROP_STRENGTH, + LAST_PROP +}; + +static void +nm_ap_init (NMAccessPoint *ap) +{ + NMAccessPointPrivate *priv = NM_AP_GET_PRIVATE (ap); + + priv->dbus_path = NULL; + priv->mode = NM_802_11_MODE_INFRA; + priv->flags = NM_802_11_AP_FLAGS_NONE; + priv->wpa_flags = NM_802_11_AP_SEC_NONE; + priv->rsn_flags = NM_802_11_AP_SEC_NONE; + priv->broadcast = TRUE; +} + +static void +finalize (GObject *object) +{ + NMAccessPointPrivate *priv = NM_AP_GET_PRIVATE (object); + + g_free (priv->dbus_path); + g_free (priv->supplicant_path); + if (priv->ssid) + g_byte_array_free (priv->ssid, TRUE); + + G_OBJECT_CLASS (nm_ap_parent_class)->finalize (object); +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMAccessPoint *ap = NM_AP (object); + + switch (prop_id) { + case PROP_FLAGS: + nm_ap_set_flags (ap, g_value_get_uint (value)); + break; + case PROP_WPA_FLAGS: + nm_ap_set_wpa_flags (ap, g_value_get_uint (value)); + break; + case PROP_RSN_FLAGS: + nm_ap_set_rsn_flags (ap, g_value_get_uint (value)); + break; + case PROP_SSID: + nm_ap_set_ssid (ap, (GByteArray *) g_value_get_boxed (value)); + break; + case PROP_FREQUENCY: + nm_ap_set_freq (ap, g_value_get_uint (value)); + break; + case PROP_MODE: + nm_ap_set_mode (ap, g_value_get_uint (value)); + break; + case PROP_MAX_BITRATE: + nm_ap_set_max_bitrate (ap, g_value_get_uint (value)); + break; + case PROP_STRENGTH: + nm_ap_set_strength (ap, g_value_get_schar (value)); + break; + case PROP_HW_ADDRESS: + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMAccessPointPrivate *priv = NM_AP_GET_PRIVATE (object); + GArray * ssid; + int len; + int i; + + switch (prop_id) { + case PROP_FLAGS: + g_value_set_uint (value, priv->flags); + break; + case PROP_WPA_FLAGS: + g_value_set_uint (value, priv->wpa_flags); + break; + case PROP_RSN_FLAGS: + g_value_set_uint (value, priv->rsn_flags); + break; + case PROP_SSID: + len = priv->ssid ? priv->ssid->len : 0; + ssid = g_array_sized_new (FALSE, TRUE, sizeof (unsigned char), len); + for (i = 0; i < len; i++) + g_array_append_val (ssid, priv->ssid->data[i]); + g_value_set_boxed (value, ssid); + g_array_free (ssid, TRUE); + break; + case PROP_FREQUENCY: + g_value_set_uint (value, priv->freq); + break; + case PROP_HW_ADDRESS: + g_value_take_string (value, nm_utils_hwaddr_ntoa (&priv->address, ARPHRD_ETHER)); + break; + case PROP_MODE: + g_value_set_uint (value, priv->mode); + break; + case PROP_MAX_BITRATE: + g_value_set_uint (value, priv->max_bitrate); + break; + case PROP_STRENGTH: + g_value_set_schar (value, priv->strength); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_ap_class_init (NMAccessPointClass *ap_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (ap_class); + const NM80211ApSecurityFlags all_sec_flags = NM_802_11_AP_SEC_NONE + | NM_802_11_AP_SEC_PAIR_WEP40 + | NM_802_11_AP_SEC_PAIR_WEP104 + | NM_802_11_AP_SEC_PAIR_TKIP + | NM_802_11_AP_SEC_PAIR_CCMP + | NM_802_11_AP_SEC_GROUP_WEP40 + | NM_802_11_AP_SEC_GROUP_WEP104 + | NM_802_11_AP_SEC_GROUP_TKIP + | NM_802_11_AP_SEC_GROUP_CCMP + | NM_802_11_AP_SEC_KEY_MGMT_PSK + | NM_802_11_AP_SEC_KEY_MGMT_802_1X; + + g_type_class_add_private (ap_class, sizeof (NMAccessPointPrivate)); + + /* virtual methods */ + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->finalize = finalize; + + /* properties */ + g_object_class_install_property + (object_class, PROP_FLAGS, + g_param_spec_uint (NM_AP_FLAGS, + "Flags", + "Flags", + NM_802_11_AP_FLAGS_NONE, + NM_802_11_AP_FLAGS_PRIVACY, + NM_802_11_AP_FLAGS_NONE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property + (object_class, PROP_WPA_FLAGS, + g_param_spec_uint (NM_AP_WPA_FLAGS, + "WPA Flags", + "WPA Flags", + NM_802_11_AP_SEC_NONE, + all_sec_flags, + NM_802_11_AP_SEC_NONE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property + (object_class, PROP_RSN_FLAGS, + g_param_spec_uint (NM_AP_RSN_FLAGS, + "RSN Flags", + "RSN Flags", + NM_802_11_AP_SEC_NONE, + all_sec_flags, + NM_802_11_AP_SEC_NONE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property + (object_class, PROP_SSID, + g_param_spec_boxed (NM_AP_SSID, + "SSID", + "SSID", + DBUS_TYPE_G_UCHAR_ARRAY, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property + (object_class, PROP_FREQUENCY, + g_param_spec_uint (NM_AP_FREQUENCY, + "Frequency", + "Frequency", + 0, 10000, 0, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property + (object_class, PROP_HW_ADDRESS, + g_param_spec_string (NM_AP_HW_ADDRESS, + "MAC Address", + "Hardware MAC address", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property + (object_class, PROP_MODE, + g_param_spec_uint (NM_AP_MODE, + "Mode", + "Mode", + NM_802_11_MODE_ADHOC, NM_802_11_MODE_INFRA, NM_802_11_MODE_INFRA, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property + (object_class, PROP_MAX_BITRATE, + g_param_spec_uint (NM_AP_MAX_BITRATE, + "Max Bitrate", + "Max Bitrate", + 0, G_MAXUINT16, 0, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property + (object_class, PROP_STRENGTH, + g_param_spec_char (NM_AP_STRENGTH, + "Strength", + "Strength", + G_MININT8, G_MAXINT8, 0, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + nm_dbus_manager_register_exported_type (nm_dbus_manager_get (), + G_TYPE_FROM_CLASS (ap_class), + &dbus_glib_nm_access_point_object_info); +} + +void +nm_ap_export_to_dbus (NMAccessPoint *ap) +{ + NMAccessPointPrivate *priv; + static guint32 counter = 0; + + g_return_if_fail (NM_IS_AP (ap)); + + priv = NM_AP_GET_PRIVATE (ap); + + if (priv->dbus_path) { + nm_log_err (LOGD_CORE, "Tried to export AP %s twice.", priv->dbus_path); + return; + } + + priv->dbus_path = g_strdup_printf (NM_DBUS_PATH_ACCESS_POINT "/%d", counter++); + nm_dbus_manager_register_object (nm_dbus_manager_get (), priv->dbus_path, ap); +} + +/* + * nm_ap_new + * + * Create a new, blank user access point info structure + * + */ +static NMAccessPoint * +nm_ap_new (void) +{ + return (NMAccessPoint *) g_object_new (NM_TYPE_AP, NULL); +} + +static NM80211ApSecurityFlags +pair_to_flags (const char *str) +{ + g_return_val_if_fail (str != NULL, NM_802_11_AP_SEC_NONE); + + if (strcmp (str, "tkip") == 0) + return NM_802_11_AP_SEC_PAIR_TKIP; + if (strcmp (str, "ccmp") == 0) + return NM_802_11_AP_SEC_PAIR_CCMP; + return NM_802_11_AP_SEC_NONE; +} + +static NM80211ApSecurityFlags +group_to_flags (const char *str) +{ + g_return_val_if_fail (str != NULL, NM_802_11_AP_SEC_NONE); + + if (strcmp (str, "wep40") == 0) + return NM_802_11_AP_SEC_GROUP_WEP40; + if (strcmp (str, "wep104") == 0) + return NM_802_11_AP_SEC_GROUP_WEP104; + if (strcmp (str, "tkip") == 0) + return NM_802_11_AP_SEC_GROUP_TKIP; + if (strcmp (str, "ccmp") == 0) + return NM_802_11_AP_SEC_GROUP_CCMP; + return NM_802_11_AP_SEC_NONE; +} + +static NM80211ApSecurityFlags +security_from_dict (GHashTable *security) +{ + GValue *value; + NM80211ApSecurityFlags flags = NM_802_11_AP_SEC_NONE; + const char **items, **iter; + + value = g_hash_table_lookup (security, "KeyMgmt"); + if (value) { + items = g_value_get_boxed (value); + for (iter = items; iter && *iter; iter++) { + if (strcmp (*iter, "wpa-psk") == 0) + flags |= NM_802_11_AP_SEC_KEY_MGMT_PSK; + else if (strcmp (*iter, "wpa-eap") == 0) + flags |= NM_802_11_AP_SEC_KEY_MGMT_802_1X; + } + } + + value = g_hash_table_lookup (security, "Pairwise"); + if (value) { + items = g_value_get_boxed (value); + for (iter = items; iter && *iter; iter++) + flags |= pair_to_flags (*iter); + } + + value = g_hash_table_lookup (security, "Group"); + if (value) + flags |= group_to_flags (g_value_get_string (value)); + + return flags; +} + +static void +foreach_property_cb (gpointer key, gpointer value, gpointer user_data) +{ + GValue *variant = (GValue *) value; + NMAccessPoint *ap = (NMAccessPoint *) user_data; + + if (G_VALUE_HOLDS_BOXED (variant)) { + GArray *array = g_value_get_boxed (variant); + + if (!strcmp (key, "SSID")) { + guint32 len = MIN (32, array->len); + GByteArray *ssid; + + /* Stupid ieee80211 layer uses */ + if (((len == 8) || (len == 9)) + && (memcmp (array->data, "", 8) == 0)) + return; + + if (nm_utils_is_empty_ssid ((const guint8 *) array->data, len)) + return; + + ssid = g_byte_array_sized_new (len); + g_byte_array_append (ssid, (const guint8 *) array->data, len); + nm_ap_set_ssid (ap, ssid); + g_byte_array_free (ssid, TRUE); + } else if (!strcmp (key, "BSSID")) { + struct ether_addr addr; + + if (array->len != ETH_ALEN) + return; + memset (&addr, 0, sizeof (struct ether_addr)); + memcpy (&addr, array->data, ETH_ALEN); + nm_ap_set_address (ap, &addr); + } else if (!strcmp (key, "Rates")) { + guint32 maxrate = 0; + int i; + + /* Find the max AP rate */ + for (i = 0; i < array->len; i++) { + guint32 r = g_array_index (array, guint32, i); + + if (r > maxrate) { + maxrate = r; + nm_ap_set_max_bitrate (ap, r / 1000); + } + } + } else if (!strcmp (key, "WPA")) { + NM80211ApSecurityFlags flags = nm_ap_get_wpa_flags (ap); + + flags |= security_from_dict (g_value_get_boxed (variant)); + nm_ap_set_wpa_flags (ap, flags); + } else if (!strcmp (key, "RSN")) { + NM80211ApSecurityFlags flags = nm_ap_get_rsn_flags (ap); + + flags |= security_from_dict (g_value_get_boxed (variant)); + nm_ap_set_rsn_flags (ap, flags); + } + } else if (G_VALUE_HOLDS_UINT (variant)) { + guint32 val = g_value_get_uint (variant); + + if (!strcmp (key, "Frequency")) + nm_ap_set_freq (ap, val); + } else if (G_VALUE_HOLDS_INT (variant)) { + gint val = g_value_get_int (variant); + + if (!strcmp (key, "Signal")) + nm_ap_set_strength (ap, nm_ap_utils_level_to_quality (val)); + } else if (G_VALUE_HOLDS_STRING (variant)) { + const char *val = g_value_get_string (variant); + + if (val && !strcmp (key, "Mode")) { + if (strcmp (val, "infrastructure") == 0) + nm_ap_set_mode (ap, NM_802_11_MODE_INFRA); + else if (strcmp (val, "ad-hoc") == 0) + nm_ap_set_mode (ap, NM_802_11_MODE_ADHOC); + } + } else if (G_VALUE_HOLDS_BOOLEAN (variant)) { + gboolean val = g_value_get_boolean (variant); + + if (strcmp (key, "Privacy") == 0) { + if (val) { + NM80211ApFlags flags = nm_ap_get_flags (ap); + nm_ap_set_flags (ap, flags | NM_802_11_AP_FLAGS_PRIVACY); + } + } + } +} + +NMAccessPoint * +nm_ap_new_from_properties (const char *supplicant_path, GHashTable *properties) +{ + NMAccessPoint *ap; + const struct ether_addr * addr; + const char bad_bssid1[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + const char bad_bssid2[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + + g_return_val_if_fail (properties != NULL, NULL); + + ap = nm_ap_new (); + + g_object_freeze_notify (G_OBJECT (ap)); + g_hash_table_foreach (properties, foreach_property_cb, ap); + + nm_ap_set_supplicant_path (ap, supplicant_path); + + /* ignore APs with invalid BSSIDs */ + addr = nm_ap_get_address (ap); + if ( !(memcmp (addr->ether_addr_octet, bad_bssid1, ETH_ALEN)) + || !(memcmp (addr->ether_addr_octet, bad_bssid2, ETH_ALEN))) { + g_object_unref (ap); + return NULL; + } + + nm_ap_set_last_seen (ap, nm_utils_get_monotonic_timestamp_s ()); + + if (!nm_ap_get_ssid (ap)) + nm_ap_set_broadcast (ap, FALSE); + + g_object_thaw_notify (G_OBJECT (ap)); + + return ap; +} + +#define PROTO_WPA "wpa" +#define PROTO_RSN "rsn" + +static gboolean +has_proto (NMSettingWirelessSecurity *sec, const char *proto) +{ + guint32 num_protos = nm_setting_wireless_security_get_num_protos (sec); + guint32 i; + + if (num_protos == 0) + return TRUE; /* interpret no protos as "all" */ + + for (i = 0; i < num_protos; i++) { + if (!strcmp (nm_setting_wireless_security_get_proto (sec, i), proto)) + return TRUE; + } + return FALSE; +} + +static void +add_pair_ciphers (NMAccessPoint *ap, NMSettingWirelessSecurity *sec) +{ + guint32 num = nm_setting_wireless_security_get_num_pairwise (sec); + NM80211ApSecurityFlags flags = NM_802_11_AP_SEC_NONE; + guint32 i; + + /* If no ciphers are specified, that means "all" WPA ciphers */ + if (num == 0) { + flags |= NM_802_11_AP_SEC_PAIR_TKIP | NM_802_11_AP_SEC_PAIR_CCMP; + } else { + for (i = 0; i < num; i++) { + const char *cipher = nm_setting_wireless_security_get_pairwise (sec, i); + + if (!strcmp (cipher, "tkip")) + flags |= NM_802_11_AP_SEC_PAIR_TKIP; + else if (!strcmp (cipher, "ccmp")) + flags |= NM_802_11_AP_SEC_PAIR_CCMP; + } + } + + if (has_proto (sec, PROTO_WPA)) + nm_ap_set_wpa_flags (ap, nm_ap_get_wpa_flags (ap) | flags); + if (has_proto (sec, PROTO_RSN)) + nm_ap_set_rsn_flags (ap, nm_ap_get_rsn_flags (ap) | flags); +} + +static void +add_group_ciphers (NMAccessPoint *ap, NMSettingWirelessSecurity *sec) +{ + guint32 num = nm_setting_wireless_security_get_num_groups (sec); + NM80211ApSecurityFlags flags = NM_802_11_AP_SEC_NONE; + guint32 i; + + /* If no ciphers are specified, that means "all" WPA ciphers */ + if (num == 0) { + flags |= NM_802_11_AP_SEC_GROUP_TKIP | NM_802_11_AP_SEC_GROUP_CCMP; + } else { + for (i = 0; i < num; i++) { + const char *cipher = nm_setting_wireless_security_get_group (sec, i); + + if (!strcmp (cipher, "wep40")) + flags |= NM_802_11_AP_SEC_GROUP_WEP40; + else if (!strcmp (cipher, "wep104")) + flags |= NM_802_11_AP_SEC_GROUP_WEP104; + else if (!strcmp (cipher, "tkip")) + flags |= NM_802_11_AP_SEC_GROUP_TKIP; + else if (!strcmp (cipher, "ccmp")) + flags |= NM_802_11_AP_SEC_GROUP_CCMP; + } + } + + if (has_proto (sec, PROTO_WPA)) + nm_ap_set_wpa_flags (ap, nm_ap_get_wpa_flags (ap) | flags); + if (has_proto (sec, PROTO_RSN)) + nm_ap_set_rsn_flags (ap, nm_ap_get_rsn_flags (ap) | flags); +} + +NMAccessPoint * +nm_ap_new_fake_from_connection (NMConnection *connection) +{ + NMAccessPoint *ap; + NMSettingWireless *s_wireless; + NMSettingWirelessSecurity *s_wireless_sec; + const GByteArray *ssid; + const char *mode, *band, *key_mgmt; + guint32 channel; + NM80211ApSecurityFlags flags; + gboolean psk = FALSE, eap = FALSE; + + g_return_val_if_fail (connection != NULL, NULL); + + s_wireless = nm_connection_get_setting_wireless (connection); + g_return_val_if_fail (s_wireless != NULL, NULL); + + ssid = nm_setting_wireless_get_ssid (s_wireless); + g_return_val_if_fail (ssid != NULL, NULL); + g_return_val_if_fail (ssid->len > 0, NULL); + + ap = nm_ap_new (); + nm_ap_set_fake (ap, TRUE); + nm_ap_set_ssid (ap, ssid); + + // FIXME: bssid too? + + mode = nm_setting_wireless_get_mode (s_wireless); + if (mode) { + if (!strcmp (mode, "infrastructure")) + nm_ap_set_mode (ap, NM_802_11_MODE_INFRA); + else if (!strcmp (mode, "adhoc")) + nm_ap_set_mode (ap, NM_802_11_MODE_ADHOC); + else if (!strcmp (mode, "ap")) { + nm_ap_set_mode (ap, NM_802_11_MODE_INFRA); + NM_AP_GET_PRIVATE (ap)->hotspot = TRUE; + } else + goto error; + } else { + nm_ap_set_mode (ap, NM_802_11_MODE_INFRA); + } + + band = nm_setting_wireless_get_band (s_wireless); + channel = nm_setting_wireless_get_channel (s_wireless); + + if (band && channel) { + guint32 freq = nm_utils_wifi_channel_to_freq (channel, band); + + if (freq == 0) + goto error; + + nm_ap_set_freq (ap, freq); + } + + s_wireless_sec = nm_connection_get_setting_wireless_security (connection); + /* Assume presence of a security setting means the AP is encrypted */ + if (!s_wireless_sec) + goto done; + + key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wireless_sec); + + /* Everything below here uses encryption */ + nm_ap_set_flags (ap, nm_ap_get_flags (ap) | NM_802_11_AP_FLAGS_PRIVACY); + + /* Static & Dynamic WEP */ + if (!strcmp (key_mgmt, "none") || !strcmp (key_mgmt, "ieee8021x")) + goto done; + + psk = !strcmp (key_mgmt, "wpa-psk"); + eap = !strcmp (key_mgmt, "wpa-eap"); + if (psk || eap) { + if (has_proto (s_wireless_sec, PROTO_WPA)) { + flags = nm_ap_get_wpa_flags (ap); + flags |= eap ? NM_802_11_AP_SEC_KEY_MGMT_802_1X : NM_802_11_AP_SEC_KEY_MGMT_PSK; + nm_ap_set_wpa_flags (ap, flags); + } + if (has_proto (s_wireless_sec, PROTO_RSN)) { + flags = nm_ap_get_rsn_flags (ap); + flags |= eap ? NM_802_11_AP_SEC_KEY_MGMT_802_1X : NM_802_11_AP_SEC_KEY_MGMT_PSK; + nm_ap_set_rsn_flags (ap, flags); + } + + add_pair_ciphers (ap, s_wireless_sec); + add_group_ciphers (ap, s_wireless_sec); + } else if (!strcmp (key_mgmt, "wpa-none")) { + guint32 i; + + /* Ad-Hoc has special requirements: proto=WPA, pairwise=(none), and + * group=TKIP/CCMP (but not both). + */ + + flags = nm_ap_get_wpa_flags (ap); + flags |= NM_802_11_AP_SEC_KEY_MGMT_PSK; + + /* Clear ciphers; pairwise must be unset anyway, and group gets set below */ + flags &= ~( NM_802_11_AP_SEC_PAIR_WEP40 + | NM_802_11_AP_SEC_PAIR_WEP104 + | NM_802_11_AP_SEC_PAIR_TKIP + | NM_802_11_AP_SEC_PAIR_CCMP + | NM_802_11_AP_SEC_GROUP_WEP40 + | NM_802_11_AP_SEC_GROUP_WEP104 + | NM_802_11_AP_SEC_GROUP_TKIP + | NM_802_11_AP_SEC_GROUP_CCMP); + + for (i = 0; i < nm_setting_wireless_security_get_num_groups (s_wireless_sec); i++) { + if (!strcmp (nm_setting_wireless_security_get_group (s_wireless_sec, i), "ccmp")) { + flags |= NM_802_11_AP_SEC_GROUP_CCMP; + break; + } + } + + /* Default to TKIP since not all WPA-capable cards can do CCMP */ + if (!(flags & NM_802_11_AP_SEC_GROUP_CCMP)) + flags |= NM_802_11_AP_SEC_GROUP_TKIP; + + nm_ap_set_wpa_flags (ap, flags); + + /* Don't use Ad-Hoc RSN yet */ + nm_ap_set_rsn_flags (ap, NM_802_11_AP_SEC_NONE); + } + +done: + return ap; + +error: + g_object_unref (ap); + return NULL; +} + + +#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x" +#define MAC_ARG(x) ((guint8*)(x))[0],((guint8*)(x))[1],((guint8*)(x))[2],((guint8*)(x))[3],((guint8*)(x))[4],((guint8*)(x))[5] + +void +nm_ap_dump (NMAccessPoint *ap, const char *prefix) +{ + NMAccessPointPrivate *priv; + + g_return_if_fail (NM_IS_AP (ap)); + + priv = NM_AP_GET_PRIVATE (ap); + + nm_log_dbg (LOGD_WIFI_SCAN, "%s'%s' (%p)", + prefix, + priv->ssid ? nm_utils_escape_ssid (priv->ssid->data, priv->ssid->len) : "(none)", + ap); + nm_log_dbg (LOGD_WIFI_SCAN, " BSSID " MAC_FMT, MAC_ARG (priv->address.ether_addr_octet)); + nm_log_dbg (LOGD_WIFI_SCAN, " mode %d", priv->mode); + nm_log_dbg (LOGD_WIFI_SCAN, " flags 0x%X", priv->flags); + nm_log_dbg (LOGD_WIFI_SCAN, " wpa flags 0x%X", priv->wpa_flags); + nm_log_dbg (LOGD_WIFI_SCAN, " rsn flags 0x%X", priv->rsn_flags); + nm_log_dbg (LOGD_WIFI_SCAN, " quality %d", priv->strength); + nm_log_dbg (LOGD_WIFI_SCAN, " frequency %d", priv->freq); + nm_log_dbg (LOGD_WIFI_SCAN, " max rate %d", priv->max_bitrate); + nm_log_dbg (LOGD_WIFI_SCAN, " last-seen %d", (int) priv->last_seen); +} + +const char * +nm_ap_get_dbus_path (NMAccessPoint *ap) +{ + g_return_val_if_fail (NM_IS_AP (ap), NULL); + + return NM_AP_GET_PRIVATE (ap)->dbus_path; +} + +const char * +nm_ap_get_supplicant_path (NMAccessPoint *ap) +{ + g_return_val_if_fail (NM_IS_AP (ap), NULL); + + return NM_AP_GET_PRIVATE (ap)->supplicant_path; +} + +void +nm_ap_set_supplicant_path (NMAccessPoint *ap, const char *path) +{ + g_return_if_fail (NM_IS_AP (ap)); + g_return_if_fail (path != NULL); + + g_free (NM_AP_GET_PRIVATE (ap)->supplicant_path); + NM_AP_GET_PRIVATE (ap)->supplicant_path = g_strdup (path); +} + +/* + * Get/set functions for ssid + * + */ +const GByteArray * nm_ap_get_ssid (const NMAccessPoint *ap) +{ + g_return_val_if_fail (NM_IS_AP (ap), NULL); + + return NM_AP_GET_PRIVATE (ap)->ssid; +} + +void +nm_ap_set_ssid (NMAccessPoint *ap, const GByteArray * ssid) +{ + NMAccessPointPrivate *priv; + + g_return_if_fail (NM_IS_AP (ap)); + + priv = NM_AP_GET_PRIVATE (ap); + + if (ssid == priv->ssid) + return; + + /* same SSID */ + if ((ssid && priv->ssid) && (ssid->len == priv->ssid->len)) { + if (!memcmp (ssid->data, priv->ssid->data, ssid->len)) + return; + } + + if (priv->ssid) { + g_byte_array_free (priv->ssid, TRUE); + priv->ssid = NULL; + } + + if (ssid) { + /* Should never get zero-length SSIDs */ + g_warn_if_fail (ssid->len > 0); + + if (ssid->len) { + priv->ssid = g_byte_array_sized_new (ssid->len); + priv->ssid->len = ssid->len; + memcpy (priv->ssid->data, ssid->data, ssid->len); + } + } + + g_object_notify (G_OBJECT (ap), NM_AP_SSID); +} + + +NM80211ApFlags +nm_ap_get_flags (NMAccessPoint *ap) +{ + g_return_val_if_fail (NM_IS_AP (ap), NM_802_11_AP_SEC_NONE); + + return NM_AP_GET_PRIVATE (ap)->flags; +} + + +void +nm_ap_set_flags (NMAccessPoint *ap, NM80211ApFlags flags) +{ + NMAccessPointPrivate *priv; + + g_return_if_fail (NM_IS_AP (ap)); + + priv = NM_AP_GET_PRIVATE (ap); + + if (priv->flags != flags) { + priv->flags = flags; + g_object_notify (G_OBJECT (ap), NM_AP_FLAGS); + } +} + +NM80211ApSecurityFlags +nm_ap_get_wpa_flags (NMAccessPoint *ap) +{ + g_return_val_if_fail (NM_IS_AP (ap), NM_802_11_AP_SEC_NONE); + + return NM_AP_GET_PRIVATE (ap)->wpa_flags; +} + + +void +nm_ap_set_wpa_flags (NMAccessPoint *ap, NM80211ApSecurityFlags flags) +{ + NMAccessPointPrivate *priv; + + g_return_if_fail (NM_IS_AP (ap)); + + priv = NM_AP_GET_PRIVATE (ap); + if (priv->wpa_flags != flags) { + priv->wpa_flags = flags; + g_object_notify (G_OBJECT (ap), NM_AP_WPA_FLAGS); + } +} + +NM80211ApSecurityFlags +nm_ap_get_rsn_flags (NMAccessPoint *ap) +{ + g_return_val_if_fail (NM_IS_AP (ap), NM_802_11_AP_SEC_NONE); + + return NM_AP_GET_PRIVATE (ap)->rsn_flags; +} + + +void +nm_ap_set_rsn_flags (NMAccessPoint *ap, NM80211ApSecurityFlags flags) +{ + NMAccessPointPrivate *priv; + + g_return_if_fail (NM_IS_AP (ap)); + + priv = NM_AP_GET_PRIVATE (ap); + if (priv->rsn_flags != flags) { + priv->rsn_flags = flags; + g_object_notify (G_OBJECT (ap), NM_AP_RSN_FLAGS); + } +} + +/* + * Get/set functions for address + * + */ +const struct ether_addr * nm_ap_get_address (const NMAccessPoint *ap) +{ + g_return_val_if_fail (NM_IS_AP (ap), NULL); + + return &NM_AP_GET_PRIVATE (ap)->address; +} + +void nm_ap_set_address (NMAccessPoint *ap, const struct ether_addr * addr) +{ + NMAccessPointPrivate *priv; + + g_return_if_fail (NM_IS_AP (ap)); + g_return_if_fail (addr != NULL); + + priv = NM_AP_GET_PRIVATE (ap); + + if (memcmp (addr, &priv->address, sizeof (priv->address))) { + memcpy (&NM_AP_GET_PRIVATE (ap)->address, addr, sizeof (struct ether_addr)); + g_object_notify (G_OBJECT (ap), NM_AP_HW_ADDRESS); + } +} + + +/* + * Get/set functions for mode (ie Ad-Hoc, Infrastructure, etc) + * + */ +NM80211Mode nm_ap_get_mode (NMAccessPoint *ap) +{ + NM80211Mode mode; + + g_return_val_if_fail (NM_IS_AP (ap), -1); + + g_object_get (ap, NM_AP_MODE, &mode, NULL); + + return mode; +} + +void nm_ap_set_mode (NMAccessPoint *ap, const NM80211Mode mode) +{ + NMAccessPointPrivate *priv; + + g_return_if_fail (NM_IS_AP (ap)); + g_return_if_fail ( mode == NM_802_11_MODE_ADHOC + || mode == NM_802_11_MODE_INFRA); + + priv = NM_AP_GET_PRIVATE (ap); + + if (priv->mode != mode) { + priv->mode = mode; + g_object_notify (G_OBJECT (ap), NM_AP_MODE); + } +} + +gboolean +nm_ap_is_hotspot (NMAccessPoint *ap) +{ + g_return_val_if_fail (NM_IS_AP (ap), FALSE); + + return NM_AP_GET_PRIVATE (ap)->hotspot; +} + +/* + * Get/set functions for strength + * + */ +gint8 nm_ap_get_strength (NMAccessPoint *ap) +{ + gint8 strength; + + g_return_val_if_fail (NM_IS_AP (ap), 0); + + g_object_get (ap, NM_AP_STRENGTH, &strength, NULL); + + return strength; +} + +void nm_ap_set_strength (NMAccessPoint *ap, const gint8 strength) +{ + NMAccessPointPrivate *priv; + + g_return_if_fail (NM_IS_AP (ap)); + + priv = NM_AP_GET_PRIVATE (ap); + + if (priv->strength != strength) { + priv->strength = strength; + g_object_notify (G_OBJECT (ap), NM_AP_STRENGTH); + } +} + + +/* + * Get/set functions for frequency + * + */ +guint32 +nm_ap_get_freq (NMAccessPoint *ap) +{ + guint32 freq; + + g_return_val_if_fail (NM_IS_AP (ap), 0); + + g_object_get (ap, NM_AP_FREQUENCY, &freq, NULL); + + return freq; +} + +void +nm_ap_set_freq (NMAccessPoint *ap, + const guint32 freq) +{ + NMAccessPointPrivate *priv; + + g_return_if_fail (NM_IS_AP (ap)); + + priv = NM_AP_GET_PRIVATE (ap); + + if (priv->freq != freq) { + priv->freq = freq; + g_object_notify (G_OBJECT (ap), NM_AP_FREQUENCY); + } +} + + +/* + * Get/set functions for max bitrate (in kbit/s) + * + */ +guint32 nm_ap_get_max_bitrate (NMAccessPoint *ap) +{ + guint32 rate; + + g_return_val_if_fail (NM_IS_AP (ap), 0); + + g_object_get (ap, NM_AP_MAX_BITRATE, &rate, NULL); + + return rate; +} + +void +nm_ap_set_max_bitrate (NMAccessPoint *ap, guint32 bitrate) +{ + NMAccessPointPrivate *priv; + + g_return_if_fail (NM_IS_AP (ap)); + + priv = NM_AP_GET_PRIVATE (ap); + + if (priv->max_bitrate != bitrate) { + priv->max_bitrate = bitrate; + g_object_notify (G_OBJECT (ap), NM_AP_MAX_BITRATE); + } +} + +/* + * Get/Set functions to indicate that an access point is 'fake', ie whether + * or not it was created from scan results + */ +gboolean nm_ap_get_fake (const NMAccessPoint *ap) +{ + g_return_val_if_fail (NM_IS_AP (ap), FALSE); + + return NM_AP_GET_PRIVATE (ap)->fake; +} + +void nm_ap_set_fake (NMAccessPoint *ap, gboolean fake) +{ + g_return_if_fail (NM_IS_AP (ap)); + + NM_AP_GET_PRIVATE (ap)->fake = fake; +} + + +/* + * Get/Set functions to indicate whether an AP broadcasts its SSID. + */ +gboolean nm_ap_get_broadcast (NMAccessPoint *ap) +{ + g_return_val_if_fail (NM_IS_AP (ap), TRUE); + + return NM_AP_GET_PRIVATE (ap)->broadcast; +} + + +void nm_ap_set_broadcast (NMAccessPoint *ap, gboolean broadcast) +{ + g_return_if_fail (NM_IS_AP (ap)); + + NM_AP_GET_PRIVATE (ap)->broadcast = broadcast; +} + + +/* + * Get/Set functions for how long ago the AP was last seen in a scan. + * APs older than a certain date are dropped from the list. + * + */ +gint32 +nm_ap_get_last_seen (const NMAccessPoint *ap) +{ + g_return_val_if_fail (NM_IS_AP (ap), FALSE); + + return NM_AP_GET_PRIVATE (ap)->last_seen; +} + +void +nm_ap_set_last_seen (NMAccessPoint *ap, gint32 last_seen) +{ + g_return_if_fail (NM_IS_AP (ap)); + + NM_AP_GET_PRIVATE (ap)->last_seen = last_seen; +} + +gboolean +nm_ap_check_compatible (NMAccessPoint *self, + NMConnection *connection) +{ + NMAccessPointPrivate *priv; + NMSettingWireless *s_wireless; + NMSettingWirelessSecurity *s_wireless_sec; + const char *mode; + const char *band; + const GByteArray *bssid; + guint32 channel; + + g_return_val_if_fail (NM_IS_AP (self), FALSE); + g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE); + + priv = NM_AP_GET_PRIVATE (self); + + s_wireless = nm_connection_get_setting_wireless (connection); + if (s_wireless == NULL) + return FALSE; + + if (!nm_utils_same_ssid (nm_setting_wireless_get_ssid (s_wireless), priv->ssid, TRUE)) + return FALSE; + + bssid = nm_setting_wireless_get_bssid (s_wireless); + if (bssid && memcmp (bssid->data, &priv->address, ETH_ALEN)) + return FALSE; + + mode = nm_setting_wireless_get_mode (s_wireless); + if (mode) { + if (!strcmp (mode, "infrastructure") && (priv->mode != NM_802_11_MODE_INFRA)) + return FALSE; + if (!strcmp (mode, "adhoc") && (priv->mode != NM_802_11_MODE_ADHOC)) + return FALSE; + if ( !strcmp (mode, "ap") + && (priv->mode != NM_802_11_MODE_INFRA || priv->hotspot != TRUE)) + return FALSE; + } + + band = nm_setting_wireless_get_band (s_wireless); + if (band) { + if (!strcmp (band, "a")) { + if (priv->freq < 4915 || priv->freq > 5825) + return FALSE; + } else if (!strcmp (band, "bg")) { + if (priv->freq < 2412 || priv->freq > 2484) + return FALSE; + } + } + + channel = nm_setting_wireless_get_channel (s_wireless); + if (channel) { + guint32 ap_chan = nm_utils_wifi_freq_to_channel (priv->freq); + + if (channel != ap_chan) + return FALSE; + } + + s_wireless_sec = nm_connection_get_setting_wireless_security (connection); + + return nm_setting_wireless_ap_security_compatible (s_wireless, + s_wireless_sec, + nm_ap_get_flags (self), + nm_ap_get_wpa_flags (self), + nm_ap_get_rsn_flags (self), + nm_ap_get_mode (self)); +} + +gboolean +nm_ap_complete_connection (NMAccessPoint *self, + NMConnection *connection, + gboolean lock_bssid, + GError **error) +{ + NMAccessPointPrivate *priv = NM_AP_GET_PRIVATE (self); + + g_return_val_if_fail (connection != NULL, FALSE); + + return nm_ap_utils_complete_connection (priv->ssid, + priv->address.ether_addr_octet, + priv->mode, + priv->flags, + priv->wpa_flags, + priv->rsn_flags, + connection, + lock_bssid, + error); +} + +static gboolean +capabilities_compatible (NM80211ApSecurityFlags a_flags, NM80211ApSecurityFlags b_flags) +{ + if (a_flags == b_flags) + return TRUE; + + /* Make sure there's a common key management method */ + if (!((a_flags & 0x300) & (b_flags & 0x300))) + return FALSE; + + /* Ensure common pairwise ciphers */ + if (!((a_flags & 0xF) & (b_flags & 0xF))) + return FALSE; + + /* Ensure common group ciphers */ + if (!((a_flags & 0xF0) & (b_flags & 0xF0))) + return FALSE; + + return TRUE; +} + +NMAccessPoint * +nm_ap_match_in_list (NMAccessPoint *find_ap, + GSList *ap_list, + gboolean strict_match) +{ + GSList *iter; + + g_return_val_if_fail (find_ap != NULL, NULL); + + for (iter = ap_list; iter; iter = g_slist_next (iter)) { + NMAccessPoint * list_ap = NM_AP (iter->data); + const GByteArray * list_ssid = nm_ap_get_ssid (list_ap); + const struct ether_addr * list_addr = nm_ap_get_address (list_ap); + + const GByteArray * find_ssid = nm_ap_get_ssid (find_ap); + const struct ether_addr * find_addr = nm_ap_get_address (find_ap); + + /* SSID match; if both APs are hiding their SSIDs, + * let matching continue on BSSID and other properties + */ + if ( (!list_ssid && find_ssid) + || (list_ssid && !find_ssid) + || !nm_utils_same_ssid (list_ssid, find_ssid, TRUE)) + continue; + + /* BSSID match */ + if ( (strict_match || nm_ethernet_address_is_valid (find_addr)) + && nm_ethernet_address_is_valid (list_addr) + && memcmp (list_addr->ether_addr_octet, + find_addr->ether_addr_octet, + ETH_ALEN) != 0) { + continue; + } + + /* mode match */ + if (nm_ap_get_mode (list_ap) != nm_ap_get_mode (find_ap)) + continue; + + /* Frequency match */ + if (nm_ap_get_freq (list_ap) != nm_ap_get_freq (find_ap)) + continue; + + /* AP flags */ + if (nm_ap_get_flags (list_ap) != nm_ap_get_flags (find_ap)) + continue; + + if (strict_match) { + if (nm_ap_get_wpa_flags (list_ap) != nm_ap_get_wpa_flags (find_ap)) + continue; + + if (nm_ap_get_rsn_flags (list_ap) != nm_ap_get_rsn_flags (find_ap)) + continue; + } else { + NM80211ApSecurityFlags list_wpa_flags = nm_ap_get_wpa_flags (list_ap); + NM80211ApSecurityFlags find_wpa_flags = nm_ap_get_wpa_flags (find_ap); + NM80211ApSecurityFlags list_rsn_flags = nm_ap_get_rsn_flags (list_ap); + NM80211ApSecurityFlags find_rsn_flags = nm_ap_get_rsn_flags (find_ap); + + /* Just ensure that there is overlap in the capabilities */ + if ( !capabilities_compatible (list_wpa_flags, find_wpa_flags) + && !capabilities_compatible (list_rsn_flags, find_rsn_flags)) + continue; + } + + return list_ap; + } + + return NULL; +} + diff --git a/src/devices/wifi/nm-wifi-ap.h b/src/devices/wifi/nm-wifi-ap.h new file mode 100644 index 00000000..f51fa078 --- /dev/null +++ b/src/devices/wifi/nm-wifi-ap.h @@ -0,0 +1,121 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2004 - 2011 Red Hat, Inc. + * Copyright (C) 2006 - 2008 Novell, Inc. + */ + +#ifndef NM_ACCESS_POINT_H +#define NM_ACCESS_POINT_H + +#include +#include +#include "NetworkManager.h" +#include "nm-connection.h" + +#define NM_TYPE_AP (nm_ap_get_type ()) +#define NM_AP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_AP, NMAccessPoint)) +#define NM_AP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_AP, NMAccessPointClass)) +#define NM_IS_AP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_AP)) +#define NM_IS_AP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_AP)) +#define NM_AP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_AP, NMAccessPointClass)) + +#define NM_AP_FLAGS "flags" +#define NM_AP_WPA_FLAGS "wpa-flags" +#define NM_AP_RSN_FLAGS "rsn-flags" +#define NM_AP_SSID "ssid" +#define NM_AP_FREQUENCY "frequency" +#define NM_AP_HW_ADDRESS "hw-address" +#define NM_AP_MODE "mode" +#define NM_AP_MAX_BITRATE "max-bitrate" +#define NM_AP_STRENGTH "strength" + +typedef struct { + GObject parent; +} NMAccessPoint; + +typedef struct { + GObjectClass parent; + +} NMAccessPointClass; + +GType nm_ap_get_type (void); + +NMAccessPoint * nm_ap_new_from_properties (const char *supplicant_path, + GHashTable *properties); +NMAccessPoint * nm_ap_new_fake_from_connection (NMConnection *connection); +void nm_ap_export_to_dbus (NMAccessPoint *ap); + +const char * nm_ap_get_dbus_path (NMAccessPoint *ap); + +const char * nm_ap_get_supplicant_path (NMAccessPoint *ap); +void nm_ap_set_supplicant_path (NMAccessPoint *ap, + const char *path); + +const GByteArray * nm_ap_get_ssid (const NMAccessPoint * ap); +void nm_ap_set_ssid (NMAccessPoint * ap, const GByteArray * ssid); + +NM80211ApFlags nm_ap_get_flags (NMAccessPoint *ap); +void nm_ap_set_flags (NMAccessPoint *ap, NM80211ApFlags flags); + +NM80211ApSecurityFlags nm_ap_get_wpa_flags (NMAccessPoint *ap); +void nm_ap_set_wpa_flags (NMAccessPoint *ap, NM80211ApSecurityFlags flags); + +NM80211ApSecurityFlags nm_ap_get_rsn_flags (NMAccessPoint *ap); +void nm_ap_set_rsn_flags (NMAccessPoint *ap, NM80211ApSecurityFlags flags); + +const struct ether_addr * nm_ap_get_address (const NMAccessPoint *ap); +void nm_ap_set_address (NMAccessPoint *ap, const struct ether_addr *addr); + +NM80211Mode nm_ap_get_mode (NMAccessPoint *ap); +void nm_ap_set_mode (NMAccessPoint *ap, const NM80211Mode mode); + +gboolean nm_ap_is_hotspot (NMAccessPoint *ap); + +gint8 nm_ap_get_strength (NMAccessPoint *ap); +void nm_ap_set_strength (NMAccessPoint *ap, gint8 strength); + +guint32 nm_ap_get_freq (NMAccessPoint *ap); +void nm_ap_set_freq (NMAccessPoint *ap, guint32 freq); + +guint32 nm_ap_get_max_bitrate (NMAccessPoint *ap); +void nm_ap_set_max_bitrate (NMAccessPoint *ap, guint32 bitrate); + +gboolean nm_ap_get_fake (const NMAccessPoint *ap); +void nm_ap_set_fake (NMAccessPoint *ap, gboolean fake); + +gboolean nm_ap_get_broadcast (NMAccessPoint *ap); +void nm_ap_set_broadcast (NMAccessPoint *ap, gboolean broadcast); + +gint32 nm_ap_get_last_seen (const NMAccessPoint *ap); +void nm_ap_set_last_seen (NMAccessPoint *ap, gint32 last_seen); + +gboolean nm_ap_check_compatible (NMAccessPoint *self, + NMConnection *connection); + +gboolean nm_ap_complete_connection (NMAccessPoint *self, + NMConnection *connection, + gboolean lock_bssid, + GError **error); + +NMAccessPoint * nm_ap_match_in_list (NMAccessPoint *find_ap, + GSList *ap_list, + gboolean strict_match); + +void nm_ap_dump (NMAccessPoint *ap, const char *prefix); + +#endif /* NM_ACCESS_POINT_H */ diff --git a/src/devices/wifi/nm-wifi-enum-types.c b/src/devices/wifi/nm-wifi-enum-types.c new file mode 100644 index 00000000..e914cfd6 --- /dev/null +++ b/src/devices/wifi/nm-wifi-enum-types.c @@ -0,0 +1,58 @@ + + + +/* Generated by glib-mkenums. Do not edit */ + +#include "nm-wifi-enum-types.h" + +#include "nm-device-wifi.h" +#include "nm-wifi-ap.h" +#include "nm-device-olpc-mesh.h" + +GType +nm_wifi_error_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { NM_WIFI_ERROR_CONNECTION_NOT_WIRELESS, "NM_WIFI_ERROR_CONNECTION_NOT_WIRELESS", "ConnectionNotWireless" }, + { NM_WIFI_ERROR_CONNECTION_INVALID, "NM_WIFI_ERROR_CONNECTION_INVALID", "ConnectionInvalid" }, + { NM_WIFI_ERROR_CONNECTION_INCOMPATIBLE, "NM_WIFI_ERROR_CONNECTION_INCOMPATIBLE", "ConnectionIncompatible" }, + { NM_WIFI_ERROR_ACCESS_POINT_NOT_FOUND, "NM_WIFI_ERROR_ACCESS_POINT_NOT_FOUND", "AccessPointNotFound" }, + { NM_WIFI_ERROR_SCAN_NOT_ALLOWED, "NM_WIFI_ERROR_SCAN_NOT_ALLOWED", "ScanNotAllowed" }, + { NM_WIFI_ERROR_AP_MODE_UNSUPPORTED, "NM_WIFI_ERROR_AP_MODE_UNSUPPORTED", "ApModeUnsupported" }, + { NM_WIFI_ERROR_ADHOC_MODE_UNSUPPORTED, "NM_WIFI_ERROR_ADHOC_MODE_UNSUPPORTED", "AdhocModeUnsupported" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("NMWifiError"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +nm_olpc_mesh_error_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { NM_OLPC_MESH_ERROR_CONNECTION_NOT_MESH, "NM_OLPC_MESH_ERROR_CONNECTION_NOT_MESH", "ConnectionNotMesh" }, + { NM_OLPC_MESH_ERROR_CONNECTION_INVALID, "NM_OLPC_MESH_ERROR_CONNECTION_INVALID", "ConnectionInvalid" }, + { NM_OLPC_MESH_ERROR_CONNECTION_INCOMPATIBLE, "NM_OLPC_MESH_ERROR_CONNECTION_INCOMPATIBLE", "ConnectionIncompatible" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("NMOlpcMeshError"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} + + + diff --git a/src/devices/wifi/nm-wifi-enum-types.h b/src/devices/wifi/nm-wifi-enum-types.h new file mode 100644 index 00000000..d4dca5bf --- /dev/null +++ b/src/devices/wifi/nm-wifi-enum-types.h @@ -0,0 +1,21 @@ + + + +/* Generated by glib-mkenums. Do not edit */ + +#ifndef __NM_WIFI_ENUM_TYPES_H__ +#define __NM_WIFI_ENUM_TYPES_H__ + +#include + +G_BEGIN_DECLS +GType nm_wifi_error_get_type (void) G_GNUC_CONST; +#define NM_TYPE_WIFI_ERROR (nm_wifi_error_get_type ()) +GType nm_olpc_mesh_error_get_type (void) G_GNUC_CONST; +#define NM_TYPE_OLPC_MESH_ERROR (nm_olpc_mesh_error_get_type ()) +G_END_DECLS + +#endif /* __NM_WIFI_ENUM_TYPES_H__ */ + + + diff --git a/src/devices/wifi/nm-wifi-factory.c b/src/devices/wifi/nm-wifi-factory.c new file mode 100644 index 00000000..02ad93f4 --- /dev/null +++ b/src/devices/wifi/nm-wifi-factory.c @@ -0,0 +1,89 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2011 - 2014 Red Hat, Inc. + */ + +#include + +#include "nm-device-factory.h" +#include "nm-device-wifi.h" +#include "nm-device-olpc-mesh.h" +#include "nm-settings-connection.h" + +#define NM_TYPE_WIFI_FACTORY (nm_wifi_factory_get_type ()) +#define NM_WIFI_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_WIFI_FACTORY, NMWifiFactory)) + +typedef struct { + GObject parent; +} NMWifiFactory; + +typedef struct { + GObjectClass parent; +} NMWifiFactoryClass; + +static GType nm_wifi_factory_get_type (void); + +static void device_factory_interface_init (NMDeviceFactory *factory_iface); + +G_DEFINE_TYPE_EXTENDED (NMWifiFactory, nm_wifi_factory, G_TYPE_OBJECT, 0, + G_IMPLEMENT_INTERFACE (NM_TYPE_DEVICE_FACTORY, device_factory_interface_init)) + +/**************************************************************************/ + +#define PLUGIN_TYPE NM_DEVICE_TYPE_WIFI + +G_MODULE_EXPORT NMDeviceFactory * +nm_device_factory_create (GError **error) +{ + return (NMDeviceFactory *) g_object_new (NM_TYPE_WIFI_FACTORY, NULL); +} + +G_MODULE_EXPORT NMDeviceType +nm_device_factory_get_device_type (void) +{ + return PLUGIN_TYPE; +} + +/**************************************************************************/ + +static NMDevice * +new_link (NMDeviceFactory *factory, NMPlatformLink *plink, GError **error) +{ + if (plink->type == NM_LINK_TYPE_WIFI) + return nm_device_wifi_new (plink); + else if (plink->type == NM_LINK_TYPE_OLPC_MESH) + return nm_device_olpc_mesh_new (plink); + return NULL; +} + +static void +device_factory_interface_init (NMDeviceFactory *factory_iface) +{ + factory_iface->new_link = new_link; +} + +static void +nm_wifi_factory_init (NMWifiFactory *self) +{ +} + +static void +nm_wifi_factory_class_init (NMWifiFactoryClass *wf_class) +{ +} + diff --git a/src/devices/wifi/tests/Makefile.am b/src/devices/wifi/tests/Makefile.am new file mode 100644 index 00000000..2667c5f1 --- /dev/null +++ b/src/devices/wifi/tests/Makefile.am @@ -0,0 +1,28 @@ +AM_CPPFLAGS = \ + -I$(top_srcdir)/include \ + -I$(top_builddir)/include \ + -I$(top_srcdir)/libnm-util \ + -I$(top_builddir)/libnm-util \ + -I$(top_srcdir)/src/platform \ + -I$(top_srcdir)/src/logging \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/src/devices/wifi \ + -I$(top_builddir)/src \ + -DG_LOG_DOMAIN=\""NetworkManager-wifi"\" \ + -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \ + $(GLIB_CFLAGS) \ + $(DBUS_CFLAGS) + +noinst_PROGRAMS = test-wifi-ap-utils + +test_wifi_ap_utils_SOURCES = \ + test-wifi-ap-utils.c \ + $(srcdir)/../nm-wifi-ap.c \ + $(srcdir)/../nm-wifi-ap.h \ + $(srcdir)/../nm-wifi-ap-utils.c \ + $(srcdir)/../nm-wifi-ap-utils.h + +test_wifi_ap_utils_LDADD = $(top_builddir)/src/libNetworkManager.la + +TESTS = test-wifi-ap-utils + diff --git a/src/devices/wifi/tests/Makefile.in b/src/devices/wifi/tests/Makefile.in new file mode 100644 index 00000000..c0e75eed --- /dev/null +++ b/src/devices/wifi/tests/Makefile.in @@ -0,0 +1,891 @@ +# Makefile.in generated by automake 1.13.4 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +noinst_PROGRAMS = test-wifi-ap-utils$(EXEEXT) +TESTS = test-wifi-ap-utils$(EXEEXT) +subdir = src/devices/wifi/tests +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(top_srcdir)/build-aux/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_lib_readline.m4 \ + $(top_srcdir)/m4/compiler_warnings.m4 \ + $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/gnome-code-coverage.m4 \ + $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ + $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \ + $(top_srcdir)/m4/introspection.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ + $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ + $(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +PROGRAMS = $(noinst_PROGRAMS) +am_test_wifi_ap_utils_OBJECTS = test-wifi-ap-utils.$(OBJEXT) \ + nm-wifi-ap.$(OBJEXT) nm-wifi-ap-utils.$(OBJEXT) +test_wifi_ap_utils_OBJECTS = $(am_test_wifi_ap_utils_OBJECTS) +test_wifi_ap_utils_DEPENDENCIES = \ + $(top_builddir)/src/libNetworkManager.la +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(test_wifi_ap_utils_SOURCES) +DIST_SOURCES = $(test_wifi_ap_utils_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__tty_colors_dummy = \ + mgn= red= grn= lgn= blu= brg= std=; \ + am__color_tests=no +am__tty_colors = { \ + $(am__tty_colors_dummy); \ + if test "X$(AM_COLOR_TESTS)" = Xno; then \ + am__color_tests=no; \ + elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ + am__color_tests=yes; \ + elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ + am__color_tests=yes; \ + fi; \ + if test $$am__color_tests = yes; then \ + red=''; \ + grn=''; \ + lgn=''; \ + blu=''; \ + mgn=''; \ + brg=''; \ + std=''; \ + fi; \ +} +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALL_LINGUAS = @ALL_LINGUAS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CKDB_PATH = @CKDB_PATH@ +CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@ +CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@ +CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIRNAME = @DATADIRNAME@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_100_CFLAGS = @DBUS_GLIB_100_CFLAGS@ +DBUS_GLIB_100_LIBS = @DBUS_GLIB_100_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DHCLIENT_PATH = @DHCLIENT_PATH@ +DHCPCD_PATH = @DHCPCD_PATH@ +DISTRO_NETWORK_SERVICE = @DISTRO_NETWORK_SERVICE@ +DLLTOOL = @DLLTOOL@ +DNSMASQ_PATH = @DNSMASQ_PATH@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GENHTML = @GENHTML@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MAKEFILE = @GLIB_MAKEFILE@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ +GNUTLS_LIBS = @GNUTLS_LIBS@ +GREP = @GREP@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GUDEV_CFLAGS = @GUDEV_CFLAGS@ +GUDEV_LIBS = @GUDEV_LIBS@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_PERL = @INTLTOOL_PERL@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ +INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ +INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ +INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +IPTABLES_PATH = @IPTABLES_PATH@ +IWMX_SDK_CFLAGS = @IWMX_SDK_CFLAGS@ +IWMX_SDK_LIBS = @IWMX_SDK_LIBS@ +KERNEL_FIRMWARE_DIR = @KERNEL_FIRMWARE_DIR@ +LCOV = @LCOV@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDL = @LIBDL@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBM = @LIBM@ +LIBNDP_CFLAGS = @LIBNDP_CFLAGS@ +LIBNDP_LIBS = @LIBNDP_LIBS@ +LIBNL_CFLAGS = @LIBNL_CFLAGS@ +LIBNL_LIBS = @LIBNL_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@ +LIBSOUP_LIBS = @LIBSOUP_LIBS@ +LIBTEAMDCTL_CFLAGS = @LIBTEAMDCTL_CFLAGS@ +LIBTEAMDCTL_LIBS = @LIBTEAMDCTL_LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MM_GLIB_CFLAGS = @MM_GLIB_CFLAGS@ +MM_GLIB_LIBS = @MM_GLIB_LIBS@ +MOC = @MOC@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NEWT_CFLAGS = @NEWT_CFLAGS@ +NEWT_LIBS = @NEWT_LIBS@ +NM = @NM@ +NMEDIT = @NMEDIT@ +NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ +NM_MICRO_VERSION = @NM_MICRO_VERSION@ +NM_MINOR_VERSION = @NM_MINOR_VERSION@ +NM_MODIFY_SYSTEM_POLICY = @NM_MODIFY_SYSTEM_POLICY@ +NM_VERSION = @NM_VERSION@ +NSS_CFLAGS = @NSS_CFLAGS@ +NSS_LIBS = @NSS_LIBS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +POLKIT_CFLAGS = @POLKIT_CFLAGS@ +POLKIT_LIBS = @POLKIT_LIBS@ +POSUB = @POSUB@ +PPPD_PATH = @PPPD_PATH@ +PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@ +PPPOE_PATH = @PPPOE_PATH@ +QT_CFLAGS = @QT_CFLAGS@ +QT_LIBS = @QT_LIBS@ +RANLIB = @RANLIB@ +READLINE_LIBS = @READLINE_LIBS@ +SED = @SED@ +SELINUX_CFLAGS = @SELINUX_CFLAGS@ +SELINUX_LIBS = @SELINUX_LIBS@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SYSTEMD_200_CFLAGS = @SYSTEMD_200_CFLAGS@ +SYSTEMD_200_LIBS = @SYSTEMD_200_LIBS@ +SYSTEMD_INHIBIT_CFLAGS = @SYSTEMD_INHIBIT_CFLAGS@ +SYSTEMD_INHIBIT_LIBS = @SYSTEMD_INHIBIT_LIBS@ +SYSTEMD_LOGIN_CFLAGS = @SYSTEMD_LOGIN_CFLAGS@ +SYSTEMD_LOGIN_LIBS = @SYSTEMD_LOGIN_LIBS@ +SYSTEM_CA_PATH = @SYSTEM_CA_PATH@ +UDEV_BASE_DIR = @UDEV_BASE_DIR@ +USE_NLS = @USE_NLS@ +UUID_CFLAGS = @UUID_CFLAGS@ +UUID_LIBS = @UUID_LIBS@ +VALGRIND_RULES = @VALGRIND_RULES@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ +VERSION = @VERSION@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +intltool__v_merge_options_ = @intltool__v_merge_options_@ +intltool__v_merge_options_0 = @intltool__v_merge_options_0@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +nmbinary = @nmbinary@ +nmconfdir = @nmconfdir@ +nmdatadir = @nmdatadir@ +nmrundir = @nmrundir@ +nmstatedir = @nmstatedir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +with_dhclient = @with_dhclient@ +with_dhcpcd = @with_dhcpcd@ +with_netconfig = @with_netconfig@ +with_resolvconf = @with_resolvconf@ +with_valgrind = @with_valgrind@ +AM_CPPFLAGS = \ + -I$(top_srcdir)/include \ + -I$(top_builddir)/include \ + -I$(top_srcdir)/libnm-util \ + -I$(top_builddir)/libnm-util \ + -I$(top_srcdir)/src/platform \ + -I$(top_srcdir)/src/logging \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/src/devices/wifi \ + -I$(top_builddir)/src \ + -DG_LOG_DOMAIN=\""NetworkManager-wifi"\" \ + -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \ + $(GLIB_CFLAGS) \ + $(DBUS_CFLAGS) + +test_wifi_ap_utils_SOURCES = \ + test-wifi-ap-utils.c \ + $(srcdir)/../nm-wifi-ap.c \ + $(srcdir)/../nm-wifi-ap.h \ + $(srcdir)/../nm-wifi-ap-utils.c \ + $(srcdir)/../nm-wifi-ap-utils.h + +test_wifi_ap_utils_LDADD = $(top_builddir)/src/libNetworkManager.la +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/devices/wifi/tests/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/devices/wifi/tests/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +test-wifi-ap-utils$(EXEEXT): $(test_wifi_ap_utils_OBJECTS) $(test_wifi_ap_utils_DEPENDENCIES) $(EXTRA_test_wifi_ap_utils_DEPENDENCIES) + @rm -f test-wifi-ap-utils$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_wifi_ap_utils_OBJECTS) $(test_wifi_ap_utils_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-wifi-ap-utils.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-wifi-ap.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-wifi-ap-utils.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +nm-wifi-ap.o: $(srcdir)/../nm-wifi-ap.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-wifi-ap.o -MD -MP -MF $(DEPDIR)/nm-wifi-ap.Tpo -c -o nm-wifi-ap.o `test -f '$(srcdir)/../nm-wifi-ap.c' || echo '$(srcdir)/'`$(srcdir)/../nm-wifi-ap.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-wifi-ap.Tpo $(DEPDIR)/nm-wifi-ap.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../nm-wifi-ap.c' object='nm-wifi-ap.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-wifi-ap.o `test -f '$(srcdir)/../nm-wifi-ap.c' || echo '$(srcdir)/'`$(srcdir)/../nm-wifi-ap.c + +nm-wifi-ap.obj: $(srcdir)/../nm-wifi-ap.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-wifi-ap.obj -MD -MP -MF $(DEPDIR)/nm-wifi-ap.Tpo -c -o nm-wifi-ap.obj `if test -f '$(srcdir)/../nm-wifi-ap.c'; then $(CYGPATH_W) '$(srcdir)/../nm-wifi-ap.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../nm-wifi-ap.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-wifi-ap.Tpo $(DEPDIR)/nm-wifi-ap.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../nm-wifi-ap.c' object='nm-wifi-ap.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-wifi-ap.obj `if test -f '$(srcdir)/../nm-wifi-ap.c'; then $(CYGPATH_W) '$(srcdir)/../nm-wifi-ap.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../nm-wifi-ap.c'; fi` + +nm-wifi-ap-utils.o: $(srcdir)/../nm-wifi-ap-utils.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-wifi-ap-utils.o -MD -MP -MF $(DEPDIR)/nm-wifi-ap-utils.Tpo -c -o nm-wifi-ap-utils.o `test -f '$(srcdir)/../nm-wifi-ap-utils.c' || echo '$(srcdir)/'`$(srcdir)/../nm-wifi-ap-utils.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-wifi-ap-utils.Tpo $(DEPDIR)/nm-wifi-ap-utils.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../nm-wifi-ap-utils.c' object='nm-wifi-ap-utils.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-wifi-ap-utils.o `test -f '$(srcdir)/../nm-wifi-ap-utils.c' || echo '$(srcdir)/'`$(srcdir)/../nm-wifi-ap-utils.c + +nm-wifi-ap-utils.obj: $(srcdir)/../nm-wifi-ap-utils.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-wifi-ap-utils.obj -MD -MP -MF $(DEPDIR)/nm-wifi-ap-utils.Tpo -c -o nm-wifi-ap-utils.obj `if test -f '$(srcdir)/../nm-wifi-ap-utils.c'; then $(CYGPATH_W) '$(srcdir)/../nm-wifi-ap-utils.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../nm-wifi-ap-utils.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-wifi-ap-utils.Tpo $(DEPDIR)/nm-wifi-ap-utils.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../nm-wifi-ap-utils.c' object='nm-wifi-ap-utils.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-wifi-ap-utils.obj `if test -f '$(srcdir)/../nm-wifi-ap-utils.c'; then $(CYGPATH_W) '$(srcdir)/../nm-wifi-ap-utils.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../nm-wifi-ap-utils.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +check-TESTS: $(TESTS) + @failed=0; all=0; xfail=0; xpass=0; skip=0; \ + srcdir=$(srcdir); export srcdir; \ + list=' $(TESTS) '; \ + $(am__tty_colors); \ + if test -n "$$list"; then \ + for tst in $$list; do \ + if test -f ./$$tst; then dir=./; \ + elif test -f $$tst; then dir=; \ + else dir="$(srcdir)/"; fi; \ + if $(TESTS_ENVIRONMENT) $${dir}$$tst $(AM_TESTS_FD_REDIRECT); then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$tst[\ \ ]*) \ + xpass=`expr $$xpass + 1`; \ + failed=`expr $$failed + 1`; \ + col=$$red; res=XPASS; \ + ;; \ + *) \ + col=$$grn; res=PASS; \ + ;; \ + esac; \ + elif test $$? -ne 77; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$tst[\ \ ]*) \ + xfail=`expr $$xfail + 1`; \ + col=$$lgn; res=XFAIL; \ + ;; \ + *) \ + failed=`expr $$failed + 1`; \ + col=$$red; res=FAIL; \ + ;; \ + esac; \ + else \ + skip=`expr $$skip + 1`; \ + col=$$blu; res=SKIP; \ + fi; \ + echo "$${col}$$res$${std}: $$tst"; \ + done; \ + if test "$$all" -eq 1; then \ + tests="test"; \ + All=""; \ + else \ + tests="tests"; \ + All="All "; \ + fi; \ + if test "$$failed" -eq 0; then \ + if test "$$xfail" -eq 0; then \ + banner="$$All$$all $$tests passed"; \ + else \ + if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \ + banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \ + fi; \ + else \ + if test "$$xpass" -eq 0; then \ + banner="$$failed of $$all $$tests failed"; \ + else \ + if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \ + banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \ + fi; \ + fi; \ + dashes="$$banner"; \ + skipped=""; \ + if test "$$skip" -ne 0; then \ + if test "$$skip" -eq 1; then \ + skipped="($$skip test was not run)"; \ + else \ + skipped="($$skip tests were not run)"; \ + fi; \ + test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$skipped"; \ + fi; \ + report=""; \ + if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ + report="Please report to $(PACKAGE_BUGREPORT)"; \ + test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$report"; \ + fi; \ + dashes=`echo "$$dashes" | sed s/./=/g`; \ + if test "$$failed" -eq 0; then \ + col="$$grn"; \ + else \ + col="$$red"; \ + fi; \ + echo "$${col}$$dashes$${std}"; \ + echo "$${col}$$banner$${std}"; \ + test -z "$$skipped" || echo "$${col}$$skipped$${std}"; \ + test -z "$$report" || echo "$${col}$$report$${std}"; \ + echo "$${col}$$dashes$${std}"; \ + test "$$failed" -eq 0; \ + else :; fi + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: check-am install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ + clean-generic clean-libtool clean-noinstPROGRAMS cscopelist-am \ + ctags ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/devices/wifi/tests/test-wifi-ap-utils.c b/src/devices/wifi/tests/test-wifi-ap-utils.c new file mode 100644 index 00000000..36d58f2a --- /dev/null +++ b/src/devices/wifi/tests/test-wifi-ap-utils.c @@ -0,0 +1,1545 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2011 Red Hat, Inc. + * + */ + +#include +#include + +#include "nm-wifi-ap-utils.h" +#include "nm-dbus-glib-types.h" + +#include "nm-setting-connection.h" +#include "nm-setting-wireless.h" +#include "nm-setting-wireless-security.h" +#include "nm-setting-8021x.h" + +#define DEBUG 1 + +/*******************************************/ + +#define COMPARE(src, expected, success, error, edomain, ecode) \ +{ \ + if (expected) { \ + if (!success) { \ + g_assert (error != NULL); \ + g_warning ("Failed to complete connection: (%d) %s", error->code, error->message); \ + } \ + g_assert (success == TRUE); \ + g_assert (error == NULL); \ +\ + success = nm_connection_compare (src, expected, NM_SETTING_COMPARE_FLAG_EXACT); \ + if (success == FALSE && DEBUG) { \ + g_message ("\n- COMPLETED ---------------------------------\n"); \ + nm_connection_dump (src); \ + g_message ("+ EXPECTED ++++++++++++++++++++++++++++++++++++\n"); \ + nm_connection_dump (expected); \ + g_message ("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"); \ + } \ + g_assert (success == TRUE); \ + } else { \ + if (success) { \ + g_message ("\n- COMPLETED ---------------------------------\n"); \ + nm_connection_dump (src); \ + } \ + g_assert (success == FALSE); \ + g_assert_error (error, edomain, ecode); \ + } \ + \ + g_clear_error (&error); \ +} + +static gboolean +complete_connection (const char *ssid, + const guint8 bssid[ETH_ALEN], + NM80211Mode mode, + guint32 flags, + guint32 wpa_flags, + guint32 rsn_flags, + gboolean lock_bssid, + NMConnection *src, + GError **error) +{ + GByteArray *tmp; + gboolean success; + NMSettingWireless *s_wifi; + + /* Add a wifi setting if one doesn't exist */ + s_wifi = nm_connection_get_setting_wireless (src); + if (!s_wifi) { + s_wifi = (NMSettingWireless *) nm_setting_wireless_new (); + nm_connection_add_setting (src, NM_SETTING (s_wifi)); + } + + tmp = g_byte_array_sized_new (strlen (ssid)); + g_byte_array_append (tmp, (const guint8 *) ssid, strlen (ssid)); + + success = nm_ap_utils_complete_connection (tmp, + bssid, + mode, + flags, + wpa_flags, + rsn_flags, + src, + lock_bssid, + error); + g_byte_array_free (tmp, TRUE); + return success; +} + +typedef struct { + const char *key; + const char *str; + guint32 uint; +} KeyData; + +static void +set_items (NMSetting *setting, const KeyData *items) +{ + const KeyData *item; + GParamSpec *pspec; + GByteArray *tmp; + + for (item = items; item && item->key; item++) { + g_assert (item->key); + pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (setting), item->key); + g_assert (pspec); + + if (pspec->value_type == G_TYPE_STRING) { + g_assert (item->uint == 0); + if (item->str) + g_object_set (G_OBJECT (setting), item->key, item->str, NULL); + } else if (pspec->value_type == G_TYPE_UINT) { + g_assert (item->str == NULL); + g_object_set (G_OBJECT (setting), item->key, item->uint, NULL); + } else if (pspec->value_type == G_TYPE_INT) { + gint foo = (gint) item->uint; + + g_assert (item->str == NULL); + g_object_set (G_OBJECT (setting), item->key, foo, NULL); + } else if (pspec->value_type == G_TYPE_BOOLEAN) { + gboolean foo = !! (item->uint); + + g_assert (item->str == NULL); + g_object_set (G_OBJECT (setting), item->key, foo, NULL); + } else if (pspec->value_type == DBUS_TYPE_G_UCHAR_ARRAY) { + g_assert (item->str); + tmp = g_byte_array_sized_new (strlen (item->str)); + g_byte_array_append (tmp, (const guint8 *) item->str, strlen (item->str)); + g_object_set (G_OBJECT (setting), item->key, tmp, NULL); + g_byte_array_free (tmp, TRUE); + } else { + /* Special types, check based on property name */ + if (!strcmp (item->key, NM_SETTING_WIRELESS_SECURITY_PROTO)) + nm_setting_wireless_security_add_proto (NM_SETTING_WIRELESS_SECURITY (setting), item->str); + else if (!strcmp (item->key, NM_SETTING_WIRELESS_SECURITY_PAIRWISE)) + nm_setting_wireless_security_add_pairwise (NM_SETTING_WIRELESS_SECURITY (setting), item->str); + else if (!strcmp (item->key, NM_SETTING_WIRELESS_SECURITY_GROUP)) + nm_setting_wireless_security_add_group (NM_SETTING_WIRELESS_SECURITY (setting), item->str); + else if (!strcmp (item->key, NM_SETTING_802_1X_EAP)) + nm_setting_802_1x_add_eap_method (NM_SETTING_802_1X (setting), item->str); + } + } +} + +static NMSettingWireless * +fill_wifi_empty (NMConnection *connection) +{ + NMSettingWireless *s_wifi; + + s_wifi = nm_connection_get_setting_wireless (connection); + if (!s_wifi) { + s_wifi = (NMSettingWireless *) nm_setting_wireless_new (); + nm_connection_add_setting (connection, NM_SETTING (s_wifi)); + } + return s_wifi; +} + +static NMSettingWireless * +fill_wifi (NMConnection *connection, const KeyData items[]) +{ + NMSettingWireless *s_wifi; + + s_wifi = nm_connection_get_setting_wireless (connection); + if (!s_wifi) { + s_wifi = (NMSettingWireless *) nm_setting_wireless_new (); + nm_connection_add_setting (connection, NM_SETTING (s_wifi)); + } + + set_items (NM_SETTING (s_wifi), items); + return s_wifi; +} + +static NMSettingWirelessSecurity * +fill_wsec (NMConnection *connection, const KeyData items[]) +{ + NMSettingWirelessSecurity *s_wsec; + + s_wsec = nm_connection_get_setting_wireless_security (connection); + if (!s_wsec) { + s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new (); + nm_connection_add_setting (connection, NM_SETTING (s_wsec)); + } + + set_items (NM_SETTING (s_wsec), items); + return s_wsec; +} + +static NMSetting8021x * +fill_8021x (NMConnection *connection, const KeyData items[]) +{ + NMSetting8021x *s_8021x; + + s_8021x = nm_connection_get_setting_802_1x (connection); + if (!s_8021x) { + s_8021x = (NMSetting8021x *) nm_setting_802_1x_new (); + nm_connection_add_setting (connection, NM_SETTING (s_8021x)); + } + + set_items (NM_SETTING (s_8021x), items); + return s_8021x; +} + +static NMConnection * +create_basic (const char *ssid, + const guint8 *bssid, + NM80211Mode mode) +{ + NMConnection *connection; + NMSettingWireless *s_wifi = NULL; + GByteArray *tmp; + + connection = nm_connection_new (); + + s_wifi = (NMSettingWireless *) nm_setting_wireless_new (); + nm_connection_add_setting (connection, NM_SETTING (s_wifi)); + + /* SSID */ + tmp = g_byte_array_sized_new (strlen (ssid)); + g_byte_array_append (tmp, (const guint8 *) ssid, strlen (ssid)); + g_object_set (G_OBJECT (s_wifi), NM_SETTING_WIRELESS_SSID, tmp, NULL); + g_byte_array_free (tmp, TRUE); + + /* BSSID */ + if (bssid) { + tmp = g_byte_array_sized_new (ETH_ALEN); + g_byte_array_append (tmp, bssid, ETH_ALEN); + g_object_set (G_OBJECT (s_wifi), NM_SETTING_WIRELESS_BSSID, tmp, NULL); + g_byte_array_free (tmp, TRUE); + } + + if (mode == NM_802_11_MODE_INFRA) + g_object_set (G_OBJECT (s_wifi), NM_SETTING_WIRELESS_MODE, "infrastructure", NULL); + else if (mode == NM_802_11_MODE_ADHOC) + g_object_set (G_OBJECT (s_wifi), NM_SETTING_WIRELESS_MODE, "adhoc", NULL); + else + g_assert_not_reached (); + + return connection; +} + +/*******************************************/ + +static void +test_lock_bssid (void) +{ + NMConnection *src, *expected; + const guint8 bssid[ETH_ALEN] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 }; + const char *ssid = "blahblah"; + gboolean success; + GError *error = NULL; + + src = nm_connection_new (); + success = complete_connection (ssid, bssid, + NM_802_11_MODE_INFRA, NM_802_11_AP_FLAGS_NONE, + NM_802_11_AP_SEC_NONE, NM_802_11_AP_SEC_NONE, + TRUE, + src, &error); + expected = create_basic (ssid, bssid, NM_802_11_MODE_INFRA); + COMPARE (src, expected, success, error, 0, 0); + + g_object_unref (src); + g_object_unref (expected); +} + +/*******************************************/ + +static void +test_open_ap_empty_connection (void) +{ + NMConnection *src, *expected; + const guint8 bssid[ETH_ALEN] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 }; + const char *ssid = "blahblah"; + gboolean success; + GError *error = NULL; + + /* Test that an empty source connection is correctly filled with the + * SSID and Infra modes of the given AP details. + */ + + src = nm_connection_new (); + success = complete_connection (ssid, bssid, + NM_802_11_MODE_INFRA, NM_802_11_AP_FLAGS_NONE, + NM_802_11_AP_SEC_NONE, NM_802_11_AP_SEC_NONE, + FALSE, + src, &error); + expected = create_basic (ssid, NULL, NM_802_11_MODE_INFRA); + COMPARE (src, expected, success, error, 0, 0); + + g_object_unref (src); + g_object_unref (expected); +} + +/*******************************************/ + +static void +test_open_ap_leap_connection_1 (gconstpointer add_wifi) +{ + NMConnection *src; + const guint8 bssid[ETH_ALEN] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 }; + const KeyData src_wsec[] = { { NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME, "Bill Smith", 0 }, { NULL } }; + gboolean success; + GError *error = NULL; + + /* Test that a basic connection filled with a LEAP username is + * rejected when completion is attempted with an open AP. LEAP requires + * the AP to have the Privacy bit set. + */ + + src = nm_connection_new (); + if (add_wifi) + fill_wifi_empty (src); + fill_wsec (src, src_wsec); + + success = complete_connection ("blahblah", bssid, + NM_802_11_MODE_INFRA, NM_802_11_AP_FLAGS_NONE, + NM_802_11_AP_SEC_NONE, NM_802_11_AP_SEC_NONE, + FALSE, + src, &error); + /* We expect failure */ + COMPARE (src, NULL, success, error, NM_SETTING_WIRELESS_SECURITY_ERROR, NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY); + + g_object_unref (src); +} + +/*******************************************/ + +static void +test_open_ap_leap_connection_2 (void) +{ + NMConnection *src; + const guint8 bssid[ETH_ALEN] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 }; + const KeyData src_wsec[] = { { NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x", 0 }, { NULL } }; + gboolean success; + GError *error = NULL; + + /* Test that a basic connection specifying IEEE8021x security (ie, Dynamic + * WEP or LEAP) is rejected when completion is attempted with an open AP. + */ + + src = nm_connection_new (); + fill_wifi_empty (src); + fill_wsec (src, src_wsec); + + success = complete_connection ("blahblah", bssid, + NM_802_11_MODE_INFRA, NM_802_11_AP_FLAGS_NONE, + NM_802_11_AP_SEC_NONE, NM_802_11_AP_SEC_NONE, + FALSE, + src, &error); + /* We expect failure */ + COMPARE (src, NULL, success, error, NM_SETTING_WIRELESS_SECURITY_ERROR, NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY); + + g_object_unref (src); +} + +/*******************************************/ + +static void +test_open_ap_wep_connection (gconstpointer add_wifi) +{ + NMConnection *src; + const guint8 bssid[ETH_ALEN] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 }; + const KeyData src_wsec[] = { + { NM_SETTING_WIRELESS_SECURITY_WEP_KEY0, "11111111111111111111111111", 0 }, + { NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX, NULL, 0 }, + { NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "open", 0 }, + { NULL } }; + gboolean success; + GError *error = NULL; + + /* Test that a static WEP connection is rejected when completion is + * attempted with an open AP. + */ + + src = nm_connection_new (); + if (add_wifi) + fill_wifi_empty (src); + fill_wsec (src, src_wsec); + success = complete_connection ("blahblah", bssid, + NM_802_11_MODE_INFRA, NM_802_11_AP_FLAGS_NONE, + NM_802_11_AP_SEC_NONE, NM_802_11_AP_SEC_NONE, + FALSE, + src, &error); + /* We expect failure */ + COMPARE (src, NULL, success, error, NM_SETTING_WIRELESS_SECURITY_ERROR, NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY); + + g_object_unref (src); +} + +/*******************************************/ + +static void +test_ap_wpa_psk_connection_base (const char *key_mgmt, + const char *auth_alg, + guint32 flags, + guint32 wpa_flags, + guint32 rsn_flags, + gboolean add_wifi, + NMConnection *expected) +{ + NMConnection *src; + const char *ssid = "blahblah"; + const guint8 bssid[ETH_ALEN] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 }; + const KeyData exp_wifi[] = { + { NM_SETTING_WIRELESS_SSID, ssid, 0 }, + { NM_SETTING_WIRELESS_MODE, "infrastructure", 0 }, + { NULL } }; + const KeyData both_wsec[] = { + { NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, key_mgmt, 0 }, + { NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, auth_alg, 0 }, + { NM_SETTING_WIRELESS_SECURITY_PSK, "asdfasdfasdfasdfasdfafs", 0 }, + { NULL } }; + gboolean success; + GError *error = NULL; + + src = nm_connection_new (); + if (add_wifi) + fill_wifi_empty (src); + fill_wsec (src, both_wsec); + success = complete_connection (ssid, bssid, NM_802_11_MODE_INFRA, + flags, wpa_flags, rsn_flags, + FALSE, src, &error); + if (expected) { + fill_wifi (expected, exp_wifi); + fill_wsec (expected, both_wsec); + } + COMPARE (src, expected, success, error, NM_SETTING_WIRELESS_SECURITY_ERROR, NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY); + + g_object_unref (src); +} + +static void +test_open_ap_wpa_psk_connection_1 (void) +{ + /* Test that a WPA-PSK connection filling only the PSK itself and *not* + * filling the wifi setting is rejected when completion is attempted with + * an open AP. + */ + test_ap_wpa_psk_connection_base (NULL, NULL, + NM_802_11_AP_FLAGS_NONE, + NM_802_11_AP_SEC_NONE, + NM_802_11_AP_SEC_NONE, + FALSE, NULL); +} + +static void +test_open_ap_wpa_psk_connection_2 (void) +{ + /* Test that a WPA-PSK connection filling only the PSK itself and also + * filling the wifi setting is rejected when completion is attempted with + * an open AP. + */ + test_ap_wpa_psk_connection_base (NULL, NULL, + NM_802_11_AP_FLAGS_NONE, + NM_802_11_AP_SEC_NONE, + NM_802_11_AP_SEC_NONE, + TRUE, NULL); +} + +static void +test_open_ap_wpa_psk_connection_3 (void) +{ + /* Test that a WPA-PSK connection filling the PSK and setting the auth alg + * to 'open' is rejected when completion is attempted with an open AP. + */ + test_ap_wpa_psk_connection_base (NULL, "open", + NM_802_11_AP_FLAGS_NONE, + NM_802_11_AP_SEC_NONE, + NM_802_11_AP_SEC_NONE, + FALSE, NULL); +} + +static void +test_open_ap_wpa_psk_connection_4 (void) +{ + /* Test that a WPA-PSK connection filling the PSK and setting the auth alg + * to 'shared' is rejected when completion is attempted with an open AP. + * Shared auth cannot be used with WPA. + */ + test_ap_wpa_psk_connection_base (NULL, "shared", + NM_802_11_AP_FLAGS_NONE, + NM_802_11_AP_SEC_NONE, + NM_802_11_AP_SEC_NONE, + FALSE, NULL); +} + +static void +test_open_ap_wpa_psk_connection_5 (void) +{ + /* Test that a WPA-PSK connection filling the PSK, the auth algorithm, and + * key management is rejected when completion is attempted with an open AP. + */ + test_ap_wpa_psk_connection_base ("wpa-psk", "open", + NM_802_11_AP_FLAGS_NONE, + NM_802_11_AP_SEC_NONE, + NM_802_11_AP_SEC_NONE, + FALSE, NULL); +} + +/*******************************************/ + +static void +test_ap_wpa_eap_connection_base (const char *key_mgmt, + const char *auth_alg, + guint32 flags, + guint32 wpa_flags, + guint32 rsn_flags, + gboolean add_wifi, + guint error_domain, + guint error_code) +{ + NMConnection *src; + const guint8 bssid[ETH_ALEN] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 }; + const KeyData src_empty[] = { { NULL } }; + const KeyData src_wsec[] = { + { NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, key_mgmt, 0 }, + { NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, auth_alg, 0 }, + { NULL } }; + gboolean success; + GError *error = NULL; + + src = nm_connection_new (); + if (add_wifi) + fill_wifi_empty (src); + fill_wsec (src, src_wsec); + fill_8021x (src, src_empty); + success = complete_connection ("blahblah", bssid, NM_802_11_MODE_INFRA, + flags, wpa_flags, rsn_flags, + FALSE, src, &error); + /* Failure expected */ + COMPARE (src, NULL, success, error, error_domain, error_code); + + g_object_unref (src); +} + +enum { + IDX_NONE = 0, + IDX_OPEN, + IDX_PRIV, + IDX_WPA_PSK_PTKIP_GTKIP, + IDX_WPA_PSK_PTKIP_PCCMP_GTKIP, + IDX_WPA_RSN_PSK_PTKIP_PCCMP_GTKIP, + IDX_WPA_RSN_PSK_PCCMP_GCCMP, + IDX_RSN_PSK_PCCMP_GCCMP, + IDX_RSN_PSK_PTKIP_PCCMP_GTKIP, + IDX_WPA_8021X, + IDX_RSN_8021X, +}; + +static guint32 +flags_for_idx (guint32 idx) +{ + if (idx == IDX_OPEN) + return NM_802_11_AP_FLAGS_NONE; + else if ( idx == IDX_PRIV + || idx == IDX_WPA_PSK_PTKIP_GTKIP + || idx == IDX_WPA_PSK_PTKIP_PCCMP_GTKIP + || idx == IDX_RSN_PSK_PCCMP_GCCMP + || idx == IDX_RSN_PSK_PTKIP_PCCMP_GTKIP + || idx == IDX_WPA_RSN_PSK_PTKIP_PCCMP_GTKIP + || idx == IDX_WPA_RSN_PSK_PCCMP_GCCMP + || idx == IDX_WPA_8021X + || idx == IDX_RSN_8021X) + return NM_802_11_AP_FLAGS_PRIVACY; + else + g_assert_not_reached (); +} + +static guint32 +wpa_flags_for_idx (guint32 idx) +{ + if (idx == IDX_OPEN || idx == IDX_PRIV || idx == IDX_RSN_8021X + || idx == IDX_RSN_PSK_PCCMP_GCCMP || idx == IDX_RSN_PSK_PTKIP_PCCMP_GTKIP) + return NM_802_11_AP_SEC_NONE; + else if (idx == IDX_WPA_PSK_PTKIP_GTKIP) + return NM_802_11_AP_SEC_PAIR_TKIP | NM_802_11_AP_SEC_GROUP_TKIP | NM_802_11_AP_SEC_KEY_MGMT_PSK; + else if (idx == IDX_WPA_RSN_PSK_PTKIP_PCCMP_GTKIP) + return NM_802_11_AP_SEC_PAIR_TKIP | NM_802_11_AP_SEC_PAIR_CCMP | NM_802_11_AP_SEC_GROUP_TKIP | NM_802_11_AP_SEC_KEY_MGMT_PSK; + else if (IDX_WPA_RSN_PSK_PCCMP_GCCMP) + return NM_802_11_AP_SEC_PAIR_CCMP | NM_802_11_AP_SEC_GROUP_CCMP | NM_802_11_AP_SEC_KEY_MGMT_PSK; + else if (idx == IDX_WPA_8021X) + return NM_802_11_AP_SEC_PAIR_TKIP | NM_802_11_AP_SEC_GROUP_TKIP | NM_802_11_AP_SEC_KEY_MGMT_802_1X; + else + g_assert_not_reached (); +} + +static guint32 +rsn_flags_for_idx (guint32 idx) +{ + if (idx == IDX_OPEN || idx == IDX_PRIV || idx == IDX_WPA_8021X + || idx == IDX_WPA_PSK_PTKIP_GTKIP || idx == IDX_WPA_PSK_PTKIP_PCCMP_GTKIP) + return NM_802_11_AP_SEC_NONE; + else if (idx == IDX_RSN_PSK_PCCMP_GCCMP) + return NM_802_11_AP_SEC_PAIR_CCMP | NM_802_11_AP_SEC_GROUP_CCMP | NM_802_11_AP_SEC_KEY_MGMT_PSK; + else if (idx == IDX_RSN_PSK_PTKIP_PCCMP_GTKIP) + return NM_802_11_AP_SEC_PAIR_TKIP | NM_802_11_AP_SEC_PAIR_CCMP | NM_802_11_AP_SEC_GROUP_TKIP | NM_802_11_AP_SEC_KEY_MGMT_PSK; + else if (idx == IDX_WPA_RSN_PSK_PTKIP_PCCMP_GTKIP) + return NM_802_11_AP_SEC_PAIR_TKIP | NM_802_11_AP_SEC_PAIR_CCMP | NM_802_11_AP_SEC_GROUP_TKIP | NM_802_11_AP_SEC_KEY_MGMT_PSK; + else if (idx == IDX_WPA_RSN_PSK_PCCMP_GCCMP) + return NM_802_11_AP_SEC_PAIR_CCMP | NM_802_11_AP_SEC_GROUP_CCMP | NM_802_11_AP_SEC_KEY_MGMT_PSK; + else if (idx == IDX_RSN_8021X) + return NM_802_11_AP_SEC_PAIR_CCMP | NM_802_11_AP_SEC_GROUP_CCMP | NM_802_11_AP_SEC_KEY_MGMT_802_1X; + else + g_assert_not_reached (); +} + +static guint32 +error_domain_for_idx (guint32 idx, guint num) +{ + if (idx == IDX_OPEN) + return NM_SETTING_WIRELESS_SECURITY_ERROR; + else if (idx == IDX_PRIV) { + if (num <= 3) + return NM_SETTING_802_1X_ERROR; + else + return NM_SETTING_WIRELESS_SECURITY_ERROR; + } else if (idx == IDX_WPA_PSK_PTKIP_GTKIP || idx == IDX_WPA_PSK_PTKIP_PCCMP_GTKIP + || idx == IDX_WPA_RSN_PSK_PCCMP_GCCMP || idx == IDX_WPA_RSN_PSK_PTKIP_PCCMP_GTKIP + || idx == IDX_RSN_PSK_PTKIP_PCCMP_GTKIP || idx == IDX_RSN_PSK_PCCMP_GCCMP) + return NM_SETTING_WIRELESS_SECURITY_ERROR; + else + g_assert_not_reached (); +} + +static guint32 +error_code_for_idx (guint32 idx, guint num) +{ + if (idx == IDX_OPEN) + return NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY; + else if (idx == IDX_PRIV) { + if (num <= 3) + return NM_SETTING_802_1X_ERROR_MISSING_PROPERTY; + else + return NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY; + } else if (idx == IDX_WPA_PSK_PTKIP_GTKIP || idx == IDX_WPA_PSK_PTKIP_PCCMP_GTKIP + || idx == IDX_WPA_RSN_PSK_PCCMP_GCCMP || idx == IDX_WPA_RSN_PSK_PTKIP_PCCMP_GTKIP + || idx == IDX_RSN_PSK_PTKIP_PCCMP_GTKIP || idx == IDX_RSN_PSK_PCCMP_GCCMP) + return NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY; + else + g_assert_not_reached (); +} + +static void +test_ap_wpa_eap_connection_1 (gconstpointer data) +{ + guint idx = GPOINTER_TO_UINT (data); + + test_ap_wpa_eap_connection_base (NULL, NULL, + flags_for_idx (idx), + wpa_flags_for_idx (idx), + rsn_flags_for_idx (idx), + FALSE, + error_domain_for_idx (idx, 1), + error_code_for_idx (idx, 1)); +} + +static void +test_ap_wpa_eap_connection_2 (gconstpointer data) +{ + guint idx = GPOINTER_TO_UINT (data); + + test_ap_wpa_eap_connection_base (NULL, NULL, + flags_for_idx (idx), + wpa_flags_for_idx (idx), + rsn_flags_for_idx (idx), + TRUE, + error_domain_for_idx (idx, 2), + error_code_for_idx (idx, 2)); +} + +static void +test_ap_wpa_eap_connection_3 (gconstpointer data) +{ + guint idx = GPOINTER_TO_UINT (data); + + test_ap_wpa_eap_connection_base (NULL, "open", + flags_for_idx (idx), + wpa_flags_for_idx (idx), + rsn_flags_for_idx (idx), + FALSE, + error_domain_for_idx (idx, 3), + error_code_for_idx (idx, 3)); +} + +static void +test_ap_wpa_eap_connection_4 (gconstpointer data) +{ + guint idx = GPOINTER_TO_UINT (data); + + test_ap_wpa_eap_connection_base (NULL, "shared", + flags_for_idx (idx), + wpa_flags_for_idx (idx), + rsn_flags_for_idx (idx), + FALSE, + error_domain_for_idx (idx, 4), + error_code_for_idx (idx, 4)); +} + +static void +test_ap_wpa_eap_connection_5 (gconstpointer data) +{ + guint idx = GPOINTER_TO_UINT (data); + + test_ap_wpa_eap_connection_base ("wpa-eap", "open", + flags_for_idx (idx), + wpa_flags_for_idx (idx), + rsn_flags_for_idx (idx), + FALSE, + error_domain_for_idx (idx, 5), + error_code_for_idx (idx, 5)); +} + +/*******************************************/ + +static void +test_priv_ap_empty_connection (void) +{ + NMConnection *src, *expected; + const guint8 bssid[ETH_ALEN] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 }; + const char *ssid = "blahblah"; + const KeyData exp_wsec[] = { + { NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "none", 0 }, + { NULL } }; + gboolean success; + GError *error = NULL; + + /* Test that an empty connection is completed to a valid Static WEP + * connection when completed with an AP with the Privacy bit set. + */ + + src = nm_connection_new (); + success = complete_connection (ssid, bssid, + NM_802_11_MODE_INFRA, NM_802_11_AP_FLAGS_PRIVACY, + NM_802_11_AP_SEC_NONE, NM_802_11_AP_SEC_NONE, + FALSE, + src, &error); + + /* Static WEP connection expected */ + expected = create_basic (ssid, NULL, NM_802_11_MODE_INFRA); + fill_wsec (expected, exp_wsec); + COMPARE (src, expected, success, error, 0, 0); + + g_object_unref (src); + g_object_unref (expected); +} + +/*******************************************/ + +static void +test_priv_ap_leap_connection_1 (gconstpointer add_wifi) +{ + NMConnection *src, *expected; + const char *ssid = "blahblah"; + const guint8 bssid[ETH_ALEN] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 }; + const char *leap_username = "Bill Smith"; + const KeyData src_wsec[] = { + { NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x", 0 }, + { NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME, leap_username, 0 }, + { NULL } }; + const KeyData exp_wsec[] = { + { NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x", 0 }, + { NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "leap", 0 }, + { NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME, leap_username, 0 }, + { NULL } }; + gboolean success; + GError *error = NULL; + + /* Test that an minimal LEAP connection specifying only key management and + * the LEAP username is completed to a full LEAP connection when completed + * with an AP with the Privacy bit set. + */ + + src = nm_connection_new (); + if (add_wifi) + fill_wifi_empty (src); + fill_wsec (src, src_wsec); + success = complete_connection (ssid, bssid, + NM_802_11_MODE_INFRA, NM_802_11_AP_FLAGS_PRIVACY, + NM_802_11_AP_SEC_NONE, NM_802_11_AP_SEC_NONE, + FALSE, + src, &error); + /* We expect success here; since LEAP APs just set the 'privacy' flag + * there's no way to determine from the AP's beacon whether it's static WEP, + * dynamic WEP, or LEAP. + */ + expected = create_basic (ssid, NULL, NM_802_11_MODE_INFRA); + fill_wsec (expected, exp_wsec); + COMPARE (src, expected, success, error, 0, 0); + + g_object_unref (src); +} + +/*******************************************/ + +static void +test_priv_ap_leap_connection_2 (void) +{ + NMConnection *src; + const guint8 bssid[ETH_ALEN] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 }; + const KeyData src_wsec[] = { + { NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x", 0 }, + { NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "leap", 0 }, + { NULL } }; + gboolean success; + GError *error = NULL; + + /* Test that an minimal LEAP connection specifying only key management and + * the LEAP auth alg is completed to a full LEAP connection when completed + * with an AP with the Privacy bit set. + */ + + src = nm_connection_new (); + fill_wifi_empty (src); + fill_wsec (src, src_wsec); + success = complete_connection ("blahblah", bssid, + NM_802_11_MODE_INFRA, NM_802_11_AP_FLAGS_PRIVACY, + NM_802_11_AP_SEC_NONE, NM_802_11_AP_SEC_NONE, + FALSE, + src, &error); + /* We expect failure here, we need a LEAP username */ + COMPARE (src, NULL, success, error, NM_SETTING_WIRELESS_SECURITY_ERROR, NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_USERNAME); + + g_object_unref (src); +} + +/*******************************************/ + +static void +test_priv_ap_dynamic_wep_1 (void) +{ + NMConnection *src, *expected; + const char *ssid = "blahblah"; + const guint8 bssid[ETH_ALEN] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 }; + const KeyData src_wsec[] = { + { NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x", 0 }, + { NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "open", 0 }, + { NULL } }; + const KeyData both_8021x[] = { + { NM_SETTING_802_1X_EAP, "peap", 0 }, + { NM_SETTING_802_1X_IDENTITY, "Bill Smith", 0 }, + { NM_SETTING_802_1X_PHASE2_AUTH, "mschapv2", 0 }, + { NULL } }; + const KeyData exp_wsec[] = { + { NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x", 0 }, + { NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "open", 0 }, + { NULL } }; + gboolean success; + GError *error = NULL; + + /* Test that an minimal Dynamic WEP connection specifying key management, + * the auth algorithm, and valid 802.1x setting is completed to a valid + * Dynamic WEP connection when completed with an AP with the Privacy bit set. + */ + + src = nm_connection_new (); + fill_wifi_empty (src); + fill_wsec (src, src_wsec); + fill_8021x (src, both_8021x); + success = complete_connection (ssid, bssid, + NM_802_11_MODE_INFRA, NM_802_11_AP_FLAGS_PRIVACY, + NM_802_11_AP_SEC_NONE, NM_802_11_AP_SEC_NONE, + FALSE, + src, &error); + + /* We expect a completed Dynamic WEP connection */ + expected = create_basic (ssid, NULL, NM_802_11_MODE_INFRA); + fill_wsec (expected, exp_wsec); + fill_8021x (expected, both_8021x); + COMPARE (src, expected, success, error, 0, 0); + + g_object_unref (src); +} + +/*******************************************/ + +static void +test_priv_ap_dynamic_wep_2 (void) +{ + NMConnection *src, *expected; + const char *ssid = "blahblah"; + const guint8 bssid[ETH_ALEN] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 }; + const KeyData src_wsec[] = { + { NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "open", 0 }, + { NULL } }; + const KeyData both_8021x[] = { + { NM_SETTING_802_1X_EAP, "peap", 0 }, + { NM_SETTING_802_1X_IDENTITY, "Bill Smith", 0 }, + { NM_SETTING_802_1X_PHASE2_AUTH, "mschapv2", 0 }, + { NULL } }; + const KeyData exp_wsec[] = { + { NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x", 0 }, + { NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "open", 0 }, + { NULL } }; + gboolean success; + GError *error = NULL; + + /* Test that an minimal Dynamic WEP connection specifying only the auth + * algorithm and a valid 802.1x setting is completed to a valid Dynamic + * WEP connection when completed with an AP with the Privacy bit set. + */ + + src = nm_connection_new (); + fill_wifi_empty (src); + fill_wsec (src, src_wsec); + fill_8021x (src, both_8021x); + success = complete_connection (ssid, bssid, + NM_802_11_MODE_INFRA, NM_802_11_AP_FLAGS_PRIVACY, + NM_802_11_AP_SEC_NONE, NM_802_11_AP_SEC_NONE, + FALSE, + src, &error); + + /* We expect a completed Dynamic WEP connection */ + expected = create_basic (ssid, NULL, NM_802_11_MODE_INFRA); + fill_wsec (expected, exp_wsec); + fill_8021x (expected, both_8021x); + COMPARE (src, expected, success, error, 0, 0); + + g_object_unref (src); +} + +/*******************************************/ + +static void +test_priv_ap_dynamic_wep_3 (void) +{ + NMConnection *src; + const guint8 bssid[ETH_ALEN] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 }; + const KeyData src_wsec[] = { + { NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "shared", 0 }, + { NULL } }; + const KeyData src_8021x[] = { + { NM_SETTING_802_1X_EAP, "peap", 0 }, + { NM_SETTING_802_1X_IDENTITY, "Bill Smith", 0 }, + { NM_SETTING_802_1X_PHASE2_AUTH, "mschapv2", 0 }, + { NULL } }; + gboolean success; + GError *error = NULL; + + /* Ensure that a basic connection specifying 'shared' auth and an 802.1x + * setting is rejected, as 802.1x is incompatible with 'shared' auth. + */ + + src = nm_connection_new (); + fill_wifi_empty (src); + fill_wsec (src, src_wsec); + fill_8021x (src, src_8021x); + success = complete_connection ("blahblah", bssid, + NM_802_11_MODE_INFRA, NM_802_11_AP_FLAGS_PRIVACY, + NM_802_11_AP_SEC_NONE, NM_802_11_AP_SEC_NONE, + FALSE, + src, &error); + /* Expect failure; shared is not compatible with dynamic WEP */ + COMPARE (src, NULL, success, error, NM_SETTING_WIRELESS_SECURITY_ERROR, NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY); + + g_object_unref (src); +} + +/*******************************************/ + +static void +test_priv_ap_wpa_psk_connection_1 (void) +{ + /* Test that a basic WPA-PSK connection is rejected when completion is + * attempted with an AP with just the Privacy bit set. Lack of WPA/RSN + * flags means the AP provides Static/Dynamic WEP or LEAP, not WPA. + */ + test_ap_wpa_psk_connection_base (NULL, NULL, + NM_802_11_AP_FLAGS_PRIVACY, + NM_802_11_AP_SEC_NONE, + NM_802_11_AP_SEC_NONE, + FALSE, NULL); +} + +static void +test_priv_ap_wpa_psk_connection_2 (void) +{ + /* Test that a basic WPA-PSK connection is rejected when completion is + * attempted with an AP with just the Privacy bit set. Lack of WPA/RSN + * flags means the AP provides Static/Dynamic WEP or LEAP, not WPA. + */ + test_ap_wpa_psk_connection_base (NULL, NULL, + NM_802_11_AP_FLAGS_PRIVACY, + NM_802_11_AP_SEC_NONE, + NM_802_11_AP_SEC_NONE, + TRUE, NULL); +} + +static void +test_priv_ap_wpa_psk_connection_3 (void) +{ + /* Test that a basic WPA-PSK connection specifying only the auth algorithm + * is rejected when completion is attempted with an AP with just the Privacy + * bit set. Lack of WPA/RSN flags means the AP provides Static/Dynamic WEP + * or LEAP, not WPA. + */ + test_ap_wpa_psk_connection_base (NULL, "open", + NM_802_11_AP_FLAGS_PRIVACY, + NM_802_11_AP_SEC_NONE, + NM_802_11_AP_SEC_NONE, + FALSE, NULL); +} + +static void +test_priv_ap_wpa_psk_connection_4 (void) +{ + /* Test that a basic WPA-PSK connection specifying only the auth algorithm + * is rejected when completion is attempted with an AP with just the Privacy + * bit set. Lack of WPA/RSN flags means the AP provides Static/Dynamic WEP + * or LEAP, not WPA. Second, 'shared' auth is incompatible with WPA. + */ + test_ap_wpa_psk_connection_base (NULL, "shared", + NM_802_11_AP_FLAGS_PRIVACY, + NM_802_11_AP_SEC_NONE, + NM_802_11_AP_SEC_NONE, + FALSE, NULL); +} + +static void +test_priv_ap_wpa_psk_connection_5 (void) +{ + /* Test that a WPA-PSK connection specifying both the key management and + * auth algorithm is rejected when completion is attempted with an AP with + * just the Privacy bit set. Lack of WPA/RSN flags means the AP provides + * Static/Dynamic WEP or LEAP, not WPA. + */ + test_ap_wpa_psk_connection_base ("wpa-psk", "open", + NM_802_11_AP_FLAGS_PRIVACY, + NM_802_11_AP_SEC_NONE, + NM_802_11_AP_SEC_NONE, + FALSE, NULL); +} + +/*******************************************/ + +static void +test_wpa_ap_empty_connection (gconstpointer data) +{ + guint idx = GPOINTER_TO_UINT (data); + NMConnection *src, *expected; + const guint8 bssid[ETH_ALEN] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 }; + const char *ssid = "blahblah"; + const KeyData exp_wsec[] = { + { NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-psk", 0 }, + { NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "open", 0 }, + { NULL } }; + gboolean success; + GError *error = NULL; + + /* Test that a basic WPA-PSK connection specifying just key management and + * the auth algorithm is completed successfully when given an AP with WPA + * or RSN flags. + */ + + src = nm_connection_new (); + success = complete_connection (ssid, bssid, + NM_802_11_MODE_INFRA, NM_802_11_AP_FLAGS_PRIVACY, + wpa_flags_for_idx (idx), + rsn_flags_for_idx (idx), + FALSE, src, &error); + + /* WPA connection expected */ + expected = create_basic (ssid, NULL, NM_802_11_MODE_INFRA); + fill_wsec (expected, exp_wsec); + COMPARE (src, expected, success, error, 0, 0); + + g_object_unref (src); + g_object_unref (expected); +} + +/*******************************************/ + +static void +test_wpa_ap_leap_connection_1 (gconstpointer data) +{ + guint idx = GPOINTER_TO_UINT (data); + NMConnection *src; + const char *ssid = "blahblah"; + const guint8 bssid[ETH_ALEN] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 }; + const char *leap_username = "Bill Smith"; + const KeyData src_wsec[] = { + { NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x", 0 }, + { NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME, leap_username, 0 }, + { NULL } }; + gboolean success; + GError *error = NULL; + + /* Test that completion of a LEAP connection with a WPA-enabled AP is + * rejected since WPA APs (usually) do not support LEAP. + */ + + src = nm_connection_new (); + fill_wifi_empty (src); + fill_wsec (src, src_wsec); + success = complete_connection (ssid, bssid, + NM_802_11_MODE_INFRA, NM_802_11_AP_FLAGS_PRIVACY, + wpa_flags_for_idx (idx), + rsn_flags_for_idx (idx), + FALSE, + src, &error); + /* Expect failure here; WPA APs don't support old-school LEAP */ + COMPARE (src, NULL, success, error, NM_SETTING_WIRELESS_SECURITY_ERROR, NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY); + + g_object_unref (src); +} + +/*******************************************/ + +static void +test_wpa_ap_leap_connection_2 (gconstpointer data) +{ + guint idx = GPOINTER_TO_UINT (data); + NMConnection *src; + const guint8 bssid[ETH_ALEN] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 }; + const KeyData src_wsec[] = { + { NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x", 0 }, + { NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "leap", 0 }, + { NULL } }; + gboolean success; + GError *error = NULL; + + /* Test that completion of a LEAP connection with a WPA-enabled AP is + * rejected since WPA APs (usually) do not support LEAP. + */ + + src = nm_connection_new (); + fill_wifi_empty (src); + fill_wsec (src, src_wsec); + success = complete_connection ("blahblah", bssid, + NM_802_11_MODE_INFRA, NM_802_11_AP_FLAGS_PRIVACY, + wpa_flags_for_idx (idx), + rsn_flags_for_idx (idx), + FALSE, + src, &error); + /* We expect failure here, we need a LEAP username */ + COMPARE (src, NULL, success, error, NM_SETTING_WIRELESS_SECURITY_ERROR, NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY); + + g_object_unref (src); +} + +/*******************************************/ + +static void +test_wpa_ap_dynamic_wep_connection (gconstpointer data) +{ + guint idx = GPOINTER_TO_UINT (data); + NMConnection *src; + const guint8 bssid[ETH_ALEN] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 }; + const KeyData src_wsec[] = { + { NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x", 0 }, + { NULL } }; + gboolean success; + GError *error = NULL; + + /* Test that completion of a Dynamic WEP connection with a WPA-enabled AP is + * rejected since WPA APs (usually) do not support Dynamic WEP. + */ + + src = nm_connection_new (); + fill_wifi_empty (src); + fill_wsec (src, src_wsec); + success = complete_connection ("blahblah", bssid, + NM_802_11_MODE_INFRA, NM_802_11_AP_FLAGS_PRIVACY, + wpa_flags_for_idx (idx), + rsn_flags_for_idx (idx), + FALSE, + src, &error); + /* We expect failure here since Dynamic WEP is incompatible with WPA */ + COMPARE (src, NULL, success, error, NM_SETTING_WIRELESS_SECURITY_ERROR, NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY); + + g_object_unref (src); +} + +/*******************************************/ + +static void +test_wpa_ap_wpa_psk_connection_1 (gconstpointer data) +{ + guint idx = GPOINTER_TO_UINT (data); + NMConnection *expected; + const KeyData exp_wsec[] = { + { NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-psk", 0 }, + { NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "open", 0 }, + { NULL } }; + + expected = nm_connection_new (); + fill_wsec (expected, exp_wsec); + test_ap_wpa_psk_connection_base (NULL, NULL, + NM_802_11_AP_FLAGS_PRIVACY, + wpa_flags_for_idx (idx), + rsn_flags_for_idx (idx), + FALSE, expected); + g_object_unref (expected); +} + +static void +test_wpa_ap_wpa_psk_connection_2 (gconstpointer data) +{ + guint idx = GPOINTER_TO_UINT (data); + NMConnection *expected; + const KeyData exp_wsec[] = { + { NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-psk", 0 }, + { NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "open", 0 }, + { NULL } }; + + expected = nm_connection_new (); + fill_wsec (expected, exp_wsec); + test_ap_wpa_psk_connection_base (NULL, NULL, + NM_802_11_AP_FLAGS_PRIVACY, + wpa_flags_for_idx (idx), + rsn_flags_for_idx (idx), + TRUE, expected); + g_object_unref (expected); +} + +static void +test_wpa_ap_wpa_psk_connection_3 (gconstpointer data) +{ + guint idx = GPOINTER_TO_UINT (data); + NMConnection *expected; + const KeyData exp_wsec[] = { + { NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-psk", 0 }, + { NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "open", 0 }, + { NULL } }; + + expected = nm_connection_new (); + fill_wsec (expected, exp_wsec); + test_ap_wpa_psk_connection_base (NULL, "open", + NM_802_11_AP_FLAGS_PRIVACY, + wpa_flags_for_idx (idx), + rsn_flags_for_idx (idx), + FALSE, expected); + g_object_unref (expected); +} + +static void +test_wpa_ap_wpa_psk_connection_4 (gconstpointer data) +{ + guint idx = GPOINTER_TO_UINT (data); + test_ap_wpa_psk_connection_base (NULL, "shared", + NM_802_11_AP_FLAGS_PRIVACY, + wpa_flags_for_idx (idx), + rsn_flags_for_idx (idx), + FALSE, NULL); +} + +static void +test_wpa_ap_wpa_psk_connection_5 (gconstpointer data) +{ + guint idx = GPOINTER_TO_UINT (data); + NMConnection *expected; + const KeyData exp_wsec[] = { + { NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-psk", 0 }, + { NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "open", 0 }, + { NULL } }; + + expected = nm_connection_new (); + fill_wsec (expected, exp_wsec); + test_ap_wpa_psk_connection_base ("wpa-psk", "open", + NM_802_11_AP_FLAGS_PRIVACY, + wpa_flags_for_idx (idx), + rsn_flags_for_idx (idx), + FALSE, expected); + g_object_unref (expected); +} + +/*******************************************/ + +static void +test_strength_dbm (void) +{ + /* boundary conditions first */ + g_assert_cmpint (nm_ap_utils_level_to_quality (-1), ==, 100); + g_assert_cmpint (nm_ap_utils_level_to_quality (-40), ==, 100); + g_assert_cmpint (nm_ap_utils_level_to_quality (-30), ==, 100); + g_assert_cmpint (nm_ap_utils_level_to_quality (-100), ==, 0); + g_assert_cmpint (nm_ap_utils_level_to_quality (-200), ==, 0); + + g_assert_cmpint (nm_ap_utils_level_to_quality (-81), ==, 32); + g_assert_cmpint (nm_ap_utils_level_to_quality (-92), ==, 14); + g_assert_cmpint (nm_ap_utils_level_to_quality (-74), ==, 44); + g_assert_cmpint (nm_ap_utils_level_to_quality (-81), ==, 32); + g_assert_cmpint (nm_ap_utils_level_to_quality (-66), ==, 57); +} + +static void +test_strength_percent (void) +{ + int i; + + /* boundary conditions first */ + g_assert_cmpint (nm_ap_utils_level_to_quality (0), ==, 0); + g_assert_cmpint (nm_ap_utils_level_to_quality (100), ==, 100); + g_assert_cmpint (nm_ap_utils_level_to_quality (110), ==, 100); + + for (i = 0; i <= 100; i++) + g_assert_cmpint (nm_ap_utils_level_to_quality (i), ==, i); +} + +static void +test_strength_wext (void) +{ + /* boundary conditions that we assume aren't WEXT first */ + g_assert_cmpint (nm_ap_utils_level_to_quality (256), ==, 100); + g_assert_cmpint (nm_ap_utils_level_to_quality (110), ==, 100); + + /* boundary conditions that we assume are WEXT */ + g_assert_cmpint (nm_ap_utils_level_to_quality (111), ==, 0); + g_assert_cmpint (nm_ap_utils_level_to_quality (150), ==, 0); + g_assert_cmpint (nm_ap_utils_level_to_quality (225), ==, 100); + g_assert_cmpint (nm_ap_utils_level_to_quality (255), ==, 100); + + g_assert_cmpint (nm_ap_utils_level_to_quality (157), ==, 2); + g_assert_cmpint (nm_ap_utils_level_to_quality (200), ==, 74); + g_assert_cmpint (nm_ap_utils_level_to_quality (215), ==, 99); +} + +/*******************************************/ + +int +main (int argc, char **argv) +{ + gsize i; + +#if !GLIB_CHECK_VERSION (2, 35, 0) + g_type_init (); +#endif + + g_test_init (&argc, &argv, NULL); + + g_test_add_func ("/wifi/lock_bssid", + test_lock_bssid); + + /* Open AP tests; make sure that connections to be completed that have + * various security-related settings already set cause the completion + * to fail. + */ + g_test_add_func ("/wifi/open_ap/empty_connection", + test_open_ap_empty_connection); + g_test_add_data_func ("/wifi/open_ap/leap_connection/1", + (gconstpointer) TRUE, + test_open_ap_leap_connection_1); + g_test_add_data_func ("/wifi/open_ap/leap_connection/1_no_add_wifi", + (gconstpointer) FALSE, + test_open_ap_leap_connection_1); + g_test_add_func ("/wifi/open_ap/leap_connection/2", + test_open_ap_leap_connection_2); + g_test_add_data_func ("/wifi/open_ap/wep_connection", + (gconstpointer) TRUE, + test_open_ap_wep_connection); + g_test_add_data_func ("/wifi/open_ap/wep_connection", + (gconstpointer) FALSE, + test_open_ap_wep_connection); + + g_test_add_func ("/wifi/open_ap/wpa_psk_connection/1", + test_open_ap_wpa_psk_connection_1); + g_test_add_func ("/wifi/open_ap/wpa_psk_connection/2", + test_open_ap_wpa_psk_connection_2); + g_test_add_func ("/wifi/open_ap/wpa_psk_connection/3", + test_open_ap_wpa_psk_connection_3); + g_test_add_func ("/wifi/open_ap/wpa_psk_connection/4", + test_open_ap_wpa_psk_connection_4); + g_test_add_func ("/wifi/open_ap/wpa_psk_connection/5", + test_open_ap_wpa_psk_connection_5); + + g_test_add_data_func ("/wifi/open_ap/wpa_eap_connection/1", + (gconstpointer) IDX_OPEN, + test_ap_wpa_eap_connection_1); + g_test_add_data_func ("/wifi/open_ap/wpa_eap_connection/2", + (gconstpointer) IDX_OPEN, + test_ap_wpa_eap_connection_2); + g_test_add_data_func ("/wifi/open_ap/wpa_eap_connection/3", + (gconstpointer) IDX_OPEN, + test_ap_wpa_eap_connection_3); + g_test_add_data_func ("/wifi/open_ap/wpa_eap_connection/4", + (gconstpointer) IDX_OPEN, + test_ap_wpa_eap_connection_4); + g_test_add_data_func ("/wifi/open_ap/wpa_eap_connection/5", + (gconstpointer) IDX_OPEN, + test_ap_wpa_eap_connection_5); + + /* WEP AP tests */ + g_test_add_func ("/wifi/priv_ap/empty_connection", + test_priv_ap_empty_connection); + g_test_add_data_func ("/wifi/priv_ap/leap_connection/1", + (gconstpointer) FALSE, + test_priv_ap_leap_connection_1); + g_test_add_func ("/wifi/priv_ap/leap_connection/2", + test_priv_ap_leap_connection_2); + + g_test_add_func ("/wifi/priv_ap/dynamic_wep/1", + test_priv_ap_dynamic_wep_1); + g_test_add_func ("/wifi/priv_ap/dynamic_wep/2", + test_priv_ap_dynamic_wep_2); + g_test_add_func ("/wifi/priv_ap/dynamic_wep/3", + test_priv_ap_dynamic_wep_3); + + g_test_add_func ("/wifi/priv_ap/wpa_psk_connection/1", + test_priv_ap_wpa_psk_connection_1); + g_test_add_func ("/wifi/priv_ap/wpa_psk_connection/2", + test_priv_ap_wpa_psk_connection_2); + g_test_add_func ("/wifi/priv_ap/wpa_psk_connection/3", + test_priv_ap_wpa_psk_connection_3); + g_test_add_func ("/wifi/priv_ap/wpa_psk_connection/4", + test_priv_ap_wpa_psk_connection_4); + g_test_add_func ("/wifi/priv_ap/wpa_psk_connection/5", + test_priv_ap_wpa_psk_connection_5); + + g_test_add_data_func ("/wifi/priv_ap/wpa_eap_connection/1", + (gconstpointer) IDX_PRIV, + test_ap_wpa_eap_connection_1); + g_test_add_data_func ("/wifi/priv_ap/wpa_eap_connection/2", + (gconstpointer) IDX_PRIV, + test_ap_wpa_eap_connection_2); + g_test_add_data_func ("/wifi/priv_ap/wpa_eap_connection/3", + (gconstpointer) IDX_PRIV, + test_ap_wpa_eap_connection_3); + g_test_add_data_func ("/wifi/priv_ap/wpa_eap_connection/4", + (gconstpointer) IDX_PRIV, + test_ap_wpa_eap_connection_4); + g_test_add_data_func ("/wifi/priv_ap/wpa_eap_connection/5", + (gconstpointer) IDX_PRIV, + test_ap_wpa_eap_connection_5); + + /* WPA-PSK tests */ + for (i = IDX_WPA_PSK_PTKIP_GTKIP; i <= IDX_WPA_RSN_PSK_PCCMP_GCCMP; i++) { + g_test_add_data_func ("/wifi/wpa_psk/empty_connection", + (gconstpointer) i, + test_wpa_ap_empty_connection); + g_test_add_data_func ("/wifi/wpa_psk/leap_connection/1", + (gconstpointer) i, + test_wpa_ap_leap_connection_1); + g_test_add_data_func ("/wifi/wpa_psk/leap_connection/2", + (gconstpointer) i, + test_wpa_ap_leap_connection_2); + + g_test_add_data_func ("/wifi/wpa_psk/dynamic_wep_connection", + (gconstpointer) i, + test_wpa_ap_dynamic_wep_connection); + + g_test_add_data_func ("/wifi/wpa_psk/wpa_psk_connection/1", + (gconstpointer) i, + test_wpa_ap_wpa_psk_connection_1); + g_test_add_data_func ("/wifi/wpa_psk/wpa_psk_connection/2", + (gconstpointer) i, + test_wpa_ap_wpa_psk_connection_2); + g_test_add_data_func ("/wifi/wpa_psk/wpa_psk_connection/3", + (gconstpointer) i, + test_wpa_ap_wpa_psk_connection_3); + g_test_add_data_func ("/wifi/wpa_psk/wpa_psk_connection/4", + (gconstpointer) i, + test_wpa_ap_wpa_psk_connection_4); + g_test_add_data_func ("/wifi/wpa_psk/wpa_psk_connection/5", + (gconstpointer) i, + test_wpa_ap_wpa_psk_connection_5); + + g_test_add_data_func ("/wifi/wpa_psk/wpa_eap_connection/1", + (gconstpointer) i, + test_ap_wpa_eap_connection_1); + g_test_add_data_func ("/wifi/wpa_psk/wpa_eap_connection/2", + (gconstpointer) i, + test_ap_wpa_eap_connection_2); + g_test_add_data_func ("/wifi/wpa_psk/wpa_eap_connection/3", + (gconstpointer) i, + test_ap_wpa_eap_connection_3); + g_test_add_data_func ("/wifi/wpa_psk/wpa_eap_connection/4", + (gconstpointer) i, + test_ap_wpa_eap_connection_4); + g_test_add_data_func ("/wifi/wpa_psk/wpa_eap_connection/5", + (gconstpointer) i, + test_ap_wpa_eap_connection_5); + } + + /* RSN-PSK tests */ + for (i = IDX_WPA_RSN_PSK_PTKIP_PCCMP_GTKIP; i <= IDX_RSN_PSK_PTKIP_PCCMP_GTKIP; i++) { + g_test_add_data_func ("/wifi/rsn_psk/empty_connection", + (gconstpointer) i, + test_wpa_ap_empty_connection); + g_test_add_data_func ("/wifi/rsn_psk/leap_connection/1", + (gconstpointer) i, + test_wpa_ap_leap_connection_1); + g_test_add_data_func ("/wifi/rsn_psk/leap_connection/2", + (gconstpointer) i, + test_wpa_ap_leap_connection_2); + + g_test_add_data_func ("/wifi/rsn_psk/dynamic_wep_connection", + (gconstpointer) i, + test_wpa_ap_dynamic_wep_connection); + + g_test_add_data_func ("/wifi/rsn_psk/wpa_psk_connection/1", + (gconstpointer) i, + test_wpa_ap_wpa_psk_connection_1); + g_test_add_data_func ("/wifi/rsn_psk/wpa_psk_connection/2", + (gconstpointer) i, + test_wpa_ap_wpa_psk_connection_2); + g_test_add_data_func ("/wifi/rsn_psk/wpa_psk_connection/3", + (gconstpointer) i, + test_wpa_ap_wpa_psk_connection_3); + g_test_add_data_func ("/wifi/rsn_psk/wpa_psk_connection/4", + (gconstpointer) i, + test_wpa_ap_wpa_psk_connection_4); + g_test_add_data_func ("/wifi/rsn_psk/wpa_psk_connection/5", + (gconstpointer) i, + test_wpa_ap_wpa_psk_connection_5); + + g_test_add_data_func ("/wifi/rsn_psk/wpa_eap_connection/1", + (gconstpointer) i, + test_ap_wpa_eap_connection_1); + g_test_add_data_func ("/wifi/rsn_psk/wpa_eap_connection/2", + (gconstpointer) i, + test_ap_wpa_eap_connection_2); + g_test_add_data_func ("/wifi/rsn_psk/wpa_eap_connection/3", + (gconstpointer) i, + test_ap_wpa_eap_connection_3); + g_test_add_data_func ("/wifi/rsn_psk/wpa_eap_connection/4", + (gconstpointer) i, + test_ap_wpa_eap_connection_4); + g_test_add_data_func ("/wifi/rsn_psk/wpa_eap_connection/5", + (gconstpointer) i, + test_ap_wpa_eap_connection_5); + } + + /* Scanned signal strength conversion tests */ + g_test_add_func ("/wifi/strength/dbm", + test_strength_dbm); + g_test_add_func ("/wifi/strength/percent", + test_strength_percent); + g_test_add_func ("/wifi/strength/wext", + test_strength_wext); + + return g_test_run (); +} diff --git a/src/devices/wimax/Makefile.am b/src/devices/wimax/Makefile.am new file mode 100644 index 00000000..def8bf62 --- /dev/null +++ b/src/devices/wimax/Makefile.am @@ -0,0 +1,63 @@ +AM_CPPFLAGS = \ + -I${top_srcdir}/src \ + -I${top_builddir}/src \ + -I${top_srcdir}/src/logging \ + -I${top_srcdir}/src/devices \ + -I${top_srcdir}/src/platform \ + -I${top_builddir}/include \ + -I${top_srcdir}/include \ + -I${top_builddir}/libnm-util \ + -I${top_srcdir}/libnm-util \ + -DG_LOG_DOMAIN=\""NetworkManager-wimax"\" \ + -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \ + $(DBUS_CFLAGS) \ + $(POLKIT_CFLAGS) \ + $(IWMX_SDK_CFLAGS) \ + $(LIBNL_CFLAGS) \ + $(GUDEV_CFLAGS) + +pkglib_LTLIBRARIES = libnm-device-plugin-wimax.la + +SYMBOL_VIS_FILE=$(srcdir)/exports.ver + +libnm_device_plugin_wimax_la_SOURCES = \ + nm-wimax-factory.c \ + nm-device-wimax.c \ + nm-device-wimax.h \ + nm-wimax-nsp.c \ + nm-wimax-nsp.h \ + nm-wimax-types.h \ + nm-wimax-util.c \ + nm-wimax-util.h \ + iwmxsdk.c \ + iwmxsdk.h + +libnm_device_plugin_wimax_la_LDFLAGS = \ + -module -avoid-version \ + -Wl,--version-script=$(SYMBOL_VIS_FILE) + +libnm_device_plugin_wimax_la_LIBADD = \ + $(DBUS_LIBS) \ + $(IWMX_SDK_LIBS) \ + $(GUDEV_LIBS) + +nm-wimax-nsp-glue.h: $(top_srcdir)/introspection/nm-wimax-nsp.xml + dbus-binding-tool --prefix=nm_wimax_nsp --mode=glib-server --output=$@ $< + +nm-device-wimax-glue.h: $(top_srcdir)/introspection/nm-device-wimax.xml + dbus-binding-tool --prefix=nm_device_wimax --mode=glib-server --output=$@ $< + +BUILT_SOURCES = \ + nm-wimax-nsp-glue.h \ + nm-device-wimax-glue.h + +CLEANFILES = $(BUILT_SOURCES) +EXTRA_DIST = $(SYMBOL_VIS_FILE) + +if ENABLE_TESTS + +check-local: + $(top_srcdir)/tools/check-exports.sh $(builddir)/.libs/libnm-device-plugin-wimax.so $(SYMBOL_VIS_FILE) + +endif + diff --git a/src/devices/wimax/Makefile.in b/src/devices/wimax/Makefile.in new file mode 100644 index 00000000..ba16d277 --- /dev/null +++ b/src/devices/wimax/Makefile.in @@ -0,0 +1,850 @@ +# Makefile.in generated by automake 1.13.4 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/devices/wimax +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(top_srcdir)/build-aux/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_lib_readline.m4 \ + $(top_srcdir)/m4/compiler_warnings.m4 \ + $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/gnome-code-coverage.m4 \ + $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ + $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \ + $(top_srcdir)/m4/introspection.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ + $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ + $(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(pkglibdir)" +LTLIBRARIES = $(pkglib_LTLIBRARIES) +am__DEPENDENCIES_1 = +libnm_device_plugin_wimax_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +am_libnm_device_plugin_wimax_la_OBJECTS = nm-wimax-factory.lo \ + nm-device-wimax.lo nm-wimax-nsp.lo nm-wimax-util.lo iwmxsdk.lo +libnm_device_plugin_wimax_la_OBJECTS = \ + $(am_libnm_device_plugin_wimax_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libnm_device_plugin_wimax_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(libnm_device_plugin_wimax_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libnm_device_plugin_wimax_la_SOURCES) +DIST_SOURCES = $(libnm_device_plugin_wimax_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALL_LINGUAS = @ALL_LINGUAS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CKDB_PATH = @CKDB_PATH@ +CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@ +CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@ +CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIRNAME = @DATADIRNAME@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_100_CFLAGS = @DBUS_GLIB_100_CFLAGS@ +DBUS_GLIB_100_LIBS = @DBUS_GLIB_100_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DHCLIENT_PATH = @DHCLIENT_PATH@ +DHCPCD_PATH = @DHCPCD_PATH@ +DISTRO_NETWORK_SERVICE = @DISTRO_NETWORK_SERVICE@ +DLLTOOL = @DLLTOOL@ +DNSMASQ_PATH = @DNSMASQ_PATH@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GENHTML = @GENHTML@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MAKEFILE = @GLIB_MAKEFILE@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ +GNUTLS_LIBS = @GNUTLS_LIBS@ +GREP = @GREP@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GUDEV_CFLAGS = @GUDEV_CFLAGS@ +GUDEV_LIBS = @GUDEV_LIBS@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_PERL = @INTLTOOL_PERL@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ +INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ +INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ +INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +IPTABLES_PATH = @IPTABLES_PATH@ +IWMX_SDK_CFLAGS = @IWMX_SDK_CFLAGS@ +IWMX_SDK_LIBS = @IWMX_SDK_LIBS@ +KERNEL_FIRMWARE_DIR = @KERNEL_FIRMWARE_DIR@ +LCOV = @LCOV@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDL = @LIBDL@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBM = @LIBM@ +LIBNDP_CFLAGS = @LIBNDP_CFLAGS@ +LIBNDP_LIBS = @LIBNDP_LIBS@ +LIBNL_CFLAGS = @LIBNL_CFLAGS@ +LIBNL_LIBS = @LIBNL_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@ +LIBSOUP_LIBS = @LIBSOUP_LIBS@ +LIBTEAMDCTL_CFLAGS = @LIBTEAMDCTL_CFLAGS@ +LIBTEAMDCTL_LIBS = @LIBTEAMDCTL_LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MM_GLIB_CFLAGS = @MM_GLIB_CFLAGS@ +MM_GLIB_LIBS = @MM_GLIB_LIBS@ +MOC = @MOC@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NEWT_CFLAGS = @NEWT_CFLAGS@ +NEWT_LIBS = @NEWT_LIBS@ +NM = @NM@ +NMEDIT = @NMEDIT@ +NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ +NM_MICRO_VERSION = @NM_MICRO_VERSION@ +NM_MINOR_VERSION = @NM_MINOR_VERSION@ +NM_MODIFY_SYSTEM_POLICY = @NM_MODIFY_SYSTEM_POLICY@ +NM_VERSION = @NM_VERSION@ +NSS_CFLAGS = @NSS_CFLAGS@ +NSS_LIBS = @NSS_LIBS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +POLKIT_CFLAGS = @POLKIT_CFLAGS@ +POLKIT_LIBS = @POLKIT_LIBS@ +POSUB = @POSUB@ +PPPD_PATH = @PPPD_PATH@ +PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@ +PPPOE_PATH = @PPPOE_PATH@ +QT_CFLAGS = @QT_CFLAGS@ +QT_LIBS = @QT_LIBS@ +RANLIB = @RANLIB@ +READLINE_LIBS = @READLINE_LIBS@ +SED = @SED@ +SELINUX_CFLAGS = @SELINUX_CFLAGS@ +SELINUX_LIBS = @SELINUX_LIBS@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SYSTEMD_200_CFLAGS = @SYSTEMD_200_CFLAGS@ +SYSTEMD_200_LIBS = @SYSTEMD_200_LIBS@ +SYSTEMD_INHIBIT_CFLAGS = @SYSTEMD_INHIBIT_CFLAGS@ +SYSTEMD_INHIBIT_LIBS = @SYSTEMD_INHIBIT_LIBS@ +SYSTEMD_LOGIN_CFLAGS = @SYSTEMD_LOGIN_CFLAGS@ +SYSTEMD_LOGIN_LIBS = @SYSTEMD_LOGIN_LIBS@ +SYSTEM_CA_PATH = @SYSTEM_CA_PATH@ +UDEV_BASE_DIR = @UDEV_BASE_DIR@ +USE_NLS = @USE_NLS@ +UUID_CFLAGS = @UUID_CFLAGS@ +UUID_LIBS = @UUID_LIBS@ +VALGRIND_RULES = @VALGRIND_RULES@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ +VERSION = @VERSION@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +intltool__v_merge_options_ = @intltool__v_merge_options_@ +intltool__v_merge_options_0 = @intltool__v_merge_options_0@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +nmbinary = @nmbinary@ +nmconfdir = @nmconfdir@ +nmdatadir = @nmdatadir@ +nmrundir = @nmrundir@ +nmstatedir = @nmstatedir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +with_dhclient = @with_dhclient@ +with_dhcpcd = @with_dhcpcd@ +with_netconfig = @with_netconfig@ +with_resolvconf = @with_resolvconf@ +with_valgrind = @with_valgrind@ +AM_CPPFLAGS = \ + -I${top_srcdir}/src \ + -I${top_builddir}/src \ + -I${top_srcdir}/src/logging \ + -I${top_srcdir}/src/devices \ + -I${top_srcdir}/src/platform \ + -I${top_builddir}/include \ + -I${top_srcdir}/include \ + -I${top_builddir}/libnm-util \ + -I${top_srcdir}/libnm-util \ + -DG_LOG_DOMAIN=\""NetworkManager-wimax"\" \ + -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \ + $(DBUS_CFLAGS) \ + $(POLKIT_CFLAGS) \ + $(IWMX_SDK_CFLAGS) \ + $(LIBNL_CFLAGS) \ + $(GUDEV_CFLAGS) + +pkglib_LTLIBRARIES = libnm-device-plugin-wimax.la +SYMBOL_VIS_FILE = $(srcdir)/exports.ver +libnm_device_plugin_wimax_la_SOURCES = \ + nm-wimax-factory.c \ + nm-device-wimax.c \ + nm-device-wimax.h \ + nm-wimax-nsp.c \ + nm-wimax-nsp.h \ + nm-wimax-types.h \ + nm-wimax-util.c \ + nm-wimax-util.h \ + iwmxsdk.c \ + iwmxsdk.h + +libnm_device_plugin_wimax_la_LDFLAGS = \ + -module -avoid-version \ + -Wl,--version-script=$(SYMBOL_VIS_FILE) + +libnm_device_plugin_wimax_la_LIBADD = \ + $(DBUS_LIBS) \ + $(IWMX_SDK_LIBS) \ + $(GUDEV_LIBS) + +BUILT_SOURCES = \ + nm-wimax-nsp-glue.h \ + nm-device-wimax-glue.h + +CLEANFILES = $(BUILT_SOURCES) +EXTRA_DIST = $(SYMBOL_VIS_FILE) +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/devices/wimax/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/devices/wimax/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +install-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkglibdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ + } + +uninstall-pkglibLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ + done + +clean-pkglibLTLIBRARIES: + -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) + @list='$(pkglib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libnm-device-plugin-wimax.la: $(libnm_device_plugin_wimax_la_OBJECTS) $(libnm_device_plugin_wimax_la_DEPENDENCIES) $(EXTRA_libnm_device_plugin_wimax_la_DEPENDENCIES) + $(AM_V_CCLD)$(libnm_device_plugin_wimax_la_LINK) -rpath $(pkglibdir) $(libnm_device_plugin_wimax_la_OBJECTS) $(libnm_device_plugin_wimax_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iwmxsdk.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-device-wimax.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-wimax-factory.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-wimax-nsp.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-wimax-util.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +@ENABLE_TESTS_FALSE@check-local: +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) check-local +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(pkglibdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-am + +clean-am: clean-generic clean-libtool clean-pkglibLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-pkglibLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pkglibLTLIBRARIES + +.MAKE: all check check-am install install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am check-local clean \ + clean-generic clean-libtool clean-pkglibLTLIBRARIES \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-pkglibLTLIBRARIES install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am uninstall-pkglibLTLIBRARIES + + +nm-wimax-nsp-glue.h: $(top_srcdir)/introspection/nm-wimax-nsp.xml + dbus-binding-tool --prefix=nm_wimax_nsp --mode=glib-server --output=$@ $< + +nm-device-wimax-glue.h: $(top_srcdir)/introspection/nm-device-wimax.xml + dbus-binding-tool --prefix=nm_device_wimax --mode=glib-server --output=$@ $< + +@ENABLE_TESTS_TRUE@check-local: +@ENABLE_TESTS_TRUE@ $(top_srcdir)/tools/check-exports.sh $(builddir)/.libs/libnm-device-plugin-wimax.so $(SYMBOL_VIS_FILE) + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/devices/wimax/exports.ver b/src/devices/wimax/exports.ver new file mode 100644 index 00000000..d2c45124 --- /dev/null +++ b/src/devices/wimax/exports.ver @@ -0,0 +1,7 @@ +{ +global: + nm_device_factory_create; + nm_device_factory_get_device_type; +local: + *; +}; diff --git a/src/devices/wimax/iwmxsdk.c b/src/devices/wimax/iwmxsdk.c new file mode 100644 index 00000000..d1ef7b68 --- /dev/null +++ b/src/devices/wimax/iwmxsdk.c @@ -0,0 +1,1517 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * + * Copyright (C) 2011 Red Hat, Inc. All rights reserved. + * Copyright (C) 2007-2010 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include "logging/nm-logging.h" +#include "iwmxsdk.h" + +static WIMAX_API_DEVICE_ID g_api; +static GMutex add_remove_mutex; + +/* Misc utilities */ +#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0])) + +/* Misc values */ +enum { + /* + * WARNING!!!!! + * + * ONLY ONE DEVICE SUPPORTED + * + * - on removal, there is no way to know which device was + * removed (the removed device is removed from the list and + * the callback doesn't have any more information than the + * index in the list that getlistdevice would return -- racy + * as hell). + * + * - on insertion, there is not enough information provided. + */ + IWMX_SDK_DEV_MAX = 1, +}; + +/* Yes, this is dirty; see above on IWMX_SDK_DEV_MAX */ +static struct wmxsdk *g_iwmx_sdk_devs[IWMX_SDK_DEV_MAX]; + +static struct wmxsdk *deviceid_to_wmxsdk(WIMAX_API_DEVICE_ID *device_id) +{ + unsigned cnt; + for (cnt = 0; cnt < IWMX_SDK_DEV_MAX; cnt++) { + struct wmxsdk *wmxsdk = g_iwmx_sdk_devs[cnt]; + if (wmxsdk && + wmxsdk->device_id.deviceIndex == device_id->deviceIndex) + return wmxsdk; + } + return NULL; +} + +static int deviceid_to_index(WIMAX_API_DEVICE_ID *device_id) +{ + unsigned cnt; + + for (cnt = 0; cnt < IWMX_SDK_DEV_MAX; cnt++) { + struct wmxsdk *wmxsdk = g_iwmx_sdk_devs[cnt]; + if (wmxsdk && wmxsdk->device_id.deviceIndex == device_id->deviceIndex) + return cnt; + } + return -1; +} + +struct wmxsdk *iwmx_sdk_get_wmxsdk_for_iface(const char *iface) +{ + unsigned cnt; + + for (cnt = 0; cnt < IWMX_SDK_DEV_MAX; cnt++) { + struct wmxsdk *wmxsdk = g_iwmx_sdk_devs[cnt]; + if (wmxsdk && !strcmp(wmxsdk->ifname, iface)) + return wmxsdk; + } + return NULL; +} + +/* + * FIXME: pulled it it out of some hole + * + * the cinr to percentage computation comes from the L3/L4 doc + * + * But some other places (L4 code) have a more complex, seemingly + * logarithmical computation. + * + * Oh well... + * + */ +static int cinr_to_percentage(int cinr) +{ + int strength; + if (cinr <= -5) + strength = 0; + else if (cinr >= 25) + strength = 100; + else /* Calc percentage on the value from -5 to 25 */ + strength = ((100UL * (cinr - -5)) / (25 - -5)); + return strength; +} + +/**************************************************************/ + +typedef struct { + WimaxNewWmxsdkFunc callback; + void *user_data; +} NewSdkCallback; + +static GMutex new_callbacks_mutex; +static GSList *new_callbacks = NULL; + +void iwmx_sdk_new_callback_register(WimaxNewWmxsdkFunc callback, void *user_data) +{ + NewSdkCallback *cb; + + cb = g_malloc0 (sizeof (NewSdkCallback)); + g_assert (cb); + cb->callback = callback; + cb->user_data = user_data; + + g_mutex_lock (&new_callbacks_mutex); + new_callbacks = g_slist_append (new_callbacks, cb); + g_mutex_unlock (&new_callbacks_mutex); +} + +void iwmx_sdk_new_callback_unregister(WimaxNewWmxsdkFunc callback, void *user_data) +{ + GSList *iter; + NewSdkCallback *found = NULL; + + g_mutex_lock (&new_callbacks_mutex); + for (iter = new_callbacks; iter; iter = g_slist_next (iter)) { + NewSdkCallback *cb = iter->data; + + if (cb->callback == callback && cb->user_data == user_data) { + found = cb; + break; + } + } + + if (found) { + new_callbacks = g_slist_remove (new_callbacks, found); + g_free (found); + } + g_mutex_unlock (&new_callbacks_mutex); +} + +static void iwmx_sdk_call_new_callbacks(struct wmxsdk *wmxsdk) +{ + GSList *iter; + + g_mutex_lock (&new_callbacks_mutex); + for (iter = new_callbacks; iter; iter = g_slist_next (iter)) { + NewSdkCallback *cb = iter->data; + + cb->callback (wmxsdk, cb->user_data); + } + g_mutex_unlock (&new_callbacks_mutex); +} + +/****************************************************************/ + +typedef struct { + struct wmxsdk *wmxsdk; + WIMAX_API_DEVICE_STATUS new_status; + WIMAX_API_DEVICE_STATUS old_status; + WIMAX_API_STATUS_REASON reason; + WIMAX_API_CONNECTION_PROGRESS_INFO progress; +} StateChangeInfo; + +static gboolean +state_change_handler(gpointer user_data) +{ + StateChangeInfo *info = user_data; + + if (info->wmxsdk->state_change_cb) { + info->wmxsdk->state_change_cb(info->wmxsdk, + info->new_status, + info->old_status, + info->reason, + info->progress, + info->wmxsdk->callback_data); + } + wmxsdk_unref(info->wmxsdk); + memset(info, 0, sizeof(*info)); + free(info); + return FALSE; +} + +static void +_schedule_state_change(struct wmxsdk *wmxsdk, + WIMAX_API_DEVICE_STATUS new_status, + WIMAX_API_DEVICE_STATUS old_status, + WIMAX_API_STATUS_REASON reason, + WIMAX_API_CONNECTION_PROGRESS_INFO progress) +{ + StateChangeInfo *info; + + info = malloc(sizeof (*info)); + if (!info) + return; + + memset(info, 0, sizeof(*info)); + info->wmxsdk = wmxsdk; + info->new_status = new_status; + info->old_status = old_status; + info->reason = reason; + info->progress = progress; + + wmxsdk_ref(wmxsdk); + g_idle_add(state_change_handler, info); +} + +typedef struct { + struct wmxsdk *wmxsdk; + WIMAX_API_MEDIA_STATUS media_status; +} MediaStatusInfo; + +static gboolean +media_status_change_handler(gpointer user_data) +{ + MediaStatusInfo *info = user_data; + + if (info->wmxsdk->media_status_cb) { + info->wmxsdk->media_status_cb(info->wmxsdk, + info->media_status, + info->wmxsdk->callback_data); + } + wmxsdk_unref(info->wmxsdk); + memset(info, 0, sizeof(*info)); + free(info); + return FALSE; +} + +static void +_schedule_media_status_change(struct wmxsdk *wmxsdk, + WIMAX_API_MEDIA_STATUS media_status) +{ + MediaStatusInfo *info; + + info = malloc(sizeof (*info)); + if (!info) + return; + + memset(info, 0, sizeof(*info)); + info->wmxsdk = wmxsdk; + info->media_status = media_status; + + wmxsdk_ref(wmxsdk); + g_idle_add(media_status_change_handler, info); +} + +typedef struct { + struct wmxsdk *wmxsdk; + WIMAX_API_NETWORK_CONNECTION_RESP result; +} ConnectResultInfo; + +static gboolean +connect_result_handler(gpointer user_data) +{ + ConnectResultInfo *info = user_data; + + if (info->wmxsdk->connect_result_cb) { + info->wmxsdk->connect_result_cb(info->wmxsdk, + info->result, + info->wmxsdk->callback_data); + } + wmxsdk_unref(info->wmxsdk); + memset(info, 0, sizeof(*info)); + free(info); + return FALSE; +} + +static void +_schedule_connect_result(struct wmxsdk *wmxsdk, + WIMAX_API_NETWORK_CONNECTION_RESP resp) +{ + ConnectResultInfo *info; + + info = malloc(sizeof (*info)); + if (!info) + return; + + memset(info, 0, sizeof(*info)); + info->wmxsdk = wmxsdk; + info->result = resp; + + wmxsdk_ref(wmxsdk); + g_idle_add(connect_result_handler, info); +} + +typedef struct { + struct wmxsdk *wmxsdk; + WIMAX_API_NSP_INFO_EX *nsps; + guint num_nsps; +} ScanResultInfo; + +static gboolean +scan_result_handler(gpointer user_data) +{ + ScanResultInfo *info = user_data; + + if (info->wmxsdk->scan_result_cb) { + info->wmxsdk->scan_result_cb(info->wmxsdk, + info->nsps, + info->num_nsps, + info->wmxsdk->callback_data); + } + wmxsdk_unref(info->wmxsdk); + free(info->nsps); + memset(info, 0, sizeof(*info)); + free(info); + return FALSE; +} + +static void +_schedule_scan_result(struct wmxsdk *wmxsdk, + WIMAX_API_NSP_INFO_EX *nsps, + guint num_nsps) +{ + ScanResultInfo *info; + size_t nsps_size; + int i, tmp; + + info = malloc(sizeof (*info)); + if (!info) + return; + + memset(info, 0, sizeof(*info)); + info->wmxsdk = wmxsdk; + + nsps_size = num_nsps * sizeof (WIMAX_API_NSP_INFO_EX); + info->nsps = malloc(nsps_size); + memcpy(info->nsps, nsps, nsps_size); + info->num_nsps = num_nsps; + + /* CAPI may report link quality as zero -- if it does check if it is a bug + * by computing it based on CINR. If it is different, use the computed one. + */ + for (i = 0; i < num_nsps; i++) { + WIMAX_API_NSP_INFO_EX *nsp = &info->nsps[i]; + + if (nsp->linkQuality == 0) { + tmp = cinr_to_percentage(nsp->CINR - 10); + if (tmp != nsp->linkQuality) + nsp->linkQuality = tmp; + } + } + + wmxsdk_ref(wmxsdk); + g_idle_add(scan_result_handler, info); +} + +static gboolean +removed_handler(gpointer user_data) +{ + struct wmxsdk *wmxsdk = user_data; + + if (wmxsdk->removed_cb) + wmxsdk->removed_cb(wmxsdk, wmxsdk->callback_data); + wmxsdk_unref(wmxsdk); + return FALSE; +} + +static void +_schedule_removed(struct wmxsdk *wmxsdk) +{ + wmxsdk_ref(wmxsdk); + g_idle_add(removed_handler, wmxsdk); +} + +/****************************************************************/ + +/* + * Convert a WiMAX API status to an string. + */ +const char *iwmx_sdk_dev_status_to_str(WIMAX_API_DEVICE_STATUS status) +{ + switch (status) { + case WIMAX_API_DEVICE_STATUS_UnInitialized: + return "uninitialized"; + case WIMAX_API_DEVICE_STATUS_RF_OFF_HW_SW: + return "rf off"; + case WIMAX_API_DEVICE_STATUS_RF_OFF_HW: + return "rf off (hard-block)"; + case WIMAX_API_DEVICE_STATUS_RF_OFF_SW: + return "rf off (soft-block)"; + case WIMAX_API_DEVICE_STATUS_Ready: + return "ready"; + case WIMAX_API_DEVICE_STATUS_Scanning: + return "scanning"; + case WIMAX_API_DEVICE_STATUS_Connecting: + return "connecting"; + case WIMAX_API_DEVICE_STATUS_Data_Connected: + return "connected"; + default: + return "unknown"; + } +} + +const char *iwmx_sdk_reason_to_str(WIMAX_API_STATUS_REASON reason) +{ + switch (reason) { + case WIMAX_API_STATUS_REASON_Normal: + return "normal"; + + /**< Failed to complete NW entry with the selected operator (unspecified reason). */ + case WIMAX_API_STATUS_REASON_Fail_to_connect_to_NW: + return "unspecified failure"; + + /**< Failed to complete ranging */ + case WIMAX_API_STATUS_REASON_Fail_to_connect_Ranging: + return "ranging failed"; + + /**< SBC phase failed */ + case WIMAX_API_STATUS_REASON_Fail_to_connect_SBC: + return "sbc failed"; + + /**< Security error. EAP authentication failed device level */ + case WIMAX_API_STATUS_REASON_Fail_to_connect_EAP_AUTH_Device: + return "EAP device auth failed"; + + /**< Security error. EAP authentication failed user level */ + case WIMAX_API_STATUS_REASON_Fail_to_connect_EAP_AUTH_user: + return "EAP user auth failed"; + + /**< Security error. Handshake failed */ + case WIMAX_API_STATUS_REASON_Fail_to_connect_3_Way_Handshake: + return "3 way handshake failed"; + + /**< Registration failed */ + case WIMAX_API_STATUS_REASON_Fail_to_connect_REG: + return "registration failed"; + + /**< Failed to initialize the data path (failed to perform DSA to one UL and one DL SFs). */ + case WIMAX_API_STATUS_REASON_Fail_to_connect_datapath: + return "datapath failed"; + + default: + return "unknown"; + } +} + +const char *iwmx_sdk_media_status_to_str(WIMAX_API_MEDIA_STATUS status) +{ + switch (status) { + case WIMAX_API_MEDIA_STATUS_LINK_UP: + return "link-up"; + case WIMAX_API_MEDIA_STATUS_LINK_DOWN: + return "link-down"; + case WIMAX_API_MEDIA_STATUS_LINK_RENEW: + return "link-renew"; + default: + return "unknown"; + } +} + +const char * +iwmx_sdk_con_progress_to_str(WIMAX_API_CONNECTION_PROGRESS_INFO progress) +{ + switch (progress) { + + /**< Device is in Ranging */ + case WIMAX_API_DEVICE_CONNECTION_PROGRESS_Ranging: + return "ranging"; + + /**< Device is in SBC */ + case WIMAX_API_DEVICE_CONNECTION_PROGRESS_SBC: + return "sbc"; + + /**< Device is in EAP authentication Device */ + case WIMAX_API_DEVICE_CONNECTION_PROGRESS_EAP_authentication_Device: + return "eap-auth-device"; + + /**< Device is in EAP authentication User */ + case WIMAX_API_DEVICE_CONNECTION_PROGRESS_EAP_authentication_User: + return "eap-auth-user"; + + /**< Device is in 3-way-handshake */ + case WIMAX_API_DEVICE_CONNECTION_PROGRESS_3_way_handshake: + return "3way-handshake"; + + /**< Device is in Registration */ + case WIMAX_API_DEVICE_CONNECTION_PROGRESS_Registration: + return "registration"; + + /**< Device is in De-registration */ + case WIMAX_API_DEVICE_CONNECTION_PROGRESS_De_registration: + return "deregistration"; + + /**< Device is registered (operational) */ + case WIMAX_API_DEVICE_CONNECTION_PROGRESS_Registered: + return "registered"; + + default: + return "unknown"; + } +} + +/* + * Get the device's status from the device + * + * Does NOT cache the result + * Does NOT trigger a state change in NetworkManager + * + * Returns < 0 errno code on error, status code if ok. + */ +static WIMAX_API_DEVICE_STATUS iwmx_sdk_get_device_status(struct wmxsdk *wmxsdk) +{ + WIMAX_API_RET r; + char errstr[512]; + UINT32 errstr_size = sizeof(errstr); + + WIMAX_API_DEVICE_STATUS dev_status; + WIMAX_API_CONNECTION_PROGRESS_INFO pi; + + r = GetDeviceStatus(&wmxsdk->device_id, &dev_status, &pi); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot read device state: %d (%s)", r, errstr); + dev_status = -EIO; + } + return dev_status; +} + +/* + * Get the device's status from the device but return a string describing it + * + * Same conditions as iwmx_sdk_get_device_status(). + */ +static const char *iwmx_sdk_get_device_status_str(struct wmxsdk *wmxsdk) +{ + const char *result; + WIMAX_API_DEVICE_STATUS dev_status; + + dev_status = iwmx_sdk_get_device_status(wmxsdk); + if ((int) dev_status < 0) + result = "cannot read device state"; + else + result = iwmx_sdk_dev_status_to_str(dev_status); + return result; +} + +/* + * If the device is connected but we don't know about the network, + * create the knowledge of it. + * + * Asks the WiMAX API to report which NSP we are connected to and we + * create/update a network_el in the device's network list. Then + * return it. + * + * Returns NULL on error. + * + */ +WIMAX_API_CONNECTED_NSP_INFO_EX *iwmx_sdk_get_connected_network(struct wmxsdk *wmxsdk) +{ + WIMAX_API_CONNECTED_NSP_INFO_EX *nsp_info = NULL; + WIMAX_API_RET r; + char errstr[512]; + UINT32 errstr_size = sizeof(errstr); + + nsp_info = malloc(sizeof (*nsp_info)); + if (!nsp_info) { + nm_log_err(LOGD_WIMAX, "wmxsdk: cannot allocate NSP info"); + return NULL; + } + + r = GetConnectedNSPEx(&wmxsdk->device_id, nsp_info); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot get connected NSP info: %d (%s)", r, errstr); + free (nsp_info); + nsp_info = NULL; + } else { + /* Migth be 0 sometimes; fix that up */ + if (nsp_info->linkQuality == 0) { + int linkq_expected = cinr_to_percentage(nsp_info->CINR - 10); + if (linkq_expected != nsp_info->linkQuality) + nsp_info->linkQuality = linkq_expected; + } + } + + return nsp_info; +} + +/* + * Asks the WiMAX API to report current link statistics. + * + * Returns NULL on error. + * + */ +WIMAX_API_LINK_STATUS_INFO_EX *iwmx_sdk_get_link_status_info(struct wmxsdk *wmxsdk) +{ + WIMAX_API_LINK_STATUS_INFO_EX *stats = NULL; + WIMAX_API_RET r; + char errstr[512]; + UINT32 errstr_size = sizeof(errstr); + + /* Only report if connected */ + if (iwmxsdk_status_get(wmxsdk) < WIMAX_API_DEVICE_STATUS_Connecting) { + nm_log_err(LOGD_WIMAX, "wmxsdk: cannot get link status info unless connected"); + return NULL; + } + + stats = malloc(sizeof (*stats)); + if (!stats) { + nm_log_err(LOGD_WIMAX, "wmxsdk: cannot allocate links status info"); + return NULL; + } + + r = GetLinkStatusEx(&wmxsdk->device_id, stats); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot get link status info: %d (%s)", r, errstr); + free (stats); + stats = NULL; + } + + return stats; +} + +/* + * Callback for a RF State command + * + * Called by the WiMAX API when a command sent to change the RF state + * is completed. This is just a confirmation of what happened with the + * command. + * + * We don't do anything, as when the device changes state, the state + * change callback is called and that will fiddle with the NetworkManager + * internals. + */ +static void __iwmx_sdk_rf_state_cb(WIMAX_API_DEVICE_ID *device_id, + WIMAX_API_RF_STATE rf_state) +{ + nm_log_dbg(LOGD_WIMAX, "rf_state changed to %d", rf_state); +} + +/* + * Turn the radio on or off + * + * First it checks that we are in the right state before doing + * anything; there might be no need to do anything. + * + * Issue a command to the WiMAX API, wait for a callback confirming it + * is done. Sometimes the callback is missed -- in that case, do force + * a state change evaluation. + * + * Frustration note: + * + * Geezoos efing Xist, they make difficult even the most simple + * of the operations + * + * This thing is definitely a pain. If the radio is ON already + * and you switch it on again...well, there is no way to tell + * because you don't get a callback saying it basically + * suceeded. But on the other hand, if the thing was in a + * different state and action needs to be taken, you have to wait + * for a callback to confirm it's done. However, there is also an + * state change callback, which is almost the same, so now you + * have to handle things in two "unrelated" threads of execution. + * + * How the shpx are you expected to tell the difference? Check + * status first? On timeout? Nice gap (eighteen wheeler size) for + * race conditions. + */ +int iwmx_sdk_rf_state_set(struct wmxsdk *wmxsdk, WIMAX_API_RF_STATE rf_state) +{ + int result; + + WIMAX_API_RET r; + char errstr[512]; + UINT32 errstr_size = sizeof(errstr); + WIMAX_API_DEVICE_STATUS dev_status; + + g_assert(rf_state == WIMAX_API_RF_ON || rf_state == WIMAX_API_RF_OFF); + + /* Guess what the current radio state is; if it is ON + * already, don't redo it. */ + dev_status = iwmx_sdk_get_device_status(wmxsdk); + if ((int) dev_status < 0) { + result = dev_status; + goto error_get_status; + } + switch (dev_status) { + case WIMAX_API_DEVICE_STATUS_UnInitialized: + result = -EINVAL; + goto error_cant_do; + case WIMAX_API_DEVICE_STATUS_RF_OFF_HW_SW: + case WIMAX_API_DEVICE_STATUS_RF_OFF_HW: + nm_log_err(LOGD_WIMAX, "wmxsdk: cannot turn on radio: hw switch is off"); + result = -EPERM; + goto error_cant_do; + break; + case WIMAX_API_DEVICE_STATUS_RF_OFF_SW: + if (rf_state == WIMAX_API_RF_OFF) { + result = 0; + nm_log_dbg(LOGD_WIMAX, "radio is already off"); + goto out_done; + } + break; + case WIMAX_API_DEVICE_STATUS_Ready: + case WIMAX_API_DEVICE_STATUS_Scanning: + case WIMAX_API_DEVICE_STATUS_Connecting: + case WIMAX_API_DEVICE_STATUS_Data_Connected: + if (rf_state == WIMAX_API_RF_ON) { + result = 0; + nm_log_dbg(LOGD_WIMAX, "radio is already on"); + goto out_done; + } + break; + default: + g_assert(1); + } + /* Ok, flip the radio */ + r = CmdControlPowerManagement(&wmxsdk->device_id, rf_state); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot flip radio to %d: %d (%s) [device is in state %s]", + rf_state, r, errstr, iwmx_sdk_get_device_status_str(wmxsdk)); + result = -EIO; + } else + result = -EINPROGRESS; +out_done: +error_cant_do: +error_get_status: + return result; +} + +/* + * Read the cached device status + */ +WIMAX_API_DEVICE_STATUS iwmxsdk_status_get(struct wmxsdk *wmxsdk) +{ + WIMAX_API_DEVICE_STATUS status; + + g_mutex_lock(&wmxsdk->status_mutex); + status = wmxsdk->status; + g_mutex_unlock(&wmxsdk->status_mutex); + return status; +} + +/* + * Callback for a Connect command + * + * Called by the WiMAX API when a command sent to connect is + * completed. This is just a confirmation of what happened with the + * command. + * + * WE DON'T DO MUCH HERE -- the real meat happens when a state change + * callback is sent, where we detect we move to connected state (or + * from disconnecting to something else); the state change callback is + * called and that will fiddle with the NetworkManager internals. + */ +static void __iwmx_sdk_connect_cb(WIMAX_API_DEVICE_ID *device_id, + WIMAX_API_NETWORK_CONNECTION_RESP resp) +{ + WIMAX_API_DEVICE_STATUS status; + struct wmxsdk *wmxsdk = deviceid_to_wmxsdk(device_id); + + status = iwmxsdk_status_get(wmxsdk); + if (resp == WIMAX_API_CONNECTION_SUCCESS) { + if (status != WIMAX_API_DEVICE_STATUS_Data_Connected) { + nm_log_err(LOGD_WIMAX, "wmxsdk: error: connect worked, but state" + " didn't change (now it is %d [%s])", + status, + iwmx_sdk_dev_status_to_str(status)); + } + } else { + nm_log_err(LOGD_WIMAX, "wmxsdk: failed to connect (status %d: %s)", + status, iwmx_sdk_dev_status_to_str(status)); + } + + _schedule_connect_result(wmxsdk, resp); +} + +/* + * Connect to a network + * + * This function starts the connection process to a given network; + * when the device changes status, the status change callback will + * tell NetworkManager if the network is finally connected or not. + * + * One of the reasons it is done like that is to allow external tools + * to control the device and the plugin just passing the status so + * NetworkManager displays the right info. + */ +int iwmx_sdk_connect(struct wmxsdk *wmxsdk, const char *nsp_name) +{ + int result = 0; + + WIMAX_API_RET r; + char errstr[512]; + UINT32 errstr_size = sizeof(errstr); + WIMAX_API_DEVICE_STATUS dev_status; + char sdk_name[MAX_SIZE_OF_NSP_NAME]; + + g_mutex_lock(&wmxsdk->connect_mutex); + /* Guess what the current radio state is; if it is ON + * already, don't redo it. */ + dev_status = iwmxsdk_status_get(wmxsdk); + if ((int) dev_status < 0) { + result = dev_status; + goto error_get_status; + } + switch (dev_status) { + case WIMAX_API_DEVICE_STATUS_UnInitialized: + nm_log_err(LOGD_WIMAX, "wmxsdk: SW BUG? HW is uninitialized"); + result = -EINVAL; + goto error_cant_do; + case WIMAX_API_DEVICE_STATUS_RF_OFF_HW_SW: + case WIMAX_API_DEVICE_STATUS_RF_OFF_HW: + case WIMAX_API_DEVICE_STATUS_RF_OFF_SW: + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot connect: radio is off"); + result = -EPERM; + goto error_cant_do; + case WIMAX_API_DEVICE_STATUS_Ready: + case WIMAX_API_DEVICE_STATUS_Scanning: + break; + case WIMAX_API_DEVICE_STATUS_Connecting: + nm_log_dbg(LOGD_WIMAX, "Connect already pending, waiting for it"); + result = -EINPROGRESS; + goto error_cant_do; + case WIMAX_API_DEVICE_STATUS_Data_Connected: + nm_log_err(LOGD_WIMAX, "wmxsdk: BUG? need to disconnect?"); + result = -EINVAL; + goto error_cant_do; + default: + g_assert(1); + } + + /* The SDK treats the network name as wchar_t* while the contents are + * actually just UTF-8... WTF? Hand it a full buffer to work around + * boundary cases where the NSP name contains an odd # of characters. + */ + memset(sdk_name, 0, sizeof (sdk_name)); + memcpy(sdk_name, nsp_name, strlen (nsp_name)); + + /* Ok, do the connection, wait for a callback */ + r = CmdConnectToNetwork(&wmxsdk->device_id, &sdk_name[0], 0, 0); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot connect to network %s: %d (%s) - device is in state '%s'", + nsp_name, r, errstr, + iwmx_sdk_get_device_status_str(wmxsdk)); + result = -EIO; + } + +error_cant_do: +error_get_status: + g_mutex_unlock(&wmxsdk->connect_mutex); + return result; +} + +/* + * Callback for a Disconnect command + * + * Called by the WiMAX API when a command sent to connect is + * completed. This is just a confirmation of what happened with the + * command. + * + * When the device changes state, the state change callback is called + * and that will fiddle with the NetworkManager internals. + * + * We just update the result of the command and wake up anybody who is + * waiting for this conditional variable. + */ +static void __iwmx_sdk_disconnect_cb(WIMAX_API_DEVICE_ID *device_id, + WIMAX_API_NETWORK_CONNECTION_RESP resp) +{ + struct wmxsdk *wmxsdk = deviceid_to_wmxsdk(device_id); + WIMAX_API_DEVICE_STATUS status; + + status = iwmxsdk_status_get(wmxsdk); + if (resp == WIMAX_API_CONNECTION_SUCCESS) { + if (status == WIMAX_API_DEVICE_STATUS_Data_Connected) { + nm_log_err(LOGD_WIMAX, "wmxsdk: error: disconnect worked, " + "but state didn't change (now it is %d [%s])", status, + iwmx_sdk_dev_status_to_str(status)); + } + } else + nm_log_err(LOGD_WIMAX, "wmxsdk: failed to disconnect (status %d: %s)", + status, iwmx_sdk_dev_status_to_str(status)); +} + +/* + * Disconnect from a network + * + * This function tells the device to disconnect; the state change + * callback will take care of inform NetworkManager's internals. + */ +int iwmx_sdk_disconnect(struct wmxsdk *wmxsdk) +{ + int result; + + WIMAX_API_RET r; + char errstr[512]; + UINT32 errstr_size = sizeof(errstr); + WIMAX_API_DEVICE_STATUS dev_status; + + g_mutex_lock(&wmxsdk->connect_mutex); + /* Guess what the current radio state is; if it is ON + * already, don't redo it. */ + dev_status = iwmx_sdk_get_device_status(wmxsdk); + if ((int) dev_status < 0) { + result = dev_status; + goto error_get_status; + } + switch (dev_status) { + case WIMAX_API_DEVICE_STATUS_UnInitialized: + nm_log_err(LOGD_WIMAX, "wmxsdk: SW BUG? HW is uninitialized"); + result = -EINVAL; + goto error_cant_do; + case WIMAX_API_DEVICE_STATUS_RF_OFF_HW_SW: + case WIMAX_API_DEVICE_STATUS_RF_OFF_HW: + case WIMAX_API_DEVICE_STATUS_RF_OFF_SW: + nm_log_dbg(LOGD_WIMAX, "Cannot disconnect, radio is off; ignoring"); + result = 0; + goto error_cant_do; + case WIMAX_API_DEVICE_STATUS_Ready: + case WIMAX_API_DEVICE_STATUS_Scanning: + nm_log_dbg(LOGD_WIMAX, "Cannot disconnect, already disconnected; ignoring"); + result = 0; + goto error_cant_do; + case WIMAX_API_DEVICE_STATUS_Connecting: + case WIMAX_API_DEVICE_STATUS_Data_Connected: + break; + default: + g_assert(1); + } + /* Ok, flip the radio */ + r = CmdDisconnectFromNetwork(&wmxsdk->device_id); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot disconnect from network: %d (%s)", r, errstr); + result = -EIO; + } else + result = -EINPROGRESS; +error_cant_do: +error_get_status: + g_mutex_unlock(&wmxsdk->connect_mutex); + return result; +} + +/* + * Turn fast reconnect capability on/off + * + * This function tells wimaxd to turn fast reconnect on or off. + */ +int iwmx_sdk_set_fast_reconnect_enabled(struct wmxsdk *wmxsdk, int enabled) +{ + WIMAX_API_RET r; + char errstr[512]; + UINT32 errstr_size = sizeof(errstr); + + r = SetFastReconnectCapabilityStatus(&wmxsdk->device_id, !!enabled); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot set fast reconnect to %d: %d (%s)", + enabled, r, errstr); + return -EIO; + } + return 0; +} + +static void __iwmx_sdk_media_status_update_cb (WIMAX_API_DEVICE_ID_P device_id, + WIMAX_API_MEDIA_STATUS mediaStatus) +{ + struct wmxsdk *wmxsdk = deviceid_to_wmxsdk(device_id); + + /* Ignore redundant LINK_UP events */ + if ( mediaStatus == WIMAX_API_MEDIA_STATUS_LINK_UP + && wmxsdk->media_status == WIMAX_API_MEDIA_STATUS_LINK_UP) + return; + + wmxsdk->media_status = mediaStatus; + + nm_log_dbg(LOGD_WIMAX, "wmxsdk: media status change to (%d) %s", + mediaStatus, iwmx_sdk_media_status_to_str (mediaStatus)); + + _schedule_media_status_change(wmxsdk, mediaStatus); +} + +/* + * Callback for state change messages + * + * Just pass them to the state transition handler + */ +static void __iwmx_sdk_state_change_cb(WIMAX_API_DEVICE_ID *device_id, + WIMAX_API_DEVICE_STATUS status, + WIMAX_API_STATUS_REASON reason, + WIMAX_API_CONNECTION_PROGRESS_INFO pi) +{ + struct wmxsdk *wmxsdk = deviceid_to_wmxsdk(device_id); + WIMAX_API_DEVICE_STATUS old_status; + + nm_log_dbg(LOGD_WIMAX, "wmxsdk: state change to (%d) %s reason (%d) %s", + status, iwmx_sdk_dev_status_to_str (status), + reason, iwmx_sdk_reason_to_str (reason)); + + g_mutex_lock(&wmxsdk->status_mutex); + old_status = wmxsdk->status; + wmxsdk->status = status; + g_mutex_unlock(&wmxsdk->status_mutex); + + _schedule_state_change(wmxsdk, status, old_status, reason, pi); +} + +/* + * Called by _iwmx_sdk_*scan_cb() when [wide or preferred] scan results + * are available. + * + * From here we update NetworkManager's idea of which networks are available. + */ +static void __iwmx_sdk_scan_common_cb(WIMAX_API_DEVICE_ID *device_id, + WIMAX_API_NSP_INFO_EX *nsp_list, + UINT32 nsp_list_size) +{ + struct wmxsdk *wmxsdk = deviceid_to_wmxsdk(device_id); + + g_mutex_lock(&wmxsdk->network_mutex); + _schedule_scan_result(wmxsdk, nsp_list, nsp_list_size); + g_mutex_unlock(&wmxsdk->network_mutex); +} + +/* + * Called by the WiMAX API when we get a wide scan result + * + * We treat them same as wide, so we just call that. + */ +static void __iwmx_sdk_wide_scan_cb(WIMAX_API_DEVICE_ID *device_id, + WIMAX_API_NSP_INFO_EX *nsp_list, + UINT32 nsp_list_size) +{ + __iwmx_sdk_scan_common_cb(device_id, nsp_list, nsp_list_size); +} + +/* + * Called by the WiMAX API when we get a normal (non wide) scan result + * + * We treat them same as wide, so we just call that. + */ +static void __iwmx_sdk_scan_cb(WIMAX_API_DEVICE_ID *device_id, + WIMAX_API_NSP_INFO_EX *nsp_list, + UINT32 nsp_list_size, UINT32 searchProgress) +{ + __iwmx_sdk_scan_common_cb(device_id, nsp_list, nsp_list_size); +} + +/* + * Called to ask the device to scan for networks + * + * We don't really scan as the WiMAX SDK daemon scans in the + * background for us. We just get the results and hand them back via + * the scan_result_cb callback. + */ +int iwmx_sdk_get_networks(struct wmxsdk *wmxsdk) +{ + int result; + + UINT32 nsp_list_length = 10; + WIMAX_API_NSP_INFO_EX nsp_list[10]; /* FIXME: up to 32? */ + + WIMAX_API_RET r; + char errstr[512]; + UINT32 errstr_size = sizeof(errstr); + + r = GetNetworkListEx(&wmxsdk->device_id, nsp_list, &nsp_list_length); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot get network list: %d (%s)", r, errstr); + result = -EIO; + goto error_scan; + } + + if (nsp_list_length == 0) { + nm_log_dbg(LOGD_WIMAX, "no networks"); + } else + __iwmx_sdk_scan_common_cb(&wmxsdk->device_id, nsp_list, + nsp_list_length); + result = 0; +error_scan: + return result; +} + +/* + * Initialize the WiMAX API, register with it, setup callbacks + * + */ +static int iwmx_sdk_setup(struct wmxsdk *wmxsdk) +{ + int result, status; + + WIMAX_API_RET r; + + char errstr[512]; + UINT32 errstr_size = sizeof(errstr); + + result = -ENFILE; + + /* device_id initialized by iwmx_sdk_dev_add */ + + r = WiMaxDeviceOpen(&wmxsdk->device_id); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot open device: %d (%s)", r, errstr); + goto error_wimaxdeviceopen; + } + + /* + * We scan in auto mode (in the background) + * + * Otherwise is messy -- if we have NetworkManager triggering a scan + * when we call iwmx_nm_scan() -> iwmx_sdk_scan(), most of the + * times that causes a race condition when the UI asks for a + * scan right before displaying the network menu. As there is + * no way to cancel an ongoing scan before connecting, we are + * stuck. So we do auto bg and have iwmx_sdk_scan() just return + * the current network list. + */ + r = SetConnectionMode(&wmxsdk->device_id, + WIMAX_API_CONNECTION_AUTO_SCAN_MANUAL_CONNECT); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot set connectin mode to manual: %d (%s)", r, errstr); + goto error_connection_mode; + } + + r = SubscribeControlPowerManagement(&wmxsdk->device_id, + __iwmx_sdk_rf_state_cb); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot subscribe to radio change events: %u (%s)", r, errstr); + result = -EIO; + goto error_subscribe_rf_state; + } + + r = SubscribeDeviceStatusChange(&wmxsdk->device_id, + __iwmx_sdk_state_change_cb); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot subscribe to state chaneg events: %d (%s)", r, errstr); + goto error_subscribe_state_change; + } + + r = SubscribeNetworkSearchWideScanEx(&wmxsdk->device_id, + __iwmx_sdk_wide_scan_cb); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot subscribe to wide scan events: %d (%s)", r, errstr); + goto error_subscribe_wide_scan; + } + r = SubscribeNetworkSearchEx(&wmxsdk->device_id, __iwmx_sdk_scan_cb); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot subscribe to scan events: %d (%s)", r, errstr); + goto error_subscribe_scan; + } + + r = SubscribeConnectToNetwork(&wmxsdk->device_id, + __iwmx_sdk_connect_cb); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot subscribe to connect events: %d (%s)", r, errstr); + goto error_subscribe_connect; + } + + r = SubscribeDisconnectToNetwork(&wmxsdk->device_id, + __iwmx_sdk_disconnect_cb); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot subscribe to disconnect events: %d (%s)", r, errstr); + goto error_subscribe_disconnect; + } + + r = SubscribeMediaStatusUpdate(&wmxsdk->device_id, __iwmx_sdk_media_status_update_cb); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot subscribe to media status events: %d (%s)", r, errstr); + goto error_subscribe_media_status; + } + + status = iwmx_sdk_get_device_status(wmxsdk); + if ((int) status < 0) + status = WIMAX_API_DEVICE_STATUS_UnInitialized; + + g_mutex_lock(&wmxsdk->status_mutex); + wmxsdk->status = status; + g_mutex_unlock(&wmxsdk->status_mutex); + + _schedule_state_change(wmxsdk, + status, + WIMAX_API_DEVICE_STATUS_UnInitialized, + WIMAX_API_STATUS_REASON_Normal, + WIMAX_API_DEVICE_CONNECTION_PROGRESS_Ranging); + + return 0; + + UnsubscribeMediaStatusUpdate(&wmxsdk->device_id); +error_subscribe_media_status: + UnsubscribeDisconnectToNetwork(&wmxsdk->device_id); +error_subscribe_disconnect: + UnsubscribeConnectToNetwork(&wmxsdk->device_id); +error_subscribe_connect: + UnsubscribeNetworkSearchEx(&wmxsdk->device_id); +error_subscribe_scan: + UnsubscribeNetworkSearchWideScanEx(&wmxsdk->device_id); +error_subscribe_wide_scan: + UnsubscribeDeviceStatusChange(&wmxsdk->device_id); +error_subscribe_state_change: + UnsubscribeControlPowerManagement(&wmxsdk->device_id); +error_subscribe_rf_state: +error_connection_mode: + WiMaxDeviceClose(&wmxsdk->device_id); +error_wimaxdeviceopen: + return result; +} + +/* + * Called when a device is torn down + * + * Cleanup all that is done in iwmx_sdk_setup(). Remove callbacks, + * unregister from the WiMAX API. + */ +static void iwmx_sdk_remove(struct wmxsdk *wmxsdk) +{ + UnsubscribeMediaStatusUpdate(&wmxsdk->device_id); + UnsubscribeDisconnectToNetwork(&wmxsdk->device_id); + UnsubscribeConnectToNetwork(&wmxsdk->device_id); + UnsubscribeNetworkSearchEx(&wmxsdk->device_id); + UnsubscribeNetworkSearchWideScanEx(&wmxsdk->device_id); + UnsubscribeDeviceStatusChange(&wmxsdk->device_id); + UnsubscribeControlPowerManagement(&wmxsdk->device_id); + WiMaxDeviceClose(&wmxsdk->device_id); +} + +void iwmx_sdk_set_callbacks(struct wmxsdk *wmxsdk, + WimaxStateChangeFunc state_change_cb, + WimaxMediaStatusFunc media_status_cb, + WimaxConnectResultFunc connect_result_cb, + WimaxScanResultFunc scan_result_cb, + WimaxRemovedFunc removed_cb, + void *user_data) +{ + wmxsdk->state_change_cb = state_change_cb; + wmxsdk->media_status_cb = media_status_cb; + wmxsdk->connect_result_cb = connect_result_cb; + wmxsdk->scan_result_cb = scan_result_cb; + wmxsdk->removed_cb = removed_cb; + wmxsdk->callback_data = user_data; +} + +/* Initialize a [zeroed] struct wmxsdk */ +static struct wmxsdk *wmxsdk_new(void) +{ + struct wmxsdk *wmxsdk; + + wmxsdk = malloc(sizeof(*wmxsdk)); + if (wmxsdk) { + memset(wmxsdk, 0, sizeof(*wmxsdk)); + + wmxsdk->refcount = 1; + g_mutex_init(&wmxsdk->network_mutex); + + wmxsdk->status = WIMAX_API_DEVICE_STATUS_UnInitialized; + g_mutex_init(&wmxsdk->status_mutex); + + g_mutex_init(&wmxsdk->connect_mutex); + } + return wmxsdk; +} + +struct wmxsdk *wmxsdk_ref(struct wmxsdk *wmxsdk) +{ + g_atomic_int_add(&wmxsdk->refcount, 1); + return wmxsdk; +} + +void wmxsdk_unref(struct wmxsdk *wmxsdk) +{ + if (g_atomic_int_dec_and_test(&wmxsdk->refcount)) { + g_mutex_clear(&wmxsdk->status_mutex); + g_mutex_clear(&wmxsdk->connect_mutex); + memset(wmxsdk, 0, sizeof(*wmxsdk)); + free(wmxsdk); + } +} + +static void iwmx_sdk_dev_add(unsigned idx, unsigned api_idx, const char *name) +{ + struct wmxsdk *wmxsdk; + const char *s; + + if (idx >= IWMX_SDK_DEV_MAX) { + nm_log_err(LOGD_WIMAX, "BUG! idx (%u) >= IWMX_SDK_DEV_MAX (%u)", idx, IWMX_SDK_DEV_MAX); + return; + } + if (g_iwmx_sdk_devs[idx] != NULL) { + nm_log_err(LOGD_WIMAX, "BUG! device index %u already enumerated?", idx); + return; + } + + wmxsdk = wmxsdk_new(); + if (wmxsdk == NULL) { + nm_log_err(LOGD_WIMAX, "Can't allocate %zu bytes", sizeof(*wmxsdk)); + return; + } + + /* + * This depends on a hack in the WiMAX Network Service; it has + * to return, as part of the device name, a string "if:IFNAME" + * where the OS's device name is stored. + */ + s = strstr(name, "if:"); + if (s == NULL + || sscanf(s, "if:%15[^ \f\n\r\t\v]", wmxsdk->ifname) != 1) { + nm_log_err(LOGD_WIMAX, "Cannot extract network interface name off '%s'", + name); + goto error; + } + nm_log_dbg(LOGD_WIMAX, "network interface name: '%s'", wmxsdk->ifname); + + strncpy(wmxsdk->name, name, sizeof(wmxsdk->name)); + wmxsdk->device_id.privilege = WIMAX_API_PRIVILEGE_READ_WRITE; + wmxsdk->device_id.deviceIndex = api_idx; + + if (iwmx_sdk_setup(wmxsdk) != 0) { + nm_log_err(LOGD_WIMAX, "wxmsdk: %s: cannot set up interface", wmxsdk->ifname); + goto error; + } + + g_iwmx_sdk_devs[idx] = wmxsdk; + + /* Notify listeners of new devices */ + iwmx_sdk_call_new_callbacks (wmxsdk); + return; + +error: + wmxsdk_unref(wmxsdk); + return; +} + +static void iwmx_sdk_dev_rm(unsigned idx) +{ + struct wmxsdk *wmxsdk; + + if (idx >= IWMX_SDK_DEV_MAX) { + nm_log_err(LOGD_WIMAX, "BUG! idx (%u) >= IWMX_SDK_DEV_MAX (%u)", idx, IWMX_SDK_DEV_MAX); + return; + } + + wmxsdk = g_iwmx_sdk_devs[idx]; + _schedule_removed(wmxsdk); + iwmx_sdk_remove(wmxsdk); + wmxsdk_unref(wmxsdk); + g_iwmx_sdk_devs[idx] = NULL; +} + +static void iwmx_sdk_addremove_cb(WIMAX_API_DEVICE_ID *devid, + BOOL presence) +{ + unsigned int cnt; + WIMAX_API_RET r; + WIMAX_API_HW_DEVICE_ID device_id_list[5]; + UINT32 device_id_list_size = ARRAY_SIZE(device_id_list); + char errstr[512]; + UINT32 errstr_size = sizeof(errstr); + + g_mutex_lock(&add_remove_mutex); + + nm_log_dbg(LOGD_WIMAX, "cb: handle %u index #%u is %d", devid->sdkHandle, + devid->deviceIndex, presence); + + r = GetListDevice(devid, device_id_list, &device_id_list_size); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(devid, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot obtain list of devices: %d (%s)", r, errstr); + goto out; + } + + if (device_id_list_size == 0) { + nm_log_dbg(LOGD_WIMAX, "No WiMAX devices reported"); + } else { + for (cnt = 0; cnt < device_id_list_size; cnt++) { + WIMAX_API_HW_DEVICE_ID *dev = + device_id_list + cnt; + nm_log_dbg(LOGD_WIMAX, "#%u index #%u device %s", cnt, + dev->deviceIndex, dev->deviceName); + } + } + + if (presence) { + WIMAX_API_HW_DEVICE_ID *dev; + + /* Make sure the wimax NS isn't lying to us */ + if (device_id_list_size < devid->deviceIndex) { + nm_log_err(LOGD_WIMAX, "wmxsdk: changed device (%u) not in the list? (%u items)", + devid->deviceIndex, device_id_list_size); + goto out; + } + + /* Add the device to our internal list */ + dev = device_id_list + devid->deviceIndex; + iwmx_sdk_dev_add(devid->deviceIndex, dev->deviceIndex, dev->deviceName); + } else { + /* Remove the device from our internal list */ + int idx = deviceid_to_index(devid); + + if (idx >= 0) + iwmx_sdk_dev_rm(idx); + } + +out: + g_mutex_unlock(&add_remove_mutex); +} + +/* + * Initialize the WiMAX API, register with it, setup callbacks for + * device coming up / dissapearing + */ +int iwmx_sdk_api_init(void) +{ + int result; + unsigned int cnt; + WIMAX_API_RET r; + char errstr[512]; + UINT32 errstr_size = sizeof(errstr); + + WIMAX_API_HW_DEVICE_ID device_id_list[5]; + UINT32 device_id_list_size = ARRAY_SIZE(device_id_list); + + memset(&g_api, 0, sizeof(g_api)); + g_api.privilege = WIMAX_API_PRIVILEGE_READ_WRITE; + + result = -EIO; + r = WiMaxAPIOpen(&g_api); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&g_api, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: WiMaxAPIOpen failed with %d (%s)", r, errstr); + goto error_wimaxapiopen; + } + + r = SubscribeDeviceInsertRemove(&g_api, iwmx_sdk_addremove_cb); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&g_api, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: insert/remove subscribe failed with %d (%s)", r, errstr); + goto error_close; + } + + r = GetListDevice(&g_api, device_id_list, &device_id_list_size); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&g_api, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot obtain list of devices: %d (%s)", r, errstr); + goto error_close; + } + if (device_id_list_size < g_api.deviceIndex) { + nm_log_err(LOGD_WIMAX, "wmxsdk: changed device (%u) not in the list? (%u items)", + g_api.deviceIndex, device_id_list_size); + } + + if (device_id_list_size == 0) { + nm_log_dbg(LOGD_WIMAX, "No WiMAX devices reported"); + } else { + for (cnt = 0; cnt < device_id_list_size; cnt++) { + WIMAX_API_HW_DEVICE_ID *dev = device_id_list + cnt; + nm_log_dbg(LOGD_WIMAX, "#%u index #%u device %s", cnt, dev->deviceIndex, dev->deviceName); + iwmx_sdk_dev_add(cnt, dev->deviceIndex, dev->deviceName); + } + } + return 0; + +error_close: + WiMaxAPIClose(&g_api); +error_wimaxapiopen: + return result; +} + +void iwmx_sdk_api_exit(void) +{ + WIMAX_API_RET r; + + char errstr[512]; + UINT32 errstr_size = sizeof(errstr); + + r = WiMaxAPIClose(&g_api); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&g_api, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: WiMaxAPIClose failed with %d (%s)", r, errstr); + } + return; +} diff --git a/src/devices/wimax/iwmxsdk.h b/src/devices/wimax/iwmxsdk.h new file mode 100644 index 00000000..785ca8c2 --- /dev/null +++ b/src/devices/wimax/iwmxsdk.h @@ -0,0 +1,111 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * + * Copyright (C) 2011 Red Hat, Inc. All rights reserved. + * Copyright (C) 2007-2010 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef IWMXSDK_H +#define IWMXSDK_H + +#include +#include +#include + +struct wmxsdk; + +typedef void (*WimaxNewWmxsdkFunc) (struct wmxsdk *wmxsdk, void *user_data); + +typedef void (*WimaxStateChangeFunc) (struct wmxsdk *wmxsdk, + WIMAX_API_DEVICE_STATUS new_status, + WIMAX_API_DEVICE_STATUS old_status, + WIMAX_API_STATUS_REASON reason, + WIMAX_API_CONNECTION_PROGRESS_INFO info, + void *user_data); + +typedef void (*WimaxMediaStatusFunc) (struct wmxsdk *wmxsdk, + WIMAX_API_MEDIA_STATUS media_status, + void *user_data); + +typedef void (*WimaxConnectResultFunc) (struct wmxsdk *wmxsdk, + WIMAX_API_NETWORK_CONNECTION_RESP resp, + void *user_data); + +typedef void (*WimaxScanResultFunc) (struct wmxsdk *wmxsdk, + WIMAX_API_NSP_INFO_EX *nsps, + guint num_nsps, + void *user_data); + +typedef void (*WimaxRemovedFunc) (struct wmxsdk *wmxsdk, void *user_data); + +struct wmxsdk { + gint refcount; + + WIMAX_API_DEVICE_ID device_id; + + WimaxStateChangeFunc state_change_cb; + WimaxMediaStatusFunc media_status_cb; + WimaxConnectResultFunc connect_result_cb; + WimaxScanResultFunc scan_result_cb; + WimaxRemovedFunc removed_cb; + void *callback_data; + + GMutex network_mutex; + + WIMAX_API_DEVICE_STATUS status; + WIMAX_API_MEDIA_STATUS media_status; + GMutex status_mutex; + + GMutex connect_mutex; + + char name[100]; + char ifname[16]; +}; + +struct wmxsdk *iwmx_sdk_get_wmxsdk_for_iface(const char *iface); + +struct wmxsdk *wmxsdk_ref(struct wmxsdk *wmxsdk); +void wmxsdk_unref(struct wmxsdk *wmxsdk); + +/* Register/unregister callbacks when a new wmxsdk is set up */ +void iwmx_sdk_new_callback_register(WimaxNewWmxsdkFunc callback, void *user_data); +void iwmx_sdk_new_callback_unregister(WimaxNewWmxsdkFunc callback, void *user_data); + +void iwmx_sdk_set_callbacks(struct wmxsdk *wmxsdk, + WimaxStateChangeFunc state_change_cb, + WimaxMediaStatusFunc media_status_func, + WimaxConnectResultFunc connect_result_cb, + WimaxScanResultFunc scan_result_cb, + WimaxRemovedFunc removed_cb, + void *user_data); + +WIMAX_API_DEVICE_STATUS iwmxsdk_status_get(struct wmxsdk *wmxsdk); +int iwmx_sdk_connect(struct wmxsdk *wmxsdk, const char *nsp_name); +int iwmx_sdk_disconnect(struct wmxsdk *wmxsdk); +int iwmx_sdk_set_fast_reconnect_enabled(struct wmxsdk *wmxsdk, int enabled); +WIMAX_API_CONNECTED_NSP_INFO_EX *iwmx_sdk_get_connected_network(struct wmxsdk *wmxsdk); +WIMAX_API_LINK_STATUS_INFO_EX *iwmx_sdk_get_link_status_info(struct wmxsdk *wmxsdk); +const char *iwmx_sdk_dev_status_to_str(WIMAX_API_DEVICE_STATUS status); +const char *iwmx_sdk_reason_to_str(WIMAX_API_STATUS_REASON reason); +const char *iwmx_sdk_media_status_to_str(WIMAX_API_MEDIA_STATUS status); +const char *iwmx_sdk_con_progress_to_str(WIMAX_API_CONNECTION_PROGRESS_INFO progress); +int iwmx_sdk_rf_state_set(struct wmxsdk *wmxsdk, WIMAX_API_RF_STATE rf_state); +int iwmx_sdk_get_networks(struct wmxsdk *wmxsdk); +int iwmx_sdk_api_init(void); +void iwmx_sdk_api_exit(void); + +#endif /* IWMXSDK_H */ diff --git a/src/devices/wimax/nm-device-wimax.c b/src/devices/wimax/nm-device-wimax.c new file mode 100644 index 00000000..1bdda489 --- /dev/null +++ b/src/devices/wimax/nm-device-wimax.c @@ -0,0 +1,1445 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2010 - 2011 Red Hat, Inc. + * Copyright (C) 2009 Novell, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "nm-device-wimax.h" +#include "nm-wimax-util.h" +#include "nm-logging.h" +#include "nm-device-private.h" +#include "NetworkManagerUtils.h" +#include "nm-dbus-manager.h" +#include "nm-connection.h" +#include "nm-setting-connection.h" +#include "nm-setting-wimax.h" +#include "nm-utils.h" +#include "nm-rfkill-manager.h" +#include "iwmxsdk.h" +#include "nm-enum-types.h" +#include "nm-dbus-glib-types.h" + +static gboolean impl_device_get_nsp_list (NMDeviceWimax *device, GPtrArray **list, GError **error); + +#include "nm-device-wimax-glue.h" + +G_DEFINE_TYPE (NMDeviceWimax, nm_device_wimax, NM_TYPE_DEVICE) + +enum { + PROP_0, + PROP_NSPS, + PROP_ACTIVE_NSP, + PROP_CENTER_FREQ, + PROP_RSSI, + PROP_CINR, + PROP_TX_POWER, + PROP_BSID, + + LAST_PROP +}; + +enum { + NSP_ADDED, + NSP_REMOVED, + + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +#define NM_DEVICE_WIMAX_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \ + NM_TYPE_DEVICE_WIMAX, \ + NMDeviceWimaxPrivate)) + +typedef struct { + gboolean disposed; + + struct wmxsdk *sdk; + WIMAX_API_DEVICE_STATUS status; + gboolean connect_failed; + + gboolean enabled; + gboolean wimaxd_enabled; + guint activation_timeout_id; + + /* Track whether stage1 (Prepare) is completed yet or not */ + gboolean prepare_done; + + guint sdk_action_defer_id; + + guint link_timeout_id; + guint poll_id; + + GSList *nsp_list; + NMWimaxNsp *current_nsp; + + /* interesting stuff when connected */ + guint center_freq; + gint rssi; + gint cinr; + gint tx_power; + char *bsid; +} NMDeviceWimaxPrivate; + +/***********************************************************/ + +#define NM_WIMAX_ERROR (nm_wimax_error_quark ()) + +static GQuark +nm_wimax_error_quark (void) +{ + static GQuark quark = 0; + if (!quark) + quark = g_quark_from_static_string ("nm-wimax-error"); + return quark; +} + +/***********************************************************/ + +static gboolean +impl_device_get_nsp_list (NMDeviceWimax *self, GPtrArray **nsps, GError **error) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + GSList *iter; + + *nsps = g_ptr_array_sized_new (4); + for (iter = priv->nsp_list; iter; iter = iter->next) + g_ptr_array_add (*nsps, g_strdup (nm_wimax_nsp_get_dbus_path (NM_WIMAX_NSP (iter->data)))); + + return TRUE; +} + +static void +set_current_nsp (NMDeviceWimax *self, NMWimaxNsp *new_nsp) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + NMWimaxNsp *old_nsp; + gboolean path_changed = FALSE; + + old_nsp = priv->current_nsp; + priv->current_nsp = NULL; + + if (new_nsp) + priv->current_nsp = g_object_ref (new_nsp); + + if (old_nsp && new_nsp) { + path_changed = (g_strcmp0 (nm_wimax_nsp_get_dbus_path (old_nsp), + nm_wimax_nsp_get_dbus_path (new_nsp)) != 0); + } + + /* Only notify if it's really changed */ + if (old_nsp != new_nsp || path_changed) + g_object_notify (G_OBJECT (self), NM_DEVICE_WIMAX_ACTIVE_NSP); + + if (old_nsp) + g_object_unref (old_nsp); +} + +static gboolean +activation_timed_out (gpointer data) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (data); + + priv->activation_timeout_id = 0; + nm_device_state_changed (NM_DEVICE (data), NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_CONFIG_FAILED); + + return FALSE; +} + +static void +emit_nsp_added_removed (NMDeviceWimax *self, + guint signum, + NMWimaxNsp *nsp, + gboolean recheck_available_connections) +{ + g_signal_emit (self, signals[signum], 0, nsp); + g_object_notify (G_OBJECT (self), NM_DEVICE_WIMAX_NSPS); + nm_device_emit_recheck_auto_activate (NM_DEVICE (self)); + if (recheck_available_connections) + nm_device_recheck_available_connections (NM_DEVICE (self)); +} + +static void +remove_all_nsps (NMDeviceWimax *self) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + + set_current_nsp (self, NULL); + + while (priv->nsp_list) { + NMWimaxNsp *nsp = NM_WIMAX_NSP (priv->nsp_list->data); + + priv->nsp_list = g_slist_remove (priv->nsp_list, nsp); + emit_nsp_added_removed (self, NSP_REMOVED, nsp, FALSE); + g_object_unref (nsp); + } + + nm_device_recheck_available_connections (NM_DEVICE (self)); +} + +static NMWimaxNsp * +get_nsp_by_name (NMDeviceWimax *self, const char *name) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + GSList *iter; + + g_return_val_if_fail (name, NULL); + + for (iter = priv->nsp_list; iter; iter = iter->next) { + NMWimaxNsp *nsp = NM_WIMAX_NSP (iter->data); + + if (!g_strcmp0 (nm_wimax_nsp_get_name (nsp), name)) + return nsp; + } + + return NULL; +} + +static NMWimaxNsp * +get_nsp_by_path (NMDeviceWimax *self, const char *path) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + GSList *iter; + + g_return_val_if_fail (path, NULL); + + for (iter = priv->nsp_list; iter; iter = iter->next) { + NMWimaxNsp *nsp = NM_WIMAX_NSP (iter->data); + + if (!strcmp (nm_wimax_nsp_get_dbus_path (nsp), path)) + return nsp; + } + + return NULL; +} + +static gboolean +update_availability (NMDeviceWimax *self, gboolean old_available) +{ + NMDevice *device = NM_DEVICE (self); + NMDeviceState state; + gboolean new_available, changed = FALSE; + + new_available = nm_device_is_available (device); + if (new_available == old_available) + return FALSE; + + state = nm_device_get_state (device); + if (state == NM_DEVICE_STATE_UNAVAILABLE) { + if (new_available == TRUE) { + nm_device_state_changed (device, + NM_DEVICE_STATE_DISCONNECTED, + NM_DEVICE_STATE_REASON_NONE); + changed = TRUE; + } + } else if (state >= NM_DEVICE_STATE_DISCONNECTED) { + if (new_available == FALSE) { + nm_device_state_changed (device, + NM_DEVICE_STATE_UNAVAILABLE, + NM_DEVICE_STATE_REASON_NONE); + changed = TRUE; + } + } + + return changed; +} + +/* NMDeviceInterface interface */ + +static void +set_enabled (NMDevice *device, gboolean enabled) +{ + NMDeviceWimax *self = NM_DEVICE_WIMAX (device); + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + gboolean old_available; + int ret; + const char *iface; + + iface = nm_device_get_iface (NM_DEVICE (self)); + + nm_log_dbg (LOGD_WIMAX, "(%s): setting radio enabled %d -> %d", + iface, priv->enabled, enabled); + if (priv->enabled == enabled) + return; + + old_available = nm_device_is_available (NM_DEVICE (device)); + priv->enabled = enabled; + + nm_log_dbg (LOGD_WIMAX, "(%s): radio now %s", + iface, priv->enabled ? "enabled" : "disabled"); + + /* Set the WiMAX device RF state to the current user-specified enabled state */ + if (priv->sdk) { + ret = iwmx_sdk_rf_state_set (priv->sdk, + enabled ? WIMAX_API_RF_ON : WIMAX_API_RF_OFF); + if (ret < 0 && ret != -EINPROGRESS) { + nm_log_warn (LOGD_WIMAX, "(%s): failed to %s radio", + iface, priv->enabled ? "enable" : "disable"); + } + } + + update_availability (self, old_available); +} + +/* NMDevice methods */ + +static gboolean +check_connection_compatible (NMDevice *device, NMConnection *connection) +{ + NMSettingConnection *s_con; + NMSettingWimax *s_wimax; + const char *connection_type; + const GByteArray *mac; + + if (!NM_DEVICE_CLASS (nm_device_wimax_parent_class)->check_connection_compatible (device, connection)) + return FALSE; + + s_con = nm_connection_get_setting_connection (connection); + g_assert (s_con); + + connection_type = nm_setting_connection_get_connection_type (s_con); + if (strcmp (connection_type, NM_SETTING_WIMAX_SETTING_NAME)) + return FALSE; + + s_wimax = nm_connection_get_setting_wimax (connection); + if (!s_wimax) + return FALSE; + + mac = nm_setting_wimax_get_mac_address (s_wimax); + if (mac && memcmp (mac->data, nm_device_get_hw_address (device, NULL), ETH_ALEN)) + return FALSE; + + return TRUE; +} + +static gboolean +check_connection_available (NMDevice *device, + NMConnection *connection, + const char *specific_object) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (device); + const GSList *ns_iter = NULL; + NMWimaxNsp *nsp; + + if (specific_object) { + nsp = get_nsp_by_path (NM_DEVICE_WIMAX (device), specific_object); + return nsp ? nm_wimax_nsp_check_compatible (nsp, connection) : FALSE; + } + + /* Ensure the connection applies to an NSP in the scan list */ + for (ns_iter = priv->nsp_list; ns_iter; ns_iter = ns_iter->next) { + if (nm_wimax_nsp_check_compatible (NM_WIMAX_NSP (ns_iter->data), connection)) + return TRUE; + } + + return FALSE; +} + +static gboolean +complete_connection (NMDevice *device, + NMConnection *connection, + const char *specific_object, + const GSList *existing_connections, + GError **error) +{ + NMDeviceWimax *self = NM_DEVICE_WIMAX (device); + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + NMSettingWimax *s_wimax; + const GByteArray *setting_mac; + const guint8 *hw_address; + char *format; + const char *nsp_name = NULL; + NMWimaxNsp *nsp = NULL; + GSList *iter; + + s_wimax = nm_connection_get_setting_wimax (connection); + + if (!specific_object) { + /* If not given a specific object, we need at minimum an NSP name */ + if (!s_wimax) { + g_set_error_literal (error, + NM_WIMAX_ERROR, + NM_WIMAX_ERROR_CONNECTION_INVALID, + "A 'wimax' setting is required if no NSP path was given."); + return FALSE; + } + + nsp_name = nm_setting_wimax_get_network_name (s_wimax); + if (!nsp_name || !strlen (nsp_name)) { + g_set_error_literal (error, + NM_WIMAX_ERROR, + NM_WIMAX_ERROR_CONNECTION_INVALID, + "A 'wimax' setting with a valid network name is required if no NSP path was given."); + return FALSE; + } + + /* Find a compatible NSP in the list */ + nsp = get_nsp_by_name (self, nsp_name); + + /* If we still don't have an NSP, then the WiMAX settings needs to be + * fully specified by the client. Might not be able to find the NSP + * if the scan didn't find the NSP yet. + */ + if (!nsp) { + if (!nm_setting_verify (NM_SETTING (s_wimax), NULL, error)) + return FALSE; + } + } else { + /* Find a compatible NSP in the list */ + for (iter = priv->nsp_list; iter; iter = g_slist_next (iter)) { + if (!strcmp (specific_object, nm_wimax_nsp_get_dbus_path (NM_WIMAX_NSP (iter->data)))) { + nsp = NM_WIMAX_NSP (iter->data); + break; + } + } + + if (!nsp) { + g_set_error (error, + NM_WIMAX_ERROR, + NM_WIMAX_ERROR_NSP_NOT_FOUND, + "The NSP %s was not in the scan list.", + specific_object); + return FALSE; + } + + nsp_name = nm_wimax_nsp_get_name (nsp); + } + + /* Add a WiMAX setting if one doesn't exist */ + if (!s_wimax) { + s_wimax = (NMSettingWimax *) nm_setting_wimax_new (); + nm_connection_add_setting (connection, NM_SETTING (s_wimax)); + } + + g_assert (nsp_name); + format = g_strdup_printf ("%s %%d", nsp_name); + nm_utils_complete_generic (connection, + NM_SETTING_WIMAX_SETTING_NAME, + existing_connections, + format, + nsp_name, + TRUE); + g_free (format); + g_object_set (G_OBJECT (s_wimax), NM_SETTING_WIMAX_NETWORK_NAME, nsp_name, NULL); + + setting_mac = nm_setting_wimax_get_mac_address (s_wimax); + hw_address = nm_device_get_hw_address (device, NULL); + if (setting_mac) { + /* Make sure the setting MAC (if any) matches the device's permanent MAC */ + if (memcmp (setting_mac->data, hw_address, ETH_ALEN)) { + g_set_error (error, + NM_SETTING_WIMAX_ERROR, + NM_SETTING_WIMAX_ERROR_INVALID_PROPERTY, + NM_SETTING_WIMAX_MAC_ADDRESS); + return FALSE; + } + } else { + GByteArray *mac; + const guint8 null_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; + + /* Lock the connection to this device by default */ + if (memcmp (hw_address, null_mac, ETH_ALEN)) { + mac = g_byte_array_sized_new (ETH_ALEN); + g_byte_array_append (mac, hw_address, ETH_ALEN); + g_object_set (G_OBJECT (s_wimax), NM_SETTING_WIMAX_MAC_ADDRESS, mac, NULL); + g_byte_array_free (mac, TRUE); + } + } + + return TRUE; +} + +static gboolean +can_auto_connect (NMDevice *device, + NMConnection *connection, + char **specific_object) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (device); + GSList *iter; + + if (!NM_DEVICE_CLASS (nm_device_wimax_parent_class)->can_auto_connect (device, connection, specific_object)) + return FALSE; + + for (iter = priv->nsp_list; iter; iter = iter->next) { + NMWimaxNsp *nsp = NM_WIMAX_NSP (iter->data); + + if (nm_wimax_nsp_check_compatible (nsp, connection)) { + *specific_object = (char *) nm_wimax_nsp_get_dbus_path (nsp); + return TRUE; + } + } + + return FALSE; +} + +static gboolean +is_available (NMDevice *device) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (device); + const char *iface = nm_device_get_iface (device); + + if (!priv->enabled) { + nm_log_dbg (LOGD_WIMAX, "(%s): not available because not enabled", iface); + return FALSE; + } + + if (!priv->wimaxd_enabled) { + nm_log_dbg (LOGD_WIMAX, "(%s): not available because not enabled in wimaxd", iface); + return FALSE; + } + + if (!nm_wimax_util_sdk_is_initialized ()) { + nm_log_dbg (LOGD_WIMAX, "(%s): not available because WiMAX SDK not initialized", iface); + return FALSE; + } + + if (!priv->sdk) { + nm_log_dbg (LOGD_WIMAX, "(%s): not available because not known to WiMAX SDK", iface); + return FALSE; + } + + return iwmxsdk_status_get (priv->sdk) >= WIMAX_API_DEVICE_STATUS_Ready; +} + +static void +clear_activation_timeout (NMDeviceWimax *self) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + + if (priv->activation_timeout_id) { + g_source_remove (priv->activation_timeout_id); + priv->activation_timeout_id = 0; + } + + priv->connect_failed = FALSE; +} + +static void +clear_link_timeout (NMDeviceWimax *self) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + + if (priv->link_timeout_id) { + g_source_remove (priv->link_timeout_id); + priv->link_timeout_id = 0; + } +} + +static void +clear_connected_poll (NMDeviceWimax *self) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + + if (priv->poll_id) { + g_source_remove (priv->poll_id); + priv->poll_id = 0; + } +} + +static NMActStageReturn +act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (device); + NMActRequest *req; + GSList *iter; + const char *path; + NMWimaxNsp *nsp = NULL; + + clear_link_timeout (NM_DEVICE_WIMAX (device)); + + *reason = NM_DEVICE_STATE_REASON_NONE; + + req = nm_device_get_act_request (device); + if (!req) + return NM_ACT_STAGE_RETURN_FAILURE; + + path = nm_active_connection_get_specific_object (NM_ACTIVE_CONNECTION (req)); + if (!path) + return NM_ACT_STAGE_RETURN_FAILURE; + + /* Find the NSP in the scan list */ + for (iter = priv->nsp_list; iter; iter = iter->next) { + NMWimaxNsp *candidate = NM_WIMAX_NSP (iter->data); + + if (!strcmp (path, nm_wimax_nsp_get_dbus_path (candidate))) { + nsp = candidate; + break; + } + } + + /* Couldn't find the NSP for some reason */ + if (nsp == NULL) + return NM_ACT_STAGE_RETURN_FAILURE; + + set_current_nsp (NM_DEVICE_WIMAX (device), nsp); + + priv->prepare_done = TRUE; + + /* If the device is scanning, it won't connect, so we have to wait until + * it's not scanning to proceed to stage 2. + */ + if (priv->status == WIMAX_API_DEVICE_STATUS_Scanning) + return NM_ACT_STAGE_RETURN_POSTPONE; + + return NM_ACT_STAGE_RETURN_SUCCESS; +} + +static NMActStageReturn +act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (device); + NMConnection *connection; + NMSettingWimax *s_wimax; + const char *nsp_name, *iface; + int ret; + + iface = nm_device_get_iface (device); + g_assert (iface); + + connection = nm_device_get_connection (device); + g_assert (connection); + + s_wimax = nm_connection_get_setting_wimax (connection); + g_assert (s_wimax); + + nsp_name = nm_setting_wimax_get_network_name (s_wimax); + g_assert (nsp_name); + + nm_log_info (LOGD_WIMAX, "(%s): connecting to NSP '%s'", + iface, nsp_name); + + priv->connect_failed = FALSE; + ret = iwmx_sdk_connect (priv->sdk, nsp_name); + if (ret < 0 && ret != -EINPROGRESS) { + nm_log_err (LOGD_WIMAX, "(%s): failed to connect to NSP '%s'", + iface, nsp_name); + *reason = NM_DEVICE_STATE_REASON_CONFIG_FAILED; + return NM_ACT_STAGE_RETURN_FAILURE; + } + + /* FIXME: Is 40 seconds good estimation? I have no idea */ + priv->activation_timeout_id = g_timeout_add_seconds (40, activation_timed_out, device); + + return NM_ACT_STAGE_RETURN_POSTPONE; +} + +static void +force_disconnect (NMDeviceWimax *self, struct wmxsdk *sdk) +{ + WIMAX_API_DEVICE_STATUS status; + int ret; + const char *iface; + + g_return_if_fail (sdk != NULL); + + iface = nm_device_get_iface (NM_DEVICE (self)); + + status = iwmxsdk_status_get (sdk); + if ((int) status < 0) { + nm_log_err (LOGD_WIMAX, "(%s): failed to read WiMAX device status: %d", + iface, status); + return; + } + + if ( status == WIMAX_API_DEVICE_STATUS_Connecting + || status == WIMAX_API_DEVICE_STATUS_Data_Connected) { + nm_log_dbg (LOGD_WIMAX, "(%s): requesting disconnect", iface); + ret = iwmx_sdk_disconnect (sdk); + if (ret < 0 && ret != -EINPROGRESS) { + nm_log_err (LOGD_WIMAX, "(%s): failed to disconnect WiMAX device: %d", + iface, ret); + } + } +} + +static void +deactivate (NMDevice *device) +{ + NMDeviceWimax *self = NM_DEVICE_WIMAX (device); + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + + clear_activation_timeout (self); + clear_link_timeout (self); + clear_connected_poll (self); + + set_current_nsp (self, NULL); + + if (priv->sdk) { + /* Read explicit status here just to make sure we have the most + * up-to-date status and to ensure we disconnect if needed. + */ + force_disconnect (self, priv->sdk); + } +} + +/*************************************************************************/ + +static void +wmx_state_change_cb (struct wmxsdk *wmxsdk, + WIMAX_API_DEVICE_STATUS new_status, + WIMAX_API_DEVICE_STATUS old_status, + WIMAX_API_STATUS_REASON reason, + WIMAX_API_CONNECTION_PROGRESS_INFO progress, + void *user_data) +{ + NMDeviceWimax *self = NM_DEVICE_WIMAX (user_data); + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + NMDeviceState state; + const char *iface; + gboolean old_available = FALSE; + const char *nsp_name = NULL; + + iface = nm_device_get_iface (NM_DEVICE (self)); + nm_log_info (LOGD_WIMAX, "(%s): wimax state change %s -> %s (%s (%d))", + iface, + iwmx_sdk_dev_status_to_str (old_status), + iwmx_sdk_dev_status_to_str (new_status), + iwmx_sdk_con_progress_to_str (progress), + progress); + + if (new_status == old_status) + return; + + state = nm_device_get_state (NM_DEVICE (self)); + old_available = nm_device_is_available (NM_DEVICE (self)); + + priv->status = new_status; + if (priv->current_nsp) + nsp_name = nm_wimax_nsp_get_name (priv->current_nsp); + + switch (new_status) { + case WIMAX_API_DEVICE_STATUS_UnInitialized: + case WIMAX_API_DEVICE_STATUS_RF_OFF_HW_SW: + case WIMAX_API_DEVICE_STATUS_RF_OFF_HW: + case WIMAX_API_DEVICE_STATUS_RF_OFF_SW: + if (priv->wimaxd_enabled) { + priv->wimaxd_enabled = FALSE; + if (update_availability (self, old_available)) + return; + } + break; + case WIMAX_API_DEVICE_STATUS_Connecting: + case WIMAX_API_DEVICE_STATUS_Data_Connected: + /* If for some reason we're initially connected, force a disconnect here */ + if (state < NM_DEVICE_STATE_DISCONNECTED) + force_disconnect (self, wmxsdk); + /* Fall through */ + case WIMAX_API_DEVICE_STATUS_Ready: + case WIMAX_API_DEVICE_STATUS_Scanning: + if (priv->wimaxd_enabled == FALSE) { + priv->wimaxd_enabled = TRUE; + if (update_availability (self, old_available)) + return; + } + break; + default: + nm_log_warn (LOGD_WIMAX, "(%s): unhandled WiMAX device state %d", + iface, new_status); + break; + } + + /* Handle activation success and failure */ + if (nm_device_is_activating (NM_DEVICE (self))) { + if (new_status == WIMAX_API_DEVICE_STATUS_Data_Connected) { + /* Success */ + clear_activation_timeout (self); + + nm_log_info (LOGD_WIMAX, "(%s): connected to '%s'", + iface, nsp_name); + nm_device_activate_schedule_stage3_ip_config_start (NM_DEVICE (self)); + return; + } + + if (priv->connect_failed) { + /* Connection attempt failed */ + nm_log_info (LOGD_WIMAX, "(%s): connection to '%s' failed: (%d) %s", + iface, nsp_name, reason, iwmx_sdk_reason_to_str (reason)); + nm_device_state_changed (NM_DEVICE (self), + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_CONFIG_FAILED); + return; + } + + /* If stage2 was postponed because the device was scanning or something, + * then check if we need to move to stage2 now that the device might be + * ready. + */ + if (state == NM_DEVICE_STATE_PREPARE && priv->prepare_done) { + if ( new_status == WIMAX_API_DEVICE_STATUS_Ready + || new_status == WIMAX_API_DEVICE_STATUS_Connecting) { + nm_device_activate_schedule_stage2_device_config (NM_DEVICE (self)); + return; + } + } + } + + /* Handle disconnection */ + if (state == NM_DEVICE_STATE_ACTIVATED) { + if ( old_status == WIMAX_API_DEVICE_STATUS_Data_Connected + && new_status < WIMAX_API_DEVICE_STATUS_Connecting) { + + nm_log_info (LOGD_WIMAX, "(%s): disconnected from '%s': (%d) %s", + iface, nsp_name, reason, iwmx_sdk_reason_to_str (reason)); + + nm_device_state_changed (NM_DEVICE (self), + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_CONFIG_FAILED); + } + } +} + +static gboolean +link_timeout_cb (gpointer user_data) +{ + NMDeviceWimax *self = NM_DEVICE_WIMAX (user_data); + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + + priv->link_timeout_id = 0; + + nm_log_dbg (LOGD_WIMAX, "(%s): link timed out", nm_device_get_iface (NM_DEVICE (self))); + nm_device_state_changed (NM_DEVICE (self), + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_CARRIER); + + return FALSE; +} + +static void +wmx_media_status_cb (struct wmxsdk *wmxsdk, + WIMAX_API_MEDIA_STATUS new_status, + void *user_data) +{ + NMDeviceWimax *self = NM_DEVICE_WIMAX (user_data); + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + NMDeviceState state; + const char *iface; + + iface = nm_device_get_iface (NM_DEVICE (self)); + state = nm_device_get_state (NM_DEVICE (self)); + + nm_log_dbg (LOGD_WIMAX, "(%s): media status change to %s", + iface, iwmx_sdk_media_status_to_str (new_status)); + + /* We only care about media events while activated */ + if (state != NM_DEVICE_STATE_ACTIVATED) + return; + + clear_link_timeout (self); + + switch (new_status) { + case WIMAX_API_MEDIA_STATUS_LINK_UP: + break; + case WIMAX_API_MEDIA_STATUS_LINK_DOWN: + nm_log_dbg (LOGD_WIMAX, "(%s): starting link timeout", iface); + priv->link_timeout_id = g_timeout_add_seconds (15, link_timeout_cb, self); + break; + case WIMAX_API_MEDIA_STATUS_LINK_RENEW: + nm_log_dbg (LOGD_WIMAX, "(%s): renewing DHCP lease", iface); + if (!nm_device_dhcp4_renew (NM_DEVICE (self), TRUE)) { + nm_device_state_changed (NM_DEVICE (self), + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_DHCP_FAILED); + } + break; + default: + nm_log_err (LOGD_WIMAX, "(%s): unhandled media status %d", iface, new_status); + break; + } +} + +static void +wmx_connect_result_cb (struct wmxsdk *wmxsdk, + WIMAX_API_NETWORK_CONNECTION_RESP result, + void *user_data) +{ + NMDeviceWimax *self = NM_DEVICE_WIMAX (user_data); + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + + if (nm_device_is_activating (NM_DEVICE (self))) { + priv->connect_failed = (result == WIMAX_API_CONNECTION_SUCCESS); + /* Wait for the state change so we can get the reason code; we + * cache the connect failure so we don't have to wait for the + * activation timeout. + */ + } +} + +static void +remove_outdated_nsps (NMDeviceWimax *self, + WIMAX_API_NSP_INFO_EX *nsp_list, + guint32 list_size) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + GSList *iter; + GSList *to_remove = NULL; + + for (iter = priv->nsp_list; iter; iter = iter->next) { + NMWimaxNsp *nsp = NM_WIMAX_NSP (iter->data); + gboolean found = FALSE; + int i; + + for (i = 0; i < list_size; i++) { + WIMAX_API_NSP_INFO_EX *info = &nsp_list[i]; + + if (!g_strcmp0 (nm_wimax_nsp_get_name (nsp), (char *) info->NSPName)) { + found = TRUE; + break; + } + } + + if (!found) + to_remove = g_slist_prepend (to_remove, nsp); + } + + for (iter = to_remove; iter; iter = iter->next) { + NMWimaxNsp *nsp = NM_WIMAX_NSP (iter->data); + + emit_nsp_added_removed (self, NSP_REMOVED, nsp, FALSE); + priv->nsp_list = g_slist_remove (priv->nsp_list, nsp); + g_object_unref (nsp); + } + + if (g_slist_length(to_remove) > 0) + nm_device_recheck_available_connections (NM_DEVICE (self)); + + g_slist_free (to_remove); +} + +static void +wmx_scan_result_cb (struct wmxsdk *wmxsdk, + WIMAX_API_NSP_INFO_EX *nsps, + guint num_nsps, + void *user_data) +{ + NMDeviceWimax *self = NM_DEVICE_WIMAX (user_data); + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + const char *iface = nm_device_get_iface (NM_DEVICE (self)); + int i; + + remove_outdated_nsps (self, nsps, num_nsps); + + /* Add new NSPs and update existing ones */ + for (i = 0; i < num_nsps; i++) { + WIMAX_API_NSP_INFO_EX *sdk_nsp = &nsps[i]; + const char *nsp_name = (const char *) sdk_nsp->NSPName; + NMWimaxNspNetworkType net_type; + guint signalq; + NMWimaxNsp *nsp; + gboolean new_nsp; + + nsp = get_nsp_by_name (self, nsp_name); + new_nsp = (nsp == NULL); + if (new_nsp) { + nsp = nm_wimax_nsp_new (nsp_name); + nm_log_dbg (LOGD_WIMAX, "(%s): new WiMAX NSP '%s'", iface, nsp_name); + } + + net_type = nm_wimax_util_convert_network_type (sdk_nsp->networkType); + if (net_type != nm_wimax_nsp_get_network_type (nsp)) + g_object_set (nsp, NM_WIMAX_NSP_NETWORK_TYPE, net_type, NULL); + + signalq = CLAMP (sdk_nsp->linkQuality, 0, 100); + if (signalq != nm_wimax_nsp_get_signal_quality (nsp)) + g_object_set (nsp, NM_WIMAX_NSP_SIGNAL_QUALITY, signalq, NULL); + + nm_log_dbg (LOGD_WIMAX, "(%s): WiMAX NSP '%s' quality %d%% type %d", + iface, nsp_name, sdk_nsp->linkQuality, net_type); + + if (new_nsp) { + priv->nsp_list = g_slist_append (priv->nsp_list, nsp); + nm_wimax_nsp_export_to_dbus (nsp); + emit_nsp_added_removed (self, NSP_ADDED, nsp, TRUE); + } + } +} + +static void +wmx_removed_cb (struct wmxsdk *wmxsdk, void *user_data) +{ + NMDeviceWimax *self = NM_DEVICE_WIMAX (user_data); + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + + if (!priv->sdk) { + nm_log_dbg (LOGD_WIMAX, "(%s): removed unhandled WiMAX interface", wmxsdk->ifname); + return; + } + + nm_log_dbg (LOGD_WIMAX, "(%s): removed WiMAX interface", wmxsdk->ifname); + + /* Clear callbacks just in case we don't hold the last reference */ + iwmx_sdk_set_callbacks (priv->sdk, NULL, NULL, NULL, NULL, NULL, NULL); + wmxsdk_unref (priv->sdk); + priv->sdk = NULL; + + priv->status = WIMAX_API_DEVICE_STATUS_UnInitialized; + nm_device_state_changed (NM_DEVICE (self), + NM_DEVICE_STATE_UNAVAILABLE, + NM_DEVICE_STATE_REASON_NONE); +} + +/*************************************************************************/ + +static inline gint +sdk_rssi_to_dbm (guint raw_rssi) +{ + /* Values range from 0x00 to 0x53, where -123dBm is encoded as 0x00 and + * -40dBm encoded as 0x53 in 1dB increments. + */ + return raw_rssi - 123; +} + +static inline gint +sdk_cinr_to_db (guint raw_cinr) +{ + /* Values range from 0x00 to 0x3F, where -10dB is encoded as 0x00 and + * 53dB encoded as 0x3F in 1dB increments. + */ + return raw_cinr - 10; +} + +static inline gint +sdk_tx_pow_to_dbm (guint raw_tx_pow) +{ + /* Values range from 0x00 to 0xFF, where -84dBm is encoded as 0x00 and + * 43.5dBm is encoded as 0xFF in 0.5dB increments. Normalize so that + * 0 dBm == 0. + */ + return (int) (((double) raw_tx_pow / 2.0) - 84) * 2; +} + +static void +set_link_status (NMDeviceWimax *self, WIMAX_API_LINK_STATUS_INFO_EX *link_status) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + guint center_freq = 0; + gint conv_rssi = 0, conv_cinr = 0, conv_tx_pow = 0; + char *new_bsid = NULL; + + if (link_status) { + center_freq = link_status->centerFrequency; + conv_rssi = sdk_rssi_to_dbm (link_status->RSSI); + conv_cinr = sdk_cinr_to_db (link_status->CINR); + conv_tx_pow = sdk_tx_pow_to_dbm (link_status->txPWR); + new_bsid = nm_utils_hwaddr_ntoa_len (link_status->bsId, 6); + } + + if (priv->center_freq != center_freq) { + priv->center_freq = center_freq; + g_object_notify (G_OBJECT (self), NM_DEVICE_WIMAX_CENTER_FREQUENCY); + } + + if (priv->rssi != conv_rssi) { + priv->rssi = conv_rssi; + g_object_notify (G_OBJECT (self), NM_DEVICE_WIMAX_RSSI); + } + + if (priv->cinr != conv_cinr) { + priv->cinr = conv_cinr; + g_object_notify (G_OBJECT (self), NM_DEVICE_WIMAX_CINR); + } + + if (priv->tx_power != conv_tx_pow) { + priv->tx_power = conv_tx_pow; + g_object_notify (G_OBJECT (self), NM_DEVICE_WIMAX_TX_POWER); + } + + if (g_strcmp0 (priv->bsid, new_bsid) != 0) { + g_free (priv->bsid); + priv->bsid = new_bsid; + g_object_notify (G_OBJECT (self), NM_DEVICE_WIMAX_BSID); + } else + g_free (new_bsid); +} + +static gboolean +connected_poll_cb (gpointer user_data) +{ + NMDeviceWimax *self = NM_DEVICE_WIMAX (user_data); + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + WIMAX_API_CONNECTED_NSP_INFO_EX *sdk_nsp; + WIMAX_API_LINK_STATUS_INFO_EX *link_status; + + g_return_val_if_fail (priv->sdk != NULL, FALSE); + + /* Get details of the connected NSP */ + sdk_nsp = iwmx_sdk_get_connected_network (priv->sdk); + if (sdk_nsp) { + const char *nsp_name = (const char *) sdk_nsp->NSPName; + NMWimaxNsp *nsp; + + nsp = get_nsp_by_name (self, nsp_name); + if (nsp) { + NMWimaxNspNetworkType net_type; + guint signalq; + + net_type = nm_wimax_util_convert_network_type (sdk_nsp->networkType); + if (net_type != nm_wimax_nsp_get_network_type (nsp)) + g_object_set (nsp, NM_WIMAX_NSP_NETWORK_TYPE, net_type, NULL); + + signalq = sdk_nsp->linkQuality; + if (signalq != nm_wimax_nsp_get_signal_quality (nsp)) + g_object_set (nsp, NM_WIMAX_NSP_SIGNAL_QUALITY, signalq, NULL); + + nm_log_dbg (LOGD_WIMAX, "(%s): WiMAX NSP '%s' quality %d%% type %d", + nm_device_get_iface (NM_DEVICE (self)), + nsp_name, sdk_nsp->linkQuality, net_type); + } + free (sdk_nsp); + } + + /* Get details of the current radio link */ + link_status = iwmx_sdk_get_link_status_info (priv->sdk); + if (link_status) { + set_link_status (self, link_status); + free (link_status); + } + + return TRUE; /* reschedule */ +} + +static void +device_state_changed (NMDevice *device, + NMDeviceState new_state, + NMDeviceState old_state, + NMDeviceStateReason reason) +{ + NMDeviceWimax *self = NM_DEVICE_WIMAX (device); + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + + /* Reset our stage1 (Prepare) done marker since it's only valid while in stage1 */ + priv->prepare_done = FALSE; + + if (new_state < NM_DEVICE_STATE_DISCONNECTED) + remove_all_nsps (self); + + /* Request initial NSP list when device is first started */ + if ( new_state == NM_DEVICE_STATE_DISCONNECTED + && old_state < NM_DEVICE_STATE_DISCONNECTED) { + if (priv->sdk) + iwmx_sdk_get_networks (priv->sdk); + } + + if (new_state == NM_DEVICE_STATE_FAILED || new_state <= NM_DEVICE_STATE_DISCONNECTED) { + set_current_nsp (self, NULL); + clear_activation_timeout (self); + } + + if (new_state == NM_DEVICE_STATE_ACTIVATED) { + /* poll link quality and BSID */ + clear_connected_poll (self); + priv->poll_id = g_timeout_add_seconds (10, connected_poll_cb, self); + connected_poll_cb (self); + } else { + clear_link_timeout (self); + clear_connected_poll (self); + set_link_status (self, NULL); + } +} + +/*************************************************************************/ + +static gboolean +sdk_action_defer_cb (gpointer user_data) +{ + NMDeviceWimax *self = NM_DEVICE_WIMAX (user_data); + gboolean old_available = nm_device_is_available (NM_DEVICE (self)); + + NM_DEVICE_WIMAX_GET_PRIVATE (self)->sdk_action_defer_id = 0; + update_availability (self, old_available); + return FALSE; +} + +static void +wmx_new_sdk_cb (struct wmxsdk *sdk, void *user_data) +{ + NMDeviceWimax *self = NM_DEVICE_WIMAX (user_data); + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + + /* We only track one wmxsdk at a time because the WiMAX SDK is pretty stupid */ + if (priv->sdk) { + nm_log_dbg (LOGD_WIMAX, "(%s): WiMAX interface already known", sdk->ifname); + return; + } + + nm_log_dbg (LOGD_WIMAX, "(%s): new WiMAX interface (%s)", sdk->ifname, sdk->name); + + /* Now that we have an SDK, schedule an idle handler to start the device up */ + priv->sdk = wmxsdk_ref (sdk); + iwmx_sdk_set_callbacks(priv->sdk, + wmx_state_change_cb, + wmx_media_status_cb, + wmx_connect_result_cb, + wmx_scan_result_cb, + wmx_removed_cb, + self); + iwmx_sdk_set_fast_reconnect_enabled (priv->sdk, 0); + + if (!priv->sdk_action_defer_id) + priv->sdk_action_defer_id = g_idle_add (sdk_action_defer_cb, self); +} + +/*************************************************************************/ + +NMDevice * +nm_device_wimax_new (NMPlatformLink *platform_device) +{ + NMDevice *device; + + g_return_val_if_fail (platform_device != NULL, NULL); + + device = (NMDevice *) g_object_new (NM_TYPE_DEVICE_WIMAX, + NM_DEVICE_PLATFORM_DEVICE, platform_device, + NM_DEVICE_TYPE_DESC, "WiMAX", + NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_WIMAX, + NM_DEVICE_RFKILL_TYPE, RFKILL_TYPE_WIMAX, + NULL); + if (device) { + struct wmxsdk *sdk; + + nm_wimax_util_sdk_ref (); + + /* See if the SDK already knows about this interface */ + sdk = iwmx_sdk_get_wmxsdk_for_iface (platform_device->name); + if (sdk) + wmx_new_sdk_cb (sdk, device); + + /* If it doesn't, we want to be notified when it does */ + iwmx_sdk_new_callback_register (wmx_new_sdk_cb, device); + } + + return device; +} + +static void +nm_device_wimax_init (NMDeviceWimax *self) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + + priv->status = WIMAX_API_DEVICE_STATUS_UnInitialized; +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMDeviceWimax *self = NM_DEVICE_WIMAX (object); + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + GPtrArray *array; + GSList *iter; + + switch (prop_id) { + case PROP_NSPS: + array = g_ptr_array_sized_new (4); + for (iter = priv->nsp_list; iter; iter = g_slist_next (iter)) + g_ptr_array_add (array, g_strdup (nm_wimax_nsp_get_dbus_path (NM_WIMAX_NSP (iter->data)))); + g_value_take_boxed (value, array); + break; + case PROP_ACTIVE_NSP: + if (priv->current_nsp) + g_value_set_boxed (value, nm_wimax_nsp_get_dbus_path (priv->current_nsp)); + else + g_value_set_boxed (value, "/"); + break; + case PROP_CENTER_FREQ: + g_value_set_uint (value, priv->center_freq); + break; + case PROP_RSSI: + g_value_set_int (value, priv->rssi); + break; + case PROP_CINR: + g_value_set_int (value, priv->cinr); + break; + case PROP_TX_POWER: + g_value_set_int (value, priv->tx_power); + break; + case PROP_BSID: + g_value_set_string (value, priv->bsid); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +dispose (GObject *object) +{ + NMDeviceWimax *self = NM_DEVICE_WIMAX (object); + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + + if (priv->disposed) + goto done; + + priv->disposed = TRUE; + + clear_activation_timeout (self); + clear_link_timeout (self); + clear_connected_poll (self); + + if (priv->sdk_action_defer_id) + g_source_remove (priv->sdk_action_defer_id); + + if (priv->sdk) { + iwmx_sdk_set_callbacks (priv->sdk, NULL, NULL, NULL, NULL, NULL, NULL); + wmxsdk_unref (priv->sdk); + } + + g_free (priv->bsid); + + set_current_nsp (self, NULL); + + g_slist_free_full (priv->nsp_list, g_object_unref); + + iwmx_sdk_new_callback_unregister (wmx_new_sdk_cb, self); + nm_wimax_util_sdk_unref (); + +done: + G_OBJECT_CLASS (nm_device_wimax_parent_class)->dispose (object); +} + +static void +nm_device_wimax_class_init (NMDeviceWimaxClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (NMDeviceWimaxPrivate)); + + /* Virtual methods */ + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->dispose = dispose; + + device_class->check_connection_compatible = check_connection_compatible; + device_class->check_connection_available = check_connection_available; + device_class->complete_connection = complete_connection; + device_class->can_auto_connect = can_auto_connect; + device_class->is_available = is_available; + device_class->act_stage1_prepare = act_stage1_prepare; + device_class->act_stage2_config = act_stage2_config; + device_class->deactivate = deactivate; + device_class->set_enabled = set_enabled; + + device_class->state_changed = device_state_changed; + + /* Properties */ + g_object_class_install_property + (object_class, PROP_NSPS, + g_param_spec_boxed (NM_DEVICE_WIMAX_NSPS, + "Network access points", + "Network access points", + DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH, + G_PARAM_READABLE)); + + g_object_class_install_property (object_class, PROP_ACTIVE_NSP, + g_param_spec_boxed (NM_DEVICE_WIMAX_ACTIVE_NSP, + "Active NSP", + "Currently active NSP", + DBUS_TYPE_G_OBJECT_PATH, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_CENTER_FREQ, + g_param_spec_uint (NM_DEVICE_WIMAX_CENTER_FREQUENCY, + "Center frequency", + "Center frequency", + 0, G_MAXUINT, 0, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_RSSI, + g_param_spec_int (NM_DEVICE_WIMAX_RSSI, + "RSSI", + "RSSI", + G_MININT, G_MAXINT, 0, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_CINR, + g_param_spec_int (NM_DEVICE_WIMAX_CINR, + "CINR", + "CINR", + G_MININT, G_MAXINT, 0, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_TX_POWER, + g_param_spec_int (NM_DEVICE_WIMAX_TX_POWER, + "TX Power", + "TX Power", + G_MININT, G_MAXINT, 0, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_BSID, + g_param_spec_string (NM_DEVICE_WIMAX_BSID, + "BSID", + "BSID", + NULL, + G_PARAM_READABLE)); + + /* Signals */ + signals[NSP_ADDED] = + g_signal_new ("nsp-added", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMDeviceWimaxClass, nsp_added), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + G_TYPE_OBJECT); + + signals[NSP_REMOVED] = + g_signal_new ("nsp-removed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMDeviceWimaxClass, nsp_removed), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + G_TYPE_OBJECT); + + nm_dbus_manager_register_exported_type (nm_dbus_manager_get (), + G_TYPE_FROM_CLASS (klass), + &dbus_glib_nm_device_wimax_object_info); + + dbus_g_error_domain_register (NM_WIMAX_ERROR, NULL, NM_TYPE_WIMAX_ERROR); +} diff --git a/src/devices/wimax/nm-device-wimax.h b/src/devices/wimax/nm-device-wimax.h new file mode 100644 index 00000000..8b252ee1 --- /dev/null +++ b/src/devices/wimax/nm-device-wimax.h @@ -0,0 +1,73 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2010 - 2011 Red Hat, Inc. + * Copyright (C) 2009 Novell, Inc. + */ + +#ifndef NM_DEVICE_WIMAX_H +#define NM_DEVICE_WIMAX_H + +#include +#include "nm-device.h" +#include "nm-wimax-nsp.h" + +G_BEGIN_DECLS + +#define NM_TYPE_DEVICE_WIMAX (nm_device_wimax_get_type ()) +#define NM_DEVICE_WIMAX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_WIMAX, NMDeviceWimax)) +#define NM_DEVICE_WIMAX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_WIMAX, NMDeviceWimaxClass)) +#define NM_IS_DEVICE_WIMAX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_WIMAX)) +#define NM_IS_DEVICE_WIMAX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_WIMAX)) +#define NM_DEVICE_WIMAX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_WIMAX, NMDeviceWimaxClass)) + +typedef enum +{ + NM_WIMAX_ERROR_CONNECTION_NOT_WIMAX = 0, /*< nick=ConnectionNotWimax >*/ + NM_WIMAX_ERROR_CONNECTION_INVALID, /*< nick=ConnectionInvalid >*/ + NM_WIMAX_ERROR_CONNECTION_INCOMPATIBLE, /*< nick=ConnectionIncompatible >*/ + NM_WIMAX_ERROR_NSP_NOT_FOUND, /*< nick=NspNotFound >*/ +} NMWimaxError; + +#define NM_DEVICE_WIMAX_NSPS "nsps" +#define NM_DEVICE_WIMAX_ACTIVE_NSP "active-nsp" +#define NM_DEVICE_WIMAX_CENTER_FREQUENCY "center-frequency" +#define NM_DEVICE_WIMAX_RSSI "rssi" +#define NM_DEVICE_WIMAX_CINR "cinr" +#define NM_DEVICE_WIMAX_TX_POWER "tx-power" +#define NM_DEVICE_WIMAX_BSID "bsid" + +typedef struct { + NMDevice parent; +} NMDeviceWimax; + +typedef struct { + NMDeviceClass parent; + + /* Signals */ + void (*nsp_added) (NMDeviceWimax *wimax, NMWimaxNsp *nsp); + void (*nsp_removed) (NMDeviceWimax *wimax, NMWimaxNsp *nsp); + void (*properties_changed) (NMDeviceWimax *wimax, GHashTable *properties); +} NMDeviceWimaxClass; + +GType nm_device_wimax_get_type (void); + +NMDevice *nm_device_wimax_new (NMPlatformLink *platform_device); + +G_END_DECLS + +#endif /* NM_DEVICE_WIMAX_H */ diff --git a/src/devices/wimax/nm-wimax-factory.c b/src/devices/wimax/nm-wimax-factory.c new file mode 100644 index 00000000..ca962e68 --- /dev/null +++ b/src/devices/wimax/nm-wimax-factory.c @@ -0,0 +1,89 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2011 - 2014 Red Hat, Inc. + */ + +#include + +#include "nm-device-factory.h" +#include "nm-device-wimax.h" + +#define NM_TYPE_WIMAX_FACTORY (nm_wimax_factory_get_type ()) +#define NM_WIMAX_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_WIMAX_FACTORY, NMWimaxFactory)) + +typedef struct { + GObject parent; +} NMWimaxFactory; + +typedef struct { + GObjectClass parent; +} NMWimaxFactoryClass; + +static GType nm_wimax_factory_get_type (void); + +static void device_factory_interface_init (NMDeviceFactory *factory_iface); + +G_DEFINE_TYPE_EXTENDED (NMWimaxFactory, nm_wimax_factory, G_TYPE_OBJECT, 0, + G_IMPLEMENT_INTERFACE (NM_TYPE_DEVICE_FACTORY, device_factory_interface_init)) + +/**************************************************************************/ + +#define PLUGIN_TYPE NM_DEVICE_TYPE_WIMAX + +G_MODULE_EXPORT NMDeviceFactory * +nm_device_factory_create (GError **error) +{ + return (NMDeviceFactory *) g_object_new (NM_TYPE_WIMAX_FACTORY, NULL); +} + +G_MODULE_EXPORT NMDeviceType +nm_device_factory_get_device_type (void) +{ + return PLUGIN_TYPE; +} + +/**************************************************************************/ + +static NMDevice * +new_link (NMDeviceFactory *factory, NMPlatformLink *plink, GError **error) +{ + /* FIXME: check udev 'DEVTYPE' instead; but since we only support Intel + * WiMAX devices for now this is appropriate. + */ + if (g_strcmp0 (plink->driver, "i2400m_usb") != 0) + return NULL; /* unsupported */ + + return (NMDevice *) nm_device_wimax_new (plink); +} + +static void +device_factory_interface_init (NMDeviceFactory *factory_iface) +{ + factory_iface->new_link = new_link; +} + +static void +nm_wimax_factory_init (NMWimaxFactory *factory) +{ +} + +static void +nm_wimax_factory_class_init (NMWimaxFactoryClass *wf_class) +{ +} + diff --git a/src/devices/wimax/nm-wimax-nsp.c b/src/devices/wimax/nm-wimax-nsp.c new file mode 100644 index 00000000..efe3b058 --- /dev/null +++ b/src/devices/wimax/nm-wimax-nsp.c @@ -0,0 +1,242 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2010 - 2012 Red Hat, Inc. + * Copyright (C) 2009 Novell, Inc. + */ + +#include "nm-wimax-nsp.h" +#include "NetworkManager.h" +#include "nm-dbus-manager.h" +#include "nm-setting-wimax.h" +#include "nm-wimax-nsp-glue.h" +#include "nm-utils.h" + +G_DEFINE_TYPE (NMWimaxNsp, nm_wimax_nsp, G_TYPE_OBJECT) + +enum { + PROP_0, + + PROP_NAME, + PROP_SIGNAL_QUALITY, + PROP_NETWORK_TYPE, + + LAST_PROP +}; + +#define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_WIMAX_NSP, NMWimaxNspPrivate)) + +typedef struct { + char *dbus_path; + + char *name; + guint32 signal_quality; + NMWimaxNspNetworkType network_type; +} NMWimaxNspPrivate; + +NMWimaxNsp * +nm_wimax_nsp_new (const char *name) +{ + g_return_val_if_fail (name != NULL, NULL); + + return NM_WIMAX_NSP (g_object_new (NM_TYPE_WIMAX_NSP, + NM_WIMAX_NSP_NAME, name, + NULL)); +} + +const char * +nm_wimax_nsp_get_name (NMWimaxNsp *self) +{ + g_return_val_if_fail (NM_IS_WIMAX_NSP (self), NULL); + + return GET_PRIVATE (self)->name; +} + +guint32 +nm_wimax_nsp_get_signal_quality (NMWimaxNsp *self) +{ + g_return_val_if_fail (NM_IS_WIMAX_NSP (self), 0); + + return GET_PRIVATE (self)->signal_quality; +} + +NMWimaxNspNetworkType +nm_wimax_nsp_get_network_type (NMWimaxNsp *self) +{ + g_return_val_if_fail (NM_IS_WIMAX_NSP (self), 0); + + return GET_PRIVATE (self)->network_type; +} + +void +nm_wimax_nsp_export_to_dbus (NMWimaxNsp *self) +{ + NMWimaxNspPrivate *priv; + static guint32 counter = 0; + + g_return_if_fail (NM_IS_WIMAX_NSP (self)); + + priv = GET_PRIVATE (self); + + g_return_if_fail (priv->dbus_path == NULL); + + priv->dbus_path = g_strdup_printf (NM_DBUS_PATH_WIMAX_NSP "/%d", counter++); + nm_dbus_manager_register_object (nm_dbus_manager_get (), priv->dbus_path, self); +} + +const char * +nm_wimax_nsp_get_dbus_path (NMWimaxNsp *self) +{ + g_return_val_if_fail (NM_IS_WIMAX_NSP (self), NULL); + + return GET_PRIVATE (self)->dbus_path; +} + +gboolean +nm_wimax_nsp_check_compatible (NMWimaxNsp *self, + NMConnection *connection) +{ + NMWimaxNspPrivate *priv; + NMSettingWimax *s_wimax; + + g_return_val_if_fail (NM_IS_WIMAX_NSP (self), FALSE); + g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE); + + priv = GET_PRIVATE (self); + + s_wimax = nm_connection_get_setting_wimax (connection); + if (!s_wimax) + return FALSE; + + return g_strcmp0 (nm_wimax_nsp_get_name (self), nm_setting_wimax_get_network_name (s_wimax)) == 0; +} + +static void +nm_wimax_nsp_init (NMWimaxNsp *self) +{ +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMWimaxNspPrivate *priv = GET_PRIVATE (object); + guint32 quality; + guint network_type; + + switch (prop_id) { + case PROP_NAME: + /* Construct only */ + priv->name = g_value_dup_string (value); + break; + case PROP_SIGNAL_QUALITY: + quality = g_value_get_uint (value); + if (quality != priv->signal_quality) { + priv->signal_quality = CLAMP (quality, 0, 100); + g_object_notify (object, NM_WIMAX_NSP_SIGNAL_QUALITY); + } + break; + case PROP_NETWORK_TYPE: + network_type = g_value_get_uint (value); + if (network_type != priv->network_type) { + priv->network_type = network_type; + g_object_notify (object, NM_WIMAX_NSP_NETWORK_TYPE); + } + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMWimaxNsp *self = NM_WIMAX_NSP (object); + + switch (prop_id) { + case PROP_NAME: + g_value_set_string (value, nm_wimax_nsp_get_name (self)); + break; + case PROP_SIGNAL_QUALITY: + g_value_set_uint (value, nm_wimax_nsp_get_signal_quality (self)); + break; + case PROP_NETWORK_TYPE: + g_value_set_uint (value, nm_wimax_nsp_get_network_type (self)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +finalize (GObject *object) +{ + NMWimaxNspPrivate *priv = GET_PRIVATE (object); + + g_free (priv->name); + g_free (priv->dbus_path); + + G_OBJECT_CLASS (nm_wimax_nsp_parent_class)->finalize (object); +} + +static void +nm_wimax_nsp_class_init (NMWimaxNspClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (NMWimaxNspPrivate)); + + /* Virtual methods */ + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->finalize = finalize; + + g_object_class_install_property + (object_class, PROP_NAME, + g_param_spec_string (NM_WIMAX_NSP_NAME, + "Name", + "Name", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property + (object_class, PROP_SIGNAL_QUALITY, + g_param_spec_uint (NM_WIMAX_NSP_SIGNAL_QUALITY, + "SignalQuality", + "SignalQuality", + 0, + 100, + 0, + G_PARAM_READWRITE)); + + g_object_class_install_property + (object_class, PROP_NETWORK_TYPE, + g_param_spec_uint (NM_WIMAX_NSP_NETWORK_TYPE, + "NetworkType", + "NetworkType", + NM_WIMAX_NSP_NETWORK_TYPE_UNKNOWN, + NM_WIMAX_NSP_NETWORK_TYPE_ROAMING_PARTNER, + NM_WIMAX_NSP_NETWORK_TYPE_UNKNOWN, + G_PARAM_READWRITE)); + + nm_dbus_manager_register_exported_type (nm_dbus_manager_get (), + G_TYPE_FROM_CLASS (klass), + &dbus_glib_nm_wimax_nsp_object_info); +} diff --git a/src/devices/wimax/nm-wimax-nsp.h b/src/devices/wimax/nm-wimax-nsp.h new file mode 100644 index 00000000..a74b68a7 --- /dev/null +++ b/src/devices/wimax/nm-wimax-nsp.h @@ -0,0 +1,63 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2009 Novell, Inc. + */ + +#ifndef NM_WIMAX_NSP_H +#define NM_WIMAX_NSP_H + +#include +#include "nm-wimax-types.h" +#include "nm-connection.h" + +#define NM_TYPE_WIMAX_NSP (nm_wimax_nsp_get_type ()) +#define NM_WIMAX_NSP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_WIMAX_NSP, NMWimaxNsp)) +#define NM_WIMAX_NSP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_WIMAX_NSP, NMWimaxNspClass)) +#define NM_IS_WIMAX_NSP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_WIMAX_NSP)) +#define NM_IS_WIMAX_NSP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_WIMAX_NSP)) +#define NM_WIMAX_NSP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_WIMAX_NSP, NMWimaxNspClass)) + +#define NM_WIMAX_NSP_NAME "name" +#define NM_WIMAX_NSP_SIGNAL_QUALITY "signal-quality" +#define NM_WIMAX_NSP_NETWORK_TYPE "network-type" + +typedef struct { + GObject parent; +} NMWimaxNsp; + +typedef struct { + GObjectClass parent; + + /* Signals */ + void (*properties_changed) (NMWimaxNsp *nsp, GHashTable *properties); +} NMWimaxNspClass; + +GType nm_wimax_nsp_get_type (void); + +NMWimaxNsp *nm_wimax_nsp_new (const char *name); +const char *nm_wimax_nsp_get_name (NMWimaxNsp *self); +guint32 nm_wimax_nsp_get_signal_quality (NMWimaxNsp *self); +NMWimaxNspNetworkType nm_wimax_nsp_get_network_type (NMWimaxNsp *self); + +void nm_wimax_nsp_export_to_dbus (NMWimaxNsp *self); +const char *nm_wimax_nsp_get_dbus_path (NMWimaxNsp *self); + +gboolean nm_wimax_nsp_check_compatible (NMWimaxNsp *self, + NMConnection *connection); + +#endif /* NM_WIMAX_NSP_H */ diff --git a/src/devices/wimax/nm-wimax-types.h b/src/devices/wimax/nm-wimax-types.h new file mode 100644 index 00000000..8c807fd8 --- /dev/null +++ b/src/devices/wimax/nm-wimax-types.h @@ -0,0 +1,31 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2009 Novell, Inc. + */ + +#ifndef NM_WIMAX_TYPES_H +#define NM_WIMAX_TYPES_H + +typedef enum { + NM_WIMAX_NSP_NETWORK_TYPE_UNKNOWN, + NM_WIMAX_NSP_NETWORK_TYPE_HOME, + NM_WIMAX_NSP_NETWORK_TYPE_PARTNER, + NM_WIMAX_NSP_NETWORK_TYPE_ROAMING_PARTNER +} NMWimaxNspNetworkType; + +#endif /* NM_WIMAX_TYPES_H */ diff --git a/src/devices/wimax/nm-wimax-util.c b/src/devices/wimax/nm-wimax-util.c new file mode 100644 index 00000000..bca25a1d --- /dev/null +++ b/src/devices/wimax/nm-wimax-util.c @@ -0,0 +1,82 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2009 Novell, Inc. + */ + +#include +#include "nm-wimax-util.h" +#include "nm-utils.h" +#include "iwmxsdk.h" +#include "nm-logging.h" + +static guint sdk_refcount = 0; + +void +nm_wimax_util_sdk_ref (void) +{ + int ret = 0; + + if (sdk_refcount == 0) { + ret = iwmx_sdk_api_init (); + if (ret != 0) { + nm_log_warn (LOGD_WIMAX, "Failed to initialize WiMAX: %d", ret); + return; + } + } + sdk_refcount++; +} + +gboolean +nm_wimax_util_sdk_is_initialized (void) +{ + return sdk_refcount > 0; +} + +void +nm_wimax_util_sdk_unref (void) +{ + g_return_if_fail (sdk_refcount > 0); + + sdk_refcount--; + if (sdk_refcount == 0) + iwmx_sdk_api_exit (); +} + +NMWimaxNspNetworkType +nm_wimax_util_convert_network_type (WIMAX_API_NETWORK_TYPE wimax_network_type) +{ + NMWimaxNspNetworkType type; + + switch (wimax_network_type) { + case WIMAX_API_HOME: + type = NM_WIMAX_NSP_NETWORK_TYPE_HOME; + break; + case WIMAX_API_PARTNER: + type = NM_WIMAX_NSP_NETWORK_TYPE_PARTNER; + break; + case WIMAX_API_ROAMING_PARTNER: + type = NM_WIMAX_NSP_NETWORK_TYPE_ROAMING_PARTNER; + break; + default: + type = NM_WIMAX_NSP_NETWORK_TYPE_UNKNOWN; + break; + } + + return type; +} + diff --git a/src/devices/wimax/nm-wimax-util.h b/src/devices/wimax/nm-wimax-util.h new file mode 100644 index 00000000..71f5aa29 --- /dev/null +++ b/src/devices/wimax/nm-wimax-util.h @@ -0,0 +1,38 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2009 Novell, Inc. + */ + +#ifndef NM_WIMAX_UTIL_H +#define NM_WIMAX_UTIL_H + +#include + +#include +#include +#include "nm-wimax-types.h" + +void nm_wimax_util_sdk_ref (void); + +gboolean nm_wimax_util_sdk_is_initialized (void); + +void nm_wimax_util_sdk_unref (void); + +NMWimaxNspNetworkType nm_wimax_util_convert_network_type (WIMAX_API_NETWORK_TYPE wimax_network_type); + +#endif /* NM_WIMAX_UTIL_H */ diff --git a/src/devices/wwan/Makefile.am b/src/devices/wwan/Makefile.am new file mode 100644 index 00000000..988f4679 --- /dev/null +++ b/src/devices/wwan/Makefile.am @@ -0,0 +1,95 @@ +include $(GLIB_MAKEFILE) + +@GNOME_CODE_COVERAGE_RULES@ + +AM_CPPFLAGS = \ + -I${top_srcdir}/src \ + -I${top_builddir}/src \ + -I${top_srcdir}/src/logging \ + -I${top_srcdir}/src/devices \ + -I${top_srcdir}/src/settings \ + -I${top_srcdir}/src/platform \ + -I${top_builddir}/include \ + -I${top_srcdir}/include \ + -I${top_builddir}/libnm-util \ + -I${top_srcdir}/libnm-util \ + -DG_LOG_DOMAIN=\""NetworkManager-wwan"\" \ + -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \ + $(DBUS_CFLAGS) \ + $(POLKIT_CFLAGS) \ + $(MM_GLIB_CFLAGS) + +BUILT_SOURCES = $(null) + +pkglib_LTLIBRARIES = libnm-wwan.la libnm-device-plugin-wwan.la + +########################################################### + +GLIB_GENERATED = nm-modem-enum-types.h nm-modem-enum-types.c +GLIB_MKENUMS_H_FLAGS = --identifier-prefix NM +GLIB_MKENUMS_C_FLAGS = --identifier-prefix NM +nm_modem_enum_types_sources = $(srcdir)/nm-modem.h + +BUILT_SOURCES += $(GLIB_GENERATED) + +libnm_wwan_la_SOURCES = \ + nm-modem-old.c \ + nm-modem-old.h \ + nm-modem-old-types.h \ + nm-modem-manager.c \ + nm-modem-manager.h \ + nm-modem.c \ + nm-modem.h \ + \ + $(GLIB_GENERATED) + +if WITH_MODEM_MANAGER_1 +libnm_wwan_la_SOURCES += \ + nm-modem-broadband.c \ + nm-modem-broadband.h +endif + +WWAN_SYMBOL_VIS_FILE=$(srcdir)/wwan-exports.ver + +libnm_wwan_la_LDFLAGS = \ + -avoid-version \ + -Wl,--version-script=$(WWAN_SYMBOL_VIS_FILE) +libnm_wwan_la_LIBADD = $(DBUS_LIBS) $(MM_GLIB_LIBS) + +########################################################### + +nm-device-modem-glue.h: $(top_srcdir)/introspection/nm-device-modem.xml + dbus-binding-tool --prefix=nm_device_modem --mode=glib-server --output=$@ $< + +BUILT_SOURCES += nm-device-modem-glue.h + +SYMBOL_VIS_FILE=$(srcdir)/exports.ver + +libnm_device_plugin_wwan_la_SOURCES = \ + nm-wwan-factory.c \ + nm-wwan-factory.h \ + nm-device-modem.c \ + nm-device-modem.h \ + nm-device-modem-glue.h + +libnm_device_plugin_wwan_la_LDFLAGS = \ + -module -avoid-version \ + -Wl,--version-script=$(SYMBOL_VIS_FILE) + +libnm_device_plugin_wwan_la_LIBADD = \ + libnm-wwan.la \ + $(DBUS_LIBS) + +########################################################### + +CLEANFILES = $(BUILT_SOURCES) +EXTRA_DIST = $(SYMBOL_VIS_FILE) $(WWAN_SYMBOL_VIS_FILE) + +if ENABLE_TESTS + +check-local: + $(top_srcdir)/tools/check-exports.sh $(builddir)/.libs/libnm-device-plugin-wwan.so $(SYMBOL_VIS_FILE) + $(top_srcdir)/tools/check-exports.sh $(builddir)/.libs/libnm-wwan.so $(WWAN_SYMBOL_VIS_FILE) + +endif + diff --git a/src/devices/wwan/Makefile.in b/src/devices/wwan/Makefile.in new file mode 100644 index 00000000..ae33d1c8 --- /dev/null +++ b/src/devices/wwan/Makefile.in @@ -0,0 +1,886 @@ +# Makefile.in generated by automake 1.13.4 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +@WITH_MODEM_MANAGER_1_TRUE@am__append_1 = \ +@WITH_MODEM_MANAGER_1_TRUE@ nm-modem-broadband.c \ +@WITH_MODEM_MANAGER_1_TRUE@ nm-modem-broadband.h + +subdir = src/devices/wwan +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(top_srcdir)/build-aux/depcomp README +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_lib_readline.m4 \ + $(top_srcdir)/m4/compiler_warnings.m4 \ + $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/gnome-code-coverage.m4 \ + $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ + $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \ + $(top_srcdir)/m4/introspection.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ + $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ + $(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(pkglibdir)" +LTLIBRARIES = $(pkglib_LTLIBRARIES) +am__DEPENDENCIES_1 = +libnm_device_plugin_wwan_la_DEPENDENCIES = libnm-wwan.la \ + $(am__DEPENDENCIES_1) +am_libnm_device_plugin_wwan_la_OBJECTS = nm-wwan-factory.lo \ + nm-device-modem.lo +libnm_device_plugin_wwan_la_OBJECTS = \ + $(am_libnm_device_plugin_wwan_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libnm_device_plugin_wwan_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(libnm_device_plugin_wwan_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +libnm_wwan_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +am__libnm_wwan_la_SOURCES_DIST = nm-modem-old.c nm-modem-old.h \ + nm-modem-old-types.h nm-modem-manager.c nm-modem-manager.h \ + nm-modem.c nm-modem.h nm-modem-enum-types.h \ + nm-modem-enum-types.c nm-modem-broadband.c \ + nm-modem-broadband.h +am__objects_1 = nm-modem-enum-types.lo +@WITH_MODEM_MANAGER_1_TRUE@am__objects_2 = nm-modem-broadband.lo +am_libnm_wwan_la_OBJECTS = nm-modem-old.lo nm-modem-manager.lo \ + nm-modem.lo $(am__objects_1) $(am__objects_2) +libnm_wwan_la_OBJECTS = $(am_libnm_wwan_la_OBJECTS) +libnm_wwan_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libnm_wwan_la_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libnm_device_plugin_wwan_la_SOURCES) \ + $(libnm_wwan_la_SOURCES) +DIST_SOURCES = $(libnm_device_plugin_wwan_la_SOURCES) \ + $(am__libnm_wwan_la_SOURCES_DIST) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALL_LINGUAS = @ALL_LINGUAS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CKDB_PATH = @CKDB_PATH@ +CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@ +CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@ +CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIRNAME = @DATADIRNAME@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_100_CFLAGS = @DBUS_GLIB_100_CFLAGS@ +DBUS_GLIB_100_LIBS = @DBUS_GLIB_100_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DHCLIENT_PATH = @DHCLIENT_PATH@ +DHCPCD_PATH = @DHCPCD_PATH@ +DISTRO_NETWORK_SERVICE = @DISTRO_NETWORK_SERVICE@ +DLLTOOL = @DLLTOOL@ +DNSMASQ_PATH = @DNSMASQ_PATH@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GENHTML = @GENHTML@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MAKEFILE = @GLIB_MAKEFILE@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ +GNUTLS_LIBS = @GNUTLS_LIBS@ +GREP = @GREP@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GUDEV_CFLAGS = @GUDEV_CFLAGS@ +GUDEV_LIBS = @GUDEV_LIBS@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_PERL = @INTLTOOL_PERL@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ +INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ +INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ +INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +IPTABLES_PATH = @IPTABLES_PATH@ +IWMX_SDK_CFLAGS = @IWMX_SDK_CFLAGS@ +IWMX_SDK_LIBS = @IWMX_SDK_LIBS@ +KERNEL_FIRMWARE_DIR = @KERNEL_FIRMWARE_DIR@ +LCOV = @LCOV@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDL = @LIBDL@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBM = @LIBM@ +LIBNDP_CFLAGS = @LIBNDP_CFLAGS@ +LIBNDP_LIBS = @LIBNDP_LIBS@ +LIBNL_CFLAGS = @LIBNL_CFLAGS@ +LIBNL_LIBS = @LIBNL_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@ +LIBSOUP_LIBS = @LIBSOUP_LIBS@ +LIBTEAMDCTL_CFLAGS = @LIBTEAMDCTL_CFLAGS@ +LIBTEAMDCTL_LIBS = @LIBTEAMDCTL_LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MM_GLIB_CFLAGS = @MM_GLIB_CFLAGS@ +MM_GLIB_LIBS = @MM_GLIB_LIBS@ +MOC = @MOC@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NEWT_CFLAGS = @NEWT_CFLAGS@ +NEWT_LIBS = @NEWT_LIBS@ +NM = @NM@ +NMEDIT = @NMEDIT@ +NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ +NM_MICRO_VERSION = @NM_MICRO_VERSION@ +NM_MINOR_VERSION = @NM_MINOR_VERSION@ +NM_MODIFY_SYSTEM_POLICY = @NM_MODIFY_SYSTEM_POLICY@ +NM_VERSION = @NM_VERSION@ +NSS_CFLAGS = @NSS_CFLAGS@ +NSS_LIBS = @NSS_LIBS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +POLKIT_CFLAGS = @POLKIT_CFLAGS@ +POLKIT_LIBS = @POLKIT_LIBS@ +POSUB = @POSUB@ +PPPD_PATH = @PPPD_PATH@ +PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@ +PPPOE_PATH = @PPPOE_PATH@ +QT_CFLAGS = @QT_CFLAGS@ +QT_LIBS = @QT_LIBS@ +RANLIB = @RANLIB@ +READLINE_LIBS = @READLINE_LIBS@ +SED = @SED@ +SELINUX_CFLAGS = @SELINUX_CFLAGS@ +SELINUX_LIBS = @SELINUX_LIBS@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SYSTEMD_200_CFLAGS = @SYSTEMD_200_CFLAGS@ +SYSTEMD_200_LIBS = @SYSTEMD_200_LIBS@ +SYSTEMD_INHIBIT_CFLAGS = @SYSTEMD_INHIBIT_CFLAGS@ +SYSTEMD_INHIBIT_LIBS = @SYSTEMD_INHIBIT_LIBS@ +SYSTEMD_LOGIN_CFLAGS = @SYSTEMD_LOGIN_CFLAGS@ +SYSTEMD_LOGIN_LIBS = @SYSTEMD_LOGIN_LIBS@ +SYSTEM_CA_PATH = @SYSTEM_CA_PATH@ +UDEV_BASE_DIR = @UDEV_BASE_DIR@ +USE_NLS = @USE_NLS@ +UUID_CFLAGS = @UUID_CFLAGS@ +UUID_LIBS = @UUID_LIBS@ +VALGRIND_RULES = @VALGRIND_RULES@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ +VERSION = @VERSION@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +intltool__v_merge_options_ = @intltool__v_merge_options_@ +intltool__v_merge_options_0 = @intltool__v_merge_options_0@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +nmbinary = @nmbinary@ +nmconfdir = @nmconfdir@ +nmdatadir = @nmdatadir@ +nmrundir = @nmrundir@ +nmstatedir = @nmstatedir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +with_dhclient = @with_dhclient@ +with_dhcpcd = @with_dhcpcd@ +with_netconfig = @with_netconfig@ +with_resolvconf = @with_resolvconf@ +with_valgrind = @with_valgrind@ +AM_CPPFLAGS = \ + -I${top_srcdir}/src \ + -I${top_builddir}/src \ + -I${top_srcdir}/src/logging \ + -I${top_srcdir}/src/devices \ + -I${top_srcdir}/src/settings \ + -I${top_srcdir}/src/platform \ + -I${top_builddir}/include \ + -I${top_srcdir}/include \ + -I${top_builddir}/libnm-util \ + -I${top_srcdir}/libnm-util \ + -DG_LOG_DOMAIN=\""NetworkManager-wwan"\" \ + -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \ + $(DBUS_CFLAGS) \ + $(POLKIT_CFLAGS) \ + $(MM_GLIB_CFLAGS) + +BUILT_SOURCES = $(null) $(GLIB_GENERATED) nm-device-modem-glue.h +pkglib_LTLIBRARIES = libnm-wwan.la libnm-device-plugin-wwan.la + +########################################################### +GLIB_GENERATED = nm-modem-enum-types.h nm-modem-enum-types.c +GLIB_MKENUMS_H_FLAGS = --identifier-prefix NM +GLIB_MKENUMS_C_FLAGS = --identifier-prefix NM +nm_modem_enum_types_sources = $(srcdir)/nm-modem.h +libnm_wwan_la_SOURCES = nm-modem-old.c nm-modem-old.h \ + nm-modem-old-types.h nm-modem-manager.c nm-modem-manager.h \ + nm-modem.c nm-modem.h $(GLIB_GENERATED) $(am__append_1) +WWAN_SYMBOL_VIS_FILE = $(srcdir)/wwan-exports.ver +libnm_wwan_la_LDFLAGS = \ + -avoid-version \ + -Wl,--version-script=$(WWAN_SYMBOL_VIS_FILE) + +libnm_wwan_la_LIBADD = $(DBUS_LIBS) $(MM_GLIB_LIBS) +SYMBOL_VIS_FILE = $(srcdir)/exports.ver +libnm_device_plugin_wwan_la_SOURCES = \ + nm-wwan-factory.c \ + nm-wwan-factory.h \ + nm-device-modem.c \ + nm-device-modem.h \ + nm-device-modem-glue.h + +libnm_device_plugin_wwan_la_LDFLAGS = \ + -module -avoid-version \ + -Wl,--version-script=$(SYMBOL_VIS_FILE) + +libnm_device_plugin_wwan_la_LIBADD = \ + libnm-wwan.la \ + $(DBUS_LIBS) + + +########################################################### +CLEANFILES = $(BUILT_SOURCES) +EXTRA_DIST = $(SYMBOL_VIS_FILE) $(WWAN_SYMBOL_VIS_FILE) +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/devices/wwan/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/devices/wwan/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +install-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkglibdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ + } + +uninstall-pkglibLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ + done + +clean-pkglibLTLIBRARIES: + -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) + @list='$(pkglib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libnm-device-plugin-wwan.la: $(libnm_device_plugin_wwan_la_OBJECTS) $(libnm_device_plugin_wwan_la_DEPENDENCIES) $(EXTRA_libnm_device_plugin_wwan_la_DEPENDENCIES) + $(AM_V_CCLD)$(libnm_device_plugin_wwan_la_LINK) -rpath $(pkglibdir) $(libnm_device_plugin_wwan_la_OBJECTS) $(libnm_device_plugin_wwan_la_LIBADD) $(LIBS) + +libnm-wwan.la: $(libnm_wwan_la_OBJECTS) $(libnm_wwan_la_DEPENDENCIES) $(EXTRA_libnm_wwan_la_DEPENDENCIES) + $(AM_V_CCLD)$(libnm_wwan_la_LINK) -rpath $(pkglibdir) $(libnm_wwan_la_OBJECTS) $(libnm_wwan_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-device-modem.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-modem-broadband.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-modem-enum-types.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-modem-manager.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-modem-old.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-modem.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-wwan-factory.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +@ENABLE_TESTS_FALSE@check-local: +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) check-local +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(pkglibdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-am + +clean-am: clean-generic clean-libtool clean-pkglibLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-pkglibLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pkglibLTLIBRARIES + +.MAKE: all check check-am install install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am check-local clean \ + clean-generic clean-libtool clean-pkglibLTLIBRARIES \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-pkglibLTLIBRARIES install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am uninstall-pkglibLTLIBRARIES + +include $(GLIB_MAKEFILE) + +@GNOME_CODE_COVERAGE_RULES@ + +########################################################### + +nm-device-modem-glue.h: $(top_srcdir)/introspection/nm-device-modem.xml + dbus-binding-tool --prefix=nm_device_modem --mode=glib-server --output=$@ $< + +@ENABLE_TESTS_TRUE@check-local: +@ENABLE_TESTS_TRUE@ $(top_srcdir)/tools/check-exports.sh $(builddir)/.libs/libnm-device-plugin-wwan.so $(SYMBOL_VIS_FILE) +@ENABLE_TESTS_TRUE@ $(top_srcdir)/tools/check-exports.sh $(builddir)/.libs/libnm-wwan.so $(WWAN_SYMBOL_VIS_FILE) + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/devices/wwan/README b/src/devices/wwan/README new file mode 100644 index 00000000..4661c042 --- /dev/null +++ b/src/devices/wwan/README @@ -0,0 +1,45 @@ + +ModemManager integration is organized as follows: + + +Common source +******************************************************************************** + + * nm-modem.[h|c]: + Defines the basic `NMModem' object. The core NetworkManager implementation + will use this interface exclusively, regardless of the real final type of + the modem object. + + * nm-modem-manager.[h|c]: + Defines the `NMModemManager' object, which takes care of listening to + signals from the DBus interface notifying about added or removed modems. + It also takes care of creating proper `NMModem' objects from the + information retrieved from the DBus interface. + + +ModemManager 0.7 integration +******************************************************************************** + + * nm-modem-broadband.[h|c]: + Defines the `NMModemBroadband' object, which is a subclass of `NMModem'. + This object handles both 3GPP and 3GPP2 modems exposed in the new + `ModemManager1' interface. + + +ModemManager 0.4/0.5/0.6 integration +******************************************************************************** + + * nm-modem-old-types.h: + Defines helper types to use with the (old) ModemManager DBus API. + + * nm-modem-old.[h|c]: + Defines the `NMModemGeneric' object. All modem objects based on the old + ModemManager interface are subclasses of this one. + + * nm-modem-gsm.[h|c]: + Defines the `NMModemGsm' object, which is a subclass of `NMModemGeneric'. + This object handles 3GPP-specific (GSM, UMTS, HSPA, LTE) modems. + + * nm-modem-cdma.[h|c]: + Defines the `NMModemCdma' object, which is a subclass of `NMModemGeneric'. + This object handles 3GPP2-specific modems (CDMA, EV-DO). diff --git a/src/devices/wwan/exports.ver b/src/devices/wwan/exports.ver new file mode 100644 index 00000000..d2c45124 --- /dev/null +++ b/src/devices/wwan/exports.ver @@ -0,0 +1,7 @@ +{ +global: + nm_device_factory_create; + nm_device_factory_get_device_type; +local: + *; +}; diff --git a/src/devices/wwan/nm-device-modem-glue.h b/src/devices/wwan/nm-device-modem-glue.h new file mode 100644 index 00000000..21271491 --- /dev/null +++ b/src/devices/wwan/nm-device-modem-glue.h @@ -0,0 +1,73 @@ +/* Generated by dbus-binding-tool; do not edit! */ + + +#ifndef __dbus_glib_marshal_nm_device_modem_MARSHAL_H__ +#define __dbus_glib_marshal_nm_device_modem_MARSHAL_H__ + +#include + +G_BEGIN_DECLS + +#ifdef G_ENABLE_DEBUG +#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v) +#define g_marshal_value_peek_char(v) g_value_get_schar (v) +#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v) +#define g_marshal_value_peek_int(v) g_value_get_int (v) +#define g_marshal_value_peek_uint(v) g_value_get_uint (v) +#define g_marshal_value_peek_long(v) g_value_get_long (v) +#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v) +#define g_marshal_value_peek_int64(v) g_value_get_int64 (v) +#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v) +#define g_marshal_value_peek_enum(v) g_value_get_enum (v) +#define g_marshal_value_peek_flags(v) g_value_get_flags (v) +#define g_marshal_value_peek_float(v) g_value_get_float (v) +#define g_marshal_value_peek_double(v) g_value_get_double (v) +#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v) +#define g_marshal_value_peek_param(v) g_value_get_param (v) +#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v) +#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v) +#define g_marshal_value_peek_object(v) g_value_get_object (v) +#define g_marshal_value_peek_variant(v) g_value_get_variant (v) +#else /* !G_ENABLE_DEBUG */ +/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API. + * Do not access GValues directly in your code. Instead, use the + * g_value_get_*() functions + */ +#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int +#define g_marshal_value_peek_char(v) (v)->data[0].v_int +#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint +#define g_marshal_value_peek_int(v) (v)->data[0].v_int +#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint +#define g_marshal_value_peek_long(v) (v)->data[0].v_long +#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 +#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 +#define g_marshal_value_peek_enum(v) (v)->data[0].v_long +#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_float(v) (v)->data[0].v_float +#define g_marshal_value_peek_double(v) (v)->data[0].v_double +#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer +#endif /* !G_ENABLE_DEBUG */ + + +G_END_DECLS + +#endif /* __dbus_glib_marshal_nm_device_modem_MARSHAL_H__ */ + +#include +static const DBusGMethodInfo dbus_glib_nm_device_modem_methods[] = { +}; + +const DBusGObjectInfo dbus_glib_nm_device_modem_object_info = { 1, + dbus_glib_nm_device_modem_methods, + 0, +"\0", +"org.freedesktop.NetworkManager.Device.Modem\0PropertiesChanged\0\0", +"org.freedesktop.NetworkManager.Device.Modem\0ModemCapabilities\0modem_capabilities\0read\0org.freedesktop.NetworkManager.Device.Modem\0CurrentCapabilities\0current_capabilities\0read\0\0" +}; + diff --git a/src/devices/wwan/nm-device-modem.c b/src/devices/wwan/nm-device-modem.c new file mode 100644 index 00000000..678f7795 --- /dev/null +++ b/src/devices/wwan/nm-device-modem.c @@ -0,0 +1,646 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2009 - 2011 Red Hat, Inc. + */ + +#include "config.h" + +#include + +#include "nm-device-modem.h" +#include "nm-modem.h" +#include "nm-modem-old.h" +#include "nm-device-private.h" +#include "nm-rfkill-manager.h" +#include "nm-logging.h" +#include "nm-dbus-manager.h" +#include "nm-settings-connection.h" + +#if WITH_MODEM_MANAGER_1 +#include "nm-modem-broadband.h" +#endif + +G_DEFINE_TYPE (NMDeviceModem, nm_device_modem, NM_TYPE_DEVICE) + +#define NM_DEVICE_MODEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_MODEM, NMDeviceModemPrivate)) + +#include "nm-device-modem-glue.h" + +typedef struct { + NMModem *modem; + NMDeviceModemCapabilities caps; + NMDeviceModemCapabilities current_caps; + gboolean rf_enabled; +} NMDeviceModemPrivate; + +enum { + PROP_0, + PROP_MODEM, + PROP_CAPABILITIES, + PROP_CURRENT_CAPABILITIES, +}; + +/*****************************************************************************/ + +static void +ppp_failed (NMModem *modem, NMDeviceStateReason reason, gpointer user_data) +{ + NMDevice *device = NM_DEVICE (user_data); + + switch (nm_device_get_state (device)) { + case NM_DEVICE_STATE_PREPARE: + case NM_DEVICE_STATE_CONFIG: + case NM_DEVICE_STATE_NEED_AUTH: + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, reason); + break; + case NM_DEVICE_STATE_IP_CONFIG: + case NM_DEVICE_STATE_IP_CHECK: + case NM_DEVICE_STATE_SECONDARIES: + case NM_DEVICE_STATE_ACTIVATED: + if (nm_device_activate_ip4_state_in_conf (device)) + nm_device_activate_schedule_ip4_config_timeout (device); + else { + nm_device_state_changed (device, + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); + } + break; + default: + break; + } +} + +static void +modem_prepare_result (NMModem *modem, + gboolean success, + NMDeviceStateReason reason, + gpointer user_data) +{ + NMDevice *device = NM_DEVICE (user_data); + NMDeviceState state; + + state = nm_device_get_state (device); + g_return_if_fail (state == NM_DEVICE_STATE_PREPARE); + + if (success) + nm_device_activate_schedule_stage2_device_config (device); + else { + if (reason == NM_DEVICE_STATE_REASON_SIM_PIN_INCORRECT) { + /* If the connect failed because the SIM PIN was wrong don't allow + * the device to be auto-activated anymore, which would risk locking + * the SIM if the incorrect PIN continues to be used. + */ + g_object_set (G_OBJECT (device), NM_DEVICE_AUTOCONNECT, FALSE, NULL); + nm_log_info (LOGD_MB, "(%s): disabling autoconnect due to failed SIM PIN", + nm_device_get_iface (device)); + } + + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, reason); + } +} + +static void +modem_auth_requested (NMModem *modem, gpointer user_data) +{ + NMDevice *device = NM_DEVICE (user_data); + + /* Auth requests (PIN, PAP/CHAP passwords, etc) only get handled + * during activation. + */ + if (!nm_device_is_activating (device)) + return; + + nm_device_state_changed (device, + NM_DEVICE_STATE_NEED_AUTH, + NM_DEVICE_STATE_REASON_NONE); +} + +static void +modem_auth_result (NMModem *modem, GError *error, gpointer user_data) +{ + NMDevice *device = NM_DEVICE (user_data); + + if (error) { + nm_device_state_changed (device, + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_NO_SECRETS); + } else { + /* Otherwise, on success for modem secrets we need to schedule stage1 again */ + g_return_if_fail (nm_device_get_state (device) == NM_DEVICE_STATE_NEED_AUTH); + nm_device_activate_schedule_stage1_device_prepare (device); + } +} + +static void +modem_ip4_config_result (NMModem *self, + NMIP4Config *config, + GError *error, + gpointer user_data) +{ + NMDevice *device = NM_DEVICE (user_data); + + g_return_if_fail (nm_device_activate_ip4_state_in_conf (device) == TRUE); + + if (error) { + nm_log_warn (LOGD_MB | LOGD_IP4, "retrieving IP4 configuration failed: (%d) %s", + error ? error->code : -1, + error && error->message ? error->message : "(unknown)"); + + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); + } else + nm_device_activate_schedule_ip4_config_result (device, config); +} + +static void +data_port_changed_cb (NMModem *modem, GParamSpec *pspec, gpointer user_data) +{ + NMDevice *self = NM_DEVICE (user_data); + + /* We set the IP iface in the device as soon as we know it, so that we + * properly ifup it if needed */ + nm_device_set_ip_iface (self, nm_modem_get_data_port (modem)); +} + +static void +modem_state_cb (NMModem *modem, + NMModemState new_state, + NMModemState old_state, + gpointer user_data) +{ + NMDevice *device = NM_DEVICE (user_data); + NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (device); + NMDeviceState dev_state = nm_device_get_state (device); + + if (new_state <= NM_MODEM_STATE_DISABLING && + old_state > NM_MODEM_STATE_DISABLING && + priv->rf_enabled) { + /* Called when the ModemManager modem enabled state is changed externally + * to NetworkManager (eg something using MM's D-Bus API directly). + */ + if (nm_device_is_activating (device) || dev_state == NM_DEVICE_STATE_ACTIVATED) { + /* user-initiated action, hence DISCONNECTED not FAILED */ + nm_device_state_changed (device, + NM_DEVICE_STATE_DISCONNECTED, + NM_DEVICE_STATE_REASON_USER_REQUESTED); + return; + } + } + + if (new_state < NM_MODEM_STATE_CONNECTING && + old_state >= NM_MODEM_STATE_CONNECTING && + dev_state >= NM_DEVICE_STATE_NEED_AUTH && + dev_state <= NM_DEVICE_STATE_ACTIVATED) { + /* Fail the device if the modem disconnects unexpectedly while the + * device is activating/activated. */ + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER); + return; + } + + if (new_state > NM_MODEM_STATE_LOCKED && old_state == NM_MODEM_STATE_LOCKED) { + /* If the modem is now unlocked, enable/disable it according to the + * device's enabled/disabled state. + */ + nm_modem_set_mm_enabled (priv->modem, priv->rf_enabled); + } + + if ((dev_state >= NM_DEVICE_STATE_DISCONNECTED) && !nm_device_is_available (device)) { + nm_device_state_changed (device, + NM_DEVICE_STATE_UNAVAILABLE, + NM_DEVICE_STATE_REASON_MODEM_FAILED); + return; + } + + if ((dev_state == NM_DEVICE_STATE_UNAVAILABLE) && nm_device_is_available (device)) { + nm_device_state_changed (device, + NM_DEVICE_STATE_DISCONNECTED, + NM_DEVICE_STATE_REASON_MODEM_AVAILABLE); + return; + } +} + +static void +modem_removed_cb (NMModem *modem, gpointer user_data) +{ + g_signal_emit_by_name (NM_DEVICE (user_data), NM_DEVICE_REMOVED); +} + +/*****************************************************************************/ + +static gboolean +owns_iface (NMDevice *device, const char *iface) +{ + NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (device); + + g_assert (priv->modem); + return nm_modem_owns_port (priv->modem, iface); +} + +/*****************************************************************************/ + +static void +device_state_changed (NMDevice *device, + NMDeviceState new_state, + NMDeviceState old_state, + NMDeviceStateReason reason) +{ + NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (device); + NMConnection *connection = nm_device_get_connection (device); + + g_assert (priv->modem); + + if (new_state == NM_DEVICE_STATE_UNAVAILABLE && + old_state < NM_DEVICE_STATE_UNAVAILABLE) { + /* Log initial modem state */ + nm_log_info (LOGD_MB, "(%s): modem state '%s'", + nm_device_get_iface (device), + nm_modem_state_to_string (nm_modem_get_state (priv->modem))); + } + + nm_modem_device_state_changed (priv->modem, new_state, old_state, reason); + + switch (reason) { + case NM_DEVICE_STATE_REASON_GSM_REGISTRATION_DENIED: + case NM_DEVICE_STATE_REASON_GSM_REGISTRATION_NOT_SEARCHING: + case NM_DEVICE_STATE_REASON_GSM_SIM_NOT_INSERTED: + case NM_DEVICE_STATE_REASON_GSM_SIM_PIN_REQUIRED: + case NM_DEVICE_STATE_REASON_GSM_SIM_PUK_REQUIRED: + case NM_DEVICE_STATE_REASON_GSM_SIM_WRONG: + case NM_DEVICE_STATE_REASON_SIM_PIN_INCORRECT: + case NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED: + case NM_DEVICE_STATE_REASON_GSM_APN_FAILED: + /* Block autoconnect of the just-failed connection for situations + * where a retry attempt would just fail again. + */ + if (connection) + nm_settings_connection_set_autoconnect_blocked_reason (NM_SETTINGS_CONNECTION (connection), reason); + break; + default: + break; + } +} + +static guint +get_hw_address_length (NMDevice *device, gboolean *out_permanent) +{ + return 0; +} + +static gboolean +check_connection_compatible (NMDevice *device, NMConnection *connection) +{ + if (!NM_DEVICE_CLASS (nm_device_modem_parent_class)->check_connection_compatible (device, connection)) + return FALSE; + + return nm_modem_check_connection_compatible (NM_DEVICE_MODEM_GET_PRIVATE (device)->modem, connection); +} + +static gboolean +check_connection_available (NMDevice *device, + NMConnection *connection, + const char *specific_object) +{ + NMDeviceModem *self = NM_DEVICE_MODEM (device); + NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (self); + NMModemState state; + + if (!priv->rf_enabled || !priv->modem) + return FALSE; + + state = nm_modem_get_state (priv->modem); + if (state <= NM_MODEM_STATE_INITIALIZING) + return FALSE; + + if (state == NM_MODEM_STATE_LOCKED) { + NMSettingGsm *s_gsm = nm_connection_get_setting_gsm (connection); + + /* Can't use a connection without a PIN if the modem is locked */ + if (!s_gsm || !nm_setting_gsm_get_pin (s_gsm)) + return FALSE; + } + + return TRUE; +} + +static gboolean +complete_connection (NMDevice *device, + NMConnection *connection, + const char *specific_object, + const GSList *existing_connections, + GError **error) +{ + NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (device); + + return nm_modem_complete_connection (priv->modem, connection, existing_connections, error); +} + +static void +deactivate (NMDevice *device) +{ + nm_modem_deactivate (NM_DEVICE_MODEM_GET_PRIVATE (device)->modem, device); +} + +static NMActStageReturn +act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) +{ + NMActStageReturn ret; + NMActRequest *req; + + ret = NM_DEVICE_CLASS (nm_device_modem_parent_class)->act_stage1_prepare (device, reason); + if (ret != NM_ACT_STAGE_RETURN_SUCCESS) + return ret; + + req = nm_device_get_act_request (device); + g_assert (req); + + return nm_modem_act_stage1_prepare (NM_DEVICE_MODEM_GET_PRIVATE (device)->modem, req, reason); +} + +static NMActStageReturn +act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) +{ + NMActRequest *req; + + req = nm_device_get_act_request (device); + g_assert (req); + + return nm_modem_act_stage2_config (NM_DEVICE_MODEM_GET_PRIVATE (device)->modem, req, reason); +} + +static NMActStageReturn +act_stage3_ip4_config_start (NMDevice *device, + NMIP4Config **out_config, + NMDeviceStateReason *reason) +{ + return nm_modem_stage3_ip4_config_start (NM_DEVICE_MODEM_GET_PRIVATE (device)->modem, + device, + NM_DEVICE_CLASS (nm_device_modem_parent_class), + reason); +} + +static void +ip4_config_pre_commit (NMDevice *device, NMIP4Config *config) +{ + nm_modem_ip4_pre_commit (NM_DEVICE_MODEM_GET_PRIVATE (device)->modem, device, config); +} + +static NMActStageReturn +act_stage3_ip6_config_start (NMDevice *device, + NMIP6Config **out_config, + NMDeviceStateReason *reason) +{ + return nm_modem_stage3_ip6_config_start (NM_DEVICE_MODEM_GET_PRIVATE (device)->modem, + device, + NM_DEVICE_CLASS (nm_device_modem_parent_class), + reason); +} + +/*****************************************************************************/ + +static gboolean +get_enabled (NMDevice *device) +{ + NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (device); + NMModemState modem_state = nm_modem_get_state (priv->modem); + + return priv->rf_enabled && (modem_state >= NM_MODEM_STATE_LOCKED); +} + +static void +set_enabled (NMDevice *device, gboolean enabled) +{ + NMDeviceModem *self = NM_DEVICE_MODEM (device); + NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (self); + + /* Called only by the Manager in response to rfkill switch changes or + * global user WWAN enable/disable preference changes. + */ + priv->rf_enabled = enabled; + + if (priv->modem) { + /* Sync the ModemManager modem enabled/disabled with rfkill/user preference */ + nm_modem_set_mm_enabled (priv->modem, enabled); + } + + if (enabled == FALSE) { + nm_device_state_changed (device, + NM_DEVICE_STATE_UNAVAILABLE, + NM_DEVICE_STATE_REASON_NONE); + } +} + +static gboolean +is_available (NMDevice *dev) +{ + NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (dev); + NMModemState modem_state; + + if (!priv->rf_enabled) { + nm_log_dbg (LOGD_MB, "(%s): not available because WWAN airplane mode is on", + nm_device_get_iface (dev)); + return FALSE; + } + + g_assert (priv->modem); + modem_state = nm_modem_get_state (priv->modem); + if (modem_state <= NM_MODEM_STATE_INITIALIZING) { + nm_log_dbg (LOGD_MB, "(%s): not available because modem is not ready (%s)", + nm_device_get_iface (dev), + nm_modem_state_to_string (modem_state)); + return FALSE; + } + + return TRUE; +} + +/*****************************************************************************/ + +NMDevice * +nm_device_modem_new (NMModem *modem) +{ + NMDeviceModemCapabilities caps = NM_DEVICE_MODEM_CAPABILITY_NONE; + NMDeviceModemCapabilities current_caps = NM_DEVICE_MODEM_CAPABILITY_NONE; + NMDevice *device; + const char *data_port; + + g_return_val_if_fail (NM_IS_MODEM (modem), NULL); + + /* Load capabilities */ + nm_modem_get_capabilities (modem, &caps, ¤t_caps); + + device = (NMDevice *) g_object_new (NM_TYPE_DEVICE_MODEM, + NM_DEVICE_UDI, nm_modem_get_path (modem), + NM_DEVICE_IFACE, nm_modem_get_uid (modem), + NM_DEVICE_DRIVER, nm_modem_get_driver (modem), + NM_DEVICE_TYPE_DESC, "Broadband", + NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_MODEM, + NM_DEVICE_RFKILL_TYPE, RFKILL_TYPE_WWAN, + NM_DEVICE_MODEM_MODEM, modem, + NM_DEVICE_MODEM_CAPABILITIES, caps, + NM_DEVICE_MODEM_CURRENT_CAPABILITIES, current_caps, + NULL); + + /* If the data port is known, set it as the IP interface immediately */ + data_port = nm_modem_get_data_port (modem); + if (data_port) + nm_device_set_ip_iface (device, data_port); + + return device; +} + +static void +nm_device_modem_init (NMDeviceModem *self) +{ +} + +static void +set_modem (NMDeviceModem *self, NMModem *modem) +{ + NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (self); + + g_return_if_fail (modem != NULL); + + priv->modem = g_object_ref (modem); + + g_signal_connect (modem, NM_MODEM_PPP_FAILED, G_CALLBACK (ppp_failed), self); + g_signal_connect (modem, NM_MODEM_PREPARE_RESULT, G_CALLBACK (modem_prepare_result), self); + g_signal_connect (modem, NM_MODEM_IP4_CONFIG_RESULT, G_CALLBACK (modem_ip4_config_result), self); + g_signal_connect (modem, NM_MODEM_AUTH_REQUESTED, G_CALLBACK (modem_auth_requested), self); + g_signal_connect (modem, NM_MODEM_AUTH_RESULT, G_CALLBACK (modem_auth_result), self); + g_signal_connect (modem, NM_MODEM_STATE_CHANGED, G_CALLBACK (modem_state_cb), self); + g_signal_connect (modem, NM_MODEM_REMOVED, G_CALLBACK (modem_removed_cb), self); + + /* In the old ModemManager the data port is known from the very beginning; + * while in the new ModemManager the data port is set afterwards when the bearer gets + * created */ + g_signal_connect (modem, "notify::" NM_MODEM_DATA_PORT, G_CALLBACK (data_port_changed_cb), self); +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (object); + + switch (prop_id) { + case PROP_MODEM: + /* construct-only */ + set_modem (NM_DEVICE_MODEM (object), g_value_get_object (value)); + break; + case PROP_CAPABILITIES: + priv->caps = g_value_get_uint (value); + break; + case PROP_CURRENT_CAPABILITIES: + priv->current_caps = g_value_get_uint (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (object); + + switch (prop_id) { + case PROP_MODEM: + g_value_set_object (value, priv->modem); + break; + case PROP_CAPABILITIES: + g_value_set_uint (value, priv->caps); + break; + case PROP_CURRENT_CAPABILITIES: + g_value_set_uint (value, priv->current_caps); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +dispose (GObject *object) +{ + NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (object); + + if (priv->modem) + g_signal_handlers_disconnect_by_data (priv->modem, NM_DEVICE_MODEM (object)); + g_clear_object (&priv->modem); + + G_OBJECT_CLASS (nm_device_modem_parent_class)->dispose (object); +} + +static void +nm_device_modem_class_init (NMDeviceModemClass *mclass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (mclass); + NMDeviceClass *device_class = NM_DEVICE_CLASS (mclass); + + g_type_class_add_private (object_class, sizeof (NMDeviceModemPrivate)); + + /* Virtual methods */ + object_class->dispose = dispose; + object_class->get_property = get_property; + object_class->set_property = set_property; + + device_class->get_hw_address_length = get_hw_address_length; + device_class->check_connection_compatible = check_connection_compatible; + device_class->check_connection_available = check_connection_available; + device_class->complete_connection = complete_connection; + device_class->deactivate = deactivate; + device_class->act_stage1_prepare = act_stage1_prepare; + device_class->act_stage2_config = act_stage2_config; + device_class->act_stage3_ip4_config_start = act_stage3_ip4_config_start; + device_class->act_stage3_ip6_config_start = act_stage3_ip6_config_start; + device_class->ip4_config_pre_commit = ip4_config_pre_commit; + device_class->get_enabled = get_enabled; + device_class->set_enabled = set_enabled; + device_class->owns_iface = owns_iface; + device_class->is_available = is_available; + + device_class->state_changed = device_state_changed; + + /* Properties */ + g_object_class_install_property + (object_class, PROP_MODEM, + g_param_spec_object (NM_DEVICE_MODEM_MODEM, + "Modem", + "Modem", + NM_TYPE_MODEM, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property (object_class, PROP_CAPABILITIES, + g_param_spec_uint (NM_DEVICE_MODEM_CAPABILITIES, + "Modem Capabilities", + "Modem Capabilities", + 0, G_MAXUINT32, NM_DEVICE_MODEM_CAPABILITY_NONE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property (object_class, PROP_CURRENT_CAPABILITIES, + g_param_spec_uint (NM_DEVICE_MODEM_CURRENT_CAPABILITIES, + "Current modem Capabilities", + "Current modem Capabilities", + 0, G_MAXUINT32, NM_DEVICE_MODEM_CAPABILITY_NONE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + nm_dbus_manager_register_exported_type (nm_dbus_manager_get (), + G_TYPE_FROM_CLASS (mclass), + &dbus_glib_nm_device_modem_object_info); +} diff --git a/src/devices/wwan/nm-device-modem.h b/src/devices/wwan/nm-device-modem.h new file mode 100644 index 00000000..ee6b2988 --- /dev/null +++ b/src/devices/wwan/nm-device-modem.h @@ -0,0 +1,54 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2011 Red Hat, Inc. + */ + +#ifndef NM_DEVICE_MODEM_H +#define NM_DEVICE_MODEM_H + +#include +#include + +#include "nm-device.h" +#include "nm-modem.h" + +#define NM_TYPE_DEVICE_MODEM (nm_device_modem_get_type ()) +#define NM_DEVICE_MODEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_MODEM, NMDeviceModem)) +#define NM_DEVICE_MODEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_MODEM, NMDeviceModemClass)) +#define NM_IS_DEVICE_MODEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_MODEM)) +#define NM_IS_DEVICE_MODEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_MODEM)) +#define NM_DEVICE_MODEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_MODEM, NMDeviceModemClass)) + +#define NM_DEVICE_MODEM_MODEM "modem" +#define NM_DEVICE_MODEM_CAPABILITIES "modem-capabilities" +#define NM_DEVICE_MODEM_CURRENT_CAPABILITIES "current-capabilities" + +typedef struct { + NMDevice parent; +} NMDeviceModem; + +typedef struct { + NMDeviceClass parent; + +} NMDeviceModemClass; + +GType nm_device_modem_get_type (void); + +NMDevice *nm_device_modem_new (NMModem *modem); + +#endif /* NM_DEVICE_MODEM_H */ diff --git a/src/devices/wwan/nm-modem-broadband.c b/src/devices/wwan/nm-modem-broadband.c new file mode 100644 index 00000000..807b8924 --- /dev/null +++ b/src/devices/wwan/nm-modem-broadband.c @@ -0,0 +1,987 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2012 Aleksander Morgado + */ + +#include +#include +#include +#include "nm-modem-broadband.h" +#include "nm-setting-connection.h" +#include "nm-logging.h" +#include "NetworkManagerUtils.h" +#include "nm-device-private.h" + +G_DEFINE_TYPE (NMModemBroadband, nm_modem_broadband, NM_TYPE_MODEM) + +struct _NMModemBroadbandPrivate { + /* The modem object from dbus */ + MMObject *modem_object; + /* Per-interface objects */ + MMModem *modem_iface; + MMModemSimple *simple_iface; + + /* Connection setup */ + MMSimpleConnectProperties *connect_properties; + MMBearer *bearer; + MMBearerIpConfig *ipv4_config; + MMBearerIpConfig *ipv6_config; + + guint32 pin_tries; +}; + +enum { + PROP_0, + PROP_MODEM, +}; + +#define MODEM_CAPS_3GPP(caps) (caps & (MM_MODEM_CAPABILITY_GSM_UMTS | \ + MM_MODEM_CAPABILITY_LTE | \ + MM_MODEM_CAPABILITY_LTE_ADVANCED)) + +#define MODEM_CAPS_3GPP2(caps) (caps & (MM_MODEM_CAPABILITY_CDMA_EVDO)) + +/* Maximum time to keep the DBus call waiting for a connection result */ +#define MODEM_CONNECT_TIMEOUT_SECS 120 + +/*****************************************************************************/ + +static NMDeviceStateReason +translate_mm_error (GError *error) +{ + NMDeviceStateReason reason; + + g_return_val_if_fail (error != NULL, NM_DEVICE_STATE_REASON_UNKNOWN); + + if (g_error_matches (error, MM_CONNECTION_ERROR, MM_CONNECTION_ERROR_NO_CARRIER)) + reason = NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER; + else if (g_error_matches (error, MM_CONNECTION_ERROR, MM_CONNECTION_ERROR_NO_DIALTONE)) + reason = NM_DEVICE_STATE_REASON_MODEM_NO_DIAL_TONE; + else if (g_error_matches (error, MM_CONNECTION_ERROR, MM_CONNECTION_ERROR_BUSY)) + reason = NM_DEVICE_STATE_REASON_MODEM_BUSY; + else if (g_error_matches (error, MM_CONNECTION_ERROR, MM_CONNECTION_ERROR_NO_ANSWER)) + reason = NM_DEVICE_STATE_REASON_MODEM_DIAL_TIMEOUT; + else if (g_error_matches (error, MM_MOBILE_EQUIPMENT_ERROR, MM_MOBILE_EQUIPMENT_ERROR_NETWORK_NOT_ALLOWED)) + reason = NM_DEVICE_STATE_REASON_GSM_REGISTRATION_DENIED; + else if (g_error_matches (error, MM_MOBILE_EQUIPMENT_ERROR, MM_MOBILE_EQUIPMENT_ERROR_NETWORK_TIMEOUT)) + reason = NM_DEVICE_STATE_REASON_GSM_REGISTRATION_TIMEOUT; + else if (g_error_matches (error, MM_MOBILE_EQUIPMENT_ERROR, MM_MOBILE_EQUIPMENT_ERROR_NO_NETWORK)) + reason = NM_DEVICE_STATE_REASON_GSM_REGISTRATION_NOT_SEARCHING; + else if (g_error_matches (error, MM_MOBILE_EQUIPMENT_ERROR, MM_MOBILE_EQUIPMENT_ERROR_SIM_NOT_INSERTED)) + reason = NM_DEVICE_STATE_REASON_GSM_SIM_NOT_INSERTED; + else if (g_error_matches (error, MM_MOBILE_EQUIPMENT_ERROR, MM_MOBILE_EQUIPMENT_ERROR_SIM_PIN)) + reason = NM_DEVICE_STATE_REASON_GSM_SIM_PIN_REQUIRED; + else if (g_error_matches (error, MM_MOBILE_EQUIPMENT_ERROR, MM_MOBILE_EQUIPMENT_ERROR_SIM_PUK)) + reason = NM_DEVICE_STATE_REASON_GSM_SIM_PUK_REQUIRED; + else if (g_error_matches (error, MM_MOBILE_EQUIPMENT_ERROR, MM_MOBILE_EQUIPMENT_ERROR_SIM_WRONG)) + reason = NM_DEVICE_STATE_REASON_GSM_SIM_WRONG; + else if (g_error_matches (error, MM_MOBILE_EQUIPMENT_ERROR, MM_MOBILE_EQUIPMENT_ERROR_INCORRECT_PASSWORD)) + reason = NM_DEVICE_STATE_REASON_SIM_PIN_INCORRECT; + else { + /* unable to map the ModemManager error to a NM_DEVICE_STATE_REASON */ + nm_log_dbg (LOGD_MB, "unmapped error detected: '%s'", error->message); + reason = NM_DEVICE_STATE_REASON_UNKNOWN; + } + + return reason; +} + +/*****************************************************************************/ + +static void +get_capabilities (NMModem *_self, + NMDeviceModemCapabilities *modem_caps, + NMDeviceModemCapabilities *current_caps) +{ + NMModemBroadband *self = NM_MODEM_BROADBAND (_self); + MMModemCapability all_supported = MM_MODEM_CAPABILITY_NONE; + MMModemCapability *supported; + guint n_supported; + + /* For now, we don't care about the capability combinations, just merge all + * combinations in a single mask */ + if (mm_modem_get_supported_capabilities (self->priv->modem_iface, &supported, &n_supported)) { + guint i; + + for (i = 0; i < n_supported; i++) + all_supported |= supported[i]; + + g_free (supported); + } + + *modem_caps = (NMDeviceModemCapabilities) all_supported; + *current_caps = (NMDeviceModemCapabilities) mm_modem_get_current_capabilities (self->priv->modem_iface); +} + +static gboolean +owns_port (NMModem *_self, const char *iface) +{ + NMModemBroadband *self = NM_MODEM_BROADBAND (_self); + const MMModemPortInfo *ports = NULL; + guint n_ports = 0, i; + gboolean owns = FALSE; + + mm_modem_peek_ports (self->priv->modem_iface, &ports, &n_ports); + for (i = 0; i < n_ports && !owns; i++) + owns = (g_strcmp0 (iface, ports[i].name) == 0); + return owns; +} + +/*****************************************************************************/ + +static void +ask_for_pin (NMModemBroadband *self) +{ + guint32 tries; + + tries = self->priv->pin_tries++; + nm_modem_get_secrets (NM_MODEM (self), + NM_SETTING_GSM_SETTING_NAME, + tries ? TRUE : FALSE, + NM_SETTING_GSM_PIN); +} + +static void +connect_ready (MMModemSimple *simple_iface, + GAsyncResult *res, + NMModemBroadband *self) +{ + GError *error = NULL; + guint ip_method; + + g_clear_object (&self->priv->connect_properties); + + self->priv->bearer = mm_modem_simple_connect_finish (simple_iface, res, &error); + if (!self->priv->bearer) { + if (g_error_matches (error, + MM_MOBILE_EQUIPMENT_ERROR, + MM_MOBILE_EQUIPMENT_ERROR_SIM_PIN) || + (g_error_matches (error, + MM_CORE_ERROR, + MM_CORE_ERROR_UNAUTHORIZED) && + mm_modem_get_unlock_required (self->priv->modem_iface) == MM_MODEM_LOCK_SIM_PIN)) { + /* Request PIN */ + ask_for_pin (self); + } else { + /* Strip remote error info before logging it */ + if (g_dbus_error_is_remote_error (error)) + g_dbus_error_strip_remote_error (error); + + nm_log_warn (LOGD_MB, "(%s) failed to connect modem: %s", + nm_modem_get_uid (NM_MODEM (self)), + error && error->message ? error->message : "(unknown)"); + g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, translate_mm_error (error)); + } + + g_clear_error (&error); + g_object_unref (self); + return; + } + + /* Grab IP configurations */ + self->priv->ipv4_config = mm_bearer_get_ipv4_config (self->priv->bearer); + self->priv->ipv6_config = mm_bearer_get_ipv6_config (self->priv->bearer); + + switch (mm_bearer_ip_config_get_method (self->priv->ipv4_config)) { + case MM_BEARER_IP_METHOD_PPP: + ip_method = MM_MODEM_IP_METHOD_PPP; + break; + case MM_BEARER_IP_METHOD_STATIC: + ip_method = MM_MODEM_IP_METHOD_STATIC; + break; + case MM_BEARER_IP_METHOD_DHCP: + ip_method = MM_MODEM_IP_METHOD_DHCP; + break; + default: + error = g_error_new (NM_MODEM_ERROR, + NM_MODEM_ERROR_CONNECTION_INVALID, + "invalid IP config"); + nm_log_warn (LOGD_MB, "(%s) failed to connect modem: %s", + nm_modem_get_uid (NM_MODEM (self)), + error->message); + g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, translate_mm_error (error)); + g_error_free (error); + g_object_unref (self); + return; + } + + /* IPv4 for now only */ + g_object_set (self, + NM_MODEM_DATA_PORT, mm_bearer_get_interface (self->priv->bearer), + NM_MODEM_IP_METHOD, ip_method, + NM_MODEM_IP_TIMEOUT, mm_bearer_get_ip_timeout (self->priv->bearer), + NULL); + + g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, TRUE, NM_DEVICE_STATE_REASON_NONE); + g_object_unref (self); +} + +static MMSimpleConnectProperties * +create_cdma_connect_properties (NMConnection *connection) +{ + NMSettingCdma *setting; + MMSimpleConnectProperties *properties; + const gchar *str; + + setting = nm_connection_get_setting_cdma (connection); + properties = mm_simple_connect_properties_new (); + + str = nm_setting_cdma_get_number (setting); + if (str) + mm_simple_connect_properties_set_number (properties, str); + + return properties; +} + +static MMSimpleConnectProperties * +create_gsm_connect_properties (NMConnection *connection) +{ + NMSettingGsm *setting; + NMSettingPPP *s_ppp; + MMSimpleConnectProperties *properties; + const gchar *str; + + setting = nm_connection_get_setting_gsm (connection); + properties = mm_simple_connect_properties_new (); + + /* TODO: not needed */ + str = nm_setting_gsm_get_number (setting); + if (str) + mm_simple_connect_properties_set_number (properties, str); + + str = nm_setting_gsm_get_apn (setting); + if (str) + mm_simple_connect_properties_set_apn (properties, str); + + str = nm_setting_gsm_get_network_id (setting); + if (str) + mm_simple_connect_properties_set_operator_id (properties, str); + + str = nm_setting_gsm_get_pin (setting); + if (str) + mm_simple_connect_properties_set_pin (properties, str); + + str = nm_setting_gsm_get_username (setting); + if (str) + mm_simple_connect_properties_set_user (properties, str); + + str = nm_setting_gsm_get_password (setting); + if (str) + mm_simple_connect_properties_set_password (properties, str); + + /* Roaming */ + if (nm_setting_gsm_get_home_only (setting)) + mm_simple_connect_properties_set_allow_roaming (properties, FALSE); + + /* For IpMethod == STATIC or DHCP */ + s_ppp = nm_connection_get_setting_ppp (connection); + if (s_ppp) { + MMBearerAllowedAuth allowed_auth = MM_BEARER_ALLOWED_AUTH_UNKNOWN; + + if (nm_setting_ppp_get_noauth (s_ppp)) + allowed_auth = MM_BEARER_ALLOWED_AUTH_NONE; + if (!nm_setting_ppp_get_refuse_pap (s_ppp)) + allowed_auth |= MM_BEARER_ALLOWED_AUTH_PAP; + if (!nm_setting_ppp_get_refuse_chap (s_ppp)) + allowed_auth |= MM_BEARER_ALLOWED_AUTH_CHAP; + if (!nm_setting_ppp_get_refuse_mschap (s_ppp)) + allowed_auth |= MM_BEARER_ALLOWED_AUTH_MSCHAP; + if (!nm_setting_ppp_get_refuse_mschapv2 (s_ppp)) + allowed_auth |= MM_BEARER_ALLOWED_AUTH_MSCHAPV2; + if (!nm_setting_ppp_get_refuse_eap (s_ppp)) + allowed_auth |= MM_BEARER_ALLOWED_AUTH_EAP; + + mm_simple_connect_properties_set_allowed_auth (properties, allowed_auth); + } + + return properties; +} + +static NMActStageReturn +act_stage1_prepare (NMModem *_self, + NMConnection *connection, + NMDeviceStateReason *reason) +{ + NMModemBroadband *self = NM_MODEM_BROADBAND (_self); + MMModemCapability caps; + + g_clear_object (&self->priv->connect_properties); + + caps = mm_modem_get_current_capabilities (self->priv->modem_iface); + if (MODEM_CAPS_3GPP (caps)) + self->priv->connect_properties = create_gsm_connect_properties (connection); + else if (MODEM_CAPS_3GPP2 (caps)) + self->priv->connect_properties = create_cdma_connect_properties (connection); + else { + nm_log_warn (LOGD_MB, "(%s) not a mobile broadband modem", + nm_modem_get_uid (NM_MODEM (self))); + return NM_ACT_STAGE_RETURN_FAILURE; + } + + if (!self->priv->simple_iface) + self->priv->simple_iface = mm_object_get_modem_simple (self->priv->modem_object); + + g_dbus_proxy_set_default_timeout (G_DBUS_PROXY (self->priv->simple_iface), MODEM_CONNECT_TIMEOUT_SECS * 1000); + mm_modem_simple_connect (self->priv->simple_iface, + self->priv->connect_properties, + NULL, + (GAsyncReadyCallback)connect_ready, + g_object_ref (self)); + + return NM_ACT_STAGE_RETURN_POSTPONE; +} + +/*****************************************************************************/ + +static gboolean +check_connection_compatible (NMModem *_self, NMConnection *connection) +{ + NMModemBroadband *self = NM_MODEM_BROADBAND (_self); + MMModemCapability modem_caps; + NMSettingConnection *s_con; + + modem_caps = mm_modem_get_current_capabilities (self->priv->modem_iface); + s_con = nm_connection_get_setting_connection (connection); + g_assert (s_con); + + if (MODEM_CAPS_3GPP (modem_caps)) { + NMSettingGsm *s_gsm; + + if (!g_str_equal (nm_setting_connection_get_connection_type (s_con), + NM_SETTING_GSM_SETTING_NAME)) + return FALSE; + + s_gsm = nm_connection_get_setting_gsm (connection); + if (!s_gsm) + return FALSE; + + return TRUE; + } + + if (MODEM_CAPS_3GPP2 (modem_caps)) { + NMSettingCdma *s_cdma; + + if (!g_str_equal (nm_setting_connection_get_connection_type (s_con), + NM_SETTING_CDMA_SETTING_NAME)) + return FALSE; + + s_cdma = nm_connection_get_setting_cdma (connection); + if (!s_cdma) + return FALSE; + + return TRUE; + } + + return FALSE; +} + +/*****************************************************************************/ + +static gboolean +complete_connection (NMModem *_self, + NMConnection *connection, + const GSList *existing_connections, + GError **error) +{ + NMModemBroadband *self = NM_MODEM_BROADBAND (_self); + MMModemCapability modem_caps; + NMSettingPPP *s_ppp; + + modem_caps = mm_modem_get_current_capabilities (self->priv->modem_iface); + + /* PPP settings common to 3GPP and 3GPP2 */ + s_ppp = nm_connection_get_setting_ppp (connection); + if (!s_ppp) { + s_ppp = (NMSettingPPP *) nm_setting_ppp_new (); + g_object_set (G_OBJECT (s_ppp), + NM_SETTING_PPP_LCP_ECHO_FAILURE, 5, + NM_SETTING_PPP_LCP_ECHO_INTERVAL, 30, + NULL); + nm_connection_add_setting (connection, NM_SETTING (s_ppp)); + } + + if (MODEM_CAPS_3GPP (modem_caps)) { + NMSettingGsm *s_gsm; + + s_gsm = nm_connection_get_setting_gsm (connection); + if (!s_gsm || !nm_setting_gsm_get_apn (s_gsm)) { + /* Need an APN at least */ + g_set_error_literal (error, + NM_SETTING_GSM_ERROR, + NM_SETTING_GSM_ERROR_MISSING_PROPERTY, + NM_SETTING_GSM_APN); + return FALSE; + } + + /* TODO: This is not needed */ + if (!nm_setting_gsm_get_number (s_gsm)) + g_object_set (G_OBJECT (s_gsm), NM_SETTING_GSM_NUMBER, "*99#", NULL); + + nm_utils_complete_generic (connection, + NM_SETTING_GSM_SETTING_NAME, + existing_connections, + _("GSM connection %d"), + NULL, + FALSE); /* No IPv6 yet by default */ + + return TRUE; + } + + if (MODEM_CAPS_3GPP2 (modem_caps)) { + NMSettingCdma *s_cdma; + + s_cdma = nm_connection_get_setting_cdma (connection); + if (!s_cdma) { + s_cdma = (NMSettingCdma *) nm_setting_cdma_new (); + nm_connection_add_setting (connection, NM_SETTING (s_cdma)); + } + + if (!nm_setting_cdma_get_number (s_cdma)) + g_object_set (G_OBJECT (s_cdma), NM_SETTING_CDMA_NUMBER, "#777", NULL); + + nm_utils_complete_generic (connection, + NM_SETTING_CDMA_SETTING_NAME, + existing_connections, + _("CDMA connection %d"), + NULL, + FALSE); /* No IPv6 yet by default */ + + return TRUE; + } + + g_set_error (error, + NM_MODEM_ERROR, + NM_MODEM_ERROR_CONNECTION_INCOMPATIBLE, + "Device is not a mobile broadband modem"); + return FALSE; +} + +/*****************************************************************************/ + +static gboolean +get_user_pass (NMModem *modem, + NMConnection *connection, + const char **user, + const char **pass) +{ + NMSettingGsm *s_gsm; + NMSettingCdma *s_cdma; + + s_gsm = nm_connection_get_setting_gsm (connection); + s_cdma = nm_connection_get_setting_cdma (connection); + if (!s_gsm && !s_cdma) + return FALSE; + + if (user) { + if (s_gsm) + *user = nm_setting_gsm_get_username (s_gsm); + else if (s_cdma) + *user = nm_setting_cdma_get_username (s_cdma); + } + if (pass) { + if (s_gsm) + *pass = nm_setting_gsm_get_password (s_gsm); + else if (s_cdma) + *pass = nm_setting_cdma_get_password (s_cdma); + } + + return TRUE; +} + +/*****************************************************************************/ +/* Query/Update enabled state */ + +static void +set_power_state_low_ready (MMModem *modem, + GAsyncResult *result, + NMModemBroadband *self) +{ + GError *error = NULL; + + if (!mm_modem_set_power_state_finish (modem, result, &error)) { + /* Log but ignore errors; not all modems support low power state */ + nm_log_dbg (LOGD_MB, "(%s) failed to set modem low power state: %s", + nm_modem_get_uid (NM_MODEM (self)), + error && error->message ? error->message : "(unknown)"); + g_clear_error (&error); + } + + /* Balance refcount */ + g_object_unref (self); +} + +static void +modem_disable_ready (MMModem *modem_iface, + GAsyncResult *res, + NMModemBroadband *self) +{ + GError *error = NULL; + + if (mm_modem_disable_finish (modem_iface, res, &error)) { + /* Once disabled, move to low-power mode */ + mm_modem_set_power_state (modem_iface, + MM_MODEM_POWER_STATE_LOW, + NULL, + (GAsyncReadyCallback) set_power_state_low_ready, + g_object_ref (self)); + } else { + nm_log_warn (LOGD_MB, "(%s) failed to disable modem: %s", + nm_modem_get_uid (NM_MODEM (self)), + error && error->message ? error->message : "(unknown)"); + nm_modem_set_prev_state (NM_MODEM (self), "disable failed"); + g_clear_error (&error); + } + + /* Balance refcount */ + g_object_unref (self); +} + +static void +modem_enable_ready (MMModem *modem_iface, + GAsyncResult *res, + NMModemBroadband *self) +{ + GError *error = NULL; + + if (!mm_modem_enable_finish (modem_iface, res, &error)) { + nm_log_warn (LOGD_MB, "(%s) failed to enable modem: %s", + nm_modem_get_uid (NM_MODEM (self)), + error && error->message ? error->message : "(unknown)"); + nm_modem_set_prev_state (NM_MODEM (self), "enable failed"); + g_clear_error (&error); + } + + /* Balance refcount */ + g_object_unref (self); +} + +static void +set_mm_enabled (NMModem *_self, + gboolean enabled) +{ + NMModemBroadband *self = NM_MODEM_BROADBAND (_self); + + if (enabled) { + mm_modem_enable (self->priv->modem_iface, + NULL, /* cancellable */ + (GAsyncReadyCallback)modem_enable_ready, + g_object_ref (self)); + } else { + mm_modem_disable (self->priv->modem_iface, + NULL, /* cancellable */ + (GAsyncReadyCallback)modem_disable_ready, + g_object_ref (self)); + } +} + +/*****************************************************************************/ +/* IP method static */ + +static gboolean +ip_string_to_network_address (const gchar *str, + guint32 *out) +{ + guint32 addr = 0; + gboolean success = FALSE; + + if (!str || inet_pton (AF_INET, str, &addr) != 1) + addr = 0; + else + success = TRUE; + + *out = (guint32)addr; + return success; +} + +static gboolean +static_stage3_done (NMModemBroadband *self) +{ + GError *error = NULL; + NMIP4Config *config = NULL; + const gchar *address_string; + const gchar *gw_string; + guint32 address_network; + guint32 gw; + NMPlatformIP4Address address; + const gchar **dns; + guint i; + + g_assert (self->priv->ipv4_config); + + nm_log_info (LOGD_MB, "(%s): IPv4 static configuration:", + nm_modem_get_uid (NM_MODEM (self))); + + /* Fully fail if invalid IP address retrieved */ + address_string = mm_bearer_ip_config_get_address (self->priv->ipv4_config); + if (!ip_string_to_network_address (address_string, &address_network)) { + error = g_error_new (NM_MODEM_ERROR, + NM_MODEM_ERROR_CONNECTION_INVALID, + "(%s) retrieving IP4 configuration failed: invalid address given '%s'", + nm_modem_get_uid (NM_MODEM (self)), + address_string); + goto out; + } + + /* Missing gateway not a hard failure */ + gw_string = mm_bearer_ip_config_get_gateway (self->priv->ipv4_config); + ip_string_to_network_address (gw_string, &gw); + + config = nm_ip4_config_new (); + + memset (&address, 0, sizeof (address)); + address.address = address_network; + address.plen = mm_bearer_ip_config_get_prefix (self->priv->ipv4_config); + address.source = NM_PLATFORM_SOURCE_WWAN; + nm_ip4_config_add_address (config, &address); + + nm_log_info (LOGD_MB, " address %s/%d", address_string, address.plen); + + if (gw) { + nm_ip4_config_set_gateway (config, gw); + nm_log_info (LOGD_MB, " gateway %s", gw_string); + } + + /* DNS servers */ + dns = mm_bearer_ip_config_get_dns (self->priv->ipv4_config); + for (i = 0; dns[i]; i++) { + if ( ip_string_to_network_address (dns[i], &address_network) + && address_network > 0) { + nm_ip4_config_add_nameserver (config, address_network); + nm_log_info (LOGD_MB, " DNS %s", dns[i]); + } + } + +out: + g_signal_emit_by_name (self, NM_MODEM_IP4_CONFIG_RESULT, config, error); + g_clear_error (&error); + return FALSE; +} + +static NMActStageReturn +static_stage3_ip4_config_start (NMModem *_self, + NMActRequest *req, + NMDeviceStateReason *reason) +{ + NMModemBroadband *self = NM_MODEM_BROADBAND (_self); + + /* We schedule it in an idle just to follow the same logic as in the + * generic modem implementation. */ + g_idle_add ((GSourceFunc)static_stage3_done, self); + + return NM_ACT_STAGE_RETURN_POSTPONE; +} + +/*****************************************************************************/ +/* Disconnect */ + +typedef struct { + NMModemBroadband *self; + gboolean warn; +} SimpleDisconnectContext; + +static void +simple_disconnect_context_free (SimpleDisconnectContext *ctx) +{ + g_object_unref (ctx->self); + g_slice_free (SimpleDisconnectContext, ctx); +} + +static void +simple_disconnect_ready (MMModemSimple *modem_iface, + GAsyncResult *res, + SimpleDisconnectContext *ctx) +{ + GError *error = NULL; + + if (!mm_modem_simple_disconnect_finish (modem_iface, res, &error)) { + if (ctx->warn) + nm_log_warn (LOGD_MB, "(%s) failed to disconnect modem: %s", + nm_modem_get_uid (NM_MODEM (ctx->self)), + error && error->message ? error->message : "(unknown)"); + g_clear_error (&error); + } + + simple_disconnect_context_free (ctx); +} + +static void +disconnect (NMModem *self, + gboolean warn) +{ + SimpleDisconnectContext *ctx; + + ctx = g_slice_new (SimpleDisconnectContext); + ctx->self = g_object_ref (self); + + /* Don't bother warning on FAILED since the modem is already gone */ + ctx->warn = warn; + + mm_modem_simple_disconnect ( + ctx->self->priv->simple_iface, + NULL, /* bearer path; if NULL given ALL get disconnected */ + NULL, /* cancellable */ + (GAsyncReadyCallback)simple_disconnect_ready, + ctx); +} + +/*****************************************************************************/ + +static void +deactivate (NMModem *_self, NMDevice *device) +{ + NMModemBroadband *self = NM_MODEM_BROADBAND (_self); + + /* TODO: cancel SimpleConnect() if any */ + + /* Cleanup IPv4 addresses and routes */ + g_clear_object (&self->priv->ipv4_config); + g_clear_object (&self->priv->ipv6_config); + g_clear_object (&self->priv->bearer); + + self->priv->pin_tries = 0; + + /* Chain up parent's */ + NM_MODEM_CLASS (nm_modem_broadband_parent_class)->deactivate (_self, device); +} + +/*****************************************************************************/ + +#define MAP_STATE(name) case MM_MODEM_STATE_##name: return NM_MODEM_STATE_##name; + +static NMModemState +mm_state_to_nm (MMModemState mm_state) +{ + switch (mm_state) { + MAP_STATE(UNKNOWN) + MAP_STATE(FAILED) + MAP_STATE(INITIALIZING) + MAP_STATE(LOCKED) + MAP_STATE(DISABLED) + MAP_STATE(DISABLING) + MAP_STATE(ENABLING) + MAP_STATE(ENABLED) + MAP_STATE(SEARCHING) + MAP_STATE(REGISTERED) + MAP_STATE(DISCONNECTING) + MAP_STATE(CONNECTING) + MAP_STATE(CONNECTED) + } + return NM_MODEM_STATE_UNKNOWN; +} + +static void +modem_state_changed (MMModem *modem, + MMModemState old_state, + MMModemState new_state, + MMModemStateChangeReason reason, + NMModemBroadband *self) +{ + + /* After the SIM is unlocked MM1 will move the device to INITIALIZING which + * is an unavailable state. That makes state handling confusing here, so + * suppress this state change and let the modem move from LOCKED to DISABLED. + */ + if (new_state == MM_MODEM_STATE_INITIALIZING && old_state == MM_MODEM_STATE_LOCKED) + return; + + nm_modem_set_state (NM_MODEM (self), + mm_state_to_nm (new_state), + mm_modem_state_change_reason_get_string (reason)); +} + +/*****************************************************************************/ + +NMModem * +nm_modem_broadband_new (GObject *object, GError **error) +{ + NMModem *modem; + MMObject *modem_object; + MMModem *modem_iface; + gchar *drivers; + + g_return_val_if_fail (MM_IS_OBJECT (object), NULL); + modem_object = MM_OBJECT (object); + + /* Ensure we have the 'Modem' interface and the primary port at least */ + modem_iface = mm_object_peek_modem (modem_object); + g_return_val_if_fail (!!modem_iface, NULL); + g_return_val_if_fail (!!mm_modem_get_primary_port (modem_iface), NULL); + + /* Build a single string with all drivers listed */ + drivers = g_strjoinv (", ", (gchar **)mm_modem_get_drivers (modem_iface)); + + modem = g_object_new (NM_TYPE_MODEM_BROADBAND, + NM_MODEM_PATH, mm_object_get_path (modem_object), + NM_MODEM_UID, mm_modem_get_primary_port (modem_iface), + NM_MODEM_CONTROL_PORT, mm_modem_get_primary_port (modem_iface), + NM_MODEM_DATA_PORT, NULL, /* We don't know it until bearer created */ + NM_MODEM_STATE, mm_state_to_nm (mm_modem_get_state (modem_iface)), + NM_MODEM_DEVICE_ID, mm_modem_get_device_identifier (modem_iface), + NM_MODEM_BROADBAND_MODEM, modem_object, + NM_MODEM_DRIVER, drivers, + NULL); + g_free (drivers); + return modem; +} + +static void +get_sim_ready (MMModem *modem, + GAsyncResult *res, + NMModemBroadband *self) +{ + GError *error = NULL; + MMSim *new_sim; + + new_sim = mm_modem_get_sim_finish (modem, res, &error); + if (new_sim) { + g_object_set (G_OBJECT (self), + NM_MODEM_SIM_ID, mm_sim_get_identifier (new_sim), + NULL); + g_object_unref (new_sim); + } else { + nm_log_warn (LOGD_MB, "(%s) failed to retrieve SIM object: %s", + nm_modem_get_uid (NM_MODEM (self)), + error && error->message ? error->message : "(unknown)"); + } + g_clear_error (&error); + g_object_unref (self); +} + +static void +sim_changed (MMModem *modem, GParamSpec *pspec, gpointer user_data) +{ + NMModemBroadband *self = NM_MODEM_BROADBAND (user_data); + + g_return_if_fail (modem == self->priv->modem_iface); + + if (mm_modem_get_sim_path (self->priv->modem_iface)) { + mm_modem_get_sim (self->priv->modem_iface, + NULL, /* cancellable */ + (GAsyncReadyCallback) get_sim_ready, + g_object_ref (self)); + } else + g_object_set (G_OBJECT (self), NM_MODEM_SIM_ID, NULL, NULL); +} + +static void +nm_modem_broadband_init (NMModemBroadband *self) +{ + self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, + NM_TYPE_MODEM_BROADBAND, + NMModemBroadbandPrivate); +} + +static void +set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + NMModemBroadband *self = NM_MODEM_BROADBAND (object); + + switch (prop_id) { + case PROP_MODEM: + /* construct-only */ + self->priv->modem_object = g_value_dup_object (value); + self->priv->modem_iface = mm_object_get_modem (self->priv->modem_object); + g_assert (self->priv->modem_iface != NULL); + g_signal_connect (self->priv->modem_iface, + "state-changed", + G_CALLBACK (modem_state_changed), + self); + g_signal_connect (self->priv->modem_iface, + "notify::sim", + G_CALLBACK (sim_changed), + self); + sim_changed (self->priv->modem_iface, NULL, self); + + /* Note: don't grab the Simple iface here; the Modem interface is the + * only one assumed to be always valid and available */ + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + NMModemBroadband *self = NM_MODEM_BROADBAND (object); + + switch (prop_id) { + case PROP_MODEM: + g_value_set_object (value, self->priv->modem_object); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +dispose (GObject *object) +{ + NMModemBroadband *self = NM_MODEM_BROADBAND (object); + + g_clear_object (&self->priv->ipv4_config); + g_clear_object (&self->priv->ipv6_config); + g_clear_object (&self->priv->bearer); + g_clear_object (&self->priv->modem_iface); + g_clear_object (&self->priv->simple_iface); + g_clear_object (&self->priv->modem_object); + + G_OBJECT_CLASS (nm_modem_broadband_parent_class)->dispose (object); +} + +static void +nm_modem_broadband_class_init (NMModemBroadbandClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMModemClass *modem_class = NM_MODEM_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (NMModemBroadbandPrivate)); + + /* Virtual methods */ + object_class->dispose = dispose; + object_class->get_property = get_property; + object_class->set_property = set_property; + + modem_class->get_capabilities = get_capabilities; + modem_class->static_stage3_ip4_config_start = static_stage3_ip4_config_start; + modem_class->disconnect = disconnect; + modem_class->deactivate = deactivate; + modem_class->set_mm_enabled = set_mm_enabled; + modem_class->get_user_pass = get_user_pass; + modem_class->check_connection_compatible = check_connection_compatible; + modem_class->complete_connection = complete_connection; + modem_class->act_stage1_prepare = act_stage1_prepare; + modem_class->owns_port = owns_port; + + /* Properties */ + g_object_class_install_property + (object_class, PROP_MODEM, + g_param_spec_object (NM_MODEM_BROADBAND_MODEM, + "Modem", + "Broadband modem object", + MM_GDBUS_TYPE_OBJECT, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); +} diff --git a/src/devices/wwan/nm-modem-broadband.h b/src/devices/wwan/nm-modem-broadband.h new file mode 100644 index 00000000..e12ca68c --- /dev/null +++ b/src/devices/wwan/nm-modem-broadband.h @@ -0,0 +1,58 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2012 - Aleksander Morgado + */ + +#ifndef NM_MODEM_BROADBAND_H +#define NM_MODEM_BROADBAND_H + +#include +#include +#include "nm-modem.h" + +G_BEGIN_DECLS + +#define NM_TYPE_MODEM_BROADBAND (nm_modem_broadband_get_type ()) +#define NM_MODEM_BROADBAND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_MODEM_BROADBAND, NMModemBroadband)) +#define NM_MODEM_BROADBAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_MODEM_BROADBAND, NMModemBroadbandClass)) +#define NM_IS_MODEM_BROADBAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_MODEM_BROADBAND)) +#define NM_IS_MODEM_BROADBAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_MODEM_BROADBAND)) +#define NM_MODEM_BROADBAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_MODEM_BROADBAND, NMModemBroadbandClass)) + +#define NM_MODEM_BROADBAND_MODEM "modem" + +typedef struct _NMModemBroadband NMModemBroadband; +typedef struct _NMModemBroadbandClass NMModemBroadbandClass; +typedef struct _NMModemBroadbandPrivate NMModemBroadbandPrivate; + +struct _NMModemBroadband { + NMModem parent; + NMModemBroadbandPrivate *priv; +}; + +struct _NMModemBroadbandClass { + NMModemClass parent; +}; + +GType nm_modem_broadband_get_type (void); + +NMModem *nm_modem_broadband_new (GObject *object, GError **error); + +G_END_DECLS + +#endif /* NM_MODEM_BROADBAND_H */ diff --git a/src/devices/wwan/nm-modem-enum-types.c b/src/devices/wwan/nm-modem-enum-types.c new file mode 100644 index 00000000..cf59ba2b --- /dev/null +++ b/src/devices/wwan/nm-modem-enum-types.c @@ -0,0 +1,64 @@ + + + +/* Generated by glib-mkenums. Do not edit */ + +#include "nm-modem-enum-types.h" + +#include "nm-modem.h" + +GType +nm_modem_error_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { NM_MODEM_ERROR_CONNECTION_NOT_GSM, "NM_MODEM_ERROR_CONNECTION_NOT_GSM", "ConnectionNotGsm" }, + { NM_MODEM_ERROR_CONNECTION_NOT_CDMA, "NM_MODEM_ERROR_CONNECTION_NOT_CDMA", "ConnectionNotCdma" }, + { NM_MODEM_ERROR_CONNECTION_INVALID, "NM_MODEM_ERROR_CONNECTION_INVALID", "ConnectionInvalid" }, + { NM_MODEM_ERROR_CONNECTION_INCOMPATIBLE, "NM_MODEM_ERROR_CONNECTION_INCOMPATIBLE", "ConnectionIncompatible" }, + { NM_MODEM_ERROR_INITIALIZATION_FAILED, "NM_MODEM_ERROR_INITIALIZATION_FAILED", "InitializationFailed" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("NMModemError"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +nm_modem_state_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { NM_MODEM_STATE_UNKNOWN, "NM_MODEM_STATE_UNKNOWN", "unknown" }, + { NM_MODEM_STATE_FAILED, "NM_MODEM_STATE_FAILED", "failed" }, + { NM_MODEM_STATE_INITIALIZING, "NM_MODEM_STATE_INITIALIZING", "initializing" }, + { NM_MODEM_STATE_LOCKED, "NM_MODEM_STATE_LOCKED", "locked" }, + { NM_MODEM_STATE_DISABLED, "NM_MODEM_STATE_DISABLED", "disabled" }, + { NM_MODEM_STATE_DISABLING, "NM_MODEM_STATE_DISABLING", "disabling" }, + { NM_MODEM_STATE_ENABLING, "NM_MODEM_STATE_ENABLING", "enabling" }, + { NM_MODEM_STATE_ENABLED, "NM_MODEM_STATE_ENABLED", "enabled" }, + { NM_MODEM_STATE_SEARCHING, "NM_MODEM_STATE_SEARCHING", "searching" }, + { NM_MODEM_STATE_REGISTERED, "NM_MODEM_STATE_REGISTERED", "registered" }, + { NM_MODEM_STATE_DISCONNECTING, "NM_MODEM_STATE_DISCONNECTING", "disconnecting" }, + { NM_MODEM_STATE_CONNECTING, "NM_MODEM_STATE_CONNECTING", "connecting" }, + { NM_MODEM_STATE_CONNECTED, "NM_MODEM_STATE_CONNECTED", "connected" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("NMModemState"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} + + + diff --git a/src/devices/wwan/nm-modem-enum-types.h b/src/devices/wwan/nm-modem-enum-types.h new file mode 100644 index 00000000..81ccd8d2 --- /dev/null +++ b/src/devices/wwan/nm-modem-enum-types.h @@ -0,0 +1,21 @@ + + + +/* Generated by glib-mkenums. Do not edit */ + +#ifndef __NM_MODEM_ENUM_TYPES_H__ +#define __NM_MODEM_ENUM_TYPES_H__ + +#include + +G_BEGIN_DECLS +GType nm_modem_error_get_type (void) G_GNUC_CONST; +#define NM_TYPE_MODEM_ERROR (nm_modem_error_get_type ()) +GType nm_modem_state_get_type (void) G_GNUC_CONST; +#define NM_TYPE_MODEM_STATE (nm_modem_state_get_type ()) +G_END_DECLS + +#endif /* __NM_MODEM_ENUM_TYPES_H__ */ + + + diff --git a/src/devices/wwan/nm-modem-manager.c b/src/devices/wwan/nm-modem-manager.c new file mode 100644 index 00000000..c4811700 --- /dev/null +++ b/src/devices/wwan/nm-modem-manager.c @@ -0,0 +1,757 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2009 - 2014 Red Hat, Inc. + * Copyright (C) 2009 Novell, Inc. + * Copyright (C) 2009 Canonical Ltd. + */ + +#include +#include "config.h" +#include "nm-modem-manager.h" +#include "nm-logging.h" +#include "nm-modem.h" +#include "nm-modem-old.h" +#include "nm-dbus-manager.h" +#include "nm-modem-old-types.h" +#include "nm-dbus-glib-types.h" + +#if WITH_MODEM_MANAGER_1 +#include +#include "nm-modem-broadband.h" +#endif + +#define MODEM_POKE_INTERVAL 120 + +G_DEFINE_TYPE (NMModemManager, nm_modem_manager, G_TYPE_OBJECT) + +struct _NMModemManagerPrivate { + /* ModemManager < 0.7 */ + NMDBusManager *dbus_mgr; + DBusGProxy *proxy; + guint poke_id; + +#if WITH_MODEM_MANAGER_1 + /* ModemManager >= 0.7 */ + GDBusConnection *dbus_connection; + MMManager *modem_manager_1; + guint modem_manager_1_launch_id; + gboolean old_modem_manager_found; + gboolean new_modem_manager_found; + guint modem_manager_1_name_owner_changed_id; + guint modem_manager_1_object_added_id; + guint modem_manager_1_object_removed_id; +#endif + + /* Common */ + GHashTable *modems; +}; + +enum { + MODEM_ADDED, + LAST_SIGNAL, +}; +static guint signals[LAST_SIGNAL] = { 0 }; + +/************************************************************************/ + +static void +handle_new_modem (NMModemManager *self, NMModem *modem) +{ + const char *path; + + path = nm_modem_get_path (modem); + if (g_hash_table_lookup (self->priv->modems, path)) { + g_warn_if_reached (); + return; + } + + /* Track the new modem */ + g_hash_table_insert (self->priv->modems, g_strdup (path), modem); + g_signal_emit (self, signals[MODEM_ADDED], 0, modem); +} + +/************************************************************************/ +/* Support for ModemManager < 0.7 */ + +static void +clear_modem_manager_support (NMModemManager *self) +{ + if (self->priv->poke_id) { + g_source_remove (self->priv->poke_id); + self->priv->poke_id = 0; + } + + if (self->priv->proxy) { + g_object_unref (self->priv->proxy); + self->priv->proxy = NULL; + } +} + +static void +create_modem (NMModemManager *self, const char *path) +{ + DBusGProxy *proxy; + GError *error = NULL; + NMModem *modem = NULL; + GHashTable *properties; + + if (g_hash_table_lookup (self->priv->modems, path)) { + nm_log_warn (LOGD_MB, "modem with path %s already exists, ignoring", path); + return; + } + + proxy = dbus_g_proxy_new_for_name (nm_dbus_manager_get_connection (self->priv->dbus_mgr), + MM_OLD_DBUS_SERVICE, + path, + DBUS_INTERFACE_PROPERTIES); + g_assert (proxy); + if (dbus_g_proxy_call_with_timeout (proxy, "GetAll", 15000, &error, + G_TYPE_STRING, MM_OLD_DBUS_INTERFACE_MODEM, + G_TYPE_INVALID, + DBUS_TYPE_G_MAP_OF_VARIANT, &properties, + G_TYPE_INVALID)) { + /* Success, create the modem */ + modem = nm_modem_old_new (path, properties, &error); + if (modem) + handle_new_modem (self, modem); + else { + nm_log_warn (LOGD_MB, "failed to create modem: %s", + error ? error->message : "(unknown)"); + } + g_hash_table_destroy (properties); + } else { + nm_log_warn (LOGD_MB, "could not get modem properties: %s %s", + error ? dbus_g_error_get_name (error) : "(none)", + error ? error->message : "(unknown)"); + } + + g_object_unref (proxy); + g_clear_error (&error); +} + +static void +modem_added (DBusGProxy *proxy, const char *path, gpointer user_data) +{ + create_modem (NM_MODEM_MANAGER (user_data), path); +} + +static void +modem_removed (DBusGProxy *proxy, const char *path, gpointer user_data) +{ + NMModemManager *self = NM_MODEM_MANAGER (user_data); + NMModem *modem; + + modem = (NMModem *) g_hash_table_lookup (self->priv->modems, path); + if (modem) { + nm_modem_emit_removed (modem); + g_hash_table_remove (self->priv->modems, path); + } +} + +static void +mm_poke_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) +{ + GPtrArray *modems; + int i; + + if (dbus_g_proxy_end_call (proxy, call, NULL, + DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH, &modems, + G_TYPE_INVALID)) { + /* Don't care about the returned value, just free it */ + for (i = 0; i < modems->len; i++) + g_free ((char *) g_ptr_array_index (modems, i)); + g_ptr_array_free (modems, TRUE); + } + g_object_unref (proxy); +} + +static gboolean +poke_modem_cb (gpointer user_data) +{ + NMModemManager *self = NM_MODEM_MANAGER (user_data); + DBusGConnection *g_connection; + DBusGProxy *proxy; + + g_connection = nm_dbus_manager_get_connection (self->priv->dbus_mgr); + proxy = dbus_g_proxy_new_for_name (g_connection, + MM_OLD_DBUS_SERVICE, + MM_OLD_DBUS_PATH, + MM_OLD_DBUS_INTERFACE); + + nm_log_dbg (LOGD_MB, "Requesting to (re)launch modem-manager..."); + + dbus_g_proxy_begin_call_with_timeout (proxy, + "EnumerateDevices", + mm_poke_cb, + NULL, + NULL, + 5000, + G_TYPE_INVALID); + return TRUE; +} + +static void +enumerate_devices_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer data) +{ + NMModemManager *manager = NM_MODEM_MANAGER (data); + GPtrArray *modems; + GError *error = NULL; + + if (!dbus_g_proxy_end_call (proxy, call_id, &error, + dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH), &modems, + G_TYPE_INVALID)) { + nm_log_warn (LOGD_MB, "could not get modem list: %s", error->message); + g_error_free (error); + } else { + int i; + + for (i = 0; i < modems->len; i++) { + char *path = (char *) g_ptr_array_index (modems, i); + + create_modem (manager, path); + g_free (path); + } + + g_ptr_array_free (modems, TRUE); + } +} + +#if WITH_MODEM_MANAGER_1 +static void clear_modem_manager_1_support (NMModemManager *self); +#endif + +static void +modem_manager_appeared (NMModemManager *self, gboolean enumerate_devices) +{ + if (self->priv->poke_id) { + g_source_remove (self->priv->poke_id); + self->priv->poke_id = 0; + } + + nm_log_info (LOGD_MB, "modem-manager is now available"); + +#if WITH_MODEM_MANAGER_1 + self->priv->old_modem_manager_found = TRUE; + if (self->priv->new_modem_manager_found) + nm_log_warn (LOGD_MB, "Both the old and the new ModemManager were found"); + else + clear_modem_manager_1_support (self); +#endif + + self->priv->proxy = dbus_g_proxy_new_for_name (nm_dbus_manager_get_connection (self->priv->dbus_mgr), + MM_OLD_DBUS_SERVICE, MM_OLD_DBUS_PATH, MM_OLD_DBUS_INTERFACE); + + dbus_g_proxy_add_signal (self->priv->proxy, "DeviceAdded", DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID); + dbus_g_proxy_connect_signal (self->priv->proxy, "DeviceAdded", + G_CALLBACK (modem_added), self, + NULL); + + dbus_g_proxy_add_signal (self->priv->proxy, "DeviceRemoved", DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID); + dbus_g_proxy_connect_signal (self->priv->proxy, "DeviceRemoved", + G_CALLBACK (modem_removed), self, + NULL); + + if (enumerate_devices) + dbus_g_proxy_begin_call (self->priv->proxy, "EnumerateDevices", enumerate_devices_done, self, NULL, G_TYPE_INVALID); +} + +static gboolean +remove_one_modem (gpointer key, gpointer value, gpointer user_data) +{ + nm_modem_emit_removed (NM_MODEM (value)); + return TRUE; +} + +static void +modem_manager_disappeared (NMModemManager *self) +{ + g_hash_table_foreach_remove (self->priv->modems, remove_one_modem, self); + + if (self->priv->proxy) { + g_object_unref (self->priv->proxy); + self->priv->proxy = NULL; + } + + /* Try to activate the modem-manager */ + nm_log_dbg (LOGD_MB, "trying to start the modem manager..."); + poke_modem_cb (self); + self->priv->poke_id = g_timeout_add_seconds (MODEM_POKE_INTERVAL, poke_modem_cb, self); +} + +static void +nm_modem_manager_name_owner_changed (NMDBusManager *dbus_mgr, + const char *name, + const char *old_owner, + const char *new_owner, + gpointer user_data) +{ + gboolean old_owner_good; + gboolean new_owner_good; + + /* Can't handle the signal if its not from the modem service */ + if (strcmp (MM_OLD_DBUS_SERVICE, name) != 0) + return; + + old_owner_good = (old_owner && strlen (old_owner)); + new_owner_good = (new_owner && strlen (new_owner)); + + if (!old_owner_good && new_owner_good) { + modem_manager_appeared (NM_MODEM_MANAGER (user_data), FALSE); + } else if (old_owner_good && !new_owner_good) { + nm_log_info (LOGD_MB, "the modem manager disappeared"); + modem_manager_disappeared (NM_MODEM_MANAGER (user_data)); + } +} + +/************************************************************************/ +/* Support for ModemManager >= 0.7 */ + +#if WITH_MODEM_MANAGER_1 + +static void +modem_manager_1_clear_signals (NMModemManager *self) +{ + if (!self->priv->modem_manager_1) + return; + + if (self->priv->modem_manager_1_name_owner_changed_id) { + if (g_signal_handler_is_connected (self->priv->modem_manager_1, + self->priv->modem_manager_1_name_owner_changed_id)) + g_signal_handler_disconnect (self->priv->modem_manager_1, + self->priv->modem_manager_1_name_owner_changed_id); + self->priv->modem_manager_1_name_owner_changed_id = 0; + } + + if (self->priv->modem_manager_1_object_added_id) { + if (g_signal_handler_is_connected (self->priv->modem_manager_1, + self->priv->modem_manager_1_object_added_id)) + g_signal_handler_disconnect (self->priv->modem_manager_1, + self->priv->modem_manager_1_object_added_id); + self->priv->modem_manager_1_object_added_id = 0; + } + + if (self->priv->modem_manager_1_object_removed_id) { + if (g_signal_handler_is_connected (self->priv->modem_manager_1, + self->priv->modem_manager_1_object_removed_id)) + g_signal_handler_disconnect (self->priv->modem_manager_1, + self->priv->modem_manager_1_object_removed_id); + self->priv->modem_manager_1_object_removed_id = 0; + } +} + +static void +clear_modem_manager_1_support (NMModemManager *self) +{ + if (self->priv->modem_manager_1_launch_id) { + g_source_remove (self->priv->modem_manager_1_launch_id); + self->priv->modem_manager_1_launch_id = 0; + } + + modem_manager_1_clear_signals (self); + g_clear_object (&self->priv->modem_manager_1); + g_clear_object (&self->priv->dbus_connection); +} + +static void +modem_object_added (MMManager *modem_manager, + MMObject *modem_object, + NMModemManager *self) +{ + const gchar *path; + MMModem *modem_iface; + NMModem *modem; + GError *error = NULL; + + /* Ensure we don't have the same modem already */ + path = mm_object_get_path (modem_object); + if (g_hash_table_lookup (self->priv->modems, path)) { + nm_log_warn (LOGD_MB, "modem with path %s already exists, ignoring", path); + return; + } + + /* Ensure we have the 'Modem' interface at least */ + modem_iface = mm_object_peek_modem (modem_object); + if (!modem_iface) { + nm_log_warn (LOGD_MB, "modem with path %s doesn't have the Modem interface, ignoring", path); + return; + } + + /* Ensure we have a primary port reported */ + if (!mm_modem_get_primary_port (modem_iface)) { + nm_log_warn (LOGD_MB, "modem with path %s has unknown primary port, ignoring", path); + return; + } + + /* Create a new modem object */ + modem = nm_modem_broadband_new (G_OBJECT (modem_object), &error); + if (modem) + handle_new_modem (self, modem); + else { + nm_log_warn (LOGD_MB, "failed to create modem: %s", + error ? error->message : "(unknown)"); + } + g_clear_error (&error); +} + +static void +modem_object_removed (MMManager *manager, + MMObject *modem_object, + NMModemManager *self) +{ + NMModem *modem; + const gchar *path; + + path = mm_object_get_path (modem_object); + modem = (NMModem *) g_hash_table_lookup (self->priv->modems, path); + if (!modem) + return; + + nm_modem_emit_removed (modem); + g_hash_table_remove (self->priv->modems, path); +} + +static void +modem_manager_1_available (NMModemManager *self) +{ + GList *modems, *l; + + nm_log_info (LOGD_MB, "ModemManager available in the bus"); + + self->priv->new_modem_manager_found = TRUE; + if (self->priv->old_modem_manager_found) + nm_log_warn (LOGD_MB, "Both the old and the new ModemManager were found"); + else + clear_modem_manager_support (self); + + /* Update initial modems list */ + modems = g_dbus_object_manager_get_objects (G_DBUS_OBJECT_MANAGER (self->priv->modem_manager_1)); + for (l = modems; l; l = g_list_next (l)) + modem_object_added (self->priv->modem_manager_1, MM_OBJECT (l->data), self); + g_list_free_full (modems, (GDestroyNotify) g_object_unref); +} + +static void schedule_modem_manager_1_relaunch (NMModemManager *self, + guint n_seconds); +static void ensure_client (NMModemManager *self); + +static void +modem_manager_1_name_owner_changed (MMManager *modem_manager_1, + GParamSpec *pspec, + NMModemManager *self) +{ + gchar *name_owner; + + /* Quit poking, if any */ + if (self->priv->modem_manager_1_launch_id) { + g_source_remove (self->priv->modem_manager_1_launch_id); + self->priv->modem_manager_1_launch_id = 0; + } + + name_owner = g_dbus_object_manager_client_get_name_owner (G_DBUS_OBJECT_MANAGER_CLIENT (modem_manager_1)); + if (!name_owner) { + nm_log_info (LOGD_MB, "ModemManager disappeared from bus"); + +#if !HAVE_SYSTEMD + /* If not managed by systemd, schedule relaunch */ + schedule_modem_manager_1_relaunch (self, 0); +#endif + + return; + } + + /* Available! */ + g_free (name_owner); + + /* Hack alert: GDBusObjectManagerClient won't signal neither 'object-added' + * nor 'object-removed' if it was created while there was no ModemManager in + * the bus. This hack avoids this issue until we get a GIO with the fix + * included... */ + modem_manager_1_clear_signals (self); + g_clear_object (&self->priv->modem_manager_1); + ensure_client (self); + + /* Whenever GDBusObjectManagerClient is fixed, we can just do the following: + * modem_manager_1_available (self); + */ +} + +#if !HAVE_SYSTEMD + +static void +modem_manager_1_poke_cb (GDBusConnection *connection, + GAsyncResult *res, + NMModemManager *self) +{ + GError *error = NULL; + GVariant *result; + + result = g_dbus_connection_call_finish (connection, res, &error); + if (error) { + /* Ignore common errors when MM is not installed and such */ + if ( !g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN) + && !g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SPAWN_EXEC_FAILED) + && !g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SPAWN_FORK_FAILED) + && !g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SPAWN_FAILED) + && !g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_TIMEOUT) + && !g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SPAWN_SERVICE_NOT_FOUND)) { + nm_log_dbg (LOGD_MB, "error poking ModemManager: %s", error->message); + } + g_error_free (error); + + /* Setup timeout to relaunch */ + schedule_modem_manager_1_relaunch (self, MODEM_POKE_INTERVAL); + } else + g_variant_unref (result); + + /* Balance refcount */ + g_object_unref (self); +} + +static void +modem_manager_1_poke (NMModemManager *self) +{ + /* If there is no current owner right away, ensure we poke to get one */ + g_dbus_connection_call (self->priv->dbus_connection, + "org.freedesktop.ModemManager1", + "/org/freedesktop/ModemManager1", + "org.freedesktop.DBus.Peer", + "Ping", + NULL, /* inputs */ + NULL, /* outputs */ + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, /* cancellable */ + (GAsyncReadyCallback)modem_manager_1_poke_cb, /* callback */ + g_object_ref (self)); /* user_data */ +} + +#endif /* HAVE_SYSTEMD */ + +static void +modem_manager_1_check_name_owner (NMModemManager *self) +{ + gchar *name_owner; + + name_owner = g_dbus_object_manager_client_get_name_owner (G_DBUS_OBJECT_MANAGER_CLIENT (self->priv->modem_manager_1)); + if (name_owner) { + /* Available! */ + modem_manager_1_available (self); + g_free (name_owner); + return; + } + +#if !HAVE_SYSTEMD + /* If the lifecycle is not managed by systemd, poke */ + modem_manager_1_poke (self); +#endif +} + +static void +manager_new_ready (GObject *source, + GAsyncResult *res, + NMModemManager *self) +{ + /* Note we always get an extra reference to self here */ + + GError *error = NULL; + + g_assert (!self->priv->modem_manager_1); + self->priv->modem_manager_1 = mm_manager_new_finish (res, &error); + if (!self->priv->modem_manager_1) { + /* We're not really supposed to get any error here. If we do get one, + * though, just re-schedule the MMManager creation after some time. + * During this period, name-owner changes won't be followed. */ + nm_log_warn (LOGD_MB, "error creating ModemManager client: %s", error->message); + g_error_free (error); + /* Setup timeout to relaunch */ + schedule_modem_manager_1_relaunch (self, MODEM_POKE_INTERVAL); + } else if (self->priv->old_modem_manager_found) { + /* If we found the old MM, abort */ + clear_modem_manager_1_support (self); + } else { + /* Setup signals in the GDBusObjectManagerClient */ + self->priv->modem_manager_1_name_owner_changed_id = + g_signal_connect (self->priv->modem_manager_1, + "notify::name-owner", + G_CALLBACK (modem_manager_1_name_owner_changed), + self); + self->priv->modem_manager_1_object_added_id = + g_signal_connect (self->priv->modem_manager_1, + "object-added", + G_CALLBACK (modem_object_added), + self); + self->priv->modem_manager_1_object_removed_id = + g_signal_connect (self->priv->modem_manager_1, + "object-removed", + G_CALLBACK (modem_object_removed), + self); + + modem_manager_1_check_name_owner (self); + } + + /* Balance refcount */ + g_object_unref (self); +} + +static void +ensure_client (NMModemManager *self) +{ + g_assert (self->priv->dbus_connection); + + /* Create the GDBusObjectManagerClient. We do not request to autostart, as + * we don't really want the MMManager creation to fail. We can always poke + * later on if we want to request the autostart */ + if (!self->priv->modem_manager_1) { + mm_manager_new (self->priv->dbus_connection, + G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_DO_NOT_AUTO_START, + NULL, + (GAsyncReadyCallback)manager_new_ready, + g_object_ref (self)); + return; + } + + /* If already available, recheck name owner! */ + modem_manager_1_check_name_owner (self); +} + +static void +bus_get_ready (GObject *source, + GAsyncResult *res, + NMModemManager *self) +{ + /* Note we always get an extra reference to self here */ + + GError *error = NULL; + + self->priv->dbus_connection = g_bus_get_finish (res, &error); + if (!self->priv->dbus_connection) { + nm_log_warn (LOGD_CORE, "error getting bus connection: %s", error->message); + g_error_free (error); + /* Setup timeout to relaunch */ + schedule_modem_manager_1_relaunch (self, MODEM_POKE_INTERVAL); + } else if (self->priv->old_modem_manager_found) { + /* If we found the old MM, abort */ + clear_modem_manager_1_support (self); + } else { + /* Got the bus, ensure client */ + ensure_client (self); + } + + /* Balance refcount */ + g_object_unref (self); +} + +static gboolean +ensure_bus (NMModemManager *self) +{ + /* Clear launch ID */ + self->priv->modem_manager_1_launch_id = 0; + + if (!self->priv->dbus_connection) + g_bus_get (G_BUS_TYPE_SYSTEM, + NULL, + (GAsyncReadyCallback)bus_get_ready, + g_object_ref (self)); + else + /* If bus is already available, ensure client */ + ensure_client (self); + + return FALSE; +} + +static void +schedule_modem_manager_1_relaunch (NMModemManager *self, + guint n_seconds) +{ + /* No need to pass an extra reference to self; timeout/idle will be + * cancelled if the object gets disposed. */ + + if (n_seconds) + self->priv->modem_manager_1_launch_id = g_timeout_add_seconds (n_seconds, (GSourceFunc)ensure_bus, self); + else + self->priv->modem_manager_1_launch_id = g_idle_add ((GSourceFunc)ensure_bus, self); +} + +#endif /* WITH_MODEM_MANAGER_1 */ + +/************************************************************************/ + +static void +nm_modem_manager_init (NMModemManager *self) +{ + self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NM_TYPE_MODEM_MANAGER, NMModemManagerPrivate); + + self->priv->modems = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); + + /* ModemManager < 0.7 */ + self->priv->dbus_mgr = nm_dbus_manager_get (); + g_signal_connect (self->priv->dbus_mgr, NM_DBUS_MANAGER_NAME_OWNER_CHANGED, + G_CALLBACK (nm_modem_manager_name_owner_changed), + self); + if (nm_dbus_manager_name_has_owner (self->priv->dbus_mgr, MM_OLD_DBUS_SERVICE)) + modem_manager_appeared (self, TRUE); + else + modem_manager_disappeared (self); + +#if WITH_MODEM_MANAGER_1 + /* ModemManager >= 0.7 */ + schedule_modem_manager_1_relaunch (self, 0); +#endif +} + +static void +dispose (GObject *object) +{ + NMModemManager *self = NM_MODEM_MANAGER (object); + + /* ModemManager < 0.7 */ + clear_modem_manager_support (self); + +#if WITH_MODEM_MANAGER_1 + /* ModemManager >= 0.7 */ + clear_modem_manager_1_support (self); +#endif + + if (self->priv->modems) { + g_hash_table_foreach_remove (self->priv->modems, remove_one_modem, object); + g_hash_table_destroy (self->priv->modems); + } + + self->priv->dbus_mgr = NULL; + + /* Chain up to the parent class */ + G_OBJECT_CLASS (nm_modem_manager_parent_class)->dispose (object); +} + +static void +nm_modem_manager_class_init (NMModemManagerClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (NMModemManagerPrivate)); + + object_class->dispose = dispose; + + signals[MODEM_ADDED] = + g_signal_new (NM_MODEM_MANAGER_MODEM_ADDED, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMModemManagerClass, modem_added), + NULL, NULL, NULL, + G_TYPE_NONE, 1, NM_TYPE_MODEM); +} diff --git a/src/devices/wwan/nm-modem-manager.h b/src/devices/wwan/nm-modem-manager.h new file mode 100644 index 00000000..3082bdb3 --- /dev/null +++ b/src/devices/wwan/nm-modem-manager.h @@ -0,0 +1,49 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2009 - 2014 Red Hat, Inc. + * Copyright (C) 2009 Novell, Inc. + * Copyright (C) 2009 Canonical Ltd. + */ + +#ifndef NM_MODEM_MANAGER_H +#define NM_MODEM_MANAGER_H + +#include +#include "nm-modem.h" + +#define NM_TYPE_MODEM_MANAGER (nm_modem_manager_get_type ()) +#define NM_MODEM_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_MODEM_MANAGER, NMModemManager)) + +#define NM_MODEM_MANAGER_MODEM_ADDED "modem-added" + +typedef struct _NMModemManagerPrivate NMModemManagerPrivate; + +typedef struct { + GObject parent; + NMModemManagerPrivate *priv; +} NMModemManager; + +typedef struct { + GObjectClass parent; + + void (*modem_added) (NMModemManager *self, NMModem *modem); +} NMModemManagerClass; + +GType nm_modem_manager_get_type (void); + +#endif /* NM_MODEM_MANAGER_H */ diff --git a/src/devices/wwan/nm-modem-old-types.h b/src/devices/wwan/nm-modem-old-types.h new file mode 100644 index 00000000..84065a68 --- /dev/null +++ b/src/devices/wwan/nm-modem-old-types.h @@ -0,0 +1,70 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2009 Novell, Inc. + */ + +#ifndef NM_MODEM_OLD_TYPES_H +#define NM_MODEM_OLD_TYPES_H + +#define MM_OLD_DBUS_SERVICE "org.freedesktop.ModemManager" +#define MM_OLD_DBUS_PATH "/org/freedesktop/ModemManager" +#define MM_OLD_DBUS_INTERFACE "org.freedesktop.ModemManager" +#define MM_OLD_DBUS_INTERFACE_MODEM "org.freedesktop.ModemManager.Modem" +#define MM_OLD_DBUS_INTERFACE_MODEM_SIMPLE "org.freedesktop.ModemManager.Modem.Simple" +#define MM_OLD_DBUS_INTERFACE_MODEM_CDMA "org.freedesktop.ModemManager.Modem.Cdma" +#define MM_OLD_DBUS_INTERFACE_MODEM_GSM_CARD "org.freedesktop.ModemManager.Modem.Gsm.Card" +#define MM_OLD_DBUS_INTERFACE_MODEM_GSM_NETWORK "org.freedesktop.ModemManager.Modem.Gsm.Network" + +#define MM_OLD_MODEM_TYPE_UNKNOWN 0 +#define MM_OLD_MODEM_TYPE_GSM 1 +#define MM_OLD_MODEM_TYPE_CDMA 2 + +/* Errors */ + +#define MM_OLD_MODEM_CONNECT_ERROR_NO_CARRIER MM_OLD_DBUS_INTERFACE_MODEM ".NoCarrier" +#define MM_OLD_MODEM_CONNECT_ERROR_NO_DIALTONE MM_OLD_DBUS_INTERFACE_MODEM ".NoDialtone" +#define MM_OLD_MODEM_CONNECT_ERROR_BUSY MM_OLD_DBUS_INTERFACE_MODEM ".Busy" +#define MM_OLD_MODEM_CONNECT_ERROR_NO_ANSWER MM_OLD_DBUS_INTERFACE_MODEM ".NoAnswer" + +#define MM_OLD_MODEM_ERROR "org.freedesktop.ModemManager.Modem.Gsm" + +#define MM_OLD_MODEM_ERROR_NETWORK_NOT_ALLOWED MM_OLD_MODEM_ERROR ".NetworkNotAllowed" +#define MM_OLD_MODEM_ERROR_NETWORK_TIMEOUT MM_OLD_MODEM_ERROR ".NetworkTimeout" +#define MM_OLD_MODEM_ERROR_NO_NETWORK MM_OLD_MODEM_ERROR ".NoNetwork" +#define MM_OLD_MODEM_ERROR_SIM_NOT_INSERTED MM_OLD_MODEM_ERROR ".SimNotInserted" +#define MM_OLD_MODEM_ERROR_SIM_PIN MM_OLD_MODEM_ERROR ".SimPinRequired" +#define MM_OLD_MODEM_ERROR_SIM_PUK MM_OLD_MODEM_ERROR ".SimPukRequired" +#define MM_OLD_MODEM_ERROR_SIM_WRONG MM_OLD_MODEM_ERROR ".SimWrong" +#define MM_OLD_MODEM_ERROR_WRONG_PASSWORD MM_OLD_MODEM_ERROR ".IncorrectPassword" + +typedef enum { + MM_OLD_MODEM_STATE_UNKNOWN = 0, + MM_OLD_MODEM_STATE_DISABLED = 10, + MM_OLD_MODEM_STATE_DISABLING = 20, + MM_OLD_MODEM_STATE_ENABLING = 30, + MM_OLD_MODEM_STATE_ENABLED = 40, + MM_OLD_MODEM_STATE_SEARCHING = 50, + MM_OLD_MODEM_STATE_REGISTERED = 60, + MM_OLD_MODEM_STATE_DISCONNECTING = 70, + MM_OLD_MODEM_STATE_CONNECTING = 80, + MM_OLD_MODEM_STATE_CONNECTED = 90, + + MM_OLD_MODEM_STATE_LAST = MM_OLD_MODEM_STATE_CONNECTED +} MMOldModemState; + +#endif /* NM_MODEM_OLD_TYPES_H */ diff --git a/src/devices/wwan/nm-modem-old.c b/src/devices/wwan/nm-modem-old.c new file mode 100644 index 00000000..ce1a382e --- /dev/null +++ b/src/devices/wwan/nm-modem-old.c @@ -0,0 +1,1139 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2009 - 2013 Red Hat, Inc. + * Copyright (C) 2009 Novell, Inc. + */ + +#include +#include + +#include "nm-modem-old.h" +#include "nm-dbus-manager.h" +#include "nm-setting-connection.h" +#include "nm-properties-changed-signal.h" +#include "nm-modem-old-types.h" +#include "nm-logging.h" +#include "NetworkManagerUtils.h" +#include "nm-device-private.h" +#include "nm-dbus-glib-types.h" +#include "nm-glib-compat.h" + +G_DEFINE_TYPE (NMModemOld, nm_modem_old, NM_TYPE_MODEM) + +#define NM_MODEM_OLD_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_MODEM_OLD, NMModemOldPrivate)) + +typedef struct { + DBusGProxy *proxy; + DBusGProxy *props_proxy; + + MMOldModemState state; + NMDeviceModemCapabilities caps; + char *unlock_required; + + DBusGProxyCall *call; + GHashTable *connect_properties; + + guint32 pin_tries; + guint enable_delay_id; +} NMModemOldPrivate; + +#define CAPS_3GPP (NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS | NM_DEVICE_MODEM_CAPABILITY_LTE) + +/*****************************************************************************/ + +typedef enum { + MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_ANY = 0, + MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_GPRS, + MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_EDGE, + MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_UMTS, + MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_HSDPA, + MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_2G_PREFERRED, + MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_3G_PREFERRED, + MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_2G_ONLY, + MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_3G_ONLY, + MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_HSUPA, + MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_HSPA, + + MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_LAST = MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_HSPA +} MMModemDeprecatedMode; + +typedef enum { + MM_MODEM_GSM_ALLOWED_MODE_ANY = 0, + MM_MODEM_GSM_ALLOWED_MODE_2G_PREFERRED = 1, + MM_MODEM_GSM_ALLOWED_MODE_3G_PREFERRED = 2, + MM_MODEM_GSM_ALLOWED_MODE_2G_ONLY = 3, + MM_MODEM_GSM_ALLOWED_MODE_3G_ONLY = 4, + MM_MODEM_GSM_ALLOWED_MODE_4G_PREFERRED = 5, + MM_MODEM_GSM_ALLOWED_MODE_4G_ONLY = 6, + + MM_MODEM_GSM_ALLOWED_MODE_LAST = MM_MODEM_GSM_ALLOWED_MODE_4G_ONLY +} MMModemGsmAllowedMode; + +typedef enum { + MM_MODEM_GSM_ALLOWED_AUTH_UNKNOWN = 0x0000, + /* bits 0..4 order match Ericsson device bitmap */ + MM_MODEM_GSM_ALLOWED_AUTH_NONE = 0x0001, + MM_MODEM_GSM_ALLOWED_AUTH_PAP = 0x0002, + MM_MODEM_GSM_ALLOWED_AUTH_CHAP = 0x0004, + MM_MODEM_GSM_ALLOWED_AUTH_MSCHAP = 0x0008, + MM_MODEM_GSM_ALLOWED_AUTH_MSCHAPV2 = 0x0010, + MM_MODEM_GSM_ALLOWED_AUTH_EAP = 0x0020, + + MM_MODEM_GSM_ALLOWED_AUTH_LAST = MM_MODEM_GSM_ALLOWED_AUTH_EAP +} MMModemGsmAllowedAuth; + +static NMDeviceStateReason +translate_mm_error (GError *error) +{ + NMDeviceStateReason reason; + + if (dbus_g_error_has_name (error, MM_OLD_MODEM_CONNECT_ERROR_NO_CARRIER)) + reason = NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER; + else if (dbus_g_error_has_name (error, MM_OLD_MODEM_CONNECT_ERROR_NO_DIALTONE)) + reason = NM_DEVICE_STATE_REASON_MODEM_NO_DIAL_TONE; + else if (dbus_g_error_has_name (error, MM_OLD_MODEM_CONNECT_ERROR_BUSY)) + reason = NM_DEVICE_STATE_REASON_MODEM_BUSY; + else if (dbus_g_error_has_name (error, MM_OLD_MODEM_CONNECT_ERROR_NO_ANSWER)) + reason = NM_DEVICE_STATE_REASON_MODEM_DIAL_TIMEOUT; + else if (dbus_g_error_has_name (error, MM_OLD_MODEM_ERROR_NETWORK_NOT_ALLOWED)) + reason = NM_DEVICE_STATE_REASON_GSM_REGISTRATION_DENIED; + else if (dbus_g_error_has_name (error, MM_OLD_MODEM_ERROR_NETWORK_TIMEOUT)) + reason = NM_DEVICE_STATE_REASON_GSM_REGISTRATION_TIMEOUT; + else if (dbus_g_error_has_name (error, MM_OLD_MODEM_ERROR_NO_NETWORK)) + reason = NM_DEVICE_STATE_REASON_GSM_REGISTRATION_NOT_SEARCHING; + else if (dbus_g_error_has_name (error, MM_OLD_MODEM_ERROR_SIM_NOT_INSERTED)) + reason = NM_DEVICE_STATE_REASON_GSM_SIM_NOT_INSERTED; + else if (dbus_g_error_has_name (error, MM_OLD_MODEM_ERROR_SIM_PIN)) + reason = NM_DEVICE_STATE_REASON_GSM_SIM_PIN_REQUIRED; + else if (dbus_g_error_has_name (error, MM_OLD_MODEM_ERROR_SIM_PUK)) + reason = NM_DEVICE_STATE_REASON_GSM_SIM_PUK_REQUIRED; + else if (dbus_g_error_has_name (error, MM_OLD_MODEM_ERROR_SIM_WRONG)) + reason = NM_DEVICE_STATE_REASON_GSM_SIM_WRONG; + else if (dbus_g_error_has_name (error, MM_OLD_MODEM_ERROR_WRONG_PASSWORD)) + reason = NM_DEVICE_STATE_REASON_SIM_PIN_INCORRECT; + else { + /* unable to map the ModemManager error to a NM_DEVICE_STATE_REASON */ + nm_log_dbg (LOGD_MB, "unmapped dbus error detected: '%s'", dbus_g_error_get_name (error)); + reason = NM_DEVICE_STATE_REASON_UNKNOWN; + } + + /* FIXME: We have only GSM error messages here, and we have no idea which + activation state failed. Reasons like: + NM_DEVICE_STATE_REASON_MODEM_DIAL_FAILED, + NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED, + NM_DEVICE_STATE_REASON_GSM_APN_FAILED, + NM_DEVICE_STATE_REASON_GSM_REGISTRATION_FAILED, + NM_DEVICE_STATE_REASON_GSM_PIN_CHECK_FAILED + are not used. + */ + return reason; +} + +#define MAP_STATE(name) case MM_OLD_MODEM_STATE_##name: return NM_MODEM_STATE_##name; + +static NMModemState +mm_state_to_nm (MMOldModemState mm_state, const char *unlock_required) +{ + if (unlock_required && *unlock_required) + return NM_MODEM_STATE_LOCKED; + + switch (mm_state) { + MAP_STATE(UNKNOWN) + MAP_STATE(DISABLED) + MAP_STATE(DISABLING) + MAP_STATE(ENABLING) + MAP_STATE(ENABLED) + MAP_STATE(SEARCHING) + MAP_STATE(REGISTERED) + MAP_STATE(DISCONNECTING) + MAP_STATE(CONNECTING) + MAP_STATE(CONNECTED) + } + return NM_MODEM_STATE_UNKNOWN; +}; + +/*****************************************************************************/ + +static DBusGProxy * +nm_modem_old_get_proxy (NMModemOld *self, const char *interface) +{ + + NMModemOldPrivate *priv = NM_MODEM_OLD_GET_PRIVATE (self); + const char *current_iface; + + g_return_val_if_fail (NM_IS_MODEM_OLD (self), NULL); + + /* Default to the default interface. */ + if (interface == NULL) + interface = MM_OLD_DBUS_INTERFACE_MODEM; + + if (interface && !strcmp (interface, DBUS_INTERFACE_PROPERTIES)) + return priv->props_proxy; + + current_iface = dbus_g_proxy_get_interface (priv->proxy); + if (!current_iface || strcmp (current_iface, interface)) + dbus_g_proxy_set_interface (priv->proxy, interface); + + return priv->proxy; +} + +/*****************************************************************************/ +/* Query/Update enabled state */ + +static void +set_mm_enabled_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) +{ + GError *error = NULL; + + if (!dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID)) { + nm_log_warn (LOGD_MB, "failed to enable/disable modem: (%d) %s", + error ? error->code : -1, + error && error->message ? error->message : "(unknown)"); + nm_modem_set_prev_state (NM_MODEM (user_data), "enable/disable failed"); + } + /* Wait for the state change signal to indicate enabled state changed */ +} + +static void +set_mm_enabled (NMModem *self, gboolean enabled) +{ + dbus_g_proxy_begin_call (nm_modem_old_get_proxy (NM_MODEM_OLD (self), MM_OLD_DBUS_INTERFACE_MODEM), + "Enable", set_mm_enabled_done, + g_object_ref (self), g_object_unref, + G_TYPE_BOOLEAN, enabled, + G_TYPE_INVALID); +} + +/*****************************************************************************/ + +static void +ask_for_pin (NMModemOld *self, gboolean always_ask) +{ + NMModemOldPrivate *priv = NM_MODEM_OLD_GET_PRIVATE (self); + guint32 tries = 0; + + g_return_if_fail (NM_IS_MODEM_OLD (self)); + + if (!always_ask) + tries = priv->pin_tries++; + + nm_modem_get_secrets (NM_MODEM (self), + NM_SETTING_GSM_SETTING_NAME, + (tries || always_ask) ? TRUE : FALSE, + NM_SETTING_GSM_PIN); +} + +static void +stage1_prepare_done (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) +{ + NMModemOld *self = NM_MODEM_OLD (user_data); + NMModemOldPrivate *priv = NM_MODEM_OLD_GET_PRIVATE (self); + GError *error = NULL; + gboolean asked = FALSE; + + priv->call = NULL; + + if (priv->connect_properties) { + g_hash_table_destroy (priv->connect_properties); + priv->connect_properties = NULL; + } + + if (dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_INVALID)) + g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, TRUE, NM_DEVICE_STATE_REASON_NONE); + else { + if (priv->caps & CAPS_3GPP) { + if (dbus_g_error_has_name (error, MM_OLD_MODEM_ERROR_SIM_PIN)) { + ask_for_pin (self, FALSE); + asked = TRUE; + } else if (dbus_g_error_has_name (error, MM_OLD_MODEM_ERROR_SIM_WRONG)) { + ask_for_pin (self, TRUE); + asked = TRUE; + } + } + + if (!asked) { + nm_log_warn (LOGD_MB, "Mobile connection failed: (%d) %s", + error ? error->code : -1, + error && error->message ? error->message : "(unknown)"); + g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, translate_mm_error (error)); + } + g_error_free (error); + } +} + +static void +do_connect (NMModemOld *self) +{ + NMModemOldPrivate *priv = NM_MODEM_OLD_GET_PRIVATE (self); + DBusGProxy *proxy; + + proxy = nm_modem_old_get_proxy (NM_MODEM_OLD (self), MM_OLD_DBUS_INTERFACE_MODEM_SIMPLE); + priv->call = dbus_g_proxy_begin_call_with_timeout (proxy, + "Connect", stage1_prepare_done, + self, NULL, 120000, + DBUS_TYPE_G_MAP_OF_VARIANT, priv->connect_properties, + G_TYPE_INVALID); +} + +static void stage1_enable_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data); + +/* do_enable() is used as a GSourceFunc, hence the gboolean return */ +static gboolean +do_enable (NMModemOld *self) +{ + DBusGProxy *proxy; + + g_return_val_if_fail (NM_IS_MODEM_OLD (self), FALSE); + + NM_MODEM_OLD_GET_PRIVATE (self)->enable_delay_id = 0; + proxy = nm_modem_old_get_proxy (NM_MODEM_OLD (self), MM_OLD_DBUS_INTERFACE_MODEM); + dbus_g_proxy_begin_call_with_timeout (proxy, + "Enable", stage1_enable_done, + self, NULL, 20000, + G_TYPE_BOOLEAN, TRUE, + G_TYPE_INVALID); + return FALSE; +} + +static void +stage1_pin_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) +{ + NMModemOld *self = NM_MODEM_OLD (user_data); + NMModemOldPrivate *priv = NM_MODEM_OLD_GET_PRIVATE (self); + NMDeviceStateReason reason; + GError *error = NULL; + + if (dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID)) { + /* Success; try to enable the modem again. Wait a few seconds to ensure + * that ModemManager is ready for the enable right after the unlock. + */ + if (priv->enable_delay_id == 0) + priv->enable_delay_id = g_timeout_add_seconds (4, (GSourceFunc) do_enable, self); + } else { + nm_log_warn (LOGD_MB, "GSM PIN unlock failed: (%d) %s", + error ? error->code : -1, + error && error->message ? error->message : "(unknown)"); + + /* try to translate the error reason */ + reason = translate_mm_error (error); + if (reason == NM_DEVICE_STATE_REASON_UNKNOWN) + reason = NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED; + + g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, reason); + g_error_free (error); + } +} + +static void +handle_enable_pin_required (NMModemOld *self) +{ + NMModemOldPrivate *priv = NM_MODEM_OLD_GET_PRIVATE (self); + const char *pin = NULL; + GValue *value; + DBusGProxy *proxy; + + g_assert (priv->caps & CAPS_3GPP); + + /* See if we have a PIN already */ + value = g_hash_table_lookup (priv->connect_properties, "pin"); + if (value && G_VALUE_HOLDS_STRING (value)) + pin = g_value_get_string (value); + + /* If we do, send it */ + if (pin) { + proxy = nm_modem_old_get_proxy (NM_MODEM_OLD (self), MM_OLD_DBUS_INTERFACE_MODEM_GSM_CARD); + dbus_g_proxy_begin_call_with_timeout (proxy, + "SendPin", stage1_pin_done, + self, NULL, 10000, + G_TYPE_STRING, pin, + G_TYPE_INVALID); + } else + ask_for_pin (self, FALSE); +} + +static void +stage1_enable_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) +{ + NMModemOld *self = NM_MODEM_OLD (user_data); + NMModemOldPrivate *priv = NM_MODEM_OLD_GET_PRIVATE (self); + NMDeviceStateReason reason; + GError *error = NULL; + + if (dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID)) + do_connect (self); + else { + if ((priv->caps & CAPS_3GPP) && dbus_g_error_has_name (error, MM_OLD_MODEM_ERROR_SIM_PIN)) + handle_enable_pin_required (self); + else { + nm_log_warn (LOGD_MB, "Modem enable failed: (%d) %s", + error ? error->code : -1, + error && error->message ? error->message : "(unknown)"); + + /* try to translate the error reason */ + reason = translate_mm_error (error); + if (reason == NM_DEVICE_STATE_REASON_UNKNOWN) + reason = NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED; + g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, reason); + } + + g_error_free (error); + } +} + +static GHashTable * +create_connect_properties (NMConnection *connection) +{ + NMSettingCdma *s_cdma; + NMSettingGsm *s_gsm; + NMSettingPPP *s_ppp; + GHashTable *properties; + const char *str; + + properties = value_hash_create (); + + s_cdma = nm_connection_get_setting_cdma (connection); + if (s_cdma) { + str = nm_setting_cdma_get_number (s_cdma); + if (str) + value_hash_add_str (properties, "number", str); + return properties; + } + + s_gsm = nm_connection_get_setting_gsm (connection); + if (s_gsm) { + str = nm_setting_gsm_get_number (s_gsm); + if (str) + value_hash_add_str (properties, "number", str); + + str = nm_setting_gsm_get_apn (s_gsm); + if (str) + value_hash_add_str (properties, "apn", str); + + str = nm_setting_gsm_get_network_id (s_gsm); + if (str) + value_hash_add_str (properties, "network_id", str); + + str = nm_setting_gsm_get_pin (s_gsm); + if (str) + value_hash_add_str (properties, "pin", str); + + str = nm_setting_gsm_get_username (s_gsm); + if (str) + value_hash_add_str (properties, "username", str); + + str = nm_setting_gsm_get_password (s_gsm); + if (str) + value_hash_add_str (properties, "password", str); + +G_GNUC_BEGIN_IGNORE_DEPRECATIONS + /* Add both old and new preferred modes */ + switch (nm_setting_gsm_get_network_type (s_gsm)) { + case NM_SETTING_GSM_NETWORK_TYPE_UMTS_HSPA: + value_hash_add_uint (properties, "network_mode", MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_3G_ONLY); + value_hash_add_uint (properties, "allowed_mode", MM_MODEM_GSM_ALLOWED_MODE_3G_ONLY); + break; + case NM_SETTING_GSM_NETWORK_TYPE_GPRS_EDGE: + value_hash_add_uint (properties, "network_mode", MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_2G_ONLY); + value_hash_add_uint (properties, "allowed_mode", MM_MODEM_GSM_ALLOWED_MODE_2G_ONLY); + break; + case NM_SETTING_GSM_NETWORK_TYPE_PREFER_UMTS_HSPA: + value_hash_add_uint (properties, "network_mode", MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_3G_PREFERRED); + value_hash_add_uint (properties, "allowed_mode", MM_MODEM_GSM_ALLOWED_MODE_3G_PREFERRED); + break; + case NM_SETTING_GSM_NETWORK_TYPE_PREFER_GPRS_EDGE: + value_hash_add_uint (properties, "network_mode", MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_2G_PREFERRED); + value_hash_add_uint (properties, "allowed_mode", MM_MODEM_GSM_ALLOWED_MODE_2G_PREFERRED); + break; + case NM_SETTING_GSM_NETWORK_TYPE_PREFER_4G: + /* deprecated modes not extended for 4G, so no need to set them here */ + value_hash_add_uint (properties, "allowed_mode", MM_MODEM_GSM_ALLOWED_MODE_4G_PREFERRED); + break; + case NM_SETTING_GSM_NETWORK_TYPE_4G: + /* deprecated modes not extended for 4G, so no need to set them here */ + value_hash_add_uint (properties, "allowed_mode", MM_MODEM_GSM_ALLOWED_MODE_4G_ONLY); + break; + default: + value_hash_add_uint (properties, "network_mode", MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_ANY); + value_hash_add_uint (properties, "allowed_mode", MM_MODEM_GSM_ALLOWED_MODE_ANY); + break; + } +G_GNUC_END_IGNORE_DEPRECATIONS + + /* Roaming */ + if (nm_setting_gsm_get_home_only (s_gsm)) + value_hash_add_bool (properties, "home_only", TRUE); + + /* For IpMethod == STATIC or DHCP */ + s_ppp = nm_connection_get_setting_ppp (connection); + if (s_ppp) { + guint32 auth = MM_MODEM_GSM_ALLOWED_AUTH_UNKNOWN; + + if (nm_setting_ppp_get_noauth (s_ppp)) + auth |= MM_MODEM_GSM_ALLOWED_AUTH_NONE; + if (!nm_setting_ppp_get_refuse_pap (s_ppp)) + auth |= MM_MODEM_GSM_ALLOWED_AUTH_PAP; + if (!nm_setting_ppp_get_refuse_chap (s_ppp)) + auth |= MM_MODEM_GSM_ALLOWED_AUTH_CHAP; + if (!nm_setting_ppp_get_refuse_mschap (s_ppp)) + auth |= MM_MODEM_GSM_ALLOWED_AUTH_MSCHAP; + if (!nm_setting_ppp_get_refuse_mschapv2 (s_ppp)) + auth |= MM_MODEM_GSM_ALLOWED_AUTH_MSCHAPV2; + if (!nm_setting_ppp_get_refuse_eap (s_ppp)) + auth |= MM_MODEM_GSM_ALLOWED_AUTH_EAP; + + if (auth != MM_MODEM_GSM_ALLOWED_AUTH_UNKNOWN) + value_hash_add_uint (properties, "allowed_auth", auth); + } + + return properties; + } + + g_hash_table_destroy (properties); + return NULL; +} + +static NMActStageReturn +act_stage1_prepare (NMModem *modem, + NMConnection *connection, + NMDeviceStateReason *reason) +{ + NMModemOld *self = NM_MODEM_OLD (modem); + NMModemOldPrivate *priv = NM_MODEM_OLD_GET_PRIVATE (self); + + if (priv->connect_properties) + g_hash_table_destroy (priv->connect_properties); + priv->connect_properties = create_connect_properties (connection); + + if (nm_modem_get_state (modem) >= NM_MODEM_STATE_ENABLING) + do_connect (self); + else + do_enable (self); + + return NM_ACT_STAGE_RETURN_POSTPONE; +} + +/*****************************************************************************/ +/* IP method static */ + +static char addr_to_string_buf[INET6_ADDRSTRLEN + 1]; + +static const char * +ip_address_to_string (guint32 numeric) +{ + guint32 temp_addr; + + memset (&addr_to_string_buf, '\0', sizeof (addr_to_string_buf)); + temp_addr = numeric; + + if (inet_ntop (AF_INET, &temp_addr, addr_to_string_buf, INET_ADDRSTRLEN)) { + return addr_to_string_buf; + } else { + nm_log_warn (LOGD_VPN, "error converting IP4 address 0x%X", + ntohl (temp_addr)); + return NULL; + } +} + +static void +static_stage3_done (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) +{ + NMModemOld *self = NM_MODEM_OLD (user_data); + NMModemOldPrivate *priv = NM_MODEM_OLD_GET_PRIVATE (self); + GValueArray *ret_array = NULL; + GError *error = NULL; + NMIP4Config *config = NULL; + + priv->call = NULL; + + /* Returned value array is (uuuu): [IP, DNS1, DNS2, DNS3], all in + * network byte order. + */ + if (dbus_g_proxy_end_call (proxy, call, &error, + G_TYPE_VALUE_ARRAY, &ret_array, + G_TYPE_INVALID)) { + NMPlatformIP4Address address; + int i; + + config = nm_ip4_config_new (); + memset (&address, 0, sizeof (address)); + + nm_log_info (LOGD_MB, "(%s): IPv4 static configuration:", + nm_modem_get_uid (NM_MODEM (self))); + + /* IP address */ + address.address = g_value_get_uint (g_value_array_get_nth (ret_array, 0)); + address.plen = 32; + address.source = NM_PLATFORM_SOURCE_WWAN; + nm_ip4_config_add_address (config, &address); + + nm_log_info (LOGD_MB, " address %s/%d", + ip_address_to_string (address.address), + address.plen); + + /* DNS servers */ + for (i = 1; i < ret_array->n_values; i++) { + GValue *value = g_value_array_get_nth (ret_array, i); + guint32 tmp = g_value_get_uint (value); + + if (tmp > 0) { + nm_ip4_config_add_nameserver (config, tmp); + nm_log_info (LOGD_MB, " DNS %s", ip_address_to_string (tmp)); + } + } + g_value_array_free (ret_array); + } + + g_signal_emit_by_name (self, NM_MODEM_IP4_CONFIG_RESULT, config, error); + g_clear_error (&error); +} + +static NMActStageReturn +static_stage3_ip4_config_start (NMModem *self, + NMActRequest *req, + NMDeviceStateReason *reason) +{ + NMModemOldPrivate *priv; + + g_return_val_if_fail (NM_IS_MODEM (self), NM_ACT_STAGE_RETURN_FAILURE); + g_return_val_if_fail (NM_IS_ACT_REQUEST (req), NM_ACT_STAGE_RETURN_FAILURE); + g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); + + priv = NM_MODEM_OLD_GET_PRIVATE (self); + + priv->call = dbus_g_proxy_begin_call (nm_modem_old_get_proxy (NM_MODEM_OLD (self), + MM_OLD_DBUS_INTERFACE_MODEM), + "GetIP4Config", static_stage3_done, + self, NULL, + G_TYPE_INVALID); + + return NM_ACT_STAGE_RETURN_POSTPONE; +} + +/*****************************************************************************/ + +static void +disconnect_done (DBusGProxy *proxy, + DBusGProxyCall *call_id, + gpointer user_data) +{ + GError *error = NULL; + gboolean warn = GPOINTER_TO_UINT (user_data); + + if (!dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID) && warn) { + nm_log_info (LOGD_MB, "disconnect failed: (%d) %s", + error ? error->code : -1, + error && error->message ? error->message : "(unknown)"); + } +} + +static void +disconnect (NMModem *self, + gboolean warn) +{ + dbus_g_proxy_begin_call (nm_modem_old_get_proxy (NM_MODEM_OLD (self), + MM_OLD_DBUS_INTERFACE_MODEM), + "Disconnect", + disconnect_done, + GUINT_TO_POINTER (warn), + NULL, + G_TYPE_INVALID); +} + +/*****************************************************************************/ + +static void +deactivate (NMModem *self, NMDevice *device) +{ + NMModemOldPrivate *priv = NM_MODEM_OLD_GET_PRIVATE (self); + + priv->pin_tries = 0; + + if (priv->call) { + dbus_g_proxy_cancel_call (priv->proxy, priv->call); + priv->call = NULL; + } + + if (priv->enable_delay_id) { + g_source_remove (priv->enable_delay_id); + priv->enable_delay_id = 0; + } + + /* Chain up parent */ + NM_MODEM_CLASS (nm_modem_old_parent_class)->deactivate (self, device); +} + +/*****************************************************************************/ + +static void +modem_properties_changed (DBusGProxy *proxy, + const char *interface, + GHashTable *props, + gpointer user_data) +{ + NMModemOld *self = NM_MODEM_OLD (user_data); + NMModemOldPrivate *priv = NM_MODEM_OLD_GET_PRIVATE (self); + GValue *value; + gboolean update_state = FALSE; + + if (strcmp (interface, MM_OLD_DBUS_INTERFACE_MODEM) && + strcmp (interface, MM_OLD_DBUS_INTERFACE_MODEM_GSM_CARD)) + return; + + value = g_hash_table_lookup (props, "IpMethod"); + if (value && G_VALUE_HOLDS_UINT (value)) { + g_object_set (self, + NM_MODEM_IP_METHOD, g_value_get_uint (value), + NULL); + } + + value = g_hash_table_lookup (props, "SimIdentifier"); + if (value && G_VALUE_HOLDS_STRING (value)) { + const char *sim_id = g_value_get_string (value); + + g_object_set (self, + NM_MODEM_SIM_ID, (sim_id && *sim_id) ? sim_id : NULL, + NULL); + } + + value = g_hash_table_lookup (props, "UnlockRequired"); + if (value && G_VALUE_HOLDS_STRING (value)) { + g_free (priv->unlock_required); + priv->unlock_required = g_value_dup_string (value); + update_state = TRUE; + } + + value = g_hash_table_lookup (props, "State"); + if (value && G_VALUE_HOLDS_UINT (value)) { + priv->state = g_value_get_uint (value); + update_state = TRUE; + } + + if (update_state) { + nm_modem_set_state (NM_MODEM (self), + mm_state_to_nm (priv->state, priv->unlock_required), + NULL); + } +} + +/*****************************************************************************/ + +static gboolean +check_connection_compatible (NMModem *modem, NMConnection *connection) +{ + NMModemOldPrivate *priv = NM_MODEM_OLD_GET_PRIVATE (modem); + NMSettingConnection *s_con; + gboolean valid_cdma = FALSE, valid_gsm = FALSE; + const char *ctype; + + s_con = nm_connection_get_setting_connection (connection); + g_assert (s_con); + ctype = nm_setting_connection_get_connection_type (s_con); + g_assert (ctype); + + /* Check for valid CDMA first */ + if (strcmp (ctype, NM_SETTING_CDMA_SETTING_NAME) == 0) + valid_cdma = !!nm_connection_get_setting_cdma (connection); + + if (strcmp (ctype, NM_SETTING_GSM_SETTING_NAME) == 0) + valid_gsm = !!nm_connection_get_setting_gsm (connection); + + /* Validate CDMA */ + if (priv->caps & NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO) { + if (valid_cdma) + return TRUE; + + /* If the modem is only CDMA and the connection is not CDMA, error */ + if ((priv->caps ^ NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO) == 0) + return FALSE; + } + + /* Validate 3GPP */ + if (priv->caps & CAPS_3GPP) + return valid_gsm; + + return FALSE; +} + +/*****************************************************************************/ + +static void +complete_ppp_setting (NMConnection *connection) +{ + NMSettingPPP *s_ppp; + + s_ppp = nm_connection_get_setting_ppp (connection); + if (!s_ppp) { + s_ppp = (NMSettingPPP *) nm_setting_ppp_new (); + g_object_set (G_OBJECT (s_ppp), + NM_SETTING_PPP_LCP_ECHO_FAILURE, 5, + NM_SETTING_PPP_LCP_ECHO_INTERVAL, 30, + NULL); + nm_connection_add_setting (connection, NM_SETTING (s_ppp)); + } +} + +static gboolean +complete_connection_3gpp (NMConnection *connection, + const GSList *existing_connections, + GError **error) +{ + NMSettingGsm *s_gsm; + + s_gsm = nm_connection_get_setting_gsm (connection); + if (!s_gsm || !nm_setting_gsm_get_apn (s_gsm)) { + /* Need an APN at least */ + g_set_error_literal (error, + NM_SETTING_GSM_ERROR, + NM_SETTING_GSM_ERROR_MISSING_PROPERTY, + NM_SETTING_GSM_APN); + return FALSE; + } + + if (!nm_setting_gsm_get_number (s_gsm)) + g_object_set (G_OBJECT (s_gsm), NM_SETTING_GSM_NUMBER, "*99#", NULL); + + complete_ppp_setting (connection); + + nm_utils_complete_generic (connection, + NM_SETTING_GSM_SETTING_NAME, + existing_connections, + _("GSM connection %d"), + NULL, + FALSE); /* No IPv6 yet by default */ + return TRUE; +} + +static gboolean +complete_connection_cdma (NMConnection *connection, + const GSList *existing_connections, + GError **error) +{ + NMSettingCdma *s_cdma; + + s_cdma = nm_connection_get_setting_cdma (connection); + if (!s_cdma) { + s_cdma = (NMSettingCdma *) nm_setting_cdma_new (); + nm_connection_add_setting (connection, NM_SETTING (s_cdma)); + } + + if (!nm_setting_cdma_get_number (s_cdma)) + g_object_set (G_OBJECT (s_cdma), NM_SETTING_CDMA_NUMBER, "#777", NULL); + + complete_ppp_setting (connection); + + nm_utils_complete_generic (connection, + NM_SETTING_CDMA_SETTING_NAME, + existing_connections, + _("CDMA connection %d"), + NULL, + FALSE); /* No IPv6 yet by default */ + return TRUE; +} + +static gboolean +complete_connection (NMModem *modem, + NMConnection *connection, + const GSList *existing_connections, + GError **error) +{ + NMModemOldPrivate *priv = NM_MODEM_OLD_GET_PRIVATE (modem); + + /* If the modem has LTE, complete as 3GPP */ + if (priv->caps & NM_DEVICE_MODEM_CAPABILITY_LTE) + return complete_connection_3gpp (connection, existing_connections, error); + + /* Otherwise, prefer CDMA on the theory that if the modem has CDMA/EVDO + * that's most likely what the user will be using. + */ + if (priv->caps & NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO) + return complete_connection_cdma (connection, existing_connections, error); + + if (priv->caps & NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS) + return complete_connection_3gpp (connection, existing_connections, error); + + g_set_error_literal (error, NM_MODEM_ERROR, NM_MODEM_ERROR_CONNECTION_INCOMPATIBLE, + "Modem had no WWAN capabilities."); + return FALSE; +} + +/*****************************************************************************/ + +static gboolean +get_user_pass (NMModem *modem, + NMConnection *connection, + const char **user, + const char **pass) +{ + NMModemOldPrivate *priv = NM_MODEM_OLD_GET_PRIVATE (modem); + NMSettingCdma *s_cdma; + NMSettingGsm *s_gsm; + + if (priv->caps & NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO) { + s_cdma = nm_connection_get_setting_cdma (connection); + if (s_cdma) { + if (user) + *user = nm_setting_cdma_get_username (s_cdma); + if (pass) + *pass = nm_setting_cdma_get_password (s_cdma); + return TRUE; + } + } + + /* Fall back to GSM; will be used for CDMA devices on LTE networks too */ + s_gsm = nm_connection_get_setting_gsm (connection); + if (s_gsm) { + if (user) + *user = nm_setting_gsm_get_username (s_gsm); + if (pass) + *pass = nm_setting_gsm_get_password (s_gsm); + return TRUE; + } + + return FALSE; +} + +/*****************************************************************************/ + +static void +get_capabilities (NMModem *_self, + NMDeviceModemCapabilities *modem_caps, + NMDeviceModemCapabilities *current_caps) +{ + NMModemOld *self = NM_MODEM_OLD (_self); + + *current_caps = *modem_caps = NM_MODEM_OLD_GET_PRIVATE (self)->caps; +} + +/*****************************************************************************/ + +NMModem * +nm_modem_old_new (const char *path, GHashTable *properties, GError **error) +{ + NMDeviceModemCapabilities caps = NM_DEVICE_MODEM_CAPABILITY_NONE; + NMModemOld *self; + GHashTableIter iter; + const char *prop; + GValue *value; + const char *data_device = NULL; + const char *driver = NULL; + const char *master_device = NULL; + const char *unlock_required = NULL; + const char *device_id = NULL; + guint32 modem_type = MM_OLD_MODEM_TYPE_UNKNOWN; + guint32 ip_method = MM_MODEM_IP_METHOD_PPP; + guint32 ip_timeout = 0; + MMOldModemState state = MM_OLD_MODEM_STATE_UNKNOWN; + + g_return_val_if_fail (path != NULL, NULL); + g_return_val_if_fail (properties != NULL, NULL); + + g_hash_table_iter_init (&iter, properties); + while (g_hash_table_iter_next (&iter, (gpointer) &prop, (gpointer) &value)) { + if (g_strcmp0 (prop, "Type") == 0) + modem_type = g_value_get_uint (value); + else if (g_strcmp0 (prop, "MasterDevice") == 0) + master_device = g_value_get_string (value); + else if (g_strcmp0 (prop, "IpMethod") == 0) + ip_method = g_value_get_uint (value); + else if (g_strcmp0 (prop, "Device") == 0) + data_device = g_value_get_string (value); + else if (g_strcmp0 (prop, "Driver") == 0) + driver = g_value_get_string (value); + else if (g_strcmp0 (prop, "IpTimeout") == 0) + ip_timeout = g_value_get_uint (value); + else if (g_strcmp0 (prop, "State") == 0) + state = g_value_get_uint (value); + else if (g_strcmp0 (prop, "UnlockRequired") == 0) + unlock_required = g_value_get_string (value); + else if (g_strcmp0 (prop, "DeviceIdentifier") == 0) + device_id = g_value_get_string (value); + } + + if (modem_type == MM_OLD_MODEM_TYPE_UNKNOWN) { + g_set_error (error, NM_MODEM_ERROR, NM_MODEM_ERROR_INITIALIZATION_FAILED, + "Unhandled modem type %d", modem_type); + return NULL; + } + + if (!master_device || !strlen (master_device)) { + g_set_error_literal (error, NM_MODEM_ERROR, NM_MODEM_ERROR_INITIALIZATION_FAILED, + "Failed to retrieve modem master device."); + return NULL; + } + + if (!driver || !strlen (driver)) { + g_set_error_literal (error, NM_MODEM_ERROR, NM_MODEM_ERROR_INITIALIZATION_FAILED, + "Failed to retrieve modem driver."); + return NULL; + } + + if (!data_device || !strlen (data_device)) { + g_set_error_literal (error, NM_MODEM_ERROR, NM_MODEM_ERROR_INITIALIZATION_FAILED, + "Failed to retrieve modem data device."); + return NULL; + } + + self = (NMModemOld *) g_object_new (NM_TYPE_MODEM_OLD, + NM_MODEM_PATH, path, + NM_MODEM_DRIVER, driver, + NM_MODEM_UID, data_device, + NM_MODEM_CONTROL_PORT, NULL, + NM_MODEM_DATA_PORT, data_device, + NM_MODEM_IP_METHOD, ip_method, + NM_MODEM_IP_TIMEOUT, ip_timeout, + NM_MODEM_DEVICE_ID, device_id, + NM_MODEM_STATE, mm_state_to_nm (state, unlock_required), + NULL); + if (self) { + if (modem_type == MM_OLD_MODEM_TYPE_CDMA) + caps |= NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO; + if (modem_type == MM_OLD_MODEM_TYPE_GSM) + caps |= NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS; + + NM_MODEM_OLD_GET_PRIVATE (self)->caps = caps; + NM_MODEM_OLD_GET_PRIVATE (self)->state = state; + NM_MODEM_OLD_GET_PRIVATE (self)->unlock_required = g_strdup (unlock_required); + } + + return (NMModem *) self; +} + +static void +nm_modem_old_init (NMModemOld *self) +{ +} + +static void +get_sim_id_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) +{ + NMModemOld *self = NM_MODEM_OLD (user_data); + GValue value = G_VALUE_INIT; + + if (dbus_g_proxy_end_call (proxy, call_id, NULL, G_TYPE_VALUE, &value, G_TYPE_INVALID)) { + if (G_VALUE_HOLDS_STRING (&value)) { + const char *sim_id = g_value_get_string (&value); + + if (sim_id && *sim_id) + g_object_set (G_OBJECT (self), NM_MODEM_SIM_ID, sim_id, NULL); + } + g_value_unset (&value); + } +} + +static GObject* +constructor (GType type, + guint n_construct_params, + GObjectConstructParam *construct_params) +{ + GObject *object; + NMModemOldPrivate *priv; + DBusGConnection *bus; + + object = G_OBJECT_CLASS (nm_modem_old_parent_class)->constructor (type, n_construct_params, construct_params); + if (!object) + return NULL; + + priv = NM_MODEM_OLD_GET_PRIVATE (object); + + bus = nm_dbus_manager_get_connection (nm_dbus_manager_get ()); + priv->proxy = dbus_g_proxy_new_for_name (bus, + MM_OLD_DBUS_SERVICE, + nm_modem_get_path (NM_MODEM (object)), + MM_OLD_DBUS_INTERFACE_MODEM); + + priv->props_proxy = dbus_g_proxy_new_for_name (bus, + MM_OLD_DBUS_SERVICE, + nm_modem_get_path (NM_MODEM (object)), + DBUS_INTERFACE_PROPERTIES); + dbus_g_object_register_marshaller (g_cclosure_marshal_generic, + G_TYPE_NONE, + G_TYPE_STRING, DBUS_TYPE_G_MAP_OF_VARIANT, + G_TYPE_INVALID); + dbus_g_proxy_add_signal (priv->props_proxy, "MmPropertiesChanged", + G_TYPE_STRING, DBUS_TYPE_G_MAP_OF_VARIANT, + G_TYPE_INVALID); + dbus_g_proxy_connect_signal (priv->props_proxy, "MmPropertiesChanged", + G_CALLBACK (modem_properties_changed), + object, + NULL); + + /* Request the SIM ID */ + dbus_g_proxy_begin_call (priv->props_proxy, + "Get", + get_sim_id_done, + g_object_ref (object), g_object_unref, + G_TYPE_STRING, MM_OLD_DBUS_INTERFACE_MODEM_GSM_CARD, + G_TYPE_STRING, "SimIdentifier", + G_TYPE_INVALID); + + return object; +} + +static void +dispose (GObject *object) +{ + NMModemOldPrivate *priv = NM_MODEM_OLD_GET_PRIVATE (object); + + if (priv->proxy) { + g_object_unref (priv->proxy); + priv->proxy = NULL; + } + + if (priv->props_proxy) { + g_object_unref (priv->props_proxy); + priv->props_proxy = NULL; + } + + if (priv->connect_properties) { + g_hash_table_destroy (priv->connect_properties); + priv->connect_properties = NULL; + } + + if (priv->enable_delay_id) { + g_source_remove (priv->enable_delay_id); + priv->enable_delay_id = 0; + } + + g_free (priv->unlock_required); + priv->unlock_required = NULL; + + G_OBJECT_CLASS (nm_modem_old_parent_class)->dispose (object); +} + +static void +nm_modem_old_class_init (NMModemOldClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMModemClass *modem_class = NM_MODEM_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (NMModemOldPrivate)); + + /* Virtual methods */ + object_class->constructor = constructor; + object_class->dispose = dispose; + + modem_class->get_capabilities = get_capabilities; + modem_class->get_user_pass = get_user_pass; + modem_class->complete_connection = complete_connection; + modem_class->check_connection_compatible = check_connection_compatible; + modem_class->act_stage1_prepare = act_stage1_prepare; + modem_class->static_stage3_ip4_config_start = static_stage3_ip4_config_start; + modem_class->disconnect = disconnect; + modem_class->deactivate = deactivate; + modem_class->set_mm_enabled = set_mm_enabled; +} diff --git a/src/devices/wwan/nm-modem-old.h b/src/devices/wwan/nm-modem-old.h new file mode 100644 index 00000000..65e3db2d --- /dev/null +++ b/src/devices/wwan/nm-modem-old.h @@ -0,0 +1,53 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2009 - 2011 Red Hat, Inc. + * Copyright (C) 2009 Novell, Inc. + */ + +#ifndef NM_MODEM_OLD_H +#define NM_MODEM_OLD_H + +#include +#include +#include "nm-modem.h" +#include "nm-modem-old-types.h" + +G_BEGIN_DECLS + +#define NM_TYPE_MODEM_OLD (nm_modem_old_get_type ()) +#define NM_MODEM_OLD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_MODEM_OLD, NMModemOld)) +#define NM_MODEM_OLD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_MODEM_OLD, NMModemOldClass)) +#define NM_IS_MODEM_OLD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_MODEM_OLD)) +#define NM_IS_MODEM_OLD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_MODEM_OLD)) +#define NM_MODEM_OLD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_MODEM_OLD, NMModemOldClass)) + +typedef struct { + NMModem parent; +} NMModemOld; + +typedef struct { + NMModemClass parent; +} NMModemOldClass; + +GType nm_modem_old_get_type (void); + +NMModem *nm_modem_old_new (const char *path, GHashTable *properties, GError **error); + +G_END_DECLS + +#endif /* NM_MODEM_OLD_H */ diff --git a/src/devices/wwan/nm-modem.c b/src/devices/wwan/nm-modem.c new file mode 100644 index 00000000..fd3b4a36 --- /dev/null +++ b/src/devices/wwan/nm-modem.c @@ -0,0 +1,1119 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2009 - 2014 Red Hat, Inc. + * Copyright (C) 2009 Novell, Inc. + */ + +#include +#include "nm-modem.h" +#include "nm-platform.h" +#include "nm-dbus-manager.h" +#include "nm-setting-connection.h" +#include "nm-properties-changed-signal.h" +#include "nm-logging.h" +#include "NetworkManagerUtils.h" +#include "nm-device-private.h" +#include "nm-dbus-glib-types.h" +#include "nm-modem-enum-types.h" + +G_DEFINE_TYPE (NMModem, nm_modem, G_TYPE_OBJECT) + +#define NM_MODEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_MODEM, NMModemPrivate)) + +enum { + PROP_0, + PROP_CONTROL_PORT, + PROP_DATA_PORT, + PROP_PATH, + PROP_UID, + PROP_DRIVER, + PROP_IP_METHOD, + PROP_IP_TIMEOUT, + PROP_STATE, + PROP_DEVICE_ID, + PROP_SIM_ID, + + LAST_PROP +}; + +typedef struct { + char *uid; + char *path; + char *driver; + char *control_port; + char *data_port; + char *ppp_iface; + guint32 ip_method; + NMModemState state; + NMModemState prev_state; /* revert to this state if enable/disable fails */ + char *device_id; + char *sim_id; + + NMPPPManager *ppp_manager; + + NMActRequest *act_request; + guint32 secrets_tries; + guint32 secrets_id; + + guint32 mm_ip_timeout; + + /* PPP stats */ + guint32 in_bytes; + guint32 out_bytes; +} NMModemPrivate; + +enum { + PPP_STATS, + PPP_FAILED, + PREPARE_RESULT, + IP4_CONFIG_RESULT, + AUTH_REQUESTED, + AUTH_RESULT, + REMOVED, + STATE_CHANGED, + + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + + +/*****************************************************************************/ + +GQuark +nm_modem_error_quark (void) +{ + static GQuark quark = 0; + if (!quark) + quark = g_quark_from_static_string ("nm-modem-error"); + return quark; +} + +/*****************************************************************************/ +/* State/enabled/connected */ + +static const char *state_table[] = { + [NM_MODEM_STATE_UNKNOWN] = "unknown", + [NM_MODEM_STATE_FAILED] = "failed", + [NM_MODEM_STATE_INITIALIZING] = "initializing", + [NM_MODEM_STATE_LOCKED] = "locked", + [NM_MODEM_STATE_DISABLED] = "disabled", + [NM_MODEM_STATE_DISABLING] = "disabling", + [NM_MODEM_STATE_ENABLING] = "enabling", + [NM_MODEM_STATE_ENABLED] = "enabled", + [NM_MODEM_STATE_SEARCHING] = "searching", + [NM_MODEM_STATE_REGISTERED] = "registered", + [NM_MODEM_STATE_DISCONNECTING] = "disconnecting", + [NM_MODEM_STATE_CONNECTING] = "connecting", + [NM_MODEM_STATE_CONNECTED] = "connected", +}; + +const char * +nm_modem_state_to_string (NMModemState state) +{ + if (state >= 0 && state < G_N_ELEMENTS (state_table)) + return state_table[state]; + return NULL; +} + +NMModemState +nm_modem_get_state (NMModem *self) +{ + return NM_MODEM_GET_PRIVATE (self)->state; +} + +void +nm_modem_set_state (NMModem *self, + NMModemState new_state, + const char *reason) +{ + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); + NMModemState old_state = priv->state; + + priv->prev_state = NM_MODEM_STATE_UNKNOWN; + + if (new_state != old_state) { + nm_log_info (LOGD_MB, "(%s): modem state changed, '%s' --> '%s' (reason: %s)\n", + nm_modem_get_uid (self), + nm_modem_state_to_string (old_state), + nm_modem_state_to_string (new_state), + reason ? reason : "none"); + + priv->state = new_state; + g_object_notify (G_OBJECT (self), NM_MODEM_STATE); + g_signal_emit (self, signals[STATE_CHANGED], 0, new_state, old_state, reason); + } +} + +void +nm_modem_set_prev_state (NMModem *self, const char *reason) +{ + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); + + /* Reset modem to previous state if the state hasn't already changed */ + if (priv->prev_state != NM_MODEM_STATE_UNKNOWN) + nm_modem_set_state (self, priv->prev_state, reason); +} + +void +nm_modem_set_mm_enabled (NMModem *self, + gboolean enabled) +{ + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); + NMModemState prev_state = priv->state; + + if (enabled && priv->state >= NM_MODEM_STATE_ENABLING) { + nm_log_dbg (LOGD_MB, "(%s) cannot enable modem: already enabled", + nm_modem_get_uid (self)); + return; + } + if (!enabled && priv->state <= NM_MODEM_STATE_DISABLING) { + nm_log_dbg (LOGD_MB, "(%s) cannot disable modem: already disabled", + nm_modem_get_uid (self)); + return; + } + + if (priv->state <= NM_MODEM_STATE_INITIALIZING) { + nm_log_dbg (LOGD_MB, "(%s) cannot enable/disable modem: initializing or failed", + nm_modem_get_uid (self)); + return; + } else if (priv->state == NM_MODEM_STATE_LOCKED) { + /* Don't try to enable if the modem is locked since that will fail */ + nm_log_warn (LOGD_MB, "(%s) cannot enable/disable modem: locked", + nm_modem_get_uid (self)); + + /* Try to unlock the modem if it's being enabled */ + if (enabled) + g_signal_emit_by_name (self, NM_MODEM_AUTH_REQUESTED, 0); + return; + } + + NM_MODEM_GET_CLASS (self)->set_mm_enabled (self, enabled); + + /* Pre-empt the state change signal */ + nm_modem_set_state (self, + enabled ? NM_MODEM_STATE_ENABLING : NM_MODEM_STATE_DISABLING, + "user preference"); + priv->prev_state = prev_state; +} + +void +nm_modem_emit_removed (NMModem *self) +{ + g_signal_emit (self, signals[REMOVED], 0); +} + +/*****************************************************************************/ +/* IP method PPP */ + +static void +ppp_state_changed (NMPPPManager *ppp_manager, NMPPPStatus status, gpointer user_data) +{ + switch (status) { + case NM_PPP_STATUS_DISCONNECT: + g_signal_emit (NM_MODEM (user_data), signals[PPP_FAILED], 0, NM_DEVICE_STATE_REASON_PPP_DISCONNECT); + break; + case NM_PPP_STATUS_DEAD: + g_signal_emit (NM_MODEM (user_data), signals[PPP_FAILED], 0, NM_DEVICE_STATE_REASON_PPP_FAILED); + break; + default: + break; + } +} + +static void +ppp_ip4_config (NMPPPManager *ppp_manager, + const char *iface, + NMIP4Config *config, + gpointer user_data) +{ + NMModem *self = NM_MODEM (user_data); + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); + guint32 i, num; + guint32 bad_dns1 = htonl (0x0A0B0C0D); + guint32 good_dns1 = htonl (0x04020201); /* GTE nameserver */ + guint32 bad_dns2 = htonl (0x0A0B0C0E); + guint32 good_dns2 = htonl (0x04020202); /* GTE nameserver */ + gboolean dns_workaround = FALSE; + + /* Notify about the new data port to use */ + g_free (priv->ppp_iface); + priv->ppp_iface = g_strdup (iface); + g_object_notify (G_OBJECT (self), NM_MODEM_DATA_PORT); + + /* Work around a PPP bug (#1732) which causes many mobile broadband + * providers to return 10.11.12.13 and 10.11.12.14 for the DNS servers. + * Apparently fixed in ppp-2.4.5 but we've had some reports that this is + * not the case. + * + * http://git.ozlabs.org/?p=ppp.git;a=commitdiff_plain;h=2e09ef6886bbf00bc5a9a641110f801e372ffde6 + * http://git.ozlabs.org/?p=ppp.git;a=commitdiff_plain;h=f8191bf07df374f119a07910a79217c7618f113e + */ + + num = nm_ip4_config_get_num_nameservers (config); + if (num == 2) { + gboolean found1 = FALSE, found2 = FALSE; + + for (i = 0; i < num; i++) { + guint32 ns = nm_ip4_config_get_nameserver (config, i); + + if (ns == bad_dns1) + found1 = TRUE; + else if (ns == bad_dns2) + found2 = TRUE; + } + + /* Be somewhat conservative about substitutions; the "bad" nameservers + * could actually be valid in some cases, so only substitute if ppp + * returns *only* the two bad nameservers. + */ + dns_workaround = (found1 && found2); + } + + if (!num || dns_workaround) { + nm_log_warn (LOGD_PPP, "compensating for invalid PPP-provided nameservers"); + nm_ip4_config_reset_nameservers (config); + nm_ip4_config_add_nameserver (config, good_dns1); + nm_ip4_config_add_nameserver (config, good_dns2); + } + + g_signal_emit (self, signals[IP4_CONFIG_RESULT], 0, config, NULL); +} + +static void +ppp_stats (NMPPPManager *ppp_manager, + guint32 in_bytes, + guint32 out_bytes, + gpointer user_data) +{ + NMModem *self = NM_MODEM (user_data); + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); + + if (priv->in_bytes != in_bytes || priv->out_bytes != out_bytes) { + priv->in_bytes = in_bytes; + priv->out_bytes = out_bytes; + + g_signal_emit (self, signals[PPP_STATS], 0, in_bytes, out_bytes); + } +} + +static NMActStageReturn +ppp_stage3_ip4_config_start (NMModem *self, + NMActRequest *req, + NMDeviceStateReason *reason) +{ + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); + const char *ppp_name = NULL; + GError *error = NULL; + NMActStageReturn ret; + guint ip_timeout = 20; + + g_return_val_if_fail (NM_IS_MODEM (self), NM_ACT_STAGE_RETURN_FAILURE); + g_return_val_if_fail (NM_IS_ACT_REQUEST (req), NM_ACT_STAGE_RETURN_FAILURE); + g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); + + if (NM_MODEM_GET_CLASS (self)->get_user_pass) { + NMConnection *connection = nm_act_request_get_connection (req); + + g_assert (connection); + if (!NM_MODEM_GET_CLASS (self)->get_user_pass (self, connection, &ppp_name, NULL)) + return NM_ACT_STAGE_RETURN_FAILURE; + } + + /* Check if ModemManager requested a specific IP timeout to be used. If 0 reported, + * use the default one (20s) */ + if (priv->mm_ip_timeout > 0) { + nm_log_info (LOGD_PPP, "using modem-specified IP timeout: %u seconds", + priv->mm_ip_timeout); + ip_timeout = priv->mm_ip_timeout; + } + + priv->ppp_manager = nm_ppp_manager_new (priv->data_port); + if (nm_ppp_manager_start (priv->ppp_manager, req, ppp_name, ip_timeout, &error)) { + g_signal_connect (priv->ppp_manager, "state-changed", + G_CALLBACK (ppp_state_changed), + self); + g_signal_connect (priv->ppp_manager, "ip4-config", + G_CALLBACK (ppp_ip4_config), + self); + g_signal_connect (priv->ppp_manager, "stats", + G_CALLBACK (ppp_stats), + self); + + ret = NM_ACT_STAGE_RETURN_POSTPONE; + } else { + nm_log_err (LOGD_PPP, "error starting PPP: (%d) %s", + error ? error->code : -1, + error && error->message ? error->message : "(unknown)"); + g_error_free (error); + + g_object_unref (priv->ppp_manager); + priv->ppp_manager = NULL; + + *reason = NM_DEVICE_STATE_REASON_PPP_START_FAILED; + ret = NM_ACT_STAGE_RETURN_FAILURE; + } + + return ret; +} + +/*****************************************************************************/ + +NMActStageReturn +nm_modem_stage3_ip4_config_start (NMModem *self, + NMDevice *device, + NMDeviceClass *device_class, + NMDeviceStateReason *reason) +{ + NMModemPrivate *priv; + NMActRequest *req; + NMActStageReturn ret; + + g_return_val_if_fail (NM_IS_MODEM (self), NM_ACT_STAGE_RETURN_FAILURE); + g_return_val_if_fail (NM_IS_DEVICE (device), NM_ACT_STAGE_RETURN_FAILURE); + g_return_val_if_fail (NM_IS_DEVICE_CLASS (device_class), NM_ACT_STAGE_RETURN_FAILURE); + g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); + + req = nm_device_get_act_request (device); + g_assert (req); + + priv = NM_MODEM_GET_PRIVATE (self); + switch (priv->ip_method) { + case MM_MODEM_IP_METHOD_PPP: + ret = ppp_stage3_ip4_config_start (self, req, reason); + break; + case MM_MODEM_IP_METHOD_STATIC: + ret = NM_MODEM_GET_CLASS (self)->static_stage3_ip4_config_start (self, req, reason); + break; + case MM_MODEM_IP_METHOD_DHCP: + ret = device_class->act_stage3_ip4_config_start (device, NULL, reason); + break; + default: + nm_log_err (LOGD_MB, "unknown IP method %d", priv->ip_method); + ret = NM_ACT_STAGE_RETURN_FAILURE; + break; + } + + return ret; +} + +void +nm_modem_ip4_pre_commit (NMModem *modem, + NMDevice *device, + NMIP4Config *config) +{ + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (modem); + + /* If the modem has an ethernet-type data interface (ie, not PPP and thus + * not point-to-point) and IP config has a /32 prefix, then we assume that + * ARP will be pointless and we turn it off. + */ + if ( priv->ip_method == MM_MODEM_IP_METHOD_STATIC + || priv->ip_method == MM_MODEM_IP_METHOD_DHCP) { + const NMPlatformIP4Address *address = nm_ip4_config_get_address (config, 0); + + g_assert (address); + if (address->plen == 32) + nm_platform_link_set_noarp (nm_device_get_ip_ifindex (device)); + } +} + +/*****************************************************************************/ + +NMActStageReturn +nm_modem_stage3_ip6_config_start (NMModem *self, + NMDevice *device, + NMDeviceClass *device_class, + NMDeviceStateReason *reason) +{ + /* FIXME: We don't support IPv6 on modems quite yet... */ + nm_device_activate_schedule_ip6_config_timeout (device); + return NM_ACT_STAGE_RETURN_POSTPONE; +} + +/*****************************************************************************/ + +static void +cancel_get_secrets (NMModem *self) +{ + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); + + if (priv->secrets_id) { + nm_act_request_cancel_secrets (priv->act_request, priv->secrets_id); + priv->secrets_id = 0; + } +} + +static void +modem_secrets_cb (NMActRequest *req, + guint32 call_id, + NMConnection *connection, + GError *error, + gpointer user_data) +{ + NMModem *self = NM_MODEM (user_data); + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); + + g_return_if_fail (call_id == priv->secrets_id); + + priv->secrets_id = 0; + + if (error) + nm_log_warn (LOGD_MB, "%s", error->message); + + g_signal_emit (self, signals[AUTH_RESULT], 0, error); +} + +gboolean +nm_modem_get_secrets (NMModem *self, + const char *setting_name, + gboolean request_new, + const char *hint) +{ + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); + NMSettingsGetSecretsFlags flags = NM_SETTINGS_GET_SECRETS_FLAG_ALLOW_INTERACTION; + + cancel_get_secrets (self); + + if (request_new) + flags |= NM_SETTINGS_GET_SECRETS_FLAG_REQUEST_NEW; + priv->secrets_id = nm_act_request_get_secrets (priv->act_request, + setting_name, + flags, + hint, + modem_secrets_cb, + self); + if (priv->secrets_id) + g_signal_emit (self, signals[AUTH_REQUESTED], 0); + + return !!(priv->secrets_id); +} + +/*****************************************************************************/ + +static NMActStageReturn +act_stage1_prepare (NMModem *modem, + NMConnection *connection, + NMDeviceStateReason *reason) +{ + *reason = NM_DEVICE_STATE_REASON_UNKNOWN; + return NM_ACT_STAGE_RETURN_FAILURE; +} + +NMActStageReturn +nm_modem_act_stage1_prepare (NMModem *self, + NMActRequest *req, + NMDeviceStateReason *reason) +{ + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); + NMActStageReturn ret; + GPtrArray *hints = NULL; + const char *setting_name = NULL; + NMSettingsGetSecretsFlags flags = NM_SETTINGS_GET_SECRETS_FLAG_ALLOW_INTERACTION; + NMConnection *connection; + + if (priv->act_request) + g_object_unref (priv->act_request); + priv->act_request = g_object_ref (req); + + connection = nm_act_request_get_connection (req); + g_assert (connection); + + setting_name = nm_connection_need_secrets (connection, &hints); + if (!setting_name) { + /* Ready to connect */ + g_assert (!hints); + return NM_MODEM_GET_CLASS (self)->act_stage1_prepare (self, connection, reason); + } + + /* Secrets required... */ + if (priv->secrets_tries++) + flags |= NM_SETTINGS_GET_SECRETS_FLAG_REQUEST_NEW; + + priv->secrets_id = nm_act_request_get_secrets (req, + setting_name, + flags, + hints ? g_ptr_array_index (hints, 0) : NULL, + modem_secrets_cb, + self); + if (priv->secrets_id) { + g_signal_emit (self, signals[AUTH_REQUESTED], 0); + ret = NM_ACT_STAGE_RETURN_POSTPONE; + } else { + *reason = NM_DEVICE_STATE_REASON_NO_SECRETS; + ret = NM_ACT_STAGE_RETURN_FAILURE; + } + + if (hints) + g_ptr_array_free (hints, TRUE); + + return ret; +} + +/*****************************************************************************/ + +NMActStageReturn +nm_modem_act_stage2_config (NMModem *self, + NMActRequest *req, + NMDeviceStateReason *reason) +{ + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); + + /* Clear secrets tries counter since secrets were successfully used + * already if we get here. + */ + priv->secrets_tries = 0; + + return NM_ACT_STAGE_RETURN_SUCCESS; +} + +/*****************************************************************************/ + +gboolean +nm_modem_check_connection_compatible (NMModem *self, NMConnection *connection) +{ + if (NM_MODEM_GET_CLASS (self)->check_connection_compatible) + return NM_MODEM_GET_CLASS (self)->check_connection_compatible (self, connection); + return FALSE; +} + +/*****************************************************************************/ + +gboolean +nm_modem_complete_connection (NMModem *self, + NMConnection *connection, + const GSList *existing_connections, + GError **error) +{ + if (NM_MODEM_GET_CLASS (self)->complete_connection) + return NM_MODEM_GET_CLASS (self)->complete_connection (self, connection, existing_connections, error); + return FALSE; +} + +/*****************************************************************************/ + +static void +deactivate (NMModem *self, NMDevice *device) +{ + NMModemPrivate *priv; + int ifindex; + + g_return_if_fail (NM_IS_MODEM (self)); + g_return_if_fail (NM_IS_DEVICE (device)); + + priv = NM_MODEM_GET_PRIVATE (self); + + priv->secrets_tries = 0; + + if (priv->act_request) { + cancel_get_secrets (self); + g_object_unref (priv->act_request); + priv->act_request = NULL; + } + + priv->in_bytes = priv->out_bytes = 0; + + if (priv->ppp_manager) { + g_object_unref (priv->ppp_manager); + priv->ppp_manager = NULL; + } + + switch (priv->ip_method) { + case MM_MODEM_IP_METHOD_PPP: + break; + case MM_MODEM_IP_METHOD_STATIC: + case MM_MODEM_IP_METHOD_DHCP: + ifindex = nm_device_get_ip_ifindex (device); + if (ifindex > 0) { + nm_platform_route_flush (ifindex); + nm_platform_address_flush (ifindex); + nm_platform_link_set_down (ifindex); + } + break; + default: + nm_log_err (LOGD_MB, "unknown IP method %d", priv->ip_method); + break; + } + + g_free (priv->ppp_iface); + priv->ppp_iface = NULL; +} + +/*****************************************************************************/ + +void +nm_modem_deactivate (NMModem *self, NMDevice *device) +{ + NM_MODEM_GET_CLASS (self)->deactivate (self, device); +} + +/*****************************************************************************/ + +void +nm_modem_device_state_changed (NMModem *self, + NMDeviceState new_state, + NMDeviceState old_state, + NMDeviceStateReason reason) +{ + gboolean was_connected = FALSE, warn = TRUE; + NMModemPrivate *priv; + + g_return_if_fail (NM_IS_MODEM (self)); + + if (old_state >= NM_DEVICE_STATE_PREPARE && old_state <= NM_DEVICE_STATE_DEACTIVATING) + was_connected = TRUE; + + priv = NM_MODEM_GET_PRIVATE (self); + + /* Make sure we don't leave the serial device open */ + switch (new_state) { + case NM_DEVICE_STATE_UNMANAGED: + case NM_DEVICE_STATE_UNAVAILABLE: + case NM_DEVICE_STATE_DISCONNECTED: + case NM_DEVICE_STATE_FAILED: + if (priv->act_request) { + cancel_get_secrets (self); + g_object_unref (priv->act_request); + priv->act_request = NULL; + } + + if (was_connected) { + /* Don't bother warning on FAILED since the modem is already gone */ + if (new_state == NM_DEVICE_STATE_FAILED) + warn = FALSE; + NM_MODEM_GET_CLASS (self)->disconnect (self, warn); + } + break; + default: + break; + } +} + +/*****************************************************************************/ + +const char * +nm_modem_get_uid (NMModem *self) +{ + g_return_val_if_fail (NM_IS_MODEM (self), NULL); + + return NM_MODEM_GET_PRIVATE (self)->uid; +} + +const char * +nm_modem_get_path (NMModem *self) +{ + g_return_val_if_fail (NM_IS_MODEM (self), NULL); + + return NM_MODEM_GET_PRIVATE (self)->path; +} + +const char * +nm_modem_get_driver (NMModem *self) +{ + g_return_val_if_fail (NM_IS_MODEM (self), NULL); + + return NM_MODEM_GET_PRIVATE (self)->driver; +} + +const char * +nm_modem_get_control_port (NMModem *self) +{ + g_return_val_if_fail (NM_IS_MODEM (self), NULL); + + return NM_MODEM_GET_PRIVATE (self)->control_port; +} + +const char * +nm_modem_get_data_port (NMModem *self) +{ + g_return_val_if_fail (NM_IS_MODEM (self), NULL); + + /* The ppp_iface takes precedence over the data interface when PPP is used, + * since data_iface is the TTY over which PPP is run, and that TTY can't + * do IP. The caller really wants the thing that's doing IP. + */ + return NM_MODEM_GET_PRIVATE (self)->ppp_iface ? + NM_MODEM_GET_PRIVATE (self)->ppp_iface : NM_MODEM_GET_PRIVATE (self)->data_port; +} + +gboolean +nm_modem_owns_port (NMModem *self, const char *iface) +{ + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); + + g_return_val_if_fail (iface != NULL, FALSE); + + if (NM_MODEM_GET_CLASS (self)->owns_port) + return NM_MODEM_GET_CLASS (self)->owns_port (self, iface); + + /* Fall back to data/control ports */ + if (priv->ppp_iface && (strcmp (priv->ppp_iface, iface) == 0)) + return TRUE; + if (priv->data_port && (strcmp (priv->data_port, iface) == 0)) + return TRUE; + if (priv->control_port && (strcmp (priv->control_port, iface) == 0)) + return TRUE; + + return FALSE; +} + +/*****************************************************************************/ + +void +nm_modem_get_capabilities (NMModem *self, + NMDeviceModemCapabilities *modem_caps, + NMDeviceModemCapabilities *current_caps) +{ + g_return_if_fail (NM_IS_MODEM (self)); + + NM_MODEM_GET_CLASS (self)->get_capabilities (self, modem_caps, current_caps); +} + +/*****************************************************************************/ + +static void +nm_modem_init (NMModem *self) +{ +} + +static GObject* +constructor (GType type, + guint n_construct_params, + GObjectConstructParam *construct_params) +{ + GObject *object; + NMModemPrivate *priv; + + object = G_OBJECT_CLASS (nm_modem_parent_class)->constructor (type, + n_construct_params, + construct_params); + if (!object) + return NULL; + + priv = NM_MODEM_GET_PRIVATE (object); + + if (!priv->data_port && !priv->control_port) { + nm_log_err (LOGD_HW, "neither modem command nor data interface provided"); + goto err; + } + + if (!priv->path) { + nm_log_err (LOGD_HW, "D-Bus path not provided"); + goto err; + } + + return object; + + err: + g_object_unref (object); + return NULL; +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (object); + + switch (prop_id) { + case PROP_PATH: + g_value_set_string (value, priv->path); + break; + case PROP_DRIVER: + g_value_set_string (value, priv->driver); + break; + case PROP_CONTROL_PORT: + g_value_set_string (value, priv->control_port); + break; + case PROP_DATA_PORT: + g_value_set_string (value, nm_modem_get_data_port (NM_MODEM (object))); + break; + case PROP_UID: + g_value_set_string (value, priv->uid); + break; + case PROP_IP_METHOD: + g_value_set_uint (value, priv->ip_method); + break; + case PROP_IP_TIMEOUT: + g_value_set_uint (value, priv->mm_ip_timeout); + break; + case PROP_STATE: + g_value_set_enum (value, priv->state); + break; + case PROP_DEVICE_ID: + g_value_set_string (value, priv->device_id); + break; + case PROP_SIM_ID: + g_value_set_string (value, priv->sim_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) +{ + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (object); + + switch (prop_id) { + case PROP_PATH: + /* Construct only */ + priv->path = g_value_dup_string (value); + break; + case PROP_DRIVER: + /* Construct only */ + priv->driver = g_value_dup_string (value); + break; + case PROP_CONTROL_PORT: + priv->control_port = g_value_dup_string (value); + break; + case PROP_DATA_PORT: + priv->data_port = g_value_dup_string (value); + break; + case PROP_UID: + /* Construct only */ + priv->uid = g_value_dup_string (value); + break; + case PROP_IP_METHOD: + priv->ip_method = g_value_get_uint (value); + break; + case PROP_IP_TIMEOUT: + priv->mm_ip_timeout = g_value_get_uint (value); + break; + case PROP_STATE: + priv->state = g_value_get_enum (value); + break; + case PROP_DEVICE_ID: + /* construct only */ + 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; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +dispose (GObject *object) +{ + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (object); + + if (priv->act_request) { + g_object_unref (priv->act_request); + priv->act_request = NULL; + } + + G_OBJECT_CLASS (nm_modem_parent_class)->dispose (object); +} + +static void +finalize (GObject *object) +{ + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (object); + + g_free (priv->uid); + g_free (priv->path); + g_free (priv->driver); + g_free (priv->control_port); + g_free (priv->data_port); + g_free (priv->device_id); + g_free (priv->sim_id); + + G_OBJECT_CLASS (nm_modem_parent_class)->finalize (object); +} + +static void +nm_modem_class_init (NMModemClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (NMModemPrivate)); + + /* Virtual methods */ + object_class->constructor = constructor; + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->dispose = dispose; + object_class->finalize = finalize; + + klass->act_stage1_prepare = act_stage1_prepare; + klass->deactivate = deactivate; + + /* Properties */ + + g_object_class_install_property + (object_class, PROP_UID, + g_param_spec_string (NM_MODEM_UID, + "UID", + "Modem unique ID", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property + (object_class, PROP_PATH, + g_param_spec_string (NM_MODEM_PATH, + "DBus path", + "DBus path", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property + (object_class, PROP_DRIVER, + g_param_spec_string (NM_MODEM_DRIVER, + "Driver", + "Driver", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property + (object_class, PROP_CONTROL_PORT, + g_param_spec_string (NM_MODEM_CONTROL_PORT, + "Control port", + "The port controlling the modem", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property + (object_class, PROP_DATA_PORT, + g_param_spec_string (NM_MODEM_DATA_PORT, + "Data port", + "The port to connect to", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + g_object_class_install_property + (object_class, PROP_IP_METHOD, + g_param_spec_uint (NM_MODEM_IP_METHOD, + "IP method", + "IP method", + MM_MODEM_IP_METHOD_PPP, + MM_MODEM_IP_METHOD_DHCP, + MM_MODEM_IP_METHOD_PPP, + G_PARAM_READWRITE)); + + g_object_class_install_property + (object_class, PROP_IP_TIMEOUT, + g_param_spec_uint (NM_MODEM_IP_TIMEOUT, + "IP timeout", + "IP timeout", + 0, 360, 20, + G_PARAM_READWRITE)); + + g_object_class_install_property + (object_class, PROP_STATE, + g_param_spec_enum (NM_MODEM_STATE, + "State", + "State", + NM_TYPE_MODEM_STATE, + NM_MODEM_STATE_UNKNOWN, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property + (object_class, PROP_DEVICE_ID, + g_param_spec_string (NM_MODEM_DEVICE_ID, + "DeviceId", + "Device ID", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property + (object_class, PROP_SIM_ID, + g_param_spec_string (NM_MODEM_SIM_ID, + "SimId", + "Sim ID", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + /* Signals */ + + signals[PPP_STATS] = + g_signal_new ("ppp-stats", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMModemClass, ppp_stats), + NULL, NULL, NULL, + G_TYPE_NONE, 2, + G_TYPE_UINT, G_TYPE_UINT); + + signals[PPP_FAILED] = + g_signal_new ("ppp-failed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMModemClass, ppp_failed), + NULL, NULL, NULL, + G_TYPE_NONE, 1, G_TYPE_UINT); + + signals[IP4_CONFIG_RESULT] = + g_signal_new (NM_MODEM_IP4_CONFIG_RESULT, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMModemClass, ip4_config_result), + NULL, NULL, NULL, + G_TYPE_NONE, 2, G_TYPE_OBJECT, G_TYPE_POINTER); + + signals[PREPARE_RESULT] = + g_signal_new (NM_MODEM_PREPARE_RESULT, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMModemClass, prepare_result), + NULL, NULL, NULL, + G_TYPE_NONE, 2, G_TYPE_BOOLEAN, G_TYPE_UINT); + + signals[AUTH_REQUESTED] = + g_signal_new (NM_MODEM_AUTH_REQUESTED, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMModemClass, auth_requested), + NULL, NULL, NULL, + G_TYPE_NONE, 0); + + signals[AUTH_RESULT] = + g_signal_new (NM_MODEM_AUTH_RESULT, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMModemClass, auth_result), + NULL, NULL, NULL, + G_TYPE_NONE, 1, G_TYPE_POINTER); + + signals[REMOVED] = + g_signal_new (NM_MODEM_REMOVED, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMModemClass, removed), + NULL, NULL, NULL, + G_TYPE_NONE, 0); + + signals[STATE_CHANGED] = + g_signal_new (NM_MODEM_STATE_CHANGED, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMModemClass, state_changed), + NULL, NULL, NULL, + G_TYPE_NONE, 2, NM_TYPE_MODEM_STATE, NM_TYPE_MODEM_STATE); + + dbus_g_error_domain_register (NM_MODEM_ERROR, + NM_DBUS_INTERFACE_DEVICE_MODEM, + NM_TYPE_MODEM_ERROR); +} diff --git a/src/devices/wwan/nm-modem.h b/src/devices/wwan/nm-modem.h new file mode 100644 index 00000000..c992cf72 --- /dev/null +++ b/src/devices/wwan/nm-modem.h @@ -0,0 +1,217 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2009 - 2011 Red Hat, Inc. + * Copyright (C) 2009 Novell, Inc. + */ + +#ifndef NM_MODEM_H +#define NM_MODEM_H + +#include +#include +#include "ppp-manager/nm-ppp-manager.h" +#include "nm-device.h" + +G_BEGIN_DECLS + +#define NM_TYPE_MODEM (nm_modem_get_type ()) +#define NM_MODEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_MODEM, NMModem)) +#define NM_MODEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_MODEM, NMModemClass)) +#define NM_IS_MODEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_MODEM)) +#define NM_IS_MODEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_MODEM)) +#define NM_MODEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_MODEM, NMModemClass)) + +/* Properties */ +#define NM_MODEM_UID "uid" +#define NM_MODEM_PATH "path" +#define NM_MODEM_DRIVER "driver" +#define NM_MODEM_CONTROL_PORT "control-port" +#define NM_MODEM_DATA_PORT "data-port" +#define NM_MODEM_IP_METHOD "ip-method" +#define NM_MODEM_IP_TIMEOUT "ip-timeout" +#define NM_MODEM_STATE "state" +#define NM_MODEM_DEVICE_ID "device-id" +#define NM_MODEM_SIM_ID "sim-id" + +/* Signals */ +#define NM_MODEM_PPP_STATS "ppp-stats" +#define NM_MODEM_PPP_FAILED "ppp-failed" +#define NM_MODEM_PREPARE_RESULT "prepare-result" +#define NM_MODEM_IP4_CONFIG_RESULT "ip4-config-result" +#define NM_MODEM_AUTH_REQUESTED "auth-requested" +#define NM_MODEM_AUTH_RESULT "auth-result" +#define NM_MODEM_REMOVED "removed" +#define NM_MODEM_STATE_CHANGED "state-changed" + +#define MM_MODEM_IP_METHOD_PPP 0 +#define MM_MODEM_IP_METHOD_STATIC 1 +#define MM_MODEM_IP_METHOD_DHCP 2 + +typedef enum { + NM_MODEM_ERROR_CONNECTION_NOT_GSM, /*< nick=ConnectionNotGsm >*/ + NM_MODEM_ERROR_CONNECTION_NOT_CDMA, /*< nick=ConnectionNotCdma >*/ + NM_MODEM_ERROR_CONNECTION_INVALID, /*< nick=ConnectionInvalid >*/ + NM_MODEM_ERROR_CONNECTION_INCOMPATIBLE, /*< nick=ConnectionIncompatible >*/ + NM_MODEM_ERROR_INITIALIZATION_FAILED, /*< nick=InitializationFailed >*/ +} NMModemError; + +typedef enum { /*< underscore_name=nm_modem_state >*/ + NM_MODEM_STATE_UNKNOWN = 0, + NM_MODEM_STATE_FAILED = 1, + NM_MODEM_STATE_INITIALIZING = 2, + NM_MODEM_STATE_LOCKED = 3, + NM_MODEM_STATE_DISABLED = 4, + NM_MODEM_STATE_DISABLING = 5, + NM_MODEM_STATE_ENABLING = 6, + NM_MODEM_STATE_ENABLED = 7, + NM_MODEM_STATE_SEARCHING = 8, + NM_MODEM_STATE_REGISTERED = 9, + NM_MODEM_STATE_DISCONNECTING = 10, + NM_MODEM_STATE_CONNECTING = 11, + NM_MODEM_STATE_CONNECTED = 12, +} NMModemState; + +#define NM_MODEM_ERROR (nm_modem_error_quark ()) +GQuark nm_modem_error_quark (void); + + +typedef struct { + GObject parent; +} NMModem; + +typedef struct { + GObjectClass parent; + + void (*get_capabilities) (NMModem *self, + NMDeviceModemCapabilities *modem_caps, + NMDeviceModemCapabilities *current_caps); + + gboolean (*get_user_pass) (NMModem *modem, + NMConnection *connection, + const char **user, + const char **pass); + + gboolean (*check_connection_compatible) (NMModem *modem, + NMConnection *connection); + + gboolean (*complete_connection) (NMModem *modem, + NMConnection *connection, + const GSList *existing_connections, + GError **error); + + NMActStageReturn (*act_stage1_prepare) (NMModem *modem, + NMConnection *connection, + NMDeviceStateReason *reason); + + NMActStageReturn (*static_stage3_ip4_config_start) (NMModem *self, + NMActRequest *req, + NMDeviceStateReason *reason); + + void (*set_mm_enabled) (NMModem *self, gboolean enabled); + + void (*disconnect) (NMModem *self, gboolean warn); + + void (*deactivate) (NMModem *self, NMDevice *device); + + gboolean (*owns_port) (NMModem *self, const char *iface); + + /* Signals */ + void (*ppp_stats) (NMModem *self, guint32 in_bytes, guint32 out_bytes); + void (*ppp_failed) (NMModem *self, NMDeviceStateReason reason); + + void (*prepare_result) (NMModem *self, gboolean success, NMDeviceStateReason reason); + void (*ip4_config_result) (NMModem *self, NMIP4Config *config, GError *error); + + void (*auth_requested) (NMModem *self); + void (*auth_result) (NMModem *self, GError *error); + + void (*state_changed) (NMModem *self, + NMModemState new_state, + NMModemState old_state); + + void (*removed) (NMModem *self); +} NMModemClass; + +GType nm_modem_get_type (void); + +const char *nm_modem_get_path (NMModem *modem); +const char *nm_modem_get_uid (NMModem *modem); +const char *nm_modem_get_control_port (NMModem *modem); +const char *nm_modem_get_data_port (NMModem *modem); +const char *nm_modem_get_driver (NMModem *modem); + +gboolean nm_modem_owns_port (NMModem *modem, const char *iface); + +void nm_modem_get_capabilities (NMModem *self, + NMDeviceModemCapabilities *modem_caps, + NMDeviceModemCapabilities *current_caps); + +gboolean nm_modem_check_connection_compatible (NMModem *self, NMConnection *connection); + +gboolean nm_modem_complete_connection (NMModem *self, + NMConnection *connection, + const GSList *existing_connections, + GError **error); + +NMActStageReturn nm_modem_act_stage1_prepare (NMModem *modem, + NMActRequest *req, + NMDeviceStateReason *reason); + +NMActStageReturn nm_modem_act_stage2_config (NMModem *modem, + NMActRequest *req, + NMDeviceStateReason *reason); + +NMActStageReturn nm_modem_stage3_ip4_config_start (NMModem *modem, + NMDevice *device, + NMDeviceClass *device_class, + NMDeviceStateReason *reason); + +NMActStageReturn nm_modem_stage3_ip6_config_start (NMModem *modem, + NMDevice *device, + NMDeviceClass *device_class, + NMDeviceStateReason *reason); + +void nm_modem_ip4_pre_commit (NMModem *modem, NMDevice *device, NMIP4Config *config); + +gboolean nm_modem_get_secrets (NMModem *modem, + const char *setting_name, + gboolean request_new, + const char *hint); + +void nm_modem_deactivate (NMModem *modem, NMDevice *device); + +void nm_modem_device_state_changed (NMModem *modem, + NMDeviceState new_state, + NMDeviceState old_state, + NMDeviceStateReason reason); + +void nm_modem_set_mm_enabled (NMModem *self, gboolean enabled); + +NMModemState nm_modem_get_state (NMModem *self); +void nm_modem_set_state (NMModem *self, + NMModemState new_state, + const char *reason); +void nm_modem_set_prev_state (NMModem *self, const char *reason); +const char * nm_modem_state_to_string (NMModemState state); + +/* For the modem-manager only */ +void nm_modem_emit_removed (NMModem *self); + +G_END_DECLS + +#endif /* NM_MODEM_H */ diff --git a/src/devices/wwan/nm-wwan-factory.c b/src/devices/wwan/nm-wwan-factory.c new file mode 100644 index 00000000..b1e2307e --- /dev/null +++ b/src/devices/wwan/nm-wwan-factory.c @@ -0,0 +1,136 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2014 Red Hat, Inc. + */ + +#include +#include + +#include "config.h" +#include "nm-device-factory.h" +#include "nm-wwan-factory.h" +#include "nm-modem-manager.h" +#include "nm-device-modem.h" +#include "nm-logging.h" + +static GType nm_wwan_factory_get_type (void); + +static void device_factory_interface_init (NMDeviceFactory *factory_iface); + +G_DEFINE_TYPE_EXTENDED (NMWwanFactory, nm_wwan_factory, G_TYPE_OBJECT, 0, + G_IMPLEMENT_INTERFACE (NM_TYPE_DEVICE_FACTORY, device_factory_interface_init)) + +#define NM_WWAN_FACTORY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_WWAN_FACTORY, NMWwanFactoryPrivate)) + +typedef struct { + NMModemManager *mm; +} NMWwanFactoryPrivate; + +/************************************************************************/ + +#define PLUGIN_TYPE NM_DEVICE_TYPE_MODEM + +G_MODULE_EXPORT NMDeviceFactory * +nm_device_factory_create (GError **error) +{ + return (NMDeviceFactory *) g_object_new (NM_TYPE_WWAN_FACTORY, NULL); +} + +G_MODULE_EXPORT NMDeviceType +nm_device_factory_get_device_type (void) +{ + return PLUGIN_TYPE; +} + +/************************************************************************/ + +static void +modem_added_cb (NMModemManager *manager, + NMModem *modem, + gpointer user_data) +{ + NMWwanFactory *self = NM_WWAN_FACTORY (user_data); + NMDevice *device; + const char *driver, *port; + + /* Do nothing if the modem was consumed by some other plugin */ + if (nm_device_factory_emit_component_added (NM_DEVICE_FACTORY (self), G_OBJECT (modem))) + return; + + driver = nm_modem_get_driver (modem); + + /* If it was a Bluetooth modem and no bluetooth device claimed it, ignore + * it. The rfcomm port (and thus the modem) gets created automatically + * by the Bluetooth code during the connection process. + */ + if (driver && strstr (driver, "bluetooth")) { + port = nm_modem_get_data_port (modem); + if (!port) + port = nm_modem_get_control_port (modem); + nm_log_info (LOGD_MB, "ignoring modem '%s' (no associated Bluetooth device)", port); + return; + } + + /* Make the new modem device */ + device = nm_device_modem_new (modem); + g_assert (device); + g_signal_emit_by_name (self, NM_DEVICE_FACTORY_DEVICE_ADDED, device); + g_object_unref (device); +} + +static void +nm_wwan_factory_init (NMWwanFactory *self) +{ + NMWwanFactoryPrivate *priv = NM_WWAN_FACTORY_GET_PRIVATE (self); + + priv->mm = g_object_new (NM_TYPE_MODEM_MANAGER, NULL); + g_assert (priv->mm); + g_signal_connect (priv->mm, + NM_MODEM_MANAGER_MODEM_ADDED, + G_CALLBACK (modem_added_cb), + self); +} + +static void +device_factory_interface_init (NMDeviceFactory *factory_iface) +{ +} + +static void +dispose (GObject *object) +{ + NMWwanFactory *self = NM_WWAN_FACTORY (object); + NMWwanFactoryPrivate *priv = NM_WWAN_FACTORY_GET_PRIVATE (self); + + if (priv->mm) + g_signal_handlers_disconnect_by_func (priv->mm, modem_added_cb, self); + g_clear_object (&priv->mm); + + /* Chain up to the parent class */ + G_OBJECT_CLASS (nm_wwan_factory_parent_class)->dispose (object); +} + +static void +nm_wwan_factory_class_init (NMWwanFactoryClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (NMWwanFactoryPrivate)); + + object_class->dispose = dispose; +} diff --git a/src/devices/wwan/nm-wwan-factory.h b/src/devices/wwan/nm-wwan-factory.h new file mode 100644 index 00000000..b7aee01f --- /dev/null +++ b/src/devices/wwan/nm-wwan-factory.h @@ -0,0 +1,37 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2014 Red Hat, Inc. + */ + +#ifndef NM_WWAN_FACTORY_H +#define NM_WWAN_FACTORY_H + +#include + +#define NM_TYPE_WWAN_FACTORY (nm_wwan_factory_get_type ()) +#define NM_WWAN_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_WWAN_FACTORY, NMWwanFactory)) + +typedef struct { + GObject parent; +} NMWwanFactory; + +typedef struct { + GObjectClass parent; +} NMWwanFactoryClass; + +#endif /* NM_WWAN_FACTORY_H */ diff --git a/src/devices/wwan/wwan-exports.ver b/src/devices/wwan/wwan-exports.ver new file mode 100644 index 00000000..dc505d17 --- /dev/null +++ b/src/devices/wwan/wwan-exports.ver @@ -0,0 +1,28 @@ +{ +global: + nm_modem_act_stage1_prepare; + nm_modem_act_stage2_config; + nm_modem_check_connection_compatible; + nm_modem_complete_connection; + nm_modem_deactivate; + nm_modem_device_state_changed; + nm_modem_error_quark; + nm_modem_get_capabilities; + nm_modem_get_control_port; + nm_modem_get_data_port; + nm_modem_get_driver; + nm_modem_get_path; + nm_modem_get_secrets; + nm_modem_get_state; + nm_modem_get_type; + nm_modem_get_uid; + nm_modem_ip4_pre_commit; + nm_modem_manager_get_type; + nm_modem_owns_port; + nm_modem_set_mm_enabled; + nm_modem_stage3_ip4_config_start; + nm_modem_stage3_ip6_config_start; + nm_modem_state_to_string; +local: + *; +}; diff --git a/src/dhcp-manager/Makefile.am b/src/dhcp-manager/Makefile.am index f32a2167..63eac9d5 100644 --- a/src/dhcp-manager/Makefile.am +++ b/src/dhcp-manager/Makefile.am @@ -1,71 +1,23 @@ -SUBDIRS = . tests +libexec_PROGRAMS = nm-dhcp-helper -AM_CPPFLAGS = \ - -I${top_srcdir} \ - -I${top_builddir}/include \ - -I${top_srcdir}/include \ - -I${top_builddir}/src/generated \ - -I${top_srcdir}/src/generated \ - -I${top_srcdir}/src/logging \ - -I${top_srcdir}/src/posix-signals \ - -I${top_builddir}/libnm-util \ - -I${top_srcdir}/libnm-util \ - -I${top_srcdir}/src \ - -DRUNDIR=\"$(rundir)\" +nm_dhcp_helper_SOURCES = nm-dhcp-helper.c -noinst_LTLIBRARIES = libdhcp-manager.la libdhcp-dhclient.la - -################## dhclient ################## - -libdhcp_dhclient_la_SOURCES = \ - nm-dhcp-dhclient-utils.h \ - nm-dhcp-dhclient-utils.c \ - nm-dhcp-dhclient.h \ - nm-dhcp-dhclient.c - -libdhcp_dhclient_la_CPPFLAGS = \ +nm_dhcp_helper_CPPFLAGS = \ $(DBUS_CFLAGS) \ - $(GLIB_CFLAGS) \ - $(AM_CPPFLAGS) \ - -DSYSCONFDIR=\"$(sysconfdir)\" \ - -DLIBEXECDIR=\"$(libexecdir)\" \ - -DLOCALSTATEDIR=\"$(localstatedir)\" \ - -DDHCLIENT_PATH=\"$(DHCLIENT_PATH)\" \ - -DNMSTATEDIR=\"$(nmstatedir)\" \ - -DNMCONFDIR=\"$(nmconfdir)\" + -DG_LOG_DOMAIN=\""nm-dhcp-helper"\" \ + -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \ + -DNMRUNDIR=\"$(nmrundir)\" -libdhcp_dhclient_la_LIBADD = \ - $(top_builddir)/src/logging/libnm-logging.la \ - $(top_builddir)/src/posix-signals/libnm-posix-signals.la \ - $(top_builddir)/libnm-util/libnm-util.la \ - $(DBUS_LIBS) \ - $(GLIB_LIBS) +nm_dhcp_helper_LDADD = $(DBUS_LIBS) -################## main lib ################## -libdhcp_manager_la_SOURCES = \ - nm-dhcp-client.c \ - nm-dhcp-client.h \ - nm-dhcp-manager.c \ - nm-dhcp-manager.h \ - nm-dhcp-dhcpcd.h \ - nm-dhcp-dhcpcd.c +# FIXME: remove when dbus-glib >= 0.100 is required +dhcp_helper_conf = nm-dhcp-helper.conf -libdhcp_manager_la_CPPFLAGS = \ - $(DBUS_CFLAGS) \ - $(GLIB_CFLAGS) \ - $(AM_CPPFLAGS) \ - -DSYSCONFDIR=\"$(sysconfdir)\" \ - -DLIBEXECDIR=\"$(libexecdir)\" \ - -DLOCALSTATEDIR=\"$(localstatedir)\" \ - -DDHCLIENT_PATH=\"$(DHCLIENT_PATH)\" \ - -DDHCPCD_PATH=\"$(DHCPCD_PATH)\" \ - -DNMSTATEDIR=\"$(nmstatedir)\" +if !HAVE_DBUS_GLIB_100 +dbusservicedir = $(DBUS_SYS_DIR) +dbusservice_DATA = $(dhcp_helper_conf) +endif -libdhcp_manager_la_LIBADD = \ - $(top_builddir)/src/logging/libnm-logging.la \ - $(top_builddir)/src/posix-signals/libnm-posix-signals.la \ - $(builddir)/libdhcp-dhclient.la \ - $(DBUS_LIBS) \ - $(GLIB_LIBS) +EXTRA_DIST = $(dhcp_helper_conf) diff --git a/src/dhcp-manager/Makefile.in b/src/dhcp-manager/Makefile.in index db4b0c91..5495b12f 100644 --- a/src/dhcp-manager/Makefile.in +++ b/src/dhcp-manager/Makefile.in @@ -14,6 +14,7 @@ @SET_MAKE@ + VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ @@ -78,11 +79,13 @@ PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ +libexec_PROGRAMS = nm-dhcp-helper$(EXEEXT) subdir = src/dhcp-manager DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/build-aux/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \ +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_lib_readline.m4 \ + $(top_srcdir)/m4/compiler_warnings.m4 \ $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/gnome-code-coverage.m4 \ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ @@ -100,30 +103,17 @@ mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = -LTLIBRARIES = $(noinst_LTLIBRARIES) +am__installdirs = "$(DESTDIR)$(libexecdir)" \ + "$(DESTDIR)$(dbusservicedir)" +PROGRAMS = $(libexec_PROGRAMS) +am_nm_dhcp_helper_OBJECTS = nm_dhcp_helper-nm-dhcp-helper.$(OBJEXT) +nm_dhcp_helper_OBJECTS = $(am_nm_dhcp_helper_OBJECTS) am__DEPENDENCIES_1 = -libdhcp_dhclient_la_DEPENDENCIES = \ - $(top_builddir)/src/logging/libnm-logging.la \ - $(top_builddir)/src/posix-signals/libnm-posix-signals.la \ - $(top_builddir)/libnm-util/libnm-util.la $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) -am_libdhcp_dhclient_la_OBJECTS = \ - libdhcp_dhclient_la-nm-dhcp-dhclient-utils.lo \ - libdhcp_dhclient_la-nm-dhcp-dhclient.lo -libdhcp_dhclient_la_OBJECTS = $(am_libdhcp_dhclient_la_OBJECTS) +nm_dhcp_helper_DEPENDENCIES = $(am__DEPENDENCIES_1) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = -libdhcp_manager_la_DEPENDENCIES = \ - $(top_builddir)/src/logging/libnm-logging.la \ - $(top_builddir)/src/posix-signals/libnm-posix-signals.la \ - $(builddir)/libdhcp-dhclient.la $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) -am_libdhcp_manager_la_OBJECTS = libdhcp_manager_la-nm-dhcp-client.lo \ - libdhcp_manager_la-nm-dhcp-manager.lo \ - libdhcp_manager_la-nm-dhcp-dhcpcd.lo -libdhcp_manager_la_OBJECTS = $(am_libdhcp_manager_la_OBJECTS) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false @@ -158,30 +148,41 @@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = -SOURCES = $(libdhcp_dhclient_la_SOURCES) $(libdhcp_manager_la_SOURCES) -DIST_SOURCES = $(libdhcp_dhclient_la_SOURCES) \ - $(libdhcp_manager_la_SOURCES) -RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ - ctags-recursive dvi-recursive html-recursive info-recursive \ - install-data-recursive install-dvi-recursive \ - install-exec-recursive install-html-recursive \ - install-info-recursive install-pdf-recursive \ - install-ps-recursive install-recursive installcheck-recursive \ - installdirs-recursive pdf-recursive ps-recursive \ - tags-recursive uninstall-recursive +SOURCES = $(nm_dhcp_helper_SOURCES) +DIST_SOURCES = $(nm_dhcp_helper_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac -RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ - distclean-recursive maintainer-clean-recursive -am__recursive_targets = \ - $(RECURSIVE_TARGETS) \ - $(RECURSIVE_CLEAN_TARGETS) \ - $(am__extra_recursive_targets) -AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ - distdir +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +DATA = $(dbusservice_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is @@ -201,33 +202,7 @@ am__define_uniq_tagged_files = \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags -DIST_SUBDIRS = $(SUBDIRS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -am__relativize = \ - dir0=`pwd`; \ - sed_first='s,^\([^/]*\)/.*$$,\1,'; \ - sed_rest='s,^[^/]*/*,,'; \ - sed_last='s,^.*/\([^/]*\)$$,\1,'; \ - sed_butlast='s,/*[^/]*$$,,'; \ - while test -n "$$dir1"; do \ - first=`echo "$$dir1" | sed -e "$$sed_first"`; \ - if test "$$first" != "."; then \ - if test "$$first" = ".."; then \ - dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ - dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ - else \ - first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ - if test "$$first2" = "$$first"; then \ - dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ - else \ - dir2="../$$dir2"; \ - fi; \ - dir0="$$dir0"/"$$first"; \ - fi; \ - fi; \ - dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ - done; \ - reldir="$$dir2" ACLOCAL = @ACLOCAL@ ALL_LINGUAS = @ALL_LINGUAS@ AMTAR = @AMTAR@ @@ -253,12 +228,15 @@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIRNAME = @DATADIRNAME@ DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_100_CFLAGS = @DBUS_GLIB_100_CFLAGS@ +DBUS_GLIB_100_LIBS = @DBUS_GLIB_100_LIBS@ DBUS_LIBS = @DBUS_LIBS@ DBUS_SYS_DIR = @DBUS_SYS_DIR@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DHCLIENT_PATH = @DHCLIENT_PATH@ DHCPCD_PATH = @DHCPCD_PATH@ +DISTRO_NETWORK_SERVICE = @DISTRO_NETWORK_SERVICE@ DLLTOOL = @DLLTOOL@ DNSMASQ_PATH = @DNSMASQ_PATH@ DSYMUTIL = @DSYMUTIL@ @@ -283,7 +261,6 @@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ GTKDOC_CHECK = @GTKDOC_CHECK@ -GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ GTKDOC_MKPDF = @GTKDOC_MKPDF@ @@ -328,12 +305,16 @@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ +LIBNDP_CFLAGS = @LIBNDP_CFLAGS@ +LIBNDP_LIBS = @LIBNDP_LIBS@ LIBNL_CFLAGS = @LIBNL_CFLAGS@ LIBNL_LIBS = @LIBNL_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@ LIBSOUP_LIBS = @LIBSOUP_LIBS@ +LIBTEAMDCTL_CFLAGS = @LIBTEAMDCTL_CFLAGS@ +LIBTEAMDCTL_LIBS = @LIBTEAMDCTL_LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ @@ -350,6 +331,8 @@ MOC = @MOC@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ +NEWT_CFLAGS = @NEWT_CFLAGS@ +NEWT_LIBS = @NEWT_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ @@ -377,11 +360,16 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ POLKIT_CFLAGS = @POLKIT_CFLAGS@ POLKIT_LIBS = @POLKIT_LIBS@ POSUB = @POSUB@ +PPPD_PATH = @PPPD_PATH@ PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@ +PPPOE_PATH = @PPPOE_PATH@ QT_CFLAGS = @QT_CFLAGS@ QT_LIBS = @QT_LIBS@ RANLIB = @RANLIB@ +READLINE_LIBS = @READLINE_LIBS@ SED = @SED@ +SELINUX_CFLAGS = @SELINUX_CFLAGS@ +SELINUX_LIBS = @SELINUX_LIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ @@ -396,6 +384,7 @@ UDEV_BASE_DIR = @UDEV_BASE_DIR@ USE_NLS = @USE_NLS@ UUID_CFLAGS = @UUID_CFLAGS@ UUID_LIBS = @UUID_LIBS@ +VALGRIND_RULES = @VALGRIND_RULES@ VAPIGEN = @VAPIGEN@ VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ @@ -458,6 +447,7 @@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ +subdirs = @subdirs@ sysconfdir = @sysconfdir@ systemdsystemunitdir = @systemdsystemunitdir@ target_alias = @target_alias@ @@ -468,76 +458,22 @@ with_dhclient = @with_dhclient@ with_dhcpcd = @with_dhcpcd@ with_netconfig = @with_netconfig@ with_resolvconf = @with_resolvconf@ -SUBDIRS = . tests -AM_CPPFLAGS = \ - -I${top_srcdir} \ - -I${top_builddir}/include \ - -I${top_srcdir}/include \ - -I${top_builddir}/src/generated \ - -I${top_srcdir}/src/generated \ - -I${top_srcdir}/src/logging \ - -I${top_srcdir}/src/posix-signals \ - -I${top_builddir}/libnm-util \ - -I${top_srcdir}/libnm-util \ - -I${top_srcdir}/src \ - -DRUNDIR=\"$(rundir)\" - -noinst_LTLIBRARIES = libdhcp-manager.la libdhcp-dhclient.la - -################## dhclient ################## -libdhcp_dhclient_la_SOURCES = \ - nm-dhcp-dhclient-utils.h \ - nm-dhcp-dhclient-utils.c \ - nm-dhcp-dhclient.h \ - nm-dhcp-dhclient.c - -libdhcp_dhclient_la_CPPFLAGS = \ +with_valgrind = @with_valgrind@ +nm_dhcp_helper_SOURCES = nm-dhcp-helper.c +nm_dhcp_helper_CPPFLAGS = \ $(DBUS_CFLAGS) \ - $(GLIB_CFLAGS) \ - $(AM_CPPFLAGS) \ - -DSYSCONFDIR=\"$(sysconfdir)\" \ - -DLIBEXECDIR=\"$(libexecdir)\" \ - -DLOCALSTATEDIR=\"$(localstatedir)\" \ - -DDHCLIENT_PATH=\"$(DHCLIENT_PATH)\" \ - -DNMSTATEDIR=\"$(nmstatedir)\" \ - -DNMCONFDIR=\"$(nmconfdir)\" - -libdhcp_dhclient_la_LIBADD = \ - $(top_builddir)/src/logging/libnm-logging.la \ - $(top_builddir)/src/posix-signals/libnm-posix-signals.la \ - $(top_builddir)/libnm-util/libnm-util.la \ - $(DBUS_LIBS) \ - $(GLIB_LIBS) - - -################## main lib ################## -libdhcp_manager_la_SOURCES = \ - nm-dhcp-client.c \ - nm-dhcp-client.h \ - nm-dhcp-manager.c \ - nm-dhcp-manager.h \ - nm-dhcp-dhcpcd.h \ - nm-dhcp-dhcpcd.c - -libdhcp_manager_la_CPPFLAGS = \ - $(DBUS_CFLAGS) \ - $(GLIB_CFLAGS) \ - $(AM_CPPFLAGS) \ - -DSYSCONFDIR=\"$(sysconfdir)\" \ - -DLIBEXECDIR=\"$(libexecdir)\" \ - -DLOCALSTATEDIR=\"$(localstatedir)\" \ - -DDHCLIENT_PATH=\"$(DHCLIENT_PATH)\" \ - -DDHCPCD_PATH=\"$(DHCPCD_PATH)\" \ - -DNMSTATEDIR=\"$(nmstatedir)\" - -libdhcp_manager_la_LIBADD = \ - $(top_builddir)/src/logging/libnm-logging.la \ - $(top_builddir)/src/posix-signals/libnm-posix-signals.la \ - $(builddir)/libdhcp-dhclient.la \ - $(DBUS_LIBS) \ - $(GLIB_LIBS) - -all: all-recursive + -DG_LOG_DOMAIN=\""nm-dhcp-helper"\" \ + -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \ + -DNMRUNDIR=\"$(nmrundir)\" + +nm_dhcp_helper_LDADD = $(DBUS_LIBS) + +# FIXME: remove when dbus-glib >= 0.100 is required +dhcp_helper_conf = nm-dhcp-helper.conf +@HAVE_DBUS_GLIB_100_FALSE@dbusservicedir = $(DBUS_SYS_DIR) +@HAVE_DBUS_GLIB_100_FALSE@dbusservice_DATA = $(dhcp_helper_conf) +EXTRA_DIST = $(dhcp_helper_conf) +all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj @@ -571,23 +507,59 @@ $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): - -clean-noinstLTLIBRARIES: - -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) - @list='$(noinst_LTLIBRARIES)'; \ - locs=`for p in $$list; do echo $$p; done | \ - sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ - sort -u`; \ - test -z "$$locs" || { \ - echo rm -f $${locs}; \ - rm -f $${locs}; \ - } - -libdhcp-dhclient.la: $(libdhcp_dhclient_la_OBJECTS) $(libdhcp_dhclient_la_DEPENDENCIES) $(EXTRA_libdhcp_dhclient_la_DEPENDENCIES) - $(AM_V_CCLD)$(LINK) $(libdhcp_dhclient_la_OBJECTS) $(libdhcp_dhclient_la_LIBADD) $(LIBS) - -libdhcp-manager.la: $(libdhcp_manager_la_OBJECTS) $(libdhcp_manager_la_DEPENDENCIES) $(EXTRA_libdhcp_manager_la_DEPENDENCIES) - $(AM_V_CCLD)$(LINK) $(libdhcp_manager_la_OBJECTS) $(libdhcp_manager_la_LIBADD) $(LIBS) +install-libexecPROGRAMS: $(libexec_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(libexecdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libexecdir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + || test -f $$p1 \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-libexecPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(libexecdir)" && rm -f $$files + +clean-libexecPROGRAMS: + @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +nm-dhcp-helper$(EXEEXT): $(nm_dhcp_helper_OBJECTS) $(nm_dhcp_helper_DEPENDENCIES) $(EXTRA_nm_dhcp_helper_DEPENDENCIES) + @rm -f nm-dhcp-helper$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(nm_dhcp_helper_OBJECTS) $(nm_dhcp_helper_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) @@ -595,11 +567,7 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdhcp_dhclient_la-nm-dhcp-dhclient-utils.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdhcp_dhclient_la-nm-dhcp-dhclient.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdhcp_manager_la-nm-dhcp-client.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdhcp_manager_la-nm-dhcp-dhcpcd.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdhcp_manager_la-nm-dhcp-manager.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm_dhcp_helper-nm-dhcp-helper.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @@ -622,102 +590,55 @@ distclean-compile: @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< -libdhcp_dhclient_la-nm-dhcp-dhclient-utils.lo: nm-dhcp-dhclient-utils.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdhcp_dhclient_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libdhcp_dhclient_la-nm-dhcp-dhclient-utils.lo -MD -MP -MF $(DEPDIR)/libdhcp_dhclient_la-nm-dhcp-dhclient-utils.Tpo -c -o libdhcp_dhclient_la-nm-dhcp-dhclient-utils.lo `test -f 'nm-dhcp-dhclient-utils.c' || echo '$(srcdir)/'`nm-dhcp-dhclient-utils.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdhcp_dhclient_la-nm-dhcp-dhclient-utils.Tpo $(DEPDIR)/libdhcp_dhclient_la-nm-dhcp-dhclient-utils.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-dhcp-dhclient-utils.c' object='libdhcp_dhclient_la-nm-dhcp-dhclient-utils.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdhcp_dhclient_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libdhcp_dhclient_la-nm-dhcp-dhclient-utils.lo `test -f 'nm-dhcp-dhclient-utils.c' || echo '$(srcdir)/'`nm-dhcp-dhclient-utils.c - -libdhcp_dhclient_la-nm-dhcp-dhclient.lo: nm-dhcp-dhclient.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdhcp_dhclient_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libdhcp_dhclient_la-nm-dhcp-dhclient.lo -MD -MP -MF $(DEPDIR)/libdhcp_dhclient_la-nm-dhcp-dhclient.Tpo -c -o libdhcp_dhclient_la-nm-dhcp-dhclient.lo `test -f 'nm-dhcp-dhclient.c' || echo '$(srcdir)/'`nm-dhcp-dhclient.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdhcp_dhclient_la-nm-dhcp-dhclient.Tpo $(DEPDIR)/libdhcp_dhclient_la-nm-dhcp-dhclient.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-dhcp-dhclient.c' object='libdhcp_dhclient_la-nm-dhcp-dhclient.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdhcp_dhclient_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libdhcp_dhclient_la-nm-dhcp-dhclient.lo `test -f 'nm-dhcp-dhclient.c' || echo '$(srcdir)/'`nm-dhcp-dhclient.c - -libdhcp_manager_la-nm-dhcp-client.lo: nm-dhcp-client.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdhcp_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libdhcp_manager_la-nm-dhcp-client.lo -MD -MP -MF $(DEPDIR)/libdhcp_manager_la-nm-dhcp-client.Tpo -c -o libdhcp_manager_la-nm-dhcp-client.lo `test -f 'nm-dhcp-client.c' || echo '$(srcdir)/'`nm-dhcp-client.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdhcp_manager_la-nm-dhcp-client.Tpo $(DEPDIR)/libdhcp_manager_la-nm-dhcp-client.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-dhcp-client.c' object='libdhcp_manager_la-nm-dhcp-client.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdhcp_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libdhcp_manager_la-nm-dhcp-client.lo `test -f 'nm-dhcp-client.c' || echo '$(srcdir)/'`nm-dhcp-client.c - -libdhcp_manager_la-nm-dhcp-manager.lo: nm-dhcp-manager.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdhcp_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libdhcp_manager_la-nm-dhcp-manager.lo -MD -MP -MF $(DEPDIR)/libdhcp_manager_la-nm-dhcp-manager.Tpo -c -o libdhcp_manager_la-nm-dhcp-manager.lo `test -f 'nm-dhcp-manager.c' || echo '$(srcdir)/'`nm-dhcp-manager.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdhcp_manager_la-nm-dhcp-manager.Tpo $(DEPDIR)/libdhcp_manager_la-nm-dhcp-manager.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-dhcp-manager.c' object='libdhcp_manager_la-nm-dhcp-manager.lo' libtool=yes @AMDEPBACKSLASH@ +nm_dhcp_helper-nm-dhcp-helper.o: nm-dhcp-helper.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(nm_dhcp_helper_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm_dhcp_helper-nm-dhcp-helper.o -MD -MP -MF $(DEPDIR)/nm_dhcp_helper-nm-dhcp-helper.Tpo -c -o nm_dhcp_helper-nm-dhcp-helper.o `test -f 'nm-dhcp-helper.c' || echo '$(srcdir)/'`nm-dhcp-helper.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm_dhcp_helper-nm-dhcp-helper.Tpo $(DEPDIR)/nm_dhcp_helper-nm-dhcp-helper.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-dhcp-helper.c' object='nm_dhcp_helper-nm-dhcp-helper.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdhcp_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libdhcp_manager_la-nm-dhcp-manager.lo `test -f 'nm-dhcp-manager.c' || echo '$(srcdir)/'`nm-dhcp-manager.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(nm_dhcp_helper_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm_dhcp_helper-nm-dhcp-helper.o `test -f 'nm-dhcp-helper.c' || echo '$(srcdir)/'`nm-dhcp-helper.c -libdhcp_manager_la-nm-dhcp-dhcpcd.lo: nm-dhcp-dhcpcd.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdhcp_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libdhcp_manager_la-nm-dhcp-dhcpcd.lo -MD -MP -MF $(DEPDIR)/libdhcp_manager_la-nm-dhcp-dhcpcd.Tpo -c -o libdhcp_manager_la-nm-dhcp-dhcpcd.lo `test -f 'nm-dhcp-dhcpcd.c' || echo '$(srcdir)/'`nm-dhcp-dhcpcd.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdhcp_manager_la-nm-dhcp-dhcpcd.Tpo $(DEPDIR)/libdhcp_manager_la-nm-dhcp-dhcpcd.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-dhcp-dhcpcd.c' object='libdhcp_manager_la-nm-dhcp-dhcpcd.lo' libtool=yes @AMDEPBACKSLASH@ +nm_dhcp_helper-nm-dhcp-helper.obj: nm-dhcp-helper.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(nm_dhcp_helper_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm_dhcp_helper-nm-dhcp-helper.obj -MD -MP -MF $(DEPDIR)/nm_dhcp_helper-nm-dhcp-helper.Tpo -c -o nm_dhcp_helper-nm-dhcp-helper.obj `if test -f 'nm-dhcp-helper.c'; then $(CYGPATH_W) 'nm-dhcp-helper.c'; else $(CYGPATH_W) '$(srcdir)/nm-dhcp-helper.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm_dhcp_helper-nm-dhcp-helper.Tpo $(DEPDIR)/nm_dhcp_helper-nm-dhcp-helper.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-dhcp-helper.c' object='nm_dhcp_helper-nm-dhcp-helper.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdhcp_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libdhcp_manager_la-nm-dhcp-dhcpcd.lo `test -f 'nm-dhcp-dhcpcd.c' || echo '$(srcdir)/'`nm-dhcp-dhcpcd.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(nm_dhcp_helper_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm_dhcp_helper-nm-dhcp-helper.obj `if test -f 'nm-dhcp-helper.c'; then $(CYGPATH_W) 'nm-dhcp-helper.c'; else $(CYGPATH_W) '$(srcdir)/nm-dhcp-helper.c'; fi` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs - -# This directory's subdirectories are mostly independent; you can cd -# into them and run 'make' without going through this Makefile. -# To change the values of 'make' variables: instead of editing Makefiles, -# (1) if the variable is set in 'config.status', edit 'config.status' -# (which will cause the Makefiles to be regenerated when you run 'make'); -# (2) otherwise, pass the desired values on the 'make' command line. -$(am__recursive_targets): - @fail=; \ - if $(am__make_keepgoing); then \ - failcom='fail=yes'; \ - else \ - failcom='exit 1'; \ +install-dbusserviceDATA: $(dbusservice_DATA) + @$(NORMAL_INSTALL) + @list='$(dbusservice_DATA)'; test -n "$(dbusservicedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(dbusservicedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(dbusservicedir)" || exit 1; \ fi; \ - dot_seen=no; \ - target=`echo $@ | sed s/-recursive//`; \ - case "$@" in \ - distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ - *) list='$(SUBDIRS)' ;; \ - esac; \ - for subdir in $$list; do \ - echo "Making $$target in $$subdir"; \ - if test "$$subdir" = "."; then \ - dot_seen=yes; \ - local_target="$$target-am"; \ - else \ - local_target="$$target"; \ - fi; \ - ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ - || eval $$failcom; \ - done; \ - if test "$$dot_seen" = "no"; then \ - $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ - fi; test -z "$$fail" + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(dbusservicedir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(dbusservicedir)" || exit $$?; \ + done + +uninstall-dbusserviceDATA: + @$(NORMAL_UNINSTALL) + @list='$(dbusservice_DATA)'; test -n "$(dbusservicedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(dbusservicedir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique -tags: tags-recursive +tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ - if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ - include_option=--etags-include; \ - empty_fix=.; \ - else \ - include_option=--include; \ - empty_fix=; \ - fi; \ - list='$(SUBDIRS)'; for subdir in $$list; do \ - if test "$$subdir" = .; then :; else \ - test ! -f $$subdir/TAGS || \ - set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ - fi; \ - done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ @@ -730,7 +651,7 @@ tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $$unique; \ fi; \ fi -ctags: ctags-recursive +ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) @@ -743,7 +664,7 @@ GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" -cscopelist: cscopelist-recursive +cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ @@ -792,45 +713,22 @@ distdir: $(DISTFILES) || exit 1; \ fi; \ done - @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ - if test "$$subdir" = .; then :; else \ - $(am__make_dryrun) \ - || test -d "$(distdir)/$$subdir" \ - || $(MKDIR_P) "$(distdir)/$$subdir" \ - || exit 1; \ - dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ - $(am__relativize); \ - new_distdir=$$reldir; \ - dir1=$$subdir; dir2="$(top_distdir)"; \ - $(am__relativize); \ - new_top_distdir=$$reldir; \ - echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ - echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ - ($(am__cd) $$subdir && \ - $(MAKE) $(AM_MAKEFLAGS) \ - top_distdir="$$new_top_distdir" \ - distdir="$$new_distdir" \ - am__remove_distdir=: \ - am__skip_length_check=: \ - am__skip_mode_fix=: \ - distdir) \ - || exit 1; \ - fi; \ - done check-am: all-am -check: check-recursive -all-am: Makefile $(LTLIBRARIES) -installdirs: installdirs-recursive -installdirs-am: -install: install-recursive -install-exec: install-exec-recursive -install-data: install-data-recursive -uninstall: uninstall-recursive +check: check-am +all-am: Makefile $(PROGRAMS) $(DATA) +installdirs: + for dir in "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(dbusservicedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am -installcheck: installcheck-recursive +installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ @@ -852,93 +750,94 @@ distclean-generic: maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -clean: clean-recursive +clean: clean-am -clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ +clean-am: clean-generic clean-libexecPROGRAMS clean-libtool \ mostlyclean-am -distclean: distclean-recursive +distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags -dvi: dvi-recursive +dvi: dvi-am dvi-am: -html: html-recursive +html: html-am html-am: -info: info-recursive +info: info-am info-am: -install-data-am: +install-data-am: install-dbusserviceDATA -install-dvi: install-dvi-recursive +install-dvi: install-dvi-am install-dvi-am: -install-exec-am: +install-exec-am: install-libexecPROGRAMS -install-html: install-html-recursive +install-html: install-html-am install-html-am: -install-info: install-info-recursive +install-info: install-info-am install-info-am: install-man: -install-pdf: install-pdf-recursive +install-pdf: install-pdf-am install-pdf-am: -install-ps: install-ps-recursive +install-ps: install-ps-am install-ps-am: installcheck-am: -maintainer-clean: maintainer-clean-recursive +maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic -mostlyclean: mostlyclean-recursive +mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool -pdf: pdf-recursive +pdf: pdf-am pdf-am: -ps: ps-recursive +ps: ps-am ps-am: -uninstall-am: +uninstall-am: uninstall-dbusserviceDATA uninstall-libexecPROGRAMS -.MAKE: $(am__recursive_targets) install-am install-strip +.MAKE: install-am install-strip -.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ - check-am clean clean-generic clean-libtool \ - clean-noinstLTLIBRARIES cscopelist-am ctags ctags-am distclean \ - distclean-compile distclean-generic distclean-libtool \ - distclean-tags distdir dvi dvi-am html html-am info info-am \ - install install-am install-data install-data-am install-dvi \ +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libexecPROGRAMS clean-libtool cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dbusserviceDATA install-dvi \ install-dvi-am install-exec install-exec-am install-html \ - install-html-am install-info install-info-am install-man \ - install-pdf install-pdf-am install-ps install-ps-am \ - install-strip installcheck installcheck-am installdirs \ - installdirs-am maintainer-clean maintainer-clean-generic \ - mostlyclean mostlyclean-compile mostlyclean-generic \ - mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ - uninstall-am + install-html-am install-info install-info-am \ + install-libexecPROGRAMS install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am uninstall-dbusserviceDATA \ + uninstall-libexecPROGRAMS # Tell versions [3.59,3.63) of GNU make to not export all variables. diff --git a/src/dhcp-manager/nm-dhcp-client.c b/src/dhcp-manager/nm-dhcp-client.c index 980fcab8..03c11c74 100644 --- a/src/dhcp-manager/nm-dhcp-client.c +++ b/src/dhcp-manager/nm-dhcp-client.c @@ -28,6 +28,7 @@ #include #include +#include "NetworkManagerUtils.h" #include "nm-utils.h" #include "nm-logging.h" #include "nm-dbus-glib-types.h" @@ -38,6 +39,7 @@ typedef struct { GByteArray * hwaddr; gboolean ipv6; char * uuid; + guint priority; guint32 timeout; GByteArray * duid; @@ -57,9 +59,9 @@ typedef struct { G_DEFINE_TYPE_EXTENDED (NMDHCPClient, nm_dhcp_client, G_TYPE_OBJECT, G_TYPE_FLAG_ABSTRACT, {}) enum { - STATE_CHANGED, - TIMEOUT, - REMOVE, + SIGNAL_STATE_CHANGED, + SIGNAL_TIMEOUT, + SIGNAL_REMOVE, LAST_SIGNAL }; @@ -71,6 +73,7 @@ enum { PROP_HWADDR, PROP_IPV6, PROP_UUID, + PROP_PRIORITY, PROP_TIMEOUT, LAST_PROP }; @@ -80,7 +83,6 @@ enum { GPid nm_dhcp_client_get_pid (NMDHCPClient *self) { - g_return_val_if_fail (self != NULL, -1); g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), -1); return NM_DHCP_CLIENT_GET_PRIVATE (self)->pid; @@ -89,7 +91,6 @@ nm_dhcp_client_get_pid (NMDHCPClient *self) const char * nm_dhcp_client_get_iface (NMDHCPClient *self) { - g_return_val_if_fail (self != NULL, NULL); g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), NULL); return NM_DHCP_CLIENT_GET_PRIVATE (self)->iface; @@ -98,7 +99,6 @@ nm_dhcp_client_get_iface (NMDHCPClient *self) gboolean nm_dhcp_client_get_ipv6 (NMDHCPClient *self) { - g_return_val_if_fail (self != NULL, FALSE); g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), FALSE); return NM_DHCP_CLIENT_GET_PRIVATE (self)->ipv6; @@ -107,7 +107,6 @@ nm_dhcp_client_get_ipv6 (NMDHCPClient *self) const char * nm_dhcp_client_get_uuid (NMDHCPClient *self) { - g_return_val_if_fail (self != NULL, NULL); g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), NULL); return NM_DHCP_CLIENT_GET_PRIVATE (self)->uuid; @@ -138,9 +137,9 @@ watch_cleanup (NMDHCPClient *self) } void -nm_dhcp_client_stop_pid (GPid pid, const char *iface, guint timeout_secs) +nm_dhcp_client_stop_pid (GPid pid, const char *iface) { - int i = (timeout_secs ? timeout_secs : 3) * 5; /* default 3 seconds */ + int i = 5; /* roughly 0.5 seconds */ g_return_if_fail (pid > 0); @@ -167,7 +166,7 @@ nm_dhcp_client_stop_pid (GPid pid, const char *iface, guint timeout_secs) break; } } - g_usleep (G_USEC_PER_SEC / 5); + g_usleep (G_USEC_PER_SEC / 10); } if (i <= 0) { @@ -188,7 +187,6 @@ stop (NMDHCPClient *self, gboolean release, const GByteArray *duid) { NMDHCPClientPrivate *priv; - g_return_if_fail (self != NULL); g_return_if_fail (NM_IS_DHCP_CLIENT (self)); priv = NM_DHCP_CLIENT_GET_PRIVATE (self); @@ -197,7 +195,7 @@ stop (NMDHCPClient *self, gboolean release, const GByteArray *duid) /* Clean up the watch handler since we're explicitly killing the daemon */ watch_cleanup (self); - nm_dhcp_client_stop_pid (priv->pid, priv->iface, 0); + nm_dhcp_client_stop_pid (priv->pid, priv->iface); priv->info_only = FALSE; } @@ -213,7 +211,7 @@ daemon_timeout (gpointer user_data) } else { nm_log_warn (LOGD_DHCP4, "(%s): DHCPv4 request timed out.", priv->iface); } - g_signal_emit (G_OBJECT (self), signals[TIMEOUT], 0); + g_signal_emit (G_OBJECT (self), signals[SIGNAL_TIMEOUT], 0); return FALSE; } @@ -223,7 +221,7 @@ signal_remove (gpointer user_data) NMDHCPClient *self = NM_DHCP_CLIENT (user_data); NM_DHCP_CLIENT_GET_PRIVATE (self)->remove_id = 0; - g_signal_emit (G_OBJECT (self), signals[REMOVE], 0); + g_signal_emit (G_OBJECT (self), signals[SIGNAL_REMOVE], 0); return FALSE; } @@ -238,12 +236,12 @@ dhcp_client_set_state (NMDHCPClient *self, priv->state = state; if (emit_state) - g_signal_emit (G_OBJECT (self), signals[STATE_CHANGED], 0, priv->state); + g_signal_emit (G_OBJECT (self), signals[SIGNAL_STATE_CHANGED], 0, priv->state); if (state == DHC_END || state == DHC_ABEND) { /* Start the remove signal timer */ if (remove_now) { - g_signal_emit (G_OBJECT (self), signals[REMOVE], 0); + g_signal_emit (G_OBJECT (self), signals[SIGNAL_REMOVE], 0); } else { if (!priv->remove_id) priv->remove_id = g_timeout_add_seconds (5, signal_remove, self); @@ -299,13 +297,12 @@ start_monitor (NMDHCPClient *self) gboolean nm_dhcp_client_start_ip4 (NMDHCPClient *self, - NMSettingIP4Config *s_ip4, - guint8 *dhcp_anycast_addr, + const char *dhcp_client_id, + GByteArray *dhcp_anycast_addr, const char *hostname) { NMDHCPClientPrivate *priv; - g_return_val_if_fail (self != NULL, FALSE); g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), FALSE); priv = NM_DHCP_CLIENT_GET_PRIVATE (self); @@ -316,7 +313,7 @@ nm_dhcp_client_start_ip4 (NMDHCPClient *self, nm_log_info (LOGD_DHCP, "Activation (%s) Beginning DHCPv4 transaction (timeout in %d seconds)", priv->iface, priv->timeout); - priv->pid = NM_DHCP_CLIENT_GET_CLASS (self)->ip4_start (self, s_ip4, dhcp_anycast_addr, hostname); + priv->pid = NM_DHCP_CLIENT_GET_CLASS (self)->ip4_start (self, dhcp_client_id, dhcp_anycast_addr, hostname); if (priv->pid) start_monitor (self); @@ -334,7 +331,7 @@ machine_id_parse (const char *in, uuid_t uu) g_return_val_if_fail (in != NULL, FALSE); g_return_val_if_fail (strlen (in) == 32, FALSE); - for (i = 0; i < 32; i++, cp++) { + for (i = 0; i < 32; i++) { if (!g_ascii_isxdigit (in[i])) return FALSE; } @@ -437,7 +434,7 @@ get_duid (NMDHCPClient *self) duid = generate_duid_from_machine_id (); g_assert (duid); - if (nm_logging_level_enabled (LOGL_DEBUG)) { + if (nm_logging_enabled (LOGL_DEBUG, LOGD_DHCP6)) { escaped = escape_duid (duid); nm_log_dbg (LOGD_DHCP6, "Generated DUID %s", escaped); g_free (escaped); @@ -454,15 +451,13 @@ get_duid (NMDHCPClient *self) gboolean nm_dhcp_client_start_ip6 (NMDHCPClient *self, - NMSettingIP6Config *s_ip6, - guint8 *dhcp_anycast_addr, + GByteArray *dhcp_anycast_addr, const char *hostname, gboolean info_only) { NMDHCPClientPrivate *priv; char *escaped; - g_return_val_if_fail (self != NULL, FALSE); g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), FALSE); priv = NM_DHCP_CLIENT_GET_PRIVATE (self); @@ -476,7 +471,7 @@ nm_dhcp_client_start_ip6 (NMDHCPClient *self, if (!priv->duid) priv->duid = NM_DHCP_CLIENT_GET_CLASS (self)->get_duid (self); - if (nm_logging_level_enabled (LOGL_DEBUG)) { + if (nm_logging_enabled (LOGL_DEBUG, LOGD_DHCP)) { escaped = escape_duid (priv->duid); nm_log_dbg (LOGD_DHCP, "(%s): DHCPv6 DUID is '%s'", priv->iface, escaped); g_free (escaped); @@ -488,7 +483,6 @@ nm_dhcp_client_start_ip6 (NMDHCPClient *self, priv->iface, priv->timeout); priv->pid = NM_DHCP_CLIENT_GET_CLASS (self)->ip6_start (self, - s_ip6, dhcp_anycast_addr, hostname, info_only, @@ -524,11 +518,13 @@ nm_dhcp_client_stop_existing (const char *pid_file, const char *binary_name) exe = proc_contents; if (!strcmp (exe, binary_name)) - nm_dhcp_client_stop_pid ((GPid) tmp, NULL, 0); + nm_dhcp_client_stop_pid ((GPid) tmp, NULL); } } - remove (pid_file); + if (remove (pid_file) == -1) + nm_log_dbg (LOGD_DHCP, "Could not remove dhcp pid file \"%s\": %d (%s)", pid_file, errno, g_strerror (errno)); + g_free (proc_path); g_free (pid_contents); g_free (proc_contents); @@ -539,7 +535,6 @@ nm_dhcp_client_stop (NMDHCPClient *self, gboolean release) { NMDHCPClientPrivate *priv; - g_return_if_fail (self != NULL); g_return_if_fail (NM_IS_DHCP_CLIENT (self)); priv = NM_DHCP_CLIENT_GET_PRIVATE (self); @@ -582,63 +577,54 @@ state_is_bound (guint32 state) return FALSE; } -typedef struct { - NMDHCPState state; - const char *name; -} DhcState; - -#define STATE_TABLE_SIZE (sizeof (state_table) / sizeof (state_table[0])) - -static DhcState state_table[] = { - { DHC_NBI, "nbi" }, - { DHC_PREINIT, "preinit" }, - { DHC_PREINIT6,"preinit6" }, - { DHC_BOUND4, "bound" }, - { DHC_BOUND6, "bound6" }, - { DHC_IPV4LL, "ipv4ll" }, - { DHC_RENEW4, "renew" }, - { DHC_RENEW6, "renew6" }, - { DHC_REBOOT, "reboot" }, - { DHC_REBIND4, "rebind" }, - { DHC_REBIND6, "rebind6" }, - { DHC_STOP, "stop" }, - { DHC_STOP6, "stop6" }, - { DHC_MEDIUM, "medium" }, - { DHC_TIMEOUT, "timeout" }, - { DHC_FAIL, "fail" }, - { DHC_EXPIRE, "expire" }, - { DHC_EXPIRE6, "expire6" }, - { DHC_RELEASE, "release" }, - { DHC_RELEASE6,"release6" }, - { DHC_START, "start" }, - { DHC_ABEND, "abend" }, - { DHC_END, "end" }, - { DHC_DEPREF6, "depref6" }, +static const char *state_table[] = { + [DHC_NBI] = "nbi", + [DHC_PREINIT] = "preinit", + [DHC_PREINIT6] = "preinit6", + [DHC_BOUND4] = "bound", + [DHC_BOUND6] = "bound6", + [DHC_IPV4LL] = "ipv4ll", + [DHC_RENEW4] = "renew", + [DHC_RENEW6] = "renew6", + [DHC_REBOOT] = "reboot", + [DHC_REBIND4] = "rebind", + [DHC_REBIND6] = "rebind6", + [DHC_DEPREF6] = "depref6", + [DHC_STOP] = "stop", + [DHC_STOP6] = "stop6", + [DHC_MEDIUM] = "medium", + [DHC_TIMEOUT] = "timeout", + [DHC_FAIL] = "fail", + [DHC_EXPIRE] = "expire", + [DHC_EXPIRE6] = "expire6", + [DHC_RELEASE] = "release", + [DHC_RELEASE6] = "release6", + [DHC_START] = "start", + [DHC_ABEND] = "abend", + [DHC_END] = "end", }; -static inline const char * -state_to_string (guint32 state) +static const char * +state_to_string (NMDHCPState state) { - int i; - - for (i = 0; i < STATE_TABLE_SIZE; i++) { - if (state == state_table[i].state) - return state_table[i].name; - } - + if (state >= 0 && state < G_N_ELEMENTS (state_table)) + return state_table[state]; return NULL; } -static inline NMDHCPState +static NMDHCPState string_to_state (const char *name) { int i; - for (i = 0; i < STATE_TABLE_SIZE; i++) { - if (!strcasecmp (name, state_table[i].name)) - return state_table[i].state; - } + if (name) { + for (i = 0; i < G_N_ELEMENTS (state_table); i++) { + const char *n = state_table[i]; + if (n && !strcasecmp (name, n)) + return i; + } + } return 255; } @@ -705,7 +691,6 @@ nm_dhcp_client_new_options (NMDHCPClient *self, guint32 old_state; guint32 new_state; - g_return_if_fail (self != NULL); g_return_if_fail (NM_IS_DHCP_CLIENT (self)); g_return_if_fail (options != NULL); g_return_if_fail (reason != NULL); @@ -766,7 +751,6 @@ nm_dhcp_client_foreach_option (NMDHCPClient *self, GHashTableIter iter; gpointer iterkey, itervalue; - g_return_val_if_fail (self != NULL, FALSE); g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), FALSE); g_return_val_if_fail (func != NULL, FALSE); @@ -813,10 +797,12 @@ nm_dhcp_client_foreach_option (NMDHCPClient *self, /********************************************/ static gboolean -ip4_process_dhcpcd_rfc3442_routes (const char *str, +ip4_process_dhcpcd_rfc3442_routes (NMDHCPClient *self, + const char *str, NMIP4Config *ip4_config, guint32 *gwaddr) { + NMDHCPClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE (self); char **routes, **r; gboolean have_routes = FALSE; @@ -831,10 +817,9 @@ ip4_process_dhcpcd_rfc3442_routes (const char *str, for (r = routes; *r; r += 2) { char *slash; - NMIP4Route *route; + NMPlatformIP4Route route; int rt_cidr = 32; - struct in_addr rt_addr; - struct in_addr rt_route; + guint32 rt_addr, rt_route; slash = strchr(*r, '/'); if (slash) { @@ -856,17 +841,18 @@ ip4_process_dhcpcd_rfc3442_routes (const char *str, } have_routes = TRUE; - if (rt_cidr == 0 && rt_addr.s_addr == 0) { + if (rt_cidr == 0 && rt_addr == 0) { /* FIXME: how to handle multiple routers? */ - *gwaddr = rt_route.s_addr; + *gwaddr = rt_route; } else { - route = nm_ip4_route_new (); - nm_ip4_route_set_dest (route, (guint32) rt_addr.s_addr); - nm_ip4_route_set_prefix (route, rt_cidr); - nm_ip4_route_set_next_hop (route, (guint32) rt_route.s_addr); - - nm_ip4_config_take_route (ip4_config, route); nm_log_info (LOGD_DHCP4, " classless static route %s/%d gw %s", *r, rt_cidr, *(r + 1)); + memset (&route, 0, sizeof (route)); + route.network = rt_addr; + route.plen = rt_cidr; + route.gateway = rt_route; + route.source = NM_PLATFORM_SOURCE_DHCP; + route.metric = priv->priority; + nm_ip4_config_add_route (ip4_config, &route); } } @@ -876,14 +862,15 @@ out: } static const char ** -process_dhclient_rfc3442_route (const char **octets, NMIP4Route **out_route) +process_dhclient_rfc3442_route (const char **octets, NMPlatformIP4Route *route, gboolean *success) { const char **o = octets; int addr_len = 0, i = 0; long int tmp; - NMIP4Route *route; char *next_hop; - struct in_addr tmp_addr; + guint32 tmp_addr; + + *success = FALSE; if (!*o) return o; /* no prefix */ @@ -892,8 +879,8 @@ process_dhclient_rfc3442_route (const char **octets, NMIP4Route **out_route) if (tmp < 0 || tmp > 32) /* 32 == max IP4 prefix length */ return o; - route = nm_ip4_route_new (); - nm_ip4_route_set_prefix (route, (guint32) tmp); + memset (route, 0, sizeof (*route)); + route->plen = tmp; o++; if (tmp > 0) @@ -915,8 +902,8 @@ process_dhclient_rfc3442_route (const char **octets, NMIP4Route **out_route) g_free (str_addr); goto error; } - tmp_addr.s_addr &= nm_utils_ip4_prefix_to_netmask ((guint32) tmp); - nm_ip4_route_set_dest (route, tmp_addr.s_addr); + tmp_addr &= nm_utils_ip4_prefix_to_netmask ((guint32) tmp); + route->network = tmp_addr; } /* Handle next hop */ @@ -925,25 +912,27 @@ process_dhclient_rfc3442_route (const char **octets, NMIP4Route **out_route) g_free (next_hop); goto error; } - nm_ip4_route_set_next_hop (route, tmp_addr.s_addr); + route->gateway = tmp_addr; g_free (next_hop); - *out_route = route; + *success = TRUE; return o + 4; /* advance to past the next hop */ error: - nm_ip4_route_unref (route); return o; } static gboolean -ip4_process_dhclient_rfc3442_routes (const char *str, +ip4_process_dhclient_rfc3442_routes (NMDHCPClient *self, + const char *str, NMIP4Config *ip4_config, guint32 *gwaddr) { + NMDHCPClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE (self); char **octets, **o; gboolean have_routes = FALSE; - NMIP4Route *route = NULL; + NMPlatformIP4Route route; + gboolean success; o = octets = g_strsplit_set (str, " .", 0); if (g_strv_length (octets) < 5) { @@ -952,32 +941,28 @@ ip4_process_dhclient_rfc3442_routes (const char *str, } while (*o) { - route = NULL; - o = (char **) process_dhclient_rfc3442_route ((const char **) o, &route); - if (!route) { + memset (&route, 0, sizeof (route)); + o = (char **) process_dhclient_rfc3442_route ((const char **) o, &route, &success); + if (!success) { nm_log_warn (LOGD_DHCP4, "ignoring invalid classless static routes"); break; } have_routes = TRUE; - if (nm_ip4_route_get_prefix (route) == 0) { + if (!route.plen) { /* gateway passed as classless static route */ - *gwaddr = nm_ip4_route_get_next_hop (route); - nm_ip4_route_unref (route); + *gwaddr = route.gateway; } else { - char addr[INET_ADDRSTRLEN + 1]; - char nh[INET_ADDRSTRLEN + 1]; - struct in_addr tmp; + char addr[INET_ADDRSTRLEN]; /* normal route */ - nm_ip4_config_take_route (ip4_config, route); + route.source = NM_PLATFORM_SOURCE_DHCP; + route.metric = priv->priority; + nm_ip4_config_add_route (ip4_config, &route); - tmp.s_addr = nm_ip4_route_get_dest (route); - inet_ntop (AF_INET, &tmp, addr, sizeof (addr)); - tmp.s_addr = nm_ip4_route_get_next_hop (route); - inet_ntop (AF_INET, &tmp, nh, sizeof (nh)); nm_log_info (LOGD_DHCP4, " classless static route %s/%d gw %s", - addr, nm_ip4_route_get_prefix (route), nh); + nm_utils_inet4_ntop (route.network, addr), route.plen, + nm_utils_inet4_ntop (route.gateway, NULL)); } } @@ -987,7 +972,8 @@ out: } static gboolean -ip4_process_classless_routes (GHashTable *options, +ip4_process_classless_routes (NMDHCPClient *self, + GHashTable *options, NMIP4Config *ip4_config, guint32 *gwaddr) { @@ -1043,15 +1029,16 @@ ip4_process_classless_routes (GHashTable *options, if (strchr (str, '/')) { /* dhcpcd format */ - return ip4_process_dhcpcd_rfc3442_routes (str, ip4_config, gwaddr); + return ip4_process_dhcpcd_rfc3442_routes (self, str, ip4_config, gwaddr); } - return ip4_process_dhclient_rfc3442_routes (str, ip4_config, gwaddr); + return ip4_process_dhclient_rfc3442_routes (self, str, ip4_config, gwaddr); } static void -process_classful_routes (GHashTable *options, NMIP4Config *ip4_config) +process_classful_routes (NMDHCPClient *self, GHashTable *options, NMIP4Config *ip4_config) { + NMDHCPClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE (self); const char *str; char **searches, **s; @@ -1066,9 +1053,8 @@ process_classful_routes (GHashTable *options, NMIP4Config *ip4_config) } for (s = searches; *s; s += 2) { - NMIP4Route *route; - struct in_addr rt_addr; - struct in_addr rt_route; + NMPlatformIP4Route route; + guint32 rt_addr, rt_route; if (inet_pton (AF_INET, *s, &rt_addr) <= 0) { nm_log_warn (LOGD_DHCP, "DHCP provided invalid static route address: '%s'", *s); @@ -1079,15 +1065,26 @@ process_classful_routes (GHashTable *options, NMIP4Config *ip4_config) continue; } - // FIXME: ensure the IP addresse and route are sane - - route = nm_ip4_route_new (); - nm_ip4_route_set_dest (route, (guint32) rt_addr.s_addr); - nm_ip4_route_set_prefix (route, 32); /* 255.255.255.255 */ - nm_ip4_route_set_next_hop (route, (guint32) rt_route.s_addr); + // FIXME: ensure the IP address and route are sane + + memset (&route, 0, sizeof (route)); + route.network = rt_addr; + /* RFC 2132, updated by RFC 3442: + The Static Routes option (option 33) does not provide a subnet mask + for each route - it is assumed that the subnet mask is implicit in + whatever network number is specified in each route entry */ + route.plen = nm_utils_ip4_get_default_prefix (rt_addr); + if (rt_addr & ~nm_utils_ip4_prefix_to_netmask (route.plen)) { + /* RFC 943: target not "this network"; using host routing */ + route.plen = 32; + } + route.gateway = rt_route; + route.source = NM_PLATFORM_SOURCE_DHCP; + route.metric = priv->priority; - nm_ip4_config_take_route (ip4_config, route); - nm_log_info (LOGD_DHCP, " static route %s gw %s", *s, *(s + 1)); + nm_ip4_config_add_route (ip4_config, &route); + nm_log_info (LOGD_DHCP, " static route %s", + nm_platform_ip4_route_to_string (&route)); } out: @@ -1145,59 +1142,47 @@ ip4_options_to_config (NMDHCPClient *self) { NMDHCPClientPrivate *priv; NMIP4Config *ip4_config = NULL; - struct in_addr tmp_addr; - NMIP4Address *addr = NULL; + guint32 tmp_addr; + NMPlatformIP4Address address; char *str = NULL; - guint32 gwaddr = 0, prefix = 0; + guint32 gwaddr = 0, plen = 0; - g_return_val_if_fail (self != NULL, NULL); g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), NULL); priv = NM_DHCP_CLIENT_GET_PRIVATE (self); g_return_val_if_fail (priv->options != NULL, NULL); ip4_config = nm_ip4_config_new (); - if (!ip4_config) { - nm_log_warn (LOGD_DHCP4, "(%s): couldn't allocate memory for an IP4Config!", priv->iface); - return NULL; - } - - addr = nm_ip4_address_new (); - if (!addr) { - nm_log_warn (LOGD_DHCP4, "(%s): couldn't allocate memory for an IP4 Address!", priv->iface); - goto error; - } + memset (&address, 0, sizeof (address)); + address.timestamp = nm_utils_get_monotonic_timestamp_s (); str = g_hash_table_lookup (priv->options, "new_ip_address"); if (str && (inet_pton (AF_INET, str, &tmp_addr) > 0)) { - nm_ip4_address_set_address (addr, tmp_addr.s_addr); + address.address = tmp_addr; nm_log_info (LOGD_DHCP4, " address %s", str); } else goto error; str = g_hash_table_lookup (priv->options, "new_subnet_mask"); if (str && (inet_pton (AF_INET, str, &tmp_addr) > 0)) { - prefix = nm_utils_ip4_netmask_to_prefix (tmp_addr.s_addr); - nm_log_info (LOGD_DHCP4, " prefix %d (%s)", prefix, str); + plen = nm_utils_ip4_netmask_to_prefix (tmp_addr); + nm_log_info (LOGD_DHCP4, " plen %d (%s)", plen, str); } else { /* Get default netmask for the IP according to appropriate class. */ - prefix = nm_utils_ip4_get_default_prefix (nm_ip4_address_get_address (addr)); - nm_log_info (LOGD_DHCP4, " prefix %d (default)", prefix); + plen = nm_utils_ip4_get_default_prefix (address.address); + nm_log_info (LOGD_DHCP4, " plen %d (default)", plen); } - nm_ip4_address_set_prefix (addr, prefix); + address.plen = plen; /* Routes: if the server returns classless static routes, we MUST ignore * the 'static_routes' option. */ - if (!ip4_process_classless_routes (priv->options, ip4_config, &gwaddr)) - process_classful_routes (priv->options, ip4_config); + if (!ip4_process_classless_routes (self, priv->options, ip4_config, &gwaddr)) + process_classful_routes (self, priv->options, ip4_config); if (gwaddr) { - char buf[INET_ADDRSTRLEN + 1]; - - inet_ntop (AF_INET, &gwaddr, buf, sizeof (buf)); - nm_log_info (LOGD_DHCP4, " gateway %s", buf); - nm_ip4_address_set_gateway (addr, gwaddr); + nm_log_info (LOGD_DHCP4, " gateway %s", nm_utils_inet4_ntop (gwaddr, NULL)); + nm_ip4_config_set_gateway (ip4_config, gwaddr); } else { /* If the gateway wasn't provided as a classless static route with a * subnet length of 0, try to find it using the old-style 'routers' option. @@ -1209,8 +1194,8 @@ ip4_options_to_config (NMDHCPClient *self) for (s = routers; *s; s++) { /* FIXME: how to handle multiple routers? */ - if (inet_pton (AF_INET, *s, &tmp_addr) > 0) { - nm_ip4_address_set_gateway (addr, tmp_addr.s_addr); + if (inet_pton (AF_INET, *s, &gwaddr) > 0) { + nm_ip4_config_set_gateway (ip4_config, gwaddr); nm_log_info (LOGD_DHCP4, " gateway %s", *s); break; } else @@ -1220,8 +1205,51 @@ ip4_options_to_config (NMDHCPClient *self) } } - nm_ip4_config_take_address (ip4_config, addr); - addr = NULL; + /* + * RFC 2132, section 9.7 + * DHCP clients use the contents of the 'server identifier' field + * as the destination address for any DHCP messages unicast to + * the DHCP server. + * + * Some ISP's provide leases from central servers that are on + * different subnets that the address offered. If the host + * does not configure the interface as the default route, the + * dhcp server may not be reachable via unicast, and a host + * specific route is needed. + **/ + str = g_hash_table_lookup (priv->options, "new_dhcp_server_identifier"); + if (str) { + if (inet_pton (AF_INET, str, &tmp_addr) > 0) { + NMPlatformIP4Route route; + guint32 mask = nm_utils_ip4_prefix_to_netmask (address.plen); + + nm_log_info (LOGD_DHCP4, " server identifier %s", str); + if ((tmp_addr & mask) != (address.address & mask)) { + /* DHCP server not on assigned subnet, route needed */ + memset (&route, 0, sizeof (route)); + route.network = tmp_addr; + route.plen = 32; + /* this will be a device route if gwaddr is 0 */ + route.gateway = gwaddr; + route.source = NM_PLATFORM_SOURCE_DHCP; + route.metric = priv->priority; + nm_ip4_config_add_route (ip4_config, &route); + nm_log_dbg (LOGD_IP, "adding route for server identifier: %s", + nm_platform_ip4_route_to_string (&route)); + } + } + else + nm_log_warn (LOGD_DHCP4, "ignoring invalid server identifier '%s'", str); + } + + str = g_hash_table_lookup (priv->options, "new_dhcp_lease_time"); + if (str) { + address.lifetime = address.preferred = strtoul (str, NULL, 10); + nm_log_info (LOGD_DHCP4, " lease time %d", address.lifetime); + } + + address.source = NM_PLATFORM_SOURCE_DHCP; + nm_ip4_config_add_address (ip4_config, &address); str = g_hash_table_lookup (priv->options, "new_host_name"); if (str) @@ -1234,7 +1262,7 @@ ip4_options_to_config (NMDHCPClient *self) for (s = searches; *s; s++) { if (inet_pton (AF_INET, *s, &tmp_addr) > 0) { - nm_ip4_config_add_nameserver (ip4_config, tmp_addr.s_addr); + nm_ip4_config_add_nameserver (ip4_config, tmp_addr); nm_log_info (LOGD_DHCP4, " nameserver '%s'", *s); } else nm_log_warn (LOGD_DHCP4, "ignoring invalid nameserver '%s'", *s); @@ -1265,7 +1293,7 @@ ip4_options_to_config (NMDHCPClient *self) for (s = searches; *s; s++) { if (inet_pton (AF_INET, *s, &tmp_addr) > 0) { - nm_ip4_config_add_wins (ip4_config, tmp_addr.s_addr); + nm_ip4_config_add_wins (ip4_config, tmp_addr); nm_log_info (LOGD_DHCP4, " wins '%s'", *s); } else nm_log_warn (LOGD_DHCP4, "ignoring invalid WINS server '%s'", *s); @@ -1299,7 +1327,7 @@ ip4_options_to_config (NMDHCPClient *self) for (s = searches; *s; s++) { if (inet_pton (AF_INET, *s, &tmp_addr) > 0) { - nm_ip4_config_add_nis_server (ip4_config, tmp_addr.s_addr); + nm_ip4_config_add_nis_server (ip4_config, tmp_addr); nm_log_info (LOGD_DHCP4, " nis '%s'", *s); } else nm_log_warn (LOGD_DHCP4, "ignoring invalid NIS server '%s'", *s); @@ -1310,8 +1338,6 @@ ip4_options_to_config (NMDHCPClient *self) return ip4_config; error: - if (addr) - nm_ip4_address_unref (addr); g_object_unref (ip4_config); return NULL; } @@ -1321,7 +1347,6 @@ nm_dhcp_client_get_ip4_config (NMDHCPClient *self, gboolean test) { NMDHCPClientPrivate *priv; - g_return_val_if_fail (self != NULL, NULL); g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), NULL); priv = NM_DHCP_CLIENT_GET_PRIVATE (self); @@ -1354,14 +1379,17 @@ ip6_options_to_config (NMDHCPClient *self) NMDHCPClientPrivate *priv; NMIP6Config *ip6_config = NULL; struct in6_addr tmp_addr; - NMIP6Address *addr = NULL; + NMPlatformIP6Address address; char *str = NULL; GHashTableIter iter; gpointer key, value; - g_return_val_if_fail (self != NULL, NULL); g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), NULL); + memset (&address, 0, sizeof (address)); + address.plen = 128; + address.timestamp = nm_utils_get_monotonic_timestamp_s (); + priv = NM_DHCP_CLIENT_GET_PRIVATE (self); g_return_val_if_fail (priv->options != NULL, NULL); @@ -1372,9 +1400,17 @@ ip6_options_to_config (NMDHCPClient *self) } ip6_config = nm_ip6_config_new (); - if (!ip6_config) { - nm_log_warn (LOGD_DHCP6, "(%s): couldn't allocate memory for an IP6Config!", priv->iface); - return NULL; + + str = g_hash_table_lookup (priv->options, "new_max_life"); + if (str) { + address.lifetime = strtoul (str, NULL, 10); + nm_log_info (LOGD_DHCP6, " valid_lft %d", address.lifetime); + } + + str = g_hash_table_lookup (priv->options, "new_preferred_life"); + if (str) { + address.preferred = strtoul (str, NULL, 10); + nm_log_info (LOGD_DHCP6, " preferred_lft %d", address.preferred); } str = g_hash_table_lookup (priv->options, "new_ip6_address"); @@ -1385,14 +1421,10 @@ ip6_options_to_config (NMDHCPClient *self) goto error; } - addr = nm_ip6_address_new (); - g_assert (addr); - nm_ip6_address_set_address (addr, &tmp_addr); - /* DHCPv6 IA_NA assignments are single address only */ - nm_ip6_address_set_prefix (addr, 128); - nm_log_info (LOGD_DHCP6, " address %s/128", str); - - nm_ip6_config_take_address (ip6_config, addr); + address.address = tmp_addr; + address.source = NM_PLATFORM_SOURCE_DHCP; + nm_ip6_config_add_address (ip6_config, &address); + nm_log_info (LOGD_DHCP6, " address %s", str); } else if (priv->info_only == FALSE) { /* No address in Managed mode is a hard error */ goto error; @@ -1433,7 +1465,6 @@ nm_dhcp_client_get_ip6_config (NMDHCPClient *self, gboolean test) { NMDHCPClientPrivate *priv; - g_return_val_if_fail (self != NULL, NULL); g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), NULL); priv = NM_DHCP_CLIENT_GET_PRIVATE (self); @@ -1481,6 +1512,9 @@ get_property (GObject *object, guint prop_id, case PROP_UUID: g_value_set_string (value, priv->uuid); break; + case PROP_PRIORITY: + g_value_set_uint (value, priv->priority); + break; case PROP_TIMEOUT: g_value_set_uint (value, priv->timeout); break; @@ -1513,6 +1547,10 @@ set_property (GObject *object, guint prop_id, /* construct-only */ priv->uuid = g_value_dup_string (value); break; + case PROP_PRIORITY: + /* construct-only */ + priv->priority = g_value_get_uint (value); + break; case PROP_TIMEOUT: priv->timeout = g_value_get_uint (value); break; @@ -1604,6 +1642,14 @@ nm_dhcp_client_class_init (NMDHCPClientClass *client_class) NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + g_object_class_install_property + (object_class, PROP_PRIORITY, + g_param_spec_uint (NM_DHCP_CLIENT_PRIORITY, + "priority", + "Priority", + 0, G_MAXUINT, 0, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + g_object_class_install_property (object_class, PROP_TIMEOUT, g_param_spec_uint (NM_DHCP_CLIENT_TIMEOUT, @@ -1613,8 +1659,8 @@ nm_dhcp_client_class_init (NMDHCPClientClass *client_class) G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); /* signals */ - signals[STATE_CHANGED] = - g_signal_new ("state-changed", + signals[SIGNAL_STATE_CHANGED] = + g_signal_new (NM_DHCP_CLIENT_SIGNAL_STATE_CHANGED, G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (NMDHCPClientClass, state_changed), @@ -1622,8 +1668,8 @@ nm_dhcp_client_class_init (NMDHCPClientClass *client_class) g_cclosure_marshal_VOID__UINT, G_TYPE_NONE, 1, G_TYPE_UINT); - signals[TIMEOUT] = - g_signal_new ("timeout", + signals[SIGNAL_TIMEOUT] = + g_signal_new (NM_DHCP_CLIENT_SIGNAL_TIMEOUT, G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (NMDHCPClientClass, timeout), @@ -1631,8 +1677,8 @@ nm_dhcp_client_class_init (NMDHCPClientClass *client_class) g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); - signals[REMOVE] = - g_signal_new ("remove", + signals[SIGNAL_REMOVE] = + g_signal_new (NM_DHCP_CLIENT_SIGNAL_REMOVE, G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (NMDHCPClientClass, remove), diff --git a/src/dhcp-manager/nm-dhcp-client.h b/src/dhcp-manager/nm-dhcp-client.h index 930ec1a5..ad18926a 100644 --- a/src/dhcp-manager/nm-dhcp-client.h +++ b/src/dhcp-manager/nm-dhcp-client.h @@ -38,8 +38,13 @@ #define NM_DHCP_CLIENT_HWADDR "hwaddr" #define NM_DHCP_CLIENT_IPV6 "ipv6" #define NM_DHCP_CLIENT_UUID "uuid" +#define NM_DHCP_CLIENT_PRIORITY "priority" #define NM_DHCP_CLIENT_TIMEOUT "timeout" +#define NM_DHCP_CLIENT_SIGNAL_TIMEOUT "timeout" +#define NM_DHCP_CLIENT_SIGNAL_STATE_CHANGED "state-changed" +#define NM_DHCP_CLIENT_SIGNAL_REMOVE "remove" + typedef enum { DHC_NBI = 0, /* no broadcast interfaces found */ DHC_PREINIT, /* configuration started */ @@ -78,13 +83,12 @@ typedef struct { /* Methods */ GPid (*ip4_start) (NMDHCPClient *self, - NMSettingIP4Config *s_ip4, - guint8 *anycast_addr, + const char *dhcp_client_id, + GByteArray *anycast_addr, const char *hostname); GPid (*ip6_start) (NMDHCPClient *self, - NMSettingIP6Config *s_ip6, - guint8 *anycast_addr, + GByteArray *anycast_addr, const char *hostname, gboolean info_only, const GByteArray *duid); @@ -121,13 +125,12 @@ gboolean nm_dhcp_client_get_ipv6 (NMDHCPClient *self); const char *nm_dhcp_client_get_uuid (NMDHCPClient *self); gboolean nm_dhcp_client_start_ip4 (NMDHCPClient *self, - NMSettingIP4Config *s_ip4, - guint8 *dhcp_anycast_addr, + const char *dhcp_client_id, + GByteArray *dhcp_anycast_addr, const char *hostname); gboolean nm_dhcp_client_start_ip6 (NMDHCPClient *self, - NMSettingIP6Config *s_ip6, - guint8 *dhcp_anycast_addr, + GByteArray *dhcp_anycast_addr, const char *hostname, gboolean info_only); @@ -148,7 +151,7 @@ NMIP6Config *nm_dhcp_client_get_ip6_config (NMDHCPClient *self, gboolean test) /* Backend helpers */ void nm_dhcp_client_stop_existing (const char *pid_file, const char *binary_name); -void nm_dhcp_client_stop_pid (GPid pid, const char *iface, guint timeout_secs); +void nm_dhcp_client_stop_pid (GPid pid, const char *iface); #endif /* NM_DHCP_CLIENT_H */ diff --git a/src/dhcp-manager/nm-dhcp-dhclient-utils.c b/src/dhcp-manager/nm-dhcp-dhclient-utils.c index db4bf7e8..8527e6c0 100644 --- a/src/dhcp-manager/nm-dhcp-dhclient-utils.c +++ b/src/dhcp-manager/nm-dhcp-dhclient-utils.c @@ -25,6 +25,9 @@ #include #include "nm-dhcp-dhclient-utils.h" +#include "nm-ip4-config.h" +#include "nm-utils.h" +#include "NetworkManagerUtils.h" #define CLIENTID_TAG "send dhcp-client-identifier" #define CLIENTID_FORMAT CLIENTID_TAG " \"%s\"; # added by NetworkManager" @@ -68,33 +71,32 @@ add_hostname (GString *str, const char *format, const char *hostname) } static void -add_ip4_config (GString *str, NMSettingIP4Config *s_ip4, const char *hostname) +add_ip4_config (GString *str, const char *dhcp_client_id, const char *hostname) { - if (s_ip4) { - const char *tmp; - - tmp = nm_setting_ip4_config_get_dhcp_client_id (s_ip4); - if (tmp) { - gboolean is_octets = TRUE; - const char *p = tmp; - - while (*p) { - if (!g_ascii_isxdigit (*p) && (*p != ':')) { - is_octets = FALSE; - break; - } - p++; + if (dhcp_client_id) { + gboolean is_octets = TRUE; + int i = 0; + + while (dhcp_client_id[i]) { + if ((i % 3) != 2 && !g_ascii_isxdigit (dhcp_client_id[i])) { + is_octets = FALSE; + break; } - - /* If the client ID is just hex digits and : then don't use quotes, - * because dhclient expects either a quoted ASCII string, or a byte - * array formated as hex octets separated by : - */ - if (is_octets) - g_string_append_printf (str, CLIENTID_FORMAT_OCTETS "\n", tmp); - else - g_string_append_printf (str, CLIENTID_FORMAT "\n", tmp); + if ((i % 3) == 2 && dhcp_client_id[i] != ':') { + is_octets = FALSE; + break; + } + i++; } + + /* If the client ID is just hex digits and : then don't use quotes, + * because dhclient expects either a quoted ASCII string, or a byte + * array formated as hex octets separated by : + */ + if (is_octets) + g_string_append_printf (str, CLIENTID_FORMAT_OCTETS "\n", dhcp_client_id); + else + g_string_append_printf (str, CLIENTID_FORMAT "\n", dhcp_client_id); } add_hostname (str, HOSTNAME4_FORMAT "\n", hostname); @@ -113,7 +115,7 @@ add_ip4_config (GString *str, NMSettingIP4Config *s_ip4, const char *hostname) } static void -add_ip6_config (GString *str, NMSettingIP6Config *s_ip6, const char *hostname) +add_ip6_config (GString *str, const char *hostname) { add_hostname (str, HOSTNAME6_FORMAT "\n", hostname); g_string_append (str, @@ -125,9 +127,8 @@ add_ip6_config (GString *str, NMSettingIP6Config *s_ip6, const char *hostname) char * nm_dhcp_dhclient_create_config (const char *interface, gboolean is_ip6, - NMSettingIP4Config *s_ip4, - NMSettingIP6Config *s_ip6, - guint8 *anycast_addr, + const char *dhcp_client_id, + GByteArray *anycast_addr, const char *hostname, const char *orig_path, const char *orig_contents) @@ -155,9 +156,7 @@ nm_dhcp_dhclient_create_config (const char *interface, /* Override config file "dhcp-client-id" and use one from the * connection. */ - if ( s_ip4 - && nm_setting_ip4_config_get_dhcp_client_id (s_ip4) - && !strncmp (p, CLIENTID_TAG, strlen (CLIENTID_TAG))) + if (dhcp_client_id && !strncmp (p, CLIENTID_TAG, strlen (CLIENTID_TAG))) continue; /* Override config file hostname and use one from the connection */ @@ -222,13 +221,13 @@ nm_dhcp_dhclient_create_config (const char *interface, g_string_append_c (new_contents, '\n'); if (is_ip6) { - add_ip6_config (new_contents, s_ip6, hostname); + add_ip6_config (new_contents, hostname); add_also_request (alsoreq, "dhcp6.name-servers"); add_also_request (alsoreq, "dhcp6.domain-search"); add_also_request (alsoreq, "dhcp6.client-id"); add_also_request (alsoreq, "dhcp6.server-id"); } else { - add_ip4_config (new_contents, s_ip4, hostname); + add_ip4_config (new_contents, dhcp_client_id, hostname); add_also_request (alsoreq, "rfc3442-classless-static-routes"); add_also_request (alsoreq, "ms-classless-static-routes"); add_also_request (alsoreq, "static-routes"); @@ -247,17 +246,22 @@ nm_dhcp_dhclient_create_config (const char *interface, g_string_append_c (new_contents, '\n'); - if (anycast_addr) { + if (anycast_addr && anycast_addr->len == 6) { + const guint8 *p_anycast_addr = anycast_addr->data; + g_string_append_printf (new_contents, "interface \"%s\" {\n" " initial-interval 1; \n" " anycast-mac ethernet %02x:%02x:%02x:%02x:%02x:%02x;\n" "}\n", interface, - anycast_addr[0], anycast_addr[1], - anycast_addr[2], anycast_addr[3], - anycast_addr[4], anycast_addr[5]); + p_anycast_addr[0], p_anycast_addr[1], + p_anycast_addr[2], p_anycast_addr[3], + p_anycast_addr[4], p_anycast_addr[5]); } + /* Finally, assert that anycast_addr was unset or a 48 bit mac address. */ + g_return_val_if_fail (!anycast_addr || anycast_addr->len == 6, g_string_free (new_contents, FALSE)); + return g_string_free (new_contents, FALSE); } @@ -423,3 +427,238 @@ nm_dhcp_dhclient_save_duid (const char *leasefile, return success; } +static void +add_lease_option (GHashTable *hash, char *line) +{ + char *spc; + size_t len; + + /* Find the space after "option" */ + spc = strchr (line, ' '); + if (!spc) + return; + + /* Find the option tag's data, which is after the second space */ + if (g_str_has_prefix (line, "option ")) { + while (g_ascii_isspace (*spc)) + spc++; + spc = strchr (spc + 1, ' '); + if (!spc) + return; + } + + /* Split the line at the space */ + *spc = '\0'; + spc++; + + /* Kill the ';' at the end of the line, if any */ + len = strlen (spc); + if (*(spc + len - 1) == ';') + *(spc + len - 1) = '\0'; + + /* Strip leading quote */ + while (g_ascii_isspace (*spc)) + spc++; + if (*spc == '"') + spc++; + + /* Strip trailing quote */ + len = strlen (spc); + if (len > 0 && spc[len - 1] == '"') + spc[len - 1] = '\0'; + + if (spc[0]) + g_hash_table_insert (hash, g_strdup (line), g_strdup (spc)); +} + +#define LEASE_INVALID G_MININT64 +static GTimeSpan +lease_validity_span (const char *str_expire, GDateTime *now) +{ + GDateTime *expire = NULL; + struct tm expire_tm; + GTimeSpan span; + + g_return_val_if_fail (now != NULL, LEASE_INVALID); + g_return_val_if_fail (str_expire != NULL, LEASE_INVALID); + + /* Skip initial number (day of week?) */ + if (!isdigit (*str_expire++)) + return LEASE_INVALID; + if (!isspace (*str_expire++)) + return LEASE_INVALID; + /* Read lease expiration (in UTC) */ + if (!strptime (str_expire, "%t%Y/%m/%d %H:%M:%S", &expire_tm)) + return LEASE_INVALID; + + expire = g_date_time_new_utc (expire_tm.tm_year + 1900, + expire_tm.tm_mon + 1, + expire_tm.tm_mday, + expire_tm.tm_hour, + expire_tm.tm_min, + expire_tm.tm_sec); + if (!expire) + return LEASE_INVALID; + + span = g_date_time_difference (expire, now); + g_date_time_unref (expire); + + /* GDateTime only supports a range of less then 10000 years, so span can + * not overflow or be equal to LEASE_INVALID */ + return span; +} + +/** + * nm_dhcp_dhclient_read_lease_ip_configs: + * @iface: the interface name to match leases with + * @contents: the contents of a dhclient leasefile + * @ipv6: whether to read IPv4 or IPv6 leases + * @now: the current UTC date/time; pass %NULL to automatically use current + * UTC time. Testcases may need a different value for 'now' + * + * Reads dhclient leases from @contents and parses them into either + * #NMIP4Config or #NMIP6Config objects depending on the value of @ipv6. + * + * Returns: a #GSList of #NMIP4Config objects (if @ipv6 is %FALSE) or a list of + * #NMIP6Config objects (if @ipv6 is %TRUE) containing the lease data. + */ +GSList * +nm_dhcp_dhclient_read_lease_ip_configs (const char *iface, + const char *contents, + gboolean ipv6, + GDateTime *now) +{ + GSList *parsed = NULL, *iter, *leases = NULL; + char **line, **split = NULL; + GHashTable *hash = NULL; + gint32 now_monotonic_ts; + + g_return_val_if_fail (contents != NULL, NULL); + + split = g_strsplit_set (contents, "\n\r", -1); + if (!split) + return NULL; + + for (line = split; line && *line; line++) { + *line = g_strstrip (*line); + + if (*line[0] == '#') { + /* Comment */ + } else if (!strcmp (*line, "}")) { + /* Lease ends */ + parsed = g_slist_append (parsed, hash); + hash = NULL; + } else if (!strcmp (*line, "lease {")) { + /* Beginning of a new lease */ + if (hash) { + /* Ignore malformed lease that doesn't end before new one starts */ + g_hash_table_destroy (hash); + } + + hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); + } else if (hash && strlen (*line)) + add_lease_option (hash, *line); + } + g_strfreev (split); + + /* Check if the last lease in the file was properly ended */ + if (hash) { + /* Ignore malformed lease that doesn't end before new one starts */ + g_hash_table_destroy (hash); + hash = NULL; + } + + if (now) + g_date_time_ref (now); + else + now = g_date_time_new_now_utc (); + now_monotonic_ts = nm_utils_get_monotonic_timestamp_s (); + + for (iter = parsed; iter; iter = g_slist_next (iter)) { + NMIP4Config *ip4; + NMPlatformIP4Address address; + const char *value; + GTimeSpan expiry; + guint32 tmp, gw = 0; + + hash = iter->data; + + /* Make sure this lease is for the interface we want */ + value = g_hash_table_lookup (hash, "interface"); + if (!value || strcmp (value, iface)) + continue; + + value = g_hash_table_lookup (hash, "expire"); + if (!value) + continue; + expiry = lease_validity_span (value, now); + if (expiry == LEASE_INVALID) + continue; + + /* scale expiry to seconds (and CLAMP into the range of guint32) */ + expiry = CLAMP (expiry / G_TIME_SPAN_SECOND, 0, NM_PLATFORM_LIFETIME_PERMANENT-1); + if (expiry <= 0) { + /* the address is already expired. Don't even add it. */ + continue; + } + + memset (&address, 0, sizeof (address)); + + /* IP4 address */ + value = g_hash_table_lookup (hash, "fixed-address"); + if (!value) + continue; + if (!inet_pton (AF_INET, value, &address.address)) + continue; + + /* Gateway */ + value = g_hash_table_lookup (hash, "option routers"); + if (!value) + continue; + if (!inet_pton (AF_INET, value, &gw)) + continue; + + /* Netmask */ + value = g_hash_table_lookup (hash, "option subnet-mask"); + if (value && inet_pton (AF_INET, value, &tmp)) + address.plen = nm_utils_ip4_netmask_to_prefix (tmp); + + /* Get default netmask for the IP according to appropriate class. */ + if (!address.plen) + address.plen = nm_utils_ip4_get_default_prefix (address.address); + + address.timestamp = now_monotonic_ts; + address.lifetime = address.preferred = expiry; + address.source = NM_PLATFORM_SOURCE_DHCP; + + ip4 = nm_ip4_config_new (); + nm_ip4_config_add_address (ip4, &address); + nm_ip4_config_set_gateway (ip4, gw); + + value = g_hash_table_lookup (hash, "option domain-name-servers"); + if (value) { + char **dns, **dns_iter; + + dns = g_strsplit_set (value, ",", -1); + for (dns_iter = dns; dns_iter && *dns_iter; dns_iter++) { + if (inet_pton (AF_INET, *dns_iter, &tmp)) + nm_ip4_config_add_nameserver (ip4, tmp); + } + if (dns) + g_strfreev (dns); + } + + value = g_hash_table_lookup (hash, "option domain-name"); + if (value && value[0]) + nm_ip4_config_add_domain (ip4, value); + + /* FIXME: static routes */ + + leases = g_slist_append (leases, ip4); + } + + g_date_time_unref (now); + g_slist_free_full (parsed, (GDestroyNotify) g_hash_table_destroy); + return leases; +} + diff --git a/src/dhcp-manager/nm-dhcp-dhclient-utils.h b/src/dhcp-manager/nm-dhcp-dhclient-utils.h index 95cb0568..e8d91b31 100644 --- a/src/dhcp-manager/nm-dhcp-dhclient-utils.h +++ b/src/dhcp-manager/nm-dhcp-dhclient-utils.h @@ -27,9 +27,8 @@ char *nm_dhcp_dhclient_create_config (const char *interface, gboolean is_ip6, - NMSettingIP4Config *s_ip4, - NMSettingIP6Config *s_ip6, - guint8 *anycast_addr, + const char *dhcp_client_id, + GByteArray *anycast_addr, const char *hostname, const char *orig_path, const char *orig_contents); @@ -44,5 +43,10 @@ gboolean nm_dhcp_dhclient_save_duid (const char *leasefile, const char *escaped_duid, GError **error); +GSList *nm_dhcp_dhclient_read_lease_ip_configs (const char *iface, + const char *contents, + gboolean ipv6, + GDateTime *now); + #endif /* NM_DHCP_DHCLIENT_UTILS_H */ diff --git a/src/dhcp-manager/nm-dhcp-dhclient.c b/src/dhcp-manager/nm-dhcp-dhclient.c index 9a42f0e4..4232ee0c 100644 --- a/src/dhcp-manager/nm-dhcp-dhclient.c +++ b/src/dhcp-manager/nm-dhcp-dhclient.c @@ -32,6 +32,7 @@ #include #include #include +#include #include @@ -39,14 +40,13 @@ #include "nm-utils.h" #include "nm-logging.h" #include "nm-dhcp-dhclient-utils.h" +#include "nm-dhcp-manager.h" #include "nm-posix-signals.h" G_DEFINE_TYPE (NMDHCPDhclient, nm_dhcp_dhclient, NM_TYPE_DHCP_CLIENT) #define NM_DHCP_DHCLIENT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DHCP_DHCLIENT, NMDHCPDhclientPrivate)) -#define ACTION_SCRIPT_PATH LIBEXECDIR "/nm-dhcp-client.action" - typedef struct { const char *path; char *conf_file; @@ -136,223 +136,37 @@ get_dhclient_leasefile (const char *iface, return NULL; } -static void -add_lease_option (GHashTable *hash, char *line) -{ - char *spc; - - spc = strchr (line, ' '); - if (!spc) { - nm_log_warn (LOGD_DHCP, "DHCP lease file line '%s' did not contain a space", line); - return; - } - - /* If it's an 'option' line, split at second space */ - if (g_str_has_prefix (line, "option ")) { - spc = strchr (spc + 1, ' '); - if (!spc) { - nm_log_warn (LOGD_DHCP, "DHCP lease file option line '%s' did not contain a second space", - line); - return; - } - } - - /* Split the line at the space */ - *spc = '\0'; - spc++; - - /* Kill the ';' at the end of the line, if any */ - if (*(spc + strlen (spc) - 1) == ';') - *(spc + strlen (spc) - 1) = '\0'; - - /* Treat 'interface' specially */ - if (g_str_has_prefix (line, "interface")) { - if (*(spc) == '"') - spc++; /* Jump past the " */ - if (*(spc + strlen (spc) - 1) == '"') - *(spc + strlen (spc) - 1) = '\0'; /* Kill trailing " */ - } - - g_hash_table_insert (hash, g_strdup (line), g_strdup (spc)); -} - GSList * -nm_dhcp_dhclient_get_lease_config (const char *iface, const char *uuid, gboolean ipv6) +nm_dhcp_dhclient_get_lease_ip_configs (const char *iface, + const char *uuid, + gboolean ipv6) { - GSList *parsed = NULL, *iter, *leases = NULL; char *contents = NULL; char *leasefile; - char **line, **split = NULL; - GHashTable *hash = NULL; - - /* IPv6 not supported */ - if (ipv6) - return NULL; + GSList *leases = NULL; leasefile = get_dhclient_leasefile (iface, uuid, FALSE, NULL); if (!leasefile) return NULL; - if (!g_file_test (leasefile, G_FILE_TEST_EXISTS)) - goto out; - - if (!g_file_get_contents (leasefile, &contents, NULL, NULL)) - goto out; + if ( g_file_test (leasefile, G_FILE_TEST_EXISTS) + && g_file_get_contents (leasefile, &contents, NULL, NULL) + && contents + && contents[0]) + leases = nm_dhcp_dhclient_read_lease_ip_configs (iface, contents, ipv6, NULL); - split = g_strsplit_set (contents, "\n\r", -1); + g_free (leasefile); g_free (contents); - if (!split) - goto out; - - for (line = split; line && *line; line++) { - *line = g_strstrip (*line); - - if (!strcmp (*line, "}")) { - /* Lease ends */ - parsed = g_slist_append (parsed, hash); - hash = NULL; - } else if (!strcmp (*line, "lease {")) { - /* Beginning of a new lease */ - if (hash) { - nm_log_warn (LOGD_DHCP, "DHCP lease file %s malformed; new lease started " - "without ending previous lease", - leasefile); - g_hash_table_destroy (hash); - } - - hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); - } else if (strlen (*line)) - add_lease_option (hash, *line); - } - g_strfreev (split); - - /* Check if the last lease in the file was properly ended */ - if (hash) { - nm_log_warn (LOGD_DHCP, "DHCP lease file %s malformed; new lease started " - "without ending previous lease", - leasefile); - g_hash_table_destroy (hash); - hash = NULL; - } - - for (iter = parsed; iter; iter = g_slist_next (iter)) { - NMIP4Config *ip4; - NMIP4Address *addr; - const char *data; - struct in_addr tmp; - guint32 prefix; - struct tm expire; - - hash = iter->data; - - /* Make sure this lease is for the interface we want */ - data = g_hash_table_lookup (hash, "interface"); - if (!data || strcmp (data, iface)) - continue; - - data = g_hash_table_lookup (hash, "expire"); - if (data) { - time_t now_tt; - struct tm *now; - - /* Read lease expiration (in UTC) */ - if (!strptime (data, "%w %Y/%m/%d %H:%M:%S", &expire)) { - nm_log_warn (LOGD_DHCP, "couldn't parse DHCP lease file expire time '%s'", - data); - continue; - } - - now_tt = time (NULL); - now = gmtime(&now_tt); - - /* Ignore this lease if it's already expired */ - if (expire.tm_year < now->tm_year) - continue; - else if (expire.tm_year == now->tm_year) { - if (expire.tm_mon < now->tm_mon) - continue; - else if (expire.tm_mon == now->tm_mon) { - if (expire.tm_mday < now->tm_mday) - continue; - else if (expire.tm_mday == now->tm_mday) { - if (expire.tm_hour < now->tm_hour) - continue; - else if (expire.tm_hour == now->tm_hour) { - if (expire.tm_min < now->tm_min) - continue; - else if (expire.tm_min == now->tm_min) { - if (expire.tm_sec <= now->tm_sec) - continue; - } - } - } - } - } - /* If we get this far, the lease hasn't expired */ - } - data = g_hash_table_lookup (hash, "fixed-address"); - if (!data) - continue; - - ip4 = nm_ip4_config_new (); - addr = nm_ip4_address_new (); - - /* IP4 address */ - if (!inet_pton (AF_INET, data, &tmp)) { - nm_log_warn (LOGD_DHCP, "couldn't parse DHCP lease file IP4 address '%s'", data); - goto error; - } - nm_ip4_address_set_address (addr, tmp.s_addr); - - /* Netmask */ - data = g_hash_table_lookup (hash, "option subnet-mask"); - if (data) { - if (!inet_pton (AF_INET, data, &tmp)) { - nm_log_warn (LOGD_DHCP, "couldn't parse DHCP lease file IP4 subnet mask '%s'", data); - goto error; - } - prefix = nm_utils_ip4_netmask_to_prefix (tmp.s_addr); - } else { - /* Get default netmask for the IP according to appropriate class. */ - prefix = nm_utils_ip4_get_default_prefix (nm_ip4_address_get_address (addr)); - } - nm_ip4_address_set_prefix (addr, prefix); - - /* Gateway */ - data = g_hash_table_lookup (hash, "option routers"); - if (data) { - if (!inet_pton (AF_INET, data, &tmp)) { - nm_log_warn (LOGD_DHCP, "couldn't parse DHCP lease file IP4 gateway '%s'", data); - goto error; - } - nm_ip4_address_set_gateway (addr, tmp.s_addr); - } - - nm_ip4_config_take_address (ip4, addr); - leases = g_slist_append (leases, ip4); - continue; - - error: - nm_ip4_address_unref (addr); - g_object_unref (ip4); - } - -out: - g_slist_free_full (parsed, (GDestroyNotify) g_hash_table_destroy); - g_free (leasefile); return leases; } - - static gboolean merge_dhclient_config (const char *iface, const char *conf_file, gboolean is_ip6, - NMSettingIP4Config *s_ip4, - NMSettingIP6Config *s_ip6, - guint8 *anycast_addr, + const char *dhcp_client_id, + GByteArray *anycast_addr, const char *hostname, const char *orig_path, GError **error) @@ -363,7 +177,7 @@ merge_dhclient_config (const char *iface, g_return_val_if_fail (iface != NULL, FALSE); g_return_val_if_fail (conf_file != NULL, FALSE); - if (g_file_test (orig_path, G_FILE_TEST_EXISTS)) { + if (orig_path && g_file_test (orig_path, G_FILE_TEST_EXISTS)) { GError *read_error = NULL; if (!g_file_get_contents (orig_path, &orig, NULL, &read_error)) { @@ -373,7 +187,7 @@ merge_dhclient_config (const char *iface, } } - new = nm_dhcp_dhclient_create_config (iface, is_ip6, s_ip4, s_ip6, anycast_addr, hostname, orig_path, orig); + new = nm_dhcp_dhclient_create_config (iface, is_ip6, dhcp_client_id, anycast_addr, hostname, orig_path, orig); g_assert (new); success = g_file_set_contents (conf_file, new, -1, error); g_free (new); @@ -383,7 +197,7 @@ merge_dhclient_config (const char *iface, } static char * -get_dhclient_config (const char * iface, const char *uuid, gboolean ipv6) +find_existing_config (const char *iface, const char *uuid, gboolean ipv6) { char *path; @@ -393,17 +207,20 @@ get_dhclient_config (const char * iface, const char *uuid, gboolean ipv6) */ if (uuid) { path = g_strdup_printf (NMCONFDIR "/dhclient%s-%s.conf", ipv6 ? "6" : "", uuid); + nm_log_dbg (ipv6 ? LOGD_DHCP6 : LOGD_DHCP4, "(%s) looking for existing config %s", iface, path); if (g_file_test (path, G_FILE_TEST_EXISTS)) return path; g_free (path); } path = g_strdup_printf (NMCONFDIR "/dhclient%s-%s.conf", ipv6 ? "6" : "", iface); + nm_log_dbg (ipv6 ? LOGD_DHCP6 : LOGD_DHCP4, "(%s) looking for existing config %s", iface, path); if (g_file_test (path, G_FILE_TEST_EXISTS)) return path; g_free (path); path = g_strdup_printf (NMCONFDIR "/dhclient%s.conf", ipv6 ? "6" : ""); + nm_log_dbg (ipv6 ? LOGD_DHCP6 : LOGD_DHCP4, "(%s) looking for existing config %s", iface, path); if (g_file_test (path, G_FILE_TEST_EXISTS)) return path; g_free (path); @@ -417,21 +234,25 @@ get_dhclient_config (const char * iface, const char *uuid, gboolean ipv6) * (including Fedora) don't even provide a default configuration file. */ path = g_strdup_printf (SYSCONFDIR "/dhcp/dhclient%s-%s.conf", ipv6 ? "6" : "", iface); + nm_log_dbg (ipv6 ? LOGD_DHCP6 : LOGD_DHCP4, "(%s) looking for existing config %s", iface, path); if (g_file_test (path, G_FILE_TEST_EXISTS)) return path; g_free (path); path = g_strdup_printf (SYSCONFDIR "/dhclient%s-%s.conf", ipv6 ? "6" : "", iface); + nm_log_dbg (ipv6 ? LOGD_DHCP6 : LOGD_DHCP4, "(%s) looking for existing config %s", iface, path); if (g_file_test (path, G_FILE_TEST_EXISTS)) return path; g_free (path); path = g_strdup_printf (SYSCONFDIR "/dhcp/dhclient%s.conf", ipv6 ? "6" : ""); + nm_log_dbg (ipv6 ? LOGD_DHCP6 : LOGD_DHCP4, "(%s) looking for existing config %s", iface, path); if (g_file_test (path, G_FILE_TEST_EXISTS)) return path; g_free (path); path = g_strdup_printf (SYSCONFDIR "/dhclient%s.conf", ipv6 ? "6" : ""); + nm_log_dbg (ipv6 ? LOGD_DHCP6 : LOGD_DHCP4, "(%s) looking for existing config %s", iface, path); if (g_file_test (path, G_FILE_TEST_EXISTS)) return path; g_free (path); @@ -449,9 +270,9 @@ get_dhclient_config (const char * iface, const char *uuid, gboolean ipv6) static char * create_dhclient_config (const char *iface, gboolean is_ip6, - NMSettingIP4Config *s_ip4, - NMSettingIP6Config *s_ip6, - guint8 *dhcp_anycast_addr, + const char *uuid, + const char *dhcp_client_id, + GByteArray *dhcp_anycast_addr, const char *hostname) { char *orig = NULL, *new = NULL; @@ -461,11 +282,23 @@ create_dhclient_config (const char *iface, g_return_val_if_fail (iface != NULL, NULL); new = g_strdup_printf (NMSTATEDIR "/dhclient%s-%s.conf", is_ip6 ? "6" : "", iface); + nm_log_dbg (is_ip6 ? LOGD_DHCP6 : LOGD_DHCP4, + "(%s): creating composite dhclient config %s", + iface, new); + + orig = find_existing_config (iface, uuid, is_ip6); + if (orig) { + nm_log_dbg (is_ip6 ? LOGD_DHCP6 : LOGD_DHCP4, + "(%s): merging existing dhclient config %s", + iface, orig); + } else { + nm_log_dbg (is_ip6 ? LOGD_DHCP6 : LOGD_DHCP4, + "(%s): no existing dhclient configuration to merge", + iface); + } - /* TODO: also support UUID */ - orig = get_dhclient_config (iface, NULL, is_ip6); error = NULL; - success = merge_dhclient_config (iface, new, is_ip6, s_ip4, s_ip6, dhcp_anycast_addr, hostname, orig, &error); + success = merge_dhclient_config (iface, new, is_ip6, dhcp_client_id, dhcp_anycast_addr, hostname, orig, &error); if (!success) { nm_log_warn (LOGD_DHCP, "(%s): error creating dhclient%s configuration: %s", iface, is_ip6 ? "6" : "", error->message); @@ -523,10 +356,6 @@ dhclient_start (NMDHCPClient *client, pid_file = g_strdup_printf (LOCALSTATEDIR "/run/dhclient%s-%s.pid", ipv6 ? "6" : "", iface); - if (!pid_file) { - nm_log_warn (log_domain, "(%s): not enough memory for dhcpcd options.", iface); - return -1; - } /* Kill any existing dhclient from the pidfile */ binary_name = g_path_get_basename (priv->path); @@ -593,7 +422,7 @@ dhclient_start (NMDHCPClient *client, g_ptr_array_add (argv, (gpointer) mode_opt); } g_ptr_array_add (argv, (gpointer) "-sf"); /* Set script file */ - g_ptr_array_add (argv, (gpointer) ACTION_SCRIPT_PATH ); + g_ptr_array_add (argv, (gpointer) nm_dhcp_helper_path); if (pid_file) { g_ptr_array_add (argv, (gpointer) "-pf"); /* Set pid file */ @@ -644,16 +473,17 @@ dhclient_start (NMDHCPClient *client, static GPid ip4_start (NMDHCPClient *client, - NMSettingIP4Config *s_ip4, - guint8 *dhcp_anycast_addr, + const char *dhcp_client_id, + GByteArray *dhcp_anycast_addr, const char *hostname) { NMDHCPDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE (client); - const char *iface; + const char *iface, *uuid; iface = nm_dhcp_client_get_iface (client); + uuid = nm_dhcp_client_get_uuid (client); - priv->conf_file = create_dhclient_config (iface, FALSE, s_ip4, NULL, dhcp_anycast_addr, hostname); + priv->conf_file = create_dhclient_config (iface, FALSE, uuid, dhcp_client_id, dhcp_anycast_addr, hostname); if (!priv->conf_file) { nm_log_warn (LOGD_DHCP4, "(%s): error creating dhclient configuration file.", iface); return -1; @@ -664,18 +494,18 @@ ip4_start (NMDHCPClient *client, static GPid ip6_start (NMDHCPClient *client, - NMSettingIP6Config *s_ip6, - guint8 *dhcp_anycast_addr, + GByteArray *dhcp_anycast_addr, const char *hostname, gboolean info_only, const GByteArray *duid) { NMDHCPDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE (client); - const char *iface; + const char *iface, *uuid; iface = nm_dhcp_client_get_iface (client); + uuid = nm_dhcp_client_get_uuid (client); - priv->conf_file = create_dhclient_config (iface, TRUE, NULL, s_ip6, dhcp_anycast_addr, hostname); + priv->conf_file = create_dhclient_config (iface, TRUE, uuid, NULL, dhcp_anycast_addr, hostname); if (!priv->conf_file) { nm_log_warn (LOGD_DHCP6, "(%s): error creating dhclient6 configuration file.", iface); return -1; @@ -693,9 +523,11 @@ stop (NMDHCPClient *client, gboolean release, const GByteArray *duid) NM_DHCP_CLIENT_CLASS (nm_dhcp_dhclient_parent_class)->stop (client, release, duid); if (priv->conf_file) - remove (priv->conf_file); + if (remove (priv->conf_file) == -1) + nm_log_dbg (LOGD_DHCP, "Could not remove dhcp config file \"%s\": %d (%s)", priv->conf_file, errno, g_strerror (errno)); if (priv->pid_file) { - remove (priv->pid_file); + if (remove (priv->pid_file) == -1) + nm_log_dbg (LOGD_DHCP, "Could not remove dhcp pid file \"%s\": %d (%s)", priv->pid_file, errno, g_strerror (errno)); g_free (priv->pid_file); priv->pid_file = NULL; } @@ -706,7 +538,7 @@ stop (NMDHCPClient *client, gboolean release, const GByteArray *duid) rpid = dhclient_start (client, NULL, duid, TRUE); if (rpid > 0) { /* Wait a few seconds for the release to happen */ - nm_dhcp_client_stop_pid (rpid, nm_dhcp_client_get_iface (client), 5); + nm_dhcp_client_stop_pid (rpid, nm_dhcp_client_get_iface (client)); } } } @@ -727,13 +559,13 @@ get_duid (NMDHCPClient *client) if (leasefile) { nm_log_dbg (LOGD_DHCP, "Looking for DHCPv6 DUID in '%s'.", leasefile); duid = nm_dhcp_dhclient_read_duid (leasefile, &error); - g_free (leasefile); if (error) { nm_log_warn (LOGD_DHCP, "Failed to read leasefile '%s': (%d) %s", leasefile, error->code, error->message); g_clear_error (&error); } + g_free (leasefile); } if (!duid && priv->def_leasefile) { diff --git a/src/dhcp-manager/nm-dhcp-dhclient.h b/src/dhcp-manager/nm-dhcp-dhclient.h index 89039189..20219a63 100644 --- a/src/dhcp-manager/nm-dhcp-dhclient.h +++ b/src/dhcp-manager/nm-dhcp-dhclient.h @@ -41,7 +41,9 @@ typedef struct { GType nm_dhcp_dhclient_get_type (void); -GSList *nm_dhcp_dhclient_get_lease_config (const char *iface, const char *uuid, gboolean ipv6); +GSList *nm_dhcp_dhclient_get_lease_ip_configs (const char *iface, + const char *uuid, + gboolean ipv6); const char *nm_dhcp_dhclient_get_path (const char *try_first); diff --git a/src/dhcp-manager/nm-dhcp-dhcpcd.c b/src/dhcp-manager/nm-dhcp-dhcpcd.c index f978cccc..acfbee26 100644 --- a/src/dhcp-manager/nm-dhcp-dhcpcd.c +++ b/src/dhcp-manager/nm-dhcp-dhcpcd.c @@ -34,6 +34,7 @@ #include #include "nm-dhcp-dhcpcd.h" +#include "nm-dhcp-manager.h" #include "nm-utils.h" #include "nm-logging.h" #include "nm-posix-signals.h" @@ -42,8 +43,6 @@ G_DEFINE_TYPE (NMDHCPDhcpcd, nm_dhcp_dhcpcd, NM_TYPE_DHCP_CLIENT) #define NM_DHCP_DHCPCD_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DHCP_DHCPCD, NMDHCPDhcpcdPrivate)) -#define ACTION_SCRIPT_PATH LIBEXECDIR "/nm-dhcp-client.action" - typedef struct { const char *path; char *pid_file; @@ -73,12 +72,6 @@ nm_dhcp_dhcpcd_get_path (const char *try_first) return *path; } -GSList * -nm_dhcp_dhcpcd_get_lease_config (const char *iface, const char *uuid, gboolean ipv6) -{ - return NULL; -} - static void dhcpcd_child_setup (gpointer user_data G_GNUC_UNUSED) { @@ -95,8 +88,8 @@ dhcpcd_child_setup (gpointer user_data G_GNUC_UNUSED) static GPid ip4_start (NMDHCPClient *client, - NMSettingIP4Config *s_ip4, - guint8 *dhcp_anycast_addr, + const char *dhcp_client_id, + GByteArray *dhcp_anycast_addr, const char *hostname) { NMDHCPDhcpcdPrivate *priv = NM_DHCP_DHCPCD_GET_PRIVATE (client); @@ -104,21 +97,16 @@ ip4_start (NMDHCPClient *client, GPid pid = -1; GError *error = NULL; char *pid_contents = NULL, *binary_name, *cmd_str; - const char *iface, *uuid; + const char *iface; g_return_val_if_fail (priv->pid_file == NULL, -1); iface = nm_dhcp_client_get_iface (client); - uuid = nm_dhcp_client_get_uuid (client); /* dhcpcd does not allow custom pidfiles; the pidfile is always * RUNDIR "dhcpcd-.pid". */ priv->pid_file = g_strdup_printf (RUNDIR "/dhcpcd-%s.pid", iface); - if (!priv->pid_file) { - nm_log_warn (LOGD_DHCP4, "(%s): not enough memory for dhcpcd options.", iface); - return -1; - } if (!g_file_test (priv->path, G_FILE_TEST_EXISTS)) { nm_log_warn (LOGD_DHCP4, "%s does not exist.", priv->path); @@ -142,7 +130,7 @@ ip4_start (NMDHCPClient *client, g_ptr_array_add (argv, (gpointer) "-G"); /* Let NM handle routing */ g_ptr_array_add (argv, (gpointer) "-c"); /* Set script file */ - g_ptr_array_add (argv, (gpointer) ACTION_SCRIPT_PATH ); + g_ptr_array_add (argv, (gpointer) nm_dhcp_helper_path); #ifdef DHCPCD_SUPPORTS_IPV6 /* IPv4-only for now. NetworkManager knows better than dhcpcd when to @@ -179,8 +167,7 @@ ip4_start (NMDHCPClient *client, static GPid ip6_start (NMDHCPClient *client, - NMSettingIP6Config *s_ip6, - guint8 *dhcp_anycast_addr, + GByteArray *dhcp_anycast_addr, const char *hostname, gboolean info_only, const GByteArray *duid) @@ -197,8 +184,10 @@ stop (NMDHCPClient *client, gboolean release, const GByteArray *duid) /* Chain up to parent */ NM_DHCP_CLIENT_CLASS (nm_dhcp_dhcpcd_parent_class)->stop (client, release, duid); - if (priv->pid_file) - remove (priv->pid_file); + if (priv->pid_file) { + if (remove (priv->pid_file) == -1) + nm_log_dbg (LOGD_DHCP, "Could not remove dhcp pid file \"%s\": %d (%s)", priv->pid_file, errno, g_strerror (errno)); + } /* FIXME: implement release... */ } diff --git a/src/dhcp-manager/nm-dhcp-dhcpcd.h b/src/dhcp-manager/nm-dhcp-dhcpcd.h index c90dcb74..fb6b0628 100644 --- a/src/dhcp-manager/nm-dhcp-dhcpcd.h +++ b/src/dhcp-manager/nm-dhcp-dhcpcd.h @@ -41,8 +41,6 @@ typedef struct { GType nm_dhcp_dhcpcd_get_type (void); -GSList *nm_dhcp_dhcpcd_get_lease_config (const char *iface, const char *uuid, gboolean ipv6); - const char *nm_dhcp_dhcpcd_get_path (const char *try_first); #endif /* NM_DHCP_DHCPCD_H */ diff --git a/src/dhcp-manager/nm-dhcp-helper.c b/src/dhcp-manager/nm-dhcp-helper.c new file mode 100644 index 00000000..4ddfafe1 --- /dev/null +++ b/src/dhcp-manager/nm-dhcp-helper.c @@ -0,0 +1,345 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2007 - 2013 Red Hat, Inc. + */ + +/* for environ */ +#define _GNU_SOURCE + +#include +#include +#include +#include +#include + +#include + +#include + +#define NM_DHCP_CLIENT_DBUS_IFACE "org.freedesktop.nm_dhcp_client" + +/** + * _dbus_dict_open_write: + * @iter: A valid dbus message iterator + * @iter_dict: on return, a dict iterator to pass to further dict functions + * + * Start a dict in a dbus message. Should be paired with a call to + * _dbus_dict_close_write(). + * + * Returns: %TRUE on success, %FALSE on failure + */ +static dbus_bool_t +_dbus_dict_open_write (DBusMessageIter *iter, DBusMessageIter *iter_dict) +{ + if (!iter || !iter_dict) + return FALSE; + + return dbus_message_iter_open_container (iter, + DBUS_TYPE_ARRAY, + DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING + DBUS_TYPE_STRING_AS_STRING + DBUS_TYPE_VARIANT_AS_STRING + DBUS_DICT_ENTRY_END_CHAR_AS_STRING, + iter_dict); +} + +/** + * _dbus_dict_close_write: + * @iter: valid dbus message iterator, same as passed to _dbus_dict_open_write() + * @iter_dict: a dbus dict iterator returned from _dbus_dict_open_write() + * + * End a dict element in a dbus message. Should be paired with a call to + * _dbus_dict_open_write(). + * + * Returns: %TRUE on success, %FALSE on failure + */ +static dbus_bool_t +_dbus_dict_close_write (DBusMessageIter *iter, DBusMessageIter *iter_dict) +{ + if (!iter || !iter_dict) + return FALSE; + + return dbus_message_iter_close_container (iter, iter_dict); +} + +static dbus_bool_t +_dbus_add_dict_entry_start (DBusMessageIter *iter_dict, + DBusMessageIter *iter_dict_entry, + const char *key, + const int value_type) +{ + if (!dbus_message_iter_open_container (iter_dict, DBUS_TYPE_DICT_ENTRY, NULL, iter_dict_entry)) + return FALSE; + + if (!dbus_message_iter_append_basic (iter_dict_entry, DBUS_TYPE_STRING, &key)) + return FALSE; + + return TRUE; +} + + +static dbus_bool_t +_dbus_add_dict_entry_end (DBusMessageIter *iter_dict, + DBusMessageIter *iter_dict_entry, + DBusMessageIter *iter_dict_val) +{ + if (!dbus_message_iter_close_container (iter_dict_entry, iter_dict_val)) + return FALSE; + if (!dbus_message_iter_close_container (iter_dict, iter_dict_entry)) + return FALSE; + + return TRUE; +} + +static dbus_bool_t +_dbus_add_dict_entry_byte_array (DBusMessageIter *iter_dict, + const char *key, + const char *value, + const dbus_uint32_t value_len) +{ + DBusMessageIter iter_dict_entry, iter_dict_val, iter_array; + dbus_uint32_t i; + + if (!_dbus_add_dict_entry_start (iter_dict, &iter_dict_entry, key, DBUS_TYPE_ARRAY)) + return FALSE; + + if (!dbus_message_iter_open_container (&iter_dict_entry, + DBUS_TYPE_VARIANT, + DBUS_TYPE_ARRAY_AS_STRING + DBUS_TYPE_BYTE_AS_STRING, + &iter_dict_val)) + return FALSE; + + if (!dbus_message_iter_open_container (&iter_dict_val, + DBUS_TYPE_ARRAY, + DBUS_TYPE_BYTE_AS_STRING, + &iter_array)) + return FALSE; + + for (i = 0; i < value_len; i++) { + if (!dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_BYTE, &(value[i]))) + return FALSE; + } + + if (!dbus_message_iter_close_container (&iter_dict_val, &iter_array)) + return FALSE; + + if (!_dbus_add_dict_entry_end (iter_dict, &iter_dict_entry, &iter_dict_val)) + return FALSE; + + return TRUE; +} + +/** + * _dbus_dict_append_byte_array: + * @iter_dict: A valid %DBusMessageIter returned from _dbus_dict_open_write() + * @key: The key of the dict item + * @value: The byte array + * @value_len: The length of the byte array, in bytes + * + * Add a byte array entry to the dict. + * + * Returns: %TRUE on success, %FALSE on failure + * + */ +static dbus_bool_t +_dbus_dict_append_byte_array (DBusMessageIter *iter_dict, + const char *key, + const char *value, + const dbus_uint32_t value_len) +{ + if (!key) + return FALSE; + if (!value && (value_len != 0)) + return FALSE; + return _dbus_add_dict_entry_byte_array (iter_dict, key, value, value_len); +} + + +static const char * ignore[] = {"PATH", "SHLVL", "_", "PWD", "dhc_dbus", NULL}; + +static dbus_bool_t +build_message (DBusMessage * message) +{ + char **item; + dbus_bool_t success = FALSE; + DBusMessageIter iter, iter_dict; + + dbus_message_iter_init_append (message, &iter); + if (!_dbus_dict_open_write (&iter, &iter_dict)) + goto out; + + /* List environment and format for dbus dict */ + for (item = environ; *item; item++) { + char *name, *val, **p; + + /* Split on the = */ + name = strdup (*item); + val = strchr (name, '='); + if (!val) + goto next; + *val++ = '\0'; + if (!strlen (val)) + val = NULL; + + /* Ignore non-DCHP-related environment variables */ + for (p = (char **) ignore; *p; p++) { + if (strncmp (name, *p, strlen (*p)) == 0) + goto next; + } + + /* Value passed as a byte array rather than a string, because there are + * no character encoding guarantees with DHCP, and D-Bus requires + * strings to be UTF-8. + */ + if (!_dbus_dict_append_byte_array (&iter_dict, + name, + val ? val : "\0", + val ? strlen (val) : 1)) { + fprintf (stderr, "Error: failed to add item '%s' to signal\n", name); + } + + next: + free (name); + } + + if (!_dbus_dict_close_write (&iter, &iter_dict)) + goto out; + + success = TRUE; + +out: + return success; +} + +#if !HAVE_DBUS_GLIB_100 +static DBusConnection * +shared_connection_init (void) +{ + DBusConnection * connection; + DBusError error; + int ret; + + dbus_connection_set_change_sigpipe (TRUE); + + dbus_error_init (&error); + connection = dbus_bus_get (DBUS_BUS_SYSTEM, &error); + if (dbus_error_is_set (&error)) { + fprintf (stderr, "Error: could not get the system bus. Make sure " + "the message bus daemon is running! Message: (%s) %s\n", + error.name, + error.message); + goto error; + } + + dbus_error_init (&error); + ret = dbus_bus_request_name (connection, "org.freedesktop.nm_dhcp_client", 0, &error); + if (dbus_error_is_set (&error)) { + fprintf (stderr, "Error: Could not acquire the NM DHCP client service. " + "Message: (%s) %s\n", + error.name, + error.message); + goto error; + } + + if (ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) { + fprintf (stderr, "Error: Could not acquire the NM DHCP client service " + "as it is already taken. Return: %d\n", + ret); + goto error; + } + + return connection; + +error: + if (dbus_error_is_set (&error)) + dbus_error_free (&error); + if (connection) + dbus_connection_unref (connection); + return NULL; +} +#endif + +static void +fatal_error (void) +{ + const char *pid_str = getenv ("pid"); + int pid = 0; + + if (pid_str) + pid = strtol (pid_str, NULL, 10); + if (pid) { + fprintf (stderr, "Fatal error occured, killing dhclient instance with pid %d.\n", pid); + kill (pid, SIGTERM); + } + + exit (1); +} + +int +main (int argc, char *argv[]) +{ + DBusConnection *connection; + DBusMessage *message; + dbus_bool_t result; + DBusError error; + + dbus_connection_set_change_sigpipe (TRUE); + + dbus_error_init (&error); + connection = dbus_connection_open_private ("unix:path=" NMRUNDIR "/private-dhcp", &error); + if (!connection) { +#if !HAVE_DBUS_GLIB_100 + connection = shared_connection_init (); +#endif + if (!connection) { + fprintf (stderr, "Error: could not connect to NetworkManager DBus socket: (%s) %s\n", + error.name, error.message); + dbus_error_free (&error); + fatal_error (); + } + } + dbus_connection_set_exit_on_disconnect (connection, FALSE); + + message = dbus_message_new_signal ("/", NM_DHCP_CLIENT_DBUS_IFACE, "Event"); + if (message == NULL) { + fprintf (stderr, "Error: Not enough memory to send DHCP Event signal.\n"); + fatal_error (); + } + + /* Dump environment variables into the message */ + result = build_message (message); + if (result == FALSE) { + fprintf (stderr, "Error: Not enough memory to send DHCP Event signal.\n"); + fatal_error (); + } + + /* queue the message */ + result = dbus_connection_send (connection, message, NULL); + if (!result) { + fprintf (stderr, "Error: Could not send send DHCP Event signal.\n"); + fatal_error (); + } + dbus_message_unref (message); + + /* Send out the message */ + dbus_connection_flush (connection); + + return 0; +} + diff --git a/src/dhcp-manager/nm-dhcp-helper.conf b/src/dhcp-manager/nm-dhcp-helper.conf new file mode 100644 index 00000000..0aeae603 --- /dev/null +++ b/src/dhcp-manager/nm-dhcp-helper.conf @@ -0,0 +1,13 @@ + + + + + + + + + + + diff --git a/src/dhcp-manager/nm-dhcp-manager.c b/src/dhcp-manager/nm-dhcp-manager.c index d40eb48d..ab6966cb 100644 --- a/src/dhcp-manager/nm-dhcp-manager.c +++ b/src/dhcp-manager/nm-dhcp-manager.c @@ -15,7 +15,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright (C) 2005 - 2010 Red Hat, Inc. + * Copyright (C) 2005 - 2013 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. * */ @@ -37,12 +37,12 @@ #include "nm-dhcp-manager.h" #include "nm-dhcp-dhclient.h" #include "nm-dhcp-dhcpcd.h" -#include "nm-marshal.h" #include "nm-logging.h" #include "nm-dbus-manager.h" -#include "nm-hostname-provider.h" +#include "nm-config.h" #include "nm-dbus-glib-types.h" #include "nm-glib-compat.h" +#include "NetworkManagerUtils.h" GQuark nm_dhcp_manager_error_quark (void) @@ -55,23 +55,30 @@ nm_dhcp_manager_error_quark (void) return ret; } -#define NM_DHCP_CLIENT_DBUS_SERVICE "org.freedesktop.nm_dhcp_client" #define NM_DHCP_CLIENT_DBUS_IFACE "org.freedesktop.nm_dhcp_client" #define DHCP_TIMEOUT 45 /* default DHCP timeout, in seconds */ -static NMDHCPManager *singleton = NULL; +#define PRIV_SOCK_PATH NMRUNDIR "/private-dhcp" +#define PRIV_SOCK_TAG "dhcp" + +/* default to installed helper, but can be modified for testing */ +const char *nm_dhcp_helper_path = LIBEXECDIR "/nm-dhcp-helper"; typedef GSList * (*GetLeaseConfigFunc) (const char *iface, const char *uuid, gboolean ipv6); typedef struct { GType client_type; - GetLeaseConfigFunc get_lease_config_func; + GetLeaseConfigFunc get_lease_ip_configs_func; NMDBusManager * dbus_mgr; + guint new_conn_id; + guint dis_conn_id; + GHashTable * proxies; + GHashTable * clients; DBusGProxy * proxy; - NMHostnameProvider *hostname_provider; + char * default_hostname; } NMDHCPManagerPrivate; @@ -119,7 +126,6 @@ get_client_for_pid (NMDHCPManager *manager, GPid pid) GHashTableIter iter; gpointer value; - g_return_val_if_fail (manager != NULL, NULL); g_return_val_if_fail (NM_IS_DHCP_MANAGER (manager), NULL); priv = NM_DHCP_MANAGER_GET_PRIVATE (manager); @@ -144,7 +150,6 @@ get_client_for_iface (NMDHCPManager *manager, GHashTableIter iter; gpointer value; - g_return_val_if_fail (manager != NULL, NULL); g_return_val_if_fail (NM_IS_DHCP_MANAGER (manager), NULL); g_return_val_if_fail (iface, NULL); @@ -186,50 +191,46 @@ nm_dhcp_manager_handle_event (DBusGProxy *proxy, GHashTable *options, gpointer user_data) { - NMDHCPManager *manager; - NMDHCPManagerPrivate *priv; + NMDHCPManager *manager = NM_DHCP_MANAGER (user_data); NMDHCPClient *client; char *iface = NULL; char *pid_str = NULL; char *reason = NULL; - unsigned long temp; - - manager = NM_DHCP_MANAGER (user_data); - priv = NM_DHCP_MANAGER_GET_PRIVATE (manager); + long pid; iface = get_option (options, "interface"); if (iface == NULL) { - nm_log_warn (LOGD_DHCP, "DHCP event didn't have associated interface."); + nm_log_warn (LOGD_DHCP, "DHCP event: didn't have associated interface."); goto out; } pid_str = get_option (options, "pid"); - if (pid_str == NULL) { - nm_log_warn (LOGD_DHCP, "DHCP event didn't have associated PID."); - goto out; - } - - temp = strtoul (pid_str, NULL, 10); - if ((temp == ULONG_MAX) && (errno == ERANGE)) { - nm_log_warn (LOGD_DHCP, "couldn't convert PID"); + pid = nm_utils_ascii_str_to_int64 (pid_str, 10, 0, LONG_MAX, -1); + if (pid == -1 || pid != (GPid)pid) { + nm_log_warn (LOGD_DHCP, "DHCP event: couldn't convert PID '%s' to an integer", pid_str ? pid_str : "(null)"); goto out; } - client = get_client_for_pid (manager, (GPid) temp); + reason = get_option (options, "reason"); + client = get_client_for_pid (manager, (GPid) pid); if (client == NULL) { - nm_log_warn (LOGD_DHCP, "(pid %ld) unhandled DHCP event for interface %s", temp, iface); + if (reason && g_ascii_strcasecmp (reason, "RELEASE") == 0) { + /* This happens regularly, when the dhcp client gets killed and we receive its last message. + * Don't log a warning in this case. */ + nm_log_dbg (LOGD_DHCP, "(pid %ld) unhandled RELEASE DHCP event for interface %s", pid, iface); + } else + nm_log_warn (LOGD_DHCP, "(pid %ld) unhandled DHCP event for interface %s", pid, iface); goto out; } if (strcmp (iface, nm_dhcp_client_get_iface (client))) { nm_log_warn (LOGD_DHCP, "(pid %ld) received DHCP event from unexpected interface '%s' (expected '%s')", - temp, iface, nm_dhcp_client_get_iface (client)); + pid, iface, nm_dhcp_client_get_iface (client)); goto out; } - reason = get_option (options, "reason"); if (reason == NULL) { - nm_log_warn (LOGD_DHCP, "(pid %ld) DHCP event didn't have a reason", temp); + nm_log_warn (LOGD_DHCP, "(pid %ld) DHCP event didn't have a reason", pid); goto out; } @@ -241,6 +242,48 @@ out: g_free (reason); } +#if HAVE_DBUS_GLIB_100 +static void +new_connection_cb (NMDBusManager *mgr, + DBusGConnection *connection, + NMDHCPManager *self) +{ + NMDHCPManagerPrivate *priv = NM_DHCP_MANAGER_GET_PRIVATE (self); + DBusGProxy *proxy; + + /* Create a new proxy for the client */ + proxy = dbus_g_proxy_new_for_peer (connection, "/", NM_DHCP_CLIENT_DBUS_IFACE); + dbus_g_proxy_add_signal (proxy, + "Event", + DBUS_TYPE_G_MAP_OF_VARIANT, + G_TYPE_INVALID); + dbus_g_proxy_connect_signal (proxy, + "Event", + G_CALLBACK (nm_dhcp_manager_handle_event), + self, + NULL); + g_hash_table_insert (priv->proxies, connection, proxy); +} + +static void +dis_connection_cb (NMDBusManager *mgr, + DBusGConnection *connection, + NMDHCPManager *self) +{ + NMDHCPManagerPrivate *priv = NM_DHCP_MANAGER_GET_PRIVATE (self); + DBusGProxy *proxy; + + proxy = g_hash_table_lookup (priv->proxies, connection); + if (proxy) { + dbus_g_proxy_disconnect_signal (proxy, + "Event", + G_CALLBACK (nm_dhcp_manager_handle_event), + self); + g_hash_table_remove (priv->proxies, connection); + } +} +#endif + static GType get_client_type (const char *client, GError **error) { @@ -250,8 +293,10 @@ get_client_type (const char *client, GError **error) /* If a client was disabled at build-time, its *_PATH define will be * an empty string. */ + /* coverity[array_null] */ if (DHCLIENT_PATH && strlen (DHCLIENT_PATH)) dhclient_path = nm_dhcp_dhclient_get_path (DHCLIENT_PATH); + /* coverity[array_null] */ if (DHCPCD_PATH && strlen (DHCPCD_PATH)) dhcpcd_path = nm_dhcp_dhcpcd_get_path (DHCPCD_PATH); @@ -264,7 +309,7 @@ get_client_type (const char *client, GError **error) g_set_error_literal (error, NM_DHCP_MANAGER_ERROR, NM_DHCP_MANAGER_ERROR_BAD_CLIENT, _("no usable DHCP client could be found.")); - return 0; + return G_TYPE_INVALID; } } @@ -273,7 +318,7 @@ get_client_type (const char *client, GError **error) g_set_error_literal (error, NM_DHCP_MANAGER_ERROR, NM_DHCP_MANAGER_ERROR_BAD_CLIENT, _("'dhclient' could be found.")); - return 0; + return G_TYPE_INVALID; } return NM_TYPE_DHCP_DHCLIENT; } @@ -283,7 +328,7 @@ get_client_type (const char *client, GError **error) g_set_error_literal (error, NM_DHCP_MANAGER_ERROR, NM_DHCP_MANAGER_ERROR_BAD_CLIENT, _("'dhcpcd' could be found.")); - return 0; + return G_TYPE_INVALID; } return NM_TYPE_DHCP_DHCPCD; } @@ -291,54 +336,7 @@ get_client_type (const char *client, GError **error) g_set_error (error, NM_DHCP_MANAGER_ERROR, NM_DHCP_MANAGER_ERROR_BAD_CLIENT, _("unsupported DHCP client '%s'"), client); - return 0; -} - -NMDHCPManager * -nm_dhcp_manager_new (const char *client, GError **error) -{ - NMDHCPManagerPrivate *priv; - DBusGConnection *g_connection; - - g_warn_if_fail (singleton == NULL); - - singleton = g_object_new (NM_TYPE_DHCP_MANAGER, NULL); - priv = NM_DHCP_MANAGER_GET_PRIVATE (singleton); - - /* Client-specific setup */ - priv->client_type = get_client_type (client, error); - if (priv->client_type == NM_TYPE_DHCP_DHCLIENT) - priv->get_lease_config_func = nm_dhcp_dhclient_get_lease_config; - else if (priv->client_type == NM_TYPE_DHCP_DHCPCD) - priv->get_lease_config_func = nm_dhcp_dhcpcd_get_lease_config; - else { - nm_log_warn (LOGD_DHCP, "No usable DHCP client found! DHCP configurations will fail."); - } - - priv->clients = g_hash_table_new_full (g_direct_hash, g_direct_equal, - NULL, - (GDestroyNotify) g_object_unref); - g_assert (priv->clients); - - priv->dbus_mgr = nm_dbus_manager_get (); - g_connection = nm_dbus_manager_get_connection (priv->dbus_mgr); - priv->proxy = dbus_g_proxy_new_for_name (g_connection, - NM_DHCP_CLIENT_DBUS_SERVICE, - "/", - NM_DHCP_CLIENT_DBUS_IFACE); - g_assert (priv->proxy); - - dbus_g_proxy_add_signal (priv->proxy, - "Event", - DBUS_TYPE_G_MAP_OF_VARIANT, - G_TYPE_INVALID); - - dbus_g_proxy_connect_signal (priv->proxy, "Event", - G_CALLBACK (nm_dhcp_manager_handle_event), - singleton, - NULL); - - return singleton; + return G_TYPE_INVALID; } #define REMOVE_ID_TAG "remove-id" @@ -372,10 +370,10 @@ add_client (NMDHCPManager *self, NMDHCPClient *client) NMDHCPManagerPrivate *priv = NM_DHCP_MANAGER_GET_PRIVATE (self); guint id; - id = g_signal_connect_swapped (client, "remove", G_CALLBACK (remove_client), self); + id = g_signal_connect_swapped (client, NM_DHCP_CLIENT_SIGNAL_REMOVE, G_CALLBACK (remove_client), self); g_object_set_data (G_OBJECT (client), REMOVE_ID_TAG, GUINT_TO_POINTER (id)); - id = g_signal_connect_swapped (client, "timeout", G_CALLBACK (remove_client), self); + id = g_signal_connect_swapped (client, NM_DHCP_CLIENT_SIGNAL_TIMEOUT, G_CALLBACK (remove_client), self); g_object_set_data (G_OBJECT (client), TIMEOUT_ID_TAG, GUINT_TO_POINTER (id)); g_hash_table_insert (priv->clients, client, g_object_ref (client)); @@ -386,11 +384,11 @@ client_start (NMDHCPManager *self, const char *iface, const GByteArray *hwaddr, const char *uuid, + guint priority, gboolean ipv6, - NMSettingIP4Config *s_ip4, - NMSettingIP6Config *s_ip6, + const char *dhcp_client_id, guint32 timeout, - guint8 *dhcp_anycast_addr, + GByteArray *dhcp_anycast_addr, const char *hostname, gboolean info_only) { @@ -421,15 +419,16 @@ client_start (NMDHCPManager *self, NM_DHCP_CLIENT_HWADDR, hwaddr, NM_DHCP_CLIENT_IPV6, ipv6, NM_DHCP_CLIENT_UUID, uuid, + NM_DHCP_CLIENT_PRIORITY, priority, NM_DHCP_CLIENT_TIMEOUT, timeout ? timeout : DHCP_TIMEOUT, NULL); g_return_val_if_fail (client != NULL, NULL); add_client (self, client); if (ipv6) - success = nm_dhcp_client_start_ip6 (client, s_ip6, dhcp_anycast_addr, hostname, info_only); + success = nm_dhcp_client_start_ip6 (client, dhcp_anycast_addr, hostname, info_only); else - success = nm_dhcp_client_start_ip4 (client, s_ip4, dhcp_anycast_addr, hostname); + success = nm_dhcp_client_start_ip4 (client, dhcp_client_id, dhcp_anycast_addr, hostname); if (!success) { remove_client (self, client); @@ -440,54 +439,42 @@ client_start (NMDHCPManager *self, return client; } +static const char * +get_send_hostname (NMDHCPManager *self, const char *setting_hostname) +{ + NMDHCPManagerPrivate *priv = NM_DHCP_MANAGER_GET_PRIVATE (self); + + /* Always prefer the explicit dhcp-send-hostname if given */ + return setting_hostname ? setting_hostname : priv->default_hostname; +} + /* Caller owns a reference to the NMDHCPClient on return */ NMDHCPClient * nm_dhcp_manager_start_ip4 (NMDHCPManager *self, const char *iface, const GByteArray *hwaddr, const char *uuid, + guint priority, NMSettingIP4Config *s_ip4, guint32 timeout, - guint8 *dhcp_anycast_addr) + GByteArray *dhcp_anycast_addr) { - NMDHCPManagerPrivate *priv; - const char *hostname = NULL; - gboolean send_hostname = TRUE; + const char *hostname = NULL, *method; + gboolean send_hostname; g_return_val_if_fail (self, NULL); g_return_val_if_fail (NM_IS_DHCP_MANAGER (self), NULL); - priv = NM_DHCP_MANAGER_GET_PRIVATE (self); - - if (s_ip4) { - const char *method = nm_setting_ip4_config_get_method (s_ip4); - - if (method) { - /* Method must be 'auto' */ - g_return_val_if_fail (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0, NULL); - } - - send_hostname = nm_setting_ip4_config_get_dhcp_send_hostname (s_ip4); - if (send_hostname) - hostname = nm_setting_ip4_config_get_dhcp_hostname (s_ip4); - } + method = nm_setting_ip4_config_get_method (s_ip4); + g_return_val_if_fail (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0, NULL); - if (send_hostname) { - /* If we're supposed to send the hostname to the DHCP server but - * the user didn't specify one, then use the hostname from the - * hostname provider if there is one, otherwise use the persistent - * hostname. - */ - if (!hostname && priv->hostname_provider) { - hostname = nm_hostname_provider_get_hostname (priv->hostname_provider); - if ( hostname - && (!strcmp (hostname, "localhost.localdomain") || - !strcmp (hostname, "localhost6.localdomain6"))) - hostname = NULL; - } - } + send_hostname = nm_setting_ip4_config_get_dhcp_send_hostname (s_ip4); + if (send_hostname) + hostname = get_send_hostname (self, nm_setting_ip4_config_get_dhcp_hostname (s_ip4)); - return client_start (self, iface, hwaddr, uuid, FALSE, s_ip4, NULL, timeout, dhcp_anycast_addr, hostname, FALSE); + return client_start (self, iface, hwaddr, uuid, priority, FALSE, + nm_setting_ip4_config_get_dhcp_client_id (s_ip4), + timeout, dhcp_anycast_addr, hostname, FALSE); } /* Caller owns a reference to the NMDHCPClient on return */ @@ -496,63 +483,42 @@ nm_dhcp_manager_start_ip6 (NMDHCPManager *self, const char *iface, const GByteArray *hwaddr, const char *uuid, + guint priority, NMSettingIP6Config *s_ip6, guint32 timeout, - guint8 *dhcp_anycast_addr, + GByteArray *dhcp_anycast_addr, gboolean info_only) { - NMDHCPManagerPrivate *priv; - const char *hostname = NULL; + const char *hostname; - g_return_val_if_fail (self, NULL); g_return_val_if_fail (NM_IS_DHCP_MANAGER (self), NULL); - priv = NM_DHCP_MANAGER_GET_PRIVATE (self); - - if (s_ip6) - hostname = nm_setting_ip6_config_get_dhcp_hostname (s_ip6); - if (!hostname && priv->hostname_provider) { - hostname = nm_hostname_provider_get_hostname (priv->hostname_provider); - if ( g_strcmp0 (hostname, "localhost.localdomain") == 0 - || g_strcmp0 (hostname, "localhost6.localdomain6") == 0) - hostname = NULL; - } - - return client_start (self, iface, hwaddr, uuid, TRUE, NULL, s_ip6, timeout, dhcp_anycast_addr, hostname, info_only); -} + hostname = get_send_hostname (self, nm_setting_ip6_config_get_dhcp_hostname (s_ip6)); -static void -hostname_provider_destroyed (gpointer data, GObject *destroyed_object) -{ - NM_DHCP_MANAGER_GET_PRIVATE (data)->hostname_provider = NULL; + return client_start (self, iface, hwaddr, uuid, priority, TRUE, + NULL, timeout, dhcp_anycast_addr, hostname, info_only); } void -nm_dhcp_manager_set_hostname_provider (NMDHCPManager *manager, - NMHostnameProvider *provider) +nm_dhcp_manager_set_default_hostname (NMDHCPManager *manager, const char *hostname) { - NMDHCPManagerPrivate *priv; - - g_return_if_fail (NM_IS_DHCP_MANAGER (manager)); + NMDHCPManagerPrivate *priv = NM_DHCP_MANAGER_GET_PRIVATE (manager); - priv = NM_DHCP_MANAGER_GET_PRIVATE (manager); + g_clear_pointer (&priv->default_hostname, g_free); - if (priv->hostname_provider) { - g_object_weak_unref (G_OBJECT (priv->hostname_provider), hostname_provider_destroyed, manager); - priv->hostname_provider = NULL; - } + /* Never send 'localhost'-type names to the DHCP server */ + if (g_strcmp0 (hostname, "localhost.localdomain") == 0 || + g_strcmp0 (hostname, "localhost6.localdomain6") == 0) + return; - if (provider) { - priv->hostname_provider = provider; - g_object_weak_ref (G_OBJECT (provider), hostname_provider_destroyed, manager); - } + priv->default_hostname = g_strdup (hostname); } GSList * -nm_dhcp_manager_get_lease_config (NMDHCPManager *self, - const char *iface, - const char *uuid, - gboolean ipv6) +nm_dhcp_manager_get_lease_ip_configs (NMDHCPManager *self, + const char *iface, + const char *uuid, + gboolean ipv6) { NMDHCPManagerPrivate *priv; @@ -562,10 +528,8 @@ nm_dhcp_manager_get_lease_config (NMDHCPManager *self, priv = NM_DHCP_MANAGER_GET_PRIVATE (self); - if (priv->get_lease_config_func) - return priv->get_lease_config_func (iface, uuid, ipv6); - - nm_log_warn (LOGD_DHCP, "Cannot get a DHCP lease config (no usable DHCP client was found!)"); + if (priv->get_lease_ip_configs_func) + return priv->get_lease_ip_configs_func (iface, uuid, ipv6); return NULL; } @@ -603,13 +567,70 @@ nm_dhcp_manager_test_ip4_options_to_config (const char *dhcp_client, NMDHCPManager * nm_dhcp_manager_get (void) { - g_warn_if_fail (singleton != NULL); - return g_object_ref (singleton); + static NMDHCPManager *singleton = NULL; + + if (G_UNLIKELY (singleton == NULL)) + singleton = g_object_new (NM_TYPE_DHCP_MANAGER, NULL); + g_assert (singleton); + return singleton; } static void -nm_dhcp_manager_init (NMDHCPManager *manager) +nm_dhcp_manager_init (NMDHCPManager *self) { + NMDHCPManagerPrivate *priv = NM_DHCP_MANAGER_GET_PRIVATE (self); + const char *client; + GError *error = NULL; +#if !HAVE_DBUS_GLIB_100 + DBusGConnection *g_connection; +#endif + + /* Maps DBusGConnection :: DBusGProxy */ + priv->proxies = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref); + + /* Client-specific setup */ + client = nm_config_get_dhcp_client (nm_config_get ()); + priv->client_type = get_client_type (client, &error); + + if (priv->client_type == NM_TYPE_DHCP_DHCLIENT) + priv->get_lease_ip_configs_func = nm_dhcp_dhclient_get_lease_ip_configs; + else if (priv->client_type == G_TYPE_INVALID) { + nm_log_warn (LOGD_DHCP, "No usable DHCP client found (%s)! DHCP configurations will fail.", + error->message); + } + g_clear_error (&error); + + priv->clients = g_hash_table_new_full (g_direct_hash, g_direct_equal, + NULL, + (GDestroyNotify) g_object_unref); + g_assert (priv->clients); + + priv->dbus_mgr = nm_dbus_manager_get (); + +#if HAVE_DBUS_GLIB_100 + /* Register the socket our DHCP clients will return lease info on */ + nm_dbus_manager_private_server_register (priv->dbus_mgr, PRIV_SOCK_PATH, PRIV_SOCK_TAG); + priv->new_conn_id = g_signal_connect (priv->dbus_mgr, + NM_DBUS_MANAGER_PRIVATE_CONNECTION_NEW "::" PRIV_SOCK_TAG, + (GCallback) new_connection_cb, + self); + priv->dis_conn_id = g_signal_connect (priv->dbus_mgr, + NM_DBUS_MANAGER_PRIVATE_CONNECTION_DISCONNECTED "::" PRIV_SOCK_TAG, + (GCallback) dis_connection_cb, + self); +#else + g_connection = nm_dbus_manager_get_connection (priv->dbus_mgr); + priv->proxy = dbus_g_proxy_new_for_name (g_connection, + "org.freedesktop.nm_dhcp_client", + "/", + NM_DHCP_CLIENT_DBUS_IFACE); + g_assert (priv->proxy); + dbus_g_proxy_add_signal (priv->proxy, "Event", DBUS_TYPE_G_MAP_OF_VARIANT, G_TYPE_INVALID); + dbus_g_proxy_connect_signal (priv->proxy, "Event", + G_CALLBACK (nm_dhcp_manager_handle_event), + self, + NULL); +#endif } static void @@ -625,6 +646,23 @@ dispose (GObject *object) g_list_free (values); } + if (priv->new_conn_id) { + g_signal_handler_disconnect (priv->dbus_mgr, priv->new_conn_id); + priv->new_conn_id = 0; + } + if (priv->dis_conn_id) { + g_signal_handler_disconnect (priv->dbus_mgr, priv->dis_conn_id); + priv->dis_conn_id = 0; + } + priv->dbus_mgr = NULL; + + if (priv->proxies) { + g_hash_table_destroy (priv->proxies); + priv->proxies = NULL; + } + if (priv->proxy) + g_object_unref (priv->proxy); + G_OBJECT_CLASS (nm_dhcp_manager_parent_class)->dispose (object); } @@ -633,17 +671,10 @@ finalize (GObject *object) { NMDHCPManagerPrivate *priv = NM_DHCP_MANAGER_GET_PRIVATE (object); - if (priv->hostname_provider) { - g_object_weak_unref (G_OBJECT (priv->hostname_provider), hostname_provider_destroyed, object); - priv->hostname_provider = NULL; - } + g_free (priv->default_hostname); if (priv->clients) g_hash_table_destroy (priv->clients); - if (priv->proxy) - g_object_unref (priv->proxy); - if (priv->dbus_mgr) - g_object_unref (priv->dbus_mgr); G_OBJECT_CLASS (nm_dhcp_manager_parent_class)->finalize (object); } @@ -659,4 +690,3 @@ nm_dhcp_manager_class_init (NMDHCPManagerClass *manager_class) object_class->finalize = finalize; object_class->dispose = dispose; } - diff --git a/src/dhcp-manager/nm-dhcp-manager.h b/src/dhcp-manager/nm-dhcp-manager.h index a29a33fd..efdd4378 100644 --- a/src/dhcp-manager/nm-dhcp-manager.h +++ b/src/dhcp-manager/nm-dhcp-manager.h @@ -31,7 +31,6 @@ #include "nm-dhcp-client.h" #include "nm-ip4-config.h" #include "nm-dhcp4-config.h" -#include "nm-hostname-provider.h" typedef enum { NM_DHCP_MANAGER_ERROR_BAD_CLIENT = 0, /*< nick=BadClient >*/ @@ -60,32 +59,34 @@ typedef struct { GType nm_dhcp_manager_get_type (void); -NMDHCPManager *nm_dhcp_manager_get (void); +NMDHCPManager *nm_dhcp_manager_get (void); -void nm_dhcp_manager_set_hostname_provider(NMDHCPManager *manager, - NMHostnameProvider *provider); +void nm_dhcp_manager_set_default_hostname (NMDHCPManager *manager, + const char *hostname); NMDHCPClient * nm_dhcp_manager_start_ip4 (NMDHCPManager *manager, const char *iface, const GByteArray *hwaddr, const char *uuid, + guint priority, NMSettingIP4Config *s_ip4, guint32 timeout, - guint8 *dhcp_anycast_addr); + GByteArray *dhcp_anycast_addr); NMDHCPClient * nm_dhcp_manager_start_ip6 (NMDHCPManager *manager, const char *iface, const GByteArray *hwaddr, const char *uuid, + guint priority, NMSettingIP6Config *s_ip6, guint32 timeout, - guint8 *dhcp_anycast_addr, + GByteArray *dhcp_anycast_addr, gboolean info_only); -GSList * nm_dhcp_manager_get_lease_config (NMDHCPManager *self, - const char *iface, - const char *uuid, - gboolean ipv6); +GSList * nm_dhcp_manager_get_lease_ip_configs (NMDHCPManager *self, + const char *iface, + const char *uuid, + gboolean ipv6); /* For testing only */ NMIP4Config *nm_dhcp_manager_test_ip4_options_to_config (const char *dhcp_client, @@ -93,7 +94,6 @@ NMIP4Config *nm_dhcp_manager_test_ip4_options_to_config (const char *dhcp_client GHashTable *options, const char *reason); -/* Only for main.c */ -NMDHCPManager *nm_dhcp_manager_new (const char *client, GError **error); +extern const char* nm_dhcp_helper_path; #endif /* NM_DHCP_MANAGER_H */ diff --git a/src/dhcp-manager/tests/Makefile.am b/src/dhcp-manager/tests/Makefile.am index bf859fe7..6ef828d5 100644 --- a/src/dhcp-manager/tests/Makefile.am +++ b/src/dhcp-manager/tests/Makefile.am @@ -1,12 +1,15 @@ -if ENABLE_TESTS - AM_CPPFLAGS = \ -I$(top_srcdir)/include \ -I$(top_builddir)/include \ -I${top_srcdir}/libnm-util \ -I${top_builddir}/libnm-util \ -I$(top_srcdir)/src/dhcp-manager \ - $(GLIB_CFLAGS) + -I$(top_srcdir)/src \ + -I$(top_srcdir)/src/platform \ + -DG_LOG_DOMAIN=\""NetworkManager"\" \ + -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \ + $(GLIB_CFLAGS) \ + -DTESTDIR="\"$(abs_srcdir)\"" noinst_PROGRAMS = test-dhcp-dhclient @@ -15,22 +18,16 @@ noinst_PROGRAMS = test-dhcp-dhclient test_dhcp_dhclient_SOURCES = \ test-dhcp-dhclient.c -test_dhcp_dhclient_CPPFLAGS = \ - $(AM_CPPFLAGS) \ - -DTESTDIR="\"$(abs_srcdir)\"" - test_dhcp_dhclient_LDADD = \ - -ldl \ - $(top_builddir)/src/dhcp-manager/libdhcp-dhclient.la \ - $(top_builddir)/libnm-util/libnm-util.la \ - $(GLIB_LIBS) - -check-local: test-dhcp-dhclient - $(abs_builddir)/test-dhcp-dhclient + $(top_builddir)/src/libNetworkManager.la -endif +TESTS = test-dhcp-dhclient EXTRA_DIST = \ test-dhclient-duid.leases \ - test-dhclient-commented-duid.leases + test-dhclient-commented-duid.leases \ + leases/basic.leases \ + leases/malformed1.leases \ + leases/malformed2.leases \ + leases/malformed3.leases diff --git a/src/dhcp-manager/tests/Makefile.in b/src/dhcp-manager/tests/Makefile.in index afcee2c0..d445838f 100644 --- a/src/dhcp-manager/tests/Makefile.in +++ b/src/dhcp-manager/tests/Makefile.in @@ -78,12 +78,14 @@ PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ -@ENABLE_TESTS_TRUE@noinst_PROGRAMS = test-dhcp-dhclient$(EXEEXT) +noinst_PROGRAMS = test-dhcp-dhclient$(EXEEXT) +TESTS = test-dhcp-dhclient$(EXEEXT) subdir = src/dhcp-manager/tests DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/build-aux/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \ +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_lib_readline.m4 \ + $(top_srcdir)/m4/compiler_warnings.m4 \ $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/gnome-code-coverage.m4 \ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ @@ -102,13 +104,10 @@ CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = PROGRAMS = $(noinst_PROGRAMS) -am__test_dhcp_dhclient_SOURCES_DIST = test-dhcp-dhclient.c -@ENABLE_TESTS_TRUE@am_test_dhcp_dhclient_OBJECTS = test_dhcp_dhclient-test-dhcp-dhclient.$(OBJEXT) +am_test_dhcp_dhclient_OBJECTS = test-dhcp-dhclient.$(OBJEXT) test_dhcp_dhclient_OBJECTS = $(am_test_dhcp_dhclient_OBJECTS) -am__DEPENDENCIES_1 = -@ENABLE_TESTS_TRUE@test_dhcp_dhclient_DEPENDENCIES = $(top_builddir)/src/dhcp-manager/libdhcp-dhclient.la \ -@ENABLE_TESTS_TRUE@ $(top_builddir)/libnm-util/libnm-util.la \ -@ENABLE_TESTS_TRUE@ $(am__DEPENDENCIES_1) +test_dhcp_dhclient_DEPENDENCIES = \ + $(top_builddir)/src/libNetworkManager.la AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent @@ -148,7 +147,7 @@ am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(test_dhcp_dhclient_SOURCES) -DIST_SOURCES = $(am__test_dhcp_dhclient_SOURCES_DIST) +DIST_SOURCES = $(test_dhcp_dhclient_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ @@ -173,6 +172,28 @@ am__define_uniq_tagged_files = \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags +am__tty_colors_dummy = \ + mgn= red= grn= lgn= blu= brg= std=; \ + am__color_tests=no +am__tty_colors = { \ + $(am__tty_colors_dummy); \ + if test "X$(AM_COLOR_TESTS)" = Xno; then \ + am__color_tests=no; \ + elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ + am__color_tests=yes; \ + elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ + am__color_tests=yes; \ + fi; \ + if test $$am__color_tests = yes; then \ + red=''; \ + grn=''; \ + lgn=''; \ + blu=''; \ + mgn=''; \ + brg=''; \ + std=''; \ + fi; \ +} DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALL_LINGUAS = @ALL_LINGUAS@ @@ -199,12 +220,15 @@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIRNAME = @DATADIRNAME@ DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_100_CFLAGS = @DBUS_GLIB_100_CFLAGS@ +DBUS_GLIB_100_LIBS = @DBUS_GLIB_100_LIBS@ DBUS_LIBS = @DBUS_LIBS@ DBUS_SYS_DIR = @DBUS_SYS_DIR@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DHCLIENT_PATH = @DHCLIENT_PATH@ DHCPCD_PATH = @DHCPCD_PATH@ +DISTRO_NETWORK_SERVICE = @DISTRO_NETWORK_SERVICE@ DLLTOOL = @DLLTOOL@ DNSMASQ_PATH = @DNSMASQ_PATH@ DSYMUTIL = @DSYMUTIL@ @@ -229,7 +253,6 @@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ GTKDOC_CHECK = @GTKDOC_CHECK@ -GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ GTKDOC_MKPDF = @GTKDOC_MKPDF@ @@ -274,12 +297,16 @@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ +LIBNDP_CFLAGS = @LIBNDP_CFLAGS@ +LIBNDP_LIBS = @LIBNDP_LIBS@ LIBNL_CFLAGS = @LIBNL_CFLAGS@ LIBNL_LIBS = @LIBNL_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@ LIBSOUP_LIBS = @LIBSOUP_LIBS@ +LIBTEAMDCTL_CFLAGS = @LIBTEAMDCTL_CFLAGS@ +LIBTEAMDCTL_LIBS = @LIBTEAMDCTL_LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ @@ -296,6 +323,8 @@ MOC = @MOC@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ +NEWT_CFLAGS = @NEWT_CFLAGS@ +NEWT_LIBS = @NEWT_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ @@ -323,11 +352,16 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ POLKIT_CFLAGS = @POLKIT_CFLAGS@ POLKIT_LIBS = @POLKIT_LIBS@ POSUB = @POSUB@ +PPPD_PATH = @PPPD_PATH@ PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@ +PPPOE_PATH = @PPPOE_PATH@ QT_CFLAGS = @QT_CFLAGS@ QT_LIBS = @QT_LIBS@ RANLIB = @RANLIB@ +READLINE_LIBS = @READLINE_LIBS@ SED = @SED@ +SELINUX_CFLAGS = @SELINUX_CFLAGS@ +SELINUX_LIBS = @SELINUX_LIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ @@ -342,6 +376,7 @@ UDEV_BASE_DIR = @UDEV_BASE_DIR@ USE_NLS = @USE_NLS@ UUID_CFLAGS = @UUID_CFLAGS@ UUID_LIBS = @UUID_LIBS@ +VALGRIND_RULES = @VALGRIND_RULES@ VAPIGEN = @VAPIGEN@ VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ @@ -404,6 +439,7 @@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ +subdirs = @subdirs@ sysconfdir = @sysconfdir@ systemdsystemunitdir = @systemdsystemunitdir@ target_alias = @target_alias@ @@ -414,32 +450,35 @@ with_dhclient = @with_dhclient@ with_dhcpcd = @with_dhcpcd@ with_netconfig = @with_netconfig@ with_resolvconf = @with_resolvconf@ -@ENABLE_TESTS_TRUE@AM_CPPFLAGS = \ -@ENABLE_TESTS_TRUE@ -I$(top_srcdir)/include \ -@ENABLE_TESTS_TRUE@ -I$(top_builddir)/include \ -@ENABLE_TESTS_TRUE@ -I${top_srcdir}/libnm-util \ -@ENABLE_TESTS_TRUE@ -I${top_builddir}/libnm-util \ -@ENABLE_TESTS_TRUE@ -I$(top_srcdir)/src/dhcp-manager \ -@ENABLE_TESTS_TRUE@ $(GLIB_CFLAGS) +with_valgrind = @with_valgrind@ +AM_CPPFLAGS = \ + -I$(top_srcdir)/include \ + -I$(top_builddir)/include \ + -I${top_srcdir}/libnm-util \ + -I${top_builddir}/libnm-util \ + -I$(top_srcdir)/src/dhcp-manager \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/src/platform \ + -DG_LOG_DOMAIN=\""NetworkManager"\" \ + -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \ + $(GLIB_CFLAGS) \ + -DTESTDIR="\"$(abs_srcdir)\"" ####### policy /etc/hosts test ####### -@ENABLE_TESTS_TRUE@test_dhcp_dhclient_SOURCES = \ -@ENABLE_TESTS_TRUE@ test-dhcp-dhclient.c - -@ENABLE_TESTS_TRUE@test_dhcp_dhclient_CPPFLAGS = \ -@ENABLE_TESTS_TRUE@ $(AM_CPPFLAGS) \ -@ENABLE_TESTS_TRUE@ -DTESTDIR="\"$(abs_srcdir)\"" +test_dhcp_dhclient_SOURCES = \ + test-dhcp-dhclient.c -@ENABLE_TESTS_TRUE@test_dhcp_dhclient_LDADD = \ -@ENABLE_TESTS_TRUE@ -ldl \ -@ENABLE_TESTS_TRUE@ $(top_builddir)/src/dhcp-manager/libdhcp-dhclient.la \ -@ENABLE_TESTS_TRUE@ $(top_builddir)/libnm-util/libnm-util.la \ -@ENABLE_TESTS_TRUE@ $(GLIB_LIBS) +test_dhcp_dhclient_LDADD = \ + $(top_builddir)/src/libNetworkManager.la EXTRA_DIST = \ test-dhclient-duid.leases \ - test-dhclient-commented-duid.leases + test-dhclient-commented-duid.leases \ + leases/basic.leases \ + leases/malformed1.leases \ + leases/malformed2.leases \ + leases/malformed3.leases all: all-am @@ -495,7 +534,7 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_dhcp_dhclient-test-dhcp-dhclient.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-dhcp-dhclient.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @@ -518,20 +557,6 @@ distclean-compile: @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< -test_dhcp_dhclient-test-dhcp-dhclient.o: test-dhcp-dhclient.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_dhcp_dhclient_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_dhcp_dhclient-test-dhcp-dhclient.o -MD -MP -MF $(DEPDIR)/test_dhcp_dhclient-test-dhcp-dhclient.Tpo -c -o test_dhcp_dhclient-test-dhcp-dhclient.o `test -f 'test-dhcp-dhclient.c' || echo '$(srcdir)/'`test-dhcp-dhclient.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_dhcp_dhclient-test-dhcp-dhclient.Tpo $(DEPDIR)/test_dhcp_dhclient-test-dhcp-dhclient.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-dhcp-dhclient.c' object='test_dhcp_dhclient-test-dhcp-dhclient.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_dhcp_dhclient_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_dhcp_dhclient-test-dhcp-dhclient.o `test -f 'test-dhcp-dhclient.c' || echo '$(srcdir)/'`test-dhcp-dhclient.c - -test_dhcp_dhclient-test-dhcp-dhclient.obj: test-dhcp-dhclient.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_dhcp_dhclient_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_dhcp_dhclient-test-dhcp-dhclient.obj -MD -MP -MF $(DEPDIR)/test_dhcp_dhclient-test-dhcp-dhclient.Tpo -c -o test_dhcp_dhclient-test-dhcp-dhclient.obj `if test -f 'test-dhcp-dhclient.c'; then $(CYGPATH_W) 'test-dhcp-dhclient.c'; else $(CYGPATH_W) '$(srcdir)/test-dhcp-dhclient.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_dhcp_dhclient-test-dhcp-dhclient.Tpo $(DEPDIR)/test_dhcp_dhclient-test-dhcp-dhclient.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-dhcp-dhclient.c' object='test_dhcp_dhclient-test-dhcp-dhclient.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_dhcp_dhclient_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_dhcp_dhclient-test-dhcp-dhclient.obj `if test -f 'test-dhcp-dhclient.c'; then $(CYGPATH_W) 'test-dhcp-dhclient.c'; else $(CYGPATH_W) '$(srcdir)/test-dhcp-dhclient.c'; fi` - mostlyclean-libtool: -rm -f *.lo @@ -590,6 +615,99 @@ cscopelist-am: $(am__tagged_files) distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags +check-TESTS: $(TESTS) + @failed=0; all=0; xfail=0; xpass=0; skip=0; \ + srcdir=$(srcdir); export srcdir; \ + list=' $(TESTS) '; \ + $(am__tty_colors); \ + if test -n "$$list"; then \ + for tst in $$list; do \ + if test -f ./$$tst; then dir=./; \ + elif test -f $$tst; then dir=; \ + else dir="$(srcdir)/"; fi; \ + if $(TESTS_ENVIRONMENT) $${dir}$$tst $(AM_TESTS_FD_REDIRECT); then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$tst[\ \ ]*) \ + xpass=`expr $$xpass + 1`; \ + failed=`expr $$failed + 1`; \ + col=$$red; res=XPASS; \ + ;; \ + *) \ + col=$$grn; res=PASS; \ + ;; \ + esac; \ + elif test $$? -ne 77; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$tst[\ \ ]*) \ + xfail=`expr $$xfail + 1`; \ + col=$$lgn; res=XFAIL; \ + ;; \ + *) \ + failed=`expr $$failed + 1`; \ + col=$$red; res=FAIL; \ + ;; \ + esac; \ + else \ + skip=`expr $$skip + 1`; \ + col=$$blu; res=SKIP; \ + fi; \ + echo "$${col}$$res$${std}: $$tst"; \ + done; \ + if test "$$all" -eq 1; then \ + tests="test"; \ + All=""; \ + else \ + tests="tests"; \ + All="All "; \ + fi; \ + if test "$$failed" -eq 0; then \ + if test "$$xfail" -eq 0; then \ + banner="$$All$$all $$tests passed"; \ + else \ + if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \ + banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \ + fi; \ + else \ + if test "$$xpass" -eq 0; then \ + banner="$$failed of $$all $$tests failed"; \ + else \ + if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \ + banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \ + fi; \ + fi; \ + dashes="$$banner"; \ + skipped=""; \ + if test "$$skip" -ne 0; then \ + if test "$$skip" -eq 1; then \ + skipped="($$skip test was not run)"; \ + else \ + skipped="($$skip tests were not run)"; \ + fi; \ + test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$skipped"; \ + fi; \ + report=""; \ + if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ + report="Please report to $(PACKAGE_BUGREPORT)"; \ + test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$report"; \ + fi; \ + dashes=`echo "$$dashes" | sed s/./=/g`; \ + if test "$$failed" -eq 0; then \ + col="$$grn"; \ + else \ + col="$$red"; \ + fi; \ + echo "$${col}$$dashes$${std}"; \ + echo "$${col}$$banner$${std}"; \ + test -z "$$skipped" || echo "$${col}$$skipped$${std}"; \ + test -z "$$report" || echo "$${col}$$report$${std}"; \ + echo "$${col}$$dashes$${std}"; \ + test "$$failed" -eq 0; \ + else :; fi + distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ @@ -620,9 +738,8 @@ distdir: $(DISTFILES) || exit 1; \ fi; \ done -@ENABLE_TESTS_FALSE@check-local: check-am: all-am - $(MAKE) $(AM_MAKEFLAGS) check-local + $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile $(PROGRAMS) installdirs: @@ -729,7 +846,7 @@ uninstall-am: .MAKE: check-am install-am install-strip -.PHONY: CTAGS GTAGS TAGS all all-am check check-am check-local clean \ +.PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-generic clean-libtool clean-noinstPROGRAMS cscopelist-am \ ctags ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ @@ -744,9 +861,6 @@ uninstall-am: tags tags-am uninstall uninstall-am -@ENABLE_TESTS_TRUE@check-local: test-dhcp-dhclient -@ENABLE_TESTS_TRUE@ $(abs_builddir)/test-dhcp-dhclient - # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: diff --git a/src/dhcp-manager/tests/leases/basic.leases b/src/dhcp-manager/tests/leases/basic.leases new file mode 100644 index 00000000..703d9247 --- /dev/null +++ b/src/dhcp-manager/tests/leases/basic.leases @@ -0,0 +1,31 @@ +lease { + interface "wlan0"; + fixed-address 192.168.1.180; + option subnet-mask 255.255.255.0; + option routers 192.168.1.1; + option dhcp-lease-time 600; + option dhcp-message-type 5; + option domain-name-servers 192.168.1.1; + option dhcp-server-identifier 192.168.1.1; + option broadcast-address 192.168.1.255; + renew 5 2013/11/01 19:56:15; + rebind 5 2013/11/01 20:00:44; + expire 5 2013/11/01 20:01:59; +} +lease { + interface "wlan0"; + fixed-address 10.77.52.141; + option subnet-mask 255.0.0.0; + option dhcp-lease-time 1200; + option routers 10.77.52.254; + option dhcp-message-type 5; + option dhcp-server-identifier 10.77.52.254; + option domain-name-servers 8.8.8.8,8.8.4.4; + option dhcp-renewal-time 600; + option dhcp-rebinding-time 1050; + option domain-name "morriesguest.local"; + renew 5 2013/11/01 20:01:08; + rebind 5 2013/11/01 20:05:00; + expire 5 2013/11/01 20:06:15; +} + diff --git a/src/dhcp-manager/tests/leases/malformed1.leases b/src/dhcp-manager/tests/leases/malformed1.leases new file mode 100644 index 00000000..401d982a --- /dev/null +++ b/src/dhcp-manager/tests/leases/malformed1.leases @@ -0,0 +1,15 @@ +# missing fixed-address option +lease { + interface "wlan0"; + option subnet-mask 255.255.255.0; + option routers 192.168.1.1; + option dhcp-lease-time 600; + option dhcp-message-type 5; + option domain-name-servers 192.168.1.1; + option dhcp-server-identifier 192.168.1.1; + option broadcast-address 192.168.1.255; + renew 5 2013/11/01 19:56:15; + rebind 5 2013/11/01 20:00:44; + expire 5 2013/11/01 20:01:59; +} + diff --git a/src/dhcp-manager/tests/leases/malformed2.leases b/src/dhcp-manager/tests/leases/malformed2.leases new file mode 100644 index 00000000..adf5f6de --- /dev/null +++ b/src/dhcp-manager/tests/leases/malformed2.leases @@ -0,0 +1,15 @@ +# missing routers option +lease { + interface "wlan0"; + fixed-address 192.168.1.180; + option subnet-mask 255.255.255.0; + option dhcp-lease-time 600; + option dhcp-message-type 5; + option domain-name-servers 192.168.1.1; + option dhcp-server-identifier 192.168.1.1; + option broadcast-address 192.168.1.255; + renew 5 2013/11/01 19:56:15; + rebind 5 2013/11/01 20:00:44; + expire 5 2013/11/01 20:01:59; +} + diff --git a/src/dhcp-manager/tests/leases/malformed3.leases b/src/dhcp-manager/tests/leases/malformed3.leases new file mode 100644 index 00000000..a2afc8b6 --- /dev/null +++ b/src/dhcp-manager/tests/leases/malformed3.leases @@ -0,0 +1,15 @@ +# missing expire time +lease { + interface "wlan0"; + fixed-address 192.168.1.180; + option subnet-mask 255.255.255.0; + option routers 192.168.1.1; + option dhcp-lease-time 600; + option dhcp-message-type 5; + option domain-name-servers 192.168.1.1; + option dhcp-server-identifier 192.168.1.1; + option broadcast-address 192.168.1.255; + renew 5 2013/11/01 19:56:15; + rebind 5 2013/11/01 20:00:44; +} + diff --git a/src/dhcp-manager/tests/test-dhcp-dhclient.c b/src/dhcp-manager/tests/test-dhcp-dhclient.c index 3f34c6e0..1ab182a7 100644 --- a/src/dhcp-manager/tests/test-dhcp-dhclient.c +++ b/src/dhcp-manager/tests/test-dhcp-dhclient.c @@ -24,6 +24,7 @@ #include "nm-dhcp-dhclient-utils.h" #include "nm-utils.h" +#include "nm-ip4-config.h" #define DEBUG 0 @@ -33,18 +34,13 @@ test_config (const char *orig, const char *hostname, const char *dhcp_client_id, const char *iface, - guint8 *anycast_addr) + GByteArray *anycast_addr) { - NMSettingIP4Config *s_ip4; char *new; - s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new (); - g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID, dhcp_client_id, NULL); - new = nm_dhcp_dhclient_create_config (iface, FALSE, - s_ip4, - NULL, + dhcp_client_id, anycast_addr, hostname, "/path/to/dhclient.conf", @@ -127,6 +123,62 @@ test_override_client_id (void) /*******************************************/ +static const char *quote_client_id_expected = \ + "# Created by NetworkManager\n" + "\n" + "send dhcp-client-identifier \"1234\"; # added by NetworkManager\n" + "\n" + "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" + "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" + "option wpad code 252 = string;\n" + "\n" + "also request rfc3442-classless-static-routes;\n" + "also request ms-classless-static-routes;\n" + "also request static-routes;\n" + "also request wpad;\n" + "also request ntp-servers;\n" + "\n"; + +static void +test_quote_client_id (void) +{ + test_config (NULL, quote_client_id_expected, + NULL, + "1234", + "eth0", + NULL); +} + +/*******************************************/ + +static const char *ascii_client_id_expected = \ + "# Created by NetworkManager\n" + "\n" + "send dhcp-client-identifier \"qb:cd:ef:12:34:56\"; # added by NetworkManager\n" + "\n" + "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" + "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" + "option wpad code 252 = string;\n" + "\n" + "also request rfc3442-classless-static-routes;\n" + "also request ms-classless-static-routes;\n" + "also request static-routes;\n" + "also request wpad;\n" + "also request ntp-servers;\n" + "\n"; + +static void +test_ascii_client_id (void) +{ + test_config (NULL, ascii_client_id_expected, + NULL, + "qb:cd:ef:12:34:56", + "eth0", + NULL); +} + +/*******************************************/ + static const char *override_hostname_orig = \ "send host-name \"foobar\";\n"; @@ -398,37 +450,164 @@ test_write_existing_commented_duid (void) /*******************************************/ -#if GLIB_CHECK_VERSION(2,25,12) -typedef GTestFixtureFunc TCFunc; -#else -typedef void (*TCFunc)(void); -#endif +static void +test_read_lease_ip4_config_basic (void) +{ + GError *error = NULL; + char *contents = NULL; + gboolean success; + const char *path = TESTDIR "/leases/basic.leases"; + GSList *leases; + GDateTime *now; + NMIP4Config *config; + const NMPlatformIP4Address *addr; + guint32 expected_addr; + + success = g_file_get_contents (path, &contents, NULL, &error); + g_assert_no_error (error); + g_assert (success); -#define TESTCASE(t, d) g_test_create_case (#t, 0, d, NULL, (TCFunc) t, NULL) + /* Date from before the least expiration */ + now = g_date_time_new_utc (2013, 11, 1, 19, 55, 32); + leases = nm_dhcp_dhclient_read_lease_ip_configs ("wlan0", contents, FALSE, now); + g_assert_cmpint (g_slist_length (leases), ==, 2); + + /* IP4Config #1 */ + config = g_slist_nth_data (leases, 0); + g_assert (NM_IS_IP4_CONFIG (config)); + + /* Address */ + g_assert_cmpint (nm_ip4_config_get_num_addresses (config), ==, 1); + g_assert (inet_aton ("192.168.1.180", (struct in_addr *) &expected_addr)); + addr = nm_ip4_config_get_address (config, 0); + g_assert_cmpint (addr->address, ==, expected_addr); + g_assert_cmpint (addr->plen, ==, 24); + + /* Gateway */ + g_assert (inet_aton ("192.168.1.1", (struct in_addr *) &expected_addr)); + g_assert_cmpint (nm_ip4_config_get_gateway (config), ==, expected_addr); + + /* DNS */ + g_assert_cmpint (nm_ip4_config_get_num_nameservers (config), ==, 1); + g_assert (inet_aton ("192.168.1.1", (struct in_addr *) &expected_addr)); + g_assert_cmpint (nm_ip4_config_get_nameserver (config, 0), ==, expected_addr); + + g_assert_cmpint (nm_ip4_config_get_num_domains (config), ==, 0); + + /* IP4Config #2 */ + config = g_slist_nth_data (leases, 1); + g_assert (NM_IS_IP4_CONFIG (config)); + + /* Address */ + g_assert_cmpint (nm_ip4_config_get_num_addresses (config), ==, 1); + g_assert (inet_aton ("10.77.52.141", (struct in_addr *) &expected_addr)); + addr = nm_ip4_config_get_address (config, 0); + g_assert_cmpint (addr->address, ==, expected_addr); + g_assert_cmpint (addr->plen, ==, 8); + + /* Gateway */ + g_assert (inet_aton ("10.77.52.254", (struct in_addr *) &expected_addr)); + g_assert_cmpint (nm_ip4_config_get_gateway (config), ==, expected_addr); + + /* DNS */ + g_assert_cmpint (nm_ip4_config_get_num_nameservers (config), ==, 2); + g_assert (inet_aton ("8.8.8.8", (struct in_addr *) &expected_addr)); + g_assert_cmpint (nm_ip4_config_get_nameserver (config, 0), ==, expected_addr); + g_assert (inet_aton ("8.8.4.4", (struct in_addr *) &expected_addr)); + g_assert_cmpint (nm_ip4_config_get_nameserver (config, 1), ==, expected_addr); + + /* Domains */ + g_assert_cmpint (nm_ip4_config_get_num_domains (config), ==, 1); + g_assert_cmpstr (nm_ip4_config_get_domain (config, 0), ==, "morriesguest.local"); + + g_slist_free_full (leases, g_object_unref); + g_date_time_unref (now); + g_free (contents); +} -int main (int argc, char **argv) +static void +test_read_lease_ip4_config_expired (void) { - GTestSuite *suite; + GError *error = NULL; + char *contents = NULL; + gboolean success; + const char *path = TESTDIR "/leases/basic.leases"; + GSList *leases; + GDateTime *now; - g_test_init (&argc, &argv, NULL); + success = g_file_get_contents (path, &contents, NULL, &error); + g_assert_no_error (error); + g_assert (success); - g_type_init (); + /* Date from *after* the lease expiration */ + now = g_date_time_new_utc (2013, 12, 1, 19, 55, 32); + leases = nm_dhcp_dhclient_read_lease_ip_configs ("wlan0", contents, FALSE, now); + g_assert (leases == NULL); + + g_date_time_unref (now); + g_free (contents); +} + +static void +test_read_lease_ip4_config_expect_failure (gconstpointer user_data) +{ + GError *error = NULL; + char *contents = NULL; + gboolean success; + GSList *leases; + GDateTime *now; + + success = g_file_get_contents ((const char *) user_data, &contents, NULL, &error); + g_assert_no_error (error); + g_assert (success); + + /* Date from before the least expiration */ + now = g_date_time_new_utc (2013, 11, 1, 1, 1, 1); + leases = nm_dhcp_dhclient_read_lease_ip_configs ("wlan0", contents, FALSE, now); + g_assert (leases == NULL); - suite = g_test_get_root (); + g_date_time_unref (now); + g_free (contents); +} - g_test_suite_add (suite, TESTCASE (test_orig_missing, NULL)); - g_test_suite_add (suite, TESTCASE (test_override_client_id, NULL)); - g_test_suite_add (suite, TESTCASE (test_override_hostname, NULL)); - g_test_suite_add (suite, TESTCASE (test_existing_alsoreq, NULL)); - g_test_suite_add (suite, TESTCASE (test_existing_multiline_alsoreq, NULL)); - g_test_suite_add (suite, TESTCASE (test_duids, NULL)); +/*******************************************/ - g_test_suite_add (suite, TESTCASE (test_read_duid_from_leasefile, NULL)); - g_test_suite_add (suite, TESTCASE (test_read_commented_duid_from_leasefile, NULL)); +int +main (int argc, char **argv) +{ + g_test_init (&argc, &argv, NULL); + +#if !GLIB_CHECK_VERSION (2, 35, 0) + g_type_init (); +#endif - g_test_suite_add (suite, TESTCASE (test_write_duid, NULL)); - g_test_suite_add (suite, TESTCASE (test_write_existing_duid, NULL)); - g_test_suite_add (suite, TESTCASE (test_write_existing_commented_duid, NULL)); + g_test_add_func ("/dhcp/dhclient/orig_missing", test_orig_missing); + g_test_add_func ("/dhcp/dhclient/override_client_id", test_override_client_id); + g_test_add_func ("/dhcp/dhclient/quote_client_id", test_quote_client_id); + g_test_add_func ("/dhcp/dhclient/ascii_client_id", test_ascii_client_id); + g_test_add_func ("/dhcp/dhclient/override_hostname", test_override_hostname); + g_test_add_func ("/dhcp/dhclient/existing_alsoreq", test_existing_alsoreq); + g_test_add_func ("/dhcp/dhclient/existing_multiline_alsoreq", test_existing_multiline_alsoreq); + g_test_add_func ("/dhcp/dhclient/duids", test_duids); + + g_test_add_func ("/dhcp/dhclient/read_duid_from_leasefile", test_read_duid_from_leasefile); + g_test_add_func ("/dhcp/dhclient/read_commented_duid_from_leasefile", test_read_commented_duid_from_leasefile); + + g_test_add_func ("/dhcp/dhclient/write_duid", test_write_duid); + g_test_add_func ("/dhcp/dhclient/write_existing_duid", test_write_existing_duid); + g_test_add_func ("/dhcp/dhclient/write_existing_commented_duid", test_write_existing_commented_duid); + + g_test_add_func ("/dhcp/dhclient/leases/ip4-config/basic", test_read_lease_ip4_config_basic); + g_test_add_func ("/dhcp/dhclient/leases/ip4-config/expired", test_read_lease_ip4_config_expired); + g_test_add_data_func ("/dhcp/dhclient/leases/ip4-config/missing-address", + TESTDIR "/leases/malformed1.leases", + test_read_lease_ip4_config_expect_failure); + g_test_add_data_func ("/dhcp/dhclient/leases/ip4-config/missing-gateway", + TESTDIR "/leases/malformed2.leases", + test_read_lease_ip4_config_expect_failure); + g_test_add_data_func ("/dhcp/dhclient/leases/ip4-config/missing-expire", + TESTDIR "/leases/malformed3.leases", + test_read_lease_ip4_config_expect_failure); return g_test_run (); } diff --git a/src/dns-manager/Makefile.am b/src/dns-manager/Makefile.am deleted file mode 100644 index 4aa20c72..00000000 --- a/src/dns-manager/Makefile.am +++ /dev/null @@ -1,35 +0,0 @@ -noinst_LTLIBRARIES = libdns-manager.la - -libdns_manager_la_CPPFLAGS = \ - -I${top_srcdir}/src/logging \ - -I${top_srcdir}/src/posix-signals \ - -I${top_srcdir}/libnm-util \ - -I${top_builddir}/libnm-util \ - -I${top_srcdir}/src \ - -I${top_srcdir}/include \ - -I${top_builddir}/include \ - $(LIBNL_CFLAGS) \ - $(DBUS_CFLAGS) \ - $(GLIB_CFLAGS) \ - -DLOCALSTATEDIR=\"$(localstatedir)\" \ - -DSYSCONFDIR=\"$(sysconfdir)\" \ - -DNMCONFDIR=\"$(nmconfdir)\" \ - -DNMRUNDIR=\"$(nmrundir)\" - -libdns_manager_la_SOURCES = \ - nm-dns-manager.h \ - nm-dns-manager.c \ - nm-dns-plugin.h \ - nm-dns-plugin.c \ - nm-dns-dnsmasq.h \ - nm-dns-dnsmasq.c \ - nm-dns-utils.h \ - nm-dns-utils.c - -libdns_manager_la_LIBADD = \ - $(top_builddir)/src/logging/libnm-logging.la \ - $(top_builddir)/src/posix-signals/libnm-posix-signals.la \ - $(LIBNL_LIBS) \ - $(DBUS_LIBS) \ - $(GLIB_LIBS) - diff --git a/src/dns-manager/Makefile.in b/src/dns-manager/Makefile.in deleted file mode 100644 index a6116fb5..00000000 --- a/src/dns-manager/Makefile.in +++ /dev/null @@ -1,775 +0,0 @@ -# Makefile.in generated by automake 1.13.4 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994-2013 Free Software Foundation, Inc. - -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ - -VPATH = @srcdir@ -am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' -am__make_running_with_option = \ - case $${target_option-} in \ - ?) ;; \ - *) echo "am__make_running_with_option: internal error: invalid" \ - "target option '$${target_option-}' specified" >&2; \ - exit 1;; \ - esac; \ - has_opt=no; \ - sane_makeflags=$$MAKEFLAGS; \ - if $(am__is_gnu_make); then \ - sane_makeflags=$$MFLAGS; \ - else \ - case $$MAKEFLAGS in \ - *\\[\ \ ]*) \ - bs=\\; \ - sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ - | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ - esac; \ - fi; \ - skip_next=no; \ - strip_trailopt () \ - { \ - flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ - }; \ - for flg in $$sane_makeflags; do \ - test $$skip_next = yes && { skip_next=no; continue; }; \ - case $$flg in \ - *=*|--*) continue;; \ - -*I) strip_trailopt 'I'; skip_next=yes;; \ - -*I?*) strip_trailopt 'I';; \ - -*O) strip_trailopt 'O'; skip_next=yes;; \ - -*O?*) strip_trailopt 'O';; \ - -*l) strip_trailopt 'l'; skip_next=yes;; \ - -*l?*) strip_trailopt 'l';; \ - -[dEDm]) skip_next=yes;; \ - -[JT]) skip_next=yes;; \ - esac; \ - case $$flg in \ - *$$target_option*) has_opt=yes; break;; \ - esac; \ - done; \ - test $$has_opt = yes -am__make_dryrun = (target_option=n; $(am__make_running_with_option)) -am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) -pkgdatadir = $(datadir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkglibexecdir = $(libexecdir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = @build@ -host_triplet = @host@ -subdir = src/dns-manager -DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ - $(top_srcdir)/build-aux/depcomp -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \ - $(top_srcdir)/m4/gettext.m4 \ - $(top_srcdir)/m4/gnome-code-coverage.m4 \ - $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ - $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \ - $(top_srcdir)/m4/introspection.m4 $(top_srcdir)/m4/lib-ld.m4 \ - $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ - $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ - $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ - $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ - $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ - $(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -mkinstalldirs = $(install_sh) -d -CONFIG_HEADER = $(top_builddir)/config.h -CONFIG_CLEAN_FILES = -CONFIG_CLEAN_VPATH_FILES = -LTLIBRARIES = $(noinst_LTLIBRARIES) -am__DEPENDENCIES_1 = -libdns_manager_la_DEPENDENCIES = \ - $(top_builddir)/src/logging/libnm-logging.la \ - $(top_builddir)/src/posix-signals/libnm-posix-signals.la \ - $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) -am_libdns_manager_la_OBJECTS = libdns_manager_la-nm-dns-manager.lo \ - libdns_manager_la-nm-dns-plugin.lo \ - libdns_manager_la-nm-dns-dnsmasq.lo \ - libdns_manager_la-nm-dns-utils.lo -libdns_manager_la_OBJECTS = $(am_libdns_manager_la_OBJECTS) -AM_V_lt = $(am__v_lt_@AM_V@) -am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) -am__v_lt_0 = --silent -am__v_lt_1 = -AM_V_P = $(am__v_P_@AM_V@) -am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) -am__v_P_0 = false -am__v_P_1 = : -AM_V_GEN = $(am__v_GEN_@AM_V@) -am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) -am__v_GEN_0 = @echo " GEN " $@; -am__v_GEN_1 = -AM_V_at = $(am__v_at_@AM_V@) -am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) -am__v_at_0 = @ -am__v_at_1 = -DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) -depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp -am__depfiles_maybe = depfiles -am__mv = mv -f -COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ - $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ - $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ - $(AM_CFLAGS) $(CFLAGS) -AM_V_CC = $(am__v_CC_@AM_V@) -am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) -am__v_CC_0 = @echo " CC " $@; -am__v_CC_1 = -CCLD = $(CC) -LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(AM_LDFLAGS) $(LDFLAGS) -o $@ -AM_V_CCLD = $(am__v_CCLD_@AM_V@) -am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) -am__v_CCLD_0 = @echo " CCLD " $@; -am__v_CCLD_1 = -SOURCES = $(libdns_manager_la_SOURCES) -DIST_SOURCES = $(libdns_manager_la_SOURCES) -am__can_run_installinfo = \ - case $$AM_UPDATE_INFO_DIR in \ - n|no|NO) false;; \ - *) (install-info --version) >/dev/null 2>&1;; \ - esac -am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) -# Read a list of newline-separated strings from the standard input, -# and print each of them once, without duplicates. Input order is -# *not* preserved. -am__uniquify_input = $(AWK) '\ - BEGIN { nonempty = 0; } \ - { items[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in items) print i; }; } \ -' -# Make sure the list of sources is unique. This is necessary because, -# e.g., the same source file might be shared among _SOURCES variables -# for different programs/libraries. -am__define_uniq_tagged_files = \ - list='$(am__tagged_files)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | $(am__uniquify_input)` -ETAGS = etags -CTAGS = ctags -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -ALL_LINGUAS = @ALL_LINGUAS@ -AMTAR = @AMTAR@ -AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -AR = @AR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CKDB_PATH = @CKDB_PATH@ -CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@ -CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@ -CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CXX = @CXX@ -CXXCPP = @CXXCPP@ -CXXDEPMODE = @CXXDEPMODE@ -CXXFLAGS = @CXXFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DATADIRNAME = @DATADIRNAME@ -DBUS_CFLAGS = @DBUS_CFLAGS@ -DBUS_LIBS = @DBUS_LIBS@ -DBUS_SYS_DIR = @DBUS_SYS_DIR@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -DHCLIENT_PATH = @DHCLIENT_PATH@ -DHCPCD_PATH = @DHCPCD_PATH@ -DLLTOOL = @DLLTOOL@ -DNSMASQ_PATH = @DNSMASQ_PATH@ -DSYMUTIL = @DSYMUTIL@ -DUMPBIN = @DUMPBIN@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -FGREP = @FGREP@ -GENHTML = @GENHTML@ -GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ -GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ -GLIB_CFLAGS = @GLIB_CFLAGS@ -GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ -GLIB_LIBS = @GLIB_LIBS@ -GLIB_MAKEFILE = @GLIB_MAKEFILE@ -GLIB_MKENUMS = @GLIB_MKENUMS@ -GMSGFMT = @GMSGFMT@ -GMSGFMT_015 = @GMSGFMT_015@ -GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ -GNUTLS_LIBS = @GNUTLS_LIBS@ -GREP = @GREP@ -GTKDOC_CHECK = @GTKDOC_CHECK@ -GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ -GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ -GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ -GTKDOC_MKPDF = @GTKDOC_MKPDF@ -GTKDOC_REBASE = @GTKDOC_REBASE@ -GUDEV_CFLAGS = @GUDEV_CFLAGS@ -GUDEV_LIBS = @GUDEV_LIBS@ -HTML_DIR = @HTML_DIR@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -INTLLIBS = @INTLLIBS@ -INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ -INTLTOOL_MERGE = @INTLTOOL_MERGE@ -INTLTOOL_PERL = @INTLTOOL_PERL@ -INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ -INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ -INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ -INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ -INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ -INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ -INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ -INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ -INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ -INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ -INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ -INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ -INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ -INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ -IPTABLES_PATH = @IPTABLES_PATH@ -IWMX_SDK_CFLAGS = @IWMX_SDK_CFLAGS@ -IWMX_SDK_LIBS = @IWMX_SDK_LIBS@ -KERNEL_FIRMWARE_DIR = @KERNEL_FIRMWARE_DIR@ -LCOV = @LCOV@ -LD = @LD@ -LDFLAGS = @LDFLAGS@ -LIBDL = @LIBDL@ -LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ -LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ -LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ -LIBICONV = @LIBICONV@ -LIBINTL = @LIBINTL@ -LIBM = @LIBM@ -LIBNL_CFLAGS = @LIBNL_CFLAGS@ -LIBNL_LIBS = @LIBNL_LIBS@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@ -LIBSOUP_LIBS = @LIBSOUP_LIBS@ -LIBTOOL = @LIBTOOL@ -LIPO = @LIPO@ -LN_S = @LN_S@ -LTLIBICONV = @LTLIBICONV@ -LTLIBINTL = @LTLIBINTL@ -LTLIBOBJS = @LTLIBOBJS@ -MAINT = @MAINT@ -MAKEINFO = @MAKEINFO@ -MANIFEST_TOOL = @MANIFEST_TOOL@ -MKDIR_P = @MKDIR_P@ -MM_GLIB_CFLAGS = @MM_GLIB_CFLAGS@ -MM_GLIB_LIBS = @MM_GLIB_LIBS@ -MOC = @MOC@ -MSGFMT = @MSGFMT@ -MSGFMT_015 = @MSGFMT_015@ -MSGMERGE = @MSGMERGE@ -NM = @NM@ -NMEDIT = @NMEDIT@ -NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ -NM_MICRO_VERSION = @NM_MICRO_VERSION@ -NM_MINOR_VERSION = @NM_MINOR_VERSION@ -NM_MODIFY_SYSTEM_POLICY = @NM_MODIFY_SYSTEM_POLICY@ -NM_VERSION = @NM_VERSION@ -NSS_CFLAGS = @NSS_CFLAGS@ -NSS_LIBS = @NSS_LIBS@ -OBJDUMP = @OBJDUMP@ -OBJEXT = @OBJEXT@ -OTOOL = @OTOOL@ -OTOOL64 = @OTOOL64@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_URL = @PACKAGE_URL@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PKG_CONFIG = @PKG_CONFIG@ -PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ -PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ -POLKIT_CFLAGS = @POLKIT_CFLAGS@ -POLKIT_LIBS = @POLKIT_LIBS@ -POSUB = @POSUB@ -PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@ -QT_CFLAGS = @QT_CFLAGS@ -QT_LIBS = @QT_LIBS@ -RANLIB = @RANLIB@ -SED = @SED@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -STRIP = @STRIP@ -SYSTEMD_200_CFLAGS = @SYSTEMD_200_CFLAGS@ -SYSTEMD_200_LIBS = @SYSTEMD_200_LIBS@ -SYSTEMD_INHIBIT_CFLAGS = @SYSTEMD_INHIBIT_CFLAGS@ -SYSTEMD_INHIBIT_LIBS = @SYSTEMD_INHIBIT_LIBS@ -SYSTEMD_LOGIN_CFLAGS = @SYSTEMD_LOGIN_CFLAGS@ -SYSTEMD_LOGIN_LIBS = @SYSTEMD_LOGIN_LIBS@ -SYSTEM_CA_PATH = @SYSTEM_CA_PATH@ -UDEV_BASE_DIR = @UDEV_BASE_DIR@ -USE_NLS = @USE_NLS@ -UUID_CFLAGS = @UUID_CFLAGS@ -UUID_LIBS = @UUID_LIBS@ -VAPIGEN = @VAPIGEN@ -VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ -VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ -VERSION = @VERSION@ -XGETTEXT = @XGETTEXT@ -XGETTEXT_015 = @XGETTEXT_015@ -XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_AR = @ac_ct_AR@ -ac_ct_CC = @ac_ct_CC@ -ac_ct_CXX = @ac_ct_CXX@ -ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -intltool__v_merge_options_ = @intltool__v_merge_options_@ -intltool__v_merge_options_0 = @intltool__v_merge_options_0@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -nmbinary = @nmbinary@ -nmconfdir = @nmconfdir@ -nmdatadir = @nmdatadir@ -nmrundir = @nmrundir@ -nmstatedir = @nmstatedir@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -sysconfdir = @sysconfdir@ -systemdsystemunitdir = @systemdsystemunitdir@ -target_alias = @target_alias@ -top_build_prefix = @top_build_prefix@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -with_dhclient = @with_dhclient@ -with_dhcpcd = @with_dhcpcd@ -with_netconfig = @with_netconfig@ -with_resolvconf = @with_resolvconf@ -noinst_LTLIBRARIES = libdns-manager.la -libdns_manager_la_CPPFLAGS = \ - -I${top_srcdir}/src/logging \ - -I${top_srcdir}/src/posix-signals \ - -I${top_srcdir}/libnm-util \ - -I${top_builddir}/libnm-util \ - -I${top_srcdir}/src \ - -I${top_srcdir}/include \ - -I${top_builddir}/include \ - $(LIBNL_CFLAGS) \ - $(DBUS_CFLAGS) \ - $(GLIB_CFLAGS) \ - -DLOCALSTATEDIR=\"$(localstatedir)\" \ - -DSYSCONFDIR=\"$(sysconfdir)\" \ - -DNMCONFDIR=\"$(nmconfdir)\" \ - -DNMRUNDIR=\"$(nmrundir)\" - -libdns_manager_la_SOURCES = \ - nm-dns-manager.h \ - nm-dns-manager.c \ - nm-dns-plugin.h \ - nm-dns-plugin.c \ - nm-dns-dnsmasq.h \ - nm-dns-dnsmasq.c \ - nm-dns-utils.h \ - nm-dns-utils.c - -libdns_manager_la_LIBADD = \ - $(top_builddir)/src/logging/libnm-logging.la \ - $(top_builddir)/src/posix-signals/libnm-posix-signals.la \ - $(LIBNL_LIBS) \ - $(DBUS_LIBS) \ - $(GLIB_LIBS) - -all: all-am - -.SUFFIXES: -.SUFFIXES: .c .lo .o .obj -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ - && { if test -f $@; then exit 0; else break; fi; }; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/dns-manager/Makefile'; \ - $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --gnu src/dns-manager/Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(am__aclocal_m4_deps): - -clean-noinstLTLIBRARIES: - -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) - @list='$(noinst_LTLIBRARIES)'; \ - locs=`for p in $$list; do echo $$p; done | \ - sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ - sort -u`; \ - test -z "$$locs" || { \ - echo rm -f $${locs}; \ - rm -f $${locs}; \ - } - -libdns-manager.la: $(libdns_manager_la_OBJECTS) $(libdns_manager_la_DEPENDENCIES) $(EXTRA_libdns_manager_la_DEPENDENCIES) - $(AM_V_CCLD)$(LINK) $(libdns_manager_la_OBJECTS) $(libdns_manager_la_LIBADD) $(LIBS) - -mostlyclean-compile: - -rm -f *.$(OBJEXT) - -distclean-compile: - -rm -f *.tab.c - -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdns_manager_la-nm-dns-dnsmasq.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdns_manager_la-nm-dns-manager.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdns_manager_la-nm-dns-plugin.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdns_manager_la-nm-dns-utils.Plo@am__quote@ - -.c.o: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< - -.c.obj: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` - -.c.lo: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< - -libdns_manager_la-nm-dns-manager.lo: nm-dns-manager.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdns_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libdns_manager_la-nm-dns-manager.lo -MD -MP -MF $(DEPDIR)/libdns_manager_la-nm-dns-manager.Tpo -c -o libdns_manager_la-nm-dns-manager.lo `test -f 'nm-dns-manager.c' || echo '$(srcdir)/'`nm-dns-manager.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdns_manager_la-nm-dns-manager.Tpo $(DEPDIR)/libdns_manager_la-nm-dns-manager.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-dns-manager.c' object='libdns_manager_la-nm-dns-manager.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdns_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libdns_manager_la-nm-dns-manager.lo `test -f 'nm-dns-manager.c' || echo '$(srcdir)/'`nm-dns-manager.c - -libdns_manager_la-nm-dns-plugin.lo: nm-dns-plugin.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdns_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libdns_manager_la-nm-dns-plugin.lo -MD -MP -MF $(DEPDIR)/libdns_manager_la-nm-dns-plugin.Tpo -c -o libdns_manager_la-nm-dns-plugin.lo `test -f 'nm-dns-plugin.c' || echo '$(srcdir)/'`nm-dns-plugin.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdns_manager_la-nm-dns-plugin.Tpo $(DEPDIR)/libdns_manager_la-nm-dns-plugin.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-dns-plugin.c' object='libdns_manager_la-nm-dns-plugin.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdns_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libdns_manager_la-nm-dns-plugin.lo `test -f 'nm-dns-plugin.c' || echo '$(srcdir)/'`nm-dns-plugin.c - -libdns_manager_la-nm-dns-dnsmasq.lo: nm-dns-dnsmasq.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdns_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libdns_manager_la-nm-dns-dnsmasq.lo -MD -MP -MF $(DEPDIR)/libdns_manager_la-nm-dns-dnsmasq.Tpo -c -o libdns_manager_la-nm-dns-dnsmasq.lo `test -f 'nm-dns-dnsmasq.c' || echo '$(srcdir)/'`nm-dns-dnsmasq.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdns_manager_la-nm-dns-dnsmasq.Tpo $(DEPDIR)/libdns_manager_la-nm-dns-dnsmasq.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-dns-dnsmasq.c' object='libdns_manager_la-nm-dns-dnsmasq.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdns_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libdns_manager_la-nm-dns-dnsmasq.lo `test -f 'nm-dns-dnsmasq.c' || echo '$(srcdir)/'`nm-dns-dnsmasq.c - -libdns_manager_la-nm-dns-utils.lo: nm-dns-utils.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdns_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libdns_manager_la-nm-dns-utils.lo -MD -MP -MF $(DEPDIR)/libdns_manager_la-nm-dns-utils.Tpo -c -o libdns_manager_la-nm-dns-utils.lo `test -f 'nm-dns-utils.c' || echo '$(srcdir)/'`nm-dns-utils.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdns_manager_la-nm-dns-utils.Tpo $(DEPDIR)/libdns_manager_la-nm-dns-utils.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-dns-utils.c' object='libdns_manager_la-nm-dns-utils.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdns_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libdns_manager_la-nm-dns-utils.lo `test -f 'nm-dns-utils.c' || echo '$(srcdir)/'`nm-dns-utils.c - -mostlyclean-libtool: - -rm -f *.lo - -clean-libtool: - -rm -rf .libs _libs - -ID: $(am__tagged_files) - $(am__define_uniq_tagged_files); mkid -fID $$unique -tags: tags-am -TAGS: tags - -tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) - set x; \ - here=`pwd`; \ - $(am__define_uniq_tagged_files); \ - shift; \ - if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ - test -n "$$unique" || unique=$$empty_fix; \ - if test $$# -gt 0; then \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - "$$@" $$unique; \ - else \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$unique; \ - fi; \ - fi -ctags: ctags-am - -CTAGS: ctags -ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) - $(am__define_uniq_tagged_files); \ - test -z "$(CTAGS_ARGS)$$unique" \ - || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$unique - -GTAGS: - here=`$(am__cd) $(top_builddir) && pwd` \ - && $(am__cd) $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) "$$here" -cscopelist: cscopelist-am - -cscopelist-am: $(am__tagged_files) - list='$(am__tagged_files)'; \ - case "$(srcdir)" in \ - [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ - *) sdir=$(subdir)/$(srcdir) ;; \ - esac; \ - for i in $$list; do \ - if test -f "$$i"; then \ - echo "$(subdir)/$$i"; \ - else \ - echo "$$sdir/$$i"; \ - fi; \ - done >> $(top_builddir)/cscope.files - -distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags - -distdir: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d "$(distdir)/$$file"; then \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ - else \ - test -f "$(distdir)/$$file" \ - || cp -p $$d/$$file "$(distdir)/$$file" \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: check-am -all-am: Makefile $(LTLIBRARIES) -installdirs: -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - if test -z '$(STRIP)'; then \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - install; \ - else \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ - fi -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." -clean: clean-am - -clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ - mostlyclean-am - -distclean: distclean-am - -rm -rf ./$(DEPDIR) - -rm -f Makefile -distclean-am: clean-am distclean-compile distclean-generic \ - distclean-tags - -dvi: dvi-am - -dvi-am: - -html: html-am - -html-am: - -info: info-am - -info-am: - -install-data-am: - -install-dvi: install-dvi-am - -install-dvi-am: - -install-exec-am: - -install-html: install-html-am - -install-html-am: - -install-info: install-info-am - -install-info-am: - -install-man: - -install-pdf: install-pdf-am - -install-pdf-am: - -install-ps: install-ps-am - -install-ps-am: - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -rf ./$(DEPDIR) - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-compile mostlyclean-generic \ - mostlyclean-libtool - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: - -.MAKE: install-am install-strip - -.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ - clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ - ctags-am distclean distclean-compile distclean-generic \ - distclean-libtool distclean-tags distdir dvi dvi-am html \ - html-am info info-am install install-am install-data \ - install-data-am install-dvi install-dvi-am install-exec \ - install-exec-am install-html install-html-am install-info \ - install-info-am install-man install-pdf install-pdf-am \ - install-ps install-ps-am install-strip installcheck \ - installcheck-am installdirs maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-compile \ - mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ - tags tags-am uninstall uninstall-am - - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/src/dns-manager/nm-dns-dnsmasq.c b/src/dns-manager/nm-dns-dnsmasq.c index 1f6e5868..8367693d 100644 --- a/src/dns-manager/nm-dns-dnsmasq.c +++ b/src/dns-manager/nm-dns-dnsmasq.c @@ -30,6 +30,7 @@ #include #include "nm-dns-dnsmasq.h" +#include "nm-utils.h" #include "nm-logging.h" #include "nm-ip4-config.h" #include "nm-ip6-config.h" @@ -72,7 +73,7 @@ find_dnsmasq (void) static gboolean add_ip4_config (GString *str, NMIP4Config *ip4, gboolean split) { - char buf[INET_ADDRSTRLEN + 1]; + char buf[INET_ADDRSTRLEN]; in_addr_t addr; int nnameservers, i_nameserver, n, i; gboolean added = FALSE; @@ -87,9 +88,7 @@ add_ip4_config (GString *str, NMIP4Config *ip4, gboolean split) for (i_nameserver = 0; i_nameserver < nnameservers; i_nameserver++) { addr = nm_ip4_config_get_nameserver (ip4, i_nameserver); - memset (&buf[0], 0, sizeof (buf)); - if (!inet_ntop (AF_INET, &addr, buf, sizeof (buf))) - return FALSE; + nm_utils_inet4_ntop (addr, buf); /* searches are preferred over domains */ n = nm_ip4_config_get_num_searches (ip4); @@ -127,59 +126,34 @@ add_ip4_config (GString *str, NMIP4Config *ip4, gboolean split) /* If no searches or domains, just add the namservers */ if (!added) { for (i = 0; i < nnameservers; i++) { - memset (&buf[0], 0, sizeof (buf)); addr = nm_ip4_config_get_nameserver (ip4, i); - if (inet_ntop (AF_INET, &addr, buf, sizeof (buf))) - g_string_append_printf (str, "server=%s\n", buf); + g_string_append_printf (str, "server=%s\n", nm_utils_inet4_ntop (addr, NULL)); } } return TRUE; } -#define IP6_ADDR_BUFLEN (INET6_ADDRSTRLEN + 50) - static char * ip6_addr_to_string (const struct in6_addr *addr, const char *iface) { - char *buf, *p; - - /* allocate enough space for the address + interface name */ - buf = g_malloc0 (IP6_ADDR_BUFLEN + 1); + char *buf; - /* inet_ntop is probably supposed to do this for us, but it doesn't */ if (IN6_IS_ADDR_V4MAPPED (addr)) { - if (!inet_ntop (AF_INET, &(addr->s6_addr32[3]), buf, IP6_ADDR_BUFLEN)) - goto error; - return buf; - } - - if (!inet_ntop (AF_INET6, addr, buf, IP6_ADDR_BUFLEN)) - goto error; - - /* In the case of addr being a link-local address, inet_ntop can either - * return an address with scope identifier already in place (like - * fe80::202:b3ff:fe8d:7aaf%wlan0) or it returns an address without - * scope identifier at all (like fe80::202:b3ff:fe8d:7aaf) - */ - p = strchr (buf, '%'); - if (p) { - /* If we got a scope identifier, we need to replace the '%' - * with '@', since dnsmasq supports '%' in server= addresses + /* inet_ntop is probably supposed to do this for us, but it doesn't */ + buf = g_malloc (INET_ADDRSTRLEN); + nm_utils_inet4_ntop (addr->s6_addr32[3], buf); + } else if (!iface || !iface[0] || !IN6_IS_ADDR_LINKLOCAL (addr)) { + buf = g_malloc (INET6_ADDRSTRLEN); + nm_utils_inet6_ntop (addr, buf); + } else { + /* If we got a scope identifier, we need use '%' instead of + * '@', since dnsmasq supports '%' in server= addresses * only since version 2.58 and up */ - *p = '@'; - } else if (IN6_IS_ADDR_LINKLOCAL (addr)) { - /* If we got no scope identifier at all append the interface name */ - strncat (buf, "@", IP6_ADDR_BUFLEN - strlen (buf)); - strncat (buf, iface, IP6_ADDR_BUFLEN - strlen (buf)); + buf = g_strconcat (nm_utils_inet6_ntop (addr, NULL), "@", iface, NULL); } - return buf; - -error: - g_free (buf); - return NULL; } static gboolean @@ -203,8 +177,6 @@ add_ip6_config (GString *str, NMIP6Config *ip6, gboolean split) for (i_nameserver = 0; i_nameserver < nnameservers; i_nameserver++) { addr = nm_ip6_config_get_nameserver (ip6, i_nameserver); buf = ip6_addr_to_string (addr, iface); - if (!buf) - return FALSE; /* searches are preferred over domains */ n = nm_ip6_config_get_num_searches (ip6); @@ -225,9 +197,9 @@ add_ip6_config (GString *str, NMIP6Config *ip6, gboolean split) added = TRUE; } } - } - g_free (buf); + g_free (buf); + } } /* If no searches or domains, just add the namservers */ @@ -385,12 +357,6 @@ child_quit (NMDnsPlugin *plugin, gint status) /****************************************************************/ -static gboolean -init (NMDnsPlugin *plugin) -{ - return TRUE; -} - static gboolean is_caching (NMDnsPlugin *plugin) { @@ -405,10 +371,10 @@ get_name (NMDnsPlugin *plugin) /****************************************************************/ -NMDnsDnsmasq * +NMDnsPlugin * nm_dns_dnsmasq_new (void) { - return (NMDnsDnsmasq *) g_object_new (NM_TYPE_DNS_DNSMASQ, NULL); + return g_object_new (NM_TYPE_DNS_DNSMASQ, NULL); } static void @@ -434,7 +400,6 @@ nm_dns_dnsmasq_class_init (NMDnsDnsmasqClass *dns_class) object_class->dispose = dispose; - plugin_class->init = init; plugin_class->child_quit = child_quit; plugin_class->is_caching = is_caching; plugin_class->update = update; diff --git a/src/dns-manager/nm-dns-dnsmasq.h b/src/dns-manager/nm-dns-dnsmasq.h index 01ec5791..70933c0f 100644 --- a/src/dns-manager/nm-dns-dnsmasq.h +++ b/src/dns-manager/nm-dns-dnsmasq.h @@ -41,7 +41,7 @@ typedef struct { GType nm_dns_dnsmasq_get_type (void); -NMDnsDnsmasq *nm_dns_dnsmasq_new (void); +NMDnsPlugin *nm_dns_dnsmasq_new (void); #endif /* NM_DNS_DNSMASQ_H */ diff --git a/src/dns-manager/nm-dns-manager.c b/src/dns-manager/nm-dns-manager.c index fb426637..466aa9a8 100644 --- a/src/dns-manager/nm-dns-manager.c +++ b/src/dns-manager/nm-dns-manager.c @@ -23,17 +23,16 @@ #include "config.h" -#include -#include -#include -#include #include -#include -#include -#include +#include +#include +#include +#include #include -#include +#include + +#include #include #include "nm-dns-manager.h" @@ -42,15 +41,27 @@ #include "nm-logging.h" #include "NetworkManagerUtils.h" #include "nm-posix-signals.h" +#include "nm-config.h" #include "nm-dns-plugin.h" #include "nm-dns-dnsmasq.h" +#include "nm-dns-unbound.h" + +#if HAVE_LIBSOUP +#include -#ifndef RESOLV_CONF -#define RESOLV_CONF "/etc/resolv.conf" +#ifdef SOUP_CHECK_VERSION +#if SOUP_CHECK_VERSION (2, 40, 0) +#define DOMAIN_IS_VALID(domain) (*(domain) && !soup_tld_domain_is_public_suffix (domain)) +#endif +#endif #endif -G_DEFINE_TYPE(NMDnsManager, nm_dns_manager, G_TYPE_OBJECT) +#ifndef DOMAIN_IS_VALID +#define DOMAIN_IS_VALID(domain) (*(domain)) +#endif + +G_DEFINE_TYPE (NMDnsManager, nm_dns_manager, G_TYPE_OBJECT) #define NM_DNS_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \ NM_TYPE_DNS_MANAGER, \ @@ -59,8 +70,6 @@ G_DEFINE_TYPE(NMDnsManager, nm_dns_manager, G_TYPE_OBJECT) #define HASH_LEN 20 typedef struct { - gboolean disposed; - NMIP4Config *ip4_vpn_config; NMIP4Config *ip4_device_config; NMIP6Config *ip6_vpn_config; @@ -72,7 +81,8 @@ typedef struct { guint8 hash[HASH_LEN]; /* SHA1 hash of current DNS config */ guint8 prev_hash[HASH_LEN]; /* Hash when begin_updates() was called */ - GSList *plugins; + NMDnsManagerResolvConfMode resolv_conf_mode; + NMDnsPlugin *plugin; gboolean dns_touched; } NMDnsManagerPrivate; @@ -88,7 +98,6 @@ static guint signals[LAST_SIGNAL] = { 0 }; typedef struct { GPtrArray *nameservers; - const char *domain; GPtrArray *searches; const char *nis_domain; GPtrArray *nis_servers; @@ -121,10 +130,10 @@ merge_one_ip4_config (NMResolvConfData *rc, NMIP4Config *src) num = nm_ip4_config_get_num_nameservers (src); for (i = 0; i < num; i++) { - struct in_addr addr; + guint32 addr; char buf[INET_ADDRSTRLEN]; - addr.s_addr = nm_ip4_config_get_nameserver (src, i); + addr = nm_ip4_config_get_nameserver (src, i); if (inet_ntop (AF_INET, &addr, buf, INET_ADDRSTRLEN) > 0) add_string_item (rc->nameservers, buf); } @@ -134,22 +143,28 @@ merge_one_ip4_config (NMResolvConfData *rc, NMIP4Config *src) const char *domain; domain = nm_ip4_config_get_domain (src, i); - if (!rc->domain) - rc->domain = domain; + if (!DOMAIN_IS_VALID (domain)) + continue; add_string_item (rc->searches, domain); } num = nm_ip4_config_get_num_searches (src); - for (i = 0; i < num; i++) - add_string_item (rc->searches, nm_ip4_config_get_search (src, i)); + for (i = 0; i < num; i++) { + const char *search; + + search = nm_ip4_config_get_search (src, i); + if (!DOMAIN_IS_VALID (search)) + continue; + add_string_item (rc->searches, search); + } /* NIS stuff */ num = nm_ip4_config_get_num_nis_servers (src); for (i = 0; i < num; i++) { - struct in_addr addr; + guint32 addr; char buf[INET_ADDRSTRLEN]; - addr.s_addr = nm_ip4_config_get_nis_server (src, i); + addr = nm_ip4_config_get_nis_server (src, i); if (inet_ntop (AF_INET, &addr, buf, INET_ADDRSTRLEN) > 0) add_string_item (rc->nis_servers, buf); } @@ -168,7 +183,6 @@ merge_one_ip6_config (NMResolvConfData *rc, NMIP6Config *src) const char *iface; iface = g_object_get_data (G_OBJECT (src), IP_CONFIG_IFACE_TAG); - g_assert (iface); num = nm_ip6_config_get_num_nameservers (src); for (i = 0; i < num; i++) { @@ -184,7 +198,7 @@ merge_one_ip6_config (NMResolvConfData *rc, NMIP6Config *src) add_string_item (rc->nameservers, buf); } else { if (inet_ntop (AF_INET6, addr, buf, INET6_ADDRSTRLEN) > 0) { - if (IN6_IS_ADDR_LINKLOCAL (addr) && strchr (buf, '%') == NULL) { + if (iface && IN6_IS_ADDR_LINKLOCAL (addr)) { tmp = g_strdup_printf ("%s%%%s", buf, iface); add_string_item (rc->nameservers, tmp); g_free (tmp); @@ -199,14 +213,20 @@ merge_one_ip6_config (NMResolvConfData *rc, NMIP6Config *src) const char *domain; domain = nm_ip6_config_get_domain (src, i); - if (!rc->domain) - rc->domain = domain; + if (!DOMAIN_IS_VALID (domain)) + continue; add_string_item (rc->searches, domain); } num = nm_ip6_config_get_num_searches (src); - for (i = 0; i < num; i++) - add_string_item (rc->searches, nm_ip6_config_get_search (src, i)); + for (i = 0; i < num; i++) { + const char *search; + + search = nm_ip6_config_get_search (src, i); + if (!DOMAIN_IS_VALID (search)) + continue; + add_string_item (rc->searches, search); + } } @@ -264,8 +284,7 @@ write_to_netconfig (gint fd, const char *key, const char *value) } static gboolean -dispatch_netconfig (const char *domain, - char **searches, +dispatch_netconfig (char **searches, char **nameservers, const char *nis_domain, char **nis_servers, @@ -288,12 +307,6 @@ dispatch_netconfig (const char *domain, if (searches) { str = g_strjoinv (" ", searches); - if (domain) { - tmp = g_strconcat (domain, " ", str, NULL); - g_free (str); - str = tmp; - } - write_to_netconfig (fd, "DNSSEARCH", str); g_free (str); } @@ -333,12 +346,11 @@ dispatch_netconfig (const char *domain, static gboolean -write_resolv_conf (FILE *f, const char *domain, +write_resolv_conf (FILE *f, char **searches, char **nameservers, GError **error) { - char *domain_str = NULL; char *searches_str = NULL; char *nameservers_str = NULL; int i; @@ -349,14 +361,11 @@ write_resolv_conf (FILE *f, const char *domain, g_set_error (error, NM_DNS_MANAGER_ERROR, NM_DNS_MANAGER_ERROR_SYSTEM, - "Could not write " RESOLV_CONF ": %s\n", + "Could not write " _PATH_RESCONF ": %s\n", g_strerror (errno)); return FALSE; } - if (domain) - domain_str = g_strconcat ("domain ", domain, "\n", NULL); - if (searches) { char *tmp_str; @@ -387,13 +396,11 @@ write_resolv_conf (FILE *f, const char *domain, nameservers_str = g_string_free (str, FALSE); - if (fprintf (f, "%s%s%s", - domain_str ? domain_str : "", + if (fprintf (f, "%s%s", searches_str ? searches_str : "", strlen (nameservers_str) ? nameservers_str : "") != -1) retval = TRUE; - g_free (domain_str); g_free (searches_str); g_free (nameservers_str); @@ -402,8 +409,7 @@ write_resolv_conf (FILE *f, const char *domain, #ifdef RESOLVCONF_PATH static gboolean -dispatch_resolvconf (const char *domain, - char **searches, +dispatch_resolvconf (char **searches, char **nameservers, GError **error) { @@ -414,7 +420,7 @@ dispatch_resolvconf (const char *domain, if (! g_file_test (RESOLVCONF_PATH, G_FILE_TEST_IS_EXECUTABLE)) return FALSE; - if (domain || searches || nameservers) { + if (searches || nameservers) { cmd = g_strconcat (RESOLVCONF_PATH, " -a ", "NetworkManager", NULL); nm_log_info (LOGD_DNS, "Writing DNS information to %s", RESOLVCONF_PATH); if ((f = popen (cmd, "w")) == NULL) @@ -425,7 +431,7 @@ dispatch_resolvconf (const char *domain, RESOLVCONF_PATH, g_strerror (errno)); else { - retval = write_resolv_conf (f, domain, searches, nameservers, error); + retval = write_resolv_conf (f, searches, nameservers, error); retval &= (pclose (f) == 0); } } else { @@ -442,8 +448,7 @@ dispatch_resolvconf (const char *domain, #endif static gboolean -update_resolv_conf (const char *domain, - char **searches, +update_resolv_conf (char **searches, char **nameservers, GError **error) { @@ -457,9 +462,9 @@ update_resolv_conf (const char *domain, g_return_val_if_fail (error != NULL, FALSE); /* Find the real path of resolv.conf; it could be a symlink to something */ - resolv_conf_realpath = realpath (RESOLV_CONF, NULL); + resolv_conf_realpath = realpath (_PATH_RESCONF, NULL); if (!resolv_conf_realpath) - resolv_conf_realpath = strdup (RESOLV_CONF); + resolv_conf_realpath = strdup (_PATH_RESCONF); /* Build up the real path for the temp resolv.conf that we're about to * write out. @@ -474,24 +479,24 @@ update_resolv_conf (const char *domain, if ((f = fopen (tmp_resolv_conf_realpath, "w")) == NULL) { do_rename = 0; old_errno = errno; - if ((f = fopen (RESOLV_CONF, "w")) == NULL) { + if ((f = fopen (_PATH_RESCONF, "w")) == NULL) { g_set_error (error, NM_DNS_MANAGER_ERROR, NM_DNS_MANAGER_ERROR_SYSTEM, "Could not open %s: %s\nCould not open %s: %s\n", tmp_resolv_conf_realpath, g_strerror (old_errno), - RESOLV_CONF, + _PATH_RESCONF, g_strerror (errno)); goto out; } /* Update tmp_resolv_conf_realpath so the error message on fclose() * failure will be correct. */ - strcpy (tmp_resolv_conf_realpath, RESOLV_CONF); + strcpy (tmp_resolv_conf_realpath, _PATH_RESCONF); } - write_resolv_conf (f, domain, searches, nameservers, error); + write_resolv_conf (f, searches, nameservers, error); if (fclose (f) < 0) { if (*error == NULL) { @@ -515,7 +520,7 @@ update_resolv_conf (const char *domain, g_set_error (error, NM_DNS_MANAGER_ERROR, NM_DNS_MANAGER_ERROR_SYSTEM, - "Could not replace " RESOLV_CONF ": %s\n", + "Could not replace " _PATH_RESCONF ": %s\n", g_strerror (errno)); } } @@ -573,7 +578,6 @@ update_dns (NMDnsManager *self, NMDnsManagerPrivate *priv; NMResolvConfData rc; GSList *iter, *vpn_configs = NULL, *dev_configs = NULL, *other_configs = NULL; - const char *domain = NULL; const char *nis_domain = NULL; char **searches = NULL; char **nameservers = NULL; @@ -586,6 +590,9 @@ update_dns (NMDnsManager *self, priv = NM_DNS_MANAGER_GET_PRIVATE (self); + if (priv->resolv_conf_mode == NM_DNS_MANAGER_RESOLV_CONF_UNMANAGED) + return TRUE; + priv->dns_touched = TRUE; nm_log_dbg (LOGD_DNS, "updating resolv.conf"); @@ -594,7 +601,6 @@ update_dns (NMDnsManager *self, compute_hash (self, priv->hash); rc.nameservers = g_ptr_array_new (); - rc.domain = NULL; rc.searches = g_ptr_array_new (); rc.nis_domain = NULL; rc.nis_servers = g_ptr_array_new (); @@ -628,22 +634,25 @@ update_dns (NMDnsManager *self, g_assert_not_reached (); } - /* Add the current domain name (from the hostname) to the searches list; - * see rh #600407. The bug report is that when the hostname is set to - * something like 'dcbw.foobar.com' (ie an FQDN) that pinging 'dcbw' doesn't - * work because the resolver doesn't have anything to append to 'dcbw' when - * looking it up. + /* If the hostname is a FQDN ("dcbw.example.com"), then add the domain part of it + * ("example.com") to the searches list, to ensure that we can still resolve its + * non-FQ form ("dcbw") too. (Also, if there are no other search domains specified, + * this makes a good default.) However, if the hostname is the top level of a domain + * (eg, "example.com"), then use the hostname itself as the search (since the user is + * unlikely to want "com" as a search domain). */ if (priv->hostname) { - const char *hostsearch = strchr (priv->hostname, '.'); - - /* +1 to get rid of the dot */ - if (hostsearch && strlen (hostsearch + 1)) - add_string_item (rc.searches, hostsearch + 1); + const char *hostdomain = strchr (priv->hostname, '.'); + + if (hostdomain) { + hostdomain++; + if (DOMAIN_IS_VALID (hostdomain)) + add_string_item (rc.searches, hostdomain); + else if (DOMAIN_IS_VALID (priv->hostname)) + add_string_item (rc.searches, priv->hostname); + } } - domain = rc.domain; - /* Per 'man resolv.conf', the search list is limited to 6 domains * totalling 256 characters. */ @@ -697,15 +706,15 @@ update_dns (NMDnsManager *self, } /* Let any plugins do their thing first */ - for (iter = priv->plugins; iter; iter = g_slist_next (iter)) { - NMDnsPlugin *plugin = NM_DNS_PLUGIN (iter->data); + if (priv->plugin) { + NMDnsPlugin *plugin = priv->plugin; const char *plugin_name = nm_dns_plugin_get_name (plugin); if (nm_dns_plugin_is_caching (plugin)) { if (no_caching) { nm_log_dbg (LOGD_DNS, "DNS: plugin %s ignored (caching disabled)", plugin_name); - continue; + goto skip; } caching = TRUE; } @@ -723,7 +732,11 @@ update_dns (NMDnsManager *self, */ caching = FALSE; } + + skip: + ; } + g_slist_free (vpn_configs); g_slist_free (dev_configs); g_slist_free (other_configs); @@ -740,18 +753,18 @@ update_dns (NMDnsManager *self, } #ifdef RESOLVCONF_PATH - success = dispatch_resolvconf (domain, searches, nameservers, error); + success = dispatch_resolvconf (searches, nameservers, error); #endif #ifdef NETCONFIG_PATH if (success == FALSE) { - success = dispatch_netconfig (domain, searches, nameservers, + success = dispatch_netconfig (searches, nameservers, nis_domain, nis_servers, error); } #endif if (success == FALSE) - success = update_resolv_conf (domain, searches, nameservers, error); + success = update_resolv_conf (searches, nameservers, error); /* signal that resolv.conf was changed */ if (success) @@ -796,7 +809,6 @@ nm_dns_manager_add_ip4_config (NMDnsManager *mgr, GError *error = NULL; g_return_val_if_fail (mgr != NULL, FALSE); - g_return_val_if_fail (iface != NULL, FALSE); g_return_val_if_fail (config != NULL, FALSE); priv = NM_DNS_MANAGER_GET_PRIVATE (mgr); @@ -874,7 +886,6 @@ nm_dns_manager_add_ip6_config (NMDnsManager *mgr, GError *error = NULL; g_return_val_if_fail (mgr != NULL, FALSE); - g_return_val_if_fail (iface != NULL, FALSE); g_return_val_if_fail (config != NULL, FALSE); priv = NM_DNS_MANAGER_GET_PRIVATE (mgr); @@ -942,9 +953,18 @@ nm_dns_manager_remove_ip6_config (NMDnsManager *mgr, NMIP6Config *config) return TRUE; } +void +nm_dns_manager_set_initial_hostname (NMDnsManager *mgr, + const char *hostname) +{ + NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (mgr); + + priv->hostname = g_strdup (hostname); +} + void nm_dns_manager_set_hostname (NMDnsManager *mgr, - const char *hostname) + const char *hostname) { NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (mgr); GError *error = NULL; @@ -966,10 +986,6 @@ nm_dns_manager_set_hostname (NMDnsManager *mgr, g_free (priv->hostname); priv->hostname = g_strdup (filtered); - /* Passing the last interface here is completely bogus, but SUSE's netconfig - * wants one. But hostname changes are system-wide and *not* tied to a - * specific interface, so netconfig can't really handle this. Fake it. - */ if (!priv->updates_queue && !update_dns (mgr, FALSE, &error)) { nm_log_warn (LOGD_DNS, "could not commit DNS changes: (%d) %s", error ? error->code : -1, @@ -978,6 +994,12 @@ nm_dns_manager_set_hostname (NMDnsManager *mgr, } } +NMDnsManagerResolvConfMode +nm_dns_manager_get_resolv_conf_mode (NMDnsManager *mgr) +{ + return NM_DNS_MANAGER_GET_PRIVATE (mgr)->resolv_conf_mode; +} + void nm_dns_manager_begin_updates (NMDnsManager *mgr, const char *func) { @@ -1030,62 +1052,17 @@ nm_dns_manager_end_updates (NMDnsManager *mgr, const char *func) memset (priv->prev_hash, 0, sizeof (priv->prev_hash)); } -static void -load_plugins (NMDnsManager *self, const char **plugins) -{ - NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self); - NMDnsPlugin *plugin; - const char **iter; - gboolean have_caching = FALSE; - - if (plugins && *plugins) { - /* Create each configured plugin */ - for (iter = plugins; iter && *iter; iter++) { - if (!strcasecmp (*iter, "dnsmasq")) - plugin = NM_DNS_PLUGIN (nm_dns_dnsmasq_new ()); - else { - nm_log_warn (LOGD_DNS, "Unknown DNS plugin '%s'", *iter);\ - continue; - } - g_assert (plugin); - - /* Only one caching DNS plugin is allowed */ - if (nm_dns_plugin_is_caching (plugin)) { - if (have_caching) { - nm_log_warn (LOGD_DNS, - "Ignoring plugin %s; only one caching DNS " - "plugin is allowed.", - *iter); - g_object_unref (plugin); - continue; - } - have_caching = TRUE; - } - - nm_log_info (LOGD_DNS, "DNS: loaded plugin %s", nm_dns_plugin_get_name (plugin)); - priv->plugins = g_slist_append (priv->plugins, plugin); - g_signal_connect (plugin, NM_DNS_PLUGIN_FAILED, - G_CALLBACK (plugin_failed), - self); - } - } else { - /* Create default plugins */ - } -} - /******************************************************************/ NMDnsManager * -nm_dns_manager_get (const char **plugins) +nm_dns_manager_get (void) { static NMDnsManager * singleton = NULL; if (!singleton) { singleton = NM_DNS_MANAGER (g_object_new (NM_TYPE_DNS_MANAGER, NULL)); g_assert (singleton); - load_plugins (singleton, plugins); - } else - g_object_ref (singleton); + } return singleton; } @@ -1100,11 +1077,57 @@ nm_dns_manager_error_quark (void) return quark; } +static void +init_resolv_conf_mode (NMDnsManager *self) +{ + NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self); + const char *mode; + int fd, flags; + + fd = open (_PATH_RESCONF, O_RDONLY); + if (fd != -1) { + if (ioctl (fd, FS_IOC_GETFLAGS, &flags) == -1) + flags = 0; + close (fd); + + if (flags & FS_IMMUTABLE_FL) { + nm_log_info (LOGD_DNS, "DNS: " _PATH_RESCONF " is immutable; not managing"); + priv->resolv_conf_mode = NM_DNS_MANAGER_RESOLV_CONF_UNMANAGED; + return; + } + } + + mode = nm_config_get_dns_mode (nm_config_get ()); + if (!g_strcmp0 (mode, "none")) { + priv->resolv_conf_mode = NM_DNS_MANAGER_RESOLV_CONF_UNMANAGED; + nm_log_info (LOGD_DNS, "DNS: not managing " _PATH_RESCONF); + } else if (!g_strcmp0 (mode, "dnsmasq")) { + priv->resolv_conf_mode = NM_DNS_MANAGER_RESOLV_CONF_PROXY; + priv->plugin = nm_dns_dnsmasq_new (); + } else if (!g_strcmp0 (mode, "unbound")) { + priv->resolv_conf_mode = NM_DNS_MANAGER_RESOLV_CONF_PROXY; + priv->plugin = nm_dns_unbound_new (); + } else { + priv->resolv_conf_mode = NM_DNS_MANAGER_RESOLV_CONF_EXPLICIT; + if (mode && g_strcmp0 (mode, "default") != 0) + nm_log_warn (LOGD_DNS, "Unknown DNS mode '%s'", mode); + } +} + static void nm_dns_manager_init (NMDnsManager *self) { + NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self); + /* Set the initial hash */ compute_hash (self, NM_DNS_MANAGER_GET_PRIVATE (self)->hash); + + init_resolv_conf_mode (self); + + if (priv->plugin) { + nm_log_info (LOGD_DNS, "DNS: loaded plugin %s", nm_dns_plugin_get_name (priv->plugin)); + g_signal_connect (priv->plugin, NM_DNS_PLUGIN_FAILED, G_CALLBACK (plugin_failed), self); + } } static void @@ -1114,30 +1137,24 @@ dispose (GObject *object) NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self); GError *error = NULL; - if (priv->disposed == FALSE) { - priv->disposed = TRUE; - - g_slist_foreach (priv->plugins, (GFunc) g_object_unref, NULL); - g_slist_free (priv->plugins); - priv->plugins = NULL; - - /* If we're quitting leave a valid resolv.conf in place, not one - * pointing to 127.0.0.1 if any plugins were active. Thus update - * DNS after disposing of all plugins. But if we haven't done any - * DNS updates yet, there's no reason to touch resolv.conf on shutdown. - */ - if (priv->dns_touched && !update_dns (self, TRUE, &error)) { - nm_log_warn (LOGD_DNS, "could not commit DNS changes on shutdown: (%d) %s", - error ? error->code : -1, - error && error->message ? error->message : "(unknown)"); - g_clear_error (&error); - } + g_clear_object (&priv->plugin); - g_slist_foreach (priv->configs, (GFunc) g_object_unref, NULL); - g_slist_free (priv->configs); - priv->configs = NULL; + /* If we're quitting, leave a valid resolv.conf in place, not one + * pointing to 127.0.0.1 if any plugins were active. Thus update + * DNS after disposing of all plugins. But if we haven't done any + * DNS updates yet, there's no reason to touch resolv.conf on shutdown. + */ + if (priv->dns_touched && !update_dns (self, TRUE, &error)) { + nm_log_warn (LOGD_DNS, "could not commit DNS changes on shutdown: (%d) %s", + error ? error->code : -1, + error && error->message ? error->message : "(unknown)"); + g_clear_error (&error); + priv->dns_touched = FALSE; } + g_slist_free_full (priv->configs, g_object_unref); + priv->configs = NULL; + G_OBJECT_CLASS (nm_dns_manager_parent_class)->dispose (object); } diff --git a/src/dns-manager/nm-dns-manager.h b/src/dns-manager/nm-dns-manager.h index 0fd4c198..b2bf2467 100644 --- a/src/dns-manager/nm-dns-manager.h +++ b/src/dns-manager/nm-dns-manager.h @@ -67,7 +67,7 @@ typedef struct { GType nm_dns_manager_get_type (void); -NMDnsManager * nm_dns_manager_get (const char **plugins); +NMDnsManager * nm_dns_manager_get (void); /* Allow changes to be batched together */ void nm_dns_manager_begin_updates (NMDnsManager *mgr, const char *func); @@ -87,8 +87,30 @@ gboolean nm_dns_manager_add_ip6_config (NMDnsManager *mgr, gboolean nm_dns_manager_remove_ip6_config (NMDnsManager *mgr, NMIP6Config *config); -void nm_dns_manager_set_hostname (NMDnsManager *mgr, - const char *hostname); +void nm_dns_manager_set_initial_hostname (NMDnsManager *mgr, + const char *hostname); +void nm_dns_manager_set_hostname (NMDnsManager *mgr, + const char *hostname); + +/** + * NMDnsManagerResolvConfMode: + * @NM_DNS_MANAGER_RESOLV_CONF_UNMANAGED: NM is not managing resolv.conf + * @NM_DNS_MANAGER_RESOLV_CONF_EXPLICIT: NM is managing resolv.conf by + * adding and removing "nameserver" lines corresponding to the currently + * active connections + * @NM_DNS_MANAGER_RESOLV_CONF_PROXY: NM is managing resolv.conf by + * pointing it to some other service (eg, dnsmasq) that knows the + * nameservers corresponding to the currently active connections. + * + * NMDnsManager's behavior toward /etc/resolv.conf. + */ +typedef enum { + NM_DNS_MANAGER_RESOLV_CONF_UNMANAGED, + NM_DNS_MANAGER_RESOLV_CONF_EXPLICIT, + NM_DNS_MANAGER_RESOLV_CONF_PROXY +} NMDnsManagerResolvConfMode; + +NMDnsManagerResolvConfMode nm_dns_manager_get_resolv_conf_mode (NMDnsManager *mgr); G_END_DECLS diff --git a/src/dns-manager/nm-dns-plugin.h b/src/dns-manager/nm-dns-plugin.h index 2a66557b..41a12a58 100644 --- a/src/dns-manager/nm-dns-plugin.h +++ b/src/dns-manager/nm-dns-plugin.h @@ -42,7 +42,6 @@ typedef struct { GObjectClass parent; /* Methods */ - gboolean (*init) (NMDnsPlugin *self); /* Called when DNS information is changed. 'vpn_configs' is a list of * NMIP4Config or NMIP6Config objects from VPN connections, while diff --git a/src/dns-manager/nm-dns-unbound.c b/src/dns-manager/nm-dns-unbound.c new file mode 100644 index 00000000..137fd20b --- /dev/null +++ b/src/dns-manager/nm-dns-unbound.c @@ -0,0 +1,79 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2014 Red Hat, Inc. + * Author: Pavel Å imerda + */ +#include "nm-dns-unbound.h" +#include "NetworkManagerUtils.h" + +G_DEFINE_TYPE (NMDnsUnbound, nm_dns_unbound, NM_TYPE_DNS_PLUGIN) + +/*******************************************/ + +static gboolean +update (NMDnsPlugin *plugin, + const GSList *vpn_configs, + const GSList *dev_configs, + const GSList *other_configs, + const char *hostname) +{ + /* TODO: We currently call a script installed with the dnssec-trigger + * package that queries all information itself. Later, the dependency + * on that package will be optional and the only hard dependency will + * be unbound. + * + * Unbound configuration should be later handled by this plugin directly, + * without calling custom scripts. The dnssec-trigger functionality + * may be eventually merged into NetworkManager. + */ + return nm_spawn_process ("/usr/libexec/dnssec-trigger-script --async --update") == 0; +} + +static gboolean +is_caching (NMDnsPlugin *plugin) +{ + return TRUE; +} + +static const char * +get_name (NMDnsPlugin *plugin) +{ + return "unbound"; +} + +/****************************************************************/ + +NMDnsPlugin * +nm_dns_unbound_new (void) +{ + return g_object_new (NM_TYPE_DNS_UNBOUND, NULL); +} + +static void +nm_dns_unbound_init (NMDnsUnbound *unbound) +{ +} + +static void +nm_dns_unbound_class_init (NMDnsUnboundClass *klass) +{ + NMDnsPluginClass *plugin_class = NM_DNS_PLUGIN_CLASS (klass); + + plugin_class->update = update; + plugin_class->is_caching = is_caching; + plugin_class->get_name = get_name; +} diff --git a/src/dns-manager/nm-dns-unbound.h b/src/dns-manager/nm-dns-unbound.h new file mode 100644 index 00000000..2aaae7dd --- /dev/null +++ b/src/dns-manager/nm-dns-unbound.h @@ -0,0 +1,44 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2014 Red Hat, Inc. + */ +#ifndef NM_DNS_UNBOUND_H +#define NM_DNS_UNBOUND_H + +#include + +#include "nm-dns-plugin.h" + +#define NM_TYPE_DNS_UNBOUND (nm_dns_unbound_get_type ()) +#define NM_DNS_UNBOUND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DNS_UNBOUND, NMDnsUnbound)) +#define NM_DNS_UNBOUND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DNS_UNBOUND, NMDnsUnboundClass)) +#define NM_IS_DNS_UNBOUND(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DNS_UNBOUND)) +#define NM_IS_DNS_UNBOUND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DNS_UNBOUND)) +#define NM_DNS_UNBOUND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DNS_UNBOUND, NMDnsUnboundClass)) + +typedef struct { + NMDnsPlugin parent; +} NMDnsUnbound; + +typedef struct { + NMDnsPluginClass parent; +} NMDnsUnboundClass; + +GType nm_dns_unbound_get_type (void); + +NMDnsPlugin *nm_dns_unbound_new (void); + +#endif /* NM_DNS_UNBOUND_H */ diff --git a/src/dns-manager/nm-dns-utils.c b/src/dns-manager/nm-dns-utils.c index 615adfd1..3e564ace 100644 --- a/src/dns-manager/nm-dns-utils.c +++ b/src/dns-manager/nm-dns-utils.c @@ -46,7 +46,10 @@ add_ip4_to_rdns_array (guint32 ip, GPtrArray *domains) /* network byte order */ else if (defprefix == 24) str = g_strdup_printf ("%u.%u.%u.in-addr.arpa", p[2] & 0xFF, p[1] & 0xFF, p[0] & 0xFF); - g_return_if_fail (str != NULL); + if (!str) { + g_return_if_fail (str != NULL); + return; + } /* Suppress duplicates */ for (i = 0; i < domains->len; i++) { @@ -79,15 +82,15 @@ nm_dns_utils_get_ip4_rdns_domains (NMIP4Config *ip4) */ for (i = 0; i < nm_ip4_config_get_num_addresses (ip4); i++) { - NMIP4Address *addr = nm_ip4_config_get_address (ip4, i); + const NMPlatformIP4Address *address = nm_ip4_config_get_address (ip4, i); - add_ip4_to_rdns_array (nm_ip4_address_get_address (addr), domains); + add_ip4_to_rdns_array (address->address, domains); } for (i = 0; i < nm_ip4_config_get_num_routes (ip4); i++) { - NMIP4Route *route = nm_ip4_config_get_route (ip4, i); + const NMPlatformIP4Route *route = nm_ip4_config_get_route (ip4, i); - add_ip4_to_rdns_array (nm_ip4_route_get_dest (route), domains); + add_ip4_to_rdns_array (route->network, domains); } /* Terminating NULL so we can use g_strfreev() to free it */ diff --git a/src/dnsmasq-manager/Makefile.am b/src/dnsmasq-manager/Makefile.am deleted file mode 100644 index 42706cc2..00000000 --- a/src/dnsmasq-manager/Makefile.am +++ /dev/null @@ -1,19 +0,0 @@ -noinst_LTLIBRARIES = libdnsmasq-manager.la - -libdnsmasq_manager_la_CPPFLAGS = \ - -I${top_srcdir}/libnm-util \ - -I${top_srcdir}/src/logging \ - -I${top_srcdir}/src/posix-signals \ - -I${top_srcdir}/src \ - -I${top_srcdir}/include \ - $(GLIB_CFLAGS) \ - -DLOCALSTATEDIR=\"$(localstatedir)\" - -libdnsmasq_manager_la_SOURCES = \ - nm-dnsmasq-manager.h \ - nm-dnsmasq-manager.c - -libdnsmasq_manager_la_LIBADD = \ - $(top_builddir)/src/logging/libnm-logging.la \ - $(top_builddir)/src/posix-signals/libnm-posix-signals.la \ - $(GLIB_LIBS) diff --git a/src/dnsmasq-manager/Makefile.in b/src/dnsmasq-manager/Makefile.in deleted file mode 100644 index 9b20331f..00000000 --- a/src/dnsmasq-manager/Makefile.in +++ /dev/null @@ -1,733 +0,0 @@ -# Makefile.in generated by automake 1.13.4 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994-2013 Free Software Foundation, Inc. - -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ - -VPATH = @srcdir@ -am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' -am__make_running_with_option = \ - case $${target_option-} in \ - ?) ;; \ - *) echo "am__make_running_with_option: internal error: invalid" \ - "target option '$${target_option-}' specified" >&2; \ - exit 1;; \ - esac; \ - has_opt=no; \ - sane_makeflags=$$MAKEFLAGS; \ - if $(am__is_gnu_make); then \ - sane_makeflags=$$MFLAGS; \ - else \ - case $$MAKEFLAGS in \ - *\\[\ \ ]*) \ - bs=\\; \ - sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ - | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ - esac; \ - fi; \ - skip_next=no; \ - strip_trailopt () \ - { \ - flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ - }; \ - for flg in $$sane_makeflags; do \ - test $$skip_next = yes && { skip_next=no; continue; }; \ - case $$flg in \ - *=*|--*) continue;; \ - -*I) strip_trailopt 'I'; skip_next=yes;; \ - -*I?*) strip_trailopt 'I';; \ - -*O) strip_trailopt 'O'; skip_next=yes;; \ - -*O?*) strip_trailopt 'O';; \ - -*l) strip_trailopt 'l'; skip_next=yes;; \ - -*l?*) strip_trailopt 'l';; \ - -[dEDm]) skip_next=yes;; \ - -[JT]) skip_next=yes;; \ - esac; \ - case $$flg in \ - *$$target_option*) has_opt=yes; break;; \ - esac; \ - done; \ - test $$has_opt = yes -am__make_dryrun = (target_option=n; $(am__make_running_with_option)) -am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) -pkgdatadir = $(datadir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkglibexecdir = $(libexecdir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = @build@ -host_triplet = @host@ -subdir = src/dnsmasq-manager -DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ - $(top_srcdir)/build-aux/depcomp -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \ - $(top_srcdir)/m4/gettext.m4 \ - $(top_srcdir)/m4/gnome-code-coverage.m4 \ - $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ - $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \ - $(top_srcdir)/m4/introspection.m4 $(top_srcdir)/m4/lib-ld.m4 \ - $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ - $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ - $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ - $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ - $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ - $(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -mkinstalldirs = $(install_sh) -d -CONFIG_HEADER = $(top_builddir)/config.h -CONFIG_CLEAN_FILES = -CONFIG_CLEAN_VPATH_FILES = -LTLIBRARIES = $(noinst_LTLIBRARIES) -am__DEPENDENCIES_1 = -libdnsmasq_manager_la_DEPENDENCIES = \ - $(top_builddir)/src/logging/libnm-logging.la \ - $(top_builddir)/src/posix-signals/libnm-posix-signals.la \ - $(am__DEPENDENCIES_1) -am_libdnsmasq_manager_la_OBJECTS = \ - libdnsmasq_manager_la-nm-dnsmasq-manager.lo -libdnsmasq_manager_la_OBJECTS = $(am_libdnsmasq_manager_la_OBJECTS) -AM_V_lt = $(am__v_lt_@AM_V@) -am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) -am__v_lt_0 = --silent -am__v_lt_1 = -AM_V_P = $(am__v_P_@AM_V@) -am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) -am__v_P_0 = false -am__v_P_1 = : -AM_V_GEN = $(am__v_GEN_@AM_V@) -am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) -am__v_GEN_0 = @echo " GEN " $@; -am__v_GEN_1 = -AM_V_at = $(am__v_at_@AM_V@) -am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) -am__v_at_0 = @ -am__v_at_1 = -DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) -depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp -am__depfiles_maybe = depfiles -am__mv = mv -f -COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ - $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ - $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ - $(AM_CFLAGS) $(CFLAGS) -AM_V_CC = $(am__v_CC_@AM_V@) -am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) -am__v_CC_0 = @echo " CC " $@; -am__v_CC_1 = -CCLD = $(CC) -LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(AM_LDFLAGS) $(LDFLAGS) -o $@ -AM_V_CCLD = $(am__v_CCLD_@AM_V@) -am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) -am__v_CCLD_0 = @echo " CCLD " $@; -am__v_CCLD_1 = -SOURCES = $(libdnsmasq_manager_la_SOURCES) -DIST_SOURCES = $(libdnsmasq_manager_la_SOURCES) -am__can_run_installinfo = \ - case $$AM_UPDATE_INFO_DIR in \ - n|no|NO) false;; \ - *) (install-info --version) >/dev/null 2>&1;; \ - esac -am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) -# Read a list of newline-separated strings from the standard input, -# and print each of them once, without duplicates. Input order is -# *not* preserved. -am__uniquify_input = $(AWK) '\ - BEGIN { nonempty = 0; } \ - { items[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in items) print i; }; } \ -' -# Make sure the list of sources is unique. This is necessary because, -# e.g., the same source file might be shared among _SOURCES variables -# for different programs/libraries. -am__define_uniq_tagged_files = \ - list='$(am__tagged_files)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | $(am__uniquify_input)` -ETAGS = etags -CTAGS = ctags -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -ALL_LINGUAS = @ALL_LINGUAS@ -AMTAR = @AMTAR@ -AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -AR = @AR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CKDB_PATH = @CKDB_PATH@ -CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@ -CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@ -CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CXX = @CXX@ -CXXCPP = @CXXCPP@ -CXXDEPMODE = @CXXDEPMODE@ -CXXFLAGS = @CXXFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DATADIRNAME = @DATADIRNAME@ -DBUS_CFLAGS = @DBUS_CFLAGS@ -DBUS_LIBS = @DBUS_LIBS@ -DBUS_SYS_DIR = @DBUS_SYS_DIR@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -DHCLIENT_PATH = @DHCLIENT_PATH@ -DHCPCD_PATH = @DHCPCD_PATH@ -DLLTOOL = @DLLTOOL@ -DNSMASQ_PATH = @DNSMASQ_PATH@ -DSYMUTIL = @DSYMUTIL@ -DUMPBIN = @DUMPBIN@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -FGREP = @FGREP@ -GENHTML = @GENHTML@ -GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ -GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ -GLIB_CFLAGS = @GLIB_CFLAGS@ -GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ -GLIB_LIBS = @GLIB_LIBS@ -GLIB_MAKEFILE = @GLIB_MAKEFILE@ -GLIB_MKENUMS = @GLIB_MKENUMS@ -GMSGFMT = @GMSGFMT@ -GMSGFMT_015 = @GMSGFMT_015@ -GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ -GNUTLS_LIBS = @GNUTLS_LIBS@ -GREP = @GREP@ -GTKDOC_CHECK = @GTKDOC_CHECK@ -GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ -GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ -GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ -GTKDOC_MKPDF = @GTKDOC_MKPDF@ -GTKDOC_REBASE = @GTKDOC_REBASE@ -GUDEV_CFLAGS = @GUDEV_CFLAGS@ -GUDEV_LIBS = @GUDEV_LIBS@ -HTML_DIR = @HTML_DIR@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -INTLLIBS = @INTLLIBS@ -INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ -INTLTOOL_MERGE = @INTLTOOL_MERGE@ -INTLTOOL_PERL = @INTLTOOL_PERL@ -INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ -INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ -INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ -INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ -INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ -INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ -INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ -INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ -INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ -INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ -INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ -INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ -INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ -INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ -IPTABLES_PATH = @IPTABLES_PATH@ -IWMX_SDK_CFLAGS = @IWMX_SDK_CFLAGS@ -IWMX_SDK_LIBS = @IWMX_SDK_LIBS@ -KERNEL_FIRMWARE_DIR = @KERNEL_FIRMWARE_DIR@ -LCOV = @LCOV@ -LD = @LD@ -LDFLAGS = @LDFLAGS@ -LIBDL = @LIBDL@ -LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ -LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ -LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ -LIBICONV = @LIBICONV@ -LIBINTL = @LIBINTL@ -LIBM = @LIBM@ -LIBNL_CFLAGS = @LIBNL_CFLAGS@ -LIBNL_LIBS = @LIBNL_LIBS@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@ -LIBSOUP_LIBS = @LIBSOUP_LIBS@ -LIBTOOL = @LIBTOOL@ -LIPO = @LIPO@ -LN_S = @LN_S@ -LTLIBICONV = @LTLIBICONV@ -LTLIBINTL = @LTLIBINTL@ -LTLIBOBJS = @LTLIBOBJS@ -MAINT = @MAINT@ -MAKEINFO = @MAKEINFO@ -MANIFEST_TOOL = @MANIFEST_TOOL@ -MKDIR_P = @MKDIR_P@ -MM_GLIB_CFLAGS = @MM_GLIB_CFLAGS@ -MM_GLIB_LIBS = @MM_GLIB_LIBS@ -MOC = @MOC@ -MSGFMT = @MSGFMT@ -MSGFMT_015 = @MSGFMT_015@ -MSGMERGE = @MSGMERGE@ -NM = @NM@ -NMEDIT = @NMEDIT@ -NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ -NM_MICRO_VERSION = @NM_MICRO_VERSION@ -NM_MINOR_VERSION = @NM_MINOR_VERSION@ -NM_MODIFY_SYSTEM_POLICY = @NM_MODIFY_SYSTEM_POLICY@ -NM_VERSION = @NM_VERSION@ -NSS_CFLAGS = @NSS_CFLAGS@ -NSS_LIBS = @NSS_LIBS@ -OBJDUMP = @OBJDUMP@ -OBJEXT = @OBJEXT@ -OTOOL = @OTOOL@ -OTOOL64 = @OTOOL64@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_URL = @PACKAGE_URL@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PKG_CONFIG = @PKG_CONFIG@ -PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ -PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ -POLKIT_CFLAGS = @POLKIT_CFLAGS@ -POLKIT_LIBS = @POLKIT_LIBS@ -POSUB = @POSUB@ -PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@ -QT_CFLAGS = @QT_CFLAGS@ -QT_LIBS = @QT_LIBS@ -RANLIB = @RANLIB@ -SED = @SED@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -STRIP = @STRIP@ -SYSTEMD_200_CFLAGS = @SYSTEMD_200_CFLAGS@ -SYSTEMD_200_LIBS = @SYSTEMD_200_LIBS@ -SYSTEMD_INHIBIT_CFLAGS = @SYSTEMD_INHIBIT_CFLAGS@ -SYSTEMD_INHIBIT_LIBS = @SYSTEMD_INHIBIT_LIBS@ -SYSTEMD_LOGIN_CFLAGS = @SYSTEMD_LOGIN_CFLAGS@ -SYSTEMD_LOGIN_LIBS = @SYSTEMD_LOGIN_LIBS@ -SYSTEM_CA_PATH = @SYSTEM_CA_PATH@ -UDEV_BASE_DIR = @UDEV_BASE_DIR@ -USE_NLS = @USE_NLS@ -UUID_CFLAGS = @UUID_CFLAGS@ -UUID_LIBS = @UUID_LIBS@ -VAPIGEN = @VAPIGEN@ -VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ -VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ -VERSION = @VERSION@ -XGETTEXT = @XGETTEXT@ -XGETTEXT_015 = @XGETTEXT_015@ -XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_AR = @ac_ct_AR@ -ac_ct_CC = @ac_ct_CC@ -ac_ct_CXX = @ac_ct_CXX@ -ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -intltool__v_merge_options_ = @intltool__v_merge_options_@ -intltool__v_merge_options_0 = @intltool__v_merge_options_0@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -nmbinary = @nmbinary@ -nmconfdir = @nmconfdir@ -nmdatadir = @nmdatadir@ -nmrundir = @nmrundir@ -nmstatedir = @nmstatedir@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -sysconfdir = @sysconfdir@ -systemdsystemunitdir = @systemdsystemunitdir@ -target_alias = @target_alias@ -top_build_prefix = @top_build_prefix@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -with_dhclient = @with_dhclient@ -with_dhcpcd = @with_dhcpcd@ -with_netconfig = @with_netconfig@ -with_resolvconf = @with_resolvconf@ -noinst_LTLIBRARIES = libdnsmasq-manager.la -libdnsmasq_manager_la_CPPFLAGS = \ - -I${top_srcdir}/libnm-util \ - -I${top_srcdir}/src/logging \ - -I${top_srcdir}/src/posix-signals \ - -I${top_srcdir}/src \ - -I${top_srcdir}/include \ - $(GLIB_CFLAGS) \ - -DLOCALSTATEDIR=\"$(localstatedir)\" - -libdnsmasq_manager_la_SOURCES = \ - nm-dnsmasq-manager.h \ - nm-dnsmasq-manager.c - -libdnsmasq_manager_la_LIBADD = \ - $(top_builddir)/src/logging/libnm-logging.la \ - $(top_builddir)/src/posix-signals/libnm-posix-signals.la \ - $(GLIB_LIBS) - -all: all-am - -.SUFFIXES: -.SUFFIXES: .c .lo .o .obj -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ - && { if test -f $@; then exit 0; else break; fi; }; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/dnsmasq-manager/Makefile'; \ - $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --gnu src/dnsmasq-manager/Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(am__aclocal_m4_deps): - -clean-noinstLTLIBRARIES: - -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) - @list='$(noinst_LTLIBRARIES)'; \ - locs=`for p in $$list; do echo $$p; done | \ - sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ - sort -u`; \ - test -z "$$locs" || { \ - echo rm -f $${locs}; \ - rm -f $${locs}; \ - } - -libdnsmasq-manager.la: $(libdnsmasq_manager_la_OBJECTS) $(libdnsmasq_manager_la_DEPENDENCIES) $(EXTRA_libdnsmasq_manager_la_DEPENDENCIES) - $(AM_V_CCLD)$(LINK) $(libdnsmasq_manager_la_OBJECTS) $(libdnsmasq_manager_la_LIBADD) $(LIBS) - -mostlyclean-compile: - -rm -f *.$(OBJEXT) - -distclean-compile: - -rm -f *.tab.c - -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdnsmasq_manager_la-nm-dnsmasq-manager.Plo@am__quote@ - -.c.o: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< - -.c.obj: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` - -.c.lo: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< - -libdnsmasq_manager_la-nm-dnsmasq-manager.lo: nm-dnsmasq-manager.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdnsmasq_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libdnsmasq_manager_la-nm-dnsmasq-manager.lo -MD -MP -MF $(DEPDIR)/libdnsmasq_manager_la-nm-dnsmasq-manager.Tpo -c -o libdnsmasq_manager_la-nm-dnsmasq-manager.lo `test -f 'nm-dnsmasq-manager.c' || echo '$(srcdir)/'`nm-dnsmasq-manager.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdnsmasq_manager_la-nm-dnsmasq-manager.Tpo $(DEPDIR)/libdnsmasq_manager_la-nm-dnsmasq-manager.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-dnsmasq-manager.c' object='libdnsmasq_manager_la-nm-dnsmasq-manager.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdnsmasq_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libdnsmasq_manager_la-nm-dnsmasq-manager.lo `test -f 'nm-dnsmasq-manager.c' || echo '$(srcdir)/'`nm-dnsmasq-manager.c - -mostlyclean-libtool: - -rm -f *.lo - -clean-libtool: - -rm -rf .libs _libs - -ID: $(am__tagged_files) - $(am__define_uniq_tagged_files); mkid -fID $$unique -tags: tags-am -TAGS: tags - -tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) - set x; \ - here=`pwd`; \ - $(am__define_uniq_tagged_files); \ - shift; \ - if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ - test -n "$$unique" || unique=$$empty_fix; \ - if test $$# -gt 0; then \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - "$$@" $$unique; \ - else \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$unique; \ - fi; \ - fi -ctags: ctags-am - -CTAGS: ctags -ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) - $(am__define_uniq_tagged_files); \ - test -z "$(CTAGS_ARGS)$$unique" \ - || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$unique - -GTAGS: - here=`$(am__cd) $(top_builddir) && pwd` \ - && $(am__cd) $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) "$$here" -cscopelist: cscopelist-am - -cscopelist-am: $(am__tagged_files) - list='$(am__tagged_files)'; \ - case "$(srcdir)" in \ - [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ - *) sdir=$(subdir)/$(srcdir) ;; \ - esac; \ - for i in $$list; do \ - if test -f "$$i"; then \ - echo "$(subdir)/$$i"; \ - else \ - echo "$$sdir/$$i"; \ - fi; \ - done >> $(top_builddir)/cscope.files - -distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags - -distdir: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d "$(distdir)/$$file"; then \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ - else \ - test -f "$(distdir)/$$file" \ - || cp -p $$d/$$file "$(distdir)/$$file" \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: check-am -all-am: Makefile $(LTLIBRARIES) -installdirs: -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - if test -z '$(STRIP)'; then \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - install; \ - else \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ - fi -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." -clean: clean-am - -clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ - mostlyclean-am - -distclean: distclean-am - -rm -rf ./$(DEPDIR) - -rm -f Makefile -distclean-am: clean-am distclean-compile distclean-generic \ - distclean-tags - -dvi: dvi-am - -dvi-am: - -html: html-am - -html-am: - -info: info-am - -info-am: - -install-data-am: - -install-dvi: install-dvi-am - -install-dvi-am: - -install-exec-am: - -install-html: install-html-am - -install-html-am: - -install-info: install-info-am - -install-info-am: - -install-man: - -install-pdf: install-pdf-am - -install-pdf-am: - -install-ps: install-ps-am - -install-ps-am: - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -rf ./$(DEPDIR) - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-compile mostlyclean-generic \ - mostlyclean-libtool - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: - -.MAKE: install-am install-strip - -.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ - clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ - ctags-am distclean distclean-compile distclean-generic \ - distclean-libtool distclean-tags distdir dvi dvi-am html \ - html-am info info-am install install-am install-data \ - install-data-am install-dvi install-dvi-am install-exec \ - install-exec-am install-html install-html-am install-info \ - install-info-am install-man install-pdf install-pdf-am \ - install-ps install-ps-am install-strip installcheck \ - installcheck-am installdirs maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-compile \ - mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ - tags tags-am uninstall uninstall-am - - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/src/dnsmasq-manager/nm-dnsmasq-manager.c b/src/dnsmasq-manager/nm-dnsmasq-manager.c index 083fb533..21bbd23a 100644 --- a/src/dnsmasq-manager/nm-dnsmasq-manager.c +++ b/src/dnsmasq-manager/nm-dnsmasq-manager.c @@ -28,9 +28,11 @@ #include #include "nm-dnsmasq-manager.h" +#include "nm-dnsmasq-utils.h" #include "nm-logging.h" #include "nm-glib-compat.h" #include "nm-posix-signals.h" +#include "nm-utils.h" typedef struct { char *iface; @@ -53,6 +55,7 @@ static guint signals[LAST_SIGNAL] = { 0 }; typedef enum { NM_DNSMASQ_MANAGER_ERROR_NOT_FOUND, + NM_DNSMASQ_MANAGER_ERROR_INVALID_IP_RANGE, } NMDnsMasqManagerError; GQuark @@ -112,8 +115,6 @@ nm_dnsmasq_manager_new (const char *iface) NMDnsMasqManagerPrivate *priv; manager = (NMDnsMasqManager *) g_object_new (NM_TYPE_DNSMASQ_MANAGER, NULL); - if (!manager) - return NULL; priv = NM_DNSMASQ_MANAGER_GET_PRIVATE (manager); priv->iface = g_strdup (iface); @@ -251,10 +252,11 @@ create_dm_cmd_line (const char *iface, const char *dm_binary; NMCmdLine *cmd; GString *s; - NMIP4Address *tmp; - struct in_addr addr; - char buf[INET_ADDRSTRLEN + 15]; - char localaddr[INET_ADDRSTRLEN + 1]; + const NMPlatformIP4Address *tmp; + char first[INET_ADDRSTRLEN]; + char last[INET_ADDRSTRLEN]; + char localaddr[INET_ADDRSTRLEN]; + char *error_desc = NULL; dm_binary = nm_find_dnsmasq (); if (!dm_binary) { @@ -296,48 +298,23 @@ create_dm_cmd_line (const char *iface, nm_cmd_line_add_string (cmd, "--strict-order"); s = g_string_new ("--listen-address="); - addr.s_addr = nm_ip4_address_get_address (tmp); - if (!inet_ntop (AF_INET, &addr, &localaddr[0], INET_ADDRSTRLEN)) { - char *err_msg = g_strdup_printf ("error converting IP4 address 0x%X", - ntohl (addr.s_addr)); - g_set_error_literal (error, NM_DNSMASQ_MANAGER_ERROR, NM_DNSMASQ_MANAGER_ERROR_NOT_FOUND, err_msg); - nm_log_warn (LOGD_SHARING, "%s", err_msg); - g_free (err_msg); - goto error; - } + nm_utils_inet4_ntop (tmp->address, localaddr); g_string_append (s, localaddr); nm_cmd_line_add_string (cmd, s->str); g_string_free (s, TRUE); - s = g_string_new ("--dhcp-range="); - - /* Add start of address range */ - addr.s_addr = nm_ip4_address_get_address (tmp) + htonl (9); - if (!inet_ntop (AF_INET, &addr, &buf[0], INET_ADDRSTRLEN)) { - char *err_msg = g_strdup_printf ("error converting IP4 address 0x%X", - ntohl (addr.s_addr)); - g_set_error_literal (error, NM_DNSMASQ_MANAGER_ERROR, NM_DNSMASQ_MANAGER_ERROR_NOT_FOUND, err_msg); - nm_log_warn (LOGD_SHARING, "%s", err_msg); - g_free (err_msg); - goto error; - } - g_string_append (s, buf); - - g_string_append_c (s, ','); - - /* Add end of address range */ - addr.s_addr = nm_ip4_address_get_address (tmp) + htonl (99); - if (!inet_ntop (AF_INET, &addr, &buf[0], INET_ADDRSTRLEN)) { - char *err_msg = g_strdup_printf ("error converting IP4 address 0x%X", - ntohl (addr.s_addr)); - g_set_error_literal (error, NM_DNSMASQ_MANAGER_ERROR, NM_DNSMASQ_MANAGER_ERROR_NOT_FOUND, err_msg); - nm_log_warn (LOGD_SHARING, "%s", err_msg); - g_free (err_msg); + if (!nm_dnsmasq_utils_get_range (tmp, first, last, &error_desc)) { + g_set_error_literal (error, + NM_DNSMASQ_MANAGER_ERROR, + NM_DNSMASQ_MANAGER_ERROR_INVALID_IP_RANGE, + error_desc); + nm_log_warn (LOGD_SHARING, "Failed to find DHCP address ranges: %s", error_desc); + g_free (error_desc); goto error; } - g_string_append (s, buf); - g_string_append (s, ",60m"); + s = g_string_new ("--dhcp-range="); + g_string_append_printf (s, "%s,%s,60m", first, last); nm_cmd_line_add_string (cmd, s->str); g_string_free (s, TRUE); diff --git a/src/dnsmasq-manager/nm-dnsmasq-utils.c b/src/dnsmasq-manager/nm-dnsmasq-utils.c new file mode 100644 index 00000000..7036b409 --- /dev/null +++ b/src/dnsmasq-manager/nm-dnsmasq-utils.c @@ -0,0 +1,77 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2013 Red Hat, Inc. + */ + +#include +#include +#include + +#include "nm-dnsmasq-utils.h" +#include "nm-platform.h" +#include "nm-utils.h" + +gboolean +nm_dnsmasq_utils_get_range (const NMPlatformIP4Address *addr, + char *out_first, + char *out_last, + char **out_error_desc) +{ + guint32 host = addr->address; + guint32 prefix = addr->plen; + guint32 netmask = nm_utils_ip4_prefix_to_netmask (prefix); + guint32 first, last, reserved; + + g_return_val_if_fail (out_first != NULL, FALSE); + g_return_val_if_fail (out_last != NULL, FALSE); + + if (prefix > 30) { + if (out_error_desc) + *out_error_desc = g_strdup_printf ("Address prefix %d is too small for DHCP.", prefix); + return FALSE; + } + + /* Find the first available address *after* the local machine's IP */ + first = (host & netmask) + htonl (1); + + /* Shortcut: allow a max of 253 addresses; the - htonl(1) here is to assure + * that we don't set 'last' to the broadcast address of the network. */ + if (prefix < 24) + last = (host | ~nm_utils_ip4_prefix_to_netmask (24)) - htonl (1); + else + last = (host | ~netmask) - htonl(1); + + /* Figure out which range (either above the host address or below it) + * has more addresses. Reserve some addresses for static IPs. + */ + if (ntohl (host) - ntohl (first) > ntohl (last) - ntohl (host)) { + /* Range below the host's IP address */ + reserved = (guint32) ((ntohl (host) - ntohl (first)) / 10); + last = host - htonl (MIN (reserved, 8)) - htonl (1); + } else { + /* Range above host's IP address */ + reserved = (guint32) ((ntohl (last) - ntohl (host)) / 10); + first = host + htonl (MIN (reserved, 8)) + htonl (1); + } + + nm_utils_inet4_ntop (first, out_first); + nm_utils_inet4_ntop (last, out_last); + + return TRUE; +} + diff --git a/src/dnsmasq-manager/nm-dnsmasq-utils.h b/src/dnsmasq-manager/nm-dnsmasq-utils.h new file mode 100644 index 00000000..4534c6ef --- /dev/null +++ b/src/dnsmasq-manager/nm-dnsmasq-utils.h @@ -0,0 +1,32 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2013 Red Hat, Inc. + */ + +#ifndef NM_DNSMASQ_UTILS_H +#define NM_DNSMASQ_UTILS_H + +#include +#include "nm-platform.h" + +gboolean nm_dnsmasq_utils_get_range (const NMPlatformIP4Address *addr, + char *out_first, + char *out_last, + char **out_error_desc); + +#endif /* NM_DNSMASQ_UTILS_H */ diff --git a/src/dnsmasq-manager/tests/Makefile.am b/src/dnsmasq-manager/tests/Makefile.am new file mode 100644 index 00000000..9c7f4ab5 --- /dev/null +++ b/src/dnsmasq-manager/tests/Makefile.am @@ -0,0 +1,23 @@ +AM_CPPFLAGS = \ + -I$(top_srcdir)/include \ + -I$(top_builddir)/include \ + -I${top_srcdir}/libnm-util \ + -I${top_builddir}/libnm-util \ + -I$(top_srcdir)/src/dnsmasq-manager \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/src/platform \ + -DG_LOG_DOMAIN=\""NetworkManager"\" \ + -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \ + $(GLIB_CFLAGS) \ + -DTESTDIR="\"$(abs_srcdir)\"" + +noinst_PROGRAMS = test-dnsmasq-utils + +test_dnsmasq_utils_SOURCES = \ + test-dnsmasq-utils.c + +test_dnsmasq_utils_LDADD = \ + $(top_builddir)/src/libNetworkManager.la + +TESTS = test-dnsmasq-utils + diff --git a/src/dnsmasq-manager/tests/Makefile.in b/src/dnsmasq-manager/tests/Makefile.in new file mode 100644 index 00000000..52301e3d --- /dev/null +++ b/src/dnsmasq-manager/tests/Makefile.in @@ -0,0 +1,856 @@ +# Makefile.in generated by automake 1.13.4 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +noinst_PROGRAMS = test-dnsmasq-utils$(EXEEXT) +TESTS = test-dnsmasq-utils$(EXEEXT) +subdir = src/dnsmasq-manager/tests +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(top_srcdir)/build-aux/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_lib_readline.m4 \ + $(top_srcdir)/m4/compiler_warnings.m4 \ + $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/gnome-code-coverage.m4 \ + $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ + $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \ + $(top_srcdir)/m4/introspection.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ + $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ + $(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +PROGRAMS = $(noinst_PROGRAMS) +am_test_dnsmasq_utils_OBJECTS = test-dnsmasq-utils.$(OBJEXT) +test_dnsmasq_utils_OBJECTS = $(am_test_dnsmasq_utils_OBJECTS) +test_dnsmasq_utils_DEPENDENCIES = \ + $(top_builddir)/src/libNetworkManager.la +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(test_dnsmasq_utils_SOURCES) +DIST_SOURCES = $(test_dnsmasq_utils_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__tty_colors_dummy = \ + mgn= red= grn= lgn= blu= brg= std=; \ + am__color_tests=no +am__tty_colors = { \ + $(am__tty_colors_dummy); \ + if test "X$(AM_COLOR_TESTS)" = Xno; then \ + am__color_tests=no; \ + elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ + am__color_tests=yes; \ + elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ + am__color_tests=yes; \ + fi; \ + if test $$am__color_tests = yes; then \ + red=''; \ + grn=''; \ + lgn=''; \ + blu=''; \ + mgn=''; \ + brg=''; \ + std=''; \ + fi; \ +} +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALL_LINGUAS = @ALL_LINGUAS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CKDB_PATH = @CKDB_PATH@ +CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@ +CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@ +CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIRNAME = @DATADIRNAME@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_100_CFLAGS = @DBUS_GLIB_100_CFLAGS@ +DBUS_GLIB_100_LIBS = @DBUS_GLIB_100_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DHCLIENT_PATH = @DHCLIENT_PATH@ +DHCPCD_PATH = @DHCPCD_PATH@ +DISTRO_NETWORK_SERVICE = @DISTRO_NETWORK_SERVICE@ +DLLTOOL = @DLLTOOL@ +DNSMASQ_PATH = @DNSMASQ_PATH@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GENHTML = @GENHTML@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MAKEFILE = @GLIB_MAKEFILE@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ +GNUTLS_LIBS = @GNUTLS_LIBS@ +GREP = @GREP@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GUDEV_CFLAGS = @GUDEV_CFLAGS@ +GUDEV_LIBS = @GUDEV_LIBS@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_PERL = @INTLTOOL_PERL@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ +INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ +INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ +INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +IPTABLES_PATH = @IPTABLES_PATH@ +IWMX_SDK_CFLAGS = @IWMX_SDK_CFLAGS@ +IWMX_SDK_LIBS = @IWMX_SDK_LIBS@ +KERNEL_FIRMWARE_DIR = @KERNEL_FIRMWARE_DIR@ +LCOV = @LCOV@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDL = @LIBDL@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBM = @LIBM@ +LIBNDP_CFLAGS = @LIBNDP_CFLAGS@ +LIBNDP_LIBS = @LIBNDP_LIBS@ +LIBNL_CFLAGS = @LIBNL_CFLAGS@ +LIBNL_LIBS = @LIBNL_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@ +LIBSOUP_LIBS = @LIBSOUP_LIBS@ +LIBTEAMDCTL_CFLAGS = @LIBTEAMDCTL_CFLAGS@ +LIBTEAMDCTL_LIBS = @LIBTEAMDCTL_LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MM_GLIB_CFLAGS = @MM_GLIB_CFLAGS@ +MM_GLIB_LIBS = @MM_GLIB_LIBS@ +MOC = @MOC@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NEWT_CFLAGS = @NEWT_CFLAGS@ +NEWT_LIBS = @NEWT_LIBS@ +NM = @NM@ +NMEDIT = @NMEDIT@ +NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ +NM_MICRO_VERSION = @NM_MICRO_VERSION@ +NM_MINOR_VERSION = @NM_MINOR_VERSION@ +NM_MODIFY_SYSTEM_POLICY = @NM_MODIFY_SYSTEM_POLICY@ +NM_VERSION = @NM_VERSION@ +NSS_CFLAGS = @NSS_CFLAGS@ +NSS_LIBS = @NSS_LIBS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +POLKIT_CFLAGS = @POLKIT_CFLAGS@ +POLKIT_LIBS = @POLKIT_LIBS@ +POSUB = @POSUB@ +PPPD_PATH = @PPPD_PATH@ +PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@ +PPPOE_PATH = @PPPOE_PATH@ +QT_CFLAGS = @QT_CFLAGS@ +QT_LIBS = @QT_LIBS@ +RANLIB = @RANLIB@ +READLINE_LIBS = @READLINE_LIBS@ +SED = @SED@ +SELINUX_CFLAGS = @SELINUX_CFLAGS@ +SELINUX_LIBS = @SELINUX_LIBS@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SYSTEMD_200_CFLAGS = @SYSTEMD_200_CFLAGS@ +SYSTEMD_200_LIBS = @SYSTEMD_200_LIBS@ +SYSTEMD_INHIBIT_CFLAGS = @SYSTEMD_INHIBIT_CFLAGS@ +SYSTEMD_INHIBIT_LIBS = @SYSTEMD_INHIBIT_LIBS@ +SYSTEMD_LOGIN_CFLAGS = @SYSTEMD_LOGIN_CFLAGS@ +SYSTEMD_LOGIN_LIBS = @SYSTEMD_LOGIN_LIBS@ +SYSTEM_CA_PATH = @SYSTEM_CA_PATH@ +UDEV_BASE_DIR = @UDEV_BASE_DIR@ +USE_NLS = @USE_NLS@ +UUID_CFLAGS = @UUID_CFLAGS@ +UUID_LIBS = @UUID_LIBS@ +VALGRIND_RULES = @VALGRIND_RULES@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ +VERSION = @VERSION@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +intltool__v_merge_options_ = @intltool__v_merge_options_@ +intltool__v_merge_options_0 = @intltool__v_merge_options_0@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +nmbinary = @nmbinary@ +nmconfdir = @nmconfdir@ +nmdatadir = @nmdatadir@ +nmrundir = @nmrundir@ +nmstatedir = @nmstatedir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +with_dhclient = @with_dhclient@ +with_dhcpcd = @with_dhcpcd@ +with_netconfig = @with_netconfig@ +with_resolvconf = @with_resolvconf@ +with_valgrind = @with_valgrind@ +AM_CPPFLAGS = \ + -I$(top_srcdir)/include \ + -I$(top_builddir)/include \ + -I${top_srcdir}/libnm-util \ + -I${top_builddir}/libnm-util \ + -I$(top_srcdir)/src/dnsmasq-manager \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/src/platform \ + -DG_LOG_DOMAIN=\""NetworkManager"\" \ + -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \ + $(GLIB_CFLAGS) \ + -DTESTDIR="\"$(abs_srcdir)\"" + +test_dnsmasq_utils_SOURCES = \ + test-dnsmasq-utils.c + +test_dnsmasq_utils_LDADD = \ + $(top_builddir)/src/libNetworkManager.la + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/dnsmasq-manager/tests/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/dnsmasq-manager/tests/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +test-dnsmasq-utils$(EXEEXT): $(test_dnsmasq_utils_OBJECTS) $(test_dnsmasq_utils_DEPENDENCIES) $(EXTRA_test_dnsmasq_utils_DEPENDENCIES) + @rm -f test-dnsmasq-utils$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_dnsmasq_utils_OBJECTS) $(test_dnsmasq_utils_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-dnsmasq-utils.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +check-TESTS: $(TESTS) + @failed=0; all=0; xfail=0; xpass=0; skip=0; \ + srcdir=$(srcdir); export srcdir; \ + list=' $(TESTS) '; \ + $(am__tty_colors); \ + if test -n "$$list"; then \ + for tst in $$list; do \ + if test -f ./$$tst; then dir=./; \ + elif test -f $$tst; then dir=; \ + else dir="$(srcdir)/"; fi; \ + if $(TESTS_ENVIRONMENT) $${dir}$$tst $(AM_TESTS_FD_REDIRECT); then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$tst[\ \ ]*) \ + xpass=`expr $$xpass + 1`; \ + failed=`expr $$failed + 1`; \ + col=$$red; res=XPASS; \ + ;; \ + *) \ + col=$$grn; res=PASS; \ + ;; \ + esac; \ + elif test $$? -ne 77; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$tst[\ \ ]*) \ + xfail=`expr $$xfail + 1`; \ + col=$$lgn; res=XFAIL; \ + ;; \ + *) \ + failed=`expr $$failed + 1`; \ + col=$$red; res=FAIL; \ + ;; \ + esac; \ + else \ + skip=`expr $$skip + 1`; \ + col=$$blu; res=SKIP; \ + fi; \ + echo "$${col}$$res$${std}: $$tst"; \ + done; \ + if test "$$all" -eq 1; then \ + tests="test"; \ + All=""; \ + else \ + tests="tests"; \ + All="All "; \ + fi; \ + if test "$$failed" -eq 0; then \ + if test "$$xfail" -eq 0; then \ + banner="$$All$$all $$tests passed"; \ + else \ + if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \ + banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \ + fi; \ + else \ + if test "$$xpass" -eq 0; then \ + banner="$$failed of $$all $$tests failed"; \ + else \ + if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \ + banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \ + fi; \ + fi; \ + dashes="$$banner"; \ + skipped=""; \ + if test "$$skip" -ne 0; then \ + if test "$$skip" -eq 1; then \ + skipped="($$skip test was not run)"; \ + else \ + skipped="($$skip tests were not run)"; \ + fi; \ + test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$skipped"; \ + fi; \ + report=""; \ + if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ + report="Please report to $(PACKAGE_BUGREPORT)"; \ + test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$report"; \ + fi; \ + dashes=`echo "$$dashes" | sed s/./=/g`; \ + if test "$$failed" -eq 0; then \ + col="$$grn"; \ + else \ + col="$$red"; \ + fi; \ + echo "$${col}$$dashes$${std}"; \ + echo "$${col}$$banner$${std}"; \ + test -z "$$skipped" || echo "$${col}$$skipped$${std}"; \ + test -z "$$report" || echo "$${col}$$report$${std}"; \ + echo "$${col}$$dashes$${std}"; \ + test "$$failed" -eq 0; \ + else :; fi + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: check-am install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ + clean-generic clean-libtool clean-noinstPROGRAMS cscopelist-am \ + ctags ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/dnsmasq-manager/tests/test-dnsmasq-utils.c b/src/dnsmasq-manager/tests/test-dnsmasq-utils.c new file mode 100644 index 00000000..07dbc0f7 --- /dev/null +++ b/src/dnsmasq-manager/tests/test-dnsmasq-utils.c @@ -0,0 +1,115 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2013 Red Hat, Inc. + * + */ + +#include +#include + +#include "nm-dnsmasq-utils.h" + +static guint32 +addr_to_num (const char *addr) +{ + guint n; + + g_assert (inet_pton (AF_INET, addr, (void *) &n) == 1); + return n; +} + +static void +test_address_ranges (void) +{ + NMPlatformIP4Address addr; + char first[INET_ADDRSTRLEN]; + char last[INET_ADDRSTRLEN]; + char *error_desc = NULL; + + addr.address = addr_to_num ("192.168.0.1"); + addr.plen = 24; + g_assert (nm_dnsmasq_utils_get_range (&addr, first, last, &error_desc)); + g_assert (error_desc == NULL); + g_assert_cmpstr (first, ==, "192.168.0.10"); + g_assert_cmpstr (last, ==, "192.168.0.254"); + + addr.address = addr_to_num ("192.168.0.99"); + addr.plen = 24; + g_assert (nm_dnsmasq_utils_get_range (&addr, first, last, &error_desc)); + g_assert (error_desc == NULL); + g_assert_cmpstr (first, ==, "192.168.0.108"); + g_assert_cmpstr (last, ==, "192.168.0.254"); + + addr.address = addr_to_num ("192.168.0.254"); + addr.plen = 24; + g_assert (nm_dnsmasq_utils_get_range (&addr, first, last, &error_desc)); + g_assert (error_desc == NULL); + g_assert_cmpstr (first, ==, "192.168.0.1"); + g_assert_cmpstr (last, ==, "192.168.0.245"); + + /* Smaller networks */ + addr.address = addr_to_num ("1.2.3.1"); + addr.plen = 30; + g_assert (nm_dnsmasq_utils_get_range (&addr, first, last, &error_desc)); + g_assert (error_desc == NULL); + g_assert_cmpstr (first, ==, "1.2.3.2"); + g_assert_cmpstr (last, ==, "1.2.3.2"); + + addr.address = addr_to_num ("1.2.3.1"); + addr.plen = 29; + g_assert (nm_dnsmasq_utils_get_range (&addr, first, last, &error_desc)); + g_assert (error_desc == NULL); + g_assert_cmpstr (first, ==, "1.2.3.2"); + g_assert_cmpstr (last, ==, "1.2.3.6"); + + addr.address = addr_to_num ("1.2.3.1"); + addr.plen = 28; + g_assert (nm_dnsmasq_utils_get_range (&addr, first, last, &error_desc)); + g_assert (error_desc == NULL); + g_assert_cmpstr (first, ==, "1.2.3.3"); + g_assert_cmpstr (last, ==, "1.2.3.14"); + + addr.address = addr_to_num ("1.2.3.1"); + addr.plen = 26; + g_assert (nm_dnsmasq_utils_get_range (&addr, first, last, &error_desc)); + g_assert (error_desc == NULL); + g_assert_cmpstr (first, ==, "1.2.3.8"); + g_assert_cmpstr (last, ==, "1.2.3.62"); + + addr.address = addr_to_num ("1.2.3.1"); + addr.plen = 31; + g_assert (nm_dnsmasq_utils_get_range (&addr, first, last, &error_desc) == FALSE); + g_assert (error_desc); + g_free (error_desc); +} + +/*******************************************/ + +int +main (int argc, char **argv) +{ + g_test_init (&argc, &argv, NULL); + +#if !GLIB_CHECK_VERSION (2, 35, 0) + g_type_init (); +#endif + + g_test_add_func ("/dnsmasq-manager/address-ranges", test_address_ranges); + + return g_test_run (); +} + diff --git a/src/firewall-manager/Makefile.am b/src/firewall-manager/Makefile.am deleted file mode 100644 index 15bde51a..00000000 --- a/src/firewall-manager/Makefile.am +++ /dev/null @@ -1,21 +0,0 @@ -noinst_LTLIBRARIES = libfirewall-manager.la - -libfirewall_manager_la_CPPFLAGS = \ - -I${top_srcdir}/src \ - -I${top_srcdir}/src/logging \ - -I${top_srcdir}/include \ - -I${top_srcdir}/libnm-util \ - $(DBUS_CFLAGS) \ - $(GLIB_CFLAGS) \ - -DNM_PKGDATADIR=\"$(pkgdatadir)\" \ - -DNM_LOCALSTATEDIR=\"$(localstatedir)\" - -libfirewall_manager_la_SOURCES = \ - nm-firewall-manager.h \ - nm-firewall-manager.c - -libfirewall_manager_la_LIBADD = \ - $(top_builddir)/src/logging/libnm-logging.la \ - $(DBUS_LIBS) \ - $(GLIB_LIBS) - diff --git a/src/firewall-manager/Makefile.in b/src/firewall-manager/Makefile.in deleted file mode 100644 index 690f0b3d..00000000 --- a/src/firewall-manager/Makefile.in +++ /dev/null @@ -1,733 +0,0 @@ -# Makefile.in generated by automake 1.13.4 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994-2013 Free Software Foundation, Inc. - -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ - -VPATH = @srcdir@ -am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' -am__make_running_with_option = \ - case $${target_option-} in \ - ?) ;; \ - *) echo "am__make_running_with_option: internal error: invalid" \ - "target option '$${target_option-}' specified" >&2; \ - exit 1;; \ - esac; \ - has_opt=no; \ - sane_makeflags=$$MAKEFLAGS; \ - if $(am__is_gnu_make); then \ - sane_makeflags=$$MFLAGS; \ - else \ - case $$MAKEFLAGS in \ - *\\[\ \ ]*) \ - bs=\\; \ - sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ - | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ - esac; \ - fi; \ - skip_next=no; \ - strip_trailopt () \ - { \ - flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ - }; \ - for flg in $$sane_makeflags; do \ - test $$skip_next = yes && { skip_next=no; continue; }; \ - case $$flg in \ - *=*|--*) continue;; \ - -*I) strip_trailopt 'I'; skip_next=yes;; \ - -*I?*) strip_trailopt 'I';; \ - -*O) strip_trailopt 'O'; skip_next=yes;; \ - -*O?*) strip_trailopt 'O';; \ - -*l) strip_trailopt 'l'; skip_next=yes;; \ - -*l?*) strip_trailopt 'l';; \ - -[dEDm]) skip_next=yes;; \ - -[JT]) skip_next=yes;; \ - esac; \ - case $$flg in \ - *$$target_option*) has_opt=yes; break;; \ - esac; \ - done; \ - test $$has_opt = yes -am__make_dryrun = (target_option=n; $(am__make_running_with_option)) -am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) -pkgdatadir = $(datadir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkglibexecdir = $(libexecdir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = @build@ -host_triplet = @host@ -subdir = src/firewall-manager -DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ - $(top_srcdir)/build-aux/depcomp -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \ - $(top_srcdir)/m4/gettext.m4 \ - $(top_srcdir)/m4/gnome-code-coverage.m4 \ - $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ - $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \ - $(top_srcdir)/m4/introspection.m4 $(top_srcdir)/m4/lib-ld.m4 \ - $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ - $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ - $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ - $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ - $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ - $(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -mkinstalldirs = $(install_sh) -d -CONFIG_HEADER = $(top_builddir)/config.h -CONFIG_CLEAN_FILES = -CONFIG_CLEAN_VPATH_FILES = -LTLIBRARIES = $(noinst_LTLIBRARIES) -am__DEPENDENCIES_1 = -libfirewall_manager_la_DEPENDENCIES = \ - $(top_builddir)/src/logging/libnm-logging.la \ - $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) -am_libfirewall_manager_la_OBJECTS = \ - libfirewall_manager_la-nm-firewall-manager.lo -libfirewall_manager_la_OBJECTS = $(am_libfirewall_manager_la_OBJECTS) -AM_V_lt = $(am__v_lt_@AM_V@) -am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) -am__v_lt_0 = --silent -am__v_lt_1 = -AM_V_P = $(am__v_P_@AM_V@) -am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) -am__v_P_0 = false -am__v_P_1 = : -AM_V_GEN = $(am__v_GEN_@AM_V@) -am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) -am__v_GEN_0 = @echo " GEN " $@; -am__v_GEN_1 = -AM_V_at = $(am__v_at_@AM_V@) -am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) -am__v_at_0 = @ -am__v_at_1 = -DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) -depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp -am__depfiles_maybe = depfiles -am__mv = mv -f -COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ - $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ - $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ - $(AM_CFLAGS) $(CFLAGS) -AM_V_CC = $(am__v_CC_@AM_V@) -am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) -am__v_CC_0 = @echo " CC " $@; -am__v_CC_1 = -CCLD = $(CC) -LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(AM_LDFLAGS) $(LDFLAGS) -o $@ -AM_V_CCLD = $(am__v_CCLD_@AM_V@) -am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) -am__v_CCLD_0 = @echo " CCLD " $@; -am__v_CCLD_1 = -SOURCES = $(libfirewall_manager_la_SOURCES) -DIST_SOURCES = $(libfirewall_manager_la_SOURCES) -am__can_run_installinfo = \ - case $$AM_UPDATE_INFO_DIR in \ - n|no|NO) false;; \ - *) (install-info --version) >/dev/null 2>&1;; \ - esac -am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) -# Read a list of newline-separated strings from the standard input, -# and print each of them once, without duplicates. Input order is -# *not* preserved. -am__uniquify_input = $(AWK) '\ - BEGIN { nonempty = 0; } \ - { items[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in items) print i; }; } \ -' -# Make sure the list of sources is unique. This is necessary because, -# e.g., the same source file might be shared among _SOURCES variables -# for different programs/libraries. -am__define_uniq_tagged_files = \ - list='$(am__tagged_files)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | $(am__uniquify_input)` -ETAGS = etags -CTAGS = ctags -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -ALL_LINGUAS = @ALL_LINGUAS@ -AMTAR = @AMTAR@ -AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -AR = @AR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CKDB_PATH = @CKDB_PATH@ -CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@ -CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@ -CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CXX = @CXX@ -CXXCPP = @CXXCPP@ -CXXDEPMODE = @CXXDEPMODE@ -CXXFLAGS = @CXXFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DATADIRNAME = @DATADIRNAME@ -DBUS_CFLAGS = @DBUS_CFLAGS@ -DBUS_LIBS = @DBUS_LIBS@ -DBUS_SYS_DIR = @DBUS_SYS_DIR@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -DHCLIENT_PATH = @DHCLIENT_PATH@ -DHCPCD_PATH = @DHCPCD_PATH@ -DLLTOOL = @DLLTOOL@ -DNSMASQ_PATH = @DNSMASQ_PATH@ -DSYMUTIL = @DSYMUTIL@ -DUMPBIN = @DUMPBIN@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -FGREP = @FGREP@ -GENHTML = @GENHTML@ -GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ -GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ -GLIB_CFLAGS = @GLIB_CFLAGS@ -GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ -GLIB_LIBS = @GLIB_LIBS@ -GLIB_MAKEFILE = @GLIB_MAKEFILE@ -GLIB_MKENUMS = @GLIB_MKENUMS@ -GMSGFMT = @GMSGFMT@ -GMSGFMT_015 = @GMSGFMT_015@ -GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ -GNUTLS_LIBS = @GNUTLS_LIBS@ -GREP = @GREP@ -GTKDOC_CHECK = @GTKDOC_CHECK@ -GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ -GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ -GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ -GTKDOC_MKPDF = @GTKDOC_MKPDF@ -GTKDOC_REBASE = @GTKDOC_REBASE@ -GUDEV_CFLAGS = @GUDEV_CFLAGS@ -GUDEV_LIBS = @GUDEV_LIBS@ -HTML_DIR = @HTML_DIR@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -INTLLIBS = @INTLLIBS@ -INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ -INTLTOOL_MERGE = @INTLTOOL_MERGE@ -INTLTOOL_PERL = @INTLTOOL_PERL@ -INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ -INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ -INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ -INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ -INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ -INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ -INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ -INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ -INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ -INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ -INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ -INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ -INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ -INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ -IPTABLES_PATH = @IPTABLES_PATH@ -IWMX_SDK_CFLAGS = @IWMX_SDK_CFLAGS@ -IWMX_SDK_LIBS = @IWMX_SDK_LIBS@ -KERNEL_FIRMWARE_DIR = @KERNEL_FIRMWARE_DIR@ -LCOV = @LCOV@ -LD = @LD@ -LDFLAGS = @LDFLAGS@ -LIBDL = @LIBDL@ -LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ -LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ -LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ -LIBICONV = @LIBICONV@ -LIBINTL = @LIBINTL@ -LIBM = @LIBM@ -LIBNL_CFLAGS = @LIBNL_CFLAGS@ -LIBNL_LIBS = @LIBNL_LIBS@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@ -LIBSOUP_LIBS = @LIBSOUP_LIBS@ -LIBTOOL = @LIBTOOL@ -LIPO = @LIPO@ -LN_S = @LN_S@ -LTLIBICONV = @LTLIBICONV@ -LTLIBINTL = @LTLIBINTL@ -LTLIBOBJS = @LTLIBOBJS@ -MAINT = @MAINT@ -MAKEINFO = @MAKEINFO@ -MANIFEST_TOOL = @MANIFEST_TOOL@ -MKDIR_P = @MKDIR_P@ -MM_GLIB_CFLAGS = @MM_GLIB_CFLAGS@ -MM_GLIB_LIBS = @MM_GLIB_LIBS@ -MOC = @MOC@ -MSGFMT = @MSGFMT@ -MSGFMT_015 = @MSGFMT_015@ -MSGMERGE = @MSGMERGE@ -NM = @NM@ -NMEDIT = @NMEDIT@ -NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ -NM_MICRO_VERSION = @NM_MICRO_VERSION@ -NM_MINOR_VERSION = @NM_MINOR_VERSION@ -NM_MODIFY_SYSTEM_POLICY = @NM_MODIFY_SYSTEM_POLICY@ -NM_VERSION = @NM_VERSION@ -NSS_CFLAGS = @NSS_CFLAGS@ -NSS_LIBS = @NSS_LIBS@ -OBJDUMP = @OBJDUMP@ -OBJEXT = @OBJEXT@ -OTOOL = @OTOOL@ -OTOOL64 = @OTOOL64@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_URL = @PACKAGE_URL@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PKG_CONFIG = @PKG_CONFIG@ -PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ -PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ -POLKIT_CFLAGS = @POLKIT_CFLAGS@ -POLKIT_LIBS = @POLKIT_LIBS@ -POSUB = @POSUB@ -PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@ -QT_CFLAGS = @QT_CFLAGS@ -QT_LIBS = @QT_LIBS@ -RANLIB = @RANLIB@ -SED = @SED@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -STRIP = @STRIP@ -SYSTEMD_200_CFLAGS = @SYSTEMD_200_CFLAGS@ -SYSTEMD_200_LIBS = @SYSTEMD_200_LIBS@ -SYSTEMD_INHIBIT_CFLAGS = @SYSTEMD_INHIBIT_CFLAGS@ -SYSTEMD_INHIBIT_LIBS = @SYSTEMD_INHIBIT_LIBS@ -SYSTEMD_LOGIN_CFLAGS = @SYSTEMD_LOGIN_CFLAGS@ -SYSTEMD_LOGIN_LIBS = @SYSTEMD_LOGIN_LIBS@ -SYSTEM_CA_PATH = @SYSTEM_CA_PATH@ -UDEV_BASE_DIR = @UDEV_BASE_DIR@ -USE_NLS = @USE_NLS@ -UUID_CFLAGS = @UUID_CFLAGS@ -UUID_LIBS = @UUID_LIBS@ -VAPIGEN = @VAPIGEN@ -VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ -VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ -VERSION = @VERSION@ -XGETTEXT = @XGETTEXT@ -XGETTEXT_015 = @XGETTEXT_015@ -XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_AR = @ac_ct_AR@ -ac_ct_CC = @ac_ct_CC@ -ac_ct_CXX = @ac_ct_CXX@ -ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -intltool__v_merge_options_ = @intltool__v_merge_options_@ -intltool__v_merge_options_0 = @intltool__v_merge_options_0@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -nmbinary = @nmbinary@ -nmconfdir = @nmconfdir@ -nmdatadir = @nmdatadir@ -nmrundir = @nmrundir@ -nmstatedir = @nmstatedir@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -sysconfdir = @sysconfdir@ -systemdsystemunitdir = @systemdsystemunitdir@ -target_alias = @target_alias@ -top_build_prefix = @top_build_prefix@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -with_dhclient = @with_dhclient@ -with_dhcpcd = @with_dhcpcd@ -with_netconfig = @with_netconfig@ -with_resolvconf = @with_resolvconf@ -noinst_LTLIBRARIES = libfirewall-manager.la -libfirewall_manager_la_CPPFLAGS = \ - -I${top_srcdir}/src \ - -I${top_srcdir}/src/logging \ - -I${top_srcdir}/include \ - -I${top_srcdir}/libnm-util \ - $(DBUS_CFLAGS) \ - $(GLIB_CFLAGS) \ - -DNM_PKGDATADIR=\"$(pkgdatadir)\" \ - -DNM_LOCALSTATEDIR=\"$(localstatedir)\" - -libfirewall_manager_la_SOURCES = \ - nm-firewall-manager.h \ - nm-firewall-manager.c - -libfirewall_manager_la_LIBADD = \ - $(top_builddir)/src/logging/libnm-logging.la \ - $(DBUS_LIBS) \ - $(GLIB_LIBS) - -all: all-am - -.SUFFIXES: -.SUFFIXES: .c .lo .o .obj -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ - && { if test -f $@; then exit 0; else break; fi; }; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/firewall-manager/Makefile'; \ - $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --gnu src/firewall-manager/Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(am__aclocal_m4_deps): - -clean-noinstLTLIBRARIES: - -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) - @list='$(noinst_LTLIBRARIES)'; \ - locs=`for p in $$list; do echo $$p; done | \ - sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ - sort -u`; \ - test -z "$$locs" || { \ - echo rm -f $${locs}; \ - rm -f $${locs}; \ - } - -libfirewall-manager.la: $(libfirewall_manager_la_OBJECTS) $(libfirewall_manager_la_DEPENDENCIES) $(EXTRA_libfirewall_manager_la_DEPENDENCIES) - $(AM_V_CCLD)$(LINK) $(libfirewall_manager_la_OBJECTS) $(libfirewall_manager_la_LIBADD) $(LIBS) - -mostlyclean-compile: - -rm -f *.$(OBJEXT) - -distclean-compile: - -rm -f *.tab.c - -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libfirewall_manager_la-nm-firewall-manager.Plo@am__quote@ - -.c.o: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< - -.c.obj: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` - -.c.lo: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< - -libfirewall_manager_la-nm-firewall-manager.lo: nm-firewall-manager.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libfirewall_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libfirewall_manager_la-nm-firewall-manager.lo -MD -MP -MF $(DEPDIR)/libfirewall_manager_la-nm-firewall-manager.Tpo -c -o libfirewall_manager_la-nm-firewall-manager.lo `test -f 'nm-firewall-manager.c' || echo '$(srcdir)/'`nm-firewall-manager.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libfirewall_manager_la-nm-firewall-manager.Tpo $(DEPDIR)/libfirewall_manager_la-nm-firewall-manager.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-firewall-manager.c' object='libfirewall_manager_la-nm-firewall-manager.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libfirewall_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libfirewall_manager_la-nm-firewall-manager.lo `test -f 'nm-firewall-manager.c' || echo '$(srcdir)/'`nm-firewall-manager.c - -mostlyclean-libtool: - -rm -f *.lo - -clean-libtool: - -rm -rf .libs _libs - -ID: $(am__tagged_files) - $(am__define_uniq_tagged_files); mkid -fID $$unique -tags: tags-am -TAGS: tags - -tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) - set x; \ - here=`pwd`; \ - $(am__define_uniq_tagged_files); \ - shift; \ - if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ - test -n "$$unique" || unique=$$empty_fix; \ - if test $$# -gt 0; then \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - "$$@" $$unique; \ - else \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$unique; \ - fi; \ - fi -ctags: ctags-am - -CTAGS: ctags -ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) - $(am__define_uniq_tagged_files); \ - test -z "$(CTAGS_ARGS)$$unique" \ - || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$unique - -GTAGS: - here=`$(am__cd) $(top_builddir) && pwd` \ - && $(am__cd) $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) "$$here" -cscopelist: cscopelist-am - -cscopelist-am: $(am__tagged_files) - list='$(am__tagged_files)'; \ - case "$(srcdir)" in \ - [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ - *) sdir=$(subdir)/$(srcdir) ;; \ - esac; \ - for i in $$list; do \ - if test -f "$$i"; then \ - echo "$(subdir)/$$i"; \ - else \ - echo "$$sdir/$$i"; \ - fi; \ - done >> $(top_builddir)/cscope.files - -distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags - -distdir: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d "$(distdir)/$$file"; then \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ - else \ - test -f "$(distdir)/$$file" \ - || cp -p $$d/$$file "$(distdir)/$$file" \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: check-am -all-am: Makefile $(LTLIBRARIES) -installdirs: -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - if test -z '$(STRIP)'; then \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - install; \ - else \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ - fi -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." -clean: clean-am - -clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ - mostlyclean-am - -distclean: distclean-am - -rm -rf ./$(DEPDIR) - -rm -f Makefile -distclean-am: clean-am distclean-compile distclean-generic \ - distclean-tags - -dvi: dvi-am - -dvi-am: - -html: html-am - -html-am: - -info: info-am - -info-am: - -install-data-am: - -install-dvi: install-dvi-am - -install-dvi-am: - -install-exec-am: - -install-html: install-html-am - -install-html-am: - -install-info: install-info-am - -install-info-am: - -install-man: - -install-pdf: install-pdf-am - -install-pdf-am: - -install-ps: install-ps-am - -install-ps-am: - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -rf ./$(DEPDIR) - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-compile mostlyclean-generic \ - mostlyclean-libtool - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: - -.MAKE: install-am install-strip - -.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ - clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ - ctags-am distclean distclean-compile distclean-generic \ - distclean-libtool distclean-tags distdir dvi dvi-am html \ - html-am info info-am install install-am install-data \ - install-data-am install-dvi install-dvi-am install-exec \ - install-exec-am install-html install-html-am install-info \ - install-info-am install-man install-pdf install-pdf-am \ - install-ps install-ps-am install-strip installcheck \ - installcheck-am installdirs maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-compile \ - mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ - tags tags-am uninstall uninstall-am - - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/src/firewall-manager/nm-firewall-manager.c b/src/firewall-manager/nm-firewall-manager.c index cdb2f3fa..c99372a1 100644 --- a/src/firewall-manager/nm-firewall-manager.c +++ b/src/firewall-manager/nm-firewall-manager.c @@ -44,7 +44,6 @@ typedef struct { guint name_owner_id; DBusGProxy * proxy; gboolean running; - gboolean disposed; } NMFirewallManagerPrivate; enum { @@ -61,16 +60,40 @@ typedef struct { char *iface; FwAddToZoneFunc callback; gpointer user_data; + guint id; + gboolean completed; } CBInfo; static void cb_info_free (CBInfo *info) { g_return_if_fail (info != NULL); + + if (!info->completed) + nm_log_dbg (LOGD_FIREWALL, "(%s) firewall zone call cancelled [%u]", info->iface, info->id); + g_free (info->iface); g_free (info); } +static CBInfo * +_cb_info_create (const char *iface, FwAddToZoneFunc callback, gpointer user_data) +{ + static guint id; + CBInfo *info; + + info = g_malloc (sizeof (CBInfo)); + if (++id == 0) + ++id; + info->id = id; + info->iface = g_strdup (iface); + info->completed = FALSE; + info->callback = callback; + info->user_data = user_data; + + return info; +} + static void add_or_change_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) { @@ -83,16 +106,20 @@ add_or_change_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data G_TYPE_INVALID)) { g_assert (error); if (g_strcmp0 (error->message, "ZONE_ALREADY_SET") != 0) { - nm_log_warn (LOGD_FIREWALL, "(%s) firewall zone add/change failed: (%d) %s", - info->iface, error->code, error->message); + nm_log_warn (LOGD_FIREWALL, "(%s) firewall zone add/change failed [%u]: (%d) %s", + info->iface, info->id, error->code, error->message); } else { - nm_log_dbg (LOGD_FIREWALL, "(%s) firewall zone add/change failed: (%d) %s", - info->iface, error->code, error->message); + nm_log_dbg (LOGD_FIREWALL, "(%s) firewall zone add/change failed [%u]: (%d) %s", + info->iface, info->id, error->code, error->message); } + } else { + nm_log_dbg (LOGD_FIREWALL, "(%s) firewall zone add/change succeeded [%u]", + info->iface, info->id); } info->callback (error, info->user_data); + info->completed = TRUE; g_free (zone); g_clear_error (&error); } @@ -114,13 +141,10 @@ nm_firewall_manager_add_or_change_zone (NMFirewallManager *self, return NULL; } - info = g_malloc0 (sizeof (*info)); - info->iface = g_strdup (iface); - info->callback = callback; - info->user_data = user_data; + info = _cb_info_create (iface, callback, user_data); - nm_log_dbg (LOGD_FIREWALL, "(%s) firewall zone %s -> %s%s%s", iface, add ? "add" : "change", - zone?"\"":"", zone ? zone : "default", zone?"\"":""); + nm_log_dbg (LOGD_FIREWALL, "(%s) firewall zone %s -> %s%s%s [%u]", iface, add ? "add" : "change", + zone?"\"":"", zone ? zone : "default", zone?"\"":"", info->id); return dbus_g_proxy_begin_call_with_timeout (priv->proxy, add ? "addInterface" : "changeZone", add_or_change_cb, @@ -145,11 +169,18 @@ remove_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) g_assert (error); /* ignore UNKNOWN_INTERFACE errors */ if (error->message && !strstr (error->message, "UNKNOWN_INTERFACE")) { - nm_log_warn (LOGD_FIREWALL, "(%s) firewall zone remove failed: (%d) %s", - info->iface, error->code, error->message); + nm_log_warn (LOGD_FIREWALL, "(%s) firewall zone remove failed [%u]: (%d) %s", + info->iface, info->id, error->code, error->message); + } else { + nm_log_dbg (LOGD_FIREWALL, "(%s) firewall zone remove failed [%u]: (%d) %s", + info->iface, info->id, error->code, error->message); } + } else { + nm_log_dbg (LOGD_FIREWALL, "(%s) firewall zone remove succeeded [%u]", + info->iface, info->id); } + info->completed = TRUE; g_free (zone); g_clear_error (&error); } @@ -167,10 +198,10 @@ nm_firewall_manager_remove_from_zone (NMFirewallManager *self, return NULL; } - info = g_malloc0 (sizeof (*info)); - info->iface = g_strdup (iface); + info = _cb_info_create (iface, NULL, NULL); - nm_log_dbg (LOGD_FIREWALL, "(%s) firewall zone remove -> %s", iface, zone ); + nm_log_dbg (LOGD_FIREWALL, "(%s) firewall zone remove -> %s%s%s [%u]", iface, + zone?"\"":"", zone ? zone : "*", zone?"\"":"", info->id); return dbus_g_proxy_begin_call_with_timeout (priv->proxy, "removeInterface", remove_cb, @@ -184,7 +215,6 @@ nm_firewall_manager_remove_from_zone (NMFirewallManager *self, void nm_firewall_manager_cancel_call (NMFirewallManager *self, gpointer call) { - g_return_if_fail (self != NULL); g_return_if_fail (NM_IS_FIREWALL_MANAGER (self)); dbus_g_proxy_cancel_call (NM_FIREWALL_MANAGER_GET_PRIVATE (self)->proxy, (DBusGProxyCall *) call); @@ -248,7 +278,7 @@ nm_firewall_manager_init (NMFirewallManager * self) NMFirewallManagerPrivate *priv = NM_FIREWALL_MANAGER_GET_PRIVATE (self); DBusGConnection *bus; - priv->dbus_mgr = nm_dbus_manager_get (); + priv->dbus_mgr = g_object_ref (nm_dbus_manager_get ()); priv->name_owner_id = g_signal_connect (priv->dbus_mgr, NM_DBUS_MANAGER_NAME_OWNER_CHANGED, G_CALLBACK (name_owner_changed), @@ -287,20 +317,14 @@ dispose (GObject *object) { NMFirewallManagerPrivate *priv = NM_FIREWALL_MANAGER_GET_PRIVATE (object); - if (priv->disposed) - goto out; - priv->disposed = TRUE; - if (priv->dbus_mgr) { - if (priv->name_owner_id) - g_signal_handler_disconnect (priv->dbus_mgr, priv->name_owner_id); - g_object_unref (G_OBJECT (priv->dbus_mgr)); + g_signal_handler_disconnect (priv->dbus_mgr, priv->name_owner_id); + priv->name_owner_id = 0; + g_clear_object (&priv->dbus_mgr); } - if (priv->proxy) - g_object_unref (priv->proxy); + g_clear_object (&priv->proxy); -out: /* Chain up to the parent class */ G_OBJECT_CLASS (nm_firewall_manager_parent_class)->dispose (object); } diff --git a/src/generated/Makefile.am b/src/generated/Makefile.am deleted file mode 100644 index b313e454..00000000 --- a/src/generated/Makefile.am +++ /dev/null @@ -1,91 +0,0 @@ -include $(GLIB_MAKEFILE) - -noinst_LTLIBRARIES = libnm-generated.la - -libnm_generated_la_SOURCES = \ - nm-enum-types.c \ - nm-enum-types.h \ - nm-marshal.c \ - nm-marshal.h - -nm_daemon_all_sources = \ - $(top_srcdir)/src/*.[ch] \ - $(top_srcdir)/src/logging/*.[ch] \ - $(top_srcdir)/src/dns-manager/*.[ch] \ - $(top_srcdir)/src/vpn-manager/*.[ch] \ - $(top_srcdir)/src/dhcp-manager/*.[ch] \ - $(top_srcdir)/src/ip6-manager/*.[ch] \ - $(top_srcdir)/src/supplicant-manager/*.[ch] \ - $(top_srcdir)/src/ppp-manager/*.[ch] \ - $(top_srcdir)/src/dnsmasq-manager/*.[ch] \ - $(top_srcdir)/src/modem-manager/*.[ch] \ - $(top_srcdir)/src/bluez-manager/*.[ch] \ - $(top_srcdir)/src/firewall-manager/*.[ch] \ - $(top_srcdir)/src/settings/*.[ch] - -if WITH_WIMAX -nm_daemon_all_sources += $(top_srcdir)/src/wimax/*.[ch] -endif - -nm_daemon_sources_no_bindings = \ - $(filter-out %-glue.h %-bindings.h, $(wildcard $(nm_daemon_all_sources))) - -if WITH_MODEM_MANAGER_1 -# We filter out this file, which doesn't have any enum, and which clashes -# with ModemManager1-defined symbols -nm_daemon_sources = \ - $(filter-out $(top_srcdir)/src/modem-manager/nm-modem-types.h, $(wildcard $(nm_daemon_sources_no_bindings))) -else -# Don't include ModemManager1-specific headers if we're not compiling with -# ModemManager1 support. -nm_daemon_sources = \ - $(filter-out $(top_srcdir)/src/modem-manager/nm-modem-broadband.h, $(wildcard $(nm_daemon_sources_no_bindings))) -endif - -GLIB_GENERATED = nm-enum-types.h nm-enum-types.c -nm_enum_types_sources = $(nm_daemon_sources) -GLIB_MKENUMS_H_FLAGS = --identifier-prefix NM -GLIB_MKENUMS_C_FLAGS = --identifier-prefix NM - -GLIB_GENERATED += nm-marshal.h nm-marshal.c -nm_marshal_sources = $(nm_daemon_sources) - -libnm_generated_la_CPPFLAGS = \ - -I${top_srcdir}/include \ - -I${top_builddir}/include \ - -I${top_srcdir}/src \ - -I${top_srcdir}/src/logging \ - -I${top_srcdir}/src/dns-manager \ - -I${top_srcdir}/src/vpn-manager \ - -I${top_srcdir}/src/dhcp-manager \ - -I${top_srcdir}/src/ip6-manager \ - -I${top_srcdir}/src/supplicant-manager \ - -I${top_srcdir}/src/ppp-manager \ - -I${top_srcdir}/src/dnsmasq-manager \ - -I${top_srcdir}/src/modem-manager \ - -I$(top_srcdir)/src/bluez-manager \ - -I$(top_srcdir)/src/firewall-manager \ - -I$(top_srcdir)/src/settings \ - -I$(top_srcdir)/src/wifi \ - -I$(top_srcdir)/libnm-util \ - $(DBUS_CFLAGS) \ - $(GLIB_CFLAGS) \ - $(GUDEV_CFLAGS) \ - $(LIBNL_CFLAGS) \ - $(POLKIT_CFLAGS) \ - $(SYSTEMD_LOGIN_CFLAGS) \ - $(IWMX_SDK_CFLAGS) - -if WITH_WIMAX -libnm_generated_la_CPPFLAGS += -I$(top_srcdir)/src/wimax -endif - -if WITH_MODEM_MANAGER_1 -libnm_generated_la_CPPFLAGS += $(MM_GLIB_CFLAGS) -endif - -libnm_generated_la_LIBADD = \ - $(GLIB_LIBS) - -BUILT_SOURCES = $(GLIB_GENERATED) - diff --git a/src/generated/Makefile.in b/src/generated/Makefile.in deleted file mode 100644 index 350bf7f7..00000000 --- a/src/generated/Makefile.in +++ /dev/null @@ -1,788 +0,0 @@ -# Makefile.in generated by automake 1.13.4 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994-2013 Free Software Foundation, Inc. - -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ - -VPATH = @srcdir@ -am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' -am__make_running_with_option = \ - case $${target_option-} in \ - ?) ;; \ - *) echo "am__make_running_with_option: internal error: invalid" \ - "target option '$${target_option-}' specified" >&2; \ - exit 1;; \ - esac; \ - has_opt=no; \ - sane_makeflags=$$MAKEFLAGS; \ - if $(am__is_gnu_make); then \ - sane_makeflags=$$MFLAGS; \ - else \ - case $$MAKEFLAGS in \ - *\\[\ \ ]*) \ - bs=\\; \ - sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ - | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ - esac; \ - fi; \ - skip_next=no; \ - strip_trailopt () \ - { \ - flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ - }; \ - for flg in $$sane_makeflags; do \ - test $$skip_next = yes && { skip_next=no; continue; }; \ - case $$flg in \ - *=*|--*) continue;; \ - -*I) strip_trailopt 'I'; skip_next=yes;; \ - -*I?*) strip_trailopt 'I';; \ - -*O) strip_trailopt 'O'; skip_next=yes;; \ - -*O?*) strip_trailopt 'O';; \ - -*l) strip_trailopt 'l'; skip_next=yes;; \ - -*l?*) strip_trailopt 'l';; \ - -[dEDm]) skip_next=yes;; \ - -[JT]) skip_next=yes;; \ - esac; \ - case $$flg in \ - *$$target_option*) has_opt=yes; break;; \ - esac; \ - done; \ - test $$has_opt = yes -am__make_dryrun = (target_option=n; $(am__make_running_with_option)) -am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) -pkgdatadir = $(datadir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkglibexecdir = $(libexecdir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = @build@ -host_triplet = @host@ -@WITH_WIMAX_TRUE@am__append_1 = $(top_srcdir)/src/wimax/*.[ch] -@WITH_WIMAX_TRUE@am__append_2 = -I$(top_srcdir)/src/wimax -@WITH_MODEM_MANAGER_1_TRUE@am__append_3 = $(MM_GLIB_CFLAGS) -subdir = src/generated -DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ - $(top_srcdir)/build-aux/depcomp -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \ - $(top_srcdir)/m4/gettext.m4 \ - $(top_srcdir)/m4/gnome-code-coverage.m4 \ - $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ - $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \ - $(top_srcdir)/m4/introspection.m4 $(top_srcdir)/m4/lib-ld.m4 \ - $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ - $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ - $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ - $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ - $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ - $(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -mkinstalldirs = $(install_sh) -d -CONFIG_HEADER = $(top_builddir)/config.h -CONFIG_CLEAN_FILES = -CONFIG_CLEAN_VPATH_FILES = -LTLIBRARIES = $(noinst_LTLIBRARIES) -am__DEPENDENCIES_1 = -libnm_generated_la_DEPENDENCIES = $(am__DEPENDENCIES_1) -am_libnm_generated_la_OBJECTS = libnm_generated_la-nm-enum-types.lo \ - libnm_generated_la-nm-marshal.lo -libnm_generated_la_OBJECTS = $(am_libnm_generated_la_OBJECTS) -AM_V_lt = $(am__v_lt_@AM_V@) -am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) -am__v_lt_0 = --silent -am__v_lt_1 = -AM_V_P = $(am__v_P_@AM_V@) -am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) -am__v_P_0 = false -am__v_P_1 = : -AM_V_GEN = $(am__v_GEN_@AM_V@) -am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) -am__v_GEN_0 = @echo " GEN " $@; -am__v_GEN_1 = -AM_V_at = $(am__v_at_@AM_V@) -am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) -am__v_at_0 = @ -am__v_at_1 = -DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) -depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp -am__depfiles_maybe = depfiles -am__mv = mv -f -COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ - $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ - $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ - $(AM_CFLAGS) $(CFLAGS) -AM_V_CC = $(am__v_CC_@AM_V@) -am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) -am__v_CC_0 = @echo " CC " $@; -am__v_CC_1 = -CCLD = $(CC) -LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(AM_LDFLAGS) $(LDFLAGS) -o $@ -AM_V_CCLD = $(am__v_CCLD_@AM_V@) -am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) -am__v_CCLD_0 = @echo " CCLD " $@; -am__v_CCLD_1 = -SOURCES = $(libnm_generated_la_SOURCES) -DIST_SOURCES = $(libnm_generated_la_SOURCES) -am__can_run_installinfo = \ - case $$AM_UPDATE_INFO_DIR in \ - n|no|NO) false;; \ - *) (install-info --version) >/dev/null 2>&1;; \ - esac -am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) -# Read a list of newline-separated strings from the standard input, -# and print each of them once, without duplicates. Input order is -# *not* preserved. -am__uniquify_input = $(AWK) '\ - BEGIN { nonempty = 0; } \ - { items[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in items) print i; }; } \ -' -# Make sure the list of sources is unique. This is necessary because, -# e.g., the same source file might be shared among _SOURCES variables -# for different programs/libraries. -am__define_uniq_tagged_files = \ - list='$(am__tagged_files)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | $(am__uniquify_input)` -ETAGS = etags -CTAGS = ctags -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -ALL_LINGUAS = @ALL_LINGUAS@ -AMTAR = @AMTAR@ -AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -AR = @AR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CKDB_PATH = @CKDB_PATH@ -CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@ -CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@ -CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CXX = @CXX@ -CXXCPP = @CXXCPP@ -CXXDEPMODE = @CXXDEPMODE@ -CXXFLAGS = @CXXFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DATADIRNAME = @DATADIRNAME@ -DBUS_CFLAGS = @DBUS_CFLAGS@ -DBUS_LIBS = @DBUS_LIBS@ -DBUS_SYS_DIR = @DBUS_SYS_DIR@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -DHCLIENT_PATH = @DHCLIENT_PATH@ -DHCPCD_PATH = @DHCPCD_PATH@ -DLLTOOL = @DLLTOOL@ -DNSMASQ_PATH = @DNSMASQ_PATH@ -DSYMUTIL = @DSYMUTIL@ -DUMPBIN = @DUMPBIN@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -FGREP = @FGREP@ -GENHTML = @GENHTML@ -GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ -GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ -GLIB_CFLAGS = @GLIB_CFLAGS@ -GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ -GLIB_LIBS = @GLIB_LIBS@ -GLIB_MAKEFILE = @GLIB_MAKEFILE@ -GLIB_MKENUMS = @GLIB_MKENUMS@ -GMSGFMT = @GMSGFMT@ -GMSGFMT_015 = @GMSGFMT_015@ -GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ -GNUTLS_LIBS = @GNUTLS_LIBS@ -GREP = @GREP@ -GTKDOC_CHECK = @GTKDOC_CHECK@ -GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ -GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ -GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ -GTKDOC_MKPDF = @GTKDOC_MKPDF@ -GTKDOC_REBASE = @GTKDOC_REBASE@ -GUDEV_CFLAGS = @GUDEV_CFLAGS@ -GUDEV_LIBS = @GUDEV_LIBS@ -HTML_DIR = @HTML_DIR@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -INTLLIBS = @INTLLIBS@ -INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ -INTLTOOL_MERGE = @INTLTOOL_MERGE@ -INTLTOOL_PERL = @INTLTOOL_PERL@ -INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ -INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ -INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ -INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ -INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ -INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ -INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ -INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ -INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ -INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ -INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ -INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ -INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ -INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ -IPTABLES_PATH = @IPTABLES_PATH@ -IWMX_SDK_CFLAGS = @IWMX_SDK_CFLAGS@ -IWMX_SDK_LIBS = @IWMX_SDK_LIBS@ -KERNEL_FIRMWARE_DIR = @KERNEL_FIRMWARE_DIR@ -LCOV = @LCOV@ -LD = @LD@ -LDFLAGS = @LDFLAGS@ -LIBDL = @LIBDL@ -LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ -LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ -LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ -LIBICONV = @LIBICONV@ -LIBINTL = @LIBINTL@ -LIBM = @LIBM@ -LIBNL_CFLAGS = @LIBNL_CFLAGS@ -LIBNL_LIBS = @LIBNL_LIBS@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@ -LIBSOUP_LIBS = @LIBSOUP_LIBS@ -LIBTOOL = @LIBTOOL@ -LIPO = @LIPO@ -LN_S = @LN_S@ -LTLIBICONV = @LTLIBICONV@ -LTLIBINTL = @LTLIBINTL@ -LTLIBOBJS = @LTLIBOBJS@ -MAINT = @MAINT@ -MAKEINFO = @MAKEINFO@ -MANIFEST_TOOL = @MANIFEST_TOOL@ -MKDIR_P = @MKDIR_P@ -MM_GLIB_CFLAGS = @MM_GLIB_CFLAGS@ -MM_GLIB_LIBS = @MM_GLIB_LIBS@ -MOC = @MOC@ -MSGFMT = @MSGFMT@ -MSGFMT_015 = @MSGFMT_015@ -MSGMERGE = @MSGMERGE@ -NM = @NM@ -NMEDIT = @NMEDIT@ -NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ -NM_MICRO_VERSION = @NM_MICRO_VERSION@ -NM_MINOR_VERSION = @NM_MINOR_VERSION@ -NM_MODIFY_SYSTEM_POLICY = @NM_MODIFY_SYSTEM_POLICY@ -NM_VERSION = @NM_VERSION@ -NSS_CFLAGS = @NSS_CFLAGS@ -NSS_LIBS = @NSS_LIBS@ -OBJDUMP = @OBJDUMP@ -OBJEXT = @OBJEXT@ -OTOOL = @OTOOL@ -OTOOL64 = @OTOOL64@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_URL = @PACKAGE_URL@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PKG_CONFIG = @PKG_CONFIG@ -PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ -PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ -POLKIT_CFLAGS = @POLKIT_CFLAGS@ -POLKIT_LIBS = @POLKIT_LIBS@ -POSUB = @POSUB@ -PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@ -QT_CFLAGS = @QT_CFLAGS@ -QT_LIBS = @QT_LIBS@ -RANLIB = @RANLIB@ -SED = @SED@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -STRIP = @STRIP@ -SYSTEMD_200_CFLAGS = @SYSTEMD_200_CFLAGS@ -SYSTEMD_200_LIBS = @SYSTEMD_200_LIBS@ -SYSTEMD_INHIBIT_CFLAGS = @SYSTEMD_INHIBIT_CFLAGS@ -SYSTEMD_INHIBIT_LIBS = @SYSTEMD_INHIBIT_LIBS@ -SYSTEMD_LOGIN_CFLAGS = @SYSTEMD_LOGIN_CFLAGS@ -SYSTEMD_LOGIN_LIBS = @SYSTEMD_LOGIN_LIBS@ -SYSTEM_CA_PATH = @SYSTEM_CA_PATH@ -UDEV_BASE_DIR = @UDEV_BASE_DIR@ -USE_NLS = @USE_NLS@ -UUID_CFLAGS = @UUID_CFLAGS@ -UUID_LIBS = @UUID_LIBS@ -VAPIGEN = @VAPIGEN@ -VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ -VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ -VERSION = @VERSION@ -XGETTEXT = @XGETTEXT@ -XGETTEXT_015 = @XGETTEXT_015@ -XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_AR = @ac_ct_AR@ -ac_ct_CC = @ac_ct_CC@ -ac_ct_CXX = @ac_ct_CXX@ -ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -intltool__v_merge_options_ = @intltool__v_merge_options_@ -intltool__v_merge_options_0 = @intltool__v_merge_options_0@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -nmbinary = @nmbinary@ -nmconfdir = @nmconfdir@ -nmdatadir = @nmdatadir@ -nmrundir = @nmrundir@ -nmstatedir = @nmstatedir@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -sysconfdir = @sysconfdir@ -systemdsystemunitdir = @systemdsystemunitdir@ -target_alias = @target_alias@ -top_build_prefix = @top_build_prefix@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -with_dhclient = @with_dhclient@ -with_dhcpcd = @with_dhcpcd@ -with_netconfig = @with_netconfig@ -with_resolvconf = @with_resolvconf@ -noinst_LTLIBRARIES = libnm-generated.la -libnm_generated_la_SOURCES = \ - nm-enum-types.c \ - nm-enum-types.h \ - nm-marshal.c \ - nm-marshal.h - -nm_daemon_all_sources = $(top_srcdir)/src/*.[ch] \ - $(top_srcdir)/src/logging/*.[ch] \ - $(top_srcdir)/src/dns-manager/*.[ch] \ - $(top_srcdir)/src/vpn-manager/*.[ch] \ - $(top_srcdir)/src/dhcp-manager/*.[ch] \ - $(top_srcdir)/src/ip6-manager/*.[ch] \ - $(top_srcdir)/src/supplicant-manager/*.[ch] \ - $(top_srcdir)/src/ppp-manager/*.[ch] \ - $(top_srcdir)/src/dnsmasq-manager/*.[ch] \ - $(top_srcdir)/src/modem-manager/*.[ch] \ - $(top_srcdir)/src/bluez-manager/*.[ch] \ - $(top_srcdir)/src/firewall-manager/*.[ch] \ - $(top_srcdir)/src/settings/*.[ch] $(am__append_1) -nm_daemon_sources_no_bindings = \ - $(filter-out %-glue.h %-bindings.h, $(wildcard $(nm_daemon_all_sources))) - -# Don't include ModemManager1-specific headers if we're not compiling with -# ModemManager1 support. -@WITH_MODEM_MANAGER_1_FALSE@nm_daemon_sources = \ -@WITH_MODEM_MANAGER_1_FALSE@ $(filter-out $(top_srcdir)/src/modem-manager/nm-modem-broadband.h, $(wildcard $(nm_daemon_sources_no_bindings))) - - -# We filter out this file, which doesn't have any enum, and which clashes -# with ModemManager1-defined symbols -@WITH_MODEM_MANAGER_1_TRUE@nm_daemon_sources = \ -@WITH_MODEM_MANAGER_1_TRUE@ $(filter-out $(top_srcdir)/src/modem-manager/nm-modem-types.h, $(wildcard $(nm_daemon_sources_no_bindings))) - -GLIB_GENERATED = nm-enum-types.h nm-enum-types.c nm-marshal.h \ - nm-marshal.c -nm_enum_types_sources = $(nm_daemon_sources) -GLIB_MKENUMS_H_FLAGS = --identifier-prefix NM -GLIB_MKENUMS_C_FLAGS = --identifier-prefix NM -nm_marshal_sources = $(nm_daemon_sources) -libnm_generated_la_CPPFLAGS = -I${top_srcdir}/include \ - -I${top_builddir}/include -I${top_srcdir}/src \ - -I${top_srcdir}/src/logging -I${top_srcdir}/src/dns-manager \ - -I${top_srcdir}/src/vpn-manager \ - -I${top_srcdir}/src/dhcp-manager \ - -I${top_srcdir}/src/ip6-manager \ - -I${top_srcdir}/src/supplicant-manager \ - -I${top_srcdir}/src/ppp-manager \ - -I${top_srcdir}/src/dnsmasq-manager \ - -I${top_srcdir}/src/modem-manager \ - -I$(top_srcdir)/src/bluez-manager \ - -I$(top_srcdir)/src/firewall-manager \ - -I$(top_srcdir)/src/settings -I$(top_srcdir)/src/wifi \ - -I$(top_srcdir)/libnm-util $(DBUS_CFLAGS) $(GLIB_CFLAGS) \ - $(GUDEV_CFLAGS) $(LIBNL_CFLAGS) $(POLKIT_CFLAGS) \ - $(SYSTEMD_LOGIN_CFLAGS) $(IWMX_SDK_CFLAGS) $(am__append_2) \ - $(am__append_3) -libnm_generated_la_LIBADD = \ - $(GLIB_LIBS) - -BUILT_SOURCES = $(GLIB_GENERATED) -all: $(BUILT_SOURCES) - $(MAKE) $(AM_MAKEFLAGS) all-am - -.SUFFIXES: -.SUFFIXES: .c .lo .o .obj -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ - && { if test -f $@; then exit 0; else break; fi; }; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/generated/Makefile'; \ - $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --gnu src/generated/Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(am__aclocal_m4_deps): - -clean-noinstLTLIBRARIES: - -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) - @list='$(noinst_LTLIBRARIES)'; \ - locs=`for p in $$list; do echo $$p; done | \ - sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ - sort -u`; \ - test -z "$$locs" || { \ - echo rm -f $${locs}; \ - rm -f $${locs}; \ - } - -libnm-generated.la: $(libnm_generated_la_OBJECTS) $(libnm_generated_la_DEPENDENCIES) $(EXTRA_libnm_generated_la_DEPENDENCIES) - $(AM_V_CCLD)$(LINK) $(libnm_generated_la_OBJECTS) $(libnm_generated_la_LIBADD) $(LIBS) - -mostlyclean-compile: - -rm -f *.$(OBJEXT) - -distclean-compile: - -rm -f *.tab.c - -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_generated_la-nm-enum-types.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_generated_la-nm-marshal.Plo@am__quote@ - -.c.o: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< - -.c.obj: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` - -.c.lo: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< - -libnm_generated_la-nm-enum-types.lo: nm-enum-types.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_generated_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_generated_la-nm-enum-types.lo -MD -MP -MF $(DEPDIR)/libnm_generated_la-nm-enum-types.Tpo -c -o libnm_generated_la-nm-enum-types.lo `test -f 'nm-enum-types.c' || echo '$(srcdir)/'`nm-enum-types.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnm_generated_la-nm-enum-types.Tpo $(DEPDIR)/libnm_generated_la-nm-enum-types.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-enum-types.c' object='libnm_generated_la-nm-enum-types.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_generated_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_generated_la-nm-enum-types.lo `test -f 'nm-enum-types.c' || echo '$(srcdir)/'`nm-enum-types.c - -libnm_generated_la-nm-marshal.lo: nm-marshal.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_generated_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_generated_la-nm-marshal.lo -MD -MP -MF $(DEPDIR)/libnm_generated_la-nm-marshal.Tpo -c -o libnm_generated_la-nm-marshal.lo `test -f 'nm-marshal.c' || echo '$(srcdir)/'`nm-marshal.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnm_generated_la-nm-marshal.Tpo $(DEPDIR)/libnm_generated_la-nm-marshal.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-marshal.c' object='libnm_generated_la-nm-marshal.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_generated_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_generated_la-nm-marshal.lo `test -f 'nm-marshal.c' || echo '$(srcdir)/'`nm-marshal.c - -mostlyclean-libtool: - -rm -f *.lo - -clean-libtool: - -rm -rf .libs _libs - -ID: $(am__tagged_files) - $(am__define_uniq_tagged_files); mkid -fID $$unique -tags: tags-am -TAGS: tags - -tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) - set x; \ - here=`pwd`; \ - $(am__define_uniq_tagged_files); \ - shift; \ - if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ - test -n "$$unique" || unique=$$empty_fix; \ - if test $$# -gt 0; then \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - "$$@" $$unique; \ - else \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$unique; \ - fi; \ - fi -ctags: ctags-am - -CTAGS: ctags -ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) - $(am__define_uniq_tagged_files); \ - test -z "$(CTAGS_ARGS)$$unique" \ - || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$unique - -GTAGS: - here=`$(am__cd) $(top_builddir) && pwd` \ - && $(am__cd) $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) "$$here" -cscopelist: cscopelist-am - -cscopelist-am: $(am__tagged_files) - list='$(am__tagged_files)'; \ - case "$(srcdir)" in \ - [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ - *) sdir=$(subdir)/$(srcdir) ;; \ - esac; \ - for i in $$list; do \ - if test -f "$$i"; then \ - echo "$(subdir)/$$i"; \ - else \ - echo "$$sdir/$$i"; \ - fi; \ - done >> $(top_builddir)/cscope.files - -distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags - -distdir: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d "$(distdir)/$$file"; then \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ - else \ - test -f "$(distdir)/$$file" \ - || cp -p $$d/$$file "$(distdir)/$$file" \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: $(BUILT_SOURCES) - $(MAKE) $(AM_MAKEFLAGS) check-am -all-am: Makefile $(LTLIBRARIES) -installdirs: -install: $(BUILT_SOURCES) - $(MAKE) $(AM_MAKEFLAGS) install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - if test -z '$(STRIP)'; then \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - install; \ - else \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ - fi -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." - -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) -clean: clean-am - -clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ - mostlyclean-am - -distclean: distclean-am - -rm -rf ./$(DEPDIR) - -rm -f Makefile -distclean-am: clean-am distclean-compile distclean-generic \ - distclean-tags - -dvi: dvi-am - -dvi-am: - -html: html-am - -html-am: - -info: info-am - -info-am: - -install-data-am: - -install-dvi: install-dvi-am - -install-dvi-am: - -install-exec-am: - -install-html: install-html-am - -install-html-am: - -install-info: install-info-am - -install-info-am: - -install-man: - -install-pdf: install-pdf-am - -install-pdf-am: - -install-ps: install-ps-am - -install-ps-am: - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -rf ./$(DEPDIR) - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-compile mostlyclean-generic \ - mostlyclean-libtool - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: - -.MAKE: all check install install-am install-strip - -.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ - clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ - ctags-am distclean distclean-compile distclean-generic \ - distclean-libtool distclean-tags distdir dvi dvi-am html \ - html-am info info-am install install-am install-data \ - install-data-am install-dvi install-dvi-am install-exec \ - install-exec-am install-html install-html-am install-info \ - install-info-am install-man install-pdf install-pdf-am \ - install-ps install-ps-am install-strip installcheck \ - installcheck-am installdirs maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-compile \ - mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ - tags tags-am uninstall uninstall-am - -include $(GLIB_MAKEFILE) - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/src/generated/nm-enum-types.c b/src/generated/nm-enum-types.c deleted file mode 100644 index 9bb95806..00000000 --- a/src/generated/nm-enum-types.c +++ /dev/null @@ -1,1036 +0,0 @@ - - - -/* Generated by glib-mkenums. Do not edit */ - -#include "nm-enum-types.h" - -#include "nm-active-connection.h" -#include "nm-wifi-ap.h" -#include "nm-device-bt.h" -#include "nm-device-infiniband.h" -#include "nm-device-bond.h" -#include "nm-device-wired.h" -#include "nm-dhcp6-config.h" -#include "nm-session-utils.h" -#include "nm-netlink-compat.h" -#include "nm-session-monitor.h" -#include "nm-connection-provider.h" -#include "nm-device-ethernet.h" -#include "nm-call-store.h" -#include "nm-config.h" -#include "nm-policy-hosts.h" -#include "nm-rfkill.h" -#include "nm-dispatcher.h" -#include "nm-ip4-config.h" -#include "nm-manager.h" -#include "nm-device-modem.h" -#include "nm-activation-request.h" -#include "nm-wifi-ap-utils.h" -#include "nm-dbus-manager.h" -#include "nm-policy-hostname.h" -#include "nm-device.h" -#include "nm-types.h" -#include "nm-ip6-config.h" -#include "nm-system.h" -#include "nm-policy.h" -#include "nm-manager-auth.h" -#include "nm-device-bridge.h" -#include "nm-device-wifi.h" -#include "nm-device-private.h" -#include "nm-netlink-utils.h" -#include "nm-dhcp4-config.h" -#include "nm-udev-manager.h" -#include "nm-connectivity.h" -#include "nm-device-vlan.h" -#include "nm-netlink-monitor.h" -#include "nm-device-olpc-mesh.h" -#include "nm-hostname-provider.h" -#include "nm-sleep-monitor.h" -#include "nm-device-factory.h" -#include "NetworkManagerUtils.h" -#include "nm-device-adsl.h" -#include "nm-properties-changed-signal.h" -#include "nm-logging.h" -#include "nm-dns-utils.h" -#include "nm-dns-plugin.h" -#include "nm-dns-manager.h" -#include "nm-dns-dnsmasq.h" -#include "nm-vpn-manager.h" -#include "nm-vpn-service.h" -#include "nm-vpn-connection.h" -#include "nm-dhcp-dhcpcd.h" -#include "nm-dhcp-dhclient.h" -#include "nm-dhcp-client.h" -#include "nm-dhcp-dhclient-utils.h" -#include "nm-dhcp-manager.h" -#include "nm-ip6-manager.h" -#include "nm-supplicant-types.h" -#include "nm-supplicant-config.h" -#include "nm-supplicant-settings-verify.h" -#include "nm-supplicant-manager.h" -#include "nm-supplicant-interface.h" -#include "nm-ppp-status.h" -#include "nm-ppp-manager.h" -#include "nm-pppd-plugin.h" -#include "nm-dnsmasq-manager.h" -#include "nm-modem.h" -#include "nm-modem-generic.h" -#include "nm-modem-cdma.h" -#include "nm-modem-broadband.h" -#include "nm-modem-gsm.h" -#include "nm-modem-manager.h" -#include "nm-bluez-device.h" -#include "nm-bluez-manager.h" -#include "nm-bluez-common.h" -#include "nm-bluez4-adapter.h" -#include "nm-firewall-manager.h" -#include "nm-settings-connection.h" -#include "nm-settings.h" -#include "nm-default-wired-connection.h" -#include "nm-system-config-interface.h" -#include "nm-settings-utils.h" -#include "nm-settings-error.h" -#include "nm-agent-manager.h" -#include "nm-inotify-helper.h" -#include "nm-secret-agent.h" -#include "nm-device-wimax.h" -#include "iwmxsdk.h" -#include "nm-wimax-types.h" -#include "nm-wimax-util.h" -#include "nm-wimax-nsp.h" - -GType -nm_bt_error_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { NM_BT_ERROR_CONNECTION_NOT_BT, "NM_BT_ERROR_CONNECTION_NOT_BT", "ConnectionNotBt" }, - { NM_BT_ERROR_CONNECTION_INVALID, "NM_BT_ERROR_CONNECTION_INVALID", "ConnectionInvalid" }, - { NM_BT_ERROR_CONNECTION_INCOMPATIBLE, "NM_BT_ERROR_CONNECTION_INCOMPATIBLE", "ConnectionIncompatible" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("NMBtError"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -nm_infiniband_error_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { NM_INFINIBAND_ERROR_CONNECTION_NOT_INFINIBAND, "NM_INFINIBAND_ERROR_CONNECTION_NOT_INFINIBAND", "ConnectionNotInfiniband" }, - { NM_INFINIBAND_ERROR_CONNECTION_INVALID, "NM_INFINIBAND_ERROR_CONNECTION_INVALID", "ConnectionInvalid" }, - { NM_INFINIBAND_ERROR_CONNECTION_INCOMPATIBLE, "NM_INFINIBAND_ERROR_CONNECTION_INCOMPATIBLE", "ConnectionIncompatible" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("NMInfinibandError"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -nm_bond_error_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { NM_BOND_ERROR_CONNECTION_NOT_BOND, "NM_BOND_ERROR_CONNECTION_NOT_BOND", "ConnectionNotBond" }, - { NM_BOND_ERROR_CONNECTION_INVALID, "NM_BOND_ERROR_CONNECTION_INVALID", "ConnectionInvalid" }, - { NM_BOND_ERROR_CONNECTION_INCOMPATIBLE, "NM_BOND_ERROR_CONNECTION_INCOMPATIBLE", "ConnectionIncompatible" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("NMBondError"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -nm_session_monitor_error_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { NM_SESSION_MONITOR_ERROR_IO_ERROR, "NM_SESSION_MONITOR_ERROR_IO_ERROR", "IOError" }, - { NM_SESSION_MONITOR_ERROR_MALFORMED_DATABASE, "NM_SESSION_MONITOR_ERROR_MALFORMED_DATABASE", "MalformedDatabase" }, - { NM_SESSION_MONITOR_ERROR_UNKNOWN_USER, "NM_SESSION_MONITOR_ERROR_UNKNOWN_USER", "UnknownUser" }, - { NM_SESSION_MONITOR_ERROR_NO_DATABASE, "NM_SESSION_MONITOR_ERROR_NO_DATABASE", "NoDatabase" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("NMSessionMonitorError"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -nm_ethernet_error_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { NM_ETHERNET_ERROR_CONNECTION_NOT_WIRED, "NM_ETHERNET_ERROR_CONNECTION_NOT_WIRED", "ConnectionNotWired" }, - { NM_ETHERNET_ERROR_CONNECTION_INVALID, "NM_ETHERNET_ERROR_CONNECTION_INVALID", "ConnectionInvalid" }, - { NM_ETHERNET_ERROR_CONNECTION_INCOMPATIBLE, "NM_ETHERNET_ERROR_CONNECTION_INCOMPATIBLE", "ConnectionIncompatible" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("NMEthernetError"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -nm_config_error_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { NM_CONFIG_ERROR_NO_MEMORY, "NM_CONFIG_ERROR_NO_MEMORY", "NoMemory" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("NMConfigError"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -nm_rf_kill_state_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { RFKILL_UNBLOCKED, "RFKILL_UNBLOCKED", "unblocked" }, - { RFKILL_SOFT_BLOCKED, "RFKILL_SOFT_BLOCKED", "soft-blocked" }, - { RFKILL_HARD_BLOCKED, "RFKILL_HARD_BLOCKED", "hard-blocked" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("RfKillState"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -nm_rf_kill_type_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { RFKILL_TYPE_WLAN, "RFKILL_TYPE_WLAN", "wlan" }, - { RFKILL_TYPE_WWAN, "RFKILL_TYPE_WWAN", "wwan" }, - { RFKILL_TYPE_WIMAX, "RFKILL_TYPE_WIMAX", "wimax" }, - { RFKILL_TYPE_UNKNOWN, "RFKILL_TYPE_UNKNOWN", "unknown" }, - { RFKILL_TYPE_MAX, "RFKILL_TYPE_MAX", "max" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("RfKillType"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -nm_dispatcher_action_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { DISPATCHER_ACTION_HOSTNAME, "DISPATCHER_ACTION_HOSTNAME", "hostname" }, - { DISPATCHER_ACTION_UP, "DISPATCHER_ACTION_UP", "up" }, - { DISPATCHER_ACTION_PRE_DOWN, "DISPATCHER_ACTION_PRE_DOWN", "pre-down" }, - { DISPATCHER_ACTION_DOWN, "DISPATCHER_ACTION_DOWN", "down" }, - { DISPATCHER_ACTION_VPN_UP, "DISPATCHER_ACTION_VPN_UP", "vpn-up" }, - { DISPATCHER_ACTION_VPN_PRE_DOWN, "DISPATCHER_ACTION_VPN_PRE_DOWN", "vpn-pre-down" }, - { DISPATCHER_ACTION_VPN_DOWN, "DISPATCHER_ACTION_VPN_DOWN", "vpn-down" }, - { DISPATCHER_ACTION_DHCP4_CHANGE, "DISPATCHER_ACTION_DHCP4_CHANGE", "dhcp4-change" }, - { DISPATCHER_ACTION_DHCP6_CHANGE, "DISPATCHER_ACTION_DHCP6_CHANGE", "dhcp6-change" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("DispatcherAction"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -nm_ip4_config_compare_flags_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { NM_IP4_COMPARE_FLAG_NONE, "NM_IP4_COMPARE_FLAG_NONE", "none" }, - { NM_IP4_COMPARE_FLAG_ADDRESSES, "NM_IP4_COMPARE_FLAG_ADDRESSES", "addresses" }, - { NM_IP4_COMPARE_FLAG_PTP_ADDRESS, "NM_IP4_COMPARE_FLAG_PTP_ADDRESS", "ptp-address" }, - { NM_IP4_COMPARE_FLAG_NAMESERVERS, "NM_IP4_COMPARE_FLAG_NAMESERVERS", "nameservers" }, - { NM_IP4_COMPARE_FLAG_ROUTES, "NM_IP4_COMPARE_FLAG_ROUTES", "routes" }, - { NM_IP4_COMPARE_FLAG_DOMAINS, "NM_IP4_COMPARE_FLAG_DOMAINS", "domains" }, - { NM_IP4_COMPARE_FLAG_SEARCHES, "NM_IP4_COMPARE_FLAG_SEARCHES", "searches" }, - { NM_IP4_COMPARE_FLAG_MTU, "NM_IP4_COMPARE_FLAG_MTU", "mtu" }, - { NM_IP4_COMPARE_FLAG_MSS, "NM_IP4_COMPARE_FLAG_MSS", "mss" }, - { NM_IP4_COMPARE_FLAG_WINS_SERVERS, "NM_IP4_COMPARE_FLAG_WINS_SERVERS", "wins-servers" }, - { NM_IP4_COMPARE_FLAG_NIS_SERVERS, "NM_IP4_COMPARE_FLAG_NIS_SERVERS", "nis-servers" }, - { NM_IP4_COMPARE_FLAG_NIS_DOMAIN, "NM_IP4_COMPARE_FLAG_NIS_DOMAIN", "nis-domain" }, - { NM_IP4_COMPARE_FLAG_ALL, "NM_IP4_COMPARE_FLAG_ALL", "all" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("NMIP4ConfigCompareFlags"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -nm_manager_error_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { NM_MANAGER_ERROR_UNKNOWN_CONNECTION, "NM_MANAGER_ERROR_UNKNOWN_CONNECTION", "UnknownConnection" }, - { NM_MANAGER_ERROR_UNKNOWN_DEVICE, "NM_MANAGER_ERROR_UNKNOWN_DEVICE", "UnknownDevice" }, - { NM_MANAGER_ERROR_UNMANAGED_DEVICE, "NM_MANAGER_ERROR_UNMANAGED_DEVICE", "UnmanagedDevice" }, - { NM_MANAGER_ERROR_SYSTEM_CONNECTION, "NM_MANAGER_ERROR_SYSTEM_CONNECTION", "SystemConnection" }, - { NM_MANAGER_ERROR_PERMISSION_DENIED, "NM_MANAGER_ERROR_PERMISSION_DENIED", "PermissionDenied" }, - { NM_MANAGER_ERROR_CONNECTION_NOT_ACTIVE, "NM_MANAGER_ERROR_CONNECTION_NOT_ACTIVE", "ConnectionNotActive" }, - { NM_MANAGER_ERROR_ALREADY_ASLEEP_OR_AWAKE, "NM_MANAGER_ERROR_ALREADY_ASLEEP_OR_AWAKE", "AlreadyAsleepOrAwake" }, - { NM_MANAGER_ERROR_ALREADY_ENABLED_OR_DISABLED, "NM_MANAGER_ERROR_ALREADY_ENABLED_OR_DISABLED", "AlreadyEnabledOrDisabled" }, - { NM_MANAGER_ERROR_UNSUPPORTED_CONNECTION_TYPE, "NM_MANAGER_ERROR_UNSUPPORTED_CONNECTION_TYPE", "UnsupportedConnectionType" }, - { NM_MANAGER_ERROR_DEPENDENCY_FAILED, "NM_MANAGER_ERROR_DEPENDENCY_FAILED", "DependencyFailed" }, - { NM_MANAGER_ERROR_AUTOCONNECT_NOT_ALLOWED, "NM_MANAGER_ERROR_AUTOCONNECT_NOT_ALLOWED", "AutoconnectNotAllowed" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("NMManagerError"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -nm_device_error_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { NM_DEVICE_ERROR_CONNECTION_ACTIVATING, "NM_DEVICE_ERROR_CONNECTION_ACTIVATING", "ConnectionActivating" }, - { NM_DEVICE_ERROR_CONNECTION_INVALID, "NM_DEVICE_ERROR_CONNECTION_INVALID", "ConnectionInvalid" }, - { NM_DEVICE_ERROR_NOT_ACTIVE, "NM_DEVICE_ERROR_NOT_ACTIVE", "NotActive" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("NMDeviceError"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -nm_ip6_config_compare_flags_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { NM_IP6_COMPARE_FLAG_NONE, "NM_IP6_COMPARE_FLAG_NONE", "none" }, - { NM_IP6_COMPARE_FLAG_ADDRESSES, "NM_IP6_COMPARE_FLAG_ADDRESSES", "addresses" }, - { NM_IP6_COMPARE_FLAG_PTP_ADDRESS, "NM_IP6_COMPARE_FLAG_PTP_ADDRESS", "ptp-address" }, - { NM_IP6_COMPARE_FLAG_NAMESERVERS, "NM_IP6_COMPARE_FLAG_NAMESERVERS", "nameservers" }, - { NM_IP6_COMPARE_FLAG_ROUTES, "NM_IP6_COMPARE_FLAG_ROUTES", "routes" }, - { NM_IP6_COMPARE_FLAG_DOMAINS, "NM_IP6_COMPARE_FLAG_DOMAINS", "domains" }, - { NM_IP6_COMPARE_FLAG_SEARCHES, "NM_IP6_COMPARE_FLAG_SEARCHES", "searches" }, - { NM_IP6_COMPARE_FLAG_MSS, "NM_IP6_COMPARE_FLAG_MSS", "mss" }, - { NM_IP6_COMPARE_FLAG_ALL, "NM_IP6_COMPARE_FLAG_ALL", "all" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("NMIP6ConfigCompareFlags"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -nm_auth_call_result_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { NM_AUTH_CALL_RESULT_UNKNOWN, "NM_AUTH_CALL_RESULT_UNKNOWN", "unknown" }, - { NM_AUTH_CALL_RESULT_YES, "NM_AUTH_CALL_RESULT_YES", "yes" }, - { NM_AUTH_CALL_RESULT_AUTH, "NM_AUTH_CALL_RESULT_AUTH", "auth" }, - { NM_AUTH_CALL_RESULT_NO, "NM_AUTH_CALL_RESULT_NO", "no" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("NMAuthCallResult"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -nm_bridge_error_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { NM_BRIDGE_ERROR_CONNECTION_NOT_BRIDGE, "NM_BRIDGE_ERROR_CONNECTION_NOT_BRIDGE", "ConnectionNotBridge" }, - { NM_BRIDGE_ERROR_CONNECTION_INVALID, "NM_BRIDGE_ERROR_CONNECTION_INVALID", "ConnectionInvalid" }, - { NM_BRIDGE_ERROR_CONNECTION_INCOMPATIBLE, "NM_BRIDGE_ERROR_CONNECTION_INCOMPATIBLE", "ConnectionIncompatible" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("NMBridgeError"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -nm_wifi_error_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { NM_WIFI_ERROR_CONNECTION_NOT_WIRELESS, "NM_WIFI_ERROR_CONNECTION_NOT_WIRELESS", "ConnectionNotWireless" }, - { NM_WIFI_ERROR_CONNECTION_INVALID, "NM_WIFI_ERROR_CONNECTION_INVALID", "ConnectionInvalid" }, - { NM_WIFI_ERROR_CONNECTION_INCOMPATIBLE, "NM_WIFI_ERROR_CONNECTION_INCOMPATIBLE", "ConnectionIncompatible" }, - { NM_WIFI_ERROR_ACCESS_POINT_NOT_FOUND, "NM_WIFI_ERROR_ACCESS_POINT_NOT_FOUND", "AccessPointNotFound" }, - { NM_WIFI_ERROR_SCAN_NOT_ALLOWED, "NM_WIFI_ERROR_SCAN_NOT_ALLOWED", "ScanNotAllowed" }, - { NM_WIFI_ERROR_AP_MODE_UNSUPPORTED, "NM_WIFI_ERROR_AP_MODE_UNSUPPORTED", "ApModeUnsupported" }, - { NM_WIFI_ERROR_ADHOC_MODE_UNSUPPORTED, "NM_WIFI_ERROR_ADHOC_MODE_UNSUPPORTED", "AdhocModeUnsupported" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("NMWifiError"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -nm_nm_nl_prop_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { NMNL_PROP_INVALID, "NMNL_PROP_INVALID", "invalid" }, - { NMNL_PROP_PROT, "NMNL_PROP_PROT", "prot" }, - { NMNL_PROP_SCOPE, "NMNL_PROP_SCOPE", "scope" }, - { NMNL_PROP_TABLE, "NMNL_PROP_TABLE", "table" }, - { NMNL_PROP_PRIO, "NMNL_PROP_PRIO", "prio" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("NmNlProp"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -nm_vlan_error_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { NM_VLAN_ERROR_CONNECTION_NOT_VLAN, "NM_VLAN_ERROR_CONNECTION_NOT_VLAN", "ConnectionNotVlan" }, - { NM_VLAN_ERROR_CONNECTION_INVALID, "NM_VLAN_ERROR_CONNECTION_INVALID", "ConnectionInvalid" }, - { NM_VLAN_ERROR_CONNECTION_INCOMPATIBLE, "NM_VLAN_ERROR_CONNECTION_INCOMPATIBLE", "ConnectionIncompatible" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("NMVlanError"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -nm_netlink_monitor_error_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { NM_NETLINK_MONITOR_ERROR_GENERIC, "NM_NETLINK_MONITOR_ERROR_GENERIC", "generic" }, - { NM_NETLINK_MONITOR_ERROR_NETLINK_ALLOC_HANDLE, "NM_NETLINK_MONITOR_ERROR_NETLINK_ALLOC_HANDLE", "netlink-alloc-handle" }, - { NM_NETLINK_MONITOR_ERROR_NETLINK_CONNECT, "NM_NETLINK_MONITOR_ERROR_NETLINK_CONNECT", "netlink-connect" }, - { NM_NETLINK_MONITOR_ERROR_NETLINK_JOIN_GROUP, "NM_NETLINK_MONITOR_ERROR_NETLINK_JOIN_GROUP", "netlink-join-group" }, - { NM_NETLINK_MONITOR_ERROR_NETLINK_ALLOC_LINK_CACHE, "NM_NETLINK_MONITOR_ERROR_NETLINK_ALLOC_LINK_CACHE", "netlink-alloc-link-cache" }, - { NM_NETLINK_MONITOR_ERROR_PROCESSING_MESSAGE, "NM_NETLINK_MONITOR_ERROR_PROCESSING_MESSAGE", "processing-message" }, - { NM_NETLINK_MONITOR_ERROR_BAD_ALLOC, "NM_NETLINK_MONITOR_ERROR_BAD_ALLOC", "bad-alloc" }, - { NM_NETLINK_MONITOR_ERROR_WAITING_FOR_SOCKET_DATA, "NM_NETLINK_MONITOR_ERROR_WAITING_FOR_SOCKET_DATA", "waiting-for-socket-data" }, - { NM_NETLINK_MONITOR_ERROR_LINK_CACHE_UPDATE, "NM_NETLINK_MONITOR_ERROR_LINK_CACHE_UPDATE", "link-cache-update" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("NMNetlinkMonitorError"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -nm_olpc_mesh_error_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { NM_OLPC_MESH_ERROR_CONNECTION_NOT_MESH, "NM_OLPC_MESH_ERROR_CONNECTION_NOT_MESH", "ConnectionNotMesh" }, - { NM_OLPC_MESH_ERROR_CONNECTION_INVALID, "NM_OLPC_MESH_ERROR_CONNECTION_INVALID", "ConnectionInvalid" }, - { NM_OLPC_MESH_ERROR_CONNECTION_INCOMPATIBLE, "NM_OLPC_MESH_ERROR_CONNECTION_INCOMPATIBLE", "ConnectionIncompatible" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("NMOlpcMeshError"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -nm_adsl_error_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { NM_ADSL_ERROR_CONNECTION_NOT_ADSL, "NM_ADSL_ERROR_CONNECTION_NOT_ADSL", "ConnectionNotAdsl" }, - { NM_ADSL_ERROR_CONNECTION_INVALID, "NM_ADSL_ERROR_CONNECTION_INVALID", "ConnectionInvalid" }, - { NM_ADSL_ERROR_CONNECTION_INCOMPATIBLE, "NM_ADSL_ERROR_CONNECTION_INCOMPATIBLE", "ConnectionIncompatible" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("NMAdslError"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -nm_logging_error_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { NM_LOGGING_ERROR_UNKNOWN_LEVEL, "NM_LOGGING_ERROR_UNKNOWN_LEVEL", "UnknownLevel" }, - { NM_LOGGING_ERROR_UNKNOWN_DOMAIN, "NM_LOGGING_ERROR_UNKNOWN_DOMAIN", "UnknownDomain" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("NMLoggingError"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -nm_dns_manager_error_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { NM_DNS_MANAGER_ERROR_SYSTEM, "NM_DNS_MANAGER_ERROR_SYSTEM", "system" }, - { NM_DNS_MANAGER_ERROR_INVALID_NAMESERVER, "NM_DNS_MANAGER_ERROR_INVALID_NAMESERVER", "invalid-nameserver" }, - { NM_DNS_MANAGER_ERROR_INVALID_HOST, "NM_DNS_MANAGER_ERROR_INVALID_HOST", "invalid-host" }, - { NM_DNS_MANAGER_ERROR_INVALID_ID, "NM_DNS_MANAGER_ERROR_INVALID_ID", "invalid-id" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("NMDnsManagerError"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -nm_dns_ip_config_type_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { NM_DNS_IP_CONFIG_TYPE_DEFAULT, "NM_DNS_IP_CONFIG_TYPE_DEFAULT", "default" }, - { NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE, "NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE", "best-device" }, - { NM_DNS_IP_CONFIG_TYPE_VPN, "NM_DNS_IP_CONFIG_TYPE_VPN", "vpn" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("NMDnsIPConfigType"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -nm_vpn_manager_error_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { NM_VPN_MANAGER_ERROR_DEVICE_NOT_ACTIVE, "NM_VPN_MANAGER_ERROR_DEVICE_NOT_ACTIVE", "BaseDeviceNotActive" }, - { NM_VPN_MANAGER_ERROR_CONNECTION_INVALID, "NM_VPN_MANAGER_ERROR_CONNECTION_INVALID", "ConnectionInvalid" }, - { NM_VPN_MANAGER_ERROR_SERVICE_INVALID, "NM_VPN_MANAGER_ERROR_SERVICE_INVALID", "ServiceInvalid" }, - { NM_VPN_MANAGER_ERROR_SERVICE_START_FAILED, "NM_VPN_MANAGER_ERROR_SERVICE_START_FAILED", "ServiceStartFailed" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("NMVPNManagerError"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -nm_dhcp_state_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { DHC_NBI, "DHC_NBI", "nbi" }, - { DHC_PREINIT, "DHC_PREINIT", "preinit" }, - { DHC_PREINIT6, "DHC_PREINIT6", "preinit6" }, - { DHC_BOUND4, "DHC_BOUND4", "bound4" }, - { DHC_BOUND6, "DHC_BOUND6", "bound6" }, - { DHC_IPV4LL, "DHC_IPV4LL", "ipv4ll" }, - { DHC_RENEW4, "DHC_RENEW4", "renew4" }, - { DHC_RENEW6, "DHC_RENEW6", "renew6" }, - { DHC_REBOOT, "DHC_REBOOT", "reboot" }, - { DHC_REBIND4, "DHC_REBIND4", "rebind4" }, - { DHC_REBIND6, "DHC_REBIND6", "rebind6" }, - { DHC_DEPREF6, "DHC_DEPREF6", "depref6" }, - { DHC_STOP, "DHC_STOP", "stop" }, - { DHC_STOP6, "DHC_STOP6", "stop6" }, - { DHC_MEDIUM, "DHC_MEDIUM", "medium" }, - { DHC_TIMEOUT, "DHC_TIMEOUT", "timeout" }, - { DHC_FAIL, "DHC_FAIL", "fail" }, - { DHC_EXPIRE, "DHC_EXPIRE", "expire" }, - { DHC_EXPIRE6, "DHC_EXPIRE6", "expire6" }, - { DHC_RELEASE, "DHC_RELEASE", "release" }, - { DHC_RELEASE6, "DHC_RELEASE6", "release6" }, - { DHC_START, "DHC_START", "start" }, - { DHC_ABEND, "DHC_ABEND", "abend" }, - { DHC_END, "DHC_END", "end" }, - { DHC_END_OPTIONS, "DHC_END_OPTIONS", "end-options" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("NMDHCPState"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -nm_dhcp_manager_error_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { NM_DHCP_MANAGER_ERROR_BAD_CLIENT, "NM_DHCP_MANAGER_ERROR_BAD_CLIENT", "BadClient" }, - { NM_DHCP_MANAGER_ERROR_INTERNAL, "NM_DHCP_MANAGER_ERROR_INTERNAL", "InternalError" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("NMDHCPManagerError"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -nm_opt_type_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { TYPE_INVALID, "TYPE_INVALID", "invalid" }, - { TYPE_INT, "TYPE_INT", "int" }, - { TYPE_BYTES, "TYPE_BYTES", "bytes" }, - { TYPE_UTF8, "TYPE_UTF8", "utf8" }, - { TYPE_KEYWORD, "TYPE_KEYWORD", "keyword" }, - { TYPE_STRING, "TYPE_STRING", "string" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("OptType"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -nm_ap_support_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { AP_SUPPORT_UNKNOWN, "AP_SUPPORT_UNKNOWN", "unknown" }, - { AP_SUPPORT_NO, "AP_SUPPORT_NO", "no" }, - { AP_SUPPORT_YES, "AP_SUPPORT_YES", "yes" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("ApSupport"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -nm_ppp_status_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { NM_PPP_STATUS_UNKNOWN, "NM_PPP_STATUS_UNKNOWN", "unknown" }, - { NM_PPP_STATUS_DEAD, "NM_PPP_STATUS_DEAD", "dead" }, - { NM_PPP_STATUS_INITIALIZE, "NM_PPP_STATUS_INITIALIZE", "initialize" }, - { NM_PPP_STATUS_SERIALCONN, "NM_PPP_STATUS_SERIALCONN", "serialconn" }, - { NM_PPP_STATUS_DORMANT, "NM_PPP_STATUS_DORMANT", "dormant" }, - { NM_PPP_STATUS_ESTABLISH, "NM_PPP_STATUS_ESTABLISH", "establish" }, - { NM_PPP_STATUS_AUTHENTICATE, "NM_PPP_STATUS_AUTHENTICATE", "authenticate" }, - { NM_PPP_STATUS_CALLBACK, "NM_PPP_STATUS_CALLBACK", "callback" }, - { NM_PPP_STATUS_NETWORK, "NM_PPP_STATUS_NETWORK", "network" }, - { NM_PPP_STATUS_RUNNING, "NM_PPP_STATUS_RUNNING", "running" }, - { NM_PPP_STATUS_TERMINATE, "NM_PPP_STATUS_TERMINATE", "terminate" }, - { NM_PPP_STATUS_DISCONNECT, "NM_PPP_STATUS_DISCONNECT", "disconnect" }, - { NM_PPP_STATUS_HOLDOFF, "NM_PPP_STATUS_HOLDOFF", "holdoff" }, - { NM_PPP_STATUS_MASTER, "NM_PPP_STATUS_MASTER", "master" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("NMPPPStatus"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -nm_dns_masq_status_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { NM_DNSMASQ_STATUS_UNKNOWN, "NM_DNSMASQ_STATUS_UNKNOWN", "unknown" }, - { NM_DNSMASQ_STATUS_DEAD, "NM_DNSMASQ_STATUS_DEAD", "dead" }, - { NM_DNSMASQ_STATUS_RUNNING, "NM_DNSMASQ_STATUS_RUNNING", "running" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("NMDnsMasqStatus"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -nm_modem_state_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { NM_MODEM_STATE_UNKNOWN, "NM_MODEM_STATE_UNKNOWN", "unknown" }, - { NM_MODEM_STATE_DISABLED, "NM_MODEM_STATE_DISABLED", "disabled" }, - { NM_MODEM_STATE_DISABLING, "NM_MODEM_STATE_DISABLING", "disabling" }, - { NM_MODEM_STATE_ENABLING, "NM_MODEM_STATE_ENABLING", "enabling" }, - { NM_MODEM_STATE_ENABLED, "NM_MODEM_STATE_ENABLED", "enabled" }, - { NM_MODEM_STATE_SEARCHING, "NM_MODEM_STATE_SEARCHING", "searching" }, - { NM_MODEM_STATE_REGISTERED, "NM_MODEM_STATE_REGISTERED", "registered" }, - { NM_MODEM_STATE_DISCONNECTING, "NM_MODEM_STATE_DISCONNECTING", "disconnecting" }, - { NM_MODEM_STATE_CONNECTING, "NM_MODEM_STATE_CONNECTING", "connecting" }, - { NM_MODEM_STATE_CONNECTED, "NM_MODEM_STATE_CONNECTED", "connected" }, - { NM_MODEM_STATE_LAST, "NM_MODEM_STATE_LAST", "last" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("NMModemState"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -nm_cdma_error_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { NM_CDMA_ERROR_CONNECTION_NOT_CDMA, "NM_CDMA_ERROR_CONNECTION_NOT_CDMA", "ConnectionNotCdma" }, - { NM_CDMA_ERROR_CONNECTION_INVALID, "NM_CDMA_ERROR_CONNECTION_INVALID", "ConnectionInvalid" }, - { NM_CDMA_ERROR_CONNECTION_INCOMPATIBLE, "NM_CDMA_ERROR_CONNECTION_INCOMPATIBLE", "ConnectionIncompatible" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("NMCdmaError"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -nm_modem_broadband_error_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { NM_MODEM_BROADBAND_ERROR_CONNECTION_NOT_GSM, "NM_MODEM_BROADBAND_ERROR_CONNECTION_NOT_GSM", "ConnectionNotGsm" }, - { NM_MODEM_BROADBAND_ERROR_CONNECTION_NOT_CDMA, "NM_MODEM_BROADBAND_ERROR_CONNECTION_NOT_CDMA", "ConnectionNotCdma" }, - { NM_MODEM_BROADBAND_ERROR_CONNECTION_INVALID, "NM_MODEM_BROADBAND_ERROR_CONNECTION_INVALID", "ConnectionInvalid" }, - { NM_MODEM_BROADBAND_ERROR_CONNECTION_INCOMPATIBLE, "NM_MODEM_BROADBAND_ERROR_CONNECTION_INCOMPATIBLE", "ConnectionIncompatible" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("NMModemBroadbandError"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -nm_gsm_error_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { NM_GSM_ERROR_CONNECTION_NOT_GSM, "NM_GSM_ERROR_CONNECTION_NOT_GSM", "ConnectionNotGsm" }, - { NM_GSM_ERROR_CONNECTION_INVALID, "NM_GSM_ERROR_CONNECTION_INVALID", "ConnectionInvalid" }, - { NM_GSM_ERROR_CONNECTION_INCOMPATIBLE, "NM_GSM_ERROR_CONNECTION_INCOMPATIBLE", "ConnectionIncompatible" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("NMGsmError"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -nm_system_config_interface_capabilities_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { NM_SYSTEM_CONFIG_INTERFACE_CAP_NONE, "NM_SYSTEM_CONFIG_INTERFACE_CAP_NONE", "none" }, - { NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_CONNECTIONS, "NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_CONNECTIONS", "modify-connections" }, - { NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_HOSTNAME, "NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_HOSTNAME", "modify-hostname" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("NMSystemConfigInterfaceCapabilities"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -nm_system_config_interface_prop_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { NM_SYSTEM_CONFIG_INTERFACE_PROP_FIRST, "NM_SYSTEM_CONFIG_INTERFACE_PROP_FIRST", "first" }, - { NM_SYSTEM_CONFIG_INTERFACE_PROP_NAME, "NM_SYSTEM_CONFIG_INTERFACE_PROP_NAME", "name" }, - { NM_SYSTEM_CONFIG_INTERFACE_PROP_INFO, "NM_SYSTEM_CONFIG_INTERFACE_PROP_INFO", "info" }, - { NM_SYSTEM_CONFIG_INTERFACE_PROP_CAPABILITIES, "NM_SYSTEM_CONFIG_INTERFACE_PROP_CAPABILITIES", "capabilities" }, - { NM_SYSTEM_CONFIG_INTERFACE_PROP_HOSTNAME, "NM_SYSTEM_CONFIG_INTERFACE_PROP_HOSTNAME", "hostname" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("NMSystemConfigInterfaceProp"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -nm_settings_error_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { NM_SETTINGS_ERROR_GENERAL, "NM_SETTINGS_ERROR_GENERAL", "GeneralError" }, - { NM_SETTINGS_ERROR_INVALID_CONNECTION, "NM_SETTINGS_ERROR_INVALID_CONNECTION", "InvalidConnection" }, - { NM_SETTINGS_ERROR_READ_ONLY_CONNECTION, "NM_SETTINGS_ERROR_READ_ONLY_CONNECTION", "ReadOnlyConnection" }, - { NM_SETTINGS_ERROR_INTERNAL_ERROR, "NM_SETTINGS_ERROR_INTERNAL_ERROR", "InternalError" }, - { NM_SETTINGS_ERROR_SECRETS_UNAVAILABLE, "NM_SETTINGS_ERROR_SECRETS_UNAVAILABLE", "SecretsUnavailable" }, - { NM_SETTINGS_ERROR_SECRETS_REQUEST_CANCELED, "NM_SETTINGS_ERROR_SECRETS_REQUEST_CANCELED", "SecretsRequestCanceled" }, - { NM_SETTINGS_ERROR_PERMISSION_DENIED, "NM_SETTINGS_ERROR_PERMISSION_DENIED", "PermissionDenied" }, - { NM_SETTINGS_ERROR_INVALID_SETTING, "NM_SETTINGS_ERROR_INVALID_SETTING", "InvalidSetting" }, - { NM_SETTINGS_ERROR_NOT_PRIVILEGED, "NM_SETTINGS_ERROR_NOT_PRIVILEGED", "NotPrivileged" }, - { NM_SETTINGS_ERROR_ADD_NOT_SUPPORTED, "NM_SETTINGS_ERROR_ADD_NOT_SUPPORTED", "AddNotSupported" }, - { NM_SETTINGS_ERROR_UPDATE_NOT_SUPPORTED, "NM_SETTINGS_ERROR_UPDATE_NOT_SUPPORTED", "UpdateNotSupported" }, - { NM_SETTINGS_ERROR_DELETE_NOT_SUPPORTED, "NM_SETTINGS_ERROR_DELETE_NOT_SUPPORTED", "DeleteNotSupported" }, - { NM_SETTINGS_ERROR_ADD_FAILED, "NM_SETTINGS_ERROR_ADD_FAILED", "AddFailed" }, - { NM_SETTINGS_ERROR_SAVE_HOSTNAME_NOT_SUPPORTED, "NM_SETTINGS_ERROR_SAVE_HOSTNAME_NOT_SUPPORTED", "SaveHostnameNotSupported" }, - { NM_SETTINGS_ERROR_SAVE_HOSTNAME_FAILED, "NM_SETTINGS_ERROR_SAVE_HOSTNAME_FAILED", "SaveHostnameFailed" }, - { NM_SETTINGS_ERROR_HOSTNAME_INVALID, "NM_SETTINGS_ERROR_HOSTNAME_INVALID", "HostnameInvalid" }, - { NM_SETTINGS_ERROR_UUID_EXISTS, "NM_SETTINGS_ERROR_UUID_EXISTS", "UuidExists" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("NMSettingsError"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -nm_agent_manager_error_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { NM_AGENT_MANAGER_ERROR_SENDER_UNKNOWN, "NM_AGENT_MANAGER_ERROR_SENDER_UNKNOWN", "SenderUnknown" }, - { NM_AGENT_MANAGER_ERROR_PERMISSION_DENIED, "NM_AGENT_MANAGER_ERROR_PERMISSION_DENIED", "PermissionDenied" }, - { NM_AGENT_MANAGER_ERROR_SESSION_NOT_FOUND, "NM_AGENT_MANAGER_ERROR_SESSION_NOT_FOUND", "SessionNotFound" }, - { NM_AGENT_MANAGER_ERROR_INVALID_IDENTIFIER, "NM_AGENT_MANAGER_ERROR_INVALID_IDENTIFIER", "InvalidIdentifier" }, - { NM_AGENT_MANAGER_ERROR_NOT_REGISTERED, "NM_AGENT_MANAGER_ERROR_NOT_REGISTERED", "NotRegistered" }, - { NM_AGENT_MANAGER_ERROR_INTERNAL_ERROR, "NM_AGENT_MANAGER_ERROR_INTERNAL_ERROR", "InternalError" }, - { NM_AGENT_MANAGER_ERROR_NO_SECRETS, "NM_AGENT_MANAGER_ERROR_NO_SECRETS", "NoSecrets" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("NMAgentManagerError"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -nm_wimax_error_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { NM_WIMAX_ERROR_CONNECTION_NOT_WIMAX, "NM_WIMAX_ERROR_CONNECTION_NOT_WIMAX", "ConnectionNotWimax" }, - { NM_WIMAX_ERROR_CONNECTION_INVALID, "NM_WIMAX_ERROR_CONNECTION_INVALID", "ConnectionInvalid" }, - { NM_WIMAX_ERROR_CONNECTION_INCOMPATIBLE, "NM_WIMAX_ERROR_CONNECTION_INCOMPATIBLE", "ConnectionIncompatible" }, - { NM_WIMAX_ERROR_NSP_NOT_FOUND, "NM_WIMAX_ERROR_NSP_NOT_FOUND", "NspNotFound" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("NMWimaxError"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -nm_wimax_nsp_network_type_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { NM_WIMAX_NSP_NETWORK_TYPE_UNKNOWN, "NM_WIMAX_NSP_NETWORK_TYPE_UNKNOWN", "unknown" }, - { NM_WIMAX_NSP_NETWORK_TYPE_HOME, "NM_WIMAX_NSP_NETWORK_TYPE_HOME", "home" }, - { NM_WIMAX_NSP_NETWORK_TYPE_PARTNER, "NM_WIMAX_NSP_NETWORK_TYPE_PARTNER", "partner" }, - { NM_WIMAX_NSP_NETWORK_TYPE_ROAMING_PARTNER, "NM_WIMAX_NSP_NETWORK_TYPE_ROAMING_PARTNER", "roaming-partner" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("NMWimaxNspNetworkType"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} - - - diff --git a/src/generated/nm-enum-types.h b/src/generated/nm-enum-types.h deleted file mode 100644 index e0703b20..00000000 --- a/src/generated/nm-enum-types.h +++ /dev/null @@ -1,99 +0,0 @@ - - - -/* Generated by glib-mkenums. Do not edit */ - -#ifndef __NM_ENUM_TYPES_H__ -#define __NM_ENUM_TYPES_H__ - -#include - -G_BEGIN_DECLS -GType nm_bt_error_get_type (void) G_GNUC_CONST; -#define NM_TYPE_BT_ERROR (nm_bt_error_get_type ()) -GType nm_infiniband_error_get_type (void) G_GNUC_CONST; -#define NM_TYPE_INFINIBAND_ERROR (nm_infiniband_error_get_type ()) -GType nm_bond_error_get_type (void) G_GNUC_CONST; -#define NM_TYPE_BOND_ERROR (nm_bond_error_get_type ()) -GType nm_session_monitor_error_get_type (void) G_GNUC_CONST; -#define NM_TYPE_SESSION_MONITOR_ERROR (nm_session_monitor_error_get_type ()) -GType nm_ethernet_error_get_type (void) G_GNUC_CONST; -#define NM_TYPE_ETHERNET_ERROR (nm_ethernet_error_get_type ()) -GType nm_config_error_get_type (void) G_GNUC_CONST; -#define NM_TYPE_CONFIG_ERROR (nm_config_error_get_type ()) -GType nm_rf_kill_state_get_type (void) G_GNUC_CONST; -#define NM_TYPE_RF_KILL_STATE (nm_rf_kill_state_get_type ()) -GType nm_rf_kill_type_get_type (void) G_GNUC_CONST; -#define NM_TYPE_RF_KILL_TYPE (nm_rf_kill_type_get_type ()) -GType nm_dispatcher_action_get_type (void) G_GNUC_CONST; -#define NM_TYPE_DISPATCHER_ACTION (nm_dispatcher_action_get_type ()) -GType nm_ip4_config_compare_flags_get_type (void) G_GNUC_CONST; -#define NM_TYPE_IP4_CONFIG_COMPARE_FLAGS (nm_ip4_config_compare_flags_get_type ()) -GType nm_manager_error_get_type (void) G_GNUC_CONST; -#define NM_TYPE_MANAGER_ERROR (nm_manager_error_get_type ()) -GType nm_device_error_get_type (void) G_GNUC_CONST; -#define NM_TYPE_DEVICE_ERROR (nm_device_error_get_type ()) -GType nm_ip6_config_compare_flags_get_type (void) G_GNUC_CONST; -#define NM_TYPE_IP6_CONFIG_COMPARE_FLAGS (nm_ip6_config_compare_flags_get_type ()) -GType nm_auth_call_result_get_type (void) G_GNUC_CONST; -#define NM_TYPE_AUTH_CALL_RESULT (nm_auth_call_result_get_type ()) -GType nm_bridge_error_get_type (void) G_GNUC_CONST; -#define NM_TYPE_BRIDGE_ERROR (nm_bridge_error_get_type ()) -GType nm_wifi_error_get_type (void) G_GNUC_CONST; -#define NM_TYPE_WIFI_ERROR (nm_wifi_error_get_type ()) -GType nm_nm_nl_prop_get_type (void) G_GNUC_CONST; -#define NM_TYPE_NM_NL_PROP (nm_nm_nl_prop_get_type ()) -GType nm_vlan_error_get_type (void) G_GNUC_CONST; -#define NM_TYPE_VLAN_ERROR (nm_vlan_error_get_type ()) -GType nm_netlink_monitor_error_get_type (void) G_GNUC_CONST; -#define NM_TYPE_NETLINK_MONITOR_ERROR (nm_netlink_monitor_error_get_type ()) -GType nm_olpc_mesh_error_get_type (void) G_GNUC_CONST; -#define NM_TYPE_OLPC_MESH_ERROR (nm_olpc_mesh_error_get_type ()) -GType nm_adsl_error_get_type (void) G_GNUC_CONST; -#define NM_TYPE_ADSL_ERROR (nm_adsl_error_get_type ()) -GType nm_logging_error_get_type (void) G_GNUC_CONST; -#define NM_TYPE_LOGGING_ERROR (nm_logging_error_get_type ()) -GType nm_dns_manager_error_get_type (void) G_GNUC_CONST; -#define NM_TYPE_DNS_MANAGER_ERROR (nm_dns_manager_error_get_type ()) -GType nm_dns_ip_config_type_get_type (void) G_GNUC_CONST; -#define NM_TYPE_DNS_IP_CONFIG_TYPE (nm_dns_ip_config_type_get_type ()) -GType nm_vpn_manager_error_get_type (void) G_GNUC_CONST; -#define NM_TYPE_VPN_MANAGER_ERROR (nm_vpn_manager_error_get_type ()) -GType nm_dhcp_state_get_type (void) G_GNUC_CONST; -#define NM_TYPE_DHCP_STATE (nm_dhcp_state_get_type ()) -GType nm_dhcp_manager_error_get_type (void) G_GNUC_CONST; -#define NM_TYPE_DHCP_MANAGER_ERROR (nm_dhcp_manager_error_get_type ()) -GType nm_opt_type_get_type (void) G_GNUC_CONST; -#define NM_TYPE_OPT_TYPE (nm_opt_type_get_type ()) -GType nm_ap_support_get_type (void) G_GNUC_CONST; -#define NM_TYPE_AP_SUPPORT (nm_ap_support_get_type ()) -GType nm_ppp_status_get_type (void) G_GNUC_CONST; -#define NM_TYPE_PPP_STATUS (nm_ppp_status_get_type ()) -GType nm_dns_masq_status_get_type (void) G_GNUC_CONST; -#define NM_TYPE_DNS_MASQ_STATUS (nm_dns_masq_status_get_type ()) -GType nm_modem_state_get_type (void) G_GNUC_CONST; -#define NM_TYPE_MODEM_STATE (nm_modem_state_get_type ()) -GType nm_cdma_error_get_type (void) G_GNUC_CONST; -#define NM_TYPE_CDMA_ERROR (nm_cdma_error_get_type ()) -GType nm_modem_broadband_error_get_type (void) G_GNUC_CONST; -#define NM_TYPE_MODEM_BROADBAND_ERROR (nm_modem_broadband_error_get_type ()) -GType nm_gsm_error_get_type (void) G_GNUC_CONST; -#define NM_TYPE_GSM_ERROR (nm_gsm_error_get_type ()) -GType nm_system_config_interface_capabilities_get_type (void) G_GNUC_CONST; -#define NM_TYPE_SYSTEM_CONFIG_INTERFACE_CAPABILITIES (nm_system_config_interface_capabilities_get_type ()) -GType nm_system_config_interface_prop_get_type (void) G_GNUC_CONST; -#define NM_TYPE_SYSTEM_CONFIG_INTERFACE_PROP (nm_system_config_interface_prop_get_type ()) -GType nm_settings_error_get_type (void) G_GNUC_CONST; -#define NM_TYPE_SETTINGS_ERROR (nm_settings_error_get_type ()) -GType nm_agent_manager_error_get_type (void) G_GNUC_CONST; -#define NM_TYPE_AGENT_MANAGER_ERROR (nm_agent_manager_error_get_type ()) -GType nm_wimax_error_get_type (void) G_GNUC_CONST; -#define NM_TYPE_WIMAX_ERROR (nm_wimax_error_get_type ()) -GType nm_wimax_nsp_network_type_get_type (void) G_GNUC_CONST; -#define NM_TYPE_WIMAX_NSP_NETWORK_TYPE (nm_wimax_nsp_network_type_get_type ()) -G_END_DECLS - -#endif /* __NM_ENUM_TYPES_H__ */ - - - diff --git a/src/generated/nm-marshal.c b/src/generated/nm-marshal.c deleted file mode 100644 index c7180f1b..00000000 --- a/src/generated/nm-marshal.c +++ /dev/null @@ -1,744 +0,0 @@ -#include "nm-marshal.h" - -#include - - -#ifdef G_ENABLE_DEBUG -#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v) -#define g_marshal_value_peek_char(v) g_value_get_schar (v) -#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v) -#define g_marshal_value_peek_int(v) g_value_get_int (v) -#define g_marshal_value_peek_uint(v) g_value_get_uint (v) -#define g_marshal_value_peek_long(v) g_value_get_long (v) -#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v) -#define g_marshal_value_peek_int64(v) g_value_get_int64 (v) -#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v) -#define g_marshal_value_peek_enum(v) g_value_get_enum (v) -#define g_marshal_value_peek_flags(v) g_value_get_flags (v) -#define g_marshal_value_peek_float(v) g_value_get_float (v) -#define g_marshal_value_peek_double(v) g_value_get_double (v) -#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v) -#define g_marshal_value_peek_param(v) g_value_get_param (v) -#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v) -#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v) -#define g_marshal_value_peek_object(v) g_value_get_object (v) -#define g_marshal_value_peek_variant(v) g_value_get_variant (v) -#else /* !G_ENABLE_DEBUG */ -/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API. - * Do not access GValues directly in your code. Instead, use the - * g_value_get_*() functions - */ -#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int -#define g_marshal_value_peek_char(v) (v)->data[0].v_int -#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint -#define g_marshal_value_peek_int(v) (v)->data[0].v_int -#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint -#define g_marshal_value_peek_long(v) (v)->data[0].v_long -#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong -#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 -#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 -#define g_marshal_value_peek_enum(v) (v)->data[0].v_long -#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong -#define g_marshal_value_peek_float(v) (v)->data[0].v_float -#define g_marshal_value_peek_double(v) (v)->data[0].v_double -#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer -#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer -#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer -#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer -#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer -#define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer -#endif /* !G_ENABLE_DEBUG */ - - -/* BOOLEAN:VOID (nm-marshal.list:1) */ -void -_nm_marshal_BOOLEAN__VOID (GClosure *closure, - GValue *return_value G_GNUC_UNUSED, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint G_GNUC_UNUSED, - gpointer marshal_data) -{ - typedef gboolean (*GMarshalFunc_BOOLEAN__VOID) (gpointer data1, - gpointer data2); - register GMarshalFunc_BOOLEAN__VOID callback; - register GCClosure *cc = (GCClosure*) closure; - register gpointer data1, data2; - gboolean v_return; - - g_return_if_fail (return_value != NULL); - g_return_if_fail (n_param_values == 1); - - if (G_CCLOSURE_SWAP_DATA (closure)) - { - data1 = closure->data; - data2 = g_value_peek_pointer (param_values + 0); - } - else - { - data1 = g_value_peek_pointer (param_values + 0); - data2 = closure->data; - } - callback = (GMarshalFunc_BOOLEAN__VOID) (marshal_data ? marshal_data : cc->callback); - - v_return = callback (data1, - data2); - - g_value_set_boolean (return_value, v_return); -} - -/* VOID:BOOLEAN,UINT (nm-marshal.list:2) */ -void -_nm_marshal_VOID__BOOLEAN_UINT (GClosure *closure, - GValue *return_value G_GNUC_UNUSED, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint G_GNUC_UNUSED, - gpointer marshal_data) -{ - typedef void (*GMarshalFunc_VOID__BOOLEAN_UINT) (gpointer data1, - gboolean arg_1, - guint arg_2, - gpointer data2); - register GMarshalFunc_VOID__BOOLEAN_UINT callback; - register GCClosure *cc = (GCClosure*) closure; - register gpointer data1, data2; - - g_return_if_fail (n_param_values == 3); - - if (G_CCLOSURE_SWAP_DATA (closure)) - { - data1 = closure->data; - data2 = g_value_peek_pointer (param_values + 0); - } - else - { - data1 = g_value_peek_pointer (param_values + 0); - data2 = closure->data; - } - callback = (GMarshalFunc_VOID__BOOLEAN_UINT) (marshal_data ? marshal_data : cc->callback); - - callback (data1, - g_marshal_value_peek_boolean (param_values + 1), - g_marshal_value_peek_uint (param_values + 2), - data2); -} - -/* VOID:INT,UINT,BOOLEAN (nm-marshal.list:3) */ -void -_nm_marshal_VOID__INT_UINT_BOOLEAN (GClosure *closure, - GValue *return_value G_GNUC_UNUSED, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint G_GNUC_UNUSED, - gpointer marshal_data) -{ - typedef void (*GMarshalFunc_VOID__INT_UINT_BOOLEAN) (gpointer data1, - gint arg_1, - guint arg_2, - gboolean arg_3, - gpointer data2); - register GMarshalFunc_VOID__INT_UINT_BOOLEAN callback; - register GCClosure *cc = (GCClosure*) closure; - register gpointer data1, data2; - - g_return_if_fail (n_param_values == 4); - - if (G_CCLOSURE_SWAP_DATA (closure)) - { - data1 = closure->data; - data2 = g_value_peek_pointer (param_values + 0); - } - else - { - data1 = g_value_peek_pointer (param_values + 0); - data2 = closure->data; - } - callback = (GMarshalFunc_VOID__INT_UINT_BOOLEAN) (marshal_data ? marshal_data : cc->callback); - - callback (data1, - g_marshal_value_peek_int (param_values + 1), - g_marshal_value_peek_uint (param_values + 2), - g_marshal_value_peek_boolean (param_values + 3), - data2); -} - -/* VOID:OBJECT,OBJECT (nm-marshal.list:4) */ -void -_nm_marshal_VOID__OBJECT_OBJECT (GClosure *closure, - GValue *return_value G_GNUC_UNUSED, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint G_GNUC_UNUSED, - gpointer marshal_data) -{ - typedef void (*GMarshalFunc_VOID__OBJECT_OBJECT) (gpointer data1, - gpointer arg_1, - gpointer arg_2, - gpointer data2); - register GMarshalFunc_VOID__OBJECT_OBJECT callback; - register GCClosure *cc = (GCClosure*) closure; - register gpointer data1, data2; - - g_return_if_fail (n_param_values == 3); - - if (G_CCLOSURE_SWAP_DATA (closure)) - { - data1 = closure->data; - data2 = g_value_peek_pointer (param_values + 0); - } - else - { - data1 = g_value_peek_pointer (param_values + 0); - data2 = closure->data; - } - callback = (GMarshalFunc_VOID__OBJECT_OBJECT) (marshal_data ? marshal_data : cc->callback); - - callback (data1, - g_marshal_value_peek_object (param_values + 1), - g_marshal_value_peek_object (param_values + 2), - data2); -} - -/* VOID:OBJECT,POINTER (nm-marshal.list:5) */ -void -_nm_marshal_VOID__OBJECT_POINTER (GClosure *closure, - GValue *return_value G_GNUC_UNUSED, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint G_GNUC_UNUSED, - gpointer marshal_data) -{ - typedef void (*GMarshalFunc_VOID__OBJECT_POINTER) (gpointer data1, - gpointer arg_1, - gpointer arg_2, - gpointer data2); - register GMarshalFunc_VOID__OBJECT_POINTER callback; - register GCClosure *cc = (GCClosure*) closure; - register gpointer data1, data2; - - g_return_if_fail (n_param_values == 3); - - if (G_CCLOSURE_SWAP_DATA (closure)) - { - data1 = closure->data; - data2 = g_value_peek_pointer (param_values + 0); - } - else - { - data1 = g_value_peek_pointer (param_values + 0); - data2 = closure->data; - } - callback = (GMarshalFunc_VOID__OBJECT_POINTER) (marshal_data ? marshal_data : cc->callback); - - callback (data1, - g_marshal_value_peek_object (param_values + 1), - g_marshal_value_peek_pointer (param_values + 2), - data2); -} - -/* VOID:OBJECT,STRING (nm-marshal.list:6) */ -void -_nm_marshal_VOID__OBJECT_STRING (GClosure *closure, - GValue *return_value G_GNUC_UNUSED, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint G_GNUC_UNUSED, - gpointer marshal_data) -{ - typedef void (*GMarshalFunc_VOID__OBJECT_STRING) (gpointer data1, - gpointer arg_1, - gpointer arg_2, - gpointer data2); - register GMarshalFunc_VOID__OBJECT_STRING callback; - register GCClosure *cc = (GCClosure*) closure; - register gpointer data1, data2; - - g_return_if_fail (n_param_values == 3); - - if (G_CCLOSURE_SWAP_DATA (closure)) - { - data1 = closure->data; - data2 = g_value_peek_pointer (param_values + 0); - } - else - { - data1 = g_value_peek_pointer (param_values + 0); - data2 = closure->data; - } - callback = (GMarshalFunc_VOID__OBJECT_STRING) (marshal_data ? marshal_data : cc->callback); - - callback (data1, - g_marshal_value_peek_object (param_values + 1), - g_marshal_value_peek_string (param_values + 2), - data2); -} - -/* VOID:POINTER (nm-marshal.list:7) */ - -/* VOID:POINTER,POINTER,POINTER,POINTER,INT (nm-marshal.list:8) */ -void -_nm_marshal_VOID__POINTER_POINTER_POINTER_POINTER_INT (GClosure *closure, - GValue *return_value G_GNUC_UNUSED, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint G_GNUC_UNUSED, - gpointer marshal_data) -{ - typedef void (*GMarshalFunc_VOID__POINTER_POINTER_POINTER_POINTER_INT) (gpointer data1, - gpointer arg_1, - gpointer arg_2, - gpointer arg_3, - gpointer arg_4, - gint arg_5, - gpointer data2); - register GMarshalFunc_VOID__POINTER_POINTER_POINTER_POINTER_INT callback; - register GCClosure *cc = (GCClosure*) closure; - register gpointer data1, data2; - - g_return_if_fail (n_param_values == 6); - - if (G_CCLOSURE_SWAP_DATA (closure)) - { - data1 = closure->data; - data2 = g_value_peek_pointer (param_values + 0); - } - else - { - data1 = g_value_peek_pointer (param_values + 0); - data2 = closure->data; - } - callback = (GMarshalFunc_VOID__POINTER_POINTER_POINTER_POINTER_INT) (marshal_data ? marshal_data : cc->callback); - - callback (data1, - g_marshal_value_peek_pointer (param_values + 1), - g_marshal_value_peek_pointer (param_values + 2), - g_marshal_value_peek_pointer (param_values + 3), - g_marshal_value_peek_pointer (param_values + 4), - g_marshal_value_peek_int (param_values + 5), - data2); -} - -/* VOID:POINTER,POINTER,STRING,BOOLEAN,POINTER,POINTER (nm-marshal.list:9) */ -void -_nm_marshal_VOID__POINTER_POINTER_STRING_BOOLEAN_POINTER_POINTER (GClosure *closure, - GValue *return_value G_GNUC_UNUSED, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint G_GNUC_UNUSED, - gpointer marshal_data) -{ - typedef void (*GMarshalFunc_VOID__POINTER_POINTER_STRING_BOOLEAN_POINTER_POINTER) (gpointer data1, - gpointer arg_1, - gpointer arg_2, - gpointer arg_3, - gboolean arg_4, - gpointer arg_5, - gpointer arg_6, - gpointer data2); - register GMarshalFunc_VOID__POINTER_POINTER_STRING_BOOLEAN_POINTER_POINTER callback; - register GCClosure *cc = (GCClosure*) closure; - register gpointer data1, data2; - - g_return_if_fail (n_param_values == 7); - - if (G_CCLOSURE_SWAP_DATA (closure)) - { - data1 = closure->data; - data2 = g_value_peek_pointer (param_values + 0); - } - else - { - data1 = g_value_peek_pointer (param_values + 0); - data2 = closure->data; - } - callback = (GMarshalFunc_VOID__POINTER_POINTER_STRING_BOOLEAN_POINTER_POINTER) (marshal_data ? marshal_data : cc->callback); - - callback (data1, - g_marshal_value_peek_pointer (param_values + 1), - g_marshal_value_peek_pointer (param_values + 2), - g_marshal_value_peek_string (param_values + 3), - g_marshal_value_peek_boolean (param_values + 4), - g_marshal_value_peek_pointer (param_values + 5), - g_marshal_value_peek_pointer (param_values + 6), - data2); -} - -/* VOID:POINTER,STRING (nm-marshal.list:10) */ -void -_nm_marshal_VOID__POINTER_STRING (GClosure *closure, - GValue *return_value G_GNUC_UNUSED, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint G_GNUC_UNUSED, - gpointer marshal_data) -{ - typedef void (*GMarshalFunc_VOID__POINTER_STRING) (gpointer data1, - gpointer arg_1, - gpointer arg_2, - gpointer data2); - register GMarshalFunc_VOID__POINTER_STRING callback; - register GCClosure *cc = (GCClosure*) closure; - register gpointer data1, data2; - - g_return_if_fail (n_param_values == 3); - - if (G_CCLOSURE_SWAP_DATA (closure)) - { - data1 = closure->data; - data2 = g_value_peek_pointer (param_values + 0); - } - else - { - data1 = g_value_peek_pointer (param_values + 0); - data2 = closure->data; - } - callback = (GMarshalFunc_VOID__POINTER_STRING) (marshal_data ? marshal_data : cc->callback); - - callback (data1, - g_marshal_value_peek_pointer (param_values + 1), - g_marshal_value_peek_string (param_values + 2), - data2); -} - -/* VOID:STRING,BOXED (nm-marshal.list:11) */ -void -_nm_marshal_VOID__STRING_BOXED (GClosure *closure, - GValue *return_value G_GNUC_UNUSED, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint G_GNUC_UNUSED, - gpointer marshal_data) -{ - typedef void (*GMarshalFunc_VOID__STRING_BOXED) (gpointer data1, - gpointer arg_1, - gpointer arg_2, - gpointer data2); - register GMarshalFunc_VOID__STRING_BOXED callback; - register GCClosure *cc = (GCClosure*) closure; - register gpointer data1, data2; - - g_return_if_fail (n_param_values == 3); - - if (G_CCLOSURE_SWAP_DATA (closure)) - { - data1 = closure->data; - data2 = g_value_peek_pointer (param_values + 0); - } - else - { - data1 = g_value_peek_pointer (param_values + 0); - data2 = closure->data; - } - callback = (GMarshalFunc_VOID__STRING_BOXED) (marshal_data ? marshal_data : cc->callback); - - callback (data1, - g_marshal_value_peek_string (param_values + 1), - g_marshal_value_peek_boxed (param_values + 2), - data2); -} - -/* VOID:STRING,BOXED,BOXED (nm-marshal.list:12) */ -void -_nm_marshal_VOID__STRING_BOXED_BOXED (GClosure *closure, - GValue *return_value G_GNUC_UNUSED, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint G_GNUC_UNUSED, - gpointer marshal_data) -{ - typedef void (*GMarshalFunc_VOID__STRING_BOXED_BOXED) (gpointer data1, - gpointer arg_1, - gpointer arg_2, - gpointer arg_3, - gpointer data2); - register GMarshalFunc_VOID__STRING_BOXED_BOXED callback; - register GCClosure *cc = (GCClosure*) closure; - register gpointer data1, data2; - - g_return_if_fail (n_param_values == 4); - - if (G_CCLOSURE_SWAP_DATA (closure)) - { - data1 = closure->data; - data2 = g_value_peek_pointer (param_values + 0); - } - else - { - data1 = g_value_peek_pointer (param_values + 0); - data2 = closure->data; - } - callback = (GMarshalFunc_VOID__STRING_BOXED_BOXED) (marshal_data ? marshal_data : cc->callback); - - callback (data1, - g_marshal_value_peek_string (param_values + 1), - g_marshal_value_peek_boxed (param_values + 2), - g_marshal_value_peek_boxed (param_values + 3), - data2); -} - -/* VOID:STRING,OBJECT (nm-marshal.list:13) */ -void -_nm_marshal_VOID__STRING_OBJECT (GClosure *closure, - GValue *return_value G_GNUC_UNUSED, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint G_GNUC_UNUSED, - gpointer marshal_data) -{ - typedef void (*GMarshalFunc_VOID__STRING_OBJECT) (gpointer data1, - gpointer arg_1, - gpointer arg_2, - gpointer data2); - register GMarshalFunc_VOID__STRING_OBJECT callback; - register GCClosure *cc = (GCClosure*) closure; - register gpointer data1, data2; - - g_return_if_fail (n_param_values == 3); - - if (G_CCLOSURE_SWAP_DATA (closure)) - { - data1 = closure->data; - data2 = g_value_peek_pointer (param_values + 0); - } - else - { - data1 = g_value_peek_pointer (param_values + 0); - data2 = closure->data; - } - callback = (GMarshalFunc_VOID__STRING_OBJECT) (marshal_data ? marshal_data : cc->callback); - - callback (data1, - g_marshal_value_peek_string (param_values + 1), - g_marshal_value_peek_object (param_values + 2), - data2); -} - -/* VOID:STRING,POINTER (nm-marshal.list:14) */ -void -_nm_marshal_VOID__STRING_POINTER (GClosure *closure, - GValue *return_value G_GNUC_UNUSED, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint G_GNUC_UNUSED, - gpointer marshal_data) -{ - typedef void (*GMarshalFunc_VOID__STRING_POINTER) (gpointer data1, - gpointer arg_1, - gpointer arg_2, - gpointer data2); - register GMarshalFunc_VOID__STRING_POINTER callback; - register GCClosure *cc = (GCClosure*) closure; - register gpointer data1, data2; - - g_return_if_fail (n_param_values == 3); - - if (G_CCLOSURE_SWAP_DATA (closure)) - { - data1 = closure->data; - data2 = g_value_peek_pointer (param_values + 0); - } - else - { - data1 = g_value_peek_pointer (param_values + 0); - data2 = closure->data; - } - callback = (GMarshalFunc_VOID__STRING_POINTER) (marshal_data ? marshal_data : cc->callback); - - callback (data1, - g_marshal_value_peek_string (param_values + 1), - g_marshal_value_peek_pointer (param_values + 2), - data2); -} - -/* VOID:STRING,STRING (nm-marshal.list:15) */ -void -_nm_marshal_VOID__STRING_STRING (GClosure *closure, - GValue *return_value G_GNUC_UNUSED, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint G_GNUC_UNUSED, - gpointer marshal_data) -{ - typedef void (*GMarshalFunc_VOID__STRING_STRING) (gpointer data1, - gpointer arg_1, - gpointer arg_2, - gpointer data2); - register GMarshalFunc_VOID__STRING_STRING callback; - register GCClosure *cc = (GCClosure*) closure; - register gpointer data1, data2; - - g_return_if_fail (n_param_values == 3); - - if (G_CCLOSURE_SWAP_DATA (closure)) - { - data1 = closure->data; - data2 = g_value_peek_pointer (param_values + 0); - } - else - { - data1 = g_value_peek_pointer (param_values + 0); - data2 = closure->data; - } - callback = (GMarshalFunc_VOID__STRING_STRING) (marshal_data ? marshal_data : cc->callback); - - callback (data1, - g_marshal_value_peek_string (param_values + 1), - g_marshal_value_peek_string (param_values + 2), - data2); -} - -/* VOID:STRING,STRING,STRING (nm-marshal.list:16) */ -void -_nm_marshal_VOID__STRING_STRING_STRING (GClosure *closure, - GValue *return_value G_GNUC_UNUSED, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint G_GNUC_UNUSED, - gpointer marshal_data) -{ - typedef void (*GMarshalFunc_VOID__STRING_STRING_STRING) (gpointer data1, - gpointer arg_1, - gpointer arg_2, - gpointer arg_3, - gpointer data2); - register GMarshalFunc_VOID__STRING_STRING_STRING callback; - register GCClosure *cc = (GCClosure*) closure; - register gpointer data1, data2; - - g_return_if_fail (n_param_values == 4); - - if (G_CCLOSURE_SWAP_DATA (closure)) - { - data1 = closure->data; - data2 = g_value_peek_pointer (param_values + 0); - } - else - { - data1 = g_value_peek_pointer (param_values + 0); - data2 = closure->data; - } - callback = (GMarshalFunc_VOID__STRING_STRING_STRING) (marshal_data ? marshal_data : cc->callback); - - callback (data1, - g_marshal_value_peek_string (param_values + 1), - g_marshal_value_peek_string (param_values + 2), - g_marshal_value_peek_string (param_values + 3), - data2); -} - -/* VOID:UINT,UINT (nm-marshal.list:17) */ -void -_nm_marshal_VOID__UINT_UINT (GClosure *closure, - GValue *return_value G_GNUC_UNUSED, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint G_GNUC_UNUSED, - gpointer marshal_data) -{ - typedef void (*GMarshalFunc_VOID__UINT_UINT) (gpointer data1, - guint arg_1, - guint arg_2, - gpointer data2); - register GMarshalFunc_VOID__UINT_UINT callback; - register GCClosure *cc = (GCClosure*) closure; - register gpointer data1, data2; - - g_return_if_fail (n_param_values == 3); - - if (G_CCLOSURE_SWAP_DATA (closure)) - { - data1 = closure->data; - data2 = g_value_peek_pointer (param_values + 0); - } - else - { - data1 = g_value_peek_pointer (param_values + 0); - data2 = closure->data; - } - callback = (GMarshalFunc_VOID__UINT_UINT) (marshal_data ? marshal_data : cc->callback); - - callback (data1, - g_marshal_value_peek_uint (param_values + 1), - g_marshal_value_peek_uint (param_values + 2), - data2); -} - -/* VOID:UINT,UINT,INT (nm-marshal.list:18) */ -void -_nm_marshal_VOID__UINT_UINT_INT (GClosure *closure, - GValue *return_value G_GNUC_UNUSED, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint G_GNUC_UNUSED, - gpointer marshal_data) -{ - typedef void (*GMarshalFunc_VOID__UINT_UINT_INT) (gpointer data1, - guint arg_1, - guint arg_2, - gint arg_3, - gpointer data2); - register GMarshalFunc_VOID__UINT_UINT_INT callback; - register GCClosure *cc = (GCClosure*) closure; - register gpointer data1, data2; - - g_return_if_fail (n_param_values == 4); - - if (G_CCLOSURE_SWAP_DATA (closure)) - { - data1 = closure->data; - data2 = g_value_peek_pointer (param_values + 0); - } - else - { - data1 = g_value_peek_pointer (param_values + 0); - data2 = closure->data; - } - callback = (GMarshalFunc_VOID__UINT_UINT_INT) (marshal_data ? marshal_data : cc->callback); - - callback (data1, - g_marshal_value_peek_uint (param_values + 1), - g_marshal_value_peek_uint (param_values + 2), - g_marshal_value_peek_int (param_values + 3), - data2); -} - -/* VOID:UINT,UINT,UINT (nm-marshal.list:19) */ -void -_nm_marshal_VOID__UINT_UINT_UINT (GClosure *closure, - GValue *return_value G_GNUC_UNUSED, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint G_GNUC_UNUSED, - gpointer marshal_data) -{ - typedef void (*GMarshalFunc_VOID__UINT_UINT_UINT) (gpointer data1, - guint arg_1, - guint arg_2, - guint arg_3, - gpointer data2); - register GMarshalFunc_VOID__UINT_UINT_UINT callback; - register GCClosure *cc = (GCClosure*) closure; - register gpointer data1, data2; - - g_return_if_fail (n_param_values == 4); - - if (G_CCLOSURE_SWAP_DATA (closure)) - { - data1 = closure->data; - data2 = g_value_peek_pointer (param_values + 0); - } - else - { - data1 = g_value_peek_pointer (param_values + 0); - data2 = closure->data; - } - callback = (GMarshalFunc_VOID__UINT_UINT_UINT) (marshal_data ? marshal_data : cc->callback); - - callback (data1, - g_marshal_value_peek_uint (param_values + 1), - g_marshal_value_peek_uint (param_values + 2), - g_marshal_value_peek_uint (param_values + 3), - data2); -} - diff --git a/src/generated/nm-marshal.h b/src/generated/nm-marshal.h deleted file mode 100644 index a940d9f1..00000000 --- a/src/generated/nm-marshal.h +++ /dev/null @@ -1,159 +0,0 @@ - -#ifndef ___nm_marshal_MARSHAL_H__ -#define ___nm_marshal_MARSHAL_H__ - -#include - -G_BEGIN_DECLS - -/* BOOLEAN:VOID (nm-marshal.list:1) */ -extern void _nm_marshal_BOOLEAN__VOID (GClosure *closure, - GValue *return_value, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint, - gpointer marshal_data); - -/* VOID:BOOLEAN,UINT (nm-marshal.list:2) */ -extern void _nm_marshal_VOID__BOOLEAN_UINT (GClosure *closure, - GValue *return_value, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint, - gpointer marshal_data); - -/* VOID:INT,UINT,BOOLEAN (nm-marshal.list:3) */ -extern void _nm_marshal_VOID__INT_UINT_BOOLEAN (GClosure *closure, - GValue *return_value, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint, - gpointer marshal_data); - -/* VOID:OBJECT,OBJECT (nm-marshal.list:4) */ -extern void _nm_marshal_VOID__OBJECT_OBJECT (GClosure *closure, - GValue *return_value, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint, - gpointer marshal_data); - -/* VOID:OBJECT,POINTER (nm-marshal.list:5) */ -extern void _nm_marshal_VOID__OBJECT_POINTER (GClosure *closure, - GValue *return_value, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint, - gpointer marshal_data); - -/* VOID:OBJECT,STRING (nm-marshal.list:6) */ -extern void _nm_marshal_VOID__OBJECT_STRING (GClosure *closure, - GValue *return_value, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint, - gpointer marshal_data); - -/* VOID:POINTER (nm-marshal.list:7) */ -#define _nm_marshal_VOID__POINTER g_cclosure_marshal_VOID__POINTER - -/* VOID:POINTER,POINTER,POINTER,POINTER,INT (nm-marshal.list:8) */ -extern void _nm_marshal_VOID__POINTER_POINTER_POINTER_POINTER_INT (GClosure *closure, - GValue *return_value, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint, - gpointer marshal_data); - -/* VOID:POINTER,POINTER,STRING,BOOLEAN,POINTER,POINTER (nm-marshal.list:9) */ -extern void _nm_marshal_VOID__POINTER_POINTER_STRING_BOOLEAN_POINTER_POINTER (GClosure *closure, - GValue *return_value, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint, - gpointer marshal_data); - -/* VOID:POINTER,STRING (nm-marshal.list:10) */ -extern void _nm_marshal_VOID__POINTER_STRING (GClosure *closure, - GValue *return_value, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint, - gpointer marshal_data); - -/* VOID:STRING,BOXED (nm-marshal.list:11) */ -extern void _nm_marshal_VOID__STRING_BOXED (GClosure *closure, - GValue *return_value, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint, - gpointer marshal_data); - -/* VOID:STRING,BOXED,BOXED (nm-marshal.list:12) */ -extern void _nm_marshal_VOID__STRING_BOXED_BOXED (GClosure *closure, - GValue *return_value, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint, - gpointer marshal_data); - -/* VOID:STRING,OBJECT (nm-marshal.list:13) */ -extern void _nm_marshal_VOID__STRING_OBJECT (GClosure *closure, - GValue *return_value, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint, - gpointer marshal_data); - -/* VOID:STRING,POINTER (nm-marshal.list:14) */ -extern void _nm_marshal_VOID__STRING_POINTER (GClosure *closure, - GValue *return_value, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint, - gpointer marshal_data); - -/* VOID:STRING,STRING (nm-marshal.list:15) */ -extern void _nm_marshal_VOID__STRING_STRING (GClosure *closure, - GValue *return_value, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint, - gpointer marshal_data); - -/* VOID:STRING,STRING,STRING (nm-marshal.list:16) */ -extern void _nm_marshal_VOID__STRING_STRING_STRING (GClosure *closure, - GValue *return_value, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint, - gpointer marshal_data); - -/* VOID:UINT,UINT (nm-marshal.list:17) */ -extern void _nm_marshal_VOID__UINT_UINT (GClosure *closure, - GValue *return_value, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint, - gpointer marshal_data); - -/* VOID:UINT,UINT,INT (nm-marshal.list:18) */ -extern void _nm_marshal_VOID__UINT_UINT_INT (GClosure *closure, - GValue *return_value, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint, - gpointer marshal_data); - -/* VOID:UINT,UINT,UINT (nm-marshal.list:19) */ -extern void _nm_marshal_VOID__UINT_UINT_UINT (GClosure *closure, - GValue *return_value, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint, - gpointer marshal_data); - -G_END_DECLS - -#endif /* ___nm_marshal_MARSHAL_H__ */ - diff --git a/src/ip6-manager/Makefile.am b/src/ip6-manager/Makefile.am deleted file mode 100644 index 25f57497..00000000 --- a/src/ip6-manager/Makefile.am +++ /dev/null @@ -1,27 +0,0 @@ -noinst_LTLIBRARIES = libip6-manager.la - -libip6_manager_la_CPPFLAGS = \ - -I${top_srcdir} \ - -I${top_builddir}/include \ - -I${top_srcdir}/include \ - -I${top_builddir}/libnm-util \ - -I${top_srcdir}/libnm-util \ - -I${top_builddir}/src/generated \ - -I${top_srcdir}/src/generated \ - -I${top_srcdir}/src/logging \ - -I${top_srcdir}/src \ - $(LIBNL_CFLAGS) \ - $(DBUS_CFLAGS) \ - $(GLIB_CFLAGS) - -libip6_manager_la_SOURCES = \ - nm-ip6-manager.c \ - nm-ip6-manager.h - -libip6_manager_la_LIBADD = \ - $(top_builddir)/src/generated/libnm-generated.la \ - $(top_builddir)/src/logging/libnm-logging.la \ - $(LIBNL_LIBS) \ - $(DBUS_LIBS) \ - $(GLIB_LIBS) - diff --git a/src/ip6-manager/Makefile.in b/src/ip6-manager/Makefile.in deleted file mode 100644 index 61a75826..00000000 --- a/src/ip6-manager/Makefile.in +++ /dev/null @@ -1,740 +0,0 @@ -# Makefile.in generated by automake 1.13.4 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994-2013 Free Software Foundation, Inc. - -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ - -VPATH = @srcdir@ -am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' -am__make_running_with_option = \ - case $${target_option-} in \ - ?) ;; \ - *) echo "am__make_running_with_option: internal error: invalid" \ - "target option '$${target_option-}' specified" >&2; \ - exit 1;; \ - esac; \ - has_opt=no; \ - sane_makeflags=$$MAKEFLAGS; \ - if $(am__is_gnu_make); then \ - sane_makeflags=$$MFLAGS; \ - else \ - case $$MAKEFLAGS in \ - *\\[\ \ ]*) \ - bs=\\; \ - sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ - | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ - esac; \ - fi; \ - skip_next=no; \ - strip_trailopt () \ - { \ - flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ - }; \ - for flg in $$sane_makeflags; do \ - test $$skip_next = yes && { skip_next=no; continue; }; \ - case $$flg in \ - *=*|--*) continue;; \ - -*I) strip_trailopt 'I'; skip_next=yes;; \ - -*I?*) strip_trailopt 'I';; \ - -*O) strip_trailopt 'O'; skip_next=yes;; \ - -*O?*) strip_trailopt 'O';; \ - -*l) strip_trailopt 'l'; skip_next=yes;; \ - -*l?*) strip_trailopt 'l';; \ - -[dEDm]) skip_next=yes;; \ - -[JT]) skip_next=yes;; \ - esac; \ - case $$flg in \ - *$$target_option*) has_opt=yes; break;; \ - esac; \ - done; \ - test $$has_opt = yes -am__make_dryrun = (target_option=n; $(am__make_running_with_option)) -am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) -pkgdatadir = $(datadir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkglibexecdir = $(libexecdir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = @build@ -host_triplet = @host@ -subdir = src/ip6-manager -DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ - $(top_srcdir)/build-aux/depcomp -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \ - $(top_srcdir)/m4/gettext.m4 \ - $(top_srcdir)/m4/gnome-code-coverage.m4 \ - $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ - $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \ - $(top_srcdir)/m4/introspection.m4 $(top_srcdir)/m4/lib-ld.m4 \ - $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ - $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ - $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ - $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ - $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ - $(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -mkinstalldirs = $(install_sh) -d -CONFIG_HEADER = $(top_builddir)/config.h -CONFIG_CLEAN_FILES = -CONFIG_CLEAN_VPATH_FILES = -LTLIBRARIES = $(noinst_LTLIBRARIES) -am__DEPENDENCIES_1 = -libip6_manager_la_DEPENDENCIES = \ - $(top_builddir)/src/generated/libnm-generated.la \ - $(top_builddir)/src/logging/libnm-logging.la \ - $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) -am_libip6_manager_la_OBJECTS = libip6_manager_la-nm-ip6-manager.lo -libip6_manager_la_OBJECTS = $(am_libip6_manager_la_OBJECTS) -AM_V_lt = $(am__v_lt_@AM_V@) -am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) -am__v_lt_0 = --silent -am__v_lt_1 = -AM_V_P = $(am__v_P_@AM_V@) -am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) -am__v_P_0 = false -am__v_P_1 = : -AM_V_GEN = $(am__v_GEN_@AM_V@) -am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) -am__v_GEN_0 = @echo " GEN " $@; -am__v_GEN_1 = -AM_V_at = $(am__v_at_@AM_V@) -am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) -am__v_at_0 = @ -am__v_at_1 = -DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) -depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp -am__depfiles_maybe = depfiles -am__mv = mv -f -COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ - $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ - $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ - $(AM_CFLAGS) $(CFLAGS) -AM_V_CC = $(am__v_CC_@AM_V@) -am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) -am__v_CC_0 = @echo " CC " $@; -am__v_CC_1 = -CCLD = $(CC) -LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(AM_LDFLAGS) $(LDFLAGS) -o $@ -AM_V_CCLD = $(am__v_CCLD_@AM_V@) -am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) -am__v_CCLD_0 = @echo " CCLD " $@; -am__v_CCLD_1 = -SOURCES = $(libip6_manager_la_SOURCES) -DIST_SOURCES = $(libip6_manager_la_SOURCES) -am__can_run_installinfo = \ - case $$AM_UPDATE_INFO_DIR in \ - n|no|NO) false;; \ - *) (install-info --version) >/dev/null 2>&1;; \ - esac -am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) -# Read a list of newline-separated strings from the standard input, -# and print each of them once, without duplicates. Input order is -# *not* preserved. -am__uniquify_input = $(AWK) '\ - BEGIN { nonempty = 0; } \ - { items[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in items) print i; }; } \ -' -# Make sure the list of sources is unique. This is necessary because, -# e.g., the same source file might be shared among _SOURCES variables -# for different programs/libraries. -am__define_uniq_tagged_files = \ - list='$(am__tagged_files)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | $(am__uniquify_input)` -ETAGS = etags -CTAGS = ctags -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -ALL_LINGUAS = @ALL_LINGUAS@ -AMTAR = @AMTAR@ -AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -AR = @AR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CKDB_PATH = @CKDB_PATH@ -CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@ -CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@ -CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CXX = @CXX@ -CXXCPP = @CXXCPP@ -CXXDEPMODE = @CXXDEPMODE@ -CXXFLAGS = @CXXFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DATADIRNAME = @DATADIRNAME@ -DBUS_CFLAGS = @DBUS_CFLAGS@ -DBUS_LIBS = @DBUS_LIBS@ -DBUS_SYS_DIR = @DBUS_SYS_DIR@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -DHCLIENT_PATH = @DHCLIENT_PATH@ -DHCPCD_PATH = @DHCPCD_PATH@ -DLLTOOL = @DLLTOOL@ -DNSMASQ_PATH = @DNSMASQ_PATH@ -DSYMUTIL = @DSYMUTIL@ -DUMPBIN = @DUMPBIN@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -FGREP = @FGREP@ -GENHTML = @GENHTML@ -GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ -GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ -GLIB_CFLAGS = @GLIB_CFLAGS@ -GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ -GLIB_LIBS = @GLIB_LIBS@ -GLIB_MAKEFILE = @GLIB_MAKEFILE@ -GLIB_MKENUMS = @GLIB_MKENUMS@ -GMSGFMT = @GMSGFMT@ -GMSGFMT_015 = @GMSGFMT_015@ -GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ -GNUTLS_LIBS = @GNUTLS_LIBS@ -GREP = @GREP@ -GTKDOC_CHECK = @GTKDOC_CHECK@ -GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ -GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ -GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ -GTKDOC_MKPDF = @GTKDOC_MKPDF@ -GTKDOC_REBASE = @GTKDOC_REBASE@ -GUDEV_CFLAGS = @GUDEV_CFLAGS@ -GUDEV_LIBS = @GUDEV_LIBS@ -HTML_DIR = @HTML_DIR@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -INTLLIBS = @INTLLIBS@ -INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ -INTLTOOL_MERGE = @INTLTOOL_MERGE@ -INTLTOOL_PERL = @INTLTOOL_PERL@ -INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ -INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ -INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ -INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ -INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ -INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ -INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ -INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ -INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ -INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ -INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ -INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ -INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ -INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ -IPTABLES_PATH = @IPTABLES_PATH@ -IWMX_SDK_CFLAGS = @IWMX_SDK_CFLAGS@ -IWMX_SDK_LIBS = @IWMX_SDK_LIBS@ -KERNEL_FIRMWARE_DIR = @KERNEL_FIRMWARE_DIR@ -LCOV = @LCOV@ -LD = @LD@ -LDFLAGS = @LDFLAGS@ -LIBDL = @LIBDL@ -LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ -LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ -LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ -LIBICONV = @LIBICONV@ -LIBINTL = @LIBINTL@ -LIBM = @LIBM@ -LIBNL_CFLAGS = @LIBNL_CFLAGS@ -LIBNL_LIBS = @LIBNL_LIBS@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@ -LIBSOUP_LIBS = @LIBSOUP_LIBS@ -LIBTOOL = @LIBTOOL@ -LIPO = @LIPO@ -LN_S = @LN_S@ -LTLIBICONV = @LTLIBICONV@ -LTLIBINTL = @LTLIBINTL@ -LTLIBOBJS = @LTLIBOBJS@ -MAINT = @MAINT@ -MAKEINFO = @MAKEINFO@ -MANIFEST_TOOL = @MANIFEST_TOOL@ -MKDIR_P = @MKDIR_P@ -MM_GLIB_CFLAGS = @MM_GLIB_CFLAGS@ -MM_GLIB_LIBS = @MM_GLIB_LIBS@ -MOC = @MOC@ -MSGFMT = @MSGFMT@ -MSGFMT_015 = @MSGFMT_015@ -MSGMERGE = @MSGMERGE@ -NM = @NM@ -NMEDIT = @NMEDIT@ -NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ -NM_MICRO_VERSION = @NM_MICRO_VERSION@ -NM_MINOR_VERSION = @NM_MINOR_VERSION@ -NM_MODIFY_SYSTEM_POLICY = @NM_MODIFY_SYSTEM_POLICY@ -NM_VERSION = @NM_VERSION@ -NSS_CFLAGS = @NSS_CFLAGS@ -NSS_LIBS = @NSS_LIBS@ -OBJDUMP = @OBJDUMP@ -OBJEXT = @OBJEXT@ -OTOOL = @OTOOL@ -OTOOL64 = @OTOOL64@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_URL = @PACKAGE_URL@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PKG_CONFIG = @PKG_CONFIG@ -PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ -PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ -POLKIT_CFLAGS = @POLKIT_CFLAGS@ -POLKIT_LIBS = @POLKIT_LIBS@ -POSUB = @POSUB@ -PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@ -QT_CFLAGS = @QT_CFLAGS@ -QT_LIBS = @QT_LIBS@ -RANLIB = @RANLIB@ -SED = @SED@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -STRIP = @STRIP@ -SYSTEMD_200_CFLAGS = @SYSTEMD_200_CFLAGS@ -SYSTEMD_200_LIBS = @SYSTEMD_200_LIBS@ -SYSTEMD_INHIBIT_CFLAGS = @SYSTEMD_INHIBIT_CFLAGS@ -SYSTEMD_INHIBIT_LIBS = @SYSTEMD_INHIBIT_LIBS@ -SYSTEMD_LOGIN_CFLAGS = @SYSTEMD_LOGIN_CFLAGS@ -SYSTEMD_LOGIN_LIBS = @SYSTEMD_LOGIN_LIBS@ -SYSTEM_CA_PATH = @SYSTEM_CA_PATH@ -UDEV_BASE_DIR = @UDEV_BASE_DIR@ -USE_NLS = @USE_NLS@ -UUID_CFLAGS = @UUID_CFLAGS@ -UUID_LIBS = @UUID_LIBS@ -VAPIGEN = @VAPIGEN@ -VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ -VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ -VERSION = @VERSION@ -XGETTEXT = @XGETTEXT@ -XGETTEXT_015 = @XGETTEXT_015@ -XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_AR = @ac_ct_AR@ -ac_ct_CC = @ac_ct_CC@ -ac_ct_CXX = @ac_ct_CXX@ -ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -intltool__v_merge_options_ = @intltool__v_merge_options_@ -intltool__v_merge_options_0 = @intltool__v_merge_options_0@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -nmbinary = @nmbinary@ -nmconfdir = @nmconfdir@ -nmdatadir = @nmdatadir@ -nmrundir = @nmrundir@ -nmstatedir = @nmstatedir@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -sysconfdir = @sysconfdir@ -systemdsystemunitdir = @systemdsystemunitdir@ -target_alias = @target_alias@ -top_build_prefix = @top_build_prefix@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -with_dhclient = @with_dhclient@ -with_dhcpcd = @with_dhcpcd@ -with_netconfig = @with_netconfig@ -with_resolvconf = @with_resolvconf@ -noinst_LTLIBRARIES = libip6-manager.la -libip6_manager_la_CPPFLAGS = \ - -I${top_srcdir} \ - -I${top_builddir}/include \ - -I${top_srcdir}/include \ - -I${top_builddir}/libnm-util \ - -I${top_srcdir}/libnm-util \ - -I${top_builddir}/src/generated \ - -I${top_srcdir}/src/generated \ - -I${top_srcdir}/src/logging \ - -I${top_srcdir}/src \ - $(LIBNL_CFLAGS) \ - $(DBUS_CFLAGS) \ - $(GLIB_CFLAGS) - -libip6_manager_la_SOURCES = \ - nm-ip6-manager.c \ - nm-ip6-manager.h - -libip6_manager_la_LIBADD = \ - $(top_builddir)/src/generated/libnm-generated.la \ - $(top_builddir)/src/logging/libnm-logging.la \ - $(LIBNL_LIBS) \ - $(DBUS_LIBS) \ - $(GLIB_LIBS) - -all: all-am - -.SUFFIXES: -.SUFFIXES: .c .lo .o .obj -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ - && { if test -f $@; then exit 0; else break; fi; }; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/ip6-manager/Makefile'; \ - $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --gnu src/ip6-manager/Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(am__aclocal_m4_deps): - -clean-noinstLTLIBRARIES: - -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) - @list='$(noinst_LTLIBRARIES)'; \ - locs=`for p in $$list; do echo $$p; done | \ - sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ - sort -u`; \ - test -z "$$locs" || { \ - echo rm -f $${locs}; \ - rm -f $${locs}; \ - } - -libip6-manager.la: $(libip6_manager_la_OBJECTS) $(libip6_manager_la_DEPENDENCIES) $(EXTRA_libip6_manager_la_DEPENDENCIES) - $(AM_V_CCLD)$(LINK) $(libip6_manager_la_OBJECTS) $(libip6_manager_la_LIBADD) $(LIBS) - -mostlyclean-compile: - -rm -f *.$(OBJEXT) - -distclean-compile: - -rm -f *.tab.c - -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libip6_manager_la-nm-ip6-manager.Plo@am__quote@ - -.c.o: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< - -.c.obj: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` - -.c.lo: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< - -libip6_manager_la-nm-ip6-manager.lo: nm-ip6-manager.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libip6_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libip6_manager_la-nm-ip6-manager.lo -MD -MP -MF $(DEPDIR)/libip6_manager_la-nm-ip6-manager.Tpo -c -o libip6_manager_la-nm-ip6-manager.lo `test -f 'nm-ip6-manager.c' || echo '$(srcdir)/'`nm-ip6-manager.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libip6_manager_la-nm-ip6-manager.Tpo $(DEPDIR)/libip6_manager_la-nm-ip6-manager.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-ip6-manager.c' object='libip6_manager_la-nm-ip6-manager.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libip6_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libip6_manager_la-nm-ip6-manager.lo `test -f 'nm-ip6-manager.c' || echo '$(srcdir)/'`nm-ip6-manager.c - -mostlyclean-libtool: - -rm -f *.lo - -clean-libtool: - -rm -rf .libs _libs - -ID: $(am__tagged_files) - $(am__define_uniq_tagged_files); mkid -fID $$unique -tags: tags-am -TAGS: tags - -tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) - set x; \ - here=`pwd`; \ - $(am__define_uniq_tagged_files); \ - shift; \ - if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ - test -n "$$unique" || unique=$$empty_fix; \ - if test $$# -gt 0; then \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - "$$@" $$unique; \ - else \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$unique; \ - fi; \ - fi -ctags: ctags-am - -CTAGS: ctags -ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) - $(am__define_uniq_tagged_files); \ - test -z "$(CTAGS_ARGS)$$unique" \ - || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$unique - -GTAGS: - here=`$(am__cd) $(top_builddir) && pwd` \ - && $(am__cd) $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) "$$here" -cscopelist: cscopelist-am - -cscopelist-am: $(am__tagged_files) - list='$(am__tagged_files)'; \ - case "$(srcdir)" in \ - [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ - *) sdir=$(subdir)/$(srcdir) ;; \ - esac; \ - for i in $$list; do \ - if test -f "$$i"; then \ - echo "$(subdir)/$$i"; \ - else \ - echo "$$sdir/$$i"; \ - fi; \ - done >> $(top_builddir)/cscope.files - -distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags - -distdir: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d "$(distdir)/$$file"; then \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ - else \ - test -f "$(distdir)/$$file" \ - || cp -p $$d/$$file "$(distdir)/$$file" \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: check-am -all-am: Makefile $(LTLIBRARIES) -installdirs: -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - if test -z '$(STRIP)'; then \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - install; \ - else \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ - fi -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." -clean: clean-am - -clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ - mostlyclean-am - -distclean: distclean-am - -rm -rf ./$(DEPDIR) - -rm -f Makefile -distclean-am: clean-am distclean-compile distclean-generic \ - distclean-tags - -dvi: dvi-am - -dvi-am: - -html: html-am - -html-am: - -info: info-am - -info-am: - -install-data-am: - -install-dvi: install-dvi-am - -install-dvi-am: - -install-exec-am: - -install-html: install-html-am - -install-html-am: - -install-info: install-info-am - -install-info-am: - -install-man: - -install-pdf: install-pdf-am - -install-pdf-am: - -install-ps: install-ps-am - -install-ps-am: - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -rf ./$(DEPDIR) - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-compile mostlyclean-generic \ - mostlyclean-libtool - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: - -.MAKE: install-am install-strip - -.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ - clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ - ctags-am distclean distclean-compile distclean-generic \ - distclean-libtool distclean-tags distdir dvi dvi-am html \ - html-am info info-am install install-am install-data \ - install-data-am install-dvi install-dvi-am install-exec \ - install-exec-am install-html install-html-am install-info \ - install-info-am install-man install-pdf install-pdf-am \ - install-ps install-ps-am install-strip installcheck \ - installcheck-am installdirs maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-compile \ - mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ - tags tags-am uninstall uninstall-am - - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/src/ip6-manager/nm-ip6-manager.c b/src/ip6-manager/nm-ip6-manager.c deleted file mode 100644 index 340867dd..00000000 --- a/src/ip6-manager/nm-ip6-manager.c +++ /dev/null @@ -1,1747 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* nm-ip6-manager.c - Handle IPv6 address configuration for NetworkManager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2009 - 2010 Red Hat, Inc. - */ - -#define _GNU_SOURCE /* for struct in6_pktinfo */ - -#include -#include -#include -#include - -#include -#include -#include - -#include "nm-ip6-manager.h" -#include "nm-netlink-monitor.h" -#include "nm-netlink-utils.h" -#include "nm-netlink-compat.h" -#include "NetworkManagerUtils.h" -#include "nm-marshal.h" -#include "nm-logging.h" -#include "nm-utils.h" - -/* Pre-DHCP addrconf timeout, in seconds */ -#define NM_IP6_TIMEOUT 20 - -/* FIXME? Stolen from the kernel sources */ -#define IF_RA_OTHERCONF 0x80 -#define IF_RA_MANAGED 0x40 -#define IF_RA_RCVD 0x20 -#define IF_RS_SENT 0x10 - -typedef struct { - NMNetlinkMonitor *monitor; - GHashTable *devices; - - struct nl_sock *nlh; - struct nl_cache *addr_cache, *route_cache; - - guint netlink_id; -} NMIP6ManagerPrivate; - -#define NM_IP6_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_IP6_MANAGER, NMIP6ManagerPrivate)) - -G_DEFINE_TYPE (NMIP6Manager, nm_ip6_manager, G_TYPE_OBJECT) - -enum { - ADDRCONF_COMPLETE, - CONFIG_CHANGED, - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -typedef enum { - NM_IP6_DEVICE_UNCONFIGURED, - NM_IP6_DEVICE_GOT_LINK_LOCAL, - NM_IP6_DEVICE_GOT_ROUTER_ADVERTISEMENT, - NM_IP6_DEVICE_GOT_ADDRESS, - NM_IP6_DEVICE_TIMED_OUT -} NMIP6DeviceState; - -typedef struct { - struct in6_addr addr; - time_t expires; -} NMIP6RDNSS; - -typedef struct { - char domain[256]; - time_t expires; -} NMIP6DNSSL; - -/******************************************************************/ - -typedef struct { - NMIP6Manager *manager; - char *iface; - int ifindex; - /* +7 since this field is used directly by stuff that expects - * padding to multiples of 8 bytes. - */ - guint8 hwaddr[NM_UTILS_HWADDR_LEN_MAX + 7]; - guint hwaddr_len; - - gboolean has_linklocal; - gboolean has_nonlinklocal; - guint dhcp_opts; - - char *disable_ip6_path; - gboolean disable_ip6_save_valid; - gint32 disable_ip6_save; - - guint finish_addrconf_id; - guint config_changed_id; - - NMIP6DeviceState state; - NMIP6DeviceState target_state; - gboolean addrconf_complete; - - GArray *rdnss_servers; - guint rdnss_timeout_id; - guint32 rdnss_timeout; - - GArray *dnssl_domains; - guint dnssl_timeout_id; - guint32 dnssl_timeout; - - time_t last_solicitation; - - guint ip6flags_poll_id; - - guint32 ra_flags; -} NMIP6Device; - -static void -clear_config_changed (NMIP6Device *device) -{ - if (device->config_changed_id) - g_source_remove (device->config_changed_id); - device->config_changed_id = 0; -} - -static void -nm_ip6_device_destroy (NMIP6Device *device) -{ - g_return_if_fail (device != NULL); - - /* reset the saved IPv6 value */ - if (device->disable_ip6_save_valid) { - nm_utils_do_sysctl (device->disable_ip6_path, - device->disable_ip6_save ? "1" : "0"); - } - - if (device->finish_addrconf_id) - g_source_remove (device->finish_addrconf_id); - - clear_config_changed (device); - - g_free (device->iface); - if (device->rdnss_servers) - g_array_free (device->rdnss_servers, TRUE); - if (device->rdnss_timeout_id) - g_source_remove (device->rdnss_timeout_id); - if (device->dnssl_domains) - g_array_free (device->dnssl_domains, TRUE); - if (device->dnssl_timeout_id) - g_source_remove (device->dnssl_timeout_id); - if (device->ip6flags_poll_id) - g_source_remove (device->ip6flags_poll_id); - - g_slice_free (NMIP6Device, device); -} - -static NMIP6Device * -nm_ip6_device_new (NMIP6Manager *manager, - int ifindex, - const guint8 *hwaddr, - guint hwaddr_len) -{ - NMIP6ManagerPrivate *priv = NM_IP6_MANAGER_GET_PRIVATE (manager); - NMIP6Device *device; - - g_return_val_if_fail (ifindex > 0, NULL); - g_return_val_if_fail (hwaddr != NULL, NULL); - g_return_val_if_fail (hwaddr_len > 0, NULL); - g_return_val_if_fail (hwaddr_len <= NM_UTILS_HWADDR_LEN_MAX, NULL); - - device = g_slice_new0 (NMIP6Device); - if (!device) { - nm_log_err (LOGD_IP6, "(%d): out of memory creating IP6 addrconf object.", - ifindex); - return NULL; - } - - device->ifindex = ifindex; - device->iface = nm_netlink_index_to_iface (ifindex); - if (!device->iface) { - nm_log_err (LOGD_IP6, "(%d): could not find interface name from index.", - ifindex); - goto error; - } - - memcpy (device->hwaddr, hwaddr, hwaddr_len); - device->hwaddr_len = hwaddr_len; - - device->manager = manager; - - device->rdnss_servers = g_array_new (FALSE, FALSE, sizeof (NMIP6RDNSS)); - - device->dnssl_domains = g_array_new (FALSE, FALSE, sizeof (NMIP6DNSSL)); - - g_hash_table_replace (priv->devices, GINT_TO_POINTER (device->ifindex), device); - - /* and the original value of IPv6 enable/disable */ - device->disable_ip6_path = g_strdup_printf ("/proc/sys/net/ipv6/conf/%s/disable_ipv6", - device->iface); - g_assert (device->disable_ip6_path); - device->disable_ip6_save_valid = nm_utils_get_proc_sys_net_value_with_bounds (device->disable_ip6_path, - device->iface, - &device->disable_ip6_save, - 0, 1); - - return device; - -error: - nm_ip6_device_destroy (device); - return NULL; -} - -static NMIP6Device * -nm_ip6_manager_get_device (NMIP6Manager *manager, int ifindex) -{ - NMIP6ManagerPrivate *priv; - - g_return_val_if_fail (manager != NULL, NULL); - g_return_val_if_fail (NM_IS_IP6_MANAGER (manager), NULL); - - priv = NM_IP6_MANAGER_GET_PRIVATE (manager); - return g_hash_table_lookup (priv->devices, GINT_TO_POINTER (ifindex)); -} - -static void -device_send_router_solicitation (NMIP6Device *device, const char *why) -{ - int sock, hops; - struct sockaddr_in6 sin6; - struct nd_router_solicit rs; - struct nd_opt_hdr lladdr_hdr; - static const guint8 local_routers_addr[] = - { 0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }; - struct msghdr mhdr; - struct iovec iov[3]; - struct cmsghdr *cmsg; - struct in6_pktinfo *ipi; - guint8 cmsgbuf[128]; - int cmsglen = 0; - time_t now; - - now = time (NULL); - if (device->last_solicitation > now - 5) - return; - device->last_solicitation = now; - - nm_log_dbg (LOGD_IP6, "(%s): %s: sending router solicitation", - device->iface, why); - - sock = socket (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); - if (sock < 0) { - nm_log_dbg (LOGD_IP6, "(%s): could not create ICMPv6 socket: %s", - device->iface, g_strerror (errno)); - return; - } - - hops = 255; - if ( setsockopt (sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &hops, sizeof (hops)) == -1 - || setsockopt (sock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &hops, sizeof (hops)) == -1) { - nm_log_dbg (LOGD_IP6, "(%s): could not set hop limit on ICMPv6 socket: %s", - device->iface, g_strerror (errno)); - close (sock); - return; - } - - /* Use the "all link-local routers" multicast address */ - memset (&sin6, 0, sizeof (sin6)); - memcpy (&sin6.sin6_addr, local_routers_addr, sizeof (sin6.sin6_addr)); - mhdr.msg_name = &sin6; - mhdr.msg_namelen = sizeof (sin6); - - /* Build the router solicitation */ - mhdr.msg_iov = iov; - memset (&rs, 0, sizeof (rs)); - rs.nd_rs_type = ND_ROUTER_SOLICIT; - iov[0].iov_len = sizeof (rs); - iov[0].iov_base = &rs; - - if (device->hwaddr_len > 0) { - memset (&lladdr_hdr, 0, sizeof (lladdr_hdr)); - lladdr_hdr.nd_opt_type = ND_OPT_SOURCE_LINKADDR; - lladdr_hdr.nd_opt_len = (sizeof (lladdr_hdr) + device->hwaddr_len + 7) % 8; - iov[1].iov_len = sizeof (lladdr_hdr); - iov[1].iov_base = &lladdr_hdr; - - iov[2].iov_len = (lladdr_hdr.nd_opt_len * 8) - 2; - iov[2].iov_base = device->hwaddr; - - mhdr.msg_iovlen = 3; - } else - mhdr.msg_iovlen = 1; - - /* Force this to go on the right device */ - memset (cmsgbuf, 0, sizeof (cmsgbuf)); - cmsg = (struct cmsghdr *) cmsgbuf; - cmsglen = CMSG_SPACE (sizeof (*ipi)); - cmsg->cmsg_len = CMSG_LEN (sizeof (*ipi)); - cmsg->cmsg_level = SOL_IPV6; - cmsg->cmsg_type = IPV6_PKTINFO; - ipi = (struct in6_pktinfo *) CMSG_DATA (cmsg); - ipi->ipi6_ifindex = device->ifindex; - - mhdr.msg_control = cmsg; - mhdr.msg_controllen = cmsglen; - - if (sendmsg (sock, &mhdr, 0) == -1) { - nm_log_dbg (LOGD_IP6, "(%s): could not send router solicitation: %s", - device->iface, g_strerror (errno)); - } - - close (sock); -} - -static char * -device_get_iface (NMIP6Device *device) -{ - return device ? device->iface : "unknown"; -} - -static const char * -state_to_string (NMIP6DeviceState state) -{ - switch (state) { - case NM_IP6_DEVICE_UNCONFIGURED: - return "unconfigured"; - case NM_IP6_DEVICE_GOT_LINK_LOCAL: - return "got-link-local"; - case NM_IP6_DEVICE_GOT_ROUTER_ADVERTISEMENT: - return "got-ra"; - case NM_IP6_DEVICE_GOT_ADDRESS: - return "got-address"; - case NM_IP6_DEVICE_TIMED_OUT: - return "timed-out"; - default: - return "unknown"; - } -} - -static gboolean -device_set_state (NMIP6Device *device, NMIP6DeviceState state) -{ - NMIP6DeviceState old_state; - - g_return_val_if_fail (device != NULL, FALSE); - - if (state == device->state) - return FALSE; - - old_state = device->state; - device->state = state; - nm_log_dbg (LOGD_IP6, "(%s) IP6 device state: %s -> %s", - device_get_iface (device), - state_to_string (old_state), - state_to_string (state)); - return TRUE; -} - -static char * -ra_flags_to_string (guint32 ra_flags) -{ - GString *s = g_string_sized_new (20); - - g_string_append (s, " ("); - if (ra_flags & IF_RS_SENT) - g_string_append_c (s, 'S'); - - if (ra_flags & IF_RA_RCVD) - g_string_append_c (s, 'R'); - - if (ra_flags & IF_RA_MANAGED) - g_string_append_c (s, 'M'); - - if (ra_flags & IF_RA_OTHERCONF) - g_string_append_c (s, 'O'); - - g_string_append_c (s, ')'); - return g_string_free (s, FALSE); -} - -static gboolean -device_set_ra_flags (NMIP6Device *device, guint ra_flags) -{ - guint old_ra_flags; - gchar *ra_flags_str, *old_ra_flags_str; - - g_return_val_if_fail (device != NULL, FALSE); - - if (ra_flags == device->ra_flags) - return FALSE; - - old_ra_flags = device->ra_flags; - device->ra_flags = ra_flags; - - if (nm_logging_level_enabled (LOGL_DEBUG)) { - ra_flags_str = ra_flags_to_string (ra_flags); - old_ra_flags_str = ra_flags_to_string (old_ra_flags); - nm_log_dbg (LOGD_IP6, "(%s) IP6 device ra_flags: 0x%08x %s -> 0x%08x %s", - device_get_iface (device), - old_ra_flags, old_ra_flags_str, - ra_flags, ra_flags_str); - g_free (ra_flags_str); - g_free (old_ra_flags_str); - } - - return TRUE; -} - -/******************************************************************/ - -typedef struct { - NMIP6Device *device; - gboolean success; -} CallbackInfo; - -static gboolean -finish_addrconf (gpointer user_data) -{ - CallbackInfo *info = user_data; - NMIP6Device *device = info->device; - NMIP6Manager *manager = device->manager; - int ifindex; - - device->finish_addrconf_id = 0; - device->addrconf_complete = TRUE; - ifindex = device->ifindex; - - /* We're done, stop polling IPv6 flags */ - if (device->ip6flags_poll_id) { - g_source_remove (device->ip6flags_poll_id); - device->ip6flags_poll_id = 0; - } - - /* And tell listeners that addrconf is complete */ - if (info->success) { - g_signal_emit (manager, signals[ADDRCONF_COMPLETE], 0, - ifindex, device->dhcp_opts, TRUE); - } else { - nm_log_info (LOGD_IP6, "(%s): IP6 addrconf timed out or failed.", - device->iface); - - nm_ip6_manager_cancel_addrconf (manager, ifindex); - g_signal_emit (manager, signals[ADDRCONF_COMPLETE], 0, - ifindex, IP6_DHCP_OPT_NONE, FALSE); - } - - return FALSE; -} - -static gboolean -emit_config_changed (gpointer user_data) -{ - CallbackInfo *info = user_data; - NMIP6Device *device = info->device; - NMIP6Manager *manager = device->manager; - - device->config_changed_id = 0; - g_signal_emit (manager, signals[CONFIG_CHANGED], 0, - device->ifindex, - device->dhcp_opts, - info->success); - return FALSE; -} - -static void set_rdnss_timeout (NMIP6Device *device); - -static gboolean -rdnss_expired (gpointer user_data) -{ - NMIP6Device *device = user_data; - CallbackInfo info = { device, FALSE }; - - nm_log_dbg (LOGD_IP6, "(%s): IPv6 RDNSS information expired", device->iface); - - set_rdnss_timeout (device); - clear_config_changed (device); - emit_config_changed (&info); - return FALSE; -} - -static gboolean -rdnss_needs_refresh (gpointer user_data) -{ - NMIP6Device *device = user_data; - gchar *msg; - - msg = g_strdup_printf ("IPv6 RDNSS due to expire in %d seconds", - device->rdnss_timeout); - device_send_router_solicitation (device, msg); - g_free (msg); - - set_rdnss_timeout (device); - - return FALSE; -} - -static void -set_rdnss_timeout (NMIP6Device *device) -{ - time_t expires = 0, now = time (NULL); - NMIP6RDNSS *rdnss; - int i; - - if (device->rdnss_timeout_id) { - g_source_remove (device->rdnss_timeout_id); - device->rdnss_timeout_id = 0; - } - - /* Find the soonest expiration time. */ - for (i = 0; i < device->rdnss_servers->len; i++) { - rdnss = &g_array_index (device->rdnss_servers, NMIP6RDNSS, i); - if (rdnss->expires == 0) - continue; - - /* If the entry has already expired, remove it; the "+ 1" is - * because g_timeout_add_seconds() might fudge the timing a - * bit. - */ - if (rdnss->expires <= now + 1) { - char buf[INET6_ADDRSTRLEN + 1]; - - if (inet_ntop (AF_INET6, &(rdnss->addr), buf, sizeof (buf)) > 0) { - nm_log_dbg (LOGD_IP6, "(%s): removing expired RA-provided nameserver %s", - device->iface, buf); - } - g_array_remove_index (device->rdnss_servers, i--); - continue; - } - - if (!expires || rdnss->expires < expires) - expires = rdnss->expires; - } - - if (expires) { - gchar *msg; - - device->rdnss_timeout = MIN (expires - now, G_MAXUINT32 - 1); - - if (device->rdnss_timeout <= 5) { - msg = g_strdup_printf ("IPv6 RDNSS about to expire in %d seconds", - device->rdnss_timeout); - device_send_router_solicitation (device, msg); - g_free (msg); - device->rdnss_timeout_id = g_timeout_add_seconds (device->rdnss_timeout, - rdnss_expired, - device); - } else { - device->rdnss_timeout_id = g_timeout_add_seconds (device->rdnss_timeout / 2, - rdnss_needs_refresh, - device); - } - } -} - -static void set_dnssl_timeout (NMIP6Device *device); - -static gboolean -dnssl_expired (gpointer user_data) -{ - NMIP6Device *device = user_data; - CallbackInfo info = { device, FALSE }; - - nm_log_dbg (LOGD_IP6, "(%s): IPv6 DNSSL information expired", device->iface); - - set_dnssl_timeout (device); - clear_config_changed (device); - emit_config_changed (&info); - return FALSE; -} - -static gboolean -dnssl_needs_refresh (gpointer user_data) -{ - NMIP6Device *device = user_data; - gchar *msg; - - msg = g_strdup_printf ("IPv6 DNSSL due to expire in %d seconds", - device->dnssl_timeout); - device_send_router_solicitation (device, msg); - g_free (msg); - - set_dnssl_timeout (device); - - return FALSE; -} - -static void -set_dnssl_timeout (NMIP6Device *device) -{ - time_t expires = 0, now = time (NULL); - NMIP6DNSSL *dnssl; - int i; - - if (device->dnssl_timeout_id) { - g_source_remove (device->dnssl_timeout_id); - device->dnssl_timeout_id = 0; - } - - /* Find the soonest expiration time. */ - for (i = 0; i < device->dnssl_domains->len; i++) { - dnssl = &g_array_index (device->dnssl_domains, NMIP6DNSSL, i); - if (dnssl->expires == 0) - continue; - - /* If the entry has already expired, remove it; the "+ 1" is - * because g_timeout_add_seconds() might fudge the timing a - * bit. - */ - if (dnssl->expires <= now + 1) { - nm_log_dbg (LOGD_IP6, "(%s): removing expired RA-provided domain %s", - device->iface, dnssl->domain); - g_array_remove_index (device->dnssl_domains, i--); - continue; - } - - if (!expires || dnssl->expires < expires) - expires = dnssl->expires; - } - - if (expires) { - gchar *msg; - - device->dnssl_timeout = MIN (expires - now, G_MAXUINT32 - 1); - - if (device->dnssl_timeout <= 5) { - msg = g_strdup_printf ("IPv6 DNSSL about to expire in %d seconds", - device->dnssl_timeout); - device_send_router_solicitation (device, msg); - g_free (msg); - device->dnssl_timeout_id = g_timeout_add_seconds (device->dnssl_timeout, - dnssl_expired, - device); - } else { - device->dnssl_timeout_id = g_timeout_add_seconds (device->dnssl_timeout / 2, - dnssl_needs_refresh, - device); - } - } -} - -static CallbackInfo * -callback_info_new (NMIP6Device *device, gboolean success) -{ - CallbackInfo *info; - - info = g_malloc0 (sizeof (CallbackInfo)); - info->device = device; - info->success = success; - return info; -} - -static void -check_addresses (NMIP6Device *device) -{ - NMIP6Manager *manager = device->manager; - NMIP6ManagerPrivate *priv = NM_IP6_MANAGER_GET_PRIVATE (manager); - struct rtnl_addr *rtnladdr; - struct nl_addr *nladdr; - struct in6_addr *addr; - - /* Reset address information */ - device->has_linklocal = FALSE; - device->has_nonlinklocal = FALSE; - - /* Look for any IPv6 addresses the kernel may have set for the device */ - for (rtnladdr = (struct rtnl_addr *) nl_cache_get_first (priv->addr_cache); - rtnladdr; - rtnladdr = (struct rtnl_addr *) nl_cache_get_next ((struct nl_object *) rtnladdr)) { - char buf[INET6_ADDRSTRLEN]; - - if (rtnl_addr_get_ifindex (rtnladdr) != device->ifindex) - continue; - - nladdr = rtnl_addr_get_local (rtnladdr); - if (!nladdr || nl_addr_get_family (nladdr) != AF_INET6) - continue; - - addr = nl_addr_get_binary_addr (nladdr); - - if (inet_ntop (AF_INET6, addr, buf, INET6_ADDRSTRLEN) > 0) { - nm_log_dbg (LOGD_IP6, "(%s): netlink address: %s/%d", - device->iface, buf, - rtnl_addr_get_prefixlen (rtnladdr)); - } - - if (IN6_IS_ADDR_LINKLOCAL (addr)) { - if (device->state == NM_IP6_DEVICE_UNCONFIGURED) - device_set_state (device, NM_IP6_DEVICE_GOT_LINK_LOCAL); - device->has_linklocal = TRUE; - } else { - if (device->state == NM_IP6_DEVICE_GOT_ROUTER_ADVERTISEMENT) - device_set_state (device, NM_IP6_DEVICE_GOT_ADDRESS); - device->has_nonlinklocal = TRUE; - } - } - - /* There might be a LL address hanging around on the interface from - * before in the initial run, but if it goes away later, make sure we - * regress from GOT_LINK_LOCAL back to UNCONFIGURED. - */ - if ((device->state == NM_IP6_DEVICE_GOT_LINK_LOCAL) && !device->has_linklocal) - device_set_state (device, NM_IP6_DEVICE_UNCONFIGURED); - - nm_log_dbg (LOGD_IP6, "(%s): addresses checked (state %s)", - device->iface, state_to_string (device->state)); -} - -static void -check_ra_flags (NMIP6Device *device) -{ - device->dhcp_opts = IP6_DHCP_OPT_NONE; - - /* We only care about router advertisements if we want a real IPv6 address */ - if ( (device->target_state == NM_IP6_DEVICE_GOT_ADDRESS) - && (device->ra_flags & IF_RA_RCVD)) { - - if (device->state < NM_IP6_DEVICE_GOT_ROUTER_ADVERTISEMENT) - device_set_state (device, NM_IP6_DEVICE_GOT_ROUTER_ADVERTISEMENT); - - if (device->ra_flags & IF_RA_MANAGED) { - device->dhcp_opts = IP6_DHCP_OPT_MANAGED; - nm_log_dbg (LOGD_IP6, "router advertisement deferred to DHCPv6"); - } else if (device->ra_flags & IF_RA_OTHERCONF) { - device->dhcp_opts = IP6_DHCP_OPT_OTHERCONF; - nm_log_dbg (LOGD_IP6, "router advertisement requests parallel DHCPv6"); - } - } - nm_log_dbg (LOGD_IP6, "(%s): router advertisement checked (state %s)", - device->iface, state_to_string (device->state)); -} - -static void -check_addrconf_complete (NMIP6Device *device) -{ - CallbackInfo *info; - - if (!device->addrconf_complete) { - /* Managed mode (ie DHCP only) short-circuits automatic addrconf, so - * we don't bother waiting for the device's target state to be reached - * when the RA requests managed mode. - */ - if ( (device->state >= device->target_state) - || (device->dhcp_opts == IP6_DHCP_OPT_MANAGED)) { - /* device->finish_addrconf_id may currently be a timeout - * rather than an idle, so we remove the existing source. - */ - if (device->finish_addrconf_id) - g_source_remove (device->finish_addrconf_id); - - nm_log_dbg (LOGD_IP6, "(%s): reached target state or Managed-mode requested (state '%s') (dhcp opts 0x%X)", - device->iface, state_to_string (device->state), - device->dhcp_opts); - - info = callback_info_new (device, TRUE); - device->finish_addrconf_id = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, - finish_addrconf, - info, - (GDestroyNotify) g_free); - } - } else { - if (!device->config_changed_id) { - gboolean success = TRUE; - - /* If for some reason an RA-provided address disappeared, we need - * to make sure we fail the connection as it's no longer valid. - */ - if ( (device->state == NM_IP6_DEVICE_GOT_ADDRESS) - && (device->target_state == NM_IP6_DEVICE_GOT_ADDRESS) - && !device->has_nonlinklocal) { - nm_log_dbg (LOGD_IP6, "(%s): RA-provided address no longer found", - device->iface); - success = FALSE; - } - - info = callback_info_new (device, success); - device->config_changed_id = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, - emit_config_changed, - info, - (GDestroyNotify) g_free); - } - } - - nm_log_dbg (LOGD_IP6, "(%s): dhcp_opts checked (state %s)", - device->iface, state_to_string (device->state)); -} - -static void -nm_ip6_device_sync_from_netlink (NMIP6Device *device) -{ - nm_log_dbg (LOGD_IP6, "(%s): syncing with netlink (ra_flags 0x%X) (state/target '%s'/'%s')", - device->iface, device->ra_flags, - state_to_string (device->state), - state_to_string (device->target_state)); - - check_ra_flags (device); - check_addresses (device); - check_addrconf_complete (device); -} - -static void -ref_object (struct nl_object *obj, void *data) -{ - struct nl_object **out = data; - - nl_object_get (obj); - *out = obj; -} - -static void -dump_address_change (NMIP6Device *device, struct nlmsghdr *hdr, struct rtnl_addr *rtnladdr) -{ - char *event; - struct nl_addr *addr; - char addr_str[40] = "none"; - - event = hdr->nlmsg_type == RTM_NEWADDR ? "new" : "lost"; - addr = rtnl_addr_get_local (rtnladdr); - if (addr) - nl_addr2str (addr, addr_str, 40); - - nm_log_dbg (LOGD_IP6, "(%s) %s address: %s", device_get_iface (device), event, addr_str); -} - -static void -dump_route_change (NMIP6Device *device, struct nlmsghdr *hdr, struct rtnl_route *rtnlroute) -{ - char *event; - struct nl_addr *dst; - char dst_str[40] = "none"; - struct nl_addr *gateway; - char gateway_str[40] = "none"; - - event = hdr->nlmsg_type == RTM_NEWROUTE ? "new" : "lost"; - dst = rtnl_route_get_dst (rtnlroute); - gateway = rtnl_route_get_gateway (rtnlroute); - if (dst) - nl_addr2str (dst, dst_str, 40); - if (gateway) - nl_addr2str (gateway, gateway_str, 40); - - nm_log_dbg (LOGD_IP6, "(%s) %s route: %s via %s",device_get_iface (device), event, dst_str, gateway_str); -} - -static NMIP6Device * -process_address_change (NMIP6Manager *manager, struct nl_msg *msg) -{ - NMIP6ManagerPrivate *priv = NM_IP6_MANAGER_GET_PRIVATE (manager); - NMIP6Device *device; - struct nlmsghdr *hdr; - struct rtnl_addr *rtnladdr; - int old_size; - - hdr = nlmsg_hdr (msg); - rtnladdr = NULL; - nl_msg_parse (msg, ref_object, &rtnladdr); - if (!rtnladdr) { - nm_log_dbg (LOGD_IP6, "error processing netlink new/del address message"); - return NULL; - } - - device = nm_ip6_manager_get_device (manager, rtnl_addr_get_ifindex (rtnladdr)); - - old_size = nl_cache_nitems (priv->addr_cache); - nl_cache_include (priv->addr_cache, (struct nl_object *)rtnladdr, NULL, NULL); - - /* The kernel will re-notify us of automatically-added addresses - * every time it gets another router advertisement. We only want - * to notify higher levels if we actually changed something. - */ - nm_log_dbg (LOGD_IP6, "(%s): address cache size: %d -> %d:", - device_get_iface (device), old_size, nl_cache_nitems (priv->addr_cache)); - dump_address_change (device, hdr, rtnladdr); - rtnl_addr_put (rtnladdr); - if (nl_cache_nitems (priv->addr_cache) == old_size) - return NULL; - - return device; -} - -static NMIP6Device * -process_route_change (NMIP6Manager *manager, struct nl_msg *msg) -{ - NMIP6ManagerPrivate *priv = NM_IP6_MANAGER_GET_PRIVATE (manager); - NMIP6Device *device; - struct nlmsghdr *hdr; - struct rtnl_route *rtnlroute; - int old_size; - - hdr = nlmsg_hdr (msg); - rtnlroute = NULL; - nl_msg_parse (msg, ref_object, &rtnlroute); - if (!rtnlroute) { - nm_log_dbg (LOGD_IP6, "error processing netlink new/del route message"); - return NULL; - } - - /* Cached/cloned routes are created by the kernel for specific operations - * and aren't part of the interface's permanent routing configuration. - */ - if (rtnl_route_get_flags (rtnlroute) & RTM_F_CLONED) { - rtnl_route_put (rtnlroute); - return NULL; - } - - device = nm_ip6_manager_get_device (manager, rtnl_route_get_oif (rtnlroute)); - - old_size = nl_cache_nitems (priv->route_cache); - nl_cache_include (priv->route_cache, (struct nl_object *)rtnlroute, NULL, NULL); - - /* As above in process_address_change */ - nm_log_dbg (LOGD_IP6, "(%s): route cache size: %d -> %d:", - device_get_iface (device), old_size, nl_cache_nitems (priv->route_cache)); - dump_route_change (device, hdr, rtnlroute); - rtnl_route_put (rtnlroute); - if (nl_cache_nitems (priv->route_cache) == old_size) - return NULL; - - return device; -} - -/* RDNSS parsing code based on rdnssd, Copyright 2007 Pierre Ynard, - * Rémi Denis-Courmont. GPLv2/3 - */ - -#define ND_OPT_RDNSS 25 -#define ND_OPT_DNSSL 31 - -struct nd_opt_rdnss { - uint8_t nd_opt_rdnss_type; - uint8_t nd_opt_rdnss_len; - uint16_t nd_opt_rdnss_reserved1; - uint32_t nd_opt_rdnss_lifetime; - /* followed by one or more IPv6 addresses */ -} __attribute__ ((packed)); - -struct nd_opt_dnssl { - uint8_t nd_opt_dnssl_type; - uint8_t nd_opt_dnssl_len; - uint16_t nd_opt_dnssl_reserved1; - uint32_t nd_opt_dnssl_lifetime; - /* followed by one or more suffixes */ -} __attribute__ ((packed)); - -static gboolean -process_nduseropt_rdnss (NMIP6Device *device, struct nd_opt_hdr *opt) -{ - size_t opt_len; - struct nd_opt_rdnss *rdnss_opt; - time_t now = time (NULL); - struct in6_addr *addr; - GArray *new_servers; - NMIP6RDNSS server, *cur_server; - gboolean changed = FALSE; - guint i; - - opt_len = opt->nd_opt_len; - - if (opt_len < 3 || (opt_len & 1) == 0) - return FALSE; - - rdnss_opt = (struct nd_opt_rdnss *) opt; - - new_servers = g_array_new (FALSE, FALSE, sizeof (NMIP6RDNSS)); - - /* Pad the DNS server expiry somewhat to give a bit of slack in cases - * where one RA gets lost or something (which can happen on unreliable - * links like WiFi where certain types of frames are not retransmitted). - * Note that 0 has special meaning and is therefore not adjusted. - */ - server.expires = ntohl (rdnss_opt->nd_opt_rdnss_lifetime); - if (server.expires > 0) - if (server.expires < 7200) - server.expires = 7200; - server.expires += now; - - for (addr = (struct in6_addr *) (rdnss_opt + 1); opt_len >= 2; addr++, opt_len -= 2) { - char buf[INET6_ADDRSTRLEN + 1]; - - if (!inet_ntop (AF_INET6, addr, buf, sizeof (buf))) { - nm_log_warn (LOGD_IP6, "(%s): received invalid RA-provided nameserver", device->iface); - continue; - } - - /* Update the cached timeout if we already saw this server */ - for (i = 0; i < device->rdnss_servers->len; i++) { - cur_server = &(g_array_index (device->rdnss_servers, NMIP6RDNSS, i)); - - if (!IN6_ARE_ADDR_EQUAL (addr, &cur_server->addr)) - continue; - - cur_server->expires = server.expires; - - if (server.expires > 0) { - nm_log_dbg (LOGD_IP6, "(%s): refreshing RA-provided nameserver %s (expires in %ld seconds)", - device->iface, buf, - server.expires - now); - break; - } - - nm_log_dbg (LOGD_IP6, "(%s): removing RA-provided nameserver %s on router request", - device->iface, buf); - - g_array_remove_index (device->rdnss_servers, i); - changed = TRUE; - break; - } - - if (server.expires == 0) - continue; - if (i < device->rdnss_servers->len) - continue; - - nm_log_dbg (LOGD_IP6, "(%s): found RA-provided nameserver %s (expires in %ld seconds)", - device->iface, buf, server.expires - now); - - server.addr = *addr; - g_array_append_val (new_servers, server); - } - - /* New servers must be added in the order they are listed in the - * RA option and before any existing servers. - * - * Note: This is the place to remove servers if we want to cap the - * number of resolvers. The RFC states that the one to expire - * first of the existing servers should be removed. - */ - if (new_servers->len) { - g_array_prepend_vals (device->rdnss_servers, - new_servers->data, new_servers->len); - changed = TRUE; - } - - g_array_free (new_servers, TRUE); - - /* Timeouts may have changed even if IPs didn't */ - set_rdnss_timeout (device); - - return changed; -} - -static const char * -parse_dnssl_domain (const unsigned char *buffer, size_t maxlen) -{ - static char domain[256]; - size_t label_len; - - domain[0] = '\0'; - - while (maxlen > 0) { - label_len = *buffer; - buffer++; - maxlen--; - - if (label_len == 0) - return domain; - - if (label_len > maxlen) - return NULL; - if ((sizeof (domain) - strlen (domain)) < (label_len + 2)) - return NULL; - - if (domain[0] != '\0') - strcat (domain, "."); - strncat (domain, (const char *)buffer, label_len); - buffer += label_len; - maxlen -= label_len; - } - - return NULL; -} - -static gboolean -process_nduseropt_dnssl (NMIP6Device *device, struct nd_opt_hdr *opt) -{ - size_t opt_len; - struct nd_opt_dnssl *dnssl_opt; - unsigned char *opt_ptr; - time_t now = time (NULL); - GArray *new_domains; - NMIP6DNSSL domain, *cur_domain; - gboolean changed; - guint i; - - opt_len = opt->nd_opt_len; - - if (opt_len < 2) - return FALSE; - - dnssl_opt = (struct nd_opt_dnssl *) opt; - - opt_ptr = (unsigned char *)(dnssl_opt + 1); - opt_len = (opt_len - 1) * 8; /* prefer bytes for later handling */ - - new_domains = g_array_new (FALSE, FALSE, sizeof (NMIP6DNSSL)); - - changed = FALSE; - - /* Pad the DNS server expiry somewhat to give a bit of slack in cases - * where one RA gets lost or something (which can happen on unreliable - * links like wifi where certain types of frames are not retransmitted). - * Note that 0 has special meaning and is therefore not adjusted. - */ - domain.expires = ntohl (dnssl_opt->nd_opt_dnssl_lifetime); - if (domain.expires > 0) - if (domain.expires < 7200) - domain.expires = 7200; - domain.expires += now; - - while (opt_len) { - const char *domain_str; - - domain_str = parse_dnssl_domain (opt_ptr, opt_len); - if (domain_str == NULL) { - nm_log_dbg (LOGD_IP6, "(%s): invalid DNSSL option, parsing aborted", - device->iface); - break; - } - - /* The DNSSL encoding of domains happen to occupy the same size - * as the length of the resulting string, including terminating - * null. */ - opt_ptr += strlen (domain_str) + 1; - opt_len -= strlen (domain_str) + 1; - - /* Ignore empty domains. They're probably just padding... */ - if (domain_str[0] == '\0') - continue; - - /* Update cached domain information if we've seen this domain before */ - for (i = 0; i < device->dnssl_domains->len; i++) { - cur_domain = &(g_array_index (device->dnssl_domains, NMIP6DNSSL, i)); - - if (strcmp (domain_str, cur_domain->domain) != 0) - continue; - - cur_domain->expires = domain.expires; - - if (domain.expires > 0) { - nm_log_dbg (LOGD_IP6, "(%s): refreshing RA-provided domain %s (expires in %ld seconds)", - device->iface, domain_str, - domain.expires - now); - break; - } - - nm_log_dbg (LOGD_IP6, "(%s): removing RA-provided domain %s on router request", - device->iface, domain_str); - - g_array_remove_index (device->dnssl_domains, i); - changed = TRUE; - break; - } - - if (domain.expires == 0) - continue; - if (i < device->dnssl_domains->len) - continue; - - nm_log_dbg (LOGD_IP6, "(%s): found RA-provided domain %s (expires in %ld seconds)", - device->iface, domain_str, domain.expires - now); - - g_assert (strlen (domain_str) < sizeof (domain.domain)); - strcpy (domain.domain, domain_str); - g_array_append_val (new_domains, domain); - } - - /* New domains must be added in the order they are listed in the - * RA option and before any existing domains. - * - * Note: This is the place to remove domains if we want to cap the - * number of domains. The RFC states that the one to expire - * first of the existing domains should be removed. - */ - if (new_domains->len) { - g_array_prepend_vals (device->dnssl_domains, - new_domains->data, new_domains->len); - changed = TRUE; - } - - g_array_free (new_domains, TRUE); - - /* Timeouts may have changed even if domains didn't */ - set_dnssl_timeout (device); - - return changed; -} - -static NMIP6Device * -process_nduseropt (NMIP6Manager *manager, struct nl_msg *msg) -{ - NMIP6Device *device; - struct nduseroptmsg *ndmsg; - struct nd_opt_hdr *opt; - guint opts_len; - gboolean changed = FALSE; - - nm_log_dbg (LOGD_IP6, "processing netlink nduseropt message"); - - ndmsg = (struct nduseroptmsg *) NLMSG_DATA (nlmsg_hdr (msg)); - - if (!nlmsg_valid_hdr (nlmsg_hdr (msg), sizeof (*ndmsg)) || - nlmsg_datalen (nlmsg_hdr (msg)) < - (ndmsg->nduseropt_opts_len + sizeof (*ndmsg))) { - nm_log_dbg (LOGD_IP6, "ignoring invalid nduseropt message"); - return NULL; - } - - if (ndmsg->nduseropt_family != AF_INET6 || - ndmsg->nduseropt_icmp_type != ND_ROUTER_ADVERT || - ndmsg->nduseropt_icmp_code != 0) { - nm_log_dbg (LOGD_IP6, "ignoring non-Router Advertisement message"); - return NULL; - } - - device = nm_ip6_manager_get_device (manager, ndmsg->nduseropt_ifindex); - if (!device) { - nm_log_dbg (LOGD_IP6, "ignoring message for unknown device"); - return NULL; - } - - opt = (struct nd_opt_hdr *) (ndmsg + 1); - opts_len = ndmsg->nduseropt_opts_len; - - while (opts_len >= sizeof (struct nd_opt_hdr)) { - size_t nd_opt_len = opt->nd_opt_len; - - if (nd_opt_len == 0 || opts_len < (nd_opt_len << 3)) - break; - - switch (opt->nd_opt_type) { - case ND_OPT_RDNSS: - changed = process_nduseropt_rdnss (device, opt); - break; - case ND_OPT_DNSSL: - changed = process_nduseropt_dnssl (device, opt); - break; - } - - opts_len -= opt->nd_opt_len << 3; - opt = (struct nd_opt_hdr *) ((uint8_t *) opt + (opt->nd_opt_len << 3)); - } - - if (changed) - return device; - else - return NULL; -} - -static struct nla_policy link_policy[IFLA_MAX + 1] = { - [IFLA_PROTINFO] = { .type = NLA_NESTED }, -}; - -static struct nla_policy link_prot_policy[IFLA_INET6_MAX + 1] = { - [IFLA_INET6_FLAGS] = { .type = NLA_U32 }, -}; - -static NMIP6Device * -process_newlink (NMIP6Manager *manager, struct nl_msg *msg) -{ - struct nlmsghdr *hdr = nlmsg_hdr (msg); - struct ifinfomsg *ifi; - NMIP6Device *device; - struct nlattr *tb[IFLA_MAX + 1]; - struct nlattr *pi[IFLA_INET6_MAX + 1]; - int err; - - /* FIXME: we have to do this manually for now since libnl doesn't yet - * support the IFLA_PROTINFO attribute of NEWLINK messages. When it does, - * we can get rid of this function and just grab IFLA_PROTINFO from - * nm_ip6_device_sync_from_netlink(), then get the IFLA_INET6_FLAGS out of - * the PROTINFO. - */ - err = nlmsg_parse (hdr, sizeof (*ifi), tb, IFLA_MAX, link_policy); - if (err < 0) { - nm_log_dbg (LOGD_IP6, "ignoring invalid newlink netlink message " - "while parsing PROTINFO attribute"); - return NULL; - } - - ifi = nlmsg_data (hdr); - if (ifi->ifi_family != AF_INET6) { - nm_log_dbg (LOGD_IP6, "ignoring netlink message family %d", ifi->ifi_family); - return NULL; - } - - device = nm_ip6_manager_get_device (manager, ifi->ifi_index); - if (!device || device->addrconf_complete) { - nm_log_dbg (LOGD_IP6, "(%s): ignoring unknown or completed device", - device ? device->iface : "(none)"); - return NULL; - } - - if (!tb[IFLA_PROTINFO]) { - nm_log_dbg (LOGD_IP6, "(%s): message had no PROTINFO attribute", device->iface); - return NULL; - } - - err = nla_parse_nested (pi, IFLA_INET6_MAX, tb[IFLA_PROTINFO], link_prot_policy); - if (err < 0) { - nm_log_dbg (LOGD_IP6, "(%s): error parsing PROTINFO flags", device->iface); - return NULL; - } - if (!pi[IFLA_INET6_FLAGS]) { - nm_log_dbg (LOGD_IP6, "(%s): message had no PROTINFO flags", device->iface); - return NULL; - } - - device_set_ra_flags (device, nla_get_u32 (pi[IFLA_INET6_FLAGS])); - - return device; -} - -static void -netlink_notification (NMNetlinkMonitor *monitor, struct nl_msg *msg, gpointer user_data) -{ - NMIP6Manager *manager = (NMIP6Manager *) user_data; - NMIP6Device *device; - struct nlmsghdr *hdr; - - hdr = nlmsg_hdr (msg); - nm_log_dbg (LOGD_HW, "netlink event type %d", hdr->nlmsg_type); - switch (hdr->nlmsg_type) { - case RTM_NEWADDR: - case RTM_DELADDR: - device = process_address_change (manager, msg); - break; - case RTM_NEWROUTE: - case RTM_DELROUTE: - device = process_route_change (manager, msg); - break; - case RTM_NEWNDUSEROPT: - device = process_nduseropt (manager, msg); - break; - case RTM_NEWLINK: - device = process_newlink (manager, msg); - break; - default: - return; - } - - if (device) { - nm_ip6_device_sync_from_netlink (device); - } -} - -gboolean -nm_ip6_manager_prepare_interface (NMIP6Manager *manager, - int ifindex, - const guint8 *hwaddr, - guint hwaddr_len, - NMSettingIP6Config *s_ip6, - const char *accept_ra_path) -{ - NMIP6ManagerPrivate *priv; - NMIP6Device *device; - const char *method = NULL; - - g_return_val_if_fail (NM_IS_IP6_MANAGER (manager), FALSE); - g_return_val_if_fail (ifindex > 0, FALSE); - g_return_val_if_fail (hwaddr != NULL, FALSE); - g_return_val_if_fail (hwaddr_len > 0, FALSE); - g_return_val_if_fail (hwaddr_len <= NM_UTILS_HWADDR_LEN_MAX, FALSE); - - priv = NM_IP6_MANAGER_GET_PRIVATE (manager); - - device = nm_ip6_device_new (manager, ifindex, hwaddr, hwaddr_len); - g_return_val_if_fail (device != NULL, FALSE); - g_return_val_if_fail ( strchr (device->iface, '/') == NULL - && strcmp (device->iface, "all") != 0 - && strcmp (device->iface, "default") != 0, - FALSE); - - if (s_ip6) - method = nm_setting_ip6_config_get_method (s_ip6); - if (!method) - method = NM_SETTING_IP6_CONFIG_METHOD_AUTO; - - /* Establish target state and turn router advertisement acceptance on or off */ - if (!strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL)) { - device->target_state = NM_IP6_DEVICE_GOT_LINK_LOCAL; - nm_utils_do_sysctl (accept_ra_path, "0"); - } else { - device->target_state = NM_IP6_DEVICE_GOT_ADDRESS; - nm_utils_do_sysctl (accept_ra_path, "2"); - } - - return TRUE; -} - -static gboolean -poll_ip6_flags (gpointer user_data) -{ - nm_netlink_monitor_request_ip6_info (NM_NETLINK_MONITOR (user_data), NULL); - return TRUE; -} - -#define FIRST_ROUTE(m) ((struct rtnl_route *) nl_cache_get_first (m)) -#define NEXT_ROUTE(m) ((struct rtnl_route *) nl_cache_get_next ((struct nl_object *) m)) - -#define FIRST_ADDR(m) ((struct rtnl_addr *) nl_cache_get_first (m)) -#define NEXT_ADDR(m) ((struct rtnl_addr *) nl_cache_get_next ((struct nl_object *) m)) - -static void -wait_for_no_addresses (NMIP6Manager *self, NMIP6Device *device) -{ - NMIP6ManagerPrivate *priv = NM_IP6_MANAGER_GET_PRIVATE (self); - guint64 now, end; - gboolean has_addrs = TRUE; - - now = end = g_get_real_time (); - end += (G_USEC_PER_SEC * 3); - - while (has_addrs && now < end) { - struct rtnl_addr *rtnladdr; - struct nl_addr *nladdr; - - nl_cache_refill (priv->nlh, priv->addr_cache); - for (has_addrs = FALSE, rtnladdr = FIRST_ADDR (priv->addr_cache); - rtnladdr; - rtnladdr = NEXT_ADDR (rtnladdr)) { - - nladdr = rtnl_addr_get_local (rtnladdr); - if ( rtnl_addr_get_ifindex (rtnladdr) == device->ifindex - && nladdr - && nl_addr_get_family (nladdr) == AF_INET6) { - /* Still IPv6 addresses on the interface */ - has_addrs = TRUE; - nm_log_dbg (LOGD_IP6, "(%s) waiting for cleared IPv6 addresses", device->iface); - g_usleep (100); - now = g_get_real_time (); - break; - } - } - } -} - -void -nm_ip6_manager_begin_addrconf (NMIP6Manager *manager, int ifindex) -{ - NMIP6ManagerPrivate *priv; - NMIP6Device *device; - CallbackInfo *info; - - g_return_if_fail (NM_IS_IP6_MANAGER (manager)); - g_return_if_fail (ifindex > 0); - - priv = NM_IP6_MANAGER_GET_PRIVATE (manager); - - device = (NMIP6Device *) g_hash_table_lookup (priv->devices, GINT_TO_POINTER (ifindex)); - g_return_if_fail (device != NULL); - - nm_log_info (LOGD_IP6, "Activation (%s) Beginning IP6 addrconf.", device->iface); - - device->addrconf_complete = FALSE; - device->ra_flags = 0; - - /* Set up a timeout on the transaction to kill it after the timeout */ - info = callback_info_new (device, FALSE); - device->finish_addrconf_id = g_timeout_add_seconds_full (G_PRIORITY_DEFAULT, - NM_IP6_TIMEOUT, - finish_addrconf, - info, - (GDestroyNotify) g_free); - - /* Bounce IPv6 on the interface to ensure the kernel will start looking for - * new RAs; there doesn't seem to be a better way to do this right now. - */ - if (device->target_state >= NM_IP6_DEVICE_GOT_ADDRESS) { - nm_utils_do_sysctl (device->disable_ip6_path, "1"); - /* Wait until all existing IPv6 addresses have been removed from the link, - * to ensure they don't confuse our IPv6 addressing state machine. - */ - wait_for_no_addresses (manager, device); - nm_utils_do_sysctl (device->disable_ip6_path, "0"); - } - - device->ip6flags_poll_id = g_timeout_add_seconds (1, poll_ip6_flags, priv->monitor); - - /* Kick off the initial IPv6 flags request */ - nm_netlink_monitor_request_ip6_info (priv->monitor, NULL); - - /* Sync flags, etc, from netlink; this will also notice if the - * device is already fully configured and schedule the - * ADDRCONF_COMPLETE signal in that case. - */ - nm_ip6_device_sync_from_netlink (device); -} - -void -nm_ip6_manager_cancel_addrconf (NMIP6Manager *manager, int ifindex) -{ - g_return_if_fail (NM_IS_IP6_MANAGER (manager)); - g_return_if_fail (ifindex > 0); - - g_hash_table_remove (NM_IP6_MANAGER_GET_PRIVATE (manager)->devices, - GINT_TO_POINTER (ifindex)); -} - -NMIP6Config * -nm_ip6_manager_get_ip6_config (NMIP6Manager *manager, int ifindex) -{ - NMIP6ManagerPrivate *priv; - NMIP6Device *device; - NMIP6Config *config; - struct rtnl_addr *rtnladdr; - struct nl_addr *nladdr; - struct in6_addr *addr; - NMIP6Address *ip6addr; - struct rtnl_route *rtnlroute; - struct nl_addr *nldest, *nlgateway; - const struct in6_addr *dest, *gateway; - uint32_t metric; - NMIP6Route *ip6route; - int i; - - g_return_val_if_fail (NM_IS_IP6_MANAGER (manager), NULL); - g_return_val_if_fail (ifindex > 0, NULL); - - priv = NM_IP6_MANAGER_GET_PRIVATE (manager); - - device = (NMIP6Device *) g_hash_table_lookup (priv->devices, - GINT_TO_POINTER (ifindex)); - if (!device) { - nm_log_warn (LOGD_IP6, "(%d): addrconf not started.", ifindex); - return NULL; - } - - config = nm_ip6_config_new (); - if (!config) { - nm_log_err (LOGD_IP6, "(%s): out of memory creating IP6 config object.", - device->iface); - return NULL; - } - - /* Make sure we refill the route and address caches, otherwise we won't get - * up-to-date information here since the netlink route/addr change messages - * may be lagging a bit. - */ - nl_cache_refill (priv->nlh, priv->route_cache); - nl_cache_refill (priv->nlh, priv->addr_cache); - - /* Add routes */ - for (rtnlroute = FIRST_ROUTE (priv->route_cache); rtnlroute; rtnlroute = NEXT_ROUTE (rtnlroute)) { - /* Make sure it's an IPv6 route for this device */ - if (rtnl_route_get_oif (rtnlroute) != device->ifindex) - continue; - if (rtnl_route_get_family (rtnlroute) != AF_INET6) - continue; - - /* And ignore cache/cloned routes as they aren't part of the interface's - * permanent routing configuration. - */ - if (rtnl_route_get_flags (rtnlroute) & RTM_F_CLONED) - continue; - - nldest = rtnl_route_get_dst (rtnlroute); - if (!nldest || nl_addr_get_family (nldest) != AF_INET6) - continue; - dest = nl_addr_get_binary_addr (nldest); - - nlgateway = rtnl_route_get_gateway (rtnlroute); - if (!nlgateway || nl_addr_get_family (nlgateway) != AF_INET6) - continue; - gateway = nl_addr_get_binary_addr (nlgateway); - - if (rtnl_route_get_dst_len (rtnlroute) == 0) { - /* Default gateway route; cache the router's address for later */ - if (!nm_ip6_config_get_gateway (config)) - nm_ip6_config_set_gateway (config, gateway); - continue; - } - - /* Also ignore link-local routes where the destination and gateway are - * the same, which apparently get added by the kernel but return -EINVAL - * when we try to add them via netlink. - */ - if (gateway && IN6_ARE_ADDR_EQUAL (dest, gateway)) - continue; - - ip6route = nm_ip6_route_new (); - nm_ip6_route_set_dest (ip6route, dest); - nm_ip6_route_set_prefix (ip6route, rtnl_route_get_dst_len (rtnlroute)); - nm_ip6_route_set_next_hop (ip6route, gateway); - rtnl_route_get_metric(rtnlroute, 1, &metric); - if (metric != UINT_MAX) - nm_ip6_route_set_metric (ip6route, metric); - nm_ip6_config_take_route (config, ip6route); - } - - /* Add addresses */ - for (rtnladdr = FIRST_ADDR (priv->addr_cache); rtnladdr; rtnladdr = NEXT_ADDR (rtnladdr)) { - if (rtnl_addr_get_ifindex (rtnladdr) != device->ifindex) - continue; - - nladdr = rtnl_addr_get_local (rtnladdr); - if (!nladdr || nl_addr_get_family (nladdr) != AF_INET6) - continue; - - addr = nl_addr_get_binary_addr (nladdr); - ip6addr = nm_ip6_address_new (); - nm_ip6_address_set_prefix (ip6addr, rtnl_addr_get_prefixlen (rtnladdr)); - nm_ip6_address_set_address (ip6addr, addr); - nm_ip6_config_take_address (config, ip6addr); - gateway = nm_ip6_config_get_gateway (config); - if (gateway) - nm_ip6_address_set_gateway (ip6addr, gateway); - } - - /* Add DNS servers */ - if (device->rdnss_servers) { - NMIP6RDNSS *rdnss = (NMIP6RDNSS *)(device->rdnss_servers->data); - - for (i = 0; i < device->rdnss_servers->len; i++) - nm_ip6_config_add_nameserver (config, &rdnss[i].addr); - } - - /* Add DNS domains */ - if (device->dnssl_domains) { - NMIP6DNSSL *dnssl = (NMIP6DNSSL *)(device->dnssl_domains->data); - - for (i = 0; i < device->dnssl_domains->len; i++) - nm_ip6_config_add_domain (config, dnssl[i].domain); - } - - return config; -} - -/******************************************************************/ - -static NMIP6Manager * -nm_ip6_manager_new (void) -{ - NMIP6Manager *manager; - NMIP6ManagerPrivate *priv; - - manager = g_object_new (NM_TYPE_IP6_MANAGER, NULL); - priv = NM_IP6_MANAGER_GET_PRIVATE (manager); - - if (!priv->devices) { - nm_log_err (LOGD_IP6, "not enough memory to initialize IP6 manager tables"); - g_object_unref (manager); - manager = NULL; - } - - return manager; -} - -static NMIP6Manager *singleton = NULL; - -NMIP6Manager * -nm_ip6_manager_get (void) -{ - if (!singleton) { - singleton = nm_ip6_manager_new (); - g_assert (singleton); - } else - g_object_ref (singleton); - - return singleton; -} - -static void -nm_ip6_manager_init (NMIP6Manager *manager) -{ - NMIP6ManagerPrivate *priv = NM_IP6_MANAGER_GET_PRIVATE (manager); - - priv->devices = g_hash_table_new_full (g_direct_hash, g_direct_equal, - NULL, - (GDestroyNotify) nm_ip6_device_destroy); - - priv->monitor = nm_netlink_monitor_get (); - nm_netlink_monitor_subscribe (priv->monitor, RTNLGRP_IPV6_IFADDR, NULL); - nm_netlink_monitor_subscribe (priv->monitor, RTNLGRP_IPV6_PREFIX, NULL); - nm_netlink_monitor_subscribe (priv->monitor, RTNLGRP_IPV6_ROUTE, NULL); - nm_netlink_monitor_subscribe (priv->monitor, RTNLGRP_ND_USEROPT, NULL); - nm_netlink_monitor_subscribe (priv->monitor, RTNLGRP_LINK, NULL); - - priv->netlink_id = g_signal_connect (priv->monitor, "notification", - G_CALLBACK (netlink_notification), manager); - - priv->nlh = nm_netlink_get_default_handle (); - rtnl_addr_alloc_cache (priv->nlh, &priv->addr_cache); - g_warn_if_fail (priv->addr_cache != NULL); - rtnl_route_alloc_cache (priv->nlh, NETLINK_ROUTE, NL_AUTO_PROVIDE, &priv->route_cache); - g_warn_if_fail (priv->route_cache != NULL); -} - -static void -finalize (GObject *object) -{ - NMIP6ManagerPrivate *priv = NM_IP6_MANAGER_GET_PRIVATE (object); - - g_signal_handler_disconnect (priv->monitor, priv->netlink_id); - - g_hash_table_destroy (priv->devices); - g_object_unref (priv->monitor); - nl_cache_free (priv->addr_cache); - nl_cache_free (priv->route_cache); - - singleton = NULL; - - G_OBJECT_CLASS (nm_ip6_manager_parent_class)->finalize (object); -} - -static void -nm_ip6_manager_class_init (NMIP6ManagerClass *manager_class) -{ - GObjectClass *object_class = G_OBJECT_CLASS (manager_class); - - g_type_class_add_private (manager_class, sizeof (NMIP6ManagerPrivate)); - - /* virtual methods */ - object_class->finalize = finalize; - - /* signals */ - signals[ADDRCONF_COMPLETE] = - g_signal_new ("addrconf-complete", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMIP6ManagerClass, addrconf_complete), - NULL, NULL, - _nm_marshal_VOID__INT_UINT_BOOLEAN, - G_TYPE_NONE, 3, G_TYPE_INT, G_TYPE_UINT, G_TYPE_BOOLEAN); - - signals[CONFIG_CHANGED] = - g_signal_new ("config-changed", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMIP6ManagerClass, config_changed), - NULL, NULL, - _nm_marshal_VOID__INT_UINT_BOOLEAN, - G_TYPE_NONE, 3, G_TYPE_INT, G_TYPE_UINT, G_TYPE_BOOLEAN); -} - diff --git a/src/ip6-manager/nm-ip6-manager.h b/src/ip6-manager/nm-ip6-manager.h deleted file mode 100644 index 886399f7..00000000 --- a/src/ip6-manager/nm-ip6-manager.h +++ /dev/null @@ -1,88 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* nm-ip6-manager.c - Handle IPv6 address configuration for NetworkManager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2009 - 2010 Red Hat, Inc. - */ - -#ifndef NM_IP6_MANAGER_H -#define NM_IP6_MANAGER_H - -#include -#include - -#include - -#include "nm-ip6-config.h" - -#define NM_TYPE_IP6_MANAGER (nm_ip6_manager_get_type ()) -#define NM_IP6_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_IP6_MANAGER, NMIP6Manager)) -#define NM_IP6_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_IP6_MANAGER, NMIP6ManagerClass)) -#define NM_IS_IP6_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_IP6_MANAGER)) -#define NM_IS_IP6_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_IP6_MANAGER)) -#define NM_IP6_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_IP6_MANAGER, NMIP6ManagerClass)) - -enum { - IP6_DHCP_OPT_NONE = 0, - IP6_DHCP_OPT_OTHERCONF, - IP6_DHCP_OPT_MANAGED -}; - -typedef struct { - GObject parent; -} NMIP6Manager; - -typedef struct { - GObjectClass parent; - - /* Signals */ - - /* addrconf_complete is emitted only during initial configuration to indicate - * that the initial configuration is complete. - */ - void (*addrconf_complete) (NMIP6Manager *manager, - guint32 ifindex, - guint dhcp_opts, - gboolean success); - - /* config_changed gets emitted only *after* initial configuration is - * complete; it's like DHCP renew and indicates that the existing config - * of the interface has changed. - */ - void (*config_changed) (NMIP6Manager *manager, - guint32 ifindex, - guint dhcp_opts, - gboolean success); -} NMIP6ManagerClass; - -GType nm_ip6_manager_get_type (void); - -NMIP6Manager *nm_ip6_manager_get (void); -gboolean nm_ip6_manager_prepare_interface (NMIP6Manager *manager, - int ifindex, - const guint8 *hwaddr, - guint hwaddr_len, - NMSettingIP6Config *s_ip6, - const char *accept_ra_path); -void nm_ip6_manager_begin_addrconf (NMIP6Manager *manager, - int ifindex); -void nm_ip6_manager_cancel_addrconf (NMIP6Manager *manager, - int ifindex); - -NMIP6Config * nm_ip6_manager_get_ip6_config (NMIP6Manager *manager, - int ifindex); - -#endif /* NM_IP6_MANAGER_H */ diff --git a/src/logging/Makefile.am b/src/logging/Makefile.am deleted file mode 100644 index e8fe60ee..00000000 --- a/src/logging/Makefile.am +++ /dev/null @@ -1,14 +0,0 @@ -noinst_LTLIBRARIES = libnm-logging.la - -libnm_logging_la_SOURCES = \ - nm-logging.c \ - nm-logging.h - -libnm_logging_la_CPPFLAGS = \ - $(GLIB_CFLAGS) \ - -DLIBEXECDIR=\"$(libexecdir)\" - -libnm_logging_la_LIBADD = \ - -ldl \ - $(GLIB_LIBS) - diff --git a/src/logging/Makefile.in b/src/logging/Makefile.in deleted file mode 100644 index c5192bf0..00000000 --- a/src/logging/Makefile.in +++ /dev/null @@ -1,723 +0,0 @@ -# Makefile.in generated by automake 1.13.4 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994-2013 Free Software Foundation, Inc. - -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ - -VPATH = @srcdir@ -am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' -am__make_running_with_option = \ - case $${target_option-} in \ - ?) ;; \ - *) echo "am__make_running_with_option: internal error: invalid" \ - "target option '$${target_option-}' specified" >&2; \ - exit 1;; \ - esac; \ - has_opt=no; \ - sane_makeflags=$$MAKEFLAGS; \ - if $(am__is_gnu_make); then \ - sane_makeflags=$$MFLAGS; \ - else \ - case $$MAKEFLAGS in \ - *\\[\ \ ]*) \ - bs=\\; \ - sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ - | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ - esac; \ - fi; \ - skip_next=no; \ - strip_trailopt () \ - { \ - flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ - }; \ - for flg in $$sane_makeflags; do \ - test $$skip_next = yes && { skip_next=no; continue; }; \ - case $$flg in \ - *=*|--*) continue;; \ - -*I) strip_trailopt 'I'; skip_next=yes;; \ - -*I?*) strip_trailopt 'I';; \ - -*O) strip_trailopt 'O'; skip_next=yes;; \ - -*O?*) strip_trailopt 'O';; \ - -*l) strip_trailopt 'l'; skip_next=yes;; \ - -*l?*) strip_trailopt 'l';; \ - -[dEDm]) skip_next=yes;; \ - -[JT]) skip_next=yes;; \ - esac; \ - case $$flg in \ - *$$target_option*) has_opt=yes; break;; \ - esac; \ - done; \ - test $$has_opt = yes -am__make_dryrun = (target_option=n; $(am__make_running_with_option)) -am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) -pkgdatadir = $(datadir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkglibexecdir = $(libexecdir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = @build@ -host_triplet = @host@ -subdir = src/logging -DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ - $(top_srcdir)/build-aux/depcomp -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \ - $(top_srcdir)/m4/gettext.m4 \ - $(top_srcdir)/m4/gnome-code-coverage.m4 \ - $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ - $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \ - $(top_srcdir)/m4/introspection.m4 $(top_srcdir)/m4/lib-ld.m4 \ - $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ - $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ - $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ - $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ - $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ - $(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -mkinstalldirs = $(install_sh) -d -CONFIG_HEADER = $(top_builddir)/config.h -CONFIG_CLEAN_FILES = -CONFIG_CLEAN_VPATH_FILES = -LTLIBRARIES = $(noinst_LTLIBRARIES) -am__DEPENDENCIES_1 = -libnm_logging_la_DEPENDENCIES = $(am__DEPENDENCIES_1) -am_libnm_logging_la_OBJECTS = libnm_logging_la-nm-logging.lo -libnm_logging_la_OBJECTS = $(am_libnm_logging_la_OBJECTS) -AM_V_lt = $(am__v_lt_@AM_V@) -am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) -am__v_lt_0 = --silent -am__v_lt_1 = -AM_V_P = $(am__v_P_@AM_V@) -am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) -am__v_P_0 = false -am__v_P_1 = : -AM_V_GEN = $(am__v_GEN_@AM_V@) -am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) -am__v_GEN_0 = @echo " GEN " $@; -am__v_GEN_1 = -AM_V_at = $(am__v_at_@AM_V@) -am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) -am__v_at_0 = @ -am__v_at_1 = -DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) -depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp -am__depfiles_maybe = depfiles -am__mv = mv -f -COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ - $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ - $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ - $(AM_CFLAGS) $(CFLAGS) -AM_V_CC = $(am__v_CC_@AM_V@) -am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) -am__v_CC_0 = @echo " CC " $@; -am__v_CC_1 = -CCLD = $(CC) -LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(AM_LDFLAGS) $(LDFLAGS) -o $@ -AM_V_CCLD = $(am__v_CCLD_@AM_V@) -am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) -am__v_CCLD_0 = @echo " CCLD " $@; -am__v_CCLD_1 = -SOURCES = $(libnm_logging_la_SOURCES) -DIST_SOURCES = $(libnm_logging_la_SOURCES) -am__can_run_installinfo = \ - case $$AM_UPDATE_INFO_DIR in \ - n|no|NO) false;; \ - *) (install-info --version) >/dev/null 2>&1;; \ - esac -am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) -# Read a list of newline-separated strings from the standard input, -# and print each of them once, without duplicates. Input order is -# *not* preserved. -am__uniquify_input = $(AWK) '\ - BEGIN { nonempty = 0; } \ - { items[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in items) print i; }; } \ -' -# Make sure the list of sources is unique. This is necessary because, -# e.g., the same source file might be shared among _SOURCES variables -# for different programs/libraries. -am__define_uniq_tagged_files = \ - list='$(am__tagged_files)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | $(am__uniquify_input)` -ETAGS = etags -CTAGS = ctags -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -ALL_LINGUAS = @ALL_LINGUAS@ -AMTAR = @AMTAR@ -AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -AR = @AR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CKDB_PATH = @CKDB_PATH@ -CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@ -CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@ -CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CXX = @CXX@ -CXXCPP = @CXXCPP@ -CXXDEPMODE = @CXXDEPMODE@ -CXXFLAGS = @CXXFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DATADIRNAME = @DATADIRNAME@ -DBUS_CFLAGS = @DBUS_CFLAGS@ -DBUS_LIBS = @DBUS_LIBS@ -DBUS_SYS_DIR = @DBUS_SYS_DIR@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -DHCLIENT_PATH = @DHCLIENT_PATH@ -DHCPCD_PATH = @DHCPCD_PATH@ -DLLTOOL = @DLLTOOL@ -DNSMASQ_PATH = @DNSMASQ_PATH@ -DSYMUTIL = @DSYMUTIL@ -DUMPBIN = @DUMPBIN@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -FGREP = @FGREP@ -GENHTML = @GENHTML@ -GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ -GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ -GLIB_CFLAGS = @GLIB_CFLAGS@ -GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ -GLIB_LIBS = @GLIB_LIBS@ -GLIB_MAKEFILE = @GLIB_MAKEFILE@ -GLIB_MKENUMS = @GLIB_MKENUMS@ -GMSGFMT = @GMSGFMT@ -GMSGFMT_015 = @GMSGFMT_015@ -GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ -GNUTLS_LIBS = @GNUTLS_LIBS@ -GREP = @GREP@ -GTKDOC_CHECK = @GTKDOC_CHECK@ -GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ -GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ -GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ -GTKDOC_MKPDF = @GTKDOC_MKPDF@ -GTKDOC_REBASE = @GTKDOC_REBASE@ -GUDEV_CFLAGS = @GUDEV_CFLAGS@ -GUDEV_LIBS = @GUDEV_LIBS@ -HTML_DIR = @HTML_DIR@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -INTLLIBS = @INTLLIBS@ -INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ -INTLTOOL_MERGE = @INTLTOOL_MERGE@ -INTLTOOL_PERL = @INTLTOOL_PERL@ -INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ -INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ -INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ -INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ -INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ -INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ -INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ -INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ -INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ -INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ -INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ -INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ -INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ -INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ -IPTABLES_PATH = @IPTABLES_PATH@ -IWMX_SDK_CFLAGS = @IWMX_SDK_CFLAGS@ -IWMX_SDK_LIBS = @IWMX_SDK_LIBS@ -KERNEL_FIRMWARE_DIR = @KERNEL_FIRMWARE_DIR@ -LCOV = @LCOV@ -LD = @LD@ -LDFLAGS = @LDFLAGS@ -LIBDL = @LIBDL@ -LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ -LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ -LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ -LIBICONV = @LIBICONV@ -LIBINTL = @LIBINTL@ -LIBM = @LIBM@ -LIBNL_CFLAGS = @LIBNL_CFLAGS@ -LIBNL_LIBS = @LIBNL_LIBS@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@ -LIBSOUP_LIBS = @LIBSOUP_LIBS@ -LIBTOOL = @LIBTOOL@ -LIPO = @LIPO@ -LN_S = @LN_S@ -LTLIBICONV = @LTLIBICONV@ -LTLIBINTL = @LTLIBINTL@ -LTLIBOBJS = @LTLIBOBJS@ -MAINT = @MAINT@ -MAKEINFO = @MAKEINFO@ -MANIFEST_TOOL = @MANIFEST_TOOL@ -MKDIR_P = @MKDIR_P@ -MM_GLIB_CFLAGS = @MM_GLIB_CFLAGS@ -MM_GLIB_LIBS = @MM_GLIB_LIBS@ -MOC = @MOC@ -MSGFMT = @MSGFMT@ -MSGFMT_015 = @MSGFMT_015@ -MSGMERGE = @MSGMERGE@ -NM = @NM@ -NMEDIT = @NMEDIT@ -NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ -NM_MICRO_VERSION = @NM_MICRO_VERSION@ -NM_MINOR_VERSION = @NM_MINOR_VERSION@ -NM_MODIFY_SYSTEM_POLICY = @NM_MODIFY_SYSTEM_POLICY@ -NM_VERSION = @NM_VERSION@ -NSS_CFLAGS = @NSS_CFLAGS@ -NSS_LIBS = @NSS_LIBS@ -OBJDUMP = @OBJDUMP@ -OBJEXT = @OBJEXT@ -OTOOL = @OTOOL@ -OTOOL64 = @OTOOL64@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_URL = @PACKAGE_URL@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PKG_CONFIG = @PKG_CONFIG@ -PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ -PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ -POLKIT_CFLAGS = @POLKIT_CFLAGS@ -POLKIT_LIBS = @POLKIT_LIBS@ -POSUB = @POSUB@ -PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@ -QT_CFLAGS = @QT_CFLAGS@ -QT_LIBS = @QT_LIBS@ -RANLIB = @RANLIB@ -SED = @SED@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -STRIP = @STRIP@ -SYSTEMD_200_CFLAGS = @SYSTEMD_200_CFLAGS@ -SYSTEMD_200_LIBS = @SYSTEMD_200_LIBS@ -SYSTEMD_INHIBIT_CFLAGS = @SYSTEMD_INHIBIT_CFLAGS@ -SYSTEMD_INHIBIT_LIBS = @SYSTEMD_INHIBIT_LIBS@ -SYSTEMD_LOGIN_CFLAGS = @SYSTEMD_LOGIN_CFLAGS@ -SYSTEMD_LOGIN_LIBS = @SYSTEMD_LOGIN_LIBS@ -SYSTEM_CA_PATH = @SYSTEM_CA_PATH@ -UDEV_BASE_DIR = @UDEV_BASE_DIR@ -USE_NLS = @USE_NLS@ -UUID_CFLAGS = @UUID_CFLAGS@ -UUID_LIBS = @UUID_LIBS@ -VAPIGEN = @VAPIGEN@ -VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ -VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ -VERSION = @VERSION@ -XGETTEXT = @XGETTEXT@ -XGETTEXT_015 = @XGETTEXT_015@ -XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_AR = @ac_ct_AR@ -ac_ct_CC = @ac_ct_CC@ -ac_ct_CXX = @ac_ct_CXX@ -ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -intltool__v_merge_options_ = @intltool__v_merge_options_@ -intltool__v_merge_options_0 = @intltool__v_merge_options_0@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -nmbinary = @nmbinary@ -nmconfdir = @nmconfdir@ -nmdatadir = @nmdatadir@ -nmrundir = @nmrundir@ -nmstatedir = @nmstatedir@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -sysconfdir = @sysconfdir@ -systemdsystemunitdir = @systemdsystemunitdir@ -target_alias = @target_alias@ -top_build_prefix = @top_build_prefix@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -with_dhclient = @with_dhclient@ -with_dhcpcd = @with_dhcpcd@ -with_netconfig = @with_netconfig@ -with_resolvconf = @with_resolvconf@ -noinst_LTLIBRARIES = libnm-logging.la -libnm_logging_la_SOURCES = \ - nm-logging.c \ - nm-logging.h - -libnm_logging_la_CPPFLAGS = \ - $(GLIB_CFLAGS) \ - -DLIBEXECDIR=\"$(libexecdir)\" - -libnm_logging_la_LIBADD = \ - -ldl \ - $(GLIB_LIBS) - -all: all-am - -.SUFFIXES: -.SUFFIXES: .c .lo .o .obj -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ - && { if test -f $@; then exit 0; else break; fi; }; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/logging/Makefile'; \ - $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --gnu src/logging/Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(am__aclocal_m4_deps): - -clean-noinstLTLIBRARIES: - -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) - @list='$(noinst_LTLIBRARIES)'; \ - locs=`for p in $$list; do echo $$p; done | \ - sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ - sort -u`; \ - test -z "$$locs" || { \ - echo rm -f $${locs}; \ - rm -f $${locs}; \ - } - -libnm-logging.la: $(libnm_logging_la_OBJECTS) $(libnm_logging_la_DEPENDENCIES) $(EXTRA_libnm_logging_la_DEPENDENCIES) - $(AM_V_CCLD)$(LINK) $(libnm_logging_la_OBJECTS) $(libnm_logging_la_LIBADD) $(LIBS) - -mostlyclean-compile: - -rm -f *.$(OBJEXT) - -distclean-compile: - -rm -f *.tab.c - -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_logging_la-nm-logging.Plo@am__quote@ - -.c.o: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< - -.c.obj: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` - -.c.lo: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< - -libnm_logging_la-nm-logging.lo: nm-logging.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_logging_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_logging_la-nm-logging.lo -MD -MP -MF $(DEPDIR)/libnm_logging_la-nm-logging.Tpo -c -o libnm_logging_la-nm-logging.lo `test -f 'nm-logging.c' || echo '$(srcdir)/'`nm-logging.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnm_logging_la-nm-logging.Tpo $(DEPDIR)/libnm_logging_la-nm-logging.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-logging.c' object='libnm_logging_la-nm-logging.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_logging_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_logging_la-nm-logging.lo `test -f 'nm-logging.c' || echo '$(srcdir)/'`nm-logging.c - -mostlyclean-libtool: - -rm -f *.lo - -clean-libtool: - -rm -rf .libs _libs - -ID: $(am__tagged_files) - $(am__define_uniq_tagged_files); mkid -fID $$unique -tags: tags-am -TAGS: tags - -tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) - set x; \ - here=`pwd`; \ - $(am__define_uniq_tagged_files); \ - shift; \ - if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ - test -n "$$unique" || unique=$$empty_fix; \ - if test $$# -gt 0; then \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - "$$@" $$unique; \ - else \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$unique; \ - fi; \ - fi -ctags: ctags-am - -CTAGS: ctags -ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) - $(am__define_uniq_tagged_files); \ - test -z "$(CTAGS_ARGS)$$unique" \ - || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$unique - -GTAGS: - here=`$(am__cd) $(top_builddir) && pwd` \ - && $(am__cd) $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) "$$here" -cscopelist: cscopelist-am - -cscopelist-am: $(am__tagged_files) - list='$(am__tagged_files)'; \ - case "$(srcdir)" in \ - [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ - *) sdir=$(subdir)/$(srcdir) ;; \ - esac; \ - for i in $$list; do \ - if test -f "$$i"; then \ - echo "$(subdir)/$$i"; \ - else \ - echo "$$sdir/$$i"; \ - fi; \ - done >> $(top_builddir)/cscope.files - -distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags - -distdir: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d "$(distdir)/$$file"; then \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ - else \ - test -f "$(distdir)/$$file" \ - || cp -p $$d/$$file "$(distdir)/$$file" \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: check-am -all-am: Makefile $(LTLIBRARIES) -installdirs: -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - if test -z '$(STRIP)'; then \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - install; \ - else \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ - fi -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." -clean: clean-am - -clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ - mostlyclean-am - -distclean: distclean-am - -rm -rf ./$(DEPDIR) - -rm -f Makefile -distclean-am: clean-am distclean-compile distclean-generic \ - distclean-tags - -dvi: dvi-am - -dvi-am: - -html: html-am - -html-am: - -info: info-am - -info-am: - -install-data-am: - -install-dvi: install-dvi-am - -install-dvi-am: - -install-exec-am: - -install-html: install-html-am - -install-html-am: - -install-info: install-info-am - -install-info-am: - -install-man: - -install-pdf: install-pdf-am - -install-pdf-am: - -install-ps: install-ps-am - -install-ps-am: - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -rf ./$(DEPDIR) - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-compile mostlyclean-generic \ - mostlyclean-libtool - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: - -.MAKE: install-am install-strip - -.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ - clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ - ctags-am distclean distclean-compile distclean-generic \ - distclean-libtool distclean-tags distdir dvi dvi-am html \ - html-am info info-am install install-am install-data \ - install-data-am install-dvi install-dvi-am install-exec \ - install-exec-am install-html install-html-am install-info \ - install-info-am install-man install-pdf install-pdf-am \ - install-ps install-ps-am install-strip installcheck \ - installcheck-am installdirs maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-compile \ - mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ - tags tags-am uninstall uninstall-am - - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/src/logging/nm-logging.c b/src/logging/nm-logging.c index 79d47f13..1577f6ec 100644 --- a/src/logging/nm-logging.c +++ b/src/logging/nm-logging.c @@ -36,31 +36,40 @@ #include "nm-logging.h" +static void +nm_log_handler (const gchar *log_domain, + GLogLevelFlags level, + const gchar *message, + gpointer ignored); + #define LOGD_ALL \ (LOGD_PLATFORM | LOGD_RFKILL | LOGD_ETHER | LOGD_WIFI | LOGD_BT | LOGD_MB | \ LOGD_DHCP4 | LOGD_DHCP6 | LOGD_PPP | LOGD_WIFI_SCAN | LOGD_IP4 | \ LOGD_IP6 | LOGD_AUTOIP4 | LOGD_DNS | LOGD_VPN | LOGD_SHARING | \ LOGD_SUPPLICANT | LOGD_AGENTS | LOGD_SETTINGS | LOGD_SUSPEND | \ - LOGD_CORE | LOGD_DEVICE | LOGD_OLPC_MESH | LOGD_WIMAX | \ + LOGD_CORE | LOGD_DEVICE | LOGD_OLPC | LOGD_WIMAX | \ LOGD_INFINIBAND | LOGD_FIREWALL | LOGD_ADSL | LOGD_BOND | \ - LOGD_VLAN | LOGD_BRIDGE | LOGD_CONCHECK) + LOGD_VLAN | LOGD_BRIDGE | LOGD_DBUS_PROPS | LOGD_TEAM | LOGD_CONCHECK | \ + LOGD_DCB | LOGD_DISPATCH) -#define LOGD_DEFAULT (LOGD_ALL & ~LOGD_WIFI_SCAN) +#define LOGD_DEFAULT (LOGD_ALL & ~(LOGD_WIFI_SCAN | LOGD_DBUS_PROPS)) -static guint32 log_level = LOGL_INFO | LOGL_WARN | LOGL_ERR; -static guint32 log_domains = LOGD_DEFAULT; +static guint32 log_level = LOGL_INFO; +static char *log_domains; +static guint64 logging[LOGL_MAX]; +static gboolean logging_set_up; +static gboolean syslog_opened; typedef struct { - guint32 num; + guint64 num; const char *name; } LogDesc; -static const LogDesc level_descs[] = { - { LOGL_ERR, "ERR" }, - { LOGL_WARN | LOGL_ERR, "WARN" }, - { LOGL_INFO | LOGL_WARN | LOGL_ERR, "INFO" }, - { LOGL_DEBUG | LOGL_INFO | LOGL_WARN | LOGL_ERR, "DEBUG" }, - { 0, NULL } +static const char *level_names[LOGL_MAX] = { + [LOGL_DEBUG] = "DEBUG", + [LOGL_INFO] = "INFO", + [LOGL_WARN] = "WARN", + [LOGL_ERR] = "ERR", }; static const LogDesc domain_descs[] = { @@ -87,7 +96,7 @@ static const LogDesc domain_descs[] = { { LOGD_SUSPEND, "SUSPEND" }, { LOGD_CORE, "CORE" }, { LOGD_DEVICE, "DEVICE" }, - { LOGD_OLPC_MESH, "OLPC" }, + { LOGD_OLPC, "OLPC" }, { LOGD_WIMAX, "WIMAX" }, { LOGD_INFINIBAND,"INFINIBAND" }, { LOGD_FIREWALL, "FIREWALL" }, @@ -95,7 +104,11 @@ static const LogDesc domain_descs[] = { { LOGD_BOND, "BOND" }, { LOGD_VLAN, "VLAN" }, { LOGD_BRIDGE, "BRIDGE" }, + { LOGD_DBUS_PROPS,"DBUS_PROPS" }, + { LOGD_TEAM, "TEAM" }, { LOGD_CONCHECK, "CONCHECK" }, + { LOGD_DCB, "DCB" }, + { LOGD_DISPATCH, "DISPATCH" }, { 0, NULL } }; @@ -119,95 +132,157 @@ nm_logging_error_quark (void) /************************************************************************/ +static gboolean +match_log_level (const char *level, + guint32 *out_level, + GError **error) +{ + int i; + + for (i = 0; i < LOGL_MAX; i++) { + if (!g_ascii_strcasecmp (level_names[i], level)) { + *out_level = i; + return TRUE; + } + } + + g_set_error (error, NM_LOGGING_ERROR, NM_LOGGING_ERROR_UNKNOWN_LEVEL, + _("Unknown log level '%s'"), level); + return FALSE; +} + gboolean -nm_logging_setup (const char *level, const char *domains, GError **error) +nm_logging_setup (const char *level, + const char *domains, + char **bad_domains, + GError **error) { + GString *unrecognized = NULL; + guint64 new_logging[LOGL_MAX]; + guint32 new_log_level = log_level; char **tmp, **iter; - guint32 new_domains = 0; + int i; - /* levels */ - if (level && strlen (level)) { - gboolean found = FALSE; - const LogDesc *diter; + logging_set_up = TRUE; - for (diter = &level_descs[0]; diter->name; diter++) { - if (!strcasecmp (diter->name, level)) { - log_level = diter->num; - found = TRUE; - break; - } - } + for (i = 0; i < LOGL_MAX; i++) + new_logging[i] = 0; - if (!found) { - g_set_error (error, NM_LOGGING_ERROR, NM_LOGGING_ERROR_UNKNOWN_LEVEL, - _("Unknown log level '%s'"), level); + /* levels */ + if (level && *level) { + if (!match_log_level (level, &new_log_level, error)) return FALSE; - } } /* domains */ - if (domains && strlen (domains)) { - tmp = g_strsplit_set (domains, ", ", 0); - for (iter = tmp; iter && *iter; iter++) { - const LogDesc *diter; - gboolean found = FALSE; - - if (!strlen (*iter)) - continue; + if (!domains || !*domains) + domains = log_domains ? log_domains : "DEFAULT"; + tmp = g_strsplit_set (domains, ", ", 0); + for (iter = tmp; iter && *iter; iter++) { + const LogDesc *diter; + guint32 domain_log_level; + guint64 bits; + char *p; + + if (!strlen (*iter)) + continue; + + p = strchr (*iter, ':'); + if (p) { + *p = '\0'; + if (!match_log_level (p + 1, &domain_log_level, error)) { + g_strfreev (tmp); + return FALSE; + } + } else + domain_log_level = new_log_level; + + bits = 0; + + /* Check for combined domains */ + if (!g_ascii_strcasecmp (*iter, LOGD_ALL_STRING)) + bits = LOGD_ALL; + else if (!g_ascii_strcasecmp (*iter, LOGD_DEFAULT_STRING)) + bits = LOGD_DEFAULT; + else if (!g_ascii_strcasecmp (*iter, LOGD_DHCP_STRING)) + bits = LOGD_DHCP; + else if (!g_ascii_strcasecmp (*iter, LOGD_IP_STRING)) + bits = LOGD_IP; + + /* Check for compatibility domains */ + else if (!g_ascii_strcasecmp (*iter, "HW")) + bits = LOGD_PLATFORM; + + else { for (diter = &domain_descs[0]; diter->name; diter++) { - if (!strcasecmp (diter->name, *iter)) { - new_domains |= diter->num; - found = TRUE; + if (!g_ascii_strcasecmp (diter->name, *iter)) { + bits = diter->num; break; } } + } - /* Check for combined domains */ - if (!strcasecmp (*iter, LOGD_ALL_STRING)) { - new_domains = LOGD_ALL; - found = TRUE; - } else if (!strcasecmp (*iter, LOGD_DEFAULT_STRING)) { - new_domains = LOGD_DEFAULT; - found = TRUE; - } else if (!strcasecmp (*iter, LOGD_DHCP_STRING)) { - new_domains |= LOGD_DHCP; - found = TRUE; - } else if (!strcasecmp (*iter, LOGD_IP_STRING)) { - new_domains |= LOGD_IP; - found = TRUE; - } - - /* Check for compatibility domains */ - if (!strcasecmp (*iter, "HW")) { - new_domains |= LOGD_PLATFORM; - found = TRUE; - } - - if (!found) { + if (!bits) { + if (!bad_domains) { g_set_error (error, NM_LOGGING_ERROR, NM_LOGGING_ERROR_UNKNOWN_DOMAIN, _("Unknown log domain '%s'"), *iter); return FALSE; } + + if (unrecognized) + g_string_append (unrecognized, ", "); + else + unrecognized = g_string_new (NULL); + g_string_append (unrecognized, *iter); + continue; } - g_strfreev (tmp); - log_domains = new_domains; + + for (i = 0; i < domain_log_level; i++) + new_logging[i] &= ~bits; + for (i = domain_log_level; i < LOGL_MAX; i++) + new_logging[i] |= bits; + } + g_strfreev (tmp); + + if (log_domains != (char *)domains) { + g_free (log_domains); + log_domains = g_strdup (domains); } + log_level = new_log_level; + for (i = 0; i < LOGL_MAX; i++) + logging[i] = new_logging[i]; + + if (unrecognized) + *bad_domains = g_string_free (unrecognized, FALSE); + return TRUE; } -const char * +char * nm_logging_level_to_string (void) { - const LogDesc *diter; + return g_strdup (level_names[log_level]); +} + +const char * +nm_logging_all_levels_to_string (void) +{ + static GString *str; + + if (G_UNLIKELY (!str)) { + int i; - for (diter = &level_descs[0]; diter->name; diter++) { - if (diter->num == log_level) - return diter->name; + str = g_string_new (NULL); + for (i = 0; i < LOGL_MAX; i++) { + if (str->len) + g_string_append_c (str, ','); + g_string_append (str, level_names[i]); + } } - g_warn_if_reached (); - return ""; + + return str->str; } char * @@ -215,61 +290,135 @@ nm_logging_domains_to_string (void) { const LogDesc *diter; GString *str; + int i; + + /* We don't just return g_strdup (log_domains) because we want to expand + * "DEFAULT" and "ALL". + */ str = g_string_sized_new (75); for (diter = &domain_descs[0]; diter->name; diter++) { - if (diter->num & log_domains) { - if (str->len) - g_string_append_c (str, ','); - g_string_append (str, diter->name); + /* If it's set for any lower level, it will also be set for LOGL_ERR */ + if (!(diter->num & logging[LOGL_ERR])) + continue; + + if (str->len) + g_string_append_c (str, ','); + g_string_append (str, diter->name); + + /* Check if it's logging at a lower level than the default. */ + for (i = 0; i < log_level; i++) { + if (diter->num & logging[i]) { + g_string_append_printf (str, ":%s", level_names[i]); + break; + } + } + /* Check if it's logging at a higher level than the default. */ + if (!(diter->num & logging[log_level])) { + for (i = log_level + 1; i < LOGL_MAX; i++) { + if (diter->num & logging[i]) { + g_string_append_printf (str, ":%s", level_names[i]); + break; + } + } } } return g_string_free (str, FALSE); } -gboolean -nm_logging_level_enabled (guint32 level) +const char * +nm_logging_all_domains_to_string (void) { - return !!(log_level & level); + static GString *str; + + if (G_UNLIKELY (!str)) { + const LogDesc *diter; + + str = g_string_new (LOGD_DEFAULT_STRING); + for (diter = &domain_descs[0]; diter->name; diter++) { + g_string_append_c (str, ','); + g_string_append (str, diter->name); + if (diter->num == LOGD_DHCP6) + g_string_append (str, "," LOGD_DHCP_STRING); + else if (diter->num == LOGD_IP6) + g_string_append (str, "," LOGD_IP_STRING); + } + g_string_append (str, "," LOGD_ALL_STRING); + } + + return str->str; } gboolean -nm_logging_domain_enabled (guint32 domain) +nm_logging_enabled (guint32 level, guint64 domain) { - return !!(log_domains & domain); + g_return_val_if_fail (level < LOGL_MAX, FALSE); + + return !!(logging[level] & domain); } void _nm_log (const char *loc, const char *func, - guint32 domain, + guint64 domain, guint32 level, const char *fmt, ...) { va_list args; char *msg; + char *fullmsg = NULL; GTimeVal tv; + int syslog_level = LOG_INFO; + int g_log_level = G_LOG_LEVEL_INFO; - if (!(log_level & level) || !(log_domains & domain)) + g_return_if_fail (level < LOGL_MAX); + + if (G_UNLIKELY (!logging_set_up)) + nm_logging_setup ("INFO", "DEFAULT", NULL, NULL); + + if (!(logging[level] & domain)) return; va_start (args, fmt); msg = g_strdup_vprintf (fmt, args); va_end (args); - if ((log_level & LOGL_DEBUG) && (level == LOGL_DEBUG)) { + switch (level) { + case LOGL_DEBUG: g_get_current_time (&tv); - syslog (LOG_INFO, " [%ld.%ld] [%s] %s(): %s", tv.tv_sec, tv.tv_usec, loc, func, msg); - } else if ((log_level & LOGL_INFO) && (level == LOGL_INFO)) - syslog (LOG_INFO, " %s", msg); - else if ((log_level & LOGL_WARN) && (level == LOGL_WARN)) - syslog (LOG_WARNING, " %s", msg); - else if ((log_level & LOGL_ERR) && (level == LOGL_ERR)) { + syslog_level = LOG_INFO; + g_log_level = G_LOG_LEVEL_DEBUG; + fullmsg = g_strdup_printf (" [%ld.%06ld] [%s] %s(): %s", tv.tv_sec, tv.tv_usec, loc, func, msg); + break; + case LOGL_INFO: + syslog_level = LOG_INFO; + g_log_level = G_LOG_LEVEL_MESSAGE; + fullmsg = g_strconcat (" ", msg, NULL); + break; + case LOGL_WARN: + syslog_level = LOG_WARNING; + g_log_level = G_LOG_LEVEL_WARNING; + fullmsg = g_strconcat (" ", msg, NULL); + break; + case LOGL_ERR: + syslog_level = LOG_ERR; + /* g_log_level is still WARNING, because ERROR is fatal */ + g_log_level = G_LOG_LEVEL_WARNING; g_get_current_time (&tv); - syslog (LOG_ERR, " [%ld.%ld] [%s] %s(): %s", tv.tv_sec, tv.tv_usec, loc, func, msg); + fullmsg = g_strdup_printf (" [%ld.%06ld] [%s] %s(): %s", tv.tv_sec, tv.tv_usec, loc, func, msg); + break; + default: + g_assert_not_reached (); } + + if (syslog_opened) + syslog (syslog_level, "%s", fullmsg); + else + g_log (G_LOG_DOMAIN, g_log_level, "%s", fullmsg); + g_free (msg); + g_free (fullmsg); } /************************************************************************/ @@ -282,7 +431,7 @@ nm_log_handler (const gchar *log_domain, { int syslog_priority; - switch (level) { + switch (level & G_LOG_LEVEL_MASK) { case G_LOG_LEVEL_ERROR: syslog_priority = LOG_CRIT; break; @@ -308,21 +457,26 @@ nm_log_handler (const gchar *log_domain, } void -nm_logging_start (gboolean become_daemon) +nm_logging_syslog_openlog (gboolean debug) { - if (become_daemon) - openlog (G_LOG_DOMAIN, LOG_PID, LOG_DAEMON); - else + if (debug) openlog (G_LOG_DOMAIN, LOG_CONS | LOG_PERROR | LOG_PID, LOG_USER); + else + openlog (G_LOG_DOMAIN, LOG_PID, LOG_DAEMON); - g_log_set_handler (G_LOG_DOMAIN, - G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION, - nm_log_handler, - NULL); + if (!syslog_opened) { + syslog_opened = TRUE; + + g_log_set_handler (G_LOG_DOMAIN, + G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION, + nm_log_handler, + NULL); + } } void -nm_logging_shutdown (void) +nm_logging_syslog_closelog (void) { - closelog (); + if (syslog_opened) + closelog (); } diff --git a/src/logging/nm-logging.h b/src/logging/nm-logging.h index 97b4110d..a53f93a5 100644 --- a/src/logging/nm-logging.h +++ b/src/logging/nm-logging.h @@ -22,43 +22,51 @@ #ifndef NM_LOGGING_H #define NM_LOGGING_H +#ifdef __NM_TEST_UTILS_H__ +#error nm-test-utils.h must be included as last header +#endif + #include #include /* Log domains */ enum { - LOGD_NONE = 0x00000000, - LOGD_PLATFORM = 0x00000001, /* Platform services */ - LOGD_RFKILL = 0x00000002, - LOGD_ETHER = 0x00000004, - LOGD_WIFI = 0x00000008, - LOGD_BT = 0x00000010, - LOGD_MB = 0x00000020, /* mobile broadband */ - LOGD_DHCP4 = 0x00000040, - LOGD_DHCP6 = 0x00000080, - LOGD_PPP = 0x00000100, - LOGD_WIFI_SCAN = 0x00000200, - LOGD_IP4 = 0x00000400, - LOGD_IP6 = 0x00000800, - LOGD_AUTOIP4 = 0x00001000, - LOGD_DNS = 0x00002000, - LOGD_VPN = 0x00004000, - LOGD_SHARING = 0x00008000, /* Connection sharing/dnsmasq */ - LOGD_SUPPLICANT = 0x00010000, /* WiFi and 802.1x */ - LOGD_AGENTS = 0x00020000, /* Secret agents */ - LOGD_SETTINGS = 0x00040000, /* Settings */ - LOGD_SUSPEND = 0x00080000, /* Suspend/Resume */ - LOGD_CORE = 0x00100000, /* Core daemon and policy stuff */ - LOGD_DEVICE = 0x00200000, /* Device state and activation */ - LOGD_OLPC_MESH = 0x00400000, - LOGD_WIMAX = 0x00800000, - LOGD_INFINIBAND = 0x01000000, - LOGD_FIREWALL = 0x02000000, - LOGD_ADSL = 0x04000000, - LOGD_BOND = 0x08000000, - LOGD_VLAN = 0x10000000, - LOGD_BRIDGE = 0x20000000, - LOGD_CONCHECK = 0x40000000 + LOGD_NONE = 0LL, + LOGD_PLATFORM = (1LL << 1), /* Platform services */ + LOGD_RFKILL = (1LL << 2), + LOGD_ETHER = (1LL << 3), + LOGD_WIFI = (1LL << 4), + LOGD_BT = (1LL << 5), + LOGD_MB = (1LL << 6), /* mobile broadband */ + LOGD_DHCP4 = (1LL << 7), + LOGD_DHCP6 = (1LL << 8), + LOGD_PPP = (1LL << 9), + LOGD_WIFI_SCAN = (1LL << 10), + LOGD_IP4 = (1LL << 11), + LOGD_IP6 = (1LL << 12), + LOGD_AUTOIP4 = (1LL << 13), + LOGD_DNS = (1LL << 14), + LOGD_VPN = (1LL << 15), + LOGD_SHARING = (1LL << 16), /* Connection sharing/dnsmasq */ + LOGD_SUPPLICANT = (1LL << 17), /* WiFi and 802.1x */ + LOGD_AGENTS = (1LL << 18), /* Secret agents */ + LOGD_SETTINGS = (1LL << 19), /* Settings */ + LOGD_SUSPEND = (1LL << 20), /* Suspend/Resume */ + LOGD_CORE = (1LL << 21), /* Core daemon and policy stuff */ + LOGD_DEVICE = (1LL << 22), /* Device state and activation */ + LOGD_OLPC = (1LL << 23), + LOGD_WIMAX = (1LL << 24), + LOGD_INFINIBAND = (1LL << 25), + LOGD_FIREWALL = (1LL << 26), + LOGD_ADSL = (1LL << 27), + LOGD_BOND = (1LL << 28), + LOGD_VLAN = (1LL << 29), + LOGD_BRIDGE = (1LL << 30), + LOGD_DBUS_PROPS = (1LL << 31), + LOGD_TEAM = (1LL << 32), + LOGD_CONCHECK = (1LL << 33), + LOGD_DCB = (1LL << 34), /* Data Center Bridging */ + LOGD_DISPATCH = (1LL << 35), }; #define LOGD_DHCP (LOGD_DHCP4 | LOGD_DHCP6) @@ -67,10 +75,12 @@ enum { /* Log levels */ enum { - LOGL_ERR = 0x00000001, - LOGL_WARN = 0x00000002, - LOGL_INFO = 0x00000004, - LOGL_DEBUG = 0x00000008 + LOGL_DEBUG, + LOGL_INFO, + LOGL_WARN, + LOGL_ERR, + + LOGL_MAX }; typedef enum { @@ -99,15 +109,17 @@ GQuark nm_logging_error_quark (void); void _nm_log (const char *loc, const char *func, - guint32 domain, + guint64 domain, guint32 level, const char *fmt, ...) __attribute__((__format__ (__printf__, 5, 6))); -const char *nm_logging_level_to_string (void); +char *nm_logging_level_to_string (void); char *nm_logging_domains_to_string (void); -gboolean nm_logging_level_enabled (guint32 level); -gboolean nm_logging_domain_enabled (guint32 domain); +gboolean nm_logging_enabled (guint32 level, guint64 domain); + +const char *nm_logging_all_levels_to_string (void); +const char *nm_logging_all_domains_to_string (void); /* Undefine the nm-utils.h logging stuff to ensure errors */ #undef nm_get_timestamp @@ -120,8 +132,11 @@ gboolean nm_logging_domain_enabled (guint32 domain); #undef nm_error #undef nm_error_str -gboolean nm_logging_setup (const char *level, const char *domains, GError **error); -void nm_logging_start (gboolean become_daemon); -void nm_logging_shutdown (void); +gboolean nm_logging_setup (const char *level, + const char *domains, + char **bad_domains, + GError **error); +void nm_logging_syslog_openlog (gboolean debug); +void nm_logging_syslog_closelog (void); #endif /* NM_LOGGING_H */ diff --git a/src/main.c b/src/main.c index eb829a7b..0ba65b0b 100644 --- a/src/main.c +++ b/src/main.c @@ -37,23 +37,24 @@ #include #include #include +#include +#include "libgsystem.h" #include "NetworkManager.h" #include "NetworkManagerUtils.h" #include "nm-manager.h" +#include "nm-linux-platform.h" #include "nm-dns-manager.h" #include "nm-dbus-manager.h" #include "nm-supplicant-manager.h" #include "nm-dhcp-manager.h" #include "nm-firewall-manager.h" -#include "nm-hostname-provider.h" -#include "nm-netlink-monitor.h" #include "nm-vpn-manager.h" #include "nm-logging.h" -#include "nm-policy-hosts.h" #include "nm-config.h" #include "nm-posix-signals.h" -#include "nm-system.h" +#include "nm-session-monitor.h" +#include "nm-dispatcher.h" #if !defined(NM_DIST_VERSION) # define NM_DIST_VERSION VERSION @@ -65,7 +66,6 @@ /* * Globals */ -static NMManager *manager = NULL; static GMainLoop *main_loop = NULL; static gboolean quit_early = FALSE; static sigset_t signal_set; @@ -154,7 +154,7 @@ write_pidfile (const char *pidfile) return FALSE; } - snprintf (pid, sizeof (pid), "%d", getpid ()); + g_snprintf (pid, sizeof (pid), "%d", getpid ()); if (write (fd, pid, strlen (pid)) < 0) fprintf (stderr, _("Writing to %s failed: %s\n"), pidfile, strerror (errno)); else @@ -233,12 +233,6 @@ parse_state_file (const char *filename, g_return_val_if_fail (wimax_enabled != NULL, FALSE); state_file = g_key_file_new (); - if (!state_file) { - g_set_error (error, NM_CONFIG_ERROR, NM_CONFIG_ERROR_NO_MEMORY, - "Not enough memory to load state file %s.", filename); - return FALSE; - } - g_key_file_set_list_separator (state_file, ','); if (!g_key_file_load_from_file (state_file, filename, G_KEY_FILE_KEEP_COMMENTS, &tmp_error)) { gboolean ret = FALSE; @@ -299,6 +293,37 @@ parse_state_file (const char *filename, return TRUE; } +static void +_init_nm_debug (const char *debug) +{ + const guint D_RLIMIT_CORE = 1; + GDebugKey keys[] = { + { "RLIMIT_CORE", D_RLIMIT_CORE }, + }; + guint flags = 0; + const char *env = getenv ("NM_DEBUG"); + + if (env && strcasecmp (env, "help") != 0) { + /* g_parse_debug_string() prints options to stderr if the variable + * is set to "help". Don't allow that. */ + flags = g_parse_debug_string (env, keys, G_N_ELEMENTS (keys)); + } + + if (debug && strcasecmp (debug, "help") != 0) + flags |= g_parse_debug_string (debug, keys, G_N_ELEMENTS (keys)); + + if (flags & D_RLIMIT_CORE) { + /* only enable this, if explicitly requested, because it might + * expose sensitive data. */ + + struct rlimit limit = { + .rlim_cur = RLIM_INFINITY, + .rlim_max = RLIM_INFINITY, + }; + setrlimit (RLIMIT_CORE, &limit); + } +} + /* * main * @@ -307,49 +332,42 @@ int main (int argc, char *argv[]) { GOptionContext *opt_ctx = NULL; - gboolean become_daemon = FALSE; + char *opt_log_level = NULL; + char *opt_log_domains = NULL; + gboolean become_daemon = TRUE, run_from_build_dir = FALSE; + gboolean debug = FALSE; gboolean g_fatal_warnings = FALSE; - char *pidfile = NULL, *state_file = NULL; - char *config_path = NULL, *plugins = NULL; - char *log_level = NULL, *log_domains = NULL; - char *connectivity_uri = NULL; - gint connectivity_interval = -1; - char *connectivity_response = NULL; + gs_free char *pidfile = NULL; + gs_free char *state_file = NULL; gboolean wifi_enabled = TRUE, net_enabled = TRUE, wwan_enabled = TRUE, wimax_enabled = TRUE; gboolean success, show_version = FALSE; - NMVPNManager *vpn_manager = NULL; - NMDnsManager *dns_mgr = NULL; - NMDBusManager *dbus_mgr = NULL; - NMSupplicantManager *sup_mgr = NULL; - NMDHCPManager *dhcp_mgr = NULL; - NMFirewallManager *fw_mgr = NULL; - NMSettings *settings = NULL; - NMConfig *config; - NMNetlinkMonitor *monitor = NULL; + int i; + NMManager *manager = NULL; + gs_unref_object NMVPNManager *vpn_manager = NULL; + gs_unref_object NMDnsManager *dns_mgr = NULL; + gs_unref_object NMDBusManager *dbus_mgr = NULL; + gs_unref_object NMSupplicantManager *sup_mgr = NULL; + gs_unref_object NMDHCPManager *dhcp_mgr = NULL; + gs_unref_object NMFirewallManager *fw_mgr = NULL; + gs_unref_object NMSettings *settings = NULL; + gs_unref_object NMConfig *config = NULL; + gs_unref_object NMSessionMonitor *session_monitor = NULL; GError *error = NULL; gboolean wrote_pidfile = FALSE; + char *bad_domains = NULL; GOptionEntry options[] = { - { "version", 0, 0, G_OPTION_ARG_NONE, &show_version, N_("Print NetworkManager version and exit"), NULL }, - { "no-daemon", 0, 0, G_OPTION_ARG_NONE, &become_daemon, N_("Don't become a daemon"), NULL }, + { "version", 'V', 0, G_OPTION_ARG_NONE, &show_version, N_("Print NetworkManager version and exit"), NULL }, + { "no-daemon", 'n', G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE, &become_daemon, N_("Don't become a daemon"), NULL }, + { "debug", 'd', 0, G_OPTION_ARG_NONE, &debug, N_("Don't become a daemon, and log to stderr"), NULL }, + { "log-level", 0, 0, G_OPTION_ARG_STRING, &opt_log_level, N_("Log level: one of [%s]"), "INFO" }, + { "log-domains", 0, 0, G_OPTION_ARG_STRING, &opt_log_domains, + N_("Log domains separated by ',': any combination of [%s]"), + "PLATFORM,RFKILL,WIFI" }, { "g-fatal-warnings", 0, 0, G_OPTION_ARG_NONE, &g_fatal_warnings, N_("Make all warnings fatal"), NULL }, - { "pid-file", 0, 0, G_OPTION_ARG_FILENAME, &pidfile, N_("Specify the location of a PID file"), N_("filename") }, + { "pid-file", 'p', 0, G_OPTION_ARG_FILENAME, &pidfile, N_("Specify the location of a PID file"), N_("filename") }, { "state-file", 0, 0, G_OPTION_ARG_FILENAME, &state_file, N_("State file location"), N_("/path/to/state.file") }, - { "config", 0, 0, G_OPTION_ARG_FILENAME, &config_path, N_("Config file location"), N_("/path/to/config.file") }, - { "plugins", 0, 0, G_OPTION_ARG_STRING, &plugins, N_("List of plugins separated by ','"), N_("plugin1,plugin2") }, - /* Translators: Do not translate the values in the square brackets */ - { "log-level", 0, 0, G_OPTION_ARG_STRING, &log_level, N_("Log level: one of [ERR, WARN, INFO, DEBUG]"), "INFO" }, - { "log-domains", 0, 0, G_OPTION_ARG_STRING, &log_domains, - /* Translators: Do not translate the values in the square brackets */ - N_("Log domains separated by ',': any combination of\n" - " [NONE,HW,RFKILL,ETHER,WIFI,BT,MB,DHCP4,DHCP6,PPP,\n" - " WIFI_SCAN,IP4,IP6,AUTOIP4,DNS,VPN,SHARING,SUPPLICANT,\n" - " AGENTS,SETTINGS,SUSPEND,CORE,DEVICE,OLPC,WIMAX,\n" - " INFINIBAND,FIREWALL,ADSL]"), - "HW,RFKILL,WIFI" }, - { "connectivity-uri", 0, 0, G_OPTION_ARG_STRING, &connectivity_uri, _("An http(s) address for checking internet connectivity"), "http://example.com" }, - { "connectivity-interval", 0, 0, G_OPTION_ARG_INT, &connectivity_interval, _("The interval between connectivity checks (in seconds)"), "60" }, - { "connectivity-response", 0, 0, G_OPTION_ARG_STRING, &connectivity_response, _("The expected start of the response"), N_("Bingo!") }, + { "run-from-build-dir", 0, 0, G_OPTION_ARG_NONE, &run_from_build_dir, "Run from build directory", NULL }, {NULL} }; @@ -366,11 +384,6 @@ main (int argc, char *argv[]) */ umask (022); - if (!g_module_supported ()) { - fprintf (stderr, _("GModules are not supported on your platform!\n")); - exit (1); - } - /* Set locale to be able to use environment variables */ setlocale (LC_ALL, ""); @@ -378,12 +391,33 @@ main (int argc, char *argv[]) bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); textdomain (GETTEXT_PACKAGE); + if (!g_module_supported ()) { + fprintf (stderr, _("GModules are not supported on your platform!\n")); + exit (1); + } + + if (getuid () != 0) { + fprintf (stderr, _("You must be root to run NetworkManager!\n")); + exit (1); + } + + for (i = 0; options[i].long_name; i++) { + if (!strcmp (options[i].long_name, "log-level")) { + options[i].description = g_strdup_printf (options[i].description, + nm_logging_all_levels_to_string ()); + } else if (!strcmp (options[i].long_name, "log-domains")) { + options[i].description = g_strdup_printf (options[i].description, + nm_logging_all_domains_to_string ()); + } + } + /* Parse options */ opt_ctx = g_option_context_new (NULL); g_option_context_set_translation_domain (opt_ctx, GETTEXT_PACKAGE); g_option_context_set_ignore_unknown_options (opt_ctx, FALSE); g_option_context_set_help_enabled (opt_ctx, TRUE); g_option_context_add_main_entries (opt_ctx, options, NULL); + g_option_context_add_main_entries (opt_ctx, nm_config_get_options (), NULL); g_option_context_set_summary (opt_ctx, _("NetworkManager monitors all network connections and automatically\nchooses the best connection to use. It also allows the user to\nspecify wireless access points which wireless cards in the computer\nshould associate with.")); @@ -403,11 +437,44 @@ main (int argc, char *argv[]) exit (0); } - if (getuid () != 0) { - fprintf (stderr, _("You must be root to run NetworkManager!\n")); + if (!nm_logging_setup (opt_log_level, + opt_log_domains, + &bad_domains, + &error)) { + fprintf (stderr, + _("%s. Please use --help to see a list of valid options.\n"), + error->message); exit (1); + } else if (bad_domains) { + fprintf (stderr, + _("Ignoring unrecognized log domain(s) '%s' passed on command line.\n"), + bad_domains); + g_clear_pointer (&bad_domains, g_free); } + /* When running from the build directory, determine our build directory + * base and set helper paths in the build tree */ + if (run_from_build_dir) { + char *path, *slash; + int g; + + /* exe is /src/.libs/lt-NetworkManager, so chop off + * the last three components */ + path = realpath ("/proc/self/exe", NULL); + g_assert (path != NULL); + for (g = 0; g < 3; ++g) { + slash = strrchr (path, '/'); + g_assert (slash != NULL); + *slash = '\0'; + } + + /* don't free these strings, we need them for the entire + * process lifetime */ + nm_dhcp_helper_path = g_strdup_printf ("%s/src/dhcp-manager/nm-dhcp-helper", path); + nm_device_autoipd_helper_path = g_strdup_printf ("%s/callouts/nm-avahi-autoipd.action", path); + + g_free (path); + } /* Setup runtime directory */ if (g_mkdir_with_parents (NMRUNDIR, 0755) != 0) { @@ -429,8 +496,7 @@ main (int argc, char *argv[]) exit (1); /* Read the config file and CLI overrides */ - config = nm_config_new (config_path, plugins, log_level, log_domains, - connectivity_uri, connectivity_interval, connectivity_response, &error); + config = nm_config_new (&error); if (config == NULL) { fprintf (stderr, _("Failed to read configuration: (%d) %s\n"), error ? error->code : -1, @@ -438,14 +504,23 @@ main (int argc, char *argv[]) exit (1); } - /* Logging setup */ - if (!nm_logging_setup (nm_config_get_log_level (config), - nm_config_get_log_domains (config), - &error)) { - fprintf (stderr, - _("%s. Please use --help to see a list of valid options.\n"), - error->message); - exit (1); + /* Initialize logging from config file *only* if not explicitly + * specified by commandline. + */ + if (opt_log_level == NULL && opt_log_domains == NULL) { + if (!nm_logging_setup (nm_config_get_log_level (config), + nm_config_get_log_domains (config), + &bad_domains, + &error)) { + fprintf (stderr, _("Error in configuration file: %s.\n"), + error->message); + exit (1); + } else if (bad_domains) { + fprintf (stderr, + _("Ignoring unrecognized log domain(s) '%s' from config files.\n"), + bad_domains); + g_clear_pointer (&bad_domains, g_free); + } } /* Parse the state file */ @@ -458,11 +533,7 @@ main (int argc, char *argv[]) } g_clear_error (&error); - /* Tricky: become_daemon is FALSE by default, so unless it's TRUE because - * of a CLI option, it'll become TRUE after this - */ - become_daemon = !become_daemon; - if (become_daemon) { + if (become_daemon && !debug) { if (daemon (0, 0) < 0) { int saved_errno; @@ -476,6 +547,8 @@ main (int argc, char *argv[]) wrote_pidfile = TRUE; } + _init_nm_debug (nm_config_get_debug (config)); + /* Set up unix signal handling - before creating threads, but after daemonizing! */ if (!setup_signals ()) exit (1); @@ -488,31 +561,23 @@ main (int argc, char *argv[]) g_log_set_always_fatal (fatal_mask); } + nm_logging_syslog_openlog (debug); + +#if !GLIB_CHECK_VERSION (2, 35, 0) g_type_init (); +#endif -/* - * Threading is always enabled starting from GLib 2.31.0. - * See also http://developer.gnome.org/glib/2.31/glib-Deprecated-Thread-APIs.html. - */ -#if !GLIB_CHECK_VERSION (2,31,0) - if (!g_thread_supported ()) - g_thread_init (NULL); - dbus_g_thread_init (); -#else dbus_threads_init_default (); -#endif /* Ensure that non-exported properties don't leak out, and that the * introspection 'access' permissions are respected. */ dbus_glib_global_set_disable_legacy_property_access (); - nm_logging_start (become_daemon); - nm_log_info (LOGD_CORE, "NetworkManager (version " NM_DIST_VERSION ") is starting..."); success = FALSE; - nm_log_info (LOGD_CORE, "Read config file %s", nm_config_get_path (config)); + nm_log_info (LOGD_CORE, "Read config: %s", nm_config_get_description (config)); nm_log_info (LOGD_CORE, "WEXT support is %s", #if HAVE_WEXT "enabled" @@ -523,27 +588,26 @@ main (int argc, char *argv[]) main_loop = g_main_loop_new (NULL, FALSE); - /* Create netlink monitor object */ - monitor = nm_netlink_monitor_get (); + /* Set up platform interaction layer */ + nm_linux_platform_setup (); /* Initialize our DBus service & connection */ dbus_mgr = nm_dbus_manager_get (); + g_assert (dbus_mgr != NULL); vpn_manager = nm_vpn_manager_get (); - if (!vpn_manager) { - nm_log_err (LOGD_CORE, "failed to start the VPN manager."); - goto done; - } + g_assert (vpn_manager != NULL); - dns_mgr = nm_dns_manager_get (nm_config_get_dns_plugins (config)); - if (!dns_mgr) { - nm_log_err (LOGD_CORE, "failed to start the DNS manager."); - goto done; - } + dns_mgr = nm_dns_manager_get (); + g_assert (dns_mgr != NULL); + + /* Initialize DHCP manager */ + dhcp_mgr = nm_dhcp_manager_get (); + g_assert (dhcp_mgr != NULL); + + nm_dispatcher_init (); - settings = nm_settings_new (nm_config_get_path (config), - nm_config_get_plugins (config), - &error); + settings = nm_settings_new (&error); if (!settings) { nm_log_err (LOGD_CORE, "failed to initialize settings storage: %s", error && error->message ? error->message : "(unknown)"); @@ -556,9 +620,6 @@ main (int argc, char *argv[]) wifi_enabled, wwan_enabled, wimax_enabled, - nm_config_get_connectivity_uri (config), - nm_config_get_connectivity_interval (config), - nm_config_get_connectivity_response (config), &error); if (manager == NULL) { nm_log_err (LOGD_CORE, "failed to initialize the network manager: %s", @@ -568,36 +629,31 @@ main (int argc, char *argv[]) /* Initialize the supplicant manager */ sup_mgr = nm_supplicant_manager_get (); - if (!sup_mgr) { - nm_log_err (LOGD_CORE, "failed to initialize the supplicant manager."); - goto done; - } - - /* Initialize DHCP manager */ - dhcp_mgr = nm_dhcp_manager_new (nm_config_get_dhcp_client (config), &error); - if (!dhcp_mgr) { - nm_log_err (LOGD_CORE, "failed to start the DHCP manager: %s.", error->message); - goto done; - } - - nm_dhcp_manager_set_hostname_provider (dhcp_mgr, NM_HOSTNAME_PROVIDER (manager)); + g_assert (sup_mgr != NULL); /* Initialize Firewall manager */ fw_mgr = nm_firewall_manager_get (); - if (!fw_mgr) { - nm_log_err (LOGD_CORE, "failed to start the Firewall manager: %s.", error->message); - goto done; - } + g_assert (fw_mgr != NULL); - /* Start our DBus service */ - if (!nm_dbus_manager_start_service (dbus_mgr)) { - nm_log_err (LOGD_CORE, "failed to start the dbus service."); + /* Initialize session monitor */ + session_monitor = nm_session_monitor_get (); + g_assert (session_monitor != NULL); + + if (!nm_dbus_manager_get_connection (dbus_mgr)) { +#if HAVE_DBUS_GLIB_100 + nm_log_warn (LOGD_CORE, "Failed to connect to D-Bus; only private bus is available"); +#else + nm_log_err (LOGD_CORE, "Failed to connect to D-Bus, exiting..."); goto done; +#endif + } else { + /* Start our DBus service */ + if (!nm_dbus_manager_start_service (dbus_mgr)) { + nm_log_err (LOGD_CORE, "failed to start the dbus service."); + goto done; + } } - /* Clean leftover "# Added by NetworkManager" entries from /etc/hosts */ - nm_policy_hosts_clean_etc_hosts (); - nm_manager_start (manager); /* Make sure the loopback interface is up. If interface is down, we bring @@ -611,7 +667,7 @@ main (int argc, char *argv[]) * physical interfaces. */ nm_log_dbg (LOGD_CORE, "setting up local loopback"); - nm_system_iface_set_up (nm_netlink_iface_to_index ("lo"), TRUE, NULL); + nm_platform_link_set_up (nm_platform_link_get_ifindex ("lo")); success = TRUE; @@ -622,47 +678,13 @@ main (int argc, char *argv[]) g_main_loop_run (main_loop); done: - if (manager) - g_object_unref (manager); - - if (settings) - g_object_unref (settings); - - if (vpn_manager) - g_object_unref (vpn_manager); - - if (dns_mgr) - g_object_unref (dns_mgr); + g_clear_object (&manager); - if (dhcp_mgr) - g_object_unref (dhcp_mgr); - - if (sup_mgr) - g_object_unref (sup_mgr); - - if (fw_mgr) - g_object_unref (fw_mgr); - - if (dbus_mgr) - g_object_unref (dbus_mgr); - - nm_logging_shutdown (); + nm_logging_syslog_closelog (); if (pidfile && wrote_pidfile) unlink (pidfile); - nm_config_free (config); - - /* Free options */ - g_free (pidfile); - g_free (state_file); - g_free (config_path); - g_free (plugins); - g_free (log_level); - g_free (log_domains); - g_free (connectivity_uri); - g_free (connectivity_response); - nm_log_info (LOGD_CORE, "exiting (%s)", success ? "success" : "error"); exit (success ? 0 : 1); } diff --git a/src/modem-manager/Makefile.am b/src/modem-manager/Makefile.am deleted file mode 100644 index 012d26ea..00000000 --- a/src/modem-manager/Makefile.am +++ /dev/null @@ -1,43 +0,0 @@ -include $(GLIB_MAKEFILE) - -noinst_LTLIBRARIES = libmodem-manager.la - -libmodem_manager_la_CPPFLAGS = \ - -I${top_srcdir}/src \ - -I${top_builddir}/src/generated \ - -I${top_srcdir}/src/generated \ - -I${top_srcdir}/src/logging \ - -I${top_builddir}/include \ - -I${top_srcdir}/include \ - -I${top_builddir}/libnm-util \ - -I${top_srcdir}/libnm-util \ - $(LIBNL_CFLAGS) \ - $(DBUS_CFLAGS) - -libmodem_manager_la_SOURCES = \ - nm-modem.c \ - nm-modem.h \ - nm-modem-generic.c \ - nm-modem-generic.h \ - nm-modem-cdma.c \ - nm-modem-cdma.h \ - nm-modem-gsm.c \ - nm-modem-gsm.h \ - nm-modem-manager.h \ - nm-modem-manager.c \ - nm-modem-types.h - -libmodem_manager_la_LIBADD = \ - $(top_builddir)/src/generated/libnm-generated.la \ - $(top_builddir)/src/logging/libnm-logging.la \ - $(LIBNL_LIBS) \ - $(DBUS_LIBS) - -# Support for the new ModemManager1 interface -if WITH_MODEM_MANAGER_1 -libmodem_manager_la_SOURCES += \ - nm-modem-broadband.h \ - nm-modem-broadband.c -libmodem_manager_la_CPPFLAGS += $(MM_GLIB_CFLAGS) -libmodem_manager_la_LIBADD += $(MM_GLIB_LIBS) -endif diff --git a/src/modem-manager/Makefile.in b/src/modem-manager/Makefile.in deleted file mode 100644 index d945f9c9..00000000 --- a/src/modem-manager/Makefile.in +++ /dev/null @@ -1,789 +0,0 @@ -# Makefile.in generated by automake 1.13.4 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994-2013 Free Software Foundation, Inc. - -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ - -VPATH = @srcdir@ -am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' -am__make_running_with_option = \ - case $${target_option-} in \ - ?) ;; \ - *) echo "am__make_running_with_option: internal error: invalid" \ - "target option '$${target_option-}' specified" >&2; \ - exit 1;; \ - esac; \ - has_opt=no; \ - sane_makeflags=$$MAKEFLAGS; \ - if $(am__is_gnu_make); then \ - sane_makeflags=$$MFLAGS; \ - else \ - case $$MAKEFLAGS in \ - *\\[\ \ ]*) \ - bs=\\; \ - sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ - | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ - esac; \ - fi; \ - skip_next=no; \ - strip_trailopt () \ - { \ - flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ - }; \ - for flg in $$sane_makeflags; do \ - test $$skip_next = yes && { skip_next=no; continue; }; \ - case $$flg in \ - *=*|--*) continue;; \ - -*I) strip_trailopt 'I'; skip_next=yes;; \ - -*I?*) strip_trailopt 'I';; \ - -*O) strip_trailopt 'O'; skip_next=yes;; \ - -*O?*) strip_trailopt 'O';; \ - -*l) strip_trailopt 'l'; skip_next=yes;; \ - -*l?*) strip_trailopt 'l';; \ - -[dEDm]) skip_next=yes;; \ - -[JT]) skip_next=yes;; \ - esac; \ - case $$flg in \ - *$$target_option*) has_opt=yes; break;; \ - esac; \ - done; \ - test $$has_opt = yes -am__make_dryrun = (target_option=n; $(am__make_running_with_option)) -am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) -pkgdatadir = $(datadir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkglibexecdir = $(libexecdir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = @build@ -host_triplet = @host@ - -# Support for the new ModemManager1 interface -@WITH_MODEM_MANAGER_1_TRUE@am__append_1 = \ -@WITH_MODEM_MANAGER_1_TRUE@ nm-modem-broadband.h \ -@WITH_MODEM_MANAGER_1_TRUE@ nm-modem-broadband.c - -@WITH_MODEM_MANAGER_1_TRUE@am__append_2 = $(MM_GLIB_CFLAGS) -@WITH_MODEM_MANAGER_1_TRUE@am__append_3 = $(MM_GLIB_LIBS) -subdir = src/modem-manager -DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ - $(top_srcdir)/build-aux/depcomp README -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \ - $(top_srcdir)/m4/gettext.m4 \ - $(top_srcdir)/m4/gnome-code-coverage.m4 \ - $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ - $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \ - $(top_srcdir)/m4/introspection.m4 $(top_srcdir)/m4/lib-ld.m4 \ - $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ - $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ - $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ - $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ - $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ - $(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -mkinstalldirs = $(install_sh) -d -CONFIG_HEADER = $(top_builddir)/config.h -CONFIG_CLEAN_FILES = -CONFIG_CLEAN_VPATH_FILES = -LTLIBRARIES = $(noinst_LTLIBRARIES) -am__DEPENDENCIES_1 = -@WITH_MODEM_MANAGER_1_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) -libmodem_manager_la_DEPENDENCIES = \ - $(top_builddir)/src/generated/libnm-generated.la \ - $(top_builddir)/src/logging/libnm-logging.la \ - $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_2) -am__libmodem_manager_la_SOURCES_DIST = nm-modem.c nm-modem.h \ - nm-modem-generic.c nm-modem-generic.h nm-modem-cdma.c \ - nm-modem-cdma.h nm-modem-gsm.c nm-modem-gsm.h \ - nm-modem-manager.h nm-modem-manager.c nm-modem-types.h \ - nm-modem-broadband.h nm-modem-broadband.c -@WITH_MODEM_MANAGER_1_TRUE@am__objects_1 = libmodem_manager_la-nm-modem-broadband.lo -am_libmodem_manager_la_OBJECTS = libmodem_manager_la-nm-modem.lo \ - libmodem_manager_la-nm-modem-generic.lo \ - libmodem_manager_la-nm-modem-cdma.lo \ - libmodem_manager_la-nm-modem-gsm.lo \ - libmodem_manager_la-nm-modem-manager.lo $(am__objects_1) -libmodem_manager_la_OBJECTS = $(am_libmodem_manager_la_OBJECTS) -AM_V_lt = $(am__v_lt_@AM_V@) -am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) -am__v_lt_0 = --silent -am__v_lt_1 = -AM_V_P = $(am__v_P_@AM_V@) -am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) -am__v_P_0 = false -am__v_P_1 = : -AM_V_GEN = $(am__v_GEN_@AM_V@) -am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) -am__v_GEN_0 = @echo " GEN " $@; -am__v_GEN_1 = -AM_V_at = $(am__v_at_@AM_V@) -am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) -am__v_at_0 = @ -am__v_at_1 = -DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) -depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp -am__depfiles_maybe = depfiles -am__mv = mv -f -COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ - $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ - $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ - $(AM_CFLAGS) $(CFLAGS) -AM_V_CC = $(am__v_CC_@AM_V@) -am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) -am__v_CC_0 = @echo " CC " $@; -am__v_CC_1 = -CCLD = $(CC) -LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(AM_LDFLAGS) $(LDFLAGS) -o $@ -AM_V_CCLD = $(am__v_CCLD_@AM_V@) -am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) -am__v_CCLD_0 = @echo " CCLD " $@; -am__v_CCLD_1 = -SOURCES = $(libmodem_manager_la_SOURCES) -DIST_SOURCES = $(am__libmodem_manager_la_SOURCES_DIST) -am__can_run_installinfo = \ - case $$AM_UPDATE_INFO_DIR in \ - n|no|NO) false;; \ - *) (install-info --version) >/dev/null 2>&1;; \ - esac -am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) -# Read a list of newline-separated strings from the standard input, -# and print each of them once, without duplicates. Input order is -# *not* preserved. -am__uniquify_input = $(AWK) '\ - BEGIN { nonempty = 0; } \ - { items[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in items) print i; }; } \ -' -# Make sure the list of sources is unique. This is necessary because, -# e.g., the same source file might be shared among _SOURCES variables -# for different programs/libraries. -am__define_uniq_tagged_files = \ - list='$(am__tagged_files)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | $(am__uniquify_input)` -ETAGS = etags -CTAGS = ctags -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -ALL_LINGUAS = @ALL_LINGUAS@ -AMTAR = @AMTAR@ -AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -AR = @AR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CKDB_PATH = @CKDB_PATH@ -CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@ -CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@ -CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CXX = @CXX@ -CXXCPP = @CXXCPP@ -CXXDEPMODE = @CXXDEPMODE@ -CXXFLAGS = @CXXFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DATADIRNAME = @DATADIRNAME@ -DBUS_CFLAGS = @DBUS_CFLAGS@ -DBUS_LIBS = @DBUS_LIBS@ -DBUS_SYS_DIR = @DBUS_SYS_DIR@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -DHCLIENT_PATH = @DHCLIENT_PATH@ -DHCPCD_PATH = @DHCPCD_PATH@ -DLLTOOL = @DLLTOOL@ -DNSMASQ_PATH = @DNSMASQ_PATH@ -DSYMUTIL = @DSYMUTIL@ -DUMPBIN = @DUMPBIN@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -FGREP = @FGREP@ -GENHTML = @GENHTML@ -GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ -GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ -GLIB_CFLAGS = @GLIB_CFLAGS@ -GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ -GLIB_LIBS = @GLIB_LIBS@ -GLIB_MAKEFILE = @GLIB_MAKEFILE@ -GLIB_MKENUMS = @GLIB_MKENUMS@ -GMSGFMT = @GMSGFMT@ -GMSGFMT_015 = @GMSGFMT_015@ -GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ -GNUTLS_LIBS = @GNUTLS_LIBS@ -GREP = @GREP@ -GTKDOC_CHECK = @GTKDOC_CHECK@ -GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ -GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ -GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ -GTKDOC_MKPDF = @GTKDOC_MKPDF@ -GTKDOC_REBASE = @GTKDOC_REBASE@ -GUDEV_CFLAGS = @GUDEV_CFLAGS@ -GUDEV_LIBS = @GUDEV_LIBS@ -HTML_DIR = @HTML_DIR@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -INTLLIBS = @INTLLIBS@ -INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ -INTLTOOL_MERGE = @INTLTOOL_MERGE@ -INTLTOOL_PERL = @INTLTOOL_PERL@ -INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ -INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ -INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ -INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ -INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ -INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ -INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ -INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ -INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ -INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ -INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ -INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ -INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ -INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ -IPTABLES_PATH = @IPTABLES_PATH@ -IWMX_SDK_CFLAGS = @IWMX_SDK_CFLAGS@ -IWMX_SDK_LIBS = @IWMX_SDK_LIBS@ -KERNEL_FIRMWARE_DIR = @KERNEL_FIRMWARE_DIR@ -LCOV = @LCOV@ -LD = @LD@ -LDFLAGS = @LDFLAGS@ -LIBDL = @LIBDL@ -LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ -LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ -LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ -LIBICONV = @LIBICONV@ -LIBINTL = @LIBINTL@ -LIBM = @LIBM@ -LIBNL_CFLAGS = @LIBNL_CFLAGS@ -LIBNL_LIBS = @LIBNL_LIBS@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@ -LIBSOUP_LIBS = @LIBSOUP_LIBS@ -LIBTOOL = @LIBTOOL@ -LIPO = @LIPO@ -LN_S = @LN_S@ -LTLIBICONV = @LTLIBICONV@ -LTLIBINTL = @LTLIBINTL@ -LTLIBOBJS = @LTLIBOBJS@ -MAINT = @MAINT@ -MAKEINFO = @MAKEINFO@ -MANIFEST_TOOL = @MANIFEST_TOOL@ -MKDIR_P = @MKDIR_P@ -MM_GLIB_CFLAGS = @MM_GLIB_CFLAGS@ -MM_GLIB_LIBS = @MM_GLIB_LIBS@ -MOC = @MOC@ -MSGFMT = @MSGFMT@ -MSGFMT_015 = @MSGFMT_015@ -MSGMERGE = @MSGMERGE@ -NM = @NM@ -NMEDIT = @NMEDIT@ -NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ -NM_MICRO_VERSION = @NM_MICRO_VERSION@ -NM_MINOR_VERSION = @NM_MINOR_VERSION@ -NM_MODIFY_SYSTEM_POLICY = @NM_MODIFY_SYSTEM_POLICY@ -NM_VERSION = @NM_VERSION@ -NSS_CFLAGS = @NSS_CFLAGS@ -NSS_LIBS = @NSS_LIBS@ -OBJDUMP = @OBJDUMP@ -OBJEXT = @OBJEXT@ -OTOOL = @OTOOL@ -OTOOL64 = @OTOOL64@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_URL = @PACKAGE_URL@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PKG_CONFIG = @PKG_CONFIG@ -PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ -PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ -POLKIT_CFLAGS = @POLKIT_CFLAGS@ -POLKIT_LIBS = @POLKIT_LIBS@ -POSUB = @POSUB@ -PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@ -QT_CFLAGS = @QT_CFLAGS@ -QT_LIBS = @QT_LIBS@ -RANLIB = @RANLIB@ -SED = @SED@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -STRIP = @STRIP@ -SYSTEMD_200_CFLAGS = @SYSTEMD_200_CFLAGS@ -SYSTEMD_200_LIBS = @SYSTEMD_200_LIBS@ -SYSTEMD_INHIBIT_CFLAGS = @SYSTEMD_INHIBIT_CFLAGS@ -SYSTEMD_INHIBIT_LIBS = @SYSTEMD_INHIBIT_LIBS@ -SYSTEMD_LOGIN_CFLAGS = @SYSTEMD_LOGIN_CFLAGS@ -SYSTEMD_LOGIN_LIBS = @SYSTEMD_LOGIN_LIBS@ -SYSTEM_CA_PATH = @SYSTEM_CA_PATH@ -UDEV_BASE_DIR = @UDEV_BASE_DIR@ -USE_NLS = @USE_NLS@ -UUID_CFLAGS = @UUID_CFLAGS@ -UUID_LIBS = @UUID_LIBS@ -VAPIGEN = @VAPIGEN@ -VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ -VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ -VERSION = @VERSION@ -XGETTEXT = @XGETTEXT@ -XGETTEXT_015 = @XGETTEXT_015@ -XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_AR = @ac_ct_AR@ -ac_ct_CC = @ac_ct_CC@ -ac_ct_CXX = @ac_ct_CXX@ -ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -intltool__v_merge_options_ = @intltool__v_merge_options_@ -intltool__v_merge_options_0 = @intltool__v_merge_options_0@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -nmbinary = @nmbinary@ -nmconfdir = @nmconfdir@ -nmdatadir = @nmdatadir@ -nmrundir = @nmrundir@ -nmstatedir = @nmstatedir@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -sysconfdir = @sysconfdir@ -systemdsystemunitdir = @systemdsystemunitdir@ -target_alias = @target_alias@ -top_build_prefix = @top_build_prefix@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -with_dhclient = @with_dhclient@ -with_dhcpcd = @with_dhcpcd@ -with_netconfig = @with_netconfig@ -with_resolvconf = @with_resolvconf@ -noinst_LTLIBRARIES = libmodem-manager.la -libmodem_manager_la_CPPFLAGS = -I${top_srcdir}/src \ - -I${top_builddir}/src/generated -I${top_srcdir}/src/generated \ - -I${top_srcdir}/src/logging -I${top_builddir}/include \ - -I${top_srcdir}/include -I${top_builddir}/libnm-util \ - -I${top_srcdir}/libnm-util $(LIBNL_CFLAGS) $(DBUS_CFLAGS) \ - $(am__append_2) -libmodem_manager_la_SOURCES = nm-modem.c nm-modem.h nm-modem-generic.c \ - nm-modem-generic.h nm-modem-cdma.c nm-modem-cdma.h \ - nm-modem-gsm.c nm-modem-gsm.h nm-modem-manager.h \ - nm-modem-manager.c nm-modem-types.h $(am__append_1) -libmodem_manager_la_LIBADD = \ - $(top_builddir)/src/generated/libnm-generated.la \ - $(top_builddir)/src/logging/libnm-logging.la $(LIBNL_LIBS) \ - $(DBUS_LIBS) $(am__append_3) -all: all-am - -.SUFFIXES: -.SUFFIXES: .c .lo .o .obj -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ - && { if test -f $@; then exit 0; else break; fi; }; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/modem-manager/Makefile'; \ - $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --gnu src/modem-manager/Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(am__aclocal_m4_deps): - -clean-noinstLTLIBRARIES: - -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) - @list='$(noinst_LTLIBRARIES)'; \ - locs=`for p in $$list; do echo $$p; done | \ - sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ - sort -u`; \ - test -z "$$locs" || { \ - echo rm -f $${locs}; \ - rm -f $${locs}; \ - } - -libmodem-manager.la: $(libmodem_manager_la_OBJECTS) $(libmodem_manager_la_DEPENDENCIES) $(EXTRA_libmodem_manager_la_DEPENDENCIES) - $(AM_V_CCLD)$(LINK) $(libmodem_manager_la_OBJECTS) $(libmodem_manager_la_LIBADD) $(LIBS) - -mostlyclean-compile: - -rm -f *.$(OBJEXT) - -distclean-compile: - -rm -f *.tab.c - -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmodem_manager_la-nm-modem-broadband.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmodem_manager_la-nm-modem-cdma.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmodem_manager_la-nm-modem-generic.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmodem_manager_la-nm-modem-gsm.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmodem_manager_la-nm-modem-manager.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmodem_manager_la-nm-modem.Plo@am__quote@ - -.c.o: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< - -.c.obj: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` - -.c.lo: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< - -libmodem_manager_la-nm-modem.lo: nm-modem.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmodem_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libmodem_manager_la-nm-modem.lo -MD -MP -MF $(DEPDIR)/libmodem_manager_la-nm-modem.Tpo -c -o libmodem_manager_la-nm-modem.lo `test -f 'nm-modem.c' || echo '$(srcdir)/'`nm-modem.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmodem_manager_la-nm-modem.Tpo $(DEPDIR)/libmodem_manager_la-nm-modem.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-modem.c' object='libmodem_manager_la-nm-modem.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmodem_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libmodem_manager_la-nm-modem.lo `test -f 'nm-modem.c' || echo '$(srcdir)/'`nm-modem.c - -libmodem_manager_la-nm-modem-generic.lo: nm-modem-generic.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmodem_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libmodem_manager_la-nm-modem-generic.lo -MD -MP -MF $(DEPDIR)/libmodem_manager_la-nm-modem-generic.Tpo -c -o libmodem_manager_la-nm-modem-generic.lo `test -f 'nm-modem-generic.c' || echo '$(srcdir)/'`nm-modem-generic.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmodem_manager_la-nm-modem-generic.Tpo $(DEPDIR)/libmodem_manager_la-nm-modem-generic.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-modem-generic.c' object='libmodem_manager_la-nm-modem-generic.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmodem_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libmodem_manager_la-nm-modem-generic.lo `test -f 'nm-modem-generic.c' || echo '$(srcdir)/'`nm-modem-generic.c - -libmodem_manager_la-nm-modem-cdma.lo: nm-modem-cdma.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmodem_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libmodem_manager_la-nm-modem-cdma.lo -MD -MP -MF $(DEPDIR)/libmodem_manager_la-nm-modem-cdma.Tpo -c -o libmodem_manager_la-nm-modem-cdma.lo `test -f 'nm-modem-cdma.c' || echo '$(srcdir)/'`nm-modem-cdma.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmodem_manager_la-nm-modem-cdma.Tpo $(DEPDIR)/libmodem_manager_la-nm-modem-cdma.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-modem-cdma.c' object='libmodem_manager_la-nm-modem-cdma.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmodem_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libmodem_manager_la-nm-modem-cdma.lo `test -f 'nm-modem-cdma.c' || echo '$(srcdir)/'`nm-modem-cdma.c - -libmodem_manager_la-nm-modem-gsm.lo: nm-modem-gsm.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmodem_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libmodem_manager_la-nm-modem-gsm.lo -MD -MP -MF $(DEPDIR)/libmodem_manager_la-nm-modem-gsm.Tpo -c -o libmodem_manager_la-nm-modem-gsm.lo `test -f 'nm-modem-gsm.c' || echo '$(srcdir)/'`nm-modem-gsm.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmodem_manager_la-nm-modem-gsm.Tpo $(DEPDIR)/libmodem_manager_la-nm-modem-gsm.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-modem-gsm.c' object='libmodem_manager_la-nm-modem-gsm.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmodem_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libmodem_manager_la-nm-modem-gsm.lo `test -f 'nm-modem-gsm.c' || echo '$(srcdir)/'`nm-modem-gsm.c - -libmodem_manager_la-nm-modem-manager.lo: nm-modem-manager.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmodem_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libmodem_manager_la-nm-modem-manager.lo -MD -MP -MF $(DEPDIR)/libmodem_manager_la-nm-modem-manager.Tpo -c -o libmodem_manager_la-nm-modem-manager.lo `test -f 'nm-modem-manager.c' || echo '$(srcdir)/'`nm-modem-manager.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmodem_manager_la-nm-modem-manager.Tpo $(DEPDIR)/libmodem_manager_la-nm-modem-manager.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-modem-manager.c' object='libmodem_manager_la-nm-modem-manager.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmodem_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libmodem_manager_la-nm-modem-manager.lo `test -f 'nm-modem-manager.c' || echo '$(srcdir)/'`nm-modem-manager.c - -libmodem_manager_la-nm-modem-broadband.lo: nm-modem-broadband.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmodem_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libmodem_manager_la-nm-modem-broadband.lo -MD -MP -MF $(DEPDIR)/libmodem_manager_la-nm-modem-broadband.Tpo -c -o libmodem_manager_la-nm-modem-broadband.lo `test -f 'nm-modem-broadband.c' || echo '$(srcdir)/'`nm-modem-broadband.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmodem_manager_la-nm-modem-broadband.Tpo $(DEPDIR)/libmodem_manager_la-nm-modem-broadband.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-modem-broadband.c' object='libmodem_manager_la-nm-modem-broadband.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmodem_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libmodem_manager_la-nm-modem-broadband.lo `test -f 'nm-modem-broadband.c' || echo '$(srcdir)/'`nm-modem-broadband.c - -mostlyclean-libtool: - -rm -f *.lo - -clean-libtool: - -rm -rf .libs _libs - -ID: $(am__tagged_files) - $(am__define_uniq_tagged_files); mkid -fID $$unique -tags: tags-am -TAGS: tags - -tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) - set x; \ - here=`pwd`; \ - $(am__define_uniq_tagged_files); \ - shift; \ - if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ - test -n "$$unique" || unique=$$empty_fix; \ - if test $$# -gt 0; then \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - "$$@" $$unique; \ - else \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$unique; \ - fi; \ - fi -ctags: ctags-am - -CTAGS: ctags -ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) - $(am__define_uniq_tagged_files); \ - test -z "$(CTAGS_ARGS)$$unique" \ - || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$unique - -GTAGS: - here=`$(am__cd) $(top_builddir) && pwd` \ - && $(am__cd) $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) "$$here" -cscopelist: cscopelist-am - -cscopelist-am: $(am__tagged_files) - list='$(am__tagged_files)'; \ - case "$(srcdir)" in \ - [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ - *) sdir=$(subdir)/$(srcdir) ;; \ - esac; \ - for i in $$list; do \ - if test -f "$$i"; then \ - echo "$(subdir)/$$i"; \ - else \ - echo "$$sdir/$$i"; \ - fi; \ - done >> $(top_builddir)/cscope.files - -distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags - -distdir: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d "$(distdir)/$$file"; then \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ - else \ - test -f "$(distdir)/$$file" \ - || cp -p $$d/$$file "$(distdir)/$$file" \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: check-am -all-am: Makefile $(LTLIBRARIES) -installdirs: -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - if test -z '$(STRIP)'; then \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - install; \ - else \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ - fi -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." -clean: clean-am - -clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ - mostlyclean-am - -distclean: distclean-am - -rm -rf ./$(DEPDIR) - -rm -f Makefile -distclean-am: clean-am distclean-compile distclean-generic \ - distclean-tags - -dvi: dvi-am - -dvi-am: - -html: html-am - -html-am: - -info: info-am - -info-am: - -install-data-am: - -install-dvi: install-dvi-am - -install-dvi-am: - -install-exec-am: - -install-html: install-html-am - -install-html-am: - -install-info: install-info-am - -install-info-am: - -install-man: - -install-pdf: install-pdf-am - -install-pdf-am: - -install-ps: install-ps-am - -install-ps-am: - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -rf ./$(DEPDIR) - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-compile mostlyclean-generic \ - mostlyclean-libtool - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: - -.MAKE: install-am install-strip - -.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ - clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ - ctags-am distclean distclean-compile distclean-generic \ - distclean-libtool distclean-tags distdir dvi dvi-am html \ - html-am info info-am install install-am install-data \ - install-data-am install-dvi install-dvi-am install-exec \ - install-exec-am install-html install-html-am install-info \ - install-info-am install-man install-pdf install-pdf-am \ - install-ps install-ps-am install-strip installcheck \ - installcheck-am installdirs maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-compile \ - mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ - tags tags-am uninstall uninstall-am - -include $(GLIB_MAKEFILE) - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/src/modem-manager/README b/src/modem-manager/README deleted file mode 100644 index c9f0f5f1..00000000 --- a/src/modem-manager/README +++ /dev/null @@ -1,45 +0,0 @@ - -ModemManager integration is organized as follows: - - -Common source -******************************************************************************** - - * nm-modem.[h|c]: - Defines the basic `NMModem' object. The core NetworkManager implementation - will use this interface exclusively, regardless of the real final type of - the modem object. - - * nm-modem-manager.[h|c]: - Defines the `NMModemManager' object, which takes care of listening to - signals from the DBus inteface notifying about added or removed modems. - It also takes care of creating proper `NMModem' objects from the - information retrieved from the DBus interface. - - -ModemManager 0.7 integration -******************************************************************************** - - * nm-modem-broadband.[h|c]: - Defines the `NMModemBroadband' object, which is a subclass of `NMModem'. - This object handles both 3GPP and 3GPP2 modems exposed in the new - `ModemManager1' interface. - - -ModemManager 0.4/0.5/0.6 integration -******************************************************************************** - - * nm-modem-types.h: - Defines helper types to use with the (old) ModemManager DBus API. - - * nm-modem-generic.[h|c]: - Defines the `NMModemGeneric' object. All modem objects based on the old - ModemManager interface are subclasses of this one. - - * nm-modem-gsm.[h|c]: - Defines the `NMModemGsm' object, which is a subclass of `NMModemGeneric'. - This object handles 3GPP-specific (GSM, UMTS, HSPA, LTE) modems. - - * nm-modem-cdma.[h|c]: - Defines the `NMModemCdma' object, which is a subclass of `NMModemGeneric'. - This object handles 3GPP2-specific modems (CDMA, EV-DO). diff --git a/src/modem-manager/nm-modem-broadband.c b/src/modem-manager/nm-modem-broadband.c deleted file mode 100644 index febab8a4..00000000 --- a/src/modem-manager/nm-modem-broadband.c +++ /dev/null @@ -1,1013 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2012 Aleksander Morgado - */ - -#include -#include -#include -#include "nm-modem-broadband.h" -#include "nm-system.h" -#include "nm-setting-connection.h" -#include "nm-logging.h" -#include "NetworkManagerUtils.h" -#include "nm-device-private.h" - -G_DEFINE_TYPE (NMModemBroadband, nm_modem_broadband, NM_TYPE_MODEM) - -struct _NMModemBroadbandPrivate { - /* The modem object from dbus */ - MMObject *modem_object; - /* Per-interface objects */ - MMModem *modem_iface; - MMModemSimple *simple_iface; - - /* Connection setup */ - MMSimpleConnectProperties *connect_properties; - MMBearer *bearer; - MMBearerIpConfig *ipv4_config; - MMBearerIpConfig *ipv6_config; - - guint32 pin_tries; -}; - -enum { - PROP_0, - PROP_MODEM, -}; - -#define MODEM_CAPS_3GPP(caps) (caps & (MM_MODEM_CAPABILITY_GSM_UMTS | \ - MM_MODEM_CAPABILITY_LTE | \ - MM_MODEM_CAPABILITY_LTE_ADVANCED)) - -#define MODEM_CAPS_3GPP2(caps) (caps & (MM_MODEM_CAPABILITY_CDMA_EVDO)) - -/* Maximum time to keep the DBus call waiting for a connection result */ -#define MODEM_CONNECT_TIMEOUT_SECS 120 - -/*****************************************************************************/ - -#define NM_MODEM_BROADBAND_ERROR (nm_modem_broadband_error_quark ()) - -static GQuark -nm_modem_broadband_error_quark (void) -{ - static GQuark quark = 0; - if (!quark) - quark = g_quark_from_static_string ("nm-modem-broadband-error"); - return quark; -} - -static NMDeviceStateReason -translate_mm_error (GError *error) -{ - NMDeviceStateReason reason; - - if (g_error_matches (error, MM_CONNECTION_ERROR, MM_CONNECTION_ERROR_NO_CARRIER)) - reason = NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER; - else if (g_error_matches (error, MM_CONNECTION_ERROR, MM_CONNECTION_ERROR_NO_DIALTONE)) - reason = NM_DEVICE_STATE_REASON_MODEM_NO_DIAL_TONE; - else if (g_error_matches (error, MM_CONNECTION_ERROR, MM_CONNECTION_ERROR_BUSY)) - reason = NM_DEVICE_STATE_REASON_MODEM_BUSY; - else if (g_error_matches (error, MM_CONNECTION_ERROR, MM_CONNECTION_ERROR_NO_ANSWER)) - reason = NM_DEVICE_STATE_REASON_MODEM_DIAL_TIMEOUT; - else if (g_error_matches (error, MM_MOBILE_EQUIPMENT_ERROR, MM_MOBILE_EQUIPMENT_ERROR_NETWORK_NOT_ALLOWED)) - reason = NM_DEVICE_STATE_REASON_GSM_REGISTRATION_DENIED; - else if (g_error_matches (error, MM_MOBILE_EQUIPMENT_ERROR, MM_MOBILE_EQUIPMENT_ERROR_NETWORK_TIMEOUT)) - reason = NM_DEVICE_STATE_REASON_GSM_REGISTRATION_TIMEOUT; - else if (g_error_matches (error, MM_MOBILE_EQUIPMENT_ERROR, MM_MOBILE_EQUIPMENT_ERROR_NO_NETWORK)) - reason = NM_DEVICE_STATE_REASON_GSM_REGISTRATION_NOT_SEARCHING; - else if (g_error_matches (error, MM_MOBILE_EQUIPMENT_ERROR, MM_MOBILE_EQUIPMENT_ERROR_SIM_NOT_INSERTED)) - reason = NM_DEVICE_STATE_REASON_GSM_SIM_NOT_INSERTED; - else if (g_error_matches (error, MM_MOBILE_EQUIPMENT_ERROR, MM_MOBILE_EQUIPMENT_ERROR_SIM_PIN)) - reason = NM_DEVICE_STATE_REASON_GSM_SIM_PIN_REQUIRED; - else if (g_error_matches (error, MM_MOBILE_EQUIPMENT_ERROR, MM_MOBILE_EQUIPMENT_ERROR_SIM_PUK)) - reason = NM_DEVICE_STATE_REASON_GSM_SIM_PUK_REQUIRED; - else if (g_error_matches (error, MM_MOBILE_EQUIPMENT_ERROR, MM_MOBILE_EQUIPMENT_ERROR_SIM_WRONG)) - reason = NM_DEVICE_STATE_REASON_GSM_SIM_WRONG; - else { - /* unable to map the ModemManager error to a NM_DEVICE_STATE_REASON */ - nm_log_dbg (LOGD_MB, "unmapped error detected: '%s'", error->message); - reason = NM_DEVICE_STATE_REASON_UNKNOWN; - } - - return reason; -} - -/*****************************************************************************/ - -void -nm_modem_broadband_get_capabilities (NMModemBroadband *self, - NMDeviceModemCapabilities *modem_caps, - NMDeviceModemCapabilities *current_caps) -{ - MMModemCapability all_supported = MM_MODEM_CAPABILITY_NONE; - MMModemCapability *supported; - guint n_supported; - - /* For now, we don't care about the capability combinations, just merge all - * combinations in a single mask */ - if (mm_modem_get_supported_capabilities (self->priv->modem_iface, &supported, &n_supported)) { - guint i; - - for (i = 0; i < n_supported; i++) - all_supported |= supported[i]; - - g_free (supported); - } - - *modem_caps = (NMDeviceModemCapabilities) all_supported; - *current_caps = (NMDeviceModemCapabilities) mm_modem_get_current_capabilities (self->priv->modem_iface); -} - -/*****************************************************************************/ - -static void -ask_for_pin (NMModemBroadband *self) -{ - guint32 tries; - - tries = self->priv->pin_tries++; - nm_modem_get_secrets (NM_MODEM (self), - NM_SETTING_GSM_SETTING_NAME, - tries ? TRUE : FALSE, - NM_SETTING_GSM_PIN); -} - -static void -connect_ready (MMModemSimple *simple_iface, - GAsyncResult *res, - NMModemBroadband *self) -{ - GError *error = NULL; - guint ip_method; - - g_clear_object (&self->priv->connect_properties); - - self->priv->bearer = mm_modem_simple_connect_finish (simple_iface, res, &error); - if (!self->priv->bearer) { - if (g_error_matches (error, - MM_MOBILE_EQUIPMENT_ERROR, - MM_MOBILE_EQUIPMENT_ERROR_SIM_PIN) || - (g_error_matches (error, - MM_CORE_ERROR, - MM_CORE_ERROR_UNAUTHORIZED) && - mm_modem_get_unlock_required (self->priv->modem_iface) == MM_MODEM_LOCK_SIM_PIN)) { - /* Request PIN */ - ask_for_pin (self); - } else { - /* Strip remote error info before logging it */ - if (g_dbus_error_is_remote_error (error)) - g_dbus_error_strip_remote_error (error); - - nm_log_warn (LOGD_MB, "(%s) failed to connect modem: %s", - nm_modem_get_uid (NM_MODEM (self)), - error && error->message ? error->message : "(unknown)"); - g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, translate_mm_error (error)); - } - - g_clear_error (&error); - g_object_unref (self); - return; - } - - /* Grab IP configurations */ - self->priv->ipv4_config = mm_bearer_get_ipv4_config (self->priv->bearer); - self->priv->ipv6_config = mm_bearer_get_ipv6_config (self->priv->bearer); - - switch (mm_bearer_ip_config_get_method (self->priv->ipv4_config)) { - case MM_BEARER_IP_METHOD_PPP: - ip_method = MM_MODEM_IP_METHOD_PPP; - break; - case MM_BEARER_IP_METHOD_STATIC: - ip_method = MM_MODEM_IP_METHOD_STATIC; - break; - case MM_BEARER_IP_METHOD_DHCP: - ip_method = MM_MODEM_IP_METHOD_DHCP; - break; - default: - error = g_error_new (NM_MODEM_BROADBAND_ERROR, - NM_MODEM_BROADBAND_ERROR_CONNECTION_INVALID, - "invalid IP config"); - nm_log_warn (LOGD_MB, "(%s) failed to connect modem: %s", - nm_modem_get_uid (NM_MODEM (self)), - error->message); - g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, translate_mm_error (error)); - g_error_free (error); - g_object_unref (self); - return; - } - - /* IPv4 for now only */ - g_object_set (self, - NM_MODEM_DATA_PORT, mm_bearer_get_interface (self->priv->bearer), - NM_MODEM_IP_METHOD, ip_method, - NM_MODEM_IP_TIMEOUT, mm_bearer_get_ip_timeout (self->priv->bearer), - NULL); - - g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, TRUE, NM_DEVICE_STATE_REASON_NONE); - g_object_unref (self); -} - -static MMSimpleConnectProperties * -create_cdma_connect_properties (NMConnection *connection) -{ - NMSettingCdma *setting; - MMSimpleConnectProperties *properties; - const gchar *str; - - setting = nm_connection_get_setting_cdma (connection); - properties = mm_simple_connect_properties_new (); - - str = nm_setting_cdma_get_number (setting); - if (str) - mm_simple_connect_properties_set_number (properties, str); - - return properties; -} - -static MMSimpleConnectProperties * -create_gsm_connect_properties (NMConnection *connection) -{ - NMSettingGsm *setting; - NMSettingPPP *s_ppp; - MMSimpleConnectProperties *properties; - const gchar *str; - - setting = nm_connection_get_setting_gsm (connection); - properties = mm_simple_connect_properties_new (); - - /* TODO: not needed */ - str = nm_setting_gsm_get_number (setting); - if (str) - mm_simple_connect_properties_set_number (properties, str); - - str = nm_setting_gsm_get_apn (setting); - if (str) - mm_simple_connect_properties_set_apn (properties, str); - - str = nm_setting_gsm_get_network_id (setting); - if (str) - mm_simple_connect_properties_set_operator_id (properties, str); - - str = nm_setting_gsm_get_pin (setting); - if (str) - mm_simple_connect_properties_set_pin (properties, str); - - str = nm_setting_gsm_get_username (setting); - if (str) - mm_simple_connect_properties_set_user (properties, str); - - str = nm_setting_gsm_get_password (setting); - if (str) - mm_simple_connect_properties_set_password (properties, str); - - /* Roaming */ - if (nm_setting_gsm_get_home_only (setting)) - mm_simple_connect_properties_set_allow_roaming (properties, FALSE); - - /* For IpMethod == STATIC or DHCP */ - s_ppp = nm_connection_get_setting_ppp (connection); - if (s_ppp) { - MMBearerAllowedAuth allowed_auth = MM_BEARER_ALLOWED_AUTH_UNKNOWN; - - if (nm_setting_ppp_get_noauth (s_ppp)) - allowed_auth = MM_BEARER_ALLOWED_AUTH_NONE; - if (!nm_setting_ppp_get_refuse_pap (s_ppp)) - allowed_auth |= MM_BEARER_ALLOWED_AUTH_PAP; - if (!nm_setting_ppp_get_refuse_chap (s_ppp)) - allowed_auth |= MM_BEARER_ALLOWED_AUTH_CHAP; - if (!nm_setting_ppp_get_refuse_mschap (s_ppp)) - allowed_auth |= MM_BEARER_ALLOWED_AUTH_MSCHAP; - if (!nm_setting_ppp_get_refuse_mschapv2 (s_ppp)) - allowed_auth |= MM_BEARER_ALLOWED_AUTH_MSCHAPV2; - if (!nm_setting_ppp_get_refuse_eap (s_ppp)) - allowed_auth |= MM_BEARER_ALLOWED_AUTH_EAP; - - mm_simple_connect_properties_set_allowed_auth (properties, allowed_auth); - } - - return properties; -} - -static NMActStageReturn -act_stage1_prepare (NMModem *_self, - NMActRequest *req, - GPtrArray **out_hints, - const char **out_setting_name, - NMDeviceStateReason *reason) -{ - NMModemBroadband *self = NM_MODEM_BROADBAND (_self); - NMConnection *connection; - - connection = nm_act_request_get_connection (req); - g_assert (connection); - - *out_setting_name = nm_connection_need_secrets (connection, out_hints); - if (!*out_setting_name) { - MMModemCapability caps; - - caps = mm_modem_get_current_capabilities (self->priv->modem_iface); - - g_clear_object (&self->priv->connect_properties); - - if (MODEM_CAPS_3GPP (caps)) - self->priv->connect_properties = create_gsm_connect_properties (connection); - else if (MODEM_CAPS_3GPP2 (caps)) - self->priv->connect_properties = create_cdma_connect_properties (connection); - else { - nm_log_warn (LOGD_MB, "(%s) not a mobile broadband modem", - nm_modem_get_uid (NM_MODEM (self))); - return NM_ACT_STAGE_RETURN_FAILURE; - } - - if (!self->priv->simple_iface) - self->priv->simple_iface = mm_object_get_modem_simple (self->priv->modem_object); - - g_dbus_proxy_set_default_timeout (G_DBUS_PROXY (self->priv->simple_iface), MODEM_CONNECT_TIMEOUT_SECS * 1000); - mm_modem_simple_connect (self->priv->simple_iface, - self->priv->connect_properties, - NULL, - (GAsyncReadyCallback)connect_ready, - g_object_ref (self)); - } else { - /* NMModem will handle requesting secrets... */ - } - - return NM_ACT_STAGE_RETURN_POSTPONE; -} - -/*****************************************************************************/ - -static NMConnection * -get_best_auto_connection (NMModem *_self, - GSList *connections, - char **specific_object) -{ - NMModemBroadband *self = NM_MODEM_BROADBAND (_self); - MMModemCapability modem_caps; - GSList *iter; - - modem_caps = mm_modem_get_current_capabilities (self->priv->modem_iface); - - for (iter = connections; iter; iter = g_slist_next (iter)) { - NMConnection *connection = NM_CONNECTION (iter->data); - NMSettingConnection *s_con; - - s_con = nm_connection_get_setting_connection (connection); - g_assert (s_con); - - if (!nm_setting_connection_get_autoconnect (s_con)) - continue; - - /* If GSM settings given and our modem is 3GPP, those are the best ones */ - if ( g_str_equal (nm_setting_connection_get_connection_type (s_con), - NM_SETTING_GSM_SETTING_NAME) - && MODEM_CAPS_3GPP (modem_caps)) - return connection; - - /* If CDMA settings given and our modem is 3GPP2, return those */ - if ( g_str_equal (nm_setting_connection_get_connection_type (s_con), - NM_SETTING_CDMA_SETTING_NAME) - && MODEM_CAPS_3GPP2 (modem_caps)) - return connection; - - /* continue */ - } - - return NULL; -} - -/*****************************************************************************/ - -static gboolean -check_connection_compatible (NMModem *_self, - NMConnection *connection, - GError **error) -{ - NMModemBroadband *self = NM_MODEM_BROADBAND (_self); - MMModemCapability modem_caps; - NMSettingConnection *s_con; - - modem_caps = mm_modem_get_current_capabilities (self->priv->modem_iface); - s_con = nm_connection_get_setting_connection (connection); - g_assert (s_con); - - if (MODEM_CAPS_3GPP (modem_caps)) { - NMSettingGsm *s_gsm; - - if (!g_str_equal (nm_setting_connection_get_connection_type (s_con), - NM_SETTING_GSM_SETTING_NAME)) { - g_set_error (error, - NM_MODEM_BROADBAND_ERROR, - NM_MODEM_BROADBAND_ERROR_CONNECTION_NOT_GSM, - "The connection was not a 3GPP connection."); - return FALSE; - } - - s_gsm = nm_connection_get_setting_gsm (connection); - if (!s_gsm) { - g_set_error (error, - NM_MODEM_BROADBAND_ERROR, - NM_MODEM_BROADBAND_ERROR_CONNECTION_INVALID, - "The connection was not a valid 3GPP connection."); - return FALSE; - } - - return TRUE; - } - - if (MODEM_CAPS_3GPP2 (modem_caps)) { - NMSettingCdma *s_cdma; - - if (!g_str_equal (nm_setting_connection_get_connection_type (s_con), - NM_SETTING_CDMA_SETTING_NAME)) { - g_set_error (error, - NM_MODEM_BROADBAND_ERROR, - NM_MODEM_BROADBAND_ERROR_CONNECTION_NOT_CDMA, - "The connection was not a 3GPP2 connection."); - return FALSE; - } - - s_cdma = nm_connection_get_setting_cdma (connection); - if (!s_cdma) { - g_set_error (error, - NM_MODEM_BROADBAND_ERROR, - NM_MODEM_BROADBAND_ERROR_CONNECTION_INVALID, - "The connection was not a valid 3GPP2 connection."); - return FALSE; - } - - return TRUE; - } - - g_set_error (error, - NM_MODEM_BROADBAND_ERROR, - NM_MODEM_BROADBAND_ERROR_CONNECTION_INCOMPATIBLE, - "Device is not a mobile broadband modem"); - return FALSE; -} - -/*****************************************************************************/ - -static gboolean -complete_connection (NMModem *_self, - NMConnection *connection, - const GSList *existing_connections, - GError **error) -{ - NMModemBroadband *self = NM_MODEM_BROADBAND (_self); - MMModemCapability modem_caps; - NMSettingPPP *s_ppp; - - modem_caps = mm_modem_get_current_capabilities (self->priv->modem_iface); - - /* PPP settings common to 3GPP and 3GPP2 */ - s_ppp = nm_connection_get_setting_ppp (connection); - if (!s_ppp) { - s_ppp = (NMSettingPPP *) nm_setting_ppp_new (); - g_object_set (G_OBJECT (s_ppp), - NM_SETTING_PPP_LCP_ECHO_FAILURE, 5, - NM_SETTING_PPP_LCP_ECHO_INTERVAL, 30, - NULL); - nm_connection_add_setting (connection, NM_SETTING (s_ppp)); - } - - if (MODEM_CAPS_3GPP (modem_caps)) { - NMSettingGsm *s_gsm; - - s_gsm = nm_connection_get_setting_gsm (connection); - if (!s_gsm || !nm_setting_gsm_get_apn (s_gsm)) { - /* Need an APN at least */ - g_set_error_literal (error, - NM_SETTING_GSM_ERROR, - NM_SETTING_GSM_ERROR_MISSING_PROPERTY, - NM_SETTING_GSM_APN); - return FALSE; - } - - /* TODO: This is not needed */ - if (!nm_setting_gsm_get_number (s_gsm)) - g_object_set (G_OBJECT (s_gsm), NM_SETTING_GSM_NUMBER, "*99#", NULL); - - nm_utils_complete_generic (connection, - NM_SETTING_GSM_SETTING_NAME, - existing_connections, - _("GSM connection %d"), - NULL, - FALSE); /* No IPv6 yet by default */ - - return TRUE; - } - - if (MODEM_CAPS_3GPP2 (modem_caps)) { - NMSettingCdma *s_cdma; - - s_cdma = nm_connection_get_setting_cdma (connection); - if (!s_cdma) { - s_cdma = (NMSettingCdma *) nm_setting_cdma_new (); - nm_connection_add_setting (connection, NM_SETTING (s_cdma)); - } - - if (!nm_setting_cdma_get_number (s_cdma)) - g_object_set (G_OBJECT (s_cdma), NM_SETTING_CDMA_NUMBER, "#777", NULL); - - nm_utils_complete_generic (connection, - NM_SETTING_CDMA_SETTING_NAME, - existing_connections, - _("CDMA connection %d"), - NULL, - FALSE); /* No IPv6 yet by default */ - - return TRUE; - } - - g_set_error (error, - NM_MODEM_BROADBAND_ERROR, - NM_MODEM_BROADBAND_ERROR_CONNECTION_INCOMPATIBLE, - "Device is not a mobile broadband modem"); - return FALSE; -} - -/*****************************************************************************/ - -static gboolean -get_user_pass (NMModem *modem, - NMConnection *connection, - const char **user, - const char **pass) -{ - NMSettingGsm *s_gsm; - NMSettingCdma *s_cdma; - - s_gsm = nm_connection_get_setting_gsm (connection); - s_cdma = nm_connection_get_setting_cdma (connection); - if (!s_gsm && !s_cdma) - return FALSE; - - if (user) { - if (s_gsm) - *user = nm_setting_gsm_get_username (s_gsm); - else if (s_cdma) - *user = nm_setting_cdma_get_username (s_cdma); - } - if (pass) { - if (s_gsm) - *pass = nm_setting_gsm_get_password (s_gsm); - else if (s_cdma) - *pass = nm_setting_cdma_get_password (s_cdma); - } - - return TRUE; -} - -/*****************************************************************************/ - -static const char * -get_setting_name (NMModem *_self) -{ - NMModemBroadband *self = NM_MODEM_BROADBAND (_self); - MMModemCapability modem_caps; - - modem_caps = mm_modem_get_current_capabilities (self->priv->modem_iface); - if (MODEM_CAPS_3GPP (modem_caps)) - return NM_SETTING_GSM_SETTING_NAME; - - if (MODEM_CAPS_3GPP2 (modem_caps)) - return NM_SETTING_CDMA_SETTING_NAME; - - return "unknown"; -} - -/*****************************************************************************/ -/* Query/Update enabled state */ - -static void -update_mm_enabled (NMModem *self, - gboolean new_enabled) -{ - if (nm_modem_get_mm_enabled (self) != new_enabled) { - g_object_set (self, - NM_MODEM_ENABLED, new_enabled, - NULL); - } -} - -static void -modem_disable_ready (MMModem *modem_iface, - GAsyncResult *res, - NMModemBroadband *self) -{ - GError *error = NULL; - - if (!mm_modem_disable_finish (modem_iface, res, &error)) { - nm_log_warn (LOGD_MB, "(%s) failed to disable modem: %s", - nm_modem_get_uid (NM_MODEM (self)), - error && error->message ? error->message : "(unknown)"); - g_clear_error (&error); - } else - /* Update enabled/disabled state again */ - update_mm_enabled (NM_MODEM (self), FALSE); - - /* Balance refcount */ - g_object_unref (self); -} - -static void -modem_enable_ready (MMModem *modem_iface, - GAsyncResult *res, - NMModemBroadband *self) -{ - GError *error = NULL; - - if (!mm_modem_enable_finish (modem_iface, res, &error)) { - nm_log_warn (LOGD_MB, "(%s) failed to enable modem: %s", - nm_modem_get_uid (NM_MODEM (self)), - error && error->message ? error->message : "(unknown)"); - g_clear_error (&error); - } else - update_mm_enabled (NM_MODEM (self), TRUE); - - /* Balance refcount */ - g_object_unref (self); -} - -static void -set_mm_enabled (NMModem *_self, - gboolean enabled) -{ - NMModemBroadband *self = NM_MODEM_BROADBAND (_self); - - if (enabled) { - /* Don't even try to enable if we're known to be already locked */ - if (mm_modem_get_state (self->priv->modem_iface) == MM_MODEM_STATE_LOCKED) { - nm_log_warn (LOGD_MB, "(%s) cannot enable modem: locked", - nm_modem_get_uid (NM_MODEM (self))); - g_signal_emit_by_name (self, NM_MODEM_AUTH_REQUESTED, 0); - return; - } - - mm_modem_enable (self->priv->modem_iface, - NULL, /* cancellable */ - (GAsyncReadyCallback)modem_enable_ready, - g_object_ref (self)); - } else { - mm_modem_disable (self->priv->modem_iface, - NULL, /* cancellable */ - (GAsyncReadyCallback)modem_disable_ready, - g_object_ref (self)); - - /* When disabling don't say we're enabled */ - update_mm_enabled (NM_MODEM (self), enabled); - } -} - -/*****************************************************************************/ -/* IP method static */ - -static gboolean -ip_string_to_network_address (const gchar *str, - guint32 *out) -{ - struct in_addr addr; - - /* IP address */ - if (inet_pton (AF_INET, str, &addr) <= 0) - return FALSE; - - *out = (guint32)addr.s_addr; - return TRUE; -} - -static gboolean -static_stage3_done (NMModemBroadband *self) -{ - GError *error = NULL; - NMIP4Config *config = NULL; - const gchar *address_string; - guint32 address_network; - NMIP4Address *addr; - const gchar **dns; - guint i; - guint prefix; - - g_assert (self->priv->ipv4_config); - - nm_log_info (LOGD_MB, "(%s): IPv4 static configuration:", - nm_modem_get_uid (NM_MODEM (self))); - - /* Fully fail if invalid IP address retrieved */ - address_string = mm_bearer_ip_config_get_address (self->priv->ipv4_config); - if (!ip_string_to_network_address (address_string, &address_network)) { - error = g_error_new (NM_MODEM_BROADBAND_ERROR, - NM_MODEM_BROADBAND_ERROR_CONNECTION_INVALID, - "(%s) retrieving IP4 configuration failed: invalid address given '%s'", - nm_modem_get_uid (NM_MODEM (self)), - address_string); - goto out; - } - - config = nm_ip4_config_new (); - addr = nm_ip4_address_new (); - nm_ip4_address_set_address (addr, address_network); - prefix = mm_bearer_ip_config_get_prefix (self->priv->ipv4_config); - if (prefix > 0) - nm_ip4_address_set_prefix (addr, prefix); - nm_ip4_config_take_address (config, addr); - - nm_log_info (LOGD_MB, " address %s/%d", - mm_bearer_ip_config_get_address (self->priv->ipv4_config), - mm_bearer_ip_config_get_prefix (self->priv->ipv4_config)); - - /* DNS servers */ - dns = mm_bearer_ip_config_get_dns (self->priv->ipv4_config); - for (i = 0; dns[i]; i++) { - if ( ip_string_to_network_address (dns[i], &address_network) - && address_network > 0) { - nm_ip4_config_add_nameserver (config, address_network); - nm_log_info (LOGD_MB, " DNS %s", dns[i]); - } - } - -out: - g_signal_emit_by_name (self, NM_MODEM_IP4_CONFIG_RESULT, config, error); - g_clear_error (&error); - return FALSE; -} - -static NMActStageReturn -static_stage3_ip4_config_start (NMModem *_self, - NMActRequest *req, - NMDeviceStateReason *reason) -{ - NMModemBroadband *self = NM_MODEM_BROADBAND (_self); - - /* We schedule it in an idle just to follow the same logic as in the - * generic modem implementation. */ - g_idle_add ((GSourceFunc)static_stage3_done, self); - - return NM_ACT_STAGE_RETURN_POSTPONE; -} - -/*****************************************************************************/ -/* Disconnect */ - -typedef struct { - NMModemBroadband *self; - gboolean warn; -} SimpleDisconnectContext; - -static void -simple_disconnect_context_free (SimpleDisconnectContext *ctx) -{ - g_object_unref (ctx->self); - g_slice_free (SimpleDisconnectContext, ctx); -} - -static void -simple_disconnect_ready (MMModemSimple *modem_iface, - GAsyncResult *res, - SimpleDisconnectContext *ctx) -{ - GError *error = NULL; - - if (!mm_modem_simple_disconnect_finish (modem_iface, res, &error)) { - if (ctx->warn) - nm_log_warn (LOGD_MB, "(%s) failed to disconnect modem: %s", - nm_modem_get_uid (NM_MODEM (ctx->self)), - error && error->message ? error->message : "(unknown)"); - g_clear_error (&error); - } - - simple_disconnect_context_free (ctx); -} - -static void -disconnect (NMModem *self, - gboolean warn) -{ - SimpleDisconnectContext *ctx; - - ctx = g_slice_new (SimpleDisconnectContext); - ctx->self = g_object_ref (self); - - /* Don't bother warning on FAILED since the modem is already gone */ - ctx->warn = warn; - - mm_modem_simple_disconnect ( - ctx->self->priv->simple_iface, - NULL, /* bearer path; if NULL given ALL get disconnected */ - NULL, /* cancellable */ - (GAsyncReadyCallback)simple_disconnect_ready, - ctx); -} - -/*****************************************************************************/ - -static void -deactivate (NMModem *_self, NMDevice *device) -{ - NMModemBroadband *self = NM_MODEM_BROADBAND (_self); - - /* TODO: cancel SimpleConnect() if any */ - - /* Cleanup IPv4 addresses and routes */ - g_clear_object (&self->priv->ipv4_config); - g_clear_object (&self->priv->ipv6_config); - g_clear_object (&self->priv->bearer); - - self->priv->pin_tries = 0; - - /* Chain up parent's */ - NM_MODEM_CLASS (nm_modem_broadband_parent_class)->deactivate (_self, device); -} - -/*****************************************************************************/ - -static void -modem_state_changed (MMModem *modem, - MMModemState old_state, - MMModemState new_state, - MMModemStateChangeReason reason, - NMModemBroadband *self) -{ - gboolean old; - gboolean new; - - nm_log_info (LOGD_MB, "(%s) modem state changed, '%s' --> '%s' (reason: %s)\n", - nm_modem_get_uid (NM_MODEM (self)), - mm_modem_state_get_string (old_state), - mm_modem_state_get_string (new_state), - mm_modem_state_change_reason_get_string (reason)); - - old = nm_modem_get_mm_enabled (NM_MODEM (self)); - new = (mm_modem_get_state (self->priv->modem_iface) >= MM_MODEM_STATE_ENABLED); - if (old != new) - g_object_set (self, - NM_MODEM_ENABLED, new, - NULL); - - old = nm_modem_get_mm_connected (NM_MODEM (self)); - new = (mm_modem_get_state (self->priv->modem_iface) >= MM_MODEM_STATE_CONNECTED); - if (old != new) - g_object_set (self, - NM_MODEM_CONNECTED, new, - NULL); -} - -/*****************************************************************************/ - -NMModem * -nm_modem_broadband_new (GObject *object) -{ - MMObject *modem_object; - MMModem *modem_iface; - - g_return_val_if_fail (MM_IS_OBJECT (object), NULL); - modem_object = MM_OBJECT (object); - - /* Ensure we have the 'Modem' interface and the primary port at least */ - modem_iface = mm_object_peek_modem (modem_object); - g_return_val_if_fail (!!modem_iface, NULL); - g_return_val_if_fail (!!mm_modem_get_primary_port (modem_iface), NULL); - - /* If the modem is in 'FAILED' state we cannot do anything with it. - * This happens when a severe error happened when trying to initialize it, - * like missing SIM. */ - if (mm_modem_get_state (modem_iface) == MM_MODEM_STATE_FAILED) { - nm_log_warn (LOGD_MB, "(%s): unusable modem detected", - mm_modem_get_primary_port (modem_iface)); - return NULL; - } - - return (NMModem *) g_object_new (NM_TYPE_MODEM_BROADBAND, - NM_MODEM_PATH, mm_object_get_path (modem_object), - NM_MODEM_UID, mm_modem_get_primary_port (modem_iface), - NM_MODEM_CONTROL_PORT, mm_modem_get_primary_port (modem_iface), - NM_MODEM_DATA_PORT, NULL, /* We don't know it until bearer created */ - NM_MODEM_BROADBAND_MODEM, modem_object, - NULL); -} - -static void -nm_modem_broadband_init (NMModemBroadband *self) -{ - self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, - NM_TYPE_MODEM_BROADBAND, - NMModemBroadbandPrivate); -} - -static void -set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - NMModemBroadband *self = NM_MODEM_BROADBAND (object); - - switch (prop_id) { - case PROP_MODEM: - /* construct-only */ - self->priv->modem_object = g_value_dup_object (value); - self->priv->modem_iface = mm_object_get_modem (self->priv->modem_object); - g_assert (self->priv->modem_iface != NULL); - g_signal_connect (self->priv->modem_iface, - "state-changed", - G_CALLBACK (modem_state_changed), - self); - - g_object_set (object, - NM_MODEM_ENABLED, (mm_modem_get_state (self->priv->modem_iface) >= MM_MODEM_STATE_ENABLED), - NM_MODEM_CONNECTED, (mm_modem_get_state (self->priv->modem_iface) >= MM_MODEM_STATE_CONNECTED), - NULL); - - /* Note: don't grab the Simple iface here; the Modem interface is the - * only one assumed to be always valid and available */ - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - NMModemBroadband *self = NM_MODEM_BROADBAND (object); - - switch (prop_id) { - case PROP_MODEM: - g_value_set_object (value, self->priv->modem_object); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -dispose (GObject *object) -{ - NMModemBroadband *self = NM_MODEM_BROADBAND (object); - - g_clear_object (&self->priv->ipv4_config); - g_clear_object (&self->priv->ipv6_config); - g_clear_object (&self->priv->bearer); - g_clear_object (&self->priv->modem_iface); - g_clear_object (&self->priv->simple_iface); - g_clear_object (&self->priv->modem_object); - - G_OBJECT_CLASS (nm_modem_broadband_parent_class)->dispose (object); -} - -static void -nm_modem_broadband_class_init (NMModemBroadbandClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - NMModemClass *modem_class = NM_MODEM_CLASS (klass); - - g_type_class_add_private (object_class, sizeof (NMModemBroadbandPrivate)); - - /* Virtual methods */ - object_class->dispose = dispose; - object_class->get_property = get_property; - object_class->set_property = set_property; - - modem_class->static_stage3_ip4_config_start = static_stage3_ip4_config_start; - modem_class->disconnect = disconnect; - modem_class->deactivate = deactivate; - modem_class->set_mm_enabled = set_mm_enabled; - modem_class->get_user_pass = get_user_pass; - modem_class->get_setting_name = get_setting_name; - modem_class->get_best_auto_connection = get_best_auto_connection; - modem_class->check_connection_compatible = check_connection_compatible; - modem_class->complete_connection = complete_connection; - modem_class->act_stage1_prepare = act_stage1_prepare; - - /* Properties */ - g_object_class_install_property - (object_class, PROP_MODEM, - g_param_spec_object (NM_MODEM_BROADBAND_MODEM, - "Modem", - "Broadband modem object", - MM_GDBUS_TYPE_OBJECT, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); -} diff --git a/src/modem-manager/nm-modem-broadband.h b/src/modem-manager/nm-modem-broadband.h deleted file mode 100644 index 005c3853..00000000 --- a/src/modem-manager/nm-modem-broadband.h +++ /dev/null @@ -1,69 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2012 - Aleksander Morgado - */ - -#ifndef NM_MODEM_BROADBAND_H -#define NM_MODEM_BROADBAND_H - -#include -#include -#include "nm-modem.h" - -G_BEGIN_DECLS - -#define NM_TYPE_MODEM_BROADBAND (nm_modem_broadband_get_type ()) -#define NM_MODEM_BROADBAND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_MODEM_BROADBAND, NMModemBroadband)) -#define NM_MODEM_BROADBAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_MODEM_BROADBAND, NMModemBroadbandClass)) -#define NM_IS_MODEM_BROADBAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_MODEM_BROADBAND)) -#define NM_IS_MODEM_BROADBAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_MODEM_BROADBAND)) -#define NM_MODEM_BROADBAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_MODEM_BROADBAND, NMModemBroadbandClass)) - -#define NM_MODEM_BROADBAND_MODEM "modem" - -typedef struct _NMModemBroadband NMModemBroadband; -typedef struct _NMModemBroadbandClass NMModemBroadbandClass; -typedef struct _NMModemBroadbandPrivate NMModemBroadbandPrivate; - -typedef enum { - NM_MODEM_BROADBAND_ERROR_CONNECTION_NOT_GSM, /*< nick=ConnectionNotGsm >*/ - NM_MODEM_BROADBAND_ERROR_CONNECTION_NOT_CDMA, /*< nick=ConnectionNotCdma >*/ - NM_MODEM_BROADBAND_ERROR_CONNECTION_INVALID, /*< nick=ConnectionInvalid >*/ - NM_MODEM_BROADBAND_ERROR_CONNECTION_INCOMPATIBLE, /*< nick=ConnectionIncompatible >*/ -} NMModemBroadbandError; - -struct _NMModemBroadband { - NMModem parent; - NMModemBroadbandPrivate *priv; -}; - -struct _NMModemBroadbandClass { - NMModemClass parent; -}; - -GType nm_modem_broadband_get_type (void); - -NMModem *nm_modem_broadband_new (GObject *object); - -void nm_modem_broadband_get_capabilities (NMModemBroadband *self, - NMDeviceModemCapabilities *modem_caps, - NMDeviceModemCapabilities *current_caps); - -G_END_DECLS - -#endif /* NM_MODEM_BROADBAND_H */ diff --git a/src/modem-manager/nm-modem-cdma.c b/src/modem-manager/nm-modem-cdma.c deleted file mode 100644 index 6bed8c2a..00000000 --- a/src/modem-manager/nm-modem-cdma.c +++ /dev/null @@ -1,358 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2009 - 2011 Red Hat, Inc. - * Copyright (C) 2009 Novell, Inc. - */ - -#include "config.h" - -#include -#include - -#include "nm-dbus-glib-types.h" -#include "nm-modem-cdma.h" -#include "nm-modem-types.h" -#include "nm-enum-types.h" -#include "nm-device.h" -#include "nm-device-private.h" -#include "nm-dbus-manager.h" -#include "nm-setting-connection.h" -#include "nm-setting-cdma.h" -#include "nm-setting-ppp.h" -#include "NetworkManagerUtils.h" -#include "nm-logging.h" - -G_DEFINE_TYPE (NMModemCdma, nm_modem_cdma, NM_TYPE_MODEM_GENERIC) - -#define NM_MODEM_CDMA_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_MODEM_CDMA, NMModemCdmaPrivate)) - -typedef struct { - DBusGProxyCall *call; - - GHashTable *connect_properties; -} NMModemCdmaPrivate; - - -#define NM_CDMA_ERROR (nm_cdma_error_quark ()) - -static GQuark -nm_cdma_error_quark (void) -{ - static GQuark quark = 0; - if (!quark) - quark = g_quark_from_static_string ("nm-cdma-error"); - return quark; -} - - -NMModem * -nm_modem_cdma_new (const char *path, - const char *data_device, - guint32 ip_method, - NMModemState state) -{ - g_return_val_if_fail (path != NULL, NULL); - g_return_val_if_fail (data_device != NULL, NULL); - - return (NMModem *) g_object_new (NM_TYPE_MODEM_CDMA, - NM_MODEM_PATH, path, - NM_MODEM_UID, data_device, - NM_MODEM_CONTROL_PORT, NULL, - NM_MODEM_DATA_PORT, data_device, - NM_MODEM_IP_METHOD, ip_method, - NM_MODEM_CONNECTED, (state == NM_MODEM_STATE_CONNECTED), - NULL); -} - -static void -stage1_prepare_done (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) -{ - NMModemCdma *self = NM_MODEM_CDMA (user_data); - NMModemCdmaPrivate *priv = NM_MODEM_CDMA_GET_PRIVATE (self); - GError *error = NULL; - - priv->call = NULL; - - if (priv->connect_properties) { - g_hash_table_destroy (priv->connect_properties); - priv->connect_properties = NULL; - } - - if (dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_INVALID)) - g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, TRUE, NM_DEVICE_STATE_REASON_NONE); - else { - nm_log_warn (LOGD_MB, "CDMA connection failed: (%d) %s", - error ? error->code : -1, - error && error->message ? error->message : "(unknown)"); - g_error_free (error); - g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, NM_DEVICE_STATE_REASON_NONE); - } -} - -static void -do_connect (NMModemCdma *self) -{ - NMModemCdmaPrivate *priv = NM_MODEM_CDMA_GET_PRIVATE (self); - DBusGProxy *proxy; - - proxy = nm_modem_generic_get_proxy (NM_MODEM_GENERIC (self), MM_OLD_DBUS_INTERFACE_MODEM_SIMPLE); - priv->call = dbus_g_proxy_begin_call_with_timeout (proxy, - "Connect", stage1_prepare_done, - self, NULL, 120000, - DBUS_TYPE_G_MAP_OF_VARIANT, priv->connect_properties, - G_TYPE_INVALID); -} - -static void -stage1_enable_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) -{ - NMModemCdma *self = NM_MODEM_CDMA (user_data); - GError *error = NULL; - - if (dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID)) - do_connect (self); - else { - nm_log_warn (LOGD_MB, "CDMA modem enable failed: (%d) %s", - error ? error->code : -1, - error && error->message ? error->message : "(unknown)"); - g_error_free (error); - g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED); - } -} - -static GHashTable * -create_connect_properties (NMConnection *connection) -{ - NMSettingCdma *setting; - GHashTable *properties; - const char *str; - - setting = nm_connection_get_setting_cdma (connection); - properties = value_hash_create (); - - str = nm_setting_cdma_get_number (setting); - if (str) - value_hash_add_str (properties, "number", str); - - return properties; -} - -static NMActStageReturn -act_stage1_prepare (NMModem *modem, - NMActRequest *req, - GPtrArray **out_hints, - const char **out_setting_name, - NMDeviceStateReason *reason) -{ - NMModemCdma *self = NM_MODEM_CDMA (modem); - NMModemCdmaPrivate *priv = NM_MODEM_CDMA_GET_PRIVATE (self); - NMConnection *connection; - - connection = nm_act_request_get_connection (req); - g_assert (connection); - - *out_setting_name = nm_connection_need_secrets (connection, out_hints); - if (!*out_setting_name) { - gboolean enabled = nm_modem_get_mm_enabled (modem); - DBusGProxy *proxy; - - if (priv->connect_properties) - g_hash_table_destroy (priv->connect_properties); - priv->connect_properties = create_connect_properties (connection); - - if (enabled) - do_connect (self); - else { - proxy = nm_modem_generic_get_proxy (NM_MODEM_GENERIC (modem), MM_OLD_DBUS_INTERFACE_MODEM); - dbus_g_proxy_begin_call_with_timeout (proxy, - "Enable", stage1_enable_done, - modem, NULL, 20000, - G_TYPE_BOOLEAN, TRUE, - G_TYPE_INVALID); - } - } else { - /* NMModem will handle requesting secrets... */ - } - - return NM_ACT_STAGE_RETURN_POSTPONE; -} - -static NMConnection * -get_best_auto_connection (NMModem *modem, - GSList *connections, - char **specific_object) -{ - GSList *iter; - - for (iter = connections; iter; iter = g_slist_next (iter)) { - NMConnection *connection = NM_CONNECTION (iter->data); - - if (nm_connection_is_type (connection, NM_SETTING_CDMA_SETTING_NAME)) - return connection; - } - return NULL; -} - -static gboolean -check_connection_compatible (NMModem *modem, - NMConnection *connection, - GError **error) -{ - NMSettingConnection *s_con; - NMSettingCdma *s_cdma; - - s_con = nm_connection_get_setting_connection (connection); - g_assert (s_con); - - if (strcmp (nm_setting_connection_get_connection_type (s_con), NM_SETTING_CDMA_SETTING_NAME)) { - g_set_error (error, - NM_CDMA_ERROR, NM_CDMA_ERROR_CONNECTION_NOT_CDMA, - "The connection was not a CDMA connection."); - return FALSE; - } - - s_cdma = nm_connection_get_setting_cdma (connection); - if (!s_cdma) { - g_set_error (error, - NM_CDMA_ERROR, NM_CDMA_ERROR_CONNECTION_INVALID, - "The connection was not a valid CDMA connection."); - return FALSE; - } - - return TRUE; -} - -static gboolean -complete_connection (NMModem *modem, - NMConnection *connection, - const GSList *existing_connections, - GError **error) -{ - NMSettingCdma *s_cdma; - NMSettingPPP *s_ppp; - - s_cdma = nm_connection_get_setting_cdma (connection); - if (!s_cdma) { - s_cdma = (NMSettingCdma *) nm_setting_cdma_new (); - nm_connection_add_setting (connection, NM_SETTING (s_cdma)); - } - - if (!nm_setting_cdma_get_number (s_cdma)) - g_object_set (G_OBJECT (s_cdma), NM_SETTING_CDMA_NUMBER, "#777", NULL); - - s_ppp = nm_connection_get_setting_ppp (connection); - if (!s_ppp) { - s_ppp = (NMSettingPPP *) nm_setting_ppp_new (); - g_object_set (G_OBJECT (s_ppp), - NM_SETTING_PPP_LCP_ECHO_FAILURE, 5, - NM_SETTING_PPP_LCP_ECHO_INTERVAL, 30, - NULL); - nm_connection_add_setting (connection, NM_SETTING (s_ppp)); - } - - nm_utils_complete_generic (connection, - NM_SETTING_CDMA_SETTING_NAME, - existing_connections, - _("CDMA connection %d"), - NULL, - FALSE); /* No IPv6 yet by default */ - - return TRUE; -} - -static gboolean -get_user_pass (NMModem *modem, - NMConnection *connection, - const char **user, - const char **pass) -{ - NMSettingCdma *s_cdma; - - s_cdma = nm_connection_get_setting_cdma (connection); - if (!s_cdma) - return FALSE; - - if (user) - *user = nm_setting_cdma_get_username (s_cdma); - if (pass) - *pass = nm_setting_cdma_get_password (s_cdma); - - return TRUE; -} - -static const char * -get_setting_name (NMModem *modem) -{ - return NM_SETTING_CDMA_SETTING_NAME; -} - -static void -deactivate (NMModem *modem, NMDevice *device) -{ - NMModemCdmaPrivate *priv = NM_MODEM_CDMA_GET_PRIVATE (modem); - - if (priv->call) { - DBusGProxy *proxy; - - proxy = nm_modem_generic_get_proxy (NM_MODEM_GENERIC (modem), MM_OLD_DBUS_INTERFACE_MODEM_SIMPLE); - dbus_g_proxy_cancel_call (proxy, priv->call); - priv->call = NULL; - } - - NM_MODEM_CLASS (nm_modem_cdma_parent_class)->deactivate (modem, device); -} - -/*****************************************************************************/ - -static void -nm_modem_cdma_init (NMModemCdma *self) -{ -} - -static void -dispose (GObject *object) -{ - NMModemCdma *self = NM_MODEM_CDMA (object); - NMModemCdmaPrivate *priv = NM_MODEM_CDMA_GET_PRIVATE (self); - - if (priv->connect_properties) - g_hash_table_destroy (priv->connect_properties); - - G_OBJECT_CLASS (nm_modem_cdma_parent_class)->dispose (object); -} - -static void -nm_modem_cdma_class_init (NMModemCdmaClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - NMModemClass *modem_class = NM_MODEM_CLASS (klass); - - g_type_class_add_private (object_class, sizeof (NMModemCdmaPrivate)); - - /* Virtual methods */ - object_class->dispose = dispose; - modem_class->get_user_pass = get_user_pass; - modem_class->get_setting_name = get_setting_name; - modem_class->get_best_auto_connection = get_best_auto_connection; - modem_class->check_connection_compatible = check_connection_compatible; - modem_class->complete_connection = complete_connection; - modem_class->act_stage1_prepare = act_stage1_prepare; - modem_class->deactivate = deactivate; - - dbus_g_error_domain_register (NM_CDMA_ERROR, NULL, NM_TYPE_CDMA_ERROR); -} diff --git a/src/modem-manager/nm-modem-cdma.h b/src/modem-manager/nm-modem-cdma.h deleted file mode 100644 index ab1b4874..00000000 --- a/src/modem-manager/nm-modem-cdma.h +++ /dev/null @@ -1,59 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2009 Red Hat, Inc. - * Copyright (C) 2009 Novell, Inc. - */ - -#ifndef NM_MODEM_CDMA_H -#define NM_MODEM_CDMA_H - -#include - -G_BEGIN_DECLS - -#define NM_TYPE_MODEM_CDMA (nm_modem_cdma_get_type ()) -#define NM_MODEM_CDMA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_MODEM_CDMA, NMModemCdma)) -#define NM_MODEM_CDMA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_MODEM_CDMA, NMModemCdmaClass)) -#define NM_IS_MODEM_CDMA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_MODEM_CDMA)) -#define NM_IS_MODEM_CDMA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_MODEM_CDMA)) -#define NM_MODEM_CDMA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_MODEM_CDMA, NMModemCdmaClass)) - -typedef enum { - NM_CDMA_ERROR_CONNECTION_NOT_CDMA = 0, /*< nick=ConnectionNotCdma >*/ - NM_CDMA_ERROR_CONNECTION_INVALID, /*< nick=ConnectionInvalid >*/ - NM_CDMA_ERROR_CONNECTION_INCOMPATIBLE, /*< nick=ConnectionIncompatible >*/ -} NMCdmaError; - -typedef struct { - NMModemGeneric parent; -} NMModemCdma; - -typedef struct { - NMModemGenericClass parent; -} NMModemCdmaClass; - -GType nm_modem_cdma_get_type (void); - -NMModem *nm_modem_cdma_new (const char *path, - const char *data_device, - guint32 ip_method, - NMModemState state); - -G_END_DECLS - -#endif /* NM_MODEM_CDMA_H */ diff --git a/src/modem-manager/nm-modem-generic.c b/src/modem-manager/nm-modem-generic.c deleted file mode 100644 index f4e7a52f..00000000 --- a/src/modem-manager/nm-modem-generic.c +++ /dev/null @@ -1,445 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2009 - 2011 Red Hat, Inc. - * Copyright (C) 2009 Novell, Inc. - */ - -#include -#include "nm-modem-generic.h" -#include "nm-system.h" -#include "nm-dbus-manager.h" -#include "nm-setting-connection.h" -#include "nm-marshal.h" -#include "nm-properties-changed-signal.h" -#include "nm-modem-types.h" -#include "nm-logging.h" -#include "NetworkManagerUtils.h" -#include "nm-device-private.h" -#include "nm-dbus-glib-types.h" - -G_DEFINE_TYPE (NMModemGeneric, nm_modem_generic, NM_TYPE_MODEM) - -#define NM_MODEM_GENERIC_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_MODEM_GENERIC, NMModemGenericPrivate)) - -typedef struct { - NMDBusManager *dbus_mgr; - DBusGProxy *proxy; - DBusGProxy *props_proxy; - - DBusGProxyCall *call; - - NMModemState state; -} NMModemGenericPrivate; - -/*****************************************************************************/ - -DBusGProxy * -nm_modem_generic_get_proxy (NMModemGeneric *self, - const char *interface) -{ - - NMModemGenericPrivate *priv = NM_MODEM_GENERIC_GET_PRIVATE (self); - const char *current_iface; - - g_return_val_if_fail (NM_IS_MODEM_GENERIC (self), NULL); - - /* Default to the default interface. */ - if (interface == NULL) - interface = MM_OLD_DBUS_INTERFACE_MODEM; - - if (interface && !strcmp (interface, DBUS_INTERFACE_PROPERTIES)) - return priv->props_proxy; - - current_iface = dbus_g_proxy_get_interface (priv->proxy); - if (!current_iface || strcmp (current_iface, interface)) - dbus_g_proxy_set_interface (priv->proxy, interface); - - return priv->proxy; -} - -/*****************************************************************************/ -/* Query/Update enabled state */ - -static void -update_mm_enabled (NMModem *self, - gboolean new_enabled) -{ - if (nm_modem_get_mm_enabled (self) != new_enabled) { - g_object_set (self, - NM_MODEM_ENABLED, new_enabled, - NULL); - } -} - -static void -get_mm_enabled_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) -{ - NMModem *self = NM_MODEM (user_data); - GError *error = NULL; - GValue value = { 0, }; - - if (!dbus_g_proxy_end_call (proxy, call_id, &error, - G_TYPE_VALUE, &value, - G_TYPE_INVALID)) { - nm_log_warn (LOGD_MB, "failed get modem enabled state: (%d) %s", - error ? error->code : -1, - error && error->message ? error->message : "(unknown)"); - return; - } - - if (G_VALUE_HOLDS_BOOLEAN (&value)) { - update_mm_enabled (self, g_value_get_boolean (&value)); - } else - nm_log_warn (LOGD_MB, "failed get modem enabled state: unexpected reply type"); - - g_value_unset (&value); -} - -static void -query_mm_enabled (NMModemGeneric *self) -{ - dbus_g_proxy_begin_call (NM_MODEM_GENERIC_GET_PRIVATE (self)->props_proxy, - "Get", get_mm_enabled_done, - self, NULL, - G_TYPE_STRING, MM_OLD_DBUS_INTERFACE_MODEM, - G_TYPE_STRING, "Enabled", - G_TYPE_INVALID); -} - -static void -set_mm_enabled_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) -{ - GError *error = NULL; - - if (!dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID)) { - nm_log_warn (LOGD_MB, "failed to enable/disable modem: (%d) %s", - error ? error->code : -1, - error && error->message ? error->message : "(unknown)"); - } - - /* Update enabled/disabled state again */ - query_mm_enabled (NM_MODEM_GENERIC (user_data)); -} - -static void -set_mm_enabled (NMModem *self, gboolean enabled) -{ - /* FIXME: For now this just toggles the ModemManager enabled state. In the - * future we want to tie this into rfkill state instead so that the user can - * toggle rfkill status of the WWAN modem. - */ - dbus_g_proxy_begin_call (nm_modem_generic_get_proxy (NM_MODEM_GENERIC (self), - MM_OLD_DBUS_INTERFACE_MODEM), - "Enable", set_mm_enabled_done, - self, NULL, - G_TYPE_BOOLEAN, enabled, - G_TYPE_INVALID); - /* If we are disabling the modem, stop saying that it's enabled. */ - if (!enabled) - update_mm_enabled (self, enabled); -} - -/*****************************************************************************/ -/* IP method static */ - -static char addr_to_string_buf[INET6_ADDRSTRLEN + 1]; - -static const char * -ip_address_to_string (guint32 numeric) -{ - struct in_addr temp_addr; - - memset (&addr_to_string_buf, '\0', sizeof (addr_to_string_buf)); - temp_addr.s_addr = numeric; - - if (inet_ntop (AF_INET, &temp_addr, addr_to_string_buf, INET_ADDRSTRLEN)) { - return addr_to_string_buf; - } else { - nm_log_warn (LOGD_VPN, "error converting IP4 address 0x%X", - ntohl (temp_addr.s_addr)); - return NULL; - } -} - -static void -static_stage3_done (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) -{ - NMModemGeneric *self = NM_MODEM_GENERIC (user_data); - NMModemGenericPrivate *priv = NM_MODEM_GENERIC_GET_PRIVATE (self); - GValueArray *ret_array = NULL; - GError *error = NULL; - NMIP4Config *config = NULL; - - priv->call = NULL; - - /* Returned value array is (uuuu): [IP, DNS1, DNS2, DNS3], all in - * network byte order. - */ - if (dbus_g_proxy_end_call (proxy, call, &error, - G_TYPE_VALUE_ARRAY, &ret_array, - G_TYPE_INVALID)) { - NMIP4Address *addr; - int i; - - config = nm_ip4_config_new (); - - addr = nm_ip4_address_new (); - - nm_log_info (LOGD_MB, "(%s): IPv4 static configuration:", - nm_modem_get_uid (NM_MODEM (self))); - - /* IP address */ - nm_ip4_address_set_address (addr, g_value_get_uint (g_value_array_get_nth (ret_array, 0))); - nm_ip4_address_set_prefix (addr, 32); - nm_ip4_config_take_address (config, addr); - - nm_log_info (LOGD_MB, " address %s/%d", - ip_address_to_string (nm_ip4_address_get_address (addr)), - nm_ip4_address_get_prefix (addr)); - - /* DNS servers */ - for (i = 1; i < ret_array->n_values; i++) { - GValue *value = g_value_array_get_nth (ret_array, i); - guint32 tmp = g_value_get_uint (value); - - if (tmp > 0) { - nm_ip4_config_add_nameserver (config, tmp); - nm_log_info (LOGD_MB, " DNS %s", ip_address_to_string (tmp)); - } - } - g_value_array_free (ret_array); - } - - g_signal_emit_by_name (self, NM_MODEM_IP4_CONFIG_RESULT, config, error); - g_clear_error (&error); -} - -static NMActStageReturn -static_stage3_ip4_config_start (NMModem *self, - NMActRequest *req, - NMDeviceStateReason *reason) -{ - NMModemGenericPrivate *priv; - - g_return_val_if_fail (self != NULL, NM_ACT_STAGE_RETURN_FAILURE); - g_return_val_if_fail (NM_IS_MODEM (self), NM_ACT_STAGE_RETURN_FAILURE); - g_return_val_if_fail (req != NULL, NM_ACT_STAGE_RETURN_FAILURE); - g_return_val_if_fail (NM_IS_ACT_REQUEST (req), NM_ACT_STAGE_RETURN_FAILURE); - g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); - - priv = NM_MODEM_GENERIC_GET_PRIVATE (self); - - priv->call = dbus_g_proxy_begin_call (nm_modem_generic_get_proxy (NM_MODEM_GENERIC (self), - MM_OLD_DBUS_INTERFACE_MODEM), - "GetIP4Config", static_stage3_done, - self, NULL, - G_TYPE_INVALID); - - return NM_ACT_STAGE_RETURN_POSTPONE; -} - -/*****************************************************************************/ - -static void -disconnect_done (DBusGProxy *proxy, - DBusGProxyCall *call_id, - gpointer user_data) -{ - GError *error = NULL; - gboolean warn = GPOINTER_TO_UINT (user_data); - - if (!dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID) && warn) { - nm_log_info (LOGD_MB, "disconnect failed: (%d) %s", - error ? error->code : -1, - error && error->message ? error->message : "(unknown)"); - } -} - -static void -disconnect (NMModem *self, - gboolean warn) -{ - dbus_g_proxy_begin_call (nm_modem_generic_get_proxy (NM_MODEM_GENERIC (self), - MM_OLD_DBUS_INTERFACE_MODEM), - "Disconnect", - disconnect_done, - GUINT_TO_POINTER (warn), - NULL, - G_TYPE_INVALID); -} - -/*****************************************************************************/ - -static void -deactivate (NMModem *self, NMDevice *device) -{ - NMModemGenericPrivate *priv; - - g_assert (NM_IS_MODEM_GENERIC (self)); - g_assert (NM_IS_DEVICE (device)); - - priv = NM_MODEM_GENERIC_GET_PRIVATE (self); - - if (priv->call) { - dbus_g_proxy_cancel_call (priv->proxy, priv->call); - priv->call = NULL; - } - - /* Chain up parent's */ - NM_MODEM_CLASS (nm_modem_generic_parent_class)->deactivate (self, device); -} - -/*****************************************************************************/ - -static void -modem_properties_changed (DBusGProxy *proxy, - const char *interface, - GHashTable *props, - gpointer user_data) -{ - NMModemGeneric *self = NM_MODEM_GENERIC (user_data); - NMModemGenericPrivate *priv = NM_MODEM_GENERIC_GET_PRIVATE (self); - GValue *value; - NMModemState new_state; - - if (strcmp (interface, MM_OLD_DBUS_INTERFACE_MODEM)) - return; - - value = g_hash_table_lookup (props, "Enabled"); - if (value && G_VALUE_HOLDS_BOOLEAN (value)) { - g_object_set (self, - NM_MODEM_ENABLED, g_value_get_boolean (value), - NULL); - } - - value = g_hash_table_lookup (props, "IpMethod"); - if (value && G_VALUE_HOLDS_UINT (value)) { - g_object_set (self, - NM_MODEM_IP_METHOD, g_value_get_uint (value), - NULL); - } - - value = g_hash_table_lookup (props, "State"); - if (value && G_VALUE_HOLDS_UINT (value)) { - new_state = g_value_get_uint (value); - if (new_state != priv->state) { - if (new_state == NM_MODEM_STATE_CONNECTED) - g_object_set (self, - NM_MODEM_CONNECTED, TRUE, - NULL); - else if (priv->state == NM_MODEM_STATE_CONNECTED) - g_object_set (self, - NM_MODEM_CONNECTED, FALSE, - NULL); - priv->state = new_state; - } - } -} - -/*****************************************************************************/ - -static void -nm_modem_generic_init (NMModemGeneric *self) -{ - NMModemGenericPrivate *priv = NM_MODEM_GENERIC_GET_PRIVATE (self); - - priv->dbus_mgr = nm_dbus_manager_get (); -} - -static GObject* -constructor (GType type, - guint n_construct_params, - GObjectConstructParam *construct_params) -{ - GObject *object; - NMModemGenericPrivate *priv; - DBusGConnection *bus; - - object = G_OBJECT_CLASS (nm_modem_generic_parent_class)->constructor (type, n_construct_params, construct_params); - if (!object) - return NULL; - - priv = NM_MODEM_GENERIC_GET_PRIVATE (object); - - bus = nm_dbus_manager_get_connection (priv->dbus_mgr); - priv->proxy = dbus_g_proxy_new_for_name (bus, - MM_OLD_DBUS_SERVICE, - nm_modem_get_path (NM_MODEM (object)), - MM_OLD_DBUS_INTERFACE_MODEM); - - priv->props_proxy = dbus_g_proxy_new_for_name (bus, - MM_OLD_DBUS_SERVICE, - nm_modem_get_path (NM_MODEM (object)), - DBUS_INTERFACE_PROPERTIES); - dbus_g_object_register_marshaller (_nm_marshal_VOID__STRING_BOXED, - G_TYPE_NONE, - G_TYPE_STRING, DBUS_TYPE_G_MAP_OF_VARIANT, - G_TYPE_INVALID); - dbus_g_proxy_add_signal (priv->props_proxy, "MmPropertiesChanged", - G_TYPE_STRING, DBUS_TYPE_G_MAP_OF_VARIANT, - G_TYPE_INVALID); - dbus_g_proxy_connect_signal (priv->props_proxy, "MmPropertiesChanged", - G_CALLBACK (modem_properties_changed), - object, - NULL); - - query_mm_enabled (NM_MODEM_GENERIC (object)); - - return object; -} - -static void -dispose (GObject *object) -{ - NMModemGenericPrivate *priv = NM_MODEM_GENERIC_GET_PRIVATE (object); - - if (priv->proxy) { - g_object_unref (priv->proxy); - priv->proxy = NULL; - } - - if (priv->props_proxy) { - g_object_unref (priv->props_proxy); - priv->props_proxy = NULL; - } - - if (priv->dbus_mgr) { - g_object_unref (priv->dbus_mgr); - priv->dbus_mgr = NULL; - } - - G_OBJECT_CLASS (nm_modem_generic_parent_class)->dispose (object); -} - -static void -nm_modem_generic_class_init (NMModemGenericClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - NMModemClass *modem_class = NM_MODEM_CLASS (klass); - - g_type_class_add_private (object_class, sizeof (NMModemGenericPrivate)); - - /* Virtual methods */ - object_class->constructor = constructor; - object_class->dispose = dispose; - - modem_class->static_stage3_ip4_config_start = static_stage3_ip4_config_start; - modem_class->disconnect = disconnect; - modem_class->deactivate = deactivate; - modem_class->set_mm_enabled = set_mm_enabled; -} diff --git a/src/modem-manager/nm-modem-generic.h b/src/modem-manager/nm-modem-generic.h deleted file mode 100644 index 59866a1e..00000000 --- a/src/modem-manager/nm-modem-generic.h +++ /dev/null @@ -1,69 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2009 - 2011 Red Hat, Inc. - * Copyright (C) 2009 Novell, Inc. - */ - -#ifndef NM_MODEM_GENERIC_H -#define NM_MODEM_GENERIC_H - -#include -#include -#include "nm-modem.h" - -G_BEGIN_DECLS - -#define NM_TYPE_MODEM_GENERIC (nm_modem_generic_get_type ()) -#define NM_MODEM_GENERIC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_MODEM_GENERIC, NMModemGeneric)) -#define NM_MODEM_GENERIC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_MODEM_GENERIC, NMModemGenericClass)) -#define NM_IS_MODEM_GENERIC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_MODEM_GENERIC)) -#define NM_IS_MODEM_GENERIC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_MODEM_GENERIC)) -#define NM_MODEM_GENERIC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_MODEM_GENERIC, NMModemGenericClass)) - -typedef enum { - NM_MODEM_STATE_UNKNOWN = 0, - NM_MODEM_STATE_DISABLED = 10, - NM_MODEM_STATE_DISABLING = 20, - NM_MODEM_STATE_ENABLING = 30, - NM_MODEM_STATE_ENABLED = 40, - NM_MODEM_STATE_SEARCHING = 50, - NM_MODEM_STATE_REGISTERED = 60, - NM_MODEM_STATE_DISCONNECTING = 70, - NM_MODEM_STATE_CONNECTING = 80, - NM_MODEM_STATE_CONNECTED = 90, - - NM_MODEM_STATE_LAST = NM_MODEM_STATE_CONNECTED -} NMModemState; - -typedef struct { - NMModem parent; -} NMModemGeneric; - -typedef struct { - NMModemClass parent; -} NMModemGenericClass; - -GType nm_modem_generic_get_type (void); - -/* Protected */ -DBusGProxy *nm_modem_generic_get_proxy (NMModemGeneric *modem, - const gchar *interface); - -G_END_DECLS - -#endif /* NM_MODEM_GENERIC_H */ diff --git a/src/modem-manager/nm-modem-gsm.c b/src/modem-manager/nm-modem-gsm.c deleted file mode 100644 index be793db9..00000000 --- a/src/modem-manager/nm-modem-gsm.c +++ /dev/null @@ -1,644 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2009 - 2011 Red Hat, Inc. - * Copyright (C) 2009 Novell, Inc. - */ - -#include "config.h" - -#include -#include - -#include "nm-dbus-glib-types.h" -#include "nm-modem-gsm.h" -#include "nm-device.h" -#include "nm-device-private.h" -#include "nm-setting-connection.h" -#include "nm-setting-gsm.h" -#include "nm-setting-ppp.h" -#include "nm-modem-types.h" -#include "nm-enum-types.h" -#include "nm-logging.h" -#include "NetworkManagerUtils.h" - -typedef enum { - MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_ANY = 0, - MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_GPRS, - MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_EDGE, - MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_UMTS, - MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_HSDPA, - MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_2G_PREFERRED, - MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_3G_PREFERRED, - MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_2G_ONLY, - MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_3G_ONLY, - MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_HSUPA, - MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_HSPA, - - MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_LAST = MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_HSPA -} MMModemDeprecatedMode; - -typedef enum { - MM_MODEM_GSM_ALLOWED_MODE_ANY = 0, - MM_MODEM_GSM_ALLOWED_MODE_2G_PREFERRED = 1, - MM_MODEM_GSM_ALLOWED_MODE_3G_PREFERRED = 2, - MM_MODEM_GSM_ALLOWED_MODE_2G_ONLY = 3, - MM_MODEM_GSM_ALLOWED_MODE_3G_ONLY = 4, - MM_MODEM_GSM_ALLOWED_MODE_4G_PREFERRED = 5, - MM_MODEM_GSM_ALLOWED_MODE_4G_ONLY = 6, - - MM_MODEM_GSM_ALLOWED_MODE_LAST = MM_MODEM_GSM_ALLOWED_MODE_4G_ONLY -} MMModemGsmAllowedMode; - -typedef enum { - MM_MODEM_GSM_ALLOWED_AUTH_UNKNOWN = 0x0000, - /* bits 0..4 order match Ericsson device bitmap */ - MM_MODEM_GSM_ALLOWED_AUTH_NONE = 0x0001, - MM_MODEM_GSM_ALLOWED_AUTH_PAP = 0x0002, - MM_MODEM_GSM_ALLOWED_AUTH_CHAP = 0x0004, - MM_MODEM_GSM_ALLOWED_AUTH_MSCHAP = 0x0008, - MM_MODEM_GSM_ALLOWED_AUTH_MSCHAPV2 = 0x0010, - MM_MODEM_GSM_ALLOWED_AUTH_EAP = 0x0020, - - MM_MODEM_GSM_ALLOWED_AUTH_LAST = MM_MODEM_GSM_ALLOWED_AUTH_EAP -} MMModemGsmAllowedAuth; - -G_DEFINE_TYPE (NMModemGsm, nm_modem_gsm, NM_TYPE_MODEM_GENERIC) - -#define NM_MODEM_GSM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_MODEM_GSM, NMModemGsmPrivate)) - -typedef struct { - DBusGProxyCall *call; - - GHashTable *connect_properties; - guint32 pin_tries; - - guint enable_delay_id; -} NMModemGsmPrivate; - - -#define NM_GSM_ERROR (nm_gsm_error_quark ()) - -static GQuark -nm_gsm_error_quark (void) -{ - static GQuark quark = 0; - if (!quark) - quark = g_quark_from_static_string ("nm-gsm-error"); - return quark; -} - -NMModem * -nm_modem_gsm_new (const char *path, - const char *data_device, - guint32 ip_method, - NMModemState state) -{ - g_return_val_if_fail (path != NULL, NULL); - g_return_val_if_fail (data_device != NULL, NULL); - - return (NMModem *) g_object_new (NM_TYPE_MODEM_GSM, - NM_MODEM_PATH, path, - NM_MODEM_UID, data_device, - NM_MODEM_CONTROL_PORT, NULL, - NM_MODEM_DATA_PORT, data_device, - NM_MODEM_IP_METHOD, ip_method, - NM_MODEM_CONNECTED, (state == NM_MODEM_STATE_CONNECTED), - NULL); -} - -static NMDeviceStateReason -translate_mm_error (GError *error) -{ - NMDeviceStateReason reason; - - if (dbus_g_error_has_name (error, MM_MODEM_CONNECT_ERROR_NO_CARRIER)) - reason = NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER; - else if (dbus_g_error_has_name (error, MM_MODEM_CONNECT_ERROR_NO_DIALTONE)) - reason = NM_DEVICE_STATE_REASON_MODEM_NO_DIAL_TONE; - else if (dbus_g_error_has_name (error, MM_MODEM_CONNECT_ERROR_BUSY)) - reason = NM_DEVICE_STATE_REASON_MODEM_BUSY; - else if (dbus_g_error_has_name (error, MM_MODEM_CONNECT_ERROR_NO_ANSWER)) - reason = NM_DEVICE_STATE_REASON_MODEM_DIAL_TIMEOUT; - else if (dbus_g_error_has_name (error, MM_MODEM_ERROR_NETWORK_NOT_ALLOWED)) - reason = NM_DEVICE_STATE_REASON_GSM_REGISTRATION_DENIED; - else if (dbus_g_error_has_name (error, MM_MODEM_ERROR_NETWORK_TIMEOUT)) - reason = NM_DEVICE_STATE_REASON_GSM_REGISTRATION_TIMEOUT; - else if (dbus_g_error_has_name (error, MM_MODEM_ERROR_NO_NETWORK)) - reason = NM_DEVICE_STATE_REASON_GSM_REGISTRATION_NOT_SEARCHING; - else if (dbus_g_error_has_name (error, MM_MODEM_ERROR_SIM_NOT_INSERTED)) - reason = NM_DEVICE_STATE_REASON_GSM_SIM_NOT_INSERTED; - else if (dbus_g_error_has_name (error, MM_MODEM_ERROR_SIM_PIN)) - reason = NM_DEVICE_STATE_REASON_GSM_SIM_PIN_REQUIRED; - else if (dbus_g_error_has_name (error, MM_MODEM_ERROR_SIM_PUK)) - reason = NM_DEVICE_STATE_REASON_GSM_SIM_PUK_REQUIRED; - else if (dbus_g_error_has_name (error, MM_MODEM_ERROR_SIM_WRONG)) - reason = NM_DEVICE_STATE_REASON_GSM_SIM_WRONG; - else { - /* unable to map the ModemManager error to a NM_DEVICE_STATE_REASON */ - nm_log_dbg (LOGD_MB, "unmapped dbus error detected: '%s'", dbus_g_error_get_name (error)); - reason = NM_DEVICE_STATE_REASON_UNKNOWN; - } - - /* FIXME: We have only GSM error messages here, and we have no idea which - activation state failed. Reasons like: - NM_DEVICE_STATE_REASON_MODEM_DIAL_FAILED, - NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED, - NM_DEVICE_STATE_REASON_GSM_APN_FAILED, - NM_DEVICE_STATE_REASON_GSM_REGISTRATION_FAILED, - NM_DEVICE_STATE_REASON_GSM_PIN_CHECK_FAILED - are not used. - */ - return reason; -} - -static void -ask_for_pin (NMModemGsm *self, gboolean always_ask) -{ - NMModemGsmPrivate *priv; - guint32 tries = 0; - - g_return_if_fail (self != NULL); - g_return_if_fail (NM_IS_MODEM_GSM (self)); - - priv = NM_MODEM_GSM_GET_PRIVATE (self); - - if (!always_ask) - tries = priv->pin_tries++; - - nm_modem_get_secrets (NM_MODEM (self), - NM_SETTING_GSM_SETTING_NAME, - (tries || always_ask) ? TRUE : FALSE, - NM_SETTING_GSM_PIN); -} - -static void -stage1_prepare_done (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) -{ - NMModemGsm *self = NM_MODEM_GSM (user_data); - NMModemGsmPrivate *priv = NM_MODEM_GSM_GET_PRIVATE (self); - GError *error = NULL; - - priv->call = NULL; - - if (priv->connect_properties) { - g_hash_table_destroy (priv->connect_properties); - priv->connect_properties = NULL; - } - - if (dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_INVALID)) - g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, TRUE, NM_DEVICE_STATE_REASON_NONE); - else { - if (dbus_g_error_has_name (error, MM_MODEM_ERROR_SIM_PIN)) - ask_for_pin (self, FALSE); - else if (dbus_g_error_has_name (error, MM_MODEM_ERROR_SIM_WRONG)) - ask_for_pin (self, TRUE); - else { - nm_log_warn (LOGD_MB, "GSM connection failed: (%d) %s", - error ? error->code : -1, - error && error->message ? error->message : "(unknown)"); - - g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, translate_mm_error (error)); - } - - g_error_free (error); - } -} - -static void -do_connect (NMModemGsm *self) -{ - NMModemGsmPrivate *priv = NM_MODEM_GSM_GET_PRIVATE (self); - DBusGProxy *proxy; - - proxy = nm_modem_generic_get_proxy (NM_MODEM_GENERIC (self), MM_OLD_DBUS_INTERFACE_MODEM_SIMPLE); - priv->call = dbus_g_proxy_begin_call_with_timeout (proxy, - "Connect", stage1_prepare_done, - self, NULL, 120000, - DBUS_TYPE_G_MAP_OF_VARIANT, priv->connect_properties, - G_TYPE_INVALID); -} - -static void stage1_enable_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data); - -/* do_enable() is used as a GSourceFunc, hence the gboolean return */ -static gboolean -do_enable (NMModemGsm *self) -{ - DBusGProxy *proxy; - - g_return_val_if_fail (self != NULL, FALSE); - g_return_val_if_fail (NM_IS_MODEM_GSM (self), FALSE); - - NM_MODEM_GSM_GET_PRIVATE (self)->enable_delay_id = 0; - proxy = nm_modem_generic_get_proxy (NM_MODEM_GENERIC (self), MM_OLD_DBUS_INTERFACE_MODEM); - dbus_g_proxy_begin_call_with_timeout (proxy, - "Enable", stage1_enable_done, - self, NULL, 20000, - G_TYPE_BOOLEAN, TRUE, - G_TYPE_INVALID); - return FALSE; -} - -static void -stage1_pin_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) -{ - NMModemGsm *self = NM_MODEM_GSM (user_data); - NMModemGsmPrivate *priv = NM_MODEM_GSM_GET_PRIVATE (self); - NMDeviceStateReason reason; - GError *error = NULL; - - if (dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID)) { - /* Success; try to enable the modem again. Wait a few seconds to ensure - * that ModemManager is ready for the enable right after the unlock. - */ - if (priv->enable_delay_id == 0) - priv->enable_delay_id = g_timeout_add_seconds (4, (GSourceFunc) do_enable, self); - } else { - nm_log_warn (LOGD_MB, "GSM PIN unlock failed: (%d) %s", - error ? error->code : -1, - error && error->message ? error->message : "(unknown)"); - - /* try to translate the error reason */ - reason = translate_mm_error (error); - if (reason == NM_DEVICE_STATE_REASON_UNKNOWN) - reason = NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED; - - g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, reason); - g_error_free (error); - } -} - -static void -handle_enable_pin_required (NMModemGsm *self) -{ - NMModemGsmPrivate *priv = NM_MODEM_GSM_GET_PRIVATE (self); - const char *pin = NULL; - GValue *value; - DBusGProxy *proxy; - - /* See if we have a PIN already */ - value = g_hash_table_lookup (priv->connect_properties, "pin"); - if (value && G_VALUE_HOLDS_STRING (value)) - pin = g_value_get_string (value); - - /* If we do, send it */ - if (pin) { - proxy = nm_modem_generic_get_proxy (NM_MODEM_GENERIC (self), MM_OLD_DBUS_INTERFACE_MODEM_GSM_CARD); - dbus_g_proxy_begin_call_with_timeout (proxy, - "SendPin", stage1_pin_done, - self, NULL, 10000, - G_TYPE_STRING, pin, - G_TYPE_INVALID); - } else - ask_for_pin (self, FALSE); -} - -static void -stage1_enable_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) -{ - NMModemGsm *self = NM_MODEM_GSM (user_data); - NMDeviceStateReason reason; - GError *error = NULL; - - if (dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID)) - do_connect (self); - else { - nm_log_warn (LOGD_MB, "GSM modem enable failed: (%d) %s", - error ? error->code : -1, - error && error->message ? error->message : "(unknown)"); - - if (dbus_g_error_has_name (error, MM_MODEM_ERROR_SIM_PIN)) - handle_enable_pin_required (self); - else { - /* try to translate the error reason */ - reason = translate_mm_error (error); - if (reason == NM_DEVICE_STATE_REASON_UNKNOWN) - reason = NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED; - g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, reason); - } - - g_error_free (error); - } -} - - -static GHashTable * -create_connect_properties (NMConnection *connection) -{ - NMSettingGsm *setting; - NMSettingPPP *s_ppp; - GHashTable *properties; - const char *str; - - setting = nm_connection_get_setting_gsm (connection); - properties = value_hash_create (); - - str = nm_setting_gsm_get_number (setting); - if (str) - value_hash_add_str (properties, "number", str); - - str = nm_setting_gsm_get_apn (setting); - if (str) - value_hash_add_str (properties, "apn", str); - - str = nm_setting_gsm_get_network_id (setting); - if (str) - value_hash_add_str (properties, "network_id", str); - - str = nm_setting_gsm_get_pin (setting); - if (str) - value_hash_add_str (properties, "pin", str); - - str = nm_setting_gsm_get_username (setting); - if (str) - value_hash_add_str (properties, "username", str); - - str = nm_setting_gsm_get_password (setting); - if (str) - value_hash_add_str (properties, "password", str); - - /* Add both old and new preferred modes */ - switch (nm_setting_gsm_get_network_type (setting)) { - case NM_SETTING_GSM_NETWORK_TYPE_UMTS_HSPA: - value_hash_add_uint (properties, "network_mode", MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_3G_ONLY); - value_hash_add_uint (properties, "allowed_mode", MM_MODEM_GSM_ALLOWED_MODE_3G_ONLY); - break; - case NM_SETTING_GSM_NETWORK_TYPE_GPRS_EDGE: - value_hash_add_uint (properties, "network_mode", MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_2G_ONLY); - value_hash_add_uint (properties, "allowed_mode", MM_MODEM_GSM_ALLOWED_MODE_2G_ONLY); - break; - case NM_SETTING_GSM_NETWORK_TYPE_PREFER_UMTS_HSPA: - value_hash_add_uint (properties, "network_mode", MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_3G_PREFERRED); - value_hash_add_uint (properties, "allowed_mode", MM_MODEM_GSM_ALLOWED_MODE_3G_PREFERRED); - break; - case NM_SETTING_GSM_NETWORK_TYPE_PREFER_GPRS_EDGE: - value_hash_add_uint (properties, "network_mode", MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_2G_PREFERRED); - value_hash_add_uint (properties, "allowed_mode", MM_MODEM_GSM_ALLOWED_MODE_2G_PREFERRED); - break; - case NM_SETTING_GSM_NETWORK_TYPE_PREFER_4G: - /* deprecated modes not extended for 4G, so no need to set them here */ - value_hash_add_uint (properties, "allowed_mode", MM_MODEM_GSM_ALLOWED_MODE_4G_PREFERRED); - break; - case NM_SETTING_GSM_NETWORK_TYPE_4G: - /* deprecated modes not extended for 4G, so no need to set them here */ - value_hash_add_uint (properties, "allowed_mode", MM_MODEM_GSM_ALLOWED_MODE_4G_ONLY); - break; - default: - value_hash_add_uint (properties, "network_mode", MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_ANY); - value_hash_add_uint (properties, "allowed_mode", MM_MODEM_GSM_ALLOWED_MODE_ANY); - break; - } - - /* Roaming */ - if (nm_setting_gsm_get_home_only (setting)) - value_hash_add_bool (properties, "home_only", TRUE); - - /* For IpMethod == STATIC or DHCP */ - s_ppp = nm_connection_get_setting_ppp (connection); - if (s_ppp) { - guint32 auth = MM_MODEM_GSM_ALLOWED_AUTH_UNKNOWN; - - if (nm_setting_ppp_get_noauth (s_ppp)) - auth |= MM_MODEM_GSM_ALLOWED_AUTH_NONE; - if (!nm_setting_ppp_get_refuse_pap (s_ppp)) - auth |= MM_MODEM_GSM_ALLOWED_AUTH_PAP; - if (!nm_setting_ppp_get_refuse_chap (s_ppp)) - auth |= MM_MODEM_GSM_ALLOWED_AUTH_CHAP; - if (!nm_setting_ppp_get_refuse_mschap (s_ppp)) - auth |= MM_MODEM_GSM_ALLOWED_AUTH_MSCHAP; - if (!nm_setting_ppp_get_refuse_mschapv2 (s_ppp)) - auth |= MM_MODEM_GSM_ALLOWED_AUTH_MSCHAPV2; - if (!nm_setting_ppp_get_refuse_eap (s_ppp)) - auth |= MM_MODEM_GSM_ALLOWED_AUTH_EAP; - - if (auth != MM_MODEM_GSM_ALLOWED_AUTH_UNKNOWN) - value_hash_add_uint (properties, "allowed_auth", auth); - } - - return properties; -} - -static NMActStageReturn -act_stage1_prepare (NMModem *modem, - NMActRequest *req, - GPtrArray **out_hints, - const char **out_setting_name, - NMDeviceStateReason *reason) -{ - NMModemGsm *self = NM_MODEM_GSM (modem); - NMModemGsmPrivate *priv = NM_MODEM_GSM_GET_PRIVATE (self); - NMConnection *connection; - - connection = nm_act_request_get_connection (req); - g_assert (connection); - - *out_setting_name = nm_connection_need_secrets (connection, out_hints); - if (!*out_setting_name) { - gboolean enabled = nm_modem_get_mm_enabled (modem); - - if (priv->connect_properties) - g_hash_table_destroy (priv->connect_properties); - priv->connect_properties = create_connect_properties (connection); - - if (enabled) - do_connect (self); - else - do_enable (self); - } else { - /* NMModem will handle requesting secrets... */ - } - - return NM_ACT_STAGE_RETURN_POSTPONE; -} - -static NMConnection * -get_best_auto_connection (NMModem *modem, - GSList *connections, - char **specific_object) -{ - GSList *iter; - - for (iter = connections; iter; iter = g_slist_next (iter)) { - NMConnection *connection = NM_CONNECTION (iter->data); - - if (nm_connection_is_type (connection, NM_SETTING_GSM_SETTING_NAME)) - return connection; - } - return NULL; -} - -static gboolean -check_connection_compatible (NMModem *modem, - NMConnection *connection, - GError **error) -{ - NMSettingConnection *s_con; - NMSettingGsm *s_gsm; - - s_con = nm_connection_get_setting_connection (connection); - g_assert (s_con); - - if (strcmp (nm_setting_connection_get_connection_type (s_con), NM_SETTING_GSM_SETTING_NAME)) { - g_set_error (error, - NM_GSM_ERROR, NM_GSM_ERROR_CONNECTION_NOT_GSM, - "The connection was not a GSM connection."); - return FALSE; - } - - s_gsm = nm_connection_get_setting_gsm (connection); - if (!s_gsm) { - g_set_error (error, - NM_GSM_ERROR, NM_GSM_ERROR_CONNECTION_INVALID, - "The connection was not a valid GSM connection."); - return FALSE; - } - - return TRUE; -} - -static gboolean -complete_connection (NMModem *modem, - NMConnection *connection, - const GSList *existing_connections, - GError **error) -{ - NMSettingGsm *s_gsm; - NMSettingPPP *s_ppp; - - s_gsm = nm_connection_get_setting_gsm (connection); - if (!s_gsm || !nm_setting_gsm_get_apn (s_gsm)) { - /* Need an APN at least */ - g_set_error_literal (error, - NM_SETTING_GSM_ERROR, - NM_SETTING_GSM_ERROR_MISSING_PROPERTY, - NM_SETTING_GSM_APN); - return FALSE; - } - - if (!nm_setting_gsm_get_number (s_gsm)) - g_object_set (G_OBJECT (s_gsm), NM_SETTING_GSM_NUMBER, "*99#", NULL); - - s_ppp = nm_connection_get_setting_ppp (connection); - if (!s_ppp) { - s_ppp = (NMSettingPPP *) nm_setting_ppp_new (); - g_object_set (G_OBJECT (s_ppp), - NM_SETTING_PPP_LCP_ECHO_FAILURE, 5, - NM_SETTING_PPP_LCP_ECHO_INTERVAL, 30, - NULL); - nm_connection_add_setting (connection, NM_SETTING (s_ppp)); - } - - nm_utils_complete_generic (connection, - NM_SETTING_GSM_SETTING_NAME, - existing_connections, - _("GSM connection %d"), - NULL, - FALSE); /* No IPv6 yet by default */ - - return TRUE; -} - -static gboolean -get_user_pass (NMModem *modem, - NMConnection *connection, - const char **user, - const char **pass) -{ - NMSettingGsm *s_gsm; - - s_gsm = nm_connection_get_setting_gsm (connection); - if (!s_gsm) - return FALSE; - - if (user) - *user = nm_setting_gsm_get_username (s_gsm); - if (pass) - *pass = nm_setting_gsm_get_password (s_gsm); - - return TRUE; -} - -static const char * -get_setting_name (NMModem *modem) -{ - return NM_SETTING_GSM_SETTING_NAME; -} - -static void -deactivate (NMModem *modem, NMDevice *device) -{ - NMModemGsmPrivate *priv = NM_MODEM_GSM_GET_PRIVATE (modem); - - if (priv->call) { - DBusGProxy *proxy; - - proxy = nm_modem_generic_get_proxy (NM_MODEM_GENERIC (modem), MM_OLD_DBUS_INTERFACE_MODEM_SIMPLE); - dbus_g_proxy_cancel_call (proxy, priv->call); - priv->call = NULL; - } - - priv->pin_tries = 0; - - if (priv->enable_delay_id) - g_source_remove (priv->enable_delay_id); - - NM_MODEM_CLASS (nm_modem_gsm_parent_class)->deactivate (modem, device); -} - - -/*****************************************************************************/ - -static void -nm_modem_gsm_init (NMModemGsm *self) -{ -} - -static void -dispose (GObject *object) -{ - NMModemGsm *self = NM_MODEM_GSM (object); - NMModemGsmPrivate *priv = NM_MODEM_GSM_GET_PRIVATE (self); - - if (priv->connect_properties) - g_hash_table_destroy (priv->connect_properties); - if (priv->enable_delay_id) - g_source_remove (priv->enable_delay_id); - - G_OBJECT_CLASS (nm_modem_gsm_parent_class)->dispose (object); -} - -static void -nm_modem_gsm_class_init (NMModemGsmClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - NMModemClass *modem_class = NM_MODEM_CLASS (klass); - - g_type_class_add_private (object_class, sizeof (NMModemGsmPrivate)); - - /* Virtual methods */ - object_class->dispose = dispose; - modem_class->get_user_pass = get_user_pass; - modem_class->get_setting_name = get_setting_name; - modem_class->get_best_auto_connection = get_best_auto_connection; - modem_class->check_connection_compatible = check_connection_compatible; - modem_class->complete_connection = complete_connection; - modem_class->act_stage1_prepare = act_stage1_prepare; - modem_class->deactivate = deactivate; - - dbus_g_error_domain_register (NM_GSM_ERROR, NULL, NM_TYPE_GSM_ERROR); -} diff --git a/src/modem-manager/nm-modem-gsm.h b/src/modem-manager/nm-modem-gsm.h deleted file mode 100644 index b0f78b0a..00000000 --- a/src/modem-manager/nm-modem-gsm.h +++ /dev/null @@ -1,59 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2009 Red Hat, Inc. - * Copyright (C) 2009 Novell, Inc. - */ - -#ifndef NM_MODEM_GSM_H -#define NM_MODEM_GSM_H - -#include - -G_BEGIN_DECLS - -#define NM_TYPE_MODEM_GSM (nm_modem_gsm_get_type ()) -#define NM_MODEM_GSM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_MODEM_GSM, NMModemGsm)) -#define NM_MODEM_GSM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_MODEM_GSM, NMModemGsmClass)) -#define NM_IS_MODEM_GSM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_MODEM_GSM)) -#define NM_IS_MODEM_GSM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_MODEM_GSM)) -#define NM_MODEM_GSM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_MODEM_GSM, NMModemGsmClass)) - -typedef enum { - NM_GSM_ERROR_CONNECTION_NOT_GSM = 0, /*< nick=ConnectionNotGsm >*/ - NM_GSM_ERROR_CONNECTION_INVALID, /*< nick=ConnectionInvalid >*/ - NM_GSM_ERROR_CONNECTION_INCOMPATIBLE, /*< nick=ConnectionIncompatible >*/ -} NMGsmError; - -typedef struct { - NMModemGeneric parent; -} NMModemGsm; - -typedef struct { - NMModemGenericClass parent; -} NMModemGsmClass; - -GType nm_modem_gsm_get_type (void); - -NMModem *nm_modem_gsm_new (const char *path, - const char *data_device, - guint32 ip_method, - NMModemState state); - -G_END_DECLS - -#endif /* NM_MODEM_GSM_H */ diff --git a/src/modem-manager/nm-modem-manager.c b/src/modem-manager/nm-modem-manager.c deleted file mode 100644 index 7b566ca4..00000000 --- a/src/modem-manager/nm-modem-manager.c +++ /dev/null @@ -1,859 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2009 - 2010 Red Hat, Inc. - * Copyright (C) 2009 Novell, Inc. - * Copyright (C) 2009 Canonical Ltd. - */ - -#include -#include "config.h" -#include "nm-modem-manager.h" -#include "nm-logging.h" -#include "nm-modem.h" -#include "nm-modem-gsm.h" -#include "nm-modem-cdma.h" -#include "nm-dbus-manager.h" -#include "nm-modem-types.h" -#include "nm-marshal.h" -#include "nm-dbus-glib-types.h" - -#if WITH_MODEM_MANAGER_1 -#include -#include "nm-modem-broadband.h" -#endif - -#define MODEM_POKE_INTERVAL 120 - -G_DEFINE_TYPE (NMModemManager, nm_modem_manager, G_TYPE_OBJECT) - -struct _NMModemManagerPrivate { - /* ModemManager < 0.7 */ - NMDBusManager *dbus_mgr; - DBusGProxy *proxy; - guint poke_id; - -#if WITH_MODEM_MANAGER_1 - /* ModemManager >= 0.7 */ - GDBusConnection *dbus_connection; - MMManager *modem_manager_1; - guint modem_manager_1_launch_id; - gboolean old_modem_manager_found; - gboolean new_modem_manager_found; - guint modem_manager_1_name_owner_changed_id; - guint modem_manager_1_object_added_id; - guint modem_manager_1_object_removed_id; -#endif - - /* Common */ - GHashTable *modems; -}; - -enum { - MODEM_ADDED, - MODEM_REMOVED, - - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - - -NMModemManager * -nm_modem_manager_get (void) -{ - static NMModemManager *singleton = NULL; - - if (!singleton) - singleton = NM_MODEM_MANAGER (g_object_new (NM_TYPE_MODEM_MANAGER, NULL)); - else - g_object_ref (singleton); - - g_assert (singleton); - return singleton; -} - -/************************************************************************/ -/* Support for ModemManager < 0.7 */ - -static void -clear_modem_manager_support (NMModemManager *self) -{ - if (self->priv->poke_id) { - g_source_remove (self->priv->poke_id); - self->priv->poke_id = 0; - } - - if (self->priv->proxy) { - g_object_unref (self->priv->proxy); - self->priv->proxy = NULL; - } -} - -static gboolean -get_modem_properties (DBusGConnection *connection, - const char *path, - char **device, - char **data_device, - char **driver, - guint32 *type, - guint32 *ip_method, - guint32 *ip_timeout, - NMModemState *state) -{ - DBusGProxy *proxy; - GError *err = NULL; - GHashTable *props = NULL; - GHashTableIter iter; - const char *prop; - GValue *value; - - proxy = dbus_g_proxy_new_for_name (connection, - MM_OLD_DBUS_SERVICE, - path, - "org.freedesktop.DBus.Properties"); - - if (!dbus_g_proxy_call_with_timeout (proxy, "GetAll", 15000, &err, - G_TYPE_STRING, MM_OLD_DBUS_INTERFACE_MODEM, - G_TYPE_INVALID, - DBUS_TYPE_G_MAP_OF_VARIANT, &props, - G_TYPE_INVALID)) { - nm_log_warn (LOGD_MB, "could not get modem properties: %s %s", - err ? dbus_g_error_get_name (err) : "(none)", - err ? err->message : "(unknown)"); - g_clear_error (&err); - goto out; - } - - if (!props) { - nm_log_warn (LOGD_MB, "no modem properties found"); - goto out; - } - - g_hash_table_iter_init (&iter, props); - while (g_hash_table_iter_next (&iter, (gpointer) &prop, (gpointer) &value)) { - if (g_strcmp0 (prop, "Type") == 0) - *type = g_value_get_uint (value); - else if (g_strcmp0 (prop, "MasterDevice") == 0) - *device = g_value_dup_string (value); - else if (g_strcmp0 (prop, "IpMethod") == 0) - *ip_method = g_value_get_uint (value); - else if (g_strcmp0 (prop, "Device") == 0) - *data_device = g_value_dup_string (value); - else if (g_strcmp0 (prop, "Driver") == 0) - *driver = g_value_dup_string (value); - else if (g_strcmp0 (prop, "IpTimeout") == 0) - *ip_timeout = g_value_get_uint (value); - else if (g_strcmp0 (prop, "State") == 0) - *state = g_value_get_uint (value); - } - g_hash_table_unref (props); - - out: - g_object_unref (proxy); - - return *data_device && *driver; -} - -static void -create_modem (NMModemManager *self, const char *path) -{ - NMModem *modem = NULL; - char *data_device = NULL, *driver = NULL, *master_device = NULL; - uint modem_type = MM_MODEM_TYPE_UNKNOWN; - uint ip_method = MM_MODEM_IP_METHOD_PPP; - uint ip_timeout = 0; - NMModemState state = NM_MODEM_STATE_UNKNOWN; - - if (g_hash_table_lookup (self->priv->modems, path)) { - nm_log_warn (LOGD_MB, "modem with path %s already exists, ignoring", path); - return; - } - - if (!get_modem_properties (nm_dbus_manager_get_connection (self->priv->dbus_mgr), - path, &master_device, &data_device, &driver, - &modem_type, &ip_method, &ip_timeout, &state)) - return; - - if (modem_type == MM_MODEM_TYPE_UNKNOWN) { - nm_log_warn (LOGD_MB, "modem with path %s has unknown type, ignoring", path); - return; - } - - if (!master_device || !strlen (master_device)) { - nm_log_warn (LOGD_MB, "modem with path %s has unknown device, ignoring", path); - return; - } - - if (!driver || !strlen (driver)) { - nm_log_warn (LOGD_MB, "modem with path %s has unknown driver, ignoring", path); - return; - } - - if (!data_device || !strlen (data_device)) { - nm_log_warn (LOGD_MB, "modem with path %s has unknown data device, ignoring", path); - return; - } - - if (modem_type == MM_MODEM_TYPE_GSM) - modem = nm_modem_gsm_new (path, data_device, ip_method, state); - else if (modem_type == MM_MODEM_TYPE_CDMA) - modem = nm_modem_cdma_new (path, data_device, ip_method, state); - else - nm_log_warn (LOGD_MB, "unknown modem type '%d'", modem_type); - - g_free (data_device); - - if (modem) { - g_object_set (G_OBJECT (modem), NM_MODEM_IP_TIMEOUT, ip_timeout, NULL); - g_hash_table_insert (self->priv->modems, g_strdup (path), modem); - g_signal_emit (self, signals[MODEM_ADDED], 0, modem, driver); - } - - g_free (driver); -} - -static void -modem_added (DBusGProxy *proxy, const char *path, gpointer user_data) -{ - create_modem (NM_MODEM_MANAGER (user_data), path); -} - -static void -modem_removed (DBusGProxy *proxy, const char *path, gpointer user_data) -{ - NMModemManager *self = NM_MODEM_MANAGER (user_data); - NMModem *modem; - - modem = (NMModem *) g_hash_table_lookup (self->priv->modems, path); - if (modem) { - g_signal_emit (self, signals[MODEM_REMOVED], 0, modem); - g_hash_table_remove (self->priv->modems, path); - } -} - -static void -mm_poke_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) -{ - GPtrArray *modems; - int i; - - if (dbus_g_proxy_end_call (proxy, call, NULL, - DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH, &modems, - G_TYPE_INVALID)) { - /* Don't care about the returned value, just free it */ - for (i = 0; i < modems->len; i++) - g_free ((char *) g_ptr_array_index (modems, i)); - g_ptr_array_free (modems, TRUE); - } - g_object_unref (proxy); -} - -static gboolean -poke_modem_cb (gpointer user_data) -{ - NMModemManager *self = NM_MODEM_MANAGER (user_data); - DBusGConnection *g_connection; - DBusGProxy *proxy; - DBusGProxyCall *call; - - g_connection = nm_dbus_manager_get_connection (self->priv->dbus_mgr); - proxy = dbus_g_proxy_new_for_name (g_connection, - MM_OLD_DBUS_SERVICE, - MM_OLD_DBUS_PATH, - MM_OLD_DBUS_INTERFACE); - - nm_log_dbg (LOGD_MB, "Requesting to (re)launch modem-manager..."); - - call = dbus_g_proxy_begin_call_with_timeout (proxy, - "EnumerateDevices", - mm_poke_cb, - NULL, - NULL, - 5000, - G_TYPE_INVALID); - return TRUE; -} - -static void -enumerate_devices_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer data) -{ - NMModemManager *manager = NM_MODEM_MANAGER (data); - GPtrArray *modems; - GError *error = NULL; - - if (!dbus_g_proxy_end_call (proxy, call_id, &error, - dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH), &modems, - G_TYPE_INVALID)) { - nm_log_warn (LOGD_MB, "could not get modem list: %s", error->message); - g_error_free (error); - } else { - int i; - - for (i = 0; i < modems->len; i++) { - char *path = (char *) g_ptr_array_index (modems, i); - - create_modem (manager, path); - g_free (path); - } - - g_ptr_array_free (modems, TRUE); - } -} - -#if WITH_MODEM_MANAGER_1 -static void clear_modem_manager_1_support (NMModemManager *self); -#endif - -static void -modem_manager_appeared (NMModemManager *self, gboolean enumerate_devices) -{ - if (self->priv->poke_id) { - g_source_remove (self->priv->poke_id); - self->priv->poke_id = 0; - } - - nm_log_info (LOGD_MB, "modem-manager is now available"); - -#if WITH_MODEM_MANAGER_1 - self->priv->old_modem_manager_found = TRUE; - if (self->priv->new_modem_manager_found) - nm_log_warn (LOGD_MB, "Both the old and the new ModemManager were found"); - else - clear_modem_manager_1_support (self); -#endif - - self->priv->proxy = dbus_g_proxy_new_for_name (nm_dbus_manager_get_connection (self->priv->dbus_mgr), - MM_OLD_DBUS_SERVICE, MM_OLD_DBUS_PATH, MM_OLD_DBUS_INTERFACE); - - dbus_g_proxy_add_signal (self->priv->proxy, "DeviceAdded", DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID); - dbus_g_proxy_connect_signal (self->priv->proxy, "DeviceAdded", - G_CALLBACK (modem_added), self, - NULL); - - dbus_g_proxy_add_signal (self->priv->proxy, "DeviceRemoved", DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID); - dbus_g_proxy_connect_signal (self->priv->proxy, "DeviceRemoved", - G_CALLBACK (modem_removed), self, - NULL); - - if (enumerate_devices) - dbus_g_proxy_begin_call (self->priv->proxy, "EnumerateDevices", enumerate_devices_done, self, NULL, G_TYPE_INVALID); -} - -static gboolean -remove_one_modem (gpointer key, gpointer value, gpointer user_data) -{ - g_signal_emit (user_data, signals[MODEM_REMOVED], 0, value); - - return TRUE; -} - -static void -modem_manager_disappeared (NMModemManager *self) -{ - g_hash_table_foreach_remove (self->priv->modems, remove_one_modem, self); - - if (self->priv->proxy) { - g_object_unref (self->priv->proxy); - self->priv->proxy = NULL; - } - - /* Try to activate the modem-manager */ - nm_log_dbg (LOGD_MB, "trying to start the modem manager..."); - poke_modem_cb (self); - self->priv->poke_id = g_timeout_add_seconds (MODEM_POKE_INTERVAL, poke_modem_cb, self); -} - -static void -nm_modem_manager_name_owner_changed (NMDBusManager *dbus_mgr, - const char *name, - const char *old_owner, - const char *new_owner, - gpointer user_data) -{ - gboolean old_owner_good; - gboolean new_owner_good; - - /* Can't handle the signal if its not from the modem service */ - if (strcmp (MM_OLD_DBUS_SERVICE, name) != 0) - return; - - old_owner_good = (old_owner && strlen (old_owner)); - new_owner_good = (new_owner && strlen (new_owner)); - - if (!old_owner_good && new_owner_good) { - modem_manager_appeared (NM_MODEM_MANAGER (user_data), FALSE); - } else if (old_owner_good && !new_owner_good) { - nm_log_info (LOGD_MB, "the modem manager disappeared"); - modem_manager_disappeared (NM_MODEM_MANAGER (user_data)); - } -} - -/************************************************************************/ -/* Support for ModemManager >= 0.7 */ - -#if WITH_MODEM_MANAGER_1 - -static void -modem_manager_1_clear_signals (NMModemManager *self) -{ - if (!self->priv->modem_manager_1) - return; - - if (self->priv->modem_manager_1_name_owner_changed_id) { - if (g_signal_handler_is_connected (self->priv->modem_manager_1, - self->priv->modem_manager_1_name_owner_changed_id)) - g_signal_handler_disconnect (self->priv->modem_manager_1, - self->priv->modem_manager_1_name_owner_changed_id); - self->priv->modem_manager_1_name_owner_changed_id = 0; - } - - if (self->priv->modem_manager_1_object_added_id) { - if (g_signal_handler_is_connected (self->priv->modem_manager_1, - self->priv->modem_manager_1_object_added_id)) - g_signal_handler_disconnect (self->priv->modem_manager_1, - self->priv->modem_manager_1_object_added_id); - self->priv->modem_manager_1_object_added_id = 0; - } - - if (self->priv->modem_manager_1_object_removed_id) { - if (g_signal_handler_is_connected (self->priv->modem_manager_1, - self->priv->modem_manager_1_object_removed_id)) - g_signal_handler_disconnect (self->priv->modem_manager_1, - self->priv->modem_manager_1_object_removed_id); - self->priv->modem_manager_1_object_removed_id = 0; - } -} - -static void -clear_modem_manager_1_support (NMModemManager *self) -{ - if (self->priv->modem_manager_1_launch_id) { - g_source_remove (self->priv->modem_manager_1_launch_id); - self->priv->modem_manager_1_launch_id = 0; - } - - modem_manager_1_clear_signals (self); - g_clear_object (&self->priv->modem_manager_1); - g_clear_object (&self->priv->dbus_connection); -} - -static void -modem_object_added (MMManager *modem_manager, - MMObject *modem_object, - NMModemManager *self) -{ - const gchar *path; - gchar *drivers; - MMModem *modem_iface; - NMModem *modem; - - /* Ensure we don't have the same modem already */ - path = mm_object_get_path (modem_object); - if (g_hash_table_lookup (self->priv->modems, path)) { - nm_log_warn (LOGD_MB, "modem with path %s already exists, ignoring", path); - return; - } - - /* Ensure we have the 'Modem' interface at least */ - modem_iface = mm_object_peek_modem (modem_object); - if (!modem_iface) { - nm_log_warn (LOGD_MB, "modem with path %s doesn't have the Modem interface, ignoring", path); - return; - } - - /* Ensure we have a primary port reported */ - if (!mm_modem_get_primary_port (modem_iface)) { - nm_log_warn (LOGD_MB, "modem with path %s has unknown primary port, ignoring", path); - return; - } - - /* Create a new modem object */ - modem = nm_modem_broadband_new (G_OBJECT (modem_object)); - if (!modem) - return; - - /* Build a single string with all drivers listed */ - drivers = g_strjoinv (", ", (gchar **)mm_modem_get_drivers (modem_iface)); - - /* Keep track of the new modem and notify about it */ - g_hash_table_insert (self->priv->modems, g_strdup (path), modem); - g_signal_emit (self, signals[MODEM_ADDED], 0, modem, drivers); - g_free (drivers); -} - -static void -modem_object_removed (MMManager *manager, - MMObject *modem_object, - NMModemManager *self) -{ - NMModem *modem; - const gchar *path; - - path = mm_object_get_path (modem_object); - modem = (NMModem *) g_hash_table_lookup (self->priv->modems, path); - if (!modem) - return; - - g_signal_emit (self, signals[MODEM_REMOVED], 0, modem); - g_hash_table_remove (self->priv->modems, path); -} - -static void -modem_manager_1_available (NMModemManager *self) -{ - GList *modems, *l; - - nm_log_info (LOGD_MB, "ModemManager available in the bus"); - - self->priv->new_modem_manager_found = TRUE; - if (self->priv->old_modem_manager_found) - nm_log_warn (LOGD_MB, "Both the old and the new ModemManager were found"); - else - clear_modem_manager_support (self); - - /* Update initial modems list */ - modems = g_dbus_object_manager_get_objects (G_DBUS_OBJECT_MANAGER (self->priv->modem_manager_1)); - for (l = modems; l; l = g_list_next (l)) - modem_object_added (self->priv->modem_manager_1, MM_OBJECT (l->data), self); - g_list_free_full (modems, (GDestroyNotify) g_object_unref); -} - -static void schedule_modem_manager_1_relaunch (NMModemManager *self, - guint n_seconds); -static void ensure_client (NMModemManager *self); - -static void -modem_manager_1_name_owner_changed (MMManager *modem_manager_1, - GParamSpec *pspec, - NMModemManager *self) -{ - gchar *name_owner; - - /* Quit poking, if any */ - if (self->priv->modem_manager_1_launch_id) { - g_source_remove (self->priv->modem_manager_1_launch_id); - self->priv->modem_manager_1_launch_id = 0; - } - - name_owner = g_dbus_object_manager_client_get_name_owner (G_DBUS_OBJECT_MANAGER_CLIENT (modem_manager_1)); - if (!name_owner) { - nm_log_info (LOGD_MB, "ModemManager disappeared from bus"); - -#if !HAVE_SYSTEMD - /* If not managed by systemd, schedule relaunch */ - schedule_modem_manager_1_relaunch (self, 0); -#endif - - return; - } - - /* Available! */ - g_free (name_owner); - - /* Hack alert: GDBusObjectManagerClient won't signal neither 'object-added' - * nor 'object-removed' if it was created while there was no ModemManager in - * the bus. This hack avoids this issue until we get a GIO with the fix - * included... */ - modem_manager_1_clear_signals (self); - g_clear_object (&self->priv->modem_manager_1); - ensure_client (self); - - /* Whenever GDBusObjectManagerClient is fixed, we can just do the following: - * modem_manager_1_available (self); - */ -} - -#if !HAVE_SYSTEMD - -static void -modem_manager_1_poke_cb (GDBusConnection *connection, - GAsyncResult *res, - NMModemManager *self) -{ - GError *error = NULL; - GVariant *result; - - result = g_dbus_connection_call_finish (connection, res, &error); - if (error) { - /* Ignore common errors when MM is not installed and such */ - if ( !g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN) - && !g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SPAWN_EXEC_FAILED) - && !g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SPAWN_FORK_FAILED) - && !g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SPAWN_FAILED) - && !g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_TIMEOUT) - && !g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SPAWN_SERVICE_NOT_FOUND)) { - nm_log_dbg (LOGD_MB, "error poking ModemManager: %s", error->message); - } - g_error_free (error); - - /* Setup timeout to relaunch */ - schedule_modem_manager_1_relaunch (self, MODEM_POKE_INTERVAL); - } else - g_variant_unref (result); - - /* Balance refcount */ - g_object_unref (self); -} - -static void -modem_manager_1_poke (NMModemManager *self) -{ - /* If there is no current owner right away, ensure we poke to get one */ - g_dbus_connection_call (self->priv->dbus_connection, - "org.freedesktop.ModemManager1", - "/org/freedesktop/ModemManager1", - "org.freedesktop.DBus.Peer", - "Ping", - NULL, /* inputs */ - NULL, /* outputs */ - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, /* cancellable */ - (GAsyncReadyCallback)modem_manager_1_poke_cb, /* callback */ - g_object_ref (self)); /* user_data */ -} - -#endif /* HAVE_SYSTEMD */ - -static void -modem_manager_1_check_name_owner (NMModemManager *self) -{ - gchar *name_owner; - - name_owner = g_dbus_object_manager_client_get_name_owner (G_DBUS_OBJECT_MANAGER_CLIENT (self->priv->modem_manager_1)); - if (name_owner) { - /* Available! */ - modem_manager_1_available (self); - g_free (name_owner); - return; - } - -#if !HAVE_SYSTEMD - /* If the lifecycle is not managed by systemd, poke */ - modem_manager_1_poke (self); -#endif -} - -static void -manager_new_ready (GObject *source, - GAsyncResult *res, - NMModemManager *self) -{ - /* Note we always get an extra reference to self here */ - - GError *error = NULL; - - g_assert (!self->priv->modem_manager_1); - self->priv->modem_manager_1 = mm_manager_new_finish (res, &error); - if (!self->priv->modem_manager_1) { - /* We're not really supposed to get any error here. If we do get one, - * though, just re-schedule the MMManager creation after some time. - * During this period, name-owner changes won't be followed. */ - nm_log_warn (LOGD_MB, "error creating ModemManager client: %s", error->message); - g_error_free (error); - /* Setup timeout to relaunch */ - schedule_modem_manager_1_relaunch (self, MODEM_POKE_INTERVAL); - } else if (self->priv->old_modem_manager_found) { - /* If we found the old MM, abort */ - clear_modem_manager_1_support (self); - } else { - /* Setup signals in the GDBusObjectManagerClient */ - self->priv->modem_manager_1_name_owner_changed_id = - g_signal_connect (self->priv->modem_manager_1, - "notify::name-owner", - G_CALLBACK (modem_manager_1_name_owner_changed), - self); - self->priv->modem_manager_1_object_added_id = - g_signal_connect (self->priv->modem_manager_1, - "object-added", - G_CALLBACK (modem_object_added), - self); - self->priv->modem_manager_1_object_removed_id = - g_signal_connect (self->priv->modem_manager_1, - "object-removed", - G_CALLBACK (modem_object_removed), - self); - - modem_manager_1_check_name_owner (self); - } - - /* Balance refcount */ - g_object_unref (self); -} - -static void -ensure_client (NMModemManager *self) -{ - g_assert (self->priv->dbus_connection); - - /* Create the GDBusObjectManagerClient. We do not request to autostart, as - * we don't really want the MMManager creation to fail. We can always poke - * later on if we want to request the autostart */ - if (!self->priv->modem_manager_1) { - mm_manager_new (self->priv->dbus_connection, - G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_DO_NOT_AUTO_START, - NULL, - (GAsyncReadyCallback)manager_new_ready, - g_object_ref (self)); - return; - } - - /* If already available, recheck name owner! */ - modem_manager_1_check_name_owner (self); -} - -static void -bus_get_ready (GObject *source, - GAsyncResult *res, - NMModemManager *self) -{ - /* Note we always get an extra reference to self here */ - - GError *error = NULL; - - self->priv->dbus_connection = g_bus_get_finish (res, &error); - if (!self->priv->dbus_connection) { - nm_log_warn (LOGD_CORE, "error getting bus connection: %s", error->message); - g_error_free (error); - /* Setup timeout to relaunch */ - schedule_modem_manager_1_relaunch (self, MODEM_POKE_INTERVAL); - } else if (self->priv->old_modem_manager_found) { - /* If we found the old MM, abort */ - clear_modem_manager_1_support (self); - } else { - /* Got the bus, ensure client */ - ensure_client (self); - } - - /* Balance refcount */ - g_object_unref (self); -} - -static gboolean -ensure_bus (NMModemManager *self) -{ - /* Clear launch ID */ - self->priv->modem_manager_1_launch_id = 0; - - if (!self->priv->dbus_connection) - g_bus_get (G_BUS_TYPE_SYSTEM, - NULL, - (GAsyncReadyCallback)bus_get_ready, - g_object_ref (self)); - else - /* If bus is already available, ensure client */ - ensure_client (self); - - return FALSE; -} - -static void -schedule_modem_manager_1_relaunch (NMModemManager *self, - guint n_seconds) -{ - /* No need to pass an extra reference to self; timeout/idle will be - * cancelled if the object gets disposed. */ - - if (n_seconds) - self->priv->modem_manager_1_launch_id = g_timeout_add_seconds (n_seconds, (GSourceFunc)ensure_bus, self); - else - self->priv->modem_manager_1_launch_id = g_idle_add ((GSourceFunc)ensure_bus, self); -} - -#endif /* WITH_MODEM_MANAGER_1 */ - -/************************************************************************/ - -static void -nm_modem_manager_init (NMModemManager *self) -{ - self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NM_TYPE_MODEM_MANAGER, NMModemManagerPrivate); - - self->priv->modems = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); - - /* ModemManager < 0.7 */ - self->priv->dbus_mgr = nm_dbus_manager_get (); - g_signal_connect (self->priv->dbus_mgr, NM_DBUS_MANAGER_NAME_OWNER_CHANGED, - G_CALLBACK (nm_modem_manager_name_owner_changed), - self); - if (nm_dbus_manager_name_has_owner (self->priv->dbus_mgr, MM_OLD_DBUS_SERVICE)) - modem_manager_appeared (self, TRUE); - else - modem_manager_disappeared (self); - -#if WITH_MODEM_MANAGER_1 - /* ModemManager >= 0.7 */ - schedule_modem_manager_1_relaunch (self, 0); -#endif -} - -static void -dispose (GObject *object) -{ - NMModemManager *self = NM_MODEM_MANAGER (object); - - /* ModemManager < 0.7 */ - clear_modem_manager_support (self); - -#if WITH_MODEM_MANAGER_1 - /* ModemManager >= 0.7 */ - clear_modem_manager_1_support (self); -#endif - - if (self->priv->modems) { - g_hash_table_foreach_remove (self->priv->modems, remove_one_modem, object); - g_hash_table_destroy (self->priv->modems); - } - - if (self->priv->dbus_mgr) { - g_object_unref (self->priv->dbus_mgr); - self->priv->dbus_mgr = NULL; - } - - /* Chain up to the parent class */ - G_OBJECT_CLASS (nm_modem_manager_parent_class)->dispose (object); -} - -static void -nm_modem_manager_class_init (NMModemManagerClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - g_type_class_add_private (object_class, sizeof (NMModemManagerPrivate)); - - object_class->dispose = dispose; - - /* signals */ - signals[MODEM_ADDED] = - g_signal_new ("modem-added", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMModemManagerClass, modem_added), - NULL, NULL, - _nm_marshal_VOID__OBJECT_STRING, - G_TYPE_NONE, 2, G_TYPE_OBJECT, G_TYPE_STRING); - - signals[MODEM_REMOVED] = - g_signal_new ("modem-removed", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMModemManagerClass, modem_removed), - NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, G_TYPE_OBJECT); -} diff --git a/src/modem-manager/nm-modem-manager.h b/src/modem-manager/nm-modem-manager.h deleted file mode 100644 index 0c2b243b..00000000 --- a/src/modem-manager/nm-modem-manager.h +++ /dev/null @@ -1,58 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2009 Red Hat, Inc. - * Copyright (C) 2009 Novell, Inc. - * Copyright (C) 2009 Canonical Ltd. - */ - -#ifndef NM_MODEM_MANAGER_H -#define NM_MODEM_MANAGER_H - -#include -#include "nm-modem.h" - -#define NM_TYPE_MODEM_MANAGER (nm_modem_manager_get_type ()) -#define NM_MODEM_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_MODEM_MANAGER, NMModemManager)) -#define NM_MODEM_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_MODEM_MANAGER, NMModemManagerClass)) -#define NM_IS_MODEM_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_MODEM_MANAGER)) -#define NM_IS_MODEM_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_MODEM_MANAGER)) -#define NM_MODEM_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_MODEM_MANAGER, NMModemManagerClass)) - -typedef struct _NMModemManager NMModemManager; -typedef struct _NMModemManagerClass NMModemManagerClass; -typedef struct _NMModemManagerPrivate NMModemManagerPrivate; - -struct _NMModemManager { - GObject parent; - NMModemManagerPrivate *priv; -}; - -struct _NMModemManagerClass { - GObjectClass parent; - - /* Signals */ - void (*modem_added) (NMModemManager *manager, NMModem *modem, const char *driver); - - void (*modem_removed) (NMModemManager *manager, NMModem *modem); -}; - -GType nm_modem_manager_get_type (void); - -NMModemManager *nm_modem_manager_get (void); - -#endif /* NM_MODEM_MANAGER_H */ diff --git a/src/modem-manager/nm-modem-types.h b/src/modem-manager/nm-modem-types.h deleted file mode 100644 index 9fc8deed..00000000 --- a/src/modem-manager/nm-modem-types.h +++ /dev/null @@ -1,106 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2009 Novell, Inc. - */ - -#ifndef NM_MODEM_TYPES_H -#define NM_MODEM_TYPES_H - -#define MM_OLD_DBUS_SERVICE "org.freedesktop.ModemManager" -#define MM_OLD_DBUS_PATH "/org/freedesktop/ModemManager" -#define MM_OLD_DBUS_INTERFACE "org.freedesktop.ModemManager" -#define MM_OLD_DBUS_INTERFACE_MODEM "org.freedesktop.ModemManager.Modem" -#define MM_OLD_DBUS_INTERFACE_MODEM_SIMPLE "org.freedesktop.ModemManager.Modem.Simple" -#define MM_OLD_DBUS_INTERFACE_MODEM_CDMA "org.freedesktop.ModemManager.Modem.Cdma" -#define MM_OLD_DBUS_INTERFACE_MODEM_GSM_CARD "org.freedesktop.ModemManager.Modem.Gsm.Card" -#define MM_OLD_DBUS_INTERFACE_MODEM_GSM_NETWORK "org.freedesktop.ModemManager.Modem.Gsm.Network" - -#define MM_MODEM_TYPE_UNKNOWN 0 -#define MM_MODEM_TYPE_GSM 1 -#define MM_MODEM_TYPE_CDMA 2 - -/* Errors */ - -#define MM_SERIAL_OPEN_FAILED MM_OLD_DBUS_INTERFACE_MODEM ".SerialOpenFailed" -#define MM_SERIAL_SEND_FAILED MM_OLD_DBUS_INTERFACE_MODEM ".SerialSendFailed" -#define MM_SERIAL_RESPONSE_TIMEOUT MM_OLD_DBUS_INTERFACE_MODEM ".SerialResponseTimeout" - -#define MM_MODEM_ERROR_GENERAL MM_OLD_DBUS_INTERFACE_MODEM ".General" -#define MM_MODEM_ERROR_OPERATION_NOT_SUPPORTED MM_OLD_DBUS_INTERFACE_MODEM ".OperationNotSupported" - -#define MM_MODEM_CONNECT_ERROR_NO_CARRIER MM_OLD_DBUS_INTERFACE_MODEM ".NoCarrier" -#define MM_MODEM_CONNECT_ERROR_NO_DIALTONE MM_OLD_DBUS_INTERFACE_MODEM ".NoDialtone" -#define MM_MODEM_CONNECT_ERROR_BUSY MM_OLD_DBUS_INTERFACE_MODEM ".Busy" -#define MM_MODEM_CONNECT_ERROR_NO_ANSWER MM_OLD_DBUS_INTERFACE_MODEM ".NoAnswer" - -#define MM_MODEM_ERROR "org.freedesktop.ModemManager.Modem.Gsm" - -#define MM_MODEM_ERROR_PHONE_FAILURE MM_MODEM_ERROR ".PhoneFailure" -#define MM_MODEM_ERROR_NO_CONNECTION MM_MODEM_ERROR ".NoConnection" -#define MM_MODEM_ERROR_LINK_RESERVED MM_MODEM_ERROR ".LinkReserved" -#define MM_MODEM_ERROR_NOT_ALLOWED MM_MODEM_ERROR ".OperationNotAllowed" -#define MM_MODEM_ERROR_NOT_SUPPORTED MM_MODEM_ERROR ".OperationNotSupported" -#define MM_MODEM_ERROR_PH_SIM_PIN MM_MODEM_ERROR ".PhSimPinRequired" -#define MM_MODEM_ERROR_PH_FSIM_PIN MM_MODEM_ERROR ".PhFSimPinRequired" -#define MM_MODEM_ERROR_PH_FSIM_PUK MM_MODEM_ERROR ".PhFPukRequired" -#define MM_MODEM_ERROR_SIM_NOT_INSERTED MM_MODEM_ERROR ".SimNotInserted" -#define MM_MODEM_ERROR_SIM_PIN MM_MODEM_ERROR ".SimPinRequired" -#define MM_MODEM_ERROR_SIM_PUK MM_MODEM_ERROR ".SimPukRequired" -#define MM_MODEM_ERROR_SIM_FAILURE MM_MODEM_ERROR ".SimFailure" -#define MM_MODEM_ERROR_SIM_BUSY MM_MODEM_ERROR ".SimBusy" -#define MM_MODEM_ERROR_SIM_WRONG MM_MODEM_ERROR ".SimWrong" -#define MM_MODEM_ERROR_WRONG_PASSWORD MM_MODEM_ERROR ".IncorrectPassword" -#define MM_MODEM_ERROR_SIM_PIN2 MM_MODEM_ERROR ".SimPin2Required" -#define MM_MODEM_ERROR_SIM_PUK2 MM_MODEM_ERROR ".SimPuk2Required" -#define MM_MODEM_ERROR_MEMORY_FULL MM_MODEM_ERROR ".MemoryFull" -#define MM_MODEM_ERROR_INVALID_INDEX MM_MODEM_ERROR ".InvalidIndex" -#define MM_MODEM_ERROR_NOT_FOUND MM_MODEM_ERROR ".NotFound" -#define MM_MODEM_ERROR_MEMORY_FAILURE MM_MODEM_ERROR ".MemoryFailure" -#define MM_MODEM_ERROR_TEXT_TOO_LONG MM_MODEM_ERROR ".TextTooLong" -#define MM_MODEM_ERROR_INVALID_CHARS MM_MODEM_ERROR ".InvalidChars" -#define MM_MODEM_ERROR_DIAL_STRING_TOO_LONG MM_MODEM_ERROR ".DialStringTooLong" -#define MM_MODEM_ERROR_DIAL_STRING_INVALID MM_MODEM_ERROR ".InvalidDialString" -#define MM_MODEM_ERROR_NO_NETWORK MM_MODEM_ERROR ".NoNetwork" -#define MM_MODEM_ERROR_NETWORK_TIMEOUT MM_MODEM_ERROR ".NetworkTimeout" -#define MM_MODEM_ERROR_NETWORK_NOT_ALLOWED MM_MODEM_ERROR ".NetworkNotAllowed" -#define MM_MODEM_ERROR_NETWORK_PIN MM_MODEM_ERROR ".NetworkPinRequired" -#define MM_MODEM_ERROR_NETWORK_PUK MM_MODEM_ERROR ".NetworkPukRequired" -#define MM_MODEM_ERROR_NETWORK_SUBSET_PIN MM_MODEM_ERROR ".NetworkSubsetPinRequired" -#define MM_MODEM_ERROR_NETWORK_SUBSET_PUK MM_MODEM_ERROR ".NetworkSubsetPukRequired" -#define MM_MODEM_ERROR_SERVICE_PIN MM_MODEM_ERROR ".ServicePinRequired" -#define MM_MODEM_ERROR_SERVICE_PUK MM_MODEM_ERROR ".ServicePukRequired" -#define MM_MODEM_ERROR_CORP_PIN MM_MODEM_ERROR ".CorporatePinRequired" -#define MM_MODEM_ERROR_CORP_PUK MM_MODEM_ERROR ".CorporatePukRequired" -#define MM_MODEM_ERROR_HIDDEN_KEY MM_MODEM_ERROR ".HiddenKeyRequired" -#define MM_MODEM_ERROR_EAP_NOT_SUPPORTED MM_MODEM_ERROR ".EapMethodNotSupported" -#define MM_MODEM_ERROR_INCORRECT_PARAMS MM_MODEM_ERROR ".IncorrectParams" -#define MM_MODEM_ERROR_UNKNOWN MM_MODEM_ERROR ".Unknown" -#define MM_MODEM_ERROR_GPRS_ILLEGAL_MS MM_MODEM_ERROR ".GprsIllegalMs" -#define MM_MODEM_ERROR_GPRS_ILLEGAL_ME MM_MODEM_ERROR ".GprsIllegalMe" -#define MM_MODEM_ERROR_GPRS_SERVICE_NOT_ALLOWED MM_MODEM_ERROR ".GprsServiceNotAllowed" -#define MM_MODEM_ERROR_GPRS_PLMN_NOT_ALLOWED MM_MODEM_ERROR ".GprsPlmnNotAllowed" -#define MM_MODEM_ERROR_GPRS_LOCATION_NOT_ALLOWED MM_MODEM_ERROR ".GprsLocationNotAllowed" -#define MM_MODEM_ERROR_GPRS_ROAMING_NOT_ALLOWED MM_MODEM_ERROR ".GprsRoamingNotAllowed" -#define MM_MODEM_ERROR_GPRS_OPTION_NOT_SUPPORTED MM_MODEM_ERROR ".GprsOptionNotSupported" -#define MM_MODEM_ERROR_GPRS_NOT_SUBSCRIBED MM_MODEM_ERROR ".GprsNotSubscribed" -#define MM_MODEM_ERROR_GPRS_OUT_OF_ORDER MM_MODEM_ERROR ".GprsOutOfOrder" -#define MM_MODEM_ERROR_GPRS_PDP_AUTH_FAILURE MM_MODEM_ERROR ".GprsPdpAuthFailure" -#define MM_MODEM_ERROR_GPRS_UNKNOWN MM_MODEM_ERROR ".GprsUnspecified" -#define MM_MODEM_ERROR_GPRS_INVALID_CLASS MM_MODEM_ERROR ".GprsInvalidClass" - -#endif /* NM_MODEM_TYPES_H */ diff --git a/src/modem-manager/nm-modem.c b/src/modem-manager/nm-modem.c deleted file mode 100644 index 34aeccf4..00000000 --- a/src/modem-manager/nm-modem.c +++ /dev/null @@ -1,953 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2009 - 2011 Red Hat, Inc. - * Copyright (C) 2009 Novell, Inc. - */ - -#include -#include "nm-modem.h" -#include "nm-system.h" -#include "nm-dbus-manager.h" -#include "nm-setting-connection.h" -#include "nm-marshal.h" -#include "nm-properties-changed-signal.h" -#include "nm-modem-types.h" -#include "nm-logging.h" -#include "NetworkManagerUtils.h" -#include "nm-device-private.h" -#include "nm-dbus-glib-types.h" - -G_DEFINE_TYPE (NMModem, nm_modem, G_TYPE_OBJECT) - -#define NM_MODEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_MODEM, NMModemPrivate)) - -enum { - PROP_0, - PROP_CONTROL_PORT, - PROP_DATA_PORT, - PROP_PATH, - PROP_UID, - PROP_IP_METHOD, - PROP_IP_TIMEOUT, - PROP_ENABLED, - PROP_CONNECTED, - - LAST_PROP -}; - -typedef struct { - char *uid; - char *path; - char *control_port; - char *data_port; - char *ppp_iface; - guint32 ip_method; - - NMPPPManager *ppp_manager; - - NMActRequest *act_request; - guint32 secrets_tries; - guint32 secrets_id; - - gboolean mm_enabled; - guint32 mm_ip_timeout; - gboolean mm_connected; - - /* PPP stats */ - guint32 in_bytes; - guint32 out_bytes; -} NMModemPrivate; - -enum { - PPP_STATS, - PPP_FAILED, - PREPARE_RESULT, - IP4_CONFIG_RESULT, - AUTH_REQUESTED, - AUTH_RESULT, - - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -/*****************************************************************************/ -/* Get/Set enabled/connected */ - -gboolean -nm_modem_get_mm_enabled (NMModem *self) -{ - return NM_MODEM_GET_PRIVATE (self)->mm_enabled; -} - -void -nm_modem_set_mm_enabled (NMModem *self, - gboolean enabled) -{ - NMModemPrivate *priv; - - priv = NM_MODEM_GET_PRIVATE (self); - - if (priv->mm_enabled != enabled) - NM_MODEM_GET_CLASS (self)->set_mm_enabled (self, enabled); -} - -gboolean -nm_modem_get_mm_connected (NMModem *self) -{ - return NM_MODEM_GET_PRIVATE (self)->mm_connected; -} - -/*****************************************************************************/ -/* IP method PPP */ - -static void -ppp_state_changed (NMPPPManager *ppp_manager, NMPPPStatus status, gpointer user_data) -{ - switch (status) { - case NM_PPP_STATUS_DISCONNECT: - g_signal_emit (NM_MODEM (user_data), signals[PPP_FAILED], 0, NM_DEVICE_STATE_REASON_PPP_DISCONNECT); - break; - case NM_PPP_STATUS_DEAD: - g_signal_emit (NM_MODEM (user_data), signals[PPP_FAILED], 0, NM_DEVICE_STATE_REASON_PPP_FAILED); - break; - default: - break; - } -} - -static void -ppp_ip4_config (NMPPPManager *ppp_manager, - const char *iface, - NMIP4Config *config, - gpointer user_data) -{ - NMModem *self = NM_MODEM (user_data); - NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); - guint32 i, num; - guint32 bad_dns1 = htonl (0x0A0B0C0D); - guint32 good_dns1 = htonl (0x04020201); /* GTE nameserver */ - guint32 bad_dns2 = htonl (0x0A0B0C0E); - guint32 good_dns2 = htonl (0x04020202); /* GTE nameserver */ - gboolean dns_workaround = FALSE; - - /* Notify about the new data port to use */ - g_free (priv->ppp_iface); - priv->ppp_iface = g_strdup (iface); - g_object_notify (G_OBJECT (self), NM_MODEM_DATA_PORT); - - /* Work around a PPP bug (#1732) which causes many mobile broadband - * providers to return 10.11.12.13 and 10.11.12.14 for the DNS servers. - * Apparently fixed in ppp-2.4.5 but we've had some reports that this is - * not the case. - * - * http://git.ozlabs.org/?p=ppp.git;a=commitdiff_plain;h=2e09ef6886bbf00bc5a9a641110f801e372ffde6 - * http://git.ozlabs.org/?p=ppp.git;a=commitdiff_plain;h=f8191bf07df374f119a07910a79217c7618f113e - */ - - num = nm_ip4_config_get_num_nameservers (config); - if (num == 2) { - gboolean found1 = FALSE, found2 = FALSE; - - for (i = 0; i < num; i++) { - guint32 ns = nm_ip4_config_get_nameserver (config, i); - - if (ns == bad_dns1) - found1 = TRUE; - else if (ns == bad_dns2) - found2 = TRUE; - } - - /* Be somewhat conservative about substitutions; the "bad" nameservers - * could actually be valid in some cases, so only substitute if ppp - * returns *only* the two bad nameservers. - */ - dns_workaround = (found1 && found2); - } - - if (!num || dns_workaround) { - nm_log_warn (LOGD_PPP, "compensating for invalid PPP-provided nameservers"); - nm_ip4_config_reset_nameservers (config); - nm_ip4_config_add_nameserver (config, good_dns1); - nm_ip4_config_add_nameserver (config, good_dns2); - } - - g_signal_emit (self, signals[IP4_CONFIG_RESULT], 0, config, NULL); -} - -static void -ppp_stats (NMPPPManager *ppp_manager, - guint32 in_bytes, - guint32 out_bytes, - gpointer user_data) -{ - NMModem *self = NM_MODEM (user_data); - NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); - - if (priv->in_bytes != in_bytes || priv->out_bytes != out_bytes) { - priv->in_bytes = in_bytes; - priv->out_bytes = out_bytes; - - g_signal_emit (self, signals[PPP_STATS], 0, in_bytes, out_bytes); - } -} - -static NMActStageReturn -ppp_stage3_ip4_config_start (NMModem *self, - NMActRequest *req, - NMDeviceStateReason *reason) -{ - NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); - const char *ppp_name = NULL; - GError *error = NULL; - NMActStageReturn ret; - guint ip_timeout = 20; - - g_return_val_if_fail (self != NULL, NM_ACT_STAGE_RETURN_FAILURE); - g_return_val_if_fail (NM_IS_MODEM (self), NM_ACT_STAGE_RETURN_FAILURE); - g_return_val_if_fail (req != NULL, NM_ACT_STAGE_RETURN_FAILURE); - g_return_val_if_fail (NM_IS_ACT_REQUEST (req), NM_ACT_STAGE_RETURN_FAILURE); - g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); - - if (NM_MODEM_GET_CLASS (self)->get_user_pass) { - NMConnection *connection = nm_act_request_get_connection (req); - - g_assert (connection); - if (!NM_MODEM_GET_CLASS (self)->get_user_pass (self, connection, &ppp_name, NULL)) - return NM_ACT_STAGE_RETURN_FAILURE; - } - - /* Check if ModemManager requested a specific IP timeout to be used. If 0 reported, - * use the default one (20s) */ - if (priv->mm_ip_timeout > 0) { - nm_log_info (LOGD_PPP, "using modem-specified IP timeout: %u seconds", - priv->mm_ip_timeout); - ip_timeout = priv->mm_ip_timeout; - } - - priv->ppp_manager = nm_ppp_manager_new (priv->data_port); - if (nm_ppp_manager_start (priv->ppp_manager, req, ppp_name, ip_timeout, &error)) { - g_signal_connect (priv->ppp_manager, "state-changed", - G_CALLBACK (ppp_state_changed), - self); - g_signal_connect (priv->ppp_manager, "ip4-config", - G_CALLBACK (ppp_ip4_config), - self); - g_signal_connect (priv->ppp_manager, "stats", - G_CALLBACK (ppp_stats), - self); - - ret = NM_ACT_STAGE_RETURN_POSTPONE; - } else { - nm_log_err (LOGD_PPP, "error starting PPP: (%d) %s", - error ? error->code : -1, - error && error->message ? error->message : "(unknown)"); - g_error_free (error); - - g_object_unref (priv->ppp_manager); - priv->ppp_manager = NULL; - - *reason = NM_DEVICE_STATE_REASON_PPP_START_FAILED; - ret = NM_ACT_STAGE_RETURN_FAILURE; - } - - return ret; -} - -/*****************************************************************************/ - -NMActStageReturn -nm_modem_stage3_ip4_config_start (NMModem *self, - NMDevice *device, - NMDeviceClass *device_class, - NMDeviceStateReason *reason) -{ - NMModemPrivate *priv; - NMActRequest *req; - NMActStageReturn ret; - - g_return_val_if_fail (self != NULL, NM_ACT_STAGE_RETURN_FAILURE); - g_return_val_if_fail (NM_IS_MODEM (self), NM_ACT_STAGE_RETURN_FAILURE); - g_return_val_if_fail (device != NULL, NM_ACT_STAGE_RETURN_FAILURE); - g_return_val_if_fail (NM_IS_DEVICE (device), NM_ACT_STAGE_RETURN_FAILURE); - g_return_val_if_fail (device_class != NULL, NM_ACT_STAGE_RETURN_FAILURE); - g_return_val_if_fail (NM_IS_DEVICE_CLASS (device_class), NM_ACT_STAGE_RETURN_FAILURE); - g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); - - req = nm_device_get_act_request (device); - g_assert (req); - - priv = NM_MODEM_GET_PRIVATE (self); - switch (priv->ip_method) { - case MM_MODEM_IP_METHOD_PPP: - ret = ppp_stage3_ip4_config_start (self, req, reason); - break; - case MM_MODEM_IP_METHOD_STATIC: - ret = NM_MODEM_GET_CLASS (self)->static_stage3_ip4_config_start (self, req, reason); - break; - case MM_MODEM_IP_METHOD_DHCP: - ret = device_class->act_stage3_ip4_config_start (device, NULL, reason); - break; - default: - nm_log_err (LOGD_MB, "unknown IP method %d", priv->ip_method); - ret = NM_ACT_STAGE_RETURN_FAILURE; - break; - } - - return ret; -} - -void -nm_modem_ip4_pre_commit (NMModem *modem, - NMDevice *device, - NMIP4Config *config) -{ - NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (modem); - - /* If the modem has an ethernet-type data interface (ie, not PPP and thus - * not point-to-point) and IP config has a /32 prefix, then we assume that - * ARP will be pointless and we turn it off. - */ - if ( priv->ip_method == MM_MODEM_IP_METHOD_STATIC - || priv->ip_method == MM_MODEM_IP_METHOD_DHCP) { - NMIP4Address *addr = nm_ip4_config_get_address (config, 0); - - g_assert (addr); - if (nm_ip4_address_get_prefix (addr) == 32) - nm_system_iface_set_arp (nm_device_get_ip_ifindex (device), FALSE); - } -} - -/*****************************************************************************/ - -NMActStageReturn -nm_modem_stage3_ip6_config_start (NMModem *self, - NMDevice *device, - NMDeviceClass *device_class, - NMDeviceStateReason *reason) -{ - /* FIXME: We don't support IPv6 on modems quite yet... */ - nm_device_activate_schedule_ip6_config_timeout (device); - return NM_ACT_STAGE_RETURN_POSTPONE; -} - -/*****************************************************************************/ - -static void -cancel_get_secrets (NMModem *self) -{ - NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); - - if (priv->secrets_id) { - nm_act_request_cancel_secrets (priv->act_request, priv->secrets_id); - priv->secrets_id = 0; - } -} - -static void -modem_secrets_cb (NMActRequest *req, - guint32 call_id, - NMConnection *connection, - GError *error, - gpointer user_data) -{ - NMModem *self = NM_MODEM (user_data); - NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); - - g_return_if_fail (call_id == priv->secrets_id); - - priv->secrets_id = 0; - - if (error) - nm_log_warn (LOGD_MB, "%s", error->message); - - g_signal_emit (self, signals[AUTH_RESULT], 0, error); -} - -gboolean -nm_modem_get_secrets (NMModem *self, - const char *setting_name, - gboolean request_new, - const char *hint) -{ - NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); - NMSettingsGetSecretsFlags flags = NM_SETTINGS_GET_SECRETS_FLAG_ALLOW_INTERACTION; - - cancel_get_secrets (self); - - if (request_new) - flags |= NM_SETTINGS_GET_SECRETS_FLAG_REQUEST_NEW; - priv->secrets_id = nm_act_request_get_secrets (priv->act_request, - setting_name, - flags, - hint, - modem_secrets_cb, - self); - if (priv->secrets_id) - g_signal_emit (self, signals[AUTH_REQUESTED], 0); - - return !!(priv->secrets_id); -} - -/*****************************************************************************/ - -static NMActStageReturn -act_stage1_prepare (NMModem *modem, - NMActRequest *req, - GPtrArray **out_hints, - const char **out_setting_name, - NMDeviceStateReason *reason) -{ - *reason = NM_DEVICE_STATE_REASON_UNKNOWN; - return NM_ACT_STAGE_RETURN_FAILURE; -} - -NMActStageReturn -nm_modem_act_stage1_prepare (NMModem *self, - NMActRequest *req, - NMDeviceStateReason *reason) -{ - NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); - NMActStageReturn ret; - GPtrArray *hints = NULL; - const char *setting_name = NULL; - NMSettingsGetSecretsFlags flags = NM_SETTINGS_GET_SECRETS_FLAG_ALLOW_INTERACTION; - - if (priv->act_request) - g_object_unref (priv->act_request); - priv->act_request = g_object_ref (req); - - ret = NM_MODEM_GET_CLASS (self)->act_stage1_prepare (self, - req, - &hints, - &setting_name, - reason); - if ((ret == NM_ACT_STAGE_RETURN_POSTPONE) && setting_name) { - if (priv->secrets_tries++) - flags |= NM_SETTINGS_GET_SECRETS_FLAG_REQUEST_NEW; - - priv->secrets_id = nm_act_request_get_secrets (req, - setting_name, - flags, - hints ? g_ptr_array_index (hints, 0) : NULL, - modem_secrets_cb, - self); - if (priv->secrets_id) - g_signal_emit (self, signals[AUTH_REQUESTED], 0); - else { - *reason = NM_DEVICE_STATE_REASON_NO_SECRETS; - ret = NM_ACT_STAGE_RETURN_FAILURE; - } - - if (hints) - g_ptr_array_free (hints, TRUE); - } - - return ret; -} - -/*****************************************************************************/ - -NMActStageReturn -nm_modem_act_stage2_config (NMModem *self, - NMActRequest *req, - NMDeviceStateReason *reason) -{ - NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); - - /* Clear secrets tries counter since secrets were successfully used - * already if we get here. - */ - priv->secrets_tries = 0; - - return NM_ACT_STAGE_RETURN_SUCCESS; -} - -/*****************************************************************************/ - -NMConnection * -nm_modem_get_best_auto_connection (NMModem *self, - GSList *connections, - char **specific_object) -{ - if (NM_MODEM_GET_CLASS (self)->get_best_auto_connection) - return NM_MODEM_GET_CLASS (self)->get_best_auto_connection (self, connections, specific_object); - return NULL; -} - -/*****************************************************************************/ - -gboolean -nm_modem_check_connection_compatible (NMModem *self, - NMConnection *connection, - GError **error) -{ - if (NM_MODEM_GET_CLASS (self)->check_connection_compatible) - return NM_MODEM_GET_CLASS (self)->check_connection_compatible (self, connection, error); - return FALSE; -} - -/*****************************************************************************/ - -gboolean -nm_modem_complete_connection (NMModem *self, - NMConnection *connection, - const GSList *existing_connections, - GError **error) -{ - if (NM_MODEM_GET_CLASS (self)->complete_connection) - return NM_MODEM_GET_CLASS (self)->complete_connection (self, connection, existing_connections, error); - return FALSE; -} - -/*****************************************************************************/ - -static void -deactivate (NMModem *self, NMDevice *device) -{ - NMModemPrivate *priv; - int ifindex; - - g_return_if_fail (self != NULL); - g_return_if_fail (NM_IS_MODEM (self)); - g_return_if_fail (device != NULL); - g_return_if_fail (NM_IS_DEVICE (device)); - - priv = NM_MODEM_GET_PRIVATE (self); - - priv->secrets_tries = 0; - - if (priv->act_request) { - cancel_get_secrets (self); - g_object_unref (priv->act_request); - priv->act_request = NULL; - } - - priv->in_bytes = priv->out_bytes = 0; - - if (priv->ppp_manager) { - g_object_unref (priv->ppp_manager); - priv->ppp_manager = NULL; - } - - switch (priv->ip_method) { - case MM_MODEM_IP_METHOD_PPP: - break; - case MM_MODEM_IP_METHOD_STATIC: - case MM_MODEM_IP_METHOD_DHCP: - ifindex = nm_device_get_ip_ifindex (device); - if (ifindex > 0) { - /* FIXME: use AF_UNSPEC here when we have IPv6 support */ - nm_system_iface_flush_routes (ifindex, AF_INET); - nm_system_iface_flush_addresses (ifindex, AF_UNSPEC); - nm_system_iface_set_up (ifindex, FALSE, NULL); - } - break; - default: - nm_log_err (LOGD_MB, "unknown IP method %d", priv->ip_method); - break; - } - - g_free (priv->ppp_iface); - priv->ppp_iface = NULL; -} - -/*****************************************************************************/ - -void -nm_modem_deactivate (NMModem *self, NMDevice *device) -{ - NM_MODEM_GET_CLASS (self)->deactivate (self, device); -} - -/*****************************************************************************/ - -void -nm_modem_device_state_changed (NMModem *self, - NMDeviceState new_state, - NMDeviceState old_state, - NMDeviceStateReason reason) -{ - gboolean was_connected = FALSE, warn = TRUE; - NMModemPrivate *priv; - - g_return_if_fail (self != NULL); - g_return_if_fail (NM_IS_MODEM (self)); - - if (old_state >= NM_DEVICE_STATE_PREPARE && old_state <= NM_DEVICE_STATE_ACTIVATED) - was_connected = TRUE; - - priv = NM_MODEM_GET_PRIVATE (self); - - /* Make sure we don't leave the serial device open */ - switch (new_state) { - case NM_DEVICE_STATE_NEED_AUTH: - if (priv->ppp_manager) - break; - /* else fall through */ - case NM_DEVICE_STATE_UNMANAGED: - case NM_DEVICE_STATE_UNAVAILABLE: - case NM_DEVICE_STATE_FAILED: - case NM_DEVICE_STATE_DISCONNECTED: - if (new_state != NM_DEVICE_STATE_NEED_AUTH) { - if (priv->act_request) { - cancel_get_secrets (self); - g_object_unref (priv->act_request); - priv->act_request = NULL; - } - } - - if (was_connected) { - /* Don't bother warning on FAILED since the modem is already gone */ - if (new_state == NM_DEVICE_STATE_FAILED) - warn = FALSE; - NM_MODEM_GET_CLASS (self)->disconnect (self, warn); - } - break; - default: - break; - } -} - -/*****************************************************************************/ - -const char * -nm_modem_get_uid (NMModem *self) -{ - g_return_val_if_fail (self != NULL, NULL); - g_return_val_if_fail (NM_IS_MODEM (self), NULL); - - return NM_MODEM_GET_PRIVATE (self)->uid; -} - -const char * -nm_modem_get_path (NMModem *self) -{ - g_return_val_if_fail (self != NULL, NULL); - g_return_val_if_fail (NM_IS_MODEM (self), NULL); - - return NM_MODEM_GET_PRIVATE (self)->path; -} - -const char * -nm_modem_get_control_port (NMModem *self) -{ - g_return_val_if_fail (self != NULL, NULL); - g_return_val_if_fail (NM_IS_MODEM (self), NULL); - - return NM_MODEM_GET_PRIVATE (self)->control_port; -} - -const char * -nm_modem_get_data_port (NMModem *self) -{ - g_return_val_if_fail (self != NULL, NULL); - g_return_val_if_fail (NM_IS_MODEM (self), NULL); - - /* The ppp_iface takes precedence over the data interface when PPP is used, - * since data_iface is the TTY over which PPP is run, and that TTY can't - * do IP. The caller really wants the thing that's doing IP. - */ - return NM_MODEM_GET_PRIVATE (self)->ppp_iface ? - NM_MODEM_GET_PRIVATE (self)->ppp_iface : NM_MODEM_GET_PRIVATE (self)->data_port; -} - -/*****************************************************************************/ - -static void -nm_modem_init (NMModem *self) -{ -} - -static GObject* -constructor (GType type, - guint n_construct_params, - GObjectConstructParam *construct_params) -{ - GObject *object; - NMModemPrivate *priv; - - object = G_OBJECT_CLASS (nm_modem_parent_class)->constructor (type, - n_construct_params, - construct_params); - if (!object) - return NULL; - - priv = NM_MODEM_GET_PRIVATE (object); - - if (!priv->data_port && !priv->control_port) { - nm_log_err (LOGD_HW, "neither modem command nor data interface provided"); - goto err; - } - - if (!priv->path) { - nm_log_err (LOGD_HW, "D-Bus path not provided"); - goto err; - } - - return object; - - err: - g_object_unref (object); - return NULL; -} - -static void -get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) -{ - NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (object); - - switch (prop_id) { - case PROP_PATH: - g_value_set_string (value, priv->path); - break; - case PROP_CONTROL_PORT: - g_value_set_string (value, priv->control_port); - break; - case PROP_DATA_PORT: - g_value_set_string (value, nm_modem_get_data_port (NM_MODEM (object))); - break; - case PROP_UID: - g_value_set_string (value, priv->uid); - break; - case PROP_IP_METHOD: - g_value_set_uint (value, priv->ip_method); - break; - case PROP_IP_TIMEOUT: - g_value_set_uint (value, priv->mm_ip_timeout); - break; - case PROP_ENABLED: - g_value_set_boolean (value, priv->mm_enabled); - break; - case PROP_CONNECTED: - g_value_set_boolean (value, priv->mm_connected); - 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) -{ - NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (object); - - switch (prop_id) { - case PROP_PATH: - /* Construct only */ - priv->path = g_value_dup_string (value); - break; - case PROP_CONTROL_PORT: - priv->control_port = g_value_dup_string (value); - break; - case PROP_DATA_PORT: - priv->data_port = g_value_dup_string (value); - break; - case PROP_UID: - /* Construct only */ - priv->uid = g_value_dup_string (value); - break; - case PROP_IP_METHOD: - priv->ip_method = g_value_get_uint (value); - break; - case PROP_IP_TIMEOUT: - priv->mm_ip_timeout = g_value_get_uint (value); - break; - case PROP_ENABLED: - priv->mm_enabled = g_value_get_boolean (value); - break; - case PROP_CONNECTED: - priv->mm_connected = g_value_get_boolean (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -dispose (GObject *object) -{ - NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (object); - - if (priv->act_request) { - g_object_unref (priv->act_request); - priv->act_request = NULL; - } - - G_OBJECT_CLASS (nm_modem_parent_class)->dispose (object); -} - -static void -finalize (GObject *object) -{ - NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (object); - - g_free (priv->uid); - g_free (priv->path); - g_free (priv->control_port); - g_free (priv->data_port); - - G_OBJECT_CLASS (nm_modem_parent_class)->finalize (object); -} - -static void -nm_modem_class_init (NMModemClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - g_type_class_add_private (object_class, sizeof (NMModemPrivate)); - - /* Virtual methods */ - object_class->constructor = constructor; - object_class->set_property = set_property; - object_class->get_property = get_property; - object_class->dispose = dispose; - object_class->finalize = finalize; - - klass->act_stage1_prepare = act_stage1_prepare; - klass->deactivate = deactivate; - - /* Properties */ - - g_object_class_install_property - (object_class, PROP_UID, - g_param_spec_string (NM_MODEM_UID, - "UID", - "Modem unique ID", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - g_object_class_install_property - (object_class, PROP_PATH, - g_param_spec_string (NM_MODEM_PATH, - "DBus path", - "DBus path", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - g_object_class_install_property - (object_class, PROP_CONTROL_PORT, - g_param_spec_string (NM_MODEM_CONTROL_PORT, - "Control port", - "The port controlling the modem", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - g_object_class_install_property - (object_class, PROP_DATA_PORT, - g_param_spec_string (NM_MODEM_DATA_PORT, - "Data port", - "The port to connect to", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - - g_object_class_install_property - (object_class, PROP_IP_METHOD, - g_param_spec_uint (NM_MODEM_IP_METHOD, - "IP method", - "IP method", - MM_MODEM_IP_METHOD_PPP, - MM_MODEM_IP_METHOD_DHCP, - MM_MODEM_IP_METHOD_PPP, - G_PARAM_READWRITE)); - - g_object_class_install_property - (object_class, PROP_IP_TIMEOUT, - g_param_spec_uint (NM_MODEM_IP_TIMEOUT, - "IP timeout", - "IP timeout", - 0, 360, 20, - G_PARAM_READWRITE)); - - g_object_class_install_property - (object_class, PROP_ENABLED, - g_param_spec_boolean (NM_MODEM_ENABLED, - "Enabled", - "Enabled", - TRUE, - G_PARAM_READWRITE)); - - g_object_class_install_property - (object_class, PROP_CONNECTED, - g_param_spec_boolean (NM_MODEM_CONNECTED, - "Connected", - "Connected", - TRUE, - G_PARAM_READWRITE)); - - /* Signals */ - - signals[PPP_STATS] = - g_signal_new ("ppp-stats", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMModemClass, ppp_stats), - NULL, NULL, - _nm_marshal_VOID__UINT_UINT, - G_TYPE_NONE, 2, - G_TYPE_UINT, G_TYPE_UINT); - - signals[PPP_FAILED] = - g_signal_new ("ppp-failed", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMModemClass, ppp_failed), - NULL, NULL, - g_cclosure_marshal_VOID__UINT, - G_TYPE_NONE, 1, G_TYPE_UINT); - - signals[IP4_CONFIG_RESULT] = - g_signal_new (NM_MODEM_IP4_CONFIG_RESULT, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMModemClass, ip4_config_result), - NULL, NULL, - _nm_marshal_VOID__OBJECT_POINTER, - G_TYPE_NONE, 2, G_TYPE_OBJECT, G_TYPE_POINTER); - - signals[PREPARE_RESULT] = - g_signal_new (NM_MODEM_PREPARE_RESULT, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMModemClass, prepare_result), - NULL, NULL, - _nm_marshal_VOID__BOOLEAN_UINT, - G_TYPE_NONE, 2, G_TYPE_BOOLEAN, G_TYPE_UINT); - - signals[AUTH_REQUESTED] = - g_signal_new (NM_MODEM_AUTH_REQUESTED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMModemClass, auth_requested), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - signals[AUTH_RESULT] = - g_signal_new (NM_MODEM_AUTH_RESULT, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMModemClass, auth_result), - NULL, NULL, - g_cclosure_marshal_VOID__POINTER, - G_TYPE_NONE, 1, G_TYPE_POINTER); -} diff --git a/src/modem-manager/nm-modem.h b/src/modem-manager/nm-modem.h deleted file mode 100644 index d01aaf2c..00000000 --- a/src/modem-manager/nm-modem.h +++ /dev/null @@ -1,173 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2009 - 2011 Red Hat, Inc. - * Copyright (C) 2009 Novell, Inc. - */ - -#ifndef NM_MODEM_H -#define NM_MODEM_H - -#include -#include -#include "ppp-manager/nm-ppp-manager.h" -#include "nm-device.h" - -G_BEGIN_DECLS - -#define NM_TYPE_MODEM (nm_modem_get_type ()) -#define NM_MODEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_MODEM, NMModem)) -#define NM_MODEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_MODEM, NMModemClass)) -#define NM_IS_MODEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_MODEM)) -#define NM_IS_MODEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_MODEM)) -#define NM_MODEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_MODEM, NMModemClass)) - -#define NM_MODEM_UID "uid" -#define NM_MODEM_PATH "path" -#define NM_MODEM_CONTROL_PORT "control-port" -#define NM_MODEM_DATA_PORT "data-port" -#define NM_MODEM_IP_METHOD "ip-method" -#define NM_MODEM_IP_TIMEOUT "ip-timeout" -#define NM_MODEM_ENABLED "enabled" -#define NM_MODEM_CONNECTED "connected" - -#define NM_MODEM_PPP_STATS "ppp-stats" -#define NM_MODEM_PPP_FAILED "ppp-failed" -#define NM_MODEM_PREPARE_RESULT "prepare-result" -#define NM_MODEM_IP4_CONFIG_RESULT "ip4-config-result" -#define NM_MODEM_AUTH_REQUESTED "auth-requested" -#define NM_MODEM_AUTH_RESULT "auth-result" - -#define MM_MODEM_IP_METHOD_PPP 0 -#define MM_MODEM_IP_METHOD_STATIC 1 -#define MM_MODEM_IP_METHOD_DHCP 2 - -typedef struct { - GObject parent; -} NMModem; - -typedef struct { - GObjectClass parent; - - gboolean (*get_user_pass) (NMModem *modem, - NMConnection *connection, - const char **user, - const char **pass); - - const char * (*get_setting_name) (NMModem *modem); - - gboolean (*check_connection_compatible) (NMModem *modem, - NMConnection *connection, - GError **error); - - gboolean (*complete_connection) (NMModem *modem, - NMConnection *connection, - const GSList *existing_connections, - GError **error); - - NMConnection * (*get_best_auto_connection) (NMModem *modem, - GSList *connections, - char **specific_object); - - NMActStageReturn (*act_stage1_prepare) (NMModem *modem, - NMActRequest *req, - GPtrArray **out_hints, - const char **out_setting_name, - NMDeviceStateReason *reason); - - NMActStageReturn (*static_stage3_ip4_config_start) (NMModem *self, - NMActRequest *req, - NMDeviceStateReason *reason); - - void (*set_mm_enabled) (NMModem *self, gboolean enabled); - - void (*disconnect) (NMModem *self, gboolean warn); - - void (*deactivate) (NMModem *self, NMDevice *device); - - /* Signals */ - void (*ppp_stats) (NMModem *self, guint32 in_bytes, guint32 out_bytes); - void (*ppp_failed) (NMModem *self, NMDeviceStateReason reason); - - void (*prepare_result) (NMModem *self, gboolean success, NMDeviceStateReason reason); - void (*ip4_config_result) (NMModem *self, NMIP4Config *config, GError *error); - - void (*auth_requested) (NMModem *self); - void (*auth_result) (NMModem *self, GError *error); -} NMModemClass; - -GType nm_modem_get_type (void); - -const char *nm_modem_get_path (NMModem *modem); -const char *nm_modem_get_uid (NMModem *modem); -const char *nm_modem_get_control_port (NMModem *modem); -const char *nm_modem_get_data_port (NMModem *modem); - -NMConnection *nm_modem_get_best_auto_connection (NMModem *self, - GSList *connections, - char **specific_object); - -gboolean nm_modem_check_connection_compatible (NMModem *self, - NMConnection *connection, - GError **error); - -gboolean nm_modem_complete_connection (NMModem *self, - NMConnection *connection, - const GSList *existing_connections, - GError **error); - -NMActStageReturn nm_modem_act_stage1_prepare (NMModem *modem, - NMActRequest *req, - NMDeviceStateReason *reason); - -NMActStageReturn nm_modem_act_stage2_config (NMModem *modem, - NMActRequest *req, - NMDeviceStateReason *reason); - -NMActStageReturn nm_modem_stage3_ip4_config_start (NMModem *modem, - NMDevice *device, - NMDeviceClass *device_class, - NMDeviceStateReason *reason); - -NMActStageReturn nm_modem_stage3_ip6_config_start (NMModem *modem, - NMDevice *device, - NMDeviceClass *device_class, - NMDeviceStateReason *reason); - -void nm_modem_ip4_pre_commit (NMModem *modem, NMDevice *device, NMIP4Config *config); - -gboolean nm_modem_get_secrets (NMModem *modem, - const char *setting_name, - gboolean request_new, - const char *hint); - -void nm_modem_deactivate (NMModem *modem, NMDevice *device); - -void nm_modem_device_state_changed (NMModem *modem, - NMDeviceState new_state, - NMDeviceState old_state, - NMDeviceStateReason reason); - -gboolean nm_modem_get_mm_enabled (NMModem *self); - -void nm_modem_set_mm_enabled (NMModem *self, gboolean enabled); - -gboolean nm_modem_get_mm_connected (NMModem *self); - -G_END_DECLS - -#endif /* NM_MODEM_H */ diff --git a/src/nm-access-point-glue.h b/src/nm-access-point-glue.h new file mode 100644 index 00000000..ad4d5916 --- /dev/null +++ b/src/nm-access-point-glue.h @@ -0,0 +1,73 @@ +/* Generated by dbus-binding-tool; do not edit! */ + + +#ifndef __dbus_glib_marshal_nm_access_point_MARSHAL_H__ +#define __dbus_glib_marshal_nm_access_point_MARSHAL_H__ + +#include + +G_BEGIN_DECLS + +#ifdef G_ENABLE_DEBUG +#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v) +#define g_marshal_value_peek_char(v) g_value_get_schar (v) +#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v) +#define g_marshal_value_peek_int(v) g_value_get_int (v) +#define g_marshal_value_peek_uint(v) g_value_get_uint (v) +#define g_marshal_value_peek_long(v) g_value_get_long (v) +#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v) +#define g_marshal_value_peek_int64(v) g_value_get_int64 (v) +#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v) +#define g_marshal_value_peek_enum(v) g_value_get_enum (v) +#define g_marshal_value_peek_flags(v) g_value_get_flags (v) +#define g_marshal_value_peek_float(v) g_value_get_float (v) +#define g_marshal_value_peek_double(v) g_value_get_double (v) +#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v) +#define g_marshal_value_peek_param(v) g_value_get_param (v) +#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v) +#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v) +#define g_marshal_value_peek_object(v) g_value_get_object (v) +#define g_marshal_value_peek_variant(v) g_value_get_variant (v) +#else /* !G_ENABLE_DEBUG */ +/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API. + * Do not access GValues directly in your code. Instead, use the + * g_value_get_*() functions + */ +#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int +#define g_marshal_value_peek_char(v) (v)->data[0].v_int +#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint +#define g_marshal_value_peek_int(v) (v)->data[0].v_int +#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint +#define g_marshal_value_peek_long(v) (v)->data[0].v_long +#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 +#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 +#define g_marshal_value_peek_enum(v) (v)->data[0].v_long +#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_float(v) (v)->data[0].v_float +#define g_marshal_value_peek_double(v) (v)->data[0].v_double +#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer +#endif /* !G_ENABLE_DEBUG */ + + +G_END_DECLS + +#endif /* __dbus_glib_marshal_nm_access_point_MARSHAL_H__ */ + +#include +static const DBusGMethodInfo dbus_glib_nm_access_point_methods[] = { +}; + +const DBusGObjectInfo dbus_glib_nm_access_point_object_info = { 1, + dbus_glib_nm_access_point_methods, + 0, +"\0", +"org.freedesktop.NetworkManager.AccessPoint\0PropertiesChanged\0\0", +"org.freedesktop.NetworkManager.AccessPoint\0Flags\0flags\0read\0org.freedesktop.NetworkManager.AccessPoint\0WpaFlags\0wpa_flags\0read\0org.freedesktop.NetworkManager.AccessPoint\0RsnFlags\0rsn_flags\0read\0org.freedesktop.NetworkManager.AccessPoint\0Ssid\0ssid\0read\0org.freedesktop.NetworkManager.AccessPoint\0Frequency\0frequency\0read\0org.freedesktop.NetworkManager.AccessPoint\0HwAddress\0hw_address\0read\0org.freedesktop.NetworkManager.AccessPoint\0Mode\0mode\0read\0org.freedesktop.NetworkManager.AccessPoint\0MaxBitrate\0max_bitrate\0read\0org.freedesktop.NetworkManager.AccessPoint\0Strength\0strength\0read\0\0" +}; + diff --git a/src/nm-activation-request.c b/src/nm-activation-request.c index e17f2a7e..9f9ee0f9 100644 --- a/src/nm-activation-request.c +++ b/src/nm-activation-request.c @@ -27,6 +27,8 @@ #include #include +#include "libgsystem.h" + #include "nm-activation-request.h" #include "nm-logging.h" #include "nm-setting-wireless-security.h" @@ -49,15 +51,21 @@ typedef struct { } ShareRule; typedef struct { - NMConnection *connection; - NMDevice *device; - guint device_state_id; - char *dbus_sender; GSList *secrets_calls; gboolean shared; GSList *share_rules; } NMActRequestPrivate; +enum { + PROP_0, + PROP_IP4_CONFIG, + PROP_DHCP4_CONFIG, + PROP_IP6_CONFIG, + PROP_DHCP6_CONFIG, + + LAST_PROP +}; + /*******************************************************************/ NMConnection * @@ -68,14 +76,6 @@ nm_act_request_get_connection (NMActRequest *req) return nm_active_connection_get_connection (NM_ACTIVE_CONNECTION (req)); } -const char * -nm_act_request_get_dbus_sender (NMActRequest *req) -{ - g_return_val_if_fail (NM_IS_ACT_REQUEST (req), NULL); - - return NM_ACT_REQUEST_GET_PRIVATE (req)->dbus_sender; -} - /*******************************************************************/ typedef struct { @@ -115,7 +115,7 @@ nm_act_request_get_secrets (NMActRequest *self, GetSecretsInfo *info; guint32 call_id; NMConnection *connection; - gboolean user_requested; + const char *hints[2] = { hint, NULL }; g_return_val_if_fail (self, 0); g_return_val_if_fail (NM_IS_ACT_REQUEST (self), 0); @@ -127,17 +127,15 @@ nm_act_request_get_secrets (NMActRequest *self, info->callback = callback; info->callback_data = callback_data; - user_requested = nm_active_connection_get_user_requested (NM_ACTIVE_CONNECTION (self)); - if (user_requested) + if (nm_active_connection_get_user_requested (NM_ACTIVE_CONNECTION (self))) flags |= NM_SETTINGS_GET_SECRETS_FLAG_USER_REQUESTED; connection = nm_active_connection_get_connection (NM_ACTIVE_CONNECTION (self)); call_id = nm_settings_connection_get_secrets (NM_SETTINGS_CONNECTION (connection), - user_requested, - nm_active_connection_get_user_uid (NM_ACTIVE_CONNECTION (self)), + nm_active_connection_get_subject (NM_ACTIVE_CONNECTION (self)), setting_name, flags, - hint, + hints, get_secrets_cb, info, NULL); @@ -154,6 +152,7 @@ void nm_act_request_cancel_secrets (NMActRequest *self, guint32 call_id) { NMActRequestPrivate *priv; + NMConnection *connection; GSList *iter; g_return_if_fail (self); @@ -162,6 +161,7 @@ nm_act_request_cancel_secrets (NMActRequest *self, guint32 call_id) priv = NM_ACT_REQUEST_GET_PRIVATE (self); + connection = nm_active_connection_get_connection (NM_ACTIVE_CONNECTION (self)); for (iter = priv->secrets_calls; iter; iter = g_slist_next (iter)) { GetSecretsInfo *info = iter->data; @@ -170,7 +170,7 @@ nm_act_request_cancel_secrets (NMActRequest *self, guint32 call_id) priv->secrets_calls = g_slist_remove_link (priv->secrets_calls, iter); g_slist_free (iter); - nm_settings_connection_cancel_secrets (NM_SETTINGS_CONNECTION (priv->connection), call_id); + nm_settings_connection_cancel_secrets (NM_SETTINGS_CONNECTION (connection), call_id); g_free (info); break; } @@ -226,8 +226,8 @@ nm_act_request_set_shared (NMActRequest *req, gboolean shared) for (iter = list; iter; iter = g_slist_next (iter)) { ShareRule *rule = (ShareRule *) iter->data; char *envp[1] = { NULL }; - char **argv; - char *cmd; + gs_strfreev char **argv = NULL; + gs_free char *cmd = NULL; cmd = g_strdup_printf ("%s --table %s %s %s", IPTABLES_PATH, @@ -254,9 +254,6 @@ nm_act_request_set_shared (NMActRequest *req, gboolean shared) WEXITSTATUS (status)); } } - g_free (cmd); - if (argv) - g_strfreev (argv); } g_slist_free (list); @@ -295,13 +292,47 @@ nm_act_request_add_share_rule (NMActRequest *req, /********************************************************************/ static void -device_state_changed (NMDevice *device, GParamSpec *pspec, NMActRequest *self) +device_notify (GObject *object, + GParamSpec *pspec, + gpointer self) { - NMActRequestPrivate *priv = NM_ACT_REQUEST_GET_PRIVATE (self); + g_object_notify (self, pspec->name); +} + +static void +device_state_changed (NMActiveConnection *active, + NMDevice *device, + NMDeviceState new_state, + NMDeviceState old_state) +{ + NMActiveConnectionState cur_ac_state = nm_active_connection_get_state (active); NMActiveConnectionState ac_state = NM_ACTIVE_CONNECTION_STATE_UNKNOWN; + /* Decide which device state changes to handle when this active connection + * is not the device's current request. Two cases here: (a) the AC is + * pending and not yet active, and (b) the AC was active but the device is + * entering DISCONNECTED state (which clears the device's current AC before + * emitting the state change signal). + */ + if (NM_ACTIVE_CONNECTION (nm_device_get_act_request (device)) != active) { + /* Some other request is activating; this one must be pending */ + if (new_state >= NM_DEVICE_STATE_PREPARE) + return; + else if (new_state == NM_DEVICE_STATE_DISCONNECTED) { + /* This request hasn't started activating yet; the device is + * disconnecting and cleaning up a previous activation request. + */ + if (cur_ac_state < NM_ACTIVE_CONNECTION_STATE_ACTIVATING) + return; + + /* Catch device disconnections after this request has been active */ + } + + /* All states < DISCONNECTED are fatal and handled */ + } + /* Set NMActiveConnection state based on the device's state */ - switch (nm_device_get_state (device)) { + switch (new_state) { case NM_DEVICE_STATE_PREPARE: case NM_DEVICE_STATE_CONFIG: case NM_DEVICE_STATE_NEED_AUTH: @@ -312,6 +343,15 @@ device_state_changed (NMDevice *device, GParamSpec *pspec, NMActRequest *self) break; case NM_DEVICE_STATE_ACTIVATED: ac_state = NM_ACTIVE_CONNECTION_STATE_ACTIVATED; + + g_signal_connect (device, "notify::" NM_DEVICE_IP4_CONFIG, + G_CALLBACK (device_notify), active); + g_signal_connect (device, "notify::" NM_DEVICE_DHCP4_CONFIG, + G_CALLBACK (device_notify), active); + g_signal_connect (device, "notify::" NM_DEVICE_IP6_CONFIG, + G_CALLBACK (device_notify), active); + g_signal_connect (device, "notify::" NM_DEVICE_DHCP6_CONFIG, + G_CALLBACK (device_notify), active); break; case NM_DEVICE_STATE_DEACTIVATING: ac_state = NM_ACTIVE_CONNECTION_STATE_DEACTIVATING; @@ -322,12 +362,7 @@ device_state_changed (NMDevice *device, GParamSpec *pspec, NMActRequest *self) case NM_DEVICE_STATE_UNAVAILABLE: ac_state = NM_ACTIVE_CONNECTION_STATE_DEACTIVATED; - /* No longer need to pay attention to device state */ - if (priv->device && priv->device_state_id) { - g_signal_handler_disconnect (priv->device, priv->device_state_id); - priv->device_state_id = 0; - } - g_clear_object (&priv->device); + g_signal_handlers_disconnect_by_func (device, G_CALLBACK (device_notify), active); break; default: break; @@ -335,11 +370,33 @@ device_state_changed (NMDevice *device, GParamSpec *pspec, NMActRequest *self) if ( ac_state == NM_ACTIVE_CONNECTION_STATE_DEACTIVATED || ac_state == NM_ACTIVE_CONNECTION_STATE_UNKNOWN) { - nm_active_connection_set_default (NM_ACTIVE_CONNECTION (self), FALSE); - nm_active_connection_set_default6 (NM_ACTIVE_CONNECTION (self), FALSE); + nm_active_connection_set_default (active, FALSE); + nm_active_connection_set_default6 (active, FALSE); } - nm_active_connection_set_state (NM_ACTIVE_CONNECTION (self), ac_state); + nm_active_connection_set_state (active, ac_state); +} + +static void +master_failed (NMActiveConnection *self) +{ + NMDevice *device; + NMDeviceState device_state; + + /* If the connection has an active device, fail it */ + device = nm_active_connection_get_device (self); + if (device) { + device_state = nm_device_get_state (device); + if (nm_device_is_activating (device) || (device_state == NM_DEVICE_STATE_ACTIVATED)) { + nm_device_state_changed (device, + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED); + return; + } + } + + /* If no device, or the device wasn't active, just move to deactivated state */ + nm_active_connection_set_state (self, NM_ACTIVE_CONNECTION_STATE_DEACTIVATED); } /********************************************************************/ @@ -350,52 +407,31 @@ device_state_changed (NMDevice *device, GParamSpec *pspec, NMActRequest *self) * @connection: the connection to activate @device with * @specific_object: the object path of the specific object (ie, WiFi access point, * etc) that will be used to activate @connection and @device - * @user_requested: pass %TRUE if the activation was requested via D-Bus, - * otherwise %FALSE if requested internally by NM (ie, autoconnect) - * @user_uid: if @user_requested is %TRUE, the Unix UID of the user that requested - * @dbus_sender: if @user_requested is %TRUE, the D-BUS sender that requested - * the activation - * @assumed: pass %TRUE if the activation should "assume" (ie, taking over) an - * existing connection made before this instance of NM started - * @device: the device/interface to configure according to @connection - * @master: if the activation depends on another device (ie, bond or bridge - * master to which this device will be enslaved) pass the #NMDevice that this - * activation request be enslaved to + * @subject: the #NMAuthSubject representing the requestor of the activation + * @device: the device/interface to configure according to @connection; or %NULL + * if the connection describes a software device which will be created during + * connection activation * - * Begins activation of @device using the given @connection and other details. + * Creates a new device-based activation request. * * Returns: the new activation request on success, %NULL on error. */ NMActRequest * nm_act_request_new (NMConnection *connection, const char *specific_object, - gboolean user_requested, - gulong user_uid, - const char *dbus_sender, - gboolean assumed, - NMDevice *device, - NMDevice *master) + NMAuthSubject *subject, + NMDevice *device) { - GObject *object; - g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); - g_return_val_if_fail (NM_DEVICE (device), NULL); - - object = g_object_new (NM_TYPE_ACT_REQUEST, - NM_ACTIVE_CONNECTION_INT_CONNECTION, connection, - NM_ACTIVE_CONNECTION_INT_DEVICE, device, - NM_ACTIVE_CONNECTION_SPECIFIC_OBJECT, specific_object, - NM_ACTIVE_CONNECTION_INT_USER_REQUESTED, user_requested, - NM_ACTIVE_CONNECTION_INT_USER_UID, user_uid, - NM_ACTIVE_CONNECTION_INT_ASSUMED, assumed, - NM_ACTIVE_CONNECTION_INT_MASTER, master, - NULL); - if (object) { - nm_active_connection_export (NM_ACTIVE_CONNECTION (object)); - NM_ACT_REQUEST_GET_PRIVATE (object)->dbus_sender = g_strdup (dbus_sender); - } - - return (NMActRequest *) object; + g_return_val_if_fail (!device || NM_IS_DEVICE (device), NULL); + g_return_val_if_fail (NM_IS_AUTH_SUBJECT (subject), NULL); + + return (NMActRequest *) g_object_new (NM_TYPE_ACT_REQUEST, + NM_ACTIVE_CONNECTION_INT_CONNECTION, connection, + NM_ACTIVE_CONNECTION_INT_DEVICE, device, + NM_ACTIVE_CONNECTION_SPECIFIC_OBJECT, specific_object, + NM_ACTIVE_CONNECTION_INT_SUBJECT, subject, + NULL); } static void @@ -403,39 +439,13 @@ nm_act_request_init (NMActRequest *req) { } -static void -constructed (GObject *object) -{ - NMActRequestPrivate *priv = NM_ACT_REQUEST_GET_PRIVATE (object); - NMConnection *connection; - NMDevice *device; - - G_OBJECT_CLASS (nm_act_request_parent_class)->constructed (object); - - connection = nm_active_connection_get_connection (NM_ACTIVE_CONNECTION (object)); - priv->connection = g_object_ref (connection); - - device = nm_active_connection_get_device (NM_ACTIVE_CONNECTION (object)); - if (device) { - priv->device = g_object_ref (device); - priv->device_state_id = g_signal_connect (priv->device, - "notify::" NM_DEVICE_STATE, - G_CALLBACK (device_state_changed), - NM_ACT_REQUEST (object)); - } -} - static void dispose (GObject *object) { NMActRequestPrivate *priv = NM_ACT_REQUEST_GET_PRIVATE (object); + NMConnection *connection; GSList *iter; - if (priv->device && priv->device_state_id) { - g_signal_handler_disconnect (priv->device, priv->device_state_id); - priv->device_state_id = 0; - } - /* Clear any share rules */ if (priv->share_rules) { nm_act_request_set_shared (NM_ACT_REQUEST (object), FALSE); @@ -443,34 +453,72 @@ dispose (GObject *object) } /* Kill any in-progress secrets requests */ - for (iter = priv->secrets_calls; iter; iter = g_slist_next (iter)) { + connection = nm_active_connection_get_connection (NM_ACTIVE_CONNECTION (object)); + for (iter = priv->secrets_calls; connection && iter; iter = g_slist_next (iter)) { GetSecretsInfo *info = iter->data; - g_assert (priv->connection); - nm_settings_connection_cancel_secrets (NM_SETTINGS_CONNECTION (priv->connection), info->call_id); + nm_settings_connection_cancel_secrets (NM_SETTINGS_CONNECTION (connection), info->call_id); g_free (info); } g_slist_free (priv->secrets_calls); priv->secrets_calls = NULL; - g_free (priv->dbus_sender); - priv->dbus_sender = NULL; + G_OBJECT_CLASS (nm_act_request_parent_class)->dispose (object); +} - g_clear_object (&priv->device); - g_clear_object (&priv->connection); +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMDevice *device; - G_OBJECT_CLASS (nm_act_request_parent_class)->dispose (object); + device = nm_active_connection_get_device (NM_ACTIVE_CONNECTION (object)); + if (!device) { + g_value_set_boxed (value, "/"); + return; + } + + switch (prop_id) { + case PROP_IP4_CONFIG: + g_object_get_property (G_OBJECT (device), NM_DEVICE_IP4_CONFIG, value); + break; + case PROP_DHCP4_CONFIG: + g_object_get_property (G_OBJECT (device), NM_DEVICE_DHCP4_CONFIG, value); + break; + case PROP_IP6_CONFIG: + g_object_get_property (G_OBJECT (device), NM_DEVICE_IP6_CONFIG, value); + break; + case PROP_DHCP6_CONFIG: + g_object_get_property (G_OBJECT (device), NM_DEVICE_DHCP6_CONFIG, value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } } static void nm_act_request_class_init (NMActRequestClass *req_class) { GObjectClass *object_class = G_OBJECT_CLASS (req_class); + NMActiveConnectionClass *active_class = NM_ACTIVE_CONNECTION_CLASS (req_class); g_type_class_add_private (req_class, sizeof (NMActRequestPrivate)); /* virtual methods */ - object_class->constructed = constructed; object_class->dispose = dispose; + object_class->get_property = get_property; + active_class->master_failed = master_failed; + active_class->device_state_changed = device_state_changed; + + /* properties */ + g_object_class_override_property (object_class, PROP_IP4_CONFIG, + NM_ACTIVE_CONNECTION_IP4_CONFIG); + g_object_class_override_property (object_class, PROP_DHCP4_CONFIG, + NM_ACTIVE_CONNECTION_DHCP4_CONFIG); + g_object_class_override_property (object_class, PROP_IP6_CONFIG, + NM_ACTIVE_CONNECTION_IP6_CONFIG); + g_object_class_override_property (object_class, PROP_DHCP6_CONFIG, + NM_ACTIVE_CONNECTION_DHCP6_CONFIG); } diff --git a/src/nm-activation-request.h b/src/nm-activation-request.h index 15971094..87ea41f9 100644 --- a/src/nm-activation-request.h +++ b/src/nm-activation-request.h @@ -42,27 +42,17 @@ typedef struct { typedef struct { NMActiveConnectionClass parent; - /* Signals */ - void (*properties_changed) (NMActRequest *req, GHashTable *properties); } NMActRequestClass; GType nm_act_request_get_type (void); NMActRequest *nm_act_request_new (NMConnection *connection, const char *specific_object, - gboolean user_requested, - gulong user_uid, - const char *dbus_sender, - gboolean assumed, - NMDevice *device, - NMDevice *master); + NMAuthSubject *subject, + NMDevice *device); NMConnection *nm_act_request_get_connection (NMActRequest *req); -gulong nm_act_request_get_user_uid (NMActRequest *req); - -const char *nm_act_request_get_dbus_sender (NMActRequest *req); - gboolean nm_act_request_get_shared (NMActRequest *req); void nm_act_request_set_shared (NMActRequest *req, gboolean shared); diff --git a/src/nm-active-connection-glue.h b/src/nm-active-connection-glue.h new file mode 100644 index 00000000..9076e186 --- /dev/null +++ b/src/nm-active-connection-glue.h @@ -0,0 +1,73 @@ +/* Generated by dbus-binding-tool; do not edit! */ + + +#ifndef __dbus_glib_marshal_nm_active_connection_MARSHAL_H__ +#define __dbus_glib_marshal_nm_active_connection_MARSHAL_H__ + +#include + +G_BEGIN_DECLS + +#ifdef G_ENABLE_DEBUG +#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v) +#define g_marshal_value_peek_char(v) g_value_get_schar (v) +#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v) +#define g_marshal_value_peek_int(v) g_value_get_int (v) +#define g_marshal_value_peek_uint(v) g_value_get_uint (v) +#define g_marshal_value_peek_long(v) g_value_get_long (v) +#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v) +#define g_marshal_value_peek_int64(v) g_value_get_int64 (v) +#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v) +#define g_marshal_value_peek_enum(v) g_value_get_enum (v) +#define g_marshal_value_peek_flags(v) g_value_get_flags (v) +#define g_marshal_value_peek_float(v) g_value_get_float (v) +#define g_marshal_value_peek_double(v) g_value_get_double (v) +#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v) +#define g_marshal_value_peek_param(v) g_value_get_param (v) +#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v) +#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v) +#define g_marshal_value_peek_object(v) g_value_get_object (v) +#define g_marshal_value_peek_variant(v) g_value_get_variant (v) +#else /* !G_ENABLE_DEBUG */ +/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API. + * Do not access GValues directly in your code. Instead, use the + * g_value_get_*() functions + */ +#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int +#define g_marshal_value_peek_char(v) (v)->data[0].v_int +#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint +#define g_marshal_value_peek_int(v) (v)->data[0].v_int +#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint +#define g_marshal_value_peek_long(v) (v)->data[0].v_long +#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 +#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 +#define g_marshal_value_peek_enum(v) (v)->data[0].v_long +#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_float(v) (v)->data[0].v_float +#define g_marshal_value_peek_double(v) (v)->data[0].v_double +#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer +#endif /* !G_ENABLE_DEBUG */ + + +G_END_DECLS + +#endif /* __dbus_glib_marshal_nm_active_connection_MARSHAL_H__ */ + +#include +static const DBusGMethodInfo dbus_glib_nm_active_connection_methods[] = { +}; + +const DBusGObjectInfo dbus_glib_nm_active_connection_object_info = { 1, + dbus_glib_nm_active_connection_methods, + 0, +"\0", +"org.freedesktop.NetworkManager.Connection.Active\0PropertiesChanged\0\0", +"org.freedesktop.NetworkManager.Connection.Active\0Connection\0connection\0read\0org.freedesktop.NetworkManager.Connection.Active\0SpecificObject\0specific_object\0read\0org.freedesktop.NetworkManager.Connection.Active\0Id\0id\0read\0org.freedesktop.NetworkManager.Connection.Active\0Uuid\0uuid\0read\0org.freedesktop.NetworkManager.Connection.Active\0Type\0type\0read\0org.freedesktop.NetworkManager.Connection.Active\0Devices\0devices\0read\0org.freedesktop.NetworkManager.Connection.Active\0State\0state\0read\0org.freedesktop.NetworkManager.Connection.Active\0Default\0default\0read\0org.freedesktop.NetworkManager.Connection.Active\0Ip4Config\0ip4_config\0read\0org.freedesktop.NetworkManager.Connection.Active\0Dhcp4Config\0dhcp4_config\0read\0org.freedesktop.NetworkManager.Connection.Active\0Default6\0default6\0read\0org.freedesktop.NetworkManager.Connection.Active\0Ip6Config\0ip6_config\0read\0org.freedesktop.NetworkManager.Connection.Active\0Dhcp6Config\0dhcp6_config\0read\0org.freedesktop.NetworkManager.Connection.Active\0Vpn\0vpn\0read\0org.freedesktop.NetworkManager.Connection.Active\0Master\0master\0read\0\0" +}; + diff --git a/src/nm-active-connection.c b/src/nm-active-connection.c index 6e3a5da6..172aa614 100644 --- a/src/nm-active-connection.c +++ b/src/nm-active-connection.c @@ -15,7 +15,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright (C) 2008 - 2012 Red Hat, Inc. + * Copyright (C) 2008 - 2014 Red Hat, Inc. */ #include @@ -25,9 +25,10 @@ #include "nm-logging.h" #include "nm-dbus-glib-types.h" #include "nm-dbus-manager.h" -#include "nm-properties-changed-signal.h" #include "nm-device.h" #include "nm-settings-connection.h" +#include "nm-manager-auth.h" +#include "NetworkManagerUtils.h" #include "nm-active-connection-glue.h" @@ -44,47 +45,76 @@ typedef struct { char *specific_object; NMDevice *device; + char *pending_activation_id; + gboolean is_default; gboolean is_default6; NMActiveConnectionState state; gboolean vpn; - gboolean user_requested; - gulong user_uid; + NMAuthSubject *subject; + NMActiveConnection *master; + gboolean master_ready; + gboolean assumed; - NMDevice *master; + + NMAuthChain *chain; + const char *wifi_shared_permission; + NMActiveConnectionAuthResultFunc result_func; + gpointer user_data1; + gpointer user_data2; } NMActiveConnectionPrivate; enum { PROP_0, PROP_CONNECTION, + PROP_ID, PROP_UUID, + PROP_TYPE, PROP_SPECIFIC_OBJECT, PROP_DEVICES, PROP_STATE, PROP_DEFAULT, + PROP_IP4_CONFIG, + PROP_DHCP4_CONFIG, PROP_DEFAULT6, + PROP_IP6_CONFIG, + PROP_DHCP6_CONFIG, PROP_VPN, PROP_MASTER, PROP_INT_CONNECTION, PROP_INT_DEVICE, - PROP_INT_USER_REQUESTED, - PROP_INT_USER_UID, - PROP_INT_ASSUMED, + PROP_INT_SUBJECT, PROP_INT_MASTER, + PROP_INT_MASTER_READY, LAST_PROP }; -enum { - PROPERTIES_CHANGED, - LAST_SIGNAL -}; -static guint signals[LAST_SIGNAL] = { 0 }; +static void check_master_ready (NMActiveConnection *self); +static void _device_cleanup (NMActiveConnection *self); /****************************************************************/ +static const char * +state_to_string (NMActiveConnectionState state) +{ + switch (state) { + case NM_ACTIVE_CONNECTION_STATE_UNKNOWN: + return "unknown"; + case NM_ACTIVE_CONNECTION_STATE_ACTIVATING: + return "activating"; + case NM_ACTIVE_CONNECTION_STATE_ACTIVATED: + return "activated"; + case NM_ACTIVE_CONNECTION_STATE_DEACTIVATING: + return "deactivating"; + case NM_ACTIVE_CONNECTION_STATE_DEACTIVATED: + return "deactivated"; + } + return "(none)"; +} + NMActiveConnectionState nm_active_connection_get_state (NMActiveConnection *self) { @@ -109,33 +139,79 @@ nm_active_connection_set_state (NMActiveConnection *self, priv->state = new_state; g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_STATE); + check_master_ready (self); + if ( new_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED || old_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) { nm_settings_connection_update_timestamp (NM_SETTINGS_CONNECTION (priv->connection), (guint64) time (NULL), TRUE); } + if (priv->device) { + if ( old_state < NM_ACTIVE_CONNECTION_STATE_ACTIVATED + && new_state >= NM_ACTIVE_CONNECTION_STATE_ACTIVATED && + priv->pending_activation_id) + { + nm_device_remove_pending_action (priv->device, priv->pending_activation_id, TRUE); + g_clear_pointer (&priv->pending_activation_id, g_free); + } + } + + if ( new_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED + || old_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) { + g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_IP4_CONFIG); + g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_DHCP4_CONFIG); + g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_IP6_CONFIG); + g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_DHCP6_CONFIG); + } + if (priv->state == NM_ACTIVE_CONNECTION_STATE_DEACTIVATED) { - /* Device is no longer relevant when deactivated */ - g_clear_object (&priv->device); + /* Device is no longer relevant when deactivated. So remove it and + * emit property change notification so clients re-read the value, + * which will be NULL due to conditions in get_property(). + */ + _device_cleanup (self); g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_DEVICES); } } const char * -nm_active_connection_get_name (NMActiveConnection *self) +nm_active_connection_get_id (NMActiveConnection *self) { g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), NULL); return nm_connection_get_id (NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->connection); } +const char * +nm_active_connection_get_uuid (NMActiveConnection *self) +{ + g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), NULL); + + return nm_connection_get_uuid (NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->connection); +} + NMConnection * nm_active_connection_get_connection (NMActiveConnection *self) { return NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->connection; } +void +nm_active_connection_set_connection (NMActiveConnection *self, + NMConnection *connection) +{ + NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self); + + /* Can't change connection after the ActiveConnection is exported over D-Bus */ + g_return_if_fail (priv->path == NULL); + g_return_if_fail (priv->connection == NULL || !NM_IS_SETTINGS_CONNECTION (priv->connection)); + + if (priv->connection) + g_object_unref (priv->connection); + priv->connection = g_object_ref (connection); +} + const char * nm_active_connection_get_path (NMActiveConnection *self) { @@ -154,6 +230,11 @@ nm_active_connection_set_specific_object (NMActiveConnection *self, { NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self); + /* Nothing that calls this function should be using paths from D-Bus, + * where NM uses "/" to mean NULL. + */ + g_assert (g_strcmp0 (specific_object, "/") != 0); + if (g_strcmp0 (priv->specific_object, specific_object) == 0) return; @@ -212,14 +293,20 @@ void nm_active_connection_export (NMActiveConnection *self) { NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self); - NMDBusManager *dbus_mgr; static guint32 counter = 0; + g_assert (priv->device || priv->vpn); + priv->path = g_strdup_printf (NM_DBUS_PATH "/ActiveConnection/%d", counter++); - dbus_mgr = nm_dbus_manager_get (); - dbus_g_connection_register_g_object (nm_dbus_manager_get_connection (dbus_mgr), - priv->path, G_OBJECT (self)); - g_object_unref (dbus_mgr); + nm_dbus_manager_register_object (nm_dbus_manager_get (), priv->path, self); +} + +NMAuthSubject * +nm_active_connection_get_subject (NMActiveConnection *self) +{ + g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), NULL); + + return NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->subject; } gboolean @@ -227,34 +314,98 @@ nm_active_connection_get_user_requested (NMActiveConnection *self) { g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), FALSE); - return NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->user_requested; + return !nm_auth_subject_get_internal (NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->subject); } -gulong -nm_active_connection_get_user_uid (NMActiveConnection *self) +NMDevice * +nm_active_connection_get_device (NMActiveConnection *self) { - g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), G_MAXULONG); + g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), NULL); - return NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->user_uid; + return NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->device; } -gboolean -nm_active_connection_get_assumed (NMActiveConnection *self) +static void +device_state_changed (NMDevice *device, + NMDeviceState new_state, + NMDeviceState old_state, + NMDeviceStateReason reason, + gpointer user_data) { - g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), FALSE); + NMActiveConnection *self = NM_ACTIVE_CONNECTION (user_data); + NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self); - return NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->assumed; + /* When already deactivated or before activation, device state changes are useless */ + if (priv->state >= NM_ACTIVE_CONNECTION_STATE_DEACTIVATED) + return; + if (old_state < NM_DEVICE_STATE_DISCONNECTED) + return; + + /* Let subclasses handle the state change */ + if (NM_ACTIVE_CONNECTION_GET_CLASS (self)->device_state_changed) + NM_ACTIVE_CONNECTION_GET_CLASS (self)->device_state_changed (self, device, new_state, old_state); } -NMDevice * -nm_active_connection_get_device (NMActiveConnection *self) +static void +device_master_changed (GObject *object, + GParamSpec *pspec, + gpointer user_data) { - g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), NULL); + NMDevice *device = NM_DEVICE (object); + NMActiveConnection *self = NM_ACTIVE_CONNECTION (user_data); + NMActiveConnection *master; + NMActiveConnectionState master_state; - return NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->device; + if (NM_ACTIVE_CONNECTION (nm_device_get_act_request (device)) != self) + return; + if (!nm_device_get_master (device)) + return; + g_signal_handlers_disconnect_by_func (device, G_CALLBACK (device_master_changed), self); + + master = nm_active_connection_get_master (self); + g_assert (master); + + master_state = nm_active_connection_get_state (master); + if (master_state >= NM_ACTIVE_CONNECTION_STATE_DEACTIVATING) { + /* Master failed before attaching the slave */ + if (NM_ACTIVE_CONNECTION_GET_CLASS (self)->master_failed) + NM_ACTIVE_CONNECTION_GET_CLASS (self)->master_failed (self); + } } -NMDevice * +gboolean +nm_active_connection_set_device (NMActiveConnection *self, NMDevice *device) +{ + NMActiveConnectionPrivate *priv; + + g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), FALSE); + g_return_val_if_fail (!device || NM_IS_DEVICE (device), FALSE); + + priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self); + + if (device) { + g_return_val_if_fail (priv->device == NULL, FALSE); + + /* Device obviously can't be its own master */ + g_return_val_if_fail (!priv->master || device != nm_active_connection_get_device (priv->master), FALSE); + + priv->device = g_object_ref (device); + g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_INT_DEVICE); + + g_signal_connect (device, "state-changed", + G_CALLBACK (device_state_changed), self); + g_signal_connect (device, "notify::master", + G_CALLBACK (device_master_changed), self); + + if (!priv->assumed) { + priv->pending_activation_id = g_strdup_printf ("activation::%p", (void *)self); + nm_device_add_pending_action (device, priv->pending_activation_id, TRUE); + } + } + return TRUE; +} + +NMActiveConnection * nm_active_connection_get_master (NMActiveConnection *self) { g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), NULL); @@ -262,6 +413,247 @@ nm_active_connection_get_master (NMActiveConnection *self) return NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->master; } +/** + * nm_active_connection_get_master_ready: + * @self: the #NMActiveConnection + * + * Returns: %TRUE if the connection has a master connection, and that + * master connection is ready to accept slaves. Otherwise %FALSE. + */ +gboolean +nm_active_connection_get_master_ready (NMActiveConnection *self) +{ + g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), FALSE); + + return NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->master_ready; +} + +static void +check_master_ready (NMActiveConnection *self) +{ + NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self); + NMActiveConnectionState master_state = NM_ACTIVE_CONNECTION_STATE_UNKNOWN; + + if (priv->state != NM_ACTIVE_CONNECTION_STATE_ACTIVATING) { + nm_log_dbg (LOGD_DEVICE, "(%p): not signalling master-ready (not activating)", self); + return; + } + if (!priv->master) { + nm_log_dbg (LOGD_DEVICE, "(%p): not signalling master-ready (no master)", self); + return; + } + if (priv->master_ready) { + nm_log_dbg (LOGD_DEVICE, "(%p): not signalling master-ready (already signaled)", self); + return; + } + + /* ActiveConnetions don't enter the ACTIVATING state until they have a + * NMDevice in PREPARE or higher states, so the master active connection's + * device will be ready to accept slaves when the master is in ACTIVATING + * or higher states. + */ + master_state = nm_active_connection_get_state (priv->master); + nm_log_dbg (LOGD_DEVICE, "(%p): master ActiveConnection [%p] state now '%s' (%d)", + self, priv->master, state_to_string (master_state), master_state); + + if ( master_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATING + || master_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) { + nm_log_dbg (LOGD_DEVICE, "(%p): signalling master-ready", self); + + priv->master_ready = TRUE; + g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_INT_MASTER_READY); + + /* Also notify clients to recheck the exported 'master' property to + * ensure that if the master connection was created without a device + * that we notify clients when the master device is known. + */ + g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_MASTER); + } +} + +static void +master_state_cb (NMActiveConnection *master, + GParamSpec *pspec, + gpointer user_data) +{ + NMActiveConnection *self = NM_ACTIVE_CONNECTION (user_data); + NMActiveConnectionState master_state = nm_active_connection_get_state (master); + + check_master_ready (self); + + nm_log_dbg (LOGD_DEVICE, "(%p): master ActiveConnection [%p] state now '%s' (%d)", + self, master, state_to_string (master_state), master_state); + + if (master_state == NM_ACTIVE_CONNECTION_STATE_DEACTIVATING && + nm_active_connection_get_device (master) == NULL) { + /* Master failed without ever creating its device */ + if (NM_ACTIVE_CONNECTION_GET_CLASS (self)->master_failed) + NM_ACTIVE_CONNECTION_GET_CLASS (self)->master_failed (self); + } +} + +/** + * nm_active_connection_set_master: + * @self: the #NMActiveConnection + * @master: if the activation depends on another device (ie, bond or bridge + * master to which this device will be enslaved) pass the #NMActiveConnection + * that this activation request is a child of + * + * Sets the master active connection of @self. + */ +void +nm_active_connection_set_master (NMActiveConnection *self, NMActiveConnection *master) +{ + NMActiveConnectionPrivate *priv; + + g_return_if_fail (NM_IS_ACTIVE_CONNECTION (self)); + g_return_if_fail (NM_IS_ACTIVE_CONNECTION (master)); + + priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self); + + /* Master is write-once, and must be set before exporting the object */ + g_return_if_fail (priv->master == NULL); + g_return_if_fail (priv->path == NULL); + if (priv->device) { + /* Note, the master ActiveConnection may not yet have a device */ + g_return_if_fail (priv->device != nm_active_connection_get_device (master)); + } + + nm_log_dbg (LOGD_DEVICE, "(%p): master ActiveConnection is [%p] %s", + self, master, nm_active_connection_get_id (master)); + + priv->master = g_object_ref (master); + g_signal_connect (priv->master, + "notify::" NM_ACTIVE_CONNECTION_STATE, + (GCallback) master_state_cb, + self); + + check_master_ready (self); +} + +void +nm_active_connection_set_assumed (NMActiveConnection *self, gboolean assumed) +{ + NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self); + + g_return_if_fail (priv->assumed == FALSE); + priv->assumed = assumed; + + if (priv->pending_activation_id) { + nm_device_remove_pending_action (priv->device, priv->pending_activation_id, TRUE); + g_clear_pointer (&priv->pending_activation_id, g_free); + } +} + +gboolean +nm_active_connection_get_assumed (NMActiveConnection *self) +{ + return NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->assumed; +} + +/****************************************************************/ + +static void +auth_done (NMAuthChain *chain, + GError *error, + DBusGMethodInvocation *unused, + gpointer user_data) +{ + NMActiveConnection *self = NM_ACTIVE_CONNECTION (user_data); + NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self); + NMAuthCallResult result; + + g_assert (priv->chain == chain); + g_assert (priv->result_func != NULL); + + /* Must stay alive over the callback */ + g_object_ref (self); + + if (error) { + priv->result_func (self, FALSE, error->message, priv->user_data1, priv->user_data2); + goto done; + } + + /* Caller has had a chance to obtain authorization, so we only need to + * check for 'yes' here. + */ + result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_NETWORK_CONTROL); + if (result != NM_AUTH_CALL_RESULT_YES) { + priv->result_func (self, + FALSE, + "Not authorized to control networking.", + priv->user_data1, + priv->user_data2); + goto done; + } + + if (priv->wifi_shared_permission) { + result = nm_auth_chain_get_result (chain, priv->wifi_shared_permission); + if (result != NM_AUTH_CALL_RESULT_YES) { + priv->result_func (self, + FALSE, + "Not authorized to share connections via wifi.", + priv->user_data1, + priv->user_data2); + goto done; + } + } + + /* Otherwise authorized and available to activate */ + priv->result_func (self, TRUE, NULL, priv->user_data1, priv->user_data2); + +done: + nm_auth_chain_unref (chain); + priv->chain = NULL; + priv->result_func = NULL; + priv->user_data1 = NULL; + priv->user_data2 = NULL; + + g_object_unref (self); +} + +/** + * nm_active_connection_authorize: + * @self: the #NMActiveConnection + * @result_func: function to be called on success or error + * @user_data1: pointer passed to @result_func + * @user_data2: additional pointer passed to @result_func + * + * Checks whether the subject that initiated the active connection (read from + * the #NMActiveConnection::subject property) is authorized to complete this + * activation request. + */ +void +nm_active_connection_authorize (NMActiveConnection *self, + NMActiveConnectionAuthResultFunc result_func, + gpointer user_data1, + gpointer user_data2) +{ + NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self); + const char *wifi_permission = NULL; + + g_return_if_fail (result_func != NULL); + g_return_if_fail (priv->chain == NULL); + + priv->chain = nm_auth_chain_new_subject (priv->subject, NULL, auth_done, self); + g_assert (priv->chain); + + /* Check that the subject is allowed to use networking at all */ + nm_auth_chain_add_call (priv->chain, NM_AUTH_PERMISSION_NETWORK_CONTROL, TRUE); + + /* Shared wifi connections require special permissions too */ + wifi_permission = nm_utils_get_shared_wifi_permission (priv->connection); + if (wifi_permission) { + priv->wifi_shared_permission = wifi_permission; + nm_auth_chain_add_call (priv->chain, wifi_permission, TRUE); + } + + /* Wait for authorization */ + priv->result_func = result_func; + priv->user_data1 = user_data1; + priv->user_data2 = user_data2; +} + /****************************************************************/ static void @@ -269,11 +661,19 @@ nm_active_connection_init (NMActiveConnection *self) { } +static void +constructed (GObject *object) +{ + G_OBJECT_CLASS (nm_active_connection_parent_class)->constructed (object); + g_assert (NM_ACTIVE_CONNECTION_GET_PRIVATE (object)->subject); +} + static void set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (object); + const char *tmp; switch (prop_id) { case PROP_INT_CONNECTION: @@ -281,28 +681,19 @@ set_property (GObject *object, guint prop_id, priv->connection = g_value_dup_object (value); break; case PROP_INT_DEVICE: - g_warn_if_fail (priv->device == NULL); - priv->device = g_value_dup_object (value); - if (priv->device) - g_warn_if_fail (priv->device != priv->master); + nm_active_connection_set_device (NM_ACTIVE_CONNECTION (object), g_value_get_object (value)); break; - case PROP_INT_USER_REQUESTED: - priv->user_requested = g_value_get_boolean (value); - break; - case PROP_INT_USER_UID: - priv->user_uid = g_value_get_ulong (value); - break; - case PROP_INT_ASSUMED: - priv->assumed = g_value_get_boolean (value); + case PROP_INT_SUBJECT: + priv->subject = g_value_dup_object (value); break; case PROP_INT_MASTER: - g_warn_if_fail (priv->master == NULL); - priv->master = g_value_dup_object (value); - if (priv->master) - g_warn_if_fail (priv->master != priv->device); + nm_active_connection_set_master (NM_ACTIVE_CONNECTION (object), g_value_get_object (value)); break; case PROP_SPECIFIC_OBJECT: - priv->specific_object = g_value_dup_boxed (value); + tmp = g_value_get_boxed (value); + /* NM uses "/" to mean NULL */ + if (g_strcmp0 (tmp, "/") != 0) + priv->specific_object = g_value_dup_boxed (value); break; case PROP_DEFAULT: priv->is_default = g_value_get_boolean (value); @@ -327,20 +718,27 @@ get_property (GObject *object, guint prop_id, { NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (object); GPtrArray *devices; + NMDevice *master_device = NULL; switch (prop_id) { case PROP_CONNECTION: g_value_set_boxed (value, nm_connection_get_path (priv->connection)); break; + case PROP_ID: + g_value_set_string (value, nm_connection_get_id (priv->connection)); + break; case PROP_UUID: g_value_set_string (value, nm_connection_get_uuid (priv->connection)); break; + case PROP_TYPE: + g_value_set_string (value, nm_connection_get_connection_type (priv->connection)); + break; case PROP_SPECIFIC_OBJECT: g_value_set_boxed (value, priv->specific_object ? priv->specific_object : "/"); break; case PROP_DEVICES: devices = g_ptr_array_sized_new (1); - if (priv->device) + if (priv->device && priv->state < NM_ACTIVE_CONNECTION_STATE_DEACTIVATED) g_ptr_array_add (devices, g_strdup (nm_device_get_path (priv->device))); g_value_take_boxed (value, devices); break; @@ -350,14 +748,35 @@ get_property (GObject *object, guint prop_id, case PROP_DEFAULT: g_value_set_boolean (value, priv->is_default); break; + case PROP_IP4_CONFIG: + /* The IP and DHCP config properties may be overridden by a subclass */ + g_value_set_boxed (value, "/"); + break; + case PROP_DHCP4_CONFIG: + g_value_set_boxed (value, "/"); + break; case PROP_DEFAULT6: g_value_set_boolean (value, priv->is_default6); break; + case PROP_IP6_CONFIG: + g_value_set_boxed (value, "/"); + break; + case PROP_DHCP6_CONFIG: + g_value_set_boxed (value, "/"); + break; case PROP_VPN: g_value_set_boolean (value, priv->vpn); break; case PROP_MASTER: - g_value_set_boxed (value, priv->master ? nm_device_get_path (priv->master) : "/"); + if (priv->master) + master_device = nm_active_connection_get_device (priv->master); + g_value_set_boxed (value, master_device ? nm_device_get_path (master_device) : "/"); + break; + case PROP_INT_SUBJECT: + g_value_set_object (value, priv->subject); + break; + case PROP_INT_MASTER_READY: + g_value_set_boolean (value, priv->master_ready); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -365,10 +784,34 @@ get_property (GObject *object, guint prop_id, } } +static void +_device_cleanup (NMActiveConnection *self) +{ + NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self); + + if (priv->device) { + g_signal_handlers_disconnect_by_func (priv->device, G_CALLBACK (device_state_changed), self); + g_signal_handlers_disconnect_by_func (priv->device, G_CALLBACK (device_master_changed), self); + } + + if (priv->pending_activation_id) { + nm_device_remove_pending_action (priv->device, priv->pending_activation_id, TRUE); + g_clear_pointer (&priv->pending_activation_id, g_free); + } + + g_clear_object (&priv->device); +} + static void dispose (GObject *object) { - NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (object); + NMActiveConnection *self = NM_ACTIVE_CONNECTION (object); + NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self); + + if (priv->chain) { + nm_auth_chain_unref (priv->chain); + priv->chain = NULL; + } g_free (priv->path); priv->path = NULL; @@ -376,22 +819,31 @@ dispose (GObject *object) priv->specific_object = NULL; g_clear_object (&priv->connection); - g_clear_object (&priv->device); + + _device_cleanup (self); + + if (priv->master) { + g_signal_handlers_disconnect_by_func (priv->master, + (GCallback) master_state_cb, + self); + } g_clear_object (&priv->master); + g_clear_object (&priv->subject); G_OBJECT_CLASS (nm_active_connection_parent_class)->dispose (object); } static void -nm_active_connection_class_init (NMActiveConnectionClass *vpn_class) +nm_active_connection_class_init (NMActiveConnectionClass *ac_class) { - GObjectClass *object_class = G_OBJECT_CLASS (vpn_class); + GObjectClass *object_class = G_OBJECT_CLASS (ac_class); - g_type_class_add_private (vpn_class, sizeof (NMActiveConnectionPrivate)); + g_type_class_add_private (ac_class, sizeof (NMActiveConnectionPrivate)); /* virtual methods */ object_class->get_property = get_property; object_class->set_property = set_property; + object_class->constructed = constructed; object_class->dispose = dispose; /* D-Bus exported properties */ @@ -402,6 +854,13 @@ nm_active_connection_class_init (NMActiveConnectionClass *vpn_class) DBUS_TYPE_G_OBJECT_PATH, G_PARAM_READABLE)); + g_object_class_install_property (object_class, PROP_ID, + g_param_spec_string (NM_ACTIVE_CONNECTION_ID, + "Connection ID", + "Connection ID", + NULL, + G_PARAM_READABLE)); + g_object_class_install_property (object_class, PROP_UUID, g_param_spec_string (NM_ACTIVE_CONNECTION_UUID, "Connection UUID", @@ -409,6 +868,13 @@ nm_active_connection_class_init (NMActiveConnectionClass *vpn_class) NULL, G_PARAM_READABLE)); + g_object_class_install_property (object_class, PROP_TYPE, + g_param_spec_string (NM_ACTIVE_CONNECTION_TYPE, + "Connection Type", + "Connection Type", + NULL, + G_PARAM_READABLE)); + g_object_class_install_property (object_class, PROP_SPECIFIC_OBJECT, g_param_spec_boxed (NM_ACTIVE_CONNECTION_SPECIFIC_OBJECT, "Specific object", @@ -439,6 +905,20 @@ nm_active_connection_class_init (NMActiveConnectionClass *vpn_class) FALSE, G_PARAM_READWRITE)); + g_object_class_install_property (object_class, PROP_IP4_CONFIG, + g_param_spec_boxed (NM_ACTIVE_CONNECTION_IP4_CONFIG, + "IP4 Config", + "IP4 Config", + DBUS_TYPE_G_OBJECT_PATH, + G_PARAM_READABLE)); + + g_object_class_install_property (object_class, PROP_DHCP4_CONFIG, + g_param_spec_boxed (NM_ACTIVE_CONNECTION_DHCP4_CONFIG, + "DHCP4 Config", + "DHCP4 Config", + DBUS_TYPE_G_OBJECT_PATH, + G_PARAM_READABLE)); + g_object_class_install_property (object_class, PROP_DEFAULT6, g_param_spec_boolean (NM_ACTIVE_CONNECTION_DEFAULT6, "Default6", @@ -446,6 +926,20 @@ nm_active_connection_class_init (NMActiveConnectionClass *vpn_class) FALSE, G_PARAM_READWRITE)); + g_object_class_install_property (object_class, PROP_IP6_CONFIG, + g_param_spec_boxed (NM_ACTIVE_CONNECTION_IP6_CONFIG, + "IP6 Config", + "IP6 Config", + DBUS_TYPE_G_OBJECT_PATH, + G_PARAM_READABLE)); + + g_object_class_install_property (object_class, PROP_DHCP6_CONFIG, + g_param_spec_boxed (NM_ACTIVE_CONNECTION_DHCP6_CONFIG, + "DHCP6 Config", + "DHCP6 Config", + DBUS_TYPE_G_OBJECT_PATH, + G_PARAM_READABLE)); + g_object_class_install_property (object_class, PROP_VPN, g_param_spec_boolean (NM_ACTIVE_CONNECTION_VPN, "VPN", @@ -466,49 +960,37 @@ nm_active_connection_class_init (NMActiveConnectionClass *vpn_class) "Internal Connection", "Internal connection", NM_TYPE_CONNECTION, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | NM_PROPERTY_PARAM_NO_EXPORT)); + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (object_class, PROP_INT_DEVICE, g_param_spec_object (NM_ACTIVE_CONNECTION_INT_DEVICE, "Internal device", "Internal device", NM_TYPE_DEVICE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | NM_PROPERTY_PARAM_NO_EXPORT)); + G_PARAM_READWRITE)); - g_object_class_install_property (object_class, PROP_INT_USER_REQUESTED, - g_param_spec_boolean (NM_ACTIVE_CONNECTION_INT_USER_REQUESTED, - "User requested", - "User requested", - FALSE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | NM_PROPERTY_PARAM_NO_EXPORT)); - - g_object_class_install_property (object_class, PROP_INT_USER_UID, - g_param_spec_ulong (NM_ACTIVE_CONNECTION_INT_USER_UID, - "User UID", - "User UID (if user requested)", - 0, G_MAXULONG, 0, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | NM_PROPERTY_PARAM_NO_EXPORT)); - - g_object_class_install_property (object_class, PROP_INT_ASSUMED, - g_param_spec_boolean (NM_ACTIVE_CONNECTION_INT_ASSUMED, - "Assumed", - "Assumed", - FALSE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | NM_PROPERTY_PARAM_NO_EXPORT)); + g_object_class_install_property (object_class, PROP_INT_SUBJECT, + g_param_spec_object (NM_ACTIVE_CONNECTION_INT_SUBJECT, + "Subject", + "Subject", + NM_TYPE_AUTH_SUBJECT, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (object_class, PROP_INT_MASTER, g_param_spec_object (NM_ACTIVE_CONNECTION_INT_MASTER, - "Internal master device", - "Internal device", - NM_TYPE_DEVICE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | NM_PROPERTY_PARAM_NO_EXPORT)); - - /* Signals */ - signals[PROPERTIES_CHANGED] = - nm_properties_changed_signal_new (object_class, - G_STRUCT_OFFSET (NMActiveConnectionClass, properties_changed)); - - dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (vpn_class), - &dbus_glib_nm_active_connection_object_info); + "Internal master active connection", + "Internal active connection", + NM_TYPE_ACTIVE_CONNECTION, + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_INT_MASTER_READY, + g_param_spec_boolean (NM_ACTIVE_CONNECTION_INT_MASTER_READY, + "Internal master active connection ready for slaves", + "Internal active connection ready", + FALSE, G_PARAM_READABLE)); + + nm_dbus_manager_register_exported_type (nm_dbus_manager_get (), + G_TYPE_FROM_CLASS (ac_class), + &dbus_glib_nm_active_connection_object_info); } diff --git a/src/nm-active-connection.h b/src/nm-active-connection.h index 2f17c583..0d96c872 100644 --- a/src/nm-active-connection.h +++ b/src/nm-active-connection.h @@ -24,6 +24,7 @@ #include #include "nm-types.h" #include "nm-connection.h" +#include "nm-auth-subject.h" #define NM_TYPE_ACTIVE_CONNECTION (nm_active_connection_get_type ()) #define NM_ACTIVE_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_ACTIVE_CONNECTION, NMActiveConnection)) @@ -34,23 +35,27 @@ /* D-Bus Exported Properties */ #define NM_ACTIVE_CONNECTION_CONNECTION "connection" +#define NM_ACTIVE_CONNECTION_ID "id" #define NM_ACTIVE_CONNECTION_UUID "uuid" +#define NM_ACTIVE_CONNECTION_TYPE "type" #define NM_ACTIVE_CONNECTION_SPECIFIC_OBJECT "specific-object" #define NM_ACTIVE_CONNECTION_DEVICES "devices" #define NM_ACTIVE_CONNECTION_STATE "state" #define NM_ACTIVE_CONNECTION_DEFAULT "default" +#define NM_ACTIVE_CONNECTION_IP4_CONFIG "ip4-config" +#define NM_ACTIVE_CONNECTION_DHCP4_CONFIG "dhcp4-config" #define NM_ACTIVE_CONNECTION_DEFAULT6 "default6" +#define NM_ACTIVE_CONNECTION_IP6_CONFIG "ip6-config" +#define NM_ACTIVE_CONNECTION_DHCP6_CONFIG "dhcp6-config" #define NM_ACTIVE_CONNECTION_VPN "vpn" #define NM_ACTIVE_CONNECTION_MASTER "master" -/* Internal non-exported construct-time properties */ +/* Internal non-exported properties */ #define NM_ACTIVE_CONNECTION_INT_CONNECTION "int-connection" #define NM_ACTIVE_CONNECTION_INT_DEVICE "int-device" -#define NM_ACTIVE_CONNECTION_INT_USER_REQUESTED "int-user-requested" -#define NM_ACTIVE_CONNECTION_INT_USER_UID "int-user-uid" -#define NM_ACTIVE_CONNECTION_INT_ASSUMED "int-assumed" +#define NM_ACTIVE_CONNECTION_INT_SUBJECT "int-subject" #define NM_ACTIVE_CONNECTION_INT_MASTER "int-master" - +#define NM_ACTIVE_CONNECTION_INT_MASTER_READY "int-master-ready" typedef struct { GObject parent; @@ -59,16 +64,41 @@ typedef struct { typedef struct { GObjectClass parent; - /* Signals */ - void (*properties_changed) (NMActiveConnection *active, GHashTable *properties); + /* re-emits device state changes as a convenience for subclasses for + * device states >= DISCONNECTED. + */ + void (*device_state_changed) (NMActiveConnection *connection, + NMDevice *device, + NMDeviceState new_state, + NMDeviceState old_state); + void (*master_failed) (NMActiveConnection *connection); } NMActiveConnectionClass; GType nm_active_connection_get_type (void); +typedef void (*NMActiveConnectionAuthResultFunc) (NMActiveConnection *self, + gboolean success, + const char *error_desc, + gpointer user_data1, + gpointer user_data2); + +void nm_active_connection_authorize (NMActiveConnection *self, + NMActiveConnectionAuthResultFunc result_func, + gpointer user_data1, + gpointer user_data2); + void nm_active_connection_export (NMActiveConnection *self); NMConnection *nm_active_connection_get_connection (NMActiveConnection *self); -const char * nm_active_connection_get_name (NMActiveConnection *self); + +void nm_active_connection_set_connection (NMActiveConnection *self, + NMConnection *connection); + +const char * nm_active_connection_get_id (NMActiveConnection *self); + +const char * nm_active_connection_get_uuid (NMActiveConnection *self); + +const char * nm_active_connection_get_connection_type (NMActiveConnection *self); const char * nm_active_connection_get_path (NMActiveConnection *self); @@ -94,12 +124,22 @@ void nm_active_connection_set_state (NMActiveConnection *self, NMDevice * nm_active_connection_get_device (NMActiveConnection *self); +gboolean nm_active_connection_set_device (NMActiveConnection *self, NMDevice *device); + +NMAuthSubject *nm_active_connection_get_subject (NMActiveConnection *self); + gboolean nm_active_connection_get_user_requested (NMActiveConnection *self); -gulong nm_active_connection_get_user_uid (NMActiveConnection *self); +NMActiveConnection *nm_active_connection_get_master (NMActiveConnection *self); -gboolean nm_active_connection_get_assumed (NMActiveConnection *self); +gboolean nm_active_connection_get_master_ready (NMActiveConnection *self); -NMDevice * nm_active_connection_get_master (NMActiveConnection *self); +void nm_active_connection_set_master (NMActiveConnection *self, + NMActiveConnection *master); + +void nm_active_connection_set_assumed (NMActiveConnection *self, + gboolean assumed); + +gboolean nm_active_connection_get_assumed (NMActiveConnection *self); #endif /* NM_ACTIVE_CONNECTION_H */ diff --git a/src/nm-agent-manager-glue.h b/src/nm-agent-manager-glue.h new file mode 100644 index 00000000..6e884c8a --- /dev/null +++ b/src/nm-agent-manager-glue.h @@ -0,0 +1,170 @@ +/* Generated by dbus-binding-tool; do not edit! */ + + +#ifndef __dbus_glib_marshal_nm_agent_manager_MARSHAL_H__ +#define __dbus_glib_marshal_nm_agent_manager_MARSHAL_H__ + +#include + +G_BEGIN_DECLS + +#ifdef G_ENABLE_DEBUG +#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v) +#define g_marshal_value_peek_char(v) g_value_get_schar (v) +#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v) +#define g_marshal_value_peek_int(v) g_value_get_int (v) +#define g_marshal_value_peek_uint(v) g_value_get_uint (v) +#define g_marshal_value_peek_long(v) g_value_get_long (v) +#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v) +#define g_marshal_value_peek_int64(v) g_value_get_int64 (v) +#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v) +#define g_marshal_value_peek_enum(v) g_value_get_enum (v) +#define g_marshal_value_peek_flags(v) g_value_get_flags (v) +#define g_marshal_value_peek_float(v) g_value_get_float (v) +#define g_marshal_value_peek_double(v) g_value_get_double (v) +#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v) +#define g_marshal_value_peek_param(v) g_value_get_param (v) +#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v) +#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v) +#define g_marshal_value_peek_object(v) g_value_get_object (v) +#define g_marshal_value_peek_variant(v) g_value_get_variant (v) +#else /* !G_ENABLE_DEBUG */ +/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API. + * Do not access GValues directly in your code. Instead, use the + * g_value_get_*() functions + */ +#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int +#define g_marshal_value_peek_char(v) (v)->data[0].v_int +#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint +#define g_marshal_value_peek_int(v) (v)->data[0].v_int +#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint +#define g_marshal_value_peek_long(v) (v)->data[0].v_long +#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 +#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 +#define g_marshal_value_peek_enum(v) (v)->data[0].v_long +#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_float(v) (v)->data[0].v_float +#define g_marshal_value_peek_double(v) (v)->data[0].v_double +#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer +#endif /* !G_ENABLE_DEBUG */ + + +/* NONE:POINTER */ +#define dbus_glib_marshal_nm_agent_manager_VOID__POINTER g_cclosure_marshal_VOID__POINTER +#define dbus_glib_marshal_nm_agent_manager_NONE__POINTER dbus_glib_marshal_nm_agent_manager_VOID__POINTER + +/* NONE:STRING,UINT,POINTER */ +extern void dbus_glib_marshal_nm_agent_manager_VOID__STRING_UINT_POINTER (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); +void +dbus_glib_marshal_nm_agent_manager_VOID__STRING_UINT_POINTER (GClosure *closure, + GValue *return_value G_GNUC_UNUSED, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint G_GNUC_UNUSED, + gpointer marshal_data) +{ + typedef void (*GMarshalFunc_VOID__STRING_UINT_POINTER) (gpointer data1, + gpointer arg_1, + guint arg_2, + gpointer arg_3, + gpointer data2); + register GMarshalFunc_VOID__STRING_UINT_POINTER callback; + register GCClosure *cc = (GCClosure*) closure; + register gpointer data1, data2; + + g_return_if_fail (n_param_values == 4); + + if (G_CCLOSURE_SWAP_DATA (closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer (param_values + 0); + } + else + { + data1 = g_value_peek_pointer (param_values + 0); + data2 = closure->data; + } + callback = (GMarshalFunc_VOID__STRING_UINT_POINTER) (marshal_data ? marshal_data : cc->callback); + + callback (data1, + g_marshal_value_peek_string (param_values + 1), + g_marshal_value_peek_uint (param_values + 2), + g_marshal_value_peek_pointer (param_values + 3), + data2); +} +#define dbus_glib_marshal_nm_agent_manager_NONE__STRING_UINT_POINTER dbus_glib_marshal_nm_agent_manager_VOID__STRING_UINT_POINTER + +/* NONE:STRING,POINTER */ +extern void dbus_glib_marshal_nm_agent_manager_VOID__STRING_POINTER (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); +void +dbus_glib_marshal_nm_agent_manager_VOID__STRING_POINTER (GClosure *closure, + GValue *return_value G_GNUC_UNUSED, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint G_GNUC_UNUSED, + gpointer marshal_data) +{ + typedef void (*GMarshalFunc_VOID__STRING_POINTER) (gpointer data1, + gpointer arg_1, + gpointer arg_2, + gpointer data2); + register GMarshalFunc_VOID__STRING_POINTER callback; + register GCClosure *cc = (GCClosure*) closure; + register gpointer data1, data2; + + g_return_if_fail (n_param_values == 3); + + if (G_CCLOSURE_SWAP_DATA (closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer (param_values + 0); + } + else + { + data1 = g_value_peek_pointer (param_values + 0); + data2 = closure->data; + } + callback = (GMarshalFunc_VOID__STRING_POINTER) (marshal_data ? marshal_data : cc->callback); + + callback (data1, + g_marshal_value_peek_string (param_values + 1), + g_marshal_value_peek_pointer (param_values + 2), + data2); +} +#define dbus_glib_marshal_nm_agent_manager_NONE__STRING_POINTER dbus_glib_marshal_nm_agent_manager_VOID__STRING_POINTER + +G_END_DECLS + +#endif /* __dbus_glib_marshal_nm_agent_manager_MARSHAL_H__ */ + +#include +static const DBusGMethodInfo dbus_glib_nm_agent_manager_methods[] = { + { (GCallback) impl_agent_manager_register, dbus_glib_marshal_nm_agent_manager_NONE__STRING_POINTER, 0 }, + { (GCallback) impl_agent_manager_register_with_capabilities, dbus_glib_marshal_nm_agent_manager_NONE__STRING_UINT_POINTER, 71 }, + { (GCallback) impl_agent_manager_unregister, dbus_glib_marshal_nm_agent_manager_NONE__POINTER, 175 }, +}; + +const DBusGObjectInfo dbus_glib_nm_agent_manager_object_info = { 1, + dbus_glib_nm_agent_manager_methods, + 3, +"org.freedesktop.NetworkManager.AgentManager\0Register\0A\0identifier\0I\0s\0\0org.freedesktop.NetworkManager.AgentManager\0RegisterWithCapabilities\0A\0identifier\0I\0s\0capabilities\0I\0u\0\0org.freedesktop.NetworkManager.AgentManager\0Unregister\0A\0\0\0", +"\0", +"\0" +}; + diff --git a/src/nm-auth-subject.c b/src/nm-auth-subject.c new file mode 100644 index 00000000..e770af49 --- /dev/null +++ b/src/nm-auth-subject.c @@ -0,0 +1,216 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2013 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 +#include +#include +#include +#include + +#if WITH_POLKIT +#include +#endif + +#include "nm-auth-subject.h" +#include "nm-dbus-manager.h" + +G_DEFINE_TYPE (NMAuthSubject, nm_auth_subject, G_TYPE_OBJECT) + +#define NM_AUTH_SUBJECT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_AUTH_SUBJECT, NMAuthSubjectPrivate)) + +typedef struct { + gulong pid; + gulong uid; + char *dbus_sender; + +#if WITH_POLKIT + PolkitSubject *pk_subject; +#endif +} NMAuthSubjectPrivate; + +static NMAuthSubject * +_new_common (DBusGMethodInvocation *context, + DBusConnection *connection, + DBusMessage *message, + gboolean internal) +{ + NMAuthSubject *subject; + NMAuthSubjectPrivate *priv; + NMDBusManager *dbus_mgr; + gboolean success = FALSE; + + g_return_val_if_fail (context || (connection && message) || internal, NULL); + if (internal) + g_return_val_if_fail (context == NULL && connection == NULL && message == NULL, NULL); + + subject = NM_AUTH_SUBJECT (g_object_new (NM_TYPE_AUTH_SUBJECT, NULL)); + priv = NM_AUTH_SUBJECT_GET_PRIVATE (subject); + + dbus_mgr = nm_dbus_manager_get (); + + if (internal) { + priv->uid = 0; + priv->pid = 0; + return subject; + } + + if (context) { + success = nm_dbus_manager_get_caller_info (dbus_mgr, + context, + &priv->dbus_sender, + &priv->uid, + &priv->pid); + } else if (message) { + success = nm_dbus_manager_get_caller_info_from_message (dbus_mgr, + connection, + message, + &priv->dbus_sender, + &priv->uid, + &priv->pid); + } else + g_assert_not_reached (); + + if (!success) { + g_object_unref (subject); + return NULL; + } + + g_assert (priv->dbus_sender); + g_assert_cmpuint (priv->pid, !=, 0); + +#if WITH_POLKIT + /* FIXME: should we use polkit_unix_session_new() to store the session ID + * of a short-lived process, so that the process can exit but we can still + * ask that user for authorization? + */ + priv->pk_subject = polkit_unix_process_new_for_owner (priv->pid, 0, priv->uid); + if (!priv->pk_subject) + return NULL; +#endif + + return subject; +} + + +NMAuthSubject * +nm_auth_subject_new_from_context (DBusGMethodInvocation *context) +{ + return _new_common (context, NULL, NULL, FALSE); +} + +NMAuthSubject * +nm_auth_subject_new_from_message (DBusConnection *connection, + DBusMessage *message) +{ + return _new_common (NULL, connection, message, FALSE); +} + +/** + * 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 _new_common (NULL, NULL, NULL, TRUE); +} + +/**************************************************************/ + +gulong +nm_auth_subject_get_uid (NMAuthSubject *subject) +{ + return NM_AUTH_SUBJECT_GET_PRIVATE (subject)->uid; +} + +gulong +nm_auth_subject_get_pid (NMAuthSubject *subject) +{ + return NM_AUTH_SUBJECT_GET_PRIVATE (subject)->pid; +} + +const char * +nm_auth_subject_get_dbus_sender (NMAuthSubject *subject) +{ + return NM_AUTH_SUBJECT_GET_PRIVATE (subject)->dbus_sender; +} + +gboolean +nm_auth_subject_get_internal (NMAuthSubject *subject) +{ + /* internal requests will have no dbus sender */ + return NM_AUTH_SUBJECT_GET_PRIVATE (subject)->dbus_sender ? FALSE : TRUE; +} + +#if WITH_POLKIT +PolkitSubject * +nm_auth_subject_get_polkit_subject (NMAuthSubject *subject) +{ + return NM_AUTH_SUBJECT_GET_PRIVATE (subject)->pk_subject; +} +#endif + +/******************************************************************/ + +static void +nm_auth_subject_init (NMAuthSubject *self) +{ + NMAuthSubjectPrivate *priv = NM_AUTH_SUBJECT_GET_PRIVATE (self); + + priv->pid = G_MAXULONG; + priv->uid = G_MAXULONG; +} + +static void +finalize (GObject *object) +{ + NMAuthSubjectPrivate *priv = NM_AUTH_SUBJECT_GET_PRIVATE (object); + + g_free (priv->dbus_sender); + +#if WITH_POLKIT + if (priv->pk_subject) + g_object_unref (priv->pk_subject); +#endif + + 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); + + g_type_class_add_private (config_class, sizeof (NMAuthSubjectPrivate)); + + /* virtual methods */ + object_class->finalize = finalize; +} diff --git a/src/nm-auth-subject.h b/src/nm-auth-subject.h new file mode 100644 index 00000000..06359890 --- /dev/null +++ b/src/nm-auth-subject.h @@ -0,0 +1,70 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2013 Red Hat, Inc. + */ + +#ifndef NM_AUTH_SUBJECT_H +#define NM_AUTH_SUBJECT_H + +#include +#include +#include +#include +#include + +#if WITH_POLKIT +#include +#endif + +#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 struct { + GObject parent; +} NMAuthSubject; + +typedef struct { + GObjectClass parent; + +} NMAuthSubjectClass; + +GType nm_auth_subject_get_type (void); + +NMAuthSubject *nm_auth_subject_new_from_context (DBusGMethodInvocation *context); + +NMAuthSubject *nm_auth_subject_new_from_message (DBusConnection *connection, DBusMessage *message); + +NMAuthSubject *nm_auth_subject_new_internal (void); + +gulong nm_auth_subject_get_uid (NMAuthSubject *subject); + +gulong nm_auth_subject_get_pid (NMAuthSubject *subject); + +const char *nm_auth_subject_get_dbus_sender (NMAuthSubject *subject); + +gboolean nm_auth_subject_get_internal (NMAuthSubject *subject); + +#if WITH_POLKIT +PolkitSubject *nm_auth_subject_get_polkit_subject (NMAuthSubject *subject); +#endif + +#endif /* NM_AUTH_SUBJECT_H */ diff --git a/src/nm-call-store.c b/src/nm-call-store.c deleted file mode 100644 index df400d0f..00000000 --- a/src/nm-call-store.c +++ /dev/null @@ -1,209 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2007 Novell, Inc. - * Copyright (C) 2010 Red Hat, Inc. - */ - -#include "nm-call-store.h" -#include "nm-logging.h" - -NMCallStore * -nm_call_store_new (void) -{ - return g_hash_table_new_full (NULL, NULL, NULL, - (GDestroyNotify) g_hash_table_destroy); -} - -static void -object_destroyed_cb (gpointer data, GObject *object) -{ - g_hash_table_remove ((NMCallStore *) data, object); -} - -void -nm_call_store_add (NMCallStore *store, - GObject *object, - gpointer *call_id) -{ - GHashTable *call_ids_hash; - - g_return_if_fail (store != NULL); - g_return_if_fail (object != NULL); - g_return_if_fail (call_id != NULL); - - call_ids_hash = g_hash_table_lookup (store, object); - if (!call_ids_hash) { - call_ids_hash = g_hash_table_new (NULL, NULL); - g_hash_table_insert (store, object, call_ids_hash); - g_object_weak_ref (object, object_destroyed_cb, store); - } - - g_hash_table_insert (call_ids_hash, call_id, NULL); -} - -void -nm_call_store_remove (NMCallStore *store, - GObject *object, - gpointer call_id) -{ - GHashTable *call_ids_hash; - - g_return_if_fail (store != NULL); - g_return_if_fail (object != NULL); - g_return_if_fail (call_id != NULL); - - call_ids_hash = g_hash_table_lookup (store, object); - if (!call_ids_hash) { - nm_log_warn (LOGD_CORE, "Trying to remove a non-existant call id."); - return; - } - - if (!g_hash_table_remove (call_ids_hash, call_id)) - nm_log_warn (LOGD_CORE, "Trying to remove a non-existant call id."); - - if (g_hash_table_size (call_ids_hash) == 0) { - g_hash_table_remove (store, object); - g_object_weak_unref (object, object_destroyed_cb, store); - } -} - -typedef struct { - GObject *object; - gint count; - NMCallStoreFunc callback; - gpointer user_data; -} StoreForeachInfo; - -static void -call_callback (gpointer call_id, gpointer user_data) -{ - StoreForeachInfo *info = (StoreForeachInfo *) user_data; - - if (info->count >= 0) { - if (info->callback (info->object, call_id, info->user_data)) - info->count++; - else - info->count = -1; - } -} - -static void -prepend_id (gpointer key, gpointer value, gpointer user_data) -{ - GSList **list = (GSList **) user_data; - - *list = g_slist_prepend (*list, key); -} - -static GSList * -get_call_ids (GHashTable *hash) -{ - GSList *ids = NULL; - - g_hash_table_foreach (hash, prepend_id, &ids); - - return ids; -} - -static void -call_all_callbacks (gpointer key, gpointer value, gpointer user_data) -{ - StoreForeachInfo *info = (StoreForeachInfo *) user_data; - GSList *ids; - - info->object = G_OBJECT (key); - - /* Create a copy of the hash keys (call_ids) so that the callback is - free to modify the store */ - ids = get_call_ids ((GHashTable *) value); - g_slist_foreach (ids, call_callback, info); - g_slist_free (ids); -} - -static void -duplicate_hash (gpointer key, gpointer value, gpointer user_data) -{ - g_hash_table_insert ((GHashTable *) user_data, key, value); -} - -int -nm_call_store_foreach (NMCallStore *store, - GObject *object, - NMCallStoreFunc callback, - gpointer user_data) -{ - StoreForeachInfo info; - - g_return_val_if_fail (store != NULL, -1); - g_return_val_if_fail (callback != NULL, -1); - - info.object = object; - info.count = 0; - info.callback = callback; - info.user_data = user_data; - - if (object) { - GHashTable *call_ids_hash; - GSList *ids; - - call_ids_hash = g_hash_table_lookup (store, object); - if (!call_ids_hash) { - nm_log_warn (LOGD_CORE, "Object not in store"); - return -1; - } - - /* Create a copy of the hash keys (call_ids) so that the callback is - free to modify the store */ - ids = get_call_ids (call_ids_hash); - g_slist_foreach (ids, call_callback, &info); - g_slist_free (ids); - } else { - GHashTable *copy; - - /* Create a copy of the main store so that callbacks can modify it */ - copy = g_hash_table_new (NULL, NULL); - g_hash_table_foreach (store, duplicate_hash, copy); - g_hash_table_foreach (copy, call_all_callbacks, &info); - g_hash_table_destroy (copy); - } - - return info.count; -} - -static void -remove_weakref (gpointer key, gpointer value, gpointer user_data) -{ - g_object_weak_unref (G_OBJECT (key), object_destroyed_cb, user_data); -} - -void -nm_call_store_clear (NMCallStore *store) -{ - g_return_if_fail (store); - - g_hash_table_foreach (store, remove_weakref, store); - g_hash_table_remove_all (store); -} - -void -nm_call_store_destroy (NMCallStore *store) -{ - g_return_if_fail (store); - - g_hash_table_destroy (store); -} diff --git a/src/nm-call-store.h b/src/nm-call-store.h deleted file mode 100644 index 0ae5a769..00000000 --- a/src/nm-call-store.h +++ /dev/null @@ -1,47 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * (C) Copyright 2007 Novell, Inc. - */ - -#ifndef NM_CALLBACK_STORE_H -#define NM_CALLBACK_STORE_H - -#include - -typedef GHashTable NMCallStore; - -typedef gboolean (*NMCallStoreFunc) (GObject *object, gpointer call_id, gpointer user_data); - -NMCallStore *nm_call_store_new (void); -void nm_call_store_add (NMCallStore *store, - GObject *object, - gpointer *call_id); - -void nm_call_store_remove (NMCallStore *store, - GObject *object, - gpointer call_id); - -int nm_call_store_foreach (NMCallStore *store, - GObject *object, - NMCallStoreFunc callback, - gpointer user_data); - -void nm_call_store_clear (NMCallStore *store); -void nm_call_store_destroy (NMCallStore *store); - -#endif /* NM_CALLBACK_STORE_H */ diff --git a/src/nm-config.c b/src/nm-config.c deleted file mode 100644 index 6e801d35..00000000 --- a/src/nm-config.c +++ /dev/null @@ -1,294 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2011 Red Hat, Inc. - */ - -#include -#include -#include - -#include "nm-config.h" - -#define NM_DEFAULT_SYSTEM_CONF_FILE NMCONFDIR "/NetworkManager.conf" -#define NM_OLD_SYSTEM_CONF_FILE NMCONFDIR "/nm-system-settings.conf" - -struct NMConfig { - char *path; - char **plugins; - char *dhcp_client; - char **dns_plugins; - char *log_level; - char *log_domains; - char *connectivity_uri; - guint connectivity_interval; - char *connectivity_response; -}; - -/************************************************************************/ - -GQuark -nm_config_error_quark (void) -{ - static GQuark quark = 0; - if (!quark) - quark = g_quark_from_static_string ("nm-config-error"); - return quark; -} - -/************************************************************************/ - -const char * -nm_config_get_path (NMConfig *config) -{ - g_return_val_if_fail (config != NULL, NULL); - - return config->path; -} - -const char ** -nm_config_get_plugins (NMConfig *config) -{ - g_return_val_if_fail (config != NULL, NULL); - - return (const char **) config->plugins; -} - -const char * -nm_config_get_dhcp_client (NMConfig *config) -{ - g_return_val_if_fail (config != NULL, NULL); - - return config->dhcp_client; -} - -const char ** -nm_config_get_dns_plugins (NMConfig *config) -{ - g_return_val_if_fail (config != NULL, NULL); - - return (const char **) config->dns_plugins; -} - -const char * -nm_config_get_log_level (NMConfig *config) -{ - g_return_val_if_fail (config != NULL, NULL); - - return config->log_level; -} - -const char * -nm_config_get_log_domains (NMConfig *config) -{ - g_return_val_if_fail (config != NULL, NULL); - - return config->log_domains; -} - -const char * -nm_config_get_connectivity_uri (NMConfig *config) -{ - g_return_val_if_fail (config != NULL, NULL); - - return config->connectivity_uri; -} - -const guint -nm_config_get_connectivity_interval (NMConfig *config) -{ - g_return_val_if_fail (config != NULL, 0); - - return config->connectivity_interval; -} - -const char * -nm_config_get_connectivity_response (NMConfig *config) -{ - g_return_val_if_fail (config != NULL, NULL); - - return config->connectivity_response; -} - - -/************************************************************************/ - -static gboolean -fill_from_file (NMConfig *config, - const char *path, - const char *cli_plugins, - const char *cli_log_level, - const char *cli_log_domains, - const char *cli_connectivity_uri, - const gint cli_connectivity_interval, - const char *cli_connectivity_response, - GError **error) -{ - GKeyFile *kf; - gboolean success = FALSE; - - if (g_file_test (path, G_FILE_TEST_EXISTS) == FALSE) { - g_set_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_NOT_FOUND, "file %s not found", path); - return FALSE; - } - - kf = g_key_file_new (); - if (!kf) { - g_set_error (error, NM_CONFIG_ERROR, NM_CONFIG_ERROR_NO_MEMORY, - "Not enough memory to load config file %s", path); - return FALSE; - } - - g_key_file_set_list_separator (kf, ','); - if (g_key_file_load_from_file (kf, path, G_KEY_FILE_NONE, error)) { - config->path = g_strdup (path); - - /* CLI provided options override config file options */ - if (cli_plugins && strlen (cli_plugins)) - config->plugins = g_strsplit_set (cli_plugins, ",", 0); - else - config->plugins = g_key_file_get_string_list (kf, "main", "plugins", NULL, NULL); - - config->dhcp_client = g_key_file_get_value (kf, "main", "dhcp", NULL); - config->dns_plugins = g_key_file_get_string_list (kf, "main", "dns", NULL, NULL); - - if (cli_log_level && strlen (cli_log_level)) - config->log_level = g_strdup (cli_log_level); - else - config->log_level = g_key_file_get_value (kf, "logging", "level", NULL); - - if (cli_log_domains && strlen (cli_log_domains)) - config->log_domains = g_strdup (cli_log_domains); - else - config->log_domains = g_key_file_get_value (kf, "logging", "domains", NULL); - - if (cli_connectivity_uri && strlen (cli_connectivity_uri)) - config->connectivity_uri = g_strdup (cli_connectivity_uri); - else - config->connectivity_uri = g_key_file_get_value (kf, "connectivity", "uri", NULL); - - if (cli_connectivity_interval >= 0) - config->connectivity_interval = cli_connectivity_interval; - else - config->connectivity_interval = g_key_file_get_integer (kf, "connectivity", "interval", NULL); - - if (cli_connectivity_response && strlen (cli_connectivity_response)) - config->connectivity_response = g_strdup (cli_connectivity_response); - else - config->connectivity_response = g_key_file_get_value (kf, "connectivity", "response", NULL); - - success = TRUE; - } - - g_key_file_free (kf); - return success; -} - -NMConfig * -nm_config_new (const char *cli_config_path, - const char *cli_plugins, - const char *cli_log_level, - const char *cli_log_domains, - const char *cli_connectivity_uri, - const gint cli_connectivity_interval, - const char *cli_connectivity_response, - GError **error) -{ - NMConfig *config; - GError *local = NULL; - - config = g_malloc0 (sizeof (*config)); - - if (cli_config_path) { - /* Bad user-specific config file path is a hard error */ - if (!fill_from_file (config, cli_config_path, cli_plugins, cli_log_level, cli_log_domains, - cli_connectivity_uri, cli_connectivity_interval, cli_connectivity_response, - error)) { - nm_config_free (config); - return NULL; - } - return config; - } - - /* Even though we prefer NetworkManager.conf, we need to check the - * old nm-system-settings.conf first to preserve compat with older - * setups. In package managed systems dropping a NetworkManager.conf - * onto the system would make NM use it instead of nm-system-settings.conf, - * changing behavior during an upgrade. We don't want that. - */ - - /* Try deprecated nm-system-settings.conf first */ - if (fill_from_file (config, NM_OLD_SYSTEM_CONF_FILE, cli_plugins, cli_log_level, cli_log_domains, - cli_connectivity_uri, cli_connectivity_interval, cli_connectivity_response, - &local)) - return config; - - if (g_error_matches (local, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_NOT_FOUND) == FALSE) { - fprintf (stderr, "Default config file %s invalid: (%d) %s\n", - NM_OLD_SYSTEM_CONF_FILE, - local ? local->code : -1, - (local && local->message) ? local->message : "unknown"); - } - g_clear_error (&local); - - /* Try the standard config file location next */ - if (fill_from_file (config, NM_DEFAULT_SYSTEM_CONF_FILE, cli_plugins, cli_log_level, cli_log_domains, - cli_connectivity_uri, cli_connectivity_interval, cli_connectivity_response, - &local)) - return config; - - if (g_error_matches (local, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_NOT_FOUND) == FALSE) { - fprintf (stderr, "Default config file %s invalid: (%d) %s\n", - NM_DEFAULT_SYSTEM_CONF_FILE, - local ? local->code : -1, - (local && local->message) ? local->message : "unknown"); - g_propagate_error (error, local); - nm_config_free (config); - return NULL; - } - - /* If for some reason no config file exists, and NM wasn't given on on - * the command line, just use the default config file path. - */ - if (config->path == NULL) { - config->path = g_strdup (NM_DEFAULT_SYSTEM_CONF_FILE); - fprintf (stderr, "No config file found or given; using %s\n", - NM_DEFAULT_SYSTEM_CONF_FILE); - } - - /* ignore error if config file not found */ - g_clear_error (&local); - return config; -} - -void -nm_config_free (NMConfig *config) -{ - g_return_if_fail (config != NULL); - - g_free (config->path); - g_strfreev (config->plugins); - g_free (config->dhcp_client); - g_strfreev (config->dns_plugins); - g_free (config->log_level); - g_free (config->log_domains); - g_free (config->connectivity_uri); - g_free (config->connectivity_response); - memset (config, 0, sizeof (*config)); - g_free (config); -} - diff --git a/src/nm-config.h b/src/nm-config.h deleted file mode 100644 index 6c4206c1..00000000 --- a/src/nm-config.h +++ /dev/null @@ -1,59 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2011 Red Hat, Inc. - */ - -#ifndef NM_CONFIG_H -#define NM_CONFIG_H - -#include -#include - -typedef struct NMConfig NMConfig; - -typedef enum { - NM_CONFIG_ERROR_NO_MEMORY = 0, /*< nick=NoMemory >*/ -} NMConfigError; - -#define NM_CONFIG_ERROR (nm_config_error_quark ()) -GQuark nm_config_error_quark (void); - - -NMConfig *nm_config_new (const char *cli_config_path, - const char *cli_plugins, - const char *cli_log_level, - const char *cli_log_domains, - const char *cli_connectivity_check_uri, - const gint connectivity_check_interval, - const char *cli_connectivity_check_response, - GError **error); - -const char *nm_config_get_path (NMConfig *config); -const char **nm_config_get_plugins (NMConfig *config); -const char *nm_config_get_dhcp_client (NMConfig *config); -const char **nm_config_get_dns_plugins (NMConfig *config); -const char *nm_config_get_log_level (NMConfig *config); -const char *nm_config_get_log_domains (NMConfig *config); -const char *nm_config_get_connectivity_uri (NMConfig *config); -const guint nm_config_get_connectivity_interval (NMConfig *config); -const char *nm_config_get_connectivity_response (NMConfig *config); - -void nm_config_free (NMConfig *config); - -#endif /* NM_CONFIG_H */ - diff --git a/src/nm-connection-provider.c b/src/nm-connection-provider.c index 1c4b9a06..f6ee7454 100644 --- a/src/nm-connection-provider.c +++ b/src/nm-connection-provider.c @@ -14,6 +14,7 @@ */ #include "nm-connection-provider.h" +#include "nm-utils.h" GSList * nm_connection_provider_get_best_connections (NMConnectionProvider *self, @@ -40,24 +41,49 @@ nm_connection_provider_get_connections (NMConnectionProvider *self) return NULL; } -gboolean -nm_connection_provider_has_connections_loaded (NMConnectionProvider *self) -{ - g_return_val_if_fail (NM_IS_CONNECTION_PROVIDER (self), FALSE); - - g_assert (NM_CONNECTION_PROVIDER_GET_INTERFACE (self)->has_connections_loaded); - return NM_CONNECTION_PROVIDER_GET_INTERFACE (self)->has_connections_loaded (self); -} - +/** + * nm_connection_provider_add_connection: + * @self: the #NMConnectionProvider + * @connection: the source connection to create a new #NMSettingsConnection from + * @save_to_disk: %TRUE to save the connection to disk immediately, %FALSE to + * not save to disk + * @error: on return, a location to store any errors that may occur + * + * Creates a new #NMSettingsConnection for the given source @connection. + * The plugin owns the returned object and the caller must reference the object + * to continue using it. + * + * Returns: the new #NMSettingsConnection or %NULL + */ NMConnection * nm_connection_provider_add_connection (NMConnectionProvider *self, NMConnection *connection, + gboolean save_to_disk, GError **error) { g_return_val_if_fail (NM_IS_CONNECTION_PROVIDER (self), NULL); g_assert (NM_CONNECTION_PROVIDER_GET_INTERFACE (self)->add_connection); - return NM_CONNECTION_PROVIDER_GET_INTERFACE (self)->add_connection (self, connection, error); + return NM_CONNECTION_PROVIDER_GET_INTERFACE (self)->add_connection (self, connection, save_to_disk, error); +} + +/** + * nm_connection_provider_get_connection_by_uuid: + * @self: the #NMConnectionProvider + * @uuid: the UUID to search for + * + * Returns: the connection with the given @uuid, or %NULL + */ +NMConnection * +nm_connection_provider_get_connection_by_uuid (NMConnectionProvider *self, + const char *uuid) +{ + g_return_val_if_fail (NM_IS_CONNECTION_PROVIDER (self), NULL); + g_return_val_if_fail (uuid != NULL, NULL); + g_return_val_if_fail (nm_utils_is_uuid (uuid), NULL); + + g_assert (NM_CONNECTION_PROVIDER_GET_INTERFACE (self)->get_connection_by_uuid); + return NM_CONNECTION_PROVIDER_GET_INTERFACE (self)->get_connection_by_uuid (self, uuid); } /*****************************************************************************/ @@ -96,14 +122,6 @@ nm_connection_provider_init (gpointer g_iface) NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_OBJECT); - - g_signal_new (NM_CP_SIGNAL_CONNECTIONS_LOADED, - iface_type, - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMConnectionProvider, connections_loaded), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); } GType diff --git a/src/nm-connection-provider.h b/src/nm-connection-provider.h index 1502545b..5093d055 100644 --- a/src/nm-connection-provider.h +++ b/src/nm-connection-provider.h @@ -29,7 +29,6 @@ typedef struct _NMConnectionProvider NMConnectionProvider; #define NM_CP_SIGNAL_CONNECTION_ADDED "cp-connection-added" #define NM_CP_SIGNAL_CONNECTION_UPDATED "cp-connection-updated" #define NM_CP_SIGNAL_CONNECTION_REMOVED "cp-connection-removed" -#define NM_CP_SIGNAL_CONNECTIONS_LOADED "cp-connections-loaded" /** @@ -58,12 +57,14 @@ struct _NMConnectionProvider { const GSList * (*get_connections) (NMConnectionProvider *self); - gboolean (*has_connections_loaded) (NMConnectionProvider *self); - NMConnection * (*add_connection) (NMConnectionProvider *self, NMConnection *connection, + gboolean save_to_disk, GError **error); + NMConnection * (*get_connection_by_uuid) (NMConnectionProvider *self, + const char *uuid); + /* Signals */ void (*connection_added) (NMConnectionProvider *self, NMConnection *connection); @@ -71,11 +72,17 @@ struct _NMConnectionProvider { void (*connection_removed) (NMConnectionProvider *self, NMConnection *connection); - void (*connections_loaded) (NMConnectionProvider *self); }; GType nm_connection_provider_get_type (void); +/** + * nm_connection_provider_get: + * + * Returns: the global #NMConnectionProvider + */ +NMConnectionProvider *nm_connection_provider_get (void); + /** * nm_connection_provider_get_best_connections: * @self: the #NMConnectionProvider @@ -109,29 +116,21 @@ GSList *nm_connection_provider_get_best_connections (NMConnectionProvider *self, */ const GSList *nm_connection_provider_get_connections (NMConnectionProvider *self); -/** - * nm_connection_provider_has_connections_loaded: - * @self: the #NMConnectionProvider - * - * Returns: TRUE or FALSE indicating whether the connections of the provider are already - * loaded. If they are not yet loaded, the provider will not emit the signals - * NM_CP_SIGNAL_CONNECTION_ADDED, NM_CP_SIGNAL_CONNECTION_UPDATED and - * NM_CP_SIGNAL_CONNECTION_REMOVED until NM_CP_SIGNAL_CONNECTIONS_LOADED gets - * emited. - */ -gboolean nm_connection_provider_has_connections_loaded (NMConnectionProvider *self); - - /** * nm_connection_provider_add_connection: * @self: the #NMConnectionProvider * @connection: the connection to be added + * @save_to_disk: whether to store the connection on disk * @error: returns any error if adding fails * * returns: a newly added #NMConnection. */ NMConnection *nm_connection_provider_add_connection (NMConnectionProvider *self, NMConnection *connection, + gboolean save_to_disk, GError **error); +NMConnection *nm_connection_provider_get_connection_by_uuid (NMConnectionProvider *self, + const char *uuid); + #endif /* NM_CONNECTION_PROVIDER_H */ diff --git a/src/nm-connectivity.c b/src/nm-connectivity.c index 7e3bed99..5c6a43f6 100644 --- a/src/nm-connectivity.c +++ b/src/nm-connectivity.c @@ -28,7 +28,7 @@ #include "nm-connectivity.h" #include "nm-logging.h" -#include "nm-manager.h" +#include "nm-config.h" G_DEFINE_TYPE (NMConnectivity, nm_connectivity, G_TYPE_OBJECT) @@ -238,15 +238,18 @@ nm_connectivity_check_finish (NMConnectivity *self, NMConnectivity * -nm_connectivity_new (const gchar *check_uri, - guint check_interval, - const gchar *check_response) +nm_connectivity_new (void) { NMConnectivity *self; + NMConfig *config; + const char *check_response; + + config = nm_config_get (); + check_response = nm_config_get_connectivity_response (config); self = g_object_new (NM_TYPE_CONNECTIVITY, - NM_CONNECTIVITY_URI, check_uri, - NM_CONNECTIVITY_INTERVAL, check_interval, + NM_CONNECTIVITY_URI, nm_config_get_connectivity_uri (config), + NM_CONNECTIVITY_INTERVAL, nm_config_get_connectivity_interval (config), NM_CONNECTIVITY_RESPONSE, check_response ? check_response : DEFAULT_RESPONSE, NULL); g_return_val_if_fail (self != NULL, NULL); diff --git a/src/nm-connectivity.h b/src/nm-connectivity.h index 98a00884..04d0f2a3 100644 --- a/src/nm-connectivity.h +++ b/src/nm-connectivity.h @@ -50,9 +50,7 @@ typedef struct { GType nm_connectivity_get_type (void); -NMConnectivity *nm_connectivity_new (const gchar *check_uri, - guint check_interval, - const gchar *check_response); +NMConnectivity *nm_connectivity_new (void); void nm_connectivity_set_online (NMConnectivity *self, gboolean online); diff --git a/src/nm-dbus-manager.c b/src/nm-dbus-manager.c index 8552f559..f9269b61 100644 --- a/src/nm-dbus-manager.c +++ b/src/nm-dbus-manager.c @@ -15,15 +15,20 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright (C) 2006 - 2010 Red Hat, Inc. + * Copyright (C) 2006 - 2013 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. */ #include "config.h" +#include +#include +#include +#include + #include "NetworkManager.h" #include "nm-dbus-manager.h" -#include "nm-marshal.h" #include "nm-glib-compat.h" +#include "nm-properties-changed-signal.h" #include #include @@ -31,9 +36,14 @@ #include #include "nm-logging.h" +#define PRIV_SOCK_PATH NMRUNDIR "/private" +#define PRIV_SOCK_TAG "private" + enum { DBUS_CONNECTION_CHANGED = 0, NAME_OWNER_CHANGED, + PRIVATE_CONNECTION_NEW, + PRIVATE_CONNECTION_DISCONNECTED, NUMBER_OF_SIGNALS }; @@ -45,11 +55,17 @@ G_DEFINE_TYPE(NMDBusManager, nm_dbus_manager, G_TYPE_OBJECT) NM_TYPE_DBUS_MANAGER, \ NMDBusManagerPrivate)) +typedef struct _PrivateServer PrivateServer; + typedef struct { DBusConnection *connection; DBusGConnection *g_connection; + GHashTable *exported; gboolean started; + GSList *private_servers; + PrivateServer *priv_server; + DBusGProxy *proxy; guint proxy_destroy_id; @@ -59,35 +75,462 @@ typedef struct { static gboolean nm_dbus_manager_init_bus (NMDBusManager *self); static void nm_dbus_manager_cleanup (NMDBusManager *self, gboolean dispose); static void start_reconnection_timeout (NMDBusManager *self); +static void object_destroyed (NMDBusManager *self, gpointer object); NMDBusManager * nm_dbus_manager_get (void) { static NMDBusManager *singleton = NULL; + static gsize once = 0; - if (!singleton) { - singleton = NM_DBUS_MANAGER (g_object_new (NM_TYPE_DBUS_MANAGER, NULL)); + if (g_once_init_enter (&once)) { + singleton = (NMDBusManager *) g_object_new (NM_TYPE_DBUS_MANAGER, NULL); + g_assert (singleton); if (!nm_dbus_manager_init_bus (singleton)) start_reconnection_timeout (singleton); + g_once_init_leave (&once, 1); + } + return singleton; +} + +/**************************************************************/ + +struct _PrivateServer { + char *tag; + GQuark detail; + char *address; + DBusServer *server; + GHashTable *connections; + NMDBusManager *manager; +}; + +static DBusHandlerResult +private_server_message_filter (DBusConnection *conn, + DBusMessage *message, + void *data) +{ + PrivateServer *s = data; + + /* Clean up after the connection */ + if (dbus_message_is_signal (message, DBUS_INTERFACE_LOCAL, "Disconnected")) { + nm_log_dbg (LOGD_CORE, "(%s) closed connection %p on private socket.", + s->tag, conn); + + /* Emit this for the manager */ + g_signal_emit (s->manager, + signals[PRIVATE_CONNECTION_DISCONNECTED], + s->detail, + dbus_connection_get_g_connection (conn)); + + g_hash_table_remove (s->connections, conn); + + /* Let dbus-glib process the message too */ + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +static dbus_bool_t +allow_only_root (DBusConnection *connection, unsigned long uid, void *data) +{ + return uid == 0; +} + +static void +private_server_new_connection (DBusServer *server, + DBusConnection *conn, + gpointer user_data) +{ + PrivateServer *s = user_data; + static guint32 counter = 0; + char *sender; + + if (!dbus_connection_add_filter (conn, private_server_message_filter, s, NULL)) { + dbus_connection_close (conn); + return; + } + dbus_connection_set_unix_user_function (conn, allow_only_root, NULL, NULL); + dbus_connection_setup_with_g_main (conn, NULL); + + /* Fake a sender since private connections don't have one */ + sender = g_strdup_printf ("x:y:%d", counter++); + g_hash_table_insert (s->connections, dbus_connection_ref (conn), sender); + + nm_log_dbg (LOGD_CORE, "(%s) accepted connection %p on private socket.", s->tag, conn); + + /* Emit this for the manager */ + g_signal_emit (s->manager, + signals[PRIVATE_CONNECTION_NEW], + s->detail, + dbus_connection_get_g_connection (conn)); +} + +static void +private_server_dbus_connection_destroy (DBusConnection *conn) +{ + if (dbus_connection_get_is_connected (conn)) + dbus_connection_close (conn); + dbus_connection_unref (conn); +} + +static PrivateServer * +private_server_new (const char *path, + const char *tag, + NMDBusManager *manager) +{ + PrivateServer *s; + DBusServer *server; + DBusError error; + char *address; + + unlink (path); + address = g_strdup_printf ("unix:path=%s", path); + + nm_log_dbg (LOGD_CORE, "(%s) creating private socket %s.", tag, address); + + dbus_error_init (&error); + server = dbus_server_listen (address, &error); + if (!server) { + nm_log_warn (LOGD_CORE, "(%s) failed to set up private socket %s: %s", + tag, address, error.message); + dbus_error_free (&error); + return NULL; + } + + s = g_malloc0 (sizeof (*s)); + s->address = address; + s->server = server; + dbus_server_setup_with_g_main (s->server, NULL); + dbus_server_set_new_connection_function (s->server, private_server_new_connection, s, NULL); + + s->connections = g_hash_table_new_full (g_direct_hash, g_direct_equal, + (GDestroyNotify) private_server_dbus_connection_destroy, + g_free); + s->manager = manager; + s->tag = g_strdup (tag); + s->detail = g_quark_from_string (s->tag); + + return s; +} + +static void +private_server_free (gpointer ptr) +{ + PrivateServer *s = ptr; + + unlink (s->address); + g_free (s->address); + g_free (s->tag); + g_hash_table_destroy (s->connections); + dbus_server_unref (s->server); + memset (s, 0, sizeof (*s)); + g_free (s); +} + +void +nm_dbus_manager_private_server_register (NMDBusManager *self, + const char *path, + const char *tag) +{ + NMDBusManagerPrivate *priv = NM_DBUS_MANAGER_GET_PRIVATE (self); + PrivateServer *s; + GSList *iter; + +#if !HAVE_DBUS_GLIB_100 + g_assert_not_reached (); +#endif + + g_return_if_fail (self != NULL); + g_return_if_fail (path != NULL); + g_return_if_fail (tag != NULL); + + /* Only one instance per tag; but don't warn */ + for (iter = priv->private_servers; iter; iter = g_slist_next (iter)) { + s = iter->data; + if (g_strcmp0 (tag, s->tag) == 0) + return; + } + + s = private_server_new (path, tag, self); + if (s) + priv->private_servers = g_slist_append (priv->private_servers, s); +} + +static const char * +private_server_get_connection_owner (PrivateServer *s, DBusGConnection *connection) +{ + g_return_val_if_fail (s != NULL, NULL); + g_return_val_if_fail (connection != NULL, NULL); + + return g_hash_table_lookup (s->connections, dbus_g_connection_get_connection (connection)); +} + +/**************************************************************/ + +static gboolean +_bus_get_unix_pid (NMDBusManager *self, + const char *sender, + gulong *out_pid, + GError **error) +{ + guint32 unix_pid = G_MAXUINT32; + + if (!dbus_g_proxy_call_with_timeout (NM_DBUS_MANAGER_GET_PRIVATE (self)->proxy, + "GetConnectionUnixProcessID", 2000, error, + G_TYPE_STRING, sender, + G_TYPE_INVALID, + G_TYPE_UINT, &unix_pid, + G_TYPE_INVALID)) { + return FALSE; + } + + *out_pid = (gulong) unix_pid; + return TRUE; +} + +/** + * _get_caller_info_from_context(): + * + * Given a dbus-glib method invocation, or a DBusConnection + DBusMessage, + * return the sender and the UID of the sender. + */ +static gboolean +_get_caller_info (NMDBusManager *self, + DBusGMethodInvocation *context, + DBusConnection *connection, + DBusMessage *message, + char **out_sender, + gulong *out_uid, + gulong *out_pid) +{ + NMDBusManagerPrivate *priv = NM_DBUS_MANAGER_GET_PRIVATE (self); + DBusGConnection *gconn; + char *sender; + const char *priv_sender; + DBusError error; + GSList *iter; + + if (context) { + gconn = dbus_g_method_invocation_get_g_connection (context); + g_assert (gconn); + connection = dbus_g_connection_get_connection (gconn); + + /* only bus connections will have a sender */ + sender = dbus_g_method_get_sender (context); } else { - g_object_ref (singleton); + g_assert (message); + sender = g_strdup (dbus_message_get_sender (message)); + } + g_assert (connection); + + if (!sender) { + /* Might be a private connection, for which we fake a sender */ + for (iter = priv->private_servers; iter; iter = g_slist_next (iter)) { + PrivateServer *s = iter->data; + + priv_sender = g_hash_table_lookup (s->connections, connection); + if (priv_sender) { + if (out_uid) + *out_uid = 0; + if (out_sender) + *out_sender = g_strdup (priv_sender); + if (out_pid) { + if (!dbus_connection_get_unix_process_id (connection, out_pid)) + *out_pid = G_MAXULONG; + } + return TRUE; + } + } + return FALSE; } - g_assert (singleton); - return singleton; + /* Bus connections always have a sender */ + g_assert (sender); + if (out_uid) { + dbus_error_init (&error); + *out_uid = dbus_bus_get_unix_user (connection, sender, &error); + if (dbus_error_is_set (&error)) { + dbus_error_free (&error); + *out_uid = G_MAXULONG; + g_free (sender); + return FALSE; + } + } + + if (out_pid) { + if (!_bus_get_unix_pid (self, sender, out_pid, NULL)) { + *out_pid = G_MAXULONG; + g_free (sender); + return FALSE; + } + } + + if (out_sender) + *out_sender = g_strdup (sender); + + g_free (sender); + return TRUE; +} + +gboolean +nm_dbus_manager_get_caller_info (NMDBusManager *self, + DBusGMethodInvocation *context, + char **out_sender, + gulong *out_uid, + gulong *out_pid) +{ + return _get_caller_info (self, context, NULL, NULL, out_sender, out_uid, out_pid); +} + +gboolean +nm_dbus_manager_get_caller_info_from_message (NMDBusManager *self, + DBusConnection *connection, + DBusMessage *message, + char **out_sender, + gulong *out_uid, + gulong *out_pid) +{ + return _get_caller_info (self, NULL, connection, message, out_sender, out_uid, out_pid); } +gboolean +nm_dbus_manager_get_unix_user (NMDBusManager *self, + const char *sender, + gulong *out_uid) +{ + NMDBusManagerPrivate *priv = NM_DBUS_MANAGER_GET_PRIVATE (self); + GSList *iter; + DBusError error; + + g_return_val_if_fail (sender != NULL, FALSE); + g_return_val_if_fail (out_uid != NULL, FALSE); + + /* Check if it's a private connection sender, which we fake */ + for (iter = priv->private_servers; iter; iter = g_slist_next (iter)) { + PrivateServer *s = iter->data; + GHashTableIter hiter; + const char *priv_sender; + + g_hash_table_iter_init (&hiter, s->connections); + while (g_hash_table_iter_next (&hiter, NULL, (gpointer) &priv_sender)) { + if (g_strcmp0 (sender, priv_sender) == 0) { + *out_uid = 0; + return TRUE; + } + } + } + + /* Otherwise, a bus connection */ + dbus_error_init (&error); + *out_uid = dbus_bus_get_unix_user (priv->connection, sender, &error); + if (dbus_error_is_set (&error)) { + nm_log_warn (LOGD_CORE, "Failed to get unix user for dbus sender '%s': %s", + sender, error.message); + return FALSE; + } + + return TRUE; +} + +/**************************************************************/ + +#if HAVE_DBUS_GLIB_100 +static void +private_connection_new (NMDBusManager *self, DBusGConnection *connection) +{ + NMDBusManagerPrivate *priv = NM_DBUS_MANAGER_GET_PRIVATE (self); + GHashTableIter iter; + GObject *object; + const char *path; + + /* Register all exported objects on this private connection */ + g_hash_table_iter_init (&iter, priv->exported); + while (g_hash_table_iter_next (&iter, (gpointer) &object, (gpointer) &path)) { + dbus_g_connection_register_g_object (connection, path, object); + nm_log_dbg (LOGD_CORE, "(%s) registered %p (%s) at '%s' on private socket.", + PRIV_SOCK_TAG, object, G_OBJECT_TYPE_NAME (object), path); + } +} + +static void +private_connection_disconnected (NMDBusManager *self, DBusGConnection *connection) +{ + NMDBusManagerPrivate *priv = NM_DBUS_MANAGER_GET_PRIVATE (self); + const char *owner; + + owner = private_server_get_connection_owner (priv->priv_server, connection); + g_assert (owner); + + /* Fake a NameOwnerChanged to let listerners know this owner has quit */ + g_signal_emit (G_OBJECT (self), signals[NAME_OWNER_CHANGED], + 0, owner, owner, NULL); +} + +static void +private_server_setup (NMDBusManager *self) +{ + NMDBusManagerPrivate *priv = NM_DBUS_MANAGER_GET_PRIVATE (self); + + /* Skip this step if this is just a test program */ + if (g_test_initialized ()) + return; + + /* Set up our main private DBus socket */ + if (mkdir (NMRUNDIR, 0700) == -1) { + if (errno != EEXIST) + nm_log_warn (LOGD_CORE, "Error creating directory \"%s\": %d (%s)", NMRUNDIR, errno, g_strerror (errno)); + } + priv->priv_server = private_server_new (PRIV_SOCK_PATH, PRIV_SOCK_TAG, self); + if (priv->priv_server) { + priv->private_servers = g_slist_append (priv->private_servers, priv->priv_server); + + g_signal_connect (self, + NM_DBUS_MANAGER_PRIVATE_CONNECTION_NEW "::" PRIV_SOCK_TAG, + (GCallback) private_connection_new, + NULL); + g_signal_connect (self, + NM_DBUS_MANAGER_PRIVATE_CONNECTION_DISCONNECTED "::" PRIV_SOCK_TAG, + (GCallback) private_connection_disconnected, + NULL); + } +} +#endif /* HAVE_DBUS_GLIB_100 */ + static void nm_dbus_manager_init (NMDBusManager *self) { + NMDBusManagerPrivate *priv = NM_DBUS_MANAGER_GET_PRIVATE (self); + + priv->exported = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free); + +#if HAVE_DBUS_GLIB_100 + private_server_setup (self); +#endif } static void nm_dbus_manager_dispose (GObject *object) { - NMDBusManagerPrivate *priv = NM_DBUS_MANAGER_GET_PRIVATE (object); + NMDBusManager *self = NM_DBUS_MANAGER (object); + NMDBusManagerPrivate *priv = NM_DBUS_MANAGER_GET_PRIVATE (self); + GHashTableIter iter; + GObject *exported; - nm_dbus_manager_cleanup (NM_DBUS_MANAGER (object), TRUE); + if (priv->exported) { + g_hash_table_iter_init (&iter, priv->exported); + while (g_hash_table_iter_next (&iter, (gpointer) &exported, NULL)) + g_object_weak_unref (exported, (GWeakNotify) object_destroyed, self); + + g_hash_table_destroy (priv->exported); + priv->exported = NULL; + } + + g_slist_free_full (priv->private_servers, private_server_free); + priv->private_servers = NULL; + priv->priv_server = NULL; + + nm_dbus_manager_cleanup (self, TRUE); if (priv->reconnect_id) { g_source_remove (priv->reconnect_id); @@ -102,6 +545,8 @@ nm_dbus_manager_class_init (NMDBusManagerClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); + g_type_class_add_private (klass, sizeof (NMDBusManagerPrivate)); + object_class->dispose = nm_dbus_manager_dispose; signals[DBUS_CONNECTION_CHANGED] = @@ -109,7 +554,7 @@ nm_dbus_manager_class_init (NMDBusManagerClass *klass) G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NMDBusManagerClass, dbus_connection_changed), - NULL, NULL, _nm_marshal_VOID__POINTER, + NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_POINTER); signals[NAME_OWNER_CHANGED] = @@ -117,10 +562,24 @@ nm_dbus_manager_class_init (NMDBusManagerClass *klass) G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NMDBusManagerClass, name_owner_changed), - NULL, NULL, _nm_marshal_VOID__STRING_STRING_STRING, + NULL, NULL, NULL, G_TYPE_NONE, 3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); - g_type_class_add_private (klass, sizeof (NMDBusManagerPrivate)); + signals[PRIVATE_CONNECTION_NEW] = + g_signal_new (NM_DBUS_MANAGER_PRIVATE_CONNECTION_NEW, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, + G_STRUCT_OFFSET (NMDBusManagerClass, private_connection_new), + NULL, NULL, NULL, + G_TYPE_NONE, 1, G_TYPE_POINTER); + + signals[PRIVATE_CONNECTION_DISCONNECTED] = + g_signal_new (NM_DBUS_MANAGER_PRIVATE_CONNECTION_DISCONNECTED, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, + G_STRUCT_OFFSET (NMDBusManagerClass, private_connection_disconnected), + NULL, NULL, NULL, + G_TYPE_NONE, 1, G_TYPE_POINTER); } @@ -195,6 +654,9 @@ nm_dbus_manager_get_name_owner (NMDBusManager *self, if (error) g_return_val_if_fail (*error == NULL, NULL); + if (!NM_DBUS_MANAGER_GET_PRIVATE (self)->proxy) + return NULL; + if (!dbus_g_proxy_call_with_timeout (NM_DBUS_MANAGER_GET_PRIVATE (self)->proxy, "GetNameOwner", 2000, error, G_TYPE_STRING, name, @@ -217,6 +679,9 @@ nm_dbus_manager_name_has_owner (NMDBusManager *self, g_return_val_if_fail (NM_IS_DBUS_MANAGER (self), FALSE); g_return_val_if_fail (name != NULL, FALSE); + if (!NM_DBUS_MANAGER_GET_PRIVATE (self)->proxy) + return FALSE; + if (!dbus_g_proxy_call (NM_DBUS_MANAGER_GET_PRIVATE (self)->proxy, "NameHasOwner", &err, G_TYPE_STRING, name, @@ -262,7 +727,6 @@ static gboolean nm_dbus_manager_init_bus (NMDBusManager *self) { NMDBusManagerPrivate *priv = NM_DBUS_MANAGER_GET_PRIVATE (self); - GError *err = NULL; if (priv->connection) { nm_log_warn (LOGD_CORE, "DBus Manager already has a valid connection."); @@ -271,12 +735,14 @@ nm_dbus_manager_init_bus (NMDBusManager *self) dbus_connection_set_change_sigpipe (TRUE); - priv->g_connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &err); + priv->g_connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, NULL); if (!priv->g_connection) { - nm_log_err (LOGD_CORE, "Could not get the system bus. Make sure " - "the message bus daemon is running! Message: %s", - err->message); - g_error_free (err); + /* Log with 'info' severity; there won't be a bus daemon in minimal + * environments (eg, initrd) where we only want to use the private + * socket. + */ + nm_log_info (LOGD_CORE, "Could not connect to the system bus; only the " + "private D-Bus socket will be available."); return FALSE; } @@ -321,6 +787,10 @@ nm_dbus_manager_start_service (NMDBusManager *self) return FALSE; } + /* Pointless to request a name when we aren't connected to the bus */ + if (!priv->proxy) + return FALSE; + if (!dbus_g_proxy_call (priv->proxy, "RequestName", &err, G_TYPE_STRING, NM_DBUS_SERVICE, G_TYPE_UINT, DBUS_NAME_FLAG_DO_NOT_QUEUE, @@ -358,3 +828,149 @@ nm_dbus_manager_get_connection (NMDBusManager *self) return NM_DBUS_MANAGER_GET_PRIVATE (self)->g_connection; } + +static void +object_destroyed (NMDBusManager *self, gpointer object) +{ + g_hash_table_remove (NM_DBUS_MANAGER_GET_PRIVATE (self)->exported, object); +} + +void +nm_dbus_manager_register_exported_type (NMDBusManager *self, + GType object_type, + const DBusGObjectInfo *info) +{ + const char *properties_info, *dbus_name, *gobject_name, *tmp_access; + + dbus_g_object_type_install_info (object_type, info); + if (!info->exported_properties) + return; + + properties_info = info->exported_properties; + while (*properties_info) { + /* The format is: "interface\0DBusPropertyName\0gobject_property_name\0access\0" */ + dbus_name = strchr (properties_info, '\0') + 1; + gobject_name = strchr (dbus_name, '\0') + 1; + tmp_access = strchr (gobject_name, '\0') + 1; + properties_info = strchr (tmp_access, '\0') + 1; + + /* Note that nm-properties-changed-signal takes advantage of the + * fact that @dbus_name and @gobject_name are static data that won't + * ever be freed. + */ + nm_properties_changed_signal_add_property (object_type, dbus_name, gobject_name); + } +} + +void +nm_dbus_manager_register_object (NMDBusManager *self, + const char *path, + gpointer object) +{ + NMDBusManagerPrivate *priv = NM_DBUS_MANAGER_GET_PRIVATE (self); + GHashTableIter iter; + DBusConnection *connection; + + g_assert (G_IS_OBJECT (object)); + + g_warn_if_fail (g_hash_table_lookup (priv->exported, object) == NULL); + g_hash_table_insert (priv->exported, G_OBJECT (object), g_strdup (path)); + + if (priv->g_connection) + dbus_g_connection_register_g_object (priv->g_connection, path, G_OBJECT (object)); + + if (priv->priv_server) { + g_hash_table_iter_init (&iter, priv->priv_server->connections); + while (g_hash_table_iter_next (&iter, (gpointer) &connection, NULL)) { + dbus_g_connection_register_g_object (dbus_connection_get_g_connection (connection), + path, + G_OBJECT (object)); + } + } + + g_object_weak_ref (G_OBJECT (object), (GWeakNotify) object_destroyed, self); +} + +void +nm_dbus_manager_unregister_object (NMDBusManager *self, gpointer object) +{ + NMDBusManagerPrivate *priv = NM_DBUS_MANAGER_GET_PRIVATE (self); + GHashTableIter iter; + DBusConnection *connection; + + g_assert (G_IS_OBJECT (object)); + + g_hash_table_remove (NM_DBUS_MANAGER_GET_PRIVATE (self)->exported, G_OBJECT (object)); + g_object_weak_unref (G_OBJECT (object), (GWeakNotify) object_destroyed, self); + + if (priv->g_connection) + dbus_g_connection_unregister_g_object (priv->g_connection, G_OBJECT (object)); + + if (priv->priv_server) { + g_hash_table_iter_init (&iter, priv->priv_server->connections); + while (g_hash_table_iter_next (&iter, (gpointer) &connection, NULL)) { + dbus_g_connection_unregister_g_object (dbus_connection_get_g_connection (connection), + G_OBJECT (object)); + } + } +} + +/** + * nm_dbus_manager_new_proxy: + * @self: the #NMDBusManager + * @context: the method call context this proxy should be created + * @name: any name on the message bus + * @path: name of the object instance to call methods on + * @iface: name of the interface to call methods on + * + * Creates a new proxy for a name on a given bus. Since the process which + * called the D-Bus method could be coming from a private connection or the + * system bus connection, differnet proxies must be created for each case. This + * function abstracts that. + * + * Returns: a #DBusGProxy capable of calling D-Bus methods of the calling process + */ +DBusGProxy * +nm_dbus_manager_new_proxy (NMDBusManager *self, + DBusGMethodInvocation *context, + const char *name, + const char *path, + const char *iface) +{ + NMDBusManagerPrivate *priv = NM_DBUS_MANAGER_GET_PRIVATE (self); + DBusGConnection *connection; + GSList *iter; + const char *owner; + + connection = dbus_g_method_invocation_get_g_connection (context); + g_assert (connection); + + /* Might be a private connection, for which we fake a sender */ + for (iter = priv->private_servers; iter; iter = g_slist_next (iter)) { + PrivateServer *s = iter->data; + + owner = private_server_get_connection_owner (s, connection); + if (owner) { + g_assert_cmpstr (owner, ==, name); + return dbus_g_proxy_new_for_peer (connection, path, iface); + } + } + + return dbus_g_proxy_new_for_name (connection, name, path, iface); +} + +#if !HAVE_DBUS_GLIB_GMI_GET_CONNECTION +struct _HACKDBusGMethodInvocation { + DBusGConnection *connection; + /* ... */ +}; + +DBusGConnection * +dbus_g_method_invocation_get_g_connection (DBusGMethodInvocation *context) +{ + /* Evil hack; this method exists in dbus-glib >= 101, but if we don't + * have that, emulate it. + */ + return ((struct _HACKDBusGMethodInvocation *) context)->connection; +} +#endif /* HAVE_DBUS_GLIB_GMI_GET_CONNECTION */ diff --git a/src/nm-dbus-manager.h b/src/nm-dbus-manager.h index 83ffa966..7895a203 100644 --- a/src/nm-dbus-manager.h +++ b/src/nm-dbus-manager.h @@ -22,6 +22,7 @@ #ifndef __NM_DBUS_MANAGER_H__ #define __NM_DBUS_MANAGER_H__ +#include #include #include #include @@ -39,8 +40,10 @@ typedef gboolean (* NMDBusSignalHandlerFunc) (DBusConnection * connection, #define NM_IS_DBUS_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), NM_TYPE_DBUS_MANAGER)) #define NM_DBUS_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), NM_TYPE_DBUS_MANAGER, NMDBusManagerClass)) -#define NM_DBUS_MANAGER_DBUS_CONNECTION_CHANGED "dbus-connection-changed" -#define NM_DBUS_MANAGER_NAME_OWNER_CHANGED "name-owner-changed" +#define NM_DBUS_MANAGER_DBUS_CONNECTION_CHANGED "dbus-connection-changed" +#define NM_DBUS_MANAGER_NAME_OWNER_CHANGED "name-owner-changed" +#define NM_DBUS_MANAGER_PRIVATE_CONNECTION_NEW "private-connection-new" +#define NM_DBUS_MANAGER_PRIVATE_CONNECTION_DISCONNECTED "private-connection-disconnected" typedef struct { GObject parent; @@ -57,6 +60,12 @@ typedef struct { const char *name, const char *old_owner, const char *new_owner); + + void (*private_connection_new) (NMDBusManager *mgr, + DBusGConnection *connection); + + void (*private_connection_disconnected) (NMDBusManager *mgr, + DBusGConnection *connection); } NMDBusManagerClass; GType nm_dbus_manager_get_type (void); @@ -75,6 +84,47 @@ gboolean nm_dbus_manager_name_has_owner (NMDBusManager *self, DBusConnection * nm_dbus_manager_get_dbus_connection (NMDBusManager *self); DBusGConnection * nm_dbus_manager_get_connection (NMDBusManager *self); +gboolean nm_dbus_manager_get_caller_info (NMDBusManager *self, + DBusGMethodInvocation *context, + char **out_sender, + gulong *out_uid, + gulong *out_pid); + +gboolean nm_dbus_manager_get_unix_user (NMDBusManager *self, + const char *sender, + gulong *out_uid); + +gboolean nm_dbus_manager_get_caller_info_from_message (NMDBusManager *self, + DBusConnection *connection, + DBusMessage *message, + char **out_sender, + gulong *out_uid, + gulong *out_pid); + +void nm_dbus_manager_register_exported_type (NMDBusManager *self, + GType object_type, + const DBusGObjectInfo *info); + +void nm_dbus_manager_register_object (NMDBusManager *self, + const char *path, + gpointer object); + +void nm_dbus_manager_unregister_object (NMDBusManager *self, gpointer object); + +void nm_dbus_manager_private_server_register (NMDBusManager *self, + const char *path, + const char *tag); + +DBusGProxy *nm_dbus_manager_new_proxy (NMDBusManager *self, + DBusGMethodInvocation *context, + const char *name, + const char *path, + const char *iface); + +#if !HAVE_DBUS_GLIB_GMI_GET_CONNECTION +DBusGConnection *dbus_g_method_invocation_get_g_connection (DBusGMethodInvocation *context); +#endif + G_END_DECLS #endif /* __NM_DBUS_MANAGER_H__ */ diff --git a/src/nm-dcb.c b/src/nm-dcb.c new file mode 100644 index 00000000..3bdbf7d5 --- /dev/null +++ b/src/nm-dcb.c @@ -0,0 +1,426 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2013 Red Hat, Inc. + */ + +#include +#include +#include + +#include +#include "nm-dcb.h" +#include "nm-platform.h" +#include "NetworkManagerUtils.h" +#include "nm-posix-signals.h" +#include "nm-logging.h" + +GQuark +nm_dcb_error_quark (void) +{ + static GQuark ret = 0; + + if (ret == 0) + ret = g_quark_from_static_string ("nm-dcb-error"); + return ret; +} + +static const char *helper_names[] = { "dcbtool", "fcoeadm" }; + +gboolean +do_helper (const char *iface, + guint which, + DcbFunc run_func, + gpointer user_data, + GError **error, + const char *fmt, + ...) +{ + char **argv = NULL, **split = NULL, *cmdline, *errmsg = NULL; + gboolean success = FALSE; + guint i, u; + va_list args; + + g_return_val_if_fail (fmt != NULL, FALSE); + + va_start (args, fmt); + cmdline = g_strdup_vprintf (fmt, args); + va_end (args); + + split = g_strsplit_set (cmdline, " ", 0); + if (!split) { + g_set_error (error, NM_DCB_ERROR, NM_DCB_ERROR_INTERNAL, + "failure parsing %s command line", helper_names[which]); + goto out; + } + + /* Allocate space for path, custom arg, interface name, arguments, and NULL */ + i = u = 0; + argv = g_new0 (char *, g_strv_length (split) + 4); + argv[i++] = NULL; /* Placeholder for dcbtool path */ + if (which == DCBTOOL) { + argv[i++] = "sc"; + argv[i++] = (char *) iface; + } + while (u < g_strv_length (split)) + argv[i++] = split[u++]; + argv[i++] = NULL; + success = run_func (argv, which, user_data, error); + if (!success && error) + g_assert (*error); + +out: + if (split) + g_strfreev (split); + g_free (argv); + g_free (cmdline); + g_free (errmsg); + return success; +} + +gboolean +_dcb_enable (const char *iface, + gboolean enable, + DcbFunc run_func, + gpointer user_data, + GError **error) +{ + if (enable) + return do_helper (iface, DCBTOOL, run_func, user_data, error, "dcb on"); + else + return do_helper (iface, DCBTOOL, run_func, user_data, error, "dcb off"); +} + +#define SET_FLAGS(f, tag) \ +G_STMT_START { \ + if (!do_helper (iface, DCBTOOL, run_func, user_data, error, tag " e:%c a:%c w:%c", \ + f & NM_SETTING_DCB_FLAG_ENABLE ? '1' : '0', \ + f & NM_SETTING_DCB_FLAG_ADVERTISE ? '1' : '0', \ + f & NM_SETTING_DCB_FLAG_WILLING ? '1' : '0')) \ + return FALSE; \ +} G_STMT_END + +#define SET_APP(f, s, tag) \ +G_STMT_START { \ + gint prio = nm_setting_dcb_get_app_##tag##_priority (s); \ + \ + SET_FLAGS (f, "app:" #tag); \ + if ((f & NM_SETTING_DCB_FLAG_ENABLE) && (prio >= 0)) { \ + if (!do_helper (iface, DCBTOOL, run_func, user_data, error, "app:" #tag " appcfg:%02x", (1 << prio))) \ + return FALSE; \ + } \ +} G_STMT_END + +gboolean +_dcb_setup (const char *iface, + NMSettingDcb *s_dcb, + DcbFunc run_func, + gpointer user_data, + GError **error) +{ + NMSettingDcbFlags flags; + guint i; + + g_assert (s_dcb); + + /* FCoE */ + flags = nm_setting_dcb_get_app_fcoe_flags (s_dcb); + SET_APP (flags, s_dcb, fcoe); + + /* iSCSI */ + flags = nm_setting_dcb_get_app_iscsi_flags (s_dcb); + SET_APP (flags, s_dcb, iscsi); + + /* FIP */ + flags = nm_setting_dcb_get_app_fip_flags (s_dcb); + SET_APP (flags, s_dcb, fip); + + /* Priority Flow Control */ + flags = nm_setting_dcb_get_priority_flow_control_flags (s_dcb); + SET_FLAGS (flags, "pfc"); + if (flags & NM_SETTING_DCB_FLAG_ENABLE) { + char buf[10]; + + for (i = 0; i < 8; i++) + buf[i] = nm_setting_dcb_get_priority_flow_control (s_dcb, i) ? '1' : '0'; + buf[i] = 0; + if (!do_helper (iface, DCBTOOL, run_func, user_data, error, "pfc pfcup:%s", buf)) + return FALSE; + } + + /* Priority Groups */ + flags = nm_setting_dcb_get_priority_group_flags (s_dcb); + if (flags & NM_SETTING_DCB_FLAG_ENABLE) { + GString *s; + gboolean success; + guint id; + + s = g_string_sized_new (150); + + g_string_append_printf (s, "pg e:1 a:%c w:%c", + flags & NM_SETTING_DCB_FLAG_ADVERTISE ? '1' : '0', + flags & NM_SETTING_DCB_FLAG_WILLING ? '1' : '0'); + + /* Priority Groups */ + g_string_append (s, " pgid:"); + for (i = 0; i < 8; i++) { + id = nm_setting_dcb_get_priority_group_id (s_dcb, i); + g_assert (id < 8 || id == 15); + g_string_append_c (s, (id < 8) ? ('0' + id) : 'f'); + } + + /* Priority Group Bandwidth */ + g_string_append_printf (s, " pgpct:%u,%u,%u,%u,%u,%u,%u,%u", + nm_setting_dcb_get_priority_group_bandwidth (s_dcb, 0), + nm_setting_dcb_get_priority_group_bandwidth (s_dcb, 1), + nm_setting_dcb_get_priority_group_bandwidth (s_dcb, 2), + nm_setting_dcb_get_priority_group_bandwidth (s_dcb, 3), + nm_setting_dcb_get_priority_group_bandwidth (s_dcb, 4), + nm_setting_dcb_get_priority_group_bandwidth (s_dcb, 5), + nm_setting_dcb_get_priority_group_bandwidth (s_dcb, 6), + nm_setting_dcb_get_priority_group_bandwidth (s_dcb, 7)); + + /* Priority Bandwidth */ + g_string_append_printf (s, " uppct:%u,%u,%u,%u,%u,%u,%u,%u", + nm_setting_dcb_get_priority_bandwidth (s_dcb, 0), + nm_setting_dcb_get_priority_bandwidth (s_dcb, 1), + nm_setting_dcb_get_priority_bandwidth (s_dcb, 2), + nm_setting_dcb_get_priority_bandwidth (s_dcb, 3), + nm_setting_dcb_get_priority_bandwidth (s_dcb, 4), + nm_setting_dcb_get_priority_bandwidth (s_dcb, 5), + nm_setting_dcb_get_priority_bandwidth (s_dcb, 6), + nm_setting_dcb_get_priority_bandwidth (s_dcb, 7)); + + /* Strict Bandwidth */ + g_string_append (s, " strict:"); + for (i = 0; i < 8; i++) + g_string_append_c (s, nm_setting_dcb_get_priority_strict_bandwidth (s_dcb, i) ? '1' : '0'); + + /* Priority Traffic Class */ + g_string_append (s, " up2tc:"); + for (i = 0; i < 8; i++) { + id = nm_setting_dcb_get_priority_traffic_class (s_dcb, i); + g_assert (id < 8); + g_string_append_c (s, '0' + id); + } + + success = do_helper (iface, DCBTOOL, run_func, user_data, error, "%s", s->str); + g_string_free (s, TRUE); + if (!success) + return FALSE; + } else { + /* Ignore disable failure since lldpad <= 0.9.46 does not support disabling + * priority groups without specifying an entire PG config. + */ + (void) do_helper (iface, DCBTOOL, run_func, user_data, error, "pg e:0"); + } + + return TRUE; +} + +gboolean +_dcb_cleanup (const char *iface, + DcbFunc run_func, + gpointer user_data, + GError **error) +{ + const char *cmds[] = { + "app:fcoe e:0", + "app:iscsi e:0", + "app:fip e:0", + "pfc e:0", + "pg e:0", + NULL + }; + const char **iter = cmds; + gboolean success = TRUE; + + /* Turn everything off and return first error we get (if any) */ + while (iter && *iter) { + if (!do_helper (iface, DCBTOOL, run_func, user_data, success ? error : NULL, "%s", *iter)) + success = FALSE; + iter++; + } + + if (!_dcb_enable (iface, FALSE, run_func, user_data, success ? error : NULL)) + success = FALSE; + + return success; +} + +gboolean +_fcoe_setup (const char *iface, + NMSettingDcb *s_dcb, + DcbFunc run_func, + gpointer user_data, + GError **error) +{ + NMSettingDcbFlags flags; + + g_assert (s_dcb); + + flags = nm_setting_dcb_get_app_fcoe_flags (s_dcb); + if (flags & NM_SETTING_DCB_FLAG_ENABLE) { + const char *mode = nm_setting_dcb_get_app_fcoe_mode (s_dcb); + + if (!do_helper (NULL, FCOEADM, run_func, user_data, error, "-m %s -c %s", mode, iface)) + return FALSE; + } else { + if (!do_helper (NULL, FCOEADM, run_func, user_data, error, "-d %s", iface)) + return FALSE; + } + + return TRUE; +} + +gboolean +_fcoe_cleanup (const char *iface, + DcbFunc run_func, + gpointer user_data, + GError **error) +{ + return do_helper (NULL, FCOEADM, run_func, user_data, error, "-d %s", iface); +} + + +static const char *dcbpaths[] = { + "/sbin/dcbtool", + "/usr/sbin/dcbtool", + "/usr/local/sbin/dcbtool", + NULL +}; +static const char *fcoepaths[] = { + "/sbin/fcoeadm", + "/usr/sbin/fcoeadm", + "/usr/local/sbin/fcoeadm", + NULL +}; + + +static gboolean +run_helper (char **argv, guint which, gpointer user_data, GError **error) +{ + static const char *helper_path[2] = { NULL, NULL }; + int exit_status = 0; + gboolean success; + char *errmsg = NULL, *outmsg = NULL; + const char **iter; + char *cmdline; + + if (G_UNLIKELY (helper_path[which] == NULL)) { + iter = (which == DCBTOOL) ? dcbpaths : fcoepaths; + while (*iter) { + if (g_file_test (*iter, G_FILE_TEST_EXISTS)) + helper_path[which] = *iter; + iter++; + } + if (!helper_path[which]) { + g_set_error (error, NM_DCB_ERROR, NM_DCB_ERROR_HELPER_NOT_FOUND, + "%s not found", + which == DCBTOOL ? "dcbtool" : "fcoadm"); + return FALSE; + } + } + + argv[0] = (char *) helper_path[which]; + cmdline = g_strjoinv (" ", argv); + nm_log_dbg (LOGD_DCB, "%s", cmdline); + + success = g_spawn_sync ("/", argv, NULL, 0 /*G_SPAWN_DEFAULT*/, + nm_unblock_posix_signals, NULL, + &outmsg, &errmsg, &exit_status, error); + /* Log any stderr output */ + if (success && WIFEXITED (exit_status) && WEXITSTATUS (exit_status) && (errmsg || outmsg)) { + gboolean ignore_error = FALSE; + + /* Ignore fcoeadm "success" errors like when FCoE is already set up */ + if (errmsg && strstr (errmsg, "Connection already created")) + ignore_error = TRUE; + + if (ignore_error == FALSE) { + nm_log_warn (LOGD_DCB, "'%s' failed: '%s'", + cmdline, (errmsg && strlen (errmsg)) ? errmsg : outmsg); + g_set_error (error, NM_DCB_ERROR, NM_DCB_ERROR_HELPER_FAILED, + "Failed to run '%s'", cmdline); + success = FALSE; + } + } + g_free (outmsg); + g_free (errmsg); + + g_free (cmdline); + return success; +} + +gboolean +nm_dcb_enable (const char *iface, gboolean enable, GError **error) +{ + return _dcb_enable (iface, enable, run_helper, GUINT_TO_POINTER (DCBTOOL), error); +} + +gboolean +nm_dcb_setup (const char *iface, NMSettingDcb *s_dcb, GError **error) +{ + gboolean success; + + success = _dcb_setup (iface, s_dcb, run_helper, GUINT_TO_POINTER (DCBTOOL), error); + if (success) + success = _fcoe_setup (iface, s_dcb, run_helper, GUINT_TO_POINTER (FCOEADM), error); + + return success; +} + +static void +carrier_wait (const char *iface, guint secs, gboolean up) +{ + int ifindex, count = secs * 10; + + g_return_if_fail (iface != NULL); + + ifindex = nm_platform_link_get_ifindex (iface); + if (ifindex > 0) { + /* To work around driver quirks and lldpad handling of carrier status, + * we must wait a short period of time to see if the carrier goes + * down, and then wait for the carrier to come back up again. Otherwise + * subsequent lldpad calls may fail with "Device not found, link down + * or DCB not enabled" errors. + */ + nm_log_dbg (LOGD_DCB, "(%s): cleanup waiting for carrier %s", + iface, up ? "up" : "down"); + g_usleep (G_USEC_PER_SEC / 4); + while (nm_platform_link_is_connected (ifindex) != up && count-- > 0) { + g_usleep (G_USEC_PER_SEC / 10); + nm_platform_link_refresh (ifindex); + } + } +} + +gboolean +nm_dcb_cleanup (const char *iface, GError **error) +{ + /* Ignore FCoE cleanup errors */ + _fcoe_cleanup (iface, run_helper, GUINT_TO_POINTER (FCOEADM), NULL); + + /* Must pause a bit to wait for carrier-up since disabling FCoE may + * cause the device to take the link down, making lldpad return errors. + */ + carrier_wait (iface, 2, FALSE); + carrier_wait (iface, 4, TRUE); + + return _dcb_cleanup (iface, run_helper, GUINT_TO_POINTER (DCBTOOL), error); +} + diff --git a/src/nm-dcb.h b/src/nm-dcb.h new file mode 100644 index 00000000..bfe5cedf --- /dev/null +++ b/src/nm-dcb.h @@ -0,0 +1,100 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2013 Red Hat, Inc. + */ + +#ifndef NM_DCB_H +#define NM_DCB_H + +#include +#include "nm-setting-dcb.h" + +/** + * NMDcbError: + * @NM_DCB_ERROR_UNKNOWN: unknown or unclassified error + * @NM_DCB_ERROR_INTERNAL: a internal programmer error + * @NM_DCB_ERROR_BAD_CONFIG: configuration was invalid + * @NM_DCB_ERROR_HELPER_NOT_FOUND: the required helper program was not found + * @NM_DCB_ERROR_HELPER_FAILED: the helper program failed + * + * NOTE: these errors are internal-use only and should never be used with D-Bus. + **/ +typedef enum { + NM_DCB_ERROR_UNKNOWN = 0, + NM_DCB_ERROR_INTERNAL, + NM_DCB_ERROR_BAD_CONFIG, + NM_DCB_ERROR_HELPER_NOT_FOUND, + NM_DCB_ERROR_HELPER_FAILED, +} NMDcbError; + +#define NM_DCB_ERROR (nm_dcb_error_quark ()) +GQuark nm_dcb_error_quark (void); +#define NM_TYPE_DCB_ERROR (nm_dcb_error_get_type ()) +GType nm_dcb_error_get_type (void); + + +gboolean nm_dcb_enable (const char *iface, gboolean enable, GError **error); +gboolean nm_dcb_setup (const char *iface, NMSettingDcb *s_dcb, GError **error); +gboolean nm_dcb_cleanup (const char *iface, GError **error); + +/* For testcases only! */ +typedef gboolean (*DcbFunc) (char **argv, + guint which, + gpointer user_data, + GError **error); + +#define DCBTOOL 0 +#define FCOEADM 1 + +gboolean do_helper (const char *iface, + guint which, + DcbFunc run_func, + gpointer user_data, + GError **error, + const char *fmt, + ...) G_GNUC_PRINTF(6, 7); + +gboolean _dcb_enable (const char *iface, + gboolean enable, + DcbFunc run_func, + gpointer user_data, + GError **error); + +gboolean _dcb_setup (const char *iface, + NMSettingDcb *s_dcb, + DcbFunc run_func, + gpointer user_data, + GError **error); + +gboolean _dcb_cleanup (const char *iface, + DcbFunc run_func, + gpointer user_data, + GError **error); + +gboolean _fcoe_setup (const char *iface, + NMSettingDcb *s_dcb, + DcbFunc run_func, + gpointer user_data, + GError **error); + +gboolean _fcoe_cleanup (const char *iface, + DcbFunc run_func, + gpointer user_data, + GError **error); + +#endif /* NM_DCB_H */ diff --git a/src/nm-device-adsl.c b/src/nm-device-adsl.c deleted file mode 100644 index db678d9f..00000000 --- a/src/nm-device-adsl.c +++ /dev/null @@ -1,851 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Pantelis Koukousoulas - */ - -#include - -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "nm-device-adsl.h" -#include "nm-device-private.h" -#include "nm-properties-changed-signal.h" -#include "NetworkManagerUtils.h" -#include "nm-logging.h" -#include "nm-enum-types.h" -#include "nm-system.h" -#include "nm-netlink-monitor.h" - -#include "ppp-manager/nm-ppp-manager.h" -#include "nm-setting-adsl.h" - -#include "nm-device-adsl-glue.h" - -G_DEFINE_TYPE (NMDeviceAdsl, nm_device_adsl, NM_TYPE_DEVICE) - -#define NM_DEVICE_ADSL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_ADSL, NMDeviceAdslPrivate)) - -#define NM_ADSL_ERROR (nm_adsl_error_quark ()) - -static GQuark -nm_adsl_error_quark (void) -{ - static GQuark quark = 0; - if (!quark) - quark = g_quark_from_static_string ("nm-adsl-error"); - return quark; -} - -/**********************************************/ - -typedef struct { - gboolean disposed; - gboolean carrier; - guint carrier_poll_id; - int atm_index; - - /* Watch for 'nas' interfaces going away */ - NMNetlinkMonitor *monitor; - guint netlink_id; - - /* PPP */ - NMPPPManager *ppp_manager; - - /* RFC 2684 bridging (PPPoE over ATM) */ - int brfd; - int nas_ifindex; - char * nas_ifname; - guint8 nas_hw_addr[ETH_ALEN]; -} NMDeviceAdslPrivate; - -enum { - PROPERTIES_CHANGED, - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -enum { - PROP_0, - PROP_CARRIER, - - LAST_PROP -}; - -/**************************************************************/ - -static guint32 -get_generic_capabilities (NMDevice *dev) -{ - guint32 caps = NM_DEVICE_CAP_NM_SUPPORTED; - caps |= NM_DEVICE_CAP_CARRIER_DETECT; - return caps; -} - -static gboolean -can_interrupt_activation (NMDevice *dev) -{ - NMDeviceAdsl *self = NM_DEVICE_ADSL (dev); - gboolean interrupt = FALSE; - - /* Devices that support carrier detect can interrupt activation - * if the link becomes inactive. - */ - if (NM_DEVICE_ADSL_GET_PRIVATE (self)->carrier == FALSE) - interrupt = TRUE; - - return interrupt; -} - -static gboolean -is_available (NMDevice *dev) -{ - NMDeviceAdsl *self = NM_DEVICE_ADSL (dev); - - /* Can't do anything if there isn't a carrier */ - if (!NM_DEVICE_ADSL_GET_PRIVATE (self)->carrier) - return FALSE; - - return TRUE; -} - -static gboolean -check_connection_compatible (NMDevice *device, - NMConnection *connection, - GError **error) -{ - NMSettingAdsl *s_adsl; - const char *protocol; - - if (!nm_connection_is_type (connection, NM_SETTING_ADSL_SETTING_NAME)) { - g_set_error (error, - NM_ADSL_ERROR, NM_ADSL_ERROR_CONNECTION_NOT_ADSL, - "The connection was not an ADSL connection."); - return FALSE; - } - - s_adsl = nm_connection_get_setting_adsl (connection); - if (!s_adsl) { - g_set_error (error, - NM_ADSL_ERROR, NM_ADSL_ERROR_CONNECTION_INVALID, - "The connection was not a valid ADSL connection."); - return FALSE; - } - - /* FIXME: we don't yet support IPoATM */ - protocol = nm_setting_adsl_get_protocol (s_adsl); - if (g_strcmp0 (protocol, NM_SETTING_ADSL_PROTOCOL_IPOATM) == 0) { - g_set_error (error, - NM_ADSL_ERROR, NM_ADSL_ERROR_CONNECTION_INVALID, - "IPoATM connections are not yet supported."); - return FALSE; - } - - return TRUE; -} - -static gboolean -complete_connection (NMDevice *device, - NMConnection *connection, - const char *specific_object, - const GSList *existing_connections, - GError **error) -{ - NMSettingAdsl *s_adsl; - - /* - * We can't telepathically figure out the username, so if - * it wasn't given, we can't complete the connection. - */ - s_adsl = nm_connection_get_setting_adsl (connection); - if (s_adsl && !nm_setting_verify (NM_SETTING (s_adsl), NULL, error)) - return FALSE; - - nm_utils_complete_generic (connection, - NM_SETTING_ADSL_SETTING_NAME, - existing_connections, - _("ADSL connection %d"), - NULL, - FALSE); /* No IPv6 yet by default */ - - - return TRUE; -} - -static NMConnection * -get_best_auto_connection (NMDevice *dev, - GSList *connections, - char **specific_object) -{ - GSList *iter; - - for (iter = connections; iter; iter = g_slist_next (iter)) { - NMConnection *connection = NM_CONNECTION (iter->data); - - if (!nm_connection_is_type (connection, NM_SETTING_ADSL_SETTING_NAME)) - continue; - - if (nm_connection_get_setting_adsl (connection)) - return connection; - } - return NULL; -} - -/**************************************************************/ - -static void -set_nas_iface (NMDeviceAdsl *self, int idx, const char *name) -{ - NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (self); - gsize addrlen; - - g_return_if_fail (name != NULL); - - g_warn_if_fail (priv->nas_ifindex <= 0); - if (idx > 0) - priv->nas_ifindex = idx; - else - priv->nas_ifindex = nm_netlink_iface_to_index (name); - g_warn_if_fail (priv->nas_ifindex > 0); - - g_warn_if_fail (priv->nas_ifname == NULL); - priv->nas_ifname = g_strdup (name); - - /* Update NAS interface's MAC address */ - addrlen = nm_device_read_hwaddr (NM_DEVICE (self), - priv->nas_hw_addr, - sizeof (priv->nas_hw_addr), - NULL); - g_warn_if_fail (addrlen == sizeof (priv->nas_hw_addr)); -} - -static gboolean -br2684_create_iface (NMDeviceAdsl *self, NMSettingAdsl *s_adsl) -{ - NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (self); - const char *iface = nm_device_get_iface (NM_DEVICE (self)); - struct atm_newif_br2684 ni; - int err, fd; - gboolean success = FALSE; - guint num = 0; - - g_return_val_if_fail (s_adsl != NULL, FALSE); - - fd = socket (PF_ATMPVC, SOCK_DGRAM, ATM_AAL5); - if (fd < 0) { - nm_log_err (LOGD_ADSL, "(%s): failed to open ATM control socket (%d)", - iface, errno); - return FALSE; - } - - memset (&ni, 0, sizeof (ni)); - ni.backend_num = ATM_BACKEND_BR2684; - ni.media = BR2684_MEDIA_ETHERNET; - ni.mtu = 1500; - - /* Loop attempting to create an interface that doesn't exist yet. The - * kernel can create one for us automatically, but due to API issues it - * cannot return that name to us. Since we want to know the name right - * away, just brute-force it. - */ - while (num < 10000) { - memset (&ni.ifname, 0, sizeof (ni.ifname)); - snprintf (ni.ifname, sizeof (ni.ifname), "nas%d", num); - - err = ioctl (fd, ATM_NEWBACKENDIF, &ni); - if (err == 0) { - set_nas_iface (self, -1, ni.ifname); - nm_log_info (LOGD_ADSL, "(%s): using NAS interface %s (%d)", - iface, priv->nas_ifname, priv->nas_ifindex); - success = TRUE; - break; - } else if (errno == -EEXIST) { - /* Try again */ - num++; - } else { - nm_log_warn (LOGD_ADSL, "(%s): failed to create br2684 interface (%d)", - iface, errno); - break; - } - } - - close (fd); - return success; -} - -static gboolean -br2684_assign_vcc (NMDeviceAdsl *self, NMSettingAdsl *s_adsl) -{ - NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (self); - const char *iface = nm_device_get_iface (NM_DEVICE (self)); - struct sockaddr_atmpvc addr; - struct atm_backend_br2684 be; - struct atm_qos qos; - int err, bufsize = 8192; - const char *encapsulation; - gboolean is_llc; - - g_return_val_if_fail (priv->brfd == -1, FALSE); - g_return_val_if_fail (priv->nas_ifname != NULL, FALSE); - - priv->brfd = socket (PF_ATMPVC, SOCK_DGRAM, ATM_AAL5); - if (priv->brfd < 0) { - nm_log_err (LOGD_ADSL, "(%s): failed to open ATM control socket (%d)", - iface, errno); - return FALSE; - } - - err = setsockopt (priv->brfd, SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof (bufsize)); - if (err != 0) { - nm_log_err (LOGD_ADSL, "(%s): failed to set SNDBUF option (%d)", - iface, errno); - goto error; - } - - /* QoS */ - memset (&qos, 0, sizeof (qos)); - qos.aal = ATM_AAL5; - qos.txtp.traffic_class = ATM_UBR; - qos.txtp.max_sdu = 1524; - qos.txtp.pcr = ATM_MAX_PCR; - qos.rxtp = qos.txtp; - - err = setsockopt (priv->brfd, SOL_ATM, SO_ATMQOS, &qos, sizeof (qos)); - if (err != 0) { - nm_log_err (LOGD_ADSL, "(%s): failed to set QoS (%d)", - iface, errno); - goto error; - } - - encapsulation = nm_setting_adsl_get_encapsulation (s_adsl); - - /* VPI/VCI */ - memset (&addr, 0, sizeof (addr)); - addr.sap_family = AF_ATMPVC; - addr.sap_addr.itf = priv->atm_index; - addr.sap_addr.vpi = (guint16) nm_setting_adsl_get_vpi (s_adsl); - addr.sap_addr.vci = (int) nm_setting_adsl_get_vci (s_adsl); - - nm_log_dbg (LOGD_ADSL, "(%s): assigning address %d.%d.%d encapsulation %s", - nm_device_get_iface (NM_DEVICE (self)), - priv->atm_index, addr.sap_addr.vpi, addr.sap_addr.vci, - encapsulation); - - err = connect (priv->brfd, (struct sockaddr*) &addr, sizeof (addr)); - if (err != 0) { - nm_log_err (LOGD_ADSL, "(%s): failed to set VPI/VCI (%d)", - iface, errno); - goto error; - } - - /* And last attach the VCC to the interface */ - is_llc = (g_strcmp0 (encapsulation, "llc") == 0); - - memset (&be, 0, sizeof (be)); - be.backend_num = ATM_BACKEND_BR2684; - be.ifspec.method = BR2684_FIND_BYIFNAME; - strcpy (be.ifspec.spec.ifname, priv->nas_ifname); - be.fcs_in = BR2684_FCSIN_NO; - be.fcs_out = BR2684_FCSOUT_NO; - be.encaps = is_llc ? BR2684_ENCAPS_LLC : BR2684_ENCAPS_VC; - err = ioctl (priv->brfd, ATM_SETBACKEND, &be); - if (err != 0) { - nm_log_err (LOGD_ADSL, "(%s): failed to attach VCC (%d)", - iface, errno); - goto error; - } - - return TRUE; - -error: - close (priv->brfd); - priv->brfd = -1; - return FALSE; -} - -static void -netlink_notification (NMNetlinkMonitor *monitor, - struct nl_msg *msg, - gpointer user_data) -{ - NMDeviceAdsl *self = NM_DEVICE_ADSL (user_data); - NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (self); - NMDevice *device = NM_DEVICE (user_data); - struct nlmsghdr *hdr = nlmsg_hdr (msg); - const char *iface = nm_device_get_iface (device); - - /* This only gets called for PPPoE connections and "nas" interfaces */ - - if ((hdr->nlmsg_type == RTM_DELLINK) && (priv->nas_ifindex >= 0)) { - struct ifinfomsg *ifi = nlmsg_data (hdr); - - if (ifi->ifi_index == priv->nas_ifindex) { - /* NAS device went away for some reason; kill the connection */ - nm_log_dbg (LOGD_ADSL, "(%s): NAS interface disappeared", iface); - nm_device_state_changed (device, - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_BR2684_FAILED); - } - } -} - -static NMActStageReturn -act_stage2_config (NMDevice *device, NMDeviceStateReason *out_reason) -{ - NMDeviceAdsl *self = NM_DEVICE_ADSL (device); - NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (self); - NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; - NMSettingAdsl *s_adsl; - const char *protocol; - - g_assert (out_reason); - - s_adsl = nm_connection_get_setting_adsl (nm_device_get_connection (device)); - g_assert (s_adsl); - - protocol = nm_setting_adsl_get_protocol (s_adsl); - nm_log_dbg (LOGD_ADSL, "(%s): using ADSL protocol '%s'", - nm_device_get_iface (device), protocol); - - if (g_strcmp0 (protocol, NM_SETTING_ADSL_PROTOCOL_PPPOE) == 0) { - - /* PPPoE needs RFC2684 bridging before we can do PPP over it */ - if (!br2684_create_iface (self, s_adsl)) { - *out_reason = NM_DEVICE_STATE_REASON_BR2684_FAILED; - goto done; - } - - /* Set up the VCC */ - if (!br2684_assign_vcc (self, s_adsl)) { - *out_reason = NM_DEVICE_STATE_REASON_BR2684_FAILED; - goto done; - } - - /* Watch for the 'nas' interface going away */ - priv->netlink_id = g_signal_connect (priv->monitor, "notification", - G_CALLBACK (netlink_notification), - self); - - nm_log_dbg (LOGD_ADSL, "(%s): ATM setup successful", nm_device_get_iface (device)); - - /* otherwise we're good for stage3 */ - nm_system_iface_set_up (priv->nas_ifindex, TRUE, NULL); - ret = NM_ACT_STAGE_RETURN_SUCCESS; - - } else if (g_strcmp0 (protocol, NM_SETTING_ADSL_PROTOCOL_PPPOA) == 0) { - /* PPPoA doesn't need anything special */ - ret = NM_ACT_STAGE_RETURN_SUCCESS; - } else { - nm_log_warn (LOGD_ADSL, "(%s): unhandled ADSL protocol '%s'", - nm_device_get_iface (device), protocol); - } - -done: - return ret; -} - -static void -ppp_state_changed (NMPPPManager *ppp_manager, NMPPPStatus status, gpointer user_data) -{ - NMDevice *device = NM_DEVICE (user_data); - - switch (status) { - case NM_PPP_STATUS_DISCONNECT: - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_PPP_DISCONNECT); - break; - case NM_PPP_STATUS_DEAD: - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_PPP_FAILED); - break; - default: - break; - } -} - -static void -ppp_ip4_config (NMPPPManager *ppp_manager, - const char *iface, - NMIP4Config *config, - gpointer user_data) -{ - NMDevice *device = NM_DEVICE (user_data); - - /* Ignore PPP IP4 events that come in after initial configuration */ - if (nm_device_activate_ip4_state_in_conf (device)) { - nm_device_set_ip_iface (device, iface); - nm_device_activate_schedule_ip4_config_result (device, config); - } -} - -static NMActStageReturn -act_stage3_ip4_config_start (NMDevice *device, - NMIP4Config **out_config, - NMDeviceStateReason *reason) -{ - NMDeviceAdsl *self = NM_DEVICE_ADSL (device); - NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (self); - NMConnection *connection; - NMSettingAdsl *s_adsl; - NMActRequest *req; - GError *err = NULL; - NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; - const char *iface = nm_device_get_iface (device); - const char *ppp_iface; - - req = nm_device_get_act_request (device); - g_assert (req); - - connection = nm_act_request_get_connection (req); - g_assert (req); - - s_adsl = nm_connection_get_setting_adsl (connection); - g_assert (s_adsl); - - /* PPPoE uses the NAS inteface, not the ATM interface */ - if (g_strcmp0 (nm_setting_adsl_get_protocol (s_adsl), NM_SETTING_ADSL_PROTOCOL_PPPOE) == 0) { - g_assert (priv->nas_ifname); - ppp_iface = priv->nas_ifname; - - nm_log_dbg (LOGD_ADSL, "(%s): starting PPPoE on NAS interface %s", - iface, priv->nas_ifname); - } else { - ppp_iface = iface; - nm_log_dbg (LOGD_ADSL, "(%s): starting PPPoA", iface); - } - - priv->ppp_manager = nm_ppp_manager_new (ppp_iface); - if (nm_ppp_manager_start (priv->ppp_manager, req, nm_setting_adsl_get_username (s_adsl), 30, &err)) { - g_signal_connect (priv->ppp_manager, "state-changed", - G_CALLBACK (ppp_state_changed), - self); - g_signal_connect (priv->ppp_manager, "ip4-config", - G_CALLBACK (ppp_ip4_config), - self); - ret = NM_ACT_STAGE_RETURN_POSTPONE; - } else { - nm_log_warn (LOGD_ADSL, "(%s): PPP failed to start: %s", iface, err->message); - g_error_free (err); - - g_object_unref (priv->ppp_manager); - priv->ppp_manager = NULL; - - *reason = NM_DEVICE_STATE_REASON_PPP_START_FAILED; - } - - return ret; -} - -static void -deactivate (NMDevice *device) -{ - NMDeviceAdsl *self = NM_DEVICE_ADSL (device); - NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (self); - - if (priv->ppp_manager) { - g_object_unref (priv->ppp_manager); - priv->ppp_manager = NULL; - } - - if (priv->netlink_id) { - g_signal_handler_disconnect (priv->monitor, priv->netlink_id); - priv->netlink_id = 0; - } - - if (priv->brfd >= 0) { - close (priv->brfd); - priv->brfd = -1; - } - - /* FIXME: kernel has no way of explicitly deleting the 'nasX' interface yet, - * so it gets leaked. It does get destroyed when it's no longer in use, - * but we have no control over that. - */ - if (priv->nas_ifindex >= 0) - priv->nas_ifindex = -1; - g_free (priv->nas_ifname); - priv->nas_ifname = NULL; - memset (priv->nas_hw_addr, 0, sizeof (priv->nas_hw_addr)); -} - -/**************************************************************/ - -static const guint8 * -get_hw_address (NMDevice *device, guint *out_len) -{ - NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (device); - - *out_len = priv->nas_ifname ? sizeof (priv->nas_hw_addr) : 0; - return priv->nas_hw_addr; -} - -static void -set_carrier (NMDeviceAdsl *self, const gboolean carrier) -{ - NMDeviceAdslPrivate *priv; - NMDeviceState state; - - g_return_if_fail (NM_IS_DEVICE (self)); - - priv = NM_DEVICE_ADSL_GET_PRIVATE (self); - - if (priv->carrier == carrier) - return; - - priv->carrier = carrier; - g_object_notify (G_OBJECT (self), NM_DEVICE_ADSL_CARRIER); - - state = nm_device_get_state (NM_DEVICE (self)); - nm_log_info (LOGD_HW, "(%s): carrier now %s (device state %d)", - nm_device_get_iface (NM_DEVICE (self)), - carrier ? "ON" : "OFF", - state); - - if (state == NM_DEVICE_STATE_UNAVAILABLE) { - if (priv->carrier) - nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_DISCONNECTED, NM_DEVICE_STATE_REASON_CARRIER); - } else if (state >= NM_DEVICE_STATE_DISCONNECTED) { - if (!priv->carrier) - nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_UNAVAILABLE, NM_DEVICE_STATE_REASON_CARRIER); - } -} - -static gboolean -carrier_update_cb (gpointer user_data) -{ - NMDeviceAdsl *self = NM_DEVICE_ADSL (user_data); - GError *error = NULL; - gboolean carrier = FALSE; - char *path, *contents; - const char *iface; - gboolean success; - - iface = nm_device_get_iface (NM_DEVICE (self)); - - path = g_strdup_printf ("/sys/class/atm/%s/carrier", iface); - success = g_file_get_contents (path, &contents, NULL, &error); - g_free (path); - - if (!success) { - nm_log_dbg (LOGD_ADSL, "error reading %s: (%d) %s", - path, - error ? error->code : -1, - error && error->message ? error->message : "(unknown)"); - g_clear_error (&error); - return TRUE; - } - - carrier = (gboolean) atoi (contents); - g_free (contents); - set_carrier (self, carrier); - return TRUE; -} - -/**************************************************************/ - -NMDevice * -nm_device_adsl_new (const char *udi, - const char *iface, - const char *driver) -{ - g_return_val_if_fail (udi != NULL, NULL); - - return (NMDevice *) g_object_new (NM_TYPE_DEVICE_ADSL, - NM_DEVICE_UDI, udi, - NM_DEVICE_IFACE, iface, - NM_DEVICE_DRIVER, driver, - NM_DEVICE_TYPE_DESC, "ADSL", - NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_ADSL, - NULL); -} - -static int -get_atm_index (const char *iface, GError **error) -{ - char *path, *contents; - int idx = -1; - - path = g_strdup_printf ("/sys/class/atm/%s/atmindex", iface); - if (g_file_get_contents (path, &contents, NULL, error)) - idx = atoi (contents); - g_free (path); - g_free (contents); - return idx; -} - -static GObject* -constructor (GType type, - guint n_construct_params, - GObjectConstructParam *construct_params) -{ - GObject *object; - NMDeviceAdslPrivate *priv; - GError *error = NULL; - - object = G_OBJECT_CLASS (nm_device_adsl_parent_class)->constructor (type, - n_construct_params, - construct_params); - if (!object) - return NULL; - - priv = NM_DEVICE_ADSL_GET_PRIVATE (object); - - priv->atm_index = get_atm_index (nm_device_get_iface (NM_DEVICE (object)), &error); - if (priv->atm_index < 0) { - nm_log_dbg (LOGD_ADSL, "error reading ATM device index: (%d) %s", - error ? error->code : -1, - error && error->message ? error->message : "(unknown)"); - g_clear_error (&error); - g_object_unref (object); - return NULL; - } else { - nm_log_dbg (LOGD_ADSL, "(%s): ATM device index %d", - nm_device_get_iface (NM_DEVICE (object)), priv->atm_index); - } - - /* Poll the carrier */ - priv->carrier_poll_id = g_timeout_add_seconds (5, carrier_update_cb, object); - - return object; -} - -static void -dispose (GObject *object) -{ - NMDeviceAdsl *self = NM_DEVICE_ADSL (object); - NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (self); - - if (priv->disposed) { - G_OBJECT_CLASS (nm_device_adsl_parent_class)->dispose (object); - return; - } - - priv->disposed = TRUE; - - if (priv->carrier_poll_id) { - g_source_remove (priv->carrier_poll_id); - priv->carrier_poll_id = 0; - } - - if (priv->netlink_id) { - g_source_remove (priv->netlink_id); - priv->netlink_id = 0; - } - - if (priv->monitor) { - nm_netlink_monitor_unsubscribe (priv->monitor, RTNLGRP_LINK); - g_object_unref (priv->monitor); - priv->monitor = NULL; - } - - g_free (priv->nas_ifname); - priv->nas_ifname = NULL; - - G_OBJECT_CLASS (nm_device_adsl_parent_class)->dispose (object); -} - -static void -get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) -{ - NMDeviceAdsl *self = NM_DEVICE_ADSL (object); - NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE(self); - - switch (prop_id) { - case PROP_CARRIER: - g_value_set_boolean (value, priv->carrier); - 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) -{ - switch (prop_id) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -nm_device_adsl_init (NMDeviceAdsl *self) -{ - NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (self); - - priv->monitor = nm_netlink_monitor_get (); - nm_netlink_monitor_subscribe (priv->monitor, RTNLGRP_LINK, NULL); -} - -static void -nm_device_adsl_class_init (NMDeviceAdslClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass); - - g_type_class_add_private (object_class, sizeof (NMDeviceAdslPrivate)); - - object_class->constructor = constructor; - object_class->dispose = dispose; - object_class->get_property = get_property; - object_class->set_property = set_property; - - parent_class->get_generic_capabilities = get_generic_capabilities; - parent_class->can_interrupt_activation = can_interrupt_activation; - parent_class->is_available = is_available; - - parent_class->check_connection_compatible = check_connection_compatible; - parent_class->get_best_auto_connection = get_best_auto_connection; - parent_class->complete_connection = complete_connection; - - parent_class->get_hw_address = get_hw_address; - parent_class->act_stage2_config = act_stage2_config; - parent_class->act_stage3_ip4_config_start = act_stage3_ip4_config_start; - parent_class->deactivate = deactivate; - - /* properties */ - g_object_class_install_property - (object_class, PROP_CARRIER, - g_param_spec_boolean (NM_DEVICE_ADSL_CARRIER, - "Carrier", - "Carrier", - FALSE, - G_PARAM_READABLE)); - - /* Signals */ - signals[PROPERTIES_CHANGED] = - nm_properties_changed_signal_new (object_class, - G_STRUCT_OFFSET (NMDeviceAdslClass, properties_changed)); - - dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass), - &dbus_glib_nm_device_adsl_object_info); -} diff --git a/src/nm-device-adsl.h b/src/nm-device-adsl.h deleted file mode 100644 index 7ecb4350..00000000 --- a/src/nm-device-adsl.h +++ /dev/null @@ -1,66 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Author: Pantelis Koukousoulas - * Copyright (C) 2009 - 2011 Red Hat Inc. - */ - -#ifndef NM_DEVICE_ADSL_H -#define NM_DEVICE_ADSL_H - -#include - -// Parent class -#include "nm-device.h" - -G_BEGIN_DECLS - -#define NM_TYPE_DEVICE_ADSL (nm_device_adsl_get_type ()) -#define NM_DEVICE_ADSL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_ADSL, NMDeviceAdsl)) -#define NM_DEVICE_ADSL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_ADSL, NMDeviceAdslClass)) -#define NM_IS_DEVICE_ADSL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_ADSL)) -#define NM_IS_DEVICE_ADSL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_ADSL)) -#define NM_DEVICE_ADSL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_ADSL, NMDeviceAdslClass)) - -typedef enum { - NM_ADSL_ERROR_CONNECTION_NOT_ADSL = 0, /*< nick=ConnectionNotAdsl >*/ - NM_ADSL_ERROR_CONNECTION_INVALID, /*< nick=ConnectionInvalid >*/ - NM_ADSL_ERROR_CONNECTION_INCOMPATIBLE, /*< nick=ConnectionIncompatible >*/ -} NMAdslError; - -#define NM_DEVICE_ADSL_CARRIER "carrier" - -typedef struct { - NMDevice parent; -} NMDeviceAdsl; - -typedef struct { - NMDeviceClass parent; - - /* Signals */ - void (*properties_changed) (NMDeviceAdsl *device, GHashTable *properties); -} NMDeviceAdslClass; - -GType nm_device_adsl_get_type (void); - -NMDevice *nm_device_adsl_new (const char *udi, - const char *iface, - const char *driver); - -G_END_DECLS - -#endif /* NM_DEVICE_ADSL_H */ diff --git a/src/nm-device-bond-glue.h b/src/nm-device-bond-glue.h new file mode 100644 index 00000000..6a2f5702 --- /dev/null +++ b/src/nm-device-bond-glue.h @@ -0,0 +1,73 @@ +/* Generated by dbus-binding-tool; do not edit! */ + + +#ifndef __dbus_glib_marshal_nm_device_bond_MARSHAL_H__ +#define __dbus_glib_marshal_nm_device_bond_MARSHAL_H__ + +#include + +G_BEGIN_DECLS + +#ifdef G_ENABLE_DEBUG +#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v) +#define g_marshal_value_peek_char(v) g_value_get_schar (v) +#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v) +#define g_marshal_value_peek_int(v) g_value_get_int (v) +#define g_marshal_value_peek_uint(v) g_value_get_uint (v) +#define g_marshal_value_peek_long(v) g_value_get_long (v) +#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v) +#define g_marshal_value_peek_int64(v) g_value_get_int64 (v) +#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v) +#define g_marshal_value_peek_enum(v) g_value_get_enum (v) +#define g_marshal_value_peek_flags(v) g_value_get_flags (v) +#define g_marshal_value_peek_float(v) g_value_get_float (v) +#define g_marshal_value_peek_double(v) g_value_get_double (v) +#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v) +#define g_marshal_value_peek_param(v) g_value_get_param (v) +#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v) +#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v) +#define g_marshal_value_peek_object(v) g_value_get_object (v) +#define g_marshal_value_peek_variant(v) g_value_get_variant (v) +#else /* !G_ENABLE_DEBUG */ +/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API. + * Do not access GValues directly in your code. Instead, use the + * g_value_get_*() functions + */ +#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int +#define g_marshal_value_peek_char(v) (v)->data[0].v_int +#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint +#define g_marshal_value_peek_int(v) (v)->data[0].v_int +#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint +#define g_marshal_value_peek_long(v) (v)->data[0].v_long +#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 +#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 +#define g_marshal_value_peek_enum(v) (v)->data[0].v_long +#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_float(v) (v)->data[0].v_float +#define g_marshal_value_peek_double(v) (v)->data[0].v_double +#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer +#endif /* !G_ENABLE_DEBUG */ + + +G_END_DECLS + +#endif /* __dbus_glib_marshal_nm_device_bond_MARSHAL_H__ */ + +#include +static const DBusGMethodInfo dbus_glib_nm_device_bond_methods[] = { +}; + +const DBusGObjectInfo dbus_glib_nm_device_bond_object_info = { 1, + dbus_glib_nm_device_bond_methods, + 0, +"\0", +"org.freedesktop.NetworkManager.Device.Bond\0PropertiesChanged\0\0", +"org.freedesktop.NetworkManager.Device.Bond\0HwAddress\0hw_address\0read\0org.freedesktop.NetworkManager.Device.Bond\0Carrier\0carrier\0read\0org.freedesktop.NetworkManager.Device.Bond\0Slaves\0slaves\0read\0\0" +}; + diff --git a/src/nm-device-bond.c b/src/nm-device-bond.c deleted file mode 100644 index 7f47a3a6..00000000 --- a/src/nm-device-bond.c +++ /dev/null @@ -1,526 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2011 - 2012 Red Hat, Inc. - */ - -#include "config.h" - -#include -#include - -#include - -#include "nm-device-bond.h" -#include "nm-logging.h" -#include "nm-properties-changed-signal.h" -#include "nm-utils.h" -#include "NetworkManagerUtils.h" -#include "nm-device-private.h" -#include "nm-netlink-monitor.h" -#include "nm-dbus-glib-types.h" -#include "nm-enum-types.h" -#include "nm-system.h" - -#include "nm-device-bond-glue.h" - - -G_DEFINE_TYPE (NMDeviceBond, nm_device_bond, NM_TYPE_DEVICE_WIRED) - -#define NM_DEVICE_BOND_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_BOND, NMDeviceBondPrivate)) - -#define NM_BOND_ERROR (nm_bond_error_quark ()) - -typedef struct { - guint8 hw_addr[NM_UTILS_HWADDR_LEN_MAX]; - gsize hw_addr_len; -} NMDeviceBondPrivate; - -enum { - PROPERTIES_CHANGED, - - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -enum { - PROP_0, - PROP_HW_ADDRESS, - PROP_CARRIER, - PROP_SLAVES, - - LAST_PROP -}; - -/******************************************************************/ - -static GQuark -nm_bond_error_quark (void) -{ - static GQuark quark = 0; - if (!quark) - quark = g_quark_from_static_string ("nm-bond-error"); - return quark; -} - -/******************************************************************/ - -static void -carrier_action (NMDeviceWired *self, NMDeviceState state, gboolean carrier) -{ - /* Carrier can't be used to signal availability of the bond master because - * the bond's carrier follows the slaves' carriers. So carrier gets - * ignored when determining whether or not the device can be activated. - * - * Second, just because all slaves have been removed or have lost carrier - * does not mean the master should be deactivated. This could be due to - * user addition/removal of slaves, and is also normal operation with some - * failover modes. - * - * For these reasons, carrier changes are effectively ignored by overriding - * the parent class' carrier handling and doing nothing. - */ -} - -static void -update_hw_address (NMDevice *dev) -{ - NMDeviceBondPrivate *priv = NM_DEVICE_BOND_GET_PRIVATE (dev); - gsize addrlen; - gboolean changed = FALSE; - - addrlen = nm_device_read_hwaddr (dev, priv->hw_addr, sizeof (priv->hw_addr), &changed); - if (addrlen) { - priv->hw_addr_len = addrlen; - if (changed) - g_object_notify (G_OBJECT (dev), NM_DEVICE_BOND_HW_ADDRESS); - } -} - -static const guint8 * -get_hw_address (NMDevice *device, guint *out_len) -{ - *out_len = NM_DEVICE_BOND_GET_PRIVATE (device)->hw_addr_len; - return NM_DEVICE_BOND_GET_PRIVATE (device)->hw_addr; -} - -static guint32 -get_generic_capabilities (NMDevice *dev) -{ - return NM_DEVICE_CAP_CARRIER_DETECT | NM_DEVICE_CAP_NM_SUPPORTED; -} - -static gboolean -is_available (NMDevice *dev) -{ - if (NM_DEVICE_GET_CLASS (dev)->hw_is_up) - return NM_DEVICE_GET_CLASS (dev)->hw_is_up (dev); - return FALSE; -} - -static gboolean -match_bond_connection (NMDevice *device, NMConnection *connection, GError **error) -{ - const char *iface; - NMSettingBond *s_bond; - - s_bond = nm_connection_get_setting_bond (connection); - if (!s_bond || !nm_connection_is_type (connection, NM_SETTING_BOND_SETTING_NAME)) { - g_set_error (error, NM_BOND_ERROR, NM_BOND_ERROR_CONNECTION_NOT_BOND, - "The connection was not a bond connection."); - return FALSE; - } - - /* Bond connections must specify the virtual interface name */ - iface = nm_connection_get_virtual_iface_name (connection); - if (!iface || strcmp (nm_device_get_iface (device), iface)) { - g_set_error (error, NM_BOND_ERROR, NM_BOND_ERROR_CONNECTION_NOT_BOND, - "The bond connection virtual interface name did not match."); - return FALSE; - } - - /* FIXME: match bond properties like mode, etc? */ - - return TRUE; -} - -static NMConnection * -get_best_auto_connection (NMDevice *dev, - GSList *connections, - char **specific_object) -{ - GSList *iter; - - for (iter = connections; iter; iter = g_slist_next (iter)) { - NMConnection *connection = NM_CONNECTION (iter->data); - - if (match_bond_connection (dev, connection, NULL)) - return connection; - } - return NULL; -} - -static gboolean -check_connection_compatible (NMDevice *device, - NMConnection *connection, - GError **error) -{ - return match_bond_connection (device, connection, error); -} - -static gboolean -complete_connection (NMDevice *device, - NMConnection *connection, - const char *specific_object, - const GSList *existing_connections, - GError **error) -{ - NMSettingBond *s_bond, *tmp; - guint32 i = 0; - char *name; - const GSList *iter; - gboolean found; - - nm_utils_complete_generic (connection, - NM_SETTING_BOND_SETTING_NAME, - existing_connections, - _("Bond connection %d"), - NULL, - TRUE); - - s_bond = nm_connection_get_setting_bond (connection); - if (!s_bond) { - s_bond = (NMSettingBond *) nm_setting_bond_new (); - nm_connection_add_setting (connection, NM_SETTING (s_bond)); - } - - /* Grab the first name that doesn't exist in either our connections - * or a device on the system. - */ - while (i < 500 && !nm_setting_bond_get_interface_name (s_bond)) { - name = g_strdup_printf ("bond%u", i); - /* check interface names */ - if (nm_netlink_iface_to_index (name) < 0) { - /* check existing bond connections */ - for (iter = existing_connections, found = FALSE; iter; iter = g_slist_next (iter)) { - NMConnection *candidate = iter->data; - - tmp = nm_connection_get_setting_bond (candidate); - if (tmp && nm_connection_is_type (candidate, NM_SETTING_BOND_SETTING_NAME)) { - if (g_strcmp0 (nm_setting_bond_get_interface_name (tmp), name) == 0) { - found = TRUE; - break; - } - } - } - - if (!found) - g_object_set (G_OBJECT (s_bond), NM_SETTING_BOND_INTERFACE_NAME, name, NULL); - } - - g_free (name); - i++; - } - - return TRUE; -} - -static gboolean -spec_match_list (NMDevice *device, const GSList *specs) -{ - NMDeviceBondPrivate *priv = NM_DEVICE_BOND_GET_PRIVATE (device); - char *hwaddr; - gboolean matched; - - hwaddr = nm_utils_hwaddr_ntoa (priv->hw_addr, nm_utils_hwaddr_type (priv->hw_addr_len)); - matched = nm_match_spec_hwaddr (specs, hwaddr); - g_free (hwaddr); - - return matched; -} - -static gboolean -bond_match_config (NMDevice *self, NMConnection *connection) -{ - NMSettingBond *s_bond; - const char *ifname; - - s_bond = nm_connection_get_setting_bond (connection); - if (!s_bond) - return FALSE; - - /* Interface name */ - ifname = nm_setting_bond_get_interface_name (s_bond); - if (g_strcmp0 (ifname, nm_device_get_ip_iface (self)) != 0) - return FALSE; - - return TRUE; -} - -static NMConnection * -connection_match_config (NMDevice *self, const GSList *connections) -{ - const GSList *iter; - GSList *bond_matches; - NMConnection *match; - - /* First narrow @connections down to those that match in their - * NMSettingBond configuration. - */ - bond_matches = NULL; - for (iter = connections; iter; iter = iter->next) { - NMConnection *candidate = NM_CONNECTION (iter->data); - - if (!nm_connection_is_type (candidate, NM_SETTING_BOND_SETTING_NAME)) - continue; - if (!bond_match_config (self, candidate)) - continue; - - bond_matches = g_slist_prepend (bond_matches, candidate); - } - - /* Now pass those to the super method, which will check IP config */ - bond_matches = g_slist_reverse (bond_matches); - match = NM_DEVICE_CLASS (nm_device_bond_parent_class)->connection_match_config (self, bond_matches); - g_slist_free (bond_matches); - - return match; -} - -/******************************************************************/ - -static NMActStageReturn -act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason) -{ - NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS; - NMConnection *connection; - NMSettingBond *s_bond; - gboolean no_firmware = FALSE; - - g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); - - ret = NM_DEVICE_CLASS (nm_device_bond_parent_class)->act_stage1_prepare (dev, reason); - if (ret == NM_ACT_STAGE_RETURN_SUCCESS) { - connection = nm_device_get_connection (dev); - g_assert (connection); - s_bond = nm_connection_get_setting_bond (connection); - g_assert (s_bond); - - /* Interface must be down to set bond options */ - nm_device_hw_take_down (dev, TRUE); - - if (!nm_system_apply_bonding_config (nm_device_get_ip_iface (dev), s_bond)) - ret = NM_ACT_STAGE_RETURN_FAILURE; - - nm_device_hw_bring_up (dev, TRUE, &no_firmware); - } - return ret; -} - -static gboolean -enslave_slave (NMDevice *device, NMDevice *slave, NMConnection *connection) -{ - gboolean success, no_firmware = FALSE; - const char *iface = nm_device_get_ip_iface (device); - const char *slave_iface = nm_device_get_ip_iface (slave); - - nm_device_hw_take_down (slave, TRUE); - - success = nm_system_bond_enslave (nm_device_get_ip_ifindex (device), - iface, - nm_device_get_ip_ifindex (slave), - slave_iface); - - nm_device_hw_bring_up (slave, TRUE, &no_firmware); - - if (success) { - nm_log_info (LOGD_BOND, "(%s): enslaved bond slave %s", iface, slave_iface); - g_object_notify (G_OBJECT (device), "slaves"); - } - - return success; -} - -static gboolean -release_slave (NMDevice *device, NMDevice *slave) -{ - gboolean success, no_firmware = FALSE; - - success = nm_system_bond_release (nm_device_get_ip_ifindex (device), - nm_device_get_ip_iface (device), - nm_device_get_ip_ifindex (slave), - nm_device_get_ip_iface (slave)); - nm_log_info (LOGD_BOND, "(%s): released bond slave %s (success %d)", - nm_device_get_ip_iface (device), - nm_device_get_ip_iface (slave), - success); - g_object_notify (G_OBJECT (device), "slaves"); - - /* Kernel bonding code "closes" the slave when releasing it, (which clears - * IFF_UP), so we must bring it back up here to ensure carrier changes and - * other state is noticed by the now-released slave. - */ - if (!nm_device_hw_bring_up (slave, TRUE, &no_firmware)) { - nm_log_warn (LOGD_BOND, "(%s): released bond slave could not be brought up.", - nm_device_get_iface (slave)); - } - - return success; -} - -/******************************************************************/ - -NMDevice * -nm_device_bond_new (const char *udi, const char *iface) -{ - g_return_val_if_fail (udi != NULL, NULL); - g_return_val_if_fail (iface != NULL, NULL); - - return (NMDevice *) g_object_new (NM_TYPE_DEVICE_BOND, - NM_DEVICE_UDI, udi, - NM_DEVICE_IFACE, iface, - NM_DEVICE_DRIVER, "bonding", - NM_DEVICE_TYPE_DESC, "Bond", - NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_BOND, - NM_DEVICE_IS_MASTER, TRUE, - NULL); -} - -static void -constructed (GObject *object) -{ - G_OBJECT_CLASS (nm_device_bond_parent_class)->constructed (object); - - nm_log_dbg (LOGD_HW | LOGD_BOND, "(%s): kernel ifindex %d", - nm_device_get_iface (NM_DEVICE (object)), - nm_device_get_ifindex (NM_DEVICE (object))); -} - -static void -nm_device_bond_init (NMDeviceBond * self) -{ -} - -static void -get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) -{ - NMDeviceBondPrivate *priv = NM_DEVICE_BOND_GET_PRIVATE (object); - GPtrArray *slaves; - GSList *list, *iter; - char *hwaddr; - - switch (prop_id) { - case PROP_HW_ADDRESS: - hwaddr = nm_utils_hwaddr_ntoa (priv->hw_addr, nm_utils_hwaddr_type (priv->hw_addr_len)); - g_value_take_string (value, hwaddr); - break; - case PROP_CARRIER: - g_value_set_boolean (value, nm_device_wired_get_carrier (NM_DEVICE_WIRED (object))); - break; - case PROP_SLAVES: - slaves = g_ptr_array_new (); - list = nm_device_master_get_slaves (NM_DEVICE (object)); - for (iter = list; iter; iter = iter->next) - g_ptr_array_add (slaves, g_strdup (nm_device_get_path (NM_DEVICE (iter->data)))); - g_slist_free (list); - g_value_take_boxed (value, slaves); - 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) -{ - switch (prop_id) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -nm_device_bond_class_init (NMDeviceBondClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass); - NMDeviceWiredClass *wired_class = NM_DEVICE_WIRED_CLASS (klass); - - g_type_class_add_private (object_class, sizeof (NMDeviceBondPrivate)); - - /* virtual methods */ - object_class->constructed = constructed; - object_class->get_property = get_property; - object_class->set_property = set_property; - - parent_class->get_generic_capabilities = get_generic_capabilities; - parent_class->update_hw_address = update_hw_address; - parent_class->get_hw_address = get_hw_address; - parent_class->is_available = is_available; - parent_class->get_best_auto_connection = get_best_auto_connection; - parent_class->check_connection_compatible = check_connection_compatible; - parent_class->complete_connection = complete_connection; - - parent_class->spec_match_list = spec_match_list; - parent_class->connection_match_config = connection_match_config; - - parent_class->act_stage1_prepare = act_stage1_prepare; - parent_class->enslave_slave = enslave_slave; - parent_class->release_slave = release_slave; - - wired_class->carrier_action = carrier_action; - - /* properties */ - g_object_class_install_property - (object_class, PROP_HW_ADDRESS, - g_param_spec_string (NM_DEVICE_BOND_HW_ADDRESS, - "Active MAC Address", - "Currently set hardware MAC address", - NULL, - G_PARAM_READABLE)); - - g_object_class_install_property - (object_class, PROP_CARRIER, - g_param_spec_boolean (NM_DEVICE_BOND_CARRIER, - "Carrier", - "Carrier", - FALSE, - G_PARAM_READABLE)); - - g_object_class_install_property - (object_class, PROP_SLAVES, - g_param_spec_boxed (NM_DEVICE_BOND_SLAVES, - "Slaves", - "Slaves", - DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH, - G_PARAM_READABLE)); - - /* Signals */ - signals[PROPERTIES_CHANGED] = - nm_properties_changed_signal_new (object_class, - G_STRUCT_OFFSET (NMDeviceBondClass, properties_changed)); - - dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass), - &dbus_glib_nm_device_bond_object_info); - - dbus_g_error_domain_register (NM_BOND_ERROR, NULL, NM_TYPE_BOND_ERROR); -} diff --git a/src/nm-device-bond.h b/src/nm-device-bond.h deleted file mode 100644 index eeca5606..00000000 --- a/src/nm-device-bond.h +++ /dev/null @@ -1,66 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2012 Red Hat, Inc. - */ - -#ifndef NM_DEVICE_BOND_H -#define NM_DEVICE_BOND_H - -#include - -#include "nm-device-wired.h" - -G_BEGIN_DECLS - -#define NM_TYPE_DEVICE_BOND (nm_device_bond_get_type ()) -#define NM_DEVICE_BOND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_BOND, NMDeviceBond)) -#define NM_DEVICE_BOND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_BOND, NMDeviceBondClass)) -#define NM_IS_DEVICE_BOND(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_BOND)) -#define NM_IS_DEVICE_BOND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_BOND)) -#define NM_DEVICE_BOND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_BOND, NMDeviceBondClass)) - -typedef enum { - NM_BOND_ERROR_CONNECTION_NOT_BOND = 0, /*< nick=ConnectionNotBond >*/ - NM_BOND_ERROR_CONNECTION_INVALID, /*< nick=ConnectionInvalid >*/ - NM_BOND_ERROR_CONNECTION_INCOMPATIBLE, /*< nick=ConnectionIncompatible >*/ -} NMBondError; - -#define NM_DEVICE_BOND_HW_ADDRESS "hw-address" -#define NM_DEVICE_BOND_CARRIER "carrier" -#define NM_DEVICE_BOND_SLAVES "slaves" - -typedef struct { - NMDeviceWired parent; -} NMDeviceBond; - -typedef struct { - NMDeviceWiredClass parent; - - /* Signals */ - void (*properties_changed) (NMDeviceBond *device, GHashTable *properties); -} NMDeviceBondClass; - - -GType nm_device_bond_get_type (void); - -NMDevice *nm_device_bond_new (const char *udi, - const char *iface); - -G_END_DECLS - -#endif /* NM_DEVICE_BOND_H */ diff --git a/src/nm-device-bridge-glue.h b/src/nm-device-bridge-glue.h new file mode 100644 index 00000000..63b86954 --- /dev/null +++ b/src/nm-device-bridge-glue.h @@ -0,0 +1,73 @@ +/* Generated by dbus-binding-tool; do not edit! */ + + +#ifndef __dbus_glib_marshal_nm_device_bridge_MARSHAL_H__ +#define __dbus_glib_marshal_nm_device_bridge_MARSHAL_H__ + +#include + +G_BEGIN_DECLS + +#ifdef G_ENABLE_DEBUG +#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v) +#define g_marshal_value_peek_char(v) g_value_get_schar (v) +#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v) +#define g_marshal_value_peek_int(v) g_value_get_int (v) +#define g_marshal_value_peek_uint(v) g_value_get_uint (v) +#define g_marshal_value_peek_long(v) g_value_get_long (v) +#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v) +#define g_marshal_value_peek_int64(v) g_value_get_int64 (v) +#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v) +#define g_marshal_value_peek_enum(v) g_value_get_enum (v) +#define g_marshal_value_peek_flags(v) g_value_get_flags (v) +#define g_marshal_value_peek_float(v) g_value_get_float (v) +#define g_marshal_value_peek_double(v) g_value_get_double (v) +#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v) +#define g_marshal_value_peek_param(v) g_value_get_param (v) +#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v) +#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v) +#define g_marshal_value_peek_object(v) g_value_get_object (v) +#define g_marshal_value_peek_variant(v) g_value_get_variant (v) +#else /* !G_ENABLE_DEBUG */ +/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API. + * Do not access GValues directly in your code. Instead, use the + * g_value_get_*() functions + */ +#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int +#define g_marshal_value_peek_char(v) (v)->data[0].v_int +#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint +#define g_marshal_value_peek_int(v) (v)->data[0].v_int +#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint +#define g_marshal_value_peek_long(v) (v)->data[0].v_long +#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 +#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 +#define g_marshal_value_peek_enum(v) (v)->data[0].v_long +#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_float(v) (v)->data[0].v_float +#define g_marshal_value_peek_double(v) (v)->data[0].v_double +#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer +#endif /* !G_ENABLE_DEBUG */ + + +G_END_DECLS + +#endif /* __dbus_glib_marshal_nm_device_bridge_MARSHAL_H__ */ + +#include +static const DBusGMethodInfo dbus_glib_nm_device_bridge_methods[] = { +}; + +const DBusGObjectInfo dbus_glib_nm_device_bridge_object_info = { 1, + dbus_glib_nm_device_bridge_methods, + 0, +"\0", +"org.freedesktop.NetworkManager.Device.Bridge\0PropertiesChanged\0\0", +"org.freedesktop.NetworkManager.Device.Bridge\0HwAddress\0hw_address\0read\0org.freedesktop.NetworkManager.Device.Bridge\0Carrier\0carrier\0read\0org.freedesktop.NetworkManager.Device.Bridge\0Slaves\0slaves\0read\0\0" +}; + diff --git a/src/nm-device-bridge.c b/src/nm-device-bridge.c deleted file mode 100644 index 39275c8b..00000000 --- a/src/nm-device-bridge.c +++ /dev/null @@ -1,579 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2011 - 2012 Red Hat, Inc. - */ - -#include "config.h" - -#include -#include - -#include - -#include "nm-device-bridge.h" -#include "nm-logging.h" -#include "nm-properties-changed-signal.h" -#include "nm-utils.h" -#include "NetworkManagerUtils.h" -#include "nm-device-private.h" -#include "nm-netlink-monitor.h" -#include "nm-dbus-glib-types.h" -#include "nm-enum-types.h" -#include "nm-system.h" - -#include "nm-device-bridge-glue.h" - - -G_DEFINE_TYPE (NMDeviceBridge, nm_device_bridge, NM_TYPE_DEVICE_WIRED) - -#define NM_DEVICE_BRIDGE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_BRIDGE, NMDeviceBridgePrivate)) - -#define NM_BRIDGE_ERROR (nm_bridge_error_quark ()) - -typedef struct { - guint8 hw_addr[NM_UTILS_HWADDR_LEN_MAX]; - gsize hw_addr_len; -} NMDeviceBridgePrivate; - -enum { - PROPERTIES_CHANGED, - - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -enum { - PROP_0, - PROP_HW_ADDRESS, - PROP_CARRIER, - PROP_SLAVES, - - LAST_PROP -}; - -/******************************************************************/ - -static GQuark -nm_bridge_error_quark (void) -{ - static GQuark quark = 0; - if (!quark) - quark = g_quark_from_static_string ("nm-bridge-error"); - return quark; -} - -/******************************************************************/ - -static void -carrier_action (NMDeviceWired *self, NMDeviceState state, gboolean carrier) -{ - /* Bridge carrier state follows IFF_UP with no ports, and port carrier - * states when ports are added. Thus carrier isn't useful when deciding - * to auto-activate the bridge master. Also, like bond masters, when the - * carrier state changes due to slave changes, we shouldn't deactivate the - * bridge since the user may be reconfiguring ports. - * - * For these reasons, carrier changes are effectively ignored by overriding - * the parent class' carrier handling and doing nothing. - */ -} - -static void -update_hw_address (NMDevice *dev) -{ - NMDeviceBridgePrivate *priv = NM_DEVICE_BRIDGE_GET_PRIVATE (dev); - gsize addrlen; - gboolean changed = FALSE; - - addrlen = nm_device_read_hwaddr (dev, priv->hw_addr, sizeof (priv->hw_addr), &changed); - if (addrlen) { - priv->hw_addr_len = addrlen; - if (changed) - g_object_notify (G_OBJECT (dev), NM_DEVICE_BRIDGE_HW_ADDRESS); - } -} - -static const guint8 * -get_hw_address (NMDevice *device, guint *out_len) -{ - *out_len = NM_DEVICE_BRIDGE_GET_PRIVATE (device)->hw_addr_len; - return NM_DEVICE_BRIDGE_GET_PRIVATE (device)->hw_addr; -} - -static guint32 -get_generic_capabilities (NMDevice *dev) -{ - return NM_DEVICE_CAP_CARRIER_DETECT | NM_DEVICE_CAP_NM_SUPPORTED; -} - -static gboolean -is_available (NMDevice *dev) -{ - if (NM_DEVICE_GET_CLASS (dev)->hw_is_up) - return NM_DEVICE_GET_CLASS (dev)->hw_is_up (dev); - return FALSE; -} - -static gboolean -match_bridge_connection (NMDevice *device, NMConnection *connection, GError **error) -{ - const char *iface; - NMSettingBridge *s_bridge; - - s_bridge = nm_connection_get_setting_bridge (connection); - if (!s_bridge || !nm_connection_is_type (connection, NM_SETTING_BRIDGE_SETTING_NAME)) { - g_set_error (error, NM_BRIDGE_ERROR, NM_BRIDGE_ERROR_CONNECTION_NOT_BRIDGE, - "The connection was not a bridge connection."); - return FALSE; - } - - /* Bridge connections must specify the virtual interface name */ - iface = nm_connection_get_virtual_iface_name (connection); - if (!iface || strcmp (nm_device_get_iface (device), iface)) { - g_set_error (error, NM_BRIDGE_ERROR, NM_BRIDGE_ERROR_CONNECTION_INVALID, - "The bridge connection virtual interface name did not match."); - return FALSE; - } - - return TRUE; -} - -static NMConnection * -get_best_auto_connection (NMDevice *dev, - GSList *connections, - char **specific_object) -{ - GSList *iter; - - for (iter = connections; iter; iter = g_slist_next (iter)) { - NMConnection *connection = NM_CONNECTION (iter->data); - NMSettingConnection *s_con; - - s_con = nm_connection_get_setting_connection (connection); - g_assert (s_con); - if ( nm_setting_connection_get_autoconnect (s_con) - && match_bridge_connection (dev, connection, NULL)) - return connection; - } - return NULL; -} - -static gboolean -check_connection_compatible (NMDevice *device, - NMConnection *connection, - GError **error) -{ - return match_bridge_connection (device, connection, error); -} - -static gboolean -complete_connection (NMDevice *device, - NMConnection *connection, - const char *specific_object, - const GSList *existing_connections, - GError **error) -{ - NMSettingBridge *s_bridge, *tmp; - guint32 i = 0; - char *name; - const GSList *iter; - gboolean found; - - nm_utils_complete_generic (connection, - NM_SETTING_BRIDGE_SETTING_NAME, - existing_connections, - _("Bridge connection %d"), - NULL, - TRUE); - - s_bridge = nm_connection_get_setting_bridge (connection); - if (!s_bridge) { - s_bridge = (NMSettingBridge *) nm_setting_bridge_new (); - nm_connection_add_setting (connection, NM_SETTING (s_bridge)); - } - - /* Grab the first name that doesn't exist in either our connections - * or a device on the system. - */ - while (i < 500 && !nm_setting_bridge_get_interface_name (s_bridge)) { - name = g_strdup_printf ("br%u", i); - /* check interface names */ - if (nm_netlink_iface_to_index (name) < 0) { - /* check existing bridge connections */ - for (iter = existing_connections, found = FALSE; iter; iter = g_slist_next (iter)) { - NMConnection *candidate = iter->data; - - tmp = nm_connection_get_setting_bridge (candidate); - if (tmp && nm_connection_is_type (candidate, NM_SETTING_BRIDGE_SETTING_NAME)) { - if (g_strcmp0 (nm_setting_bridge_get_interface_name (tmp), name) == 0) { - found = TRUE; - break; - } - } - } - - if (!found) - g_object_set (G_OBJECT (s_bridge), NM_SETTING_BRIDGE_INTERFACE_NAME, name, NULL); - } - - g_free (name); - i++; - } - - return TRUE; -} - -static gboolean -spec_match_list (NMDevice *device, const GSList *specs) -{ - NMDeviceBridgePrivate *priv = NM_DEVICE_BRIDGE_GET_PRIVATE (device); - char *hwaddr; - gboolean matched; - - hwaddr = nm_utils_hwaddr_ntoa (priv->hw_addr, nm_utils_hwaddr_type (priv->hw_addr_len)); - matched = nm_match_spec_hwaddr (specs, hwaddr); - g_free (hwaddr); - - return matched; -} - -static gboolean -bridge_match_config (NMDevice *self, NMConnection *connection) -{ - NMSettingBridge *s_bridge; - const char *ifname; - - s_bridge = nm_connection_get_setting_bridge (connection); - if (!s_bridge) - return FALSE; - - /* Interface name */ - ifname = nm_setting_bridge_get_interface_name (s_bridge); - if (g_strcmp0 (ifname, nm_device_get_ip_iface (self)) != 0) - return FALSE; - - return TRUE; -} - -static NMConnection * -connection_match_config (NMDevice *self, const GSList *connections) -{ - const GSList *iter; - GSList *bridge_matches; - NMConnection *match; - - /* First narrow @connections down to those that match in their - * NMSettingBridge configuration. - */ - bridge_matches = NULL; - for (iter = connections; iter; iter = iter->next) { - NMConnection *candidate = NM_CONNECTION (iter->data); - - if (!nm_connection_is_type (candidate, NM_SETTING_BRIDGE_SETTING_NAME)) - continue; - if (!bridge_match_config (self, candidate)) - continue; - - bridge_matches = g_slist_prepend (bridge_matches, candidate); - } - - /* Now pass those to the super method, which will check IP config */ - bridge_matches = g_slist_reverse (bridge_matches); - match = NM_DEVICE_CLASS (nm_device_bridge_parent_class)->connection_match_config (self, bridge_matches); - g_slist_free (bridge_matches); - - return match; -} - -/******************************************************************/ - -static void -set_sysfs_uint (const char *iface, - GObject *obj, - const char *obj_prop, - const char *dir, - const char *sysfs_prop, - gboolean default_if_zero, - gboolean user_hz_compensate) -{ - char *path, *s; - GParamSpec *pspec; - GValue val = { 0 }; - guint32 uval = 0; - - pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (obj), obj_prop); - g_return_if_fail (pspec != NULL); - - /* Get the property's value */ - g_value_init (&val, G_PARAM_SPEC_VALUE_TYPE (pspec)); - g_object_get_property (obj, obj_prop, &val); - if (G_VALUE_HOLDS_BOOLEAN (&val)) - uval = g_value_get_boolean (&val) ? 1 : 0; - else if (G_VALUE_HOLDS_UINT (&val)) { - uval = g_value_get_uint (&val); - - /* zero means "unspecified" for some NM properties but isn't in the - * allowed kernel range, so reset the property to the default value. - */ - if (default_if_zero && uval == 0) { - g_value_unset (&val); - g_value_init (&val, G_PARAM_SPEC_VALUE_TYPE (pspec)); - g_param_value_set_default (pspec, &val); - uval = g_value_get_uint (&val); - } - } else - g_assert_not_reached (); - - g_value_unset (&val); - - /* Linux kernel bridge interfaces use 'centiseconds' for time-based values. - * In reality it's not centiseconds, but depends on HZ and USER_HZ, which - * is almost always works out to be a multiplier of 100, so we can assume - * centiseconds. See clock_t_to_jiffies(). - */ - if (user_hz_compensate) - uval *= 100; - - path = g_strdup_printf ("/sys/class/net/%s/%s/%s", iface, dir, sysfs_prop); - s = g_strdup_printf ("%u", uval); - /* FIXME: how should failure be handled? */ - nm_utils_do_sysctl (path, s); - g_free (path); - g_free (s); -} - -static NMActStageReturn -act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason) -{ - NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS; - NMConnection *connection; - NMSettingBridge *s_bridge; - const char *iface; - - g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); - - ret = NM_DEVICE_CLASS (nm_device_bridge_parent_class)->act_stage1_prepare (dev, reason); - if (ret == NM_ACT_STAGE_RETURN_SUCCESS) { - connection = nm_device_get_connection (dev); - g_assert (connection); - - s_bridge = nm_connection_get_setting_bridge (connection); - g_assert (s_bridge); - - iface = nm_device_get_ip_iface (dev); - g_assert (iface); - - set_sysfs_uint (iface, G_OBJECT (s_bridge), NM_SETTING_BRIDGE_STP, "bridge", "stp_state", FALSE, FALSE); - set_sysfs_uint (iface, G_OBJECT (s_bridge), NM_SETTING_BRIDGE_PRIORITY, "bridge", "priority", TRUE, FALSE); - set_sysfs_uint (iface, G_OBJECT (s_bridge), NM_SETTING_BRIDGE_FORWARD_DELAY, "bridge", "forward_delay", TRUE, TRUE); - set_sysfs_uint (iface, G_OBJECT (s_bridge), NM_SETTING_BRIDGE_HELLO_TIME, "bridge", "hello_time", TRUE, TRUE); - set_sysfs_uint (iface, G_OBJECT (s_bridge), NM_SETTING_BRIDGE_MAX_AGE, "bridge", "max_age", TRUE, TRUE); - set_sysfs_uint (iface, G_OBJECT (s_bridge), NM_SETTING_BRIDGE_AGEING_TIME, "bridge", "ageing_time", TRUE, TRUE); - } - return ret; -} - -static gboolean -enslave_slave (NMDevice *device, NMDevice *slave, NMConnection *connection) -{ - gboolean success; - NMSettingBridgePort *s_port; - const char *iface = nm_device_get_ip_iface (device); - const char *slave_iface = nm_device_get_ip_iface (slave); - - success = nm_system_bridge_attach (nm_device_get_ip_ifindex (device), - iface, - nm_device_get_ip_ifindex (slave), - slave_iface); - if (!success) - return FALSE; - - /* Set port properties */ - s_port = nm_connection_get_setting_bridge_port (connection); - if (s_port) { - set_sysfs_uint (slave_iface, G_OBJECT (s_port), NM_SETTING_BRIDGE_PORT_PRIORITY, "brport", "priority", TRUE, FALSE); - set_sysfs_uint (slave_iface, G_OBJECT (s_port), NM_SETTING_BRIDGE_PORT_PATH_COST, "brport", "path_cost", TRUE, FALSE); - set_sysfs_uint (slave_iface, G_OBJECT (s_port), NM_SETTING_BRIDGE_PORT_HAIRPIN_MODE, "brport", "hairpin_mode", FALSE, FALSE); - } - - nm_log_info (LOGD_BRIDGE, "(%s): attached bridge port %s", iface, slave_iface); - - g_object_notify (G_OBJECT (device), NM_DEVICE_BRIDGE_SLAVES); - - return TRUE; -} - -static gboolean -release_slave (NMDevice *device, NMDevice *slave) -{ - gboolean success; - - success = nm_system_bridge_detach (nm_device_get_ip_ifindex (device), - nm_device_get_ip_iface (device), - nm_device_get_ip_ifindex (slave), - nm_device_get_ip_iface (slave)); - nm_log_info (LOGD_BRIDGE, "(%s): detached bridge port %s (success %d)", - nm_device_get_ip_iface (device), - nm_device_get_ip_iface (slave), - success); - g_object_notify (G_OBJECT (device), NM_DEVICE_BRIDGE_SLAVES); - return success; -} - -/******************************************************************/ - -NMDevice * -nm_device_bridge_new (const char *udi, const char *iface) -{ - g_return_val_if_fail (udi != NULL, NULL); - g_return_val_if_fail (iface != NULL, NULL); - - return (NMDevice *) g_object_new (NM_TYPE_DEVICE_BRIDGE, - NM_DEVICE_UDI, udi, - NM_DEVICE_IFACE, iface, - NM_DEVICE_DRIVER, "bridge", - NM_DEVICE_TYPE_DESC, "Bridge", - NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_BRIDGE, - NM_DEVICE_IS_MASTER, TRUE, - NULL); -} - -static void -constructed (GObject *object) -{ - G_OBJECT_CLASS (nm_device_bridge_parent_class)->constructed (object); - - nm_log_dbg (LOGD_HW | LOGD_BRIDGE, "(%s): kernel ifindex %d", - nm_device_get_iface (NM_DEVICE (object)), - nm_device_get_ifindex (NM_DEVICE (object))); -} - -static void -nm_device_bridge_init (NMDeviceBridge * self) -{ -} - -static void -get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) -{ - NMDeviceBridgePrivate *priv = NM_DEVICE_BRIDGE_GET_PRIVATE (object); - GPtrArray *slaves; - GSList *list, *iter; - char *hwaddr; - - switch (prop_id) { - case PROP_HW_ADDRESS: - hwaddr = nm_utils_hwaddr_ntoa (priv->hw_addr, nm_utils_hwaddr_type (priv->hw_addr_len)); - g_value_take_string (value, hwaddr); - break; - case PROP_CARRIER: - g_value_set_boolean (value, nm_device_wired_get_carrier (NM_DEVICE_WIRED (object))); - break; - case PROP_SLAVES: - slaves = g_ptr_array_new (); - list = nm_device_master_get_slaves (NM_DEVICE (object)); - for (iter = list; iter; iter = iter->next) - g_ptr_array_add (slaves, g_strdup (nm_device_get_path (NM_DEVICE (iter->data)))); - g_slist_free (list); - g_value_take_boxed (value, slaves); - 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) -{ - switch (prop_id) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -nm_device_bridge_class_init (NMDeviceBridgeClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass); - NMDeviceWiredClass *wired_class = NM_DEVICE_WIRED_CLASS (klass); - - g_type_class_add_private (object_class, sizeof (NMDeviceBridgePrivate)); - - /* virtual methods */ - object_class->constructed = constructed; - object_class->get_property = get_property; - object_class->set_property = set_property; - - parent_class->get_generic_capabilities = get_generic_capabilities; - parent_class->update_hw_address = update_hw_address; - parent_class->get_hw_address = get_hw_address; - parent_class->is_available = is_available; - parent_class->get_best_auto_connection = get_best_auto_connection; - parent_class->check_connection_compatible = check_connection_compatible; - parent_class->complete_connection = complete_connection; - - parent_class->spec_match_list = spec_match_list; - parent_class->connection_match_config = connection_match_config; - - parent_class->act_stage1_prepare = act_stage1_prepare; - parent_class->enslave_slave = enslave_slave; - parent_class->release_slave = release_slave; - - wired_class->carrier_action = carrier_action; - - /* properties */ - g_object_class_install_property - (object_class, PROP_HW_ADDRESS, - g_param_spec_string (NM_DEVICE_BRIDGE_HW_ADDRESS, - "Active MAC Address", - "Currently set hardware MAC address", - NULL, - G_PARAM_READABLE)); - - g_object_class_install_property - (object_class, PROP_CARRIER, - g_param_spec_boolean (NM_DEVICE_BRIDGE_CARRIER, - "Carrier", - "Carrier", - FALSE, - G_PARAM_READABLE)); - - g_object_class_install_property - (object_class, PROP_SLAVES, - g_param_spec_boxed (NM_DEVICE_BRIDGE_SLAVES, - "Slaves", - "Slaves", - DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH, - G_PARAM_READABLE)); - - /* Signals */ - signals[PROPERTIES_CHANGED] = - nm_properties_changed_signal_new (object_class, - G_STRUCT_OFFSET (NMDeviceBridgeClass, properties_changed)); - - dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass), - &dbus_glib_nm_device_bridge_object_info); - - dbus_g_error_domain_register (NM_BRIDGE_ERROR, NULL, NM_TYPE_BRIDGE_ERROR); -} diff --git a/src/nm-device-bridge.h b/src/nm-device-bridge.h deleted file mode 100644 index bf0ed01e..00000000 --- a/src/nm-device-bridge.h +++ /dev/null @@ -1,66 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2012 Red Hat, Inc. - */ - -#ifndef NM_DEVICE_BRIDGE_H -#define NM_DEVICE_BRIDGE_H - -#include - -#include "nm-device-wired.h" - -G_BEGIN_DECLS - -#define NM_TYPE_DEVICE_BRIDGE (nm_device_bridge_get_type ()) -#define NM_DEVICE_BRIDGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_BRIDGE, NMDeviceBridge)) -#define NM_DEVICE_BRIDGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_BRIDGE, NMDeviceBridgeClass)) -#define NM_IS_DEVICE_BRIDGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_BRIDGE)) -#define NM_IS_DEVICE_BRIDGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_BRIDGE)) -#define NM_DEVICE_BRIDGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_BRIDGE, NMDeviceBridgeClass)) - -typedef enum { - NM_BRIDGE_ERROR_CONNECTION_NOT_BRIDGE = 0, /*< nick=ConnectionNotBridge >*/ - NM_BRIDGE_ERROR_CONNECTION_INVALID, /*< nick=ConnectionInvalid >*/ - NM_BRIDGE_ERROR_CONNECTION_INCOMPATIBLE, /*< nick=ConnectionIncompatible >*/ -} NMBridgeError; - -#define NM_DEVICE_BRIDGE_HW_ADDRESS "hw-address" -#define NM_DEVICE_BRIDGE_CARRIER "carrier" -#define NM_DEVICE_BRIDGE_SLAVES "slaves" - -typedef struct { - NMDeviceWired parent; -} NMDeviceBridge; - -typedef struct { - NMDeviceWiredClass parent; - - /* Signals */ - void (*properties_changed) (NMDeviceBridge *device, GHashTable *properties); -} NMDeviceBridgeClass; - - -GType nm_device_bridge_get_type (void); - -NMDevice *nm_device_bridge_new (const char *udi, - const char *iface); - -G_END_DECLS - -#endif /* NM_DEVICE_BRIDGE_H */ diff --git a/src/nm-device-bt.c b/src/nm-device-bt.c deleted file mode 100644 index e0aa4678..00000000 --- a/src/nm-device-bt.c +++ /dev/null @@ -1,1311 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2009 - 2011 Red Hat, Inc. - */ - -#include "config.h" - -#include -#include -#include -#include - -#include -#include - -#include "nm-glib-compat.h" -#include "nm-bluez-common.h" -#include "nm-bluez-device.h" -#include "nm-dbus-manager.h" -#include "nm-device-bt.h" -#include "nm-device-private.h" -#include "nm-logging.h" -#include "nm-marshal.h" -#include "ppp-manager/nm-ppp-manager.h" -#include "nm-properties-changed-signal.h" -#include "nm-setting-connection.h" -#include "nm-setting-bluetooth.h" -#include "nm-setting-cdma.h" -#include "nm-setting-gsm.h" -#include "nm-setting-serial.h" -#include "nm-setting-ppp.h" -#include "nm-device-bt-glue.h" -#include "NetworkManagerUtils.h" -#include "nm-enum-types.h" -#include "nm-utils.h" - -#define MM_OLD_DBUS_SERVICE "org.freedesktop.ModemManager" -#define MM_NEW_DBUS_SERVICE "org.freedesktop.ModemManager1" - -G_DEFINE_TYPE (NMDeviceBt, nm_device_bt, NM_TYPE_DEVICE) - -#define NM_DEVICE_BT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_BT, NMDeviceBtPrivate)) - -static gboolean modem_stage1 (NMDeviceBt *self, NMModem *modem, NMDeviceStateReason *reason); - -typedef struct { - NMDBusManager *dbus_mgr; - guint mm_watch_id; - gboolean mm_running; - - NMBluezDevice *bt_device; - - guint8 hw_addr[ETH_ALEN]; /* binary representation of bdaddr */ - char *bdaddr; - char *name; - guint32 capabilities; - - gboolean connected; - gboolean have_iface; - - char *rfcomm_iface; - NMModem *modem; - guint32 timeout_id; - - guint32 bt_type; /* BT type of the current connection */ -} NMDeviceBtPrivate; - -enum { - PROP_0, - PROP_HW_ADDRESS, - PROP_BT_NAME, - PROP_BT_CAPABILITIES, - PROP_BT_DEVICE, - - LAST_PROP -}; - -enum { - PPP_STATS, - PROPERTIES_CHANGED, - - LAST_SIGNAL -}; -static guint signals[LAST_SIGNAL] = { 0 }; - - -#define NM_BT_ERROR (nm_bt_error_quark ()) - -static GQuark -nm_bt_error_quark (void) -{ - static GQuark quark = 0; - if (!quark) - quark = g_quark_from_static_string ("nm-bt-error"); - return quark; -} - -guint32 nm_device_bt_get_capabilities (NMDeviceBt *self) -{ - g_return_val_if_fail (self != NULL, NM_BT_CAPABILITY_NONE); - g_return_val_if_fail (NM_IS_DEVICE_BT (self), NM_BT_CAPABILITY_NONE); - - return NM_DEVICE_BT_GET_PRIVATE (self)->capabilities; -} - -static guint32 -get_connection_bt_type (NMConnection *connection) -{ - NMSettingBluetooth *s_bt; - const char *bt_type; - - s_bt = nm_connection_get_setting_bluetooth (connection); - if (!s_bt) - return NM_BT_CAPABILITY_NONE; - - bt_type = nm_setting_bluetooth_get_connection_type (s_bt); - g_assert (bt_type); - - if (!strcmp (bt_type, NM_SETTING_BLUETOOTH_TYPE_DUN)) - return NM_BT_CAPABILITY_DUN; - else if (!strcmp (bt_type, NM_SETTING_BLUETOOTH_TYPE_PANU)) - return NM_BT_CAPABILITY_NAP; - - return NM_BT_CAPABILITY_NONE; -} - -static NMConnection * -get_best_auto_connection (NMDevice *device, - GSList *connections, - char **specific_object) -{ - NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device); - GSList *iter; - - for (iter = connections; iter; iter = g_slist_next (iter)) { - NMConnection *connection = NM_CONNECTION (iter->data); - guint32 bt_type; - - if (!nm_connection_is_type (connection, NM_SETTING_BLUETOOTH_SETTING_NAME)) - continue; - - bt_type = get_connection_bt_type (connection); - if (!(bt_type & priv->capabilities)) - continue; - - /* Can't auto-activate a DUN connection without ModemManager */ - if (bt_type == NM_BT_CAPABILITY_DUN && priv->mm_running == FALSE) - continue; - - return connection; - } - return NULL; -} - -static gboolean -check_connection_compatible (NMDevice *device, - NMConnection *connection, - GError **error) -{ - NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device); - NMSettingConnection *s_con; - NMSettingBluetooth *s_bt; - const GByteArray *array; - char *str; - int addr_match = FALSE; - guint32 bt_type; - - s_con = nm_connection_get_setting_connection (connection); - g_assert (s_con); - - if (strcmp (nm_setting_connection_get_connection_type (s_con), NM_SETTING_BLUETOOTH_SETTING_NAME)) { - g_set_error (error, - NM_BT_ERROR, NM_BT_ERROR_CONNECTION_NOT_BT, - "The connection was not a Bluetooth connection."); - return FALSE; - } - - s_bt = nm_connection_get_setting_bluetooth (connection); - if (!s_bt) { - g_set_error (error, - NM_BT_ERROR, NM_BT_ERROR_CONNECTION_INVALID, - "The connection was not a valid Bluetooth connection."); - return FALSE; - } - - array = nm_setting_bluetooth_get_bdaddr (s_bt); - if (!array || (array->len != ETH_ALEN)) { - g_set_error (error, - NM_BT_ERROR, NM_BT_ERROR_CONNECTION_INVALID, - "The connection did not contain a valid Bluetooth address."); - return FALSE; - } - - bt_type = get_connection_bt_type (connection); - if (!(bt_type & priv->capabilities)) { - g_set_error (error, - NM_BT_ERROR, NM_BT_ERROR_CONNECTION_INCOMPATIBLE, - "The connection was not compatible with the device's capabilities."); - return FALSE; - } - - str = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X", - array->data[0], array->data[1], array->data[2], - array->data[3], array->data[4], array->data[5]); - addr_match = !strcmp (priv->bdaddr, str); - g_free (str); - - return addr_match; -} - -static gboolean -check_connection_available (NMDevice *device, NMConnection *connection) -{ - NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device); - guint32 bt_type; - - bt_type = get_connection_bt_type (connection); - if (!(bt_type & priv->capabilities)) - return FALSE; - - /* DUN connections aren't available without ModemManager */ - if (bt_type == NM_BT_CAPABILITY_DUN && priv->mm_running == FALSE) - return FALSE; - - return TRUE; -} - -static gboolean -complete_connection (NMDevice *device, - NMConnection *connection, - const char *specific_object, - const GSList *existing_connections, - GError **error) -{ - NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device); - NMSettingBluetooth *s_bt; - const GByteArray *setting_bdaddr; - struct ether_addr *devaddr = ether_aton (priv->bdaddr); - const char *ctype; - gboolean is_dun = FALSE, is_pan = FALSE; - NMSettingGsm *s_gsm; - NMSettingCdma *s_cdma; - NMSettingSerial *s_serial; - NMSettingPPP *s_ppp; - const char *format = NULL, *preferred = NULL; - - s_gsm = nm_connection_get_setting_gsm (connection); - s_cdma = nm_connection_get_setting_cdma (connection); - s_serial = nm_connection_get_setting_serial (connection); - s_ppp = nm_connection_get_setting_ppp (connection); - - s_bt = nm_connection_get_setting_bluetooth (connection); - if (!s_bt) { - s_bt = (NMSettingBluetooth *) nm_setting_bluetooth_new (); - nm_connection_add_setting (connection, NM_SETTING (s_bt)); - } - - ctype = nm_setting_bluetooth_get_connection_type (s_bt); - if (ctype) { - if (!strcmp (ctype, NM_SETTING_BLUETOOTH_TYPE_DUN)) - is_dun = TRUE; - else if (!strcmp (ctype, NM_SETTING_BLUETOOTH_TYPE_PANU)) - is_pan = TRUE; - } else { - if (s_gsm || s_cdma) - is_dun = TRUE; - else if (priv->capabilities & NM_BT_CAPABILITY_NAP) - is_pan = TRUE; - } - - if (is_pan) { - /* Make sure the device supports PAN */ - if (!(priv->capabilities & NM_BT_CAPABILITY_NAP)) { - g_set_error_literal (error, - NM_SETTING_BLUETOOTH_ERROR, - NM_SETTING_BLUETOOTH_ERROR_INVALID_PROPERTY, - "PAN required but Bluetooth device does not support NAP"); - return FALSE; - } - - /* PAN can't use any DUN-related settings */ - if (s_gsm || s_cdma || s_serial || s_ppp) { - g_set_error_literal (error, - NM_SETTING_BLUETOOTH_ERROR, - NM_SETTING_BLUETOOTH_ERROR_INVALID_PROPERTY, - "PAN incompatible with GSM, CDMA, or serial settings"); - return FALSE; - } - - g_object_set (G_OBJECT (s_bt), - NM_SETTING_BLUETOOTH_TYPE, NM_SETTING_BLUETOOTH_TYPE_PANU, - NULL); - - format = _("PAN connection %d"); - } else if (is_dun) { - /* Make sure the device supports PAN */ - if (!(priv->capabilities & NM_BT_CAPABILITY_DUN)) { - g_set_error_literal (error, - NM_SETTING_BLUETOOTH_ERROR, - NM_SETTING_BLUETOOTH_ERROR_INVALID_PROPERTY, - "DUN required but Bluetooth device does not support DUN"); - return FALSE; - } - - /* Need at least a GSM or a CDMA setting */ - if (!s_gsm && !s_cdma) { - g_set_error_literal (error, - NM_SETTING_BLUETOOTH_ERROR, - NM_SETTING_BLUETOOTH_ERROR_INVALID_PROPERTY, - "Setting requires DUN but no GSM or CDMA setting is present"); - return FALSE; - } - - g_object_set (G_OBJECT (s_bt), - NM_SETTING_BLUETOOTH_TYPE, NM_SETTING_BLUETOOTH_TYPE_DUN, - NULL); - - if (s_gsm) { - format = _("GSM connection %d"); - if (!nm_setting_gsm_get_number (s_gsm)) - g_object_set (G_OBJECT (s_gsm), NM_SETTING_GSM_NUMBER, "*99#", NULL); - } else if (s_cdma) { - format = _("CDMA connection %d"); - if (!nm_setting_cdma_get_number (s_cdma)) - g_object_set (G_OBJECT (s_cdma), NM_SETTING_GSM_NUMBER, "#777", NULL); - } else - format = _("DUN connection %d"); - } else { - g_set_error_literal (error, - NM_SETTING_BLUETOOTH_ERROR, - NM_SETTING_BLUETOOTH_ERROR_INVALID_PROPERTY, - "Unknown/unhandled Bluetooth connection type"); - return FALSE; - } - - nm_utils_complete_generic (connection, - NM_SETTING_BLUETOOTH_SETTING_NAME, - existing_connections, - format, - preferred, - is_dun ? FALSE : TRUE); /* No IPv6 yet for DUN */ - - setting_bdaddr = nm_setting_bluetooth_get_bdaddr (s_bt); - if (setting_bdaddr) { - /* Make sure the setting BT Address (if any) matches the device's */ - if (memcmp (setting_bdaddr->data, devaddr->ether_addr_octet, ETH_ALEN)) { - g_set_error_literal (error, - NM_SETTING_BLUETOOTH_ERROR, - NM_SETTING_BLUETOOTH_ERROR_INVALID_PROPERTY, - NM_SETTING_BLUETOOTH_BDADDR); - return FALSE; - } - } else { - GByteArray *bdaddr; - const guint8 null_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; - - /* Lock the connection to this device by default */ - if (memcmp (devaddr->ether_addr_octet, null_mac, ETH_ALEN)) { - bdaddr = g_byte_array_sized_new (ETH_ALEN); - g_byte_array_append (bdaddr, devaddr->ether_addr_octet, ETH_ALEN); - g_object_set (G_OBJECT (s_bt), NM_SETTING_BLUETOOTH_BDADDR, bdaddr, NULL); - g_byte_array_free (bdaddr, TRUE); - } - } - - return TRUE; -} - -static guint32 -get_generic_capabilities (NMDevice *dev) -{ - return NM_DEVICE_CAP_NM_SUPPORTED; -} - -static const guint8 * -get_hw_address (NMDevice *device, guint *out_len) -{ - NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device); - - *out_len = sizeof (priv->hw_addr); - return priv->hw_addr; -} - -static gboolean -hwaddr_matches (NMDevice *device, - NMConnection *connection, - const guint8 *other_hwaddr, - guint other_hwaddr_len, - gboolean fail_if_no_hwaddr) -{ - NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device); - NMSettingBluetooth *s_bt; - const GByteArray *mac = NULL; - gboolean matches = FALSE; - GByteArray *devmac; - - s_bt = nm_connection_get_setting_bluetooth (connection); - if (s_bt) - mac = nm_setting_bluetooth_get_bdaddr (s_bt); - - if (mac) { - devmac = nm_utils_hwaddr_atoba (priv->bdaddr, ARPHRD_ETHER); - g_return_val_if_fail (devmac != NULL, FALSE); - g_return_val_if_fail (devmac->len == mac->len, FALSE); - - if (other_hwaddr) { - g_return_val_if_fail (other_hwaddr_len == devmac->len, FALSE); - matches = (memcmp (mac->data, other_hwaddr, mac->len) == 0) ? TRUE : FALSE; - } else - matches = (memcmp (mac->data, devmac->data, mac->len) == 0) ? TRUE : FALSE; - - g_byte_array_free (devmac, TRUE); - return matches; - } else if (fail_if_no_hwaddr == FALSE) - return TRUE; - - return FALSE; -} - -/*****************************************************************************/ -/* IP method PPP */ - -static void -ppp_stats (NMModem *modem, - guint32 in_bytes, - guint32 out_bytes, - gpointer user_data) -{ - g_signal_emit (NM_DEVICE_BT (user_data), signals[PPP_STATS], 0, in_bytes, out_bytes); -} - -static void -ppp_failed (NMModem *modem, NMDeviceStateReason reason, gpointer user_data) -{ - NMDevice *device = NM_DEVICE (user_data); - - switch (nm_device_get_state (device)) { - case NM_DEVICE_STATE_PREPARE: - case NM_DEVICE_STATE_CONFIG: - case NM_DEVICE_STATE_NEED_AUTH: - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, reason); - break; - case NM_DEVICE_STATE_IP_CONFIG: - case NM_DEVICE_STATE_IP_CHECK: - case NM_DEVICE_STATE_SECONDARIES: - case NM_DEVICE_STATE_ACTIVATED: - if (nm_device_activate_ip4_state_in_conf (device)) - nm_device_activate_schedule_ip4_config_timeout (device); - else { - nm_device_state_changed (device, - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); - } - break; - default: - break; - } -} - -static void -modem_auth_requested (NMModem *modem, gpointer user_data) -{ - nm_device_state_changed (NM_DEVICE (user_data), - NM_DEVICE_STATE_NEED_AUTH, - NM_DEVICE_STATE_REASON_NONE); -} - -static void -modem_auth_result (NMModem *modem, GError *error, gpointer user_data) -{ - NMDevice *device = NM_DEVICE (user_data); - NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device); - NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; - - if (error) { - nm_device_state_changed (device, - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_NO_SECRETS); - } else { - /* Otherwise, on success for GSM/CDMA secrets we need to schedule modem stage1 again */ - g_return_if_fail (nm_device_get_state (device) == NM_DEVICE_STATE_NEED_AUTH); - if (!modem_stage1 (NM_DEVICE_BT (device), priv->modem, &reason)) - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, reason); - } -} - -static void -modem_prepare_result (NMModem *modem, - gboolean success, - NMDeviceStateReason reason, - gpointer user_data) -{ - NMDevice *device = NM_DEVICE (user_data); - NMDeviceState state; - - state = nm_device_get_state (device); - g_return_if_fail (state == NM_DEVICE_STATE_CONFIG || state == NM_DEVICE_STATE_NEED_AUTH); - - if (success) { - NMActRequest *req; - NMActStageReturn ret; - NMDeviceStateReason stage2_reason = NM_DEVICE_STATE_REASON_NONE; - - req = nm_device_get_act_request (device); - g_assert (req); - - ret = nm_modem_act_stage2_config (modem, req, &stage2_reason); - switch (ret) { - case NM_ACT_STAGE_RETURN_POSTPONE: - break; - case NM_ACT_STAGE_RETURN_SUCCESS: - nm_device_activate_schedule_stage3_ip_config_start (device); - break; - case NM_ACT_STAGE_RETURN_FAILURE: - default: - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, stage2_reason); - break; - } - } else - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, reason); -} - -static void -device_state_changed (NMDevice *device, - NMDeviceState new_state, - NMDeviceState old_state, - NMDeviceStateReason reason) -{ - NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device); - - if (priv->modem) - nm_modem_device_state_changed (priv->modem, new_state, old_state, reason); -} - -static void -modem_ip4_config_result (NMModem *self, - NMIP4Config *config, - GError *error, - gpointer user_data) -{ - NMDevice *device = NM_DEVICE (user_data); - - g_return_if_fail (nm_device_activate_ip4_state_in_conf (device) == TRUE); - - if (error) { - nm_log_warn (LOGD_MB | LOGD_IP4 | LOGD_BT, - "(%s): retrieving IP4 configuration failed: (%d) %s", - nm_device_get_ip_iface (device), - error ? error->code : -1, - error && error->message ? error->message : "(unknown)"); - - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); - } else - nm_device_activate_schedule_ip4_config_result (device, config); -} - -static void -data_port_changed_cb (NMModem *modem, GParamSpec *pspec, gpointer user_data) -{ - NMDevice *self = NM_DEVICE (user_data); - - nm_device_set_ip_iface (self, nm_modem_get_data_port (modem)); -} - -static gboolean -modem_stage1 (NMDeviceBt *self, NMModem *modem, NMDeviceStateReason *reason) -{ - NMActRequest *req; - NMActStageReturn ret; - - g_return_val_if_fail (reason != NULL, FALSE); - - req = nm_device_get_act_request (NM_DEVICE (self)); - g_assert (req); - - ret = nm_modem_act_stage1_prepare (modem, req, reason); - switch (ret) { - case NM_ACT_STAGE_RETURN_POSTPONE: - case NM_ACT_STAGE_RETURN_SUCCESS: - /* Success, wait for the 'prepare-result' signal */ - return TRUE; - case NM_ACT_STAGE_RETURN_FAILURE: - default: - break; - } - - return FALSE; -} - -/*****************************************************************************/ - -gboolean -nm_device_bt_modem_added (NMDeviceBt *self, - NMModem *modem, - const char *driver) -{ - NMDeviceBtPrivate *priv; - const gchar *modem_data_port; - const gchar *modem_control_port; - char *base; - NMDeviceState state; - NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; - - g_return_val_if_fail (self != NULL, FALSE); - g_return_val_if_fail (NM_IS_DEVICE_BT (self), FALSE); - g_return_val_if_fail (modem != NULL, FALSE); - g_return_val_if_fail (NM_IS_MODEM (modem), FALSE); - - priv = NM_DEVICE_BT_GET_PRIVATE (self); - modem_data_port = nm_modem_get_data_port (modem); - modem_control_port = nm_modem_get_control_port (modem); - g_return_val_if_fail (modem_data_port != NULL || modem_control_port != NULL, FALSE); - - if (!priv->rfcomm_iface) - return FALSE; - - base = g_path_get_basename (priv->rfcomm_iface); - if (g_strcmp0 (base, modem_data_port) && g_strcmp0 (base, modem_control_port)) { - g_free (base); - return FALSE; - } - g_free (base); - - /* Got the modem */ - if (priv->timeout_id) { - g_source_remove (priv->timeout_id); - priv->timeout_id = 0; - } - - /* Can only accept the modem in stage2, but since the interface matched - * what we were expecting, don't let anything else claim the modem either. - */ - state = nm_device_get_state (NM_DEVICE (self)); - if (state != NM_DEVICE_STATE_CONFIG) { - nm_log_warn (LOGD_BT | LOGD_MB, - "(%s): modem found but device not in correct state (%d)", - nm_device_get_iface (NM_DEVICE (self)), - nm_device_get_state (NM_DEVICE (self))); - return TRUE; - } - - nm_log_info (LOGD_BT | LOGD_MB, - "Activation (%s/bluetooth) Stage 2 of 5 (Device Configure) modem found.", - nm_device_get_iface (NM_DEVICE (self))); - - if (priv->modem) { - g_warn_if_reached (); - g_object_unref (priv->modem); - } - - priv->modem = g_object_ref (modem); - g_signal_connect (modem, NM_MODEM_PPP_STATS, G_CALLBACK (ppp_stats), self); - g_signal_connect (modem, NM_MODEM_PPP_FAILED, G_CALLBACK (ppp_failed), self); - g_signal_connect (modem, NM_MODEM_PREPARE_RESULT, G_CALLBACK (modem_prepare_result), self); - g_signal_connect (modem, NM_MODEM_IP4_CONFIG_RESULT, G_CALLBACK (modem_ip4_config_result), self); - g_signal_connect (modem, NM_MODEM_AUTH_REQUESTED, G_CALLBACK (modem_auth_requested), self); - g_signal_connect (modem, NM_MODEM_AUTH_RESULT, G_CALLBACK (modem_auth_result), self); - - /* In the old ModemManager the data port is known from the very beginning; - * while in the new ModemManager the data port is set afterwards when the bearer gets - * created */ - if (modem_data_port) - nm_device_set_ip_iface (NM_DEVICE (self), modem_data_port); - g_signal_connect (modem, "notify::" NM_MODEM_DATA_PORT, G_CALLBACK (data_port_changed_cb), self); - - /* Kick off the modem connection */ - if (!modem_stage1 (self, modem, &reason)) - nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_FAILED, reason); - - return TRUE; -} - -gboolean -nm_device_bt_modem_removed (NMDeviceBt *self, NMModem *modem) -{ - NMDeviceBtPrivate *priv; - NMDeviceState state; - - g_return_val_if_fail (self != NULL, FALSE); - g_return_val_if_fail (NM_IS_DEVICE_BT (self), FALSE); - g_return_val_if_fail (modem != NULL, FALSE); - g_return_val_if_fail (NM_IS_MODEM (modem), FALSE); - - priv = NM_DEVICE_BT_GET_PRIVATE (self); - - if (modem != priv->modem) - return FALSE; - - /* Fail the device if the modem was removed while active */ - state = nm_device_get_state (NM_DEVICE (self)); - if ( state == NM_DEVICE_STATE_ACTIVATED - || nm_device_is_activating (NM_DEVICE (self))) { - nm_device_state_changed (NM_DEVICE (self), - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_BT_FAILED); - } else { - g_object_unref (priv->modem); - priv->modem = NULL; - } - - return TRUE; -} - -static gboolean -modem_find_timeout (gpointer user_data) -{ - NMDeviceBt *self = NM_DEVICE_BT (user_data); - - NM_DEVICE_BT_GET_PRIVATE (self)->timeout_id = 0; - nm_device_state_changed (NM_DEVICE (self), - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_MODEM_NOT_FOUND); - return FALSE; -} - -static void -check_connect_continue (NMDeviceBt *self) -{ - NMDevice *device = NM_DEVICE (self); - NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self); - gboolean pan = (priv->bt_type == NM_BT_CAPABILITY_NAP); - gboolean dun = (priv->bt_type == NM_BT_CAPABILITY_DUN); - - if (!priv->connected || !priv->have_iface) - return; - - nm_log_info (LOGD_BT, "Activation (%s %s/bluetooth) Stage 2 of 5 (Device Configure) " - "successful. Will connect via %s.", - nm_device_get_iface (device), - nm_device_get_ip_iface (device), - dun ? "DUN" : (pan ? "PAN" : "unknown")); - - /* Kill the connect timeout since we're connected now */ - if (priv->timeout_id) { - g_source_remove (priv->timeout_id); - priv->timeout_id = 0; - } - - if (pan) { - /* Bluez says we're connected now. Start IP config. */ - nm_device_activate_schedule_stage3_ip_config_start (device); - } else if (dun) { - /* Wait for ModemManager to find the modem */ - priv->timeout_id = g_timeout_add_seconds (30, modem_find_timeout, self); - - nm_log_info (LOGD_BT | LOGD_MB, "Activation (%s/bluetooth) Stage 2 of 5 (Device Configure) " - "waiting for modem to appear.", - nm_device_get_iface (device)); - } else - g_assert_not_reached (); -} - -static void -bluez_connect_cb (GObject *object, - GAsyncResult *res, - void *user_data) -{ - NMDeviceBt *self = NM_DEVICE_BT (user_data); - NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self); - GError *error = NULL; - const char *device; - - device = nm_bluez_device_connect_finish (NM_BLUEZ_DEVICE (object), - res, &error); - - if (!device) { - nm_log_warn (LOGD_BT, "Error connecting with bluez: %s", - error && error->message ? error->message : "(unknown)"); - g_clear_error (&error); - - nm_device_state_changed (NM_DEVICE (self), - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_BT_FAILED); - return; - } - - if (priv->bt_type == NM_BT_CAPABILITY_DUN) { - g_free (priv->rfcomm_iface); - priv->rfcomm_iface = g_strdup (device); - } else if (priv->bt_type == NM_BT_CAPABILITY_NAP) { - nm_device_set_ip_iface (NM_DEVICE (self), device); - } - - nm_log_dbg (LOGD_BT, "(%s): connect request successful", - nm_device_get_iface (NM_DEVICE (self))); - - /* Stage 3 gets scheduled when Bluez says we're connected */ - priv->have_iface = TRUE; - check_connect_continue (self); -} - -static void -bluez_connected_changed (NMBluezDevice *bt_device, - GParamSpec *pspec, - NMDevice *device) -{ - NMDeviceBt *self = NM_DEVICE_BT (device); - NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self); - gboolean connected; - NMDeviceState state; - - state = nm_device_get_state (device); - connected = nm_bluez_device_get_connected (bt_device); - if (connected) { - if (state == NM_DEVICE_STATE_CONFIG) { - nm_log_dbg (LOGD_BT, "(%s): connected to the device", - nm_device_get_iface (device)); - - priv->connected = TRUE; - check_connect_continue (self); - } - } else { - gboolean fail = FALSE; - - /* Bluez says we're disconnected from the device. Suck. */ - - if (nm_device_is_activating (device)) { - nm_log_info (LOGD_BT, - "Activation (%s/bluetooth): bluetooth link disconnected.", - nm_device_get_iface (device)); - fail = TRUE; - } else if (state == NM_DEVICE_STATE_ACTIVATED) { - nm_log_info (LOGD_BT, "(%s): bluetooth link disconnected.", - nm_device_get_iface (device)); - fail = TRUE; - } - - if (fail) { - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_CARRIER); - priv->connected = FALSE; - } - } -} - -static gboolean -bt_connect_timeout (gpointer user_data) -{ - NMDeviceBt *self = NM_DEVICE_BT (user_data); - - nm_log_dbg (LOGD_BT, "(%s): initial connection timed out", - nm_device_get_iface (NM_DEVICE (self))); - - NM_DEVICE_BT_GET_PRIVATE (self)->timeout_id = 0; - nm_device_state_changed (NM_DEVICE (self), - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_BT_FAILED); - return FALSE; -} - -static NMActStageReturn -act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) -{ - NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device); - NMConnection *connection; - - connection = nm_device_get_connection (device); - g_assert (connection); - priv->bt_type = get_connection_bt_type (connection); - if (priv->bt_type == NM_BT_CAPABILITY_NONE) { - // FIXME: set a reason code - return NM_ACT_STAGE_RETURN_FAILURE; - } - - if (priv->bt_type == NM_BT_CAPABILITY_DUN && !priv->mm_running) { - *reason = NM_DEVICE_STATE_REASON_MODEM_MANAGER_UNAVAILABLE; - return NM_ACT_STAGE_RETURN_FAILURE; - } - - nm_log_dbg (LOGD_BT, "(%s): requesting connection to the device", - nm_device_get_iface (device)); - - /* Connect to the BT device */ - nm_bluez_device_connect_async (priv->bt_device, - priv->bt_type & (NM_BT_CAPABILITY_DUN | NM_BT_CAPABILITY_NAP), - bluez_connect_cb, device); - - if (priv->timeout_id) - g_source_remove (priv->timeout_id); - priv->timeout_id = g_timeout_add_seconds (30, bt_connect_timeout, device); - - return NM_ACT_STAGE_RETURN_POSTPONE; -} - -static NMActStageReturn -act_stage3_ip4_config_start (NMDevice *device, - NMIP4Config **out_config, - NMDeviceStateReason *reason) -{ - NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device); - NMActStageReturn ret; - - if (priv->bt_type == NM_BT_CAPABILITY_DUN) { - ret = nm_modem_stage3_ip4_config_start (NM_DEVICE_BT_GET_PRIVATE (device)->modem, - device, - NM_DEVICE_CLASS (nm_device_bt_parent_class), - reason); - } else - ret = NM_DEVICE_CLASS (nm_device_bt_parent_class)->act_stage3_ip4_config_start (device, out_config, reason); - - return ret; -} - -static NMActStageReturn -act_stage3_ip6_config_start (NMDevice *device, - NMIP6Config **out_config, - NMDeviceStateReason *reason) -{ - NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device); - NMActStageReturn ret; - - if (priv->bt_type == NM_BT_CAPABILITY_DUN) { - ret = nm_modem_stage3_ip6_config_start (NM_DEVICE_BT_GET_PRIVATE (device)->modem, - device, - NM_DEVICE_CLASS (nm_device_bt_parent_class), - reason); - } else - ret = NM_DEVICE_CLASS (nm_device_bt_parent_class)->act_stage3_ip6_config_start (device, out_config, reason); - - return ret; -} - -static void -deactivate (NMDevice *device) -{ - NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device); - - priv->have_iface = FALSE; - priv->connected = FALSE; - - if (priv->bt_type == NM_BT_CAPABILITY_DUN) { - if (priv->modem) { - nm_modem_deactivate (priv->modem, device); - - /* Since we're killing the Modem object before it'll get the - * state change signal, simulate the state change here. - */ - nm_modem_device_state_changed (priv->modem, - NM_DEVICE_STATE_DISCONNECTED, - NM_DEVICE_STATE_ACTIVATED, - NM_DEVICE_STATE_REASON_USER_REQUESTED); - g_object_unref (priv->modem); - priv->modem = NULL; - } - } - - if (priv->bt_type != NM_BT_CAPABILITY_NONE) - nm_bluez_device_disconnect (priv->bt_device); - - if (priv->timeout_id) { - g_source_remove (priv->timeout_id); - priv->timeout_id = 0; - } - - priv->bt_type = NM_BT_CAPABILITY_NONE; - - g_free (priv->rfcomm_iface); - priv->rfcomm_iface = NULL; - - if (NM_DEVICE_CLASS (nm_device_bt_parent_class)->deactivate) - NM_DEVICE_CLASS (nm_device_bt_parent_class)->deactivate (device); -} - -/*****************************************************************************/ - -static gboolean -is_available (NMDevice *dev) -{ - NMDeviceBt *self = NM_DEVICE_BT (dev); - NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self); - - /* PAN doesn't need ModemManager, so devices that support it are always available */ - if (priv->capabilities & NM_BT_CAPABILITY_NAP) - return TRUE; - - /* DUN requires ModemManager */ - return priv->mm_running; -} - -static void -handle_availability_change (NMDeviceBt *self, - gboolean old_available, - NMDeviceStateReason unavailable_reason) -{ - NMDevice *device = NM_DEVICE (self); - NMDeviceState state; - gboolean available; - - state = nm_device_get_state (device); - if (state < NM_DEVICE_STATE_UNAVAILABLE) { - nm_log_dbg (LOGD_BT, "(%s): availability blocked by UNMANAGED state", - nm_device_get_iface (device)); - return; - } - - available = nm_device_is_available (device); - if (available == old_available) - return; - - if (available) { - if (state != NM_DEVICE_STATE_UNAVAILABLE) - nm_log_warn (LOGD_CORE | LOGD_BT, "not in expected unavailable state!"); - - nm_device_state_changed (device, - NM_DEVICE_STATE_DISCONNECTED, - NM_DEVICE_STATE_REASON_NONE); - } else { - nm_device_state_changed (device, - NM_DEVICE_STATE_UNAVAILABLE, - unavailable_reason); - } -} - -static void -set_mm_running (NMDeviceBt *self, gboolean running) -{ - NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self); - gboolean old_available; - - if (priv->mm_running == running) - return; - - nm_log_dbg (LOGD_BT, "(%s): ModemManager now %s", - nm_device_get_iface (NM_DEVICE (self)), - running ? "available" : "unavailable"); - - old_available = nm_device_is_available (NM_DEVICE (self)); - priv->mm_running = running; - handle_availability_change (self, old_available, NM_DEVICE_STATE_REASON_MODEM_MANAGER_UNAVAILABLE); - - /* Need to recheck available connections whenever MM appears or disappears, - * since the device could be both DUN and NAP capable and thus may not - * change state (which rechecks available connections) when MM comes and goes. - */ - if (priv->capabilities & NM_BT_CAPABILITY_DUN) - nm_device_recheck_available_connections (NM_DEVICE (self)); -} - -static void -mm_name_owner_changed (NMDBusManager *dbus_mgr, - const char *name, - const char *old_owner, - const char *new_owner, - NMDeviceBt *self) -{ - gboolean old_owner_good; - gboolean new_owner_good; - - /* Can't handle the signal if its not from the modem service */ - if ( strcmp (MM_OLD_DBUS_SERVICE, name) != 0 -#if WITH_MODEM_MANAGER_1 - && strcmp (MM_NEW_DBUS_SERVICE, name) != 0 -#endif - ) - return; - - old_owner_good = (old_owner && strlen (old_owner)); - new_owner_good = (new_owner && strlen (new_owner)); - - if (!old_owner_good && new_owner_good) - set_mm_running (self, TRUE); - else if (old_owner_good && !new_owner_good) - set_mm_running (self, FALSE); -} - -/*****************************************************************************/ - -NMDevice * -nm_device_bt_new (NMBluezDevice *bt_device, - const char *udi, - const char *bdaddr, - const char *name, - guint32 capabilities, - gboolean managed) -{ - g_return_val_if_fail (udi != NULL, NULL); - g_return_val_if_fail (bdaddr != NULL, NULL); - g_return_val_if_fail (name != NULL, NULL); - g_return_val_if_fail (capabilities != NM_BT_CAPABILITY_NONE, NULL); - g_return_val_if_fail (NM_IS_BLUEZ_DEVICE (bt_device), NULL); - - return (NMDevice *) g_object_new (NM_TYPE_DEVICE_BT, - NM_DEVICE_UDI, udi, - NM_DEVICE_IFACE, bdaddr, - NM_DEVICE_DRIVER, "bluez", - NM_DEVICE_BT_HW_ADDRESS, bdaddr, - NM_DEVICE_BT_DEVICE, bt_device, - NM_DEVICE_BT_NAME, name, - NM_DEVICE_BT_CAPABILITIES, capabilities, - NM_DEVICE_MANAGED, managed, - NM_DEVICE_TYPE_DESC, "Bluetooth", - NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_BT, - NULL); -} - -static void -nm_device_bt_init (NMDeviceBt *self) -{ - NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self); - gboolean mm_running; - - priv->dbus_mgr = nm_dbus_manager_get (); - - priv->mm_watch_id = g_signal_connect (priv->dbus_mgr, - NM_DBUS_MANAGER_NAME_OWNER_CHANGED, - G_CALLBACK (mm_name_owner_changed), - self); - - /* Initial check to see if ModemManager is running */ - mm_running = nm_dbus_manager_name_has_owner (priv->dbus_mgr, MM_OLD_DBUS_SERVICE); -#if WITH_MODEM_MANAGER_1 - if (!mm_running) - mm_running = nm_dbus_manager_name_has_owner (priv->dbus_mgr, MM_NEW_DBUS_SERVICE); -#endif - set_mm_running (self, mm_running); -} - -static void -set_property (GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec) -{ - NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (object); - - switch (prop_id) { - case PROP_HW_ADDRESS: - /* Construct only */ - priv->bdaddr = g_ascii_strup (g_value_get_string (value), -1); - if (!nm_utils_hwaddr_aton (priv->bdaddr, ARPHRD_ETHER, &priv->hw_addr)) - nm_log_err (LOGD_HW, "Failed to convert BT address '%s'", priv->bdaddr); - break; - case PROP_BT_NAME: - /* Construct only */ - priv->name = g_value_dup_string (value); - break; - case PROP_BT_CAPABILITIES: - /* Construct only */ - priv->capabilities = g_value_get_uint (value); - break; - case PROP_BT_DEVICE: - /* Construct only */ - priv->bt_device = g_value_dup_object (value); - - /* Watch for BT device property changes */ - g_signal_connect (priv->bt_device, "notify::" NM_BLUEZ_DEVICE_CONNECTED, - G_CALLBACK (bluez_connected_changed), - object); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) -{ - NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (object); - - switch (prop_id) { - case PROP_HW_ADDRESS: - g_value_set_string (value, priv->bdaddr); - break; - case PROP_BT_NAME: - g_value_set_string (value, priv->name); - break; - case PROP_BT_CAPABILITIES: - g_value_set_uint (value, priv->capabilities); - break; - case PROP_BT_DEVICE: - g_value_set_object (value, priv->bt_device); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -dispose (GObject *object) -{ - NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (object); - - if (priv->timeout_id) { - g_source_remove (priv->timeout_id); - priv->timeout_id = 0; - } - - g_signal_handlers_disconnect_by_func (priv->bt_device, - G_CALLBACK (bluez_connected_changed), - object); - - if (priv->dbus_mgr && priv->mm_watch_id) { - g_signal_handler_disconnect (priv->dbus_mgr, priv->mm_watch_id); - priv->mm_watch_id = 0; - } - g_clear_object (&priv->dbus_mgr); - - g_clear_object (&priv->modem); - g_clear_object (&priv->bt_device); - - G_OBJECT_CLASS (nm_device_bt_parent_class)->dispose (object); -} - -static void -finalize (GObject *object) -{ - NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (object); - - g_free (priv->rfcomm_iface); - g_free (priv->bdaddr); - g_free (priv->name); - - G_OBJECT_CLASS (nm_device_bt_parent_class)->finalize (object); -} - -static void -nm_device_bt_class_init (NMDeviceBtClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); - - g_type_class_add_private (object_class, sizeof (NMDeviceBtPrivate)); - - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->dispose = dispose; - object_class->finalize = finalize; - - device_class->get_best_auto_connection = get_best_auto_connection; - device_class->get_generic_capabilities = get_generic_capabilities; - device_class->deactivate = deactivate; - device_class->act_stage2_config = act_stage2_config; - device_class->act_stage3_ip4_config_start = act_stage3_ip4_config_start; - device_class->act_stage3_ip6_config_start = act_stage3_ip6_config_start; - device_class->check_connection_compatible = check_connection_compatible; - device_class->check_connection_available = check_connection_available; - device_class->complete_connection = complete_connection; - device_class->hwaddr_matches = hwaddr_matches; - device_class->get_hw_address = get_hw_address; - device_class->is_available = is_available; - - device_class->state_changed = device_state_changed; - - /* Properties */ - g_object_class_install_property - (object_class, PROP_HW_ADDRESS, - g_param_spec_string (NM_DEVICE_BT_HW_ADDRESS, - "Bluetooth address", - "Bluetooth address", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - g_object_class_install_property - (object_class, PROP_BT_NAME, - g_param_spec_string (NM_DEVICE_BT_NAME, - "Bluetooth device name", - "Bluetooth device name", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - g_object_class_install_property - (object_class, PROP_BT_CAPABILITIES, - g_param_spec_uint (NM_DEVICE_BT_CAPABILITIES, - "Bluetooth device capabilities", - "Bluetooth device capabilities", - NM_BT_CAPABILITY_NONE, G_MAXUINT, NM_BT_CAPABILITY_NONE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - g_object_class_install_property - (object_class, PROP_BT_DEVICE, - g_param_spec_object (NM_DEVICE_BT_DEVICE, - "NMBluezDevice object for the Device", - "NMBluezDevice object for the Device", - NM_TYPE_BLUEZ_DEVICE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | NM_PROPERTY_PARAM_NO_EXPORT)); - - /* Signals */ - signals[PPP_STATS] = - g_signal_new ("ppp-stats", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMDeviceBtClass, ppp_stats), - NULL, NULL, - _nm_marshal_VOID__UINT_UINT, - G_TYPE_NONE, 2, - G_TYPE_UINT, G_TYPE_UINT); - - signals[PROPERTIES_CHANGED] = - nm_properties_changed_signal_new (object_class, - G_STRUCT_OFFSET (NMDeviceBtClass, properties_changed)); - - dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass), - &dbus_glib_nm_device_bt_object_info); - - dbus_g_error_domain_register (NM_BT_ERROR, NULL, NM_TYPE_BT_ERROR); -} diff --git a/src/nm-device-bt.h b/src/nm-device-bt.h deleted file mode 100644 index 82d4bfa7..00000000 --- a/src/nm-device-bt.h +++ /dev/null @@ -1,79 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2009 Red Hat, Inc. - */ - -#ifndef NM_DEVICE_BT_H -#define NM_DEVICE_BT_H - -#include -#include "nm-bluez-device.h" -#include "nm-modem.h" - -G_BEGIN_DECLS - -#define NM_TYPE_DEVICE_BT (nm_device_bt_get_type ()) -#define NM_DEVICE_BT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_BT, NMDeviceBt)) -#define NM_DEVICE_BT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_BT, NMDeviceBtClass)) -#define NM_IS_DEVICE_BT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_BT)) -#define NM_IS_DEVICE_BT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_BT)) -#define NM_DEVICE_BT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_BT, NMDeviceBtClass)) - -typedef enum { - NM_BT_ERROR_CONNECTION_NOT_BT = 0, /*< nick=ConnectionNotBt >*/ - NM_BT_ERROR_CONNECTION_INVALID, /*< nick=ConnectionInvalid >*/ - NM_BT_ERROR_CONNECTION_INCOMPATIBLE, /*< nick=ConnectionIncompatible >*/ -} NMBtError; - -#define NM_DEVICE_BT_HW_ADDRESS "hw-address" -#define NM_DEVICE_BT_NAME "name" -#define NM_DEVICE_BT_CAPABILITIES "bt-capabilities" -#define NM_DEVICE_BT_DEVICE "bt-device" - -typedef struct { - NMDevice parent; -} NMDeviceBt; - -typedef struct { - NMDeviceClass parent; - - /* Signals */ - void (*ppp_stats) (NMDeviceBt *device, guint32 in_bytes, guint32 out_bytes); - void (*properties_changed) (NMDeviceBt *device, GHashTable *properties); -} NMDeviceBtClass; - -GType nm_device_bt_get_type (void); - -NMDevice *nm_device_bt_new (NMBluezDevice *bt_device, - const char *udi, - const char *bdaddr, - const char *name, - guint32 capabilities, - gboolean managed); - -guint32 nm_device_bt_get_capabilities (NMDeviceBt *device); - -gboolean nm_device_bt_modem_added (NMDeviceBt *device, - NMModem *modem, - const char *driver); - -gboolean nm_device_bt_modem_removed (NMDeviceBt *device, NMModem *modem); - -G_END_DECLS - -#endif /* NM_DEVICE_BT_H */ diff --git a/src/nm-device-ethernet-glue.h b/src/nm-device-ethernet-glue.h new file mode 100644 index 00000000..81630086 --- /dev/null +++ b/src/nm-device-ethernet-glue.h @@ -0,0 +1,73 @@ +/* Generated by dbus-binding-tool; do not edit! */ + + +#ifndef __dbus_glib_marshal_nm_device_ethernet_MARSHAL_H__ +#define __dbus_glib_marshal_nm_device_ethernet_MARSHAL_H__ + +#include + +G_BEGIN_DECLS + +#ifdef G_ENABLE_DEBUG +#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v) +#define g_marshal_value_peek_char(v) g_value_get_schar (v) +#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v) +#define g_marshal_value_peek_int(v) g_value_get_int (v) +#define g_marshal_value_peek_uint(v) g_value_get_uint (v) +#define g_marshal_value_peek_long(v) g_value_get_long (v) +#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v) +#define g_marshal_value_peek_int64(v) g_value_get_int64 (v) +#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v) +#define g_marshal_value_peek_enum(v) g_value_get_enum (v) +#define g_marshal_value_peek_flags(v) g_value_get_flags (v) +#define g_marshal_value_peek_float(v) g_value_get_float (v) +#define g_marshal_value_peek_double(v) g_value_get_double (v) +#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v) +#define g_marshal_value_peek_param(v) g_value_get_param (v) +#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v) +#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v) +#define g_marshal_value_peek_object(v) g_value_get_object (v) +#define g_marshal_value_peek_variant(v) g_value_get_variant (v) +#else /* !G_ENABLE_DEBUG */ +/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API. + * Do not access GValues directly in your code. Instead, use the + * g_value_get_*() functions + */ +#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int +#define g_marshal_value_peek_char(v) (v)->data[0].v_int +#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint +#define g_marshal_value_peek_int(v) (v)->data[0].v_int +#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint +#define g_marshal_value_peek_long(v) (v)->data[0].v_long +#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 +#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 +#define g_marshal_value_peek_enum(v) (v)->data[0].v_long +#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_float(v) (v)->data[0].v_float +#define g_marshal_value_peek_double(v) (v)->data[0].v_double +#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer +#endif /* !G_ENABLE_DEBUG */ + + +G_END_DECLS + +#endif /* __dbus_glib_marshal_nm_device_ethernet_MARSHAL_H__ */ + +#include +static const DBusGMethodInfo dbus_glib_nm_device_ethernet_methods[] = { +}; + +const DBusGObjectInfo dbus_glib_nm_device_ethernet_object_info = { 1, + dbus_glib_nm_device_ethernet_methods, + 0, +"\0", +"org.freedesktop.NetworkManager.Device.Wired\0PropertiesChanged\0\0", +"org.freedesktop.NetworkManager.Device.Wired\0HwAddress\0hw_address\0read\0org.freedesktop.NetworkManager.Device.Wired\0PermHwAddress\0perm_hw_address\0read\0org.freedesktop.NetworkManager.Device.Wired\0Speed\0speed\0read\0org.freedesktop.NetworkManager.Device.Wired\0Carrier\0carrier\0read\0\0" +}; + diff --git a/src/nm-device-ethernet.c b/src/nm-device-ethernet.c deleted file mode 100644 index 75824519..00000000 --- a/src/nm-device-ethernet.c +++ /dev/null @@ -1,1675 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2005 - 2012 Red Hat, Inc. - * Copyright (C) 2006 - 2008 Novell, Inc. - */ - -#include "config.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "nm-glib-compat.h" -#include "nm-device-ethernet.h" -#include "nm-device-private.h" -#include "nm-activation-request.h" -#include "NetworkManagerUtils.h" -#include "nm-supplicant-manager.h" -#include "nm-supplicant-interface.h" -#include "nm-supplicant-config.h" -#include "nm-system.h" -#include "nm-setting-connection.h" -#include "nm-setting-wired.h" -#include "nm-setting-8021x.h" -#include "nm-setting-pppoe.h" -#include "nm-setting-bond.h" -#include "ppp-manager/nm-ppp-manager.h" -#include "nm-logging.h" -#include "nm-properties-changed-signal.h" -#include "nm-utils.h" -#include "nm-enum-types.h" -#include "nm-netlink-monitor.h" - -#include "nm-device-ethernet-glue.h" - - -G_DEFINE_TYPE (NMDeviceEthernet, nm_device_ethernet, NM_TYPE_DEVICE_WIRED) - -#define NM_DEVICE_ETHERNET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_ETHERNET, NMDeviceEthernetPrivate)) - -#define WIRED_SECRETS_TRIES "wired-secrets-tries" - -#define NM_ETHERNET_ERROR (nm_ethernet_error_quark ()) - -typedef struct Supplicant { - NMSupplicantManager *mgr; - NMSupplicantInterface *iface; - - /* signal handler ids */ - guint iface_error_id; - guint iface_state_id; - - /* Timeouts and idles */ - guint iface_con_error_cb_id; - guint con_timeout_id; -} Supplicant; - -typedef struct { - guint8 hw_addr[ETH_ALEN]; /* Current MAC address */ - guint8 perm_hw_addr[ETH_ALEN]; /* Permanent MAC address */ - guint8 initial_hw_addr[ETH_ALEN]; /* Initial MAC address (as seen when NM starts) */ - - Supplicant supplicant; - guint supplicant_timeout_id; - - /* s390 */ - char * subchan1; - char * subchan2; - char * subchan3; - char * subchannels; /* Composite used for checking unmanaged specs */ - - /* PPPoE */ - NMPPPManager *ppp_manager; - NMIP4Config *pending_ip4_config; -} NMDeviceEthernetPrivate; - -enum { - PROPERTIES_CHANGED, - - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -enum { - PROP_0, - PROP_HW_ADDRESS, - PROP_PERM_HW_ADDRESS, - PROP_SPEED, - PROP_CARRIER, - - LAST_PROP -}; - - -static gboolean supports_mii_carrier_detect (NMDeviceEthernet *dev); -static gboolean supports_ethtool_carrier_detect (NMDeviceEthernet *dev); - -static GQuark -nm_ethernet_error_quark (void) -{ - static GQuark quark = 0; - if (!quark) - quark = g_quark_from_static_string ("nm-ethernet-error"); - return quark; -} - -static void -_update_s390_subchannels (NMDeviceEthernet *self) -{ - NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); - const char *iface; - GUdevClient *client; - GUdevDevice *dev; - GUdevDevice *parent = NULL; - const char *parent_path, *item, *driver; - const char *subsystems[] = { "net", NULL }; - GDir *dir; - GError *error = NULL; - - iface = nm_device_get_iface (NM_DEVICE (self)); - - client = g_udev_client_new (subsystems); - if (!client) { - nm_log_warn (LOGD_DEVICE | LOGD_HW, "(%s): failed to initialize GUdev client", iface); - return; - } - - dev = g_udev_client_query_by_subsystem_and_name (client, "net", iface); - if (!dev) { - nm_log_warn (LOGD_DEVICE | LOGD_HW, "(%s): failed to find device with udev", iface); - goto out; - } - - /* Try for the "ccwgroup" parent */ - parent = g_udev_device_get_parent_with_subsystem (dev, "ccwgroup", NULL); - if (!parent) { - /* FIXME: whatever 'lcs' devices' subsystem is here... */ - if (!parent) { - /* Not an s390 device */ - goto out; - } - } - - parent_path = g_udev_device_get_sysfs_path (parent); - dir = g_dir_open (parent_path, 0, &error); - if (!dir) { - nm_log_warn (LOGD_DEVICE | LOGD_HW, "(%s): failed to open directory '%s': %s", - iface, parent_path, - error && error->message ? error->message : "(unknown)"); - g_clear_error (&error); - goto out; - } - - /* FIXME: we probably care about ordering here to ensure that we map - * cdev0 -> subchan1, cdev1 -> subchan2, etc. - */ - while ((item = g_dir_read_name (dir))) { - char buf[50]; - char *cdev_path; - - if (strncmp (item, "cdev", 4)) - continue; /* Not a subchannel link */ - - cdev_path = g_strdup_printf ("%s/%s", parent_path, item); - - memset (buf, 0, sizeof (buf)); - errno = 0; - if (readlink (cdev_path, &buf[0], sizeof (buf) - 1) >= 0) { - if (!priv->subchan1) - priv->subchan1 = g_path_get_basename (buf); - else if (!priv->subchan2) - priv->subchan2 = g_path_get_basename (buf); - else if (!priv->subchan3) - priv->subchan3 = g_path_get_basename (buf); - } else { - nm_log_warn (LOGD_DEVICE | LOGD_HW, - "(%s): failed to read cdev link '%s': %d", - iface, cdev_path, errno); - } - g_free (cdev_path); - }; - - g_dir_close (dir); - - if (priv->subchan3) { - priv->subchannels = g_strdup_printf ("%s,%s,%s", - priv->subchan1, - priv->subchan2, - priv->subchan3); - } else if (priv->subchan2) { - priv->subchannels = g_strdup_printf ("%s,%s", - priv->subchan1, - priv->subchan2); - } else - priv->subchannels = g_strdup (priv->subchan1); - - driver = nm_device_get_driver (NM_DEVICE (self)); - nm_log_info (LOGD_DEVICE | LOGD_HW, - "(%s): found s390 '%s' subchannels [%s]", - iface, driver ? driver : "(unknown driver)", priv->subchannels); - -out: - if (parent) - g_object_unref (parent); - if (dev) - g_object_unref (dev); - g_object_unref (client); -} - -static GObject* -constructor (GType type, - guint n_construct_params, - GObjectConstructParam *construct_params) -{ - GObject *object; - NMDeviceEthernetPrivate *priv; - NMDevice *self; - int itype; - - object = G_OBJECT_CLASS (nm_device_ethernet_parent_class)->constructor (type, - n_construct_params, - construct_params); - if (object) { - self = NM_DEVICE (object); - priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); - - // FIXME: Convert this into a no-export property so type can be specified - // when the device is created. - itype = nm_system_get_iface_type (nm_device_get_ifindex (self), nm_device_get_iface (self)); - g_assert (itype == NM_IFACE_TYPE_UNSPEC); - - nm_log_dbg (LOGD_HW | LOGD_ETHER, "(%s): kernel ifindex %d", - nm_device_get_iface (NM_DEVICE (self)), - nm_device_get_ifindex (NM_DEVICE (self))); - - /* s390 stuff */ - _update_s390_subchannels (NM_DEVICE_ETHERNET (self)); - } - - return object; -} - -static void -clear_secrets_tries (NMDevice *device) -{ - NMActRequest *req; - NMConnection *connection; - - req = nm_device_get_act_request (device); - if (req) { - connection = nm_act_request_get_connection (req); - /* Clear wired secrets tries on success, failure, or when deactivating */ - g_object_set_data (G_OBJECT (connection), WIRED_SECRETS_TRIES, NULL); - } -} - -static void -device_state_changed (NMDevice *device, - NMDeviceState new_state, - NMDeviceState old_state, - NMDeviceStateReason reason) -{ - switch (new_state) { - case NM_DEVICE_STATE_ACTIVATED: - case NM_DEVICE_STATE_FAILED: - case NM_DEVICE_STATE_DISCONNECTED: - clear_secrets_tries (device); - break; - default: - break; - } -} - -static void -nm_device_ethernet_init (NMDeviceEthernet * self) -{ -} - -static gboolean -is_up (NMDevice *device) -{ - if (!NM_DEVICE_ETHERNET_GET_PRIVATE (device)->supplicant.mgr) - return FALSE; - - return TRUE; -} - -static gboolean -bring_up (NMDevice *dev) -{ - NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (dev); - - priv->supplicant.mgr = nm_supplicant_manager_get (); - - return priv->supplicant.mgr ? TRUE : FALSE; -} - -static void -take_down (NMDevice *dev) -{ - NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (dev); - - if (priv->supplicant.mgr) { - g_object_unref (priv->supplicant.mgr); - priv->supplicant.mgr = NULL; - } -} - -NMDevice * -nm_device_ethernet_new (const char *udi, - const char *iface, - const char *driver) -{ - g_return_val_if_fail (udi != NULL, NULL); - g_return_val_if_fail (iface != NULL, NULL); - g_return_val_if_fail (driver != NULL, NULL); - - return (NMDevice *) g_object_new (NM_TYPE_DEVICE_ETHERNET, - NM_DEVICE_UDI, udi, - NM_DEVICE_IFACE, iface, - NM_DEVICE_DRIVER, driver, - NM_DEVICE_TYPE_DESC, "Ethernet", - NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_ETHERNET, - NULL); -} - -static void -update_hw_address (NMDevice *dev) -{ - NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (dev); - gsize addrlen; - gboolean changed = FALSE; - - addrlen = nm_device_read_hwaddr (dev, priv->hw_addr, sizeof (priv->hw_addr), &changed); - if (addrlen) { - g_return_if_fail (addrlen == ETH_ALEN); - if (changed) - g_object_notify (G_OBJECT (dev), NM_DEVICE_ETHERNET_HW_ADDRESS); - } -} - -static gboolean -_set_hw_addr (NMDeviceEthernet *self, const guint8 *addr, const char *detail) -{ - NMDevice *dev = NM_DEVICE (self); - NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); - const char *iface; - char *mac_str = NULL; - gboolean success = FALSE; - - g_return_val_if_fail (addr != NULL, FALSE); - - iface = nm_device_get_iface (dev); - - /* Do nothing if current MAC is same */ - if (!memcmp (priv->hw_addr, addr, ETH_ALEN)) { - nm_log_dbg (LOGD_DEVICE | LOGD_ETHER, "(%s): no MAC address change needed", iface); - return TRUE; - } - - mac_str = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X", - addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); - - /* Can't change MAC address while device is up */ - nm_device_hw_take_down (dev, FALSE); - - success = nm_system_iface_set_mac (nm_device_get_ip_ifindex (dev), (struct ether_addr *) addr); - if (success) { - /* MAC address succesfully changed; update the current MAC to match */ - update_hw_address (dev); - if (memcmp (priv->hw_addr, addr, ETH_ALEN) == 0) { - nm_log_info (LOGD_DEVICE | LOGD_ETHER, "(%s): %s MAC address to %s", - iface, detail, mac_str); - } else { - nm_log_warn (LOGD_DEVICE | LOGD_ETHER, "(%s): new MAC address %s " - "not successfully set", - iface, mac_str); - } - } else { - nm_log_warn (LOGD_DEVICE | LOGD_ETHER, "(%s): failed to %s MAC address to %s", - iface, detail, mac_str); - } - nm_device_hw_bring_up (dev, FALSE, NULL); - g_free (mac_str); - - return success; -} - -static void -update_permanent_hw_address (NMDevice *dev) -{ - NMDeviceEthernet *self = NM_DEVICE_ETHERNET (dev); - NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); - struct ifreq req; - struct ethtool_perm_addr *epaddr = NULL; - int fd, ret; - - fd = socket (PF_INET, SOCK_DGRAM, 0); - if (fd < 0) { - nm_log_warn (LOGD_HW, "couldn't open control socket."); - return; - } - - /* Get permanent MAC address */ - memset (&req, 0, sizeof (struct ifreq)); - strncpy (req.ifr_name, nm_device_get_iface (dev), IFNAMSIZ); - - epaddr = g_malloc0 (sizeof (struct ethtool_perm_addr) + ETH_ALEN); - epaddr->cmd = ETHTOOL_GPERMADDR; - epaddr->size = ETH_ALEN; - req.ifr_data = (void *) epaddr; - - errno = 0; - ret = ioctl (fd, SIOCETHTOOL, &req); - if ((ret < 0) || !nm_ethernet_address_is_valid ((struct ether_addr *) epaddr->data)) { - nm_log_dbg (LOGD_HW | LOGD_ETHER, "(%s): unable to read permanent MAC address (error %d)", - nm_device_get_iface (dev), errno); - /* Fall back to current address */ - memcpy (epaddr->data, priv->hw_addr, ETH_ALEN); - } - - if (memcmp (&priv->perm_hw_addr, epaddr->data, ETH_ALEN)) { - memcpy (&priv->perm_hw_addr, epaddr->data, ETH_ALEN); - g_object_notify (G_OBJECT (dev), NM_DEVICE_ETHERNET_PERMANENT_HW_ADDRESS); - } - - g_free (epaddr); - close (fd); -} - -static void -update_initial_hw_address (NMDevice *dev) -{ - NMDeviceEthernet *self = NM_DEVICE_ETHERNET (dev); - NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); - gsize addrlen; - char *mac_str = NULL; - - /* This sets initial MAC address from current MAC address. It should only - * be called from NMDevice constructor() to really get the initial address. - */ - addrlen = nm_device_read_hwaddr (dev, - priv->initial_hw_addr, - sizeof (priv->initial_hw_addr), - NULL); - if (addrlen) - g_return_if_fail (addrlen == ETH_ALEN); - - mac_str = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X", - priv->initial_hw_addr[0], - priv->initial_hw_addr[1], - priv->initial_hw_addr[2], - priv->initial_hw_addr[3], - priv->initial_hw_addr[4], - priv->initial_hw_addr[5]); - - nm_log_dbg (LOGD_DEVICE | LOGD_ETHER, "(%s): read initial MAC address %s", - nm_device_get_iface (dev), mac_str); - - g_free (mac_str); -} - -static const guint8 * -get_hw_address (NMDevice *device, guint *out_len) -{ - *out_len = ETH_ALEN; - return NM_DEVICE_ETHERNET_GET_PRIVATE (device)->hw_addr; -} - -static guint32 -get_generic_capabilities (NMDevice *dev) -{ - NMDeviceEthernet *self = NM_DEVICE_ETHERNET (dev); - guint32 caps = NM_DEVICE_CAP_NONE; - - /* cipsec devices are also explicitly unsupported at this time */ - if (strstr (nm_device_get_iface (dev), "cipsec")) - return NM_DEVICE_CAP_NONE; - - if (supports_ethtool_carrier_detect (self) || supports_mii_carrier_detect (self)) - caps |= NM_DEVICE_CAP_CARRIER_DETECT; - - caps |= NM_DEVICE_CAP_NM_SUPPORTED; - - return caps; -} - -static gboolean -match_subchans (NMDeviceEthernet *self, NMSettingWired *s_wired, gboolean *try_mac) -{ - NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); - const GPtrArray *subchans; - int i; - - *try_mac = TRUE; - - subchans = nm_setting_wired_get_s390_subchannels (s_wired); - if (!subchans) - return TRUE; - - /* connection requires subchannels but the device has none */ - if (!priv->subchannels) - return FALSE; - - /* Make sure each subchannel in the connection is a subchannel of this device */ - for (i = 0; i < subchans->len; i++) { - const char *candidate = g_ptr_array_index (subchans, i); - - if ( (priv->subchan1 && !strcmp (priv->subchan1, candidate)) - || (priv->subchan2 && !strcmp (priv->subchan2, candidate)) - || (priv->subchan3 && !strcmp (priv->subchan3, candidate))) - continue; - - return FALSE; /* a subchannel was not found */ - } - - *try_mac = FALSE; - return TRUE; -} - -static gboolean -match_ethernet_connection (NMDevice *device, NMConnection *connection, - gboolean check_blacklist, GError **error) -{ - NMDeviceEthernet *self = NM_DEVICE_ETHERNET (device); - NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); - NMSettingWired *s_wired; - - s_wired = nm_connection_get_setting_wired (connection); - - if (nm_connection_is_type (connection, NM_SETTING_PPPOE_SETTING_NAME)) { - /* NOP */ - } else if (nm_connection_is_type (connection, NM_SETTING_WIRED_SETTING_NAME)) { - if (!s_wired) { - g_set_error (error, - NM_ETHERNET_ERROR, NM_ETHERNET_ERROR_CONNECTION_INVALID, - "The connection was not a valid wired connection."); - return FALSE; - } - } else { - g_set_error (error, - NM_ETHERNET_ERROR, NM_ETHERNET_ERROR_CONNECTION_NOT_WIRED, - "The connection was not a wired, bond, or PPPoE connection."); - return FALSE; - } - - if (s_wired) { - const GByteArray *mac; - gboolean try_mac = TRUE; - const GSList *mac_blacklist, *mac_blacklist_iter; - - if (!match_subchans (self, s_wired, &try_mac)) { - g_set_error (error, - NM_ETHERNET_ERROR, NM_ETHERNET_ERROR_CONNECTION_INCOMPATIBLE, - "The connection's s390 subchannels did not match this device."); - return FALSE; - } - - mac = nm_setting_wired_get_mac_address (s_wired); - if (try_mac && mac && memcmp (mac->data, &priv->perm_hw_addr, ETH_ALEN)) { - g_set_error (error, - NM_ETHERNET_ERROR, NM_ETHERNET_ERROR_CONNECTION_INCOMPATIBLE, - "The connection's MAC address did not match this device."); - return FALSE; - } - - if (!check_blacklist) - return TRUE; - - /* Check for MAC address blacklist */ - mac_blacklist = nm_setting_wired_get_mac_address_blacklist (s_wired); - for (mac_blacklist_iter = mac_blacklist; mac_blacklist_iter; - mac_blacklist_iter = g_slist_next (mac_blacklist_iter)) { - struct ether_addr addr; - - if (!ether_aton_r (mac_blacklist_iter->data, &addr)) { - g_warn_if_reached (); - return FALSE; - } - if (memcmp (&addr, &priv->perm_hw_addr, ETH_ALEN) == 0) { - g_set_error (error, - NM_ETHERNET_ERROR, NM_ETHERNET_ERROR_CONNECTION_INCOMPATIBLE, - "The connection's MAC address (%s) is blacklisted in %s.", - (char *) mac_blacklist_iter->data, NM_SETTING_WIRED_MAC_ADDRESS_BLACKLIST); - return FALSE; - } - } - } - - return TRUE; -} - -static NMConnection * -get_best_auto_connection (NMDevice *dev, - GSList *connections, - char **specific_object) -{ - GSList *iter; - - for (iter = connections; iter; iter = g_slist_next (iter)) { - NMConnection *connection = NM_CONNECTION (iter->data); - - if (match_ethernet_connection (dev, connection, TRUE, NULL)) - return connection; - } - - return NULL; -} - -/* FIXME: Move it to nm-device.c and then get rid of all foo_device_get_setting() all around. - It's here now to keep the patch short. */ -static NMSetting * -device_get_setting (NMDevice *device, GType setting_type) -{ - NMActRequest *req; - NMSetting *setting = NULL; - - req = nm_device_get_act_request (device); - if (req) { - NMConnection *connection; - - connection = nm_act_request_get_connection (req); - if (connection) - setting = nm_connection_get_setting (connection, setting_type); - } - - return setting; -} - -/*****************************************************************************/ -/* 802.1X */ - -static void -remove_supplicant_timeouts (NMDeviceEthernet *self) -{ - NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); - - if (priv->supplicant.con_timeout_id) { - g_source_remove (priv->supplicant.con_timeout_id); - priv->supplicant.con_timeout_id = 0; - } - - if (priv->supplicant_timeout_id) { - g_source_remove (priv->supplicant_timeout_id); - priv->supplicant_timeout_id = 0; - } -} - -static void -remove_supplicant_interface_error_handler (NMDeviceEthernet *self) -{ - NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); - - if (priv->supplicant.iface_error_id != 0) { - g_signal_handler_disconnect (priv->supplicant.iface, priv->supplicant.iface_error_id); - priv->supplicant.iface_error_id = 0; - } - - if (priv->supplicant.iface_con_error_cb_id > 0) { - g_source_remove (priv->supplicant.iface_con_error_cb_id); - priv->supplicant.iface_con_error_cb_id = 0; - } -} - -static void -supplicant_interface_release (NMDeviceEthernet *self) -{ - NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); - - remove_supplicant_timeouts (self); - remove_supplicant_interface_error_handler (self); - - if (priv->supplicant.iface_state_id > 0) { - g_signal_handler_disconnect (priv->supplicant.iface, priv->supplicant.iface_state_id); - priv->supplicant.iface_state_id = 0; - } - - if (priv->supplicant.iface) { - nm_supplicant_interface_disconnect (priv->supplicant.iface); - nm_supplicant_manager_iface_release (priv->supplicant.mgr, priv->supplicant.iface); - priv->supplicant.iface = NULL; - } -} - -static void -wired_secrets_cb (NMActRequest *req, - guint32 call_id, - NMConnection *connection, - GError *error, - gpointer user_data) -{ - NMDevice *dev = NM_DEVICE (user_data); - - g_return_if_fail (req == nm_device_get_act_request (dev)); - g_return_if_fail (nm_device_get_state (dev) == NM_DEVICE_STATE_NEED_AUTH); - g_return_if_fail (nm_act_request_get_connection (req) == connection); - - if (error) { - nm_log_warn (LOGD_ETHER, "%s", error->message); - nm_device_state_changed (dev, - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_NO_SECRETS); - } else - nm_device_activate_schedule_stage1_device_prepare (dev); -} - -static gboolean -link_timeout_cb (gpointer user_data) -{ - NMDeviceEthernet *self = NM_DEVICE_ETHERNET (user_data); - NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); - NMDevice *dev = NM_DEVICE (self); - NMActRequest *req; - NMConnection *connection; - const char *setting_name; - - priv->supplicant_timeout_id = 0; - - req = nm_device_get_act_request (dev); - - if (nm_device_get_state (dev) == NM_DEVICE_STATE_ACTIVATED) { - nm_device_state_changed (dev, - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT); - return FALSE; - } - - /* Disconnect event during initial authentication and credentials - * ARE checked - we are likely to have wrong key. Ask the user for - * another one. - */ - if (nm_device_get_state (dev) != NM_DEVICE_STATE_CONFIG) - goto time_out; - - connection = nm_act_request_get_connection (req); - nm_connection_clear_secrets (connection); - setting_name = nm_connection_need_secrets (connection, NULL); - if (!setting_name) - goto time_out; - - nm_log_info (LOGD_DEVICE | LOGD_ETHER, - "Activation (%s/wired): disconnected during authentication," - " asking for new key.", - nm_device_get_iface (dev)); - supplicant_interface_release (self); - - nm_device_state_changed (dev, NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT); - nm_act_request_get_secrets (req, - setting_name, - NM_SETTINGS_GET_SECRETS_FLAG_REQUEST_NEW, - NULL, - wired_secrets_cb, - self); - - return FALSE; - -time_out: - nm_log_warn (LOGD_DEVICE | LOGD_ETHER, - "(%s): link timed out.", nm_device_get_iface (dev)); - nm_device_state_changed (dev, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT); - - return FALSE; -} - -static NMSupplicantConfig * -build_supplicant_config (NMDeviceEthernet *self) -{ - const char *con_uuid; - NMSupplicantConfig *config = NULL; - NMSetting8021x *security; - NMConnection *connection; - - connection = nm_device_get_connection (NM_DEVICE (self)); - g_assert (connection); - con_uuid = nm_connection_get_uuid (connection); - - config = nm_supplicant_config_new (); - if (!config) - return NULL; - - security = nm_connection_get_setting_802_1x (connection); - if (!nm_supplicant_config_add_setting_8021x (config, security, con_uuid, TRUE)) { - nm_log_warn (LOGD_DEVICE, "Couldn't add 802.1X security setting to supplicant config."); - g_object_unref (config); - config = NULL; - } - - return config; -} - -static void -supplicant_iface_state_cb (NMSupplicantInterface *iface, - guint32 new_state, - guint32 old_state, - int disconnect_reason, - gpointer user_data) -{ - NMDeviceEthernet *self = NM_DEVICE_ETHERNET (user_data); - NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); - NMDevice *device = NM_DEVICE (self); - NMSupplicantConfig *config; - gboolean success = FALSE; - NMDeviceState devstate; - - if (new_state == old_state) - return; - - nm_log_info (LOGD_DEVICE | LOGD_ETHER, - "(%s): supplicant interface state: %s -> %s", - nm_device_get_iface (device), - nm_supplicant_interface_state_to_string (old_state), - nm_supplicant_interface_state_to_string (new_state)); - - devstate = nm_device_get_state (device); - - switch (new_state) { - case NM_SUPPLICANT_INTERFACE_STATE_READY: - config = build_supplicant_config (self); - if (config) { - success = nm_supplicant_interface_set_config (priv->supplicant.iface, config); - g_object_unref (config); - - if (!success) { - nm_log_err (LOGD_DEVICE | LOGD_ETHER, - "Activation (%s/wired): couldn't send security " - "configuration to the supplicant.", - nm_device_get_iface (device)); - } - } else { - nm_log_warn (LOGD_DEVICE | LOGD_ETHER, - "Activation (%s/wired): couldn't build security configuration.", - nm_device_get_iface (device)); - } - - if (!success) { - nm_device_state_changed (device, - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED); - } - break; - case NM_SUPPLICANT_INTERFACE_STATE_COMPLETED: - remove_supplicant_interface_error_handler (self); - remove_supplicant_timeouts (self); - - /* If this is the initial association during device activation, - * schedule the next activation stage. - */ - if (devstate == NM_DEVICE_STATE_CONFIG) { - nm_log_info (LOGD_DEVICE | LOGD_ETHER, - "Activation (%s/wired) Stage 2 of 5 (Device Configure) successful.", - nm_device_get_iface (device)); - nm_device_activate_schedule_stage3_ip_config_start (device); - } - break; - case NM_SUPPLICANT_INTERFACE_STATE_DISCONNECTED: - if ((devstate == NM_DEVICE_STATE_ACTIVATED) || nm_device_is_activating (device)) { - /* Start the link timeout so we allow some time for reauthentication */ - if (!priv->supplicant_timeout_id) - priv->supplicant_timeout_id = g_timeout_add_seconds (15, link_timeout_cb, device); - } - break; - case NM_SUPPLICANT_INTERFACE_STATE_DOWN: - supplicant_interface_release (self); - remove_supplicant_timeouts (self); - - if ((devstate == NM_DEVICE_STATE_ACTIVATED) || nm_device_is_activating (device)) { - nm_device_state_changed (device, - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); - } - break; - default: - break; - } -} - -static gboolean -supplicant_iface_connection_error_cb_handler (gpointer user_data) -{ - NMDeviceEthernet *self = NM_DEVICE_ETHERNET (user_data); - NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); - - supplicant_interface_release (self); - nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED); - - priv->supplicant.iface_con_error_cb_id = 0; - return FALSE; -} - -static void -supplicant_iface_connection_error_cb (NMSupplicantInterface *iface, - const char *name, - const char *message, - gpointer user_data) -{ - NMDeviceEthernet *self = NM_DEVICE_ETHERNET (user_data); - NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); - guint id; - - nm_log_warn (LOGD_DEVICE | LOGD_ETHER, - "Activation (%s/wired): association request to the supplicant failed: %s - %s", - nm_device_get_iface (NM_DEVICE (self)), name, message); - - if (priv->supplicant.iface_con_error_cb_id) - g_source_remove (priv->supplicant.iface_con_error_cb_id); - - id = g_idle_add (supplicant_iface_connection_error_cb_handler, self); - priv->supplicant.iface_con_error_cb_id = id; -} - -static NMActStageReturn -handle_auth_or_fail (NMDeviceEthernet *self, - NMActRequest *req, - gboolean new_secrets) -{ - const char *setting_name; - guint32 tries; - NMConnection *connection; - - connection = nm_act_request_get_connection (req); - g_assert (connection); - - tries = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (connection), WIRED_SECRETS_TRIES)); - if (tries > 3) - return NM_ACT_STAGE_RETURN_FAILURE; - - nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_NONE); - - nm_connection_clear_secrets (connection); - setting_name = nm_connection_need_secrets (connection, NULL); - if (setting_name) { - NMSettingsGetSecretsFlags flags = NM_SETTINGS_GET_SECRETS_FLAG_ALLOW_INTERACTION; - - /* If the caller doesn't necessarily want completely new secrets, - * only ask for new secrets after the first failure. - */ - if (new_secrets || tries) - flags |= NM_SETTINGS_GET_SECRETS_FLAG_REQUEST_NEW; - nm_act_request_get_secrets (req, setting_name, flags, NULL, wired_secrets_cb, self); - - g_object_set_data (G_OBJECT (connection), WIRED_SECRETS_TRIES, GUINT_TO_POINTER (++tries)); - } else { - nm_log_info (LOGD_DEVICE, "Cleared secrets, but setting didn't need any secrets."); - } - - return NM_ACT_STAGE_RETURN_POSTPONE; -} - -static gboolean -supplicant_connection_timeout_cb (gpointer user_data) -{ - NMDeviceEthernet *self = NM_DEVICE_ETHERNET (user_data); - NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); - NMDevice *device = NM_DEVICE (self); - NMActRequest *req; - const char *iface; - - priv->supplicant.con_timeout_id = 0; - - iface = nm_device_get_iface (device); - - /* Authentication failed, encryption key is probably bad */ - nm_log_warn (LOGD_DEVICE | LOGD_ETHER, - "Activation (%s/wired): association took too long.", iface); - - supplicant_interface_release (self); - req = nm_device_get_act_request (device); - g_assert (req); - - if (handle_auth_or_fail (self, req, TRUE) == NM_ACT_STAGE_RETURN_POSTPONE) { - nm_log_info (LOGD_DEVICE | LOGD_ETHER, - "Activation (%s/wired): asking for new secrets", iface); - } else - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_NO_SECRETS); - - return FALSE; -} - -static gboolean -supplicant_interface_init (NMDeviceEthernet *self) -{ - NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); - const char *iface; - - iface = nm_device_get_iface (NM_DEVICE (self)); - - /* Create supplicant interface */ - priv->supplicant.iface = nm_supplicant_manager_iface_get (priv->supplicant.mgr, iface, FALSE); - if (!priv->supplicant.iface) { - nm_log_err (LOGD_DEVICE | LOGD_ETHER, - "Couldn't initialize supplicant interface for %s.", - iface); - supplicant_interface_release (self); - return FALSE; - } - - /* Listen for it's state signals */ - priv->supplicant.iface_state_id = g_signal_connect (priv->supplicant.iface, - NM_SUPPLICANT_INTERFACE_STATE, - G_CALLBACK (supplicant_iface_state_cb), - self); - - /* Hook up error signal handler to capture association errors */ - priv->supplicant.iface_error_id = g_signal_connect (priv->supplicant.iface, - "connection-error", - G_CALLBACK (supplicant_iface_connection_error_cb), - self); - - /* Set up a timeout on the connection attempt to fail it after 25 seconds */ - priv->supplicant.con_timeout_id = g_timeout_add_seconds (25, supplicant_connection_timeout_cb, self); - - return TRUE; -} - -static NMActStageReturn -act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason) -{ - NMDeviceEthernet *self = NM_DEVICE_ETHERNET (dev); - NMActRequest *req; - NMSettingWired *s_wired; - const GByteArray *cloned_mac; - NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS; - - g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); - - ret = NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->act_stage1_prepare (dev, reason); - if (ret == NM_ACT_STAGE_RETURN_SUCCESS) { - req = nm_device_get_act_request (NM_DEVICE (self)); - g_return_val_if_fail (req != NULL, NM_ACT_STAGE_RETURN_FAILURE); - - s_wired = (NMSettingWired *) device_get_setting (dev, NM_TYPE_SETTING_WIRED); - if (s_wired) { - /* Set device MAC address if the connection wants to change it */ - cloned_mac = nm_setting_wired_get_cloned_mac_address (s_wired); - if (cloned_mac && (cloned_mac->len == ETH_ALEN)) - _set_hw_addr (self, (const guint8 *) cloned_mac->data, "set"); - } - } - - return ret; -} - -static NMActStageReturn -nm_8021x_stage2_config (NMDeviceEthernet *self, NMDeviceStateReason *reason) -{ - NMConnection *connection; - NMSetting8021x *security; - const char *setting_name; - const char *iface; - NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; - - connection = nm_device_get_connection (NM_DEVICE (self)); - g_assert (connection); - security = nm_connection_get_setting_802_1x (connection); - if (!security) { - nm_log_err (LOGD_DEVICE, "Invalid or missing 802.1X security"); - *reason = NM_DEVICE_STATE_REASON_CONFIG_FAILED; - return ret; - } - - iface = nm_device_get_iface (NM_DEVICE (self)); - - /* If we need secrets, get them */ - setting_name = nm_connection_need_secrets (connection, NULL); - if (setting_name) { - NMActRequest *req = nm_device_get_act_request (NM_DEVICE (self)); - - nm_log_info (LOGD_DEVICE | LOGD_ETHER, - "Activation (%s/wired): connection '%s' has security, but secrets are required.", - iface, nm_connection_get_id (connection)); - - ret = handle_auth_or_fail (self, req, FALSE); - if (ret != NM_ACT_STAGE_RETURN_POSTPONE) - *reason = NM_DEVICE_STATE_REASON_NO_SECRETS; - } else { - nm_log_info (LOGD_DEVICE | LOGD_ETHER, - "Activation (%s/wired): connection '%s' requires no security. No secrets needed.", - iface, nm_connection_get_id (connection)); - - if (supplicant_interface_init (self)) - ret = NM_ACT_STAGE_RETURN_POSTPONE; - else - *reason = NM_DEVICE_STATE_REASON_CONFIG_FAILED; - } - - return ret; -} - -/*****************************************************************************/ -/* PPPoE */ - -static void -ppp_state_changed (NMPPPManager *ppp_manager, NMPPPStatus status, gpointer user_data) -{ - NMDevice *device = NM_DEVICE (user_data); - - switch (status) { - case NM_PPP_STATUS_DISCONNECT: - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_PPP_DISCONNECT); - break; - case NM_PPP_STATUS_DEAD: - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_PPP_FAILED); - break; - default: - break; - } -} - -static void -ppp_ip4_config (NMPPPManager *ppp_manager, - const char *iface, - NMIP4Config *config, - gpointer user_data) -{ - NMDevice *device = NM_DEVICE (user_data); - - /* Ignore PPP IP4 events that come in after initial configuration */ - if (nm_device_activate_ip4_state_in_conf (device)) { - nm_device_set_ip_iface (device, iface); - nm_device_activate_schedule_ip4_config_result (device, config); - } -} - -static NMActStageReturn -pppoe_stage3_ip4_config_start (NMDeviceEthernet *self, NMDeviceStateReason *reason) -{ - NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); - NMConnection *connection; - NMSettingPPPOE *s_pppoe; - NMActRequest *req; - GError *err = NULL; - NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; - - req = nm_device_get_act_request (NM_DEVICE (self)); - g_assert (req); - - connection = nm_act_request_get_connection (req); - g_assert (req); - - s_pppoe = nm_connection_get_setting_pppoe (connection); - g_assert (s_pppoe); - - priv->ppp_manager = nm_ppp_manager_new (nm_device_get_iface (NM_DEVICE (self))); - if (nm_ppp_manager_start (priv->ppp_manager, req, nm_setting_pppoe_get_username (s_pppoe), 30, &err)) { - g_signal_connect (priv->ppp_manager, "state-changed", - G_CALLBACK (ppp_state_changed), - self); - g_signal_connect (priv->ppp_manager, "ip4-config", - G_CALLBACK (ppp_ip4_config), - self); - ret = NM_ACT_STAGE_RETURN_POSTPONE; - } else { - nm_log_warn (LOGD_DEVICE, "(%s): PPPoE failed to start: %s", - nm_device_get_iface (NM_DEVICE (self)), err->message); - g_error_free (err); - - g_object_unref (priv->ppp_manager); - priv->ppp_manager = NULL; - - *reason = NM_DEVICE_STATE_REASON_PPP_START_FAILED; - } - - return ret; -} - -static NMActStageReturn -act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) -{ - NMSettingConnection *s_con; - const char *connection_type; - NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS; - - g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); - - s_con = NM_SETTING_CONNECTION (device_get_setting (device, NM_TYPE_SETTING_CONNECTION)); - g_assert (s_con); - - /* 802.1x has to run before any IP configuration since the 802.1x auth - * process opens the port up for normal traffic. - */ - connection_type = nm_setting_connection_get_connection_type (s_con); - if (!strcmp (connection_type, NM_SETTING_WIRED_SETTING_NAME)) { - NMSetting8021x *security; - - security = (NMSetting8021x *) device_get_setting (device, NM_TYPE_SETTING_802_1X); - if (security) - ret = nm_8021x_stage2_config (NM_DEVICE_ETHERNET (device), reason); - } - - return ret; -} - -static NMActStageReturn -act_stage3_ip4_config_start (NMDevice *device, - NMIP4Config **out_config, - NMDeviceStateReason *reason) -{ - NMSettingConnection *s_con; - const char *connection_type; - - g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); - - s_con = NM_SETTING_CONNECTION (device_get_setting (device, NM_TYPE_SETTING_CONNECTION)); - g_assert (s_con); - - connection_type = nm_setting_connection_get_connection_type (s_con); - if (!strcmp (connection_type, NM_SETTING_PPPOE_SETTING_NAME)) - return pppoe_stage3_ip4_config_start (NM_DEVICE_ETHERNET (device), reason); - - return NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->act_stage3_ip4_config_start (device, out_config, reason); -} - -static void -ip4_config_pre_commit (NMDevice *device, NMIP4Config *config) -{ - NMConnection *connection; - NMSettingWired *s_wired; - guint32 mtu; - - /* MTU only set for plain ethernet */ - if (NM_DEVICE_ETHERNET_GET_PRIVATE (device)->ppp_manager) - return; - - connection = nm_device_get_connection (device); - g_assert (connection); - s_wired = nm_connection_get_setting_wired (connection); - g_assert (s_wired); - - /* MTU override */ - mtu = nm_setting_wired_get_mtu (s_wired); - if (mtu) - nm_ip4_config_set_mtu (config, mtu); -} - -static void -deactivate (NMDevice *device) -{ - NMDeviceEthernet *self = NM_DEVICE_ETHERNET (device); - NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); - - /* Clear wired secrets tries when deactivating */ - clear_secrets_tries (device); - - if (priv->pending_ip4_config) { - g_object_unref (priv->pending_ip4_config); - priv->pending_ip4_config = NULL; - } - - if (priv->ppp_manager) { - g_object_unref (priv->ppp_manager); - priv->ppp_manager = NULL; - } - - supplicant_interface_release (self); - - /* Reset MAC address back to initial address */ - _set_hw_addr (self, priv->initial_hw_addr, "reset"); -} - -static gboolean -check_connection_compatible (NMDevice *device, - NMConnection *connection, - GError **error) -{ - return match_ethernet_connection (device, connection, TRUE, error); -} - -static gboolean -complete_connection (NMDevice *device, - NMConnection *connection, - const char *specific_object, - const GSList *existing_connections, - GError **error) -{ - NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (device); - NMSettingWired *s_wired; - NMSettingPPPOE *s_pppoe; - const GByteArray *setting_mac; - - s_pppoe = nm_connection_get_setting_pppoe (connection); - - /* We can't telepathically figure out the service name or username, so if - * those weren't given, we can't complete the connection. - */ - if (s_pppoe && !nm_setting_verify (NM_SETTING (s_pppoe), NULL, error)) - return FALSE; - - /* Default to an ethernet-only connection, but if a PPPoE setting was given - * then PPPoE should be our connection type. - */ - nm_utils_complete_generic (connection, - s_pppoe ? NM_SETTING_PPPOE_SETTING_NAME : NM_SETTING_WIRED_SETTING_NAME, - existing_connections, - s_pppoe ? _("PPPoE connection %d") : _("Wired connection %d"), - NULL, - s_pppoe ? FALSE : TRUE); /* No IPv6 by default yet for PPPoE */ - - s_wired = nm_connection_get_setting_wired (connection); - if (!s_wired) { - s_wired = (NMSettingWired *) nm_setting_wired_new (); - nm_connection_add_setting (connection, NM_SETTING (s_wired)); - } - - setting_mac = nm_setting_wired_get_mac_address (s_wired); - if (setting_mac) { - /* Make sure the setting MAC (if any) matches the device's permanent MAC */ - if (memcmp (setting_mac->data, priv->perm_hw_addr, ETH_ALEN)) { - g_set_error_literal (error, - NM_SETTING_WIRED_ERROR, - NM_SETTING_WIRED_ERROR_INVALID_PROPERTY, - NM_SETTING_WIRED_MAC_ADDRESS); - return FALSE; - } - } else { - GByteArray *mac; - const guint8 null_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; - - /* Lock the connection to this device by default */ - if (memcmp (priv->perm_hw_addr, null_mac, ETH_ALEN)) { - mac = g_byte_array_sized_new (ETH_ALEN); - g_byte_array_append (mac, priv->perm_hw_addr, ETH_ALEN); - g_object_set (G_OBJECT (s_wired), NM_SETTING_WIRED_MAC_ADDRESS, mac, NULL); - g_byte_array_free (mac, TRUE); - } - } - - return TRUE; -} - -static gboolean -spec_match_list (NMDevice *device, const GSList *specs) -{ - NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (device); - char *hwaddr; - gboolean matched; - - hwaddr = nm_utils_hwaddr_ntoa (&priv->perm_hw_addr, ARPHRD_ETHER); - matched = nm_match_spec_hwaddr (specs, hwaddr); - g_free (hwaddr); - - if (!matched && priv->subchannels) - matched = nm_match_spec_s390_subchannels (specs, priv->subchannels); - - return matched; -} - -static NMConnection * -connection_match_config (NMDevice *self, const GSList *connections) -{ - const GSList *iter; - GSList *ether_matches; - NMConnection *match; - - /* First narrow @connections down to those that match in their - * NMSettingWired configuration. - */ - ether_matches = NULL; - for (iter = connections; iter; iter = iter->next) { - NMConnection *candidate = NM_CONNECTION (iter->data); - - /* Can't assume 802.1x or PPPoE connections; they have too much state - * that's impossible to get on-the-fly from PPPoE or the supplicant. - */ - if ( nm_connection_get_setting_802_1x (candidate) - || nm_connection_get_setting_pppoe (candidate)) - continue; - - if (!match_ethernet_connection (self, candidate, FALSE, NULL)) - continue; - - ether_matches = g_slist_prepend (ether_matches, candidate); - } - - /* Now pass those to the super method, which will check IP config */ - ether_matches = g_slist_reverse (ether_matches); - match = NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->connection_match_config (self, ether_matches); - g_slist_free (ether_matches); - - return match; -} - -static gboolean -hwaddr_matches (NMDevice *device, - NMConnection *connection, - const guint8 *other_hwaddr, - guint other_hwaddr_len, - gboolean fail_if_no_hwaddr) -{ - NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (device); - NMSettingWired *s_wired; - const GByteArray *mac = NULL; - - s_wired = nm_connection_get_setting_wired (connection); - if (s_wired) - mac = nm_setting_wired_get_mac_address (s_wired); - - if (mac) { - g_return_val_if_fail (mac->len == ETH_ALEN, FALSE); - if (other_hwaddr) { - g_return_val_if_fail (other_hwaddr_len == ETH_ALEN, FALSE); - if (memcmp (mac->data, other_hwaddr, mac->len) == 0) - return TRUE; - } else if (memcmp (mac->data, priv->hw_addr, mac->len) == 0) - return TRUE; - } else if (fail_if_no_hwaddr == FALSE) - return TRUE; - - return FALSE; -} - -static void -dispose (GObject *object) -{ - NMDeviceEthernet *self = NM_DEVICE_ETHERNET (object); - NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); - - g_free (priv->subchan1); - g_free (priv->subchan2); - g_free (priv->subchan3); - g_free (priv->subchannels); - - G_OBJECT_CLASS (nm_device_ethernet_parent_class)->dispose (object); -} - -static void -get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) -{ - NMDeviceEthernet *self = NM_DEVICE_ETHERNET (object); - NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); - - switch (prop_id) { - case PROP_HW_ADDRESS: - g_value_take_string (value, nm_utils_hwaddr_ntoa (priv->hw_addr, ARPHRD_ETHER)); - break; - case PROP_PERM_HW_ADDRESS: - g_value_take_string (value, nm_utils_hwaddr_ntoa (&priv->perm_hw_addr, ARPHRD_ETHER)); - break; - case PROP_SPEED: - g_value_set_uint (value, nm_device_wired_get_speed (NM_DEVICE_WIRED (self))); - break; - case PROP_CARRIER: - g_value_set_boolean (value, nm_device_wired_get_carrier (NM_DEVICE_WIRED (self))); - 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) -{ - switch (prop_id) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -nm_device_ethernet_class_init (NMDeviceEthernetClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass); - - g_type_class_add_private (object_class, sizeof (NMDeviceEthernetPrivate)); - - /* virtual methods */ - object_class->constructor = constructor; - object_class->dispose = dispose; - object_class->get_property = get_property; - object_class->set_property = set_property; - - parent_class->get_generic_capabilities = get_generic_capabilities; - parent_class->is_up = is_up; - parent_class->bring_up = bring_up; - parent_class->take_down = take_down; - parent_class->update_hw_address = update_hw_address; - parent_class->get_hw_address = get_hw_address; - parent_class->update_permanent_hw_address = update_permanent_hw_address; - parent_class->update_initial_hw_address = update_initial_hw_address; - parent_class->get_best_auto_connection = get_best_auto_connection; - parent_class->check_connection_compatible = check_connection_compatible; - parent_class->complete_connection = complete_connection; - - parent_class->act_stage1_prepare = act_stage1_prepare; - parent_class->act_stage2_config = act_stage2_config; - parent_class->act_stage3_ip4_config_start = act_stage3_ip4_config_start; - parent_class->ip4_config_pre_commit = ip4_config_pre_commit; - parent_class->deactivate = deactivate; - parent_class->spec_match_list = spec_match_list; - parent_class->connection_match_config = connection_match_config; - parent_class->hwaddr_matches = hwaddr_matches; - - parent_class->state_changed = device_state_changed; - - /* properties */ - g_object_class_install_property - (object_class, PROP_HW_ADDRESS, - g_param_spec_string (NM_DEVICE_ETHERNET_HW_ADDRESS, - "Active MAC Address", - "Currently set hardware MAC address", - NULL, - G_PARAM_READABLE)); - - g_object_class_install_property - (object_class, PROP_PERM_HW_ADDRESS, - g_param_spec_string (NM_DEVICE_ETHERNET_PERMANENT_HW_ADDRESS, - "Permanent MAC Address", - "Permanent hardware MAC address", - NULL, - G_PARAM_READABLE)); - - g_object_class_install_property - (object_class, PROP_SPEED, - g_param_spec_uint (NM_DEVICE_ETHERNET_SPEED, - "Speed", - "Speed", - 0, G_MAXUINT32, 0, - G_PARAM_READABLE)); - - g_object_class_install_property - (object_class, PROP_CARRIER, - g_param_spec_boolean (NM_DEVICE_ETHERNET_CARRIER, - "Carrier", - "Carrier", - FALSE, - G_PARAM_READABLE)); - - /* Signals */ - signals[PROPERTIES_CHANGED] = - nm_properties_changed_signal_new (object_class, - G_STRUCT_OFFSET (NMDeviceEthernetClass, properties_changed)); - - dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass), - &dbus_glib_nm_device_ethernet_object_info); - - dbus_g_error_domain_register (NM_ETHERNET_ERROR, NULL, NM_TYPE_ETHERNET_ERROR); -} - - -/**************************************/ -/* Ethtool capability detection */ -/**************************************/ - -static gboolean -supports_ethtool_carrier_detect (NMDeviceEthernet *self) -{ - int fd; - struct ifreq ifr; - gboolean supports_ethtool = FALSE; - struct ethtool_cmd edata; - - g_return_val_if_fail (self != NULL, FALSE); - - fd = socket (PF_INET, SOCK_DGRAM, 0); - if (fd < 0) { - nm_log_err (LOGD_HW, "couldn't open control socket."); - return FALSE; - } - - memset (&ifr, 0, sizeof (struct ifreq)); - strncpy (ifr.ifr_name, nm_device_get_iface (NM_DEVICE (self)), IFNAMSIZ); - - edata.cmd = ETHTOOL_GLINK; - ifr.ifr_data = (char *) &edata; - - errno = 0; - if (ioctl (fd, SIOCETHTOOL, &ifr) < 0) { - nm_log_dbg (LOGD_HW | LOGD_ETHER, "SIOCETHTOOL failed: %d", errno); - goto out; - } - - supports_ethtool = TRUE; - -out: - close (fd); - nm_log_dbg (LOGD_HW | LOGD_ETHER, "ethtool %s supported", - supports_ethtool ? "is" : "not"); - return supports_ethtool; -} - - -/**************************************/ -/* MII capability detection */ -/**************************************/ -#define _LINUX_IF_H -#include -#undef _LINUX_IF_H - -static int -mdio_read (NMDeviceEthernet *self, int fd, struct ifreq *ifr, int location) -{ - struct mii_ioctl_data *mii; - int val = -1; - - g_return_val_if_fail (fd >= 0, -1); - g_return_val_if_fail (ifr != NULL, -1); - - mii = (struct mii_ioctl_data *) &ifr->ifr_ifru; - mii->reg_num = location; - - errno = 0; - if (ioctl (fd, SIOCGMIIREG, ifr) == 0) { - nm_log_dbg (LOGD_HW | LOGD_ETHER, "SIOCGMIIREG result 0x%X", mii->val_out); - val = mii->val_out; - } else { - nm_log_dbg (LOGD_HW | LOGD_ETHER, "SIOCGMIIREG failed: %d", errno); - } - - return val; -} - -static gboolean -supports_mii_carrier_detect (NMDeviceEthernet *self) -{ - int fd, bmsr; - struct ifreq ifr; - gboolean supports_mii = FALSE; - - g_return_val_if_fail (self != NULL, FALSE); - - fd = socket (PF_INET, SOCK_DGRAM, 0); - if (fd < 0) { - nm_log_err (LOGD_HW, "couldn't open control socket."); - return FALSE; - } - - memset (&ifr, 0, sizeof (struct ifreq)); - strncpy (ifr.ifr_name, nm_device_get_iface (NM_DEVICE (self)), IFNAMSIZ); - - errno = 0; - if (ioctl (fd, SIOCGMIIPHY, &ifr) < 0) { - nm_log_dbg (LOGD_HW | LOGD_ETHER, "SIOCGMIIPHY failed: %d", errno); - goto out; - } - - /* If we can read the BMSR register, we assume that the card supports MII link detection */ - bmsr = mdio_read (self, fd, &ifr, MII_BMSR); - supports_mii = (bmsr != -1) ? TRUE : FALSE; - nm_log_dbg (LOGD_HW | LOGD_ETHER, "MII %s supported", - supports_mii ? "is" : "not"); - -out: - close (fd); - return supports_mii; -} diff --git a/src/nm-device-ethernet.h b/src/nm-device-ethernet.h deleted file mode 100644 index deb0feca..00000000 --- a/src/nm-device-ethernet.h +++ /dev/null @@ -1,71 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2005 - 2010 Red Hat, Inc. - * Copyright (C) 2006 - 2008 Novell, Inc. - */ - -#ifndef NM_DEVICE_ETHERNET_H -#define NM_DEVICE_ETHERNET_H - -#include - -#include "nm-device-wired.h" - -G_BEGIN_DECLS - -#define NM_TYPE_DEVICE_ETHERNET (nm_device_ethernet_get_type ()) -#define NM_DEVICE_ETHERNET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_ETHERNET, NMDeviceEthernet)) -#define NM_DEVICE_ETHERNET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_ETHERNET, NMDeviceEthernetClass)) -#define NM_IS_DEVICE_ETHERNET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_ETHERNET)) -#define NM_IS_DEVICE_ETHERNET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_ETHERNET)) -#define NM_DEVICE_ETHERNET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_ETHERNET, NMDeviceEthernetClass)) - -typedef enum -{ - NM_ETHERNET_ERROR_CONNECTION_NOT_WIRED = 0, /*< nick=ConnectionNotWired >*/ - NM_ETHERNET_ERROR_CONNECTION_INVALID, /*< nick=ConnectionInvalid >*/ - NM_ETHERNET_ERROR_CONNECTION_INCOMPATIBLE, /*< nick=ConnectionIncompatible >*/ -} NMEthernetError; - -#define NM_DEVICE_ETHERNET_HW_ADDRESS "hw-address" -#define NM_DEVICE_ETHERNET_PERMANENT_HW_ADDRESS "perm-hw-address" -#define NM_DEVICE_ETHERNET_SPEED "speed" -#define NM_DEVICE_ETHERNET_CARRIER "carrier" - -typedef struct { - NMDeviceWired parent; -} NMDeviceEthernet; - -typedef struct { - NMDeviceWiredClass parent; - - /* Signals */ - void (*properties_changed) (NMDeviceEthernet *device, GHashTable *properties); -} NMDeviceEthernetClass; - - -GType nm_device_ethernet_get_type (void); - - -NMDevice *nm_device_ethernet_new (const char *udi, - const char *iface, - const char *driver); - -G_END_DECLS - -#endif /* NM_DEVICE_ETHERNET_H */ diff --git a/src/nm-device-factory.h b/src/nm-device-factory.h deleted file mode 100644 index 8a4f4467..00000000 --- a/src/nm-device-factory.h +++ /dev/null @@ -1,91 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2007 - 2011 Red Hat, Inc. - */ - -#ifndef NM_DEVICE_FACTORY_H -#define NM_DEVICE_FACTORY_H - -#include -#include -#include - -#include "NetworkManager.h" - -/* WARNING: this file is private API between NetworkManager and its internal - * device plugins. Its API can change at any time and is not guaranteed to be - * stable. NM and device plugins are distributed together and this API is - * not meant to enable third-party plugins. - */ - -/** - * nm_device_factory_create_device: - * @device: GUdev device object representing the device - * @devpath: sysfs path of the device - * @ifname: interface name of the device - * @driver: driver of the device - * @error: error for failure information - * - * Creates a #NMDevice subclass if the given information represents a device - * the factory is capable of creating. If the information does represent a - * device the factory is capable of creating, but the device could not be - * created, %NULL should be returned and @error should be set. If the - * factory is not capable of creating a device with the given information - * (ie, the factory creates Ethernet devices but the information represents - * a WiFi device) it should return %NULL and leave @error untouched. - * - * Returns: the device object (a subclass of #NMDevice) or %NULL - */ -GObject *nm_device_factory_create_device (GUdevDevice *device, - const char *devpath, - const char *ifname, - const char *driver, - GError **error); - -/* Should match nm_device_factory() */ -typedef GObject * (*NMDeviceFactoryCreateFunc) (GUdevDevice *device, - const char *devpath, - const char *ifname, - const char *driver, - GError **error); - -/** - * nm_device_factory_get_priority: - * - * Returns the priority of this plugin. Higher numbers mean a higher priority. - * - * Returns: plugin priority - */ -guint32 nm_device_factory_get_priority (void); - -typedef guint32 (*NMDeviceFactoryPriorityFunc) (void); - -/** - * nm_device_factory_get_type: - * - * Returns the type of device this factory can create. Only one factory for - * each type of device is allowed. - * - * Returns: the %NMDeviceType - */ -NMDeviceType nm_device_factory_get_type (void); - -typedef NMDeviceType (*NMDeviceFactoryTypeFunc) (void); - -#endif /* NM_DEVICE_FACTORY_H */ - diff --git a/src/nm-device-generic-glue.h b/src/nm-device-generic-glue.h new file mode 100644 index 00000000..472ade14 --- /dev/null +++ b/src/nm-device-generic-glue.h @@ -0,0 +1,73 @@ +/* Generated by dbus-binding-tool; do not edit! */ + + +#ifndef __dbus_glib_marshal_nm_device_generic_MARSHAL_H__ +#define __dbus_glib_marshal_nm_device_generic_MARSHAL_H__ + +#include + +G_BEGIN_DECLS + +#ifdef G_ENABLE_DEBUG +#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v) +#define g_marshal_value_peek_char(v) g_value_get_schar (v) +#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v) +#define g_marshal_value_peek_int(v) g_value_get_int (v) +#define g_marshal_value_peek_uint(v) g_value_get_uint (v) +#define g_marshal_value_peek_long(v) g_value_get_long (v) +#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v) +#define g_marshal_value_peek_int64(v) g_value_get_int64 (v) +#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v) +#define g_marshal_value_peek_enum(v) g_value_get_enum (v) +#define g_marshal_value_peek_flags(v) g_value_get_flags (v) +#define g_marshal_value_peek_float(v) g_value_get_float (v) +#define g_marshal_value_peek_double(v) g_value_get_double (v) +#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v) +#define g_marshal_value_peek_param(v) g_value_get_param (v) +#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v) +#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v) +#define g_marshal_value_peek_object(v) g_value_get_object (v) +#define g_marshal_value_peek_variant(v) g_value_get_variant (v) +#else /* !G_ENABLE_DEBUG */ +/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API. + * Do not access GValues directly in your code. Instead, use the + * g_value_get_*() functions + */ +#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int +#define g_marshal_value_peek_char(v) (v)->data[0].v_int +#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint +#define g_marshal_value_peek_int(v) (v)->data[0].v_int +#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint +#define g_marshal_value_peek_long(v) (v)->data[0].v_long +#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 +#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 +#define g_marshal_value_peek_enum(v) (v)->data[0].v_long +#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_float(v) (v)->data[0].v_float +#define g_marshal_value_peek_double(v) (v)->data[0].v_double +#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer +#endif /* !G_ENABLE_DEBUG */ + + +G_END_DECLS + +#endif /* __dbus_glib_marshal_nm_device_generic_MARSHAL_H__ */ + +#include +static const DBusGMethodInfo dbus_glib_nm_device_generic_methods[] = { +}; + +const DBusGObjectInfo dbus_glib_nm_device_generic_object_info = { 1, + dbus_glib_nm_device_generic_methods, + 0, +"\0", +"org.freedesktop.NetworkManager.Device.Generic\0PropertiesChanged\0\0", +"org.freedesktop.NetworkManager.Device.Generic\0HwAddress\0hw_address\0read\0org.freedesktop.NetworkManager.Device.Generic\0TypeDescription\0type_description\0read\0\0" +}; + diff --git a/src/nm-device-glue.h b/src/nm-device-glue.h new file mode 100644 index 00000000..55b7c558 --- /dev/null +++ b/src/nm-device-glue.h @@ -0,0 +1,78 @@ +/* Generated by dbus-binding-tool; do not edit! */ + + +#ifndef __dbus_glib_marshal_nm_device_MARSHAL_H__ +#define __dbus_glib_marshal_nm_device_MARSHAL_H__ + +#include + +G_BEGIN_DECLS + +#ifdef G_ENABLE_DEBUG +#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v) +#define g_marshal_value_peek_char(v) g_value_get_schar (v) +#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v) +#define g_marshal_value_peek_int(v) g_value_get_int (v) +#define g_marshal_value_peek_uint(v) g_value_get_uint (v) +#define g_marshal_value_peek_long(v) g_value_get_long (v) +#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v) +#define g_marshal_value_peek_int64(v) g_value_get_int64 (v) +#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v) +#define g_marshal_value_peek_enum(v) g_value_get_enum (v) +#define g_marshal_value_peek_flags(v) g_value_get_flags (v) +#define g_marshal_value_peek_float(v) g_value_get_float (v) +#define g_marshal_value_peek_double(v) g_value_get_double (v) +#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v) +#define g_marshal_value_peek_param(v) g_value_get_param (v) +#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v) +#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v) +#define g_marshal_value_peek_object(v) g_value_get_object (v) +#define g_marshal_value_peek_variant(v) g_value_get_variant (v) +#else /* !G_ENABLE_DEBUG */ +/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API. + * Do not access GValues directly in your code. Instead, use the + * g_value_get_*() functions + */ +#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int +#define g_marshal_value_peek_char(v) (v)->data[0].v_int +#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint +#define g_marshal_value_peek_int(v) (v)->data[0].v_int +#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint +#define g_marshal_value_peek_long(v) (v)->data[0].v_long +#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 +#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 +#define g_marshal_value_peek_enum(v) (v)->data[0].v_long +#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_float(v) (v)->data[0].v_float +#define g_marshal_value_peek_double(v) (v)->data[0].v_double +#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer +#endif /* !G_ENABLE_DEBUG */ + + +/* NONE:POINTER */ +#define dbus_glib_marshal_nm_device_VOID__POINTER g_cclosure_marshal_VOID__POINTER +#define dbus_glib_marshal_nm_device_NONE__POINTER dbus_glib_marshal_nm_device_VOID__POINTER + +G_END_DECLS + +#endif /* __dbus_glib_marshal_nm_device_MARSHAL_H__ */ + +#include +static const DBusGMethodInfo dbus_glib_nm_device_methods[] = { + { (GCallback) impl_device_disconnect, dbus_glib_marshal_nm_device_NONE__POINTER, 0 }, +}; + +const DBusGObjectInfo dbus_glib_nm_device_object_info = { 1, + dbus_glib_nm_device_methods, + 1, +"org.freedesktop.NetworkManager.Device\0Disconnect\0A\0\0\0", +"org.freedesktop.NetworkManager.Device\0StateChanged\0\0", +"org.freedesktop.NetworkManager.Device\0Udi\0udi\0read\0org.freedesktop.NetworkManager.Device\0Interface\0interface\0read\0org.freedesktop.NetworkManager.Device\0IpInterface\0ip_interface\0read\0org.freedesktop.NetworkManager.Device\0Driver\0driver\0read\0org.freedesktop.NetworkManager.Device\0DriverVersion\0driver_version\0read\0org.freedesktop.NetworkManager.Device\0FirmwareVersion\0firmware_version\0read\0org.freedesktop.NetworkManager.Device\0Capabilities\0capabilities\0read\0org.freedesktop.NetworkManager.Device\0Ip4Address\0ip4_address\0read\0org.freedesktop.NetworkManager.Device\0State\0state\0read\0org.freedesktop.NetworkManager.Device\0StateReason\0state_reason\0read\0org.freedesktop.NetworkManager.Device\0ActiveConnection\0active_connection\0read\0org.freedesktop.NetworkManager.Device\0Ip4Config\0ip4_config\0read\0org.freedesktop.NetworkManager.Device\0Dhcp4Config\0dhcp4_config\0read\0org.freedesktop.NetworkManager.Device\0Ip6Config\0ip6_config\0read\0org.freedesktop.NetworkManager.Device\0Dhcp6Config\0dhcp6_config\0read\0org.freedesktop.NetworkManager.Device\0Managed\0managed\0read\0org.freedesktop.NetworkManager.Device\0Autoconnect\0autoconnect\0readwrite\0org.freedesktop.NetworkManager.Device\0FirmwareMissing\0firmware_missing\0read\0org.freedesktop.NetworkManager.Device\0DeviceType\0device_type\0read\0org.freedesktop.NetworkManager.Device\0AvailableConnections\0available_connections\0read\0org.freedesktop.NetworkManager.Device\0PhysicalPortId\0physical_port_id\0read\0org.freedesktop.NetworkManager.Device\0Mtu\0mtu\0read\0\0" +}; + diff --git a/src/nm-device-gre-glue.h b/src/nm-device-gre-glue.h new file mode 100644 index 00000000..1347170d --- /dev/null +++ b/src/nm-device-gre-glue.h @@ -0,0 +1,73 @@ +/* Generated by dbus-binding-tool; do not edit! */ + + +#ifndef __dbus_glib_marshal_nm_device_gre_MARSHAL_H__ +#define __dbus_glib_marshal_nm_device_gre_MARSHAL_H__ + +#include + +G_BEGIN_DECLS + +#ifdef G_ENABLE_DEBUG +#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v) +#define g_marshal_value_peek_char(v) g_value_get_schar (v) +#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v) +#define g_marshal_value_peek_int(v) g_value_get_int (v) +#define g_marshal_value_peek_uint(v) g_value_get_uint (v) +#define g_marshal_value_peek_long(v) g_value_get_long (v) +#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v) +#define g_marshal_value_peek_int64(v) g_value_get_int64 (v) +#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v) +#define g_marshal_value_peek_enum(v) g_value_get_enum (v) +#define g_marshal_value_peek_flags(v) g_value_get_flags (v) +#define g_marshal_value_peek_float(v) g_value_get_float (v) +#define g_marshal_value_peek_double(v) g_value_get_double (v) +#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v) +#define g_marshal_value_peek_param(v) g_value_get_param (v) +#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v) +#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v) +#define g_marshal_value_peek_object(v) g_value_get_object (v) +#define g_marshal_value_peek_variant(v) g_value_get_variant (v) +#else /* !G_ENABLE_DEBUG */ +/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API. + * Do not access GValues directly in your code. Instead, use the + * g_value_get_*() functions + */ +#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int +#define g_marshal_value_peek_char(v) (v)->data[0].v_int +#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint +#define g_marshal_value_peek_int(v) (v)->data[0].v_int +#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint +#define g_marshal_value_peek_long(v) (v)->data[0].v_long +#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 +#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 +#define g_marshal_value_peek_enum(v) (v)->data[0].v_long +#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_float(v) (v)->data[0].v_float +#define g_marshal_value_peek_double(v) (v)->data[0].v_double +#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer +#endif /* !G_ENABLE_DEBUG */ + + +G_END_DECLS + +#endif /* __dbus_glib_marshal_nm_device_gre_MARSHAL_H__ */ + +#include +static const DBusGMethodInfo dbus_glib_nm_device_gre_methods[] = { +}; + +const DBusGObjectInfo dbus_glib_nm_device_gre_object_info = { 1, + dbus_glib_nm_device_gre_methods, + 0, +"\0", +"org.freedesktop.NetworkManager.Device.Gre\0PropertiesChanged\0\0", +"org.freedesktop.NetworkManager.Device.Gre\0Parent\0parent\0read\0org.freedesktop.NetworkManager.Device.Gre\0InputFlags\0input_flags\0read\0org.freedesktop.NetworkManager.Device.Gre\0OutputFlags\0output_flags\0read\0org.freedesktop.NetworkManager.Device.Gre\0InputKey\0input_key\0read\0org.freedesktop.NetworkManager.Device.Gre\0OutputKey\0output_key\0read\0org.freedesktop.NetworkManager.Device.Gre\0Local\0local\0read\0org.freedesktop.NetworkManager.Device.Gre\0Remote\0remote\0read\0org.freedesktop.NetworkManager.Device.Gre\0Ttl\0ttl\0read\0org.freedesktop.NetworkManager.Device.Gre\0Tos\0tos\0read\0org.freedesktop.NetworkManager.Device.Gre\0PathMtuDiscovery\0path_mtu_discovery\0read\0\0" +}; + diff --git a/src/nm-device-infiniband-glue.h b/src/nm-device-infiniband-glue.h new file mode 100644 index 00000000..a762f57c --- /dev/null +++ b/src/nm-device-infiniband-glue.h @@ -0,0 +1,73 @@ +/* Generated by dbus-binding-tool; do not edit! */ + + +#ifndef __dbus_glib_marshal_nm_device_infiniband_MARSHAL_H__ +#define __dbus_glib_marshal_nm_device_infiniband_MARSHAL_H__ + +#include + +G_BEGIN_DECLS + +#ifdef G_ENABLE_DEBUG +#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v) +#define g_marshal_value_peek_char(v) g_value_get_schar (v) +#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v) +#define g_marshal_value_peek_int(v) g_value_get_int (v) +#define g_marshal_value_peek_uint(v) g_value_get_uint (v) +#define g_marshal_value_peek_long(v) g_value_get_long (v) +#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v) +#define g_marshal_value_peek_int64(v) g_value_get_int64 (v) +#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v) +#define g_marshal_value_peek_enum(v) g_value_get_enum (v) +#define g_marshal_value_peek_flags(v) g_value_get_flags (v) +#define g_marshal_value_peek_float(v) g_value_get_float (v) +#define g_marshal_value_peek_double(v) g_value_get_double (v) +#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v) +#define g_marshal_value_peek_param(v) g_value_get_param (v) +#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v) +#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v) +#define g_marshal_value_peek_object(v) g_value_get_object (v) +#define g_marshal_value_peek_variant(v) g_value_get_variant (v) +#else /* !G_ENABLE_DEBUG */ +/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API. + * Do not access GValues directly in your code. Instead, use the + * g_value_get_*() functions + */ +#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int +#define g_marshal_value_peek_char(v) (v)->data[0].v_int +#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint +#define g_marshal_value_peek_int(v) (v)->data[0].v_int +#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint +#define g_marshal_value_peek_long(v) (v)->data[0].v_long +#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 +#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 +#define g_marshal_value_peek_enum(v) (v)->data[0].v_long +#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_float(v) (v)->data[0].v_float +#define g_marshal_value_peek_double(v) (v)->data[0].v_double +#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer +#endif /* !G_ENABLE_DEBUG */ + + +G_END_DECLS + +#endif /* __dbus_glib_marshal_nm_device_infiniband_MARSHAL_H__ */ + +#include +static const DBusGMethodInfo dbus_glib_nm_device_infiniband_methods[] = { +}; + +const DBusGObjectInfo dbus_glib_nm_device_infiniband_object_info = { 1, + dbus_glib_nm_device_infiniband_methods, + 0, +"\0", +"org.freedesktop.NetworkManager.Device.Infiniband\0PropertiesChanged\0\0", +"org.freedesktop.NetworkManager.Device.Infiniband\0HwAddress\0hw_address\0read\0org.freedesktop.NetworkManager.Device.Infiniband\0Carrier\0carrier\0read\0\0" +}; + diff --git a/src/nm-device-infiniband.c b/src/nm-device-infiniband.c deleted file mode 100644 index c7dcf19c..00000000 --- a/src/nm-device-infiniband.c +++ /dev/null @@ -1,509 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2011 Red Hat, Inc. - */ - -#include "config.h" - -#include -#include - -#include -#include - -#include "nm-device-infiniband.h" -#include "nm-logging.h" -#include "nm-properties-changed-signal.h" -#include "nm-utils.h" -#include "NetworkManagerUtils.h" -#include "nm-device-private.h" -#include "nm-enum-types.h" - -#include "nm-device-infiniband-glue.h" - - -G_DEFINE_TYPE (NMDeviceInfiniband, nm_device_infiniband, NM_TYPE_DEVICE_WIRED) - -#define NM_DEVICE_INFINIBAND_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_INFINIBAND, NMDeviceInfinibandPrivate)) - -#define NM_INFINIBAND_ERROR (nm_infiniband_error_quark ()) - -typedef struct { - guint8 hw_addr[INFINIBAND_ALEN]; -} NMDeviceInfinibandPrivate; - -enum { - PROPERTIES_CHANGED, - - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -enum { - PROP_0, - PROP_HW_ADDRESS, - PROP_CARRIER, - - LAST_PROP -}; - -static GQuark -nm_infiniband_error_quark (void) -{ - static GQuark quark = 0; - if (!quark) - quark = g_quark_from_static_string ("nm-infiniband-error"); - return quark; -} - -static GObject* -constructor (GType type, - guint n_construct_params, - GObjectConstructParam *construct_params) -{ - GObject *object; - NMDeviceInfinibandPrivate *priv; - NMDevice *self; - - object = G_OBJECT_CLASS (nm_device_infiniband_parent_class)->constructor (type, - n_construct_params, - construct_params); - if (!object) - return NULL; - - self = NM_DEVICE (object); - priv = NM_DEVICE_INFINIBAND_GET_PRIVATE (self); - - nm_log_dbg (LOGD_HW | LOGD_INFINIBAND, "(%s): kernel ifindex %d", - nm_device_get_iface (NM_DEVICE (self)), - nm_device_get_ifindex (NM_DEVICE (self))); - - return object; -} - -static void -nm_device_infiniband_init (NMDeviceInfiniband * self) -{ -} - -NMDevice * -nm_device_infiniband_new (const char *udi, - const char *iface, - const char *driver) -{ - g_return_val_if_fail (udi != NULL, NULL); - g_return_val_if_fail (iface != NULL, NULL); - g_return_val_if_fail (driver != NULL, NULL); - - return (NMDevice *) g_object_new (NM_TYPE_DEVICE_INFINIBAND, - NM_DEVICE_UDI, udi, - NM_DEVICE_IFACE, iface, - NM_DEVICE_DRIVER, driver, - NM_DEVICE_TYPE_DESC, "InfiniBand", - NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_INFINIBAND, - NULL); -} - -static void -update_hw_address (NMDevice *dev) -{ - NMDeviceInfinibandPrivate *priv = NM_DEVICE_INFINIBAND_GET_PRIVATE (dev); - gsize addrlen; - gboolean changed = FALSE; - - addrlen = nm_device_read_hwaddr (dev, priv->hw_addr, sizeof (priv->hw_addr), &changed); - if (addrlen) { - g_return_if_fail (addrlen == INFINIBAND_ALEN); - if (changed) - g_object_notify (G_OBJECT (dev), NM_DEVICE_INFINIBAND_HW_ADDRESS); - } -} - -static const guint8 * -get_hw_address (NMDevice *device, guint *out_len) -{ - *out_len = INFINIBAND_ALEN; - return NM_DEVICE_INFINIBAND_GET_PRIVATE (device)->hw_addr; -} - -static guint32 -get_generic_capabilities (NMDevice *dev) -{ - return NM_DEVICE_CAP_CARRIER_DETECT | NM_DEVICE_CAP_NM_SUPPORTED; -} - -static NMConnection * -get_best_auto_connection (NMDevice *dev, - GSList *connections, - char **specific_object) -{ - NMDeviceInfinibandPrivate *priv = NM_DEVICE_INFINIBAND_GET_PRIVATE (dev); - GSList *iter; - - for (iter = connections; iter; iter = g_slist_next (iter)) { - NMConnection *connection = NM_CONNECTION (iter->data); - NMSettingInfiniband *s_infiniband; - - if (!nm_connection_is_type (connection, NM_SETTING_INFINIBAND_SETTING_NAME)) - continue; - - s_infiniband = nm_connection_get_setting_infiniband (connection); - if (!s_infiniband) - continue; - - if (s_infiniband) { - const GByteArray *mac; - - mac = nm_setting_infiniband_get_mac_address (s_infiniband); - if (mac && memcmp (mac->data, priv->hw_addr, INFINIBAND_ALEN)) - continue; - } - - return connection; - } - return NULL; -} - -static NMActStageReturn -act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason) -{ - NMActRequest *req; - NMConnection *connection; - NMSettingInfiniband *s_infiniband; - const char *transport_mode; - char *mode_path; - gboolean ok; - - g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); - - req = nm_device_get_act_request (dev); - g_return_val_if_fail (req != NULL, NM_ACT_STAGE_RETURN_FAILURE); - - connection = nm_act_request_get_connection (req); - g_assert (connection); - s_infiniband = nm_connection_get_setting_infiniband (connection); - g_assert (s_infiniband); - - transport_mode = nm_setting_infiniband_get_transport_mode (s_infiniband); - - mode_path = g_strdup_printf ("/sys/class/net/%s/mode", nm_device_get_iface (dev)); - if (!g_file_test (mode_path, G_FILE_TEST_EXISTS)) { - g_free (mode_path); - - if (!strcmp (transport_mode, "datagram")) - return NM_ACT_STAGE_RETURN_SUCCESS; - else { - *reason = NM_DEVICE_STATE_REASON_INFINIBAND_MODE; - return NM_ACT_STAGE_RETURN_FAILURE; - } - } - - ok = nm_utils_do_sysctl (mode_path, transport_mode); - g_free (mode_path); - - if (!ok) { - *reason = NM_DEVICE_STATE_REASON_CONFIG_FAILED; - return NM_ACT_STAGE_RETURN_FAILURE; - } - - return NM_DEVICE_CLASS (nm_device_infiniband_parent_class)->act_stage1_prepare (dev, reason); -} - -static void -ip4_config_pre_commit (NMDevice *self, NMIP4Config *config) -{ - NMConnection *connection; - NMSettingInfiniband *s_infiniband; - guint32 mtu; - - connection = nm_device_get_connection (self); - g_assert (connection); - s_infiniband = nm_connection_get_setting_infiniband (connection); - g_assert (s_infiniband); - - /* MTU override */ - mtu = nm_setting_infiniband_get_mtu (s_infiniband); - if (mtu) - nm_ip4_config_set_mtu (config, mtu); -} - -static gboolean -check_connection_compatible (NMDevice *device, - NMConnection *connection, - GError **error) -{ - NMDeviceInfinibandPrivate *priv = NM_DEVICE_INFINIBAND_GET_PRIVATE (device); - NMSettingInfiniband *s_infiniband; - const GByteArray *mac; - - if (!nm_connection_is_type (connection, NM_SETTING_INFINIBAND_SETTING_NAME)) { - g_set_error (error, - NM_INFINIBAND_ERROR, - NM_INFINIBAND_ERROR_CONNECTION_NOT_INFINIBAND, - "The connection was not an InfiniBand connection."); - return FALSE; - } - - s_infiniband = nm_connection_get_setting_infiniband (connection); - if (!s_infiniband) { - g_set_error (error, - NM_INFINIBAND_ERROR, NM_INFINIBAND_ERROR_CONNECTION_INVALID, - "The connection was not a valid infiniband connection."); - return FALSE; - } - - if (s_infiniband) { - mac = nm_setting_infiniband_get_mac_address (s_infiniband); - if (mac && memcmp (mac->data, priv->hw_addr, INFINIBAND_ALEN)) { - g_set_error (error, - NM_INFINIBAND_ERROR, - NM_INFINIBAND_ERROR_CONNECTION_INCOMPATIBLE, - "The connection's MAC address did not match this device."); - return FALSE; - } - } - - return TRUE; -} - -static gboolean -complete_connection (NMDevice *device, - NMConnection *connection, - const char *specific_object, - const GSList *existing_connections, - GError **error) -{ - NMDeviceInfinibandPrivate *priv = NM_DEVICE_INFINIBAND_GET_PRIVATE (device); - NMSettingInfiniband *s_infiniband; - const GByteArray *setting_mac; - - nm_utils_complete_generic (connection, - NM_SETTING_INFINIBAND_SETTING_NAME, - existing_connections, - _("InfiniBand connection %d"), - NULL, - TRUE); - - s_infiniband = nm_connection_get_setting_infiniband (connection); - if (!s_infiniband) { - s_infiniband = (NMSettingInfiniband *) nm_setting_infiniband_new (); - nm_connection_add_setting (connection, NM_SETTING (s_infiniband)); - } - - setting_mac = nm_setting_infiniband_get_mac_address (s_infiniband); - if (setting_mac) { - /* Make sure the setting MAC (if any) matches the device's MAC */ - if (memcmp (setting_mac->data, priv->hw_addr, INFINIBAND_ALEN)) { - g_set_error_literal (error, - NM_SETTING_INFINIBAND_ERROR, - NM_SETTING_INFINIBAND_ERROR_INVALID_PROPERTY, - NM_SETTING_INFINIBAND_MAC_ADDRESS); - return FALSE; - } - } else { - GByteArray *mac; - - /* Lock the connection to this device by default */ - mac = g_byte_array_sized_new (sizeof (priv->hw_addr)); - g_byte_array_append (mac, priv->hw_addr, sizeof (priv->hw_addr)); - g_object_set (G_OBJECT (s_infiniband), NM_SETTING_INFINIBAND_MAC_ADDRESS, mac, NULL); - g_byte_array_free (mac, TRUE); - } - - if (!nm_setting_infiniband_get_transport_mode (s_infiniband)) - g_object_set (G_OBJECT (s_infiniband), NM_SETTING_INFINIBAND_TRANSPORT_MODE, "datagram", NULL); - - return TRUE; -} - -static gboolean -spec_match_list (NMDevice *device, const GSList *specs) -{ - NMDeviceInfinibandPrivate *priv = NM_DEVICE_INFINIBAND_GET_PRIVATE (device); - char *hwaddr; - gboolean matched; - - hwaddr = nm_utils_hwaddr_ntoa (priv->hw_addr, ARPHRD_INFINIBAND); - matched = nm_match_spec_hwaddr (specs, hwaddr); - g_free (hwaddr); - - return matched; -} - -static gboolean -infiniband_match_config (NMDevice *self, NMConnection *connection) -{ - NMDeviceInfinibandPrivate *priv = NM_DEVICE_INFINIBAND_GET_PRIVATE (self); - NMSettingInfiniband *s_infiniband; - const GByteArray *s_mac; - - s_infiniband = nm_connection_get_setting_infiniband (connection); - if (!s_infiniband) - return FALSE; - - /* MAC address check */ - s_mac = nm_setting_infiniband_get_mac_address (s_infiniband); - if (s_mac && memcmp (s_mac->data, priv->hw_addr, INFINIBAND_ALEN)) - return FALSE; - - return TRUE; -} - -static NMConnection * -connection_match_config (NMDevice *self, const GSList *connections) -{ - const GSList *iter; - GSList *infiniband_matches; - NMConnection *match; - - /* First narrow @connections down to those that match in their - * NMSettingInfiniband configuration. - */ - infiniband_matches = NULL; - for (iter = connections; iter; iter = iter->next) { - NMConnection *candidate = NM_CONNECTION (iter->data); - - if (!nm_connection_is_type (candidate, NM_SETTING_INFINIBAND_SETTING_NAME)) - continue; - if (!infiniband_match_config (self, candidate)) - continue; - - infiniband_matches = g_slist_prepend (infiniband_matches, candidate); - } - - /* Now pass those to the super method, which will check IP config */ - infiniband_matches = g_slist_reverse (infiniband_matches); - match = NM_DEVICE_CLASS (nm_device_infiniband_parent_class)->connection_match_config (self, infiniband_matches); - g_slist_free (infiniband_matches); - - return match; -} - -static gboolean -hwaddr_matches (NMDevice *device, - NMConnection *connection, - const guint8 *other_hwaddr, - guint other_hwaddr_len, - gboolean fail_if_no_hwaddr) -{ - NMDeviceInfinibandPrivate *priv = NM_DEVICE_INFINIBAND_GET_PRIVATE (device); - NMSettingInfiniband *s_ib; - const GByteArray *mac = NULL; - - s_ib = nm_connection_get_setting_infiniband (connection); - if (s_ib) - mac = nm_setting_infiniband_get_mac_address (s_ib); - - if (mac) { - g_return_val_if_fail (mac->len == INFINIBAND_ALEN, FALSE); - if (other_hwaddr) { - g_return_val_if_fail (other_hwaddr_len == INFINIBAND_ALEN, FALSE); - if (memcmp (mac->data, other_hwaddr, mac->len) == 0) - return TRUE; - } else if (memcmp (mac->data, priv->hw_addr, mac->len) == 0) - return TRUE; - } else if (fail_if_no_hwaddr == FALSE) - return TRUE; - - return FALSE; -} - -static void -get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) -{ - NMDeviceInfinibandPrivate *priv = NM_DEVICE_INFINIBAND_GET_PRIVATE (object); - - switch (prop_id) { - case PROP_HW_ADDRESS: - g_value_take_string (value, nm_utils_hwaddr_ntoa (priv->hw_addr, ARPHRD_INFINIBAND)); - break; - case PROP_CARRIER: - g_value_set_boolean (value, nm_device_wired_get_carrier (NM_DEVICE_WIRED (object))); - 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) -{ - switch (prop_id) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -nm_device_infiniband_class_init (NMDeviceInfinibandClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass); - - g_type_class_add_private (object_class, sizeof (NMDeviceInfinibandPrivate)); - - /* virtual methods */ - object_class->constructor = constructor; - object_class->get_property = get_property; - object_class->set_property = set_property; - - parent_class->get_generic_capabilities = get_generic_capabilities; - parent_class->update_hw_address = update_hw_address; - parent_class->get_hw_address = get_hw_address; - parent_class->get_best_auto_connection = get_best_auto_connection; - parent_class->check_connection_compatible = check_connection_compatible; - parent_class->complete_connection = complete_connection; - - parent_class->act_stage1_prepare = act_stage1_prepare; - parent_class->ip4_config_pre_commit = ip4_config_pre_commit; - parent_class->spec_match_list = spec_match_list; - parent_class->connection_match_config = connection_match_config; - parent_class->hwaddr_matches = hwaddr_matches; - - /* properties */ - g_object_class_install_property - (object_class, PROP_HW_ADDRESS, - g_param_spec_string (NM_DEVICE_INFINIBAND_HW_ADDRESS, - "Active MAC Address", - "Currently set hardware MAC address", - NULL, - G_PARAM_READABLE)); - - g_object_class_install_property - (object_class, PROP_CARRIER, - g_param_spec_boolean (NM_DEVICE_INFINIBAND_CARRIER, - "Carrier", - "Carrier", - FALSE, - G_PARAM_READABLE)); - - /* Signals */ - signals[PROPERTIES_CHANGED] = - nm_properties_changed_signal_new (object_class, - G_STRUCT_OFFSET (NMDeviceInfinibandClass, properties_changed)); - - dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass), - &dbus_glib_nm_device_infiniband_object_info); - - dbus_g_error_domain_register (NM_INFINIBAND_ERROR, NULL, NM_TYPE_INFINIBAND_ERROR); -} diff --git a/src/nm-device-infiniband.h b/src/nm-device-infiniband.h deleted file mode 100644 index fe88c901..00000000 --- a/src/nm-device-infiniband.h +++ /dev/null @@ -1,66 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2011 Red Hat, Inc. - */ - -#ifndef NM_DEVICE_INFINIBAND_H -#define NM_DEVICE_INFINIBAND_H - -#include - -#include "nm-device-wired.h" - -G_BEGIN_DECLS - -#define NM_TYPE_DEVICE_INFINIBAND (nm_device_infiniband_get_type ()) -#define NM_DEVICE_INFINIBAND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_INFINIBAND, NMDeviceInfiniband)) -#define NM_DEVICE_INFINIBAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_INFINIBAND, NMDeviceInfinibandClass)) -#define NM_IS_DEVICE_INFINIBAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_INFINIBAND)) -#define NM_IS_DEVICE_INFINIBAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_INFINIBAND)) -#define NM_DEVICE_INFINIBAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_INFINIBAND, NMDeviceInfinibandClass)) - -typedef enum { - NM_INFINIBAND_ERROR_CONNECTION_NOT_INFINIBAND = 0, /*< nick=ConnectionNotInfiniband >*/ - NM_INFINIBAND_ERROR_CONNECTION_INVALID, /*< nick=ConnectionInvalid >*/ - NM_INFINIBAND_ERROR_CONNECTION_INCOMPATIBLE, /*< nick=ConnectionIncompatible >*/ -} NMInfinibandError; - -#define NM_DEVICE_INFINIBAND_HW_ADDRESS "hw-address" -#define NM_DEVICE_INFINIBAND_CARRIER "carrier" - -typedef struct { - NMDeviceWired parent; -} NMDeviceInfiniband; - -typedef struct { - NMDeviceWiredClass parent; - - /* Signals */ - void (*properties_changed) (NMDeviceInfiniband *device, GHashTable *properties); -} NMDeviceInfinibandClass; - - -GType nm_device_infiniband_get_type (void); - -NMDevice *nm_device_infiniband_new (const char *udi, - const char *iface, - const char *driver); - -G_END_DECLS - -#endif /* NM_DEVICE_INFINIBAND_H */ diff --git a/src/nm-device-macvlan-glue.h b/src/nm-device-macvlan-glue.h new file mode 100644 index 00000000..18f5d602 --- /dev/null +++ b/src/nm-device-macvlan-glue.h @@ -0,0 +1,73 @@ +/* Generated by dbus-binding-tool; do not edit! */ + + +#ifndef __dbus_glib_marshal_nm_device_macvlan_MARSHAL_H__ +#define __dbus_glib_marshal_nm_device_macvlan_MARSHAL_H__ + +#include + +G_BEGIN_DECLS + +#ifdef G_ENABLE_DEBUG +#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v) +#define g_marshal_value_peek_char(v) g_value_get_schar (v) +#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v) +#define g_marshal_value_peek_int(v) g_value_get_int (v) +#define g_marshal_value_peek_uint(v) g_value_get_uint (v) +#define g_marshal_value_peek_long(v) g_value_get_long (v) +#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v) +#define g_marshal_value_peek_int64(v) g_value_get_int64 (v) +#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v) +#define g_marshal_value_peek_enum(v) g_value_get_enum (v) +#define g_marshal_value_peek_flags(v) g_value_get_flags (v) +#define g_marshal_value_peek_float(v) g_value_get_float (v) +#define g_marshal_value_peek_double(v) g_value_get_double (v) +#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v) +#define g_marshal_value_peek_param(v) g_value_get_param (v) +#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v) +#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v) +#define g_marshal_value_peek_object(v) g_value_get_object (v) +#define g_marshal_value_peek_variant(v) g_value_get_variant (v) +#else /* !G_ENABLE_DEBUG */ +/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API. + * Do not access GValues directly in your code. Instead, use the + * g_value_get_*() functions + */ +#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int +#define g_marshal_value_peek_char(v) (v)->data[0].v_int +#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint +#define g_marshal_value_peek_int(v) (v)->data[0].v_int +#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint +#define g_marshal_value_peek_long(v) (v)->data[0].v_long +#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 +#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 +#define g_marshal_value_peek_enum(v) (v)->data[0].v_long +#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_float(v) (v)->data[0].v_float +#define g_marshal_value_peek_double(v) (v)->data[0].v_double +#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer +#endif /* !G_ENABLE_DEBUG */ + + +G_END_DECLS + +#endif /* __dbus_glib_marshal_nm_device_macvlan_MARSHAL_H__ */ + +#include +static const DBusGMethodInfo dbus_glib_nm_device_macvlan_methods[] = { +}; + +const DBusGObjectInfo dbus_glib_nm_device_macvlan_object_info = { 1, + dbus_glib_nm_device_macvlan_methods, + 0, +"\0", +"org.freedesktop.NetworkManager.Device.Macvlan\0PropertiesChanged\0\0", +"org.freedesktop.NetworkManager.Device.Macvlan\0Parent\0parent\0read\0org.freedesktop.NetworkManager.Device.Macvlan\0Mode\0mode\0read\0org.freedesktop.NetworkManager.Device.Macvlan\0NoPromisc\0no_promisc\0read\0\0" +}; + diff --git a/src/nm-device-modem.c b/src/nm-device-modem.c deleted file mode 100644 index 24d9cefb..00000000 --- a/src/nm-device-modem.c +++ /dev/null @@ -1,544 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2009 - 2011 Red Hat, Inc. - */ - -#include "config.h" - -#include - -#include "nm-device-modem.h" -#include "nm-modem.h" -#include "nm-modem-cdma.h" -#include "nm-modem-gsm.h" -#include "nm-device-private.h" -#include "nm-properties-changed-signal.h" -#include "nm-rfkill.h" -#include "nm-marshal.h" -#include "nm-logging.h" -#include "nm-system.h" - -#if WITH_MODEM_MANAGER_1 -#include "nm-modem-broadband.h" -#endif - -G_DEFINE_TYPE (NMDeviceModem, nm_device_modem, NM_TYPE_DEVICE) - -#define NM_DEVICE_MODEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_MODEM, NMDeviceModemPrivate)) - -#include "nm-device-modem-glue.h" - -typedef struct { - NMModem *modem; - NMDeviceModemCapabilities caps; - NMDeviceModemCapabilities current_caps; -} NMDeviceModemPrivate; - -enum { - PROP_0, - PROP_MODEM, - PROP_CAPABILITIES, - PROP_CURRENT_CAPABILITIES, -}; - -enum { - PROPERTIES_CHANGED, - ENABLE_CHANGED, - LAST_SIGNAL -}; -static guint signals[LAST_SIGNAL] = { 0 }; - -static void set_enabled (NMDevice *device, gboolean enabled); - -/*****************************************************************************/ - -static void -ppp_failed (NMModem *modem, NMDeviceStateReason reason, gpointer user_data) -{ - NMDevice *device = NM_DEVICE (user_data); - - switch (nm_device_get_state (device)) { - case NM_DEVICE_STATE_PREPARE: - case NM_DEVICE_STATE_CONFIG: - case NM_DEVICE_STATE_NEED_AUTH: - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, reason); - break; - case NM_DEVICE_STATE_IP_CONFIG: - case NM_DEVICE_STATE_IP_CHECK: - case NM_DEVICE_STATE_SECONDARIES: - case NM_DEVICE_STATE_ACTIVATED: - if (nm_device_activate_ip4_state_in_conf (device)) - nm_device_activate_schedule_ip4_config_timeout (device); - else { - nm_device_state_changed (device, - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); - } - break; - default: - break; - } -} - -static void -modem_prepare_result (NMModem *modem, - gboolean success, - NMDeviceStateReason reason, - gpointer user_data) -{ - NMDevice *device = NM_DEVICE (user_data); - NMDeviceState state; - - state = nm_device_get_state (device); - g_return_if_fail (state == NM_DEVICE_STATE_PREPARE); - - if (success) - nm_device_activate_schedule_stage2_device_config (device); - else - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, reason); -} - -static void -modem_auth_requested (NMModem *modem, gpointer user_data) -{ - nm_device_state_changed (NM_DEVICE (user_data), - NM_DEVICE_STATE_NEED_AUTH, - NM_DEVICE_STATE_REASON_NONE); -} - -static void -modem_auth_result (NMModem *modem, GError *error, gpointer user_data) -{ - NMDevice *device = NM_DEVICE (user_data); - - if (error) { - nm_device_state_changed (device, - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_NO_SECRETS); - } else { - /* Otherwise, on success for modem secrets we need to schedule stage1 again */ - g_return_if_fail (nm_device_get_state (device) == NM_DEVICE_STATE_NEED_AUTH); - nm_device_activate_schedule_stage1_device_prepare (device); - } -} - -static void -modem_ip4_config_result (NMModem *self, - NMIP4Config *config, - GError *error, - gpointer user_data) -{ - NMDevice *device = NM_DEVICE (user_data); - - g_return_if_fail (nm_device_activate_ip4_state_in_conf (device) == TRUE); - - if (error) { - nm_log_warn (LOGD_MB | LOGD_IP4, "retrieving IP4 configuration failed: (%d) %s", - error ? error->code : -1, - error && error->message ? error->message : "(unknown)"); - - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); - } else - nm_device_activate_schedule_ip4_config_result (device, config); -} - -static void -data_port_changed_cb (NMModem *modem, GParamSpec *pspec, gpointer user_data) -{ - NMDevice *self = NM_DEVICE (user_data); - - /* We set the IP iface in the device as soon as we know it, so that we - * properly ifup it if needed */ - nm_device_set_ip_iface (self, nm_modem_get_data_port (modem)); -} - -static void -modem_enabled_cb (NMModem *modem, GParamSpec *pspec, gpointer user_data) -{ - NMDeviceModem *self = NM_DEVICE_MODEM (user_data); - NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (self); - - set_enabled (NM_DEVICE (self), nm_modem_get_mm_enabled (priv->modem)); - - g_signal_emit (G_OBJECT (self), signals[ENABLE_CHANGED], 0); -} - -static void -modem_connected_cb (NMModem *modem, GParamSpec *pspec, gpointer user_data) -{ - NMDeviceModem *self = NM_DEVICE_MODEM (user_data); - NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (self); - - if ( nm_device_get_state (NM_DEVICE (self)) == NM_DEVICE_STATE_ACTIVATED - && !nm_modem_get_mm_connected (priv->modem)) { - /* Fail the device if the modem disconnects unexpectedly */ - nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER); - } -} - -/*****************************************************************************/ - -NMModem * -nm_device_modem_get_modem (NMDeviceModem *self) -{ - g_return_val_if_fail (self != NULL, NULL); - g_return_val_if_fail (NM_IS_DEVICE_MODEM (self), NULL); - - return NM_DEVICE_MODEM_GET_PRIVATE (self)->modem; -} - -/*****************************************************************************/ - -static void -device_state_changed (NMDevice *device, - NMDeviceState new_state, - NMDeviceState old_state, - NMDeviceStateReason reason) -{ - nm_modem_device_state_changed (NM_DEVICE_MODEM_GET_PRIVATE (device)->modem, - new_state, - old_state, - reason); -} - -static guint32 -get_generic_capabilities (NMDevice *device) -{ - return NM_DEVICE_CAP_NM_SUPPORTED; -} - -static NMConnection * -get_best_auto_connection (NMDevice *device, - GSList *connections, - char **specific_object) -{ - NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (device); - - return nm_modem_get_best_auto_connection (priv->modem, connections, specific_object); -} - -static gboolean -check_connection_compatible (NMDevice *device, - NMConnection *connection, - GError **error) -{ - NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (device); - - return nm_modem_check_connection_compatible (priv->modem, connection, error); -} - -static gboolean -complete_connection (NMDevice *device, - NMConnection *connection, - const char *specific_object, - const GSList *existing_connections, - GError **error) -{ - NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (device); - - return nm_modem_complete_connection (priv->modem, connection, existing_connections, error); -} - -static void -deactivate (NMDevice *device) -{ - nm_modem_deactivate (NM_DEVICE_MODEM_GET_PRIVATE (device)->modem, device); -} - -static NMActStageReturn -act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) -{ - NMActRequest *req; - - req = nm_device_get_act_request (device); - g_assert (req); - - return nm_modem_act_stage1_prepare (NM_DEVICE_MODEM_GET_PRIVATE (device)->modem, req, reason); -} - -static NMActStageReturn -act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) -{ - NMActRequest *req; - - req = nm_device_get_act_request (device); - g_assert (req); - - return nm_modem_act_stage2_config (NM_DEVICE_MODEM_GET_PRIVATE (device)->modem, req, reason); -} - -static NMActStageReturn -act_stage3_ip4_config_start (NMDevice *device, - NMIP4Config **out_config, - NMDeviceStateReason *reason) -{ - return nm_modem_stage3_ip4_config_start (NM_DEVICE_MODEM_GET_PRIVATE (device)->modem, - device, - NM_DEVICE_CLASS (nm_device_modem_parent_class), - reason); -} - -static void -ip4_config_pre_commit (NMDevice *device, NMIP4Config *config) -{ - nm_modem_ip4_pre_commit (NM_DEVICE_MODEM_GET_PRIVATE (device)->modem, device, config); -} - -static NMActStageReturn -act_stage3_ip6_config_start (NMDevice *device, - NMIP6Config **out_config, - NMDeviceStateReason *reason) -{ - return nm_modem_stage3_ip6_config_start (NM_DEVICE_MODEM_GET_PRIVATE (device)->modem, - device, - NM_DEVICE_CLASS (nm_device_modem_parent_class), - reason); -} - -/*****************************************************************************/ - -static gboolean -get_enabled (NMDevice *device) -{ - return nm_modem_get_mm_enabled (NM_DEVICE_MODEM_GET_PRIVATE (device)->modem); -} - -static void -set_enabled (NMDevice *device, gboolean enabled) -{ - NMDeviceModem *self = NM_DEVICE_MODEM (device); - NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (self); - NMDeviceState state; - - if (priv->modem) { - nm_modem_set_mm_enabled (priv->modem, enabled); - - if (enabled == FALSE) { - state = nm_device_get_state (device); - if (nm_device_is_activating (device) || state == NM_DEVICE_STATE_ACTIVATED) { - /* user-initiated action, hence DISCONNECTED not FAILED */ - nm_device_state_changed (device, - NM_DEVICE_STATE_DISCONNECTED, - NM_DEVICE_STATE_REASON_USER_REQUESTED); - } - } - } -} - -/*****************************************************************************/ - -NMDevice * -nm_device_modem_new (NMModem *modem, const char *driver) -{ - NMDeviceModemCapabilities caps = NM_DEVICE_MODEM_CAPABILITY_NONE; - NMDeviceModemCapabilities current_caps = NM_DEVICE_MODEM_CAPABILITY_NONE; - const gchar *type_desc = NULL; - const gchar *ip_iface = NULL; - - g_return_val_if_fail (modem != NULL, NULL); - g_return_val_if_fail (NM_IS_MODEM (modem), NULL); - g_return_val_if_fail (driver != NULL, NULL); - - if (NM_IS_MODEM_CDMA (modem)) { - caps = NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO; - current_caps = caps; - type_desc = "CDMA/EVDO"; - ip_iface = nm_modem_get_data_port (modem); - } else if (NM_IS_MODEM_GSM (modem)) { - caps = NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS; - current_caps = caps; - type_desc = "GSM/UMTS"; - ip_iface = nm_modem_get_data_port (modem); - } -#if WITH_MODEM_MANAGER_1 - else if (NM_IS_MODEM_BROADBAND (modem)) { - nm_modem_broadband_get_capabilities (NM_MODEM_BROADBAND (modem), &caps, ¤t_caps); - type_desc = "Broadband"; - /* data port not yet known in broadband modems */ - } -#endif - else { - nm_log_warn (LOGD_MB, "unhandled modem type %s", G_OBJECT_TYPE_NAME (modem)); - return NULL; - } - - return (NMDevice *) g_object_new (NM_TYPE_DEVICE_MODEM, - NM_DEVICE_UDI, nm_modem_get_path (modem), - NM_DEVICE_IFACE, nm_modem_get_uid (modem), - NM_DEVICE_IP_IFACE, ip_iface, - NM_DEVICE_DRIVER, driver, - NM_DEVICE_TYPE_DESC, type_desc, - NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_MODEM, - NM_DEVICE_RFKILL_TYPE, RFKILL_TYPE_WWAN, - NM_DEVICE_MODEM_MODEM, modem, - NM_DEVICE_MODEM_CAPABILITIES, caps, - NM_DEVICE_MODEM_CURRENT_CAPABILITIES, caps, - NULL); -} - -static void -nm_device_modem_init (NMDeviceModem *self) -{ -} - -static void -set_modem (NMDeviceModem *self, NMModem *modem) -{ - NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (self); - - g_return_if_fail (modem != NULL); - - priv->modem = g_object_ref (modem); - - g_signal_connect (modem, NM_MODEM_PPP_FAILED, G_CALLBACK (ppp_failed), self); - g_signal_connect (modem, NM_MODEM_PREPARE_RESULT, G_CALLBACK (modem_prepare_result), self); - g_signal_connect (modem, NM_MODEM_IP4_CONFIG_RESULT, G_CALLBACK (modem_ip4_config_result), self); - g_signal_connect (modem, NM_MODEM_AUTH_REQUESTED, G_CALLBACK (modem_auth_requested), self); - g_signal_connect (modem, NM_MODEM_AUTH_RESULT, G_CALLBACK (modem_auth_result), self); - g_signal_connect (modem, "notify::" NM_MODEM_ENABLED, G_CALLBACK (modem_enabled_cb), self); - g_signal_connect (modem, "notify::" NM_MODEM_CONNECTED, G_CALLBACK (modem_connected_cb), self); - - /* In the old ModemManager the data port is known from the very beginning; - * while in the new ModemManager the data port is set afterwards when the bearer gets - * created */ - g_signal_connect (modem, "notify::" NM_MODEM_DATA_PORT, G_CALLBACK (data_port_changed_cb), self); -} - -static void -set_property (GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec) -{ - NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (object); - - switch (prop_id) { - case PROP_MODEM: - /* construct-only */ - set_modem (NM_DEVICE_MODEM (object), g_value_get_object (value)); - break; - case PROP_CAPABILITIES: - priv->caps = g_value_get_uint (value); - break; - case PROP_CURRENT_CAPABILITIES: - priv->current_caps = g_value_get_uint (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) -{ - NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (object); - - switch (prop_id) { - case PROP_MODEM: - g_value_set_object (value, priv->modem); - break; - case PROP_CAPABILITIES: - g_value_set_uint (value, priv->caps); - break; - case PROP_CURRENT_CAPABILITIES: - g_value_set_uint (value, priv->current_caps); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -finalize (GObject *object) -{ - NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (object); - - g_object_unref (priv->modem); - priv->modem = NULL; - - G_OBJECT_CLASS (nm_device_modem_parent_class)->finalize (object); -} - -static void -nm_device_modem_class_init (NMDeviceModemClass *mclass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (mclass); - NMDeviceClass *device_class = NM_DEVICE_CLASS (mclass); - - g_type_class_add_private (object_class, sizeof (NMDeviceModemPrivate)); - - /* Virtual methods */ - object_class->finalize = finalize; - object_class->get_property = get_property; - object_class->set_property = set_property; - - device_class->get_generic_capabilities = get_generic_capabilities; - device_class->get_best_auto_connection = get_best_auto_connection; - device_class->check_connection_compatible = check_connection_compatible; - device_class->complete_connection = complete_connection; - device_class->deactivate = deactivate; - device_class->act_stage1_prepare = act_stage1_prepare; - device_class->act_stage2_config = act_stage2_config; - device_class->act_stage3_ip4_config_start = act_stage3_ip4_config_start; - device_class->act_stage3_ip6_config_start = act_stage3_ip6_config_start; - device_class->ip4_config_pre_commit = ip4_config_pre_commit; - device_class->get_enabled = get_enabled; - device_class->set_enabled = set_enabled; - - device_class->state_changed = device_state_changed; - - /* Properties */ - g_object_class_install_property - (object_class, PROP_MODEM, - g_param_spec_object (NM_DEVICE_MODEM_MODEM, - "Modem", - "Modem", - NM_TYPE_MODEM, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | NM_PROPERTY_PARAM_NO_EXPORT)); - - g_object_class_install_property (object_class, PROP_CAPABILITIES, - g_param_spec_uint (NM_DEVICE_MODEM_CAPABILITIES, - "Modem Capabilities", - "Modem Capabilities", - 0, G_MAXUINT32, NM_DEVICE_MODEM_CAPABILITY_NONE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - g_object_class_install_property (object_class, PROP_CURRENT_CAPABILITIES, - g_param_spec_uint (NM_DEVICE_MODEM_CURRENT_CAPABILITIES, - "Current modem Capabilities", - "Current modem Capabilities", - 0, G_MAXUINT32, NM_DEVICE_MODEM_CAPABILITY_NONE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - /* Signals */ - signals[PROPERTIES_CHANGED] = - nm_properties_changed_signal_new (object_class, - G_STRUCT_OFFSET (NMDeviceModemClass, properties_changed)); - - signals[ENABLE_CHANGED] = - g_signal_new (NM_DEVICE_MODEM_ENABLE_CHANGED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - 0, NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (mclass), - &dbus_glib_nm_device_modem_object_info); -} diff --git a/src/nm-device-modem.h b/src/nm-device-modem.h deleted file mode 100644 index 85c626a3..00000000 --- a/src/nm-device-modem.h +++ /dev/null @@ -1,60 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2011 Red Hat, Inc. - */ - -#ifndef NM_DEVICE_MODEM_H -#define NM_DEVICE_MODEM_H - -#include -#include - -#include "nm-device.h" -#include "nm-modem.h" - -#define NM_TYPE_DEVICE_MODEM (nm_device_modem_get_type ()) -#define NM_DEVICE_MODEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_MODEM, NMDeviceModem)) -#define NM_DEVICE_MODEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_MODEM, NMDeviceModemClass)) -#define NM_IS_DEVICE_MODEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_MODEM)) -#define NM_IS_DEVICE_MODEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_MODEM)) -#define NM_DEVICE_MODEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_MODEM, NMDeviceModemClass)) - -#define NM_DEVICE_MODEM_MODEM "modem" -#define NM_DEVICE_MODEM_CAPABILITIES "modem-capabilities" -#define NM_DEVICE_MODEM_CURRENT_CAPABILITIES "current-capabilities" - -#define NM_DEVICE_MODEM_ENABLE_CHANGED "enable-changed" - -typedef struct { - NMDevice parent; -} NMDeviceModem; - -typedef struct { - NMDeviceClass parent; - - void (*properties_changed) (NMDeviceModem *self, GHashTable *properties); -} NMDeviceModemClass; - -GType nm_device_modem_get_type (void); - -NMDevice *nm_device_modem_new (NMModem *modem, const char *driver); - -/* Private for subclases */ -NMModem *nm_device_modem_get_modem (NMDeviceModem *self); - -#endif /* NM_DEVICE_MODEM_H */ diff --git a/src/nm-device-olpc-mesh.c b/src/nm-device-olpc-mesh.c deleted file mode 100644 index 1417736f..00000000 --- a/src/nm-device-olpc-mesh.c +++ /dev/null @@ -1,773 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * Dan Williams - * Sjoerd Simons - * Daniel Drake - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * (C) Copyright 2005 - 2011 Red Hat, Inc. - * (C) Copyright 2008 Collabora Ltd. - * (C) Copyright 2009 One Laptop per Child - */ - -#include "config.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "nm-device.h" -#include "nm-device-wifi.h" -#include "nm-device-olpc-mesh.h" -#include "nm-device-private.h" -#include "nm-utils.h" -#include "nm-logging.h" -#include "NetworkManagerUtils.h" -#include "nm-activation-request.h" -#include "nm-properties-changed-signal.h" -#include "nm-setting-connection.h" -#include "nm-setting-olpc-mesh.h" -#include "nm-system.h" -#include "nm-manager.h" -#include "nm-enum-types.h" -#include "wifi-utils.h" -#if HAVE_WEXT -#include "wifi-utils-wext.h" -#endif - -/* This is a bug; but we can't really change API now... */ -#include "NetworkManagerVPN.h" - - -#include "nm-device-olpc-mesh-glue.h" - -G_DEFINE_TYPE (NMDeviceOlpcMesh, nm_device_olpc_mesh, NM_TYPE_DEVICE) - -#define NM_DEVICE_OLPC_MESH_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_OLPC_MESH, NMDeviceOlpcMeshPrivate)) - - -enum { - PROP_0, - PROP_HW_ADDRESS, - PROP_COMPANION, - PROP_ACTIVE_CHANNEL, - - LAST_PROP -}; - -enum { - PROPERTIES_CHANGED, - - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -#define NM_OLPC_MESH_ERROR (nm_olpc_mesh_error_quark ()) - - -struct _NMDeviceOlpcMeshPrivate -{ - gboolean dispose_has_run; - - guint8 hw_addr[ETH_ALEN]; - - GByteArray * ssid; - - WifiData * wifi_data; - - gboolean up; - - NMDevice * companion; - gboolean stage1_waiting; - guint device_added_id; - guint device_removed_id; - guint cmp_state_changed_id; - guint cmp_scanning_id; - guint cmp_scanning_allowed_id; - guint cmp_autoconnect_allowed_id; -}; - -static void state_changed (NMDevice *device, NMDeviceState new_state, - NMDeviceState old_state, NMDeviceStateReason reason); - -static GQuark -nm_olpc_mesh_error_quark (void) -{ - static GQuark quark = 0; - if (!quark) - quark = g_quark_from_static_string ("nm-mesh-error"); - return quark; -} - -static guint32 -get_generic_capabilities (NMDevice *dev) -{ - return NM_DEVICE_CAP_NM_SUPPORTED; -} - -static void -nm_device_olpc_mesh_init (NMDeviceOlpcMesh * self) -{ - NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); - - priv->dispose_has_run = FALSE; - priv->companion = NULL; - priv->stage1_waiting = FALSE; - - memset (&priv->hw_addr, 0, sizeof (priv->hw_addr)); -} - -static GObject* -constructor (GType type, - guint n_construct_params, - GObjectConstructParam *construct_params) -{ - GObject *object; - GObjectClass *klass; - NMDeviceOlpcMesh *self; - NMDeviceOlpcMeshPrivate *priv; - - klass = G_OBJECT_CLASS (nm_device_olpc_mesh_parent_class); - object = klass->constructor (type, n_construct_params, construct_params); - if (!object) - return NULL; - - self = NM_DEVICE_OLPC_MESH (object); - priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); - - nm_log_dbg (LOGD_HW | LOGD_OLPC_MESH, "(%s): kernel ifindex %d", - nm_device_get_iface (NM_DEVICE (self)), - nm_device_get_ifindex (NM_DEVICE (self))); - - /* - * The kernel driver now uses nl80211, but we force use of WEXT because - * the cfg80211 interactions are not quite ready to support access to - * mesh control through nl80211 just yet. - */ -#if HAVE_WEXT - priv->wifi_data = wifi_wext_init (nm_device_get_iface (NM_DEVICE (self)), - nm_device_get_ifindex (NM_DEVICE (self)), - FALSE); -#endif - if (priv->wifi_data == NULL) { - nm_log_warn (LOGD_HW | LOGD_OLPC_MESH, "(%s): failed to initialize WiFi driver", - nm_device_get_iface (NM_DEVICE (self))); - g_object_unref (object); - return NULL; - } - - /* shorter timeout for mesh connectivity */ - nm_device_set_dhcp_timeout (NM_DEVICE (self), 20); - return object; -} - -static gboolean -is_up (NMDevice *device) -{ - NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (device); - NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); - - return priv->up; -} - -static gboolean -bring_up (NMDevice *dev) -{ - NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (dev); - NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); - - priv->up = TRUE; - return TRUE; -} - -static void -device_cleanup (NMDeviceOlpcMesh *self) -{ - NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); - - if (priv->ssid) { - g_byte_array_free (priv->ssid, TRUE); - priv->ssid = NULL; - } - priv->up = FALSE; -} - -static void -take_down (NMDevice *dev) -{ - device_cleanup (NM_DEVICE_OLPC_MESH (dev)); -} - -static gboolean -check_connection_compatible (NMDevice *device, - NMConnection *connection, - GError **error) -{ - NMSettingConnection *s_con; - NMSettingOlpcMesh *s_mesh; - - s_con = nm_connection_get_setting_connection (connection); - g_assert (s_con); - - if (strcmp (nm_setting_connection_get_connection_type (s_con), NM_SETTING_OLPC_MESH_SETTING_NAME)) { - g_set_error (error, - NM_OLPC_MESH_ERROR, NM_OLPC_MESH_ERROR_CONNECTION_NOT_MESH, - "The connection was not a Mesh connection."); - return FALSE; - } - - s_mesh = nm_connection_get_setting_olpc_mesh (connection); - if (!s_mesh) { - g_set_error (error, - NM_OLPC_MESH_ERROR, NM_OLPC_MESH_ERROR_CONNECTION_INVALID, - "The connection was not a valid Mesh connection."); - return FALSE; - } - - return TRUE; -} - -#define DEFAULT_SSID "olpc-mesh" - -static gboolean -complete_connection (NMDevice *device, - NMConnection *connection, - const char *specific_object, - const GSList *existing_connections, - GError **error) -{ - NMSettingOlpcMesh *s_mesh; - GByteArray *tmp; - - s_mesh = nm_connection_get_setting_olpc_mesh (connection); - if (!s_mesh) { - s_mesh = (NMSettingOlpcMesh *) nm_setting_olpc_mesh_new (); - nm_connection_add_setting (connection, NM_SETTING (s_mesh)); - } - - if (!nm_setting_olpc_mesh_get_ssid (s_mesh)) { - tmp = g_byte_array_sized_new (strlen (DEFAULT_SSID)); - g_byte_array_append (tmp, (const guint8 *) DEFAULT_SSID, strlen (DEFAULT_SSID)); - g_object_set (G_OBJECT (s_mesh), NM_SETTING_OLPC_MESH_SSID, tmp, NULL); - g_byte_array_free (tmp, TRUE); - } - - if (!nm_setting_olpc_mesh_get_dhcp_anycast_address (s_mesh)) { - const guint8 anycast[ETH_ALEN] = { 0xC0, 0x27, 0xC0, 0x27, 0xC0, 0x27 }; - - tmp = g_byte_array_sized_new (ETH_ALEN); - g_byte_array_append (tmp, anycast, sizeof (anycast)); - g_object_set (G_OBJECT (s_mesh), NM_SETTING_OLPC_MESH_DHCP_ANYCAST_ADDRESS, tmp, NULL); - g_byte_array_free (tmp, TRUE); - - } - - nm_utils_complete_generic (connection, - NM_SETTING_OLPC_MESH_SETTING_NAME, - existing_connections, - _("Mesh %d"), - NULL, - FALSE); /* No IPv6 by default */ - - return TRUE; -} - -/****************************************************************************/ - -static void -update_hw_address (NMDevice *dev) -{ - NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (dev); - NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); - gsize addrlen; - gboolean changed = FALSE; - - addrlen = nm_device_read_hwaddr (dev, priv->hw_addr, sizeof (priv->hw_addr), &changed); - if (addrlen) { - g_return_if_fail (addrlen == ETH_ALEN); - if (changed) - g_object_notify (G_OBJECT (dev), NM_DEVICE_OLPC_MESH_HW_ADDRESS); - } -} - -static const guint8 * -get_hw_address (NMDevice *device, guint *out_len) -{ - NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (device); - - *out_len = sizeof (priv->hw_addr); - return priv->hw_addr; -} - -static NMActStageReturn -act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason) -{ - NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (dev); - gboolean scanning; - - /* disconnect companion device, if it is connected */ - if (nm_device_get_act_request (NM_DEVICE (priv->companion))) { - nm_log_info (LOGD_OLPC_MESH, "(%s): disconnecting companion device %s", - nm_device_get_iface (dev), - nm_device_get_iface (priv->companion)); - /* FIXME: VPN stuff here is a bug; but we can't really change API now... */ - nm_device_state_changed (NM_DEVICE (priv->companion), - NM_DEVICE_STATE_DISCONNECTED, - NM_VPN_CONNECTION_STATE_REASON_USER_DISCONNECTED); - nm_log_info (LOGD_OLPC_MESH, "(%s): companion %s disconnected", - nm_device_get_iface (dev), - nm_device_get_iface (priv->companion)); - } - - - /* wait with continuing configuration untill the companion device is done scanning */ - g_object_get (priv->companion, "scanning", &scanning, NULL); - if (scanning) { - priv->stage1_waiting = TRUE; - return NM_ACT_STAGE_RETURN_POSTPONE; - } - - return NM_ACT_STAGE_RETURN_SUCCESS; -} - -static void -_mesh_set_channel (NMDeviceOlpcMesh *self, guint32 channel) -{ - NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); - - if (wifi_utils_get_mesh_channel (priv->wifi_data) != channel) { - if (wifi_utils_set_mesh_channel (priv->wifi_data, channel)) - g_object_notify (G_OBJECT (self), NM_DEVICE_OLPC_MESH_ACTIVE_CHANNEL); - } -} - -static NMActStageReturn -act_stage2_config (NMDevice *dev, NMDeviceStateReason *reason) -{ - NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (dev); - NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); - NMConnection *connection; - NMSettingOlpcMesh *s_mesh; - guint32 channel; - const GByteArray *anycast_addr_array; - guint8 *anycast_addr = NULL; - - connection = nm_device_get_connection (dev); - g_assert (connection); - - s_mesh = nm_connection_get_setting_olpc_mesh (connection); - g_assert (s_mesh); - - channel = nm_setting_olpc_mesh_get_channel (s_mesh); - if (channel != 0) - _mesh_set_channel (self, channel); - wifi_utils_set_mesh_ssid (priv->wifi_data, nm_setting_olpc_mesh_get_ssid (s_mesh)); - - anycast_addr_array = nm_setting_olpc_mesh_get_dhcp_anycast_address (s_mesh); - if (anycast_addr_array) - anycast_addr = anycast_addr_array->data; - - nm_device_set_dhcp_anycast_address (dev, anycast_addr); - return NM_ACT_STAGE_RETURN_SUCCESS; -} - -static void -companion_cleanup (NMDeviceOlpcMesh *self) -{ - NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); - - if (priv->companion == NULL) - return; - - if (priv->cmp_state_changed_id) { - g_signal_handler_disconnect (priv->companion, priv->cmp_state_changed_id); - priv->cmp_state_changed_id = 0; - } - - if (priv->cmp_scanning_id) { - g_signal_handler_disconnect (priv->companion, priv->cmp_scanning_id); - priv->cmp_scanning_id = 0; - } - - if (priv->cmp_scanning_allowed_id) { - g_signal_handler_disconnect (priv->companion, priv->cmp_scanning_allowed_id); - priv->cmp_scanning_allowed_id = 0; - } - - if (priv->cmp_autoconnect_allowed_id) { - g_signal_handler_disconnect (priv->companion, priv->cmp_autoconnect_allowed_id); - priv->cmp_autoconnect_allowed_id = 0; - } - - priv->companion = NULL; - g_object_notify (G_OBJECT (self), NM_DEVICE_OLPC_MESH_COMPANION); -} - -static void -dispose (GObject *object) -{ - NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (object); - NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); - NMManager *manager; - - if (priv->dispose_has_run) { - G_OBJECT_CLASS (nm_device_olpc_mesh_parent_class)->dispose (object); - return; - } - priv->dispose_has_run = TRUE; - - if (priv->wifi_data) - wifi_utils_deinit (priv->wifi_data); - - device_cleanup (self); - companion_cleanup (self); - - manager = nm_manager_get (); - if (priv->device_added_id) - g_signal_handler_disconnect (manager, priv->device_added_id); - if (priv->device_removed_id) - g_signal_handler_disconnect (manager, priv->device_removed_id); - g_object_unref (manager); - - G_OBJECT_CLASS (nm_device_olpc_mesh_parent_class)->dispose (object); -} - -static void -get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) -{ - NMDeviceOlpcMesh *device = NM_DEVICE_OLPC_MESH (object); - NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (device); - - switch (prop_id) { - case PROP_HW_ADDRESS: - g_value_take_string (value, nm_utils_hwaddr_ntoa (priv->hw_addr, ARPHRD_ETHER)); - break; - case PROP_COMPANION: - if (priv->companion) - g_value_set_boxed (value, nm_device_get_path (priv->companion)); - else - g_value_set_boxed (value, "/"); - break; - case PROP_ACTIVE_CHANNEL: - g_value_set_uint (value, wifi_utils_get_mesh_channel (priv->wifi_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) -{ - switch (prop_id) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -nm_device_olpc_mesh_class_init (NMDeviceOlpcMeshClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass); - - g_type_class_add_private (object_class, sizeof (NMDeviceOlpcMeshPrivate)); - - object_class->constructor = constructor; - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->dispose = dispose; - - parent_class->get_type_capabilities = NULL; - parent_class->get_generic_capabilities = get_generic_capabilities; - parent_class->is_up = is_up; - parent_class->bring_up = bring_up; - parent_class->take_down = take_down; - parent_class->update_hw_address = update_hw_address; - parent_class->get_hw_address = get_hw_address; - parent_class->check_connection_compatible = check_connection_compatible; - parent_class->complete_connection = complete_connection; - - parent_class->act_stage1_prepare = act_stage1_prepare; - parent_class->act_stage2_config = act_stage2_config; - - parent_class->state_changed = state_changed; - - /* Properties */ - g_object_class_install_property - (object_class, PROP_HW_ADDRESS, - g_param_spec_string (NM_DEVICE_OLPC_MESH_HW_ADDRESS, - "MAC Address", - "Hardware MAC address", - NULL, - G_PARAM_READABLE)); - - g_object_class_install_property - (object_class, PROP_COMPANION, - g_param_spec_boxed (NM_DEVICE_OLPC_MESH_COMPANION, - "Companion device", - "Companion device object path", - DBUS_TYPE_G_OBJECT_PATH, - G_PARAM_READABLE)); - - g_object_class_install_property - (object_class, PROP_ACTIVE_CHANNEL, - g_param_spec_uint (NM_DEVICE_OLPC_MESH_ACTIVE_CHANNEL, - "Active channel", - "Active channel", - 0, G_MAXUINT32, 0, - G_PARAM_READABLE)); - - signals[PROPERTIES_CHANGED] = - nm_properties_changed_signal_new (object_class, - G_STRUCT_OFFSET (NMDeviceOlpcMeshClass, properties_changed)); - - dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass), &dbus_glib_nm_device_olpc_mesh_object_info); - - dbus_g_error_domain_register (NM_OLPC_MESH_ERROR, NULL, - NM_TYPE_OLPC_MESH_ERROR); -} - -static void -companion_notify_cb (NMDeviceWifi *companion, GParamSpec *pspec, gpointer user_data) -{ - NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (user_data); - NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); - gboolean scanning; - - if (!priv->stage1_waiting) - return; - - g_object_get (companion, "scanning", &scanning, NULL); - - if (!scanning) { - priv->stage1_waiting = FALSE; - nm_device_activate_schedule_stage2_device_config (NM_DEVICE (self)); - } -} - -/* disconnect from mesh if someone starts using the companion */ -static void -companion_state_changed_cb (NMDeviceWifi *companion, - NMDeviceState state, - NMDeviceState old_state, - NMDeviceStateReason reason, - gpointer user_data) -{ - NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (user_data); - NMDeviceState self_state = nm_device_get_state (NM_DEVICE (self)); - - if ( self_state < NM_DEVICE_STATE_PREPARE - || self_state > NM_DEVICE_STATE_ACTIVATED - || state < NM_DEVICE_STATE_PREPARE - || state > NM_DEVICE_STATE_ACTIVATED) - return; - - nm_log_dbg (LOGD_OLPC_MESH, "(%s): disconnecting mesh due to companion connectivity", - nm_device_get_iface (NM_DEVICE (self))); - /* FIXME: VPN stuff here is a bug; but we can't really change API now... */ - nm_device_state_changed (NM_DEVICE (self), - NM_DEVICE_STATE_DISCONNECTED, - NM_VPN_CONNECTION_STATE_REASON_USER_DISCONNECTED); -} - -static gboolean -companion_scan_allowed_cb (NMDeviceWifi *companion, gpointer user_data) -{ - NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (user_data); - NMDeviceState state = nm_device_get_state (NM_DEVICE (self)); - - /* Don't allow the companion to scan while configuring the mesh interface */ - return (state < NM_DEVICE_STATE_PREPARE) || (state > NM_DEVICE_STATE_IP_CONFIG); -} - -static gboolean -companion_autoconnect_allowed_cb (NMDeviceWifi *companion, gpointer user_data) -{ - NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (user_data); - NMDeviceState state = nm_device_get_state (NM_DEVICE (self)); - - /* Don't allow the companion to autoconnect while a mesh connection is - * active */ - return (state < NM_DEVICE_STATE_PREPARE) || (state > NM_DEVICE_STATE_ACTIVATED); -} - -static gboolean -is_companion (NMDeviceOlpcMesh *self, NMDevice *other) -{ - NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); - const guint8 *their_addr; - guint their_addr_len = 0; - NMManager *manager; - - if (!NM_IS_DEVICE_WIFI (other)) - return FALSE; - - their_addr = nm_device_get_hw_address (other, &their_addr_len); - if ( (their_addr_len != ETH_ALEN) - || (memcmp (priv->hw_addr, their_addr, ETH_ALEN) != 0)) - return FALSE; - - priv->companion = other; - - /* When we've found the companion, stop listening for other devices */ - manager = nm_manager_get (); - if (priv->device_added_id) { - g_signal_handler_disconnect (manager, priv->device_added_id); - priv->device_added_id = 0; - } - g_object_unref (manager); - - nm_device_state_changed (NM_DEVICE (self), - NM_DEVICE_STATE_DISCONNECTED, - NM_DEVICE_STATE_REASON_NONE); - - nm_log_info (LOGD_OLPC_MESH, "(%s): found companion WiFi device %s", - nm_device_get_iface (NM_DEVICE (self)), - nm_device_get_iface (other)); - - priv->cmp_state_changed_id = g_signal_connect (G_OBJECT (other), "state-changed", - G_CALLBACK (companion_state_changed_cb), self); - - priv->cmp_scanning_id = g_signal_connect (G_OBJECT (other), "notify::scanning", - G_CALLBACK (companion_notify_cb), self); - - priv->cmp_scanning_allowed_id = g_signal_connect (G_OBJECT (other), "scanning-allowed", - G_CALLBACK (companion_scan_allowed_cb), self); - - priv->cmp_autoconnect_allowed_id = g_signal_connect (G_OBJECT (other), "autoconnect-allowed", - G_CALLBACK (companion_autoconnect_allowed_cb), self); - - g_object_notify (G_OBJECT (self), NM_DEVICE_OLPC_MESH_COMPANION); - - return TRUE; -} - -static void -device_added_cb (NMManager *manager, NMDevice *other, gpointer user_data) -{ - NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (user_data); - - is_companion (self, other); -} - -static void -device_removed_cb (NMManager *manager, NMDevice *other, gpointer user_data) -{ - NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (user_data); - - if (other == NM_DEVICE_OLPC_MESH_GET_PRIVATE (self)->companion) - companion_cleanup (self); -} - -static gboolean -check_companion_cb (gpointer user_data) -{ - NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (user_data); - NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); - NMManager *manager; - GSList *list; - - if (priv->companion != NULL) { - nm_device_state_changed (NM_DEVICE (user_data), - NM_DEVICE_STATE_DISCONNECTED, - NM_DEVICE_STATE_REASON_NONE); - return FALSE; - } - - if (priv->device_added_id != 0) - return FALSE; - - manager = nm_manager_get (); - - priv->device_added_id = g_signal_connect (manager, "device-added", - G_CALLBACK (device_added_cb), self); - if (!priv->device_removed_id) { - priv->device_removed_id = g_signal_connect (manager, "device-removed", - G_CALLBACK (device_removed_cb), self); - } - - /* Try to find the companion if it's already known to the NMManager */ - for (list = nm_manager_get_devices (manager); list ; list = g_slist_next (list)) { - if (is_companion (self, NM_DEVICE (list->data))) - break; - } - - g_object_unref (manager); - - return FALSE; -} - -static void -state_changed (NMDevice *device, NMDeviceState new_state, - NMDeviceState old_state, NMDeviceStateReason reason) -{ - NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (device); - - switch (new_state) { - case NM_DEVICE_STATE_UNMANAGED: - break; - case NM_DEVICE_STATE_UNAVAILABLE: - /* If transitioning to UNAVAILABLE and the companion device is known then - * transition to DISCONNECTED otherwise wait for our companion. - */ - g_idle_add (check_companion_cb, self); - break; - case NM_DEVICE_STATE_ACTIVATED: - break; - case NM_DEVICE_STATE_FAILED: - break; - case NM_DEVICE_STATE_DISCONNECTED: - break; - default: - break; - } -} - - -NMDevice * -nm_device_olpc_mesh_new (const char *udi, - const char *iface, - const char *driver) -{ - g_return_val_if_fail (udi != NULL, NULL); - g_return_val_if_fail (iface != NULL, NULL); - g_return_val_if_fail (driver != NULL, NULL); - - return (NMDevice *) g_object_new (NM_TYPE_DEVICE_OLPC_MESH, - NM_DEVICE_UDI, udi, - NM_DEVICE_IFACE, iface, - NM_DEVICE_DRIVER, driver, - NM_DEVICE_TYPE_DESC, "802.11 OLPC Mesh", - NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_OLPC_MESH, - NULL); -} diff --git a/src/nm-device-olpc-mesh.h b/src/nm-device-olpc-mesh.h deleted file mode 100644 index 9d42ecfa..00000000 --- a/src/nm-device-olpc-mesh.h +++ /dev/null @@ -1,88 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ - -/* NetworkManager -- Network link manager - * - * Dan Williams - * Sjoerd Simons - * Daniel Drake - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * (C) Copyright 2005 Red Hat, Inc. - * (C) Copyright 2008 Collabora Ltd. - * (C) Copyright 2009 One Laptop per Child - */ - -#ifndef NM_DEVICE_OLPC_MESH_H -#define NM_DEVICE_OLPC_MESH_H - -#include -#include - -#include "nm-device.h" - -G_BEGIN_DECLS - -#define NM_TYPE_DEVICE_OLPC_MESH (nm_device_olpc_mesh_get_type ()) -#define NM_DEVICE_OLPC_MESH(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_OLPC_MESH, NMDeviceOlpcMesh)) -#define NM_DEVICE_OLPC_MESH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_OLPC_MESH, NMDeviceOlpcMeshClass)) -#define NM_IS_DEVICE_OLPC_MESH(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_OLPC_MESH)) -#define NM_IS_DEVICE_OLPC_MESH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_OLPC_MESH)) -#define NM_DEVICE_OLPC_MESH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_OLPC_MESH, NMDeviceOlpcMeshClass)) - -typedef enum -{ - NM_OLPC_MESH_ERROR_CONNECTION_NOT_MESH = 0, /*< nick=ConnectionNotMesh >*/ - NM_OLPC_MESH_ERROR_CONNECTION_INVALID, /*< nick=ConnectionInvalid >*/ - NM_OLPC_MESH_ERROR_CONNECTION_INCOMPATIBLE, /*< nick=ConnectionIncompatible >*/ -} NMOlpcMeshError; - -#define NM_DEVICE_OLPC_MESH_HW_ADDRESS "hw-address" -#define NM_DEVICE_OLPC_MESH_COMPANION "companion" -#define NM_DEVICE_OLPC_MESH_BITRATE "bitrate" -#define NM_DEVICE_OLPC_MESH_ACTIVE_CHANNEL "active-channel" - -#ifndef NM_DEVICE_OLPC_MESH_DEFINED -#define NM_DEVICE_OLPC_MESH_DEFINED -typedef struct _NMDeviceOlpcMesh NMDeviceOlpcMesh; -#endif - -typedef struct _NMDeviceOlpcMeshClass NMDeviceOlpcMeshClass; -typedef struct _NMDeviceOlpcMeshPrivate NMDeviceOlpcMeshPrivate; - -struct _NMDeviceOlpcMesh -{ - NMDevice parent; -}; - -struct _NMDeviceOlpcMeshClass -{ - NMDeviceClass parent; - - /* Signals */ - void (*properties_changed) (NMDeviceOlpcMesh *device, - GHashTable *properties); -}; - - -GType nm_device_olpc_mesh_get_type (void); - -NMDevice *nm_device_olpc_mesh_new (const char *udi, - const char *iface, - const char *driver); - -G_END_DECLS - -#endif /* NM_DEVICE_OLPC_MESH_H */ diff --git a/src/nm-device-private.h b/src/nm-device-private.h deleted file mode 100644 index 8edae660..00000000 --- a/src/nm-device-private.h +++ /dev/null @@ -1,92 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2007 - 2008 Novell, Inc. - * Copyright (C) 2007 - 2011 Red Hat, Inc. - */ - -#ifndef NM_DEVICE_PRIVATE_H -#define NM_DEVICE_PRIVATE_H - -#include "nm-device.h" - -/* This file should only be used by subclasses of NMDevice */ - -enum NMActStageReturn { - NM_ACT_STAGE_RETURN_FAILURE = 0, - NM_ACT_STAGE_RETURN_SUCCESS, /* Activation stage done */ - NM_ACT_STAGE_RETURN_POSTPONE, /* Long-running operation in progress */ - NM_ACT_STAGE_RETURN_WAIT, /* Not ready to start stage; wait */ - NM_ACT_STAGE_RETURN_STOP /* Activation stage done; nothing to do */ -}; - -void nm_device_set_ip_iface (NMDevice *self, const char *iface); - -void nm_device_activate_schedule_stage3_ip_config_start (NMDevice *device); - -gboolean nm_device_activate_stage3_ip4_start (NMDevice *self); - -gboolean nm_device_activate_stage3_ip6_start (NMDevice *self); - -gboolean nm_device_hw_bring_up (NMDevice *self, gboolean wait, gboolean *no_firmware); - -void nm_device_hw_take_down (NMDevice *self, gboolean block); - -gsize nm_device_read_hwaddr (NMDevice *dev, guint8 *out_buf, gsize buf_len, gboolean *out_changed); - -gboolean nm_device_ip_config_should_fail (NMDevice *self, gboolean ip6); - -void nm_device_set_firmware_missing (NMDevice *self, gboolean missing); - -guint32 nm_device_get_capabilities (NMDevice *dev); -guint32 nm_device_get_type_capabilities (NMDevice *dev); - -void nm_device_activate_schedule_stage1_device_prepare (NMDevice *device); -void nm_device_activate_schedule_stage2_device_config (NMDevice *device); - -void nm_device_activate_schedule_ip4_config_result(NMDevice *device, NMIP4Config *config); -void nm_device_activate_schedule_ip4_config_timeout (NMDevice *device); - -void nm_device_activate_schedule_ip6_config_result (NMDevice *device, NMIP6Config *config); -void nm_device_activate_schedule_ip6_config_timeout (NMDevice *device); - -gboolean nm_device_activate_ip4_state_in_conf (NMDevice *device); -gboolean nm_device_activate_ip4_state_in_wait (NMDevice *device); - -gboolean nm_device_activate_ip6_state_in_conf (NMDevice *device); -gboolean nm_device_activate_ip6_state_in_wait (NMDevice *device); - -void nm_device_set_dhcp_timeout (NMDevice *device, guint32 timeout); -void nm_device_set_dhcp_anycast_address (NMDevice *device, guint8 *addr); - -gboolean nm_device_dhcp4_renew (NMDevice *device, gboolean release); - -gboolean nm_device_match_ip_config (NMDevice *device, NMConnection *connection); - -NMConnectionProvider *nm_device_get_connection_provider (NMDevice *device); - -void nm_device_recheck_available_connections (NMDevice *device); - -void nm_device_queued_state_clear (NMDevice *device); - -NMDeviceState nm_device_queued_state_peek (NMDevice *device); - -gboolean nm_device_get_enslaved (NMDevice *device); - -NMDevice *nm_device_master_get_slave_by_ifindex (NMDevice *dev, int ifindex); - -#endif /* NM_DEVICE_PRIVATE_H */ diff --git a/src/nm-device-team-glue.h b/src/nm-device-team-glue.h new file mode 100644 index 00000000..405975c8 --- /dev/null +++ b/src/nm-device-team-glue.h @@ -0,0 +1,73 @@ +/* Generated by dbus-binding-tool; do not edit! */ + + +#ifndef __dbus_glib_marshal_nm_device_team_MARSHAL_H__ +#define __dbus_glib_marshal_nm_device_team_MARSHAL_H__ + +#include + +G_BEGIN_DECLS + +#ifdef G_ENABLE_DEBUG +#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v) +#define g_marshal_value_peek_char(v) g_value_get_schar (v) +#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v) +#define g_marshal_value_peek_int(v) g_value_get_int (v) +#define g_marshal_value_peek_uint(v) g_value_get_uint (v) +#define g_marshal_value_peek_long(v) g_value_get_long (v) +#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v) +#define g_marshal_value_peek_int64(v) g_value_get_int64 (v) +#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v) +#define g_marshal_value_peek_enum(v) g_value_get_enum (v) +#define g_marshal_value_peek_flags(v) g_value_get_flags (v) +#define g_marshal_value_peek_float(v) g_value_get_float (v) +#define g_marshal_value_peek_double(v) g_value_get_double (v) +#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v) +#define g_marshal_value_peek_param(v) g_value_get_param (v) +#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v) +#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v) +#define g_marshal_value_peek_object(v) g_value_get_object (v) +#define g_marshal_value_peek_variant(v) g_value_get_variant (v) +#else /* !G_ENABLE_DEBUG */ +/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API. + * Do not access GValues directly in your code. Instead, use the + * g_value_get_*() functions + */ +#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int +#define g_marshal_value_peek_char(v) (v)->data[0].v_int +#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint +#define g_marshal_value_peek_int(v) (v)->data[0].v_int +#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint +#define g_marshal_value_peek_long(v) (v)->data[0].v_long +#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 +#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 +#define g_marshal_value_peek_enum(v) (v)->data[0].v_long +#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_float(v) (v)->data[0].v_float +#define g_marshal_value_peek_double(v) (v)->data[0].v_double +#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer +#endif /* !G_ENABLE_DEBUG */ + + +G_END_DECLS + +#endif /* __dbus_glib_marshal_nm_device_team_MARSHAL_H__ */ + +#include +static const DBusGMethodInfo dbus_glib_nm_device_team_methods[] = { +}; + +const DBusGObjectInfo dbus_glib_nm_device_team_object_info = { 1, + dbus_glib_nm_device_team_methods, + 0, +"\0", +"org.freedesktop.NetworkManager.Device.Team\0PropertiesChanged\0\0", +"org.freedesktop.NetworkManager.Device.Team\0HwAddress\0hw_address\0read\0org.freedesktop.NetworkManager.Device.Team\0Carrier\0carrier\0read\0org.freedesktop.NetworkManager.Device.Team\0Slaves\0slaves\0read\0\0" +}; + diff --git a/src/nm-device-tun-glue.h b/src/nm-device-tun-glue.h new file mode 100644 index 00000000..96cea85b --- /dev/null +++ b/src/nm-device-tun-glue.h @@ -0,0 +1,73 @@ +/* Generated by dbus-binding-tool; do not edit! */ + + +#ifndef __dbus_glib_marshal_nm_device_tun_MARSHAL_H__ +#define __dbus_glib_marshal_nm_device_tun_MARSHAL_H__ + +#include + +G_BEGIN_DECLS + +#ifdef G_ENABLE_DEBUG +#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v) +#define g_marshal_value_peek_char(v) g_value_get_schar (v) +#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v) +#define g_marshal_value_peek_int(v) g_value_get_int (v) +#define g_marshal_value_peek_uint(v) g_value_get_uint (v) +#define g_marshal_value_peek_long(v) g_value_get_long (v) +#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v) +#define g_marshal_value_peek_int64(v) g_value_get_int64 (v) +#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v) +#define g_marshal_value_peek_enum(v) g_value_get_enum (v) +#define g_marshal_value_peek_flags(v) g_value_get_flags (v) +#define g_marshal_value_peek_float(v) g_value_get_float (v) +#define g_marshal_value_peek_double(v) g_value_get_double (v) +#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v) +#define g_marshal_value_peek_param(v) g_value_get_param (v) +#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v) +#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v) +#define g_marshal_value_peek_object(v) g_value_get_object (v) +#define g_marshal_value_peek_variant(v) g_value_get_variant (v) +#else /* !G_ENABLE_DEBUG */ +/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API. + * Do not access GValues directly in your code. Instead, use the + * g_value_get_*() functions + */ +#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int +#define g_marshal_value_peek_char(v) (v)->data[0].v_int +#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint +#define g_marshal_value_peek_int(v) (v)->data[0].v_int +#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint +#define g_marshal_value_peek_long(v) (v)->data[0].v_long +#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 +#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 +#define g_marshal_value_peek_enum(v) (v)->data[0].v_long +#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_float(v) (v)->data[0].v_float +#define g_marshal_value_peek_double(v) (v)->data[0].v_double +#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer +#endif /* !G_ENABLE_DEBUG */ + + +G_END_DECLS + +#endif /* __dbus_glib_marshal_nm_device_tun_MARSHAL_H__ */ + +#include +static const DBusGMethodInfo dbus_glib_nm_device_tun_methods[] = { +}; + +const DBusGObjectInfo dbus_glib_nm_device_tun_object_info = { 1, + dbus_glib_nm_device_tun_methods, + 0, +"\0", +"org.freedesktop.NetworkManager.Device.Tun\0PropertiesChanged\0\0", +"org.freedesktop.NetworkManager.Device.Tun\0Owner\0owner\0read\0org.freedesktop.NetworkManager.Device.Tun\0Group\0group\0read\0org.freedesktop.NetworkManager.Device.Tun\0Mode\0mode\0read\0org.freedesktop.NetworkManager.Device.Tun\0NoPi\0no_pi\0read\0org.freedesktop.NetworkManager.Device.Tun\0VnetHdr\0vnet_hdr\0read\0org.freedesktop.NetworkManager.Device.Tun\0MultiQueue\0multi_queue\0read\0\0" +}; + diff --git a/src/nm-device-veth-glue.h b/src/nm-device-veth-glue.h new file mode 100644 index 00000000..f411964e --- /dev/null +++ b/src/nm-device-veth-glue.h @@ -0,0 +1,73 @@ +/* Generated by dbus-binding-tool; do not edit! */ + + +#ifndef __dbus_glib_marshal_nm_device_veth_MARSHAL_H__ +#define __dbus_glib_marshal_nm_device_veth_MARSHAL_H__ + +#include + +G_BEGIN_DECLS + +#ifdef G_ENABLE_DEBUG +#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v) +#define g_marshal_value_peek_char(v) g_value_get_schar (v) +#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v) +#define g_marshal_value_peek_int(v) g_value_get_int (v) +#define g_marshal_value_peek_uint(v) g_value_get_uint (v) +#define g_marshal_value_peek_long(v) g_value_get_long (v) +#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v) +#define g_marshal_value_peek_int64(v) g_value_get_int64 (v) +#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v) +#define g_marshal_value_peek_enum(v) g_value_get_enum (v) +#define g_marshal_value_peek_flags(v) g_value_get_flags (v) +#define g_marshal_value_peek_float(v) g_value_get_float (v) +#define g_marshal_value_peek_double(v) g_value_get_double (v) +#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v) +#define g_marshal_value_peek_param(v) g_value_get_param (v) +#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v) +#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v) +#define g_marshal_value_peek_object(v) g_value_get_object (v) +#define g_marshal_value_peek_variant(v) g_value_get_variant (v) +#else /* !G_ENABLE_DEBUG */ +/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API. + * Do not access GValues directly in your code. Instead, use the + * g_value_get_*() functions + */ +#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int +#define g_marshal_value_peek_char(v) (v)->data[0].v_int +#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint +#define g_marshal_value_peek_int(v) (v)->data[0].v_int +#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint +#define g_marshal_value_peek_long(v) (v)->data[0].v_long +#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 +#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 +#define g_marshal_value_peek_enum(v) (v)->data[0].v_long +#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_float(v) (v)->data[0].v_float +#define g_marshal_value_peek_double(v) (v)->data[0].v_double +#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer +#endif /* !G_ENABLE_DEBUG */ + + +G_END_DECLS + +#endif /* __dbus_glib_marshal_nm_device_veth_MARSHAL_H__ */ + +#include +static const DBusGMethodInfo dbus_glib_nm_device_veth_methods[] = { +}; + +const DBusGObjectInfo dbus_glib_nm_device_veth_object_info = { 1, + dbus_glib_nm_device_veth_methods, + 0, +"\0", +"org.freedesktop.NetworkManager.Device.Veth\0PropertiesChanged\0\0", +"org.freedesktop.NetworkManager.Device.Veth\0Peer\0peer\0read\0\0" +}; + diff --git a/src/nm-device-vlan-glue.h b/src/nm-device-vlan-glue.h new file mode 100644 index 00000000..c9e51d54 --- /dev/null +++ b/src/nm-device-vlan-glue.h @@ -0,0 +1,73 @@ +/* Generated by dbus-binding-tool; do not edit! */ + + +#ifndef __dbus_glib_marshal_nm_device_vlan_MARSHAL_H__ +#define __dbus_glib_marshal_nm_device_vlan_MARSHAL_H__ + +#include + +G_BEGIN_DECLS + +#ifdef G_ENABLE_DEBUG +#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v) +#define g_marshal_value_peek_char(v) g_value_get_schar (v) +#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v) +#define g_marshal_value_peek_int(v) g_value_get_int (v) +#define g_marshal_value_peek_uint(v) g_value_get_uint (v) +#define g_marshal_value_peek_long(v) g_value_get_long (v) +#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v) +#define g_marshal_value_peek_int64(v) g_value_get_int64 (v) +#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v) +#define g_marshal_value_peek_enum(v) g_value_get_enum (v) +#define g_marshal_value_peek_flags(v) g_value_get_flags (v) +#define g_marshal_value_peek_float(v) g_value_get_float (v) +#define g_marshal_value_peek_double(v) g_value_get_double (v) +#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v) +#define g_marshal_value_peek_param(v) g_value_get_param (v) +#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v) +#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v) +#define g_marshal_value_peek_object(v) g_value_get_object (v) +#define g_marshal_value_peek_variant(v) g_value_get_variant (v) +#else /* !G_ENABLE_DEBUG */ +/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API. + * Do not access GValues directly in your code. Instead, use the + * g_value_get_*() functions + */ +#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int +#define g_marshal_value_peek_char(v) (v)->data[0].v_int +#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint +#define g_marshal_value_peek_int(v) (v)->data[0].v_int +#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint +#define g_marshal_value_peek_long(v) (v)->data[0].v_long +#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 +#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 +#define g_marshal_value_peek_enum(v) (v)->data[0].v_long +#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_float(v) (v)->data[0].v_float +#define g_marshal_value_peek_double(v) (v)->data[0].v_double +#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer +#endif /* !G_ENABLE_DEBUG */ + + +G_END_DECLS + +#endif /* __dbus_glib_marshal_nm_device_vlan_MARSHAL_H__ */ + +#include +static const DBusGMethodInfo dbus_glib_nm_device_vlan_methods[] = { +}; + +const DBusGObjectInfo dbus_glib_nm_device_vlan_object_info = { 1, + dbus_glib_nm_device_vlan_methods, + 0, +"\0", +"org.freedesktop.NetworkManager.Device.Vlan\0PropertiesChanged\0\0", +"org.freedesktop.NetworkManager.Device.Vlan\0HwAddress\0hw_address\0read\0org.freedesktop.NetworkManager.Device.Vlan\0Carrier\0carrier\0read\0org.freedesktop.NetworkManager.Device.Vlan\0VlanId\0vlan_id\0read\0\0" +}; + diff --git a/src/nm-device-vlan.c b/src/nm-device-vlan.c deleted file mode 100644 index d8e1f3c1..00000000 --- a/src/nm-device-vlan.c +++ /dev/null @@ -1,777 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2011 - 2012 Red Hat, Inc. - */ - -#include "config.h" - -#include -#include - -#include -#include -#include - -#include "nm-device-vlan.h" -#include "nm-logging.h" -#include "nm-properties-changed-signal.h" -#include "nm-utils.h" -#include "NetworkManagerUtils.h" -#include "nm-device-private.h" -#include "nm-netlink-monitor.h" -#include "nm-enum-types.h" -#include "nm-system.h" - -#include "nm-device-vlan-glue.h" - - -G_DEFINE_TYPE (NMDeviceVlan, nm_device_vlan, NM_TYPE_DEVICE) - -#define NM_DEVICE_VLAN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_VLAN, NMDeviceVlanPrivate)) - -#define NM_VLAN_ERROR (nm_vlan_error_quark ()) - -typedef struct { - gboolean disposed; - - NMDevice *parent; - guint parent_state_id; - - guint vlan_id; - - guint8 hw_addr[NM_UTILS_HWADDR_LEN_MAX]; - guint hw_addr_len; - - gboolean carrier; - NMNetlinkMonitor *monitor; - gulong link_connected_id; - gulong link_disconnected_id; - guint carrier_action_defer_id; -} NMDeviceVlanPrivate; - -enum { - PROPERTIES_CHANGED, - - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -enum { - PROP_0, - PROP_HW_ADDRESS, - PROP_CARRIER, - PROP_VLAN_ID, - - LAST_PROP -}; - -static void -set_carrier (NMDeviceVlan *self, - const gboolean carrier, - const gboolean defer_action); - -/******************************************************************/ - -static GQuark -nm_vlan_error_quark (void) -{ - static GQuark quark = 0; - if (!quark) - quark = g_quark_from_static_string ("nm-vlan-error"); - return quark; -} - -/******************************************************************/ - -static guint32 -get_generic_capabilities (NMDevice *dev) -{ - /* We assume VLAN interfaces always support carrier detect */ - return NM_DEVICE_CAP_CARRIER_DETECT | NM_DEVICE_CAP_NM_SUPPORTED; -} - -static gboolean -get_carrier_sync (NMDeviceVlan *self) -{ - NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (self); - GError *error = NULL; - guint32 ifflags = 0; - - /* Get initial link state */ - if (!nm_netlink_monitor_get_flags_sync (priv->monitor, - nm_device_get_ip_ifindex (NM_DEVICE (self)), - &ifflags, - &error)) { - nm_log_warn (LOGD_HW | LOGD_VLAN, - "(%s): couldn't get carrier state: (%d) %s", - nm_device_get_ip_iface (NM_DEVICE (self)), - error ? error->code : -1, - (error && error->message) ? error->message : "unknown"); - g_clear_error (&error); - } - - return !!(ifflags & IFF_LOWER_UP); -} - -static gboolean -hw_bring_up (NMDevice *dev, gboolean *no_firmware) -{ - gboolean success = FALSE, carrier; - guint i = 20; - - while (i-- > 0 && !success) { - success = NM_DEVICE_CLASS (nm_device_vlan_parent_class)->hw_bring_up (dev, no_firmware); - g_usleep (50); - } - - if (success) { - /* Block a bit to make sure the carrier comes on; it's delayed a bit - * after setting the interface up. - */ - i = 20; - while (i-- > 0) { - carrier = get_carrier_sync (NM_DEVICE_VLAN (dev)); - set_carrier (NM_DEVICE_VLAN (dev), carrier, carrier ? FALSE : TRUE); - if (carrier) - break; - g_usleep (100); - } - } - return success; -} - -static void -update_hw_address (NMDevice *dev) -{ - NMDeviceVlan *self = NM_DEVICE_VLAN (dev); - NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (self); - gsize addrlen; - gboolean changed = FALSE; - - addrlen = nm_device_read_hwaddr (dev, priv->hw_addr, sizeof (priv->hw_addr), &changed); - if (addrlen) { - priv->hw_addr_len = addrlen; - if (changed) - g_object_notify (G_OBJECT (self), NM_DEVICE_VLAN_HW_ADDRESS); - } -} - -static const guint8 * -get_hw_address (NMDevice *device, guint *out_len) -{ - NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (device); - - *out_len = priv->hw_addr_len; - return priv->hw_addr; -} - -static gboolean -can_interrupt_activation (NMDevice *dev) -{ - /* Can interrupt activation if the carrier drops while activating */ - return NM_DEVICE_VLAN_GET_PRIVATE (dev)->carrier ? FALSE : TRUE; -} - -static gboolean -is_available (NMDevice *dev) -{ - return NM_DEVICE_VLAN_GET_PRIVATE (dev)->carrier ? TRUE : FALSE; -} - -/******************************************************************/ - -static gboolean -match_parent (NMDeviceVlan *self, const char *parent, GError **error) -{ - NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (self); - - g_return_val_if_fail (parent != NULL, FALSE); - - if (nm_utils_is_uuid (parent)) { - NMActRequest *parent_req; - NMConnection *parent_connection; - - /* If the parent is a UUID, the connection matches if our parent - * device has that connection activated. - */ - - parent_req = nm_device_get_act_request (priv->parent); - if (!parent_req) { - g_set_error_literal (error, NM_VLAN_ERROR, NM_VLAN_ERROR_CONNECTION_INVALID, - "Parent interface not active; could not match UUID"); - return FALSE; - } - - parent_connection = nm_active_connection_get_connection (NM_ACTIVE_CONNECTION (parent_req)); - if (!parent_connection) { - g_set_error_literal (error, NM_VLAN_ERROR, NM_VLAN_ERROR_CONNECTION_INVALID, - "Parent interface had no connection; could not match UUID"); - return FALSE; - } - if (g_strcmp0 (parent, nm_connection_get_uuid (parent_connection)) != 0) { - g_set_error_literal (error, NM_VLAN_ERROR, NM_VLAN_ERROR_CONNECTION_INVALID, - "Parent interface UUID did not match connection UUID"); - return FALSE; - } - } else { - /* interface name */ - if (g_strcmp0 (parent, nm_device_get_ip_iface (priv->parent)) != 0) { - g_set_error_literal (error, NM_VLAN_ERROR, NM_VLAN_ERROR_CONNECTION_INVALID, - "Parent interface name did not match connection"); - return FALSE; - } - } - - return TRUE; -} - -static gboolean -match_vlan_connection (NMDeviceVlan *self, NMConnection *connection, GError **error) -{ - NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (self); - NMSettingVlan *s_vlan; - const char *parent, *iface = NULL; - - s_vlan = nm_connection_get_setting_vlan (connection); - if (!s_vlan) { - g_set_error (error, NM_VLAN_ERROR, NM_VLAN_ERROR_CONNECTION_INVALID, - "The connection was not a VLAN connection."); - return FALSE; - } - - if (nm_setting_vlan_get_id (s_vlan) != priv->vlan_id) { - g_set_error (error, NM_VLAN_ERROR, NM_VLAN_ERROR_CONNECTION_INVALID, - "The connection's VLAN ID did not match the device's VLAN ID."); - return FALSE; - } - - /* Check parent interface; could be an interface name or a UUID */ - parent = nm_setting_vlan_get_parent (s_vlan); - if (parent) { - if (!match_parent (self, parent, error)) - return FALSE; - } else { - /* Parent could be a MAC address in a hardware-specific setting */ - if (!nm_device_hwaddr_matches (priv->parent, connection, NULL, 0, TRUE)) { - g_set_error (error, NM_VLAN_ERROR, NM_VLAN_ERROR_CONNECTION_INVALID, - "Failed to match the VLAN parent interface via hardware address."); - return FALSE; - } - } - - /* Ensure the interface name matches. If not specified we assume a match - * since both the parent interface and the VLAN ID matched by the time we - * get here. - */ - iface = nm_connection_get_virtual_iface_name (connection); - if (iface) { - if (g_strcmp0 (nm_device_get_ip_iface (NM_DEVICE (self)), iface) != 0) { - g_set_error (error, NM_VLAN_ERROR, NM_VLAN_ERROR_CONNECTION_INVALID, - "The VLAN connection virtual interface name did not match."); - return FALSE; - } - } - - return TRUE; -} - -static NMConnection * -get_best_auto_connection (NMDevice *dev, - GSList *connections, - char **specific_object) -{ - GSList *iter; - - for (iter = connections; iter; iter = g_slist_next (iter)) { - NMConnection *connection = NM_CONNECTION (iter->data); - - if (match_vlan_connection (NM_DEVICE_VLAN (dev), connection, NULL)) - return connection; - } - return NULL; -} - -static gboolean -check_connection_compatible (NMDevice *device, - NMConnection *connection, - GError **error) -{ - return match_vlan_connection (NM_DEVICE_VLAN (device), connection, error); -} - -static gboolean -complete_connection (NMDevice *device, - NMConnection *connection, - const char *specific_object, - const GSList *existing_connections, - GError **error) -{ - NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (device); - NMSettingVlan *s_vlan; - - nm_utils_complete_generic (connection, - NM_SETTING_VLAN_SETTING_NAME, - existing_connections, - _("VLAN connection %d"), - NULL, - TRUE); - - s_vlan = nm_connection_get_setting_vlan (connection); - if (!s_vlan) { - g_set_error_literal (error, NM_VLAN_ERROR, NM_VLAN_ERROR_CONNECTION_INVALID, - "A 'vlan' setting is required."); - return FALSE; - } - - /* If there's no VLAN interface, no parent, and no hardware address in the - * settings, then there's not enough information to complete the setting. - */ - if (!nm_setting_vlan_get_parent (s_vlan)) { - if (!nm_device_hwaddr_matches (priv->parent, connection, NULL, 0, TRUE)) { - /* FIXME: put priv->hw_addr into the connection in the appropriate - * hardware-specific setting. - */ - g_set_error_literal (error, NM_VLAN_ERROR, NM_VLAN_ERROR_CONNECTION_INVALID, - "The 'vlan' setting had no interface name, parent, or hardware address."); - return FALSE; - } - } - - return TRUE; -} - -static gboolean -spec_match_list (NMDevice *device, const GSList *specs) -{ - NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (device); - char *hwaddr; - gboolean matched; - int itype = nm_utils_hwaddr_type (priv->hw_addr_len); - - hwaddr = nm_utils_hwaddr_ntoa (priv->hw_addr, itype); - matched = nm_match_spec_hwaddr (specs, hwaddr); - g_free (hwaddr); - - return matched; -} - -static gboolean -vlan_match_config (NMDevice *device, NMConnection *connection) -{ - NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (device); - NMSettingVlan *s_vlan; - const char *ifname, *parent; - gboolean fail_if_no_hwaddr = FALSE; - - s_vlan = nm_connection_get_setting_vlan (connection); - if (!s_vlan) - return FALSE; - - /* Interface name */ - ifname = nm_setting_vlan_get_interface_name (s_vlan); - if (g_strcmp0 (ifname, nm_device_get_ip_iface (device)) != 0) - return FALSE; - - if (nm_setting_vlan_get_id (s_vlan) != priv->vlan_id) - return FALSE; - - parent = nm_setting_vlan_get_parent (s_vlan); - if (parent) { - if (!match_parent (NM_DEVICE_VLAN (device), parent, NULL)) - return FALSE; - } else { - /* If there's no parent and no interface name given, then the only way - * we have to identify the VLAN interface the connection matches is - * a hardware-specific setting's hardware address property, so we want - * to fail the match below if we there is none. - */ - if (ifname == NULL) - fail_if_no_hwaddr = TRUE; - } - - /* MAC address check; we ask the parent to check our own MAC address, - * because only the parent knows what kind of NMSetting the MAC - * address will be in. The VLAN device shouldn't have to know what kind - * of interface the parent is. - */ - if (!nm_device_hwaddr_matches (priv->parent, connection, priv->hw_addr, priv->hw_addr_len, fail_if_no_hwaddr)) - return FALSE; - - return TRUE; -} - -static NMConnection * -connection_match_config (NMDevice *self, const GSList *connections) -{ - const GSList *iter; - - /* First narrow @connections down to those that match in their - * NMSettingVlan configuration. - */ - for (iter = connections; iter; iter = iter->next) { - NMConnection *candidate = iter->data; - - if (!nm_connection_is_type (candidate, NM_SETTING_VLAN_SETTING_NAME)) - continue; - if (!vlan_match_config (self, candidate)) - continue; - if (!nm_device_match_ip_config (self, candidate)) - continue; - - return candidate; - } - return NULL; -} - -/******************************************************************/ - -static void -carrier_action_defer_clear (NMDeviceVlan *self) -{ - NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (self); - - if (priv->carrier_action_defer_id) { - g_source_remove (priv->carrier_action_defer_id); - priv->carrier_action_defer_id = 0; - } -} - -static gboolean -carrier_action_defer_cb (gpointer user_data) -{ - NMDeviceVlan *self = NM_DEVICE_VLAN (user_data); - NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (self); - NMDeviceState state; - - priv->carrier_action_defer_id = 0; - - state = nm_device_get_state (NM_DEVICE (self)); - if (state == NM_DEVICE_STATE_UNAVAILABLE) { - if (priv->carrier) - nm_device_queue_state (NM_DEVICE (self), NM_DEVICE_STATE_DISCONNECTED, NM_DEVICE_STATE_REASON_CARRIER); - } else if (state >= NM_DEVICE_STATE_DISCONNECTED) { - if (!priv->carrier) - nm_device_queue_state (NM_DEVICE (self), NM_DEVICE_STATE_UNAVAILABLE, NM_DEVICE_STATE_REASON_CARRIER); - } - return FALSE; -} - -static void -set_carrier (NMDeviceVlan *self, - const gboolean carrier, - const gboolean defer_action) -{ - NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (self); - NMDeviceState state; - - if (priv->carrier == carrier) - return; - - /* Clear any previous deferred action */ - carrier_action_defer_clear (self); - - priv->carrier = carrier; - g_object_notify (G_OBJECT (self), NM_DEVICE_VLAN_CARRIER); - - state = nm_device_get_state (NM_DEVICE (self)); - nm_log_info (LOGD_HW | LOGD_VLAN, - "(%s): carrier now %s (device state %d%s)", - nm_device_get_iface (NM_DEVICE (self)), - carrier ? "ON" : "OFF", - state, - defer_action ? ", deferring action for 4 seconds" : ""); - - if (defer_action) - priv->carrier_action_defer_id = g_timeout_add_seconds (4, carrier_action_defer_cb, self); - else - carrier_action_defer_cb (self); -} - -static void -carrier_on (NMNetlinkMonitor *monitor, int idx, NMDevice *device) -{ - /* Make sure signal is for us */ - if (idx == nm_device_get_ifindex (device)) - set_carrier (NM_DEVICE_VLAN (device), TRUE, FALSE); -} - -static void -carrier_off (NMNetlinkMonitor *monitor, int idx, NMDevice *device) -{ - NMDeviceState state; - gboolean defer = FALSE; - - /* Make sure signal is for us */ - if (idx == nm_device_get_ifindex (device)) { - /* Defer carrier-off event actions while connected by a few seconds - * so that tripping over a cable, power-cycling a switch, or breaking - * off the RJ45 locking tab isn't so catastrophic. - */ - state = nm_device_get_state (device); - if (state > NM_DEVICE_STATE_DISCONNECTED) - defer = TRUE; - - set_carrier (NM_DEVICE_VLAN (device), FALSE, defer); - } -} - -static void -carrier_watch_init (NMDeviceVlan *self) -{ - NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (self); - - priv->monitor = nm_netlink_monitor_get (); - priv->link_connected_id = g_signal_connect (priv->monitor, "carrier-on", - G_CALLBACK (carrier_on), - self); - priv->link_disconnected_id = g_signal_connect (priv->monitor, "carrier-off", - G_CALLBACK (carrier_off), - self); - - priv->carrier = get_carrier_sync (NM_DEVICE_VLAN (self)); - - nm_log_info (LOGD_HW | LOGD_VLAN, "(%s): carrier is %s", - nm_device_get_iface (NM_DEVICE (self)), - priv->carrier ? "ON" : "OFF"); - - /* Request link state again just in case an error occurred getting the - * initial link state. - */ - nm_netlink_monitor_request_status (priv->monitor); -} - -/******************************************************************/ - -static void -parent_state_changed (NMDevice *parent, - NMDeviceState new_state, - NMDeviceState old_state, - NMDeviceStateReason reason, - gpointer user_data) -{ - NMDeviceVlan *self = NM_DEVICE_VLAN (user_data); - - if (new_state < NM_DEVICE_STATE_DISCONNECTED) { - /* If the parent becomes unavailable or unmanaged so does the VLAN */ - nm_device_state_changed (NM_DEVICE (self), new_state, reason); - } else if ( new_state == NM_DEVICE_STATE_DISCONNECTED - && old_state < NM_DEVICE_STATE_DISCONNECTED) { - /* Mark VLAN interface as available/disconnected when the parent - * becomes available as a result of carrier changes or becoming - * initialized. - */ - nm_device_state_changed (NM_DEVICE (self), new_state, reason); - } -} - -/******************************************************************/ - -NMDevice * -nm_device_vlan_new (const char *udi, const char *iface, NMDevice *parent) -{ - NMDevice *device; - - g_return_val_if_fail (udi != NULL, NULL); - g_return_val_if_fail (iface != NULL, NULL); - g_return_val_if_fail (parent != NULL, NULL); - - device = (NMDevice *) g_object_new (NM_TYPE_DEVICE_VLAN, - NM_DEVICE_UDI, udi, - NM_DEVICE_IFACE, iface, - NM_DEVICE_DRIVER, "8021q", - NM_DEVICE_TYPE_DESC, "VLAN", - NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_VLAN, - NULL); - if (device) { - NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (device); - int ifindex = nm_device_get_ifindex (device); - int parent_ifindex = -1, itype; - int vlan_id; - - itype = nm_system_get_iface_type (ifindex, iface); - if (itype != NM_IFACE_TYPE_VLAN) { - nm_log_err (LOGD_VLAN, "(%s): failed to get VLAN interface type.", iface); - g_object_unref (device); - return NULL; - } - - if (!nm_system_get_iface_vlan_info (ifindex, &parent_ifindex, &vlan_id)) { - nm_log_warn (LOGD_VLAN, "(%s): failed to get VLAN interface info.", iface); - g_object_unref (device); - return NULL; - } - - if ( parent_ifindex < 0 - || parent_ifindex != nm_device_get_ip_ifindex (parent) - || vlan_id < 0) { - nm_log_warn (LOGD_VLAN, "(%s): VLAN parent ifindex (%d) or VLAN ID (%d) invalid.", - iface, parent_ifindex, priv->vlan_id); - g_object_unref (device); - return NULL; - } - - priv->vlan_id = vlan_id; - priv->parent = g_object_ref (parent); - priv->parent_state_id = g_signal_connect (priv->parent, - "state-changed", - G_CALLBACK (parent_state_changed), - device); - - carrier_watch_init (NM_DEVICE_VLAN (device)); - - nm_log_dbg (LOGD_HW | LOGD_ETHER, "(%s): kernel ifindex %d", iface, ifindex); - nm_log_info (LOGD_HW | LOGD_ETHER, "(%s): VLAN ID %d with parent %s", - iface, priv->vlan_id, nm_device_get_iface (parent)); - } - - return device; -} - -static void -nm_device_vlan_init (NMDeviceVlan * self) -{ -} - -static void -get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) -{ - NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (object); - char *hwaddr; - - switch (prop_id) { - case PROP_HW_ADDRESS: - hwaddr = nm_utils_hwaddr_ntoa (priv->hw_addr, nm_utils_hwaddr_type (priv->hw_addr_len)); - g_value_take_string (value, hwaddr); - break; - case PROP_CARRIER: - g_value_set_boolean (value, priv->carrier); - break; - case PROP_VLAN_ID: - g_value_set_uint (value, priv->vlan_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) -{ - NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (object); - - switch (prop_id) { - case PROP_VLAN_ID: - priv->vlan_id = g_value_get_uint (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -dispose (GObject *object) -{ - NMDeviceVlan *self = NM_DEVICE_VLAN (object); - NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (self); - - if (priv->disposed) { - G_OBJECT_CLASS (nm_device_vlan_parent_class)->dispose (object); - return; - } - priv->disposed = TRUE; - - if (priv->link_connected_id) - g_signal_handler_disconnect (priv->monitor, priv->link_connected_id); - if (priv->link_disconnected_id) - g_signal_handler_disconnect (priv->monitor, priv->link_disconnected_id); - carrier_action_defer_clear (self); - - g_object_unref (priv->monitor); - - g_signal_handler_disconnect (priv->parent, priv->parent_state_id); - g_object_unref (priv->parent); - - G_OBJECT_CLASS (nm_device_vlan_parent_class)->dispose (object); -} - -static void -nm_device_vlan_class_init (NMDeviceVlanClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass); - - g_type_class_add_private (object_class, sizeof (NMDeviceVlanPrivate)); - - /* virtual methods */ - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->dispose = dispose; - - parent_class->get_generic_capabilities = get_generic_capabilities; - parent_class->update_hw_address = update_hw_address; - parent_class->get_hw_address = get_hw_address; - parent_class->hw_bring_up = hw_bring_up; - parent_class->can_interrupt_activation = can_interrupt_activation; - parent_class->is_available = is_available; - - parent_class->get_best_auto_connection = get_best_auto_connection; - parent_class->check_connection_compatible = check_connection_compatible; - parent_class->complete_connection = complete_connection; - parent_class->spec_match_list = spec_match_list; - parent_class->connection_match_config = connection_match_config; - - /* properties */ - g_object_class_install_property - (object_class, PROP_HW_ADDRESS, - g_param_spec_string (NM_DEVICE_VLAN_HW_ADDRESS, - "Active MAC Address", - "Currently set hardware MAC address", - NULL, - G_PARAM_READABLE)); - - g_object_class_install_property - (object_class, PROP_CARRIER, - g_param_spec_boolean (NM_DEVICE_VLAN_CARRIER, - "Carrier", - "Carrier", - FALSE, - G_PARAM_READABLE)); - - g_object_class_install_property - (object_class, PROP_VLAN_ID, - g_param_spec_uint (NM_DEVICE_VLAN_ID, - "VLAN ID", - "VLAN ID", - 0, 4095, 0, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - /* Signals */ - signals[PROPERTIES_CHANGED] = - nm_properties_changed_signal_new (object_class, - G_STRUCT_OFFSET (NMDeviceVlanClass, properties_changed)); - - dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass), - &dbus_glib_nm_device_vlan_object_info); - - dbus_g_error_domain_register (NM_VLAN_ERROR, NULL, NM_TYPE_VLAN_ERROR); -} diff --git a/src/nm-device-vlan.h b/src/nm-device-vlan.h deleted file mode 100644 index 7c5fa24c..00000000 --- a/src/nm-device-vlan.h +++ /dev/null @@ -1,67 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2012 Red Hat, Inc. - */ - -#ifndef NM_DEVICE_VLAN_H -#define NM_DEVICE_VLAN_H - -#include - -#include "nm-device-wired.h" - -G_BEGIN_DECLS - -#define NM_TYPE_DEVICE_VLAN (nm_device_vlan_get_type ()) -#define NM_DEVICE_VLAN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_VLAN, NMDeviceVlan)) -#define NM_DEVICE_VLAN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_VLAN, NMDeviceVlanClass)) -#define NM_IS_DEVICE_VLAN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_VLAN)) -#define NM_IS_DEVICE_VLAN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_VLAN)) -#define NM_DEVICE_VLAN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_VLAN, NMDeviceVlanClass)) - -typedef enum { - NM_VLAN_ERROR_CONNECTION_NOT_VLAN = 0, /*< nick=ConnectionNotVlan >*/ - NM_VLAN_ERROR_CONNECTION_INVALID, /*< nick=ConnectionInvalid >*/ - NM_VLAN_ERROR_CONNECTION_INCOMPATIBLE, /*< nick=ConnectionIncompatible >*/ -} NMVlanError; - -#define NM_DEVICE_VLAN_HW_ADDRESS "hw-address" -#define NM_DEVICE_VLAN_CARRIER "carrier" -#define NM_DEVICE_VLAN_ID "vlan-id" - -typedef struct { - NMDevice parent; -} NMDeviceVlan; - -typedef struct { - NMDeviceClass parent; - - /* Signals */ - void (*properties_changed) (NMDeviceVlan *device, GHashTable *properties); -} NMDeviceVlanClass; - - -GType nm_device_vlan_get_type (void); - -NMDevice *nm_device_vlan_new (const char *udi, - const char *iface, - NMDevice *parent); - -G_END_DECLS - -#endif /* NM_DEVICE_VLAN_H */ diff --git a/src/nm-device-vxlan-glue.h b/src/nm-device-vxlan-glue.h new file mode 100644 index 00000000..988dbd32 --- /dev/null +++ b/src/nm-device-vxlan-glue.h @@ -0,0 +1,73 @@ +/* Generated by dbus-binding-tool; do not edit! */ + + +#ifndef __dbus_glib_marshal_nm_device_vxlan_MARSHAL_H__ +#define __dbus_glib_marshal_nm_device_vxlan_MARSHAL_H__ + +#include + +G_BEGIN_DECLS + +#ifdef G_ENABLE_DEBUG +#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v) +#define g_marshal_value_peek_char(v) g_value_get_schar (v) +#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v) +#define g_marshal_value_peek_int(v) g_value_get_int (v) +#define g_marshal_value_peek_uint(v) g_value_get_uint (v) +#define g_marshal_value_peek_long(v) g_value_get_long (v) +#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v) +#define g_marshal_value_peek_int64(v) g_value_get_int64 (v) +#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v) +#define g_marshal_value_peek_enum(v) g_value_get_enum (v) +#define g_marshal_value_peek_flags(v) g_value_get_flags (v) +#define g_marshal_value_peek_float(v) g_value_get_float (v) +#define g_marshal_value_peek_double(v) g_value_get_double (v) +#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v) +#define g_marshal_value_peek_param(v) g_value_get_param (v) +#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v) +#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v) +#define g_marshal_value_peek_object(v) g_value_get_object (v) +#define g_marshal_value_peek_variant(v) g_value_get_variant (v) +#else /* !G_ENABLE_DEBUG */ +/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API. + * Do not access GValues directly in your code. Instead, use the + * g_value_get_*() functions + */ +#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int +#define g_marshal_value_peek_char(v) (v)->data[0].v_int +#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint +#define g_marshal_value_peek_int(v) (v)->data[0].v_int +#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint +#define g_marshal_value_peek_long(v) (v)->data[0].v_long +#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 +#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 +#define g_marshal_value_peek_enum(v) (v)->data[0].v_long +#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_float(v) (v)->data[0].v_float +#define g_marshal_value_peek_double(v) (v)->data[0].v_double +#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer +#endif /* !G_ENABLE_DEBUG */ + + +G_END_DECLS + +#endif /* __dbus_glib_marshal_nm_device_vxlan_MARSHAL_H__ */ + +#include +static const DBusGMethodInfo dbus_glib_nm_device_vxlan_methods[] = { +}; + +const DBusGObjectInfo dbus_glib_nm_device_vxlan_object_info = { 1, + dbus_glib_nm_device_vxlan_methods, + 0, +"\0", +"org.freedesktop.NetworkManager.Device.Vxlan\0PropertiesChanged\0\0", +"org.freedesktop.NetworkManager.Device.Vxlan\0Parent\0parent\0read\0org.freedesktop.NetworkManager.Device.Vxlan\0Id\0id\0read\0org.freedesktop.NetworkManager.Device.Vxlan\0Group\0group\0read\0org.freedesktop.NetworkManager.Device.Vxlan\0Local\0local\0read\0org.freedesktop.NetworkManager.Device.Vxlan\0Tos\0tos\0read\0org.freedesktop.NetworkManager.Device.Vxlan\0Ttl\0ttl\0read\0org.freedesktop.NetworkManager.Device.Vxlan\0Learning\0learning\0read\0org.freedesktop.NetworkManager.Device.Vxlan\0Ageing\0ageing\0read\0org.freedesktop.NetworkManager.Device.Vxlan\0Limit\0limit\0read\0org.freedesktop.NetworkManager.Device.Vxlan\0DstPort\0dst_port\0read\0org.freedesktop.NetworkManager.Device.Vxlan\0SrcPortMin\0src_port_min\0read\0org.freedesktop.NetworkManager.Device.Vxlan\0SrcPortMax\0src_port_max\0read\0org.freedesktop.NetworkManager.Device.Vxlan\0Proxy\0proxy\0read\0org.freedesktop.NetworkManager.Device.Vxlan\0Rsc\0rsc\0read\0org.freedesktop.NetworkManager.Device.Vxlan\0L2miss\0l2miss\0read\0org.freedesktop.NetworkManager.Device.Vxlan\0L3miss\0l3miss\0read\0\0" +}; + diff --git a/src/nm-device-wifi.c b/src/nm-device-wifi.c deleted file mode 100644 index 8ca52780..00000000 --- a/src/nm-device-wifi.c +++ /dev/null @@ -1,3903 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2005 - 2012 Red Hat, Inc. - * Copyright (C) 2006 - 2008 Novell, Inc. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "nm-glib-compat.h" -#include "nm-device.h" -#include "nm-device-wifi.h" -#include "nm-device-private.h" -#include "nm-utils.h" -#include "nm-logging.h" -#include "nm-marshal.h" -#include "NetworkManagerUtils.h" -#include "nm-activation-request.h" -#include "nm-supplicant-manager.h" -#include "nm-supplicant-interface.h" -#include "nm-supplicant-config.h" -#include "nm-properties-changed-signal.h" -#include "nm-setting-connection.h" -#include "nm-setting-wireless.h" -#include "nm-setting-wireless-security.h" -#include "nm-setting-8021x.h" -#include "nm-setting-ip4-config.h" -#include "nm-setting-ip6-config.h" -#include "nm-system.h" -#include "nm-manager-auth.h" -#include "nm-settings-connection.h" -#include "nm-enum-types.h" -#include "wifi-utils.h" - -static gboolean impl_device_get_access_points (NMDeviceWifi *device, - GPtrArray **aps, - GError **err); - -static void impl_device_request_scan (NMDeviceWifi *device, - GHashTable *options, - DBusGMethodInvocation *context); - -#include "nm-device-wifi-glue.h" - - -/* All of these are in seconds */ -#define SCAN_INTERVAL_MIN 3 -#define SCAN_INTERVAL_STEP 20 -#define SCAN_INTERVAL_MAX 120 - -#define WIRELESS_SECRETS_TRIES "wireless-secrets-tries" - -G_DEFINE_TYPE (NMDeviceWifi, nm_device_wifi, NM_TYPE_DEVICE) - -#define NM_DEVICE_WIFI_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_WIFI, NMDeviceWifiPrivate)) - - -enum { - PROP_0, - PROP_HW_ADDRESS, - PROP_PERM_HW_ADDRESS, - PROP_MODE, - PROP_BITRATE, - PROP_ACTIVE_ACCESS_POINT, - PROP_CAPABILITIES, - PROP_SCANNING, - PROP_IPW_RFKILL_STATE, - - LAST_PROP -}; - -enum { - ACCESS_POINT_ADDED, - ACCESS_POINT_REMOVED, - HIDDEN_AP_FOUND, - PROPERTIES_CHANGED, - SCANNING_ALLOWED, - - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -#define SUP_SIG_ID_LEN 6 - -typedef struct Supplicant { - NMSupplicantManager *mgr; - NMSupplicantInterface *iface; - - guint sig_ids[SUP_SIG_ID_LEN]; - guint iface_error_id; - - /* Timeouts and idles */ - guint iface_con_error_cb_id; - guint con_timeout_id; -} Supplicant; - -struct _NMDeviceWifiPrivate { - gboolean disposed; - - guint8 hw_addr[ETH_ALEN]; /* Currently set MAC address */ - guint8 perm_hw_addr[ETH_ALEN]; /* Permanent MAC address */ - guint8 initial_hw_addr[ETH_ALEN]; /* Initial MAC address (as seen when NM starts) */ - - /* Legacy rfkill for ipw2x00; will be fixed with 2.6.33 kernel */ - char * ipw_rfkill_path; - guint ipw_rfkill_id; - RfKillState ipw_rfkill_state; - - gint8 invalid_strength_counter; - - GSList * ap_list; - NMAccessPoint * current_ap; - guint32 rate; - gboolean enabled; /* rfkilled or not */ - - time_t scheduled_scan_time; - guint8 scan_interval; /* seconds */ - guint pending_scan_id; - guint scanlist_cull_id; - - Supplicant supplicant; - WifiData * wifi_data; - gboolean ssid_found; - NM80211Mode mode; - - guint32 failed_link_count; - guint periodic_source_id; - guint link_timeout_id; - - NMDeviceWifiCapabilities capabilities; -}; - -static gboolean check_scanning_allowed (NMDeviceWifi *self); - -static void schedule_scan (NMDeviceWifi *self, gboolean backoff); - -static void cancel_pending_scan (NMDeviceWifi *self); - -static void cleanup_association_attempt (NMDeviceWifi * self, - gboolean disconnect); - -static void remove_supplicant_timeouts (NMDeviceWifi *self); - -static void supplicant_iface_state_cb (NMSupplicantInterface *iface, - guint32 new_state, - guint32 old_state, - int disconnect_reason, - gpointer user_data); - -static void supplicant_iface_new_bss_cb (NMSupplicantInterface * iface, - const char *object_path, - GHashTable *properties, - NMDeviceWifi * self); - -static void supplicant_iface_bss_updated_cb (NMSupplicantInterface *iface, - const char *object_path, - GHashTable *properties, - NMDeviceWifi *self); - -static void supplicant_iface_bss_removed_cb (NMSupplicantInterface *iface, - const char *object_path, - NMDeviceWifi *self); - -static void supplicant_iface_scan_done_cb (NMSupplicantInterface * iface, - gboolean success, - NMDeviceWifi * self); - -static void supplicant_iface_notify_scanning_cb (NMSupplicantInterface * iface, - GParamSpec * pspec, - NMDeviceWifi * self); - -static void schedule_scanlist_cull (NMDeviceWifi *self); - -static gboolean request_wireless_scan (gpointer user_data); - -static void update_hw_address (NMDevice *dev); - -/*****************************************************************/ - -#define NM_WIFI_ERROR (nm_wifi_error_quark ()) - -static GQuark -nm_wifi_error_quark (void) -{ - static GQuark quark = 0; - if (!quark) - quark = g_quark_from_static_string ("nm-wifi-error"); - return quark; -} - -/*****************************************************************/ - -/* IPW rfkill handling (until 2.6.33) */ -RfKillState -nm_device_wifi_get_ipw_rfkill_state (NMDeviceWifi *self) -{ - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - char *contents = NULL; - RfKillState state = RFKILL_UNBLOCKED; - const char *str_state = NULL; - - if ( priv->ipw_rfkill_path - && g_file_get_contents (priv->ipw_rfkill_path, &contents, NULL, NULL)) { - contents = g_strstrip (contents); - - /* 0 - RF kill not enabled - * 1 - SW based RF kill active (sysfs) - * 2 - HW based RF kill active - * 3 - Both HW and SW baed RF kill active - */ - switch (contents[0]) { - case '1': - state = RFKILL_SOFT_BLOCKED; - str_state = "soft-blocked"; - break; - case '2': - case '3': - state = RFKILL_HARD_BLOCKED; - str_state = "hard-blocked"; - break; - case '0': - str_state = "unblocked"; - default: - break; - } - g_free (contents); - - nm_log_dbg (LOGD_RFKILL, "(%s): ipw rfkill state '%s'", - nm_device_get_iface (NM_DEVICE (self)), - str_state ? str_state : "(unknown)"); - } - - return state; -} - -static gboolean -ipw_rfkill_state_work (gpointer user_data) -{ - NMDeviceWifi *self = NM_DEVICE_WIFI (user_data); - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - RfKillState old_state; - - old_state = priv->ipw_rfkill_state; - priv->ipw_rfkill_state = nm_device_wifi_get_ipw_rfkill_state (self); - if (priv->ipw_rfkill_state != old_state) - g_object_notify (G_OBJECT (self), NM_DEVICE_WIFI_IPW_RFKILL_STATE); - - return TRUE; -} - -/*****************************************************************/ - -static guint32 -get_generic_capabilities (NMDevice *dev) -{ - return NM_DEVICE_CAP_NM_SUPPORTED; -} - -static GObject* -constructor (GType type, - guint n_construct_params, - GObjectConstructParam *construct_params) -{ - GObject *object; - GObjectClass *klass; - NMDeviceWifi *self; - NMDeviceWifiPrivate *priv; - - klass = G_OBJECT_CLASS (nm_device_wifi_parent_class); - object = klass->constructor (type, n_construct_params, construct_params); - if (!object) - return NULL; - - self = NM_DEVICE_WIFI (object); - priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - - nm_log_dbg (LOGD_HW | LOGD_WIFI, "(%s): kernel ifindex %d", - nm_device_get_iface (NM_DEVICE (self)), - nm_device_get_ifindex (NM_DEVICE (self))); - - priv->wifi_data = wifi_utils_init (nm_device_get_iface (NM_DEVICE (self)), - nm_device_get_ifindex (NM_DEVICE (self)), - TRUE); - if (priv->wifi_data == NULL) { - nm_log_warn (LOGD_HW | LOGD_WIFI, "(%s): failed to initialize WiFi driver", - nm_device_get_iface (NM_DEVICE (self))); - g_object_unref (object); - return NULL; - } - priv->capabilities = wifi_utils_get_caps (priv->wifi_data); - - if (priv->capabilities & NM_WIFI_DEVICE_CAP_AP) { - nm_log_info (LOGD_HW | LOGD_WIFI, "(%s): driver supports Access Point (AP) mode", - nm_device_get_iface (NM_DEVICE (self))); - } - - /* Connect to the supplicant manager */ - priv->supplicant.mgr = nm_supplicant_manager_get (); - g_assert (priv->supplicant.mgr); - - /* The ipw2x00 drivers don't integrate with the kernel rfkill subsystem until - * 2.6.33. Thus all our nice libgudev magic is useless. So we get to poll. - * - * FIXME: when 2.6.33 comes lands, we can do some sysfs parkour to figure out - * if we need to poll or not by matching /sys/class/net/ethX/device to one - * of the /sys/class/rfkill/rfkillX/device links. If there's a match, we - * don't have to poll. - */ - priv->ipw_rfkill_path = g_strdup_printf ("/sys/class/net/%s/device/rf_kill", - nm_device_get_iface (NM_DEVICE (self))); - if (!g_file_test (priv->ipw_rfkill_path, G_FILE_TEST_IS_REGULAR)) { - g_free (priv->ipw_rfkill_path); - priv->ipw_rfkill_path = NULL; - } - priv->ipw_rfkill_state = nm_device_wifi_get_ipw_rfkill_state (self); - - return object; -} - -static gboolean -supplicant_interface_acquire (NMDeviceWifi *self) -{ - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - guint id, i = 0; - - g_return_val_if_fail (self != NULL, FALSE); - /* interface already acquired? */ - g_return_val_if_fail (priv->supplicant.iface == NULL, TRUE); - - priv->supplicant.iface = nm_supplicant_manager_iface_get (priv->supplicant.mgr, - nm_device_get_iface (NM_DEVICE (self)), - TRUE); - if (priv->supplicant.iface == NULL) { - nm_log_err (LOGD_WIFI, "Couldn't initialize supplicant interface for %s.", - nm_device_get_iface (NM_DEVICE (self))); - return FALSE; - } - - memset (priv->supplicant.sig_ids, 0, sizeof (priv->supplicant.sig_ids)); - - id = g_signal_connect (priv->supplicant.iface, - NM_SUPPLICANT_INTERFACE_STATE, - G_CALLBACK (supplicant_iface_state_cb), - self); - priv->supplicant.sig_ids[i++] = id; - - id = g_signal_connect (priv->supplicant.iface, - NM_SUPPLICANT_INTERFACE_NEW_BSS, - G_CALLBACK (supplicant_iface_new_bss_cb), - self); - priv->supplicant.sig_ids[i++] = id; - - id = g_signal_connect (priv->supplicant.iface, - NM_SUPPLICANT_INTERFACE_BSS_UPDATED, - G_CALLBACK (supplicant_iface_bss_updated_cb), - self); - priv->supplicant.sig_ids[i++] = id; - - id = g_signal_connect (priv->supplicant.iface, - NM_SUPPLICANT_INTERFACE_BSS_REMOVED, - G_CALLBACK (supplicant_iface_bss_removed_cb), - self); - priv->supplicant.sig_ids[i++] = id; - - id = g_signal_connect (priv->supplicant.iface, - NM_SUPPLICANT_INTERFACE_SCAN_DONE, - G_CALLBACK (supplicant_iface_scan_done_cb), - self); - priv->supplicant.sig_ids[i++] = id; - - id = g_signal_connect (priv->supplicant.iface, - "notify::scanning", - G_CALLBACK (supplicant_iface_notify_scanning_cb), - self); - priv->supplicant.sig_ids[i++] = id; - - return TRUE; -} - -static void -remove_supplicant_interface_error_handler (NMDeviceWifi *self) -{ - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - - if (!priv->supplicant.iface) - return; - - if (priv->supplicant.iface_error_id > 0) { - g_signal_handler_disconnect (priv->supplicant.iface, priv->supplicant.iface_error_id); - priv->supplicant.iface_error_id = 0; - } - - if (priv->supplicant.iface_con_error_cb_id > 0) { - g_source_remove (priv->supplicant.iface_con_error_cb_id); - priv->supplicant.iface_con_error_cb_id = 0; - } -} - -static void -supplicant_interface_release (NMDeviceWifi *self) -{ - NMDeviceWifiPrivate *priv; - guint i; - - g_return_if_fail (self != NULL); - - priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - - cancel_pending_scan (self); - - /* Reset the scan interval to be pretty frequent when disconnected */ - priv->scan_interval = SCAN_INTERVAL_MIN + SCAN_INTERVAL_STEP; - nm_log_dbg (LOGD_WIFI_SCAN, "(%s): reset scanning interval to %d seconds", - nm_device_get_iface (NM_DEVICE (self)), - priv->scan_interval); - - remove_supplicant_interface_error_handler (self); - - /* Clear supplicant interface signal handlers */ - for (i = 0; i < SUP_SIG_ID_LEN; i++) { - if (priv->supplicant.sig_ids[i] > 0) - g_signal_handler_disconnect (priv->supplicant.iface, priv->supplicant.sig_ids[i]); - } - memset (priv->supplicant.sig_ids, 0, sizeof (priv->supplicant.sig_ids)); - - if (priv->scanlist_cull_id) { - g_source_remove (priv->scanlist_cull_id); - priv->scanlist_cull_id = 0; - } - - if (priv->supplicant.iface) { - /* Tell the supplicant to disconnect from the current AP */ - nm_supplicant_interface_disconnect (priv->supplicant.iface); - - nm_supplicant_manager_iface_release (priv->supplicant.mgr, priv->supplicant.iface); - priv->supplicant.iface = NULL; - } -} - -static NMAccessPoint * -get_ap_by_path (NMDeviceWifi *self, const char *path) -{ - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - GSList *iter; - - for (iter = priv->ap_list; iter; iter = g_slist_next (iter)) { - if (g_strcmp0 (path, nm_ap_get_dbus_path (NM_AP (iter->data))) == 0) - return NM_AP (iter->data); - } - return NULL; -} - -static NMAccessPoint * -get_ap_by_supplicant_path (NMDeviceWifi *self, const char *path) -{ - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - GSList *iter; - - for (iter = priv->ap_list; iter && path; iter = g_slist_next (iter)) { - if (g_strcmp0 (path, nm_ap_get_supplicant_path (NM_AP (iter->data))) == 0) - return NM_AP (iter->data); - } - return NULL; -} - -static NMAccessPoint * -get_active_ap (NMDeviceWifi *self, - NMAccessPoint *ignore_ap, - gboolean match_hidden) -{ - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - const char *iface = nm_device_get_iface (NM_DEVICE (self)); - struct ether_addr bssid; - GByteArray *ssid; - GSList *iter; - int i = 0; - NMAccessPoint *match_nofreq = NULL, *active_ap = NULL; - gboolean found_a_band = FALSE; - gboolean found_bg_band = FALSE; - NM80211Mode devmode; - guint32 devfreq; - - wifi_utils_get_bssid (priv->wifi_data, &bssid); - nm_log_dbg (LOGD_WIFI, "(%s): active BSSID: %02x:%02x:%02x:%02x:%02x:%02x", - iface, - bssid.ether_addr_octet[0], bssid.ether_addr_octet[1], - bssid.ether_addr_octet[2], bssid.ether_addr_octet[3], - bssid.ether_addr_octet[4], bssid.ether_addr_octet[5]); - - if (!nm_ethernet_address_is_valid (&bssid)) - return NULL; - - ssid = wifi_utils_get_ssid (priv->wifi_data); - nm_log_dbg (LOGD_WIFI, "(%s): active SSID: %s%s%s", - iface, - ssid ? "'" : "", - ssid ? nm_utils_escape_ssid (ssid->data, ssid->len) : "(none)", - ssid ? "'" : ""); - - devmode = wifi_utils_get_mode (priv->wifi_data); - devfreq = wifi_utils_get_freq (priv->wifi_data); - - /* When matching hidden APs, do a second pass that ignores the SSID check, - * because NM might not yet know the SSID of the hidden AP in the scan list - * and therefore it won't get matched the first time around. - */ - while (i++ < (match_hidden ? 2 : 1)) { - nm_log_dbg (LOGD_WIFI, " Pass #%d %s", i, i > 1 ? "(ignoring SSID)" : ""); - - /* Find this SSID + BSSID in the device's AP list */ - for (iter = priv->ap_list; iter; iter = g_slist_next (iter)) { - NMAccessPoint *ap = NM_AP (iter->data); - const struct ether_addr *ap_bssid = nm_ap_get_address (ap); - const GByteArray *ap_ssid = nm_ap_get_ssid (ap); - NM80211Mode apmode; - guint32 apfreq; - - nm_log_dbg (LOGD_WIFI, " AP: %s%s%s %02x:%02x:%02x:%02x:%02x:%02x", - ap_ssid ? "'" : "", - ap_ssid ? nm_utils_escape_ssid (ap_ssid->data, ap_ssid->len) : "(none)", - ap_ssid ? "'" : "", - ap_bssid->ether_addr_octet[0], ap_bssid->ether_addr_octet[1], - ap_bssid->ether_addr_octet[2], ap_bssid->ether_addr_octet[3], - ap_bssid->ether_addr_octet[4], ap_bssid->ether_addr_octet[5]); - - if (ignore_ap && (ap == ignore_ap)) { - nm_log_dbg (LOGD_WIFI, " ignored"); - continue; - } - - if (memcmp (bssid.ether_addr_octet, ap_bssid->ether_addr_octet, ETH_ALEN)) { - nm_log_dbg (LOGD_WIFI, " BSSID mismatch"); - continue; - } - - if ((i == 0) && !nm_utils_same_ssid (ssid, ap_ssid, TRUE)) { - nm_log_dbg (LOGD_WIFI, " SSID mismatch"); - continue; - } - - apmode = nm_ap_get_mode (ap); - if (devmode != apmode) { - nm_log_dbg (LOGD_WIFI, " mode mismatch (device %d, ap %d)", - devmode, apmode); - continue; - } - - apfreq = nm_ap_get_freq (ap); - if (devfreq != apfreq) { - nm_log_dbg (LOGD_WIFI, " frequency mismatch (device %u, ap %u)", - devfreq, apfreq); - - if (match_nofreq == NULL) - match_nofreq = ap; - - if (apfreq > 4000) - found_a_band = TRUE; - else if (apfreq > 2000) - found_bg_band = TRUE; - continue; - } - - // FIXME: handle security settings here too - nm_log_dbg (LOGD_WIFI, " matched"); - active_ap = ap; - goto done; - } - } - - /* Some proprietary drivers (wl.o) report tuned frequency (like when - * scanning) instead of the associated AP's frequency. This is a great - * example of how WEXT is underspecified. We use frequency to find the - * active AP in the scan list because some configurations use the same - * SSID/BSSID on the 2GHz and 5GHz bands simultaneously, and we need to - * make sure we get the right AP in the right band. This configuration - * is uncommon though, and the frequency check penalizes closed drivers we - * can't fix. Because we're not total dicks, ignore the frequency condition - * if the associated BSSID/SSID exists only in one band since that's most - * likely the AP we want. Sometimes wl.o returns a frequency of 0, so if - * we can't match the AP based on frequency at all, just give up. - */ - if (match_nofreq && ((found_a_band != found_bg_band) || (devfreq == 0))) { - const struct ether_addr *ap_bssid = nm_ap_get_address (match_nofreq); - const GByteArray *ap_ssid = nm_ap_get_ssid (match_nofreq); - - nm_log_dbg (LOGD_WIFI, " matched %s%s%s %02x:%02x:%02x:%02x:%02x:%02x", - ap_ssid ? "'" : "", - ap_ssid ? nm_utils_escape_ssid (ap_ssid->data, ap_ssid->len) : "(none)", - ap_ssid ? "'" : "", - ap_bssid->ether_addr_octet[0], ap_bssid->ether_addr_octet[1], - ap_bssid->ether_addr_octet[2], ap_bssid->ether_addr_octet[3], - ap_bssid->ether_addr_octet[4], ap_bssid->ether_addr_octet[5]); - - active_ap = match_nofreq; - } - - nm_log_dbg (LOGD_WIFI, " No matching AP found."); - -done: - if (ssid) - g_byte_array_free (ssid, TRUE); - return active_ap; -} - -static void -update_seen_bssids_cache (NMDeviceWifi *self, NMAccessPoint *ap) -{ - NMActRequest *req; - NMConnection *connection; - - g_return_if_fail (NM_IS_DEVICE_WIFI (self)); - - if (ap == NULL) - return; - - /* Don't cache the BSSID for Ad-Hoc APs */ - if (nm_ap_get_mode (ap) != NM_802_11_MODE_INFRA) - return; - - if (nm_device_get_state (NM_DEVICE (self)) == NM_DEVICE_STATE_ACTIVATED) { - req = nm_device_get_act_request (NM_DEVICE (self)); - if (req) { - connection = nm_act_request_get_connection (req); - nm_settings_connection_add_seen_bssid (NM_SETTINGS_CONNECTION (connection), - nm_ap_get_address (ap)); - } - } -} - -static void -set_active_ap (NMDeviceWifi *self, NMAccessPoint *new_ap) -{ - NMDeviceWifiPrivate *priv; - char *old_path = NULL; - NMAccessPoint *old_ap; - - g_return_if_fail (NM_IS_DEVICE_WIFI (self)); - - priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - old_ap = priv->current_ap; - - if (old_ap) { - old_path = g_strdup (nm_ap_get_dbus_path (old_ap)); - priv->current_ap = NULL; - } - - if (new_ap) { - priv->current_ap = g_object_ref (new_ap); - - /* Move the current AP to the front of the scan list. Since we - * do a lot of searches looking for the current AP, it saves - * time to have it in front. - */ - priv->ap_list = g_slist_remove (priv->ap_list, new_ap); - priv->ap_list = g_slist_prepend (priv->ap_list, new_ap); - - /* Update seen BSSIDs cache */ - update_seen_bssids_cache (self, priv->current_ap); - } - - /* Unref old AP here to ensure object lives if new_ap == old_ap */ - if (old_ap) - g_object_unref (old_ap); - - /* Only notify if it's really changed */ - if ( (!old_path && new_ap) - || (old_path && !new_ap) - || (old_path && new_ap && strcmp (old_path, nm_ap_get_dbus_path (new_ap)))) - g_object_notify (G_OBJECT (self), NM_DEVICE_WIFI_ACTIVE_ACCESS_POINT); - - g_free (old_path); -} - -/* Called both as a GSourceFunc and standalone */ -static gboolean -periodic_update (gpointer user_data) -{ - NMDeviceWifi *self = NM_DEVICE_WIFI (user_data); - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - NMAccessPoint *new_ap; - guint32 new_rate, percent; - NMDeviceState state; - guint32 supplicant_state; - - /* BSSID and signal strength have meaningful values only if the device - * is activated and not scanning. - */ - state = nm_device_get_state (NM_DEVICE (self)); - if (state != NM_DEVICE_STATE_ACTIVATED) - return TRUE; - - /* Only update current AP if we're actually talking to something, otherwise - * assume the old one (if any) is still valid until we're told otherwise or - * the connection fails. - */ - supplicant_state = nm_supplicant_interface_get_state (priv->supplicant.iface); - if ( supplicant_state < NM_SUPPLICANT_INTERFACE_STATE_AUTHENTICATING - || supplicant_state > NM_SUPPLICANT_INTERFACE_STATE_COMPLETED - || nm_supplicant_interface_get_scanning (priv->supplicant.iface)) - return TRUE; - - /* In AP mode we currently have nothing to do. */ - if (priv->mode == NM_802_11_MODE_AP) - return TRUE; - - /* In IBSS mode, most newer firmware/drivers do "BSS coalescing" where - * multiple IBSS stations using the same SSID will eventually switch to - * using the same BSSID to avoid network segmentation. When this happens, - * the card's reported BSSID will change, but the the new BSS may not - * be in the scan list, since scanning isn't done in ad-hoc mode for - * various reasons. So pull the BSSID from the card and update the - * current AP with it, if the current AP is adhoc. - */ - if (priv->current_ap && (nm_ap_get_mode (priv->current_ap) == NM_802_11_MODE_ADHOC)) { - struct ether_addr bssid = { {0x0, 0x0, 0x0, 0x0, 0x0, 0x0} }; - - wifi_utils_get_bssid (priv->wifi_data, &bssid); - /* 0x02 means "locally administered" and should be OR-ed into - * the first byte of IBSS BSSIDs. - */ - if ( (bssid.ether_addr_octet[0] & 0x02) - && nm_ethernet_address_is_valid (&bssid)) - nm_ap_set_address (priv->current_ap, &bssid); - } - - new_ap = get_active_ap (self, NULL, FALSE); - if (new_ap) { - /* Try to smooth out the strength. Atmel cards, for example, will give no strength - * one second and normal strength the next. - */ - percent = wifi_utils_get_qual (priv->wifi_data); - if (percent >= 0 || ++priv->invalid_strength_counter > 3) { - nm_ap_set_strength (new_ap, (gint8) percent); - priv->invalid_strength_counter = 0; - } - } - - if ((new_ap || priv->current_ap) && (new_ap != priv->current_ap)) { - const struct ether_addr *new_bssid = NULL; - const GByteArray *new_ssid = NULL; - const struct ether_addr *old_bssid = NULL; - const GByteArray *old_ssid = NULL; - char *old_addr = NULL, *new_addr = NULL; - - if (new_ap) { - new_bssid = nm_ap_get_address (new_ap); - new_addr = nm_utils_hwaddr_ntoa (new_bssid, ARPHRD_ETHER); - new_ssid = nm_ap_get_ssid (new_ap); - } - - if (priv->current_ap) { - old_bssid = nm_ap_get_address (priv->current_ap); - old_addr = nm_utils_hwaddr_ntoa (old_bssid, ARPHRD_ETHER); - old_ssid = nm_ap_get_ssid (priv->current_ap); - } - - nm_log_info (LOGD_WIFI, "(%s): roamed from BSSID %s (%s) to %s (%s)", - nm_device_get_iface (NM_DEVICE (self)), - old_addr ? old_addr : "(none)", - old_ssid ? nm_utils_escape_ssid (old_ssid->data, old_ssid->len) : "(none)", - new_addr ? new_addr : "(none)", - new_ssid ? nm_utils_escape_ssid (new_ssid->data, new_ssid->len) : "(none)"); - g_free (old_addr); - g_free (new_addr); - - set_active_ap (self, new_ap); - } - - new_rate = wifi_utils_get_rate (priv->wifi_data); - if (new_rate != priv->rate) { - priv->rate = new_rate; - g_object_notify (G_OBJECT (self), NM_DEVICE_WIFI_BITRATE); - } - - return TRUE; -} - -static gboolean -hw_bring_up (NMDevice *device, gboolean *no_firmware) -{ - if (!NM_DEVICE_WIFI_GET_PRIVATE (device)->enabled) - return FALSE; - - return NM_DEVICE_CLASS (nm_device_wifi_parent_class)->hw_bring_up (device, no_firmware); -} - -static gboolean -is_up (NMDevice *device) -{ - if (!NM_DEVICE_WIFI_GET_PRIVATE (device)->periodic_source_id) - return FALSE; - - return TRUE; -} - -static gboolean -bring_up (NMDevice *dev) -{ - NMDeviceWifi *self = NM_DEVICE_WIFI (dev); - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - - priv->periodic_source_id = g_timeout_add_seconds (6, periodic_update, self); - return TRUE; -} - -static gboolean -_set_hw_addr (NMDeviceWifi *self, const guint8 *addr, const char *detail) -{ - NMDevice *dev = NM_DEVICE (self); - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - const char *iface; - char *mac_str = NULL; - gboolean success = FALSE; - - g_return_val_if_fail (addr != NULL, FALSE); - - iface = nm_device_get_iface (dev); - - mac_str = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X", - addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); - - /* Do nothing if current MAC is same */ - if (!memcmp (&priv->hw_addr, addr, ETH_ALEN)) { - nm_log_dbg (LOGD_DEVICE | LOGD_ETHER, "(%s): no MAC address change needed", iface); - g_free (mac_str); - return TRUE; - } - - /* Can't change MAC address while device is up */ - nm_device_hw_take_down (dev, FALSE); - - success = nm_system_iface_set_mac (nm_device_get_ip_ifindex (dev), (struct ether_addr *) addr); - if (success) { - /* MAC address succesfully changed; update the current MAC to match */ - update_hw_address (dev); - nm_log_info (LOGD_DEVICE | LOGD_ETHER, "(%s): %s MAC address to %s", - iface, detail, mac_str); - } else { - nm_log_warn (LOGD_DEVICE | LOGD_ETHER, "(%s): failed to %s MAC address to %s", - iface, detail, mac_str); - } - hw_bring_up (dev, NULL); - g_free (mac_str); - - return success; -} - -static void -remove_access_point (NMDeviceWifi *device, NMAccessPoint *ap) -{ - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (device); - - g_signal_emit (device, signals[ACCESS_POINT_REMOVED], 0, ap); - priv->ap_list = g_slist_remove (priv->ap_list, ap); - g_object_unref (ap); - - nm_device_recheck_available_connections (NM_DEVICE (device)); -} - -static void -remove_all_aps (NMDeviceWifi *self) -{ - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - - /* Remove outdated APs */ - while (g_slist_length (priv->ap_list)) { - NMAccessPoint *ap = NM_AP (priv->ap_list->data); - remove_access_point (self, ap); - } - g_slist_free (priv->ap_list); - priv->ap_list = NULL; -} - -static void -take_down (NMDevice *dev) -{ - NMDeviceWifi *self = NM_DEVICE_WIFI (dev); - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - - if (priv->periodic_source_id) { - g_source_remove (priv->periodic_source_id); - priv->periodic_source_id = 0; - } - - cleanup_association_attempt (self, TRUE); - set_active_ap (self, NULL); - remove_all_aps (self); -} - -static void -deactivate (NMDevice *dev) -{ - NMDeviceWifi *self = NM_DEVICE_WIFI (dev); - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - NMAccessPoint *orig_ap = nm_device_wifi_get_activation_ap (self); - NMActRequest *req; - NMConnection *connection; - NM80211Mode old_mode = priv->mode; - - req = nm_device_get_act_request (dev); - if (req) { - connection = nm_act_request_get_connection (req); - /* Clear wireless secrets tries when deactivating */ - g_object_set_data (G_OBJECT (connection), WIRELESS_SECRETS_TRIES, NULL); - } - - cleanup_association_attempt (self, TRUE); - - set_active_ap (self, NULL); - priv->rate = 0; - - /* If the AP is 'fake', i.e. it wasn't actually found from - * a scan but the user tried to connect to it manually (maybe it - * was non-broadcasting or something) get rid of it, because 'fake' - * APs should only live for as long as we're connected to them. Fixes - * a bug where user-created Ad-Hoc APs are never removed from the scan - * list, because scanning is disabled while in Ad-Hoc mode (for stability), - * and thus the AP culling never happens. (bgo #569241) - */ - if (orig_ap && nm_ap_get_fake (orig_ap)) { - remove_access_point (self, orig_ap); - } - - /* Reset MAC address back to initial address */ - _set_hw_addr (self, priv->initial_hw_addr, "reset"); - - /* Ensure we're in infrastructure mode after deactivation; some devices - * (usually older ones) don't scan well in adhoc mode. - */ - if (wifi_utils_get_mode (priv->wifi_data) != NM_802_11_MODE_INFRA) { - nm_device_hw_take_down (NM_DEVICE (self), TRUE); - wifi_utils_set_mode (priv->wifi_data, NM_802_11_MODE_INFRA); - nm_device_hw_bring_up (NM_DEVICE (self), TRUE, NULL); - } - - if (priv->mode != NM_802_11_MODE_INFRA) { - priv->mode = NM_802_11_MODE_INFRA; - g_object_notify (G_OBJECT (self), NM_DEVICE_WIFI_MODE); - } - - /* Ensure we trigger a scan after deactivating a Hotspot */ - if (old_mode == NM_802_11_MODE_AP) { - cancel_pending_scan (self); - request_wireless_scan (self); - } -} - -static gboolean -is_adhoc_wpa (NMConnection *connection) -{ - NMSettingWireless *s_wifi; - NMSettingWirelessSecurity *s_wsec; - const char *mode, *key_mgmt; - - /* The kernel doesn't support Ad-Hoc WPA connections well at this time, - * and turns them into open networks. It's been this way since at least - * 2.6.30 or so; until that's fixed, disable WPA-protected Ad-Hoc networks. - */ - - s_wifi = nm_connection_get_setting_wireless (connection); - g_return_val_if_fail (s_wifi != NULL, FALSE); - - mode = nm_setting_wireless_get_mode (s_wifi); - if (g_strcmp0 (mode, NM_SETTING_WIRELESS_MODE_ADHOC) != 0) - return FALSE; - - s_wsec = nm_connection_get_setting_wireless_security (connection); - if (!s_wsec) - return FALSE; - - key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wsec); - if (g_strcmp0 (key_mgmt, "wpa-none") != 0) - return FALSE; - - return TRUE; -} - -static gboolean -check_connection_compatible (NMDevice *device, - NMConnection *connection, - GError **error) -{ - NMDeviceWifi *self = NM_DEVICE_WIFI (device); - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - NMSettingConnection *s_con; - NMSettingWireless *s_wireless; - const GByteArray *mac; - const GSList *mac_blacklist, *mac_blacklist_iter; - const char *mode; - - s_con = nm_connection_get_setting_connection (connection); - g_assert (s_con); - - if (strcmp (nm_setting_connection_get_connection_type (s_con), NM_SETTING_WIRELESS_SETTING_NAME)) { - g_set_error (error, - NM_WIFI_ERROR, NM_WIFI_ERROR_CONNECTION_NOT_WIRELESS, - "The connection was not a WiFi connection."); - return FALSE; - } - - s_wireless = nm_connection_get_setting_wireless (connection); - if (!s_wireless) { - g_set_error (error, - NM_WIFI_ERROR, NM_WIFI_ERROR_CONNECTION_INVALID, - "The connection was not a valid WiFi connection."); - return FALSE; - } - - - mac = nm_setting_wireless_get_mac_address (s_wireless); - if (mac && memcmp (mac->data, &priv->perm_hw_addr, ETH_ALEN)) { - g_set_error (error, - NM_WIFI_ERROR, NM_WIFI_ERROR_CONNECTION_INCOMPATIBLE, - "The connection's MAC address did not match this device."); - return FALSE; - } - - /* Check for MAC address blacklist */ - mac_blacklist = nm_setting_wireless_get_mac_address_blacklist (s_wireless); - for (mac_blacklist_iter = mac_blacklist; mac_blacklist_iter; - mac_blacklist_iter = g_slist_next (mac_blacklist_iter)) { - struct ether_addr addr; - - if (!ether_aton_r (mac_blacklist_iter->data, &addr)) { - g_warn_if_reached (); - continue; - } - if (memcmp (&addr, &priv->perm_hw_addr, ETH_ALEN) == 0) { - g_set_error (error, - NM_WIFI_ERROR, NM_WIFI_ERROR_CONNECTION_INCOMPATIBLE, - "The connection's MAC address (%s) is blacklisted in %s.", - (char *) mac_blacklist_iter->data, NM_SETTING_WIRELESS_MAC_ADDRESS_BLACKLIST); - return FALSE; - } - } - - if (is_adhoc_wpa (connection)) { - g_set_error_literal (error, - NM_WIFI_ERROR, - NM_WIFI_ERROR_CONNECTION_INCOMPATIBLE, - "WPA Ad-Hoc disabled due to kernel bugs"); - return FALSE; - } - - /* Early exit if supplicant or device doesn't support requested mode */ - mode = nm_setting_wireless_get_mode (s_wireless); - if (g_strcmp0 (mode, NM_SETTING_WIRELESS_MODE_ADHOC) == 0) { - if (!(priv->capabilities & NM_WIFI_DEVICE_CAP_ADHOC)) { - g_set_error_literal (error, - NM_WIFI_ERROR, - NM_WIFI_ERROR_ADHOC_MODE_UNSUPPORTED, - "Ad-Hoc mode is not supported by this device."); - return FALSE; - } - } else if (g_strcmp0 (mode, NM_SETTING_WIRELESS_MODE_AP) == 0) { - if (!(priv->capabilities & NM_WIFI_DEVICE_CAP_AP)) { - g_set_error_literal (error, - NM_WIFI_ERROR, - NM_WIFI_ERROR_AP_MODE_UNSUPPORTED, - "Access Point (AP) mode is not supported by this device."); - return FALSE; - } - - if (priv->supplicant.iface) { - switch (nm_supplicant_interface_get_ap_support (priv->supplicant.iface)) { - case AP_SUPPORT_NO: - g_set_error_literal (error, - NM_WIFI_ERROR, - NM_WIFI_ERROR_AP_MODE_UNSUPPORTED, - "Access Point (AP) mode is not supported by the supplicant."); - return FALSE; - case AP_SUPPORT_YES: - case AP_SUPPORT_UNKNOWN: - default: - break; - } - } - } - - // FIXME: check channel/freq/band against bands the hardware supports - // FIXME: check encryption against device capabilities - // FIXME: check bitrate against device capabilities - - return TRUE; -} - - -static gboolean -check_connection_available (NMDevice *device, NMConnection *connection) -{ - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (device); - NMSettingWireless *s_wifi; - const char *mode; - GSList *ap_iter = NULL; - - s_wifi = nm_connection_get_setting_wireless (connection); - - /* Ad-Hoc and AP connections are always available because they may be - * started at any time. - */ - mode = nm_setting_wireless_get_mode (s_wifi); - if (g_strcmp0 (mode, "adhoc") == 0 || g_strcmp0 (mode, "ap") == 0) - return TRUE; - - /* Hidden SSIDs obviously don't always appear in the scan list either */ - if (nm_setting_wireless_get_hidden (s_wifi)) - return TRUE; - - /* check if its visible */ - for (ap_iter = priv->ap_list; ap_iter; ap_iter = g_slist_next (ap_iter)) { - if (nm_ap_check_compatible (NM_AP (ap_iter->data), connection)) - return TRUE; - } - - return FALSE; -} - -/* - * List of manufacturer default SSIDs that are often unchanged by users. - * - * NOTE: this list should *not* contain networks that you would like to - * automatically roam to like "Starbucks" or "AT&T" or "T-Mobile HotSpot". - */ -static const char * -manf_defaults[] = { - "linksys", - "linksys-a", - "linksys-g", - "default", - "belkin54g", - "NETGEAR", - "o2DSL", - "WLAN", - "ALICE-WLAN", - "Speedport W 501V", -}; - -#define ARRAY_SIZE(a) (sizeof (a) / sizeof (a[0])) - -static gboolean -is_manf_default_ssid (const GByteArray *ssid) -{ - int i; - - for (i = 0; i < ARRAY_SIZE (manf_defaults); i++) { - if (ssid->len == strlen (manf_defaults[i])) { - if (memcmp (manf_defaults[i], ssid->data, ssid->len) == 0) - return TRUE; - } - } - return FALSE; -} - -static gboolean -complete_connection (NMDevice *device, - NMConnection *connection, - const char *specific_object, - const GSList *existing_connections, - GError **error) -{ - NMDeviceWifi *self = NM_DEVICE_WIFI (device); - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - NMSettingWireless *s_wifi; - NMSettingWirelessSecurity *s_wsec; - NMSetting8021x *s_8021x; - const GByteArray *setting_mac; - char *format, *str_ssid = NULL; - NMAccessPoint *ap = NULL; - const GByteArray *ssid = NULL; - GSList *iter; - - s_wifi = nm_connection_get_setting_wireless (connection); - s_wsec = nm_connection_get_setting_wireless_security (connection); - s_8021x = nm_connection_get_setting_802_1x (connection); - - if (!specific_object) { - /* If not given a specific object, we need at minimum an SSID */ - if (!s_wifi) { - g_set_error_literal (error, - NM_WIFI_ERROR, - NM_WIFI_ERROR_CONNECTION_INVALID, - "A 'wireless' setting is required if no AP path was given."); - return FALSE; - } - - ssid = nm_setting_wireless_get_ssid (s_wifi); - if (!ssid || !ssid->len) { - g_set_error_literal (error, - NM_WIFI_ERROR, - NM_WIFI_ERROR_CONNECTION_INVALID, - "A 'wireless' setting with a valid SSID is required if no AP path was given."); - return FALSE; - } - - /* Find a compatible AP in the scan list */ - for (iter = priv->ap_list; iter; iter = g_slist_next (iter)) { - if (nm_ap_check_compatible (NM_AP (iter->data), connection)) { - ap = NM_AP (iter->data); - break; - } - } - - /* If we still don't have an AP, then the WiFI settings needs to be - * fully specified by the client. Might not be able to find an AP - * if the network isn't broadcasting the SSID for example. - */ - if (!ap) { - GSList *settings = NULL; - gboolean valid; - - settings = g_slist_prepend (settings, s_wifi); - if (s_wsec) - settings = g_slist_prepend (settings, s_wsec); - if (s_8021x) - settings = g_slist_prepend (settings, s_8021x); - valid = nm_setting_verify (NM_SETTING (s_wifi), settings, error); - g_slist_free (settings); - if (!valid) - return FALSE; - } - } else { - ap = get_ap_by_path (self, specific_object); - if (!ap) { - g_set_error (error, - NM_WIFI_ERROR, - NM_WIFI_ERROR_ACCESS_POINT_NOT_FOUND, - "The access point %s was not in the scan list.", - specific_object); - return FALSE; - } - } - - /* Add a wifi setting if one doesn't exist yet */ - if (!s_wifi) { - s_wifi = (NMSettingWireless *) nm_setting_wireless_new (); - nm_connection_add_setting (connection, NM_SETTING (s_wifi)); - } - - if (ap) { - ssid = nm_ap_get_ssid (ap); - - if (ssid == NULL) { - /* The AP must be hidden. Connecting to a WiFi AP requires the SSID - * as part of the initial handshake, so check the connection details - * for the SSID. The AP object will still be used for encryption - * settings and such. - */ - ssid = nm_setting_wireless_get_ssid (s_wifi); - } - - if (ssid == NULL) { - /* If there's no SSID on the AP itself, and no SSID in the - * connection data, then we cannot connect at all. Return an error. - */ - g_set_error_literal (error, - NM_WIFI_ERROR, - NM_WIFI_ERROR_CONNECTION_INVALID, - "A 'wireless' setting with a valid SSID is required for hidden access points."); - return FALSE; - } - - /* If the SSID is a well-known SSID, lock the connection to the AP's - * specific BSSID so NM doesn't autoconnect to some random wifi net. - */ - if (!nm_ap_complete_connection (ap, - connection, - is_manf_default_ssid (ssid), - error)) - return FALSE; - } - - /* The kernel doesn't support Ad-Hoc WPA connections well at this time, - * and turns them into open networks. It's been this way since at least - * 2.6.30 or so; until that's fixed, disable WPA-protected Ad-Hoc networks. - */ - if (is_adhoc_wpa (connection)) { - g_set_error_literal (error, - NM_SETTING_WIRELESS_ERROR, - NM_SETTING_WIRELESS_ERROR_INVALID_PROPERTY, - "WPA Ad-Hoc disabled due to kernel bugs"); - return FALSE; - } - - g_assert (ssid); - str_ssid = nm_utils_ssid_to_utf8 (ssid); - format = g_strdup_printf ("%s %%d", str_ssid); - - nm_utils_complete_generic (connection, - NM_SETTING_WIRELESS_SETTING_NAME, - existing_connections, - format, - str_ssid, - TRUE); - g_free (str_ssid); - g_free (format); - - setting_mac = nm_setting_wireless_get_mac_address (s_wifi); - if (setting_mac) { - /* Make sure the setting MAC (if any) matches the device's permanent MAC */ - if (memcmp (setting_mac->data, priv->perm_hw_addr, ETH_ALEN)) { - g_set_error (error, - NM_SETTING_WIRELESS_ERROR, - NM_SETTING_WIRELESS_ERROR_INVALID_PROPERTY, - NM_SETTING_WIRELESS_MAC_ADDRESS); - return FALSE; - } - } else { - GByteArray *mac; - const guint8 null_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; - - /* Lock the connection to this device by default if it uses a - * permanent MAC address (ie not a 'locally administered' one) - */ - if ( !(priv->perm_hw_addr[0] & 0x02) - && memcmp (priv->perm_hw_addr, null_mac, ETH_ALEN)) { - mac = g_byte_array_sized_new (ETH_ALEN); - g_byte_array_append (mac, priv->perm_hw_addr, ETH_ALEN); - g_object_set (G_OBJECT (s_wifi), NM_SETTING_WIRELESS_MAC_ADDRESS, mac, NULL); - g_byte_array_free (mac, TRUE); - } - } - - return TRUE; -} - -static gboolean -is_available (NMDevice *dev) -{ - NMDeviceWifi *self = NM_DEVICE_WIFI (dev); - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - NMSupplicantInterface *sup_iface; - guint32 state; - - if (!priv->enabled) { - nm_log_dbg (LOGD_WIFI, "(%s): not available because not enabled", - nm_device_get_iface (dev)); - return FALSE; - } - - sup_iface = priv->supplicant.iface; - if (!sup_iface) { - nm_log_dbg (LOGD_WIFI, "(%s): not available because supplicant not running", - nm_device_get_iface (dev)); - return FALSE; - } - - state = nm_supplicant_interface_get_state (sup_iface); - if ( state < NM_SUPPLICANT_INTERFACE_STATE_READY - || state > NM_SUPPLICANT_INTERFACE_STATE_COMPLETED) { - nm_log_dbg (LOGD_WIFI, "(%s): not available because supplicant interface not ready", - nm_device_get_iface (dev)); - return FALSE; - } - - return TRUE; -} - -static NMConnection * -get_best_auto_connection (NMDevice *dev, - GSList *connections, - char **specific_object) -{ - NMDeviceWifi *self = NM_DEVICE_WIFI (dev); - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - GSList *iter, *ap_iter; - - for (iter = connections; iter; iter = g_slist_next (iter)) { - NMConnection *connection = NM_CONNECTION (iter->data); - NMSettingWireless *s_wireless; - const GByteArray *mac; - const GSList *mac_blacklist, *mac_blacklist_iter; - gboolean mac_blacklist_found = FALSE; - NMSettingIP4Config *s_ip4; - const char *method = NULL; - guint64 timestamp = 0; - - if (!nm_connection_is_type (connection, NM_SETTING_WIRELESS_SETTING_NAME)) - continue; - - /* Don't autoconnect to networks that have been tried at least once - * but haven't been successful, since these are often accidental choices - * from the menu and the user may not know the password. - */ - if (nm_settings_connection_get_timestamp (NM_SETTINGS_CONNECTION (connection), ×tamp)) { - if (timestamp == 0) - continue; - } - - s_wireless = nm_connection_get_setting_wireless (connection); - if (!s_wireless) - continue; - - mac = nm_setting_wireless_get_mac_address (s_wireless); - if (mac && memcmp (mac->data, &priv->perm_hw_addr, ETH_ALEN)) - continue; - - /* Check for MAC address blacklist */ - mac_blacklist = nm_setting_wireless_get_mac_address_blacklist (s_wireless); - for (mac_blacklist_iter = mac_blacklist; mac_blacklist_iter; - mac_blacklist_iter = g_slist_next (mac_blacklist_iter)) { - struct ether_addr addr; - - if (!ether_aton_r (mac_blacklist_iter->data, &addr)) { - g_warn_if_reached (); - continue; - } - if (memcmp (&addr, &priv->perm_hw_addr, ETH_ALEN) == 0) { - mac_blacklist_found = TRUE; - break; - } - } - /* Found device MAC address in the blacklist - do not use this connection */ - if (mac_blacklist_found) - continue; - - /* Use the connection if it's a shared connection */ - s_ip4 = nm_connection_get_setting_ip4_config (connection); - if (s_ip4) - method = nm_setting_ip4_config_get_method (s_ip4); - - if (s_ip4 && !strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_SHARED)) - return connection; - - for (ap_iter = priv->ap_list; ap_iter; ap_iter = g_slist_next (ap_iter)) { - NMAccessPoint *ap = NM_AP (ap_iter->data); - - if (nm_ap_check_compatible (ap, connection)) { - /* All good; connection is usable */ - *specific_object = (char *) nm_ap_get_dbus_path (ap); - return connection; - } - } - } - return NULL; -} - -static void -ap_list_dump (NMDeviceWifi *self) -{ - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - GSList * elt; - int i = 0; - - g_return_if_fail (NM_IS_DEVICE_WIFI (self)); - - nm_log_dbg (LOGD_WIFI_SCAN, "Current AP list:"); - for (elt = priv->ap_list; elt; elt = g_slist_next (elt), i++) { - NMAccessPoint * ap = NM_AP (elt->data); - nm_ap_dump (ap, "List AP: "); - } - nm_log_dbg (LOGD_WIFI_SCAN, "Current AP list: done"); -} - -static gboolean -impl_device_get_access_points (NMDeviceWifi *self, - GPtrArray **aps, - GError **err) -{ - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - GSList *elt; - - *aps = g_ptr_array_new (); - - for (elt = priv->ap_list; elt; elt = g_slist_next (elt)) { - NMAccessPoint * ap = NM_AP (elt->data); - - if (nm_ap_get_ssid (ap)) - g_ptr_array_add (*aps, g_strdup (nm_ap_get_dbus_path (ap))); - } - return TRUE; -} - -static void -request_scan_cb (NMDevice *device, - DBusGMethodInvocation *context, - GError *error, - gpointer user_data) -{ - NMDeviceWifi *self = NM_DEVICE_WIFI (device); - - if (error) { - dbus_g_method_return_error (context, error); - g_clear_error (&error); - } else if (!check_scanning_allowed (self)) { - error = g_error_new_literal (NM_WIFI_ERROR, - NM_WIFI_ERROR_SCAN_NOT_ALLOWED, - "Scanning not allowed at this time"); - dbus_g_method_return_error (context, error); - g_error_free (error); - } else { - cancel_pending_scan (self); - request_wireless_scan (self); - dbus_g_method_return (context); - } -} - -static void -impl_device_request_scan (NMDeviceWifi *self, - GHashTable *options, - DBusGMethodInvocation *context) -{ - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - NMDevice *device = NM_DEVICE (self); - time_t last_scan; - GError *error; - - if ( !priv->enabled - || !priv->supplicant.iface - || nm_device_get_state (device) < NM_DEVICE_STATE_DISCONNECTED - || nm_device_is_activating (device)) { - error = g_error_new_literal (NM_WIFI_ERROR, - NM_WIFI_ERROR_SCAN_NOT_ALLOWED, - "Scanning not allowed while unavailable or activating"); - goto error; - } - - if (nm_supplicant_interface_get_scanning (priv->supplicant.iface)) { - error = g_error_new_literal (NM_WIFI_ERROR, - NM_WIFI_ERROR_SCAN_NOT_ALLOWED, - "Scanning not allowed while already scanning"); - goto error; - } - - last_scan = nm_supplicant_interface_get_last_scan_time (priv->supplicant.iface); - if ((time (NULL) - last_scan) < 10) { - error = g_error_new_literal (NM_WIFI_ERROR, - NM_WIFI_ERROR_SCAN_NOT_ALLOWED, - "Scanning not allowed immediately following previous scan"); - goto error; - } - - /* Ask the manager to authenticate this request for us */ - g_signal_emit_by_name (device, - NM_DEVICE_AUTH_REQUEST, - context, - NM_AUTH_PERMISSION_NETWORK_CONTROL, - TRUE, - request_scan_cb, - NULL); - return; - -error: - dbus_g_method_return_error (context, error); - g_error_free (error); -} - -static gboolean -scanning_allowed (NMDeviceWifi *self) -{ - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - guint32 sup_state; - NMActRequest *req; - - g_return_val_if_fail (priv->supplicant.iface != NULL, FALSE); - - /* Scanning not done in AP mode */ - if (priv->mode == NM_802_11_MODE_AP) - return FALSE; - - switch (nm_device_get_state (NM_DEVICE (self))) { - case NM_DEVICE_STATE_UNKNOWN: - case NM_DEVICE_STATE_UNMANAGED: - case NM_DEVICE_STATE_UNAVAILABLE: - case NM_DEVICE_STATE_PREPARE: - case NM_DEVICE_STATE_CONFIG: - case NM_DEVICE_STATE_NEED_AUTH: - case NM_DEVICE_STATE_IP_CONFIG: - case NM_DEVICE_STATE_IP_CHECK: - case NM_DEVICE_STATE_SECONDARIES: - case NM_DEVICE_STATE_DEACTIVATING: - /* Don't scan when unusable or activating */ - return FALSE; - case NM_DEVICE_STATE_DISCONNECTED: - case NM_DEVICE_STATE_FAILED: - /* Can always scan when disconnected */ - return TRUE; - case NM_DEVICE_STATE_ACTIVATED: - /* Need to do further checks when activated */ - break; - } - - /* Don't scan if the supplicant is busy */ - sup_state = nm_supplicant_interface_get_state (priv->supplicant.iface); - if ( sup_state == NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATING - || sup_state == NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATED - || sup_state == NM_SUPPLICANT_INTERFACE_STATE_4WAY_HANDSHAKE - || sup_state == NM_SUPPLICANT_INTERFACE_STATE_GROUP_HANDSHAKE - || nm_supplicant_interface_get_scanning (priv->supplicant.iface)) - return FALSE; - - req = nm_device_get_act_request (NM_DEVICE (self)); - if (req) { - NMConnection *connection; - NMSettingIP4Config *s_ip4; - NMSettingWireless *s_wifi; - const char *ip4_method = NULL; - const GByteArray *bssid; - - /* Don't scan when a shared connection is active; it makes drivers mad */ - connection = nm_act_request_get_connection (req); - s_ip4 = nm_connection_get_setting_ip4_config (connection); - if (s_ip4) - ip4_method = nm_setting_ip4_config_get_method (s_ip4); - - if (s_ip4 && !strcmp (ip4_method, NM_SETTING_IP4_CONFIG_METHOD_SHARED)) - return FALSE; - - /* Don't scan when the connection is locked to a specifc AP, since - * intra-ESS roaming (which requires periodic scanning) isn't being - * used due to the specific AP lock. (bgo #513820) - */ - s_wifi = nm_connection_get_setting_wireless (connection); - g_assert (s_wifi); - bssid = nm_setting_wireless_get_bssid (s_wifi); - if (bssid && bssid->len == ETH_ALEN) - return FALSE; - } - - return TRUE; -} - -static gboolean -scanning_allowed_accumulator (GSignalInvocationHint *ihint, - GValue *return_accu, - const GValue *handler_return, - gpointer data) -{ - if (!g_value_get_boolean (handler_return)) - g_value_set_boolean (return_accu, FALSE); - return TRUE; -} - -static gboolean -check_scanning_allowed (NMDeviceWifi *self) -{ - GValue instance = { 0, }; - GValue retval = { 0, }; - - g_value_init (&instance, G_TYPE_OBJECT); - g_value_take_object (&instance, self); - - g_value_init (&retval, G_TYPE_BOOLEAN); - g_value_set_boolean (&retval, TRUE); - - /* Use g_signal_emitv() rather than g_signal_emit() to avoid the return - * value being changed if no handlers are connected */ - g_signal_emitv (&instance, signals[SCANNING_ALLOWED], 0, &retval); - - return g_value_get_boolean (&retval); -} - -static gboolean -hidden_filter_func (NMConnectionProvider *provider, - NMConnection *connection, - gpointer user_data) -{ - NMSettingWireless *s_wifi; - - s_wifi = (NMSettingWireless *) nm_connection_get_setting_wireless (connection); - return s_wifi ? nm_setting_wireless_get_hidden (s_wifi) : FALSE; -} - -static GPtrArray * -build_hidden_probe_list (NMDeviceWifi *self) -{ - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - guint max_scan_ssids = nm_supplicant_interface_get_max_scan_ssids (priv->supplicant.iface); - NMConnectionProvider *provider = nm_device_get_connection_provider (NM_DEVICE (self)); - GSList *connections, *iter; - GPtrArray *ssids = NULL; - static GByteArray *nullssid = NULL; - - /* Need at least two: wildcard SSID and one or more hidden SSIDs */ - if (max_scan_ssids < 2) - return NULL; - - /* Static wildcard SSID used for every scan */ - if (G_UNLIKELY (nullssid == NULL)) - nullssid = g_byte_array_new (); - - connections = nm_connection_provider_get_best_connections (provider, - max_scan_ssids - 1, - NM_SETTING_WIRELESS_SETTING_NAME, - NULL, - hidden_filter_func, - NULL); - if (connections && connections->data) { - ssids = g_ptr_array_sized_new (max_scan_ssids - 1); - g_ptr_array_add (ssids, nullssid); /* Add wildcard SSID */ - } - - for (iter = connections; iter; iter = g_slist_next (iter)) { - NMConnection *connection = iter->data; - NMSettingWireless *s_wifi; - const GByteArray *ssid; - - s_wifi = (NMSettingWireless *) nm_connection_get_setting_wireless (connection); - g_assert (s_wifi); - ssid = nm_setting_wireless_get_ssid (s_wifi); - g_assert (ssid); - g_ptr_array_add (ssids, (gpointer) ssid); - } - g_slist_free (connections); - - return ssids; -} - -static gboolean -request_wireless_scan (gpointer user_data) -{ - NMDeviceWifi *self = NM_DEVICE_WIFI (user_data); - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - gboolean backoff = FALSE; - GPtrArray *ssids = NULL; - - if (check_scanning_allowed (self)) { - nm_log_dbg (LOGD_WIFI_SCAN, "(%s): scanning requested", - nm_device_get_iface (NM_DEVICE (self))); - - ssids = build_hidden_probe_list (self); - - if (nm_logging_level_enabled (LOGL_DEBUG)) { - if (ssids) { - guint i; - char *foo; - - for (i = 0; i < ssids->len; i++) { - foo = nm_utils_ssid_to_utf8 (g_ptr_array_index (ssids, i)); - nm_log_dbg (LOGD_WIFI_SCAN, "(%s): (%d) probe scanning SSID '%s'", - nm_device_get_iface (NM_DEVICE (self)), - i, foo ? foo : ""); - g_free (foo); - } - } else { - nm_log_dbg (LOGD_WIFI_SCAN, "(%s): no SSIDs to probe scan", - nm_device_get_iface (NM_DEVICE (self))); - } - } - - if (nm_supplicant_interface_request_scan (priv->supplicant.iface, ssids)) { - /* success */ - backoff = TRUE; - } - - if (ssids) { - /* Elements owned by the connections, so we don't free them here */ - g_ptr_array_free (ssids, TRUE); - } - } else { - nm_log_dbg (LOGD_WIFI_SCAN, "(%s): scan requested but not allowed at this time", - nm_device_get_iface (NM_DEVICE (self))); - } - - priv->pending_scan_id = 0; - schedule_scan (self, backoff); - return FALSE; -} - - -/* - * schedule_scan - * - * Schedule a wireless scan. - * - */ -static void -schedule_scan (NMDeviceWifi *self, gboolean backoff) -{ - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - time_t now = time (NULL); - - /* Cancel the pending scan if it would happen later than (now + the scan_interval) */ - if (priv->pending_scan_id) { - if (now + priv->scan_interval < priv->scheduled_scan_time) - cancel_pending_scan (self); - } - - if (!priv->pending_scan_id) { - guint factor = 2, next_scan = priv->scan_interval; - - if ( nm_device_is_activating (NM_DEVICE (self)) - || (nm_device_get_state (NM_DEVICE (self)) == NM_DEVICE_STATE_ACTIVATED)) - factor = 1; - - priv->pending_scan_id = g_timeout_add_seconds (next_scan, - request_wireless_scan, - self); - - priv->scheduled_scan_time = now + priv->scan_interval; - if (backoff && (priv->scan_interval < (SCAN_INTERVAL_MAX / factor))) { - priv->scan_interval += (SCAN_INTERVAL_STEP / factor); - /* Ensure the scan interval will never be less than 20s... */ - priv->scan_interval = MAX(priv->scan_interval, SCAN_INTERVAL_MIN + SCAN_INTERVAL_STEP); - /* ... or more than 120s */ - priv->scan_interval = MIN(priv->scan_interval, SCAN_INTERVAL_MAX); - } else if (!backoff && (priv->scan_interval == 0)) { - /* Invalid combination; would cause continual rescheduling of - * the scan and hog CPU. Reset to something minimally sane. - */ - priv->scan_interval = 5; - } - - nm_log_dbg (LOGD_WIFI_SCAN, "(%s): scheduled scan in %d seconds (interval now %d seconds)", - nm_device_get_iface (NM_DEVICE (self)), - next_scan, - priv->scan_interval); - - } -} - - -static void -cancel_pending_scan (NMDeviceWifi *self) -{ - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - - if (priv->pending_scan_id) { - g_source_remove (priv->pending_scan_id); - priv->pending_scan_id = 0; - } -} - -static void -supplicant_iface_scan_done_cb (NMSupplicantInterface *iface, - gboolean success, - NMDeviceWifi *self) -{ - nm_log_dbg (LOGD_WIFI_SCAN, "(%s): scan %s", - nm_device_get_iface (NM_DEVICE (self)), - success ? "successful" : "failed"); - - schedule_scan (self, success); - - /* Ensure that old APs get removed, which otherwise only - * happens when there are new BSSes. - */ - schedule_scanlist_cull (self); -} - - -/**************************************************************************** - * WPA Supplicant control stuff - * - */ - -#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x" -#define MAC_ARG(x) ((guint8*)(x))[0],((guint8*)(x))[1],((guint8*)(x))[2],((guint8*)(x))[3],((guint8*)(x))[4],((guint8*)(x))[5] - -/* - * merge_scanned_ap - * - * If there is already an entry that matches the BSSID and ESSID of the - * AP to merge, replace that entry with the scanned AP. Otherwise, add - * the scanned AP to the list. - * - * TODO: possibly need to differentiate entries based on security too; i.e. if - * there are two scan results with the same BSSID and SSID but different - * security options? - * - */ -static void -merge_scanned_ap (NMDeviceWifi *self, - NMAccessPoint *merge_ap) -{ - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - NMAccessPoint *found_ap = NULL; - const GByteArray *ssid; - const struct ether_addr *bssid; - gboolean strict_match = TRUE; - NMAccessPoint *current_ap = NULL; - - /* Let the manager try to fill in the SSID from seen-bssids lists */ - bssid = nm_ap_get_address (merge_ap); - ssid = nm_ap_get_ssid (merge_ap); - if (!ssid || nm_utils_is_empty_ssid (ssid->data, ssid->len)) { - /* Let the manager try to fill the AP's SSID from the database */ - g_signal_emit (self, signals[HIDDEN_AP_FOUND], 0, merge_ap); - - ssid = nm_ap_get_ssid (merge_ap); - if (ssid && (nm_utils_is_empty_ssid (ssid->data, ssid->len) == FALSE)) { - /* Yay, matched it, no longer treat as hidden */ - nm_log_dbg (LOGD_WIFI_SCAN, "(%s): matched hidden AP " MAC_FMT " => '%s'", - nm_device_get_iface (NM_DEVICE (self)), - MAC_ARG (bssid->ether_addr_octet), - nm_utils_escape_ssid (ssid->data, ssid->len)); - nm_ap_set_broadcast (merge_ap, FALSE); - } else { - /* Didn't have an entry for this AP in the database */ - nm_log_dbg (LOGD_WIFI_SCAN, "(%s): failed to match hidden AP " MAC_FMT, - nm_device_get_iface (NM_DEVICE (self)), - MAC_ARG (bssid->ether_addr_octet)); - } - } - - /* If the incoming scan result matches the hidden AP that NM is currently - * connected to but hasn't been seen in the scan list yet, don't use - * strict matching. Because the capabilities of the fake AP have to be - * constructed from the NMConnection of the activation request, they won't - * always be the same as the capabilities of the real AP from the scan. - */ - current_ap = nm_device_wifi_get_activation_ap (self); - if (current_ap && nm_ap_get_fake (current_ap)) - strict_match = FALSE; - - found_ap = get_ap_by_supplicant_path (self, nm_ap_get_supplicant_path (merge_ap)); - if (!found_ap) - found_ap = nm_ap_match_in_list (merge_ap, priv->ap_list, strict_match); - if (found_ap) { - nm_log_dbg (LOGD_WIFI_SCAN, "(%s): merging AP '%s' " MAC_FMT " (%p) with existing (%p)", - nm_device_get_iface (NM_DEVICE (self)), - ssid ? nm_utils_escape_ssid (ssid->data, ssid->len) : "(none)", - MAC_ARG (bssid->ether_addr_octet), - merge_ap, - found_ap); - - nm_ap_set_supplicant_path (found_ap, nm_ap_get_supplicant_path (merge_ap)); - nm_ap_set_flags (found_ap, nm_ap_get_flags (merge_ap)); - nm_ap_set_wpa_flags (found_ap, nm_ap_get_wpa_flags (merge_ap)); - nm_ap_set_rsn_flags (found_ap, nm_ap_get_rsn_flags (merge_ap)); - nm_ap_set_strength (found_ap, nm_ap_get_strength (merge_ap)); - nm_ap_set_last_seen (found_ap, nm_ap_get_last_seen (merge_ap)); - nm_ap_set_broadcast (found_ap, nm_ap_get_broadcast (merge_ap)); - nm_ap_set_freq (found_ap, nm_ap_get_freq (merge_ap)); - nm_ap_set_max_bitrate (found_ap, nm_ap_get_max_bitrate (merge_ap)); - - /* If the AP is noticed in a scan, it's automatically no longer - * fake, since it clearly exists somewhere. - */ - nm_ap_set_fake (found_ap, FALSE); - } else { - /* New entry in the list */ - nm_log_dbg (LOGD_WIFI_SCAN, "(%s): adding new AP '%s' " MAC_FMT " (%p)", - nm_device_get_iface (NM_DEVICE (self)), - ssid ? nm_utils_escape_ssid (ssid->data, ssid->len) : "(none)", - MAC_ARG (bssid->ether_addr_octet), - merge_ap); - - g_object_ref (merge_ap); - priv->ap_list = g_slist_prepend (priv->ap_list, merge_ap); - nm_ap_export_to_dbus (merge_ap); - g_signal_emit (self, signals[ACCESS_POINT_ADDED], 0, merge_ap); - nm_device_recheck_available_connections (NM_DEVICE (self)); - } -} - -#define WPAS_REMOVED_TAG "supplicant-removed" - -static gboolean -cull_scan_list (NMDeviceWifi *self) -{ - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - time_t now = time (NULL); - GSList *outdated_list = NULL; - GSList *elt; - guint32 removed = 0, total = 0; - - priv->scanlist_cull_id = 0; - - nm_log_dbg (LOGD_WIFI_SCAN, "(%s): checking scan list for outdated APs", - nm_device_get_iface (NM_DEVICE (self))); - - /* Walk the access point list and remove any access points older than - * three times the inactive scan interval. - */ - for (elt = priv->ap_list; elt; elt = g_slist_next (elt), total++) { - NMAccessPoint *ap = elt->data; - const guint prune_interval_s = SCAN_INTERVAL_MAX * 3; - - /* Don't cull the associated AP or manually created APs */ - if (ap == priv->current_ap || nm_ap_get_fake (ap)) - continue; - - /* Don't cull APs still known to the supplicant. Since the supplicant - * doesn't yet emit property updates for "last seen" we have to rely - * on changing signal strength for updating "last seen". But if the - * AP's strength doesn't change we won't get any updates for the AP, - * and we'll end up here even if the AP was still found by the - * supplicant in the last scan. - */ - if ( nm_ap_get_supplicant_path (ap) - && g_object_get_data (G_OBJECT (ap), WPAS_REMOVED_TAG) == NULL) - continue; - - if (nm_ap_get_last_seen (ap) + prune_interval_s < now) - outdated_list = g_slist_append (outdated_list, ap); - } - - /* Remove outdated APs */ - for (elt = outdated_list; elt; elt = g_slist_next (elt)) { - NMAccessPoint *outdated_ap = NM_AP (elt->data); - const struct ether_addr *bssid; - const GByteArray *ssid; - - bssid = nm_ap_get_address (outdated_ap); - ssid = nm_ap_get_ssid (outdated_ap); - nm_log_dbg (LOGD_WIFI_SCAN, - " removing %02x:%02x:%02x:%02x:%02x:%02x (%s%s%s)", - bssid->ether_addr_octet[0], bssid->ether_addr_octet[1], - bssid->ether_addr_octet[2], bssid->ether_addr_octet[3], - bssid->ether_addr_octet[4], bssid->ether_addr_octet[5], - ssid ? "'" : "", - ssid ? nm_utils_escape_ssid (ssid->data, ssid->len) : "(none)", - ssid ? "'" : ""); - - remove_access_point (self, outdated_ap); - removed++; - } - g_slist_free (outdated_list); - - nm_log_dbg (LOGD_WIFI_SCAN, "(%s): removed %d APs (of %d)", - nm_device_get_iface (NM_DEVICE (self)), - removed, total); - - ap_list_dump (self); - - if(removed > 0) - nm_device_recheck_available_connections (NM_DEVICE (self)); - - return FALSE; -} - -static void -schedule_scanlist_cull (NMDeviceWifi *self) -{ - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - - /* Cull the scan list after the last request for it has come in */ - if (priv->scanlist_cull_id) - g_source_remove (priv->scanlist_cull_id); - priv->scanlist_cull_id = g_timeout_add_seconds (4, (GSourceFunc) cull_scan_list, self); -} - -static void -supplicant_iface_new_bss_cb (NMSupplicantInterface *iface, - const char *object_path, - GHashTable *properties, - NMDeviceWifi *self) -{ - NMDeviceState state; - NMAccessPoint *ap; - - g_return_if_fail (self != NULL); - g_return_if_fail (properties != NULL); - g_return_if_fail (iface != NULL); - - /* Ignore new APs when unavailable, unmanaged, or in AP mode */ - state = nm_device_get_state (NM_DEVICE (self)); - if (state <= NM_DEVICE_STATE_UNAVAILABLE) - return; - if (NM_DEVICE_WIFI_GET_PRIVATE (self)->mode == NM_802_11_MODE_AP) - return; - - ap = nm_ap_new_from_properties (object_path, properties); - if (ap) { - nm_ap_dump (ap, "New AP: "); - - /* Add the AP to the device's AP list */ - merge_scanned_ap (self, ap); - g_object_unref (ap); - } else { - nm_log_warn (LOGD_WIFI_SCAN, "(%s): invalid AP properties received", - nm_device_get_iface (NM_DEVICE (self))); - } - - /* Remove outdated access points */ - schedule_scanlist_cull (self); -} - -static void -supplicant_iface_bss_updated_cb (NMSupplicantInterface *iface, - const char *object_path, - GHashTable *properties, - NMDeviceWifi *self) -{ - NMDeviceState state; - NMAccessPoint *ap; - - g_return_if_fail (self != NULL); - g_return_if_fail (object_path != NULL); - g_return_if_fail (properties != NULL); - - /* Ignore new APs when unavailable or unamnaged */ - state = nm_device_get_state (NM_DEVICE (self)); - if (state <= NM_DEVICE_STATE_UNAVAILABLE) - return; - - /* Update the AP's last-seen property */ - ap = get_ap_by_supplicant_path (self, object_path); - if (ap) - nm_ap_set_last_seen (ap, (guint32) time (NULL)); - - /* Remove outdated access points */ - schedule_scanlist_cull (self); -} - -static void -supplicant_iface_bss_removed_cb (NMSupplicantInterface *iface, - const char *object_path, - NMDeviceWifi *self) -{ - NMAccessPoint *ap; - - g_return_if_fail (self != NULL); - g_return_if_fail (object_path != NULL); - - ap = get_ap_by_supplicant_path (self, object_path); - if (ap) - g_object_set_data (G_OBJECT (ap), WPAS_REMOVED_TAG, GUINT_TO_POINTER (TRUE)); -} - - -static void -cleanup_association_attempt (NMDeviceWifi *self, gboolean disconnect) -{ - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - - remove_supplicant_interface_error_handler (self); - remove_supplicant_timeouts (self); - if (disconnect && priv->supplicant.iface) - nm_supplicant_interface_disconnect (priv->supplicant.iface); -} - -static void -wifi_secrets_cb (NMActRequest *req, - guint32 call_id, - NMConnection *connection, - GError *error, - gpointer user_data) -{ - NMDevice *dev = NM_DEVICE (user_data); - - g_return_if_fail (req == nm_device_get_act_request (dev)); - g_return_if_fail (nm_device_get_state (dev) == NM_DEVICE_STATE_NEED_AUTH); - g_return_if_fail (nm_act_request_get_connection (req) == connection); - - if (error) { - nm_log_warn (LOGD_WIFI, "%s", error->message); - nm_device_state_changed (dev, - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_NO_SECRETS); - } else - nm_device_activate_schedule_stage1_device_prepare (dev); -} - -static void -remove_link_timeout (NMDeviceWifi *self) -{ - NMDeviceWifiPrivate *priv; - - g_return_if_fail (self != NULL); - priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - - if (priv->link_timeout_id) { - g_source_remove (priv->link_timeout_id); - priv->link_timeout_id = 0; - } -} - - -/* - * link_timeout_cb - * - * Called when the link to the access point has been down for a specified - * period of time. - */ -static gboolean -link_timeout_cb (gpointer user_data) -{ - NMDevice *dev = NM_DEVICE (user_data); - NMDeviceWifi *self = NM_DEVICE_WIFI (dev); - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - NMAccessPoint *ap; - - nm_log_warn (LOGD_WIFI, "(%s): link timed out.", nm_device_get_iface (dev)); - - priv->link_timeout_id = 0; - - /* Disconnect event while activated; the supplicant hasn't been able - * to reassociate within the timeout period, so the connection must - * fail. - */ - if (nm_device_get_state (dev) != NM_DEVICE_STATE_ACTIVATED) - return FALSE; - - /* If the access point failed, and wasn't found by the supplicant when it - * attempted to reconnect, then it's probably out of range or turned off. - * Remove it from the list and if it's actually still present, it'll be - * found in the next scan. - */ - if (priv->ssid_found == FALSE) { - if (priv->current_ap) { - ap = priv->current_ap; - priv->current_ap = NULL; - } else - ap = nm_device_wifi_get_activation_ap (self); - - if (ap) - remove_access_point (self, ap); - } - - nm_device_state_changed (dev, - NM_DEVICE_STATE_FAILED, - priv->ssid_found ? NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT : - NM_DEVICE_STATE_REASON_SSID_NOT_FOUND); - return FALSE; -} - -static gboolean -need_new_8021x_secrets (NMDeviceWifi *self, - guint32 old_state, - const char **setting_name) -{ - NMSetting8021x *s_8021x; - NMSettingWirelessSecurity *s_wsec; - NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE; - NMConnection *connection; - - g_assert (setting_name != NULL); - - connection = nm_device_get_connection (NM_DEVICE (self)); - g_return_val_if_fail (connection != NULL, FALSE); - - /* 802.1x stuff only happens in the supplicant's ASSOCIATED state when it's - * attempting to authenticate with the AP. - */ - if (old_state != NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATED) - return FALSE; - - /* If it's an 802.1x or LEAP connection with "always ask"/unsaved secrets - * then we need to ask again because it might be an OTP token and the PIN - * may have changed. - */ - - s_8021x = nm_connection_get_setting_802_1x (connection); - if (s_8021x) { - nm_setting_get_secret_flags (NM_SETTING (s_8021x), - NM_SETTING_802_1X_PASSWORD, - &secret_flags, - NULL); - if (secret_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED) - *setting_name = NM_SETTING_802_1X_SETTING_NAME; - return *setting_name ? TRUE : FALSE; - } - - s_wsec = nm_connection_get_setting_wireless_security (connection); - if (s_wsec) { - nm_setting_get_secret_flags (NM_SETTING (s_wsec), - NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD, - &secret_flags, - NULL); - if (secret_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED) - *setting_name = NM_SETTING_WIRELESS_SECURITY_SETTING_NAME; - return *setting_name ? TRUE : FALSE; - } - - /* Not a LEAP or 802.1x connection */ - return FALSE; -} - -static gboolean -need_new_wpa_psk (NMDeviceWifi *self, - guint32 old_state, - const char **setting_name) -{ - NMSettingWirelessSecurity *s_wsec; - NMConnection *connection; - const char *key_mgmt = NULL; - - g_assert (setting_name != NULL); - - connection = nm_device_get_connection (NM_DEVICE (self)); - g_return_val_if_fail (connection != NULL, FALSE); - - /* A bad PSK will cause the supplicant to disconnect during the 4-way handshake */ - if (old_state != NM_SUPPLICANT_INTERFACE_STATE_4WAY_HANDSHAKE) - return FALSE; - - s_wsec = nm_connection_get_setting_wireless_security (connection); - if (s_wsec) - key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wsec); - - if (g_strcmp0 (key_mgmt, "wpa-psk") == 0) { - *setting_name = NM_SETTING_WIRELESS_SECURITY_SETTING_NAME; - return TRUE; - } - - /* Not a WPA-PSK connection */ - return FALSE; -} - -static gboolean -handle_8021x_or_psk_auth_fail (NMDeviceWifi *self, - guint32 new_state, - guint32 old_state, - int disconnect_reason) -{ - NMDevice *device = NM_DEVICE (self); - NMActRequest *req; - NMConnection *connection; - const char *setting_name = NULL; - gboolean handled = FALSE; - - g_return_val_if_fail (new_state == NM_SUPPLICANT_INTERFACE_STATE_DISCONNECTED, FALSE); - - req = nm_device_get_act_request (NM_DEVICE (self)); - g_return_val_if_fail (req != NULL, FALSE); - - connection = nm_act_request_get_connection (req); - g_assert (connection); - - if ( need_new_8021x_secrets (self, old_state, &setting_name) - || need_new_wpa_psk (self, old_state, &setting_name)) { - - nm_connection_clear_secrets (connection); - - nm_log_info (LOGD_DEVICE | LOGD_WIFI, - "Activation (%s/wireless): disconnected during association," - " asking for new key.", nm_device_get_iface (device)); - - cleanup_association_attempt (self, TRUE); - nm_device_state_changed (device, NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT); - nm_act_request_get_secrets (req, - setting_name, - NM_SETTINGS_GET_SECRETS_FLAG_ALLOW_INTERACTION - | NM_SETTINGS_GET_SECRETS_FLAG_REQUEST_NEW, - NULL, - wifi_secrets_cb, - self); - handled = TRUE; - } - - return handled; -} - -static void -supplicant_iface_state_cb (NMSupplicantInterface *iface, - guint32 new_state, - guint32 old_state, - int disconnect_reason, - gpointer user_data) -{ - NMDeviceWifi *self = NM_DEVICE_WIFI (user_data); - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - NMDevice *device = NM_DEVICE (self); - NMDeviceState devstate; - gboolean scanning; - - if (new_state == old_state) - return; - - nm_log_info (LOGD_DEVICE | LOGD_WIFI, - "(%s): supplicant interface state: %s -> %s", - nm_device_get_iface (device), - nm_supplicant_interface_state_to_string (old_state), - nm_supplicant_interface_state_to_string (new_state)); - - devstate = nm_device_get_state (device); - scanning = nm_supplicant_interface_get_scanning (iface); - - /* In these states we know the supplicant is actually talking to something */ - if ( new_state >= NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATING - && new_state <= NM_SUPPLICANT_INTERFACE_STATE_COMPLETED) - priv->ssid_found = TRUE; - - switch (new_state) { - case NM_SUPPLICANT_INTERFACE_STATE_READY: - priv->scan_interval = SCAN_INTERVAL_MIN; - - /* If the interface can now be activated because the supplicant is now - * available, transition to DISCONNECTED. - */ - if ((devstate == NM_DEVICE_STATE_UNAVAILABLE) && nm_device_is_available (device)) { - nm_device_state_changed (device, - NM_DEVICE_STATE_DISCONNECTED, - NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE); - } - - nm_log_dbg (LOGD_WIFI_SCAN, - "(%s): supplicant ready, requesting initial scan", - nm_device_get_iface (device)); - - /* Request a scan to get latest results */ - cancel_pending_scan (self); - request_wireless_scan (self); - break; - case NM_SUPPLICANT_INTERFACE_STATE_COMPLETED: - remove_supplicant_interface_error_handler (self); - remove_supplicant_timeouts (self); - - /* If this is the initial association during device activation, - * schedule the next activation stage. - */ - if (devstate == NM_DEVICE_STATE_CONFIG) { - NMAccessPoint *ap = nm_device_wifi_get_activation_ap (self); - const GByteArray *ssid = ap ? nm_ap_get_ssid (ap) : NULL; - - nm_log_info (LOGD_DEVICE | LOGD_WIFI, - "Activation (%s/wireless) Stage 2 of 5 (Device Configure) " - "successful. %s '%s'.", - nm_device_get_iface (device), - priv->mode == NM_802_11_MODE_AP ? "Started Wi-Fi Hotspot" : - "Connected to wireless network", - ssid ? nm_utils_escape_ssid (ssid->data, ssid->len) : "(none)"); - nm_device_activate_schedule_stage3_ip_config_start (device); - } else if (devstate == NM_DEVICE_STATE_ACTIVATED) - periodic_update (self); - break; - case NM_SUPPLICANT_INTERFACE_STATE_DISCONNECTED: - if ((devstate == NM_DEVICE_STATE_ACTIVATED) || nm_device_is_activating (device)) { - /* Disconnect of an 802.1x/LEAP connection during authentication, - * or disconnect of a WPA-PSK connection during the 4-way handshake, - * often means secrets are wrong. Not always the case, but until we - * have more information from wpa_supplicant about why the - * disconnect happened this is the best we can do. - */ - if (handle_8021x_or_psk_auth_fail (self, new_state, old_state, disconnect_reason)) - break; - } - - /* Otherwise it might be a stupid driver or some transient error, so - * let the supplicant try to reconnect a few more times. Give it more - * time if a scan is in progress since the link might be dropped during - * the scan but will be re-established when the scan is done. - */ - if (devstate == NM_DEVICE_STATE_ACTIVATED) { - if (priv->link_timeout_id == 0) { - priv->link_timeout_id = g_timeout_add_seconds (scanning ? 30 : 15, link_timeout_cb, self); - priv->ssid_found = FALSE; - } - } - break; - case NM_SUPPLICANT_INTERFACE_STATE_DOWN: - cleanup_association_attempt (self, FALSE); - - /* If the device is already in UNAVAILABLE state then the state change - * is a NOP and the interface won't be re-acquired in the device state - * change handler. So ensure we have a new one here so that we're - * ready if the supplicant comes back. - */ - supplicant_interface_release (self); - supplicant_interface_acquire (self); - - nm_device_state_changed (device, - NM_DEVICE_STATE_UNAVAILABLE, - NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); - break; - default: - break; - } - - /* Signal scanning state changes */ - if ( new_state == NM_SUPPLICANT_INTERFACE_STATE_SCANNING - || old_state == NM_SUPPLICANT_INTERFACE_STATE_SCANNING) - g_object_notify (G_OBJECT (self), "scanning"); -} - -struct iface_con_error_cb_data { - NMDeviceWifi *self; - char *name; - char *message; -}; - -static gboolean -supplicant_iface_connection_error_cb_handler (gpointer user_data) -{ - NMDeviceWifi *self; - NMDeviceWifiPrivate *priv; - struct iface_con_error_cb_data * cb_data = (struct iface_con_error_cb_data *) user_data; - - g_return_val_if_fail (cb_data != NULL, FALSE); - - self = cb_data->self; - priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - - if (!nm_device_is_activating (NM_DEVICE (self))) - goto out; - - nm_log_info (LOGD_DEVICE | LOGD_WIFI, - "Activation (%s/wireless): association request to the supplicant " - "failed: %s - %s", - nm_device_get_iface (NM_DEVICE (self)), - cb_data->name, - cb_data->message); - - cleanup_association_attempt (self, TRUE); - nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); - -out: - priv->supplicant.iface_con_error_cb_id = 0; - g_free (cb_data->name); - g_free (cb_data->message); - g_slice_free (struct iface_con_error_cb_data, cb_data); - return FALSE; -} - - -static void -supplicant_iface_connection_error_cb (NMSupplicantInterface * iface, - const char * name, - const char * message, - NMDeviceWifi * self) -{ - NMDeviceWifiPrivate *priv; - struct iface_con_error_cb_data *cb_data; - guint id; - - g_return_if_fail (self != NULL); - priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - - cb_data = g_slice_new0 (struct iface_con_error_cb_data); - if (cb_data == NULL) { - nm_log_err (LOGD_WIFI, "Not enough memory to process supplicant connection error."); - return; - } - - cb_data->self = self; - cb_data->name = g_strdup (name); - cb_data->message = g_strdup (message); - - if (priv->supplicant.iface_con_error_cb_id) - g_source_remove (priv->supplicant.iface_con_error_cb_id); - - id = g_idle_add (supplicant_iface_connection_error_cb_handler, cb_data); - priv->supplicant.iface_con_error_cb_id = id; -} - -static void -supplicant_iface_notify_scanning_cb (NMSupplicantInterface *iface, - GParamSpec *pspec, - NMDeviceWifi *self) -{ - NMDeviceState state; - gboolean scanning; - - scanning = nm_supplicant_interface_get_scanning (iface); - nm_log_dbg (LOGD_WIFI_SCAN, "(%s): now %s", - nm_device_get_iface (NM_DEVICE (self)), - scanning ? "scanning" : "idle"); - - g_object_notify (G_OBJECT (self), "scanning"); - - /* Run a quick update of current AP when coming out of a scan */ - state = nm_device_get_state (NM_DEVICE (self)); - if (!scanning && state == NM_DEVICE_STATE_ACTIVATED) - periodic_update (self); -} - -static void -remove_supplicant_connection_timeout (NMDeviceWifi *self) -{ - NMDeviceWifiPrivate *priv; - - g_return_if_fail (self != NULL); - priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - - /* Remove any pending timeouts on the request */ - if (priv->supplicant.con_timeout_id) { - g_source_remove (priv->supplicant.con_timeout_id); - priv->supplicant.con_timeout_id = 0; - } -} - -static NMActStageReturn -handle_auth_or_fail (NMDeviceWifi *self, - NMActRequest *req, - gboolean new_secrets) -{ - const char *setting_name; - guint32 tries; - NMConnection *connection; - NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; - - g_return_val_if_fail (NM_IS_DEVICE_WIFI (self), NM_ACT_STAGE_RETURN_FAILURE); - - if (!req) { - req = nm_device_get_act_request (NM_DEVICE (self)); - g_assert (req); - } - - connection = nm_act_request_get_connection (req); - g_assert (connection); - - tries = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (connection), WIRELESS_SECRETS_TRIES)); - if (tries > 3) - return NM_ACT_STAGE_RETURN_FAILURE; - - nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_NONE); - - nm_connection_clear_secrets (connection); - setting_name = nm_connection_need_secrets (connection, NULL); - if (setting_name) { - NMSettingsGetSecretsFlags flags = NM_SETTINGS_GET_SECRETS_FLAG_ALLOW_INTERACTION; - - if (new_secrets) - flags |= NM_SETTINGS_GET_SECRETS_FLAG_REQUEST_NEW; - nm_act_request_get_secrets (req, setting_name, flags, NULL, wifi_secrets_cb, self); - - g_object_set_data (G_OBJECT (connection), WIRELESS_SECRETS_TRIES, GUINT_TO_POINTER (++tries)); - ret = NM_ACT_STAGE_RETURN_POSTPONE; - } else - nm_log_warn (LOGD_DEVICE, "Cleared secrets, but setting didn't need any secrets."); - - return ret; -} - -static gboolean -is_encrypted (NMAccessPoint *ap, NMConnection *connection) -{ - NM80211ApFlags flags; - NM80211ApSecurityFlags wpa_flags, rsn_flags; - - g_return_val_if_fail (ap != NULL, FALSE); - g_return_val_if_fail (connection != NULL, FALSE); - - flags = nm_ap_get_flags (ap); - wpa_flags = nm_ap_get_wpa_flags (ap); - rsn_flags = nm_ap_get_rsn_flags (ap); - - if (flags & NM_802_11_AP_FLAGS_PRIVACY) - return TRUE; - if (wpa_flags & (NM_802_11_AP_SEC_KEY_MGMT_PSK | NM_802_11_AP_SEC_KEY_MGMT_802_1X)) - return TRUE; - if (rsn_flags & (NM_802_11_AP_SEC_KEY_MGMT_PSK | NM_802_11_AP_SEC_KEY_MGMT_802_1X)) - return TRUE; - - return FALSE; -} - -/* - * supplicant_connection_timeout_cb - * - * Called when the supplicant has been unable to connect to an access point - * within a specified period of time. - */ -static gboolean -supplicant_connection_timeout_cb (gpointer user_data) -{ - NMDevice *dev = NM_DEVICE (user_data); - NMDeviceWifi *self = NM_DEVICE_WIFI (user_data); - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - NMAccessPoint *ap; - NMActRequest *req; - NMConnection *connection; - - cleanup_association_attempt (self, TRUE); - - if (!nm_device_is_activating (dev)) - return FALSE; - - /* Timed out waiting for a successful connection to the AP; if the AP's - * security requires network-side authentication (like WPA or 802.1x) - * and the connection attempt timed out then it's likely the authentication - * information (passwords, pin codes, etc) are wrong. - */ - - req = nm_device_get_act_request (dev); - g_assert (req); - - connection = nm_act_request_get_connection (req); - g_assert (connection); - - if ( priv->mode == NM_802_11_MODE_ADHOC - || priv->mode == NM_802_11_MODE_AP) { - /* In Ad-Hoc and AP modes there's nothing to check the encryption key - * (if any), so supplicant timeouts here are almost certainly the wifi - * driver being really stupid. - */ - nm_log_warn (LOGD_DEVICE | LOGD_WIFI, - "Activation (%s/wireless): %s network creation took " - "too long, failing activation.", - nm_device_get_iface (dev), - priv->mode == NM_802_11_MODE_ADHOC ? "Ad-Hoc" : "Hotspot"); - nm_device_state_changed (dev, NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT); - return FALSE; - } - - g_assert (priv->mode == NM_802_11_MODE_INFRA); - ap = nm_device_wifi_get_activation_ap (self); - - if (priv->ssid_found && ap && is_encrypted (ap, connection)) { - guint64 timestamp = 0; - gboolean new_secrets = TRUE; - - /* Connection failed; either driver problems, the encryption key is - * wrong, or the passwords or certificates were wrong. - */ - nm_log_warn (LOGD_DEVICE | LOGD_WIFI, - "Activation (%s/wireless): association took too long.", - nm_device_get_iface (dev)); - - /* Ask for new secrets only if we've never activated this connection - * before. If we've connected before, don't bother the user with - * dialogs, just retry or fail, and if we never connect the user can - * fix the password somewhere else. - */ - if (nm_settings_connection_get_timestamp (NM_SETTINGS_CONNECTION (connection), ×tamp)) - new_secrets = !timestamp; - - if (handle_auth_or_fail (self, req, new_secrets) == NM_ACT_STAGE_RETURN_POSTPONE) { - nm_log_warn (LOGD_DEVICE | LOGD_WIFI, - "Activation (%s/wireless): asking for new secrets", - nm_device_get_iface (dev)); - } else { - nm_device_state_changed (dev, NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_NO_SECRETS); - } - } else { - nm_log_warn (LOGD_DEVICE | LOGD_WIFI, - "Activation (%s/wireless): association took too long, " - "failing activation.", - nm_device_get_iface (dev)); - nm_device_state_changed (dev, NM_DEVICE_STATE_FAILED, - priv->ssid_found ? NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT : - NM_DEVICE_STATE_REASON_SSID_NOT_FOUND); - } - - return FALSE; -} - - -static gboolean -start_supplicant_connection_timeout (NMDeviceWifi *self) -{ - NMDeviceWifiPrivate *priv; - guint id; - - g_return_val_if_fail (self != NULL, FALSE); - - priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - - /* Set up a timeout on the connection attempt to fail it after 25 seconds */ - id = g_timeout_add_seconds (25, supplicant_connection_timeout_cb, self); - if (id == 0) { - nm_log_err (LOGD_DEVICE | LOGD_WIFI, - "Activation (%s/wireless): couldn't start supplicant " - "timeout timer.", - nm_device_get_iface (NM_DEVICE (self))); - return FALSE; - } - priv->supplicant.con_timeout_id = id; - return TRUE; -} - - -static void -remove_supplicant_timeouts (NMDeviceWifi *self) -{ - g_return_if_fail (self != NULL); - - remove_supplicant_connection_timeout (self); - remove_link_timeout (self); -} - -static NMSupplicantConfig * -build_supplicant_config (NMDeviceWifi *self, - NMConnection *connection, - NMAccessPoint *ap) -{ - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - NMSupplicantConfig *config = NULL; - NMSettingWireless *s_wireless; - NMSettingWirelessSecurity *s_wireless_sec; - - g_return_val_if_fail (self != NULL, NULL); - - s_wireless = nm_connection_get_setting_wireless (connection); - g_return_val_if_fail (s_wireless != NULL, NULL); - - config = nm_supplicant_config_new (); - if (!config) - return NULL; - - /* Warn if AP mode may not be supported */ - if ( g_strcmp0 (nm_setting_wireless_get_mode (s_wireless), NM_SETTING_WIRELESS_MODE_AP) == 0 - && nm_supplicant_interface_get_ap_support (priv->supplicant.iface) == AP_SUPPORT_UNKNOWN) { - nm_log_warn (LOGD_WIFI, "Supplicant may not support AP mode; connection may time out."); - } - - if (!nm_supplicant_config_add_setting_wireless (config, - s_wireless, - nm_ap_get_broadcast (ap), - nm_ap_get_freq (ap), - wifi_utils_can_scan_ssid (priv->wifi_data))) { - nm_log_err (LOGD_WIFI, "Couldn't add 802-11-wireless setting to supplicant config."); - goto error; - } - - s_wireless_sec = nm_connection_get_setting_wireless_security (connection); - if (s_wireless_sec) { - NMSetting8021x *s_8021x; - const char *con_uuid = nm_connection_get_uuid (connection); - - g_assert (con_uuid); - s_8021x = nm_connection_get_setting_802_1x (connection); - if (!nm_supplicant_config_add_setting_wireless_security (config, - s_wireless_sec, - s_8021x, - con_uuid)) { - nm_log_err (LOGD_WIFI, "Couldn't add 802-11-wireless-security setting to " - "supplicant config."); - goto error; - } - } else { - if (!nm_supplicant_config_add_no_security (config)) { - nm_log_err (LOGD_WIFI, "Couldn't add unsecured option to supplicant config."); - goto error; - } - } - - return config; - -error: - g_object_unref (config); - return NULL; -} - -/****************************************************************************/ - -static void -update_hw_address (NMDevice *dev) -{ - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (dev); - gsize addrlen; - gboolean changed = FALSE; - - addrlen = nm_device_read_hwaddr (dev, priv->hw_addr, sizeof (priv->hw_addr), &changed); - if (addrlen) { - g_return_if_fail (addrlen == ETH_ALEN); - if (changed) - g_object_notify (G_OBJECT (dev), NM_DEVICE_WIFI_HW_ADDRESS); - } -} - -static void -update_permanent_hw_address (NMDevice *dev) -{ - NMDeviceWifi *self = NM_DEVICE_WIFI (dev); - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - struct ifreq req; - struct ethtool_perm_addr *epaddr = NULL; - int fd, ret; - - fd = socket (PF_INET, SOCK_DGRAM, 0); - if (fd < 0) { - nm_log_err (LOGD_HW, "could not open control socket."); - return; - } - - /* Get permanent MAC address */ - memset (&req, 0, sizeof (struct ifreq)); - strncpy (req.ifr_name, nm_device_get_iface (dev), IFNAMSIZ); - - epaddr = g_malloc0 (sizeof (struct ethtool_perm_addr) + ETH_ALEN); - epaddr->cmd = ETHTOOL_GPERMADDR; - epaddr->size = ETH_ALEN; - req.ifr_data = (void *) epaddr; - - errno = 0; - ret = ioctl (fd, SIOCETHTOOL, &req); - if ((ret < 0) || !nm_ethernet_address_is_valid ((struct ether_addr *) epaddr->data)) { - nm_log_dbg (LOGD_HW | LOGD_ETHER, "(%s): unable to read permanent MAC address (error %d)", - nm_device_get_iface (dev), errno); - /* Fall back to current address */ - memcpy (epaddr->data, &priv->hw_addr, ETH_ALEN); - } - - if (memcmp (&priv->perm_hw_addr, epaddr->data, ETH_ALEN)) { - memcpy (&priv->perm_hw_addr, epaddr->data, ETH_ALEN); - g_object_notify (G_OBJECT (dev), NM_DEVICE_WIFI_PERMANENT_HW_ADDRESS); - } - - g_free (epaddr); - close (fd); -} - -static void -update_initial_hw_address (NMDevice *dev) -{ - NMDeviceWifi *self = NM_DEVICE_WIFI (dev); - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - char *mac_str = NULL; - guint8 *addr = priv->initial_hw_addr; - guint8 zero[ETH_ALEN] = {0,0,0,0,0,0}; - - /* This sets initial MAC address from current MAC address. It should only - * be called from NMDevice constructor() to really get the initial address. - */ - if (!memcmp (&priv->hw_addr, &zero, ETH_ALEN)) - update_hw_address (dev); - - if (memcmp (&priv->initial_hw_addr, &priv->hw_addr, ETH_ALEN)) - memcpy (&priv->initial_hw_addr, &priv->hw_addr, ETH_ALEN); - - mac_str = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X", - addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); - - nm_log_dbg (LOGD_DEVICE | LOGD_ETHER, "(%s): read initial MAC address %s", - nm_device_get_iface (dev), mac_str); - - g_free (mac_str); -} - -static const guint8 * -get_hw_address (NMDevice *device, guint *out_len) -{ - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (device); - - *out_len = ETH_ALEN; - return priv->hw_addr; -} - -static NMActStageReturn -act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason) -{ - NMDeviceWifi *self = NM_DEVICE_WIFI (dev); - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - NMAccessPoint *ap = NULL; - NMActRequest *req; - NMConnection *connection; - NMSettingWireless *s_wireless; - const GByteArray *cloned_mac; - GSList *iter; - const char *mode; - - req = nm_device_get_act_request (NM_DEVICE (self)); - g_return_val_if_fail (req != NULL, NM_ACT_STAGE_RETURN_FAILURE); - - connection = nm_act_request_get_connection (req); - g_return_val_if_fail (connection != NULL, NM_ACT_STAGE_RETURN_FAILURE); - - s_wireless = nm_connection_get_setting_wireless (connection); - g_assert (s_wireless); - - mode = nm_setting_wireless_get_mode (s_wireless); - if (g_strcmp0 (mode, "infra") == 0) - priv->mode = NM_802_11_MODE_INFRA; - else if (g_strcmp0 (mode, "adhoc") == 0) - priv->mode = NM_802_11_MODE_ADHOC; - else if (g_strcmp0 (mode, "ap") == 0) { - priv->mode = NM_802_11_MODE_AP; - - /* Scanning not done in AP mode; clear the scan list */ - remove_all_aps (self); - } - g_object_notify (G_OBJECT (self), NM_DEVICE_WIFI_MODE); - - /* The kernel doesn't support Ad-Hoc WPA connections well at this time, - * and turns them into open networks. It's been this way since at least - * 2.6.30 or so; until that's fixed, disable WPA-protected Ad-Hoc networks. - */ - if (is_adhoc_wpa (connection)) { - nm_log_warn (LOGD_WIFI, "Ad-Hoc WPA disabled due to kernel bugs"); - *reason = NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED; - return NM_ACT_STAGE_RETURN_FAILURE; - } - - /* Set spoof MAC to the interface */ - cloned_mac = nm_setting_wireless_get_cloned_mac_address (s_wireless); - if (cloned_mac && (cloned_mac->len == ETH_ALEN)) - _set_hw_addr (self, (const guint8 *) cloned_mac->data, "set"); - - /* AP mode never uses a specific object or existing scanned AP */ - if (priv->mode != NM_802_11_MODE_AP) { - ap = nm_device_wifi_get_activation_ap (self); - if (ap) - goto done; - - /* Find a compatible AP in the scan list */ - for (iter = priv->ap_list; iter; iter = g_slist_next (iter)) { - NMAccessPoint *candidate = NM_AP (iter->data); - - if (nm_ap_check_compatible (candidate, connection)) { - ap = candidate; - break; - } - } - } - - /* If the user is trying to connect to an AP that NM doesn't yet know about - * (hidden network or something) or starting a Hotspot, create an fake AP - * from the security settings in the connection. This "fake" AP gets used - * until the real one is found in the scan list (Ad-Hoc or Hidden), or until - * the device is deactivated (Hotspot). - */ - if (!ap) { - ap = nm_ap_new_fake_from_connection (connection); - g_return_val_if_fail (ap != NULL, NM_ACT_STAGE_RETURN_FAILURE); - - if (nm_ap_get_mode (ap) == NM_802_11_MODE_INFRA) - nm_ap_set_broadcast (ap, FALSE); - else if (nm_ap_is_hotspot (ap)) - nm_ap_set_address (ap, (const struct ether_addr *) &priv->hw_addr); - - priv->ap_list = g_slist_prepend (priv->ap_list, ap); - nm_ap_export_to_dbus (ap); - g_signal_emit (self, signals[ACCESS_POINT_ADDED], 0, ap); - nm_device_recheck_available_connections (NM_DEVICE (self)); - } - - nm_active_connection_set_specific_object (NM_ACTIVE_CONNECTION (req), nm_ap_get_dbus_path (ap)); - -done: - set_active_ap (self, ap); - return NM_ACT_STAGE_RETURN_SUCCESS; -} - -static void -ensure_hotspot_frequency (NMDeviceWifi *self, - NMSettingWireless *s_wifi, - NMAccessPoint *ap) -{ - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - const char *band = nm_setting_wireless_get_band (s_wifi); - const guint32 a_freqs[] = { 5180, 5200, 5220, 5745, 5765, 5785, 5805, 0 }; - const guint32 bg_freqs[] = { 2412, 2437, 2462, 2472, 0 }; - guint32 freq = 0; - - g_assert (ap); - - if (nm_ap_get_freq (ap)) - return; - - if (g_strcmp0 (band, "a") == 0) - freq = wifi_utils_find_freq (priv->wifi_data, a_freqs); - else - freq = wifi_utils_find_freq (priv->wifi_data, bg_freqs); - - if (!freq) - freq = (g_strcmp0 (band, "a") == 0) ? 5180 : 2462; - - nm_ap_set_freq (ap, freq); -} - -static NMActStageReturn -act_stage2_config (NMDevice *dev, NMDeviceStateReason *reason) -{ - NMDeviceWifi *self = NM_DEVICE_WIFI (dev); - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; - const char *iface = nm_device_get_iface (dev); - NMSupplicantConfig *config = NULL; - gulong id = 0; - NMActRequest *req; - NMAccessPoint *ap; - NMConnection *connection; - const char *setting_name; - NMSettingWireless *s_wireless; - - g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); - - remove_supplicant_timeouts (self); - - req = nm_device_get_act_request (dev); - g_assert (req); - - ap = nm_device_wifi_get_activation_ap (self); - if (!ap) { - nm_log_warn (LOGD_DEVICE | LOGD_WIFI, "act_stage2_config failed due to unexpected missing activation_ap. Abort"); - *reason = NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT; - goto out; - } - - connection = nm_act_request_get_connection (req); - g_assert (connection); - - s_wireless = nm_connection_get_setting_wireless (connection); - g_assert (s_wireless); - - /* If we need secrets, get them */ - setting_name = nm_connection_need_secrets (connection, NULL); - if (setting_name) { - nm_log_info (LOGD_DEVICE | LOGD_WIFI, - "Activation (%s/wireless): access point '%s' has security," - " but secrets are required.", - iface, nm_connection_get_id (connection)); - - ret = handle_auth_or_fail (self, req, FALSE); - if (ret == NM_ACT_STAGE_RETURN_FAILURE) - *reason = NM_DEVICE_STATE_REASON_NO_SECRETS; - goto out; - } - - /* have secrets, or no secrets required */ - if (nm_setting_wireless_get_security (s_wireless)) { - nm_log_info (LOGD_DEVICE | LOGD_WIFI, - "Activation (%s/wireless): connection '%s' has security" - ", and secrets exist. No new secrets needed.", - iface, nm_connection_get_id (connection)); - } else { - nm_log_info (LOGD_DEVICE | LOGD_WIFI, - "Activation (%s/wireless): connection '%s' requires no " - "security. No secrets needed.", - iface, nm_connection_get_id (connection)); - } - - priv->ssid_found = FALSE; - - /* Supplicant requires an initial frequency for Ad-Hoc and Hotspot; if the user - * didn't specify one and we didn't find an AP that matched the connection, - * just pick a frequency the device supports. - */ - if ((nm_ap_get_mode (ap) == NM_802_11_MODE_ADHOC) || nm_ap_is_hotspot (ap)) - ensure_hotspot_frequency (self, s_wireless, ap); - - /* Build up the supplicant configuration */ - config = build_supplicant_config (self, connection, ap); - if (config == NULL) { - nm_log_err (LOGD_DEVICE | LOGD_WIFI, - "Activation (%s/wireless): couldn't build wireless configuration.", - iface); - *reason = NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED; - goto out; - } - - /* Hook up error signal handler to capture association errors */ - id = g_signal_connect (priv->supplicant.iface, - NM_SUPPLICANT_INTERFACE_CONNECTION_ERROR, - G_CALLBACK (supplicant_iface_connection_error_cb), - self); - priv->supplicant.iface_error_id = id; - - if (!nm_supplicant_interface_set_config (priv->supplicant.iface, config)) { - nm_log_err (LOGD_DEVICE | LOGD_WIFI, - "Activation (%s/wireless): couldn't send wireless " - "configuration to the supplicant.", iface); - *reason = NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED; - goto out; - } - - if (!start_supplicant_connection_timeout (self)) { - *reason = NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED; - goto out; - } - - /* We'll get stage3 started when the supplicant connects */ - ret = NM_ACT_STAGE_RETURN_POSTPONE; - -out: - if (ret == NM_ACT_STAGE_RETURN_FAILURE) - cleanup_association_attempt (self, TRUE); - - if (config) { - /* Supplicant interface object refs the config; we no longer care about - * it after this function. - */ - g_object_unref (config); - } - return ret; -} - -static void -ip4_config_pre_commit (NMDevice *device, NMIP4Config *config) -{ - NMConnection *connection; - NMSettingWireless *s_wifi; - guint32 mtu; - - connection = nm_device_get_connection (device); - g_assert (connection); - s_wifi = nm_connection_get_setting_wireless (connection); - g_assert (s_wifi); - - /* MTU override */ - mtu = nm_setting_wireless_get_mtu (s_wifi); - if (mtu) - nm_ip4_config_set_mtu (config, mtu); -} - -static gboolean -is_static_wep (NMAccessPoint *ap, NMConnection *connection) -{ - NM80211ApFlags flags; - NM80211ApSecurityFlags wpa_flags, rsn_flags; - NMSettingWirelessSecurity *s_wsec; - const char *key_mgmt; - - g_return_val_if_fail (ap != NULL, FALSE); - g_return_val_if_fail (connection != NULL, FALSE); - - flags = nm_ap_get_flags (ap); - wpa_flags = nm_ap_get_wpa_flags (ap); - rsn_flags = nm_ap_get_rsn_flags (ap); - - if ( (flags & NM_802_11_AP_FLAGS_PRIVACY) - && (wpa_flags == NM_802_11_AP_SEC_NONE) - && (rsn_flags == NM_802_11_AP_SEC_NONE)) { - s_wsec = nm_connection_get_setting_wireless_security (connection); - if (s_wsec) { - key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wsec); - if (g_strcmp0 (key_mgmt, "none") == 0) - return TRUE; - } - } - - return FALSE; -} - -static NMActStageReturn -handle_ip_config_timeout (NMDeviceWifi *self, - NMConnection *connection, - gboolean may_fail, - gboolean *chain_up, - NMDeviceStateReason *reason) -{ - NMAccessPoint *ap; - NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; - - g_return_val_if_fail (connection != NULL, NM_ACT_STAGE_RETURN_FAILURE); - - if (NM_DEVICE_WIFI_GET_PRIVATE (self)->mode == NM_802_11_MODE_AP) { - *chain_up = TRUE; - return ret; - } - - ap = nm_device_wifi_get_activation_ap (self); - - /* If IP configuration times out and it's a static WEP connection, that - * usually means the WEP key is wrong. WEP's Open System auth mode has - * no provision for figuring out if the WEP key is wrong, so you just have - * to wait for DHCP to fail to figure it out. For all other WiFi security - * types (open, WPA, 802.1x, etc) if the secrets/certs were wrong the - * connection would have failed before IP configuration. - */ - if (ap && is_static_wep (ap, connection) && (may_fail == FALSE)) { - /* Activation failed, we must have bad encryption key */ - nm_log_warn (LOGD_DEVICE | LOGD_WIFI, - "Activation (%s/wireless): could not get IP configuration for " - "connection '%s'.", - nm_device_get_iface (NM_DEVICE (self)), - nm_connection_get_id (connection)); - - ret = handle_auth_or_fail (self, NULL, TRUE); - if (ret == NM_ACT_STAGE_RETURN_POSTPONE) { - nm_log_info (LOGD_DEVICE | LOGD_WIFI, - "Activation (%s/wireless): asking for new secrets", - nm_device_get_iface (NM_DEVICE (self))); - } else { - *reason = NM_DEVICE_STATE_REASON_NO_SECRETS; - } - } else { - /* Not static WEP or failure allowed; let superclass handle it */ - *chain_up = TRUE; - } - - return ret; -} - - -static NMActStageReturn -act_stage4_ip4_config_timeout (NMDevice *dev, NMDeviceStateReason *reason) -{ - NMConnection *connection; - NMSettingIP4Config *s_ip4; - gboolean may_fail = FALSE, chain_up = FALSE; - NMActStageReturn ret; - - connection = nm_device_get_connection (dev); - g_assert (connection); - - s_ip4 = nm_connection_get_setting_ip4_config (connection); - if (s_ip4) - may_fail = nm_setting_ip4_config_get_may_fail (s_ip4); - - ret = handle_ip_config_timeout (NM_DEVICE_WIFI (dev), connection, may_fail, &chain_up, reason); - if (chain_up) - ret = NM_DEVICE_CLASS (nm_device_wifi_parent_class)->act_stage4_ip4_config_timeout (dev, reason); - - return ret; -} - -static NMActStageReturn -act_stage4_ip6_config_timeout (NMDevice *dev, NMDeviceStateReason *reason) -{ - NMConnection *connection; - NMSettingIP6Config *s_ip6; - gboolean may_fail = FALSE, chain_up = FALSE; - NMActStageReturn ret; - - connection = nm_device_get_connection (dev); - g_assert (connection); - - s_ip6 = nm_connection_get_setting_ip6_config (connection); - if (s_ip6) - may_fail = nm_setting_ip6_config_get_may_fail (s_ip6); - - ret = handle_ip_config_timeout (NM_DEVICE_WIFI (dev), connection, may_fail, &chain_up, reason); - if (chain_up) - ret = NM_DEVICE_CLASS (nm_device_wifi_parent_class)->act_stage4_ip6_config_timeout (dev, reason); - - return ret; -} - -static void -activation_success_handler (NMDevice *dev) -{ - NMDeviceWifi *self = NM_DEVICE_WIFI (dev); - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - NMAccessPoint *ap; - struct ether_addr bssid = { {0x0, 0x0, 0x0, 0x0, 0x0, 0x0} }; - NMAccessPoint *tmp_ap; - NMActRequest *req; - NMConnection *connection; - - req = nm_device_get_act_request (dev); - g_assert (req); - - connection = nm_act_request_get_connection (req); - g_assert (connection); - - /* Clear wireless secrets tries on success */ - g_object_set_data (G_OBJECT (connection), WIRELESS_SECRETS_TRIES, NULL); - - ap = nm_device_wifi_get_activation_ap (self); - - /* If the AP isn't fake, it was found in the scan list and all its - * details are known. - */ - if (!ap || !nm_ap_get_fake (ap)) - goto done; - - /* If the activate AP was fake, it probably won't have a BSSID at all. - * But if activation was successful, the card will know the BSSID. Grab - * the BSSID off the card and fill in the BSSID of the activation AP. - */ - wifi_utils_get_bssid (priv->wifi_data, &bssid); - if (!nm_ethernet_address_is_valid (nm_ap_get_address (ap))) - nm_ap_set_address (ap, &bssid); - if (!nm_ap_get_freq (ap)) - nm_ap_set_freq (ap, wifi_utils_get_freq (priv->wifi_data)); - if (!nm_ap_get_max_bitrate (ap)) - nm_ap_set_max_bitrate (ap, wifi_utils_get_rate (priv->wifi_data)); - - tmp_ap = get_active_ap (self, ap, TRUE); - if (tmp_ap) { - const GByteArray *ssid = nm_ap_get_ssid (tmp_ap); - - /* Found a better match in the scan list than the fake AP. Use it - * instead. - */ - - /* If the better match was a hidden AP, update it's SSID */ - if (!ssid || nm_utils_is_empty_ssid (ssid->data, ssid->len)) - nm_ap_set_ssid (tmp_ap, nm_ap_get_ssid (ap)); - - nm_active_connection_set_specific_object (NM_ACTIVE_CONNECTION (req), - nm_ap_get_dbus_path (tmp_ap)); - - priv->ap_list = g_slist_remove (priv->ap_list, ap); - g_object_unref (ap); - } - -done: - periodic_update (self); - - /* Update seen BSSIDs cache with the connected AP */ - update_seen_bssids_cache (self, priv->current_ap); - - /* Reset scan interval to something reasonable */ - priv->scan_interval = SCAN_INTERVAL_MIN + (SCAN_INTERVAL_STEP * 2); -} - -static void -activation_failure_handler (NMDevice *dev) -{ - NMDeviceWifi *self = NM_DEVICE_WIFI (dev); - NMAccessPoint *ap; - NMConnection *connection; - - connection = nm_device_get_connection (dev); - g_assert (connection); - - /* Clear wireless secrets tries on failure */ - g_object_set_data (G_OBJECT (connection), WIRELESS_SECRETS_TRIES, NULL); - - if ((ap = nm_device_wifi_get_activation_ap (self))) { - if (nm_ap_get_fake (ap)) { - /* Fake APs are ones that don't show up in scans, - * but which the user explicitly attempted to connect to. - * However, if we fail on one of these, remove it from the - * list because we don't have any scan or capability info - * for it, and they are pretty much useless. - */ - remove_access_point (self, ap); - } - } -} - -static gboolean -can_interrupt_activation (NMDevice *dev) -{ - if (nm_device_get_state (dev) == NM_DEVICE_STATE_NEED_AUTH) - return TRUE; - - return FALSE; -} - - -static guint32 -get_type_capabilities (NMDevice *dev) -{ - return NM_DEVICE_WIFI_GET_PRIVATE (dev)->capabilities; -} - - -static gboolean -spec_match_list (NMDevice *device, const GSList *specs) -{ - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (device); - char *hwaddr; - gboolean matched; - - hwaddr = nm_utils_hwaddr_ntoa (&priv->perm_hw_addr, ARPHRD_ETHER); - matched = nm_match_spec_hwaddr (specs, hwaddr); - g_free (hwaddr); - - return matched; -} - -static gboolean -hwaddr_matches (NMDevice *device, - NMConnection *connection, - const guint8 *other_hwaddr, - guint other_hwaddr_len, - gboolean fail_if_no_hwaddr) -{ - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (device); - NMSettingWireless *s_wifi; - const GByteArray *mac = NULL; - - s_wifi = nm_connection_get_setting_wireless (connection); - if (s_wifi) - mac = nm_setting_wireless_get_mac_address (s_wifi); - - if (mac) { - g_return_val_if_fail (mac->len == ETH_ALEN, FALSE); - if (other_hwaddr) { - g_return_val_if_fail (other_hwaddr_len == ETH_ALEN, FALSE); - if (memcmp (mac->data, other_hwaddr, mac->len) == 0) - return TRUE; - } else if (memcmp (mac->data, priv->hw_addr, mac->len) == 0) - return TRUE; - } else if (fail_if_no_hwaddr == FALSE) - return TRUE; - - return FALSE; -} - -static void -device_state_changed (NMDevice *device, - NMDeviceState new_state, - NMDeviceState old_state, - NMDeviceStateReason reason) -{ - NMDeviceWifi *self = NM_DEVICE_WIFI (device); - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - gboolean clear_aps = FALSE; - - if (new_state <= NM_DEVICE_STATE_UNAVAILABLE) { - /* Clean up the supplicant interface because in these states the - * device cannot be used. - */ - if (priv->supplicant.iface) - supplicant_interface_release (self); - } - - /* Start or stop the rfkill poll worker for ipw cards */ - if (priv->ipw_rfkill_path) { - if (new_state > NM_DEVICE_STATE_UNMANAGED) { - if (!priv->ipw_rfkill_id) - priv->ipw_rfkill_id = g_timeout_add_seconds (3, ipw_rfkill_state_work, self); - } else if (new_state <= NM_DEVICE_STATE_UNMANAGED) { - if (priv->ipw_rfkill_id) { - g_source_remove (priv->ipw_rfkill_id); - priv->ipw_rfkill_id = 0; - } - } - } - - switch (new_state) { - case NM_DEVICE_STATE_UNMANAGED: - clear_aps = TRUE; - break; - case NM_DEVICE_STATE_UNAVAILABLE: - /* If the device is enabled and the supplicant manager is ready, - * acquire a supplicant interface and transition to DISCONNECTED because - * the device is now ready to use. - */ - if (priv->enabled && (nm_device_get_firmware_missing (device) == FALSE)) { - if (!priv->supplicant.iface) - supplicant_interface_acquire (self); - } - clear_aps = TRUE; - break; - case NM_DEVICE_STATE_NEED_AUTH: - if (priv->supplicant.iface) - nm_supplicant_interface_disconnect (priv->supplicant.iface); - break; - case NM_DEVICE_STATE_ACTIVATED: - activation_success_handler (device); - break; - case NM_DEVICE_STATE_FAILED: - activation_failure_handler (device); - break; - case NM_DEVICE_STATE_DISCONNECTED: - /* Kick off a scan to get latest results */ - priv->scan_interval = SCAN_INTERVAL_MIN; - cancel_pending_scan (self); - request_wireless_scan (self); - break; - default: - break; - } - - if (clear_aps) - remove_all_aps (self); -} - -NMAccessPoint * -nm_device_wifi_get_activation_ap (NMDeviceWifi *self) -{ - NMActRequest *req; - const char *ap_path; - - g_return_val_if_fail (NM_IS_DEVICE_WIFI (self), NULL); - - req = nm_device_get_act_request (NM_DEVICE (self)); - if (!req) - return NULL; - - ap_path = nm_active_connection_get_specific_object (NM_ACTIVE_CONNECTION (req)); - - return ap_path ? get_ap_by_path (self, ap_path) : NULL; -} - -static void -set_enabled (NMDevice *device, gboolean enabled) -{ - NMDeviceWifi *self = NM_DEVICE_WIFI (device); - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - NMDeviceState state; - - if (priv->enabled == enabled) - return; - - priv->enabled = enabled; - - nm_log_dbg (LOGD_WIFI, "(%s): device now %s", - nm_device_get_iface (NM_DEVICE (device)), - enabled ? "enabled" : "disabled"); - - state = nm_device_get_state (NM_DEVICE (self)); - if (state < NM_DEVICE_STATE_UNAVAILABLE) { - nm_log_dbg (LOGD_WIFI, "(%s): %s blocked by UNMANAGED state", - enabled ? "enable" : "disable", - nm_device_get_iface (NM_DEVICE (device))); - return; - } - - if (enabled) { - gboolean no_firmware = FALSE; - - if (state != NM_DEVICE_STATE_UNAVAILABLE) - nm_log_warn (LOGD_CORE, "not in expected unavailable state!"); - - if (!nm_device_hw_bring_up (NM_DEVICE (self), TRUE, &no_firmware)) { - nm_log_dbg (LOGD_WIFI, "(%s): enable blocked by failure to bring device up", - nm_device_get_iface (NM_DEVICE (device))); - - if (no_firmware) - nm_device_set_firmware_missing (NM_DEVICE (device), TRUE); - else { - /* The device sucks, or the kernel was lying to us about the killswitch state */ - priv->enabled = FALSE; - } - return; - } - - /* Re-initialize the supplicant interface and wait for it to be ready */ - if (priv->supplicant.iface) - supplicant_interface_release (self); - supplicant_interface_acquire (self); - - nm_log_dbg (LOGD_WIFI, "(%s): enable waiting on supplicant state", - nm_device_get_iface (NM_DEVICE (device))); - } else { - nm_device_state_changed (NM_DEVICE (self), - NM_DEVICE_STATE_UNAVAILABLE, - NM_DEVICE_STATE_REASON_NONE); - nm_device_hw_take_down (NM_DEVICE (self), TRUE); - } -} - -/********************************************************************/ - -NMDevice * -nm_device_wifi_new (const char *udi, - const char *iface, - const char *driver) -{ - g_return_val_if_fail (udi != NULL, NULL); - g_return_val_if_fail (iface != NULL, NULL); - g_return_val_if_fail (driver != NULL, NULL); - - return (NMDevice *) g_object_new (NM_TYPE_DEVICE_WIFI, - NM_DEVICE_UDI, udi, - NM_DEVICE_IFACE, iface, - NM_DEVICE_DRIVER, driver, - NM_DEVICE_TYPE_DESC, "802.11 WiFi", - NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_WIFI, - NM_DEVICE_RFKILL_TYPE, RFKILL_TYPE_WLAN, - NULL); -} - -static void -nm_device_wifi_init (NMDeviceWifi *self) -{ - NM_DEVICE_WIFI_GET_PRIVATE (self)->mode = NM_802_11_MODE_INFRA; -} - -static void -dispose (GObject *object) -{ - NMDeviceWifi *self = NM_DEVICE_WIFI (object); - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - - if (priv->disposed) { - G_OBJECT_CLASS (nm_device_wifi_parent_class)->dispose (object); - return; - } - - priv->disposed = TRUE; - - if (priv->periodic_source_id) { - g_source_remove (priv->periodic_source_id); - priv->periodic_source_id = 0; - } - - cleanup_association_attempt (self, TRUE); - supplicant_interface_release (self); - - if (priv->supplicant.mgr) { - g_object_unref (priv->supplicant.mgr); - priv->supplicant.mgr = NULL; - } - - set_active_ap (self, NULL); - remove_all_aps (self); - - if (priv->wifi_data) - wifi_utils_deinit (priv->wifi_data); - - g_free (priv->ipw_rfkill_path); - if (priv->ipw_rfkill_id) { - g_source_remove (priv->ipw_rfkill_id); - priv->ipw_rfkill_id = 0; - } - - G_OBJECT_CLASS (nm_device_wifi_parent_class)->dispose (object); -} - -static void -get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) -{ - NMDeviceWifi *device = NM_DEVICE_WIFI (object); - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (device); - - switch (prop_id) { - case PROP_HW_ADDRESS: - g_value_take_string (value, nm_utils_hwaddr_ntoa (&priv->hw_addr, ARPHRD_ETHER)); - break; - case PROP_PERM_HW_ADDRESS: - g_value_take_string (value, nm_utils_hwaddr_ntoa (&priv->perm_hw_addr, ARPHRD_ETHER)); - break; - case PROP_MODE: - g_value_set_uint (value, priv->mode); - break; - case PROP_BITRATE: - g_value_set_uint (value, priv->rate); - break; - case PROP_CAPABILITIES: - g_value_set_uint (value, priv->capabilities); - break; - case PROP_ACTIVE_ACCESS_POINT: - if (priv->current_ap) - g_value_set_boxed (value, nm_ap_get_dbus_path (priv->current_ap)); - else - g_value_set_boxed (value, "/"); - break; - case PROP_SCANNING: - g_value_set_boolean (value, nm_supplicant_interface_get_scanning (priv->supplicant.iface)); - break; - case PROP_IPW_RFKILL_STATE: - g_value_set_uint (value, nm_device_wifi_get_ipw_rfkill_state (device)); - 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) -{ - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (object); - - switch (prop_id) { - case PROP_IPW_RFKILL_STATE: - /* construct only */ - priv->ipw_rfkill_state = g_value_get_uint (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - - -static void -nm_device_wifi_class_init (NMDeviceWifiClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass); - - g_type_class_add_private (object_class, sizeof (NMDeviceWifiPrivate)); - - object_class->constructor = constructor; - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->dispose = dispose; - - parent_class->get_type_capabilities = get_type_capabilities; - parent_class->get_generic_capabilities = get_generic_capabilities; - parent_class->hw_bring_up = hw_bring_up; - parent_class->is_up = is_up; - parent_class->bring_up = bring_up; - parent_class->take_down = take_down; - parent_class->update_hw_address = update_hw_address; - parent_class->get_hw_address = get_hw_address; - parent_class->update_permanent_hw_address = update_permanent_hw_address; - parent_class->update_initial_hw_address = update_initial_hw_address; - parent_class->get_best_auto_connection = get_best_auto_connection; - parent_class->is_available = is_available; - parent_class->check_connection_compatible = check_connection_compatible; - parent_class->check_connection_available = check_connection_available; - parent_class->complete_connection = complete_connection; - parent_class->set_enabled = set_enabled; - - parent_class->act_stage1_prepare = act_stage1_prepare; - parent_class->act_stage2_config = act_stage2_config; - parent_class->ip4_config_pre_commit = ip4_config_pre_commit; - parent_class->act_stage4_ip4_config_timeout = act_stage4_ip4_config_timeout; - parent_class->act_stage4_ip6_config_timeout = act_stage4_ip6_config_timeout; - parent_class->deactivate = deactivate; - parent_class->can_interrupt_activation = can_interrupt_activation; - parent_class->spec_match_list = spec_match_list; - parent_class->hwaddr_matches = hwaddr_matches; - - parent_class->state_changed = device_state_changed; - - klass->scanning_allowed = scanning_allowed; - - /* Properties */ - g_object_class_install_property (object_class, PROP_HW_ADDRESS, - g_param_spec_string (NM_DEVICE_WIFI_HW_ADDRESS, - "Active MAC Address", - "Currently set hardware MAC address", - NULL, - G_PARAM_READABLE)); - - g_object_class_install_property (object_class, PROP_PERM_HW_ADDRESS, - g_param_spec_string (NM_DEVICE_WIFI_PERMANENT_HW_ADDRESS, - "Permanent MAC Address", - "Permanent hardware MAC address", - NULL, - G_PARAM_READABLE)); - - g_object_class_install_property (object_class, PROP_MODE, - g_param_spec_uint (NM_DEVICE_WIFI_MODE, - "Mode", - "Mode", - NM_802_11_MODE_UNKNOWN, - NM_802_11_MODE_AP, - NM_802_11_MODE_INFRA, - G_PARAM_READABLE)); - - g_object_class_install_property (object_class, PROP_BITRATE, - g_param_spec_uint (NM_DEVICE_WIFI_BITRATE, - "Bitrate", - "Bitrate", - 0, G_MAXUINT32, 0, - G_PARAM_READABLE)); - - g_object_class_install_property (object_class, PROP_ACTIVE_ACCESS_POINT, - g_param_spec_boxed (NM_DEVICE_WIFI_ACTIVE_ACCESS_POINT, - "Active access point", - "Currently active access point", - DBUS_TYPE_G_OBJECT_PATH, - G_PARAM_READABLE)); - - g_object_class_install_property (object_class, PROP_CAPABILITIES, - g_param_spec_uint (NM_DEVICE_WIFI_CAPABILITIES, - "Wireless Capabilities", - "Wireless Capabilities", - 0, G_MAXUINT32, NM_WIFI_DEVICE_CAP_NONE, - G_PARAM_READABLE)); - - g_object_class_install_property (object_class, PROP_SCANNING, - g_param_spec_boolean (NM_DEVICE_WIFI_SCANNING, - "Scanning", - "Scanning", - FALSE, - G_PARAM_READABLE | NM_PROPERTY_PARAM_NO_EXPORT)); - - g_object_class_install_property (object_class, PROP_IPW_RFKILL_STATE, - g_param_spec_uint (NM_DEVICE_WIFI_IPW_RFKILL_STATE, - "IpwRfkillState", - "ipw rf-kill state", - RFKILL_UNBLOCKED, RFKILL_HARD_BLOCKED, RFKILL_UNBLOCKED, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | NM_PROPERTY_PARAM_NO_EXPORT)); - - /* Signals */ - signals[ACCESS_POINT_ADDED] = - g_signal_new ("access-point-added", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMDeviceWifiClass, access_point_added), - NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, - G_TYPE_OBJECT); - - signals[ACCESS_POINT_REMOVED] = - g_signal_new ("access-point-removed", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - 0, - NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, - G_TYPE_OBJECT); - - signals[HIDDEN_AP_FOUND] = - g_signal_new ("hidden-ap-found", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMDeviceWifiClass, hidden_ap_found), - NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, - G_TYPE_OBJECT); - - signals[PROPERTIES_CHANGED] = - nm_properties_changed_signal_new (object_class, - G_STRUCT_OFFSET (NMDeviceWifiClass, properties_changed)); - - signals[SCANNING_ALLOWED] = - g_signal_new ("scanning-allowed", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMDeviceWifiClass, scanning_allowed), - scanning_allowed_accumulator, NULL, - _nm_marshal_BOOLEAN__VOID, - G_TYPE_BOOLEAN, 0); - - dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass), &dbus_glib_nm_device_wifi_object_info); - - dbus_g_error_domain_register (NM_WIFI_ERROR, NULL, NM_TYPE_WIFI_ERROR); -} - - diff --git a/src/nm-device-wifi.h b/src/nm-device-wifi.h deleted file mode 100644 index 368d0b80..00000000 --- a/src/nm-device-wifi.h +++ /dev/null @@ -1,104 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2005 - 2010 Red Hat, Inc. - * Copyright (C) 2006 - 2008 Novell, Inc. - */ - -#ifndef NM_DEVICE_WIFI_H -#define NM_DEVICE_WIFI_H - -#include -#include -#include - -#include "nm-rfkill.h" -#include "nm-device.h" -#include "nm-wifi-ap.h" - -struct NMAccessPointList; - -G_BEGIN_DECLS - -#define NM_TYPE_DEVICE_WIFI (nm_device_wifi_get_type ()) -#define NM_DEVICE_WIFI(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_WIFI, NMDeviceWifi)) -#define NM_DEVICE_WIFI_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_WIFI, NMDeviceWifiClass)) -#define NM_IS_DEVICE_WIFI(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_WIFI)) -#define NM_IS_DEVICE_WIFI_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_WIFI)) -#define NM_DEVICE_WIFI_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_WIFI, NMDeviceWifiClass)) - -typedef enum { - NM_WIFI_ERROR_CONNECTION_NOT_WIRELESS = 0, /*< nick=ConnectionNotWireless >*/ - NM_WIFI_ERROR_CONNECTION_INVALID, /*< nick=ConnectionInvalid >*/ - NM_WIFI_ERROR_CONNECTION_INCOMPATIBLE, /*< nick=ConnectionIncompatible >*/ - NM_WIFI_ERROR_ACCESS_POINT_NOT_FOUND, /*< nick=AccessPointNotFound >*/ - NM_WIFI_ERROR_SCAN_NOT_ALLOWED, /*< nick=ScanNotAllowed >*/ - NM_WIFI_ERROR_AP_MODE_UNSUPPORTED, /*< nick=ApModeUnsupported >*/ - NM_WIFI_ERROR_ADHOC_MODE_UNSUPPORTED, /*< nick=AdhocModeUnsupported >*/ -} NMWifiError; - -#define NM_DEVICE_WIFI_HW_ADDRESS "hw-address" -#define NM_DEVICE_WIFI_PERMANENT_HW_ADDRESS "perm-hw-address" -#define NM_DEVICE_WIFI_MODE "mode" -#define NM_DEVICE_WIFI_BITRATE "bitrate" -#define NM_DEVICE_WIFI_ACTIVE_ACCESS_POINT "active-access-point" -#define NM_DEVICE_WIFI_CAPABILITIES "wireless-capabilities" -#define NM_DEVICE_WIFI_SCANNING "scanning" -#define NM_DEVICE_WIFI_IPW_RFKILL_STATE "ipw-rfkill-state" - -#ifndef NM_DEVICE_WIFI_DEFINED -#define NM_DEVICE_WIFI_DEFINED -typedef struct _NMDeviceWifi NMDeviceWifi; -#endif - -typedef struct _NMDeviceWifiClass NMDeviceWifiClass; -typedef struct _NMDeviceWifiPrivate NMDeviceWifiPrivate; - -struct _NMDeviceWifi -{ - NMDevice parent; - - /*< private >*/ - NMDeviceWifiPrivate *priv; -}; - -struct _NMDeviceWifiClass -{ - NMDeviceClass parent; - - /* Signals */ - void (*access_point_added) (NMDeviceWifi *device, NMAccessPoint *ap); - void (*access_point_removed) (NMDeviceWifi *device, NMAccessPoint *ap); - void (*hidden_ap_found) (NMDeviceWifi *device, NMAccessPoint *ap); - void (*properties_changed) (NMDeviceWifi *device, GHashTable *properties); - gboolean (*scanning_allowed) (NMDeviceWifi *device); -}; - - -GType nm_device_wifi_get_type (void); - -NMDevice *nm_device_wifi_new (const char *udi, - const char *iface, - const char *driver); - -NMAccessPoint * nm_device_wifi_get_activation_ap (NMDeviceWifi *self); - -RfKillState nm_device_wifi_get_ipw_rfkill_state (NMDeviceWifi *self); - -G_END_DECLS - -#endif /* NM_DEVICE_WIFI_H */ diff --git a/src/nm-device-wired.c b/src/nm-device-wired.c deleted file mode 100644 index 5baf5f87..00000000 --- a/src/nm-device-wired.c +++ /dev/null @@ -1,564 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2005 - 2012 Red Hat, Inc. - * Copyright (C) 2006 - 2008 Novell, Inc. - */ - -#include "config.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "nm-device-wired.h" -#include "nm-device-private.h" -#include "nm-dhcp-manager.h" -#include "nm-logging.h" -#include "nm-netlink-monitor.h" -#include "nm-netlink-utils.h" -#include "nm-system.h" -#include "nm-utils.h" -#include "NetworkManagerUtils.h" - - -G_DEFINE_TYPE (NMDeviceWired, nm_device_wired, NM_TYPE_DEVICE) - -#define NM_DEVICE_WIRED_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_WIRED, NMDeviceWiredPrivate)) - -#define NM_DEVICE_WIRED_LOG_LEVEL(dev) ((nm_device_get_device_type (dev) == NM_DEVICE_TYPE_INFINIBAND) ? LOGD_INFINIBAND : LOGD_ETHER) - -typedef struct { - gboolean carrier; - guint32 speed; - - NMNetlinkMonitor * monitor; - gulong link_connected_id; - gulong link_disconnected_id; - guint carrier_action_defer_id; - -} NMDeviceWiredPrivate; - - -/* Returns speed in Mb/s */ -static guint32 -ethtool_get_speed (NMDeviceWired *self) -{ - int fd; - struct ifreq ifr; - struct ethtool_cmd edata = { - .cmd = ETHTOOL_GSET, - }; - guint32 speed = 0; - - g_return_val_if_fail (self != NULL, 0); - - fd = socket (PF_INET, SOCK_DGRAM, 0); - if (fd < 0) { - nm_log_warn (LOGD_HW, "couldn't open control socket."); - return 0; - } - - memset (&ifr, 0, sizeof (struct ifreq)); - strncpy (ifr.ifr_name, nm_device_get_iface (NM_DEVICE (self)), IFNAMSIZ); - ifr.ifr_data = (char *) &edata; - - if (ioctl (fd, SIOCETHTOOL, &ifr) < 0) - goto out; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) - speed = edata.speed; -#else - speed = ethtool_cmd_speed (&edata); -#endif - - if (speed == G_MAXUINT16 || speed == G_MAXUINT32) - speed = 0; - -out: - close (fd); - return speed; -} - -static void -set_speed (NMDeviceWired *self, const guint32 speed) -{ - NMDeviceWiredPrivate *priv; - - g_return_if_fail (NM_IS_DEVICE (self)); - - priv = NM_DEVICE_WIRED_GET_PRIVATE (self); - if (priv->speed == speed) - return; - - priv->speed = speed; - g_object_notify (G_OBJECT (self), "speed"); - - nm_log_dbg (LOGD_HW | NM_DEVICE_WIRED_LOG_LEVEL (NM_DEVICE (self)), - "(%s): speed is now %d Mb/s", - nm_device_get_iface (NM_DEVICE (self)), - speed); -} - -static void -carrier_action_defer_clear (NMDeviceWired *self) -{ - NMDeviceWiredPrivate *priv = NM_DEVICE_WIRED_GET_PRIVATE (self); - - if (priv->carrier_action_defer_id) { - g_source_remove (priv->carrier_action_defer_id); - priv->carrier_action_defer_id = 0; - } -} - -static void -carrier_action (NMDeviceWired *self, NMDeviceState state, gboolean carrier) -{ - NMDevice *device = NM_DEVICE (self); - - if (state == NM_DEVICE_STATE_UNAVAILABLE) { - if (carrier) - nm_device_queue_state (device, NM_DEVICE_STATE_DISCONNECTED, NM_DEVICE_STATE_REASON_CARRIER); - else { - /* clear any queued state changes if they wouldn't be valid when the - * carrier is off. - */ - if (nm_device_queued_state_peek (device) >= NM_DEVICE_STATE_DISCONNECTED) - nm_device_queued_state_clear (device); - } - } else if (state >= NM_DEVICE_STATE_DISCONNECTED) { - if (!carrier && !nm_device_get_enslaved (device)) - nm_device_queue_state (device, NM_DEVICE_STATE_UNAVAILABLE, NM_DEVICE_STATE_REASON_CARRIER); - } -} - -static gboolean -carrier_action_defer_cb (gpointer user_data) -{ - NMDeviceWired *self = NM_DEVICE_WIRED (user_data); - NMDeviceWiredPrivate *priv = NM_DEVICE_WIRED_GET_PRIVATE (self); - - priv->carrier_action_defer_id = 0; - NM_DEVICE_WIRED_GET_CLASS (self)->carrier_action (self, - nm_device_get_state (NM_DEVICE (self)), - priv->carrier); - return FALSE; -} - -static void -set_carrier (NMDeviceWired *self, - const gboolean carrier, - const gboolean defer_action) -{ - NMDeviceWiredPrivate *priv = NM_DEVICE_WIRED_GET_PRIVATE (self); - NMDevice *device = NM_DEVICE (self); - NMDeviceState state; - guint32 caps; - - if (priv->carrier == carrier) - return; - - /* Clear any previous deferred action */ - carrier_action_defer_clear (self); - - /* Warn if we try to set carrier down on a device that - * doesn't support carrier detect. These devices assume - * the carrier is always up. - */ - caps = nm_device_get_capabilities (device); - g_return_if_fail (caps & NM_DEVICE_CAP_CARRIER_DETECT); - - priv->carrier = carrier; - - state = nm_device_get_state (device); - if (state >= NM_DEVICE_STATE_UNAVAILABLE) { - nm_log_info (LOGD_HW | NM_DEVICE_WIRED_LOG_LEVEL (device), - "(%s): carrier now %s (device state %d%s)", - nm_device_get_iface (device), - carrier ? "ON" : "OFF", - state, - defer_action ? ", deferring action for 4 seconds" : ""); - } - - g_object_notify (G_OBJECT (self), "carrier"); - - /* Retry IP configuration for master devices now that the carrier is on */ - if (nm_device_is_master (device) && priv->carrier) { - if (nm_device_activate_ip4_state_in_wait (device)) - nm_device_activate_stage3_ip4_start (device); - - if (nm_device_activate_ip6_state_in_wait (device)) - nm_device_activate_stage3_ip6_start (device); - } - - if (defer_action) - priv->carrier_action_defer_id = g_timeout_add_seconds (4, carrier_action_defer_cb, self); - else - carrier_action_defer_cb (self); -} - -static void -carrier_on (NMNetlinkMonitor *monitor, - int idx, - gpointer user_data) -{ - NMDevice *device = NM_DEVICE (user_data); - NMDeviceWired *self = NM_DEVICE_WIRED (device); - guint32 caps; - - /* Make sure signal is for us */ - if (idx == nm_device_get_ifindex (device)) { - caps = nm_device_get_capabilities (device); - g_return_if_fail (caps & NM_DEVICE_CAP_CARRIER_DETECT); - - set_carrier (self, TRUE, FALSE); - set_speed (self, ethtool_get_speed (self)); - } -} - -static void -carrier_off (NMNetlinkMonitor *monitor, - int idx, - gpointer user_data) -{ - NMDevice *device = NM_DEVICE (user_data); - NMDeviceWired *self = NM_DEVICE_WIRED (device); - guint32 caps; - - /* Make sure signal is for us */ - if (idx == nm_device_get_ifindex (device)) { - NMDeviceState state; - gboolean defer = FALSE; - - caps = nm_device_get_capabilities (device); - g_return_if_fail (caps & NM_DEVICE_CAP_CARRIER_DETECT); - - /* Defer carrier-off event actions while connected by a few seconds - * so that tripping over a cable, power-cycling a switch, or breaking - * off the RJ45 locking tab isn't so catastrophic. - */ - state = nm_device_get_state (device); - if (state > NM_DEVICE_STATE_DISCONNECTED) - defer = TRUE; - - set_carrier (self, FALSE, defer); - } -} - -static gboolean -get_carrier_sync (NMDeviceWired *self) -{ - NMDeviceWiredPrivate *priv = NM_DEVICE_WIRED_GET_PRIVATE (self); - GError *error = NULL; - guint32 ifflags = 0; - - /* Get initial link state */ - if (!nm_netlink_monitor_get_flags_sync (priv->monitor, - nm_device_get_ip_ifindex (NM_DEVICE (self)), - &ifflags, - &error)) { - nm_log_warn (LOGD_HW | NM_DEVICE_WIRED_LOG_LEVEL (NM_DEVICE (self)), - "(%s): couldn't get carrier state: (%d) %s", - nm_device_get_ip_iface (NM_DEVICE (self)), - error ? error->code : -1, - (error && error->message) ? error->message : "unknown"); - g_clear_error (&error); - } - - return !!(ifflags & IFF_LOWER_UP); -} - -static GObject* -constructor (GType type, - guint n_construct_params, - GObjectConstructParam *construct_params) -{ - GObject *object; - NMDeviceWiredPrivate *priv; - NMDevice *self; - guint32 caps; - - object = G_OBJECT_CLASS (nm_device_wired_parent_class)->constructor (type, - n_construct_params, - construct_params); - if (!object) - return NULL; - - self = NM_DEVICE (object); - priv = NM_DEVICE_WIRED_GET_PRIVATE (self); - - nm_log_dbg (LOGD_HW | NM_DEVICE_WIRED_LOG_LEVEL (NM_DEVICE (self)), - "(%s): kernel ifindex %d", - nm_device_get_iface (NM_DEVICE (self)), - nm_device_get_ifindex (NM_DEVICE (self))); - - caps = nm_device_get_capabilities (self); - if (caps & NM_DEVICE_CAP_CARRIER_DETECT) { - /* Only listen to netlink for cards that support carrier detect */ - priv->monitor = nm_netlink_monitor_get (); - - priv->link_connected_id = g_signal_connect (priv->monitor, "carrier-on", - G_CALLBACK (carrier_on), - self); - priv->link_disconnected_id = g_signal_connect (priv->monitor, "carrier-off", - G_CALLBACK (carrier_off), - self); - - priv->carrier = get_carrier_sync (NM_DEVICE_WIRED (self)); - - nm_log_info (LOGD_HW | NM_DEVICE_WIRED_LOG_LEVEL (NM_DEVICE (self)), - "(%s): carrier is %s", - nm_device_get_iface (NM_DEVICE (self)), - priv->carrier ? "ON" : "OFF"); - - /* Request link state again just in case an error occurred getting the - * initial link state. - */ - nm_netlink_monitor_request_status (priv->monitor); - } else { - nm_log_info (LOGD_HW | NM_DEVICE_WIRED_LOG_LEVEL (NM_DEVICE (self)), - "(%s): driver '%s' does not support carrier detection.", - nm_device_get_iface (self), - nm_device_get_driver (self)); - priv->carrier = TRUE; - } - - return object; -} - -static void -nm_device_wired_init (NMDeviceWired * self) -{ -} - -static gboolean -hw_bring_up (NMDevice *dev, gboolean *no_firmware) -{ - gboolean result, carrier; - guint32 caps; - - result = NM_DEVICE_CLASS(nm_device_wired_parent_class)->hw_bring_up (dev, no_firmware); - if (result) { - caps = nm_device_get_capabilities (dev); - if (caps & NM_DEVICE_CAP_CARRIER_DETECT) { - carrier = get_carrier_sync (NM_DEVICE_WIRED (dev)); - set_carrier (NM_DEVICE_WIRED (dev), carrier, carrier ? FALSE : TRUE); - } - } - return result; -} - -static gboolean -can_interrupt_activation (NMDevice *dev) -{ - NMDeviceWired *self = NM_DEVICE_WIRED (dev); - gboolean interrupt = FALSE; - - /* Devices that support carrier detect can interrupt activation - * if the link becomes inactive. - */ - if (nm_device_get_capabilities (dev) & NM_DEVICE_CAP_CARRIER_DETECT) { - if (NM_DEVICE_WIRED_GET_PRIVATE (self)->carrier == FALSE) - interrupt = TRUE; - } - return interrupt; -} - -static gboolean -is_available (NMDevice *dev) -{ - NMDeviceWired *self = NM_DEVICE_WIRED (dev); - - /* Can't do anything if there isn't a carrier */ - if (!NM_DEVICE_WIRED_GET_PRIVATE (self)->carrier) - return FALSE; - - return TRUE; -} - -static NMConnection * -connection_match_config (NMDevice *self, const GSList *connections) -{ - const GSList *iter; - - for (iter = connections; iter; iter = iter->next) { - NMConnection *candidate = NM_CONNECTION (iter->data); - - if (!nm_device_match_ip_config (self, candidate)) - continue; - - return candidate; - } - - return NULL; -} - -static NMActStageReturn -act_stage3_ip4_config_start (NMDevice *device, - NMIP4Config **out_config, - NMDeviceStateReason *reason) -{ - NMConnection *connection; - NMSettingIP4Config *s_ip4; - const char *method = NULL; - gboolean is_manual = FALSE; - - connection = nm_device_get_connection (device); - if (connection) { - s_ip4 = nm_connection_get_setting_ip4_config (connection); - if (s_ip4) - method = nm_setting_ip4_config_get_method (s_ip4); - - if (g_strcmp0 (method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL) == 0) - is_manual = TRUE; - } - - if ( !is_manual - && nm_device_is_master (device) - && !nm_device_wired_get_carrier (NM_DEVICE_WIRED (device))) { - nm_log_info (LOGD_IP4 | NM_DEVICE_WIRED_LOG_LEVEL (device), - "(%s): IPv4 config waiting until carrier is on", - nm_device_get_ip_iface (device)); - return NM_ACT_STAGE_RETURN_WAIT; - } - - return NM_DEVICE_CLASS (nm_device_wired_parent_class)->act_stage3_ip4_config_start (device, out_config, reason); -} - -static NMActStageReturn -act_stage3_ip6_config_start (NMDevice *device, - NMIP6Config **out_config, - NMDeviceStateReason *reason) -{ - NMConnection *connection; - NMSettingIP6Config *s_ip6; - const char *method = NULL; - gboolean is_manual = FALSE; - - connection = nm_device_get_connection (device); - if (connection) { - s_ip6 = nm_connection_get_setting_ip6_config (connection); - if (s_ip6) - method = nm_setting_ip6_config_get_method (s_ip6); - - if (g_strcmp0 (method, NM_SETTING_IP6_CONFIG_METHOD_MANUAL) == 0) - is_manual = TRUE; - } - - if ( !is_manual - && nm_device_is_master (device) - && !nm_device_wired_get_carrier (NM_DEVICE_WIRED (device))) { - nm_log_info (LOGD_IP6 | NM_DEVICE_WIRED_LOG_LEVEL (device), - "(%s): IPv6 config waiting until carrier is on", - nm_device_get_ip_iface (device)); - return NM_ACT_STAGE_RETURN_WAIT; - } - - return NM_DEVICE_CLASS (nm_device_wired_parent_class)->act_stage3_ip6_config_start (device, out_config, reason); -} - -static void -dispose (GObject *object) -{ - NMDeviceWired *self = NM_DEVICE_WIRED (object); - NMDeviceWiredPrivate *priv = NM_DEVICE_WIRED_GET_PRIVATE (self); - - if (priv->link_connected_id) { - g_signal_handler_disconnect (priv->monitor, priv->link_connected_id); - priv->link_connected_id = 0; - } - if (priv->link_disconnected_id) { - g_signal_handler_disconnect (priv->monitor, priv->link_disconnected_id); - priv->link_disconnected_id = 0; - } - - carrier_action_defer_clear (self); - - if (priv->monitor) { - g_object_unref (priv->monitor); - priv->monitor = NULL; - } - - G_OBJECT_CLASS (nm_device_wired_parent_class)->dispose (object); -} - -static void -nm_device_wired_class_init (NMDeviceWiredClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass); - NMDeviceWiredClass *wired_class = NM_DEVICE_WIRED_CLASS (klass); - - g_type_class_add_private (object_class, sizeof (NMDeviceWiredPrivate)); - - /* virtual methods */ - object_class->constructor = constructor; - object_class->dispose = dispose; - - parent_class->hw_bring_up = hw_bring_up; - parent_class->can_interrupt_activation = can_interrupt_activation; - parent_class->is_available = is_available; - parent_class->connection_match_config = connection_match_config; - parent_class->act_stage3_ip4_config_start = act_stage3_ip4_config_start; - parent_class->act_stage3_ip6_config_start = act_stage3_ip6_config_start; - - wired_class->carrier_action = carrier_action; -} - -/** - * nm_device_wired_get_carrier: - * @dev: an #NMDeviceWired - * - * Get @dev's carrier status - * - * Return value: @dev's carrier - */ -gboolean -nm_device_wired_get_carrier (NMDeviceWired *dev) -{ - NMDeviceWiredPrivate *priv; - - g_return_val_if_fail (dev != NULL, FALSE); - - priv = NM_DEVICE_WIRED_GET_PRIVATE (dev); - return priv->carrier; -} - -/** - * nm_device_wired_get_speed: - * @dev: an #NMDeviceWired - * - * Get @dev's speed - * - * Return value: @dev's speed in Mb/s - */ -guint32 -nm_device_wired_get_speed (NMDeviceWired *dev) -{ - NMDeviceWiredPrivate *priv; - - g_return_val_if_fail (dev != NULL, 0); - - priv = NM_DEVICE_WIRED_GET_PRIVATE (dev); - return priv->speed; -} diff --git a/src/nm-device-wired.h b/src/nm-device-wired.h deleted file mode 100644 index a8084352..00000000 --- a/src/nm-device-wired.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2005 - 2012 Red Hat, Inc. - * Copyright (C) 2006 - 2008 Novell, Inc. - */ - -#ifndef NM_DEVICE_WIRED_H -#define NM_DEVICE_WIRED_H - -#include - -#include "nm-device.h" - -G_BEGIN_DECLS - -#define NM_TYPE_DEVICE_WIRED (nm_device_wired_get_type ()) -#define NM_DEVICE_WIRED(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_WIRED, NMDeviceWired)) -#define NM_DEVICE_WIRED_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_WIRED, NMDeviceWiredClass)) -#define NM_IS_DEVICE_WIRED(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_WIRED)) -#define NM_IS_DEVICE_WIRED_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_WIRED)) -#define NM_DEVICE_WIRED_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_WIRED, NMDeviceWiredClass)) - -typedef struct { - NMDevice parent; -} NMDeviceWired; - -typedef struct { - NMDeviceClass parent; - - void (*carrier_action) (NMDeviceWired *self, - NMDeviceState state, - gboolean carrier); -} NMDeviceWiredClass; - -GType nm_device_wired_get_type (void); - -gboolean nm_device_wired_get_carrier (NMDeviceWired *dev); -guint32 nm_device_wired_get_speed (NMDeviceWired *dev); - -G_END_DECLS - -#endif /* NM_DEVICE_WIRED_H */ diff --git a/src/nm-device.c b/src/nm-device.c deleted file mode 100644 index a07ef338..00000000 --- a/src/nm-device.c +++ /dev/null @@ -1,5706 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2005 - 2012 Red Hat, Inc. - * Copyright (C) 2006 - 2008 Novell, Inc. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "nm-glib-compat.h" -#include "nm-device.h" -#include "nm-device-private.h" -#include "nm-device-ethernet.h" -#include "NetworkManagerUtils.h" -#include "nm-system.h" -#include "nm-dhcp-manager.h" -#include "nm-dbus-manager.h" -#include "nm-utils.h" -#include "nm-logging.h" -#include "nm-netlink-monitor.h" -#include "nm-netlink-utils.h" -#include "nm-netlink-compat.h" -#include "nm-setting-ip4-config.h" -#include "nm-setting-ip6-config.h" -#include "nm-setting-connection.h" -#include "nm-dnsmasq-manager.h" -#include "nm-dhcp4-config.h" -#include "nm-ip6-manager.h" -#include "nm-marshal.h" -#include "nm-rfkill.h" -#include "nm-firewall-manager.h" -#include "nm-properties-changed-signal.h" -#include "nm-enum-types.h" -#include "nm-settings-connection.h" -#include "nm-connection-provider.h" -#include "nm-posix-signals.h" -#include "nm-manager-auth.h" -#include "nm-dbus-glib-types.h" -#include "nm-dispatcher.h" - -static void impl_device_disconnect (NMDevice *device, DBusGMethodInvocation *context); - -#include "nm-device-interface-glue.h" - -#define PENDING_IP4_CONFIG "pending-ip4-config" -#define PENDING_IP6_CONFIG "pending-ip6-config" - -#define DBUS_G_TYPE_UINT_STRUCT (dbus_g_type_get_struct ("GValueArray", G_TYPE_UINT, G_TYPE_UINT, G_TYPE_INVALID)) - -/***********************************************************/ -#define NM_DEVICE_ERROR (nm_device_error_quark ()) - -static GQuark -nm_device_error_quark (void) -{ - static GQuark quark = 0; - if (!quark) - quark = g_quark_from_static_string ("nm-device-error"); - return quark; -} - -/***********************************************************/ - -enum { - STATE_CHANGED, - AUTOCONNECT_ALLOWED, - AUTH_REQUEST, - IP4_CONFIG_CHANGED, - IP6_CONFIG_CHANGED, - LAST_SIGNAL, -}; -static guint signals[LAST_SIGNAL] = { 0 }; - -enum { - PROP_0, - PROP_UDI, - PROP_IFACE, - PROP_IP_IFACE, - PROP_DRIVER, - PROP_DRIVER_VERSION, - PROP_FIRMWARE_VERSION, - PROP_CAPABILITIES, - PROP_IP4_ADDRESS, - PROP_IP4_CONFIG, - PROP_DHCP4_CONFIG, - PROP_IP6_CONFIG, - PROP_DHCP6_CONFIG, - PROP_STATE, - PROP_STATE_REASON, - PROP_ACTIVE_CONNECTION, - PROP_DEVICE_TYPE, - PROP_MANAGED, - PROP_AUTOCONNECT, - PROP_FIRMWARE_MISSING, - PROP_TYPE_DESC, - PROP_RFKILL_TYPE, - PROP_IFINDEX, - PROP_AVAILABLE_CONNECTIONS, - PROP_IS_MASTER, - LAST_PROP -}; - -#define DEFAULT_AUTOCONNECT TRUE - -/***********************************************************/ - -G_DEFINE_ABSTRACT_TYPE (NMDevice, nm_device, G_TYPE_OBJECT) - -#define NM_DEVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE, NMDevicePrivate)) - -typedef enum { - IP_NONE = 0, - IP_WAIT, - IP_CONF, - IP_DONE -} IpState; - -typedef struct { - NMDeviceState state; - NMDeviceStateReason reason; - guint id; -} QueuedState; - -typedef struct { - NMDevice *slave; - gboolean enslaved; - guint watch_id; -} SlaveInfo; - -typedef struct { - gboolean disposed; - gboolean initialized; - - NMDeviceState state; - NMDeviceStateReason state_reason; - QueuedState queued_state; - - char * udi; - char * path; - char * iface; /* may change, could be renamed by user */ - int ifindex; - char * ip_iface; - int ip_ifindex; - NMDeviceType type; - char * type_desc; - guint32 capabilities; - char * driver; - char * driver_version; - char * firmware_version; - gboolean managed; /* whether managed by NM or not */ - RfKillType rfkill_type; - gboolean firmware_missing; - GHashTable * available_connections; - - guint32 ip4_address; - - NMActRequest * act_request; - guint act_source_id; - gpointer act_source_func; - guint act_source6_id; - gpointer act_source6_func; - gulong secrets_updated_id; - gulong secrets_failed_id; - - /* Generic DHCP stuff */ - NMDHCPManager * dhcp_manager; - guint32 dhcp_timeout; - GByteArray * dhcp_anycast_address; - - /* IP4 configuration info */ - NMIP4Config * ip4_config; /* Config from DHCP, PPP, or system config files */ - IpState ip4_state; - NMDHCPClient * dhcp4_client; - gulong dhcp4_state_sigid; - gulong dhcp4_timeout_sigid; - NMDHCP4Config * dhcp4_config; - - /* dnsmasq stuff for shared connections */ - NMDnsMasqManager *dnsmasq_manager; - gulong dnsmasq_state_id; - - /* Firewall Manager */ - NMFirewallManager *fw_manager; - DBusGProxyCall *fw_call; - - /* avahi-autoipd stuff */ - GPid aipd_pid; - guint aipd_watch; - guint aipd_timeout; - - /* IP6 configuration info */ - NMIP6Config * ip6_config; - IpState ip6_state; - - NMIP6Manager * ip6_manager; - gulong ip6_addrconf_sigid; - gulong ip6_config_changed_sigid; - gboolean ip6_waiting_for_config; - /* IP6 config from autoconf */ - NMIP6Config * ac_ip6_config; - - char * ip6_accept_ra_path; - gint32 ip6_accept_ra_save; - - /* IPv6 privacy extensions (RFC4941) */ - char * ip6_privacy_tempaddr_path; - gint32 ip6_privacy_tempaddr_save; - - NMDHCPClient * dhcp6_client; - guint32 dhcp6_mode; - gulong dhcp6_state_sigid; - gulong dhcp6_timeout_sigid; - NMDHCP6Config * dhcp6_config; - /* IP6 config from DHCP */ - NMIP6Config * dhcp6_ip6_config; - - /* allow autoconnect feature */ - gboolean autoconnect; - - /* master interface for bridge/bond slave */ - NMDevice * master; - gboolean enslaved; - - /* slave management */ - gboolean is_master; - GSList * slaves; /* list of SlaveInfo */ - - NMConnectionProvider *con_provider; - - /* connection provider signals for available connections property */ - guint cp_added_id; - guint cp_loaded_id; - guint cp_removed_id; - guint cp_updated_id; -} NMDevicePrivate; - -static void nm_device_take_down (NMDevice *dev, gboolean wait, NMDeviceStateReason reason); - -static gboolean nm_device_bring_up (NMDevice *self, gboolean block, gboolean *no_firmware); -static gboolean nm_device_is_up (NMDevice *self); - -static gboolean nm_device_set_ip4_config (NMDevice *dev, - NMIP4Config *config, - gboolean assumed, - NMDeviceStateReason *reason); -static gboolean nm_device_set_ip6_config (NMDevice *dev, - NMIP6Config *config, - NMDeviceStateReason *reason); - -static gboolean nm_device_activate_ip6_config_commit (gpointer user_data); - -static gboolean check_connection_available (NMDevice *device, NMConnection *connection); - -static void _clear_available_connections (NMDevice *device, gboolean do_signal); - -static void dhcp4_cleanup (NMDevice *self, gboolean stop, gboolean release); - -static const char *reason_to_string (NMDeviceStateReason reason); - -static void cp_connection_added (NMConnectionProvider *cp, NMConnection *connection, gpointer user_data); -static void cp_connections_loaded (NMConnectionProvider *cp, NMConnection *connection, gpointer user_data); -static void cp_connection_removed (NMConnectionProvider *cp, NMConnection *connection, gpointer user_data); -static void cp_connection_updated (NMConnectionProvider *cp, NMConnection *connection, gpointer user_data); - -static const char *state_to_string (NMDeviceState state); - -static void -nm_device_init (NMDevice *self) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - - priv->type = NM_DEVICE_TYPE_UNKNOWN; - priv->capabilities = NM_DEVICE_CAP_NONE; - priv->state = NM_DEVICE_STATE_UNMANAGED; - priv->state_reason = NM_DEVICE_STATE_REASON_NONE; - priv->dhcp_timeout = 0; - priv->rfkill_type = RFKILL_TYPE_UNKNOWN; - priv->autoconnect = DEFAULT_AUTOCONNECT; - priv->available_connections = g_hash_table_new_full (g_direct_hash, g_direct_equal, g_object_unref, NULL); -} - -static void -update_accept_ra_save (NMDevice *self) -{ - NMDevicePrivate *priv; - const char *ip_iface; - char *new_path; - - g_return_if_fail (self != NULL); - g_return_if_fail (NM_IS_DEVICE (self)); - - priv = NM_DEVICE_GET_PRIVATE (self); - ip_iface = nm_device_get_ip_iface (self); - - new_path = g_strdup_printf ("/proc/sys/net/ipv6/conf/%s/accept_ra", ip_iface); - g_assert (new_path); - - if (priv->ip6_accept_ra_path) { - /* If the IP iface is different from before, use the new value */ - if (!strcmp (new_path, priv->ip6_accept_ra_path)) { - g_free (new_path); - return; - } - g_free (priv->ip6_accept_ra_path); - } - - /* Grab the original value of "accept_ra" so we can restore it when NM exits */ - priv->ip6_accept_ra_path = new_path; - if (!nm_utils_get_proc_sys_net_value_with_bounds (priv->ip6_accept_ra_path, - ip_iface, - &priv->ip6_accept_ra_save, - 0, 2)) { - g_free (priv->ip6_accept_ra_path); - priv->ip6_accept_ra_path = NULL; - } -} - -static void -update_ip6_privacy_save (NMDevice *self) -{ - NMDevicePrivate *priv; - const char *ip_iface; - char *new_path; - - g_return_if_fail (self != NULL); - g_return_if_fail (NM_IS_DEVICE (self)); - - priv = NM_DEVICE_GET_PRIVATE (self); - ip_iface = nm_device_get_ip_iface (self); - - new_path = g_strdup_printf ("/proc/sys/net/ipv6/conf/%s/use_tempaddr", ip_iface); - g_assert (new_path); - - if (priv->ip6_privacy_tempaddr_path) { - /* If the IP iface is different from before, use the new value */ - if (!strcmp (new_path, priv->ip6_privacy_tempaddr_path)) { - g_free (new_path); - return; - } - g_free (priv->ip6_privacy_tempaddr_path); - } - - /* Grab the original value of "use_tempaddr" so we can restore it when NM exits */ - priv->ip6_privacy_tempaddr_path = new_path; - if (!nm_utils_get_proc_sys_net_value (priv->ip6_privacy_tempaddr_path, - ip_iface, - &priv->ip6_privacy_tempaddr_save)) { - g_free (priv->ip6_privacy_tempaddr_path); - priv->ip6_privacy_tempaddr_path = NULL; - } -} - -/* - * Get driver info from SIOCETHTOOL ioctl() for 'iface' - * Returns driver and firmware versions to 'driver_version and' 'firmware_version' - */ -static gboolean -device_get_driver_info (const char *iface, char **driver_version, char **firmware_version) -{ - struct ethtool_drvinfo drvinfo; - struct ifreq req; - int fd; - - fd = socket (PF_INET, SOCK_DGRAM, 0); - if (fd < 0) { - nm_log_warn (LOGD_HW, "couldn't open control socket."); - return FALSE; - } - - /* Get driver and firmware version info */ - memset (&drvinfo, 0, sizeof (drvinfo)); - memset (&req, 0, sizeof (struct ifreq)); - strncpy (req.ifr_name, iface, IFNAMSIZ); - drvinfo.cmd = ETHTOOL_GDRVINFO; - req.ifr_data = &drvinfo; - - errno = 0; - if (ioctl (fd, SIOCETHTOOL, &req) < 0) { - nm_log_dbg (LOGD_HW, "SIOCETHTOOL ioctl() failed: cmd=ETHTOOL_GDRVINFO, iface=%s, errno=%d", - iface, errno); - close (fd); - return FALSE; - } - if (driver_version) - *driver_version = g_strdup (drvinfo.version); - if (firmware_version) - *firmware_version = g_strdup (drvinfo.fw_version); - - close (fd); - return TRUE; -} - -static GObject* -constructor (GType type, - guint n_construct_params, - GObjectConstructParam *construct_params) -{ - GObject *object; - NMDevice *dev; - NMDevicePrivate *priv; - - object = G_OBJECT_CLASS (nm_device_parent_class)->constructor (type, - n_construct_params, - construct_params); - if (!object) - return NULL; - - dev = NM_DEVICE (object); - priv = NM_DEVICE_GET_PRIVATE (dev); - - if (!priv->udi) { - nm_log_err (LOGD_DEVICE, "No device udi provided, ignoring"); - goto error; - } - - if (!priv->iface) { - nm_log_err (LOGD_DEVICE, "No device interface provided, ignoring"); - goto error; - } - - priv->capabilities |= NM_DEVICE_GET_CLASS (dev)->get_generic_capabilities (dev); - if (!(priv->capabilities & NM_DEVICE_CAP_NM_SUPPORTED)) { - nm_log_warn (LOGD_DEVICE, "(%s): Device unsupported, ignoring.", priv->iface); - goto error; - } - - priv->dhcp_manager = nm_dhcp_manager_get (); - - priv->fw_manager = nm_firewall_manager_get (); - - device_get_driver_info (priv->iface, &priv->driver_version, &priv->firmware_version); - - update_accept_ra_save (dev); - update_ip6_privacy_save (dev); - - priv->initialized = TRUE; - return object; - -error: - g_object_unref (dev); - return NULL; -} - -static void -constructed (GObject *object) -{ - NMDevice *dev = NM_DEVICE (object); - - if (NM_DEVICE_GET_CLASS (dev)->update_hw_address) - NM_DEVICE_GET_CLASS (dev)->update_hw_address (dev); - - if (NM_DEVICE_GET_CLASS (dev)->update_permanent_hw_address) - NM_DEVICE_GET_CLASS (dev)->update_permanent_hw_address (dev); - - if (NM_DEVICE_GET_CLASS (dev)->update_initial_hw_address) - NM_DEVICE_GET_CLASS (dev)->update_initial_hw_address (dev); - - if (G_OBJECT_CLASS (nm_device_parent_class)->constructed) - G_OBJECT_CLASS (nm_device_parent_class)->constructed (object); -} - -static gboolean -nm_device_hw_is_up (NMDevice *self) -{ - g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); - - if (NM_DEVICE_GET_CLASS (self)->hw_is_up) - return NM_DEVICE_GET_CLASS (self)->hw_is_up (self); - - return TRUE; -} - -static gboolean -hw_is_up (NMDevice *device) -{ - int ifindex = nm_device_get_ip_ifindex (device); - - return ifindex > 0 ? nm_system_iface_is_up (ifindex) : TRUE; -} - -static guint32 -get_generic_capabilities (NMDevice *dev) -{ - return 0; -} - -void -nm_device_set_path (NMDevice *self, const char *path) -{ - NMDevicePrivate *priv; - - g_return_if_fail (self != NULL); - - priv = NM_DEVICE_GET_PRIVATE (self); - g_return_if_fail (priv->path == NULL); - - priv->path = g_strdup (path); -} - -const char * -nm_device_get_path (NMDevice *self) -{ - g_return_val_if_fail (self != NULL, NULL); - - return NM_DEVICE_GET_PRIVATE (self)->path; -} - -const char * -nm_device_get_udi (NMDevice *self) -{ - g_return_val_if_fail (self != NULL, NULL); - - return NM_DEVICE_GET_PRIVATE (self)->udi; -} - -/* - * Get/set functions for iface - */ -const char * -nm_device_get_iface (NMDevice *self) -{ - g_return_val_if_fail (self != NULL, NULL); - - return NM_DEVICE_GET_PRIVATE (self)->iface; -} - -int -nm_device_get_ifindex (NMDevice *self) -{ - g_return_val_if_fail (self != NULL, 0); - - return NM_DEVICE_GET_PRIVATE (self)->ifindex; -} - -const char * -nm_device_get_ip_iface (NMDevice *self) -{ - NMDevicePrivate *priv; - - g_return_val_if_fail (self != NULL, NULL); - - priv = NM_DEVICE_GET_PRIVATE (self); - /* If it's not set, default to iface */ - return priv->ip_iface ? priv->ip_iface : priv->iface; -} - -int -nm_device_get_ip_ifindex (NMDevice *self) -{ - NMDevicePrivate *priv; - - g_return_val_if_fail (self != NULL, 0); - - priv = NM_DEVICE_GET_PRIVATE (self); - /* If it's not set, default to iface */ - return priv->ip_iface ? priv->ip_ifindex : priv->ifindex; -} - -void -nm_device_set_ip_iface (NMDevice *self, const char *iface) -{ - NMDevicePrivate *priv; - char *old_ip_iface; - - g_return_if_fail (NM_IS_DEVICE (self)); - - priv = NM_DEVICE_GET_PRIVATE (self); - old_ip_iface = priv->ip_iface; - priv->ip_ifindex = 0; - - priv->ip_iface = g_strdup (iface); - if (priv->ip_iface) { - priv->ip_ifindex = nm_netlink_iface_to_index (priv->ip_iface); - if (priv->ip_ifindex <= 0) { - /* Device IP interface must always be a kernel network interface */ - nm_log_warn (LOGD_HW, "(%s): failed to look up interface index", iface); - } - } - - /* Emit change notification */ - if (g_strcmp0 (old_ip_iface, priv->ip_iface)) - g_object_notify (G_OBJECT (self), NM_DEVICE_IP_IFACE); - g_free (old_ip_iface); -} - -const guint8 * -nm_device_get_hw_address (NMDevice *dev, guint *out_len) -{ - g_return_val_if_fail (dev != NULL, NULL); - g_return_val_if_fail (NM_IS_DEVICE (dev), NULL); - g_return_val_if_fail (out_len != NULL, NULL); - g_return_val_if_fail (*out_len == 0, NULL); - - if (NM_DEVICE_GET_CLASS (dev)->get_hw_address) - return NM_DEVICE_GET_CLASS (dev)->get_hw_address (dev, out_len); - return NULL; -} - -/* - * Get/set functions for driver - */ -const char * -nm_device_get_driver (NMDevice *self) -{ - g_return_val_if_fail (self != NULL, NULL); - - return NM_DEVICE_GET_PRIVATE (self)->driver; -} - -const char * -nm_device_get_driver_version (NMDevice *self) -{ - g_return_val_if_fail (self != NULL, NULL); - - return NM_DEVICE_GET_PRIVATE (self)->driver_version; -} - -const char * -nm_device_get_firmware_version (NMDevice *self) -{ - g_return_val_if_fail (self != NULL, NULL); - - return NM_DEVICE_GET_PRIVATE (self)->firmware_version; -} - - -/* - * Get/set functions for type - */ -NMDeviceType -nm_device_get_device_type (NMDevice *self) -{ - g_return_val_if_fail (NM_IS_DEVICE (self), NM_DEVICE_TYPE_UNKNOWN); - - return NM_DEVICE_GET_PRIVATE (self)->type; -} - - -/** - * nm_device_get_priority(): - * @dev: the #NMDevice - * - * Returns: the device's routing priority. Lower numbers means a "better" - * device, eg higher priority. - */ -int -nm_device_get_priority (NMDevice *dev) -{ - g_return_val_if_fail (NM_IS_DEVICE (dev), 100); - - /* Device 'priority' is used for two things: - * - * a) two devices on the same IP subnet: the "better" (ie, lower number) - * device is the default outgoing device for that subnet - * b) default route: the "better" device gets the default route. This can - * always be modified by setting a connection to never-default=TRUE, in - * which case that device will never take the default route when - * it's using that connection. - */ - - switch (nm_device_get_device_type (dev)) { - case NM_DEVICE_TYPE_ETHERNET: - return 1; - case NM_DEVICE_TYPE_INFINIBAND: - return 2; - case NM_DEVICE_TYPE_ADSL: - return 3; - case NM_DEVICE_TYPE_WIMAX: - return 4; - case NM_DEVICE_TYPE_BOND: - return 5; - case NM_DEVICE_TYPE_VLAN: - return 6; - case NM_DEVICE_TYPE_MODEM: - return 7; - case NM_DEVICE_TYPE_BT: - return 8; - case NM_DEVICE_TYPE_WIFI: - return 9; - case NM_DEVICE_TYPE_OLPC_MESH: - return 10; - default: - return 20; - } -} - - -/* - * Accessor for capabilities - */ -guint32 -nm_device_get_capabilities (NMDevice *self) -{ - g_return_val_if_fail (self != NULL, NM_DEVICE_CAP_NONE); - - return NM_DEVICE_GET_PRIVATE (self)->capabilities; -} - -/* - * Accessor for type-specific capabilities - */ -guint32 -nm_device_get_type_capabilities (NMDevice *self) -{ - g_return_val_if_fail (self != NULL, NM_DEVICE_CAP_NONE); - - return NM_DEVICE_GET_CLASS (self)->get_type_capabilities (self); -} - -static guint32 -get_type_capabilities (NMDevice *self) -{ - return NM_DEVICE_CAP_NONE; -} - - -const char * -nm_device_get_type_desc (NMDevice *self) -{ - g_return_val_if_fail (self != NULL, NULL); - - return NM_DEVICE_GET_PRIVATE (self)->type_desc; -} - -void -nm_device_set_connection_provider (NMDevice *device, - NMConnectionProvider *provider) -{ - NMDevicePrivate *priv; - - g_return_if_fail (device != NULL); - g_return_if_fail (provider != NULL); - g_return_if_fail (NM_IS_CONNECTION_PROVIDER (provider)); - - priv = NM_DEVICE_GET_PRIVATE (device); - g_return_if_fail (priv->con_provider == NULL); - - priv->con_provider = provider; - priv->cp_added_id = g_signal_connect (priv->con_provider, - NM_CP_SIGNAL_CONNECTION_ADDED, - G_CALLBACK (cp_connection_added), - device); - - priv->cp_loaded_id = g_signal_connect (priv->con_provider, - NM_CP_SIGNAL_CONNECTIONS_LOADED, - G_CALLBACK (cp_connections_loaded), - device); - - priv->cp_removed_id = g_signal_connect (priv->con_provider, - NM_CP_SIGNAL_CONNECTION_REMOVED, - G_CALLBACK (cp_connection_removed), - device); - - priv->cp_updated_id = g_signal_connect (priv->con_provider, - NM_CP_SIGNAL_CONNECTION_UPDATED, - G_CALLBACK (cp_connection_updated), - device); -} - -NMConnectionProvider * -nm_device_get_connection_provider (NMDevice *device) -{ - g_return_val_if_fail (device != NULL, NULL); - - return NM_DEVICE_GET_PRIVATE (device)->con_provider; -} - -static SlaveInfo * -find_slave_info (NMDevice *self, NMDevice *slave) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - SlaveInfo *info; - GSList *iter; - - for (iter = priv->slaves; iter; iter = g_slist_next (iter)) { - info = iter->data; - if (info->slave == slave) - return info; - } - return NULL; -} - -static void -free_slave_info (SlaveInfo *info) -{ - g_signal_handler_disconnect (info->slave, info->watch_id); - g_clear_object (&info->slave); - memset (info, 0, sizeof (*info)); - g_free (info); -} - -/** - * nm_device_enslave_slave: - * @dev: the master device - * @slave: the slave device to enslave - * @connection: the slave device's connection - * - * If @dev is capable of enslaving other devices (ie it's a bridge, bond, etc) - * then this function enslaves @slave. - * - * Returns: %TRUE on success, %FALSE on failure or if this device cannot enslave - * other devices. - */ -static gboolean -nm_device_enslave_slave (NMDevice *dev, NMDevice *slave, NMConnection *connection) -{ - SlaveInfo *info; - gboolean success = FALSE; - - g_return_val_if_fail (dev != NULL, FALSE); - g_return_val_if_fail (slave != NULL, FALSE); - g_return_val_if_fail (nm_device_get_state (slave) >= NM_DEVICE_STATE_DISCONNECTED, FALSE); - g_return_val_if_fail (NM_DEVICE_GET_CLASS (dev)->enslave_slave != NULL, FALSE); - - info = find_slave_info (dev, slave); - if (!info) - return FALSE; - - g_warn_if_fail (info->enslaved == FALSE); - success = NM_DEVICE_GET_CLASS (dev)->enslave_slave (dev, slave, connection); - if (success) { - info->enslaved = TRUE; - nm_device_slave_notify_enslaved (info->slave, TRUE, FALSE); - } - - /* Ensure the device's hardware address is up-to-date; it often changes - * when slaves change. - */ - if (NM_DEVICE_GET_CLASS (dev)->update_hw_address) - NM_DEVICE_GET_CLASS (dev)->update_hw_address (dev); - - /* Restart IP configuration if we're waiting for slaves. Do this - * after updating the hardware address as IP config may need the - * new address. - */ - if (success) { - if (NM_DEVICE_GET_PRIVATE (dev)->ip4_state == IP_WAIT) - nm_device_activate_stage3_ip4_start (dev); - - if (NM_DEVICE_GET_PRIVATE (dev)->ip6_state == IP_WAIT) - nm_device_activate_stage3_ip6_start (dev); - } - - return success; -} - -/** - * nm_device_release_one_slave: - * @dev: the master device - * @slave: the slave device to release - * @failed: %TRUE if the release was unexpected, ie the master failed - * - * If @dev is capable of enslaving other devices (ie it's a bridge, bond, etc) - * then this function releases the previously enslaved @slave. - * - * Returns: %TRUE on success, %FALSE on failure, if this device cannot enslave - * other devices, or if @slave was never enslaved. - */ -static gboolean -nm_device_release_one_slave (NMDevice *dev, NMDevice *slave, gboolean failed) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (dev); - SlaveInfo *info; - gboolean success = FALSE; - - g_return_val_if_fail (slave != NULL, FALSE); - g_return_val_if_fail (NM_DEVICE_GET_CLASS (dev)->release_slave != NULL, FALSE); - - info = find_slave_info (dev, slave); - if (!info) - return FALSE; - - if (info->enslaved) { - success = NM_DEVICE_GET_CLASS (dev)->release_slave (dev, slave); - g_warn_if_fail (success); - } - nm_device_slave_notify_enslaved (info->slave, FALSE, failed); - - priv->slaves = g_slist_remove (priv->slaves, info); - free_slave_info (info); - - /* Ensure the device's hardware address is up-to-date; it often changes - * when slaves change. - */ - if (NM_DEVICE_GET_CLASS (dev)->update_hw_address) - NM_DEVICE_GET_CLASS (dev)->update_hw_address (dev); - - return success; -} - -static void -slave_state_changed (NMDevice *slave, - NMDeviceState slave_new_state, - NMDeviceState slave_old_state, - NMDeviceStateReason reason, - NMDevice *self) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - gboolean release = FALSE; - - nm_log_dbg (LOGD_DEVICE, "(%s): slave %s state change %d (%s) -> %d (%s)", - nm_device_get_iface (self), - nm_device_get_iface (slave), - slave_old_state, - state_to_string (slave_old_state), - slave_new_state, - state_to_string (slave_new_state)); - - g_assert (priv->state > NM_DEVICE_STATE_DISCONNECTED); - g_assert (priv->state <= NM_DEVICE_STATE_ACTIVATED); - - /* Don't try to enslave slaves until the master is ready */ - if (priv->state < NM_DEVICE_STATE_CONFIG) - return; - - if (slave_new_state == NM_DEVICE_STATE_IP_CONFIG) - nm_device_enslave_slave (self, slave, nm_device_get_connection (slave)); - else if (slave_new_state > NM_DEVICE_STATE_ACTIVATED) - release = TRUE; - else if ( slave_new_state <= NM_DEVICE_STATE_DISCONNECTED - && slave_old_state > NM_DEVICE_STATE_DISCONNECTED) { - /* Catch failures due to unavailable or unmanaged */ - release = TRUE; - } - - if (release) { - nm_device_release_one_slave (self, slave, FALSE); - /* Bridge/bond interfaces are left up until manually deactivated */ - if (priv->slaves == NULL && priv->state == NM_DEVICE_STATE_ACTIVATED) { - nm_log_dbg (LOGD_DEVICE, "(%s): last slave removed; remaining activated", - nm_device_get_iface (self)); - } - } -} - -/** - * nm_device_master_add_slave: - * @dev: the master device - * @slave: the slave device to enslave - * - * If @dev is capable of enslaving other devices (ie it's a bridge, bond, etc) - * then this function adds @slave to the slave list for later enslavement. - * - * Returns: %TRUE on success, %FALSE on failure - */ -gboolean -nm_device_master_add_slave (NMDevice *dev, NMDevice *slave) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (dev); - SlaveInfo *info; - - g_return_val_if_fail (dev != NULL, FALSE); - g_return_val_if_fail (slave != NULL, FALSE); - g_return_val_if_fail (nm_device_get_state (slave) >= NM_DEVICE_STATE_DISCONNECTED, FALSE); - g_return_val_if_fail (NM_DEVICE_GET_CLASS (dev)->enslave_slave != NULL, FALSE); - - if (!find_slave_info (dev, slave)) { - info = g_malloc0 (sizeof (SlaveInfo)); - info->slave = g_object_ref (slave); - info->watch_id = g_signal_connect (slave, "state-changed", - G_CALLBACK (slave_state_changed), dev); - priv->slaves = g_slist_prepend (priv->slaves, info); - } - - return TRUE; -} - - -/** - * nm_device_master_get_slaves: - * @dev: the master device - * - * Returns: any slaves of which @device is the master. Caller owns returned list. - */ -GSList * -nm_device_master_get_slaves (NMDevice *dev) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (dev); - GSList *slaves = NULL, *iter; - - for (iter = priv->slaves; iter; iter = g_slist_next (iter)) - slaves = g_slist_prepend (slaves, ((SlaveInfo *) iter->data)->slave); - - return slaves; -} - -/** - * nm_device_master_get_slave_by_ifindex: - * @dev: the master device - * @ifindex: the slave's interface index - * - * Returns: the slave with the given @ifindex of which @device is the master, - * or %NULL if no device with @ifinidex is a slave of @device. - */ -NMDevice * -nm_device_master_get_slave_by_ifindex (NMDevice *dev, int ifindex) -{ - GSList *iter; - - for (iter = NM_DEVICE_GET_PRIVATE (dev)->slaves; iter; iter = g_slist_next (iter)) { - SlaveInfo *info = iter->data; - - if (nm_device_get_ip_ifindex (info->slave) == ifindex) - return info->slave; - } - return NULL; -} - -/** - * nm_device_is_master: - * @dev: the device - * - * Returns: whether @dev can enslave other devices (eg, bridge or bond) - */ -gboolean -nm_device_is_master (NMDevice *dev) -{ - return NM_DEVICE_GET_PRIVATE (dev)->is_master; -} - -/* release all slaves */ -static void -nm_device_master_release_slaves (NMDevice *self, gboolean failed) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - - while (priv->slaves) { - SlaveInfo *info = priv->slaves->data; - - nm_device_release_one_slave (self, info->slave, failed); - } -} - - -/** - * nm_device_slave_notify_enslaved: - * @dev: the slave device - * @enslaved: %TRUE if the device is now enslaved, %FALSE if released - * @master_failed: if released, indicates whether the release was unexpected, - * ie the master device failed. - * - * Notifies a slave that it has been enslaved or released. If released, provides - * information on whether the release was expected or not, and thus whether the - * slave should fail it's activation or gracefully deactivate. - */ -void -nm_device_slave_notify_enslaved (NMDevice *dev, - gboolean enslaved, - gboolean master_failed) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (dev); - NMConnection *connection = nm_device_get_connection (dev); - - if (enslaved) { - g_assert (priv->master); - g_warn_if_fail (priv->enslaved == FALSE); - g_warn_if_fail (priv->state == NM_DEVICE_STATE_IP_CONFIG); - - nm_log_info (LOGD_DEVICE, - "Activation (%s) connection '%s' enslaved, continuing activation", - nm_device_get_iface (dev), - nm_connection_get_id (connection)); - - /* Now that we're enslaved, proceed with activation. Remember, slaves - * don't have any IP configuration, so they skip directly to SECONDARIES. - */ - priv->enslaved = TRUE; - priv->ip4_state = IP_DONE; - priv->ip6_state = IP_DONE; - nm_device_queue_state (dev, NM_DEVICE_STATE_SECONDARIES, NM_DEVICE_STATE_REASON_NONE); - } else { - NMDeviceState new_state = NM_DEVICE_STATE_DISCONNECTED; - NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; - - if ( priv->state > NM_DEVICE_STATE_DISCONNECTED - && priv->state <= NM_DEVICE_STATE_ACTIVATED) { - if (master_failed) { - new_state = NM_DEVICE_STATE_FAILED; - reason = NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED; - - nm_log_warn (LOGD_DEVICE, - "Activation (%s) connection '%s' master failed", - nm_device_get_iface (dev), - nm_connection_get_id (connection)); - } else { - nm_log_dbg (LOGD_DEVICE, - "Activation (%s) connection '%s' master deactivated", - nm_device_get_iface (dev), - nm_connection_get_id (connection)); - } - - nm_device_queue_state (dev, new_state, reason); - } - } -} - -/** - * nm_device_get_enslaved: - * @device: the #NMDevice - * - * Returns: %TRUE if the device is enslaved to a master device (eg bridge or - * bond), %FALSE if not - */ -gboolean -nm_device_get_enslaved (NMDevice *device) -{ - return NM_DEVICE_GET_PRIVATE (device)->enslaved; -} - -/* - * nm_device_get_act_request - * - * Return the devices activation request, if any. - * - */ -NMActRequest * -nm_device_get_act_request (NMDevice *self) -{ - g_return_val_if_fail (self != NULL, NULL); - - return NM_DEVICE_GET_PRIVATE (self)->act_request; -} - -NMConnection * -nm_device_get_connection (NMDevice *self) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - - return priv->act_request ? nm_act_request_get_connection (priv->act_request) : NULL; -} - -gboolean -nm_device_is_available (NMDevice *self) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - - if (priv->firmware_missing) - return FALSE; - - if (NM_DEVICE_GET_CLASS (self)->is_available) - return NM_DEVICE_GET_CLASS (self)->is_available (self); - return TRUE; -} - -gboolean -nm_device_get_enabled (NMDevice *self) -{ - g_return_val_if_fail (self != NULL, FALSE); - g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); - - if (NM_DEVICE_GET_CLASS (self)->get_enabled) - return NM_DEVICE_GET_CLASS (self)->get_enabled (self); - return TRUE; -} - -void -nm_device_set_enabled (NMDevice *self, gboolean enabled) -{ - g_return_if_fail (self != NULL); - g_return_if_fail (NM_IS_DEVICE (self)); - - if (NM_DEVICE_GET_CLASS (self)->set_enabled) - NM_DEVICE_GET_CLASS (self)->set_enabled (self, enabled); -} - -RfKillType -nm_device_get_rfkill_type (NMDevice *self) -{ - g_return_val_if_fail (self != NULL, FALSE); - g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); - - return NM_DEVICE_GET_PRIVATE (self)->rfkill_type; -} - -static gboolean -autoconnect_allowed_accumulator (GSignalInvocationHint *ihint, - GValue *return_accu, - const GValue *handler_return, gpointer data) -{ - if (!g_value_get_boolean (handler_return)) - g_value_set_boolean (return_accu, FALSE); - return TRUE; -} - -gboolean -nm_device_autoconnect_allowed (NMDevice *self) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - GValue instance = { 0, }; - GValue retval = { 0, }; - - g_value_init (&instance, G_TYPE_OBJECT); - g_value_take_object (&instance, self); - - g_value_init (&retval, G_TYPE_BOOLEAN); - if (priv->autoconnect) - g_value_set_boolean (&retval, TRUE); - else - g_value_set_boolean (&retval, FALSE); - - /* Use g_signal_emitv() rather than g_signal_emit() to avoid the return - * value being changed if no handlers are connected */ - g_signal_emitv (&instance, signals[AUTOCONNECT_ALLOWED], 0, &retval); - return g_value_get_boolean (&retval); -} - -NMConnection * -nm_device_get_best_auto_connection (NMDevice *dev, - GSList *connections, - char **specific_object) -{ - guint32 caps; - GSList *iter, *available_conns; - NMConnection *best_connection; - - g_return_val_if_fail (NM_IS_DEVICE (dev), NULL); - g_return_val_if_fail (specific_object != NULL, NULL); - g_return_val_if_fail (*specific_object == NULL, NULL); - - caps = nm_device_get_capabilities (dev); - /* Don't use devices that SUCK */ - if (!(caps & NM_DEVICE_CAP_NM_SUPPORTED)) - return NULL; - - if (!NM_DEVICE_GET_CLASS (dev)->get_best_auto_connection) - return NULL; - - available_conns = NULL; - for (iter = connections; iter; iter = iter->next) { - NMConnection *connection = NM_CONNECTION (iter->data); - NMSettingConnection *s_con; - - s_con = nm_connection_get_setting_connection (connection); - g_assert (s_con); - if (nm_setting_connection_get_autoconnect (s_con)) - available_conns = g_slist_prepend (available_conns, connection); - } - - if (!available_conns) - return NULL; - - best_connection = NM_DEVICE_GET_CLASS (dev)->get_best_auto_connection (dev, available_conns, specific_object); - - g_slist_free (available_conns); - return best_connection; -} - -gboolean -nm_device_complete_connection (NMDevice *self, - NMConnection *connection, - const char *specific_object, - const GSList *existing_connections, - GError **error) -{ - gboolean success = FALSE; - - g_return_val_if_fail (self != NULL, FALSE); - g_return_val_if_fail (connection != NULL, FALSE); - - if (!NM_DEVICE_GET_CLASS (self)->complete_connection) { - g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CONNECTION_INVALID, - "Device class %s had no complete_connection method", - G_OBJECT_TYPE_NAME (self)); - return FALSE; - } - - success = NM_DEVICE_GET_CLASS (self)->complete_connection (self, - connection, - specific_object, - existing_connections, - error); - if (success) - success = nm_connection_verify (connection, error); - - return success; -} - -gboolean -nm_device_check_connection_compatible (NMDevice *device, - NMConnection *connection, - GError **error) -{ - g_return_val_if_fail (device != NULL, FALSE); - g_return_val_if_fail (NM_IS_DEVICE (device), FALSE); - g_return_val_if_fail (connection != NULL, FALSE); - g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE); - - if (NM_DEVICE_GET_CLASS (device)->check_connection_compatible) - return NM_DEVICE_GET_CLASS (device)->check_connection_compatible (device, connection, error); - return TRUE; -} - -gboolean -nm_device_can_assume_connections (NMDevice *device) -{ - g_return_val_if_fail (device != NULL, FALSE); - g_return_val_if_fail (NM_IS_DEVICE (device), FALSE); - - return !!NM_DEVICE_GET_CLASS (device)->connection_match_config; -} - -static void -dnsmasq_state_changed_cb (NMDnsMasqManager *manager, guint32 status, gpointer user_data) -{ - NMDevice *self = NM_DEVICE (user_data); - - switch (status) { - case NM_DNSMASQ_STATUS_DEAD: - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_SHARED_START_FAILED); - break; - default: - break; - } -} - -static void -activation_source_clear (NMDevice *self, gboolean remove_source, int family) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - guint *act_source_id; - gpointer *act_source_func; - - if (family == AF_INET6) { - act_source_id = &priv->act_source6_id; - act_source_func = &priv->act_source6_func; - } else { - act_source_id = &priv->act_source_id; - act_source_func = &priv->act_source_func; - } - - if (*act_source_id) { - if (remove_source) - g_source_remove (*act_source_id); - *act_source_id = 0; - *act_source_func = NULL; - } -} - -static void -activation_source_schedule (NMDevice *self, GSourceFunc func, int family) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - guint *act_source_id; - gpointer *act_source_func; - - if (family == AF_INET6) { - act_source_id = &priv->act_source6_id; - act_source_func = &priv->act_source6_func; - } else { - act_source_id = &priv->act_source_id; - act_source_func = &priv->act_source_func; - } - - if (*act_source_id) { - nm_log_err (LOGD_DEVICE, "activation stage already scheduled"); - } - - /* Don't bother rescheduling the same function that's about to - * run anyway. Fixes issues with crappy wireless drivers sending - * streams of associate events before NM has had a chance to process - * the first one. - */ - if (!*act_source_id || (*act_source_func != func)) { - activation_source_clear (self, TRUE, family); - *act_source_id = g_idle_add (func, self); - *act_source_func = func; - } -} - -gboolean -nm_device_ip_config_should_fail (NMDevice *self, gboolean ip6) -{ - NMConnection *connection; - NMSettingIP4Config *s_ip4; - NMSettingIP6Config *s_ip6; - - g_return_val_if_fail (self != NULL, TRUE); - - connection = nm_device_get_connection (self); - g_assert (connection); - - /* Fail the connection if the failed IP method is required to complete */ - if (ip6) { - s_ip6 = nm_connection_get_setting_ip6_config (connection); - if (s_ip6 && !nm_setting_ip6_config_get_may_fail (s_ip6)) - return TRUE; - } else { - s_ip4 = nm_connection_get_setting_ip4_config (connection); - if (s_ip4 && !nm_setting_ip4_config_get_may_fail (s_ip4)) - return TRUE; - } - - return FALSE; -} - -static NMActStageReturn -act_stage1_prepare (NMDevice *self, NMDeviceStateReason *reason) -{ - return NM_ACT_STAGE_RETURN_SUCCESS; -} - -/* - * nm_device_activate_stage1_device_prepare - * - * Prepare for device activation - * - */ -static gboolean -nm_device_activate_stage1_device_prepare (gpointer user_data) -{ - NMDevice *self = NM_DEVICE (user_data); - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - const char *iface; - NMActStageReturn ret; - NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; - - /* Clear the activation source ID now that this stage has run */ - activation_source_clear (self, FALSE, 0); - - priv->ip4_state = priv->ip6_state = IP_NONE; - - iface = nm_device_get_iface (self); - nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 1 of 5 (Device Prepare) started...", iface); - nm_device_state_changed (self, NM_DEVICE_STATE_PREPARE, NM_DEVICE_STATE_REASON_NONE); - - ret = NM_DEVICE_GET_CLASS (self)->act_stage1_prepare (self, &reason); - if (ret == NM_ACT_STAGE_RETURN_POSTPONE) { - goto out; - } else if (ret == NM_ACT_STAGE_RETURN_FAILURE) { - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); - goto out; - } - g_assert (ret == NM_ACT_STAGE_RETURN_SUCCESS); - - nm_device_activate_schedule_stage2_device_config (self); - -out: - nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 1 of 5 (Device Prepare) complete.", iface); - return FALSE; -} - - -/* - * nm_device_activate_schedule_stage1_device_prepare - * - * Prepare a device for activation - * - */ -void -nm_device_activate_schedule_stage1_device_prepare (NMDevice *self) -{ - NMDevicePrivate *priv; - - g_return_if_fail (NM_IS_DEVICE (self)); - - priv = NM_DEVICE_GET_PRIVATE (self); - g_return_if_fail (priv->act_request); - - activation_source_schedule (self, nm_device_activate_stage1_device_prepare, 0); - - nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 1 of 5 (Device Prepare) scheduled...", - nm_device_get_iface (self)); -} - -static NMActStageReturn -act_stage2_config (NMDevice *dev, NMDeviceStateReason *reason) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (dev); - GSList *iter; - - /* If we have slaves that aren't yet enslaved, do that now */ - for (iter = priv->slaves; iter; iter = g_slist_next (iter)) { - SlaveInfo *info = iter->data; - - if (nm_device_get_state (info->slave) == NM_DEVICE_STATE_IP_CONFIG) - nm_device_enslave_slave (dev, info->slave, nm_device_get_connection (info->slave)); - } - - /* Nothing to do */ - return NM_ACT_STAGE_RETURN_SUCCESS; -} - -/* - * nm_device_activate_stage2_device_config - * - * Determine device parameters and set those on the device, ie - * for wireless devices, set SSID, keys, etc. - * - */ -static gboolean -nm_device_activate_stage2_device_config (gpointer user_data) -{ - NMDevice *self = NM_DEVICE (user_data); - const char * iface; - NMActStageReturn ret; - NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; - gboolean no_firmware = FALSE; - - /* Clear the activation source ID now that this stage has run */ - activation_source_clear (self, FALSE, 0); - - iface = nm_device_get_iface (self); - nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 2 of 5 (Device Configure) starting...", iface); - nm_device_state_changed (self, NM_DEVICE_STATE_CONFIG, NM_DEVICE_STATE_REASON_NONE); - - if (!nm_device_bring_up (self, FALSE, &no_firmware)) { - if (no_firmware) - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_FIRMWARE_MISSING); - else - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_CONFIG_FAILED); - goto out; - } - - ret = NM_DEVICE_GET_CLASS (self)->act_stage2_config (self, &reason); - if (ret == NM_ACT_STAGE_RETURN_POSTPONE) - goto out; - else if (ret == NM_ACT_STAGE_RETURN_FAILURE) - { - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); - goto out; - } - g_assert (ret == NM_ACT_STAGE_RETURN_SUCCESS); - - nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 2 of 5 (Device Configure) successful.", iface); - - nm_device_activate_schedule_stage3_ip_config_start (self); - -out: - nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 2 of 5 (Device Configure) complete.", iface); - return FALSE; -} - - -/* - * nm_device_activate_schedule_stage2_device_config - * - * Schedule setup of the hardware device - * - */ -void -nm_device_activate_schedule_stage2_device_config (NMDevice *self) -{ - NMDevicePrivate *priv; - - g_return_if_fail (NM_IS_DEVICE (self)); - - priv = NM_DEVICE_GET_PRIVATE (self); - g_return_if_fail (priv->act_request); - - activation_source_schedule (self, nm_device_activate_stage2_device_config, 0); - - nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 2 of 5 (Device Configure) scheduled...", - nm_device_get_iface (self)); -} - -/*********************************************/ -/* avahi-autoipd stuff */ - -static void -aipd_timeout_remove (NMDevice *self) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - - if (priv->aipd_timeout) { - g_source_remove (priv->aipd_timeout); - priv->aipd_timeout = 0; - } -} - -static void -aipd_cleanup (NMDevice *self) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - - if (priv->aipd_watch) { - g_source_remove (priv->aipd_watch); - priv->aipd_watch = 0; - } - - if (priv->aipd_pid > 0) { - kill (priv->aipd_pid, SIGKILL); - - /* ensure the child is reaped */ - nm_log_dbg (LOGD_AUTOIP4, "waiting for avahi-autoipd pid %d to exit", priv->aipd_pid); - waitpid (priv->aipd_pid, NULL, 0); - nm_log_dbg (LOGD_AUTOIP4, "avahi-autoip pid %d cleaned up", priv->aipd_pid); - - priv->aipd_pid = -1; - } - - aipd_timeout_remove (self); -} - -static NMIP4Config * -aipd_get_ip4_config (NMDevice *self, struct in_addr lla) -{ - NMIP4Config *config = NULL; - NMIP4Address *addr; - NMIP4Route *route; - - config = nm_ip4_config_new (); - g_assert (config); - - addr = nm_ip4_address_new (); - nm_ip4_address_set_address (addr, (guint32) lla.s_addr); - nm_ip4_address_set_prefix (addr, 16); - nm_ip4_config_take_address (config, addr); - - /* Add a multicast route for link-local connections: destination= 224.0.0.0, netmask=240.0.0.0 */ - route = nm_ip4_route_new (); - nm_ip4_route_set_dest (route, (guint32) htonl (0xE0000000L)); - nm_ip4_route_set_prefix (route, 4); - nm_ip4_route_set_next_hop (route, (guint32) 0); - nm_ip4_route_set_metric (route, 0); - nm_ip4_config_take_route (config, route); - - return config; -} - -static void -autoip_changed (NMDevice *self, - NMIP4Config *config, - NMSettingIP4Config *s_ip4) -{ - NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; - - nm_utils_merge_ip4_config (config, s_ip4); - if (!nm_device_set_ip4_config (self, config, FALSE, &reason)) { - nm_log_err (LOGD_AUTOIP4, "(%s): failed to update IP4 config in response to autoip event.", - nm_device_get_iface (self)); - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); - } -} - -#define IPV4LL_NETWORK (htonl (0xA9FE0000L)) -#define IPV4LL_NETMASK (htonl (0xFFFF0000L)) - -void -nm_device_handle_autoip4_event (NMDevice *self, - const char *event, - const char *address) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - NMConnection *connection = NULL; - NMSettingIP4Config *s_ip4 = NULL; - const char *iface, *method = NULL; - - g_return_if_fail (event != NULL); - - if (priv->act_request == NULL) - return; - - connection = nm_act_request_get_connection (priv->act_request); - g_assert (connection); - - /* Ignore if the connection isn't an AutoIP connection */ - s_ip4 = nm_connection_get_setting_ip4_config (connection); - if (s_ip4) - method = nm_setting_ip4_config_get_method (s_ip4); - - if (g_strcmp0 (method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL) != 0) - return; - - iface = nm_device_get_iface (self); - - if (strcmp (event, "BIND") == 0) { - struct in_addr lla; - NMIP4Config *config; - - if (inet_pton (AF_INET, address, &lla) <= 0) { - nm_log_err (LOGD_AUTOIP4, "(%s): invalid address %s received from avahi-autoipd.", - iface, address); - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_AUTOIP_ERROR); - return; - } - - if ((lla.s_addr & IPV4LL_NETMASK) != IPV4LL_NETWORK) { - nm_log_err (LOGD_AUTOIP4, "(%s): invalid address %s received from avahi-autoipd (not link-local).", - iface, address); - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_AUTOIP_ERROR); - return; - } - - config = aipd_get_ip4_config (self, lla); - if (config == NULL) { - nm_log_err (LOGD_AUTOIP4, "failed to get autoip config"); - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); - return; - } - - if (priv->ip4_state == IP_CONF) { - aipd_timeout_remove (self); - nm_device_activate_schedule_ip4_config_result (self, config); - } else if (priv->ip4_state == IP_DONE) { - autoip_changed (self, config, s_ip4); - } else - g_assert_not_reached (); - - g_object_unref (config); - } else { - nm_log_warn (LOGD_AUTOIP4, "(%s): autoip address %s no longer valid because '%s'.", - iface, address, event); - - /* The address is gone; terminate the connection or fail activation */ - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED); - } -} - -static void -aipd_watch_cb (GPid pid, gint status, gpointer user_data) -{ - NMDevice *self = NM_DEVICE (user_data); - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - NMDeviceState state; - const char *iface; - - if (!priv->aipd_watch) - return; - priv->aipd_watch = 0; - - iface = nm_device_get_iface (self); - - if (WIFEXITED (status)) { - nm_log_dbg (LOGD_AUTOIP4, "(%s): avahi-autoipd exited with error code %d", - iface, WEXITSTATUS (status)); - } else if (WIFSTOPPED (status)) { - nm_log_warn (LOGD_AUTOIP4, "(%s): avahi-autoipd stopped unexpectedly with signal %d", - iface, WSTOPSIG (status)); - } else if (WIFSIGNALED (status)) { - nm_log_warn (LOGD_AUTOIP4, "(%s): avahi-autoipd died with signal %d", - iface, WTERMSIG (status)); - } else { - nm_log_warn (LOGD_AUTOIP4, "(%s): avahi-autoipd died from an unknown cause", iface); - } - - aipd_cleanup (self); - - state = nm_device_get_state (self); - if (nm_device_is_activating (self) || (state == NM_DEVICE_STATE_ACTIVATED)) - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_AUTOIP_FAILED); -} - -static gboolean -aipd_timeout_cb (gpointer user_data) -{ - NMDevice *self = NM_DEVICE (user_data); - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - - if (priv->aipd_timeout) { - nm_log_info (LOGD_AUTOIP4, "(%s): avahi-autoipd timed out.", nm_device_get_iface (self)); - priv->aipd_timeout = 0; - aipd_cleanup (self); - - if (priv->ip4_state == IP_CONF) - nm_device_activate_schedule_ip4_config_timeout (self); - } - - return FALSE; -} - -static void -aipd_child_setup (gpointer user_data G_GNUC_UNUSED) -{ - /* We are in the child process at this point. - * Give child it's own program group for signal - * separation. - */ - pid_t pid = getpid (); - setpgid (pid, pid); - - /* - * We blocked signals in main(). We need to restore original signal - * mask for avahi-autoipd here so that it can receive signals. - */ - nm_unblock_posix_signals (NULL); -} - -static NMActStageReturn -aipd_start (NMDevice *self, NMDeviceStateReason *reason) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - const char *iface = nm_device_get_iface (self); - char *argv[6], *cmdline; - const char **aipd_binary = NULL; - static const char *aipd_paths[] = { - "/usr/sbin/avahi-autoipd", - "/usr/local/sbin/avahi-autoipd", - NULL - }; - int i = 0; - GError *error = NULL; - - aipd_cleanup (self); - - /* Find avahi-autoipd */ - aipd_binary = aipd_paths; - while (*aipd_binary != NULL) { - if (g_file_test (*aipd_binary, G_FILE_TEST_EXISTS)) - break; - aipd_binary++; - } - - if (!*aipd_binary) { - nm_log_warn (LOGD_DEVICE | LOGD_AUTOIP4, - "Activation (%s) Stage 3 of 5 (IP Configure Start) failed" - " to start avahi-autoipd: not found", iface); - *reason = NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED; - return NM_ACT_STAGE_RETURN_FAILURE; - } - - argv[i++] = (char *) (*aipd_binary); - argv[i++] = "--script"; - argv[i++] = LIBEXECDIR "/nm-avahi-autoipd.action"; - if (nm_logging_level_enabled (LOGL_DEBUG)) - argv[i++] = "--debug"; - argv[i++] = (char *) nm_device_get_ip_iface (self); - argv[i++] = NULL; - - cmdline = g_strjoinv (" ", argv); - nm_log_dbg (LOGD_AUTOIP4, "running: %s", cmdline); - g_free (cmdline); - - if (!g_spawn_async ("/", argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD, - &aipd_child_setup, NULL, &(priv->aipd_pid), &error)) { - nm_log_warn (LOGD_DEVICE | LOGD_AUTOIP4, - "Activation (%s) Stage 3 of 5 (IP Configure Start) failed" - " to start avahi-autoipd: %s", - iface, - error && error->message ? error->message : "(unknown)"); - g_clear_error (&error); - aipd_cleanup (self); - return NM_ACT_STAGE_RETURN_FAILURE; - } - - nm_log_info (LOGD_DEVICE | LOGD_AUTOIP4, - "Activation (%s) Stage 3 of 5 (IP Configure Start) started" - " avahi-autoipd...", iface); - - /* Monitor the child process so we know when it dies */ - priv->aipd_watch = g_child_watch_add (priv->aipd_pid, aipd_watch_cb, self); - - /* Start a timeout to bound the address attempt */ - priv->aipd_timeout = g_timeout_add_seconds (20, aipd_timeout_cb, self); - - return NM_ACT_STAGE_RETURN_POSTPONE; -} - -/*********************************************/ -/* DHCPv4 stuff */ - -static void -dhcp4_add_option_cb (gpointer key, gpointer value, gpointer user_data) -{ - nm_dhcp4_config_add_option (NM_DHCP4_CONFIG (user_data), - (const char *) key, - (const char *) value); -} - -static void -dhcp4_lease_change (NMDevice *device, NMIP4Config *config) -{ - NMConnection *connection; - NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; - - if (config == NULL) { - nm_log_warn (LOGD_DHCP4, "(%s): failed to get DHCPv4 config for rebind", - nm_device_get_ip_iface (device)); - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED); - return; - } - - connection = nm_device_get_connection (device); - g_assert (connection); - - /* Merge with user overrides */ - nm_utils_merge_ip4_config (config, nm_connection_get_setting_ip4_config (connection)); - - if (!nm_device_set_ip4_config (device, config, FALSE, &reason)) { - nm_log_warn (LOGD_DHCP4, "(%s): failed to update IPv4 config in response to DHCP event.", - nm_device_get_ip_iface (device)); - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, reason); - return; - } - - /* Notify dispatcher scripts of new DHCP4 config */ - nm_dispatcher_call (DISPATCHER_ACTION_DHCP4_CHANGE, connection, device, NULL, NULL); -} - -static void -dhcp4_fail (NMDevice *device, gboolean timeout) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); - - nm_dhcp4_config_reset (priv->dhcp4_config); - - if (timeout || (priv->ip4_state == IP_CONF)) - nm_device_activate_schedule_ip4_config_timeout (device); - else if (priv->ip4_state == IP_DONE) - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED); -} - -static void -dhcp4_state_changed (NMDHCPClient *client, - NMDHCPState state, - gpointer user_data) -{ - NMDevice *device = NM_DEVICE (user_data); - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); - NMDeviceState dev_state; - NMIP4Config *config; - - g_return_if_fail (nm_dhcp_client_get_ipv6 (client) == FALSE); - - nm_log_dbg (LOGD_DHCP4, "(%s): new DHCPv4 client state %d", - nm_device_get_iface (device), state); - - dev_state = nm_device_get_state (device); - - switch (state) { - case DHC_BOUND4: /* lease obtained */ - case DHC_RENEW4: /* lease renewed */ - case DHC_REBOOT: /* have valid lease, but now obtained a different one */ - case DHC_REBIND4: /* new, different lease */ - config = nm_dhcp_client_get_ip4_config (priv->dhcp4_client, FALSE); - - /* Update the DHCP4 config object with new DHCP options */ - nm_dhcp4_config_reset (priv->dhcp4_config); - if (config) { - nm_dhcp_client_foreach_option (priv->dhcp4_client, - dhcp4_add_option_cb, - priv->dhcp4_config); - } - g_object_notify (G_OBJECT (device), NM_DEVICE_DHCP4_CONFIG); - - if (priv->ip4_state == IP_CONF) - nm_device_activate_schedule_ip4_config_result (device, config); - else if (priv->ip4_state == IP_DONE) - dhcp4_lease_change (device, config); - - if (config) - g_object_unref (config); - break; - case DHC_TIMEOUT: /* timed out contacting DHCP server */ - dhcp4_fail (device, TRUE); - break; - case DHC_END: /* dhclient exited normally */ - case DHC_FAIL: /* all attempts to contact server timed out, sleeping */ - case DHC_ABEND: /* dhclient exited abnormally */ - /* dhclient quit and can't get/renew a lease; so kill the connection */ - dhcp4_fail (device, FALSE); - break; - default: - break; - } -} - -static void -dhcp4_timeout (NMDHCPClient *client, gpointer user_data) -{ - NMDevice *device = NM_DEVICE (user_data); - - g_return_if_fail (nm_device_get_act_request (device) != NULL); - g_return_if_fail (nm_dhcp_client_get_ipv6 (client) == FALSE); - - nm_dhcp_client_stop (client, FALSE); - dhcp4_fail (device, TRUE); -} - -static NMActStageReturn -dhcp4_start (NMDevice *self, - NMConnection *connection, - NMDeviceStateReason *reason) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - NMSettingIP4Config *s_ip4; - guint8 *anycast = NULL; - GByteArray *tmp = NULL; - guint hwaddr_len = 0; - const guint8 *hwaddr; - - s_ip4 = nm_connection_get_setting_ip4_config (connection); - - if (priv->dhcp_anycast_address) - anycast = priv->dhcp_anycast_address->data; - - /* Clear old exported DHCP options */ - if (priv->dhcp4_config) - g_object_unref (priv->dhcp4_config); - priv->dhcp4_config = nm_dhcp4_config_new (); - - hwaddr = nm_device_get_hw_address (self, &hwaddr_len); - if (hwaddr) { - tmp = g_byte_array_sized_new (hwaddr_len); - g_byte_array_append (tmp, hwaddr, hwaddr_len); - } - - /* Begin DHCP on the interface */ - g_warn_if_fail (priv->dhcp4_client == NULL); - priv->dhcp4_client = nm_dhcp_manager_start_ip4 (priv->dhcp_manager, - nm_device_get_ip_iface (self), - tmp, - nm_connection_get_uuid (connection), - s_ip4, - priv->dhcp_timeout, - anycast); - - if (tmp) - g_byte_array_free (tmp, TRUE); - - if (!priv->dhcp4_client) { - *reason = NM_DEVICE_STATE_REASON_DHCP_START_FAILED; - return NM_ACT_STAGE_RETURN_FAILURE; - } - - priv->dhcp4_state_sigid = g_signal_connect (priv->dhcp4_client, - "state-changed", - G_CALLBACK (dhcp4_state_changed), - self); - priv->dhcp4_timeout_sigid = g_signal_connect (priv->dhcp4_client, - "timeout", - G_CALLBACK (dhcp4_timeout), - self); - - /* DHCP devices will be notified by the DHCP manager when stuff happens */ - return NM_ACT_STAGE_RETURN_POSTPONE; -} - -gboolean -nm_device_dhcp4_renew (NMDevice *self, gboolean release) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - NMActStageReturn ret; - NMDeviceStateReason reason; - NMConnection *connection; - - g_return_val_if_fail (priv->dhcp4_client != NULL, FALSE); - - nm_log_info (LOGD_DHCP4, "(%s): DHCPv4 lease renewal requested", - nm_device_get_iface (self)); - - /* Terminate old DHCP instance and release the old lease */ - dhcp4_cleanup (self, TRUE, release); - - connection = nm_device_get_connection (self); - g_assert (connection); - - /* Start DHCP again on the interface */ - ret = dhcp4_start (self, connection, &reason); - - return (ret != NM_ACT_STAGE_RETURN_FAILURE); -} - -/*********************************************/ - -static GHashTable *shared_ips = NULL; - -static void -release_shared_ip (gpointer data) -{ - g_hash_table_remove (shared_ips, data); -} - -static guint32 -reserve_shared_ip (void) -{ - guint32 start = (guint32) ntohl (0x0a2a0001); /* 10.42.0.1 */ - guint32 count = 0; - - while (g_hash_table_lookup (shared_ips, GUINT_TO_POINTER (start + count))) { - count += ntohl (0x100); - if (count > ntohl (0xFE00)) { - nm_log_err (LOGD_SHARING, "ran out of shared IP addresses!"); - return 0; - } - } - - g_hash_table_insert (shared_ips, GUINT_TO_POINTER (start + count), GUINT_TO_POINTER (TRUE)); - return start + count; -} - -static NMIP4Config * -shared4_new_config (NMDevice *self, NMDeviceStateReason *reason) -{ - NMIP4Config *config = NULL; - NMIP4Address *addr; - guint32 tmp_addr; - - g_return_val_if_fail (self != NULL, NULL); - - if (G_UNLIKELY (shared_ips == NULL)) - shared_ips = g_hash_table_new (g_direct_hash, g_direct_equal); - - tmp_addr = reserve_shared_ip (); - if (!tmp_addr) { - *reason = NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE; - return NULL; - } - - config = nm_ip4_config_new (); - addr = nm_ip4_address_new (); - nm_ip4_address_set_address (addr, tmp_addr); - nm_ip4_address_set_prefix (addr, 24); - nm_ip4_config_take_address (config, addr); - - /* Remove the address lock when the object gets disposed */ - g_object_set_data_full (G_OBJECT (config), "shared-ip", - GUINT_TO_POINTER (tmp_addr), release_shared_ip); - - return config; -} - -/*********************************************/ - -static gboolean -have_any_ready_slaves (NMDevice *device, const GSList *slaves) -{ - const GSList *iter; - - /* Any enslaved slave is "ready" in the generic case as it's - * at least >= NM_DEVCIE_STATE_IP_CONFIG and has had Layer 2 - * properties set up. - */ - for (iter = slaves; iter; iter = g_slist_next (iter)) { - if (nm_device_get_enslaved (iter->data)) - return TRUE; - } - return FALSE; -} - -static gboolean -ip4_requires_slaves (NMConnection *connection) -{ - NMSettingIP4Config *s_ip4; - const char *method = NM_SETTING_IP4_CONFIG_METHOD_AUTO; - - s_ip4 = nm_connection_get_setting_ip4_config (connection); - if (s_ip4) - method = nm_setting_ip4_config_get_method (s_ip4); - - return g_strcmp0 (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0; -} - -static NMActStageReturn -act_stage3_ip4_config_start (NMDevice *self, - NMIP4Config **out_config, - NMDeviceStateReason *reason) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - NMConnection *connection; - NMSettingIP4Config *s_ip4; - NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; - const char *method = NM_SETTING_IP4_CONFIG_METHOD_AUTO; - GSList *slaves; - gboolean ready_slaves; - - g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); - - connection = nm_device_get_connection (self); - g_assert (connection); - - if (priv->is_master && ip4_requires_slaves (connection)) { - /* If the master has no ready slaves, and depends on slaves for - * a successful IPv4 attempt, then postpone IPv4 addressing. - */ - slaves = nm_device_master_get_slaves (self); - ready_slaves = NM_DEVICE_GET_CLASS (self)->have_any_ready_slaves (self, slaves); - g_slist_free (slaves); - - if (ready_slaves == FALSE) { - nm_log_info (LOGD_DEVICE | LOGD_IP4, - "(%s): IPv4 config waiting until slaves are ready", - nm_device_get_ip_iface (self)); - return NM_ACT_STAGE_RETURN_WAIT; - } - } - - /* If we did not receive IP4 configuration information, default to DHCP. - * Slaves, on the other hand, never have any IP configuration themselves, - * since the master handles all of that. - */ - s_ip4 = nm_connection_get_setting_ip4_config (connection); - if (priv->master) /* eg, device is a slave */ - method = NM_SETTING_IP4_CONFIG_METHOD_DISABLED; - else if (s_ip4) - method = nm_setting_ip4_config_get_method (s_ip4); - else - method = NM_SETTING_IP4_CONFIG_METHOD_AUTO; - - /* Start IPv4 addressing based on the method requested */ - if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0) - ret = dhcp4_start (self, connection, reason); - else if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL) == 0) - ret = aipd_start (self, reason); - else if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL) == 0) { - /* Use only IPv4 config from the connection data */ - *out_config = nm_ip4_config_new (); - g_assert (*out_config); - ret = NM_ACT_STAGE_RETURN_SUCCESS; - } else if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_SHARED) == 0) { - *out_config = shared4_new_config (self, reason); - if (*out_config) { - priv->dnsmasq_manager = nm_dnsmasq_manager_new (nm_device_get_ip_iface (self)); - ret = NM_ACT_STAGE_RETURN_SUCCESS; - } else - ret = NM_ACT_STAGE_RETURN_FAILURE; - } else if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED) == 0) { - /* Nothing to do... */ - ret = NM_ACT_STAGE_RETURN_STOP; - } else { - nm_log_warn (LOGD_IP4, "(%s): unhandled IPv4 config method '%s'; will fail", - nm_device_get_ip_iface (self), method); - } - - return ret; -} - -/*********************************************/ -/* DHCPv6 stuff */ - -static void -dhcp6_add_option_cb (gpointer key, gpointer value, gpointer user_data) -{ - nm_dhcp6_config_add_option (NM_DHCP6_CONFIG (user_data), - (const char *) key, - (const char *) value); -} - -static void -merge_ip6_configs (NMIP6Config *dst, NMIP6Config *src) -{ - guint32 i; - - g_return_if_fail (src != NULL); - g_return_if_fail (dst != NULL); - - /* addresses */ - for (i = 0; i < nm_ip6_config_get_num_addresses (src); i++) - nm_ip6_config_add_address (dst, nm_ip6_config_get_address (src, i)); - - /* ptp address; only replace if src doesn't have one */ - if (!nm_ip6_config_get_ptp_address (dst)) - nm_ip6_config_set_ptp_address (dst, nm_ip6_config_get_ptp_address (src)); - - /* nameservers */ - for (i = 0; i < nm_ip6_config_get_num_nameservers (src); i++) - nm_ip6_config_add_nameserver (dst, nm_ip6_config_get_nameserver (src, i)); - - /* default gateway */ - if (!nm_ip6_config_get_gateway (dst)) - nm_ip6_config_set_gateway (dst, nm_ip6_config_get_gateway (src)); - - /* routes */ - for (i = 0; i < nm_ip6_config_get_num_routes (src); i++) - nm_ip6_config_add_route (dst, nm_ip6_config_get_route (src, i)); - - /* domains */ - for (i = 0; i < nm_ip6_config_get_num_domains (src); i++) - nm_ip6_config_add_domain (dst, nm_ip6_config_get_domain (src, i)); - - /* dns searches */ - for (i = 0; i < nm_ip6_config_get_num_searches (src); i++) - nm_ip6_config_add_search (dst, nm_ip6_config_get_search (src, i)); - - if (!nm_ip6_config_get_mss (dst)) - nm_ip6_config_set_mss (dst, nm_ip6_config_get_mss (src)); -} - -static gboolean -ip6_config_merge_and_apply (NMDevice *self, - NMIP6Config *src_config, - NMDeviceStateReason *out_reason) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - NMConnection *connection; - gboolean success; - NMIP6Config *composite; - - connection = nm_device_get_connection (self); - g_assert (connection); - - /* If no config was passed in, create a new one */ - composite = nm_ip6_config_new (); - g_assert (composite); - - /* Merge in the given config first, if any */ - if (src_config) - merge_ip6_configs (composite, src_config); - - /* Merge RA and DHCPv6 configs into the composite config */ - if (priv->ac_ip6_config && (src_config != priv->ac_ip6_config)) - merge_ip6_configs (composite, priv->ac_ip6_config); - if (priv->dhcp6_ip6_config && (src_config != priv->dhcp6_ip6_config)) - merge_ip6_configs (composite, priv->dhcp6_ip6_config); - - /* Merge user overrides into the composite config */ - nm_utils_merge_ip6_config (composite, nm_connection_get_setting_ip6_config (connection)); - - success = nm_device_set_ip6_config (self, composite, out_reason); - g_object_unref (composite); - return success; -} - -static void -dhcp6_lease_change (NMDevice *device) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); - NMConnection *connection; - NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; - - if (priv->dhcp6_ip6_config == NULL) { - nm_log_warn (LOGD_DHCP6, "(%s): failed to get DHCPv6 config for rebind", - nm_device_get_ip_iface (device)); - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED); - return; - } - - g_assert (priv->dhcp6_client); /* sanity check */ - - connection = nm_device_get_connection (device); - g_assert (connection); - - /* Apply the updated config */ - if (ip6_config_merge_and_apply (device, NULL, &reason) == FALSE) { - nm_log_warn (LOGD_DHCP6, "(%s): failed to update IPv6 config in response to DHCP event.", - nm_device_get_ip_iface (device)); - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, reason); - } else { - /* Notify dispatcher scripts of new DHCPv6 config */ - nm_dispatcher_call (DISPATCHER_ACTION_DHCP6_CHANGE, connection, device, NULL, NULL); - } -} - -static void -dhcp6_fail (NMDevice *device, gboolean timeout) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); - - nm_dhcp6_config_reset (priv->dhcp6_config); - - if (timeout || (priv->ip6_state == IP_CONF)) - nm_device_activate_schedule_ip6_config_timeout (device); - else if (priv->ip6_state == IP_DONE) - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED); -} - -static void -dhcp6_state_changed (NMDHCPClient *client, - NMDHCPState state, - gpointer user_data) -{ - NMDevice *device = NM_DEVICE (user_data); - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); - NMDeviceState dev_state; - - g_return_if_fail (nm_dhcp_client_get_ipv6 (client) == TRUE); - - nm_log_dbg (LOGD_DHCP6, "(%s): new DHCPv6 client state %d", - nm_device_get_iface (device), state); - - dev_state = nm_device_get_state (device); - - switch (state) { - case DHC_BOUND6: - case DHC_RENEW6: /* lease renewed */ - case DHC_REBOOT: /* have valid lease, but now obtained a different one */ - case DHC_REBIND6: /* new, different lease */ - if (priv->dhcp6_ip6_config) - g_object_unref (priv->dhcp6_ip6_config); - priv->dhcp6_ip6_config = nm_dhcp_client_get_ip6_config (priv->dhcp6_client, FALSE); - - /* Update the DHCP6 config object with new DHCP options */ - nm_dhcp6_config_reset (priv->dhcp6_config); - if (priv->dhcp6_ip6_config) { - nm_dhcp_client_foreach_option (priv->dhcp6_client, - dhcp6_add_option_cb, - priv->dhcp6_config); - } - g_object_notify (G_OBJECT (device), NM_DEVICE_DHCP6_CONFIG); - - if (priv->ip6_state == IP_CONF) - nm_device_activate_schedule_ip6_config_result (device, priv->dhcp6_ip6_config); - else if (priv->ip6_state == IP_DONE) - dhcp6_lease_change (device); - break; - case DHC_TIMEOUT: /* timed out contacting DHCP server */ - dhcp6_fail (device, TRUE); - break; - case DHC_END: /* dhclient exited normally */ - /* In IPv6 info-only mode, the client doesn't handle leases so it - * may exit right after getting a response from the server. That's - * normal. In that case we just ignore the exit. - */ - if (priv->dhcp6_mode == IP6_DHCP_OPT_OTHERCONF) - break; - /* Otherwise, fall through */ - case DHC_FAIL: /* all attempts to contact server timed out, sleeping */ - case DHC_ABEND: /* dhclient exited abnormally */ - /* dhclient quit and can't get/renew a lease; so kill the connection */ - dhcp6_fail (device, FALSE); - break; - default: - break; - } -} - -static void -dhcp6_timeout (NMDHCPClient *client, gpointer user_data) -{ - NMDevice *device = NM_DEVICE (user_data); - - g_return_if_fail (nm_device_get_act_request (device) != NULL); - g_return_if_fail (nm_dhcp_client_get_ipv6 (client) == TRUE); - - nm_dhcp_client_stop (client, FALSE); - dhcp6_fail (device, TRUE); -} - -static NMActStageReturn -dhcp6_start (NMDevice *self, - NMConnection *connection, - guint32 dhcp_opt, - NMDeviceStateReason *reason) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; - guint8 *anycast = NULL; - GByteArray *tmp = NULL; - guint hwaddr_len = 0; - const guint8 *hwaddr; - - if (!connection) { - connection = nm_device_get_connection (self); - g_assert (connection); - } - - /* Begin a DHCP transaction on the interface */ - - if (priv->dhcp_anycast_address) - anycast = priv->dhcp_anycast_address->data; - - /* Clear old exported DHCP options */ - if (priv->dhcp6_config) - g_object_unref (priv->dhcp6_config); - priv->dhcp6_config = nm_dhcp6_config_new (); - - g_warn_if_fail (priv->dhcp6_ip6_config == NULL); - if (priv->dhcp6_ip6_config) { - g_object_unref (priv->dhcp6_ip6_config); - priv->dhcp6_ip6_config = NULL; - } - - hwaddr = nm_device_get_hw_address (self, &hwaddr_len); - if (hwaddr) { - tmp = g_byte_array_sized_new (hwaddr_len); - g_byte_array_append (tmp, hwaddr, hwaddr_len); - } - - priv->dhcp6_client = nm_dhcp_manager_start_ip6 (priv->dhcp_manager, - nm_device_get_ip_iface (self), - tmp, - nm_connection_get_uuid (connection), - nm_connection_get_setting_ip6_config (connection), - priv->dhcp_timeout, - anycast, - (dhcp_opt == IP6_DHCP_OPT_OTHERCONF) ? TRUE : FALSE); - if (tmp) - g_byte_array_free (tmp, TRUE); - - if (priv->dhcp6_client) { - priv->dhcp6_state_sigid = g_signal_connect (priv->dhcp6_client, - "state-changed", - G_CALLBACK (dhcp6_state_changed), - self); - priv->dhcp6_timeout_sigid = g_signal_connect (priv->dhcp6_client, - "timeout", - G_CALLBACK (dhcp6_timeout), - self); - - /* DHCP devices will be notified by the DHCP manager when stuff happens */ - ret = NM_ACT_STAGE_RETURN_POSTPONE; - } else { - *reason = NM_DEVICE_STATE_REASON_DHCP_START_FAILED; - ret = NM_ACT_STAGE_RETURN_FAILURE; - } - - return ret; -} - -/******************************************/ - -static void -ip6_addrconf_complete (NMIP6Manager *ip6_manager, - int ifindex, - guint dhcp_opts, - gboolean success, - gpointer user_data) -{ - NMDevice *self = NM_DEVICE (user_data); - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - NMConnection *connection; - NMActStageReturn ret; - NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; - - if (ifindex != nm_device_get_ip_ifindex (self)) - return; - g_return_if_fail (priv->act_request != NULL); - connection = nm_device_get_connection (self); - g_assert (connection); - - if (!priv->ip6_waiting_for_config) - return; - - priv->ip6_waiting_for_config = FALSE; - - if (!success) { - nm_device_activate_schedule_ip6_config_timeout (self); - return; - } - - priv->dhcp6_mode = dhcp_opts; - - /* If addrconf is all that's required, we're done */ - if (priv->dhcp6_mode == IP6_DHCP_OPT_NONE) { - priv->ac_ip6_config = nm_ip6_manager_get_ip6_config (ip6_manager, ifindex); - nm_device_activate_schedule_ip6_config_result (self, priv->ac_ip6_config); - return; - } - - /* If the router said to use DHCP for managed or otherconf, do it */ - - /* Don't re-start DHCPv6 if it's already in progress */ - if (priv->ip6_state != IP_CONF) - return; - - nm_log_info (LOGD_DEVICE | LOGD_DHCP6, - "Activation (%s) Stage 3 of 5 (IP Configure Start) starting DHCPv6" - " as requested by IPv6 router...", - priv->iface); - - ret = dhcp6_start (self, connection, priv->dhcp6_mode, &reason); - switch (ret) { - case NM_ACT_STAGE_RETURN_SUCCESS: - /* Shouldn't get this, but handle it anyway */ - g_warn_if_reached (); - priv->ac_ip6_config = nm_ip6_manager_get_ip6_config (ip6_manager, ifindex); - nm_device_activate_schedule_ip6_config_result (self, priv->ac_ip6_config); - break; - case NM_ACT_STAGE_RETURN_POSTPONE: - /* Cache acquired autoconf config and wait for DHCPv6 to complete */ - priv->ac_ip6_config = nm_ip6_manager_get_ip6_config (ip6_manager, ifindex); - break; - default: - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); - break; - } -} - -static void -ip6_config_changed (NMIP6Manager *ip6_manager, - int ifindex, - guint dhcp_opts, - gboolean success, - gpointer user_data) -{ - NMDevice *self = NM_DEVICE (user_data); - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; - - if (ifindex != nm_device_get_ip_ifindex (self)) - return; - g_return_if_fail (priv->act_request != NULL); - - /* If autoconf failed and IPv6 previously succeeded, fail */ - if (!success && (priv->ip6_state == IP_DONE)) { - nm_device_state_changed (self, - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); - return; - } - - /* FIXME: re-run DHCPv6 here to get any new nameservers or whatever */ - - if (priv->ac_ip6_config) - g_object_unref (priv->ac_ip6_config); - priv->ac_ip6_config = nm_ip6_manager_get_ip6_config (ip6_manager, ifindex); - - if (ip6_config_merge_and_apply (self, NULL, &reason) == FALSE) { - nm_log_warn (LOGD_DHCP6, "(%s): failed to update IPv6 config in response to Router Advertisement.", - nm_device_get_ip_iface (self)); - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); - } -} - -static gboolean -addrconf6_start (NMDevice *self) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - NMConnection *connection; - gboolean success; - const guint8 *hwaddr; - guint hwaddr_len = 0; - - connection = nm_device_get_connection (self); - g_assert (connection); - - g_warn_if_fail (priv->ac_ip6_config == NULL); - if (priv->ac_ip6_config) { - g_object_unref (priv->ac_ip6_config); - priv->ac_ip6_config = NULL; - } - - if (!priv->ip6_manager) { - priv->ip6_manager = nm_ip6_manager_get (); - priv->ip6_addrconf_sigid = g_signal_connect (priv->ip6_manager, - "addrconf-complete", - G_CALLBACK (ip6_addrconf_complete), - self); - priv->ip6_config_changed_sigid = g_signal_connect (priv->ip6_manager, - "config-changed", - G_CALLBACK (ip6_config_changed), - self); - } - - hwaddr = nm_device_get_hw_address (self, &hwaddr_len); - g_warn_if_fail (hwaddr != NULL); - success = nm_ip6_manager_prepare_interface (priv->ip6_manager, - nm_device_get_ip_ifindex (self), - hwaddr, - hwaddr_len, - nm_connection_get_setting_ip6_config (connection), - priv->ip6_accept_ra_path); - if (success) { - priv->ip6_waiting_for_config = TRUE; - nm_ip6_manager_begin_addrconf (priv->ip6_manager, nm_device_get_ip_ifindex (self)); - } - - return success; -} - -static void -addrconf6_cleanup (NMDevice *self) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - - if (priv->ac_ip6_config) { - g_object_unref (priv->ac_ip6_config); - priv->ac_ip6_config = NULL; - } - - if (!priv->ip6_manager) - return; - - if (priv->ip6_addrconf_sigid) { - g_signal_handler_disconnect (priv->ip6_manager, - priv->ip6_addrconf_sigid); - priv->ip6_addrconf_sigid = 0; - } - if (priv->ip6_config_changed_sigid) { - g_signal_handler_disconnect (priv->ip6_manager, - priv->ip6_config_changed_sigid); - priv->ip6_config_changed_sigid = 0; - } - - nm_ip6_manager_cancel_addrconf (priv->ip6_manager, nm_device_get_ip_ifindex (self)); - g_object_unref (priv->ip6_manager); - priv->ip6_manager = NULL; -} - -/******************************************/ - -/* Get net.ipv6.conf.default.use_tempaddr value from /etc/sysctl.conf or - * /lib/sysctl.d/sysctl.conf - */ -static int -ip6_use_tempaddr (void) -{ - char *contents = NULL; - gsize len = 0; - const char *group_name = "[forged_group]\n"; - char *sysctl_data = NULL; - GKeyFile *keyfile; - GError *error = NULL; - int tmp, ret = -1; - - /* Read file contents to a string. */ - if (!g_file_get_contents ("/etc/sysctl.conf", &contents, &len, NULL)) - if (!g_file_get_contents ("/lib/sysctl.d/sysctl.conf", &contents, &len, NULL)) - return -1; - - /* Prepend a group so that we can use GKeyFile parser. */ - sysctl_data = g_strdup_printf ("%s%s", group_name, contents); - - keyfile = g_key_file_new (); - if (keyfile == NULL) - goto done; - - if (!g_key_file_load_from_data (keyfile, sysctl_data, len + strlen (group_name), G_KEY_FILE_NONE, NULL)) - goto done; - - tmp = g_key_file_get_integer (keyfile, "forged_group", "net.ipv6.conf.default.use_tempaddr", &error); - if (error == NULL) - ret = tmp; - -done: - g_free (contents); - g_free (sysctl_data); - g_clear_error (&error); - g_key_file_free (keyfile); - - return ret; -} - -static gboolean -ip6_requires_slaves (NMConnection *connection) -{ - NMSettingIP6Config *s_ip6; - const char *method = NM_SETTING_IP6_CONFIG_METHOD_AUTO; - - s_ip6 = nm_connection_get_setting_ip6_config (connection); - if (s_ip6) - method = nm_setting_ip6_config_get_method (s_ip6); - - /* SLAAC, DHCP, and Link-Local depend on connectivity (and thus slaves) - * to complete addressing. SLAAC and DHCP obviously need a peer to - * provide a prefix, while Link-Local must perform DAD on the local link. - */ - return g_strcmp0 (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) == 0 - || g_strcmp0 (method, NM_SETTING_IP6_CONFIG_METHOD_DHCP) == 0 - || g_strcmp0 (method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL) == 0; -} - -static NMActStageReturn -act_stage3_ip6_config_start (NMDevice *self, - NMIP6Config **out_config, - NMDeviceStateReason *reason) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - const char *ip_iface; - NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; - NMConnection *connection; - NMSettingIP6Config *s_ip6; - const char *method = NM_SETTING_IP6_CONFIG_METHOD_AUTO; - int conf_use_tempaddr; - NMSettingIP6ConfigPrivacy ip6_privacy = NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN; - const char *ip6_privacy_str = "0\n"; - GSList *slaves; - gboolean ready_slaves; - - g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); - - connection = nm_device_get_connection (self); - g_assert (connection); - - ip_iface = nm_device_get_ip_iface (self); - - if (priv->is_master && ip6_requires_slaves (connection)) { - /* If the master has no ready slaves, and depends on slaves for - * a successful IPv6 attempt, then postpone IPv6 addressing. - */ - slaves = nm_device_master_get_slaves (self); - ready_slaves = NM_DEVICE_GET_CLASS (self)->have_any_ready_slaves (self, slaves); - g_slist_free (slaves); - - if (ready_slaves == FALSE) { - nm_log_info (LOGD_DEVICE | LOGD_IP6, - "(%s): IPv6 config waiting until slaves are ready", - ip_iface); - return NM_ACT_STAGE_RETURN_WAIT; - } - } - - update_accept_ra_save (self); - update_ip6_privacy_save (self); - - priv->dhcp6_mode = IP6_DHCP_OPT_NONE; - - /* If we did not receive IP6 configuration information, default to AUTO. - * Slaves, on the other hand, never have any IP configuration themselves, - * since the master handles all of that. - */ - s_ip6 = nm_connection_get_setting_ip6_config (connection); - if (priv->master) /* eg, device is a slave */ - method = NM_SETTING_IP6_CONFIG_METHOD_IGNORE; - else if (s_ip6) - method = nm_setting_ip6_config_get_method (s_ip6); - else - method = NM_SETTING_IP6_CONFIG_METHOD_AUTO; - - if ( strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) == 0 - || strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL) == 0) { - if (!addrconf6_start (self)) { - *reason = NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE; - ret = NM_ACT_STAGE_RETURN_FAILURE; - } else - ret = NM_ACT_STAGE_RETURN_POSTPONE; - } else if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_DHCP) == 0) { - /* Router advertisements shouldn't be used in pure DHCP mode */ - if (priv->ip6_accept_ra_path) - nm_utils_do_sysctl (priv->ip6_accept_ra_path, "0"); - - priv->dhcp6_mode = IP6_DHCP_OPT_MANAGED; - ret = dhcp6_start (self, connection, priv->dhcp6_mode, reason); - } else if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE) == 0) { - /* reset the saved RA value when ipv6 is ignored */ - if (priv->ip6_accept_ra_path) { - nm_utils_do_sysctl (priv->ip6_accept_ra_path, - priv->ip6_accept_ra_save ? "1" : "0"); - } - ret = NM_ACT_STAGE_RETURN_STOP; - } else if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_MANUAL) == 0) { - /* New blank config */ - *out_config = nm_ip6_config_new (); - g_assert (*out_config); - - /* Router advertisements shouldn't be used in manual mode */ - if (priv->ip6_accept_ra_path) - nm_utils_do_sysctl (priv->ip6_accept_ra_path, "0"); - ret = NM_ACT_STAGE_RETURN_SUCCESS; - } else { - nm_log_warn (LOGD_IP6, "(%s): unhandled IPv6 config method '%s'; will fail", - nm_device_get_ip_iface (self), method); - } - - /* Other methods (shared) aren't implemented yet */ - - /* Enable/disable IPv6 Privacy Extensions. - * If a global value is configured by sysadmin (e.g. /etc/sysctl.conf), - * use that value instead of per-connection value. - */ - conf_use_tempaddr = ip6_use_tempaddr (); - if (conf_use_tempaddr >= 0) - ip6_privacy = conf_use_tempaddr; - else if (s_ip6) - ip6_privacy = nm_setting_ip6_config_get_ip6_privacy (s_ip6); - ip6_privacy = CLAMP (ip6_privacy, NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN, NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR); - - switch (ip6_privacy) { - case NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN: - case NM_SETTING_IP6_CONFIG_PRIVACY_DISABLED: - ip6_privacy_str = "0"; - break; - case NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR: - ip6_privacy_str = "1"; - break; - case NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR: - ip6_privacy_str = "2"; - break; - } - if (priv->ip6_privacy_tempaddr_path) - nm_utils_do_sysctl (priv->ip6_privacy_tempaddr_path, ip6_privacy_str); - - return ret; -} - -/** - * nm_device_activate_stage3_ip4_start: - * @self: the device - * - * Try starting IPv4 configuration. - */ -gboolean -nm_device_activate_stage3_ip4_start (NMDevice *self) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - NMActStageReturn ret; - NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; - NMIP4Config *ip4_config = NULL; - - g_assert (priv->ip4_state == IP_WAIT); - - priv->ip4_state = IP_CONF; - ret = NM_DEVICE_GET_CLASS (self)->act_stage3_ip4_config_start (self, &ip4_config, &reason); - if (ret == NM_ACT_STAGE_RETURN_SUCCESS) { - g_assert (ip4_config); - nm_device_activate_schedule_ip4_config_result (self, ip4_config); - g_object_unref (ip4_config); - } else if (ret == NM_ACT_STAGE_RETURN_FAILURE) { - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); - return FALSE; - } else if (ret == NM_ACT_STAGE_RETURN_STOP) { - /* Early finish */ - priv->ip4_state = IP_DONE; - } else if (ret == NM_ACT_STAGE_RETURN_WAIT) { - /* Wait for something to try IP config again */ - priv->ip4_state = IP_WAIT; - } else - g_assert (ret == NM_ACT_STAGE_RETURN_POSTPONE); - - return TRUE; -} - -/** - * nm_device_activate_stage3_ip6_start: - * @self: the device - * - * Try starting IPv6 configuration. - */ -gboolean -nm_device_activate_stage3_ip6_start (NMDevice *self) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - NMActStageReturn ret; - NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; - NMIP6Config *ip6_config = NULL; - - g_assert (priv->ip6_state == IP_WAIT); - - priv->ip6_state = IP_CONF; - ret = NM_DEVICE_GET_CLASS (self)->act_stage3_ip6_config_start (self, &ip6_config, &reason); - if (ret == NM_ACT_STAGE_RETURN_SUCCESS) { - g_assert (ip6_config); - nm_device_activate_schedule_ip6_config_result (self, ip6_config); - g_object_unref (ip6_config); - } else if (ret == NM_ACT_STAGE_RETURN_FAILURE) { - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); - return FALSE; - } else if (ret == NM_ACT_STAGE_RETURN_STOP) { - /* Early finish */ - priv->ip6_state = IP_DONE; - } else if (ret == NM_ACT_STAGE_RETURN_WAIT) { - /* Wait for something to try IP config again */ - priv->ip6_state = IP_WAIT; - } else - g_assert (ret == NM_ACT_STAGE_RETURN_POSTPONE); - - return TRUE; -} - -/* - * nm_device_activate_stage3_ip_config_start - * - * Begin automatic/manual IP configuration - * - */ -static gboolean -nm_device_activate_stage3_ip_config_start (gpointer user_data) -{ - NMDevice *self = NM_DEVICE (user_data); - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - const char *iface; - int ifindex; - NMDevice *master; - - /* Clear the activation source ID now that this stage has run */ - activation_source_clear (self, FALSE, 0); - - iface = nm_device_get_iface (self); - nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 3 of 5 (IP Configure Start) started...", iface); - nm_device_state_changed (self, NM_DEVICE_STATE_IP_CONFIG, NM_DEVICE_STATE_REASON_NONE); - - /* Make sure the interface is up before trying to do anything with it */ - ifindex = nm_device_get_ip_ifindex (self); - if ((ifindex > 0) && (nm_system_iface_is_up (ifindex) == FALSE)) - nm_system_iface_set_up (ifindex, TRUE, NULL); - - priv->ip4_state = priv->ip6_state = IP_WAIT; - - /* If the device is a slave, then we don't do any IP configuration but we - * use the IP config stage to indicate to the master we're ready for - * enslavement. Either the master has already enslaved us, in which case - * our state transition to SECONDARIES is already queued courtesy of - * nm_device_slave_notify_enslaved(), or the master is still activating, - * in which case we postpone activation here until the master enslaves us, - * which calls nm_device_slave_notify_enslaved(). - */ - master = nm_active_connection_get_master (NM_ACTIVE_CONNECTION (priv->act_request)); - if (master) { - if (priv->enslaved == FALSE) { - nm_log_info (LOGD_DEVICE, "Activation (%s) connection '%s' waiting on master '%s'", - nm_device_get_iface (self), - nm_connection_get_id (nm_device_get_connection (self)), - nm_device_get_iface (master)); - } - goto out; - } - - /* IPv4 */ - if (!nm_device_activate_stage3_ip4_start (self)) - goto out; - - /* IPv6 */ - if (!nm_device_activate_stage3_ip6_start (self)) - goto out; - -out: - nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 3 of 5 (IP Configure Start) complete.", iface); - return FALSE; -} - - -static void -fw_add_to_zone_cb (GError *error, gpointer user_data) -{ - NMDevice *self = NM_DEVICE (user_data); - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - - priv->fw_call = NULL; - - if (error) { - /* FIXME: fail the device activation? */ - } - - activation_source_schedule (self, nm_device_activate_stage3_ip_config_start, 0); - - nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 3 of 5 (IP Configure Start) scheduled.", - nm_device_get_iface (self)); -} - -/* - * nm_device_activate_schedule_stage3_ip_config_start - * - * Schedule IP configuration start - */ -void -nm_device_activate_schedule_stage3_ip_config_start (NMDevice *self) -{ - NMDevicePrivate *priv; - NMConnection *connection; - NMSettingConnection *s_con = NULL; - NMDeviceState state; - const char *zone; - - g_return_if_fail (NM_IS_DEVICE (self)); - - priv = NM_DEVICE_GET_PRIVATE (self); - g_return_if_fail (priv->act_request); - - state = nm_device_get_state (self); - if (nm_active_connection_get_assumed (NM_ACTIVE_CONNECTION (priv->act_request)) == FALSE) - g_warn_if_fail (state >= NM_DEVICE_STATE_PREPARE && state <= NM_DEVICE_STATE_NEED_AUTH); - - /* Add the interface to the specified firewall zone */ - connection = nm_device_get_connection (self); - g_assert (connection); - s_con = nm_connection_get_setting_connection (connection); - - zone = nm_setting_connection_get_zone (s_con); - nm_log_dbg (LOGD_DEVICE, "Activation (%s) setting firewall zone '%s'", - nm_device_get_iface (self), zone ? zone : "default"); - priv->fw_call = nm_firewall_manager_add_or_change_zone (priv->fw_manager, - nm_device_get_ip_iface (self), - zone, - TRUE, - fw_add_to_zone_cb, - self); -} - -static NMActStageReturn -act_stage4_ip4_config_timeout (NMDevice *self, NMDeviceStateReason *reason) -{ - if (nm_device_ip_config_should_fail (self, FALSE)) { - *reason = NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE; - return NM_ACT_STAGE_RETURN_FAILURE; - } - return NM_ACT_STAGE_RETURN_SUCCESS; -} - - -/* - * nm_device_activate_stage4_ip4_config_timeout - * - * Time out on retrieving the IPv4 config. - * - */ -static gboolean -nm_device_activate_ip4_config_timeout (gpointer user_data) -{ - NMDevice *self = NM_DEVICE (user_data); - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - const char *iface; - NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; - NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; - - /* Clear the activation source ID now that this stage has run */ - activation_source_clear (self, FALSE, AF_INET); - - iface = nm_device_get_iface (self); - nm_log_info (LOGD_DEVICE | LOGD_IP4, - "Activation (%s) Stage 4 of 5 (IPv4 Configure Timeout) started...", - iface); - - ret = NM_DEVICE_GET_CLASS (self)->act_stage4_ip4_config_timeout (self, &reason); - if (ret == NM_ACT_STAGE_RETURN_POSTPONE) - goto out; - else if (ret == NM_ACT_STAGE_RETURN_FAILURE) { - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); - goto out; - } - g_assert (ret == NM_ACT_STAGE_RETURN_SUCCESS); - - priv->ip4_state = IP_DONE; - - /* If IPv4 failed and IPv6 failed, the activation fails */ - if ((priv->ip6_state == IP_DONE) && (priv->ip6_config == NULL)) { - nm_device_state_changed (self, - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); - } - -out: - nm_log_info (LOGD_DEVICE | LOGD_IP4, - "Activation (%s) Stage 4 of 5 (IPv4 Configure Timeout) complete.", - iface); - return FALSE; -} - - -/* - * nm_device_activate_schedule_ip4_config_timeout - * - * Deal with a timeout of the IPv4 configuration - * - */ -void -nm_device_activate_schedule_ip4_config_timeout (NMDevice *self) -{ - NMDevicePrivate *priv; - - g_return_if_fail (NM_IS_DEVICE (self)); - - priv = NM_DEVICE_GET_PRIVATE (self); - g_return_if_fail (priv->act_request); - - activation_source_schedule (self, nm_device_activate_ip4_config_timeout, AF_INET); - - nm_log_info (LOGD_DEVICE | LOGD_IP4, - "Activation (%s) Stage 4 of 5 (IPv4 Configure Timeout) scheduled...", - nm_device_get_iface (self)); -} - - -static NMActStageReturn -act_stage4_ip6_config_timeout (NMDevice *self, NMDeviceStateReason *reason) -{ - if (nm_device_ip_config_should_fail (self, TRUE)) { - *reason = NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE; - return NM_ACT_STAGE_RETURN_FAILURE; - } - - return NM_ACT_STAGE_RETURN_SUCCESS; -} - - -/* - * nm_device_activate_ip6_config_timeout - * - * Time out on retrieving the IPv6 config. - * - */ -static gboolean -nm_device_activate_ip6_config_timeout (gpointer user_data) -{ - NMDevice *self = NM_DEVICE (user_data); - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - const char *iface; - NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; - NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; - - /* Clear the activation source ID now that this stage has run */ - activation_source_clear (self, FALSE, AF_INET6); - - iface = nm_device_get_iface (self); - nm_log_info (LOGD_DEVICE | LOGD_IP6, - "Activation (%s) Stage 4 of 5 (IPv6 Configure Timeout) started...", - iface); - - ret = NM_DEVICE_GET_CLASS (self)->act_stage4_ip6_config_timeout (self, &reason); - if (ret == NM_ACT_STAGE_RETURN_POSTPONE) - goto out; - else if (ret == NM_ACT_STAGE_RETURN_FAILURE) { - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); - goto out; - } - g_assert (ret == NM_ACT_STAGE_RETURN_SUCCESS); - - priv->ip6_state = IP_DONE; - - /* If IPv6 failed and IPv4 failed, the activation fails */ - if ((priv->ip4_state == IP_DONE) && (priv->ip4_config == NULL)) { - nm_device_state_changed (self, - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); - } - -out: - nm_log_info (LOGD_DEVICE | LOGD_IP6, - "Activation (%s) Stage 4 of 5 (IPv6 Configure Timeout) complete.", - iface); - return FALSE; -} - - -/* - * nm_device_activate_schedule_ip6_config_timeout - * - * Deal with a timeout of the IPv6 configuration - * - */ -void -nm_device_activate_schedule_ip6_config_timeout (NMDevice *self) -{ - NMDevicePrivate *priv; - - g_return_if_fail (NM_IS_DEVICE (self)); - - priv = NM_DEVICE_GET_PRIVATE (self); - g_return_if_fail (priv->act_request); - - activation_source_schedule (self, nm_device_activate_ip6_config_timeout, AF_INET6); - - nm_log_info (LOGD_DEVICE | LOGD_IP6, - "Activation (%s) Stage 4 of 5 (IPv6 Configure Timeout) scheduled...", - nm_device_get_iface (self)); -} - -static void -share_child_setup (gpointer user_data G_GNUC_UNUSED) -{ - /* We are in the child process at this point */ - pid_t pid = getpid (); - setpgid (pid, pid); - - nm_unblock_posix_signals (NULL); -} - -static gboolean -share_init (void) -{ - int status; - char *modules[] = { "ip_tables", "iptable_nat", "nf_nat_ftp", "nf_nat_irc", - "nf_nat_sip", "nf_nat_tftp", "nf_nat_pptp", "nf_nat_h323", - NULL }; - char **iter; - - if (!nm_utils_do_sysctl ("/proc/sys/net/ipv4/ip_forward", "1")) { - nm_log_err (LOGD_SHARING, "Error starting IP forwarding: (%d) %s", - errno, strerror (errno)); - return FALSE; - } - - if (!nm_utils_do_sysctl ("/proc/sys/net/ipv4/ip_dynaddr", "1")) { - nm_log_err (LOGD_SHARING, "error starting IP forwarding: (%d) %s", - errno, strerror (errno)); - } - - for (iter = modules; *iter; iter++) { - char *argv[3] = { "/sbin/modprobe", *iter, NULL }; - char *envp[1] = { NULL }; - GError *error = NULL; - - if (!g_spawn_sync ("/", argv, envp, G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL, - share_child_setup, NULL, NULL, NULL, &status, &error)) { - nm_log_err (LOGD_SHARING, "error loading NAT module %s: (%d) %s", - *iter, error ? error->code : 0, - (error && error->message) ? error->message : "unknown"); - if (error) - g_error_free (error); - } - } - - return TRUE; -} - -static void -add_share_rule (NMActRequest *req, const char *table, const char *fmt, ...) -{ - va_list args; - char *cmd; - - va_start (args, fmt); - cmd = g_strdup_vprintf (fmt, args); - va_end (args); - - nm_act_request_add_share_rule (req, table, cmd); - g_free (cmd); -} - -static gboolean -start_sharing (NMDevice *self, NMIP4Config *config) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - NMActRequest *req; - GError *error = NULL; - char str_addr[INET_ADDRSTRLEN + 1]; - char str_mask[INET_ADDRSTRLEN + 1]; - guint32 netmask, network; - NMIP4Address *ip4_addr; - const char *ip_iface; - - g_return_val_if_fail (config != NULL, FALSE); - - ip_iface = nm_device_get_ip_iface (self); - - ip4_addr = nm_ip4_config_get_address (config, 0); - if (!ip4_addr || !nm_ip4_address_get_address (ip4_addr)) - return FALSE; - - netmask = nm_utils_ip4_prefix_to_netmask (nm_ip4_address_get_prefix (ip4_addr)); - if (!inet_ntop (AF_INET, &netmask, str_mask, sizeof (str_mask))) - return FALSE; - - network = nm_ip4_address_get_address (ip4_addr) & netmask; - if (!inet_ntop (AF_INET, &network, str_addr, sizeof (str_addr))) - return FALSE; - - if (!share_init ()) - return FALSE; - - req = nm_device_get_act_request (self); - g_assert (req); - - add_share_rule (req, "filter", "INPUT --in-interface %s --protocol tcp --destination-port 53 --jump ACCEPT", ip_iface); - add_share_rule (req, "filter", "INPUT --in-interface %s --protocol udp --destination-port 53 --jump ACCEPT", ip_iface); - add_share_rule (req, "filter", "INPUT --in-interface %s --protocol tcp --destination-port 67 --jump ACCEPT", ip_iface); - add_share_rule (req, "filter", "INPUT --in-interface %s --protocol udp --destination-port 67 --jump ACCEPT", ip_iface); - add_share_rule (req, "filter", "FORWARD --in-interface %s --jump REJECT", ip_iface); - add_share_rule (req, "filter", "FORWARD --out-interface %s --jump REJECT", ip_iface); - add_share_rule (req, "filter", "FORWARD --in-interface %s --out-interface %s --jump ACCEPT", ip_iface, ip_iface); - add_share_rule (req, "filter", "FORWARD --source %s/%s --in-interface %s --jump ACCEPT", str_addr, str_mask, ip_iface); - add_share_rule (req, "filter", "FORWARD --destination %s/%s --out-interface %s --match state --state ESTABLISHED,RELATED --jump ACCEPT", str_addr, str_mask, ip_iface); - add_share_rule (req, "nat", "POSTROUTING --source %s/%s ! --destination %s/%s --jump MASQUERADE", str_addr, str_mask, str_addr, str_mask); - - nm_act_request_set_shared (req, TRUE); - - if (!nm_dnsmasq_manager_start (priv->dnsmasq_manager, config, &error)) { - nm_log_err (LOGD_SHARING, "(%s/%s): failed to start dnsmasq: %s", - nm_device_get_iface (self), ip_iface, - (error && error->message) ? error->message : "(unknown)"); - g_error_free (error); - nm_act_request_set_shared (req, FALSE); - return FALSE; - } - - priv->dnsmasq_state_id = g_signal_connect (priv->dnsmasq_manager, "state-changed", - G_CALLBACK (dnsmasq_state_changed_cb), - self); - return TRUE; -} - -static gboolean -nm_device_activate_ip4_config_commit (gpointer user_data) -{ - NMDevice *self = NM_DEVICE (user_data); - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - NMActRequest *req; - NMIP4Config *config = NULL; - const char *iface, *method = NULL; - NMConnection *connection; - NMSettingIP4Config *s_ip4; - NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; - gboolean assumed; - int ifindex; - - /* Clear the activation source ID now that this stage has run */ - activation_source_clear (self, FALSE, AF_INET); - - iface = nm_device_get_iface (self); - nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 5 of 5 (IPv4 Commit) started...", - iface); - - req = nm_device_get_act_request (self); - g_assert (req); - connection = nm_act_request_get_connection (req); - g_assert (connection); - - config = g_object_get_data (G_OBJECT (req), PENDING_IP4_CONFIG); - g_assert (config); - - /* Make sure the interface is up again just because */ - ifindex = nm_device_get_ip_ifindex (self); - if ((ifindex > 0) && (nm_system_iface_is_up (ifindex) == FALSE)) - nm_system_iface_set_up (ifindex, TRUE, NULL); - - /* Allow setting MTU etc */ - if (NM_DEVICE_GET_CLASS (self)->ip4_config_pre_commit) - NM_DEVICE_GET_CLASS (self)->ip4_config_pre_commit (self, config); - - /* Merge with user overrides */ - nm_utils_merge_ip4_config (config, nm_connection_get_setting_ip4_config (connection)); - - assumed = nm_active_connection_get_assumed (NM_ACTIVE_CONNECTION (priv->act_request)); - if (!nm_device_set_ip4_config (self, config, assumed, &reason)) { - nm_log_info (LOGD_DEVICE | LOGD_IP4, - "Activation (%s) Stage 5 of 5 (IPv4 Commit) failed", - iface); - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); - goto out; - } - - /* Start IPv4 sharing if we need it */ - s_ip4 = nm_connection_get_setting_ip4_config (connection); - if (s_ip4) - method = nm_setting_ip4_config_get_method (s_ip4); - - if (g_strcmp0 (method, NM_SETTING_IP4_CONFIG_METHOD_SHARED) == 0) { - if (!start_sharing (self, config)) { - nm_log_warn (LOGD_SHARING, "Activation (%s) Stage 5 of 5 (IPv4 Commit) start sharing failed.", iface); - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_SHARED_START_FAILED); - goto out; - } - } - - /* Enter the SECONDARIES state if this is the first method to complete */ - priv->ip4_state = IP_DONE; - if (nm_device_get_state (self) == NM_DEVICE_STATE_IP_CONFIG) - nm_device_state_changed (self, NM_DEVICE_STATE_SECONDARIES, NM_DEVICE_STATE_REASON_NONE); - -out: - nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 5 of 5 (IPv4 Commit) complete.", - iface); - - /* Balance IP config creation; nm_device_set_ip4_config() takes a reference */ - g_object_set_data (G_OBJECT (req), PENDING_IP4_CONFIG, NULL); - - return FALSE; -} - -void -nm_device_activate_schedule_ip4_config_result (NMDevice *self, NMIP4Config *config) -{ - NMDevicePrivate *priv; - - g_return_if_fail (NM_IS_DEVICE (self)); - - priv = NM_DEVICE_GET_PRIVATE (self); - g_return_if_fail (priv->act_request); - - if (config == NULL) { - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); - return; - } - - g_object_set_data_full (G_OBJECT (priv->act_request), - PENDING_IP4_CONFIG, - g_object_ref (config), - g_object_unref); - - activation_source_schedule (self, nm_device_activate_ip4_config_commit, AF_INET); - - nm_log_info (LOGD_DEVICE | LOGD_IP4, - "Activation (%s) Stage 5 of 5 (IPv4 Configure Commit) scheduled...", - nm_device_get_iface (self)); -} - -gboolean -nm_device_activate_ip4_state_in_conf (NMDevice *self) -{ - g_return_val_if_fail (self != NULL, FALSE); - return NM_DEVICE_GET_PRIVATE (self)->ip4_state == IP_CONF; -} - -gboolean -nm_device_activate_ip4_state_in_wait (NMDevice *self) -{ - g_return_val_if_fail (self != NULL, FALSE); - return NM_DEVICE_GET_PRIVATE (self)->ip4_state == IP_WAIT; -} - -static gboolean -nm_device_activate_ip6_config_commit (gpointer user_data) -{ - NMDevice *self = NM_DEVICE (user_data); - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - NMActRequest *req; - NMIP6Config *config = NULL; - const char *iface; - NMConnection *connection; - NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; - int ifindex; - - /* Clear the activation source ID now that this stage has run */ - activation_source_clear (self, FALSE, AF_INET6); - - iface = nm_device_get_iface (self); - nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 5 of 5 (IPv6 Commit) started...", - iface); - - req = nm_device_get_act_request (self); - g_assert (req); - connection = nm_act_request_get_connection (req); - g_assert (connection); - - config = g_object_get_data (G_OBJECT (req), PENDING_IP6_CONFIG); - g_assert (config); - - /* Make sure the interface is up again just because */ - ifindex = nm_device_get_ip_ifindex (self); - if ((ifindex > 0) && (nm_system_iface_is_up (ifindex) == FALSE)) - nm_system_iface_set_up (ifindex, TRUE, NULL); - - /* Allow setting MTU etc */ - if (NM_DEVICE_GET_CLASS (self)->ip6_config_pre_commit) - NM_DEVICE_GET_CLASS (self)->ip6_config_pre_commit (self, config); - - if (ip6_config_merge_and_apply (self, config, &reason)) { - /* Enter the SECONDARIES state if this is the first method to complete */ - priv->ip6_state = IP_DONE; - if (nm_device_get_state (self) == NM_DEVICE_STATE_IP_CONFIG) - nm_device_state_changed (self, NM_DEVICE_STATE_SECONDARIES, NM_DEVICE_STATE_REASON_NONE); - } else { - nm_log_info (LOGD_DEVICE | LOGD_IP6, - "Activation (%s) Stage 5 of 5 (IPv6 Commit) failed", - iface); - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); - } - - nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 5 of 5 (IPv6 Commit) complete.", - iface); - - /* Balance IP config creation; nm_device_set_ip6_config() takes a reference */ - g_object_set_data (G_OBJECT (req), PENDING_IP6_CONFIG, NULL); - - return FALSE; -} - -void -nm_device_activate_schedule_ip6_config_result (NMDevice *self, NMIP6Config *config) -{ - NMDevicePrivate *priv; - - g_return_if_fail (NM_IS_DEVICE (self)); - - priv = NM_DEVICE_GET_PRIVATE (self); - g_return_if_fail (priv->act_request); - - if (config == NULL) { - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); - return; - } - - /* Save the pending config */ - g_object_set_data_full (G_OBJECT (priv->act_request), - PENDING_IP6_CONFIG, - g_object_ref (config), - g_object_unref); - - activation_source_schedule (self, nm_device_activate_ip6_config_commit, AF_INET6); - - nm_log_info (LOGD_DEVICE | LOGD_IP4, - "Activation (%s) Stage 5 of 5 (IPv6 Commit) scheduled...", - nm_device_get_iface (self)); -} - -gboolean -nm_device_activate_ip6_state_in_conf (NMDevice *self) -{ - g_return_val_if_fail (self != NULL, FALSE); - return NM_DEVICE_GET_PRIVATE (self)->ip6_state == IP_CONF; -} - -gboolean -nm_device_activate_ip6_state_in_wait (NMDevice *self) -{ - g_return_val_if_fail (self != NULL, FALSE); - return NM_DEVICE_GET_PRIVATE (self)->ip6_state == IP_WAIT; -} - -static void -clear_act_request (NMDevice *self) -{ - NMDevicePrivate * priv; - - g_return_if_fail (self != NULL); - - priv = NM_DEVICE_GET_PRIVATE (self); - - if (!priv->act_request) - return; - - if (priv->secrets_updated_id) { - g_signal_handler_disconnect (priv->act_request, - priv->secrets_updated_id); - priv->secrets_updated_id = 0; - } - - if (priv->secrets_failed_id) { - g_signal_handler_disconnect (priv->act_request, - priv->secrets_failed_id); - priv->secrets_failed_id = 0; - } - - nm_active_connection_set_default (NM_ACTIVE_CONNECTION (priv->act_request), FALSE); - - g_clear_object (&priv->act_request); - g_object_notify (G_OBJECT (self), NM_DEVICE_ACTIVE_CONNECTION); -} - -static void -dhcp4_cleanup (NMDevice *self, gboolean stop, gboolean release) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - - if (priv->dhcp4_config) { - g_object_notify (G_OBJECT (self), NM_DEVICE_DHCP4_CONFIG); - g_object_unref (priv->dhcp4_config); - priv->dhcp4_config = NULL; - } - - if (priv->dhcp4_client) { - /* Stop any ongoing DHCP transaction on this device */ - if (priv->dhcp4_state_sigid) { - g_signal_handler_disconnect (priv->dhcp4_client, priv->dhcp4_state_sigid); - priv->dhcp4_state_sigid = 0; - } - - if (priv->dhcp4_timeout_sigid) { - g_signal_handler_disconnect (priv->dhcp4_client, priv->dhcp4_timeout_sigid); - priv->dhcp4_timeout_sigid = 0; - } - - if (stop) - nm_dhcp_client_stop (priv->dhcp4_client, release); - - g_object_unref (priv->dhcp4_client); - priv->dhcp4_client = NULL; - } -} - -static void -dhcp6_cleanup (NMDevice *self, gboolean stop, gboolean release) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - - priv->dhcp6_mode = IP6_DHCP_OPT_NONE; - - if (priv->dhcp6_ip6_config) { - g_object_unref (priv->dhcp6_ip6_config); - priv->dhcp6_ip6_config = NULL; - } - - if (priv->dhcp6_config) { - g_object_notify (G_OBJECT (self), NM_DEVICE_DHCP6_CONFIG); - g_object_unref (priv->dhcp6_config); - priv->dhcp6_config = NULL; - } - - if (priv->dhcp6_client) { - if (priv->dhcp6_state_sigid) { - g_signal_handler_disconnect (priv->dhcp6_client, priv->dhcp6_state_sigid); - priv->dhcp6_state_sigid = 0; - } - - if (priv->dhcp6_timeout_sigid) { - g_signal_handler_disconnect (priv->dhcp6_client, priv->dhcp6_timeout_sigid); - priv->dhcp6_timeout_sigid = 0; - } - - if (stop) - nm_dhcp_client_stop (priv->dhcp6_client, release); - - g_object_unref (priv->dhcp6_client); - priv->dhcp6_client = NULL; - } -} - -static void -dnsmasq_cleanup (NMDevice *self) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - - if (!priv->dnsmasq_manager) - return; - - if (priv->dnsmasq_state_id) { - g_signal_handler_disconnect (priv->dnsmasq_manager, priv->dnsmasq_state_id); - priv->dnsmasq_state_id = 0; - } - - nm_dnsmasq_manager_stop (priv->dnsmasq_manager); - g_object_unref (priv->dnsmasq_manager); - priv->dnsmasq_manager = NULL; -} - -static void -_update_ip4_address (NMDevice *self) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - struct ifreq req; - guint32 new_address; - int fd; - - g_return_if_fail (self != NULL); - - fd = socket (PF_INET, SOCK_DGRAM, 0); - if (fd < 0) { - nm_log_err (LOGD_IP4, "couldn't open control socket."); - return; - } - - memset (&req, 0, sizeof (struct ifreq)); - strncpy (req.ifr_name, nm_device_get_ip_iface (self), IFNAMSIZ); - if (ioctl (fd, SIOCGIFADDR, &req) == 0) { - new_address = ((struct sockaddr_in *)(&req.ifr_addr))->sin_addr.s_addr; - if (new_address != priv->ip4_address) - priv->ip4_address = new_address; - } - close (fd); -} - -/* - * nm_device_deactivate - * - * Remove a device's routing table entries and IP address. - * - */ -static void -nm_device_deactivate (NMDevice *self, NMDeviceStateReason reason) -{ - NMDevicePrivate *priv; - NMDeviceStateReason ignored = NM_DEVICE_STATE_REASON_NONE; - NMConnection *connection = NULL; - NMSettingConnection *s_con = NULL; - gboolean tried_ipv6 = FALSE; - int ifindex, family; - - g_return_if_fail (self != NULL); - g_return_if_fail (NM_IS_DEVICE (self)); - - nm_log_info (LOGD_DEVICE, "(%s): deactivating device (reason '%s') [%d]", - nm_device_get_iface (self), reason_to_string (reason), reason); - - /* Save whether or not we tried IPv6 for later */ - priv = NM_DEVICE_GET_PRIVATE (self); - if (priv->ip6_manager || priv->ip6_config) - tried_ipv6 = TRUE; - - /* Clean up when device was deactivated during call to firewall */ - if (priv->fw_call) { - nm_firewall_manager_cancel_call (priv->fw_manager, priv->fw_call); - priv->fw_call = NULL; - } - - if (priv->act_request) - connection = nm_act_request_get_connection (priv->act_request); - if (connection) { - s_con = nm_connection_get_setting_connection (connection); - nm_firewall_manager_remove_from_zone (priv->fw_manager, - nm_device_get_ip_iface (self), - nm_setting_connection_get_zone (s_con)); - } - - /* Break the activation chain */ - activation_source_clear (self, TRUE, AF_INET); - activation_source_clear (self, TRUE, AF_INET6); - - /* Clear any queued transitions */ - nm_device_queued_state_clear (self); - - priv->ip4_state = priv->ip6_state = IP_NONE; - - dhcp4_cleanup (self, TRUE, FALSE); - dhcp6_cleanup (self, TRUE, FALSE); - addrconf6_cleanup (self); - dnsmasq_cleanup (self); - aipd_cleanup (self); - - /* Turn off router advertisements until they are needed */ - if (priv->ip6_accept_ra_path) - nm_utils_do_sysctl (priv->ip6_accept_ra_path, "0"); - - /* Turn off IPv6 privacy extensions */ - if (priv->ip6_privacy_tempaddr_path) - nm_utils_do_sysctl (priv->ip6_privacy_tempaddr_path, "0"); - - /* Call device type-specific deactivation */ - if (NM_DEVICE_GET_CLASS (self)->deactivate) - NM_DEVICE_GET_CLASS (self)->deactivate (self); - - /* master: release slaves */ - nm_device_master_release_slaves (self, FALSE); - - /* slave: mark no longer enslaved */ - g_clear_object (&priv->master); - priv->enslaved = FALSE; - - /* Tear down an existing activation request */ - clear_act_request (self); - - /* Take out any entries in the routing table and any IP address the device had. */ - ifindex = nm_device_get_ip_ifindex (self); - family = tried_ipv6 ? AF_UNSPEC : AF_INET; - if (ifindex > 0) { - nm_system_iface_flush_routes (ifindex, family); - nm_system_iface_flush_addresses (ifindex, family); - } - - /* Clean up nameservers and addresses */ - nm_device_set_ip4_config (self, NULL, FALSE, &ignored); - nm_device_set_ip6_config (self, NULL, &ignored); - - /* Clear legacy IPv4 address property */ - priv->ip4_address = 0; - g_object_notify (G_OBJECT (self), NM_DEVICE_IP4_ADDRESS); - - /* Only clear ip_iface after flushing all routes and addreses, since - * those are identified by ip_iface, not by iface (which might be a tty - * or ATM device). - */ - nm_device_set_ip_iface (self, NULL); -} - -static void -disconnect_cb (NMDevice *device, - DBusGMethodInvocation *context, - GError *error, - gpointer user_data) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); - GError *local = NULL; - - if (error) - dbus_g_method_return_error (context, error); - else { - /* Authorized */ - if (priv->state <= NM_DEVICE_STATE_DISCONNECTED) { - local = g_error_new_literal (NM_DEVICE_ERROR, - NM_DEVICE_ERROR_NOT_ACTIVE, - "Device is not active"); - dbus_g_method_return_error (context, local); - g_error_free (local); - } else { - priv->autoconnect = FALSE; - nm_device_state_changed (device, - NM_DEVICE_STATE_DISCONNECTED, - NM_DEVICE_STATE_REASON_USER_REQUESTED); - dbus_g_method_return (context); - } - } -} - -static void -impl_device_disconnect (NMDevice *device, DBusGMethodInvocation *context) -{ - NMConnection *connection; - GError *error = NULL; - - if (NM_DEVICE_GET_PRIVATE (device)->act_request == NULL) { - error = g_error_new_literal (NM_DEVICE_ERROR, - NM_DEVICE_ERROR_NOT_ACTIVE, - "This device is not active"); - dbus_g_method_return_error (context, error); - g_error_free (error); - return; - } - - connection = nm_device_get_connection (device); - g_assert (connection); - - /* Ask the manager to authenticate this request for us */ - g_signal_emit (device, signals[AUTH_REQUEST], 0, - context, - connection, - NM_AUTH_PERMISSION_NETWORK_CONTROL, - TRUE, - disconnect_cb, - NULL); -} - -void -nm_device_activate (NMDevice *self, NMActRequest *req) -{ - NMDevicePrivate *priv; - NMConnection *connection; - - g_return_if_fail (self != NULL); - g_return_if_fail (NM_IS_DEVICE (self)); - g_return_if_fail (req != NULL); - g_return_if_fail (NM_IS_ACT_REQUEST (req)); - - priv = NM_DEVICE_GET_PRIVATE (self); - - connection = nm_act_request_get_connection (req); - g_assert (connection); - - nm_log_info (LOGD_DEVICE, "Activation (%s) starting connection '%s'", - nm_device_get_iface (self), - nm_connection_get_id (connection)); - - g_warn_if_fail (priv->state == NM_DEVICE_STATE_DISCONNECTED); - - priv->act_request = g_object_ref (req); - g_object_notify (G_OBJECT (self), NM_DEVICE_ACTIVE_CONNECTION); - - if (nm_active_connection_get_assumed (NM_ACTIVE_CONNECTION (req))) { - /* If it's an assumed connection, let the device subclass short-circuit - * the normal connection process and just copy its IP configs from the - * interface. - */ - nm_device_state_changed (self, NM_DEVICE_STATE_IP_CONFIG, NM_DEVICE_STATE_REASON_NONE); - nm_device_activate_schedule_stage3_ip_config_start (self); - } else { - NMDevice *master; - - /* HACK: update the state a bit early to avoid a race between the - * scheduled stage1 handler and nm_policy_device_change_check() thinking - * that the activation request isn't deferred because the deferred bit - * gets cleared a bit too early, when the connection becomes valid. - */ - nm_device_state_changed (self, NM_DEVICE_STATE_PREPARE, NM_DEVICE_STATE_REASON_NONE); - - /* Handle any dependencies this connection might have */ - master = nm_active_connection_get_master (NM_ACTIVE_CONNECTION (req)); - if (master) { - /* Master should at least already be activating */ - g_assert (nm_device_get_state (master) > NM_DEVICE_STATE_DISCONNECTED); - - g_assert (priv->master == NULL); - priv->master = g_object_ref (master); - nm_device_master_add_slave (master, self); - } - - nm_device_activate_schedule_stage1_device_prepare (self); - } -} - -/* - * nm_device_is_activating - * - * Return whether or not the device is currently activating itself. - * - */ -gboolean -nm_device_is_activating (NMDevice *device) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); - NMDeviceState state; - - g_return_val_if_fail (NM_IS_DEVICE (device), FALSE); - - state = nm_device_get_state (device); - if (state >= NM_DEVICE_STATE_PREPARE && state <= NM_DEVICE_STATE_SECONDARIES) - return TRUE; - - /* There's a small race between the time when stage 1 is scheduled - * and when the device actually sets STATE_PREPARE when the activation - * handler is actually run. If there's an activation handler scheduled - * we're activating anyway. - */ - return priv->act_source_id ? TRUE : FALSE; -} - - -gboolean -nm_device_can_interrupt_activation (NMDevice *self) -{ - gboolean interrupt = FALSE; - - g_return_val_if_fail (self != NULL, FALSE); - - if (NM_DEVICE_GET_CLASS (self)->can_interrupt_activation) - interrupt = NM_DEVICE_GET_CLASS (self)->can_interrupt_activation (self); - return interrupt; -} - -/* IP Configuration stuff */ - -NMDHCP4Config * -nm_device_get_dhcp4_config (NMDevice *self) -{ - g_return_val_if_fail (self != NULL, NULL); - g_return_val_if_fail (NM_IS_DEVICE (self), NULL); - - return NM_DEVICE_GET_PRIVATE (self)->dhcp4_config; -} - -NMIP4Config * -nm_device_get_ip4_config (NMDevice *self) -{ - g_return_val_if_fail (self != NULL, NULL); - g_return_val_if_fail (NM_IS_DEVICE (self), NULL); - - return NM_DEVICE_GET_PRIVATE (self)->ip4_config; -} - - -static gboolean -nm_device_set_ip4_config (NMDevice *self, - NMIP4Config *new_config, - gboolean assumed, - NMDeviceStateReason *reason) -{ - NMDevicePrivate *priv; - const char *ip_iface; - NMIP4Config *old_config = NULL; - gboolean success = TRUE; - NMIP4ConfigCompareFlags diff = NM_IP4_COMPARE_FLAG_ALL; - int ip_ifindex; - - g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); - g_return_val_if_fail (reason != NULL, FALSE); - - priv = NM_DEVICE_GET_PRIVATE (self); - ip_iface = nm_device_get_ip_iface (self); - ip_ifindex = nm_device_get_ip_ifindex (self); - - old_config = priv->ip4_config; - - if (new_config && old_config) { - diff = nm_ip4_config_diff (new_config, old_config); - if (diff == NM_IP4_COMPARE_FLAG_NONE) - return TRUE; /* no actual change */ - } else if (!new_config && !old_config) - return TRUE; - - priv->ip4_config = NULL; - - if (new_config) { - priv->ip4_config = g_object_ref (new_config); - - /* Don't touch the device's actual IP config if the connection is - * assumed when NM starts. - */ - if (!assumed) - success = nm_system_apply_ip4_config (ip_ifindex, new_config, nm_device_get_priority (self), diff); - - if (success || assumed) { - /* Export over D-Bus */ - if (!nm_ip4_config_get_dbus_path (new_config)) - nm_ip4_config_export (new_config); - _update_ip4_address (self); - } - - if (!success && reason) - *reason = NM_DEVICE_STATE_REASON_CONFIG_FAILED; - } - - g_object_notify (G_OBJECT (self), NM_DEVICE_IP4_CONFIG); - g_signal_emit (self, signals[IP4_CONFIG_CHANGED], 0, priv->ip4_config, old_config); - - if (old_config) - g_object_unref (old_config); - - return success; -} - -static gboolean -nm_device_set_ip6_config (NMDevice *self, - NMIP6Config *new_config, - NMDeviceStateReason *reason) -{ - NMDevicePrivate *priv; - const char *ip_iface; - NMIP6Config *old_config = NULL; - gboolean success = TRUE; - NMIP6ConfigCompareFlags diff = NM_IP6_COMPARE_FLAG_ALL; - int ip_ifindex; - - g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); - g_return_val_if_fail (reason != NULL, FALSE); - - priv = NM_DEVICE_GET_PRIVATE (self); - ip_iface = nm_device_get_ip_iface (self); - ip_ifindex = nm_device_get_ip_ifindex (self); - - old_config = priv->ip6_config; - - if (new_config && old_config) { - diff = nm_ip6_config_diff (new_config, old_config); - if (diff == NM_IP6_COMPARE_FLAG_NONE) - return TRUE; /* no actual change */ - } else if (!new_config && !old_config) - return TRUE; - - priv->ip6_config = NULL; - - if (new_config) { - priv->ip6_config = g_object_ref (new_config); - - success = nm_system_apply_ip6_config (ip_ifindex, new_config, nm_device_get_priority (self), diff); - - if (success) { - /* Export over D-Bus */ - if (!nm_ip6_config_get_dbus_path (new_config)) - nm_ip6_config_export (new_config); - } - - if (!success && reason) - *reason = NM_DEVICE_STATE_REASON_CONFIG_FAILED; - } - - g_object_notify (G_OBJECT (self), NM_DEVICE_IP6_CONFIG); - g_signal_emit (self, signals[IP6_CONFIG_CHANGED], 0, priv->ip6_config, old_config); - - if (old_config) - g_object_unref (old_config); - - return success; -} - -NMDHCP6Config * -nm_device_get_dhcp6_config (NMDevice *self) -{ - g_return_val_if_fail (self != NULL, NULL); - g_return_val_if_fail (NM_IS_DEVICE (self), NULL); - - return NM_DEVICE_GET_PRIVATE (self)->dhcp6_config; -} - -NMIP6Config * -nm_device_get_ip6_config (NMDevice *self) -{ - g_return_val_if_fail (self != NULL, NULL); - g_return_val_if_fail (NM_IS_DEVICE (self), NULL); - - return NM_DEVICE_GET_PRIVATE (self)->ip6_config; -} - -static gboolean -nm_device_is_up (NMDevice *self) -{ - g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); - - if (NM_DEVICE_GET_CLASS (self)->is_up) - return NM_DEVICE_GET_CLASS (self)->is_up (self); - - return TRUE; -} - -gboolean -nm_device_hw_bring_up (NMDevice *self, gboolean block, gboolean *no_firmware) -{ - gboolean success; - guint32 tries = 0; - - g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); - - if (nm_device_hw_is_up (self)) - goto out; - - nm_log_info (LOGD_HW, "(%s): bringing up device.", nm_device_get_iface (self)); - - if (NM_DEVICE_GET_CLASS (self)->hw_bring_up) { - success = NM_DEVICE_GET_CLASS (self)->hw_bring_up (self, no_firmware); - if (!success) - return FALSE; - } - - /* Wait for the device to come up if requested */ - while (block && !nm_device_hw_is_up (self) && (tries++ < 50)) - g_usleep (200); - - if (!nm_device_hw_is_up (self)) { - nm_log_warn (LOGD_HW, "(%s): device not up after timeout!", nm_device_get_iface (self)); - return FALSE; - } - -out: - /* Can only get HW address of some devices when they are up */ - if (NM_DEVICE_GET_CLASS (self)->update_hw_address) - NM_DEVICE_GET_CLASS (self)->update_hw_address (self); - - _update_ip4_address (self); - return TRUE; -} - -static gboolean -hw_bring_up (NMDevice *device, gboolean *no_firmware) -{ - int ifindex = nm_device_get_ip_ifindex (device); - - return ifindex > 0 ? nm_system_iface_set_up (ifindex, TRUE, no_firmware) : TRUE; -} - -void -nm_device_hw_take_down (NMDevice *self, gboolean block) -{ - guint32 tries = 0; - - g_return_if_fail (NM_IS_DEVICE (self)); - - if (!nm_device_hw_is_up (self)) - return; - - nm_log_info (LOGD_HW, "(%s): taking down device.", nm_device_get_iface (self)); - - if (NM_DEVICE_GET_CLASS (self)->hw_take_down) - NM_DEVICE_GET_CLASS (self)->hw_take_down (self); - - /* Wait for the device to come up if requested */ - while (block && nm_device_hw_is_up (self) && (tries++ < 50)) - g_usleep (200); -} - -static void -hw_take_down (NMDevice *device) -{ - int ifindex = nm_device_get_ip_ifindex (device); - - if (ifindex > 0) - nm_system_iface_set_up (ifindex, FALSE, NULL); -} - -static gboolean -nm_device_bring_up (NMDevice *self, gboolean block, gboolean *no_firmware) -{ - gboolean success = FALSE; - - g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); - - if (!nm_device_hw_bring_up (self, block, no_firmware)) - return FALSE; - - if (nm_device_is_up (self)) - return TRUE; - - nm_log_info (LOGD_HW, "(%s): preparing device.", nm_device_get_iface (self)); - - if (NM_DEVICE_GET_CLASS (self)->bring_up) - success = NM_DEVICE_GET_CLASS (self)->bring_up (self); - - return success; -} - -static void -nm_device_take_down (NMDevice *self, gboolean block, NMDeviceStateReason reason) -{ - g_return_if_fail (NM_IS_DEVICE (self)); - - if (nm_device_get_act_request (self)) - nm_device_deactivate (self, reason); - - if (nm_device_is_up (self)) { - nm_log_info (LOGD_HW, "(%s): cleaning up...", nm_device_get_iface (self)); - - if (NM_DEVICE_GET_CLASS (self)->take_down) - NM_DEVICE_GET_CLASS (self)->take_down (self); - } - - nm_device_hw_take_down (self, block); -} - -static void -dispose (GObject *object) -{ - NMDevice *self = NM_DEVICE (object); - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - gboolean take_down = TRUE; - - if (priv->disposed || !priv->initialized) - goto out; - - priv->disposed = TRUE; - - /* Don't down can-assume-connection capable devices that are activated with - * a connection that can be assumed. - */ - if (nm_device_can_assume_connections (self) && (priv->state == NM_DEVICE_STATE_ACTIVATED)) { - NMConnection *connection; - NMSettingIP4Config *s_ip4 = NULL; - const char *method = NULL; - - connection = nm_device_get_connection (self); - if (connection) { - /* Only static or DHCP IPv4 connections can be left up. - * All IPv6 connections can be left up, so we don't have - * to check that. - */ - s_ip4 = nm_connection_get_setting_ip4_config (connection); - if (s_ip4) - method = nm_setting_ip4_config_get_method (s_ip4); - if ( !method - || !strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO) - || !strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL) - || !strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED)) - take_down = FALSE; - } - } - - /* Clear any queued transitions */ - nm_device_queued_state_clear (self); - - /* Clean up and stop DHCP */ - dhcp4_cleanup (self, take_down, FALSE); - dhcp6_cleanup (self, take_down, FALSE); - addrconf6_cleanup (self); - dnsmasq_cleanup (self); - - g_warn_if_fail (priv->slaves == NULL); - - /* Take the device itself down and clear its IPv4 configuration */ - if (priv->managed && take_down) { - NMDeviceStateReason ignored = NM_DEVICE_STATE_REASON_NONE; - - nm_device_take_down (self, FALSE, NM_DEVICE_STATE_REASON_REMOVED); - nm_device_set_ip4_config (self, NULL, FALSE, &ignored); - } - - /* reset the saved RA value */ - if ( priv->ip6_accept_ra_path - && g_file_test (priv->ip6_accept_ra_path, G_FILE_TEST_EXISTS)) { - nm_utils_do_sysctl (priv->ip6_accept_ra_path, - priv->ip6_accept_ra_save ? "1" : "0"); - } - g_free (priv->ip6_accept_ra_path); - - /* reset the saved use_tempaddr value */ - if ( priv->ip6_privacy_tempaddr_path - && g_file_test (priv->ip6_privacy_tempaddr_path, G_FILE_TEST_EXISTS)) { - char tmp[16]; - - snprintf (tmp, sizeof (tmp), "%d", priv->ip6_privacy_tempaddr_save); - nm_utils_do_sysctl (priv->ip6_privacy_tempaddr_path, tmp); - } - g_free (priv->ip6_privacy_tempaddr_path); - - if (priv->cp_added_id) { - g_signal_handler_disconnect (priv->con_provider, priv->cp_added_id); - priv->cp_added_id = 0; - } - - if (priv->cp_loaded_id) { - g_signal_handler_disconnect (priv->con_provider, priv->cp_loaded_id); - priv->cp_loaded_id = 0; - } - - if (priv->cp_removed_id) { - g_signal_handler_disconnect (priv->con_provider, priv->cp_removed_id); - priv->cp_removed_id = 0; - } - - if (priv->cp_updated_id) { - g_signal_handler_disconnect (priv->con_provider, priv->cp_updated_id); - priv->cp_updated_id = 0; - } - - g_hash_table_unref (priv->available_connections); - - activation_source_clear (self, TRUE, AF_INET); - activation_source_clear (self, TRUE, AF_INET6); - - clear_act_request (self); - -out: - G_OBJECT_CLASS (nm_device_parent_class)->dispose (object); -} - -static void -finalize (GObject *object) -{ - NMDevice *self = NM_DEVICE (object); - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - - if (priv->dhcp_manager) - g_object_unref (priv->dhcp_manager); - - if (priv->fw_manager) - g_object_unref (priv->fw_manager); - - g_free (priv->udi); - g_free (priv->path); - g_free (priv->iface); - g_free (priv->ip_iface); - g_free (priv->driver); - g_free (priv->driver_version); - g_free (priv->firmware_version); - g_free (priv->type_desc); - if (priv->dhcp_anycast_address) - g_byte_array_free (priv->dhcp_anycast_address, TRUE); - - G_OBJECT_CLASS (nm_device_parent_class)->finalize (object); -} - - -static void -set_property (GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (object); - - switch (prop_id) { - case PROP_UDI: - /* Only virtual interfaces can set UDI post-construction */ - if (priv->initialized) - g_return_if_fail (nm_system_get_iface_type (priv->ifindex, NULL) != NM_IFACE_TYPE_UNSPEC); - - g_free (priv->udi); - priv->udi = g_strdup (g_value_get_string (value)); - break; - case PROP_IFACE: - g_free (priv->iface); - priv->ifindex = 0; - priv->iface = g_value_dup_string (value); - - /* Only look up the ifindex if it appears to be an actual kernel - * interface name. eg Bluetooth devices won't have one until we know - * the IP interface. - */ - if (priv->iface && !strchr (priv->iface, ':')) { - priv->ifindex = nm_netlink_iface_to_index (priv->iface); - if (priv->ifindex <= 0) - nm_log_warn (LOGD_HW, "(%s): failed to look up interface index", priv->iface); - } - break; - case PROP_IP_IFACE: - break; - case PROP_DRIVER: - g_free (priv->driver); - priv->driver = g_strdup (g_value_get_string (value)); - break; - case PROP_DRIVER_VERSION: - g_free (priv->driver_version); - priv->driver_version = g_strdup (g_value_get_string (value)); - break; - case PROP_FIRMWARE_VERSION: - g_free (priv->firmware_version); - priv->firmware_version = g_strdup (g_value_get_string (value)); - break; - case PROP_CAPABILITIES: - priv->capabilities = g_value_get_uint (value); - break; - case PROP_IP4_ADDRESS: - priv->ip4_address = g_value_get_uint (value); - break; - case PROP_MANAGED: - priv->managed = g_value_get_boolean (value); - break; - case PROP_AUTOCONNECT: - priv->autoconnect = g_value_get_boolean (value); - break; - case PROP_FIRMWARE_MISSING: - priv->firmware_missing = g_value_get_boolean (value); - break; - case PROP_DEVICE_TYPE: - g_return_if_fail (priv->type == NM_DEVICE_TYPE_UNKNOWN); - priv->type = g_value_get_uint (value); - break; - case PROP_TYPE_DESC: - g_free (priv->type_desc); - priv->type_desc = g_value_dup_string (value); - break; - case PROP_RFKILL_TYPE: - priv->rfkill_type = g_value_get_uint (value); - break; - case PROP_IS_MASTER: - priv->is_master = g_value_get_boolean (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static gboolean -_is_connected (NMDeviceState state) -{ - return (state >= NM_DEVICE_STATE_IP_CONFIG && state <= NM_DEVICE_STATE_DEACTIVATING); -} - -static void -get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) -{ - NMDevice *self = NM_DEVICE (object); - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - NMDeviceState state; - const char *ac_path = NULL; - GPtrArray *array; - GHashTableIter iter; - NMConnection *connection; - - state = nm_device_get_state (self); - - switch (prop_id) { - case PROP_UDI: - g_value_set_string (value, priv->udi); - break; - case PROP_IFACE: - g_value_set_string (value, priv->iface); - break; - case PROP_IP_IFACE: - if (_is_connected (state)) - g_value_set_string (value, nm_device_get_ip_iface (self)); - else - g_value_set_string (value, NULL); - break; - case PROP_IFINDEX: - g_value_set_int (value, priv->ifindex); - break; - case PROP_DRIVER: - g_value_set_string (value, priv->driver); - break; - case PROP_DRIVER_VERSION: - g_value_set_string (value, priv->driver_version); - break; - case PROP_FIRMWARE_VERSION: - g_value_set_string (value, priv->firmware_version); - break; - case PROP_CAPABILITIES: - g_value_set_uint (value, priv->capabilities); - break; - case PROP_IP4_ADDRESS: - g_value_set_uint (value, priv->ip4_address); - break; - case PROP_IP4_CONFIG: - if (_is_connected (state) && priv->ip4_config) - g_value_set_boxed (value, nm_ip4_config_get_dbus_path (priv->ip4_config)); - else - g_value_set_boxed (value, "/"); - break; - case PROP_DHCP4_CONFIG: - if (_is_connected (state) && priv->dhcp4_client) - g_value_set_boxed (value, nm_dhcp4_config_get_dbus_path (priv->dhcp4_config)); - else - g_value_set_boxed (value, "/"); - break; - case PROP_IP6_CONFIG: - if (_is_connected (state) && priv->ip6_config) - g_value_set_boxed (value, nm_ip6_config_get_dbus_path (priv->ip6_config)); - else - g_value_set_boxed (value, "/"); - break; - case PROP_DHCP6_CONFIG: - if (_is_connected (state) && priv->dhcp6_client) - g_value_set_boxed (value, nm_dhcp6_config_get_dbus_path (priv->dhcp6_config)); - else - g_value_set_boxed (value, "/"); - break; - case PROP_STATE: - g_value_set_uint (value, priv->state); - break; - case PROP_STATE_REASON: - g_value_take_boxed (value, dbus_g_type_specialized_construct (DBUS_G_TYPE_UINT_STRUCT)); - dbus_g_type_struct_set (value, - 0, priv->state, - 1, priv->state_reason, - G_MAXUINT); - break; - case PROP_ACTIVE_CONNECTION: - if (priv->act_request) - ac_path = nm_active_connection_get_path (NM_ACTIVE_CONNECTION (priv->act_request)); - g_value_set_boxed (value, ac_path ? ac_path : "/"); - break; - case PROP_DEVICE_TYPE: - g_value_set_uint (value, priv->type); - break; - case PROP_MANAGED: - g_value_set_boolean (value, priv->managed); - break; - case PROP_AUTOCONNECT: - g_value_set_boolean (value, priv->autoconnect); - break; - case PROP_FIRMWARE_MISSING: - g_value_set_boolean (value, priv->firmware_missing); - break; - case PROP_TYPE_DESC: - g_value_set_string (value, priv->type_desc); - break; - case PROP_RFKILL_TYPE: - g_value_set_uint (value, priv->rfkill_type); - break; - case PROP_AVAILABLE_CONNECTIONS: - array = g_ptr_array_sized_new (g_hash_table_size (priv->available_connections)); - g_hash_table_iter_init (&iter, priv->available_connections); - while (g_hash_table_iter_next (&iter, (gpointer) &connection, NULL)) - g_ptr_array_add (array, g_strdup (nm_connection_get_path (connection))); - g_value_take_boxed (value, array); - break; - case PROP_IS_MASTER: - g_value_set_boolean (value, priv->is_master); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - - -static void -nm_device_class_init (NMDeviceClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - g_type_class_add_private (object_class, sizeof (NMDevicePrivate)); - - /* Virtual methods */ - object_class->dispose = dispose; - object_class->finalize = finalize; - object_class->set_property = set_property; - object_class->get_property = get_property; - object_class->constructor = constructor; - object_class->constructed = constructed; - - klass->get_type_capabilities = get_type_capabilities; - klass->get_generic_capabilities = get_generic_capabilities; - klass->act_stage1_prepare = act_stage1_prepare; - klass->act_stage2_config = act_stage2_config; - klass->act_stage3_ip4_config_start = act_stage3_ip4_config_start; - klass->act_stage3_ip6_config_start = act_stage3_ip6_config_start; - klass->act_stage4_ip4_config_timeout = act_stage4_ip4_config_timeout; - klass->act_stage4_ip6_config_timeout = act_stage4_ip6_config_timeout; - klass->have_any_ready_slaves = have_any_ready_slaves; - - klass->check_connection_available = check_connection_available; - klass->hw_is_up = hw_is_up; - klass->hw_bring_up = hw_bring_up; - klass->hw_take_down = hw_take_down; - - /* Properties */ - g_object_class_install_property - (object_class, PROP_UDI, - g_param_spec_string (NM_DEVICE_UDI, - "UDI", - "Unique Device Identifier", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - - g_object_class_install_property - (object_class, PROP_IFACE, - g_param_spec_string (NM_DEVICE_IFACE, - "Interface", - "Interface", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - g_object_class_install_property - (object_class, PROP_IP_IFACE, - g_param_spec_string (NM_DEVICE_IP_IFACE, - "IP Interface", - "IP Interface", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - g_object_class_install_property - (object_class, PROP_DRIVER, - g_param_spec_string (NM_DEVICE_DRIVER, - "Driver", - "Driver", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - g_object_class_install_property - (object_class, PROP_DRIVER_VERSION, - g_param_spec_string (NM_DEVICE_DRIVER_VERSION, - "Driver Version", - "Driver Version", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - g_object_class_install_property - (object_class, PROP_FIRMWARE_VERSION, - g_param_spec_string (NM_DEVICE_FIRMWARE_VERSION, - "Firmware Version", - "Firmware Version", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - g_object_class_install_property - (object_class, PROP_CAPABILITIES, - g_param_spec_uint (NM_DEVICE_CAPABILITIES, - "Capabilities", - "Capabilities", - 0, G_MAXUINT32, NM_DEVICE_CAP_NONE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - g_object_class_install_property - (object_class, PROP_IP4_ADDRESS, - g_param_spec_uint (NM_DEVICE_IP4_ADDRESS, - "IP4 address", - "IP4 address", - 0, G_MAXUINT32, 0, /* FIXME */ - G_PARAM_READWRITE)); - - g_object_class_install_property - (object_class, PROP_IP4_CONFIG, - g_param_spec_boxed (NM_DEVICE_IP4_CONFIG, - "IP4 Config", - "IP4 Config", - DBUS_TYPE_G_OBJECT_PATH, - G_PARAM_READWRITE)); - - g_object_class_install_property - (object_class, PROP_DHCP4_CONFIG, - g_param_spec_boxed (NM_DEVICE_DHCP4_CONFIG, - "DHCP4 Config", - "DHCP4 Config", - DBUS_TYPE_G_OBJECT_PATH, - G_PARAM_READWRITE)); - - g_object_class_install_property - (object_class, PROP_IP6_CONFIG, - g_param_spec_boxed (NM_DEVICE_IP6_CONFIG, - "IP6 Config", - "IP6 Config", - DBUS_TYPE_G_OBJECT_PATH, - G_PARAM_READWRITE)); - - g_object_class_install_property - (object_class, PROP_DHCP6_CONFIG, - g_param_spec_boxed (NM_DEVICE_DHCP6_CONFIG, - "DHCP6 Config", - "DHCP6 Config", - DBUS_TYPE_G_OBJECT_PATH, - G_PARAM_READWRITE)); - - g_object_class_install_property - (object_class, PROP_STATE, - g_param_spec_uint (NM_DEVICE_STATE, - "State", - "State", - 0, G_MAXUINT32, NM_DEVICE_STATE_UNKNOWN, - G_PARAM_READABLE)); - g_object_class_install_property - (object_class, PROP_STATE_REASON, - g_param_spec_boxed (NM_DEVICE_STATE_REASON, - "StateReason", - "StateReason", - DBUS_G_TYPE_UINT_STRUCT, - G_PARAM_READABLE)); - - g_object_class_install_property - (object_class, PROP_ACTIVE_CONNECTION, - g_param_spec_boxed (NM_DEVICE_ACTIVE_CONNECTION, - "ActiveConnection", - "ActiveConnection", - DBUS_TYPE_G_OBJECT_PATH, - G_PARAM_READABLE)); - - g_object_class_install_property - (object_class, PROP_DEVICE_TYPE, - g_param_spec_uint (NM_DEVICE_DEVICE_TYPE, - "DeviceType", - "DeviceType", - 0, G_MAXUINT32, NM_DEVICE_TYPE_UNKNOWN, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | NM_PROPERTY_PARAM_NO_EXPORT)); - - g_object_class_install_property - (object_class, PROP_MANAGED, - g_param_spec_boolean (NM_DEVICE_MANAGED, - "Managed", - "Managed", - FALSE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - g_object_class_install_property - (object_class, PROP_AUTOCONNECT, - g_param_spec_boolean (NM_DEVICE_AUTOCONNECT, - "Autoconnect", - "Autoconnect", - DEFAULT_AUTOCONNECT, - G_PARAM_READWRITE)); - - g_object_class_install_property - (object_class, PROP_FIRMWARE_MISSING, - g_param_spec_boolean (NM_DEVICE_FIRMWARE_MISSING, - "FirmwareMissing", - "Firmware missing", - FALSE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - g_object_class_install_property - (object_class, PROP_TYPE_DESC, - g_param_spec_string (NM_DEVICE_TYPE_DESC, - "Type Description", - "Device type description", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | NM_PROPERTY_PARAM_NO_EXPORT)); - - g_object_class_install_property - (object_class, PROP_RFKILL_TYPE, - g_param_spec_uint (NM_DEVICE_RFKILL_TYPE, - "Rfkill Type", - "Type of rfkill switch (if any) supported by this device", - RFKILL_TYPE_WLAN, - RFKILL_TYPE_MAX, - RFKILL_TYPE_UNKNOWN, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | NM_PROPERTY_PARAM_NO_EXPORT)); - - g_object_class_install_property - (object_class, PROP_IFINDEX, - g_param_spec_int (NM_DEVICE_IFINDEX, - "Ifindex", - "Ifindex", - 0, G_MAXINT, 0, - G_PARAM_READABLE | NM_PROPERTY_PARAM_NO_EXPORT)); - - g_object_class_install_property - (object_class, PROP_AVAILABLE_CONNECTIONS, - g_param_spec_boxed (NM_DEVICE_AVAILABLE_CONNECTIONS, - "AvailableConnections", - "AvailableConnections", - DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH, - G_PARAM_READABLE)); - - g_object_class_install_property - (object_class, PROP_IS_MASTER, - g_param_spec_boolean (NM_DEVICE_IS_MASTER, - "IsMaster", - "IsMaster", - FALSE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | NM_PROPERTY_PARAM_NO_EXPORT)); - - /* Signals */ - signals[STATE_CHANGED] = - g_signal_new ("state-changed", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMDeviceClass, state_changed), - NULL, NULL, - _nm_marshal_VOID__UINT_UINT_UINT, - G_TYPE_NONE, 3, - G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT); - - signals[AUTOCONNECT_ALLOWED] = - g_signal_new ("autoconnect-allowed", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - 0, - autoconnect_allowed_accumulator, NULL, - _nm_marshal_BOOLEAN__VOID, - G_TYPE_BOOLEAN, 0); - - signals[AUTH_REQUEST] = - g_signal_new (NM_DEVICE_AUTH_REQUEST, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - 0, NULL, NULL, - /* dbus-glib context, connection, permission, allow_interaction, callback, user_data */ - _nm_marshal_VOID__POINTER_POINTER_STRING_BOOLEAN_POINTER_POINTER, - G_TYPE_NONE, 6, G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_POINTER, G_TYPE_POINTER); - - signals[IP4_CONFIG_CHANGED] = - g_signal_new (NM_DEVICE_IP4_CONFIG_CHANGED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - 0, NULL, NULL, - _nm_marshal_VOID__OBJECT_OBJECT, - G_TYPE_NONE, 2, G_TYPE_OBJECT, G_TYPE_OBJECT); - - signals[IP6_CONFIG_CHANGED] = - g_signal_new (NM_DEVICE_IP6_CONFIG_CHANGED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - 0, NULL, NULL, - _nm_marshal_VOID__OBJECT_OBJECT, - G_TYPE_NONE, 2, G_TYPE_OBJECT, G_TYPE_OBJECT); - - dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass), - &dbus_glib_nm_device_interface_object_info); - - dbus_g_error_domain_register (NM_DEVICE_ERROR, NULL, NM_TYPE_DEVICE_ERROR); -} - -void -nm_device_set_firmware_missing (NMDevice *self, gboolean new_missing) -{ - NMDevicePrivate *priv; - - g_return_if_fail (self != NULL); - g_return_if_fail (NM_IS_DEVICE (self)); - - priv = NM_DEVICE_GET_PRIVATE (self); - if (priv->firmware_missing != new_missing) { - priv->firmware_missing = new_missing; - g_object_notify (G_OBJECT (self), NM_DEVICE_FIRMWARE_MISSING); - } -} - -gboolean -nm_device_get_firmware_missing (NMDevice *self) -{ - return NM_DEVICE_GET_PRIVATE (self)->firmware_missing; -} - -static const char * -state_to_string (NMDeviceState state) -{ - switch (state) { - case NM_DEVICE_STATE_UNMANAGED: - return "unmanaged"; - case NM_DEVICE_STATE_UNAVAILABLE: - return "unavailable"; - case NM_DEVICE_STATE_DISCONNECTED: - return "disconnected"; - case NM_DEVICE_STATE_PREPARE: - return "prepare"; - case NM_DEVICE_STATE_CONFIG: - return "config"; - case NM_DEVICE_STATE_NEED_AUTH: - return "need-auth"; - case NM_DEVICE_STATE_IP_CONFIG: - return "ip-config"; - case NM_DEVICE_STATE_IP_CHECK: - return "ip-check"; - case NM_DEVICE_STATE_SECONDARIES: - return "secondaries"; - case NM_DEVICE_STATE_ACTIVATED: - return "activated"; - case NM_DEVICE_STATE_DEACTIVATING: - return "deactivating"; - case NM_DEVICE_STATE_FAILED: - return "failed"; - default: - break; - } - return "unknown"; -} - -static const char * -reason_to_string (NMDeviceStateReason reason) -{ - switch (reason) { - case NM_DEVICE_STATE_REASON_NONE: - return "none"; - case NM_DEVICE_STATE_REASON_NOW_MANAGED: - return "managed"; - case NM_DEVICE_STATE_REASON_NOW_UNMANAGED: - return "unmanaged"; - case NM_DEVICE_STATE_REASON_CONFIG_FAILED: - return "config-failed"; - case NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE: - return "ip-config-unavailable"; - case NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED: - return "ip-config-expired"; - case NM_DEVICE_STATE_REASON_NO_SECRETS: - return "no-secrets"; - case NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT: - return "supplicant-disconnect"; - case NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED: - return "supplicant-config-failed"; - case NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED: - return "supplicant-failed"; - case NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT: - return "supplicant-timeout"; - case NM_DEVICE_STATE_REASON_PPP_START_FAILED: - return "ppp-start-failed"; - case NM_DEVICE_STATE_REASON_PPP_DISCONNECT: - return "ppp-disconnect"; - case NM_DEVICE_STATE_REASON_PPP_FAILED: - return "ppp-failed"; - case NM_DEVICE_STATE_REASON_DHCP_START_FAILED: - return "dhcp-start-failed"; - case NM_DEVICE_STATE_REASON_DHCP_ERROR: - return "dhcp-error"; - case NM_DEVICE_STATE_REASON_DHCP_FAILED: - return "dhcp-failed"; - case NM_DEVICE_STATE_REASON_SHARED_START_FAILED: - return "sharing-start-failed"; - case NM_DEVICE_STATE_REASON_SHARED_FAILED: - return "sharing-failed"; - case NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED: - return "autoip-start-failed"; - case NM_DEVICE_STATE_REASON_AUTOIP_ERROR: - return "autoip-error"; - case NM_DEVICE_STATE_REASON_AUTOIP_FAILED: - return "autoip-failed"; - case NM_DEVICE_STATE_REASON_MODEM_BUSY: - return "modem-busy"; - case NM_DEVICE_STATE_REASON_MODEM_NO_DIAL_TONE: - return "modem-no-dialtone"; - case NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER: - return "modem-no-carrier"; - case NM_DEVICE_STATE_REASON_MODEM_DIAL_TIMEOUT: - return "modem-dial-timeout"; - case NM_DEVICE_STATE_REASON_MODEM_DIAL_FAILED: - return "modem-dial-failed"; - case NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED: - return "modem-init-failed"; - case NM_DEVICE_STATE_REASON_GSM_APN_FAILED: - return "gsm-apn-failed"; - case NM_DEVICE_STATE_REASON_GSM_REGISTRATION_NOT_SEARCHING: - return "gsm-registration-idle"; - case NM_DEVICE_STATE_REASON_GSM_REGISTRATION_DENIED: - return "gsm-registration-denied"; - case NM_DEVICE_STATE_REASON_GSM_REGISTRATION_TIMEOUT: - return "gsm-registration-timeout"; - case NM_DEVICE_STATE_REASON_GSM_REGISTRATION_FAILED: - return "gsm-registration-failed"; - case NM_DEVICE_STATE_REASON_GSM_PIN_CHECK_FAILED: - return "gsm-pin-check-failed"; - case NM_DEVICE_STATE_REASON_FIRMWARE_MISSING: - return "firmware-missing"; - case NM_DEVICE_STATE_REASON_REMOVED: - return "removed"; - case NM_DEVICE_STATE_REASON_SLEEPING: - return "sleeping"; - case NM_DEVICE_STATE_REASON_CONNECTION_REMOVED: - return "connection-removed"; - case NM_DEVICE_STATE_REASON_USER_REQUESTED: - return "user-requested"; - case NM_DEVICE_STATE_REASON_CARRIER: - return "carrier-changed"; - case NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED: - return "connection-assumed"; - case NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE: - return "supplicant-available"; - case NM_DEVICE_STATE_REASON_MODEM_NOT_FOUND: - return "modem-not-found"; - case NM_DEVICE_STATE_REASON_BT_FAILED: - return "bluetooth-failed"; - case NM_DEVICE_STATE_REASON_GSM_SIM_NOT_INSERTED: - return "gsm-sim-not-inserted"; - case NM_DEVICE_STATE_REASON_GSM_SIM_PIN_REQUIRED: - return "gsm-sim-pin-required"; - case NM_DEVICE_STATE_REASON_GSM_SIM_PUK_REQUIRED: - return "gsm-sim-puk-required"; - case NM_DEVICE_STATE_REASON_GSM_SIM_WRONG: - return "gsm-sim-wrong"; - case NM_DEVICE_STATE_REASON_INFINIBAND_MODE: - return "infiniband-mode"; - case NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED: - return "dependency-failed"; - case NM_DEVICE_STATE_REASON_BR2684_FAILED: - return "br2684-bridge-failed"; - case NM_DEVICE_STATE_REASON_MODEM_MANAGER_UNAVAILABLE: - return "modem-manager-unavailable"; - case NM_DEVICE_STATE_REASON_SSID_NOT_FOUND: - return "SSID not found"; - case NM_DEVICE_STATE_REASON_SECONDARY_CONNECTION_FAILED: - return "secondary-connection-failed"; - default: - break; - } - return "unknown"; -} - -void -nm_device_state_changed (NMDevice *device, - NMDeviceState state, - NMDeviceStateReason reason) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); - NMDeviceState old_state; - NMActRequest *req; - gboolean no_firmware = FALSE; - NMConnection *connection; - - /* Track re-entry */ - static gboolean in_state_changed = FALSE; - - g_warn_if_fail (in_state_changed == FALSE); - in_state_changed = TRUE; - - g_return_if_fail (NM_IS_DEVICE (device)); - - /* Do nothing if state isn't changing, but as a special case allow - * re-setting UNAVAILABLE if the device is missing firmware so that we - * can retry device initialization. - */ - if ( (priv->state == state) - && !(state == NM_DEVICE_STATE_UNAVAILABLE && priv->firmware_missing)) { - in_state_changed = FALSE; - return; - } - - old_state = priv->state; - priv->state = state; - priv->state_reason = reason; - - nm_log_info (LOGD_DEVICE, "(%s): device state change: %s -> %s (reason '%s') [%d %d %d]", - nm_device_get_iface (device), - state_to_string (old_state), - state_to_string (state), - reason_to_string (reason), - old_state, - state, - reason); - - /* Clear any queued transitions */ - nm_device_queued_state_clear (device); - - /* Cache the activation request for the dispatcher */ - req = priv->act_request ? g_object_ref (priv->act_request) : NULL; - - if (state <= NM_DEVICE_STATE_UNAVAILABLE) - _clear_available_connections (device, TRUE); - - /* Update the available connections list when a device first becomes available */ - if ( state >= NM_DEVICE_STATE_DISCONNECTED - && old_state < NM_DEVICE_STATE_DISCONNECTED) - nm_device_recheck_available_connections (device); - - /* Handle the new state here; but anything that could trigger - * another state change should be done below. - */ - switch (state) { - case NM_DEVICE_STATE_UNMANAGED: - nm_device_set_firmware_missing (device, FALSE); - if (old_state > NM_DEVICE_STATE_UNMANAGED) - nm_device_take_down (device, TRUE, reason); - break; - case NM_DEVICE_STATE_UNAVAILABLE: - if (old_state == NM_DEVICE_STATE_UNMANAGED || priv->firmware_missing) { - if (!nm_device_bring_up (device, TRUE, &no_firmware) && no_firmware) - nm_log_warn (LOGD_HW, "(%s): firmware may be missing.", nm_device_get_iface (device)); - nm_device_set_firmware_missing (device, no_firmware ? TRUE : FALSE); - } - /* Ensure the device gets deactivated in response to stuff like - * carrier changes or rfkill. But don't deactivate devices that are - * about to assume a connection since that defeats the purpose of - * assuming the device's existing connection. - */ - if (reason != NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED) - nm_device_deactivate (device, reason); - break; - case NM_DEVICE_STATE_DISCONNECTED: - if (old_state != NM_DEVICE_STATE_UNAVAILABLE) - nm_device_deactivate (device, reason); - break; - default: - priv->autoconnect = TRUE; - break; - } - - g_object_notify (G_OBJECT (device), NM_DEVICE_STATE); - g_object_notify (G_OBJECT (device), NM_DEVICE_STATE_REASON); - g_signal_emit_by_name (device, "state-changed", state, old_state, reason); - - /* Post-process the event after internal notification */ - - switch (state) { - case NM_DEVICE_STATE_UNAVAILABLE: - /* If the device can activate now (ie, it's got a carrier, the supplicant - * is active, or whatever) schedule a delayed transition to DISCONNECTED - * to get things rolling. The device can't transition immediately because - * we can't change states again from the state handler for a variety of - * reasons. - */ - if (nm_device_is_available (device)) { - nm_log_dbg (LOGD_DEVICE, "(%s): device is available, will transition to DISCONNECTED", - nm_device_get_iface (device)); - nm_device_queue_state (device, NM_DEVICE_STATE_DISCONNECTED, NM_DEVICE_STATE_REASON_NONE); - } else { - nm_log_dbg (LOGD_DEVICE, "(%s): device not yet available for transition to DISCONNECTED", - nm_device_get_iface (device)); - } - break; - case NM_DEVICE_STATE_ACTIVATED: - nm_log_info (LOGD_DEVICE, "Activation (%s) successful, device activated.", - nm_device_get_iface (device)); - nm_dispatcher_call (DISPATCHER_ACTION_UP, nm_act_request_get_connection (req), device, NULL, NULL); - break; - case NM_DEVICE_STATE_FAILED: - connection = nm_device_get_connection (device); - nm_log_warn (LOGD_DEVICE | LOGD_WIFI, - "Activation (%s) failed for connection '%s'", - nm_device_get_iface (device), - connection ? nm_connection_get_id (connection) : ""); - - /* Notify any slaves of the unexpected failure */ - nm_device_master_release_slaves (device, TRUE); - - /* If the connection doesn't yet have a timestamp, set it to zero so that - * we can distinguish between connections we've tried to activate and have - * failed (zero timestamp), connections that succeeded (non-zero timestamp), - * and those we haven't tried yet (no timestamp). - */ - if (connection && !nm_settings_connection_get_timestamp (NM_SETTINGS_CONNECTION (connection), NULL)) { - nm_settings_connection_update_timestamp (NM_SETTINGS_CONNECTION (connection), - (guint64) 0, - TRUE); - } - - /* Schedule the transition to DISCONNECTED. The device can't transition - * immediately because we can't change states again from the state - * handler for a variety of reasons. - */ - nm_device_queue_state (device, NM_DEVICE_STATE_DISCONNECTED, NM_DEVICE_STATE_REASON_NONE); - break; - case NM_DEVICE_STATE_SECONDARIES: - nm_log_dbg (LOGD_DEVICE, "(%s): device entered SECONDARIES state", - nm_device_get_iface (device)); - break; - default: - break; - } - - if (old_state == NM_DEVICE_STATE_ACTIVATED) - nm_dispatcher_call (DISPATCHER_ACTION_DOWN, nm_act_request_get_connection (req), device, NULL, NULL); - - /* Dispose of the cached activation request */ - if (req) - g_object_unref (req); - - in_state_changed = FALSE; -} - -static gboolean -queued_set_state (gpointer user_data) -{ - NMDevice *self = NM_DEVICE (user_data); - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - NMDeviceState new_state; - NMDeviceStateReason new_reason; - - if (priv->queued_state.id) { - nm_log_dbg (LOGD_DEVICE, "(%s): running queued state change to %s (id %d)", - nm_device_get_iface (self), - state_to_string (priv->queued_state.state), - priv->queued_state.id); - - /* Clear queued state struct before triggering state change, since - * the state change may queue another state. - */ - priv->queued_state.id = 0; - new_state = priv->queued_state.state; - new_reason = priv->queued_state.reason; - nm_device_queued_state_clear (self); - - nm_device_state_changed (self, new_state, new_reason); - } else { - g_warn_if_fail (priv->queued_state.state == NM_DEVICE_STATE_UNKNOWN); - g_warn_if_fail (priv->queued_state.reason == NM_DEVICE_STATE_REASON_NONE); - } - return FALSE; -} - -void -nm_device_queue_state (NMDevice *self, - NMDeviceState state, - NMDeviceStateReason reason) -{ - NMDevicePrivate *priv; - - g_return_if_fail (self != NULL); - g_return_if_fail (NM_IS_DEVICE (self)); - - priv = NM_DEVICE_GET_PRIVATE (self); - - /* We should only ever have one delayed state transition at a time */ - if (priv->queued_state.id) { - g_warn_if_fail (priv->queued_state.id == 0); - nm_device_queued_state_clear (self); - } - - priv->queued_state.state = state; - priv->queued_state.reason = reason; - priv->queued_state.id = g_idle_add (queued_set_state, self); - - nm_log_dbg (LOGD_DEVICE, "(%s): queued state change to %s (id %d)", - nm_device_get_iface (self), state_to_string (state), - priv->queued_state.id); -} - -NMDeviceState -nm_device_queued_state_peek (NMDevice *self) -{ - NMDevicePrivate *priv; - - g_return_val_if_fail (self != NULL, NM_DEVICE_STATE_UNKNOWN); - g_return_val_if_fail (NM_IS_DEVICE (self), NM_DEVICE_STATE_UNKNOWN); - - priv = NM_DEVICE_GET_PRIVATE (self); - - return priv->queued_state.id ? priv->queued_state.state : NM_DEVICE_STATE_UNKNOWN; -} - -void -nm_device_queued_state_clear (NMDevice *self) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - - if (priv->queued_state.id) { - nm_log_dbg (LOGD_DEVICE, "(%s): clearing queued state transition (id %d)", - nm_device_get_iface (self), priv->queued_state.id); - g_source_remove (priv->queued_state.id); - } - memset (&priv->queued_state, 0, sizeof (priv->queued_state)); -} - -NMDeviceState -nm_device_get_state (NMDevice *device) -{ - g_return_val_if_fail (NM_IS_DEVICE (device), NM_DEVICE_STATE_UNKNOWN); - - return NM_DEVICE_GET_PRIVATE (device)->state; -} - -gboolean -nm_device_get_managed (NMDevice *device) -{ - g_return_val_if_fail (NM_IS_DEVICE (device), FALSE); - - return NM_DEVICE_GET_PRIVATE (device)->managed; -} - -void -nm_device_set_managed (NMDevice *device, - gboolean managed, - NMDeviceStateReason reason) -{ - NMDevicePrivate *priv; - - g_return_if_fail (NM_IS_DEVICE (device)); - - priv = NM_DEVICE_GET_PRIVATE (device); - if (priv->managed == managed) - return; - - priv->managed = managed; - nm_log_dbg (LOGD_DEVICE, "(%s): now %s", - nm_device_get_iface (device), - managed ? "managed" : "unmanaged"); - - g_object_notify (G_OBJECT (device), NM_DEVICE_MANAGED); - - /* If now managed, jump to unavailable */ - if (managed) - nm_device_state_changed (device, NM_DEVICE_STATE_UNAVAILABLE, reason); - else - nm_device_state_changed (device, NM_DEVICE_STATE_UNMANAGED, reason); -} - -gboolean -nm_device_spec_match_list (NMDevice *device, const GSList *specs) -{ - g_return_val_if_fail (device != NULL, FALSE); - g_return_val_if_fail (NM_IS_DEVICE (device), FALSE); - - if (NM_DEVICE_GET_CLASS (device)->spec_match_list) - return NM_DEVICE_GET_CLASS (device)->spec_match_list (device, specs); - return FALSE; -} - -static gboolean -ip4_match_config (NMDevice *self, NMConnection *connection) -{ - NMSettingIP4Config *s_ip4; - int i, num; - GSList *leases, *iter; - NMDHCPManager *dhcp_mgr; - const char *method; - - s_ip4 = nm_connection_get_setting_ip4_config (connection); - - /* Get any saved leases that apply to this connection */ - dhcp_mgr = nm_dhcp_manager_get (); - leases = nm_dhcp_manager_get_lease_config (dhcp_mgr, - nm_device_get_iface (self), - nm_connection_get_uuid (connection), - FALSE); - g_object_unref (dhcp_mgr); - - method = s_ip4 ? nm_setting_ip4_config_get_method (s_ip4) : NM_SETTING_IP4_CONFIG_METHOD_AUTO; - if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) { - gboolean found = FALSE; - - /* Find at least one lease's address on the device */ - for (iter = leases; iter; iter = g_slist_next (iter)) { - NMIP4Config *ip4_config = iter->data; - NMIP4Address *addr = nm_ip4_config_get_address (ip4_config, 0); - struct in_addr tmp = { .s_addr = nm_ip4_address_get_address (addr) }; - - if (addr && nm_netlink_find_address (nm_device_get_ip_ifindex (self), - AF_INET, - &tmp, - nm_ip4_address_get_prefix (addr))) { - found = TRUE; /* Yay, device has same address as a lease */ - break; - } - } - g_slist_foreach (leases, (GFunc) g_object_unref, NULL); - g_slist_free (leases); - return found; - } else { - /* Maybe the connection used to be DHCP and there are stale leases; ignore them */ - g_slist_foreach (leases, (GFunc) g_object_unref, NULL); - g_slist_free (leases); - } - - if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED)) { - // FIXME: Enforce no ipv4 addresses? - return TRUE; - } - - /* 'shared' and 'link-local' aren't supported methods because 'shared' - * requires too much iptables and dnsmasq state to be reclaimed, and - * avahi-autoipd isn't smart enough to allow the link-local address to be - * determined at any point other than when it was first assigned. - */ - if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL)) - return FALSE; - - /* Everything below for static addressing */ - - /* Find all IP4 addresses of this connection on the device */ - if (s_ip4) { - num = nm_setting_ip4_config_get_num_addresses (s_ip4); - for (i = 0; i < num; i++) { - NMIP4Address *addr = nm_setting_ip4_config_get_address (s_ip4, i); - struct in_addr tmp = { .s_addr = nm_ip4_address_get_address (addr) }; - - if (!nm_netlink_find_address (nm_device_get_ip_ifindex (self), - AF_INET, - &tmp, - nm_ip4_address_get_prefix (addr))) - return FALSE; - } - } - - /* Success; all the connection's static IP addresses are assigned to the device */ - return TRUE; -} - -gboolean -nm_device_match_ip_config (NMDevice *device, NMConnection *connection) -{ - if (!ip4_match_config (device, connection)) - return FALSE; - - /* FIXME: match IPv6 config */ - - return TRUE; -} - -NMConnection * -nm_device_connection_match_config (NMDevice *device, const GSList *connections) -{ - g_return_val_if_fail (device != NULL, NULL); - g_return_val_if_fail (NM_IS_DEVICE (device), NULL); - - if (NM_DEVICE_GET_CLASS (device)->connection_match_config) - return NM_DEVICE_GET_CLASS (device)->connection_match_config (NM_DEVICE (device), connections); - return NULL; -} - -/** - * nm_device_hwaddr_matches: - * @device: the device to use when matching the hardware address - * @connection: the connection which supplies the hardware address - * @other_hwaddr: if given, use this address instead of the device's actual - * hardware address - * @other_hwaddr_len: length in bytes of @other_hwaddr - * @fail_if_no_hwaddr: whether to fail the match if @connection does not contain - * a hardware address - * - * Matches a the devices hardware address (or @other_hwaddr if given) against - * the hardware-specific setting in @connection. Allows for device-agnostic - * hardware address matching without having to know the internal details of - * the connection and which settings are used by each device subclass. - * - * Returns: %TRUE if the @device 's hardware address or @other_hwaddr matches - * a hardware address in a hardware-specific setting in @connection - */ -gboolean -nm_device_hwaddr_matches (NMDevice *device, - NMConnection *connection, - const guint8 *other_hwaddr, - guint other_hwaddr_len, - gboolean fail_if_no_hwaddr) -{ - g_return_val_if_fail (device != NULL, FALSE); - g_return_val_if_fail (NM_IS_DEVICE (device), FALSE); - if (other_hwaddr) - g_return_val_if_fail (other_hwaddr_len > 0, FALSE); - - if (NM_DEVICE_GET_CLASS (device)->hwaddr_matches) { - return NM_DEVICE_GET_CLASS (device)->hwaddr_matches (device, - connection, - other_hwaddr, - other_hwaddr_len, - fail_if_no_hwaddr); - } - return FALSE; -} - -void -nm_device_set_dhcp_timeout (NMDevice *device, guint32 timeout) -{ - g_return_if_fail (NM_IS_DEVICE (device)); - - NM_DEVICE_GET_PRIVATE (device)->dhcp_timeout = timeout; -} - -void -nm_device_set_dhcp_anycast_address (NMDevice *device, guint8 *addr) -{ - NMDevicePrivate *priv; - - g_return_if_fail (NM_IS_DEVICE (device)); - - priv = NM_DEVICE_GET_PRIVATE (device); - - if (priv->dhcp_anycast_address) { - g_byte_array_free (priv->dhcp_anycast_address, TRUE); - priv->dhcp_anycast_address = NULL; - } - - if (addr) { - priv->dhcp_anycast_address = g_byte_array_sized_new (ETH_ALEN); - g_byte_array_append (priv->dhcp_anycast_address, addr, ETH_ALEN); - } -} - -gboolean -nm_device_get_autoconnect (NMDevice *device) -{ - g_return_val_if_fail (NM_IS_DEVICE (device), FALSE); - - return NM_DEVICE_GET_PRIVATE (device)->autoconnect; -} - -static void -_signal_available_connections_changed (NMDevice *device) -{ - g_object_notify (G_OBJECT (device), NM_DEVICE_AVAILABLE_CONNECTIONS); -} - -static void -_clear_available_connections (NMDevice *device, gboolean do_signal) -{ - g_hash_table_remove_all (NM_DEVICE_GET_PRIVATE (device)->available_connections); - if (do_signal == TRUE) - _signal_available_connections_changed (device); -} - -static gboolean -_try_add_available_connection (NMDevice *self, NMConnection *connection) -{ - if (nm_device_get_state (self) < NM_DEVICE_STATE_DISCONNECTED) - return FALSE; - - if (nm_device_check_connection_compatible (self, connection, NULL)) { - /* Let subclasses implement additional checks on the connection */ - if ( NM_DEVICE_GET_CLASS (self)->check_connection_available - && NM_DEVICE_GET_CLASS (self)->check_connection_available (self, connection)) { - - g_hash_table_insert (NM_DEVICE_GET_PRIVATE (self)->available_connections, - g_object_ref (connection), - GUINT_TO_POINTER (1)); - return TRUE; - } - } - return FALSE; -} - -static gboolean -_del_available_connection (NMDevice *device, NMConnection *connection) -{ - return g_hash_table_remove (NM_DEVICE_GET_PRIVATE (device)->available_connections, connection); -} - -static gboolean -check_connection_available (NMDevice *device, NMConnection *connection) -{ - /* Default is to assume the connection is available unless a subclass - * overrides this with more specific checks. - */ - return TRUE; -} - -void -nm_device_recheck_available_connections (NMDevice *device) -{ - NMDevicePrivate *priv; - const GSList *connections, *iter; - - g_return_if_fail (device != NULL); - g_return_if_fail (NM_IS_DEVICE (device)); - - priv = NM_DEVICE_GET_PRIVATE(device); - - _clear_available_connections (device, FALSE); - - connections = nm_connection_provider_get_connections (priv->con_provider); - for (iter = connections; iter; iter = g_slist_next (iter)) - _try_add_available_connection (device, NM_CONNECTION (iter->data)); - - _signal_available_connections_changed (device); -} - -static void -cp_connection_added (NMConnectionProvider *cp, NMConnection *connection, gpointer user_data) -{ - if (_try_add_available_connection (NM_DEVICE (user_data), connection)) - _signal_available_connections_changed (NM_DEVICE (user_data)); -} - -static void -cp_connections_loaded (NMConnectionProvider *cp, NMConnection *connection, gpointer user_data) -{ - const GSList *connections, *iter; - gboolean added = FALSE; - - connections = nm_connection_provider_get_connections (cp); - for (iter = connections; iter; iter = g_slist_next (iter)) - added |= _try_add_available_connection (NM_DEVICE (user_data), NM_CONNECTION (iter->data)); - - if (added) - _signal_available_connections_changed (NM_DEVICE (user_data)); -} - -static void -cp_connection_removed (NMConnectionProvider *cp, NMConnection *connection, gpointer user_data) -{ - if (_del_available_connection (NM_DEVICE (user_data), connection)) - _signal_available_connections_changed (NM_DEVICE (user_data)); -} - -static void -cp_connection_updated (NMConnectionProvider *cp, NMConnection *connection, gpointer user_data) -{ - gboolean added, deleted; - - /* FIXME: don't remove it from the hash if it's just going to get re-added */ - deleted = _del_available_connection (NM_DEVICE (user_data), connection); - added = _try_add_available_connection (NM_DEVICE (user_data), connection); - - /* Only signal if the connection was removed OR added, but not both */ - if (added != deleted) - _signal_available_connections_changed (NM_DEVICE (user_data)); -} - -gboolean -nm_device_supports_vlans (NMDevice *device) -{ - /* At the moment, NM's VLAN code assumes all VLANs are over ethernet. */ - return NM_IS_DEVICE_ETHERNET (device); -} - -/** - * nm_device_read_hwaddr: - * @dev: the device - * @buf: an allocated buffer which on success holds the device's hardware - * address - * @buf_len: the size of @buf - * @out_changed: on success, %TRUE if the contents of @buf are different from - * the original contents of @buf when this function was called - * - * Reads the device's hardware address from the kernel and copies it into - * @buf, returning the size of the data copied into @buf. On failure - * @buf is not modified. - * - * Returns: the size of the hardware address in bytes on success, 0 on failure - */ -gsize -nm_device_read_hwaddr (NMDevice *dev, - guint8 *buf, - gsize buf_len, - gboolean *out_changed) -{ - struct rtnl_link *rtnl; - struct nl_addr *addr; - int idx; - gsize addrlen = 0; - const guint8 *binaddr; - - g_return_val_if_fail (dev != NULL, 0); - g_return_val_if_fail (buf != NULL, 0); - g_return_val_if_fail (buf_len > 0, 0); - - idx = nm_device_get_ip_ifindex (dev); - g_return_val_if_fail (idx > 0, 0); - - rtnl = nm_netlink_index_to_rtnl_link (idx); - if (!rtnl) { - nm_log_err (LOGD_HW | LOGD_DEVICE, - "(%s): failed to read hardware address (error %d)", - nm_device_get_iface (dev), errno); - return 0; - } - - addr = rtnl_link_get_addr (rtnl); - if (!addr) { - nm_log_err (LOGD_HW | LOGD_DEVICE, - "(%s): no hardware address?", - nm_device_get_iface (dev)); - goto out; - } - - addrlen = nl_addr_get_len (addr); - if (addrlen > buf_len) { - nm_log_err (LOGD_HW | LOGD_DEVICE, - "(%s): hardware address is wrong length (got %zd max %zd)", - nm_device_get_iface (dev), addrlen, buf_len); - addrlen = 0; - } else { - binaddr = nl_addr_get_binary_addr (addr); - if (out_changed) - *out_changed = memcmp (buf, binaddr, addrlen) ? TRUE : FALSE; - memcpy (buf, binaddr, addrlen); - } - -out: - rtnl_link_put (rtnl); - return addrlen; -} diff --git a/src/nm-device.h b/src/nm-device.h deleted file mode 100644 index 87e428f5..00000000 --- a/src/nm-device.h +++ /dev/null @@ -1,311 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2005 - 2012 Red Hat, Inc. - * Copyright (C) 2006 - 2008 Novell, Inc. - */ - -#ifndef NM_DEVICE_H -#define NM_DEVICE_H - -#include -#include -#include - -#include "NetworkManager.h" -#include "nm-types.h" -#include "nm-activation-request.h" -#include "nm-ip4-config.h" -#include "nm-ip6-config.h" -#include "nm-dhcp4-config.h" -#include "nm-dhcp6-config.h" -#include "nm-connection.h" -#include "nm-rfkill.h" -#include "nm-connection-provider.h" - -/* Properties */ -#define NM_DEVICE_UDI "udi" -#define NM_DEVICE_IFACE "interface" -#define NM_DEVICE_IP_IFACE "ip-interface" -#define NM_DEVICE_DRIVER "driver" -#define NM_DEVICE_DRIVER_VERSION "driver-version" -#define NM_DEVICE_FIRMWARE_VERSION "firmware-version" -#define NM_DEVICE_CAPABILITIES "capabilities" -#define NM_DEVICE_IP4_ADDRESS "ip4-address" -#define NM_DEVICE_IP4_CONFIG "ip4-config" -#define NM_DEVICE_DHCP4_CONFIG "dhcp4-config" -#define NM_DEVICE_IP6_CONFIG "ip6-config" -#define NM_DEVICE_DHCP6_CONFIG "dhcp6-config" -#define NM_DEVICE_STATE "state" -#define NM_DEVICE_STATE_REASON "state-reason" -#define NM_DEVICE_ACTIVE_CONNECTION "active-connection" -#define NM_DEVICE_DEVICE_TYPE "device-type" /* ugh */ -#define NM_DEVICE_MANAGED "managed" -#define NM_DEVICE_AUTOCONNECT "autoconnect" -#define NM_DEVICE_FIRMWARE_MISSING "firmware-missing" -#define NM_DEVICE_TYPE_DESC "type-desc" /* Internal only */ -#define NM_DEVICE_RFKILL_TYPE "rfkill-type" /* Internal only */ -#define NM_DEVICE_IFINDEX "ifindex" /* Internal only */ -#define NM_DEVICE_IS_MASTER "is-master" /* Internal only */ -#define NM_DEVICE_AVAILABLE_CONNECTIONS "available-connections" - -/* Internal signals */ -#define NM_DEVICE_AUTH_REQUEST "auth-request" -#define NM_DEVICE_IP4_CONFIG_CHANGED "ip4-config-changed" -#define NM_DEVICE_IP6_CONFIG_CHANGED "ip6-config-changed" - - -G_BEGIN_DECLS - -#define NM_TYPE_DEVICE (nm_device_get_type ()) -#define NM_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE, NMDevice)) -#define NM_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE, NMDeviceClass)) -#define NM_IS_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE)) -#define NM_IS_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE)) -#define NM_DEVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE, NMDeviceClass)) - -typedef enum NMActStageReturn NMActStageReturn; - -typedef enum { - NM_DEVICE_ERROR_CONNECTION_ACTIVATING = 0, /*< nick=ConnectionActivating >*/ - NM_DEVICE_ERROR_CONNECTION_INVALID, /*< nick=ConnectionInvalid >*/ - NM_DEVICE_ERROR_NOT_ACTIVE, /*< nick=NotActive >*/ -} NMDeviceError; - -struct _NMDevice { - GObject parent; -}; - -typedef struct { - GObjectClass parent; - - void (*state_changed) (NMDevice *device, - NMDeviceState new_state, - NMDeviceState old_state, - NMDeviceStateReason reason); - - /* Hardware state, ie IFF_UP */ - gboolean (*hw_is_up) (NMDevice *self); - gboolean (*hw_bring_up) (NMDevice *self, gboolean *no_firmware); - void (*hw_take_down) (NMDevice *self); - - /* Additional stuff required to operate the device, like a - * connection to the supplicant, Bluez, etc - */ - gboolean (*is_up) (NMDevice *self); - gboolean (*bring_up) (NMDevice *self); - void (*take_down) (NMDevice *self); - - void (* update_hw_address) (NMDevice *self); - void (* update_permanent_hw_address) (NMDevice *self); - void (* update_initial_hw_address) (NMDevice *self); - const guint8 * (* get_hw_address) (NMDevice *self, guint *out_len); - - guint32 (* get_type_capabilities) (NMDevice *self); - guint32 (* get_generic_capabilities) (NMDevice *self); - - gboolean (* is_available) (NMDevice *self); - - gboolean (* get_enabled) (NMDevice *self); - - void (* set_enabled) (NMDevice *self, gboolean enabled); - - NMConnection * (* get_best_auto_connection) (NMDevice *self, - GSList *connections, - char **specific_object); - - /* Checks whether the connection is compatible with the device using - * only the devices type and characteristics. Does not use any live - * network information like WiFi/WiMAX scan lists etc. - */ - gboolean (* check_connection_compatible) (NMDevice *self, - NMConnection *connection, - GError **error); - - /* Checks whether the connection is likely available to be activated, - * including any live network information like scan lists. Returns - * TRUE if the connection is available; FALSE if not. - */ - gboolean (* check_connection_available) (NMDevice *self, - NMConnection *connection); - - gboolean (* complete_connection) (NMDevice *self, - NMConnection *connection, - const char *specific_object, - const GSList *existing_connections, - GError **error); - - NMActStageReturn (* act_stage1_prepare) (NMDevice *self, - NMDeviceStateReason *reason); - NMActStageReturn (* act_stage2_config) (NMDevice *self, - NMDeviceStateReason *reason); - NMActStageReturn (* act_stage3_ip4_config_start) (NMDevice *self, - NMIP4Config **out_config, - NMDeviceStateReason *reason); - NMActStageReturn (* act_stage3_ip6_config_start) (NMDevice *self, - NMIP6Config **out_config, - NMDeviceStateReason *reason); - NMActStageReturn (* act_stage4_ip4_config_timeout) (NMDevice *self, - NMDeviceStateReason *reason); - NMActStageReturn (* act_stage4_ip6_config_timeout) (NMDevice *self, - NMDeviceStateReason *reason); - - /* Called right before IP config is set; use for setting MTU etc */ - void (* ip4_config_pre_commit) (NMDevice *self, NMIP4Config *config); - void (* ip6_config_pre_commit) (NMDevice *self, NMIP6Config *config); - - void (* deactivate) (NMDevice *self); - - gboolean (* can_interrupt_activation) (NMDevice *self); - - gboolean (* spec_match_list) (NMDevice *self, const GSList *specs); - - NMConnection * (* connection_match_config) (NMDevice *self, const GSList *connections); - - gboolean (* hwaddr_matches) (NMDevice *self, - NMConnection *connection, - const guint8 *other_hwaddr, - guint other_hwaddr_len, - gboolean fail_if_no_hwaddr); - - gboolean (* enslave_slave) (NMDevice *self, - NMDevice *slave, - NMConnection *connection); - - gboolean (* release_slave) (NMDevice *self, - NMDevice *slave); - - gboolean (* have_any_ready_slaves) (NMDevice *self, - const GSList *slaves); -} NMDeviceClass; - - -typedef void (*NMDeviceAuthRequestFunc) (NMDevice *device, - DBusGMethodInvocation *context, - GError *error, - gpointer user_data); - -GType nm_device_get_type (void); - -const char * nm_device_get_path (NMDevice *dev); -void nm_device_set_path (NMDevice *dev, const char *path); - -const char * nm_device_get_udi (NMDevice *dev); -const char * nm_device_get_iface (NMDevice *dev); -int nm_device_get_ifindex (NMDevice *dev); -const char * nm_device_get_ip_iface (NMDevice *dev); -int nm_device_get_ip_ifindex(NMDevice *dev); -const char * nm_device_get_driver (NMDevice *dev); -const char * nm_device_get_driver_version (NMDevice *dev); -const char * nm_device_get_firmware_version (NMDevice *dev); -const char * nm_device_get_type_desc (NMDevice *dev); -NMDeviceType nm_device_get_device_type (NMDevice *dev); - -int nm_device_get_priority (NMDevice *dev); - -const guint8 * nm_device_get_hw_address (NMDevice *dev, guint *out_len); - -NMDHCP4Config * nm_device_get_dhcp4_config (NMDevice *dev); -NMDHCP6Config * nm_device_get_dhcp6_config (NMDevice *dev); - -NMIP4Config * nm_device_get_ip4_config (NMDevice *dev); -NMIP6Config * nm_device_get_ip6_config (NMDevice *dev); - -/* Master */ -gboolean nm_device_master_add_slave (NMDevice *dev, NMDevice *slave); -GSList * nm_device_master_get_slaves (NMDevice *dev); -gboolean nm_device_is_master (NMDevice *dev); - -/* Slave */ -void nm_device_slave_notify_enslaved (NMDevice *dev, - gboolean enslaved, - gboolean master_failed); - -NMActRequest * nm_device_get_act_request (NMDevice *dev); -NMConnection * nm_device_get_connection (NMDevice *dev); - -gboolean nm_device_is_available (NMDevice *dev); - -NMConnection * nm_device_get_best_auto_connection (NMDevice *dev, - GSList *connections, - char **specific_object); - -gboolean nm_device_complete_connection (NMDevice *device, - NMConnection *connection, - const char *specific_object, - const GSList *existing_connection, - GError **error); - -gboolean nm_device_check_connection_compatible (NMDevice *device, - NMConnection *connection, - GError **error); - -gboolean nm_device_can_assume_connections (NMDevice *device); - -NMConnection * nm_device_connection_match_config (NMDevice *device, - const GSList *connections); - -gboolean nm_device_hwaddr_matches (NMDevice *device, - NMConnection *connection, - const guint8 *other_hwaddr, - guint other_hwaddr_len, - gboolean fail_if_no_hwaddr); - -gboolean nm_device_spec_match_list (NMDevice *device, const GSList *specs); - -gboolean nm_device_is_activating (NMDevice *dev); -gboolean nm_device_can_interrupt_activation (NMDevice *self); -gboolean nm_device_autoconnect_allowed (NMDevice *self); - -NMDeviceState nm_device_get_state (NMDevice *device); - -gboolean nm_device_get_enabled (NMDevice *device); - -void nm_device_set_enabled (NMDevice *device, gboolean enabled); - -RfKillType nm_device_get_rfkill_type (NMDevice *device); - -gboolean nm_device_get_managed (NMDevice *device); -void nm_device_set_managed (NMDevice *device, - gboolean managed, - NMDeviceStateReason reason); - -gboolean nm_device_get_autoconnect (NMDevice *device); - -void nm_device_handle_autoip4_event (NMDevice *self, - const char *event, - const char *address); - -void nm_device_state_changed (NMDevice *device, - NMDeviceState state, - NMDeviceStateReason reason); - -void nm_device_queue_state (NMDevice *self, - NMDeviceState state, - NMDeviceStateReason reason); - -gboolean nm_device_get_firmware_missing (NMDevice *self); - -void nm_device_activate (NMDevice *device, NMActRequest *req); - -void nm_device_set_connection_provider (NMDevice *device, NMConnectionProvider *provider); - -gboolean nm_device_supports_vlans (NMDevice *device); - -G_END_DECLS - -#endif /* NM_DEVICE_H */ diff --git a/src/nm-dhcp4-config-glue.h b/src/nm-dhcp4-config-glue.h new file mode 100644 index 00000000..b08a611b --- /dev/null +++ b/src/nm-dhcp4-config-glue.h @@ -0,0 +1,73 @@ +/* Generated by dbus-binding-tool; do not edit! */ + + +#ifndef __dbus_glib_marshal_nm_dhcp4_config_MARSHAL_H__ +#define __dbus_glib_marshal_nm_dhcp4_config_MARSHAL_H__ + +#include + +G_BEGIN_DECLS + +#ifdef G_ENABLE_DEBUG +#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v) +#define g_marshal_value_peek_char(v) g_value_get_schar (v) +#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v) +#define g_marshal_value_peek_int(v) g_value_get_int (v) +#define g_marshal_value_peek_uint(v) g_value_get_uint (v) +#define g_marshal_value_peek_long(v) g_value_get_long (v) +#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v) +#define g_marshal_value_peek_int64(v) g_value_get_int64 (v) +#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v) +#define g_marshal_value_peek_enum(v) g_value_get_enum (v) +#define g_marshal_value_peek_flags(v) g_value_get_flags (v) +#define g_marshal_value_peek_float(v) g_value_get_float (v) +#define g_marshal_value_peek_double(v) g_value_get_double (v) +#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v) +#define g_marshal_value_peek_param(v) g_value_get_param (v) +#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v) +#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v) +#define g_marshal_value_peek_object(v) g_value_get_object (v) +#define g_marshal_value_peek_variant(v) g_value_get_variant (v) +#else /* !G_ENABLE_DEBUG */ +/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API. + * Do not access GValues directly in your code. Instead, use the + * g_value_get_*() functions + */ +#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int +#define g_marshal_value_peek_char(v) (v)->data[0].v_int +#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint +#define g_marshal_value_peek_int(v) (v)->data[0].v_int +#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint +#define g_marshal_value_peek_long(v) (v)->data[0].v_long +#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 +#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 +#define g_marshal_value_peek_enum(v) (v)->data[0].v_long +#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_float(v) (v)->data[0].v_float +#define g_marshal_value_peek_double(v) (v)->data[0].v_double +#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer +#endif /* !G_ENABLE_DEBUG */ + + +G_END_DECLS + +#endif /* __dbus_glib_marshal_nm_dhcp4_config_MARSHAL_H__ */ + +#include +static const DBusGMethodInfo dbus_glib_nm_dhcp4_config_methods[] = { +}; + +const DBusGObjectInfo dbus_glib_nm_dhcp4_config_object_info = { 1, + dbus_glib_nm_dhcp4_config_methods, + 0, +"\0", +"org.freedesktop.NetworkManager.DHCP4Config\0PropertiesChanged\0\0", +"org.freedesktop.NetworkManager.DHCP4Config\0Options\0options\0read\0\0" +}; + diff --git a/src/nm-dhcp4-config.c b/src/nm-dhcp4-config.c index 567ba687..a405aa87 100644 --- a/src/nm-dhcp4-config.c +++ b/src/nm-dhcp4-config.c @@ -26,7 +26,6 @@ #include "nm-dhcp4-config.h" #include "nm-dhcp4-config-glue.h" #include "nm-dbus-glib-types.h" -#include "nm-properties-changed-signal.h" #include "nm-utils.h" @@ -47,14 +46,6 @@ enum { LAST_PROP }; -enum { - PROPERTIES_CHANGED, - - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - NMDHCP4Config * nm_dhcp4_config_new (void) @@ -140,14 +131,9 @@ nm_dhcp4_config_init (NMDHCP4Config *self) { NMDHCP4ConfigPrivate *priv = NM_DHCP4_CONFIG_GET_PRIVATE (self); static guint32 counter = 0; - DBusGConnection *connection; - NMDBusManager *dbus_mgr; - dbus_mgr = nm_dbus_manager_get (); - connection = nm_dbus_manager_get_connection (dbus_mgr); priv->dbus_path = g_strdup_printf (NM_DBUS_PATH "/DHCP4Config/%d", counter++); - dbus_g_connection_register_g_object (connection, priv->dbus_path, G_OBJECT (self)); - g_object_unref (dbus_mgr); + nm_dbus_manager_register_object (nm_dbus_manager_get (), priv->dbus_path, self); priv->options = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, nm_gvalue_destroy); } @@ -199,11 +185,7 @@ nm_dhcp4_config_class_init (NMDHCP4ConfigClass *config_class) DBUS_TYPE_G_MAP_OF_VARIANT, G_PARAM_READABLE)); - /* Signals */ - signals[PROPERTIES_CHANGED] = - nm_properties_changed_signal_new (object_class, - G_STRUCT_OFFSET (NMDHCP4ConfigClass, properties_changed)); - - dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (config_class), - &dbus_glib_nm_dhcp4_config_object_info); + nm_dbus_manager_register_exported_type (nm_dbus_manager_get (), + G_TYPE_FROM_CLASS (config_class), + &dbus_glib_nm_dhcp4_config_object_info); } diff --git a/src/nm-dhcp4-config.h b/src/nm-dhcp4-config.h index c5d78db9..6eb9ee57 100644 --- a/src/nm-dhcp4-config.h +++ b/src/nm-dhcp4-config.h @@ -38,8 +38,6 @@ typedef struct { typedef struct { GObjectClass parent; - /* Signals */ - void (*properties_changed) (NMDHCP4Config *config, GHashTable *properties); } NMDHCP4ConfigClass; #define NM_DHCP4_CONFIG_OPTIONS "options" diff --git a/src/nm-dhcp6-config-glue.h b/src/nm-dhcp6-config-glue.h new file mode 100644 index 00000000..9bfee43d --- /dev/null +++ b/src/nm-dhcp6-config-glue.h @@ -0,0 +1,73 @@ +/* Generated by dbus-binding-tool; do not edit! */ + + +#ifndef __dbus_glib_marshal_nm_dhcp6_config_MARSHAL_H__ +#define __dbus_glib_marshal_nm_dhcp6_config_MARSHAL_H__ + +#include + +G_BEGIN_DECLS + +#ifdef G_ENABLE_DEBUG +#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v) +#define g_marshal_value_peek_char(v) g_value_get_schar (v) +#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v) +#define g_marshal_value_peek_int(v) g_value_get_int (v) +#define g_marshal_value_peek_uint(v) g_value_get_uint (v) +#define g_marshal_value_peek_long(v) g_value_get_long (v) +#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v) +#define g_marshal_value_peek_int64(v) g_value_get_int64 (v) +#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v) +#define g_marshal_value_peek_enum(v) g_value_get_enum (v) +#define g_marshal_value_peek_flags(v) g_value_get_flags (v) +#define g_marshal_value_peek_float(v) g_value_get_float (v) +#define g_marshal_value_peek_double(v) g_value_get_double (v) +#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v) +#define g_marshal_value_peek_param(v) g_value_get_param (v) +#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v) +#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v) +#define g_marshal_value_peek_object(v) g_value_get_object (v) +#define g_marshal_value_peek_variant(v) g_value_get_variant (v) +#else /* !G_ENABLE_DEBUG */ +/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API. + * Do not access GValues directly in your code. Instead, use the + * g_value_get_*() functions + */ +#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int +#define g_marshal_value_peek_char(v) (v)->data[0].v_int +#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint +#define g_marshal_value_peek_int(v) (v)->data[0].v_int +#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint +#define g_marshal_value_peek_long(v) (v)->data[0].v_long +#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 +#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 +#define g_marshal_value_peek_enum(v) (v)->data[0].v_long +#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_float(v) (v)->data[0].v_float +#define g_marshal_value_peek_double(v) (v)->data[0].v_double +#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer +#endif /* !G_ENABLE_DEBUG */ + + +G_END_DECLS + +#endif /* __dbus_glib_marshal_nm_dhcp6_config_MARSHAL_H__ */ + +#include +static const DBusGMethodInfo dbus_glib_nm_dhcp6_config_methods[] = { +}; + +const DBusGObjectInfo dbus_glib_nm_dhcp6_config_object_info = { 1, + dbus_glib_nm_dhcp6_config_methods, + 0, +"\0", +"org.freedesktop.NetworkManager.DHCP6Config\0PropertiesChanged\0\0", +"org.freedesktop.NetworkManager.DHCP6Config\0Options\0options\0read\0\0" +}; + diff --git a/src/nm-dhcp6-config.c b/src/nm-dhcp6-config.c index 885e5f84..c50b8fdd 100644 --- a/src/nm-dhcp6-config.c +++ b/src/nm-dhcp6-config.c @@ -26,7 +26,6 @@ #include "nm-dhcp6-config.h" #include "nm-dhcp6-config-glue.h" #include "nm-dbus-glib-types.h" -#include "nm-properties-changed-signal.h" #include "nm-utils.h" @@ -47,14 +46,6 @@ enum { LAST_PROP }; -enum { - PROPERTIES_CHANGED, - - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - NMDHCP6Config * nm_dhcp6_config_new (void) @@ -140,14 +131,9 @@ nm_dhcp6_config_init (NMDHCP6Config *self) { NMDHCP6ConfigPrivate *priv = NM_DHCP6_CONFIG_GET_PRIVATE (self); static guint32 counter = 0; - DBusGConnection *connection; - NMDBusManager *dbus_mgr; - dbus_mgr = nm_dbus_manager_get (); - connection = nm_dbus_manager_get_connection (dbus_mgr); priv->dbus_path = g_strdup_printf (NM_DBUS_PATH "/DHCP6Config/%d", counter++); - dbus_g_connection_register_g_object (connection, priv->dbus_path, G_OBJECT (self)); - g_object_unref (dbus_mgr); + nm_dbus_manager_register_object (nm_dbus_manager_get (), priv->dbus_path, self); priv->options = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, nm_gvalue_destroy); } @@ -199,11 +185,7 @@ nm_dhcp6_config_class_init (NMDHCP6ConfigClass *config_class) DBUS_TYPE_G_MAP_OF_VARIANT, G_PARAM_READABLE)); - /* Signals */ - signals[PROPERTIES_CHANGED] = - nm_properties_changed_signal_new (object_class, - G_STRUCT_OFFSET (NMDHCP6ConfigClass, properties_changed)); - - dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (config_class), - &dbus_glib_nm_dhcp6_config_object_info); + nm_dbus_manager_register_exported_type (nm_dbus_manager_get (), + G_TYPE_FROM_CLASS (config_class), + &dbus_glib_nm_dhcp6_config_object_info); } diff --git a/src/nm-dhcp6-config.h b/src/nm-dhcp6-config.h index ef742ac4..2af65607 100644 --- a/src/nm-dhcp6-config.h +++ b/src/nm-dhcp6-config.h @@ -38,8 +38,6 @@ typedef struct { typedef struct { GObjectClass parent; - /* Signals */ - void (*properties_changed) (NMDHCP6Config *config, GHashTable *properties); } NMDHCP6ConfigClass; #define NM_DHCP6_CONFIG_OPTIONS "options" diff --git a/src/nm-dispatcher.c b/src/nm-dispatcher.c index 12cd0f0a..f955822b 100644 --- a/src/nm-dispatcher.c +++ b/src/nm-dispatcher.c @@ -20,17 +20,58 @@ */ #include +#include #include +#include #include "nm-dispatcher.h" -#include "nm-dispatcher-action.h" +#include "nm-dispatcher-api.h" #include "NetworkManagerUtils.h" #include "nm-utils.h" #include "nm-logging.h" #include "nm-dbus-manager.h" #include "nm-dbus-glib-types.h" +#include "nm-glib-compat.h" -static GSList *requests = NULL; +#define CALL_TIMEOUT (1000 * 60 * 10) /* 10 minutes for all scripts */ + +static GHashTable *requests = NULL; + +typedef struct { + GFileMonitor *monitor; + const char *const description; + const char *const dir; + const guint16 dir_len; + char has_scripts; +} Monitor; + +enum { + MONITOR_INDEX_DEFAULT, + MONITOR_INDEX_PRE_UP, + MONITOR_INDEX_PRE_DOWN, +}; + +static Monitor monitors[3] = { +#define MONITORS_INIT_SET(INDEX, USE, SCRIPT_DIR) [INDEX] = { .dir_len = STRLEN (SCRIPT_DIR), .dir = SCRIPT_DIR, .description = ("" USE), .has_scripts = TRUE } + MONITORS_INIT_SET (MONITOR_INDEX_DEFAULT, "default", NMD_SCRIPT_DIR_DEFAULT), + MONITORS_INIT_SET (MONITOR_INDEX_PRE_UP, "pre-up", NMD_SCRIPT_DIR_PRE_UP), + MONITORS_INIT_SET (MONITOR_INDEX_PRE_DOWN, "pre-down", NMD_SCRIPT_DIR_PRE_DOWN), +}; + +static const Monitor* +_get_monitor_by_action (DispatcherAction action) +{ + switch (action) { + case DISPATCHER_ACTION_PRE_UP: + case DISPATCHER_ACTION_VPN_PRE_UP: + return &monitors[MONITOR_INDEX_PRE_UP]; + case DISPATCHER_ACTION_PRE_DOWN: + case DISPATCHER_ACTION_VPN_PRE_DOWN: + return &monitors[MONITOR_INDEX_PRE_DOWN]; + default: + return &monitors[MONITOR_INDEX_DEFAULT]; + } +} static void dump_object_to_props (GObject *object, GHashTable *hash) @@ -131,19 +172,38 @@ fill_vpn_props (NMIP4Config *ip4_config, } typedef struct { + DispatcherAction action; + guint request_id; DispatcherFunc callback; gpointer user_data; - NMDBusManager *dbus_mgr; + guint idle_id; } DispatchInfo; static void dispatcher_info_free (DispatchInfo *info) { - requests = g_slist_remove (requests, info); - g_object_unref (info->dbus_mgr); + if (info->idle_id) + g_source_remove (info->idle_id); g_free (info); } +static void +_ensure_requests (void) +{ + if (G_UNLIKELY (requests == NULL)) { + requests = g_hash_table_new_full (g_direct_hash, + g_direct_equal, + NULL, + (GDestroyNotify) dispatcher_info_free); + } +} + +static void +dispatcher_info_cleanup (DispatchInfo *info) +{ + g_hash_table_remove (requests, GUINT_TO_POINTER (info->request_id)); +} + static const char * dispatch_result_to_string (DispatchResult result) { @@ -162,98 +222,178 @@ dispatch_result_to_string (DispatchResult result) g_assert_not_reached (); } +static gboolean +validate_element (guint request_id, GValue *val, GType expected_type, guint idx, guint eltnum) +{ + if (G_VALUE_TYPE (val) != expected_type) { + nm_log_dbg (LOGD_DISPATCH, "(%u) result %d element %d invalid type %s", + request_id, idx, eltnum, G_VALUE_TYPE_NAME (val)); + return FALSE; + } + return TRUE; +} + +static void +dispatcher_results_process (guint request_id, DispatcherAction action, GPtrArray *results) +{ + guint i; + const Monitor *monitor = _get_monitor_by_action (action); + + g_return_if_fail (results != NULL); + + if (results->len == 0) { + nm_log_dbg (LOGD_DISPATCH, "(%u) succeeded but no scripts invoked", + request_id); + return; + } + + for (i = 0; i < results->len; i++) { + GValueArray *item = g_ptr_array_index (results, i); + GValue *tmp; + const char *script, *err; + DispatchResult result; + const char *script_validation_msg = ""; + + if (item->n_values != 3) { + nm_log_dbg (LOGD_DISPATCH, "(%u) unexpected number of items in " + "dispatcher result (got %d, expected 3)", + request_id, item->n_values); + continue; + } + + /* Script */ + tmp = g_value_array_get_nth (item, 0); + if (!validate_element (request_id, tmp, G_TYPE_STRING, i, 0)) + continue; + script = g_value_get_string (tmp); + if (!script) { + script_validation_msg = " (path is NULL)"; + script = "(unknown)"; + } else if (!strncmp (script, monitor->dir, monitor->dir_len) /* check: prefixed by script directory */ + && script[monitor->dir_len] == '/' && script[monitor->dir_len+1] /* check: with additional "/?" */ + && !strchr (&script[monitor->dir_len+1], '/')) { /* check: and no further '/' */ + /* we expect the script to lie inside monitor->dir. If it does, + * strip the directory name. Otherwise show the full path and a warning. */ + script += monitor->dir_len + 1; + } else + script_validation_msg = " (unexpected path)"; + + + /* Result */ + tmp = g_value_array_get_nth (item, 1); + if (!validate_element (request_id, tmp, G_TYPE_UINT, i, 1)) + continue; + result = g_value_get_uint (tmp); + + /* Error */ + tmp = g_value_array_get_nth (item, 2); + if (!validate_element (request_id, tmp, G_TYPE_STRING, i, 2)) + continue; + err = g_value_get_string (tmp); + + + if (result == DISPATCH_RESULT_SUCCESS) { + nm_log_dbg (LOGD_DISPATCH, "(%u) %s succeeded%s", + request_id, + script, script_validation_msg); + } else { + nm_log_warn (LOGD_DISPATCH, "(%u) %s failed (%s): %s%s", + request_id, + script, + dispatch_result_to_string (result), + err ? err : "", script_validation_msg); + } + } +} + +static void +free_results (GPtrArray *results) +{ + g_return_if_fail (results != NULL); + g_ptr_array_foreach (results, (GFunc) g_value_array_free, NULL); + g_ptr_array_free (results, TRUE); +} + static void dispatcher_done_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) { DispatchInfo *info = user_data; GError *error = NULL; GPtrArray *results = NULL; - guint i; if (dbus_g_proxy_end_call (proxy, call, &error, DISPATCHER_TYPE_RESULT_ARRAY, &results, G_TYPE_INVALID)) { - for (i = 0; results && (i < results->len); i++) { - GValueArray *item = g_ptr_array_index (results, i); - GValue *tmp; - const char *script, *err; - DispatchResult result; - - if ( (G_VALUE_TYPE (g_value_array_get_nth (item, 0)) == G_TYPE_STRING) - && (G_VALUE_TYPE (g_value_array_get_nth (item, 1)) == G_TYPE_UINT) - && (G_VALUE_TYPE (g_value_array_get_nth (item, 2)) == G_TYPE_STRING)) { - /* result */ - tmp = g_value_array_get_nth (item, 1); - result = g_value_get_uint (tmp); - if (result != DISPATCH_RESULT_SUCCESS) { - /* script */ - tmp = g_value_array_get_nth (item, 0); - script = g_value_get_string (tmp); - - /* error */ - tmp = g_value_array_get_nth (item, 2); - err = g_value_get_string (tmp); - - nm_log_warn (LOGD_CORE, "Dispatcher script %s: %s", - dispatch_result_to_string (result), err); - } - } else - nm_log_dbg (LOGD_CORE, "Dispatcher result element %d invalid type", i); - - g_value_array_free (item); - } - g_ptr_array_free (results, TRUE); + dispatcher_results_process (info->request_id, info->action, results); + free_results (results); } else { g_assert (error); - nm_log_warn (LOGD_CORE, "Dispatcher failed: (%d) %s", error->code, error->message); + + if (!g_error_matches (error, DBUS_GERROR, DBUS_GERROR_REMOTE_EXCEPTION)) { + nm_log_warn (LOGD_DISPATCH, "(%u) failed to call dispatcher scripts: (%s:%d) %s", + info->request_id, g_quark_to_string (error->domain), + error->code, error->message); + } else if (!dbus_g_error_has_name (error, "org.freedesktop.systemd1.LoadFailed")) { + nm_log_warn (LOGD_DISPATCH, "(%u) failed to call dispatcher scripts: (%s) %s", + info->request_id, dbus_g_error_get_name (error), error->message); + } else { + nm_log_dbg (LOGD_DISPATCH, "(%u) failed to call dispatcher scripts: (%s) %s", + info->request_id, dbus_g_error_get_name (error), error->message); + } } if (info->callback) - info->callback (info, info->user_data); + info->callback (info->request_id, info->user_data); g_clear_error (&error); g_object_unref (proxy); } +static const char *action_table[] = { + [DISPATCHER_ACTION_HOSTNAME] = NMD_ACTION_HOSTNAME, + [DISPATCHER_ACTION_PRE_UP] = NMD_ACTION_PRE_UP, + [DISPATCHER_ACTION_UP] = NMD_ACTION_UP, + [DISPATCHER_ACTION_PRE_DOWN] = NMD_ACTION_PRE_DOWN, + [DISPATCHER_ACTION_DOWN] = NMD_ACTION_DOWN, + [DISPATCHER_ACTION_VPN_PRE_UP] = NMD_ACTION_VPN_PRE_UP, + [DISPATCHER_ACTION_VPN_UP] = NMD_ACTION_VPN_UP, + [DISPATCHER_ACTION_VPN_PRE_DOWN] = NMD_ACTION_VPN_PRE_DOWN, + [DISPATCHER_ACTION_VPN_DOWN] = NMD_ACTION_VPN_DOWN, + [DISPATCHER_ACTION_DHCP4_CHANGE] = NMD_ACTION_DHCP4_CHANGE, + [DISPATCHER_ACTION_DHCP6_CHANGE] = NMD_ACTION_DHCP6_CHANGE, +}; + static const char * action_to_string (DispatcherAction action) { - switch (action) { - case DISPATCHER_ACTION_HOSTNAME: - return "hostname"; - case DISPATCHER_ACTION_UP: - return "up"; - case DISPATCHER_ACTION_PRE_DOWN: - return "pre-down"; - case DISPATCHER_ACTION_DOWN: - return "down"; - case DISPATCHER_ACTION_VPN_UP: - return "vpn-up"; - case DISPATCHER_ACTION_VPN_PRE_DOWN: - return "vpn-pre-down"; - case DISPATCHER_ACTION_VPN_DOWN: - return "vpn-down"; - case DISPATCHER_ACTION_DHCP4_CHANGE: - return "dhcp4-change"; - case DISPATCHER_ACTION_DHCP6_CHANGE: - return "dhcp6-change"; - default: - break; - } - g_assert_not_reached (); + g_assert (action >= 0 && action < G_N_ELEMENTS (action_table)); + return action_table[action]; +} + +static gboolean +dispatcher_idle_cb (gpointer user_data) +{ + DispatchInfo *info = user_data; + + info->idle_id = 0; + if (info->callback) + info->callback (info->request_id, info->user_data); + dispatcher_info_cleanup (info); + return G_SOURCE_REMOVE; } -static gconstpointer +static gboolean _dispatcher_call (DispatcherAction action, + gboolean blocking, NMConnection *connection, NMDevice *device, const char *vpn_iface, NMIP4Config *vpn_ip4_config, NMIP6Config *vpn_ip6_config, DispatcherFunc callback, - gpointer user_data) + gpointer user_data, + guint *out_call_id) { - NMDBusManager *dbus_mgr; DBusGProxy *proxy; DBusGConnection *g_connection; GHashTable *connection_hash; @@ -265,26 +405,66 @@ _dispatcher_call (DispatcherAction action, GHashTable *device_dhcp6_props; GHashTable *vpn_ip4_props; GHashTable *vpn_ip6_props; - DBusGProxyCall *call; - DispatchInfo *info; + DispatchInfo *info = NULL; + gboolean success = FALSE; + GError *error = NULL; + static guint request_counter = 0; + guint reqid = ++request_counter; + + /* Wrapping protection */ + if (G_UNLIKELY (!reqid)) + reqid = ++request_counter; + + g_assert (!blocking || (!callback && !user_data)); + + _ensure_requests (); /* All actions except 'hostname' require a device */ - if (action != DISPATCHER_ACTION_HOSTNAME) - g_return_val_if_fail (NM_IS_DEVICE (device), NULL); + if (action == DISPATCHER_ACTION_HOSTNAME) { + nm_log_dbg (LOGD_DISPATCH, "(%u) dispatching action '%s'%s", + reqid, action_to_string (action), + blocking + ? " (blocking)" + : (callback ? " (with callback)" : "")); + } else { + g_return_val_if_fail (NM_IS_DEVICE (device), FALSE); + + nm_log_dbg (LOGD_DISPATCH, "(%u) (%s) dispatching action '%s'%s", + reqid, + vpn_iface ? vpn_iface : nm_device_get_iface (device), + action_to_string (action), + blocking + ? " (blocking)" + : (callback ? " (with callback)" : "")); + } + /* VPN actions require at least an IPv4 config (for now) */ if (action == DISPATCHER_ACTION_VPN_UP) - g_return_val_if_fail (vpn_ip4_config != NULL, NULL); + g_return_val_if_fail (vpn_ip4_config != NULL, FALSE); + + if (!_get_monitor_by_action(action)->has_scripts) { + if (blocking == FALSE && (out_call_id || callback)) { + info = g_malloc0 (sizeof (*info)); + info->action = action; + info->request_id = reqid; + info->callback = callback; + info->user_data = user_data; + info->idle_id = g_idle_add (dispatcher_idle_cb, info); + nm_log_dbg (LOGD_DISPATCH, "(%u) simulate request; no scripts in %s", reqid, _get_monitor_by_action(action)->dir); + } else + nm_log_dbg (LOGD_DISPATCH, "(%u) ignoring request; no scripts in %s", reqid, _get_monitor_by_action(action)->dir); + success = TRUE; + goto done; + } - dbus_mgr = nm_dbus_manager_get (); - g_connection = nm_dbus_manager_get_connection (dbus_mgr); + g_connection = nm_dbus_manager_get_connection (nm_dbus_manager_get ()); proxy = dbus_g_proxy_new_for_name (g_connection, NM_DISPATCHER_DBUS_SERVICE, NM_DISPATCHER_DBUS_PATH, NM_DISPATCHER_DBUS_IFACE); if (!proxy) { - nm_log_err (LOGD_CORE, "could not get dispatcher proxy!"); - g_object_unref (dbus_mgr); - return NULL; + nm_log_err (LOGD_DISPATCH, "(%u) could not get dispatcher proxy!", reqid); + return FALSE; } if (connection) { @@ -315,33 +495,66 @@ _dispatcher_call (DispatcherAction action, device_ip6_props, device_dhcp4_props, device_dhcp6_props); - if (vpn_iface) + if (vpn_ip4_config || vpn_ip6_config) fill_vpn_props (vpn_ip4_config, vpn_ip6_config, vpn_ip4_props, vpn_ip6_props); } - info = g_malloc0 (sizeof (*info)); - info->callback = callback; - info->user_data = user_data; - info->dbus_mgr = dbus_mgr; - /* Send the action to the dispatcher */ - call = dbus_g_proxy_begin_call_with_timeout (proxy, "Action", - dispatcher_done_cb, - info, - (GDestroyNotify) dispatcher_info_free, - 15000, - G_TYPE_STRING, action_to_string (action), - DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, connection_hash, - DBUS_TYPE_G_MAP_OF_VARIANT, connection_props, - DBUS_TYPE_G_MAP_OF_VARIANT, device_props, - DBUS_TYPE_G_MAP_OF_VARIANT, device_ip4_props, - DBUS_TYPE_G_MAP_OF_VARIANT, device_ip6_props, - DBUS_TYPE_G_MAP_OF_VARIANT, device_dhcp4_props, - DBUS_TYPE_G_MAP_OF_VARIANT, device_dhcp6_props, - G_TYPE_STRING, vpn_iface ? vpn_iface : "", - DBUS_TYPE_G_MAP_OF_VARIANT, vpn_ip4_props, - DBUS_TYPE_G_MAP_OF_VARIANT, vpn_ip6_props, - G_TYPE_INVALID); + if (blocking) { + GPtrArray *results = NULL; + + success = dbus_g_proxy_call_with_timeout (proxy, "Action", + CALL_TIMEOUT, + &error, + G_TYPE_STRING, action_to_string (action), + DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, connection_hash, + DBUS_TYPE_G_MAP_OF_VARIANT, connection_props, + DBUS_TYPE_G_MAP_OF_VARIANT, device_props, + DBUS_TYPE_G_MAP_OF_VARIANT, device_ip4_props, + DBUS_TYPE_G_MAP_OF_VARIANT, device_ip6_props, + DBUS_TYPE_G_MAP_OF_VARIANT, device_dhcp4_props, + DBUS_TYPE_G_MAP_OF_VARIANT, device_dhcp6_props, + G_TYPE_STRING, vpn_iface ? vpn_iface : "", + DBUS_TYPE_G_MAP_OF_VARIANT, vpn_ip4_props, + DBUS_TYPE_G_MAP_OF_VARIANT, vpn_ip6_props, + G_TYPE_BOOLEAN, nm_logging_enabled (LOGL_DEBUG, LOGD_DISPATCH), + G_TYPE_INVALID, + DISPATCHER_TYPE_RESULT_ARRAY, &results, + G_TYPE_INVALID); + if (success) { + dispatcher_results_process (reqid, action, results); + free_results (results); + } else { + nm_log_warn (LOGD_DISPATCH, "(%u) failed: (%d) %s", reqid, error->code, error->message); + g_error_free (error); + } + } else { + info = g_malloc0 (sizeof (*info)); + info->action = action; + info->request_id = reqid; + info->callback = callback; + info->user_data = user_data; + dbus_g_proxy_begin_call_with_timeout (proxy, "Action", + dispatcher_done_cb, + info, + (GDestroyNotify) dispatcher_info_cleanup, + CALL_TIMEOUT, + G_TYPE_STRING, action_to_string (action), + DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, connection_hash, + DBUS_TYPE_G_MAP_OF_VARIANT, connection_props, + DBUS_TYPE_G_MAP_OF_VARIANT, device_props, + DBUS_TYPE_G_MAP_OF_VARIANT, device_ip4_props, + DBUS_TYPE_G_MAP_OF_VARIANT, device_ip6_props, + DBUS_TYPE_G_MAP_OF_VARIANT, device_dhcp4_props, + DBUS_TYPE_G_MAP_OF_VARIANT, device_dhcp6_props, + G_TYPE_STRING, vpn_iface ? vpn_iface : "", + DBUS_TYPE_G_MAP_OF_VARIANT, vpn_ip4_props, + DBUS_TYPE_G_MAP_OF_VARIANT, vpn_ip6_props, + G_TYPE_BOOLEAN, nm_logging_enabled (LOGL_DEBUG, LOGD_DISPATCH), + G_TYPE_INVALID); + success = TRUE; + } + g_hash_table_destroy (connection_hash); g_hash_table_destroy (connection_props); g_hash_table_destroy (device_props); @@ -352,45 +565,205 @@ _dispatcher_call (DispatcherAction action, g_hash_table_destroy (vpn_ip4_props); g_hash_table_destroy (vpn_ip6_props); - /* Track the request in case of cancelation */ - requests = g_slist_append (requests, info); +done: + if (success && info) { + /* Track the request in case of cancelation */ + g_hash_table_insert (requests, GUINT_TO_POINTER (info->request_id), info); + if (out_call_id) + *out_call_id = info->request_id; + } else if (out_call_id) + *out_call_id = 0; - return info; + return success; } -gconstpointer +/** + * nm_dispatcher_call: + * @action: the %DispatcherAction + * @connection: the #NMConnection the action applies to + * @device: the #NMDevice the action applies to + * @callback: a caller-supplied callback to execute when done + * @user_data: caller-supplied pointer passed to @callback + * @out_call_id: on success, a call identifier which can be passed to + * nm_dispatcher_call_cancel() + * + * This method always invokes the dispatcher action asynchronously. To ignore + * the result, pass %NULL to @callback. + * + * Returns: %TRUE if the action was dispatched, %FALSE on failure + */ +gboolean nm_dispatcher_call (DispatcherAction action, NMConnection *connection, NMDevice *device, DispatcherFunc callback, - gpointer user_data) + gpointer user_data, + guint *out_call_id) +{ + return _dispatcher_call (action, FALSE, connection, device, NULL, NULL, + NULL, callback, user_data, out_call_id); +} + +/** + * nm_dispatcher_call_sync(): + * @action: the %DispatcherAction + * @connection: the #NMConnection the action applies to + * @device: the #NMDevice the action applies to + * + * This method always invokes the dispatcher action synchronously and it may + * take a long time to return. + * + * Returns: %TRUE if the action was dispatched, %FALSE on failure + */ +gboolean +nm_dispatcher_call_sync (DispatcherAction action, + NMConnection *connection, + NMDevice *device) { - return _dispatcher_call (action, connection, device, NULL, NULL, NULL, callback, user_data); + return _dispatcher_call (action, TRUE, connection, device, NULL, NULL, + NULL, NULL, NULL, NULL); } -gconstpointer +/** + * nm_dispatcher_call_vpn(): + * @action: the %DispatcherAction + * @connection: the #NMConnection the action applies to + * @parent_device: the parent #NMDevice of the VPN connection + * @vpn_iface: the IP interface of the VPN tunnel, if any + * @vpn_ip4_config: the #NMIP4Config of the VPN connection + * @vpn_ip6_config: the #NMIP6Config of the VPN connection + * @callback: a caller-supplied callback to execute when done + * @user_data: caller-supplied pointer passed to @callback + * @out_call_id: on success, a call identifier which can be passed to + * nm_dispatcher_call_cancel() + * + * This method always invokes the dispatcher action asynchronously. To ignore + * the result, pass %NULL to @callback. + * + * Returns: %TRUE if the action was dispatched, %FALSE on failure + */ +gboolean nm_dispatcher_call_vpn (DispatcherAction action, NMConnection *connection, - NMDevice *device, + NMDevice *parent_device, const char *vpn_iface, NMIP4Config *vpn_ip4_config, NMIP6Config *vpn_ip6_config, DispatcherFunc callback, - gpointer user_data) + gpointer user_data, + guint *out_call_id) { - return _dispatcher_call (action, connection, device, vpn_iface, vpn_ip4_config, vpn_ip6_config, callback, user_data); + return _dispatcher_call (action, FALSE, connection, parent_device, vpn_iface, + vpn_ip4_config, vpn_ip6_config, callback, user_data, out_call_id); +} + +/** + * nm_dispatcher_call_vpn_sync(): + * @action: the %DispatcherAction + * @connection: the #NMConnection the action applies to + * @parent_device: the parent #NMDevice of the VPN connection + * @vpn_iface: the IP interface of the VPN tunnel, if any + * @vpn_ip4_config: the #NMIP4Config of the VPN connection + * @vpn_ip6_config: the #NMIP6Config of the VPN connection + * + * This method always invokes the dispatcher action synchronously and it may + * take a long time to return. + * + * Returns: %TRUE if the action was dispatched, %FALSE on failure + */ +gboolean +nm_dispatcher_call_vpn_sync (DispatcherAction action, + NMConnection *connection, + NMDevice *parent_device, + const char *vpn_iface, + NMIP4Config *vpn_ip4_config, + NMIP6Config *vpn_ip6_config) +{ + return _dispatcher_call (action, TRUE, connection, parent_device, vpn_iface, + vpn_ip4_config, vpn_ip6_config, NULL, NULL, NULL); } void -nm_dispatcher_call_cancel (gconstpointer call) +nm_dispatcher_call_cancel (guint call_id) { - /* 'call' is really a DispatchInfo pointer, just opaque to callers. - * Look it up in our requests list, but don't access it directly before - * we've made sure it's a valid request,since it may have long since been - * freed. Canceling just means the callback doesn't get called, so set - * the DispatcherInfo's callback to NULL. + DispatchInfo *info; + + _ensure_requests (); + + /* Canceling just means the callback doesn't get called, so set the + * DispatcherInfo's callback to NULL. */ - if (g_slist_find (requests, call)) - ((DispatchInfo *) call)->callback = NULL; + info = g_hash_table_lookup (requests, GUINT_TO_POINTER (call_id)); + g_return_if_fail (info); + + if (info && info->callback) { + nm_log_dbg (LOGD_DISPATCH, "(%u) cancelling dispatcher callback action", + call_id); + info->callback = NULL; + } +} + +static void +dispatcher_dir_changed (GFileMonitor *monitor, + GFile *file, + GFile *other_file, + GFileMonitorEvent event_type, + Monitor *item) +{ + const char *name; + char *full_name; + GDir *dir; + GError *error = NULL; + + dir = g_dir_open (item->dir, 0, &error); + if (dir) { + int errsv = 0; + + item->has_scripts = FALSE; + errno = 0; + while (!item->has_scripts + && (name = g_dir_read_name (dir))) { + full_name = g_build_filename (item->dir, name, NULL); + item->has_scripts = g_file_test (full_name, G_FILE_TEST_IS_EXECUTABLE); + g_free (full_name); + } + errsv = errno; + g_dir_close (dir); + if (item->has_scripts) + nm_log_dbg (LOGD_DISPATCH, "dispatcher: %s script directory '%s' has scripts", item->description, item->dir); + else if (errsv == 0) + nm_log_dbg (LOGD_DISPATCH, "dispatcher: %s script directory '%s' has no scripts", item->description, item->dir); + else { + nm_log_dbg (LOGD_DISPATCH, "dispatcher: %s script directory '%s' error reading (%s)", item->description, item->dir, strerror (errsv)); + item->has_scripts = TRUE; + } + } else { + if (g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT)) { + nm_log_dbg (LOGD_DISPATCH, "dispatcher: %s script directory '%s' does not exist", item->description, item->dir); + item->has_scripts = FALSE; + } else { + nm_log_dbg (LOGD_DISPATCH, "dispatcher: %s script directory '%s' error (%s)", item->description, item->dir, error->message); + item->has_scripts = TRUE; + } + g_error_free (error); + } + +} + +void +nm_dispatcher_init (void) +{ + GFile *file; + guint i; + + for (i = 0; i < G_N_ELEMENTS (monitors); i++) { + file = g_file_new_for_path (monitors[i].dir); + monitors[i].monitor = g_file_monitor_directory (file, G_FILE_MONITOR_NONE, NULL, NULL); + if (monitors[i].monitor) { + g_signal_connect (monitors[i].monitor, "changed", G_CALLBACK (dispatcher_dir_changed), &monitors[i]); + dispatcher_dir_changed (monitors[i].monitor, file, NULL, 0, &monitors[i]); + } + g_object_unref (file); + } } diff --git a/src/nm-dispatcher.h b/src/nm-dispatcher.h index 05a6c875..464f6310 100644 --- a/src/nm-dispatcher.h +++ b/src/nm-dispatcher.h @@ -32,9 +32,11 @@ typedef enum { DISPATCHER_ACTION_HOSTNAME, + DISPATCHER_ACTION_PRE_UP, DISPATCHER_ACTION_UP, DISPATCHER_ACTION_PRE_DOWN, DISPATCHER_ACTION_DOWN, + DISPATCHER_ACTION_VPN_PRE_UP, DISPATCHER_ACTION_VPN_UP, DISPATCHER_ACTION_VPN_PRE_DOWN, DISPATCHER_ACTION_VPN_DOWN, @@ -42,23 +44,38 @@ typedef enum { DISPATCHER_ACTION_DHCP6_CHANGE } DispatcherAction; -typedef void (*DispatcherFunc) (gconstpointer call, gpointer user_data); +typedef void (*DispatcherFunc) (guint call_id, gpointer user_data); -gconstpointer nm_dispatcher_call (DispatcherAction action, +gboolean nm_dispatcher_call (DispatcherAction action, + NMConnection *connection, + NMDevice *device, + DispatcherFunc callback, + gpointer user_data, + guint *out_call_id); + +gboolean nm_dispatcher_call_sync (DispatcherAction action, NMConnection *connection, - NMDevice *device, - DispatcherFunc callback, - gpointer user_data); + NMDevice *device); + +gboolean nm_dispatcher_call_vpn (DispatcherAction action, + NMConnection *connection, + NMDevice *parent_device, + const char *vpn_iface, + NMIP4Config *vpn_ip4_config, + NMIP6Config *vpn_ip6_config, + DispatcherFunc callback, + gpointer user_data, + guint *out_call_id); -gconstpointer nm_dispatcher_call_vpn (DispatcherAction action, +gboolean nm_dispatcher_call_vpn_sync (DispatcherAction action, NMConnection *connection, - NMDevice *device, + NMDevice *parent_device, const char *vpn_iface, NMIP4Config *vpn_ip4_config, - NMIP6Config *vpn_ip6_config, - DispatcherFunc callback, - gpointer user_data); + NMIP6Config *vpn_ip6_config); + +void nm_dispatcher_call_cancel (guint call_id); -void nm_dispatcher_call_cancel (gconstpointer call); +void nm_dispatcher_init (void); #endif /* NM_DISPATCHER_H */ diff --git a/src/nm-enum-types.c b/src/nm-enum-types.c new file mode 100644 index 00000000..95d64a8b --- /dev/null +++ b/src/nm-enum-types.c @@ -0,0 +1,1042 @@ + + + +/* Generated by glib-mkenums. Do not edit */ + +#include "nm-enum-types.h" + +#include "nm-config.h" +#include "nm-config-device.h" +#include "nm-device.h" +#include "nm-device-bond.h" +#include "nm-device-bridge.h" +#include "nm-device-ethernet.h" +#include "nm-device-factory.h" +#include "nm-device-generic.h" +#include "nm-device-gre.h" +#include "nm-device-infiniband.h" +#include "nm-device-macvlan.h" +#include "nm-device-private.h" +#include "nm-device-team.h" +#include "nm-device-tun.h" +#include "nm-device-veth.h" +#include "nm-device-vlan.h" +#include "nm-device-vxlan.h" +#include "nm-dhcp-client.h" +#include "nm-dhcp-dhclient.h" +#include "nm-dhcp-dhclient-utils.h" +#include "nm-dhcp-dhcpcd.h" +#include "nm-dhcp-manager.h" +#include "nm-dns-dnsmasq.h" +#include "nm-dns-unbound.h" +#include "nm-dns-manager.h" +#include "nm-dns-plugin.h" +#include "nm-dns-utils.h" +#include "nm-dnsmasq-manager.h" +#include "nm-dnsmasq-utils.h" +#include "nm-firewall-manager.h" +#include "nm-logging.h" +#include "nm-fake-platform.h" +#include "nm-linux-platform.h" +#include "nm-platform.h" +#include "wifi-utils-nl80211.h" +#include "wifi-utils-private.h" +#include "wifi-utils.h" +#include "nm-fake-rdisc.h" +#include "nm-lndp-rdisc.h" +#include "nm-rdisc.h" +#include "nm-posix-signals.h" +#include "nm-ppp-manager.h" +#include "nm-ppp-status.h" +#include "nm-agent-manager.h" +#include "nm-inotify-helper.h" +#include "nm-secret-agent.h" +#include "nm-settings-connection.h" +#include "nm-settings-error.h" +#include "nm-settings-utils.h" +#include "nm-settings.h" +#include "nm-system-config-interface.h" +#include "common.h" +#include "nm-keyfile-connection.h" +#include "plugin.h" +#include "reader.h" +#include "utils.h" +#include "writer.h" +#include "nm-supplicant-config.h" +#include "nm-supplicant-interface.h" +#include "nm-supplicant-manager.h" +#include "nm-supplicant-settings-verify.h" +#include "nm-supplicant-types.h" +#include "nm-call-store.h" +#include "nm-vpn-connection.h" +#include "nm-vpn-manager.h" +#include "nm-vpn-service.h" +#include "nm-activation-request.h" +#include "nm-active-connection.h" +#include "nm-connection-provider.h" +#include "nm-connectivity.h" +#include "nm-dbus-manager.h" +#include "nm-dcb.h" +#include "nm-dhcp4-config.h" +#include "nm-dhcp6-config.h" +#include "nm-dispatcher.h" +#include "nm-ip4-config.h" +#include "nm-ip6-config.h" +#include "nm-manager-auth.h" +#include "nm-auth-subject.h" +#include "nm-manager.h" +#include "nm-policy.h" +#include "nm-properties-changed-signal.h" +#include "nm-rfkill-manager.h" +#include "nm-session-monitor.h" +#include "nm-session-utils.h" +#include "nm-sleep-monitor.h" +#include "nm-types.h" +#include "NetworkManagerUtils.h" +#include "wifi-utils-wext.h" +#include "nm-device-wimax.h" + +GType +nm_device_error_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { NM_DEVICE_ERROR_CONNECTION_ACTIVATING, "NM_DEVICE_ERROR_CONNECTION_ACTIVATING", "ConnectionActivating" }, + { NM_DEVICE_ERROR_CONNECTION_INVALID, "NM_DEVICE_ERROR_CONNECTION_INVALID", "ConnectionInvalid" }, + { NM_DEVICE_ERROR_NOT_ACTIVE, "NM_DEVICE_ERROR_NOT_ACTIVE", "NotActive" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("NMDeviceError"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +nm_unmanaged_flags_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { NM_UNMANAGED_NONE, "NM_UNMANAGED_NONE", "nm-unmanaged-none" }, + { NM_UNMANAGED_DEFAULT, "NM_UNMANAGED_DEFAULT", "nm-unmanaged-default" }, + { NM_UNMANAGED_INTERNAL, "NM_UNMANAGED_INTERNAL", "nm-unmanaged-internal" }, + { NM_UNMANAGED_USER, "NM_UNMANAGED_USER", "nm-unmanaged-user" }, + { __NM_UNMANAGED_LAST, "__NM_UNMANAGED_LAST", "--nm-unmanaged-last" }, + { NM_UNMANAGED_LAST, "NM_UNMANAGED_LAST", "nm-unmanaged-last" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("NMUnmanagedFlags"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +nm_bond_error_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { NM_BOND_ERROR_CONNECTION_NOT_BOND, "NM_BOND_ERROR_CONNECTION_NOT_BOND", "ConnectionNotBond" }, + { NM_BOND_ERROR_CONNECTION_INVALID, "NM_BOND_ERROR_CONNECTION_INVALID", "ConnectionInvalid" }, + { NM_BOND_ERROR_CONNECTION_INCOMPATIBLE, "NM_BOND_ERROR_CONNECTION_INCOMPATIBLE", "ConnectionIncompatible" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("NMBondError"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +nm_bridge_error_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { NM_BRIDGE_ERROR_CONNECTION_NOT_BRIDGE, "NM_BRIDGE_ERROR_CONNECTION_NOT_BRIDGE", "ConnectionNotBridge" }, + { NM_BRIDGE_ERROR_CONNECTION_INVALID, "NM_BRIDGE_ERROR_CONNECTION_INVALID", "ConnectionInvalid" }, + { NM_BRIDGE_ERROR_CONNECTION_INCOMPATIBLE, "NM_BRIDGE_ERROR_CONNECTION_INCOMPATIBLE", "ConnectionIncompatible" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("NMBridgeError"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +nm_ethernet_error_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { NM_ETHERNET_ERROR_CONNECTION_NOT_WIRED, "NM_ETHERNET_ERROR_CONNECTION_NOT_WIRED", "ConnectionNotWired" }, + { NM_ETHERNET_ERROR_CONNECTION_INVALID, "NM_ETHERNET_ERROR_CONNECTION_INVALID", "ConnectionInvalid" }, + { NM_ETHERNET_ERROR_CONNECTION_INCOMPATIBLE, "NM_ETHERNET_ERROR_CONNECTION_INCOMPATIBLE", "ConnectionIncompatible" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("NMEthernetError"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +nm_device_generic_error_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { NM_DEVICE_GENERIC_ERROR_CONNECTION_NOT_GENERIC, "NM_DEVICE_GENERIC_ERROR_CONNECTION_NOT_GENERIC", "ConnectionNotGeneric" }, + { NM_DEVICE_GENERIC_ERROR_CONNECTION_INVALID, "NM_DEVICE_GENERIC_ERROR_CONNECTION_INVALID", "ConnectionInvalid" }, + { NM_DEVICE_GENERIC_ERROR_CONNECTION_INCOMPATIBLE, "NM_DEVICE_GENERIC_ERROR_CONNECTION_INCOMPATIBLE", "ConnectionIncompatible" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("NMDeviceGenericError"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +nm_infiniband_error_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { NM_INFINIBAND_ERROR_CONNECTION_NOT_INFINIBAND, "NM_INFINIBAND_ERROR_CONNECTION_NOT_INFINIBAND", "ConnectionNotInfiniband" }, + { NM_INFINIBAND_ERROR_CONNECTION_INVALID, "NM_INFINIBAND_ERROR_CONNECTION_INVALID", "ConnectionInvalid" }, + { NM_INFINIBAND_ERROR_CONNECTION_INCOMPATIBLE, "NM_INFINIBAND_ERROR_CONNECTION_INCOMPATIBLE", "ConnectionIncompatible" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("NMInfinibandError"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +nm_team_error_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { NM_TEAM_ERROR_CONNECTION_NOT_TEAM, "NM_TEAM_ERROR_CONNECTION_NOT_TEAM", "ConnectionNotTeam" }, + { NM_TEAM_ERROR_CONNECTION_INVALID, "NM_TEAM_ERROR_CONNECTION_INVALID", "ConnectionInvalid" }, + { NM_TEAM_ERROR_CONNECTION_INCOMPATIBLE, "NM_TEAM_ERROR_CONNECTION_INCOMPATIBLE", "ConnectionIncompatible" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("NMTeamError"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +nm_vlan_error_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { NM_VLAN_ERROR_CONNECTION_NOT_VLAN, "NM_VLAN_ERROR_CONNECTION_NOT_VLAN", "ConnectionNotVlan" }, + { NM_VLAN_ERROR_CONNECTION_INVALID, "NM_VLAN_ERROR_CONNECTION_INVALID", "ConnectionInvalid" }, + { NM_VLAN_ERROR_CONNECTION_INCOMPATIBLE, "NM_VLAN_ERROR_CONNECTION_INCOMPATIBLE", "ConnectionIncompatible" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("NMVlanError"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +nm_dhcp_state_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { DHC_NBI, "DHC_NBI", "nbi" }, + { DHC_PREINIT, "DHC_PREINIT", "preinit" }, + { DHC_PREINIT6, "DHC_PREINIT6", "preinit6" }, + { DHC_BOUND4, "DHC_BOUND4", "bound4" }, + { DHC_BOUND6, "DHC_BOUND6", "bound6" }, + { DHC_IPV4LL, "DHC_IPV4LL", "ipv4ll" }, + { DHC_RENEW4, "DHC_RENEW4", "renew4" }, + { DHC_RENEW6, "DHC_RENEW6", "renew6" }, + { DHC_REBOOT, "DHC_REBOOT", "reboot" }, + { DHC_REBIND4, "DHC_REBIND4", "rebind4" }, + { DHC_REBIND6, "DHC_REBIND6", "rebind6" }, + { DHC_DEPREF6, "DHC_DEPREF6", "depref6" }, + { DHC_STOP, "DHC_STOP", "stop" }, + { DHC_STOP6, "DHC_STOP6", "stop6" }, + { DHC_MEDIUM, "DHC_MEDIUM", "medium" }, + { DHC_TIMEOUT, "DHC_TIMEOUT", "timeout" }, + { DHC_FAIL, "DHC_FAIL", "fail" }, + { DHC_EXPIRE, "DHC_EXPIRE", "expire" }, + { DHC_EXPIRE6, "DHC_EXPIRE6", "expire6" }, + { DHC_RELEASE, "DHC_RELEASE", "release" }, + { DHC_RELEASE6, "DHC_RELEASE6", "release6" }, + { DHC_START, "DHC_START", "start" }, + { DHC_ABEND, "DHC_ABEND", "abend" }, + { DHC_END, "DHC_END", "end" }, + { DHC_END_OPTIONS, "DHC_END_OPTIONS", "end-options" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("NMDHCPState"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +nm_dhcp_manager_error_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { NM_DHCP_MANAGER_ERROR_BAD_CLIENT, "NM_DHCP_MANAGER_ERROR_BAD_CLIENT", "BadClient" }, + { NM_DHCP_MANAGER_ERROR_INTERNAL, "NM_DHCP_MANAGER_ERROR_INTERNAL", "InternalError" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("NMDHCPManagerError"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +nm_dns_manager_error_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { NM_DNS_MANAGER_ERROR_SYSTEM, "NM_DNS_MANAGER_ERROR_SYSTEM", "system" }, + { NM_DNS_MANAGER_ERROR_INVALID_NAMESERVER, "NM_DNS_MANAGER_ERROR_INVALID_NAMESERVER", "invalid-nameserver" }, + { NM_DNS_MANAGER_ERROR_INVALID_HOST, "NM_DNS_MANAGER_ERROR_INVALID_HOST", "invalid-host" }, + { NM_DNS_MANAGER_ERROR_INVALID_ID, "NM_DNS_MANAGER_ERROR_INVALID_ID", "invalid-id" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("NMDnsManagerError"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +nm_dns_ip_config_type_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { NM_DNS_IP_CONFIG_TYPE_DEFAULT, "NM_DNS_IP_CONFIG_TYPE_DEFAULT", "default" }, + { NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE, "NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE", "best-device" }, + { NM_DNS_IP_CONFIG_TYPE_VPN, "NM_DNS_IP_CONFIG_TYPE_VPN", "vpn" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("NMDnsIPConfigType"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +nm_dns_manager_resolv_conf_mode_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { NM_DNS_MANAGER_RESOLV_CONF_UNMANAGED, "NM_DNS_MANAGER_RESOLV_CONF_UNMANAGED", "unmanaged" }, + { NM_DNS_MANAGER_RESOLV_CONF_EXPLICIT, "NM_DNS_MANAGER_RESOLV_CONF_EXPLICIT", "explicit" }, + { NM_DNS_MANAGER_RESOLV_CONF_PROXY, "NM_DNS_MANAGER_RESOLV_CONF_PROXY", "proxy" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("NMDnsManagerResolvConfMode"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +nm_dns_masq_status_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { NM_DNSMASQ_STATUS_UNKNOWN, "NM_DNSMASQ_STATUS_UNKNOWN", "unknown" }, + { NM_DNSMASQ_STATUS_DEAD, "NM_DNSMASQ_STATUS_DEAD", "dead" }, + { NM_DNSMASQ_STATUS_RUNNING, "NM_DNSMASQ_STATUS_RUNNING", "running" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("NMDnsMasqStatus"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +nm_logging_error_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { NM_LOGGING_ERROR_UNKNOWN_LEVEL, "NM_LOGGING_ERROR_UNKNOWN_LEVEL", "UnknownLevel" }, + { NM_LOGGING_ERROR_UNKNOWN_DOMAIN, "NM_LOGGING_ERROR_UNKNOWN_DOMAIN", "UnknownDomain" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("NMLoggingError"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +nm_platform_error_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { NM_PLATFORM_ERROR_NONE, "NM_PLATFORM_ERROR_NONE", "none" }, + { NM_PLATFORM_ERROR_NOT_FOUND, "NM_PLATFORM_ERROR_NOT_FOUND", "not-found" }, + { NM_PLATFORM_ERROR_EXISTS, "NM_PLATFORM_ERROR_EXISTS", "exists" }, + { NM_PLATFORM_ERROR_WRONG_TYPE, "NM_PLATFORM_ERROR_WRONG_TYPE", "wrong-type" }, + { NM_PLATFORM_ERROR_NOT_SLAVE, "NM_PLATFORM_ERROR_NOT_SLAVE", "not-slave" }, + { NM_PLATFORM_ERROR_NO_FIRMWARE, "NM_PLATFORM_ERROR_NO_FIRMWARE", "no-firmware" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("NMPlatformError"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +nm_platform_reason_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { NM_PLATFORM_REASON_NONE, "NM_PLATFORM_REASON_NONE", "none" }, + { NM_PLATFORM_REASON_INTERNAL, "NM_PLATFORM_REASON_INTERNAL", "internal" }, + { NM_PLATFORM_REASON_EXTERNAL, "NM_PLATFORM_REASON_EXTERNAL", "external" }, + { NM_PLATFORM_REASON_CACHE_CHECK, "NM_PLATFORM_REASON_CACHE_CHECK", "cache-check" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("NMPlatformReason"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +nm_link_type_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { NM_LINK_TYPE_NONE, "NM_LINK_TYPE_NONE", "none" }, + { NM_LINK_TYPE_UNKNOWN, "NM_LINK_TYPE_UNKNOWN", "unknown" }, + { NM_LINK_TYPE_ETHERNET, "NM_LINK_TYPE_ETHERNET", "ethernet" }, + { NM_LINK_TYPE_INFINIBAND, "NM_LINK_TYPE_INFINIBAND", "infiniband" }, + { NM_LINK_TYPE_OLPC_MESH, "NM_LINK_TYPE_OLPC_MESH", "olpc-mesh" }, + { NM_LINK_TYPE_WIFI, "NM_LINK_TYPE_WIFI", "wifi" }, + { NM_LINK_TYPE_WWAN_ETHERNET, "NM_LINK_TYPE_WWAN_ETHERNET", "wwan-ethernet" }, + { NM_LINK_TYPE_WIMAX, "NM_LINK_TYPE_WIMAX", "wimax" }, + { NM_LINK_TYPE_DUMMY, "NM_LINK_TYPE_DUMMY", "dummy" }, + { NM_LINK_TYPE_GRE, "NM_LINK_TYPE_GRE", "gre" }, + { NM_LINK_TYPE_GRETAP, "NM_LINK_TYPE_GRETAP", "gretap" }, + { NM_LINK_TYPE_IFB, "NM_LINK_TYPE_IFB", "ifb" }, + { NM_LINK_TYPE_LOOPBACK, "NM_LINK_TYPE_LOOPBACK", "loopback" }, + { NM_LINK_TYPE_MACVLAN, "NM_LINK_TYPE_MACVLAN", "macvlan" }, + { NM_LINK_TYPE_MACVTAP, "NM_LINK_TYPE_MACVTAP", "macvtap" }, + { NM_LINK_TYPE_OPENVSWITCH, "NM_LINK_TYPE_OPENVSWITCH", "openvswitch" }, + { NM_LINK_TYPE_TAP, "NM_LINK_TYPE_TAP", "tap" }, + { NM_LINK_TYPE_TUN, "NM_LINK_TYPE_TUN", "tun" }, + { NM_LINK_TYPE_VETH, "NM_LINK_TYPE_VETH", "veth" }, + { NM_LINK_TYPE_VLAN, "NM_LINK_TYPE_VLAN", "vlan" }, + { NM_LINK_TYPE_VXLAN, "NM_LINK_TYPE_VXLAN", "vxlan" }, + { NM_LINK_TYPE_BRIDGE, "NM_LINK_TYPE_BRIDGE", "bridge" }, + { NM_LINK_TYPE_BOND, "NM_LINK_TYPE_BOND", "bond" }, + { NM_LINK_TYPE_TEAM, "NM_LINK_TYPE_TEAM", "team" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("NMLinkType"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +nm_platform_signal_change_type_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { NM_PLATFORM_SIGNAL_ADDED, "NM_PLATFORM_SIGNAL_ADDED", "added" }, + { NM_PLATFORM_SIGNAL_CHANGED, "NM_PLATFORM_SIGNAL_CHANGED", "changed" }, + { NM_PLATFORM_SIGNAL_REMOVED, "NM_PLATFORM_SIGNAL_REMOVED", "removed" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("NMPlatformSignalChangeType"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +nm_platform_source_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { NM_PLATFORM_SOURCE_UNKNOWN, "NM_PLATFORM_SOURCE_UNKNOWN", "unknown" }, + { NM_PLATFORM_SOURCE_KERNEL, "NM_PLATFORM_SOURCE_KERNEL", "kernel" }, + { NM_PLATFORM_SOURCE_SHARED, "NM_PLATFORM_SOURCE_SHARED", "shared" }, + { NM_PLATFORM_SOURCE_IP4LL, "NM_PLATFORM_SOURCE_IP4LL", "ip4ll" }, + { NM_PLATFORM_SOURCE_PPP, "NM_PLATFORM_SOURCE_PPP", "ppp" }, + { NM_PLATFORM_SOURCE_WWAN, "NM_PLATFORM_SOURCE_WWAN", "wwan" }, + { NM_PLATFORM_SOURCE_VPN, "NM_PLATFORM_SOURCE_VPN", "vpn" }, + { NM_PLATFORM_SOURCE_DHCP, "NM_PLATFORM_SOURCE_DHCP", "dhcp" }, + { NM_PLATFORM_SOURCE_RDISC, "NM_PLATFORM_SOURCE_RDISC", "rdisc" }, + { NM_PLATFORM_SOURCE_USER, "NM_PLATFORM_SOURCE_USER", "user" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("NMPlatformSource"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +nm_rdisc_dhcp_level_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { NM_RDISC_DHCP_LEVEL_UNKNOWN, "NM_RDISC_DHCP_LEVEL_UNKNOWN", "unknown" }, + { NM_RDISC_DHCP_LEVEL_NONE, "NM_RDISC_DHCP_LEVEL_NONE", "none" }, + { NM_RDISC_DHCP_LEVEL_OTHERCONF, "NM_RDISC_DHCP_LEVEL_OTHERCONF", "otherconf" }, + { NM_RDISC_DHCP_LEVEL_MANAGED, "NM_RDISC_DHCP_LEVEL_MANAGED", "managed" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("NMRDiscDHCPLevel"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +nm_rdisc_preference_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { NM_RDISC_PREFERENCE_INVALID, "NM_RDISC_PREFERENCE_INVALID", "invalid" }, + { NM_RDISC_PREFERENCE_LOW, "NM_RDISC_PREFERENCE_LOW", "low" }, + { NM_RDISC_PREFERENCE_MEDIUM, "NM_RDISC_PREFERENCE_MEDIUM", "medium" }, + { NM_RDISC_PREFERENCE_HIGH, "NM_RDISC_PREFERENCE_HIGH", "high" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("NMRDiscPreference"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +nm_rdisc_config_map_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GFlagsValue values[] = { + { NM_RDISC_CONFIG_DHCP_LEVEL, "NM_RDISC_CONFIG_DHCP_LEVEL", "dhcp-level" }, + { NM_RDISC_CONFIG_GATEWAYS, "NM_RDISC_CONFIG_GATEWAYS", "gateways" }, + { NM_RDISC_CONFIG_ADDRESSES, "NM_RDISC_CONFIG_ADDRESSES", "addresses" }, + { NM_RDISC_CONFIG_ROUTES, "NM_RDISC_CONFIG_ROUTES", "routes" }, + { NM_RDISC_CONFIG_DNS_SERVERS, "NM_RDISC_CONFIG_DNS_SERVERS", "dns-servers" }, + { NM_RDISC_CONFIG_DNS_DOMAINS, "NM_RDISC_CONFIG_DNS_DOMAINS", "dns-domains" }, + { NM_RDISC_CONFIG_HOP_LIMIT, "NM_RDISC_CONFIG_HOP_LIMIT", "hop-limit" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_flags_register_static (g_intern_static_string ("NMRDiscConfigMap"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +nm_ppp_status_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { NM_PPP_STATUS_UNKNOWN, "NM_PPP_STATUS_UNKNOWN", "unknown" }, + { NM_PPP_STATUS_DEAD, "NM_PPP_STATUS_DEAD", "dead" }, + { NM_PPP_STATUS_INITIALIZE, "NM_PPP_STATUS_INITIALIZE", "initialize" }, + { NM_PPP_STATUS_SERIALCONN, "NM_PPP_STATUS_SERIALCONN", "serialconn" }, + { NM_PPP_STATUS_DORMANT, "NM_PPP_STATUS_DORMANT", "dormant" }, + { NM_PPP_STATUS_ESTABLISH, "NM_PPP_STATUS_ESTABLISH", "establish" }, + { NM_PPP_STATUS_AUTHENTICATE, "NM_PPP_STATUS_AUTHENTICATE", "authenticate" }, + { NM_PPP_STATUS_CALLBACK, "NM_PPP_STATUS_CALLBACK", "callback" }, + { NM_PPP_STATUS_NETWORK, "NM_PPP_STATUS_NETWORK", "network" }, + { NM_PPP_STATUS_RUNNING, "NM_PPP_STATUS_RUNNING", "running" }, + { NM_PPP_STATUS_TERMINATE, "NM_PPP_STATUS_TERMINATE", "terminate" }, + { NM_PPP_STATUS_DISCONNECT, "NM_PPP_STATUS_DISCONNECT", "disconnect" }, + { NM_PPP_STATUS_HOLDOFF, "NM_PPP_STATUS_HOLDOFF", "holdoff" }, + { NM_PPP_STATUS_MASTER, "NM_PPP_STATUS_MASTER", "master" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("NMPPPStatus"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +nm_agent_manager_error_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { NM_AGENT_MANAGER_ERROR_SENDER_UNKNOWN, "NM_AGENT_MANAGER_ERROR_SENDER_UNKNOWN", "SenderUnknown" }, + { NM_AGENT_MANAGER_ERROR_PERMISSION_DENIED, "NM_AGENT_MANAGER_ERROR_PERMISSION_DENIED", "PermissionDenied" }, + { NM_AGENT_MANAGER_ERROR_SESSION_NOT_FOUND, "NM_AGENT_MANAGER_ERROR_SESSION_NOT_FOUND", "SessionNotFound" }, + { NM_AGENT_MANAGER_ERROR_INVALID_IDENTIFIER, "NM_AGENT_MANAGER_ERROR_INVALID_IDENTIFIER", "InvalidIdentifier" }, + { NM_AGENT_MANAGER_ERROR_NOT_REGISTERED, "NM_AGENT_MANAGER_ERROR_NOT_REGISTERED", "NotRegistered" }, + { NM_AGENT_MANAGER_ERROR_INTERNAL_ERROR, "NM_AGENT_MANAGER_ERROR_INTERNAL_ERROR", "InternalError" }, + { NM_AGENT_MANAGER_ERROR_NO_SECRETS, "NM_AGENT_MANAGER_ERROR_NO_SECRETS", "NoSecrets" }, + { NM_AGENT_MANAGER_ERROR_USER_CANCELED, "NM_AGENT_MANAGER_ERROR_USER_CANCELED", "UserCanceled" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("NMAgentManagerError"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +nm_secret_agent_capabilities_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { NM_SECRET_AGENT_CAPABILITY_NONE, "NM_SECRET_AGENT_CAPABILITY_NONE", "none" }, + { NM_SECRET_AGENT_CAPABILITY_VPN_HINTS, "NM_SECRET_AGENT_CAPABILITY_VPN_HINTS", "vpn-hints" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("NMSecretAgentCapabilities"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +nm_settings_error_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { NM_SETTINGS_ERROR_GENERAL, "NM_SETTINGS_ERROR_GENERAL", "GeneralError" }, + { NM_SETTINGS_ERROR_INVALID_CONNECTION, "NM_SETTINGS_ERROR_INVALID_CONNECTION", "InvalidConnection" }, + { NM_SETTINGS_ERROR_READ_ONLY_CONNECTION, "NM_SETTINGS_ERROR_READ_ONLY_CONNECTION", "ReadOnlyConnection" }, + { NM_SETTINGS_ERROR_INTERNAL_ERROR, "NM_SETTINGS_ERROR_INTERNAL_ERROR", "InternalError" }, + { NM_SETTINGS_ERROR_SECRETS_UNAVAILABLE, "NM_SETTINGS_ERROR_SECRETS_UNAVAILABLE", "SecretsUnavailable" }, + { NM_SETTINGS_ERROR_SECRETS_REQUEST_CANCELED, "NM_SETTINGS_ERROR_SECRETS_REQUEST_CANCELED", "SecretsRequestCanceled" }, + { NM_SETTINGS_ERROR_PERMISSION_DENIED, "NM_SETTINGS_ERROR_PERMISSION_DENIED", "PermissionDenied" }, + { NM_SETTINGS_ERROR_INVALID_SETTING, "NM_SETTINGS_ERROR_INVALID_SETTING", "InvalidSetting" }, + { NM_SETTINGS_ERROR_ADD_NOT_SUPPORTED, "NM_SETTINGS_ERROR_ADD_NOT_SUPPORTED", "AddNotSupported" }, + { NM_SETTINGS_ERROR_UPDATE_NOT_SUPPORTED, "NM_SETTINGS_ERROR_UPDATE_NOT_SUPPORTED", "UpdateNotSupported" }, + { NM_SETTINGS_ERROR_DELETE_NOT_SUPPORTED, "NM_SETTINGS_ERROR_DELETE_NOT_SUPPORTED", "DeleteNotSupported" }, + { NM_SETTINGS_ERROR_ADD_FAILED, "NM_SETTINGS_ERROR_ADD_FAILED", "AddFailed" }, + { NM_SETTINGS_ERROR_SAVE_HOSTNAME_NOT_SUPPORTED, "NM_SETTINGS_ERROR_SAVE_HOSTNAME_NOT_SUPPORTED", "SaveHostnameNotSupported" }, + { NM_SETTINGS_ERROR_SAVE_HOSTNAME_FAILED, "NM_SETTINGS_ERROR_SAVE_HOSTNAME_FAILED", "SaveHostnameFailed" }, + { NM_SETTINGS_ERROR_HOSTNAME_INVALID, "NM_SETTINGS_ERROR_HOSTNAME_INVALID", "HostnameInvalid" }, + { NM_SETTINGS_ERROR_UUID_EXISTS, "NM_SETTINGS_ERROR_UUID_EXISTS", "UuidExists" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("NMSettingsError"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +nm_system_config_interface_capabilities_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { NM_SYSTEM_CONFIG_INTERFACE_CAP_NONE, "NM_SYSTEM_CONFIG_INTERFACE_CAP_NONE", "none" }, + { NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_CONNECTIONS, "NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_CONNECTIONS", "modify-connections" }, + { NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_HOSTNAME, "NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_HOSTNAME", "modify-hostname" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("NMSystemConfigInterfaceCapabilities"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +nm_system_config_interface_prop_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { NM_SYSTEM_CONFIG_INTERFACE_PROP_FIRST, "NM_SYSTEM_CONFIG_INTERFACE_PROP_FIRST", "first" }, + { NM_SYSTEM_CONFIG_INTERFACE_PROP_NAME, "NM_SYSTEM_CONFIG_INTERFACE_PROP_NAME", "name" }, + { NM_SYSTEM_CONFIG_INTERFACE_PROP_INFO, "NM_SYSTEM_CONFIG_INTERFACE_PROP_INFO", "info" }, + { NM_SYSTEM_CONFIG_INTERFACE_PROP_CAPABILITIES, "NM_SYSTEM_CONFIG_INTERFACE_PROP_CAPABILITIES", "capabilities" }, + { NM_SYSTEM_CONFIG_INTERFACE_PROP_HOSTNAME, "NM_SYSTEM_CONFIG_INTERFACE_PROP_HOSTNAME", "hostname" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("NMSystemConfigInterfaceProp"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +nm_ap_support_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { AP_SUPPORT_UNKNOWN, "AP_SUPPORT_UNKNOWN", "unknown" }, + { AP_SUPPORT_NO, "AP_SUPPORT_NO", "no" }, + { AP_SUPPORT_YES, "AP_SUPPORT_YES", "yes" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("ApSupport"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +nm_opt_type_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { TYPE_INVALID, "TYPE_INVALID", "invalid" }, + { TYPE_INT, "TYPE_INT", "int" }, + { TYPE_BYTES, "TYPE_BYTES", "bytes" }, + { TYPE_UTF8, "TYPE_UTF8", "utf8" }, + { TYPE_KEYWORD, "TYPE_KEYWORD", "keyword" }, + { TYPE_STRING, "TYPE_STRING", "string" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("OptType"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +nm_vpn_manager_error_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { NM_VPN_MANAGER_ERROR_DEVICE_NOT_ACTIVE, "NM_VPN_MANAGER_ERROR_DEVICE_NOT_ACTIVE", "BaseDeviceNotActive" }, + { NM_VPN_MANAGER_ERROR_CONNECTION_INVALID, "NM_VPN_MANAGER_ERROR_CONNECTION_INVALID", "ConnectionInvalid" }, + { NM_VPN_MANAGER_ERROR_SERVICE_INVALID, "NM_VPN_MANAGER_ERROR_SERVICE_INVALID", "ServiceInvalid" }, + { NM_VPN_MANAGER_ERROR_SERVICE_START_FAILED, "NM_VPN_MANAGER_ERROR_SERVICE_START_FAILED", "ServiceStartFailed" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("NMVPNManagerError"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +nm_dcb_error_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { NM_DCB_ERROR_UNKNOWN, "NM_DCB_ERROR_UNKNOWN", "unknown" }, + { NM_DCB_ERROR_INTERNAL, "NM_DCB_ERROR_INTERNAL", "internal" }, + { NM_DCB_ERROR_BAD_CONFIG, "NM_DCB_ERROR_BAD_CONFIG", "bad-config" }, + { NM_DCB_ERROR_HELPER_NOT_FOUND, "NM_DCB_ERROR_HELPER_NOT_FOUND", "helper-not-found" }, + { NM_DCB_ERROR_HELPER_FAILED, "NM_DCB_ERROR_HELPER_FAILED", "helper-failed" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("NMDcbError"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +nm_dispatcher_action_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { DISPATCHER_ACTION_HOSTNAME, "DISPATCHER_ACTION_HOSTNAME", "hostname" }, + { DISPATCHER_ACTION_PRE_UP, "DISPATCHER_ACTION_PRE_UP", "pre-up" }, + { DISPATCHER_ACTION_UP, "DISPATCHER_ACTION_UP", "up" }, + { DISPATCHER_ACTION_PRE_DOWN, "DISPATCHER_ACTION_PRE_DOWN", "pre-down" }, + { DISPATCHER_ACTION_DOWN, "DISPATCHER_ACTION_DOWN", "down" }, + { DISPATCHER_ACTION_VPN_PRE_UP, "DISPATCHER_ACTION_VPN_PRE_UP", "vpn-pre-up" }, + { DISPATCHER_ACTION_VPN_UP, "DISPATCHER_ACTION_VPN_UP", "vpn-up" }, + { DISPATCHER_ACTION_VPN_PRE_DOWN, "DISPATCHER_ACTION_VPN_PRE_DOWN", "vpn-pre-down" }, + { DISPATCHER_ACTION_VPN_DOWN, "DISPATCHER_ACTION_VPN_DOWN", "vpn-down" }, + { DISPATCHER_ACTION_DHCP4_CHANGE, "DISPATCHER_ACTION_DHCP4_CHANGE", "dhcp4-change" }, + { DISPATCHER_ACTION_DHCP6_CHANGE, "DISPATCHER_ACTION_DHCP6_CHANGE", "dhcp6-change" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("DispatcherAction"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +nm_auth_call_result_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { NM_AUTH_CALL_RESULT_UNKNOWN, "NM_AUTH_CALL_RESULT_UNKNOWN", "unknown" }, + { NM_AUTH_CALL_RESULT_YES, "NM_AUTH_CALL_RESULT_YES", "yes" }, + { NM_AUTH_CALL_RESULT_AUTH, "NM_AUTH_CALL_RESULT_AUTH", "auth" }, + { NM_AUTH_CALL_RESULT_NO, "NM_AUTH_CALL_RESULT_NO", "no" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("NMAuthCallResult"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +nm_manager_error_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { NM_MANAGER_ERROR_UNKNOWN_CONNECTION, "NM_MANAGER_ERROR_UNKNOWN_CONNECTION", "UnknownConnection" }, + { NM_MANAGER_ERROR_UNKNOWN_DEVICE, "NM_MANAGER_ERROR_UNKNOWN_DEVICE", "UnknownDevice" }, + { NM_MANAGER_ERROR_UNMANAGED_DEVICE, "NM_MANAGER_ERROR_UNMANAGED_DEVICE", "UnmanagedDevice" }, + { NM_MANAGER_ERROR_SYSTEM_CONNECTION, "NM_MANAGER_ERROR_SYSTEM_CONNECTION", "SystemConnection" }, + { NM_MANAGER_ERROR_PERMISSION_DENIED, "NM_MANAGER_ERROR_PERMISSION_DENIED", "PermissionDenied" }, + { NM_MANAGER_ERROR_CONNECTION_NOT_ACTIVE, "NM_MANAGER_ERROR_CONNECTION_NOT_ACTIVE", "ConnectionNotActive" }, + { NM_MANAGER_ERROR_ALREADY_ASLEEP_OR_AWAKE, "NM_MANAGER_ERROR_ALREADY_ASLEEP_OR_AWAKE", "AlreadyAsleepOrAwake" }, + { NM_MANAGER_ERROR_ALREADY_ENABLED_OR_DISABLED, "NM_MANAGER_ERROR_ALREADY_ENABLED_OR_DISABLED", "AlreadyEnabledOrDisabled" }, + { NM_MANAGER_ERROR_UNSUPPORTED_CONNECTION_TYPE, "NM_MANAGER_ERROR_UNSUPPORTED_CONNECTION_TYPE", "UnsupportedConnectionType" }, + { NM_MANAGER_ERROR_DEPENDENCY_FAILED, "NM_MANAGER_ERROR_DEPENDENCY_FAILED", "DependencyFailed" }, + { NM_MANAGER_ERROR_AUTOCONNECT_NOT_ALLOWED, "NM_MANAGER_ERROR_AUTOCONNECT_NOT_ALLOWED", "AutoconnectNotAllowed" }, + { NM_MANAGER_ERROR_CONNECTION_ALREADY_ACTIVE, "NM_MANAGER_ERROR_CONNECTION_ALREADY_ACTIVE", "ConnectionAlreadyActive" }, + { NM_MANAGER_ERROR_INTERNAL, "NM_MANAGER_ERROR_INTERNAL", "Internal" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("NMManagerError"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +nm_rf_kill_state_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { RFKILL_UNBLOCKED, "RFKILL_UNBLOCKED", "unblocked" }, + { RFKILL_SOFT_BLOCKED, "RFKILL_SOFT_BLOCKED", "soft-blocked" }, + { RFKILL_HARD_BLOCKED, "RFKILL_HARD_BLOCKED", "hard-blocked" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("RfKillState"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +nm_rf_kill_type_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { RFKILL_TYPE_WLAN, "RFKILL_TYPE_WLAN", "wlan" }, + { RFKILL_TYPE_WWAN, "RFKILL_TYPE_WWAN", "wwan" }, + { RFKILL_TYPE_WIMAX, "RFKILL_TYPE_WIMAX", "wimax" }, + { RFKILL_TYPE_UNKNOWN, "RFKILL_TYPE_UNKNOWN", "unknown" }, + { RFKILL_TYPE_MAX, "RFKILL_TYPE_MAX", "max" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("RfKillType"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +nm_session_monitor_error_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { NM_SESSION_MONITOR_ERROR_IO_ERROR, "NM_SESSION_MONITOR_ERROR_IO_ERROR", "IOError" }, + { NM_SESSION_MONITOR_ERROR_MALFORMED_DATABASE, "NM_SESSION_MONITOR_ERROR_MALFORMED_DATABASE", "MalformedDatabase" }, + { NM_SESSION_MONITOR_ERROR_UNKNOWN_USER, "NM_SESSION_MONITOR_ERROR_UNKNOWN_USER", "UnknownUser" }, + { NM_SESSION_MONITOR_ERROR_NO_DATABASE, "NM_SESSION_MONITOR_ERROR_NO_DATABASE", "NoDatabase" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("NMSessionMonitorError"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +nm_wimax_error_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { NM_WIMAX_ERROR_CONNECTION_NOT_WIMAX, "NM_WIMAX_ERROR_CONNECTION_NOT_WIMAX", "ConnectionNotWimax" }, + { NM_WIMAX_ERROR_CONNECTION_INVALID, "NM_WIMAX_ERROR_CONNECTION_INVALID", "ConnectionInvalid" }, + { NM_WIMAX_ERROR_CONNECTION_INCOMPATIBLE, "NM_WIMAX_ERROR_CONNECTION_INCOMPATIBLE", "ConnectionIncompatible" }, + { NM_WIMAX_ERROR_NSP_NOT_FOUND, "NM_WIMAX_ERROR_NSP_NOT_FOUND", "NspNotFound" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("NMWimaxError"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} + + + diff --git a/src/nm-enum-types.h b/src/nm-enum-types.h new file mode 100644 index 00000000..2bf6c734 --- /dev/null +++ b/src/nm-enum-types.h @@ -0,0 +1,99 @@ + + + +/* Generated by glib-mkenums. Do not edit */ + +#ifndef __NM_ENUM_TYPES_H__ +#define __NM_ENUM_TYPES_H__ + +#include + +G_BEGIN_DECLS +GType nm_device_error_get_type (void) G_GNUC_CONST; +#define NM_TYPE_DEVICE_ERROR (nm_device_error_get_type ()) +GType nm_unmanaged_flags_get_type (void) G_GNUC_CONST; +#define NM_TYPE_UNMANAGED_FLAGS (nm_unmanaged_flags_get_type ()) +GType nm_bond_error_get_type (void) G_GNUC_CONST; +#define NM_TYPE_BOND_ERROR (nm_bond_error_get_type ()) +GType nm_bridge_error_get_type (void) G_GNUC_CONST; +#define NM_TYPE_BRIDGE_ERROR (nm_bridge_error_get_type ()) +GType nm_ethernet_error_get_type (void) G_GNUC_CONST; +#define NM_TYPE_ETHERNET_ERROR (nm_ethernet_error_get_type ()) +GType nm_device_generic_error_get_type (void) G_GNUC_CONST; +#define NM_TYPE_DEVICE_GENERIC_ERROR (nm_device_generic_error_get_type ()) +GType nm_infiniband_error_get_type (void) G_GNUC_CONST; +#define NM_TYPE_INFINIBAND_ERROR (nm_infiniband_error_get_type ()) +GType nm_team_error_get_type (void) G_GNUC_CONST; +#define NM_TYPE_TEAM_ERROR (nm_team_error_get_type ()) +GType nm_vlan_error_get_type (void) G_GNUC_CONST; +#define NM_TYPE_VLAN_ERROR (nm_vlan_error_get_type ()) +GType nm_dhcp_state_get_type (void) G_GNUC_CONST; +#define NM_TYPE_DHCP_STATE (nm_dhcp_state_get_type ()) +GType nm_dhcp_manager_error_get_type (void) G_GNUC_CONST; +#define NM_TYPE_DHCP_MANAGER_ERROR (nm_dhcp_manager_error_get_type ()) +GType nm_dns_manager_error_get_type (void) G_GNUC_CONST; +#define NM_TYPE_DNS_MANAGER_ERROR (nm_dns_manager_error_get_type ()) +GType nm_dns_ip_config_type_get_type (void) G_GNUC_CONST; +#define NM_TYPE_DNS_IP_CONFIG_TYPE (nm_dns_ip_config_type_get_type ()) +GType nm_dns_manager_resolv_conf_mode_get_type (void) G_GNUC_CONST; +#define NM_TYPE_DNS_MANAGER_RESOLV_CONF_MODE (nm_dns_manager_resolv_conf_mode_get_type ()) +GType nm_dns_masq_status_get_type (void) G_GNUC_CONST; +#define NM_TYPE_DNS_MASQ_STATUS (nm_dns_masq_status_get_type ()) +GType nm_logging_error_get_type (void) G_GNUC_CONST; +#define NM_TYPE_LOGGING_ERROR (nm_logging_error_get_type ()) +GType nm_platform_error_get_type (void) G_GNUC_CONST; +#define NM_TYPE_PLATFORM_ERROR (nm_platform_error_get_type ()) +GType nm_platform_reason_get_type (void) G_GNUC_CONST; +#define NM_TYPE_PLATFORM_REASON (nm_platform_reason_get_type ()) +GType nm_link_type_get_type (void) G_GNUC_CONST; +#define NM_TYPE_LINK_TYPE (nm_link_type_get_type ()) +GType nm_platform_signal_change_type_get_type (void) G_GNUC_CONST; +#define NM_TYPE_PLATFORM_SIGNAL_CHANGE_TYPE (nm_platform_signal_change_type_get_type ()) +GType nm_platform_source_get_type (void) G_GNUC_CONST; +#define NM_TYPE_PLATFORM_SOURCE (nm_platform_source_get_type ()) +GType nm_rdisc_dhcp_level_get_type (void) G_GNUC_CONST; +#define NM_TYPE_RDISC_DHCP_LEVEL (nm_rdisc_dhcp_level_get_type ()) +GType nm_rdisc_preference_get_type (void) G_GNUC_CONST; +#define NM_TYPE_RDISC_PREFERENCE (nm_rdisc_preference_get_type ()) +GType nm_rdisc_config_map_get_type (void) G_GNUC_CONST; +#define NM_TYPE_RDISC_CONFIG_MAP (nm_rdisc_config_map_get_type ()) +GType nm_ppp_status_get_type (void) G_GNUC_CONST; +#define NM_TYPE_PPP_STATUS (nm_ppp_status_get_type ()) +GType nm_agent_manager_error_get_type (void) G_GNUC_CONST; +#define NM_TYPE_AGENT_MANAGER_ERROR (nm_agent_manager_error_get_type ()) +GType nm_secret_agent_capabilities_get_type (void) G_GNUC_CONST; +#define NM_TYPE_SECRET_AGENT_CAPABILITIES (nm_secret_agent_capabilities_get_type ()) +GType nm_settings_error_get_type (void) G_GNUC_CONST; +#define NM_TYPE_SETTINGS_ERROR (nm_settings_error_get_type ()) +GType nm_system_config_interface_capabilities_get_type (void) G_GNUC_CONST; +#define NM_TYPE_SYSTEM_CONFIG_INTERFACE_CAPABILITIES (nm_system_config_interface_capabilities_get_type ()) +GType nm_system_config_interface_prop_get_type (void) G_GNUC_CONST; +#define NM_TYPE_SYSTEM_CONFIG_INTERFACE_PROP (nm_system_config_interface_prop_get_type ()) +GType nm_ap_support_get_type (void) G_GNUC_CONST; +#define NM_TYPE_AP_SUPPORT (nm_ap_support_get_type ()) +GType nm_opt_type_get_type (void) G_GNUC_CONST; +#define NM_TYPE_OPT_TYPE (nm_opt_type_get_type ()) +GType nm_vpn_manager_error_get_type (void) G_GNUC_CONST; +#define NM_TYPE_VPN_MANAGER_ERROR (nm_vpn_manager_error_get_type ()) +GType nm_dcb_error_get_type (void) G_GNUC_CONST; +#define NM_TYPE_DCB_ERROR (nm_dcb_error_get_type ()) +GType nm_dispatcher_action_get_type (void) G_GNUC_CONST; +#define NM_TYPE_DISPATCHER_ACTION (nm_dispatcher_action_get_type ()) +GType nm_auth_call_result_get_type (void) G_GNUC_CONST; +#define NM_TYPE_AUTH_CALL_RESULT (nm_auth_call_result_get_type ()) +GType nm_manager_error_get_type (void) G_GNUC_CONST; +#define NM_TYPE_MANAGER_ERROR (nm_manager_error_get_type ()) +GType nm_rf_kill_state_get_type (void) G_GNUC_CONST; +#define NM_TYPE_RF_KILL_STATE (nm_rf_kill_state_get_type ()) +GType nm_rf_kill_type_get_type (void) G_GNUC_CONST; +#define NM_TYPE_RF_KILL_TYPE (nm_rf_kill_type_get_type ()) +GType nm_session_monitor_error_get_type (void) G_GNUC_CONST; +#define NM_TYPE_SESSION_MONITOR_ERROR (nm_session_monitor_error_get_type ()) +GType nm_wimax_error_get_type (void) G_GNUC_CONST; +#define NM_TYPE_WIMAX_ERROR (nm_wimax_error_get_type ()) +G_END_DECLS + +#endif /* __NM_ENUM_TYPES_H__ */ + + + diff --git a/src/nm-hostname-provider.c b/src/nm-hostname-provider.c deleted file mode 100644 index 1cd1ca6c..00000000 --- a/src/nm-hostname-provider.c +++ /dev/null @@ -1,54 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2009 Novell, Inc. - */ - -#include "nm-hostname-provider.h" - -const char * -nm_hostname_provider_get_hostname (NMHostnameProvider *self) -{ - g_return_val_if_fail (NM_IS_HOSTNAME_PROVIDER (self), NULL); - - return NM_HOSTNAME_PROVIDER_GET_INTERFACE (self)->get_hostname (self); -} - -GType -nm_hostname_provider_get_type (void) -{ - static GType type = 0; - - if (!G_UNLIKELY (type)) { - const GTypeInfo type_info = { - sizeof (NMHostnameProvider), /* class_size */ - NULL, /* base_init */ - NULL, /* base_finalize */ - NULL, - NULL, /* class_finalize */ - NULL, /* class_data */ - 0, - 0, /* n_preallocs */ - NULL - }; - - type = g_type_register_static (G_TYPE_INTERFACE, "NMHostnameProvider", &type_info, 0); - g_type_interface_add_prerequisite (type, G_TYPE_OBJECT); - } - - return type; -} diff --git a/src/nm-hostname-provider.h b/src/nm-hostname-provider.h deleted file mode 100644 index 7fe5c006..00000000 --- a/src/nm-hostname-provider.h +++ /dev/null @@ -1,44 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2009 Novell, Inc. - */ - -#ifndef NM_HOSTNAME_PROVIDER_H -#define NM_HOSTNAME_PROVIDER_H - -#include - -#define NM_TYPE_HOSTNAME_PROVIDER (nm_hostname_provider_get_type ()) -#define NM_HOSTNAME_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_HOSTNAME_PROVIDER, NMHostnameProvider)) -#define NM_IS_HOSTNAME_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_HOSTNAME_PROVIDER)) -#define NM_HOSTNAME_PROVIDER_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), NM_TYPE_HOSTNAME_PROVIDER, NMHostnameProvider)) - -typedef struct _NMHostnameProvider NMHostnameProvider; - -struct _NMHostnameProvider { - GTypeInterface g_iface; - - /* Methods */ - const char *(*get_hostname) (NMHostnameProvider *self); -}; - -GType nm_hostname_provider_get_type (void); - -const char *nm_hostname_provider_get_hostname (NMHostnameProvider *self); - -#endif /* NM_HOSTNAME_PROVIDER_H */ diff --git a/src/nm-ip4-config-glue.h b/src/nm-ip4-config-glue.h new file mode 100644 index 00000000..738dff92 --- /dev/null +++ b/src/nm-ip4-config-glue.h @@ -0,0 +1,73 @@ +/* Generated by dbus-binding-tool; do not edit! */ + + +#ifndef __dbus_glib_marshal_nm_ip4_config_MARSHAL_H__ +#define __dbus_glib_marshal_nm_ip4_config_MARSHAL_H__ + +#include + +G_BEGIN_DECLS + +#ifdef G_ENABLE_DEBUG +#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v) +#define g_marshal_value_peek_char(v) g_value_get_schar (v) +#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v) +#define g_marshal_value_peek_int(v) g_value_get_int (v) +#define g_marshal_value_peek_uint(v) g_value_get_uint (v) +#define g_marshal_value_peek_long(v) g_value_get_long (v) +#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v) +#define g_marshal_value_peek_int64(v) g_value_get_int64 (v) +#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v) +#define g_marshal_value_peek_enum(v) g_value_get_enum (v) +#define g_marshal_value_peek_flags(v) g_value_get_flags (v) +#define g_marshal_value_peek_float(v) g_value_get_float (v) +#define g_marshal_value_peek_double(v) g_value_get_double (v) +#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v) +#define g_marshal_value_peek_param(v) g_value_get_param (v) +#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v) +#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v) +#define g_marshal_value_peek_object(v) g_value_get_object (v) +#define g_marshal_value_peek_variant(v) g_value_get_variant (v) +#else /* !G_ENABLE_DEBUG */ +/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API. + * Do not access GValues directly in your code. Instead, use the + * g_value_get_*() functions + */ +#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int +#define g_marshal_value_peek_char(v) (v)->data[0].v_int +#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint +#define g_marshal_value_peek_int(v) (v)->data[0].v_int +#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint +#define g_marshal_value_peek_long(v) (v)->data[0].v_long +#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 +#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 +#define g_marshal_value_peek_enum(v) (v)->data[0].v_long +#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_float(v) (v)->data[0].v_float +#define g_marshal_value_peek_double(v) (v)->data[0].v_double +#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer +#endif /* !G_ENABLE_DEBUG */ + + +G_END_DECLS + +#endif /* __dbus_glib_marshal_nm_ip4_config_MARSHAL_H__ */ + +#include +static const DBusGMethodInfo dbus_glib_nm_ip4_config_methods[] = { +}; + +const DBusGObjectInfo dbus_glib_nm_ip4_config_object_info = { 1, + dbus_glib_nm_ip4_config_methods, + 0, +"\0", +"org.freedesktop.NetworkManager.IP4Config\0PropertiesChanged\0\0", +"org.freedesktop.NetworkManager.IP4Config\0Gateway\0gateway\0read\0org.freedesktop.NetworkManager.IP4Config\0Addresses\0addresses\0read\0org.freedesktop.NetworkManager.IP4Config\0Routes\0routes\0read\0org.freedesktop.NetworkManager.IP4Config\0Nameservers\0nameservers\0read\0org.freedesktop.NetworkManager.IP4Config\0Domains\0domains\0read\0org.freedesktop.NetworkManager.IP4Config\0Searches\0searches\0read\0org.freedesktop.NetworkManager.IP4Config\0WinsServers\0wins_servers\0read\0\0" +}; + diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c index 0722981e..e27c0436 100644 --- a/src/nm-ip4-config.c +++ b/src/nm-ip4-config.c @@ -1,5 +1,5 @@ /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager +/* NetworkManager * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -15,27 +15,22 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright (C) 2005 - 2008 Red Hat, Inc. + * Copyright (C) 2005 - 2014 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. */ -#include -#include #include -#include "nm-ip4-config.h" -#include "nm-dbus-manager.h" -#include "NetworkManager.h" -#include "NetworkManagerUtils.h" -#include "nm-setting-ip4-config.h" -#include "nm-utils.h" -#include -#include -#include +#include "nm-ip4-config.h" -#include "nm-ip4-config-glue.h" +#include "libgsystem.h" +#include "nm-platform.h" +#include "nm-utils.h" +#include "nm-dbus-manager.h" #include "nm-dbus-glib-types.h" - +#include "nm-ip4-config-glue.h" +#include "NetworkManagerUtils.h" +#include "nm-utils-private.h" G_DEFINE_TYPE (NMIP4Config, nm_ip4_config, G_TYPE_OBJECT) @@ -44,774 +39,1486 @@ G_DEFINE_TYPE (NMIP4Config, nm_ip4_config, G_TYPE_OBJECT) typedef struct { char *path; - GSList *addresses; - guint32 ptp_address; - - guint32 mtu; /* Maximum Transmission Unit of the interface */ - guint32 mss; /* Maximum Segment Size of the route */ - + gboolean never_default; + guint32 gateway; + GArray *addresses; + GArray *routes; GArray *nameservers; GPtrArray *domains; GPtrArray *searches; - - GArray *wins; - + guint32 mss; GArray *nis; - char * nis_domain; - - GSList *routes; - - gboolean never_default; + char *nis_domain; + GArray *wins; + guint32 mtu; } NMIP4ConfigPrivate; +/* internal guint32 are assigned to gobject properties of type uint. Ensure, that uint is large enough */ +G_STATIC_ASSERT (sizeof (uint) >= sizeof (guint32)); +G_STATIC_ASSERT (G_MAXUINT >= 0xFFFFFFFF); enum { PROP_0, + PROP_GATEWAY, PROP_ADDRESSES, + PROP_ROUTES, PROP_NAMESERVERS, PROP_DOMAINS, - PROP_ROUTES, + PROP_SEARCHES, PROP_WINS_SERVERS, LAST_PROP }; +static GParamSpec *obj_properties[LAST_PROP] = { NULL, }; +#define _NOTIFY(config, prop) G_STMT_START { g_object_notify_by_pspec (G_OBJECT (config), obj_properties[prop]); } G_STMT_END -static struct nl_addr * -nm_utils_ip4_addr_to_nl_addr (guint32 ip4_addr) +NMIP4Config * +nm_ip4_config_new (void) { - struct nl_addr * nla = NULL; + return (NMIP4Config *) g_object_new (NM_TYPE_IP4_CONFIG, NULL); +} - if (!(nla = nl_addr_alloc (sizeof (in_addr_t)))) - return NULL; - nl_addr_set_family (nla, AF_INET); - nl_addr_set_binary_addr (nla, &ip4_addr, sizeof (guint32)); - return nla; +void +nm_ip4_config_export (NMIP4Config *config) +{ + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); + static guint32 counter = 0; + + if (!priv->path) { + priv->path = g_strdup_printf (NM_DBUS_PATH "/IP4Config/%d", counter++); + nm_dbus_manager_register_object (nm_dbus_manager_get (), priv->path, config); + } } +const char * +nm_ip4_config_get_dbus_path (const NMIP4Config *config) +{ + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); + + return priv->path; +} -NMIP4Config * -nm_ip4_config_new (void) +static gboolean +same_prefix (guint32 address1, guint32 address2, int plen) { - return (NMIP4Config *) g_object_new (NM_TYPE_IP4_CONFIG, NULL); + guint32 masked1 = ntohl (address1) >> (32 - plen); + guint32 masked2 = ntohl (address2) >> (32 - plen); + + return masked1 == masked2; } -void -nm_ip4_config_export (NMIP4Config *config) +/******************************************************************/ + +/** + * nm_ip4_config_capture_resolv_conf(): + * @nameservers: array of guint32 + * @rc_contents: the contents of a resolv.conf or %NULL to read /etc/resolv.conf + * + * Reads all resolv.conf IPv4 nameservers and adds them to @nameservers. + * + * Returns: %TRUE if nameservers were added, %FALSE if @nameservers is unchanged + */ +gboolean +nm_ip4_config_capture_resolv_conf (GArray *nameservers, + const char *rc_contents) { + GPtrArray *read_ns; + guint i, j; + gboolean changed = FALSE; + + g_return_val_if_fail (nameservers != NULL, FALSE); + + read_ns = nm_utils_read_resolv_conf_nameservers (rc_contents); + if (!read_ns) + return FALSE; + + for (i = 0; i < read_ns->len; i++) { + const char *s = g_ptr_array_index (read_ns, i); + guint32 ns = 0; + + if (!inet_pton (AF_INET, s, (void *) &ns) || !ns) + continue; + + /* Ignore duplicates */ + for (j = 0; j < nameservers->len; j++) { + if (g_array_index (nameservers, guint32, j) == ns) + break; + } + + if (j == nameservers->len) { + g_array_append_val (nameservers, ns); + changed = TRUE; + } + } + + g_ptr_array_unref (read_ns); + return changed; +} + +static gboolean +addresses_are_duplicate (const NMPlatformIP4Address *a, const NMPlatformIP4Address *b, gboolean consider_plen) +{ + return a->address == b->address && (!consider_plen || a->plen == b->plen); +} + +static gboolean +routes_are_duplicate (const NMPlatformIP4Route *a, const NMPlatformIP4Route *b, gboolean consider_gateway_and_metric) +{ + return a->network == b->network && a->plen == b->plen && + (!consider_gateway_and_metric || (a->gateway == b->gateway && a->metric == b->metric)); +} + +NMIP4Config * +nm_ip4_config_capture (int ifindex, gboolean capture_resolv_conf) +{ + NMIP4Config *config; NMIP4ConfigPrivate *priv; - NMDBusManager *dbus_mgr; - DBusGConnection *connection; - static guint32 counter = 0; + guint i; + guint lowest_metric = G_MAXUINT; + guint32 old_gateway = 0; + gboolean has_gateway = FALSE; - g_return_if_fail (NM_IS_IP4_CONFIG (config)); + /* Slaves have no IP configuration */ + if (nm_platform_link_get_master (ifindex) > 0) + return NULL; + config = nm_ip4_config_new (); priv = NM_IP4_CONFIG_GET_PRIVATE (config); - g_return_if_fail (priv->path == NULL); - dbus_mgr = nm_dbus_manager_get (); - connection = nm_dbus_manager_get_connection (dbus_mgr); - priv->path = g_strdup_printf (NM_DBUS_PATH "/IP4Config/%d", counter++); + g_array_unref (priv->addresses); + g_array_unref (priv->routes); + + priv->addresses = nm_platform_ip4_address_get_all (ifindex); + priv->routes = nm_platform_ip4_route_get_all (ifindex, TRUE); + + /* Extract gateway from default route */ + old_gateway = priv->gateway; + for (i = 0; i < priv->routes->len; i++) { + const NMPlatformIP4Route *route = &g_array_index (priv->routes, NMPlatformIP4Route, i); + + if (route->network == 0) { + if (route->metric < lowest_metric) { + priv->gateway = route->gateway; + lowest_metric = route->metric; + } + has_gateway = TRUE; + /* Remove the default route from the list */ + g_array_remove_index (priv->routes, i); + i--; + } + } + + /* If there is a host route to the gateway, ignore that route. It is + * automatically added by NetworkManager when needed. + */ + if (has_gateway) { + for (i = 0; i < priv->routes->len; i++) { + const NMPlatformIP4Route *route = &g_array_index (priv->routes, NMPlatformIP4Route, i); + + if ( (route->plen == 32) + && (route->network == priv->gateway) + && (route->gateway == 0)) { + g_array_remove_index (priv->routes, i); + i--; + } + } + } + + /* If the interface has the default route, and has IPv4 addresses, capture + * nameservers from /etc/resolv.conf. + */ + if (priv->addresses->len && has_gateway && capture_resolv_conf) { + if (nm_ip4_config_capture_resolv_conf (priv->nameservers, NULL)) + _NOTIFY (config, PROP_NAMESERVERS); + } + + /* actually, nobody should be connected to the signal, just to be sure, notify */ + _NOTIFY (config, PROP_ADDRESSES); + _NOTIFY (config, PROP_ROUTES); + if (priv->gateway != old_gateway) + _NOTIFY (config, PROP_GATEWAY); - dbus_g_connection_register_g_object (connection, priv->path, G_OBJECT (config)); - g_object_unref (dbus_mgr); + return config; } -const char * -nm_ip4_config_get_dbus_path (NMIP4Config *config) +gboolean +nm_ip4_config_commit (const NMIP4Config *config, int ifindex) { - g_return_val_if_fail (NM_IS_IP4_CONFIG (config), NULL); + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); + int mtu = nm_ip4_config_get_mtu (config); + int i; + + g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail (config != NULL, FALSE); + + /* Addresses */ + nm_platform_ip4_address_sync (ifindex, priv->addresses); + + /* Routes */ + { + int count = nm_ip4_config_get_num_routes (config); + GArray *routes = g_array_sized_new (FALSE, FALSE, sizeof (NMPlatformIP4Route), count); + NMPlatformIP4Route route; + gboolean success; - return NM_IP4_CONFIG_GET_PRIVATE (config)->path; + for (i = 0; i < count; i++) { + memcpy (&route, nm_ip4_config_get_route (config, i), sizeof (route)); + + /* Don't add the route if it's more specific than one of the subnets + * the device already has an IP address on. + */ + if ( route.gateway == 0 + && nm_ip4_config_destination_is_direct (config, route.network, route.plen)) + continue; + + /* Don't add the default route if the connection + * is never supposed to be the default connection. + */ + if (nm_ip4_config_get_never_default (config) && route.network == 0) + continue; + + g_array_append_val (routes, route); + } + + success = nm_platform_ip4_route_sync (ifindex, routes); + g_array_unref (routes); + if (!success) + return FALSE; + } + + /* MTU */ + if (mtu && mtu != nm_platform_link_get_mtu (ifindex)) + nm_platform_link_set_mtu (ifindex, mtu); + + return TRUE; } void -nm_ip4_config_take_address (NMIP4Config *config, NMIP4Address *address) +nm_ip4_config_merge_setting (NMIP4Config *config, NMSettingIP4Config *setting, int default_route_metric) { - NMIP4ConfigPrivate *priv; + guint naddresses, nroutes, nnameservers, nsearches; + int i; - g_return_if_fail (NM_IS_IP4_CONFIG (config)); - g_return_if_fail (address != NULL); + if (!setting) + return; - priv = NM_IP4_CONFIG_GET_PRIVATE (config); - priv->addresses = g_slist_append (priv->addresses, address); + g_object_freeze_notify (G_OBJECT (config)); + + naddresses = nm_setting_ip4_config_get_num_addresses (setting); + nroutes = nm_setting_ip4_config_get_num_routes (setting); + nnameservers = nm_setting_ip4_config_get_num_dns (setting); + nsearches = nm_setting_ip4_config_get_num_dns_searches (setting); + + /* Gateway */ + if (nm_setting_ip4_config_get_never_default (setting)) + nm_ip4_config_set_never_default (config, TRUE); + else if (nm_setting_ip4_config_get_ignore_auto_routes (setting)) + nm_ip4_config_set_never_default (config, FALSE); + for (i = 0; i < naddresses; i++) { + guint32 gateway = nm_ip4_address_get_gateway (nm_setting_ip4_config_get_address (setting, i)); + + if (gateway) { + nm_ip4_config_set_gateway (config, gateway); + break; + } + } + + /* Addresses */ + for (i = 0; i < naddresses; i++) { + NMIP4Address *s_addr = nm_setting_ip4_config_get_address (setting, i); + const char *label = NM_UTILS_PRIVATE_CALL (nm_setting_ip4_config_get_address_label (setting, i)); + NMPlatformIP4Address address; + + memset (&address, 0, sizeof (address)); + address.address = nm_ip4_address_get_address (s_addr); + address.plen = nm_ip4_address_get_prefix (s_addr); + address.lifetime = NM_PLATFORM_LIFETIME_PERMANENT; + address.preferred = NM_PLATFORM_LIFETIME_PERMANENT; + address.source = NM_PLATFORM_SOURCE_USER; + if (label) + g_strlcpy (address.label, label, sizeof (address.label)); + + nm_ip4_config_add_address (config, &address); + } + + /* Routes */ + if (nm_setting_ip4_config_get_ignore_auto_routes (setting)) + nm_ip4_config_reset_routes (config); + for (i = 0; i < nroutes; i++) { + NMIP4Route *s_route = nm_setting_ip4_config_get_route (setting, i); + NMPlatformIP4Route route; + + memset (&route, 0, sizeof (route)); + route.network = nm_ip4_route_get_dest (s_route); + route.plen = nm_ip4_route_get_prefix (s_route); + route.gateway = nm_ip4_route_get_next_hop (s_route); + route.metric = nm_ip4_route_get_metric (s_route); + if (!route.metric) + route.metric = default_route_metric; + route.source = NM_PLATFORM_SOURCE_USER; + + nm_ip4_config_add_route (config, &route); + } + + /* DNS */ + if (nm_setting_ip4_config_get_ignore_auto_dns (setting)) { + nm_ip4_config_reset_nameservers (config); + nm_ip4_config_reset_domains (config); + nm_ip4_config_reset_searches (config); + } + for (i = 0; i < nnameservers; i++) + nm_ip4_config_add_nameserver (config, nm_setting_ip4_config_get_dns (setting, i)); + for (i = 0; i < nsearches; i++) + nm_ip4_config_add_search (config, nm_setting_ip4_config_get_dns_search (setting, i)); + + g_object_thaw_notify (G_OBJECT (config)); +} + +NMSetting * +nm_ip4_config_create_setting (const NMIP4Config *config) +{ + NMSettingIP4Config *s_ip4; + guint32 gateway; + guint naddresses, nroutes, nnameservers, nsearches; + const char *method = NULL; + int i; + + s_ip4 = NM_SETTING_IP4_CONFIG (nm_setting_ip4_config_new ()); + + if (!config) { + g_object_set (s_ip4, + NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_DISABLED, + NULL); + return NM_SETTING (s_ip4); + } + + gateway = nm_ip4_config_get_gateway (config); + naddresses = nm_ip4_config_get_num_addresses (config); + nroutes = nm_ip4_config_get_num_routes (config); + nnameservers = nm_ip4_config_get_num_nameservers (config); + nsearches = nm_ip4_config_get_num_searches (config); + + /* Addresses */ + for (i = 0; i < naddresses; i++) { + const NMPlatformIP4Address *address = nm_ip4_config_get_address (config, i); + NMIP4Address *s_addr; + + /* Detect dynamic address */ + if (address->lifetime != NM_PLATFORM_LIFETIME_PERMANENT) { + method = NM_SETTING_IP4_CONFIG_METHOD_AUTO; + continue; + } + + /* Static address found. */ + if (!method) + method = NM_SETTING_IP4_CONFIG_METHOD_MANUAL; + + s_addr = nm_ip4_address_new (); + + nm_ip4_address_set_address (s_addr, address->address); + nm_ip4_address_set_prefix (s_addr, address->plen); + /* For backwards compatibility, attach the gateway to an address if it's + * in the same subnet. + */ + if (same_prefix (address->address, gateway, address->plen)) + nm_ip4_address_set_gateway (s_addr, gateway); + + if (*address->label) + NM_UTILS_PRIVATE_CALL (nm_setting_ip4_config_add_address_with_label (s_ip4, s_addr, address->label)); + else + nm_setting_ip4_config_add_address (s_ip4, s_addr); + nm_ip4_address_unref (s_addr); + } + + /* Use 'disabled' if the method wasn't previously set */ + if (!method) + method = NM_SETTING_IP4_CONFIG_METHOD_DISABLED; + g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_METHOD, method, NULL); + + /* Routes */ + for (i = 0; i < nroutes; i++) { + const NMPlatformIP4Route *route = nm_ip4_config_get_route (config, i); + NMIP4Route *s_route; + + /* Ignore default route. */ + if (!route->plen) + continue; + + /* Ignore routes provided by external sources */ + if (route->source != NM_PLATFORM_SOURCE_USER) + continue; + + s_route = nm_ip4_route_new (); + nm_ip4_route_set_dest (s_route, route->network); + nm_ip4_route_set_prefix (s_route, route->plen); + nm_ip4_route_set_next_hop (s_route, route->gateway); + nm_ip4_route_set_metric (s_route, route->metric); + + nm_setting_ip4_config_add_route (s_ip4, s_route); + nm_ip4_route_unref (s_route); + } + + /* DNS */ + for (i = 0; i < nnameservers; i++) { + guint32 nameserver = nm_ip4_config_get_nameserver (config, i); + + nm_setting_ip4_config_add_dns (s_ip4, nameserver); + } + for (i = 0; i < nsearches; i++) { + const char *search = nm_ip4_config_get_search (config, i); + + nm_setting_ip4_config_add_dns_search (s_ip4, search); + } + + return NM_SETTING (s_ip4); } +/******************************************************************/ + void -nm_ip4_config_add_address (NMIP4Config *config, - NMIP4Address *address) +nm_ip4_config_merge (NMIP4Config *dst, const NMIP4Config *src) { - NMIP4ConfigPrivate *priv; - GSList *iter; + guint32 i; - g_return_if_fail (NM_IS_IP4_CONFIG (config)); - g_return_if_fail (address != NULL); + g_return_if_fail (src != NULL); + g_return_if_fail (dst != NULL); - priv = NM_IP4_CONFIG_GET_PRIVATE (config); - for (iter = priv->addresses; iter; iter = g_slist_next (iter)) { - if (nm_ip4_address_compare ((NMIP4Address *) iter->data, address)) - return; + g_object_freeze_notify (G_OBJECT (dst)); + + /* addresses */ + for (i = 0; i < nm_ip4_config_get_num_addresses (src); i++) + nm_ip4_config_add_address (dst, nm_ip4_config_get_address (src, i)); + + /* nameservers */ + for (i = 0; i < nm_ip4_config_get_num_nameservers (src); i++) + nm_ip4_config_add_nameserver (dst, nm_ip4_config_get_nameserver (src, i)); + + /* default gateway */ + if (!nm_ip4_config_get_gateway (dst)) + nm_ip4_config_set_gateway (dst, nm_ip4_config_get_gateway (src)); + + /* routes */ + for (i = 0; i < nm_ip4_config_get_num_routes (src); i++) + nm_ip4_config_add_route (dst, nm_ip4_config_get_route (src, i)); + + /* domains */ + for (i = 0; i < nm_ip4_config_get_num_domains (src); i++) + nm_ip4_config_add_domain (dst, nm_ip4_config_get_domain (src, i)); + + /* dns searches */ + for (i = 0; i < nm_ip4_config_get_num_searches (src); i++) + nm_ip4_config_add_search (dst, nm_ip4_config_get_search (src, i)); + + /* MSS */ + if (!nm_ip4_config_get_mss (dst)) + nm_ip4_config_set_mss (dst, nm_ip4_config_get_mss (src)); + + /* MTU */ + if (!nm_ip4_config_get_mtu (dst)) + nm_ip4_config_set_mtu (dst, nm_ip4_config_get_mtu (src)); + + /* NIS */ + for (i = 0; i < nm_ip4_config_get_num_nis_servers (src); i++) + nm_ip4_config_add_nis_server (dst, nm_ip4_config_get_nis_server (src, i)); + + if (nm_ip4_config_get_nis_domain (src)) + nm_ip4_config_set_nis_domain (dst, nm_ip4_config_get_nis_domain (src)); + + /* WINS */ + for (i = 0; i < nm_ip4_config_get_num_wins (src); i++) + nm_ip4_config_add_wins (dst, nm_ip4_config_get_wins (src, i)); + + g_object_thaw_notify (G_OBJECT (dst)); +} + +/** + * nm_ip4_config_subtract: + * @dst: config from which to remove everything in @src + * @src: config to remove from @dst + * + * Removes everything in @src from @dst. + */ +void +nm_ip4_config_subtract (NMIP4Config *dst, const NMIP4Config *src) +{ + guint32 i, j; + + g_return_if_fail (src != NULL); + g_return_if_fail (dst != NULL); + + g_object_freeze_notify (G_OBJECT (dst)); + + /* addresses */ + for (i = 0; i < nm_ip4_config_get_num_addresses (src); i++) { + const NMPlatformIP4Address *src_addr = nm_ip4_config_get_address (src, i); + + for (j = 0; j < nm_ip4_config_get_num_addresses (dst); j++) { + const NMPlatformIP4Address *dst_addr = nm_ip4_config_get_address (dst, j); + + if (src_addr->address == dst_addr->address && + src_addr->plen == dst_addr->plen) { + nm_ip4_config_del_address (dst, j); + break; + } + } + } + + /* nameservers */ + for (i = 0; i < nm_ip4_config_get_num_nameservers (src); i++) { + guint32 src_ns = nm_ip4_config_get_nameserver (src, i); + + for (j = 0; j < nm_ip4_config_get_num_nameservers (dst); j++) { + guint32 dst_ns = nm_ip4_config_get_nameserver (dst, j); + + if (dst_ns == src_ns) { + nm_ip4_config_del_nameserver (dst, j); + break; + } + } + } + + /* default gateway */ + if (nm_ip4_config_get_gateway (src) == nm_ip4_config_get_gateway (dst)) + nm_ip4_config_set_gateway (dst, 0); + + /* routes */ + for (i = 0; i < nm_ip4_config_get_num_routes (src); i++) { + const NMPlatformIP4Route *src_route = nm_ip4_config_get_route (src, i); + + for (j = 0; j < nm_ip4_config_get_num_routes (dst); j++) { + const NMPlatformIP4Route *dst_route = nm_ip4_config_get_route (dst, j); + + if (src_route->network == dst_route->network && src_route->plen == dst_route->plen) { + nm_ip4_config_del_route (dst, j); + break; + } + } + } + + /* domains */ + for (i = 0; i < nm_ip4_config_get_num_domains (src); i++) { + const char *src_domain = nm_ip4_config_get_domain (src, i); + + for (j = 0; j < nm_ip4_config_get_num_domains (dst); j++) { + const char *dst_domain = nm_ip4_config_get_domain (dst, j); + + if (g_strcmp0 (src_domain, dst_domain) == 0) { + nm_ip4_config_del_domain (dst, j); + break; + } + } + } + + /* dns searches */ + for (i = 0; i < nm_ip4_config_get_num_searches (src); i++) { + const char *src_search = nm_ip4_config_get_search (src, i); + + for (j = 0; j < nm_ip4_config_get_num_searches (dst); j++) { + const char *dst_search = nm_ip4_config_get_search (dst, j); + + if (g_strcmp0 (src_search, dst_search) == 0) { + nm_ip4_config_del_search (dst, j); + break; + } + } + } + + /* MSS */ + if (nm_ip4_config_get_mss (src) == nm_ip4_config_get_mss (dst)) + nm_ip4_config_set_mss (dst, 0); + + /* MTU */ + if (nm_ip4_config_get_mtu (src) == nm_ip4_config_get_mtu (dst)) + nm_ip4_config_set_mtu (dst, 0); + + /* NIS */ + for (i = 0; i < nm_ip4_config_get_num_nis_servers (src); i++) { + guint32 src_nis = nm_ip4_config_get_nis_server (src, i); + + for (j = 0; j < nm_ip4_config_get_num_nis_servers (dst); j++) { + guint32 dst_nis = nm_ip4_config_get_nis_server (dst, j); + + if (dst_nis == src_nis) { + nm_ip4_config_del_nis_server (dst, j); + break; + } + } + } + + if (g_strcmp0 (nm_ip4_config_get_nis_domain (src), nm_ip4_config_get_nis_domain (dst)) == 0) + nm_ip4_config_set_nis_domain (dst, NULL); + + /* WINS */ + for (i = 0; i < nm_ip4_config_get_num_wins (src); i++) { + guint32 src_wins = nm_ip4_config_get_wins (src, i); + + for (j = 0; j < nm_ip4_config_get_num_wins (dst); j++) { + guint32 dst_wins = nm_ip4_config_get_wins (dst, j); + + if (dst_wins == src_wins) { + nm_ip4_config_del_wins (dst, j); + break; + } + } + } + + g_object_thaw_notify (G_OBJECT (dst)); +} + + +/** + * nm_ip4_config_replace: + * @dst: config from which to remove everything in @src + * @src: config to remove from @dst + * @relevant_changes: return whether there are changes to the + * destination object that are relevant. This is equal to + * nm_ip4_config_equal() showing any difference. + * + * Replaces everything in @dst with @src so that the two configurations + * contain the same content -- with the exception of the dbus path. + * + * Returns: whether the @dst instance changed in any way (including minor changes, + * that are not signaled by the output parameter @relevant_changes). + */ +gboolean +nm_ip4_config_replace (NMIP4Config *dst, const NMIP4Config *src, gboolean *relevant_changes) +{ +#ifndef G_DISABLE_ASSERT + gboolean config_equal; +#endif + gboolean has_minor_changes = FALSE, has_relevant_changes = FALSE, are_equal; + guint i, num; + NMIP4ConfigPrivate *dst_priv, *src_priv; + const NMPlatformIP4Address *dst_addr, *src_addr; + const NMPlatformIP4Route *dst_route, *src_route; + + g_return_val_if_fail (src != NULL, FALSE); + g_return_val_if_fail (dst != NULL, FALSE); + g_return_val_if_fail (src != dst, FALSE); + +#ifndef G_DISABLE_ASSERT + config_equal = nm_ip4_config_equal (dst, src); +#endif + + dst_priv = NM_IP4_CONFIG_GET_PRIVATE (dst); + src_priv = NM_IP4_CONFIG_GET_PRIVATE (src); + + g_object_freeze_notify (G_OBJECT (dst)); + + /* never_default */ + if (src_priv->never_default != dst_priv->never_default) { + dst_priv->never_default = src_priv->never_default; + has_minor_changes = TRUE; + } + + /* default gateway */ + if (src_priv->gateway != dst_priv->gateway) { + nm_ip4_config_set_gateway (dst, src_priv->gateway); + has_relevant_changes = TRUE; + } + + /* addresses */ + num = nm_ip4_config_get_num_addresses (src); + are_equal = num == nm_ip4_config_get_num_addresses (dst); + if (are_equal) { + for (i = 0; i < num; i++ ) { + if (nm_platform_ip4_address_cmp (src_addr = nm_ip4_config_get_address (src, i), + dst_addr = nm_ip4_config_get_address (dst, i))) { + are_equal = FALSE; + if (!addresses_are_duplicate (src_addr, dst_addr, TRUE)) { + has_relevant_changes = TRUE; + break; + } + } + } + } else + has_relevant_changes = TRUE; + if (!are_equal) { + nm_ip4_config_reset_addresses (dst); + for (i = 0; i < num; i++) + nm_ip4_config_add_address (dst, nm_ip4_config_get_address (src, i)); + has_minor_changes = TRUE; + } + + /* routes */ + num = nm_ip4_config_get_num_routes (src); + are_equal = num == nm_ip4_config_get_num_routes (dst); + if (are_equal) { + for (i = 0; i < num; i++ ) { + if (nm_platform_ip4_route_cmp (src_route = nm_ip4_config_get_route (src, i), + dst_route = nm_ip4_config_get_route (dst, i))) { + are_equal = FALSE; + if (!routes_are_duplicate (src_route, dst_route, TRUE)) { + has_relevant_changes = TRUE; + break; + } + } + } + } else + has_relevant_changes = TRUE; + if (!are_equal) { + nm_ip4_config_reset_routes (dst); + for (i = 0; i < num; i++) + nm_ip4_config_add_route (dst, nm_ip4_config_get_route (src, i)); + has_minor_changes = TRUE; + } + + /* nameservers */ + num = nm_ip4_config_get_num_nameservers (src); + are_equal = num == nm_ip4_config_get_num_nameservers (dst); + if (are_equal) { + for (i = 0; i < num; i++ ) { + if (nm_ip4_config_get_nameserver (src, i) != nm_ip4_config_get_nameserver (dst, i)) { + are_equal = FALSE; + break; + } + } + } + if (!are_equal) { + nm_ip4_config_reset_nameservers (dst); + for (i = 0; i < num; i++) + nm_ip4_config_add_nameserver (dst, nm_ip4_config_get_nameserver (src, i)); + has_relevant_changes = TRUE; + } + + /* domains */ + num = nm_ip4_config_get_num_domains (src); + are_equal = num == nm_ip4_config_get_num_domains (dst); + if (are_equal) { + for (i = 0; i < num; i++ ) { + if (g_strcmp0 (nm_ip4_config_get_domain (src, i), + nm_ip4_config_get_domain (dst, i))) { + are_equal = FALSE; + break; + } + } + } + if (!are_equal) { + nm_ip4_config_reset_domains (dst); + for (i = 0; i < num; i++) + nm_ip4_config_add_domain (dst, nm_ip4_config_get_domain (src, i)); + has_relevant_changes = TRUE; + } + + /* dns searches */ + num = nm_ip4_config_get_num_searches (src); + are_equal = num == nm_ip4_config_get_num_searches (dst); + if (are_equal) { + for (i = 0; i < num; i++ ) { + if (g_strcmp0 (nm_ip4_config_get_search (src, i), + nm_ip4_config_get_search (dst, i))) { + are_equal = FALSE; + break; + } + } + } + if (!are_equal) { + nm_ip4_config_reset_searches (dst); + for (i = 0; i < num; i++) + nm_ip4_config_add_search (dst, nm_ip4_config_get_search (src, i)); + has_relevant_changes = TRUE; + } + + /* mss */ + if (src_priv->mss != dst_priv->mss) { + nm_ip4_config_set_mss (dst, src_priv->mss); + has_minor_changes = TRUE; + } + + /* nis */ + num = nm_ip4_config_get_num_nis_servers (src); + are_equal = num == nm_ip4_config_get_num_nis_servers (dst); + if (are_equal) { + for (i = 0; i < num; i++ ) { + if (nm_ip4_config_get_nis_server (src, i) != nm_ip4_config_get_nis_server (dst, i)) { + are_equal = FALSE; + break; + } + } + } + if (!are_equal) { + nm_ip4_config_reset_nis_servers (dst); + for (i = 0; i < num; i++) + nm_ip4_config_add_nis_server (dst, nm_ip4_config_get_nis_server (src, i)); + has_relevant_changes = TRUE; + } + + /* nis_domain */ + if (g_strcmp0 (src_priv->nis_domain, dst_priv->nis_domain)) { + nm_ip4_config_set_nis_domain (dst, src_priv->nis_domain); + has_relevant_changes = TRUE; + } + + /* wins */ + num = nm_ip4_config_get_num_wins (src); + are_equal = num == nm_ip4_config_get_num_wins (dst); + if (are_equal) { + for (i = 0; i < num; i++ ) { + if (nm_ip4_config_get_wins (src, i) != nm_ip4_config_get_wins (dst, i)) { + are_equal = FALSE; + break; + } + } } + if (!are_equal) { + nm_ip4_config_reset_wins (dst); + for (i = 0; i < num; i++) + nm_ip4_config_add_wins (dst, nm_ip4_config_get_wins (src, i)); + has_relevant_changes = TRUE; + } + + /* mtu */ + if (src_priv->mtu != dst_priv->mtu) { + nm_ip4_config_set_mtu (dst, src_priv->mtu); + has_minor_changes = TRUE; + } + + /* config_equal does not compare *all* the fields, therefore, we might have has_minor_changes + * regardless of config_equal. But config_equal must correspond to has_relevant_changes. */ + g_assert (config_equal == !has_relevant_changes); + + g_object_thaw_notify (G_OBJECT (dst)); - priv->addresses = g_slist_append (priv->addresses, nm_ip4_address_dup (address)); + if (relevant_changes) + *relevant_changes = has_relevant_changes; + + return has_relevant_changes || has_minor_changes; } void -nm_ip4_config_replace_address (NMIP4Config *config, - guint i, - NMIP4Address *new_address) +nm_ip4_config_dump (const NMIP4Config *config, const char *detail) { - NMIP4ConfigPrivate *priv; - GSList *old; + guint32 i, tmp; + const char *str; + + g_return_if_fail (config != NULL); - g_return_if_fail (NM_IS_IP4_CONFIG (config)); + g_message ("--------- NMIP4Config %p (%s)", config, detail); - priv = NM_IP4_CONFIG_GET_PRIVATE (config); - old = g_slist_nth (priv->addresses, i); - g_return_if_fail (old != NULL); - nm_ip4_address_unref ((NMIP4Address *) old->data); + str = nm_ip4_config_get_dbus_path (config); + if (str) + g_message (" path: %s", str); + + /* addresses */ + for (i = 0; i < nm_ip4_config_get_num_addresses (config); i++) + g_message (" a: %s", nm_platform_ip4_address_to_string (nm_ip4_config_get_address (config, i))); + + /* default gateway */ + tmp = nm_ip4_config_get_gateway (config); + g_message (" gw: %s", nm_utils_inet4_ntop (tmp, NULL)); + + /* nameservers */ + for (i = 0; i < nm_ip4_config_get_num_nameservers (config); i++) { + tmp = nm_ip4_config_get_nameserver (config, i); + g_message (" ns: %s", nm_utils_inet4_ntop (tmp, NULL)); + } + + /* routes */ + for (i = 0; i < nm_ip4_config_get_num_routes (config); i++) + g_message (" rt: %s", nm_platform_ip4_route_to_string (nm_ip4_config_get_route (config, i))); + + /* domains */ + for (i = 0; i < nm_ip4_config_get_num_domains (config); i++) + g_message (" domain: %s", nm_ip4_config_get_domain (config, i)); + + /* dns searches */ + for (i = 0; i < nm_ip4_config_get_num_searches (config); i++) + g_message (" search: %s", nm_ip4_config_get_search (config, i)); + + g_message (" mss: %u", nm_ip4_config_get_mss (config)); + g_message (" mtu: %u", nm_ip4_config_get_mtu (config)); + + /* NIS */ + for (i = 0; i < nm_ip4_config_get_num_nis_servers (config); i++) { + tmp = nm_ip4_config_get_nis_server (config, i); + g_message (" nis: %s", nm_utils_inet4_ntop (tmp, NULL)); + } + + g_message (" nisdmn: %s", nm_ip4_config_get_nis_domain (config)); + + /* WINS */ + for (i = 0; i < nm_ip4_config_get_num_wins (config); i++) { + tmp = nm_ip4_config_get_wins (config, i); + g_message (" wins: %s", nm_utils_inet4_ntop (tmp, NULL)); + } + + g_message (" n-dflt: %d", nm_ip4_config_get_never_default (config)); +} + +gboolean +nm_ip4_config_destination_is_direct (const NMIP4Config *config, guint32 network, int plen) +{ + guint naddresses = nm_ip4_config_get_num_addresses (config); + int i; + + for (i = 0; i < naddresses; i++) { + const NMPlatformIP4Address *item = nm_ip4_config_get_address (config, i); + + if (item->plen <= plen && same_prefix (item->address, network, item->plen)) + return TRUE; + } - old->data = nm_ip4_address_dup (new_address); + return FALSE; } -NMIP4Address *nm_ip4_config_get_address (NMIP4Config *config, guint i) +/******************************************************************/ + +void +nm_ip4_config_set_never_default (NMIP4Config *config, gboolean never_default) { - g_return_val_if_fail (NM_IS_IP4_CONFIG (config), NULL); + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); - return (NMIP4Address *) g_slist_nth_data (NM_IP4_CONFIG_GET_PRIVATE (config)->addresses, i); + priv->never_default = !!never_default; } -guint32 nm_ip4_config_get_num_addresses (NMIP4Config *config) +gboolean +nm_ip4_config_get_never_default (const NMIP4Config *config) { - g_return_val_if_fail (NM_IS_IP4_CONFIG (config), 0); + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); - return g_slist_length (NM_IP4_CONFIG_GET_PRIVATE (config)->addresses); + return priv->never_default; } -guint32 nm_ip4_config_get_ptp_address (NMIP4Config *config) +void +nm_ip4_config_set_gateway (NMIP4Config *config, guint32 gateway) { - g_return_val_if_fail (NM_IS_IP4_CONFIG (config), 0); + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); - return NM_IP4_CONFIG_GET_PRIVATE (config)->ptp_address; + if (priv->gateway != gateway) { + priv->gateway = gateway; + _NOTIFY (config, PROP_GATEWAY); + } } -void nm_ip4_config_set_ptp_address (NMIP4Config *config, guint32 ptp_addr) +guint32 +nm_ip4_config_get_gateway (const NMIP4Config *config) { - g_return_if_fail (NM_IS_IP4_CONFIG (config)); + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); - NM_IP4_CONFIG_GET_PRIVATE (config)->ptp_address = ptp_addr; + return priv->gateway; } -void nm_ip4_config_add_nameserver (NMIP4Config *config, guint32 nameserver) +/******************************************************************/ + +void +nm_ip4_config_reset_addresses (NMIP4Config *config) { - NMIP4ConfigPrivate *priv; - int i; + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); - g_return_if_fail (NM_IS_IP4_CONFIG (config)); - g_return_if_fail (nameserver > 0); + if (priv->addresses->len != 0) { + g_array_set_size (priv->addresses, 0); + _NOTIFY (config, PROP_ADDRESSES); + } +} - priv = NM_IP4_CONFIG_GET_PRIVATE (config); - for (i = 0; i < priv->nameservers->len; i++) { - guint32 s = g_array_index (priv->nameservers, guint32, i); +/** + * nm_ip4_config_add_address: + * @config: the #NMIP4Config + * @new: the new address to add to @config + * + * Adds the new address to @config. If an address with the same basic properties + * (address, prefix) already exists in @config, it is overwritten with the + * lifetime and preferred of @new. The source is also overwritten by the source + * from @new if that source is higher priority. + */ +void +nm_ip4_config_add_address (NMIP4Config *config, const NMPlatformIP4Address *new) +{ + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); + NMPlatformIP4Address item_old; + int i; - /* No dupes */ - if (nameserver == s) - return; + g_return_if_fail (new != NULL); + + for (i = 0; i < priv->addresses->len; i++ ) { + NMPlatformIP4Address *item = &g_array_index (priv->addresses, NMPlatformIP4Address, i); + + if (addresses_are_duplicate (item, new, FALSE)) { + if (nm_platform_ip4_address_cmp (item, new) == 0) + return; + + /* remember the old values. */ + item_old = *item; + /* Copy over old item to get new lifetime, timestamp, preferred */ + *item = *new; + + /* But restore highest priority source */ + item->source = MAX (item_old.source, new->source); + + /* for addresses that we read from the kernel, we keep the timestamps as defined + * by the previous source (item_old). The reason is, that the other source configured the lifetimes + * with "what should be" and the kernel values are "what turned out after configuring it". + * + * For other sources, the longer lifetime wins. */ + if ( (new->source == NM_PLATFORM_SOURCE_KERNEL && new->source != item_old.source) + || nm_platform_ip_address_cmp_expiry ((const NMPlatformIPAddress *) &item_old, (const NMPlatformIPAddress *) new) > 0) { + item->timestamp = item_old.timestamp; + item->lifetime = item_old.lifetime; + item->preferred = item_old.preferred; + } + if (nm_platform_ip4_address_cmp (&item_old, item) == 0) + return; + goto NOTIFY; + } } - g_array_append_val (priv->nameservers, nameserver); + g_array_append_val (priv->addresses, *new); +NOTIFY: + _NOTIFY (config, PROP_ADDRESSES); +} + +void +nm_ip4_config_del_address (NMIP4Config *config, guint i) +{ + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); + + g_return_if_fail (i < priv->addresses->len); + + g_array_remove_index (priv->addresses, i); + _NOTIFY (config, PROP_ADDRESSES); +} + +guint +nm_ip4_config_get_num_addresses (const NMIP4Config *config) +{ + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); + + return priv->addresses->len; } -guint32 nm_ip4_config_get_nameserver (NMIP4Config *config, guint i) +const NMPlatformIP4Address * +nm_ip4_config_get_address (const NMIP4Config *config, guint i) { - g_return_val_if_fail (NM_IS_IP4_CONFIG (config), 0); + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); - return g_array_index (NM_IP4_CONFIG_GET_PRIVATE (config)->nameservers, guint32, i); + return &g_array_index (priv->addresses, NMPlatformIP4Address, i); } -guint32 nm_ip4_config_get_num_nameservers (NMIP4Config *config) +gboolean +nm_ip4_config_address_exists (const NMIP4Config *config, + const NMPlatformIP4Address *needle) { - g_return_val_if_fail (NM_IS_IP4_CONFIG (config), 0); + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); + guint i; + + for (i = 0; i < priv->addresses->len; i++) { + const NMPlatformIP4Address *haystack = &g_array_index (priv->addresses, NMPlatformIP4Address, i); - return NM_IP4_CONFIG_GET_PRIVATE (config)->nameservers->len; + if (needle->address == haystack->address && needle->plen == haystack->plen) + return TRUE; + } + return FALSE; } -void nm_ip4_config_reset_nameservers (NMIP4Config *config) -{ - NMIP4ConfigPrivate *priv; +/******************************************************************/ - g_return_if_fail (NM_IS_IP4_CONFIG (config)); +void +nm_ip4_config_reset_routes (NMIP4Config *config) +{ + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); - priv = NM_IP4_CONFIG_GET_PRIVATE (config); - if (priv->nameservers->len) - g_array_remove_range (priv->nameservers, 0, priv->nameservers->len); + if (priv->routes->len != 0) { + g_array_set_size (priv->routes, 0); + _NOTIFY (config, PROP_ROUTES); + } } -void nm_ip4_config_add_wins (NMIP4Config *config, guint32 wins) +/** + * nm_ip4_config_add_route: + * @config: the #NMIP4Config + * @new: the new route to add to @config + * + * Adds the new route to @config. If a route with the same basic properties + * (network, prefix) already exists in @config, it is overwritten including the + * gateway and metric of @new. The source is also overwritten by the source + * from @new if that source is higher priority. + */ +void +nm_ip4_config_add_route (NMIP4Config *config, const NMPlatformIP4Route *new) { - NMIP4ConfigPrivate *priv; + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); + NMPlatformSource old_source; int i; - g_return_if_fail (NM_IS_IP4_CONFIG (config)); - g_return_if_fail (wins > 0); + g_return_if_fail (new != NULL); - priv = NM_IP4_CONFIG_GET_PRIVATE (config); - for (i = 0; i < priv->wins->len; i++) { - guint32 s = g_array_index (priv->wins, guint32, i); + for (i = 0; i < priv->routes->len; i++ ) { + NMPlatformIP4Route *item = &g_array_index (priv->routes, NMPlatformIP4Route, i); - /* No dupes */ - if (wins == s) - return; + if (routes_are_duplicate (item, new, FALSE)) { + if (nm_platform_ip4_route_cmp (item, new) == 0) + return; + old_source = item->source; + memcpy (item, new, sizeof (*item)); + /* Restore highest priority source */ + item->source = MAX (old_source, new->source); + goto NOTIFY; + } } - g_array_append_val (priv->wins, wins); + g_array_append_val (priv->routes, *new); +NOTIFY: + _NOTIFY (config, PROP_ROUTES); } -guint32 nm_ip4_config_get_wins (NMIP4Config *config, guint i) +void +nm_ip4_config_del_route (NMIP4Config *config, guint i) { - g_return_val_if_fail (NM_IS_IP4_CONFIG (config), 0); + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); + + g_return_if_fail (i < priv->routes->len); - return g_array_index (NM_IP4_CONFIG_GET_PRIVATE (config)->wins, guint32, i); + g_array_remove_index (priv->routes, i); + _NOTIFY (config, PROP_ROUTES); } -guint32 nm_ip4_config_get_num_wins (NMIP4Config *config) +guint +nm_ip4_config_get_num_routes (const NMIP4Config *config) { - g_return_val_if_fail (NM_IS_IP4_CONFIG (config), 0); + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); - return NM_IP4_CONFIG_GET_PRIVATE (config)->wins->len; + return priv->routes->len; } -void nm_ip4_config_reset_wins (NMIP4Config *config) +const NMPlatformIP4Route * +nm_ip4_config_get_route (const NMIP4Config *config, guint i) { - NMIP4ConfigPrivate *priv; - - g_return_if_fail (NM_IS_IP4_CONFIG (config)); + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); - priv = NM_IP4_CONFIG_GET_PRIVATE (config); - if (priv->wins->len) - g_array_remove_range (priv->wins, 0, priv->wins->len); + return &g_array_index (priv->routes, NMPlatformIP4Route, i); } +/******************************************************************/ + void -nm_ip4_config_take_route (NMIP4Config *config, NMIP4Route *route) +nm_ip4_config_reset_nameservers (NMIP4Config *config) { - NMIP4ConfigPrivate *priv; - - g_return_if_fail (NM_IS_IP4_CONFIG (config)); - g_return_if_fail (route != NULL); + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); - priv = NM_IP4_CONFIG_GET_PRIVATE (config); - priv->routes = g_slist_append (priv->routes, route); + if (priv->nameservers->len != 0) { + g_array_set_size (priv->nameservers, 0); + _NOTIFY (config, PROP_NAMESERVERS); + } } void -nm_ip4_config_add_route (NMIP4Config *config, NMIP4Route *route) +nm_ip4_config_add_nameserver (NMIP4Config *config, guint32 new) { - NMIP4ConfigPrivate *priv; - GSList *iter; + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); + int i; - g_return_if_fail (NM_IS_IP4_CONFIG (config)); - g_return_if_fail (route != NULL); + g_return_if_fail (new != 0); - priv = NM_IP4_CONFIG_GET_PRIVATE (config); - for (iter = priv->routes; iter; iter = g_slist_next (iter)) { - if (nm_ip4_route_compare ((NMIP4Route *) iter->data, route)) + for (i = 0; i < priv->nameservers->len; i++) + if (new == g_array_index (priv->nameservers, guint32, i)) return; - } - priv->routes = g_slist_append (priv->routes, nm_ip4_route_dup (route)); + g_array_append_val (priv->nameservers, new); + _NOTIFY (config, PROP_NAMESERVERS); } void -nm_ip4_config_replace_route (NMIP4Config *config, - guint i, - NMIP4Route *new_route) +nm_ip4_config_del_nameserver (NMIP4Config *config, guint i) { - NMIP4ConfigPrivate *priv; - GSList *old; - - g_return_if_fail (NM_IS_IP4_CONFIG (config)); + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); - priv = NM_IP4_CONFIG_GET_PRIVATE (config); - old = g_slist_nth (priv->routes, i); - g_return_if_fail (old != NULL); - nm_ip4_route_unref ((NMIP4Route *) old->data); + g_return_if_fail (i < priv->nameservers->len); - old->data = nm_ip4_route_dup (new_route); + g_array_remove_index (priv->nameservers, i); + _NOTIFY (config, PROP_NAMESERVERS); } -NMIP4Route * -nm_ip4_config_get_route (NMIP4Config *config, guint i) +guint32 +nm_ip4_config_get_num_nameservers (const NMIP4Config *config) { - g_return_val_if_fail (NM_IS_IP4_CONFIG (config), NULL); + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); - return (NMIP4Route *) g_slist_nth_data (NM_IP4_CONFIG_GET_PRIVATE (config)->routes, i); + return priv->nameservers->len; } -guint32 nm_ip4_config_get_num_routes (NMIP4Config *config) +guint32 +nm_ip4_config_get_nameserver (const NMIP4Config *config, guint i) { - g_return_val_if_fail (NM_IS_IP4_CONFIG (config), 0); + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); - return g_slist_length (NM_IP4_CONFIG_GET_PRIVATE (config)->routes); + return g_array_index (priv->nameservers, guint32, i); } -void nm_ip4_config_reset_routes (NMIP4Config *config) -{ - NMIP4ConfigPrivate *priv; +/******************************************************************/ - g_return_if_fail (NM_IS_IP4_CONFIG (config)); +void +nm_ip4_config_reset_domains (NMIP4Config *config) +{ + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); - priv = NM_IP4_CONFIG_GET_PRIVATE (config); - g_slist_foreach (priv->routes, (GFunc) g_free, NULL); - priv->routes = NULL; + if (priv->domains->len != 0) { + g_ptr_array_set_size (priv->domains, 0); + _NOTIFY (config, PROP_DOMAINS); + } } -void nm_ip4_config_add_domain (NMIP4Config *config, const char *domain) +void +nm_ip4_config_add_domain (NMIP4Config *config, const char *domain) { - NMIP4ConfigPrivate *priv; + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); int i; - g_return_if_fail (NM_IS_IP4_CONFIG (config)); g_return_if_fail (domain != NULL); - g_return_if_fail (strlen (domain) > 0); - - priv = NM_IP4_CONFIG_GET_PRIVATE (config); + g_return_if_fail (domain[0] != '\0'); - for (i = 0; i < priv->domains->len; i++) { - if (!strcmp (g_ptr_array_index (priv->domains, i), domain)) + for (i = 0; i < priv->domains->len; i++) + if (!g_strcmp0 (g_ptr_array_index (priv->domains, i), domain)) return; - } g_ptr_array_add (priv->domains, g_strdup (domain)); + _NOTIFY (config, PROP_DOMAINS); } -const char *nm_ip4_config_get_domain (NMIP4Config *config, guint i) +void +nm_ip4_config_del_domain (NMIP4Config *config, guint i) { - g_return_val_if_fail (NM_IS_IP4_CONFIG (config), NULL); - - return (const char *) g_ptr_array_index (NM_IP4_CONFIG_GET_PRIVATE (config)->domains, i); -} + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); -guint32 nm_ip4_config_get_num_domains (NMIP4Config *config) -{ - g_return_val_if_fail (NM_IS_IP4_CONFIG (config), 0); + g_return_if_fail (i < priv->domains->len); - return NM_IP4_CONFIG_GET_PRIVATE (config)->domains->len; + g_ptr_array_remove_index (priv->domains, i); + _NOTIFY (config, PROP_DOMAINS); } -void nm_ip4_config_reset_domains (NMIP4Config *config) +guint32 +nm_ip4_config_get_num_domains (const NMIP4Config *config) { - NMIP4ConfigPrivate *priv; - int i; - - g_return_if_fail (NM_IS_IP4_CONFIG (config)); + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); - priv = NM_IP4_CONFIG_GET_PRIVATE (config); - for (i = 0; i < priv->domains->len; i++) - g_free (g_ptr_array_index (priv->domains, i)); - g_ptr_array_free (priv->domains, TRUE); - priv->domains = g_ptr_array_sized_new (3); + return priv->domains->len; } -void nm_ip4_config_add_search (NMIP4Config *config, const char *search) +const char * +nm_ip4_config_get_domain (const NMIP4Config *config, guint i) { - NMIP4ConfigPrivate *priv; - int i; - - g_return_if_fail (config != NULL); - g_return_if_fail (search != NULL); - g_return_if_fail (strlen (search) > 0); - - priv = NM_IP4_CONFIG_GET_PRIVATE (config); - - for (i = 0; i < priv->searches->len; i++) { - if (!strcmp (g_ptr_array_index (priv->searches, i), search)) - return; - } + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); - g_ptr_array_add (priv->searches, g_strdup (search)); + return g_ptr_array_index (priv->domains, i); } -const char *nm_ip4_config_get_search (NMIP4Config *config, guint i) -{ - g_return_val_if_fail (config != NULL, NULL); - - return (const char *) g_ptr_array_index (NM_IP4_CONFIG_GET_PRIVATE (config)->searches, i); -} +/******************************************************************/ -guint32 nm_ip4_config_get_num_searches (NMIP4Config *config) +void +nm_ip4_config_reset_searches (NMIP4Config *config) { - g_return_val_if_fail (config != NULL, 0); + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); - return NM_IP4_CONFIG_GET_PRIVATE (config)->searches->len; + if (priv->searches->len != 0) { + g_ptr_array_set_size (priv->searches, 0); + _NOTIFY (config, PROP_SEARCHES); + } } -void nm_ip4_config_reset_searches (NMIP4Config *config) +void +nm_ip4_config_add_search (NMIP4Config *config, const char *new) { - NMIP4ConfigPrivate *priv; + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); int i; - g_return_if_fail (NM_IS_IP4_CONFIG (config)); + g_return_if_fail (new != NULL); + g_return_if_fail (new[0] != '\0'); - priv = NM_IP4_CONFIG_GET_PRIVATE (config); for (i = 0; i < priv->searches->len; i++) - g_free (g_ptr_array_index (priv->searches, i)); - g_ptr_array_free (priv->searches, TRUE); - priv->searches = g_ptr_array_sized_new (3); + if (!g_strcmp0 (g_ptr_array_index (priv->searches, i), new)) + return; + + g_ptr_array_add (priv->searches, g_strdup (new)); + _NOTIFY (config, PROP_SEARCHES); } -guint32 nm_ip4_config_get_mtu (NMIP4Config *config) +void +nm_ip4_config_del_search (NMIP4Config *config, guint i) { - g_return_val_if_fail (NM_IS_IP4_CONFIG (config), 0); + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); - return NM_IP4_CONFIG_GET_PRIVATE (config)->mtu; + g_return_if_fail (i < priv->searches->len); + + g_ptr_array_remove_index (priv->searches, i); + _NOTIFY (config, PROP_SEARCHES); } -void nm_ip4_config_set_mtu (NMIP4Config *config, guint32 mtu) +guint32 +nm_ip4_config_get_num_searches (const NMIP4Config *config) { - g_return_if_fail (NM_IS_IP4_CONFIG (config)); + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); - NM_IP4_CONFIG_GET_PRIVATE (config)->mtu = mtu; + return priv->searches->len; } -guint32 nm_ip4_config_get_mss (NMIP4Config *config) +const char * +nm_ip4_config_get_search (const NMIP4Config *config, guint i) { - g_return_val_if_fail (NM_IS_IP4_CONFIG (config), 0); + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); - return NM_IP4_CONFIG_GET_PRIVATE (config)->mss; + return g_ptr_array_index (priv->searches, i); } -void nm_ip4_config_set_mss (NMIP4Config *config, guint32 mss) +/******************************************************************/ + +void +nm_ip4_config_set_mss (NMIP4Config *config, guint32 mss) { - g_return_if_fail (NM_IS_IP4_CONFIG (config)); + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); - NM_IP4_CONFIG_GET_PRIVATE (config)->mss = mss; + priv->mss = mss; } -gboolean -nm_ip4_config_get_never_default (NMIP4Config *config) +guint32 +nm_ip4_config_get_mss (const NMIP4Config *config) { - g_return_val_if_fail (NM_IS_IP4_CONFIG (config), FALSE); + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); - return NM_IP4_CONFIG_GET_PRIVATE (config)->never_default; + return priv->mss; } +/******************************************************************/ + void -nm_ip4_config_set_never_default (NMIP4Config *config, gboolean never_default) +nm_ip4_config_reset_nis_servers (NMIP4Config *config) { - g_return_if_fail (NM_IS_IP4_CONFIG (config)); + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); - NM_IP4_CONFIG_GET_PRIVATE (config)->never_default = never_default; + g_array_set_size (priv->nis, 0); } -void nm_ip4_config_add_nis_server (NMIP4Config *config, guint32 nis) +void +nm_ip4_config_add_nis_server (NMIP4Config *config, guint32 nis) { - NMIP4ConfigPrivate *priv; + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); int i; - g_return_if_fail (NM_IS_IP4_CONFIG (config)); - g_return_if_fail (nis > 0); - - priv = NM_IP4_CONFIG_GET_PRIVATE (config); - for (i = 0; i < priv->nis->len; i++) { - guint32 s = g_array_index (priv->nis, guint32, i); - - /* No dupes */ - g_return_if_fail (nis != s); - } + for (i = 0; i < priv->nis->len; i++) + if (nis == g_array_index (priv->nis, guint32, i)) + return; g_array_append_val (priv->nis, nis); } -guint32 nm_ip4_config_get_nis_server (NMIP4Config *config, guint i) +void +nm_ip4_config_del_nis_server (NMIP4Config *config, guint i) { - g_return_val_if_fail (NM_IS_IP4_CONFIG (config), 0); + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); - return g_array_index (NM_IP4_CONFIG_GET_PRIVATE (config)->nis, guint32, i); + g_return_if_fail (i < priv->nis->len); + + g_array_remove_index (priv->nis, i); } -guint32 nm_ip4_config_get_num_nis_servers (NMIP4Config *config) +guint32 +nm_ip4_config_get_num_nis_servers (const NMIP4Config *config) { - g_return_val_if_fail (NM_IS_IP4_CONFIG (config), 0); + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); - return NM_IP4_CONFIG_GET_PRIVATE (config)->nis->len; + return priv->nis->len; } -void nm_ip4_config_reset_nis_servers (NMIP4Config *config) +guint32 +nm_ip4_config_get_nis_server (const NMIP4Config *config, guint i) { - NMIP4ConfigPrivate *priv; - - g_return_if_fail (NM_IS_IP4_CONFIG (config)); + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); - priv = NM_IP4_CONFIG_GET_PRIVATE (config); - if (priv->nis->len) - g_array_remove_range (priv->nis, 0, priv->nis->len); + return g_array_index (priv->nis, guint32, i); } void nm_ip4_config_set_nis_domain (NMIP4Config *config, const char *domain) { - NMIP4ConfigPrivate *priv; - - g_return_if_fail (NM_IS_IP4_CONFIG (config)); + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); - priv = NM_IP4_CONFIG_GET_PRIVATE (config); g_free (priv->nis_domain); priv->nis_domain = g_strdup (domain); } const char * -nm_ip4_config_get_nis_domain (NMIP4Config *config) +nm_ip4_config_get_nis_domain (const NMIP4Config *config) { - g_return_val_if_fail (NM_IS_IP4_CONFIG (config), 0); + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); - return NM_IP4_CONFIG_GET_PRIVATE (config)->nis_domain; + return priv->nis_domain; } -/* libnl convenience/conversion functions */ +/******************************************************************/ -static int ip4_addr_to_rtnl_local (guint32 ip4_address, struct rtnl_addr *addr) +void +nm_ip4_config_reset_wins (NMIP4Config *config) { - struct nl_addr * local = NULL; - int err = 0; - - g_return_val_if_fail (addr != NULL, -1); - - local = nm_utils_ip4_addr_to_nl_addr (ip4_address); - err = rtnl_addr_set_local (addr, local); - nl_addr_put (local); + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); - return err; + if (priv->wins->len != 0) { + g_array_set_size (priv->wins, 0); + _NOTIFY (config, PROP_WINS_SERVERS); + } } -static int ip4_addr_to_rtnl_peer (guint32 ip4_address, struct rtnl_addr *addr) +void +nm_ip4_config_add_wins (NMIP4Config *config, guint32 wins) { - struct nl_addr * peer = NULL; - int err = 0; + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); + int i; - g_return_val_if_fail (addr != NULL, -1); + g_return_if_fail (wins != 0); - peer = nm_utils_ip4_addr_to_nl_addr (ip4_address); - err = rtnl_addr_set_peer (addr, peer); - nl_addr_put (peer); + for (i = 0; i < priv->wins->len; i++) + if (wins == g_array_index (priv->wins, guint32, i)) + return; - return err; + g_array_append_val (priv->wins, wins); + _NOTIFY (config, PROP_WINS_SERVERS); } -static int ip4_addr_to_rtnl_broadcast (guint32 ip4_broadcast, struct rtnl_addr *addr) +void +nm_ip4_config_del_wins (NMIP4Config *config, guint i) { - struct nl_addr * local = NULL; - int err = 0; - - g_return_val_if_fail (addr != NULL, -1); + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); - local = nm_utils_ip4_addr_to_nl_addr (ip4_broadcast); - err = rtnl_addr_set_broadcast (addr, local); - nl_addr_put (local); + g_return_if_fail (i < priv->wins->len); - return err; + g_array_remove_index (priv->wins, i); + _NOTIFY (config, PROP_WINS_SERVERS); } - -struct rtnl_addr * -nm_ip4_config_to_rtnl_addr (NMIP4Config *config, guint32 i, guint32 flags) +guint32 +nm_ip4_config_get_num_wins (const NMIP4Config *config) { NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); - NMIP4Address *config_addr; - struct rtnl_addr *addr; - gboolean success = TRUE; - - g_return_val_if_fail (NM_IS_IP4_CONFIG (config), NULL); - - config_addr = nm_ip4_config_get_address (config, i); - g_return_val_if_fail (config_addr != NULL, NULL); - - if (!(addr = rtnl_addr_alloc())) - return NULL; - - if (flags & NM_RTNL_ADDR_ADDR) - success = (ip4_addr_to_rtnl_local (nm_ip4_address_get_address (config_addr), addr) >= 0); - - if (flags & NM_RTNL_ADDR_PTP_ADDR) - success = (ip4_addr_to_rtnl_peer (priv->ptp_address, addr) >= 0); - - if (flags & NM_RTNL_ADDR_PREFIX) - rtnl_addr_set_prefixlen (addr, nm_ip4_address_get_prefix (config_addr)); - if (flags & NM_RTNL_ADDR_BROADCAST) { - guint32 hostmask, network, bcast, netmask; - - netmask = nm_utils_ip4_prefix_to_netmask (nm_ip4_address_get_prefix (config_addr)); - network = ntohl (nm_ip4_address_get_address (config_addr)) & ntohl (netmask); - hostmask = ~ntohl (netmask); - bcast = htonl (network | hostmask); - - success = (ip4_addr_to_rtnl_broadcast (bcast, addr) >= 0); - } - - if (!success) { - rtnl_addr_put (addr); - addr = NULL; - } - - return addr; + return priv->wins->len; } -static gboolean -addr_slist_compare (GSList *a, GSList *b) +guint32 +nm_ip4_config_get_wins (const NMIP4Config *config, guint i) { - GSList *iter_a, *iter_b; - gboolean found = FALSE; - - for (iter_a = a; iter_a; iter_a = g_slist_next (iter_a)) { - NMIP4Address *addr_a = (NMIP4Address *) iter_a->data; - - for (iter_b = b, found = FALSE; iter_b; iter_b = g_slist_next (iter_b)) { - NMIP4Address *addr_b = (NMIP4Address *) iter_b->data; - - if (nm_ip4_address_compare (addr_a, addr_b)) { - found = TRUE; - break; - } - } + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); - if (!found) - return FALSE; - } - return TRUE; + return g_array_index (priv->wins, guint32, i); } -static gboolean -route_slist_compare (GSList *a, GSList *b) -{ - GSList *iter_a, *iter_b; - gboolean found = FALSE; - - for (iter_a = a; iter_a; iter_a = g_slist_next (iter_a)) { - NMIP4Route *route_a = (NMIP4Route *) iter_a->data; - - for (iter_b = b, found = FALSE; iter_b; iter_b = g_slist_next (iter_b)) { - NMIP4Route *route_b = (NMIP4Route *) iter_b->data; - - if (nm_ip4_route_compare (route_a, route_b)) { - found = TRUE; - break; - } - } - - if (!found) - return FALSE; - } - return TRUE; -} +/******************************************************************/ -static gboolean -string_array_compare (GPtrArray *a, GPtrArray *b) +void +nm_ip4_config_set_mtu (NMIP4Config *config, guint32 mtu) { - int i, j; - gboolean found = FALSE; - - for (i = 0; i < a->len; i++) { - for (j = 0, found = FALSE; j < b->len; j++) { - const char *item_a = g_ptr_array_index (a, i); - const char *item_b = g_ptr_array_index (b, j); - - if ((!item_a && !item_b) || (item_a && item_b && !strcmp (item_a, item_b))) { - found = TRUE; - break; - } - } + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); - if (!found) - return FALSE; - } - return TRUE; + priv->mtu = mtu; } -static gboolean -addr_array_compare (GArray *a, GArray *b) +guint32 +nm_ip4_config_get_mtu (const NMIP4Config *config) { - int i, j; - gboolean found = FALSE; - - for (i = 0; i < a->len; i++) { - for (j = 0, found = FALSE; j < b->len; j++) { - if (g_array_index (a, guint32, i) == g_array_index (b, guint32, j)) { - found = TRUE; - break; - } - } + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); - if (!found) - return FALSE; - } - return TRUE; + return priv->mtu; } -NMIP4ConfigCompareFlags -nm_ip4_config_diff (NMIP4Config *a, NMIP4Config *b) -{ - NMIP4ConfigPrivate *a_priv; - NMIP4ConfigPrivate *b_priv; - NMIP4ConfigCompareFlags flags = NM_IP4_COMPARE_FLAG_NONE; - - if ((a && !b) || (b && !a)) - return NM_IP4_COMPARE_FLAG_ALL; - if (!a && !b) - return NM_IP4_COMPARE_FLAG_NONE; - - a_priv = NM_IP4_CONFIG_GET_PRIVATE (a); - b_priv = NM_IP4_CONFIG_GET_PRIVATE (b); - - if ( !addr_slist_compare (a_priv->addresses, b_priv->addresses) - || !addr_slist_compare (b_priv->addresses, a_priv->addresses)) - flags |= NM_IP4_COMPARE_FLAG_ADDRESSES; - - if (a_priv->ptp_address != b_priv->ptp_address) - flags |= NM_IP4_COMPARE_FLAG_PTP_ADDRESS; - - if ( (a_priv->nameservers->len != b_priv->nameservers->len) - || !addr_array_compare (a_priv->nameservers, b_priv->nameservers) - || !addr_array_compare (b_priv->nameservers, a_priv->nameservers)) - flags |= NM_IP4_COMPARE_FLAG_NAMESERVERS; - - if ( (a_priv->wins->len != b_priv->wins->len) - || !addr_array_compare (a_priv->wins, b_priv->wins) - || !addr_array_compare (b_priv->wins, a_priv->wins)) - flags |= NM_IP4_COMPARE_FLAG_WINS_SERVERS; - - if ( (a_priv->nis->len != b_priv->nis->len) - || !addr_array_compare (a_priv->nis, b_priv->nis) - || !addr_array_compare (b_priv->nis, a_priv->nis)) - flags |= NM_IP4_COMPARE_FLAG_NIS_SERVERS; - - if ( (a_priv->nis_domain || b_priv->nis_domain) - && (g_strcmp0 (a_priv->nis_domain, b_priv->nis_domain) != 0)) - flags |= NM_IP4_COMPARE_FLAG_NIS_DOMAIN; - - if ( !route_slist_compare (a_priv->routes, b_priv->routes) - || !route_slist_compare (b_priv->routes, a_priv->routes)) - flags |= NM_IP4_COMPARE_FLAG_ROUTES; - - if ( (a_priv->domains->len != b_priv->domains->len) - || !string_array_compare (a_priv->domains, b_priv->domains) - || !string_array_compare (b_priv->domains, a_priv->domains)) - flags |= NM_IP4_COMPARE_FLAG_DOMAINS; - - if ( (a_priv->searches->len != b_priv->searches->len) - || !string_array_compare (a_priv->searches, b_priv->searches) - || !string_array_compare (b_priv->searches, a_priv->searches)) - flags |= NM_IP4_COMPARE_FLAG_SEARCHES; - - if (a_priv->mtu != b_priv->mtu) - flags |= NM_IP4_COMPARE_FLAG_MTU; - - if (a_priv->mss != b_priv->mss) - flags |= NM_IP4_COMPARE_FLAG_MSS; - - return flags; -} +/******************************************************************/ static inline void hash_u32 (GChecksum *sum, guint32 n) @@ -820,36 +1527,32 @@ hash_u32 (GChecksum *sum, guint32 n) } void -nm_ip4_config_hash (NMIP4Config *config, GChecksum *sum, gboolean dns_only) +nm_ip4_config_hash (const NMIP4Config *config, GChecksum *sum, gboolean dns_only) { - guint32 i, n; + guint32 i; const char *s; - g_return_if_fail (config != NULL); - g_return_if_fail (sum != NULL); + g_return_if_fail (config); + g_return_if_fail (sum); - if (dns_only == FALSE) { - for (i = 0; i < nm_ip4_config_get_num_addresses (config); i++) { - NMIP4Address *a = nm_ip4_config_get_address (config, i); + if (!dns_only) { + hash_u32 (sum, nm_ip4_config_get_gateway (config)); - hash_u32 (sum, nm_ip4_address_get_address (a)); - hash_u32 (sum, nm_ip4_address_get_prefix (a)); - hash_u32 (sum, nm_ip4_address_get_gateway (a)); + for (i = 0; i < nm_ip4_config_get_num_addresses (config); i++) { + const NMPlatformIP4Address *address = nm_ip4_config_get_address (config, i); + hash_u32 (sum, address->address); + hash_u32 (sum, address->plen); } for (i = 0; i < nm_ip4_config_get_num_routes (config); i++) { - NMIP4Route *r = nm_ip4_config_get_route (config, i); + const NMPlatformIP4Route *route = nm_ip4_config_get_route (config, i); - hash_u32 (sum, nm_ip4_route_get_dest (r)); - hash_u32 (sum, nm_ip4_route_get_prefix (r)); - hash_u32 (sum, nm_ip4_route_get_next_hop (r)); - hash_u32 (sum, nm_ip4_route_get_metric (r)); + hash_u32 (sum, route->network); + hash_u32 (sum, route->plen); + hash_u32 (sum, route->gateway); + hash_u32 (sum, route->metric); } - n = nm_ip4_config_get_ptp_address (config); - if (n) - hash_u32 (sum, n); - for (i = 0; i < nm_ip4_config_get_num_nis_servers (config); i++) hash_u32 (sum, nm_ip4_config_get_nis_server (config, i)); @@ -875,16 +1578,60 @@ nm_ip4_config_hash (NMIP4Config *config, GChecksum *sum, gboolean dns_only) } } +/** + * nm_ip4_config_equal: + * @a: first config to compare + * @b: second config to compare + * + * Compares two #NMIP4Configs for basic equality. This means that all + * attributes must exist in the same order in both configs (addresses, routes, + * domains, DNS servers, etc) but some attributes (address lifetimes, and address + * and route sources) are ignored. + * + * Returns: %TRUE if the configurations are basically equal to each other, + * %FALSE if not + */ +gboolean +nm_ip4_config_equal (const NMIP4Config *a, const NMIP4Config *b) +{ + GChecksum *a_checksum = g_checksum_new (G_CHECKSUM_SHA1); + GChecksum *b_checksum = g_checksum_new (G_CHECKSUM_SHA1); + gsize a_len = g_checksum_type_get_length (G_CHECKSUM_SHA1); + gsize b_len = g_checksum_type_get_length (G_CHECKSUM_SHA1); + guchar a_data[a_len], b_data[b_len]; + gboolean equal; + + if (a) + nm_ip4_config_hash (a, a_checksum, FALSE); + if (b) + nm_ip4_config_hash (b, b_checksum, FALSE); + + g_checksum_get_digest (a_checksum, a_data, &a_len); + g_checksum_get_digest (b_checksum, b_data, &b_len); + + g_assert (a_len == b_len); + equal = !memcmp (a_data, b_data, a_len); + + g_checksum_free (a_checksum); + g_checksum_free (b_checksum); + + return equal; +} + +/******************************************************************/ + static void nm_ip4_config_init (NMIP4Config *config) { NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); - priv->nameservers = g_array_new (FALSE, TRUE, sizeof (guint32)); - priv->wins = g_array_new (FALSE, TRUE, sizeof (guint32)); - priv->domains = g_ptr_array_sized_new (3); - priv->searches = g_ptr_array_sized_new (3); + priv->addresses = g_array_new (FALSE, FALSE, sizeof (NMPlatformIP4Address)); + priv->routes = g_array_new (FALSE, FALSE, sizeof (NMPlatformIP4Route)); + priv->nameservers = g_array_new (FALSE, FALSE, sizeof (guint32)); + priv->domains = g_ptr_array_new_with_free_func (g_free); + priv->searches = g_ptr_array_new_with_free_func (g_free); priv->nis = g_array_new (FALSE, TRUE, sizeof (guint32)); + priv->wins = g_array_new (FALSE, TRUE, sizeof (guint32)); } static void @@ -892,14 +1639,14 @@ finalize (GObject *object) { NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (object); - nm_utils_slist_free (priv->addresses, (GDestroyNotify) nm_ip4_address_unref); - nm_utils_slist_free (priv->routes, (GDestroyNotify) nm_ip4_route_unref); - g_array_free (priv->wins, TRUE); - g_array_free (priv->nameservers, TRUE); - g_ptr_array_free (priv->domains, TRUE); - g_ptr_array_free (priv->searches, TRUE); - g_array_free (priv->nis, TRUE); + g_array_unref (priv->addresses); + g_array_unref (priv->routes); + g_array_unref (priv->nameservers); + g_ptr_array_unref (priv->domains); + g_ptr_array_unref (priv->searches); + g_array_unref (priv->nis); g_free (priv->nis_domain); + g_array_unref (priv->wins); G_OBJECT_CLASS (nm_ip4_config_parent_class)->finalize (object); } @@ -908,11 +1655,56 @@ static void get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { + NMIP4Config *config = NM_IP4_CONFIG (object); NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (object); switch (prop_id) { + case PROP_GATEWAY: + if (priv->gateway) + g_value_set_string (value, nm_utils_inet4_ntop (priv->gateway, NULL)); + else + g_value_set_string (value, NULL); + break; case PROP_ADDRESSES: - nm_utils_ip4_addresses_to_gvalue (priv->addresses, value); + { + GPtrArray *addresses = g_ptr_array_new (); + int naddr = nm_ip4_config_get_num_addresses (config); + int i; + + for (i = 0; i < naddr; i++) { + const NMPlatformIP4Address *address = nm_ip4_config_get_address (config, i); + GArray *array = g_array_sized_new (FALSE, TRUE, sizeof (guint32), 3); + + g_array_append_val (array, address->address); + g_array_append_val (array, address->plen); + g_array_append_val (array, priv->gateway); + + g_ptr_array_add (addresses, array); + } + + g_value_take_boxed (value, addresses); + } + break; + case PROP_ROUTES: + { + GPtrArray *routes = g_ptr_array_new (); + guint nroutes = nm_ip4_config_get_num_routes (config); + int i; + + for (i = 0; i < nroutes; i++) { + const NMPlatformIP4Route *route = nm_ip4_config_get_route (config, i); + GArray *array = g_array_sized_new (FALSE, TRUE, sizeof (guint32), 4); + + g_array_append_val (array, route->network); + g_array_append_val (array, route->plen); + g_array_append_val (array, route->gateway); + g_array_append_val (array, route->metric); + + g_ptr_array_add (routes, array); + } + + g_value_take_boxed (value, routes); + } break; case PROP_NAMESERVERS: g_value_set_boxed (value, priv->nameservers); @@ -920,8 +1712,8 @@ get_property (GObject *object, guint prop_id, case PROP_DOMAINS: g_value_set_boxed (value, priv->domains); break; - case PROP_ROUTES: - nm_utils_ip4_routes_to_gvalue (priv->routes, value); + case PROP_SEARCHES: + g_value_set_boxed (value, priv->searches); break; case PROP_WINS_SERVERS: g_value_set_boxed (value, priv->wins); @@ -939,47 +1731,55 @@ nm_ip4_config_class_init (NMIP4ConfigClass *config_class) g_type_class_add_private (config_class, sizeof (NMIP4ConfigPrivate)); - /* virtual methods */ object_class->get_property = get_property; object_class->finalize = finalize; - /* properties */ - g_object_class_install_property - (object_class, PROP_ADDRESSES, + obj_properties[PROP_GATEWAY] = + g_param_spec_string (NM_IP4_CONFIG_GATEWAY, + "Gateway", + "IP4 gateway", + NULL, + G_PARAM_READABLE); + obj_properties[PROP_ADDRESSES] = g_param_spec_boxed (NM_IP4_CONFIG_ADDRESSES, - "Addresses", - "IP4 addresses", - DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UINT, - G_PARAM_READABLE)); - g_object_class_install_property - (object_class, PROP_NAMESERVERS, + "Addresses", + "IP4 addresses", + DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UINT, + G_PARAM_READABLE); + obj_properties[PROP_ROUTES] = + g_param_spec_boxed (NM_IP4_CONFIG_ROUTES, + "Routes", + "Routes", + DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UINT, + G_PARAM_READABLE); + obj_properties[PROP_NAMESERVERS] = g_param_spec_boxed (NM_IP4_CONFIG_NAMESERVERS, - "Nameservers", - "DNS list", - DBUS_TYPE_G_UINT_ARRAY, - G_PARAM_READABLE)); - g_object_class_install_property - (object_class, PROP_DOMAINS, + "Nameservers", + "DNS list", + DBUS_TYPE_G_UINT_ARRAY, + G_PARAM_READABLE); + obj_properties[PROP_DOMAINS] = g_param_spec_boxed (NM_IP4_CONFIG_DOMAINS, - "Domains", - "Domains", - DBUS_TYPE_G_ARRAY_OF_STRING, - G_PARAM_READABLE)); - g_object_class_install_property - (object_class, PROP_ROUTES, - g_param_spec_boxed (NM_IP4_CONFIG_ROUTES, - "Routes", - "Routes", - DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UINT, - G_PARAM_READABLE)); - g_object_class_install_property - (object_class, PROP_WINS_SERVERS, + "Domains", + "Domains", + DBUS_TYPE_G_ARRAY_OF_STRING, + G_PARAM_READABLE); + obj_properties[PROP_SEARCHES] = + g_param_spec_boxed (NM_IP4_CONFIG_SEARCHES, + "Searches", + "Searches", + DBUS_TYPE_G_ARRAY_OF_STRING, + G_PARAM_READABLE); + obj_properties[PROP_WINS_SERVERS] = g_param_spec_boxed (NM_IP4_CONFIG_WINS_SERVERS, - "WinsServers", - "WINS server list", - DBUS_TYPE_G_UINT_ARRAY, - G_PARAM_READABLE)); + "WinsServers", + "WINS server list", + DBUS_TYPE_G_UINT_ARRAY, + G_PARAM_READABLE); + + g_object_class_install_properties (object_class, LAST_PROP, obj_properties); - dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (config_class), - &dbus_glib_nm_ip4_config_object_info); + nm_dbus_manager_register_exported_type (nm_dbus_manager_get (), + G_TYPE_FROM_CLASS (config_class), + &dbus_glib_nm_ip4_config_object_info); } diff --git a/src/nm-ip4-config.h b/src/nm-ip4-config.h index 5433768c..c9096bb3 100644 --- a/src/nm-ip4-config.h +++ b/src/nm-ip4-config.h @@ -1,5 +1,5 @@ /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager +/* NetworkManager * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -15,23 +15,23 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright (C) 2008 Red Hat, Inc. + * Copyright (C) 2008–2013 Red Hat, Inc. */ #ifndef NM_IP4_CONFIG_H #define NM_IP4_CONFIG_H -#include #include +#include "nm-platform.h" #include "nm-setting-ip4-config.h" -#define NM_TYPE_IP4_CONFIG (nm_ip4_config_get_type ()) -#define NM_IP4_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_IP4_CONFIG, NMIP4Config)) -#define NM_IP4_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_IP4_CONFIG, NMIP4ConfigClass)) -#define NM_IS_IP4_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_IP4_CONFIG)) +#define NM_TYPE_IP4_CONFIG (nm_ip4_config_get_type ()) +#define NM_IP4_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_IP4_CONFIG, NMIP4Config)) +#define NM_IP4_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_IP4_CONFIG, NMIP4ConfigClass)) +#define NM_IS_IP4_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_IP4_CONFIG)) #define NM_IS_IP4_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_IP4_CONFIG)) -#define NM_IP4_CONFIG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_IP4_CONFIG, NMIP4ConfigClass)) +#define NM_IP4_CONFIG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_IP4_CONFIG, NMIP4ConfigClass)) typedef struct { GObject parent; @@ -41,104 +41,109 @@ typedef struct { GObjectClass parent; } NMIP4ConfigClass; +#define NM_IP4_CONFIG_GATEWAY "gateway" #define NM_IP4_CONFIG_ADDRESSES "addresses" +#define NM_IP4_CONFIG_ROUTES "routes" #define NM_IP4_CONFIG_NAMESERVERS "nameservers" #define NM_IP4_CONFIG_DOMAINS "domains" -#define NM_IP4_CONFIG_ROUTES "routes" +#define NM_IP4_CONFIG_SEARCHES "searches" #define NM_IP4_CONFIG_WINS_SERVERS "wins-servers" GType nm_ip4_config_get_type (void); -NMIP4Config * nm_ip4_config_new (void); -void nm_ip4_config_export (NMIP4Config *config); -const char * nm_ip4_config_get_dbus_path (NMIP4Config *config); - -void nm_ip4_config_take_address (NMIP4Config *config, NMIP4Address *address); -void nm_ip4_config_add_address (NMIP4Config *config, NMIP4Address *address); -void nm_ip4_config_replace_address (NMIP4Config *config, guint32 i, NMIP4Address *new_address); -NMIP4Address *nm_ip4_config_get_address (NMIP4Config *config, guint32 i); -guint32 nm_ip4_config_get_num_addresses (NMIP4Config *config); - -guint32 nm_ip4_config_get_ptp_address (NMIP4Config *config); -void nm_ip4_config_set_ptp_address (NMIP4Config *config, guint32 ptp_addr); - -void nm_ip4_config_add_nameserver (NMIP4Config *config, guint32 nameserver); -guint32 nm_ip4_config_get_nameserver (NMIP4Config *config, guint i); -guint32 nm_ip4_config_get_num_nameservers (NMIP4Config *config); -void nm_ip4_config_reset_nameservers (NMIP4Config *config); - -void nm_ip4_config_add_wins (NMIP4Config *config, guint32 wins); -guint32 nm_ip4_config_get_wins (NMIP4Config *config, guint i); -guint32 nm_ip4_config_get_num_wins (NMIP4Config *config); -void nm_ip4_config_reset_wins (NMIP4Config *config); - -void nm_ip4_config_take_route (NMIP4Config *config, NMIP4Route *route); -void nm_ip4_config_add_route (NMIP4Config *config, NMIP4Route *route); -void nm_ip4_config_replace_route (NMIP4Config *config, guint32 i, NMIP4Route *new_route); -NMIP4Route * nm_ip4_config_get_route (NMIP4Config *config, guint32 i); -guint32 nm_ip4_config_get_num_routes (NMIP4Config *config); -void nm_ip4_config_reset_routes (NMIP4Config *config); - -void nm_ip4_config_add_domain (NMIP4Config *config, const char *domain); -const char * nm_ip4_config_get_domain (NMIP4Config *config, guint i); -guint32 nm_ip4_config_get_num_domains (NMIP4Config *config); -void nm_ip4_config_reset_domains (NMIP4Config *config); - -void nm_ip4_config_add_search (NMIP4Config *config, const char *search); -const char * nm_ip4_config_get_search (NMIP4Config *config, guint i); -guint32 nm_ip4_config_get_num_searches (NMIP4Config *config); -void nm_ip4_config_reset_searches (NMIP4Config *config); - -guint32 nm_ip4_config_get_mtu (NMIP4Config *config); -void nm_ip4_config_set_mtu (NMIP4Config *config, guint32 mtu); - -guint32 nm_ip4_config_get_mss (NMIP4Config *config); -void nm_ip4_config_set_mss (NMIP4Config *config, guint32 mss); - -gboolean nm_ip4_config_get_never_default (NMIP4Config *config); -void nm_ip4_config_set_never_default (NMIP4Config *config, gboolean never_default); - -void nm_ip4_config_add_nis_server (NMIP4Config *config, guint32 nis); -guint32 nm_ip4_config_get_nis_server (NMIP4Config *config, guint i); -guint32 nm_ip4_config_get_num_nis_servers (NMIP4Config *config); -void nm_ip4_config_reset_nis_servers (NMIP4Config *config); - -void nm_ip4_config_set_nis_domain (NMIP4Config *config, const char *domain); -const char * nm_ip4_config_get_nis_domain (NMIP4Config *config); - - -/* Flags for nm_ip4_config_to_rtnl_addr() */ -#define NM_RTNL_ADDR_NONE 0x0000 -#define NM_RTNL_ADDR_ADDR 0x0001 -#define NM_RTNL_ADDR_PTP_ADDR 0x0002 -#define NM_RTNL_ADDR_PREFIX 0x0004 -#define NM_RTNL_ADDR_BROADCAST 0x0008 - -#define NM_RTNL_ADDR_DEFAULT (NM_RTNL_ADDR_ADDR | NM_RTNL_ADDR_PREFIX | NM_RTNL_ADDR_BROADCAST) -#define NM_RTNL_ADDR_PTP_DEFAULT (NM_RTNL_ADDR_ADDR | NM_RTNL_ADDR_PREFIX | NM_RTNL_ADDR_PTP_ADDR) - -struct rtnl_addr *nm_ip4_config_to_rtnl_addr (NMIP4Config *config, guint32 i, guint32 flags); - -typedef enum { - NM_IP4_COMPARE_FLAG_NONE = 0x00000000, /* match nothing, kinda pointless */ - NM_IP4_COMPARE_FLAG_ADDRESSES = 0x00000001, - NM_IP4_COMPARE_FLAG_PTP_ADDRESS = 0x00000002, - NM_IP4_COMPARE_FLAG_NAMESERVERS = 0x00000004, - NM_IP4_COMPARE_FLAG_ROUTES = 0x00000008, - NM_IP4_COMPARE_FLAG_DOMAINS = 0x00000010, - NM_IP4_COMPARE_FLAG_SEARCHES = 0x00000020, - NM_IP4_COMPARE_FLAG_MTU = 0x00000040, - NM_IP4_COMPARE_FLAG_MSS = 0x00000080, - NM_IP4_COMPARE_FLAG_WINS_SERVERS= 0x00000100, - NM_IP4_COMPARE_FLAG_NIS_SERVERS = 0x00000200, - NM_IP4_COMPARE_FLAG_NIS_DOMAIN = 0x00000400, - NM_IP4_COMPARE_FLAG_ALL = 0xFFFFFFFF /* match everything */ -} NMIP4ConfigCompareFlags; - -/* Returns a bitfield representing how the two IP4 configs differ */ -NMIP4ConfigCompareFlags nm_ip4_config_diff (NMIP4Config *a, NMIP4Config *b); - -void nm_ip4_config_hash (NMIP4Config *config, GChecksum *sum, gboolean dns_only); +NMIP4Config * nm_ip4_config_new (void); + +/* D-Bus integration */ +void nm_ip4_config_export (NMIP4Config *config); +const char * nm_ip4_config_get_dbus_path (const NMIP4Config *config); + +/* Integration with nm-platform and nm-setting */ +NMIP4Config *nm_ip4_config_capture (int ifindex, gboolean capture_resolv_conf); +gboolean nm_ip4_config_commit (const NMIP4Config *config, int ifindex); +void nm_ip4_config_merge_setting (NMIP4Config *config, NMSettingIP4Config *setting, int default_route_metric); +NMSetting *nm_ip4_config_create_setting (const NMIP4Config *config); + +/* Utility functions */ +void nm_ip4_config_merge (NMIP4Config *dst, const NMIP4Config *src); +void nm_ip4_config_subtract (NMIP4Config *dst, const NMIP4Config *src); +gboolean nm_ip4_config_replace (NMIP4Config *dst, const NMIP4Config *src, gboolean *relevant_changes); +gboolean nm_ip4_config_destination_is_direct (const NMIP4Config *config, guint32 dest, int plen); +void nm_ip4_config_dump (const NMIP4Config *config, const char *detail); + +/* Gateways */ +void nm_ip4_config_set_never_default (NMIP4Config *config, gboolean never_default); +gboolean nm_ip4_config_get_never_default (const NMIP4Config *config); +void nm_ip4_config_set_gateway (NMIP4Config *config, guint32 gateway); +guint32 nm_ip4_config_get_gateway (const NMIP4Config *config); + +/* Addresses */ +void nm_ip4_config_reset_addresses (NMIP4Config *config); +void nm_ip4_config_add_address (NMIP4Config *config, const NMPlatformIP4Address *address); +void nm_ip4_config_del_address (NMIP4Config *config, guint i); +guint nm_ip4_config_get_num_addresses (const NMIP4Config *config); +const NMPlatformIP4Address *nm_ip4_config_get_address (const NMIP4Config *config, guint i); +gboolean nm_ip4_config_address_exists (const NMIP4Config *config, const NMPlatformIP4Address *address); + +/* Routes */ +void nm_ip4_config_reset_routes (NMIP4Config *config); +void nm_ip4_config_add_route (NMIP4Config *config, const NMPlatformIP4Route *route); +void nm_ip4_config_del_route (NMIP4Config *config, guint i); +guint32 nm_ip4_config_get_num_routes (const NMIP4Config *config); +const NMPlatformIP4Route *nm_ip4_config_get_route (const NMIP4Config *config, guint32 i); + +/* Nameservers */ +void nm_ip4_config_reset_nameservers (NMIP4Config *config); +void nm_ip4_config_add_nameserver (NMIP4Config *config, guint32 nameserver); +void nm_ip4_config_del_nameserver (NMIP4Config *config, guint i); +guint32 nm_ip4_config_get_num_nameservers (const NMIP4Config *config); +guint32 nm_ip4_config_get_nameserver (const NMIP4Config *config, guint i); + +/* Domains */ +void nm_ip4_config_reset_domains (NMIP4Config *config); +void nm_ip4_config_add_domain (NMIP4Config *config, const char *domain); +void nm_ip4_config_del_domain (NMIP4Config *config, guint i); +guint32 nm_ip4_config_get_num_domains (const NMIP4Config *config); +const char * nm_ip4_config_get_domain (const NMIP4Config *config, guint i); + +/* Search lists */ +void nm_ip4_config_reset_searches (NMIP4Config *config); +void nm_ip4_config_add_search (NMIP4Config *config, const char *search); +void nm_ip4_config_del_search (NMIP4Config *config, guint i); +guint32 nm_ip4_config_get_num_searches (const NMIP4Config *config); +const char * nm_ip4_config_get_search (const NMIP4Config *config, guint i); + +/* MSS */ +void nm_ip4_config_set_mss (NMIP4Config *config, guint32 mss); +guint32 nm_ip4_config_get_mss (const NMIP4Config *config); + +/* NIS */ +void nm_ip4_config_reset_nis_servers (NMIP4Config *config); +void nm_ip4_config_add_nis_server (NMIP4Config *config, guint32 nis); +void nm_ip4_config_del_nis_server (NMIP4Config *config, guint i); +guint32 nm_ip4_config_get_num_nis_servers (const NMIP4Config *config); +guint32 nm_ip4_config_get_nis_server (const NMIP4Config *config, guint i); +void nm_ip4_config_set_nis_domain (NMIP4Config *config, const char *domain); +const char * nm_ip4_config_get_nis_domain (const NMIP4Config *config); + +/* WINS */ +void nm_ip4_config_reset_wins (NMIP4Config *config); +void nm_ip4_config_add_wins (NMIP4Config *config, guint32 wins); +void nm_ip4_config_del_wins (NMIP4Config *config, guint i); +guint32 nm_ip4_config_get_num_wins (const NMIP4Config *config); +guint32 nm_ip4_config_get_wins (const NMIP4Config *config, guint i); + +/* MTU */ +void nm_ip4_config_set_mtu (NMIP4Config *config, guint32 mtu); +guint32 nm_ip4_config_get_mtu (const NMIP4Config *config); + +void nm_ip4_config_hash (const NMIP4Config *config, GChecksum *sum, gboolean dns_only); +gboolean nm_ip4_config_equal (const NMIP4Config *a, const NMIP4Config *b); + +/******************************************************/ +/* Testing-only functions */ + +gboolean nm_ip4_config_capture_resolv_conf (GArray *nameservers, + const char *rc_contents); #endif /* NM_IP4_CONFIG_H */ diff --git a/src/nm-ip6-config-glue.h b/src/nm-ip6-config-glue.h new file mode 100644 index 00000000..62fbe1c5 --- /dev/null +++ b/src/nm-ip6-config-glue.h @@ -0,0 +1,73 @@ +/* Generated by dbus-binding-tool; do not edit! */ + + +#ifndef __dbus_glib_marshal_nm_ip6_config_MARSHAL_H__ +#define __dbus_glib_marshal_nm_ip6_config_MARSHAL_H__ + +#include + +G_BEGIN_DECLS + +#ifdef G_ENABLE_DEBUG +#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v) +#define g_marshal_value_peek_char(v) g_value_get_schar (v) +#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v) +#define g_marshal_value_peek_int(v) g_value_get_int (v) +#define g_marshal_value_peek_uint(v) g_value_get_uint (v) +#define g_marshal_value_peek_long(v) g_value_get_long (v) +#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v) +#define g_marshal_value_peek_int64(v) g_value_get_int64 (v) +#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v) +#define g_marshal_value_peek_enum(v) g_value_get_enum (v) +#define g_marshal_value_peek_flags(v) g_value_get_flags (v) +#define g_marshal_value_peek_float(v) g_value_get_float (v) +#define g_marshal_value_peek_double(v) g_value_get_double (v) +#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v) +#define g_marshal_value_peek_param(v) g_value_get_param (v) +#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v) +#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v) +#define g_marshal_value_peek_object(v) g_value_get_object (v) +#define g_marshal_value_peek_variant(v) g_value_get_variant (v) +#else /* !G_ENABLE_DEBUG */ +/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API. + * Do not access GValues directly in your code. Instead, use the + * g_value_get_*() functions + */ +#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int +#define g_marshal_value_peek_char(v) (v)->data[0].v_int +#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint +#define g_marshal_value_peek_int(v) (v)->data[0].v_int +#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint +#define g_marshal_value_peek_long(v) (v)->data[0].v_long +#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 +#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 +#define g_marshal_value_peek_enum(v) (v)->data[0].v_long +#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_float(v) (v)->data[0].v_float +#define g_marshal_value_peek_double(v) (v)->data[0].v_double +#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer +#endif /* !G_ENABLE_DEBUG */ + + +G_END_DECLS + +#endif /* __dbus_glib_marshal_nm_ip6_config_MARSHAL_H__ */ + +#include +static const DBusGMethodInfo dbus_glib_nm_ip6_config_methods[] = { +}; + +const DBusGObjectInfo dbus_glib_nm_ip6_config_object_info = { 1, + dbus_glib_nm_ip6_config_methods, + 0, +"\0", +"org.freedesktop.NetworkManager.IP6Config\0PropertiesChanged\0\0", +"org.freedesktop.NetworkManager.IP6Config\0Gateway\0gateway\0read\0org.freedesktop.NetworkManager.IP6Config\0Addresses\0addresses\0read\0org.freedesktop.NetworkManager.IP6Config\0Routes\0routes\0read\0org.freedesktop.NetworkManager.IP6Config\0Nameservers\0nameservers\0read\0org.freedesktop.NetworkManager.IP6Config\0Domains\0domains\0read\0org.freedesktop.NetworkManager.IP6Config\0Searches\0searches\0read\0\0" +}; + diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c index 511cbf46..aaf5e701 100644 --- a/src/nm-ip6-config.c +++ b/src/nm-ip6-config.c @@ -15,27 +15,22 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright (C) 2005 - 2010 Red Hat, Inc. + * Copyright (C) 2005 - 2013 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. */ -#include -#include #include -#include "nm-ip6-config.h" -#include "nm-dbus-manager.h" -#include "NetworkManager.h" -#include "NetworkManagerUtils.h" -#include "nm-setting-ip6-config.h" -#include "nm-utils.h" -#include -#include -#include +#include "nm-ip6-config.h" -#include "nm-ip6-config-glue.h" +#include "nm-glib-compat.h" +#include "libgsystem.h" +#include "nm-platform.h" +#include "nm-utils.h" +#include "nm-dbus-manager.h" #include "nm-dbus-glib-types.h" - +#include "nm-ip6-config-glue.h" +#include "NetworkManagerUtils.h" G_DEFINE_TYPE (NMIP6Config, nm_ip6_config, G_TYPE_OBJECT) @@ -44,48 +39,30 @@ G_DEFINE_TYPE (NMIP6Config, nm_ip6_config, G_TYPE_OBJECT) typedef struct { char *path; - GSList *addresses; - struct in6_addr ptp_address; - - guint32 mss; /* Maximum Segment Size of the route */ - + gboolean never_default; + struct in6_addr gateway; + GArray *addresses; + GArray *routes; GArray *nameservers; GPtrArray *domains; GPtrArray *searches; - - gboolean gateway_set; - struct in6_addr gateway; - GSList *routes; - - gboolean never_default; + guint32 mss; } NMIP6ConfigPrivate; enum { PROP_0, + PROP_GATEWAY, PROP_ADDRESSES, + PROP_ROUTES, PROP_NAMESERVERS, PROP_DOMAINS, - PROP_ROUTES, + PROP_SEARCHES, LAST_PROP }; - - -static struct nl_addr * -nm_utils_ip6_addr_to_nl_addr (const struct in6_addr *ip6_addr, guint prefix) -{ - struct nl_addr * nla = NULL; - - if (!(nla = nl_addr_alloc (sizeof (struct in6_addr)))) - return NULL; - nl_addr_set_family (nla, AF_INET6); - nl_addr_set_binary_addr (nla, (struct in6_addr *)ip6_addr, sizeof (struct in6_addr)); - if (prefix) - nl_addr_set_prefixlen (nla, prefix); - - return nla; -} +static GParamSpec *obj_properties[LAST_PROP] = { NULL, }; +#define _NOTIFY(config, prop) G_STMT_START { g_object_notify_by_pspec (G_OBJECT (config), obj_properties[prop]); } G_STMT_END NMIP6Config * @@ -97,586 +74,1316 @@ nm_ip6_config_new (void) void nm_ip6_config_export (NMIP6Config *config) { - NMIP6ConfigPrivate *priv; - NMDBusManager *dbus_mgr; - DBusGConnection *connection; + NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); static guint32 counter = 0; - g_return_if_fail (NM_IS_IP6_CONFIG (config)); - - priv = NM_IP6_CONFIG_GET_PRIVATE (config); - g_return_if_fail (priv->path == NULL); - - dbus_mgr = nm_dbus_manager_get (); - connection = nm_dbus_manager_get_connection (dbus_mgr); - priv->path = g_strdup_printf (NM_DBUS_PATH "/IP6Config/%d", counter++); - - dbus_g_connection_register_g_object (connection, priv->path, G_OBJECT (config)); - g_object_unref (dbus_mgr); + if (!priv->path) { + priv->path = g_strdup_printf (NM_DBUS_PATH "/IP6Config/%d", counter++); + nm_dbus_manager_register_object (nm_dbus_manager_get (), priv->path, config); + } } const char * -nm_ip6_config_get_dbus_path (NMIP6Config *config) +nm_ip6_config_get_dbus_path (const NMIP6Config *config) { - g_return_val_if_fail (NM_IS_IP6_CONFIG (config), NULL); + NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); - return NM_IP6_CONFIG_GET_PRIVATE (config)->path; + return priv->path; } -void -nm_ip6_config_take_address (NMIP6Config *config, NMIP6Address *address) +/******************************************************************/ + +static gboolean +same_prefix (const struct in6_addr *address1, const struct in6_addr *address2, int plen) { - NMIP6ConfigPrivate *priv; + const guint8 *bytes1 = (const guint8 *) address1; + const guint8 *bytes2 = (const guint8 *) address2; + int nbytes = plen / 8; + int nbits = plen % 8; + int masked1 = bytes1[nbytes] >> (8 - nbits); + int masked2 = bytes2[nbytes] >> (8 - nbits); - g_return_if_fail (NM_IS_IP6_CONFIG (config)); - g_return_if_fail (address != NULL); + if (nbytes && memcmp (bytes1, bytes2, nbytes)) + return FALSE; - priv = NM_IP6_CONFIG_GET_PRIVATE (config); - priv->addresses = g_slist_append (priv->addresses, address); + return masked1 == masked2; } -void -nm_ip6_config_add_address (NMIP6Config *config, - NMIP6Address *address) +/******************************************************************/ + +/** + * nm_ip6_config_capture_resolv_conf(): + * @nameservers: array of struct in6_addr + * @rc_contents: the contents of a resolv.conf or %NULL to read /etc/resolv.conf + * + * Reads all resolv.conf IPv6 nameservers and adds them to @nameservers. + * + * Returns: %TRUE if nameservers were added, %FALSE if @nameservers is unchanged + */ +gboolean +nm_ip6_config_capture_resolv_conf (GArray *nameservers, + const char *rc_contents) { - NMIP6ConfigPrivate *priv; - GSList *iter; + GPtrArray *read_ns; + guint i, j; + gboolean changed = FALSE; - g_return_if_fail (NM_IS_IP6_CONFIG (config)); - g_return_if_fail (address != NULL); + g_return_val_if_fail (nameservers != NULL, FALSE); - priv = NM_IP6_CONFIG_GET_PRIVATE (config); - for (iter = priv->addresses; iter; iter = g_slist_next (iter)) { - if (nm_ip6_address_compare ((NMIP6Address *) iter->data, address)) - return; - } + read_ns = nm_utils_read_resolv_conf_nameservers (rc_contents); + if (!read_ns) + return FALSE; - priv->addresses = g_slist_append (priv->addresses, nm_ip6_address_dup (address)); -} + for (i = 0; i < read_ns->len; i++) { + const char *s = g_ptr_array_index (read_ns, i); + struct in6_addr ns = IN6ADDR_ANY_INIT; -void -nm_ip6_config_replace_address (NMIP6Config *config, - guint i, - NMIP6Address *new_address) -{ - NMIP6ConfigPrivate *priv; - GSList *old; + if (!inet_pton (AF_INET6, s, (void *) &ns) || IN6_IS_ADDR_UNSPECIFIED (&ns)) + continue; - g_return_if_fail (NM_IS_IP6_CONFIG (config)); + /* Ignore duplicates */ + for (j = 0; j < nameservers->len; j++) { + struct in6_addr *t = &g_array_index (nameservers, struct in6_addr, j); - priv = NM_IP6_CONFIG_GET_PRIVATE (config); - old = g_slist_nth (priv->addresses, i); - g_return_if_fail (old != NULL); - nm_ip6_address_unref ((NMIP6Address *) old->data); + if (IN6_ARE_ADDR_EQUAL (t, &ns)) + break; + } + + if (j == nameservers->len) { + g_array_append_val (nameservers, ns); + changed = TRUE; + } + } - old->data = nm_ip6_address_dup (new_address); + g_ptr_array_unref (read_ns); + return changed; } -NMIP6Address *nm_ip6_config_get_address (NMIP6Config *config, guint i) +static gboolean +addresses_are_duplicate (const NMPlatformIP6Address *a, const NMPlatformIP6Address *b, gboolean consider_plen) { - g_return_val_if_fail (NM_IS_IP6_CONFIG (config), NULL); - - return (NMIP6Address *) g_slist_nth_data (NM_IP6_CONFIG_GET_PRIVATE (config)->addresses, i); + return IN6_ARE_ADDR_EQUAL (&a->address, &b->address) && (!consider_plen || a->plen == b->plen); } -guint32 nm_ip6_config_get_num_addresses (NMIP6Config *config) +static gboolean +routes_are_duplicate (const NMPlatformIP6Route *a, const NMPlatformIP6Route *b, gboolean consider_gateway_and_metric) { - g_return_val_if_fail (NM_IS_IP6_CONFIG (config), 0); + return IN6_ARE_ADDR_EQUAL (&a->network, &b->network) && a->plen == b->plen && + (!consider_gateway_and_metric || (IN6_ARE_ADDR_EQUAL (&a->gateway, &b->gateway) && a->metric == b->metric)); +} - return g_slist_length (NM_IP6_CONFIG_GET_PRIVATE (config)->addresses); +static gint +_addresses_sort_cmp_get_prio (const struct in6_addr *addr) +{ + if (IN6_IS_ADDR_V4MAPPED (addr)) + return 0; + if (IN6_IS_ADDR_V4COMPAT (addr)) + return 1; + if (IN6_IS_ADDR_UNSPECIFIED (addr)) + return 2; + if (IN6_IS_ADDR_LOOPBACK (addr)) + return 3; + if (IN6_IS_ADDR_LINKLOCAL (addr)) + return 4; + if (IN6_IS_ADDR_SITELOCAL (addr)) + return 5; + return 6; } -const struct in6_addr *nm_ip6_config_get_ptp_address (NMIP6Config *config) +static gint +_addresses_sort_cmp (gconstpointer a, gconstpointer b, gpointer user_data) { - g_return_val_if_fail (NM_IS_IP6_CONFIG (config), 0); + gint p1, p2, c; + gboolean perm1, perm2, tent1, tent2; + gboolean ipv6_privacy1, ipv6_privacy2; + const NMPlatformIP6Address *a1 = a, *a2 = b; + + /* tentative addresses are always sorted back... */ + /* sort tentative addresses after non-tentative. */ + tent1 = (a1->flags & IFA_F_TENTATIVE); + tent2 = (a2->flags & IFA_F_TENTATIVE); + if (tent1 != tent2) + return tent1 ? 1 : -1; + + /* Sort by address type. For example link local will + * be sorted *after* site local or global. */ + p1 = _addresses_sort_cmp_get_prio (&a1->address); + p2 = _addresses_sort_cmp_get_prio (&a2->address); + if (p1 != p2) + return p1 > p2 ? -1 : 1; + + ipv6_privacy1 = !!(a1->flags & (IFA_F_MANAGETEMPADDR | IFA_F_TEMPORARY)); + ipv6_privacy2 = !!(a2->flags & (IFA_F_MANAGETEMPADDR | IFA_F_TEMPORARY)); + if (ipv6_privacy1 || ipv6_privacy2) { + gboolean prefer_temp = ((NMSettingIP6ConfigPrivacy) GPOINTER_TO_INT (user_data)) == NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR; + gboolean public1 = TRUE, public2 = TRUE; + + if (ipv6_privacy1) { + if (a1->flags & IFA_F_TEMPORARY) + public1 = prefer_temp; + else + public1 = !prefer_temp; + } + if (ipv6_privacy2) { + if (a2->flags & IFA_F_TEMPORARY) + public2 = prefer_temp; + else + public2 = !prefer_temp; + } + + if (public1 != public2) + return public1 ? -1 : 1; + } + + /* Sort the addresses based on their source. */ + if (a1->source != a2->source) + return a1->source > a2->source ? -1 : 1; - return &NM_IP6_CONFIG_GET_PRIVATE (config)->ptp_address; + /* sort permanent addresses before non-permanent. */ + perm1 = (a1->flags & IFA_F_PERMANENT); + perm2 = (a2->flags & IFA_F_PERMANENT); + if (perm1 != perm2) + return perm1 ? -1 : 1; + + /* finally sort addresses lexically */ + c = memcmp (&a1->address, &a2->address, sizeof (a2->address)); + return c != 0 ? c : memcmp (a1, a2, sizeof (*a1)); } -void nm_ip6_config_set_ptp_address (NMIP6Config *config, const struct in6_addr *ptp_addr) +gboolean +nm_ip6_config_addresses_sort (NMIP6Config *self, NMSettingIP6ConfigPrivacy use_temporary) { - g_return_if_fail (NM_IS_IP6_CONFIG (config)); + NMIP6ConfigPrivate *priv; + size_t data_len = 0; + char *data_pre = NULL; + gboolean changed; + + g_return_val_if_fail (NM_IS_IP6_CONFIG (self), FALSE); + + priv = NM_IP6_CONFIG_GET_PRIVATE (self); + if (priv->addresses->len > 1) { + data_len = priv->addresses->len * g_array_get_element_size (priv->addresses); + data_pre = g_new (char, data_len); + memcpy (data_pre, priv->addresses->data, data_len); + + g_array_sort_with_data (priv->addresses, _addresses_sort_cmp, GINT_TO_POINTER (use_temporary)); + + changed = memcmp (data_pre, priv->addresses->data, data_len) != 0; + g_free (data_pre); - NM_IP6_CONFIG_GET_PRIVATE (config)->ptp_address = *ptp_addr; + if (changed) { + _NOTIFY (self, PROP_ADDRESSES); + return TRUE; + } + } + return FALSE; } -void nm_ip6_config_add_nameserver (NMIP6Config *config, const struct in6_addr *nameserver) +NMIP6Config * +nm_ip6_config_capture (int ifindex, gboolean capture_resolv_conf, NMSettingIP6ConfigPrivacy use_temporary) { + NMIP6Config *config; NMIP6ConfigPrivate *priv; - struct in6_addr *nameservers; - int i; - - g_return_if_fail (NM_IS_IP6_CONFIG (config)); - g_return_if_fail (nameserver != NULL); + guint i; + guint lowest_metric = G_MAXUINT; + struct in6_addr old_gateway = IN6ADDR_ANY_INIT; + gboolean has_gateway = FALSE; + gboolean notify_nameservers = FALSE; + + /* Slaves have no IP configuration */ + if (nm_platform_link_get_master (ifindex) > 0) + return NULL; + config = nm_ip6_config_new (); priv = NM_IP6_CONFIG_GET_PRIVATE (config); - /* No dupes */ - nameservers = (struct in6_addr *)priv->nameservers->data; - for (i = 0; i < priv->nameservers->len; i++) { - if (IN6_ARE_ADDR_EQUAL (nameserver, &nameservers[i])) - return; + g_array_unref (priv->addresses); + g_array_unref (priv->routes); + + priv->addresses = nm_platform_ip6_address_get_all (ifindex); + priv->routes = nm_platform_ip6_route_get_all (ifindex, TRUE); + + /* Extract gateway from default route */ + old_gateway = priv->gateway; + for (i = 0; i < priv->routes->len; i++) { + const NMPlatformIP6Route *route = &g_array_index (priv->routes, NMPlatformIP6Route, i); + + if (IN6_IS_ADDR_UNSPECIFIED (&route->network)) { + if (route->metric < lowest_metric) { + priv->gateway = route->gateway; + lowest_metric = route->metric; + } + has_gateway = TRUE; + /* Remove the default route from the list */ + g_array_remove_index (priv->routes, i); + i--; + } } - g_array_append_val (priv->nameservers, *nameserver); -} + /* If there is a host route to the gateway, ignore that route. It is + * automatically added by NetworkManager when needed. + */ + if (has_gateway) { + for (i = 0; i < priv->routes->len; i++) { + const NMPlatformIP6Route *route = &g_array_index (priv->routes, NMPlatformIP6Route, i); + + if ( route->plen == 128 + && IN6_ARE_ADDR_EQUAL (&route->network, &priv->gateway) + && IN6_IS_ADDR_UNSPECIFIED (&route->gateway)) { + g_array_remove_index (priv->routes, i); + i--; + } + } + } -const struct in6_addr *nm_ip6_config_get_nameserver (NMIP6Config *config, guint i) -{ - g_return_val_if_fail (NM_IS_IP6_CONFIG (config), 0); + /* If the interface has the default route, and has IPv6 addresses, capture + * nameservers from /etc/resolv.conf. + */ + if (priv->addresses->len && has_gateway && capture_resolv_conf) + notify_nameservers = nm_ip6_config_capture_resolv_conf (priv->nameservers, NULL); - return &g_array_index (NM_IP6_CONFIG_GET_PRIVATE (config)->nameservers, struct in6_addr, i); -} + g_array_sort_with_data (priv->addresses, _addresses_sort_cmp, GINT_TO_POINTER (use_temporary)); -guint32 nm_ip6_config_get_num_nameservers (NMIP6Config *config) -{ - g_return_val_if_fail (NM_IS_IP6_CONFIG (config), 0); + /* actually, nobody should be connected to the signal, just to be sure, notify */ + if (notify_nameservers) + _NOTIFY (config, PROP_NAMESERVERS); + _NOTIFY (config, PROP_ADDRESSES); + _NOTIFY (config, PROP_ROUTES); + if (!IN6_ARE_ADDR_EQUAL (&priv->gateway, &old_gateway)) + _NOTIFY (config, PROP_GATEWAY); - return NM_IP6_CONFIG_GET_PRIVATE (config)->nameservers->len; + return config; } -void nm_ip6_config_reset_nameservers (NMIP6Config *config) +gboolean +nm_ip6_config_commit (const NMIP6Config *config, int ifindex) { - NMIP6ConfigPrivate *priv; + NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); + int i; + gboolean success; - g_return_if_fail (NM_IS_IP6_CONFIG (config)); + g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail (config != NULL, FALSE); - priv = NM_IP6_CONFIG_GET_PRIVATE (config); - if (priv->nameservers->len) - g_array_remove_range (priv->nameservers, 0, priv->nameservers->len); + /* Addresses */ + nm_platform_ip6_address_sync (ifindex, priv->addresses); + + /* Routes */ + { + int count = nm_ip6_config_get_num_routes (config); + GArray *routes = g_array_sized_new (FALSE, FALSE, sizeof (NMPlatformIP6Route), count); + NMPlatformIP6Route route; + + for (i = 0; i < count; i++) { + memcpy (&route, nm_ip6_config_get_route (config, i), sizeof (route)); + + /* Don't add the route if it's more specific than one of the subnets + * the device already has an IP address on. + */ + if ( IN6_IS_ADDR_UNSPECIFIED (&route.gateway) + && nm_ip6_config_destination_is_direct (config, &route.network, route.plen)) + continue; + + /* Don't add the default route if the connection + * is never supposed to be the default connection. + */ + if (nm_ip6_config_get_never_default (config) && IN6_IS_ADDR_UNSPECIFIED (&route.network)) + continue; + + g_array_append_val (routes, route); + } + + success = nm_platform_ip6_route_sync (ifindex, routes); + g_array_unref (routes); + } + + return success; } void -nm_ip6_config_set_gateway (NMIP6Config *config, const struct in6_addr *gateway) +nm_ip6_config_merge_setting (NMIP6Config *config, NMSettingIP6Config *setting, int default_route_metric) { - NMIP6ConfigPrivate *priv; + guint naddresses, nroutes, nnameservers, nsearches; + int i; - g_return_if_fail (NM_IS_IP6_CONFIG (config)); + if (!setting) + return; - priv = NM_IP6_CONFIG_GET_PRIVATE (config); - if (gateway) - memcpy (&priv->gateway, gateway, sizeof (priv->gateway)); - priv->gateway_set = !!gateway; + naddresses = nm_setting_ip6_config_get_num_addresses (setting); + nroutes = nm_setting_ip6_config_get_num_routes (setting); + nnameservers = nm_setting_ip6_config_get_num_dns (setting); + nsearches = nm_setting_ip6_config_get_num_dns_searches (setting); + + g_object_freeze_notify (G_OBJECT (config)); + + /* Gateway */ + if (nm_setting_ip6_config_get_never_default (setting)) + nm_ip6_config_set_never_default (config, TRUE); + else if (nm_setting_ip6_config_get_ignore_auto_routes (setting)) + nm_ip6_config_set_never_default (config, FALSE); + for (i = 0; i < naddresses; i++) { + const struct in6_addr *gateway = nm_ip6_address_get_gateway (nm_setting_ip6_config_get_address (setting, i)); + + if (gateway && !IN6_IS_ADDR_UNSPECIFIED (gateway)) { + nm_ip6_config_set_gateway (config, gateway); + break; + } + } + + /* Addresses */ + for (i = 0; i < naddresses; i++) { + NMIP6Address *s_addr = nm_setting_ip6_config_get_address (setting, i); + NMPlatformIP6Address address; + + memset (&address, 0, sizeof (address)); + address.address = *nm_ip6_address_get_address (s_addr); + address.plen = nm_ip6_address_get_prefix (s_addr); + address.lifetime = NM_PLATFORM_LIFETIME_PERMANENT; + address.preferred = NM_PLATFORM_LIFETIME_PERMANENT; + address.source = NM_PLATFORM_SOURCE_USER; + + nm_ip6_config_add_address (config, &address); + } + + /* Routes */ + if (nm_setting_ip6_config_get_ignore_auto_routes (setting)) + nm_ip6_config_reset_routes (config); + for (i = 0; i < nroutes; i++) { + NMIP6Route *s_route = nm_setting_ip6_config_get_route (setting, i); + NMPlatformIP6Route route; + + memset (&route, 0, sizeof (route)); + route.network = *nm_ip6_route_get_dest (s_route); + route.plen = nm_ip6_route_get_prefix (s_route); + route.gateway = *nm_ip6_route_get_next_hop (s_route); + route.metric = nm_ip6_route_get_metric (s_route); + if (!route.metric) + route.metric = default_route_metric; + route.source = NM_PLATFORM_SOURCE_USER; + + nm_ip6_config_add_route (config, &route); + } + + /* DNS */ + if (nm_setting_ip6_config_get_ignore_auto_dns (setting)) { + nm_ip6_config_reset_nameservers (config); + nm_ip6_config_reset_domains (config); + nm_ip6_config_reset_searches (config); + } + for (i = 0; i < nnameservers; i++) + nm_ip6_config_add_nameserver (config, nm_setting_ip6_config_get_dns (setting, i)); + for (i = 0; i < nsearches; i++) + nm_ip6_config_add_search (config, nm_setting_ip6_config_get_dns_search (setting, i)); + + g_object_thaw_notify (G_OBJECT (config)); } -const struct in6_addr * -nm_ip6_config_get_gateway (NMIP6Config *config) +NMSetting * +nm_ip6_config_create_setting (const NMIP6Config *config) { - NMIP6ConfigPrivate *priv; + NMSettingIP6Config *s_ip6; + const struct in6_addr *gateway; + guint naddresses, nroutes, nnameservers, nsearches; + const char *method = NULL; + int i; - g_return_val_if_fail (NM_IS_IP6_CONFIG (config), NULL); + s_ip6 = NM_SETTING_IP6_CONFIG (nm_setting_ip6_config_new ()); - priv = NM_IP6_CONFIG_GET_PRIVATE (config); - return priv->gateway_set ? &priv->gateway : NULL; + if (!config) { + g_object_set (s_ip6, + NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE, + NULL); + return NM_SETTING (s_ip6); + } + + gateway = nm_ip6_config_get_gateway (config); + naddresses = nm_ip6_config_get_num_addresses (config); + nroutes = nm_ip6_config_get_num_routes (config); + nnameservers = nm_ip6_config_get_num_nameservers (config); + nsearches = nm_ip6_config_get_num_searches (config); + + /* Addresses */ + for (i = 0; i < naddresses; i++) { + const NMPlatformIP6Address *address = nm_ip6_config_get_address (config, i); + NMIP6Address *s_addr; + + /* Ignore link-local address. */ + if (IN6_IS_ADDR_LINKLOCAL (&address->address)) { + if (!method) + method = NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL; + continue; + } + + /* Detect dynamic address */ + if (address->lifetime != NM_PLATFORM_LIFETIME_PERMANENT) { + method = NM_SETTING_IP6_CONFIG_METHOD_AUTO; + continue; + } + + /* Static address found. */ + if (!method || strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL) == 0) + method = NM_SETTING_IP6_CONFIG_METHOD_MANUAL; + + s_addr = nm_ip6_address_new (); + + nm_ip6_address_set_address (s_addr, &address->address); + nm_ip6_address_set_prefix (s_addr, address->plen); + if (gateway) + nm_ip6_address_set_gateway (s_addr, gateway); + + nm_setting_ip6_config_add_address (s_ip6, s_addr); + nm_ip6_address_unref (s_addr); + } + + /* Use 'ignore' if the method wasn't previously set */ + if (!method) + method = NM_SETTING_IP6_CONFIG_METHOD_IGNORE; + g_object_set (s_ip6, NM_SETTING_IP6_CONFIG_METHOD, method, NULL); + + /* Routes */ + for (i = 0; i < nroutes; i++) { + const NMPlatformIP6Route *route = nm_ip6_config_get_route (config, i); + NMIP6Route *s_route; + + /* Ignore link-local route. */ + if (IN6_IS_ADDR_LINKLOCAL (&route->network)) + continue; + + /* Ignore default route. */ + if (!route->plen) + continue; + + /* Ignore routes provided by external sources */ + if (route->source != NM_PLATFORM_SOURCE_USER) + continue; + + s_route = nm_ip6_route_new (); + nm_ip6_route_set_dest (s_route, &route->network); + nm_ip6_route_set_prefix (s_route, route->plen); + if (!IN6_IS_ADDR_UNSPECIFIED (&route->network)) + nm_ip6_route_set_next_hop (s_route, &route->gateway); + nm_ip6_route_set_metric (s_route, route->metric); + + nm_setting_ip6_config_add_route (s_ip6, s_route); + nm_ip6_route_unref (s_route); + } + + /* DNS */ + for (i = 0; i < nnameservers; i++) { + const struct in6_addr *nameserver = nm_ip6_config_get_nameserver (config, i); + + nm_setting_ip6_config_add_dns (s_ip6, nameserver); + } + for (i = 0; i < nsearches; i++) { + const char *search = nm_ip6_config_get_search (config, i); + + nm_setting_ip6_config_add_dns_search (s_ip6, search); + } + + return NM_SETTING (s_ip6); } +/******************************************************************/ + void -nm_ip6_config_take_route (NMIP6Config *config, NMIP6Route *route) +nm_ip6_config_merge (NMIP6Config *dst, const NMIP6Config *src) { - NMIP6ConfigPrivate *priv; + guint32 i; - g_return_if_fail (NM_IS_IP6_CONFIG (config)); - g_return_if_fail (route != NULL); + g_return_if_fail (src != NULL); + g_return_if_fail (dst != NULL); - priv = NM_IP6_CONFIG_GET_PRIVATE (config); - priv->routes = g_slist_append (priv->routes, route); + g_object_freeze_notify (G_OBJECT (dst)); + + /* addresses */ + for (i = 0; i < nm_ip6_config_get_num_addresses (src); i++) + nm_ip6_config_add_address (dst, nm_ip6_config_get_address (src, i)); + + /* nameservers */ + for (i = 0; i < nm_ip6_config_get_num_nameservers (src); i++) + nm_ip6_config_add_nameserver (dst, nm_ip6_config_get_nameserver (src, i)); + + /* default gateway */ + if (!nm_ip6_config_get_gateway (dst)) + nm_ip6_config_set_gateway (dst, nm_ip6_config_get_gateway (src)); + + /* routes */ + for (i = 0; i < nm_ip6_config_get_num_routes (src); i++) + nm_ip6_config_add_route (dst, nm_ip6_config_get_route (src, i)); + + /* domains */ + for (i = 0; i < nm_ip6_config_get_num_domains (src); i++) + nm_ip6_config_add_domain (dst, nm_ip6_config_get_domain (src, i)); + + /* dns searches */ + for (i = 0; i < nm_ip6_config_get_num_searches (src); i++) + nm_ip6_config_add_search (dst, nm_ip6_config_get_search (src, i)); + + if (!nm_ip6_config_get_mss (dst)) + nm_ip6_config_set_mss (dst, nm_ip6_config_get_mss (src)); + + g_object_thaw_notify (G_OBJECT (dst)); } -void -nm_ip6_config_add_route (NMIP6Config *config, NMIP6Route *route) +gboolean +nm_ip6_config_destination_is_direct (const NMIP6Config *config, const struct in6_addr *network, int plen) { - NMIP6ConfigPrivate *priv; - GSList *iter; + int num = nm_ip6_config_get_num_addresses (config); + int i; - g_return_if_fail (NM_IS_IP6_CONFIG (config)); - g_return_if_fail (route != NULL); + for (i = 0; i < num; i++) { + const NMPlatformIP6Address *item = nm_ip6_config_get_address (config, i); - priv = NM_IP6_CONFIG_GET_PRIVATE (config); - for (iter = priv->routes; iter; iter = g_slist_next (iter)) { - if (nm_ip6_route_compare ((NMIP6Route *) iter->data, route)) - return; + if (item->plen <= plen && same_prefix (&item->address, network, item->plen) && + !(item->flags & IFA_F_NOPREFIXROUTE)) + return TRUE; } - priv->routes = g_slist_append (priv->routes, nm_ip6_route_dup (route)); + return FALSE; } +/** + * nm_ip6_config_subtract: + * @dst: config from which to remove everything in @src + * @src: config to remove from @dst + * + * Removes everything in @src from @dst. + */ void -nm_ip6_config_replace_route (NMIP6Config *config, - guint i, - NMIP6Route *new_route) +nm_ip6_config_subtract (NMIP6Config *dst, const NMIP6Config *src) { - NMIP6ConfigPrivate *priv; - GSList *old; + guint32 i, j; + const struct in6_addr *dst_tmp, *src_tmp; - g_return_if_fail (NM_IS_IP6_CONFIG (config)); + g_return_if_fail (src != NULL); + g_return_if_fail (dst != NULL); - priv = NM_IP6_CONFIG_GET_PRIVATE (config); - old = g_slist_nth (priv->routes, i); - g_return_if_fail (old != NULL); - nm_ip6_route_unref ((NMIP6Route *) old->data); + g_object_freeze_notify (G_OBJECT (dst)); + + /* addresses */ + for (i = 0; i < nm_ip6_config_get_num_addresses (src); i++) { + const NMPlatformIP6Address *src_addr = nm_ip6_config_get_address (src, i); + + for (j = 0; j < nm_ip6_config_get_num_addresses (dst); j++) { + const NMPlatformIP6Address *dst_addr = nm_ip6_config_get_address (dst, j); + + if (IN6_ARE_ADDR_EQUAL (&src_addr->address, &dst_addr->address)) { + nm_ip6_config_del_address (dst, j); + break; + } + } + } + + /* nameservers */ + for (i = 0; i < nm_ip6_config_get_num_nameservers (src); i++) { + const struct in6_addr *src_ns = nm_ip6_config_get_nameserver (src, i); + + for (j = 0; j < nm_ip6_config_get_num_nameservers (dst); j++) { + const struct in6_addr *dst_ns = nm_ip6_config_get_nameserver (dst, j); + + if (IN6_ARE_ADDR_EQUAL (src_ns, dst_ns)) { + nm_ip6_config_del_nameserver (dst, j); + break; + } + } + } + + /* default gateway */ + src_tmp = nm_ip6_config_get_gateway (src); + dst_tmp = nm_ip6_config_get_gateway (dst); + if (src_tmp && dst_tmp && IN6_ARE_ADDR_EQUAL (src_tmp, dst_tmp)) + nm_ip6_config_set_gateway (dst, NULL); + + /* routes */ + for (i = 0; i < nm_ip6_config_get_num_routes (src); i++) { + const NMPlatformIP6Route *src_route = nm_ip6_config_get_route (src, i); + + for (j = 0; j < nm_ip6_config_get_num_routes (dst); j++) { + const NMPlatformIP6Route *dst_route = nm_ip6_config_get_route (dst, j); + + if (routes_are_duplicate (src_route, dst_route, FALSE)) { + nm_ip6_config_del_route (dst, j); + break; + } + } + } + + /* domains */ + for (i = 0; i < nm_ip6_config_get_num_domains (src); i++) { + const char *src_domain = nm_ip6_config_get_domain (src, i); + + for (j = 0; j < nm_ip6_config_get_num_domains (dst); j++) { + const char *dst_domain = nm_ip6_config_get_domain (dst, j); - old->data = nm_ip6_route_dup (new_route); + if (g_strcmp0 (src_domain, dst_domain) == 0) { + nm_ip6_config_del_domain (dst, j); + break; + } + } + } + + /* dns searches */ + for (i = 0; i < nm_ip6_config_get_num_searches (src); i++) { + const char *src_search = nm_ip6_config_get_search (src, i); + + for (j = 0; j < nm_ip6_config_get_num_searches (dst); j++) { + const char *dst_search = nm_ip6_config_get_search (dst, j); + + if (g_strcmp0 (src_search, dst_search) == 0) { + nm_ip6_config_del_search (dst, j); + break; + } + } + } + + if (nm_ip6_config_get_mss (src) == nm_ip6_config_get_mss (dst)) + nm_ip6_config_set_mss (dst, 0); + + g_object_thaw_notify (G_OBJECT (dst)); } -NMIP6Route * -nm_ip6_config_get_route (NMIP6Config *config, guint i) +/** + * nm_ip6_config_replace: + * @dst: config which will be replaced with everything in @src + * @src: config to copy over to @dst + * @relevant_changes: return whether there are changes to the + * destination object that are relevant. This is equal to + * nm_ip6_config_equal() showing any difference. + * + * Replaces everything in @dst with @src so that the two configurations + * contain the same content -- with the exception of the dbus path. + * + * Returns: whether the @dst instance changed in any way (including minor changes, + * that are not signaled by the output parameter @relevant_changes). + */ +gboolean +nm_ip6_config_replace (NMIP6Config *dst, const NMIP6Config *src, gboolean *relevant_changes) { - g_return_val_if_fail (NM_IS_IP6_CONFIG (config), NULL); +#ifndef G_DISABLE_ASSERT + gboolean config_equal; +#endif + gboolean has_minor_changes = FALSE, has_relevant_changes = FALSE, are_equal; + guint i, num; + NMIP6ConfigPrivate *dst_priv, *src_priv; + const NMPlatformIP6Address *dst_addr, *src_addr; + const NMPlatformIP6Route *dst_route, *src_route; + + g_return_val_if_fail (src != NULL, FALSE); + g_return_val_if_fail (dst != NULL, FALSE); + g_return_val_if_fail (src != dst, FALSE); + +#ifndef G_DISABLE_ASSERT + config_equal = nm_ip6_config_equal (dst, src); +#endif + + dst_priv = NM_IP6_CONFIG_GET_PRIVATE (dst); + src_priv = NM_IP6_CONFIG_GET_PRIVATE (src); + + g_object_freeze_notify (G_OBJECT (dst)); + + /* never_default */ + if (src_priv->never_default != dst_priv->never_default) { + dst_priv->never_default = src_priv->never_default; + has_minor_changes = TRUE; + } + + /* default gateway */ + if (!IN6_ARE_ADDR_EQUAL (&src_priv->gateway, &dst_priv->gateway)) { + nm_ip6_config_set_gateway (dst, &src_priv->gateway); + has_relevant_changes = TRUE; + } + + /* addresses */ + num = nm_ip6_config_get_num_addresses (src); + are_equal = num == nm_ip6_config_get_num_addresses (dst); + if (are_equal) { + for (i = 0; i < num; i++ ) { + if (nm_platform_ip6_address_cmp (src_addr = nm_ip6_config_get_address (src, i), + dst_addr = nm_ip6_config_get_address (dst, i))) { + are_equal = FALSE; + if (!addresses_are_duplicate (src_addr, dst_addr, TRUE)) { + has_relevant_changes = TRUE; + break; + } + } + } + } else + has_relevant_changes = TRUE; + if (!are_equal) { + nm_ip6_config_reset_addresses (dst); + for (i = 0; i < num; i++) + nm_ip6_config_add_address (dst, nm_ip6_config_get_address (src, i)); + has_minor_changes = TRUE; + } + + /* routes */ + num = nm_ip6_config_get_num_routes (src); + are_equal = num == nm_ip6_config_get_num_routes (dst); + if (are_equal) { + for (i = 0; i < num; i++ ) { + if (nm_platform_ip6_route_cmp (src_route = nm_ip6_config_get_route (src, i), + dst_route = nm_ip6_config_get_route (dst, i))) { + are_equal = FALSE; + if (!routes_are_duplicate (src_route, dst_route, TRUE)) { + has_relevant_changes = TRUE; + break; + } + } + } + } else + has_relevant_changes = TRUE; + if (!are_equal) { + nm_ip6_config_reset_routes (dst); + for (i = 0; i < num; i++) + nm_ip6_config_add_route (dst, nm_ip6_config_get_route (src, i)); + has_minor_changes = TRUE; + } - return (NMIP6Route *) g_slist_nth_data (NM_IP6_CONFIG_GET_PRIVATE (config)->routes, i); + /* nameservers */ + num = nm_ip6_config_get_num_nameservers (src); + are_equal = num == nm_ip6_config_get_num_nameservers (dst); + if (are_equal) { + for (i = 0; i < num; i++ ) { + if (!IN6_ARE_ADDR_EQUAL (nm_ip6_config_get_nameserver (src, i), + nm_ip6_config_get_nameserver (dst, i))) { + are_equal = FALSE; + break; + } + } + } + if (!are_equal) { + nm_ip6_config_reset_nameservers (dst); + for (i = 0; i < num; i++) + nm_ip6_config_add_nameserver (dst, nm_ip6_config_get_nameserver (src, i)); + has_relevant_changes = TRUE; + } + + /* domains */ + num = nm_ip6_config_get_num_domains (src); + are_equal = num == nm_ip6_config_get_num_domains (dst); + if (are_equal) { + for (i = 0; i < num; i++ ) { + if (g_strcmp0 (nm_ip6_config_get_domain (src, i), + nm_ip6_config_get_domain (dst, i))) { + are_equal = FALSE; + break; + } + } + } + if (!are_equal) { + nm_ip6_config_reset_domains (dst); + for (i = 0; i < num; i++) + nm_ip6_config_add_domain (dst, nm_ip6_config_get_domain (src, i)); + has_relevant_changes = TRUE; + } + + /* dns searches */ + num = nm_ip6_config_get_num_searches (src); + are_equal = num == nm_ip6_config_get_num_searches (dst); + if (are_equal) { + for (i = 0; i < num; i++ ) { + if (g_strcmp0 (nm_ip6_config_get_search (src, i), + nm_ip6_config_get_search (dst, i))) { + are_equal = FALSE; + break; + } + } + } + if (!are_equal) { + nm_ip6_config_reset_searches (dst); + for (i = 0; i < num; i++) + nm_ip6_config_add_search (dst, nm_ip6_config_get_search (src, i)); + has_relevant_changes = TRUE; + } + + /* mss */ + if (src_priv->mss != dst_priv->mss) { + nm_ip6_config_set_mss (dst, src_priv->mss); + has_minor_changes = TRUE; + } + + /* config_equal does not compare *all* the fields, therefore, we might have has_minor_changes + * regardless of config_equal. But config_equal must correspond to has_relevant_changes. */ + g_assert (config_equal == !has_relevant_changes); + + g_object_thaw_notify (G_OBJECT (dst)); + + if (relevant_changes) + *relevant_changes = has_relevant_changes; + + return has_relevant_changes || has_minor_changes; } -guint32 nm_ip6_config_get_num_routes (NMIP6Config *config) +void +nm_ip6_config_dump (const NMIP6Config *config, const char *detail) { - g_return_val_if_fail (NM_IS_IP6_CONFIG (config), 0); + const struct in6_addr *tmp; + guint32 i; + const char *str; + + g_return_if_fail (config != NULL); + + g_message ("--------- NMIP6Config %p (%s)", config, detail); + + str = nm_ip6_config_get_dbus_path (config); + if (str) + g_message (" path: %s", str); - return g_slist_length (NM_IP6_CONFIG_GET_PRIVATE (config)->routes); + /* addresses */ + for (i = 0; i < nm_ip6_config_get_num_addresses (config); i++) + g_message (" a: %s", nm_platform_ip6_address_to_string (nm_ip6_config_get_address (config, i))); + + /* default gateway */ + tmp = nm_ip6_config_get_gateway (config); + if (tmp) + g_message (" gw: %s", nm_utils_inet6_ntop (tmp, NULL)); + + /* nameservers */ + for (i = 0; i < nm_ip6_config_get_num_nameservers (config); i++) { + tmp = nm_ip6_config_get_nameserver (config, i); + g_message (" ns: %s", nm_utils_inet6_ntop (tmp, NULL)); + } + + /* routes */ + for (i = 0; i < nm_ip6_config_get_num_routes (config); i++) + g_message (" rt: %s", nm_platform_ip6_route_to_string (nm_ip6_config_get_route (config, i))); + + /* domains */ + for (i = 0; i < nm_ip6_config_get_num_domains (config); i++) + g_message (" domain: %s", nm_ip6_config_get_domain (config, i)); + + /* dns searches */ + for (i = 0; i < nm_ip6_config_get_num_searches (config); i++) + g_message (" search: %s", nm_ip6_config_get_search (config, i)); + + g_message (" mss: %u", nm_ip6_config_get_mss (config)); + g_message (" n-dflt: %d", nm_ip6_config_get_never_default (config)); } -void nm_ip6_config_reset_routes (NMIP6Config *config) -{ - NMIP6ConfigPrivate *priv; +/******************************************************************/ - g_return_if_fail (NM_IS_IP6_CONFIG (config)); +void +nm_ip6_config_set_never_default (NMIP6Config *config, gboolean never_default) +{ + NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); - priv = NM_IP6_CONFIG_GET_PRIVATE (config); - g_slist_foreach (priv->routes, (GFunc) g_free, NULL); - priv->routes = NULL; + priv->never_default = !!never_default; } -void nm_ip6_config_add_domain (NMIP6Config *config, const char *domain) +gboolean +nm_ip6_config_get_never_default (const NMIP6Config *config) { - NMIP6ConfigPrivate *priv; - int i; + NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); - g_return_if_fail (NM_IS_IP6_CONFIG (config)); - g_return_if_fail (domain != NULL); - g_return_if_fail (strlen (domain) > 0); + return priv->never_default; +} - priv = NM_IP6_CONFIG_GET_PRIVATE (config); +void +nm_ip6_config_set_gateway (NMIP6Config *config, const struct in6_addr *gateway) +{ + NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); - for (i = 0; i < priv->domains->len; i++) { - if (!strcmp (g_ptr_array_index (priv->domains, i), domain)) + if (gateway) { + if (IN6_ARE_ADDR_EQUAL (&priv->gateway, gateway)) return; + priv->gateway = *gateway; + } else { + if (IN6_IS_ADDR_UNSPECIFIED (&priv->gateway)) + return; + memset (&priv->gateway, 0, sizeof (priv->gateway)); } - - g_ptr_array_add (priv->domains, g_strdup (domain)); + _NOTIFY (config, PROP_GATEWAY); } -const char *nm_ip6_config_get_domain (NMIP6Config *config, guint i) +const struct in6_addr * +nm_ip6_config_get_gateway (const NMIP6Config *config) { - g_return_val_if_fail (NM_IS_IP6_CONFIG (config), NULL); + NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); - return (const char *) g_ptr_array_index (NM_IP6_CONFIG_GET_PRIVATE (config)->domains, i); + return IN6_IS_ADDR_UNSPECIFIED (&priv->gateway) ? NULL : &priv->gateway; } -guint32 nm_ip6_config_get_num_domains (NMIP6Config *config) +/******************************************************************/ + +void +nm_ip6_config_reset_addresses (NMIP6Config *config) { - g_return_val_if_fail (NM_IS_IP6_CONFIG (config), 0); + NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); - return NM_IP6_CONFIG_GET_PRIVATE (config)->domains->len; + if (priv->addresses->len != 0) { + g_array_set_size (priv->addresses, 0); + _NOTIFY (config, PROP_ADDRESSES); + } } -void nm_ip6_config_reset_domains (NMIP6Config *config) +/** + * nm_ip6_config_add_address: + * @config: the #NMIP6Config + * @new: the new address to add to @config + * + * Adds the new address to @config. If an address with the same basic properties + * (address, prefix) already exists in @config, it is overwritten with the + * lifetime and preferred of @new. The source is also overwritten by the source + * from @new if that source is higher priority. + */ +void +nm_ip6_config_add_address (NMIP6Config *config, const NMPlatformIP6Address *new) { - NMIP6ConfigPrivate *priv; + NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); + NMPlatformIP6Address item_old; int i; - g_return_if_fail (NM_IS_IP6_CONFIG (config)); + g_return_if_fail (new != NULL); + + for (i = 0; i < priv->addresses->len; i++ ) { + NMPlatformIP6Address *item = &g_array_index (priv->addresses, NMPlatformIP6Address, i); + + if (IN6_ARE_ADDR_EQUAL (&item->address, &new->address)) { + if (nm_platform_ip6_address_cmp (item, new) == 0) + return; + + /* remember the old values. */ + item_old = *item; + /* Copy over old item to get new lifetime, timestamp, preferred */ + *item = *new; + + /* But restore highest priority source */ + item->source = MAX (item_old.source, new->source); + + /* for addresses that we read from the kernel, we keep the timestamps as defined + * by the previous source (item_old). The reason is, that the other source configured the lifetimes + * with "what should be" and the kernel values are "what turned out after configuring it". + * + * For other sources, the longer lifetime wins. */ + if ( (new->source == NM_PLATFORM_SOURCE_KERNEL && new->source != item_old.source) + || nm_platform_ip_address_cmp_expiry ((const NMPlatformIPAddress *) &item_old, (const NMPlatformIPAddress *) new) > 0) { + item->timestamp = item_old.timestamp; + item->lifetime = item_old.lifetime; + item->preferred = item_old.preferred; + } + if (nm_platform_ip6_address_cmp (&item_old, item) == 0) + return; + goto NOTIFY; + } + } - priv = NM_IP6_CONFIG_GET_PRIVATE (config); - for (i = 0; i < priv->domains->len; i++) - g_free (g_ptr_array_index (priv->domains, i)); - g_ptr_array_free (priv->domains, TRUE); - priv->domains = g_ptr_array_sized_new (3); + g_array_append_val (priv->addresses, *new); +NOTIFY: + _NOTIFY (config, PROP_ADDRESSES); } -void nm_ip6_config_add_search (NMIP6Config *config, const char *search) +void +nm_ip6_config_del_address (NMIP6Config *config, guint i) { - NMIP6ConfigPrivate *priv; - int i; + NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); - g_return_if_fail (config != NULL); - g_return_if_fail (search != NULL); - g_return_if_fail (strlen (search) > 0); + g_return_if_fail (i < priv->addresses->len); - priv = NM_IP6_CONFIG_GET_PRIVATE (config); + g_array_remove_index (priv->addresses, i); + _NOTIFY (config, PROP_ADDRESSES); +} - for (i = 0; i < priv->searches->len; i++) { - if (!strcmp (g_ptr_array_index (priv->searches, i), search)) - return; - } +guint +nm_ip6_config_get_num_addresses (const NMIP6Config *config) +{ + NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); + + return priv->addresses->len; +} + +const NMPlatformIP6Address * +nm_ip6_config_get_address (const NMIP6Config *config, guint i) +{ + NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); - g_ptr_array_add (priv->searches, g_strdup (search)); + return &g_array_index (priv->addresses, NMPlatformIP6Address, i); } -const char *nm_ip6_config_get_search (NMIP6Config *config, guint i) +gboolean +nm_ip6_config_address_exists (const NMIP6Config *config, + const NMPlatformIP6Address *needle) { - g_return_val_if_fail (config != NULL, NULL); + NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); + guint i; + + for (i = 0; i < priv->addresses->len; i++) { + const NMPlatformIP6Address *haystack = &g_array_index (priv->addresses, NMPlatformIP6Address, i); - return (const char *) g_ptr_array_index (NM_IP6_CONFIG_GET_PRIVATE (config)->searches, i); + if ( IN6_ARE_ADDR_EQUAL (&needle->address, &haystack->address) + && needle->plen == haystack->plen) + return TRUE; + } + return FALSE; } -guint32 nm_ip6_config_get_num_searches (NMIP6Config *config) +/******************************************************************/ + +void +nm_ip6_config_reset_routes (NMIP6Config *config) { - g_return_val_if_fail (config != NULL, 0); + NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); - return NM_IP6_CONFIG_GET_PRIVATE (config)->searches->len; + if (priv->routes->len != 0) { + g_array_set_size (priv->routes, 0); + _NOTIFY (config, PROP_ROUTES); + } } -void nm_ip6_config_reset_searches (NMIP6Config *config) +/** + * nm_ip6_config_add_route: + * @config: the #NMIP6Config + * @new: the new route to add to @config + * + * Adds the new route to @config. If a route with the same basic properties + * (network, prefix) already exists in @config, it is overwritten including the + * gateway and metric of @new. The source is also overwritten by the source + * from @new if that source is higher priority. + */ +void +nm_ip6_config_add_route (NMIP6Config *config, const NMPlatformIP6Route *new) { - NMIP6ConfigPrivate *priv; + NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); + NMPlatformSource old_source; int i; - g_return_if_fail (NM_IS_IP6_CONFIG (config)); + g_return_if_fail (new != NULL); - priv = NM_IP6_CONFIG_GET_PRIVATE (config); - for (i = 0; i < priv->searches->len; i++) - g_free (g_ptr_array_index (priv->searches, i)); - g_ptr_array_free (priv->searches, TRUE); - priv->searches = g_ptr_array_sized_new (3); + for (i = 0; i < priv->routes->len; i++ ) { + NMPlatformIP6Route *item = &g_array_index (priv->routes, NMPlatformIP6Route, i); + + if (routes_are_duplicate (item, new, FALSE)) { + if (nm_platform_ip6_route_cmp (item, new) == 0) + return; + old_source = item->source; + *item = *new; + /* Restore highest priority source */ + item->source = MAX (old_source, new->source); + goto NOTIFY; + } + } + + g_array_append_val (priv->routes, *new); +NOTIFY: + _NOTIFY (config, PROP_ROUTES); } -guint32 nm_ip6_config_get_mss (NMIP6Config *config) +void +nm_ip6_config_del_route (NMIP6Config *config, guint i) { - g_return_val_if_fail (NM_IS_IP6_CONFIG (config), 0); + NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); - return NM_IP6_CONFIG_GET_PRIVATE (config)->mss; + g_return_if_fail (i < priv->routes->len); + + g_array_remove_index (priv->routes, i); + _NOTIFY (config, PROP_ROUTES); } -void nm_ip6_config_set_mss (NMIP6Config *config, guint32 mss) +guint +nm_ip6_config_get_num_routes (const NMIP6Config *config) { - g_return_if_fail (NM_IS_IP6_CONFIG (config)); + NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); - NM_IP6_CONFIG_GET_PRIVATE (config)->mss = mss; + return priv->routes->len; } -gboolean -nm_ip6_config_get_never_default (NMIP6Config *config) +const NMPlatformIP6Route * +nm_ip6_config_get_route (const NMIP6Config *config, guint i) { - g_return_val_if_fail (NM_IS_IP6_CONFIG (config), FALSE); + NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); - return NM_IP6_CONFIG_GET_PRIVATE (config)->never_default; + return &g_array_index (priv->routes, NMPlatformIP6Route, i); } +/******************************************************************/ + void -nm_ip6_config_set_never_default (NMIP6Config *config, gboolean never_default) +nm_ip6_config_reset_nameservers (NMIP6Config *config) { - g_return_if_fail (NM_IS_IP6_CONFIG (config)); + NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); - NM_IP6_CONFIG_GET_PRIVATE (config)->never_default = never_default; + if (priv->nameservers->len != 0) { + g_array_set_size (priv->nameservers, 0); + _NOTIFY (config, PROP_NAMESERVERS); + } } -/* libnl convenience/conversion functions */ - -static int ip6_addr_to_rtnl_local (const struct in6_addr *ip6_address, - struct rtnl_addr *addr, - guint prefix) +void +nm_ip6_config_add_nameserver (NMIP6Config *config, const struct in6_addr *new) { - struct nl_addr * local = NULL; - int err = 0; + NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); + int i; - g_return_val_if_fail (addr != NULL, -1); + g_return_if_fail (new != NULL); - local = nm_utils_ip6_addr_to_nl_addr (ip6_address, prefix); - err = rtnl_addr_set_local (addr, local); - nl_addr_put (local); + for (i = 0; i < priv->nameservers->len; i++) + if (IN6_ARE_ADDR_EQUAL (new, &g_array_index (priv->nameservers, struct in6_addr, i))) + return; - return err; + g_array_append_val (priv->nameservers, *new); + _NOTIFY (config, PROP_NAMESERVERS); } -static int ip6_addr_to_rtnl_peer (const struct in6_addr *ip6_address, struct rtnl_addr *addr) +void +nm_ip6_config_del_nameserver (NMIP6Config *config, guint i) { - struct nl_addr * peer = NULL; - int err = 0; + NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); + + g_return_if_fail (i < priv->nameservers->len); - g_return_val_if_fail (addr != NULL, -1); + g_array_remove_index (priv->nameservers, i); + _NOTIFY (config, PROP_NAMESERVERS); +} - peer = nm_utils_ip6_addr_to_nl_addr (ip6_address, 0); - err = rtnl_addr_set_peer (addr, peer); - nl_addr_put (peer); +guint32 +nm_ip6_config_get_num_nameservers (const NMIP6Config *config) +{ + NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); - return err; + return priv->nameservers->len; } -struct rtnl_addr * -nm_ip6_config_to_rtnl_addr (NMIP6Config *config, guint32 i, guint32 flags) +const struct in6_addr * +nm_ip6_config_get_nameserver (const NMIP6Config *config, guint i) { NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); - NMIP6Address *config_addr; - struct rtnl_addr *addr; - gboolean success = TRUE; - g_return_val_if_fail (NM_IS_IP6_CONFIG (config), NULL); + return &g_array_index (priv->nameservers, struct in6_addr, i); +} - config_addr = nm_ip6_config_get_address (config, i); - g_return_val_if_fail (config_addr != NULL, NULL); +/******************************************************************/ - if (!(addr = rtnl_addr_alloc())) - return NULL; +void +nm_ip6_config_reset_domains (NMIP6Config *config) +{ + NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); - if (flags & NM_RTNL_ADDR_ADDR) { - success = (ip6_addr_to_rtnl_local (nm_ip6_address_get_address (config_addr), - addr, - nm_ip6_address_get_prefix (config_addr)) >= 0); + if (priv->domains->len != 0) { + g_ptr_array_set_size (priv->domains, 0); + _NOTIFY (config, PROP_DOMAINS); } +} - if (flags & NM_RTNL_ADDR_PTP_ADDR) - success = (ip6_addr_to_rtnl_peer (&priv->ptp_address, addr) >= 0); +void +nm_ip6_config_add_domain (NMIP6Config *config, const char *domain) +{ + NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); + int i; - if (flags & NM_RTNL_ADDR_PREFIX) - rtnl_addr_set_prefixlen (addr, nm_ip6_address_get_prefix (config_addr)); + g_return_if_fail (domain != NULL); + g_return_if_fail (domain[0] != '\0'); - if (!success) { - rtnl_addr_put (addr); - addr = NULL; - } + for (i = 0; i < priv->domains->len; i++) + if (!g_strcmp0 (g_ptr_array_index (priv->domains, i), domain)) + return; - return addr; + g_ptr_array_add (priv->domains, g_strdup (domain)); + _NOTIFY (config, PROP_DOMAINS); } -static gboolean -addr_slist_compare (GSList *a, GSList *b) +void +nm_ip6_config_del_domain (NMIP6Config *config, guint i) { - GSList *iter_a, *iter_b; - gboolean found = FALSE; + NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); - for (iter_a = a; iter_a; iter_a = g_slist_next (iter_a)) { - NMIP6Address *addr_a = (NMIP6Address *) iter_a->data; + g_return_if_fail (i < priv->domains->len); - for (iter_b = b, found = FALSE; iter_b; iter_b = g_slist_next (iter_b)) { - NMIP6Address *addr_b = (NMIP6Address *) iter_b->data; + g_ptr_array_remove_index (priv->domains, i); + _NOTIFY (config, PROP_DOMAINS); +} - if (nm_ip6_address_compare (addr_a, addr_b)) { - found = TRUE; - break; - } - } +guint32 +nm_ip6_config_get_num_domains (const NMIP6Config *config) +{ + NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); - if (!found) - return FALSE; - } - return TRUE; + return priv->domains->len; } -static gboolean -route_slist_compare (GSList *a, GSList *b) +const char * +nm_ip6_config_get_domain (const NMIP6Config *config, guint i) { - GSList *iter_a, *iter_b; - gboolean found = FALSE; + NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); - for (iter_a = a; iter_a; iter_a = g_slist_next (iter_a)) { - NMIP6Route *route_a = (NMIP6Route *) iter_a->data; + return g_ptr_array_index (priv->domains, i); +} - for (iter_b = b, found = FALSE; iter_b; iter_b = g_slist_next (iter_b)) { - NMIP6Route *route_b = (NMIP6Route *) iter_b->data; +/******************************************************************/ - if (nm_ip6_route_compare (route_a, route_b)) { - found = TRUE; - break; - } - } +void +nm_ip6_config_reset_searches (NMIP6Config *config) +{ + NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); - if (!found) - return FALSE; + if (priv->searches->len != 0) { + g_ptr_array_set_size (priv->searches, 0); + _NOTIFY (config, PROP_SEARCHES); } - return TRUE; } -static gboolean -string_array_compare (GPtrArray *a, GPtrArray *b) +void +nm_ip6_config_add_search (NMIP6Config *config, const char *new) { - int i, j; - gboolean found = FALSE; + NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); + int i; - for (i = 0; i < a->len; i++) { - for (j = 0, found = FALSE; j < b->len; j++) { - const char *item_a = g_ptr_array_index (a, i); - const char *item_b = g_ptr_array_index (b, j); + g_return_if_fail (new != NULL); + g_return_if_fail (new[0] != '\0'); - if ((!item_a && !item_b) || (item_a && item_b && !strcmp (item_a, item_b))) { - found = TRUE; - break; - } - } + for (i = 0; i < priv->searches->len; i++) + if (!g_strcmp0 (g_ptr_array_index (priv->searches, i), new)) + return; - if (!found) - return FALSE; - } - return TRUE; + g_ptr_array_add (priv->searches, g_strdup (new)); + _NOTIFY (config, PROP_SEARCHES); } -static gboolean -addr_array_compare (GArray *a, GArray *b) -{ - struct in6_addr *addrs_a, *addrs_b; - int i, j; - gboolean found = FALSE; - - addrs_a = (struct in6_addr *)a->data; - addrs_b = (struct in6_addr *)b->data; - for (i = 0; i < a->len; i++) { - for (j = 0, found = FALSE; j < b->len; j++) { - if (IN6_ARE_ADDR_EQUAL (&addrs_a[i], &addrs_b[j])) { - found = TRUE; - break; - } - } +void +nm_ip6_config_del_search (NMIP6Config *config, guint i) +{ + NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); - if (!found) - return FALSE; - } - return TRUE; + g_return_if_fail (i < priv->searches->len); + + g_ptr_array_remove_index (priv->searches, i); + _NOTIFY (config, PROP_SEARCHES); } -NMIP6ConfigCompareFlags -nm_ip6_config_diff (NMIP6Config *a, NMIP6Config *b) +guint32 +nm_ip6_config_get_num_searches (const NMIP6Config *config) { - NMIP6ConfigPrivate *a_priv; - NMIP6ConfigPrivate *b_priv; - NMIP6ConfigCompareFlags flags = NM_IP6_COMPARE_FLAG_NONE; - - if ((a && !b) || (b && !a)) - return NM_IP6_COMPARE_FLAG_ALL; - if (!a && !b) - return NM_IP6_COMPARE_FLAG_NONE; - - a_priv = NM_IP6_CONFIG_GET_PRIVATE (a); - b_priv = NM_IP6_CONFIG_GET_PRIVATE (b); + NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); - if ( !addr_slist_compare (a_priv->addresses, b_priv->addresses) - || !addr_slist_compare (b_priv->addresses, a_priv->addresses)) - flags |= NM_IP6_COMPARE_FLAG_ADDRESSES; + return priv->searches->len; +} - if (memcmp (&a_priv->ptp_address, &b_priv->ptp_address, sizeof (struct in6_addr)) != 0) - flags |= NM_IP6_COMPARE_FLAG_PTP_ADDRESS; +const char * +nm_ip6_config_get_search (const NMIP6Config *config, guint i) +{ + NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); - if ( (a_priv->nameservers->len != b_priv->nameservers->len) - || !addr_array_compare (a_priv->nameservers, b_priv->nameservers) - || !addr_array_compare (b_priv->nameservers, a_priv->nameservers)) - flags |= NM_IP6_COMPARE_FLAG_NAMESERVERS; + return g_ptr_array_index (priv->searches, i); +} - if ( !route_slist_compare (a_priv->routes, b_priv->routes) - || !route_slist_compare (b_priv->routes, a_priv->routes)) - flags |= NM_IP6_COMPARE_FLAG_ROUTES; +/******************************************************************/ - if ( (a_priv->domains->len != b_priv->domains->len) - || !string_array_compare (a_priv->domains, b_priv->domains) - || !string_array_compare (b_priv->domains, a_priv->domains)) - flags |= NM_IP6_COMPARE_FLAG_DOMAINS; +void +nm_ip6_config_set_mss (NMIP6Config *config, guint32 mss) +{ + NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); - if ( (a_priv->searches->len != b_priv->searches->len) - || !string_array_compare (a_priv->searches, b_priv->searches) - || !string_array_compare (b_priv->searches, a_priv->searches)) - flags |= NM_IP6_COMPARE_FLAG_SEARCHES; + priv->mss = mss; +} - if (a_priv->mss != b_priv->mss) - flags |= NM_IP6_COMPARE_FLAG_MSS; +guint32 +nm_ip6_config_get_mss (const NMIP6Config *config) +{ + NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); - return flags; + return priv->mss; } +/******************************************************************/ + static inline void hash_u32 (GChecksum *sum, guint32 n) { @@ -686,40 +1393,39 @@ hash_u32 (GChecksum *sum, guint32 n) static inline void hash_in6addr (GChecksum *sum, const struct in6_addr *a) { - g_checksum_update (sum, (const guint8 *) a, sizeof (*a)); + if (a) + g_checksum_update (sum, (const guint8 *) a, sizeof (*a)); + else + g_checksum_update (sum, (const guint8 *) &in6addr_any, sizeof (in6addr_any)); } void -nm_ip6_config_hash (NMIP6Config *config, GChecksum *sum, gboolean dns_only) +nm_ip6_config_hash (const NMIP6Config *config, GChecksum *sum, gboolean dns_only) { guint32 i; - const struct in6_addr *in6a; const char *s; - g_return_if_fail (config != NULL); - g_return_if_fail (sum != NULL); + g_return_if_fail (config); + g_return_if_fail (sum); if (dns_only == FALSE) { + hash_in6addr (sum, nm_ip6_config_get_gateway (config)); + for (i = 0; i < nm_ip6_config_get_num_addresses (config); i++) { - NMIP6Address *a = nm_ip6_config_get_address (config, i); + const NMPlatformIP6Address *address = nm_ip6_config_get_address (config, i); - hash_in6addr (sum, nm_ip6_address_get_address (a)); - hash_u32 (sum, nm_ip6_address_get_prefix (a)); - hash_in6addr (sum, nm_ip6_address_get_gateway (a)); + hash_in6addr (sum, &address->address); + hash_u32 (sum, address->plen); } for (i = 0; i < nm_ip6_config_get_num_routes (config); i++) { - NMIP6Route *r = nm_ip6_config_get_route (config, i); + const NMPlatformIP6Route *route = nm_ip6_config_get_route (config, i); - hash_in6addr (sum, nm_ip6_route_get_dest (r)); - hash_u32 (sum, nm_ip6_route_get_prefix (r)); - hash_in6addr (sum, nm_ip6_route_get_next_hop (r)); - hash_u32 (sum, nm_ip6_route_get_metric (r)); + hash_in6addr (sum, &route->network); + hash_u32 (sum, route->plen); + hash_in6addr (sum, &route->gateway); + hash_u32 (sum, route->metric); } - - in6a = nm_ip6_config_get_ptp_address (config); - if (in6a) - hash_in6addr (sum, in6a); } for (i = 0; i < nm_ip6_config_get_num_nameservers (config); i++) @@ -736,15 +1442,58 @@ nm_ip6_config_hash (NMIP6Config *config, GChecksum *sum, gboolean dns_only) } } +/** + * nm_ip6_config_equal: + * @a: first config to compare + * @b: second config to compare + * + * Compares two #NMIP6Configs for basic equality. This means that all + * attributes must exist in the same order in both configs (addresses, routes, + * domains, DNS servers, etc) but some attributes (address lifetimes, and address + * and route sources) are ignored. + * + * Returns: %TRUE if the configurations are basically equal to each other, + * %FALSE if not + */ +gboolean +nm_ip6_config_equal (const NMIP6Config *a, const NMIP6Config *b) +{ + GChecksum *a_checksum = g_checksum_new (G_CHECKSUM_SHA1); + GChecksum *b_checksum = g_checksum_new (G_CHECKSUM_SHA1); + gsize a_len = g_checksum_type_get_length (G_CHECKSUM_SHA1); + gsize b_len = g_checksum_type_get_length (G_CHECKSUM_SHA1); + guchar a_data[a_len], b_data[b_len]; + gboolean equal; + + if (a) + nm_ip6_config_hash (a, a_checksum, FALSE); + if (b) + nm_ip6_config_hash (b, b_checksum, FALSE); + + g_checksum_get_digest (a_checksum, a_data, &a_len); + g_checksum_get_digest (b_checksum, b_data, &b_len); + + g_assert (a_len == b_len); + equal = !memcmp (a_data, b_data, a_len); + + g_checksum_free (a_checksum); + g_checksum_free (b_checksum); + + return equal; +} + +/******************************************************************/ + static void nm_ip6_config_init (NMIP6Config *config) { NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); + priv->addresses = g_array_new (FALSE, TRUE, sizeof (NMPlatformIP6Address)); + priv->routes = g_array_new (FALSE, TRUE, sizeof (NMPlatformIP6Route)); priv->nameservers = g_array_new (FALSE, TRUE, sizeof (struct in6_addr)); - priv->domains = g_ptr_array_sized_new (3); - priv->searches = g_ptr_array_sized_new (3); - priv->gateway_set = FALSE; + priv->domains = g_ptr_array_new_with_free_func (g_free); + priv->searches = g_ptr_array_new_with_free_func (g_free); } static void @@ -752,11 +1501,11 @@ finalize (GObject *object) { NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (object); - nm_utils_slist_free (priv->addresses, (GDestroyNotify) nm_ip6_address_unref); - nm_utils_slist_free (priv->routes, (GDestroyNotify) nm_ip6_route_unref); - g_array_free (priv->nameservers, TRUE); - g_ptr_array_free (priv->domains, TRUE); - g_ptr_array_free (priv->searches, TRUE); + g_array_unref (priv->addresses); + g_array_unref (priv->routes); + g_array_unref (priv->nameservers); + g_ptr_array_unref (priv->domains); + g_ptr_array_unref (priv->searches); G_OBJECT_CLASS (nm_ip6_config_parent_class)->finalize (object); } @@ -786,11 +1535,100 @@ static void get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { + NMIP6Config *config = NM_IP6_CONFIG (object); NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (object); switch (prop_id) { + case PROP_GATEWAY: + if (!IN6_IS_ADDR_UNSPECIFIED (&priv->gateway)) + g_value_set_string (value, nm_utils_inet6_ntop (&priv->gateway, NULL)); + else + g_value_set_string (value, NULL); + break; case PROP_ADDRESSES: - nm_utils_ip6_addresses_to_gvalue (priv->addresses, value); + { + GPtrArray *addresses = g_ptr_array_new (); + const struct in6_addr *gateway = nm_ip6_config_get_gateway (config); + int naddr = nm_ip6_config_get_num_addresses (config); + int i; + + for (i = 0; i < naddr; i++) { + const NMPlatformIP6Address *address = nm_ip6_config_get_address (config, i); + + GValueArray *array = g_value_array_new (3); + GValue element = G_VALUE_INIT; + GByteArray *ba; + + /* IP address */ + g_value_init (&element, DBUS_TYPE_G_UCHAR_ARRAY); + ba = g_byte_array_new (); + g_byte_array_append (ba, (guint8 *) &address->address, 16); + g_value_take_boxed (&element, ba); + g_value_array_append (array, &element); + g_value_unset (&element); + + /* Prefix */ + g_value_init (&element, G_TYPE_UINT); + g_value_set_uint (&element, address->plen); + g_value_array_append (array, &element); + g_value_unset (&element); + + /* Gateway */ + g_value_init (&element, DBUS_TYPE_G_UCHAR_ARRAY); + ba = g_byte_array_new (); + g_byte_array_append (ba, (guint8 *) (gateway ? gateway : &in6addr_any), sizeof (*gateway)); + g_value_take_boxed (&element, ba); + g_value_array_append (array, &element); + g_value_unset (&element); + + g_ptr_array_add (addresses, array); + } + + g_value_take_boxed (value, addresses); + } + break; + case PROP_ROUTES: + { + GPtrArray *routes = g_ptr_array_new (); + int nroutes = nm_ip6_config_get_num_routes (config); + int i; + + for (i = 0; i < nroutes; i++) { + const NMPlatformIP6Route *route = nm_ip6_config_get_route (config, i); + + GValueArray *array = g_value_array_new (4); + GByteArray *ba; + GValue element = G_VALUE_INIT; + + g_value_init (&element, DBUS_TYPE_G_UCHAR_ARRAY); + ba = g_byte_array_new (); + g_byte_array_append (ba, (guint8 *) &route->network, sizeof (route->network)); + g_value_take_boxed (&element, ba); + g_value_array_append (array, &element); + g_value_unset (&element); + + g_value_init (&element, G_TYPE_UINT); + g_value_set_uint (&element, route->plen); + g_value_array_append (array, &element); + g_value_unset (&element); + + g_value_init (&element, DBUS_TYPE_G_UCHAR_ARRAY); + ba = g_byte_array_new (); + g_byte_array_append (ba, (guint8 *) &route->gateway, sizeof (route->gateway)); + g_value_take_boxed (&element, ba); + g_value_array_append (array, &element); + g_value_unset (&element); + + g_value_init (&element, G_TYPE_UINT); + g_value_set_uint (&element, route->metric); + g_value_array_append (array, &element); + g_value_unset (&element); + + g_ptr_array_add (routes, array); + } + + g_value_take_boxed (value, routes); + } break; case PROP_NAMESERVERS: nameservers_to_gvalue (priv->nameservers, value); @@ -798,8 +1636,8 @@ get_property (GObject *object, guint prop_id, case PROP_DOMAINS: g_value_set_boxed (value, priv->domains); break; - case PROP_ROUTES: - nm_utils_ip6_routes_to_gvalue (priv->routes, value); + case PROP_SEARCHES: + g_value_set_boxed (value, priv->searches); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -819,34 +1657,46 @@ nm_ip6_config_class_init (NMIP6ConfigClass *config_class) object_class->finalize = finalize; /* properties */ - g_object_class_install_property (object_class, PROP_ADDRESSES, - g_param_spec_boxed (NM_IP6_CONFIG_ADDRESSES, - "Addresses", - "IP6 addresses", - DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS, - G_PARAM_READABLE)); - - g_object_class_install_property (object_class, PROP_NAMESERVERS, - g_param_spec_boxed (NM_IP6_CONFIG_NAMESERVERS, - "Nameservers", - "DNS list", - DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UCHAR, - G_PARAM_READABLE)); - - g_object_class_install_property (object_class, PROP_DOMAINS, - g_param_spec_boxed (NM_IP6_CONFIG_DOMAINS, - "Domains", - "Domains", - DBUS_TYPE_G_ARRAY_OF_STRING, - G_PARAM_READABLE)); - - g_object_class_install_property (object_class, PROP_ROUTES, - g_param_spec_boxed (NM_IP6_CONFIG_ROUTES, - "Routes", - "Routes", - DBUS_TYPE_G_ARRAY_OF_IP6_ROUTE, - G_PARAM_READABLE)); - - dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (config_class), - &dbus_glib_nm_ip6_config_object_info); + obj_properties[PROP_GATEWAY] = + g_param_spec_string (NM_IP6_CONFIG_GATEWAY, + "Gateway", + "IP6 Gateway", + NULL, + G_PARAM_READABLE); + obj_properties[PROP_ADDRESSES] = + g_param_spec_boxed (NM_IP6_CONFIG_ADDRESSES, + "Addresses", + "IP6 addresses", + DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS, + G_PARAM_READABLE); + obj_properties[PROP_ROUTES] = + g_param_spec_boxed (NM_IP6_CONFIG_ROUTES, + "Routes", + "Routes", + DBUS_TYPE_G_ARRAY_OF_IP6_ROUTE, + G_PARAM_READABLE); + obj_properties[PROP_NAMESERVERS] = + g_param_spec_boxed (NM_IP6_CONFIG_NAMESERVERS, + "Nameservers", + "DNS list", + DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UCHAR, + G_PARAM_READABLE); + obj_properties[PROP_DOMAINS] = + g_param_spec_boxed (NM_IP6_CONFIG_DOMAINS, + "Domains", + "Domains", + DBUS_TYPE_G_ARRAY_OF_STRING, + G_PARAM_READABLE); + obj_properties[PROP_SEARCHES] = + g_param_spec_boxed (NM_IP6_CONFIG_SEARCHES, + "Searches", + "Searches", + DBUS_TYPE_G_ARRAY_OF_STRING, + G_PARAM_READABLE); + + g_object_class_install_properties (object_class, LAST_PROP, obj_properties); + + nm_dbus_manager_register_exported_type (nm_dbus_manager_get (), + G_TYPE_FROM_CLASS (config_class), + &dbus_glib_nm_ip6_config_object_info); } diff --git a/src/nm-ip6-config.h b/src/nm-ip6-config.h index 158f5494..b7b9d83e 100644 --- a/src/nm-ip6-config.h +++ b/src/nm-ip6-config.h @@ -1,5 +1,5 @@ /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager +/* NetworkManager * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -15,23 +15,23 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright (C) 2008 Red Hat, Inc. + * Copyright (C) 2008–2013 Red Hat, Inc. */ #ifndef NM_IP6_CONFIG_H #define NM_IP6_CONFIG_H -#include #include +#include "nm-platform.h" #include "nm-setting-ip6-config.h" -#define NM_TYPE_IP6_CONFIG (nm_ip6_config_get_type ()) -#define NM_IP6_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_IP6_CONFIG, NMIP6Config)) -#define NM_IP6_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_IP6_CONFIG, NMIP6ConfigClass)) -#define NM_IS_IP6_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_IP6_CONFIG)) +#define NM_TYPE_IP6_CONFIG (nm_ip6_config_get_type ()) +#define NM_IP6_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_IP6_CONFIG, NMIP6Config)) +#define NM_IP6_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_IP6_CONFIG, NMIP6ConfigClass)) +#define NM_IS_IP6_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_IP6_CONFIG)) #define NM_IS_IP6_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_IP6_CONFIG)) -#define NM_IP6_CONFIG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_IP6_CONFIG, NMIP6ConfigClass)) +#define NM_IP6_CONFIG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_IP6_CONFIG, NMIP6ConfigClass)) typedef struct { GObject parent; @@ -41,85 +41,90 @@ typedef struct { GObjectClass parent; } NMIP6ConfigClass; +#define NM_IP6_CONFIG_GATEWAY "gateway" #define NM_IP6_CONFIG_ADDRESSES "addresses" +#define NM_IP6_CONFIG_ROUTES "routes" #define NM_IP6_CONFIG_NAMESERVERS "nameservers" #define NM_IP6_CONFIG_DOMAINS "domains" -#define NM_IP6_CONFIG_ROUTES "routes" +#define NM_IP6_CONFIG_SEARCHES "searches" GType nm_ip6_config_get_type (void); -NMIP6Config * nm_ip6_config_new (void); -void nm_ip6_config_export (NMIP6Config *config); -const char * nm_ip6_config_get_dbus_path (NMIP6Config *config); - -void nm_ip6_config_take_address (NMIP6Config *config, NMIP6Address *address); -void nm_ip6_config_add_address (NMIP6Config *config, NMIP6Address *address); -void nm_ip6_config_replace_address (NMIP6Config *config, guint32 i, NMIP6Address *new_address); -NMIP6Address *nm_ip6_config_get_address (NMIP6Config *config, guint32 i); -guint32 nm_ip6_config_get_num_addresses (NMIP6Config *config); - -const struct in6_addr *nm_ip6_config_get_ptp_address (NMIP6Config *config); -void nm_ip6_config_set_ptp_address (NMIP6Config *config, const struct in6_addr *ptp_addr); - -void nm_ip6_config_add_nameserver (NMIP6Config *config, const struct in6_addr *nameserver); -const struct in6_addr *nm_ip6_config_get_nameserver (NMIP6Config *config, guint i); -guint32 nm_ip6_config_get_num_nameservers (NMIP6Config *config); -void nm_ip6_config_reset_nameservers (NMIP6Config *config); - -void nm_ip6_config_set_gateway (NMIP6Config *config, const struct in6_addr *gateway); -const struct in6_addr *nm_ip6_config_get_gateway (NMIP6Config *config); - -void nm_ip6_config_take_route (NMIP6Config *config, NMIP6Route *route); -void nm_ip6_config_add_route (NMIP6Config *config, NMIP6Route *route); -void nm_ip6_config_replace_route (NMIP6Config *config, guint32 i, NMIP6Route *new_route); -NMIP6Route * nm_ip6_config_get_route (NMIP6Config *config, guint32 i); -guint32 nm_ip6_config_get_num_routes (NMIP6Config *config); -void nm_ip6_config_reset_routes (NMIP6Config *config); - -void nm_ip6_config_add_domain (NMIP6Config *config, const char *domain); -const char * nm_ip6_config_get_domain (NMIP6Config *config, guint i); -guint32 nm_ip6_config_get_num_domains (NMIP6Config *config); -void nm_ip6_config_reset_domains (NMIP6Config *config); - -void nm_ip6_config_add_search (NMIP6Config *config, const char *search); -const char * nm_ip6_config_get_search (NMIP6Config *config, guint i); -guint32 nm_ip6_config_get_num_searches (NMIP6Config *config); -void nm_ip6_config_reset_searches (NMIP6Config *config); - -guint32 nm_ip6_config_get_mss (NMIP6Config *config); -void nm_ip6_config_set_mss (NMIP6Config *config, guint32 mss); - -gboolean nm_ip6_config_get_never_default (NMIP6Config *config); -void nm_ip6_config_set_never_default (NMIP6Config *config, gboolean never_default); - -/* Flags for nm_ip6_config_to_rtnl_addr() */ -#define NM_RTNL_ADDR_NONE 0x0000 -#define NM_RTNL_ADDR_ADDR 0x0001 -#define NM_RTNL_ADDR_PTP_ADDR 0x0002 -#define NM_RTNL_ADDR_PREFIX 0x0004 -#define NM_RTNL_ADDR_BROADCAST 0x0008 - -#define NM_RTNL_ADDR_DEFAULT (NM_RTNL_ADDR_ADDR | NM_RTNL_ADDR_PREFIX | NM_RTNL_ADDR_BROADCAST) -#define NM_RTNL_ADDR_PTP_DEFAULT (NM_RTNL_ADDR_ADDR | NM_RTNL_ADDR_PREFIX | NM_RTNL_ADDR_PTP_ADDR) - -struct rtnl_addr *nm_ip6_config_to_rtnl_addr (NMIP6Config *config, guint32 i, guint32 flags); - -typedef enum { - NM_IP6_COMPARE_FLAG_NONE = 0x00000000, /* match nothing, kinda pointless */ - NM_IP6_COMPARE_FLAG_ADDRESSES = 0x00000001, - NM_IP6_COMPARE_FLAG_PTP_ADDRESS = 0x00000002, - NM_IP6_COMPARE_FLAG_NAMESERVERS = 0x00000004, - NM_IP6_COMPARE_FLAG_ROUTES = 0x00000008, - NM_IP6_COMPARE_FLAG_DOMAINS = 0x00000010, - NM_IP6_COMPARE_FLAG_SEARCHES = 0x00000020, - NM_IP6_COMPARE_FLAG_MSS = 0x00000080, - NM_IP6_COMPARE_FLAG_ALL = 0xFFFFFFFF /* match everything */ -} NMIP6ConfigCompareFlags; - -/* Returns a bitfield representing how the two IP6 configs differ */ -NMIP6ConfigCompareFlags nm_ip6_config_diff (NMIP6Config *a, NMIP6Config *b); - -void nm_ip6_config_hash (NMIP6Config *config, GChecksum *sum, gboolean dns_only); +NMIP6Config * nm_ip6_config_new (void); + +/* D-Bus integration */ +void nm_ip6_config_export (NMIP6Config *config); +const char * nm_ip6_config_get_dbus_path (const NMIP6Config *config); + +/* Integration with nm-platform and nm-setting */ +NMIP6Config *nm_ip6_config_capture (int ifindex, gboolean capture_resolv_conf, NMSettingIP6ConfigPrivacy use_temporary); +gboolean nm_ip6_config_commit (const NMIP6Config *config, int ifindex); +void nm_ip6_config_merge_setting (NMIP6Config *config, NMSettingIP6Config *setting, int default_route_metric); +NMSetting *nm_ip6_config_create_setting (const NMIP6Config *config); + +/* Utility functions */ +void nm_ip6_config_merge (NMIP6Config *dst, const NMIP6Config *src); +void nm_ip6_config_subtract (NMIP6Config *dst, const NMIP6Config *src); +gboolean nm_ip6_config_replace (NMIP6Config *dst, const NMIP6Config *src, gboolean *relevant_changes); +int nm_ip6_config_destination_is_direct (const NMIP6Config *config, const struct in6_addr *dest, int plen); +void nm_ip6_config_dump (const NMIP6Config *config, const char *detail); + +/* Gateways */ +void nm_ip6_config_set_never_default (NMIP6Config *config, gboolean never_default); +gboolean nm_ip6_config_get_never_default (const NMIP6Config *config); +void nm_ip6_config_set_gateway (NMIP6Config *config, const struct in6_addr *); +const struct in6_addr *nm_ip6_config_get_gateway (const NMIP6Config *config); + +/* Addresses */ +void nm_ip6_config_reset_addresses (NMIP6Config *config); +void nm_ip6_config_add_address (NMIP6Config *config, const NMPlatformIP6Address *address); +void nm_ip6_config_del_address (NMIP6Config *config, guint i); +guint nm_ip6_config_get_num_addresses (const NMIP6Config *config); +const NMPlatformIP6Address *nm_ip6_config_get_address (const NMIP6Config *config, guint i); +gboolean nm_ip6_config_address_exists (const NMIP6Config *config, const NMPlatformIP6Address *address); +gboolean nm_ip6_config_addresses_sort (NMIP6Config *config, NMSettingIP6ConfigPrivacy use_temporary); + + +/* Routes */ +void nm_ip6_config_reset_routes (NMIP6Config *config); +void nm_ip6_config_add_route (NMIP6Config *config, const NMPlatformIP6Route *route); +void nm_ip6_config_del_route (NMIP6Config *config, guint i); +guint32 nm_ip6_config_get_num_routes (const NMIP6Config *config); +const NMPlatformIP6Route *nm_ip6_config_get_route (const NMIP6Config *config, guint32 i); + +/* Nameservers */ +void nm_ip6_config_reset_nameservers (NMIP6Config *config); +void nm_ip6_config_add_nameserver (NMIP6Config *config, const struct in6_addr *nameserver); +void nm_ip6_config_del_nameserver (NMIP6Config *config, guint i); +guint32 nm_ip6_config_get_num_nameservers (const NMIP6Config *config); +const struct in6_addr *nm_ip6_config_get_nameserver (const NMIP6Config *config, guint i); + +/* Domains */ +void nm_ip6_config_reset_domains (NMIP6Config *config); +void nm_ip6_config_add_domain (NMIP6Config *config, const char *domain); +void nm_ip6_config_del_domain (NMIP6Config *config, guint i); +guint32 nm_ip6_config_get_num_domains (const NMIP6Config *config); +const char * nm_ip6_config_get_domain (const NMIP6Config *config, guint i); + +/* Search lists */ +void nm_ip6_config_reset_searches (NMIP6Config *config); +void nm_ip6_config_add_search (NMIP6Config *config, const char *search); +void nm_ip6_config_del_search (NMIP6Config *config, guint i); +guint32 nm_ip6_config_get_num_searches (const NMIP6Config *config); +const char * nm_ip6_config_get_search (const NMIP6Config *config, guint i); + +/* MSS */ +void nm_ip6_config_set_mss (NMIP6Config *config, guint32 mss); +guint32 nm_ip6_config_get_mss (const NMIP6Config *config); + +void nm_ip6_config_hash (const NMIP6Config *config, GChecksum *sum, gboolean dns_only); +gboolean nm_ip6_config_equal (const NMIP6Config *a, const NMIP6Config *b); + +/******************************************************/ +/* Testing-only functions */ + +gboolean nm_ip6_config_capture_resolv_conf (GArray *nameservers, + const char *rc_contents); #endif /* NM_IP6_CONFIG_H */ diff --git a/src/nm-manager-auth.c b/src/nm-manager-auth.c index 21192bdf..7f8b3130 100644 --- a/src/nm-manager-auth.c +++ b/src/nm-manager-auth.c @@ -31,6 +31,7 @@ #include "nm-manager-auth.h" #include "nm-logging.h" #include "nm-dbus-manager.h" +#include "nm-auth-subject.h" struct NMAuthChain { guint32 refcount; @@ -42,8 +43,12 @@ struct NMAuthChain { DBusGMethodInvocation *context; char *owner; + gulong user_uid; + NMAuthSubject *subject; GError *error; + guint idle_id; + NMAuthChainResultFunc done_func; gpointer user_data; }; @@ -52,8 +57,7 @@ typedef struct { NMAuthChain *chain; GCancellable *cancellable; char *permission; - guint idle_id; - gboolean disposed; + guint call_idle_id; } AuthCall; typedef struct { @@ -72,93 +76,123 @@ free_data (gpointer data) g_free (tmp); } +static gboolean +auth_chain_finish (gpointer user_data) +{ + NMAuthChain *self = user_data; + + self->idle_id = 0; + + /* Ensure we say alive across the callback */ + self->refcount++; + self->done_func (self, self->error, self->context, self->user_data); + nm_auth_chain_unref (self); + return FALSE; +} + #if WITH_POLKIT static PolkitAuthority * -pk_authority_get (void) +pk_authority_get (GError **error) { static PolkitAuthority *authority = NULL; - GError *error = NULL; - if (authority == NULL) { - authority = polkit_authority_get_sync (NULL, &error); - if (authority == NULL) { - nm_log_err (LOGD_CORE, "Failed to initialize PolicyKit: (%d) %s", - error ? error->code : -1, - (error && error->message) ? error->message : "(unknown)"); - g_clear_error (&error); - return NULL; - } - } + if (authority == NULL) + authority = polkit_authority_get_sync (NULL, error); /* Yes, ref every time; we want to keep the object alive */ - return g_object_ref (authority); + g_warn_if_fail (authority); + return authority ? g_object_ref (authority) : NULL; } #endif static NMAuthChain * -_auth_chain_new (DBusGMethodInvocation *context, - DBusGProxy *proxy, - DBusMessage *message, +_auth_chain_new (NMAuthSubject *subject, const char *dbus_sender, + gulong user_uid, + DBusGMethodInvocation *context, NMAuthChainResultFunc done_func, gpointer user_data) { NMAuthChain *self; - g_return_val_if_fail (context || proxy || message || dbus_sender, NULL); + g_return_val_if_fail (subject || user_uid == 0 || dbus_sender, NULL); self = g_malloc0 (sizeof (NMAuthChain)); self->refcount = 1; #if WITH_POLKIT - self->authority = pk_authority_get (); + self->authority = pk_authority_get (&self->error); #endif self->data = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, free_data); self->done_func = done_func; self->user_data = user_data; self->context = context; - if (proxy) - self->owner = g_strdup (dbus_g_proxy_get_bus_name (proxy)); - else if (context) - self->owner = dbus_g_method_get_sender (context); - else if (message) - self->owner = g_strdup (dbus_message_get_sender (message)); - else if (dbus_sender) + if (subject) { + self->user_uid = nm_auth_subject_get_uid (subject); + self->subject = g_object_ref (subject); + } else { + self->user_uid = user_uid; self->owner = g_strdup (dbus_sender); - - if (!self->owner) { - /* Need an owner */ - g_warn_if_fail (self->owner); - nm_auth_chain_unref (self); - self = NULL; + if (user_uid > 0 && !self->owner) { + /* Need an owner */ + g_warn_if_fail (self->owner); + nm_auth_chain_unref (self); + self = NULL; + } } return self; } NMAuthChain * -nm_auth_chain_new (DBusGMethodInvocation *context, - DBusGProxy *proxy, - NMAuthChainResultFunc done_func, - gpointer user_data) +nm_auth_chain_new_dbus_sender (const char *dbus_sender, + gulong user_uid, + NMAuthChainResultFunc done_func, + gpointer user_data) { - return _auth_chain_new (context, proxy, NULL, NULL, done_func, user_data); + return _auth_chain_new (NULL, dbus_sender, user_uid, NULL, done_func, user_data); } +/* Creates the NMAuthSubject automatically */ NMAuthChain * -nm_auth_chain_new_raw_message (DBusMessage *message, - NMAuthChainResultFunc done_func, - gpointer user_data) +nm_auth_chain_new_context (DBusGMethodInvocation *context, + NMAuthChainResultFunc done_func, + gpointer user_data) { - return _auth_chain_new (NULL, NULL, message, NULL, done_func, user_data); + NMAuthSubject *subject; + NMAuthChain *chain; + + g_return_val_if_fail (context != NULL, NULL); + + subject = nm_auth_subject_new_from_context (context); + if (!subject) + return NULL; + + chain = nm_auth_chain_new_subject (subject, + context, + done_func, + user_data); + g_object_unref (subject); + return chain; } +/* Requires an NMAuthSubject */ NMAuthChain * -nm_auth_chain_new_dbus_sender (const char *dbus_sender, - NMAuthChainResultFunc done_func, - gpointer user_data) +nm_auth_chain_new_subject (NMAuthSubject *subject, + DBusGMethodInvocation *context, + NMAuthChainResultFunc done_func, + gpointer user_data) { - return _auth_chain_new (NULL, NULL, NULL, dbus_sender, done_func, user_data); + NMAuthChain *chain; + + g_return_val_if_fail (NM_IS_AUTH_SUBJECT (subject), NULL); + chain = _auth_chain_new (subject, NULL, G_MAXULONG, context, done_func, user_data); + + /* Chains creation from a valid NMAuthSubject cannot fail since the + * subject already has all the necessary auth info. + */ + g_assert (chain); + return chain; } gpointer @@ -269,10 +303,8 @@ nm_auth_chain_check_done (NMAuthChain *self) g_return_if_fail (self != NULL); if (g_slist_length (self->calls) == 0) { - /* Ensure we say alive across the callback */ - self->refcount++; - self->done_func (self, self->error, self->context, self->user_data); - nm_auth_chain_unref (self); + g_assert (self->idle_id == 0); + self->idle_id = g_idle_add (auth_chain_finish, self); } } @@ -293,32 +325,15 @@ auth_call_new (NMAuthChain *chain, const char *permission) call = g_malloc0 (sizeof (AuthCall)); call->chain = chain; call->permission = g_strdup (permission); - call->cancellable = g_cancellable_new (); chain->calls = g_slist_append (chain->calls, call); return call; } -static void -auth_call_cancel (AuthCall *call) -{ - call->disposed = TRUE; - g_cancellable_cancel (call->cancellable); -} - static void auth_call_free (AuthCall *call) { - g_return_if_fail (call != NULL); - - call->disposed = TRUE; g_free (call->permission); - call->permission = NULL; - call->chain = NULL; - g_object_unref (call->cancellable); - call->cancellable = NULL; - if (call->idle_id) - g_source_remove (call->idle_id); - memset (call, 0, sizeof (*call)); + g_clear_object (&call->cancellable); g_free (call); } @@ -326,9 +341,6 @@ auth_call_free (AuthCall *call) static gboolean auth_call_complete (AuthCall *call) { - g_return_val_if_fail (call != NULL, FALSE); - - call->idle_id = 0; nm_auth_chain_remove_call (call->chain, call); nm_auth_chain_check_done (call->chain); auth_call_free (call); @@ -336,12 +348,20 @@ auth_call_complete (AuthCall *call) } static void -auth_call_schedule_early_finish (AuthCall *call, GError *error) +auth_call_cancel (gpointer user_data) { - if (!call->chain->error) - call->chain->error = error; - if (!call->idle_id) - call->idle_id = g_idle_add ((GSourceFunc) auth_call_complete, call); + AuthCall *call = user_data; + + if (call->cancellable) { + /* we don't free call immediately. Instead we cancel the async operation + * and set cancellable to NULL. pk_call_cb() will check for this and + * do the final cleanup. */ + g_cancellable_cancel (call->cancellable); + g_clear_object (&call->cancellable); + } else { + g_source_remove (call->call_idle_id); + auth_call_free (call); + } } #if WITH_POLKIT @@ -349,25 +369,26 @@ static void pk_call_cb (GObject *object, GAsyncResult *result, gpointer user_data) { AuthCall *call = user_data; - NMAuthChain *chain = call->chain; PolkitAuthorizationResult *pk_result; GError *error = NULL; - /* If the call is already disposed do nothing */ - if (call->disposed) { + pk_result = polkit_authority_check_authorization_finish ((PolkitAuthority *) object, result, &error); + + /* If the call is already canceled do nothing */ + if (!call->cancellable) { + g_clear_error (&error); + g_clear_object (&pk_result); auth_call_free (call); return; } - pk_result = polkit_authority_check_authorization_finish (chain->authority, result, &error); if (error) { - if (!chain->error) - chain->error = g_error_copy (error); + if (!call->chain->error) + call->chain->error = g_error_copy (error); nm_log_warn (LOGD_CORE, "error requesting auth for %s: (%d) %s", - call->permission, - error ? error->code : -1, - error && error->message ? error->message : "(unknown)"); + call->permission, error->code, error->message); + g_clear_error (&error); } else { guint call_result = NM_AUTH_CALL_RESULT_UNKNOWN; @@ -380,48 +401,58 @@ pk_call_cb (GObject *object, GAsyncResult *result, gpointer user_data) } else call_result = NM_AUTH_CALL_RESULT_NO; - nm_auth_chain_set_data (chain, call->permission, GUINT_TO_POINTER (call_result), NULL); - } - - g_clear_error (&error); - if (pk_result) + nm_auth_chain_set_data (call->chain, call->permission, GUINT_TO_POINTER (call_result), NULL); g_object_unref (pk_result); + } auth_call_complete (call); } -#endif -gboolean -nm_auth_chain_add_call (NMAuthChain *self, - const char *permission, - gboolean allow_interaction) +static void +auth_call_schedule_complete_with_error (AuthCall *call, const char *msg) { - AuthCall *call; + if (!call->chain->error) + call->chain->error = g_error_new_literal (DBUS_GERROR, DBUS_GERROR_FAILED, msg); + call->call_idle_id = g_idle_add ((GSourceFunc) auth_call_complete, call); +} -#if WITH_POLKIT +static gboolean +_add_call_polkit (NMAuthChain *self, + const char *permission, + gboolean allow_interaction) +{ PolkitSubject *subject; PolkitCheckAuthorizationFlags flags = POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE; + AuthCall *call; g_return_val_if_fail (self != NULL, FALSE); - g_return_val_if_fail (self->owner != NULL, FALSE); + g_return_val_if_fail (self->owner || self->subject, FALSE); g_return_val_if_fail (permission != NULL, FALSE); - subject = polkit_system_bus_name_new (self->owner); - if (!subject) - return FALSE; - call = auth_call_new (self, permission); if (self->authority == NULL) { /* No polkit, no authorization */ - auth_call_schedule_early_finish (call, g_error_new_literal (0, 0, "PolicyKit unavailable")); - g_object_unref (subject); + auth_call_schedule_complete_with_error (call, "PolicyKit not running"); return FALSE; } + if (self->subject) { + subject = g_object_ref (nm_auth_subject_get_polkit_subject (self->subject)); + g_assert (subject); + } else { + g_assert (self->owner); + subject = polkit_system_bus_name_new (self->owner); + if (!subject) { + auth_call_schedule_complete_with_error (call, "Failed to create polkit subject"); + return FALSE; + } + } + if (allow_interaction) flags = POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION; + call->cancellable = g_cancellable_new (); polkit_authority_check_authorization (self->authority, subject, permission, @@ -431,40 +462,52 @@ nm_auth_chain_add_call (NMAuthChain *self, pk_call_cb, call); g_object_unref (subject); -#else - /* -- NO POLKIT -- */ + return TRUE; +} +#endif + +gboolean +nm_auth_chain_add_call (NMAuthChain *self, + const char *permission, + gboolean allow_interaction) +{ + AuthCall *call; g_return_val_if_fail (self != NULL, FALSE); - /* When PolicyKit is disabled, everything is authorized */ - call = auth_call_new (self, permission); - nm_auth_chain_set_data (self, permission, GUINT_TO_POINTER (NM_AUTH_CALL_RESULT_YES), NULL); - auth_call_schedule_early_finish (call, NULL); +#if WITH_POLKIT + /* Non-root always gets authenticated when using polkit */ + if (self->user_uid > 0) + return _add_call_polkit (self, permission, allow_interaction); #endif + /* Root user or non-polkit always gets the permission */ + call = auth_call_new (self, permission); + nm_auth_chain_set_data (self, permission, GUINT_TO_POINTER (NM_AUTH_CALL_RESULT_YES), NULL); + call->call_idle_id = g_idle_add ((GSourceFunc) auth_call_complete, call); return TRUE; } void nm_auth_chain_unref (NMAuthChain *self) { - GSList *iter; - g_return_if_fail (self != NULL); self->refcount--; if (self->refcount > 0) return; + if (self->idle_id) + g_source_remove (self->idle_id); + #if WITH_POLKIT if (self->authority) g_object_unref (self->authority); #endif g_free (self->owner); + g_object_unref (self->subject); - for (iter = self->calls; iter; iter = g_slist_next (iter)) - auth_call_cancel ((AuthCall *) iter->data); - g_slist_free (self->calls); + g_slist_free_full (self->calls, auth_call_cancel); g_clear_error (&self->error); g_hash_table_destroy (self->data); @@ -475,59 +518,6 @@ nm_auth_chain_unref (NMAuthChain *self) /************ utils **************/ -gboolean -nm_auth_get_caller_uid (DBusGMethodInvocation *context, - NMDBusManager *dbus_mgr, - gulong *out_uid, - char **out_error_desc) -{ - DBusConnection *connection; - char *sender = NULL; - gboolean success = FALSE; - DBusError dbus_error; - - g_return_val_if_fail (context != NULL, FALSE); - g_return_val_if_fail (out_uid != NULL, FALSE); - - if (!dbus_mgr) { - dbus_mgr = nm_dbus_manager_get (); - g_assert (dbus_mgr); - } else - g_object_ref (dbus_mgr); - - *out_uid = G_MAXULONG; - - sender = dbus_g_method_get_sender (context); - if (!sender) { - if (out_error_desc) - *out_error_desc = g_strdup ("Could not determine D-Bus requestor"); - goto out; - } - - connection = nm_dbus_manager_get_dbus_connection (dbus_mgr); - if (!connection) { - if (out_error_desc) - *out_error_desc = g_strdup ("Could not get the D-Bus system bus"); - goto out; - } - - dbus_error_init (&dbus_error); - /* FIXME: do this async */ - *out_uid = dbus_bus_get_unix_user (connection, sender, &dbus_error); - if (dbus_error_is_set (&dbus_error)) { - if (out_error_desc) - *out_error_desc = g_strdup_printf ("Could not determine the user ID of the requestor"); - dbus_error_free (&dbus_error); - *out_uid = G_MAXULONG; - } else - success = TRUE; - -out: - g_object_unref (dbus_mgr); - g_free (sender); - return success; -} - gboolean nm_auth_uid_in_acl (NMConnection *connection, NMSessionMonitor *smon, @@ -545,9 +535,6 @@ nm_auth_uid_in_acl (NMConnection *connection, if (0 == uid) return TRUE; - s_con = nm_connection_get_setting_connection (connection); - g_assert (s_con); - /* Reject the request if the request comes from no session at all */ if (!nm_session_monitor_uid_has_session (smon, uid, &user, &local)) { if (out_error_desc) { @@ -565,6 +552,14 @@ nm_auth_uid_in_acl (NMConnection *connection, return FALSE; } + s_con = nm_connection_get_setting_connection (connection); + if (!s_con) { + /* This can only happen when called from AddAndActivate, so we know + * the user will be authorized when the connection is completed. + */ + return TRUE; + } + /* Match the username returned by the session check to a user in the ACL */ if (!nm_setting_connection_permissions_user_allowed (s_con, user)) { if (out_error_desc) @@ -608,7 +603,7 @@ nm_auth_changed_func_register (GDestroyNotify callback, gpointer callback_data) gboolean found = FALSE; #if WITH_POLKIT - authority = pk_authority_get (); + authority = pk_authority_get (NULL); if (!authority) return; diff --git a/src/nm-manager-auth.h b/src/nm-manager-auth.h index 15317c71..43dd6398 100644 --- a/src/nm-manager-auth.h +++ b/src/nm-manager-auth.h @@ -27,6 +27,7 @@ #include #include "nm-dbus-manager.h" #include "nm-session-monitor.h" +#include "nm-auth-subject.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" @@ -55,19 +56,20 @@ typedef void (*NMAuthChainResultFunc) (NMAuthChain *chain, DBusGMethodInvocation *context, gpointer user_data); -NMAuthChain *nm_auth_chain_new (DBusGMethodInvocation *context, - DBusGProxy *proxy, - NMAuthChainResultFunc done_func, - gpointer user_data); - -NMAuthChain *nm_auth_chain_new_raw_message (DBusMessage *message, - NMAuthChainResultFunc done_func, - gpointer user_data); - NMAuthChain *nm_auth_chain_new_dbus_sender (const char *dbus_sender, + gulong user_uid, NMAuthChainResultFunc done_func, gpointer user_data); +NMAuthChain *nm_auth_chain_new_context (DBusGMethodInvocation *context, + NMAuthChainResultFunc done_func, + gpointer user_data); + +NMAuthChain *nm_auth_chain_new_subject (NMAuthSubject *subject, + DBusGMethodInvocation *context, + NMAuthChainResultFunc done_func, + gpointer user_data); + gpointer nm_auth_chain_get_data (NMAuthChain *chain, const char *tag); gpointer nm_auth_chain_steal_data (NMAuthChain *chain, const char *tag); @@ -92,12 +94,6 @@ gboolean nm_auth_chain_add_call (NMAuthChain *chain, void nm_auth_chain_unref (NMAuthChain *chain); -/* Utils */ -gboolean nm_auth_get_caller_uid (DBusGMethodInvocation *context, - NMDBusManager *dbus_mgr, - gulong *out_uid, - char **out_error_desc); - /* Caller must free returned error description */ gboolean nm_auth_uid_in_acl (NMConnection *connection, NMSessionMonitor *smon, diff --git a/src/nm-manager-glue.h b/src/nm-manager-glue.h new file mode 100644 index 00000000..1f365b0e --- /dev/null +++ b/src/nm-manager-glue.h @@ -0,0 +1,416 @@ +/* Generated by dbus-binding-tool; do not edit! */ + + +#ifndef __dbus_glib_marshal_nm_manager_MARSHAL_H__ +#define __dbus_glib_marshal_nm_manager_MARSHAL_H__ + +#include + +G_BEGIN_DECLS + +#ifdef G_ENABLE_DEBUG +#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v) +#define g_marshal_value_peek_char(v) g_value_get_schar (v) +#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v) +#define g_marshal_value_peek_int(v) g_value_get_int (v) +#define g_marshal_value_peek_uint(v) g_value_get_uint (v) +#define g_marshal_value_peek_long(v) g_value_get_long (v) +#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v) +#define g_marshal_value_peek_int64(v) g_value_get_int64 (v) +#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v) +#define g_marshal_value_peek_enum(v) g_value_get_enum (v) +#define g_marshal_value_peek_flags(v) g_value_get_flags (v) +#define g_marshal_value_peek_float(v) g_value_get_float (v) +#define g_marshal_value_peek_double(v) g_value_get_double (v) +#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v) +#define g_marshal_value_peek_param(v) g_value_get_param (v) +#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v) +#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v) +#define g_marshal_value_peek_object(v) g_value_get_object (v) +#define g_marshal_value_peek_variant(v) g_value_get_variant (v) +#else /* !G_ENABLE_DEBUG */ +/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API. + * Do not access GValues directly in your code. Instead, use the + * g_value_get_*() functions + */ +#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int +#define g_marshal_value_peek_char(v) (v)->data[0].v_int +#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint +#define g_marshal_value_peek_int(v) (v)->data[0].v_int +#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint +#define g_marshal_value_peek_long(v) (v)->data[0].v_long +#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 +#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 +#define g_marshal_value_peek_enum(v) (v)->data[0].v_long +#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_float(v) (v)->data[0].v_float +#define g_marshal_value_peek_double(v) (v)->data[0].v_double +#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer +#endif /* !G_ENABLE_DEBUG */ + + +/* NONE:BOXED,POINTER */ +extern void dbus_glib_marshal_nm_manager_VOID__BOXED_POINTER (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); +void +dbus_glib_marshal_nm_manager_VOID__BOXED_POINTER (GClosure *closure, + GValue *return_value G_GNUC_UNUSED, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint G_GNUC_UNUSED, + gpointer marshal_data) +{ + typedef void (*GMarshalFunc_VOID__BOXED_POINTER) (gpointer data1, + gpointer arg_1, + gpointer arg_2, + gpointer data2); + register GMarshalFunc_VOID__BOXED_POINTER callback; + register GCClosure *cc = (GCClosure*) closure; + register gpointer data1, data2; + + g_return_if_fail (n_param_values == 3); + + if (G_CCLOSURE_SWAP_DATA (closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer (param_values + 0); + } + else + { + data1 = g_value_peek_pointer (param_values + 0); + data2 = closure->data; + } + callback = (GMarshalFunc_VOID__BOXED_POINTER) (marshal_data ? marshal_data : cc->callback); + + callback (data1, + g_marshal_value_peek_boxed (param_values + 1), + g_marshal_value_peek_pointer (param_values + 2), + data2); +} +#define dbus_glib_marshal_nm_manager_NONE__BOXED_POINTER dbus_glib_marshal_nm_manager_VOID__BOXED_POINTER + +/* NONE:BOOLEAN,POINTER */ +extern void dbus_glib_marshal_nm_manager_VOID__BOOLEAN_POINTER (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); +void +dbus_glib_marshal_nm_manager_VOID__BOOLEAN_POINTER (GClosure *closure, + GValue *return_value G_GNUC_UNUSED, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint G_GNUC_UNUSED, + gpointer marshal_data) +{ + typedef void (*GMarshalFunc_VOID__BOOLEAN_POINTER) (gpointer data1, + gboolean arg_1, + gpointer arg_2, + gpointer data2); + register GMarshalFunc_VOID__BOOLEAN_POINTER callback; + register GCClosure *cc = (GCClosure*) closure; + register gpointer data1, data2; + + g_return_if_fail (n_param_values == 3); + + if (G_CCLOSURE_SWAP_DATA (closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer (param_values + 0); + } + else + { + data1 = g_value_peek_pointer (param_values + 0); + data2 = closure->data; + } + callback = (GMarshalFunc_VOID__BOOLEAN_POINTER) (marshal_data ? marshal_data : cc->callback); + + callback (data1, + g_marshal_value_peek_boolean (param_values + 1), + g_marshal_value_peek_pointer (param_values + 2), + data2); +} +#define dbus_glib_marshal_nm_manager_NONE__BOOLEAN_POINTER dbus_glib_marshal_nm_manager_VOID__BOOLEAN_POINTER + +/* NONE:POINTER */ +#define dbus_glib_marshal_nm_manager_VOID__POINTER g_cclosure_marshal_VOID__POINTER +#define dbus_glib_marshal_nm_manager_NONE__POINTER dbus_glib_marshal_nm_manager_VOID__POINTER + +/* NONE:BOXED,BOXED,BOXED,POINTER */ +extern void dbus_glib_marshal_nm_manager_VOID__BOXED_BOXED_BOXED_POINTER (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); +void +dbus_glib_marshal_nm_manager_VOID__BOXED_BOXED_BOXED_POINTER (GClosure *closure, + GValue *return_value G_GNUC_UNUSED, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint G_GNUC_UNUSED, + gpointer marshal_data) +{ + typedef void (*GMarshalFunc_VOID__BOXED_BOXED_BOXED_POINTER) (gpointer data1, + gpointer arg_1, + gpointer arg_2, + gpointer arg_3, + gpointer arg_4, + gpointer data2); + register GMarshalFunc_VOID__BOXED_BOXED_BOXED_POINTER callback; + register GCClosure *cc = (GCClosure*) closure; + register gpointer data1, data2; + + g_return_if_fail (n_param_values == 5); + + if (G_CCLOSURE_SWAP_DATA (closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer (param_values + 0); + } + else + { + data1 = g_value_peek_pointer (param_values + 0); + data2 = closure->data; + } + callback = (GMarshalFunc_VOID__BOXED_BOXED_BOXED_POINTER) (marshal_data ? marshal_data : cc->callback); + + callback (data1, + g_marshal_value_peek_boxed (param_values + 1), + g_marshal_value_peek_boxed (param_values + 2), + g_marshal_value_peek_boxed (param_values + 3), + g_marshal_value_peek_pointer (param_values + 4), + data2); +} +#define dbus_glib_marshal_nm_manager_NONE__BOXED_BOXED_BOXED_POINTER dbus_glib_marshal_nm_manager_VOID__BOXED_BOXED_BOXED_POINTER + +/* NONE:STRING,STRING,POINTER */ +extern void dbus_glib_marshal_nm_manager_VOID__STRING_STRING_POINTER (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); +void +dbus_glib_marshal_nm_manager_VOID__STRING_STRING_POINTER (GClosure *closure, + GValue *return_value G_GNUC_UNUSED, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint G_GNUC_UNUSED, + gpointer marshal_data) +{ + typedef void (*GMarshalFunc_VOID__STRING_STRING_POINTER) (gpointer data1, + gpointer arg_1, + gpointer arg_2, + gpointer arg_3, + gpointer data2); + register GMarshalFunc_VOID__STRING_STRING_POINTER callback; + register GCClosure *cc = (GCClosure*) closure; + register gpointer data1, data2; + + g_return_if_fail (n_param_values == 4); + + if (G_CCLOSURE_SWAP_DATA (closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer (param_values + 0); + } + else + { + data1 = g_value_peek_pointer (param_values + 0); + data2 = closure->data; + } + callback = (GMarshalFunc_VOID__STRING_STRING_POINTER) (marshal_data ? marshal_data : cc->callback); + + callback (data1, + g_marshal_value_peek_string (param_values + 1), + g_marshal_value_peek_string (param_values + 2), + g_marshal_value_peek_pointer (param_values + 3), + data2); +} +#define dbus_glib_marshal_nm_manager_NONE__STRING_STRING_POINTER dbus_glib_marshal_nm_manager_VOID__STRING_STRING_POINTER + +/* BOOLEAN:STRING,POINTER,POINTER */ +extern void dbus_glib_marshal_nm_manager_BOOLEAN__STRING_POINTER_POINTER (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); +void +dbus_glib_marshal_nm_manager_BOOLEAN__STRING_POINTER_POINTER (GClosure *closure, + GValue *return_value G_GNUC_UNUSED, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint G_GNUC_UNUSED, + gpointer marshal_data) +{ + typedef gboolean (*GMarshalFunc_BOOLEAN__STRING_POINTER_POINTER) (gpointer data1, + gpointer arg_1, + gpointer arg_2, + gpointer arg_3, + gpointer data2); + register GMarshalFunc_BOOLEAN__STRING_POINTER_POINTER callback; + register GCClosure *cc = (GCClosure*) closure; + register gpointer data1, data2; + gboolean v_return; + + g_return_if_fail (return_value != NULL); + g_return_if_fail (n_param_values == 4); + + if (G_CCLOSURE_SWAP_DATA (closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer (param_values + 0); + } + else + { + data1 = g_value_peek_pointer (param_values + 0); + data2 = closure->data; + } + callback = (GMarshalFunc_BOOLEAN__STRING_POINTER_POINTER) (marshal_data ? marshal_data : cc->callback); + + v_return = callback (data1, + g_marshal_value_peek_string (param_values + 1), + g_marshal_value_peek_pointer (param_values + 2), + g_marshal_value_peek_pointer (param_values + 3), + data2); + + g_value_set_boolean (return_value, v_return); +} + +/* BOOLEAN:POINTER,POINTER */ +extern void dbus_glib_marshal_nm_manager_BOOLEAN__POINTER_POINTER (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); +void +dbus_glib_marshal_nm_manager_BOOLEAN__POINTER_POINTER (GClosure *closure, + GValue *return_value G_GNUC_UNUSED, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint G_GNUC_UNUSED, + gpointer marshal_data) +{ + typedef gboolean (*GMarshalFunc_BOOLEAN__POINTER_POINTER) (gpointer data1, + gpointer arg_1, + gpointer arg_2, + gpointer data2); + register GMarshalFunc_BOOLEAN__POINTER_POINTER callback; + register GCClosure *cc = (GCClosure*) closure; + register gpointer data1, data2; + gboolean v_return; + + g_return_if_fail (return_value != NULL); + g_return_if_fail (n_param_values == 3); + + if (G_CCLOSURE_SWAP_DATA (closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer (param_values + 0); + } + else + { + data1 = g_value_peek_pointer (param_values + 0); + data2 = closure->data; + } + callback = (GMarshalFunc_BOOLEAN__POINTER_POINTER) (marshal_data ? marshal_data : cc->callback); + + v_return = callback (data1, + g_marshal_value_peek_pointer (param_values + 1), + g_marshal_value_peek_pointer (param_values + 2), + data2); + + g_value_set_boolean (return_value, v_return); +} + +/* BOOLEAN:POINTER,POINTER,POINTER */ +extern void dbus_glib_marshal_nm_manager_BOOLEAN__POINTER_POINTER_POINTER (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); +void +dbus_glib_marshal_nm_manager_BOOLEAN__POINTER_POINTER_POINTER (GClosure *closure, + GValue *return_value G_GNUC_UNUSED, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint G_GNUC_UNUSED, + gpointer marshal_data) +{ + typedef gboolean (*GMarshalFunc_BOOLEAN__POINTER_POINTER_POINTER) (gpointer data1, + gpointer arg_1, + gpointer arg_2, + gpointer arg_3, + gpointer data2); + register GMarshalFunc_BOOLEAN__POINTER_POINTER_POINTER callback; + register GCClosure *cc = (GCClosure*) closure; + register gpointer data1, data2; + gboolean v_return; + + g_return_if_fail (return_value != NULL); + g_return_if_fail (n_param_values == 4); + + if (G_CCLOSURE_SWAP_DATA (closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer (param_values + 0); + } + else + { + data1 = g_value_peek_pointer (param_values + 0); + data2 = closure->data; + } + callback = (GMarshalFunc_BOOLEAN__POINTER_POINTER_POINTER) (marshal_data ? marshal_data : cc->callback); + + v_return = callback (data1, + g_marshal_value_peek_pointer (param_values + 1), + g_marshal_value_peek_pointer (param_values + 2), + g_marshal_value_peek_pointer (param_values + 3), + data2); + + g_value_set_boolean (return_value, v_return); +} + +G_END_DECLS + +#endif /* __dbus_glib_marshal_nm_manager_MARSHAL_H__ */ + +#include +static const DBusGMethodInfo dbus_glib_nm_manager_methods[] = { + { (GCallback) impl_manager_get_devices, dbus_glib_marshal_nm_manager_BOOLEAN__POINTER_POINTER, 0 }, + { (GCallback) impl_manager_get_device_by_ip_iface, dbus_glib_marshal_nm_manager_BOOLEAN__STRING_POINTER_POINTER, 62 }, + { (GCallback) impl_manager_activate_connection, dbus_glib_marshal_nm_manager_NONE__BOXED_BOXED_BOXED_POINTER, 140 }, + { (GCallback) impl_manager_add_and_activate_connection, dbus_glib_marshal_nm_manager_NONE__BOXED_BOXED_BOXED_POINTER, 265 }, + { (GCallback) impl_manager_deactivate_connection, dbus_glib_marshal_nm_manager_NONE__BOXED_POINTER, 417 }, + { (GCallback) impl_manager_sleep, dbus_glib_marshal_nm_manager_NONE__BOOLEAN_POINTER, 494 }, + { (GCallback) impl_manager_enable, dbus_glib_marshal_nm_manager_NONE__BOOLEAN_POINTER, 544 }, + { (GCallback) impl_manager_get_permissions, dbus_glib_marshal_nm_manager_NONE__POINTER, 596 }, + { (GCallback) impl_manager_set_logging, dbus_glib_marshal_nm_manager_NONE__STRING_STRING_POINTER, 669 }, + { (GCallback) impl_manager_get_logging, dbus_glib_marshal_nm_manager_BOOLEAN__POINTER_POINTER_POINTER, 736 }, + { (GCallback) impl_manager_check_connectivity, dbus_glib_marshal_nm_manager_NONE__POINTER, 811 }, + { (GCallback) impl_manager_get_state, dbus_glib_marshal_nm_manager_BOOLEAN__POINTER_POINTER, 884 }, +}; + +const DBusGObjectInfo dbus_glib_nm_manager_object_info = { 1, + dbus_glib_nm_manager_methods, + 12, +"org.freedesktop.NetworkManager\0GetDevices\0S\0devices\0O\0F\0N\0ao\0\0org.freedesktop.NetworkManager\0GetDeviceByIpIface\0S\0iface\0I\0s\0device\0O\0F\0N\0o\0\0org.freedesktop.NetworkManager\0ActivateConnection\0A\0connection\0I\0o\0device\0I\0o\0specific_object\0I\0o\0active_connection\0O\0F\0N\0o\0\0org.freedesktop.NetworkManager\0AddAndActivateConnection\0A\0connection\0I\0a{sa{sv}}\0device\0I\0o\0specific_object\0I\0o\0path\0O\0F\0N\0o\0active_connection\0O\0F\0N\0o\0\0org.freedesktop.NetworkManager\0DeactivateConnection\0A\0active_connection\0I\0o\0\0org.freedesktop.NetworkManager\0Sleep\0A\0sleep\0I\0b\0\0org.freedesktop.NetworkManager\0Enable\0A\0enable\0I\0b\0\0org.freedesktop.NetworkManager\0GetPermissions\0A\0permissions\0O\0F\0N\0a{ss}\0\0org.freedesktop.NetworkManager\0SetLogging\0A\0level\0I\0s\0domains\0I\0s\0\0org.freedesktop.NetworkManager\0GetLogging\0S\0level\0O\0F\0N\0s\0domains\0O\0F\0N\0s\0\0org.freedesktop.NetworkManager\0CheckConnectivity\0A\0connectivity\0O\0F\0N\0u\0\0org.freedesktop.NetworkManager\0state\0S\0state\0O\0F\0N\0u\0\0\0", +"org.freedesktop.NetworkManager\0CheckPermissions\0org.freedesktop.NetworkManager\0StateChanged\0org.freedesktop.NetworkManager\0PropertiesChanged\0org.freedesktop.NetworkManager\0DeviceAdded\0org.freedesktop.NetworkManager\0DeviceRemoved\0\0", +"org.freedesktop.NetworkManager\0Devices\0devices\0read\0org.freedesktop.NetworkManager\0NetworkingEnabled\0networking_enabled\0read\0org.freedesktop.NetworkManager\0WirelessEnabled\0wireless_enabled\0readwrite\0org.freedesktop.NetworkManager\0WirelessHardwareEnabled\0wireless_hardware_enabled\0read\0org.freedesktop.NetworkManager\0WwanEnabled\0wwan_enabled\0readwrite\0org.freedesktop.NetworkManager\0WwanHardwareEnabled\0wwan_hardware_enabled\0read\0org.freedesktop.NetworkManager\0WimaxEnabled\0wimax_enabled\0readwrite\0org.freedesktop.NetworkManager\0WimaxHardwareEnabled\0wimax_hardware_enabled\0read\0org.freedesktop.NetworkManager\0ActiveConnections\0active_connections\0read\0org.freedesktop.NetworkManager\0PrimaryConnection\0primary_connection\0read\0org.freedesktop.NetworkManager\0ActivatingConnection\0activating_connection\0read\0org.freedesktop.NetworkManager\0Startup\0startup\0read\0org.freedesktop.NetworkManager\0Version\0version\0read\0org.freedesktop.NetworkManager\0State\0state\0read\0org.freedesktop.NetworkManager\0Connectivity\0connectivity\0read\0\0" +}; + diff --git a/src/nm-manager.c b/src/nm-manager.c index 9037e649..09a1985a 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -21,6 +21,7 @@ #include +#include #include #include #include @@ -38,37 +39,32 @@ #include "nm-logging.h" #include "nm-dbus-manager.h" #include "nm-vpn-manager.h" -#include "nm-modem-manager.h" -#include "nm-device-bt.h" #include "nm-device.h" #include "nm-device-ethernet.h" -#include "nm-device-wifi.h" -#include "nm-device-olpc-mesh.h" -#include "nm-device-modem.h" #include "nm-device-infiniband.h" #include "nm-device-bond.h" +#include "nm-device-team.h" #include "nm-device-bridge.h" #include "nm-device-vlan.h" -#include "nm-device-adsl.h" -#include "nm-system.h" -#include "nm-properties-changed-signal.h" -#include "nm-setting-bluetooth.h" +#include "nm-device-generic.h" +#include "nm-device-veth.h" +#include "nm-device-tun.h" +#include "nm-device-macvlan.h" +#include "nm-device-vxlan.h" +#include "nm-device-gre.h" #include "nm-setting-connection.h" #include "nm-setting-wireless.h" #include "nm-setting-vpn.h" -#include "nm-marshal.h" #include "nm-dbus-glib-types.h" -#include "nm-udev-manager.h" -#include "nm-hostname-provider.h" -#include "nm-bluez-manager.h" -#include "nm-bluez-common.h" +#include "nm-platform.h" +#include "nm-rfkill-manager.h" +#include "nm-dhcp-manager.h" #include "nm-settings.h" #include "nm-settings-connection.h" #include "nm-manager-auth.h" #include "NetworkManagerUtils.h" #include "nm-utils.h" #include "nm-device-factory.h" -#include "wifi-utils.h" #include "nm-enum-types.h" #include "nm-sleep-monitor.h" #include "nm-connectivity.h" @@ -118,10 +114,10 @@ static gboolean impl_manager_get_state (NMManager *manager, guint32 *state, GError **error); -static gboolean impl_manager_set_logging (NMManager *manager, - const char *level, - const char *domains, - GError **error); +static void impl_manager_set_logging (NMManager *manager, + const char *level, + const char *domains, + DBusGMethodInvocation *context); static void impl_manager_get_logging (NMManager *manager, char **level, @@ -132,67 +128,37 @@ static void impl_manager_check_connectivity (NMManager *manager, #include "nm-manager-glue.h" -static void bluez_manager_bdaddr_added_cb (NMBluezManager *bluez_mgr, - NMBluezDevice *bt_device, - const char *bdaddr, - const char *name, - const char *object_path, - guint32 uuids, - NMManager *manager); - -static void bluez_manager_bdaddr_removed_cb (NMBluezManager *bluez_mgr, - const char *bdaddr, - const char *object_path, - gpointer user_data); - -static void add_device (NMManager *self, NMDevice *device); - -static void hostname_provider_init (NMHostnameProvider *provider_class); - -static NMActiveConnection *internal_activate_device (NMManager *manager, - NMDevice *device, - NMConnection *connection, - const char *specific_object, - gboolean user_requested, - gulong sender_uid, - const char *dbus_sender, - gboolean assumed, - NMActiveConnection *master, - GError **error); - -static NMDevice *find_device_by_ip_iface (NMManager *self, const gchar *iface); +static void add_device (NMManager *self, NMDevice *device, gboolean generate_con); +static void remove_device (NMManager *self, NMDevice *device, gboolean quitting); -static GSList * remove_one_device (NMManager *manager, - GSList *list, - NMDevice *device, - gboolean quitting); +static NMActiveConnection *_new_active_connection (NMManager *self, + NMConnection *connection, + const char *specific_object, + NMDevice *device, + NMAuthSubject *subject, + GError **error); -static void rfkill_change_wifi (const char *desc, gboolean enabled); +static void policy_activating_device_changed (GObject *object, GParamSpec *pspec, gpointer user_data); -#define SSD_POKE_INTERVAL 120 -#define ORIGDEV_TAG "originating-device" +static NMDevice *find_device_by_ip_iface (NMManager *self, const gchar *iface); -typedef struct PendingActivation PendingActivation; -typedef void (*PendingActivationFunc) (PendingActivation *pending, - GError *error); +static void rfkill_change (const char *desc, RfKillType rtype, gboolean enabled); -struct PendingActivation { - NMManager *manager; +static gboolean find_master (NMManager *self, + NMConnection *connection, + NMDevice *device, + NMConnection **out_master_connection, + NMDevice **out_master_device, + NMActiveConnection **out_master_ac, + GError **error); - DBusGMethodInvocation *context; - PendingActivationFunc callback; - NMAuthChain *chain; - const char *wifi_shared_permission; +static void nm_manager_update_state (NMManager *manager); - char *connection_path; - NMConnection *connection; - char *specific_object_path; - char *device_path; -}; +#define SSD_POKE_INTERVAL 120 +#define ORIGDEV_TAG "originating-device" typedef struct { gboolean user_enabled; - gboolean daemon_enabled; gboolean sw_enabled; gboolean hw_enabled; RfKillType rtype; @@ -200,8 +166,6 @@ typedef struct { const char *key; const char *prop; const char *hw_prop; - RfKillState (*other_enabled_func) (NMManager *); - RfKillState (*daemon_enabled_func) (NMManager *); } RadioState; typedef struct { @@ -216,13 +180,13 @@ typedef struct { NMState state; NMConnectivity *connectivity; + int ignore_link_added_cb; + NMPolicy *policy; NMDBusManager *dbus_mgr; - guint dbus_connection_changed_id; - NMUdevManager *udev_mgr; - NMBluezManager *bluez_mgr; - NMSessionMonitor *session_monitor; + gboolean prop_filter_added; + NMRfkillManager *rfkill_mgr; /* List of NMDeviceFactoryFunc pointers sorted in priority order */ GSList *factories; @@ -236,10 +200,6 @@ typedef struct { NMVPNManager *vpn_manager; - NMModemManager *modem_manager; - guint modem_added_id; - guint modem_removed_id; - DBusGProxy *aipd_proxy; NMSleepMonitor *sleep_monitor; @@ -247,27 +207,21 @@ typedef struct { /* Firmware dir monitor */ GFileMonitor *fw_monitor; - guint fw_monitor_id; guint fw_changed_id; guint timestamp_update_id; - GHashTable *nm_bridges; - - gboolean disposed; + gboolean startup; } NMManagerPrivate; #define NM_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_MANAGER, NMManagerPrivate)) -G_DEFINE_TYPE_EXTENDED (NMManager, nm_manager, G_TYPE_OBJECT, 0, - G_IMPLEMENT_INTERFACE (NM_TYPE_HOSTNAME_PROVIDER, - hostname_provider_init)) +G_DEFINE_TYPE (NMManager, nm_manager, G_TYPE_OBJECT) enum { DEVICE_ADDED, DEVICE_REMOVED, STATE_CHANGED, - PROPERTIES_CHANGED, CHECK_PERMISSIONS, USER_PERMISSIONS_CHANGED, ACTIVE_CONNECTION_ADDED, @@ -282,6 +236,7 @@ enum { PROP_0, PROP_VERSION, PROP_STATE, + PROP_STARTUP, PROP_NETWORKING_ENABLED, PROP_WIRELESS_ENABLED, PROP_WIRELESS_HARDWARE_ENABLED, @@ -293,6 +248,7 @@ enum { PROP_CONNECTIVITY, PROP_PRIMARY_CONNECTION, PROP_ACTIVATING_CONNECTION, + PROP_DEVICES, /* Not exported */ PROP_HOSTNAME, @@ -320,13 +276,29 @@ nm_manager_error_quark (void) static void active_connection_state_changed (NMActiveConnection *active, GParamSpec *pspec, NMManager *self); +static void active_connection_default_changed (NMActiveConnection *active, + GParamSpec *pspec, + NMManager *self); -static void -active_connection_removed (NMManager *self, NMActiveConnection *active) +/* Returns: whether to notify D-Bus of the removal or not */ +static gboolean +active_connection_remove (NMManager *self, NMActiveConnection *active) { - g_signal_emit (self, signals[ACTIVE_CONNECTION_REMOVED], 0, active); - g_signal_handlers_disconnect_by_func (active, active_connection_state_changed, self); - g_object_unref (active); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + gboolean notify = !!nm_active_connection_get_path (active); + GSList *found; + + /* FIXME: switch to a GList for faster removal */ + found = g_slist_find (priv->active_connections, active); + if (found) { + priv->active_connections = g_slist_remove (priv->active_connections, active); + g_signal_emit (self, signals[ACTIVE_CONNECTION_REMOVED], 0, active); + g_signal_handlers_disconnect_by_func (active, active_connection_state_changed, self); + g_signal_handlers_disconnect_by_func (active, active_connection_default_changed, self); + g_object_unref (active); + } + + return found && notify; } static gboolean @@ -335,24 +307,21 @@ _active_connection_cleanup (gpointer user_data) NMManager *self = NM_MANAGER (user_data); NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); GSList *iter; - gboolean changed = FALSE; priv->ac_cleanup_id = 0; + g_object_freeze_notify (G_OBJECT (self)); iter = priv->active_connections; while (iter) { NMActiveConnection *ac = iter->data; iter = iter->next; if (nm_active_connection_get_state (ac) == NM_ACTIVE_CONNECTION_STATE_DEACTIVATED) { - priv->active_connections = g_slist_remove (priv->active_connections, ac); - active_connection_removed (self, ac); - changed = TRUE; + if (active_connection_remove (self, ac)) + g_object_notify (G_OBJECT (self), NM_MANAGER_ACTIVE_CONNECTIONS); } } - - if (changed) - g_object_notify (G_OBJECT (self), NM_MANAGER_ACTIVE_CONNECTIONS); + g_object_thaw_notify (G_OBJECT (self)); return FALSE; } @@ -375,8 +344,25 @@ active_connection_state_changed (NMActiveConnection *active, if (!priv->ac_cleanup_id) priv->ac_cleanup_id = g_idle_add (_active_connection_cleanup, self); } + + nm_manager_update_state (self); +} + +static void +active_connection_default_changed (NMActiveConnection *active, + GParamSpec *pspec, + NMManager *self) +{ + nm_manager_update_state (self); } +/** + * active_connection_add(): + * @self: the #NMManager + * @active: the #NMActiveConnection to manage + * + * Begins to track and manage @active. Increases the refcount of @active. + */ static void active_connection_add (NMManager *self, NMActiveConnection *active) { @@ -384,13 +370,27 @@ active_connection_add (NMManager *self, NMActiveConnection *active) g_return_if_fail (g_slist_find (priv->active_connections, active) == FALSE); - priv->active_connections = g_slist_prepend (priv->active_connections, active); - g_signal_connect (active, "notify::" NM_ACTIVE_CONNECTION_STATE, + priv->active_connections = g_slist_prepend (priv->active_connections, + g_object_ref (active)); + + g_signal_connect (active, + "notify::" NM_ACTIVE_CONNECTION_STATE, G_CALLBACK (active_connection_state_changed), self); + g_signal_connect (active, + "notify::" NM_ACTIVE_CONNECTION_DEFAULT, + G_CALLBACK (active_connection_default_changed), + self); + g_signal_connect (active, + "notify::" NM_ACTIVE_CONNECTION_DEFAULT6, + G_CALLBACK (active_connection_default_changed), + self); g_signal_emit (self, signals[ACTIVE_CONNECTION_ADDED], 0, active); - g_object_notify (G_OBJECT (self), NM_MANAGER_ACTIVE_CONNECTIONS); + + /* Only notify D-Bus if the active connection is actually exported */ + if (nm_active_connection_get_path (active)) + g_object_notify (G_OBJECT (self), NM_MANAGER_ACTIVE_CONNECTIONS); } const GSList * @@ -399,6 +399,55 @@ nm_manager_get_active_connections (NMManager *manager) return NM_MANAGER_GET_PRIVATE (manager)->active_connections; } +static NMActiveConnection * +find_ac_for_connection (NMManager *manager, NMConnection *connection) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); + GSList *iter; + NMActiveConnection *ac; + NMConnection *ac_connection; + NMActiveConnectionState ac_state; + const char *uuid; + + uuid = nm_connection_get_uuid (connection); + for (iter = priv->active_connections; iter; iter = iter->next) { + ac = iter->data; + ac_connection = nm_active_connection_get_connection (ac); + ac_state = nm_active_connection_get_state (ac); + + if ( !strcmp (nm_connection_get_uuid (ac_connection), uuid) + && (ac_state < NM_ACTIVE_CONNECTION_STATE_DEACTIVATED)) + return ac; + } + + return NULL; +} + +/* Filter out connections that are already active. + * nm_settings_get_connections() returns sorted list. We need to preserve the + * order so that we didn't change auto-activation order (recent timestamps + * are first). + * Caller is responsible for freeing the returned list with g_slist_free(). + */ +GSList * +nm_manager_get_activatable_connections (NMManager *manager) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); + GSList *all_connections = nm_settings_get_connections (priv->settings); + GSList *connections = NULL, *iter; + NMConnection *connection; + + for (iter = all_connections; iter; iter = iter->next) { + connection = iter->data; + + if (!find_ac_for_connection (manager, connection)) + connections = g_slist_prepend (connections, connection); + } + + g_slist_free (all_connections); + return g_slist_reverse (connections); +} + static NMActiveConnection * active_connection_get_by_path (NMManager *manager, const char *path) { @@ -411,7 +460,7 @@ active_connection_get_by_path (NMManager *manager, const char *path) for (iter = priv->active_connections; iter; iter = g_slist_next (iter)) { NMActiveConnection *candidate = iter->data; - if (strcmp (path, nm_active_connection_get_path (candidate)) == 0) + if (g_strcmp0 (path, nm_active_connection_get_path (candidate)) == 0) return candidate; } return NULL; @@ -465,6 +514,21 @@ nm_manager_get_device_by_master (NMManager *manager, const char *master, const c return NULL; } +NMDevice * +nm_manager_get_device_by_ifindex (NMManager *manager, int ifindex) +{ + GSList *iter; + + for (iter = NM_MANAGER_GET_PRIVATE (manager)->devices; iter; iter = iter->next) { + NMDevice *device = NM_DEVICE (iter->data); + + if (nm_device_get_ifindex (device) == ifindex) + return device; + } + + return NULL; +} + static gboolean manager_sleeping (NMManager *self) { @@ -475,95 +539,41 @@ manager_sleeping (NMManager *self) return FALSE; } -static void -modem_added (NMModemManager *modem_manager, - NMModem *modem, - const char *driver, - gpointer user_data) +static const char * +_nm_state_to_string (NMState state) { - NMManager *self = NM_MANAGER (user_data); - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMDevice *replace_device, *device = NULL; - const char *modem_iface; - GSList *iter; - - /* Don't rely only on the data port; use the control port if available */ - modem_iface = nm_modem_get_data_port (modem); - if (!modem_iface) - modem_iface = nm_modem_get_control_port (modem); - g_return_if_fail (modem_iface); - - replace_device = find_device_by_ip_iface (NM_MANAGER (user_data), modem_iface); - if (replace_device) { - priv->devices = remove_one_device (NM_MANAGER (user_data), - priv->devices, - replace_device, - FALSE); - } - - /* Give Bluetooth DUN devices first chance to claim the modem */ - for (iter = priv->devices; iter; iter = g_slist_next (iter)) { - if (nm_device_get_device_type (iter->data) == NM_DEVICE_TYPE_BT) { - if (nm_device_bt_modem_added (NM_DEVICE_BT (iter->data), modem, driver)) - return; - } - } - - /* If it was a Bluetooth modem and no bluetooth device claimed it, ignore - * it. The rfcomm port (and thus the modem) gets created automatically - * by the Bluetooth code during the connection process. - */ - if (driver && !strcmp (driver, "bluetooth")) { - nm_log_info (LOGD_MB, "ignoring modem '%s' (no associated Bluetooth device)", modem_iface); - return; + switch (state) { + case NM_STATE_ASLEEP: + return "ASLEEP"; + case NM_STATE_DISCONNECTED: + return "DISCONNECTED"; + case NM_STATE_DISCONNECTING: + return "DISCONNECTING"; + case NM_STATE_CONNECTING: + return "CONNECTING"; + case NM_STATE_CONNECTED_LOCAL: + return "CONNECTED_LOCAL"; + case NM_STATE_CONNECTED_SITE: + return "CONNECTED_SITE"; + case NM_STATE_CONNECTED_GLOBAL: + return "CONNECTED_GLOBAL"; + case NM_STATE_UNKNOWN: + default: + return "UNKNOWN"; } - - /* Make the new modem device */ - device = nm_device_modem_new (modem, driver); - if (device) - add_device (self, device); } static void set_state (NMManager *manager, NMState state) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); - const char *state_str; if (priv->state == state) return; priv->state = state; - switch (state) { - case NM_STATE_ASLEEP: - state_str = "ASLEEP"; - break; - case NM_STATE_DISCONNECTED: - state_str = "DISCONNECTED"; - break; - case NM_STATE_DISCONNECTING: - state_str = "DISCONNECTING"; - break; - case NM_STATE_CONNECTING: - state_str = "CONNECTING"; - break; - case NM_STATE_CONNECTED_LOCAL: - state_str = "CONNECTED_LOCAL"; - break; - case NM_STATE_CONNECTED_SITE: - state_str = "CONNECTED_SITE"; - break; - case NM_STATE_CONNECTED_GLOBAL: - state_str = "CONNECTED_GLOBAL"; - break; - case NM_STATE_UNKNOWN: - default: - state_str = "UNKNOWN"; - break; - } - - nm_log_info (LOGD_CORE, "NetworkManager state is now %s", state_str); + nm_log_info (LOGD_CORE, "NetworkManager state is now %s", _nm_state_to_string (state)); g_object_notify (G_OBJECT (manager), NM_MANAGER_STATE); g_signal_emit (manager, signals[STATE_CHANGED], 0, priv->state); @@ -590,12 +600,59 @@ checked_connectivity (GObject *object, GAsyncResult *result, gpointer user_data) g_object_unref (manager); } +static NMState +find_best_device_state (NMManager *manager, gboolean *want_connectivity_check) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); + NMState best_state = NM_STATE_DISCONNECTED; + GSList *iter; + + for (iter = priv->active_connections; iter; iter = iter->next) { + NMActiveConnection *ac = NM_ACTIVE_CONNECTION (iter->data); + NMActiveConnectionState ac_state = nm_active_connection_get_state (ac); + + switch (ac_state) { + case NM_ACTIVE_CONNECTION_STATE_ACTIVATED: + if ( nm_active_connection_get_default (ac) + || nm_active_connection_get_default6 (ac)) { + nm_connectivity_set_online (priv->connectivity, TRUE); + if (nm_connectivity_get_state (priv->connectivity) == NM_CONNECTIVITY_FULL) { + *want_connectivity_check = FALSE; + return NM_STATE_CONNECTED_GLOBAL; + } + + best_state = NM_STATE_CONNECTING; + *want_connectivity_check = TRUE; + } else { + if (best_state < NM_STATE_CONNECTING) + best_state = NM_STATE_CONNECTED_LOCAL; + } + break; + case NM_ACTIVE_CONNECTION_STATE_ACTIVATING: + if (!nm_active_connection_get_assumed (ac)) { + if (best_state != NM_STATE_CONNECTED_GLOBAL) + best_state = NM_STATE_CONNECTING; + } + break; + case NM_ACTIVE_CONNECTION_STATE_DEACTIVATING: + if (!nm_active_connection_get_assumed (ac)) { + if (best_state < NM_STATE_DISCONNECTING) + best_state = NM_STATE_DISCONNECTING; + } + break; + default: + break; + } + } + + return best_state; +} + static void nm_manager_update_state (NMManager *manager) { NMManagerPrivate *priv; NMState new_state = NM_STATE_DISCONNECTED; - GSList *iter; gboolean want_connectivity_check = FALSE; g_return_if_fail (NM_IS_MANAGER (manager)); @@ -604,30 +661,8 @@ nm_manager_update_state (NMManager *manager) if (manager_sleeping (manager)) new_state = NM_STATE_ASLEEP; - else { - for (iter = priv->devices; iter; iter = iter->next) { - NMDevice *dev = NM_DEVICE (iter->data); - NMDeviceState state = nm_device_get_state (dev); - - if (state == NM_DEVICE_STATE_ACTIVATED) { - nm_connectivity_set_online (priv->connectivity, TRUE); - if (nm_connectivity_get_state (priv->connectivity) != NM_CONNECTIVITY_FULL) { - new_state = NM_STATE_CONNECTING; - want_connectivity_check = TRUE; - } else { - new_state = NM_STATE_CONNECTED_GLOBAL; - break; - } - } - - if (nm_device_is_activating (dev)) - new_state = NM_STATE_CONNECTING; - else if (new_state != NM_STATE_CONNECTING) { - if (state == NM_DEVICE_STATE_DEACTIVATING) - new_state = NM_STATE_DISCONNECTING; - } - } - } + else + new_state = find_best_device_state (manager, &want_connectivity_check); if (new_state == NM_STATE_CONNECTING && want_connectivity_check) { nm_connectivity_check_async (priv->connectivity, @@ -660,65 +695,99 @@ manager_device_state_changed (NMDevice *device, default: break; } +} - nm_manager_update_state (self); +static void device_has_pending_action_changed (NMDevice *device, + GParamSpec *pspec, + NMManager *self); + +static void +check_if_startup_complete (NMManager *self) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + GSList *iter; + + if (!priv->startup) + return; + + for (iter = priv->devices; iter; iter = iter->next) { + NMDevice *dev = iter->data; + + if (nm_device_has_pending_action (dev)) { + nm_log_dbg (LOGD_CORE, "check_if_startup_complete returns FALSE because of %s", + nm_device_get_iface (dev)); + return; + } + } + + nm_log_info (LOGD_CORE, "startup complete"); + + priv->startup = FALSE; + g_object_notify (G_OBJECT (self), "startup"); + + /* We don't have to watch notify::has-pending-action any more. */ + for (iter = priv->devices; iter; iter = iter->next) { + NMDevice *dev = iter->data; + + g_signal_handlers_disconnect_by_func (dev, G_CALLBACK (device_has_pending_action_changed), self); + } +} + +static void +device_has_pending_action_changed (NMDevice *device, + GParamSpec *pspec, + NMManager *self) +{ + check_if_startup_complete (self); } -/* Removes a device from a device list; returns the start of the new device list */ -static GSList * -remove_one_device (NMManager *manager, - GSList *list, - NMDevice *device, - gboolean quitting) +static void +remove_device (NMManager *manager, NMDevice *device, gboolean quitting) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); if (nm_device_get_managed (device)) { - /* When quitting, we want to leave up interfaces & connections - * that can be taken over again (ie, "assumed") when NM restarts - * so that '/etc/init.d/NetworkManager restart' will not distrupt - * networking for interfaces that support connection assumption. - * All other devices get unmanaged when NM quits so that their - * connections get torn down and the interface is deactivated. - */ + NMActRequest *req = nm_device_get_act_request (device); + gboolean unmanage = FALSE; - if ( !nm_device_can_assume_connections (device) - || (nm_device_get_state (device) != NM_DEVICE_STATE_ACTIVATED) - || !quitting) - nm_device_set_managed (device, FALSE, NM_DEVICE_STATE_REASON_REMOVED); + /* Leave activated interfaces up when quitting so their configuration + * can be taken over when NM restarts. This ensures connectivity while + * NM is stopped. Devices which do not support connection assumption + * cannot be left up. + */ + if (!quitting) /* Forced removal; device already gone */ + unmanage = TRUE; + else if (!nm_device_can_assume_active_connection (device)) + unmanage = TRUE; + else if (!req) + unmanage = TRUE; + + if (unmanage) { + if (quitting) + nm_device_set_unmanaged_quitting (device); + else + nm_device_set_unmanaged (device, NM_UNMANAGED_INTERNAL, TRUE, NM_DEVICE_STATE_REASON_REMOVED); + } } - g_signal_handlers_disconnect_by_func (device, manager_device_state_changed, manager); + g_signal_handlers_disconnect_matched (device, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, manager); + + nm_settings_device_removed (priv->settings, device, quitting); + priv->devices = g_slist_remove (priv->devices, device); - nm_settings_device_removed (priv->settings, device); g_signal_emit (manager, signals[DEVICE_REMOVED], 0, device); + g_object_notify (G_OBJECT (manager), NM_MANAGER_DEVICES); + + nm_dbus_manager_unregister_object (priv->dbus_mgr, device); g_object_unref (device); - return g_slist_remove (list, device); + check_if_startup_complete (manager); } static void -modem_removed (NMModemManager *modem_manager, - NMModem *modem, - gpointer user_data) +device_removed_cb (NMDevice *device, gpointer user_data) { - NMManager *self = NM_MANAGER (user_data); - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMDevice *found; - GSList *iter; - - /* Give Bluetooth DUN devices first chance to handle the modem removal */ - for (iter = priv->devices; iter; iter = g_slist_next (iter)) { - if (nm_device_get_device_type (iter->data) == NM_DEVICE_TYPE_BT) { - if (nm_device_bt_modem_removed (NM_DEVICE_BT (iter->data), modem)) - return; - } - } - - /* Otherwise remove the standalone modem */ - found = nm_manager_get_device_by_udi (self, nm_modem_get_path (modem)); - if (found) - priv->devices = remove_one_device (self, priv->devices, found, FALSE); + remove_device (NM_MANAGER (user_data), device, FALSE); } static void @@ -760,18 +829,6 @@ aipd_handle_event (DBusGProxy *proxy, nm_log_warn (LOGD_AUTOIP4, "(%s): unhandled avahi-autoipd event", iface); } -static const char * -hostname_provider_get_hostname (NMHostnameProvider *provider) -{ - return NM_MANAGER_GET_PRIVATE (provider)->hostname; -} - -static void -hostname_provider_init (NMHostnameProvider *provider_class) -{ - provider_class->get_hostname = hostname_provider_get_hostname; -} - NMState nm_manager_get_state (NMManager *manager) { @@ -780,315 +837,53 @@ nm_manager_get_state (NMManager *manager) return NM_MANAGER_GET_PRIVATE (manager)->state; } -static gboolean -might_be_vpn (NMConnection *connection) -{ - NMSettingConnection *s_con; - const char *ctype = NULL; - - if (nm_connection_get_setting_vpn (connection)) - return TRUE; - - /* Make sure it's not a VPN, which we can't autocomplete yet */ - s_con = nm_connection_get_setting_connection (connection); - if (s_con) - ctype = nm_setting_connection_get_connection_type (s_con); - - return (g_strcmp0 (ctype, NM_SETTING_VPN_SETTING_NAME) == 0); -} +/*******************************************************************/ +/* Settings stuff via NMSettings */ +/*******************************************************************/ -static gboolean -try_complete_vpn (NMConnection *connection, GSList *existing, GError **error) +static NMDevice * +get_device_from_hwaddr (NMManager *self, const GByteArray *setting_mac) { - g_assert (might_be_vpn (connection) == TRUE); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + const guint8 *device_mac; + guint device_mac_len; + GSList *iter; - if (!nm_connection_get_setting_vpn (connection)) { - g_set_error_literal (error, - NM_MANAGER_ERROR, - NM_MANAGER_ERROR_UNSUPPORTED_CONNECTION_TYPE, - "VPN connections require a 'vpn' setting"); - return FALSE; - } + if (!setting_mac) + return NULL; - nm_utils_complete_generic (connection, - NM_SETTING_VPN_SETTING_NAME, - existing, - _("VPN connection %d"), - NULL, - FALSE); /* No IPv6 by default for now */ + for (iter = priv->devices; iter; iter = g_slist_next (iter)) { + NMDevice *device = iter->data; - return TRUE; + device_mac = nm_device_get_hw_address (iter->data, &device_mac_len); + if ( setting_mac->len == device_mac_len + && memcmp (setting_mac->data, device_mac, device_mac_len) == 0) + return device; + } + return NULL; } -static PendingActivation * -pending_activation_new (NMManager *manager, - DBusGMethodInvocation *context, - const char *device_path, - const char *connection_path, - GHashTable *settings, - const char *specific_object_path, - PendingActivationFunc callback, - GError **error) +static NMDevice * +find_vlan_parent (NMManager *self, + NMConnection *connection) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); - PendingActivation *pending; - NMDevice *device = NULL; - NMConnection *connection = NULL; - GSList *all_connections = NULL; - gboolean success; + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + NMSettingVlan *s_vlan; + NMSettingWired *s_wired; + NMConnection *parent_connection; + const char *parent_iface; + NMDevice *parent = NULL; + const GByteArray *setting_mac; + GSList *iter; - g_return_val_if_fail (manager != NULL, NULL); - g_return_val_if_fail (context != NULL, NULL); - g_return_val_if_fail (device_path != NULL, NULL); + /* The 'parent' property could be given by an interface name, a + * connection UUID, or the MAC address of an NMSettingWired. + */ + s_vlan = nm_connection_get_setting_vlan (connection); + g_return_val_if_fail (s_vlan != NULL, NULL); - /* A object path of "/" means NULL */ - if (g_strcmp0 (specific_object_path, "/") == 0) - specific_object_path = NULL; - if (g_strcmp0 (device_path, "/") == 0) - device_path = NULL; - - /* Create the partial connection from the given settings */ - if (settings) { - if (device_path) - device = nm_manager_get_device_by_path (manager, device_path); - if (!device) { - g_set_error_literal (error, - NM_MANAGER_ERROR, - NM_MANAGER_ERROR_UNKNOWN_DEVICE, - "Device not found"); - return NULL; - } - - connection = nm_connection_new (); - nm_connection_replace_settings (connection, settings, NULL); - - all_connections = nm_settings_get_connections (priv->settings); - - if (might_be_vpn (connection)) { - /* Try to fill the VPN's connection setting and name at least */ - success = try_complete_vpn (connection, all_connections, error); - } else { - /* Let each device subclass complete the connection */ - success = nm_device_complete_connection (device, - connection, - specific_object_path, - all_connections, - error); - } - g_slist_free (all_connections); - - if (success == FALSE) { - g_object_unref (connection); - return NULL; - } - } - - pending = g_slice_new0 (PendingActivation); - pending->manager = manager; - pending->context = context; - pending->callback = callback; - - pending->connection_path = g_strdup (connection_path); - pending->connection = connection; - - /* "/" is special-cased to NULL to get through D-Bus */ - if (specific_object_path && strcmp (specific_object_path, "/")) - pending->specific_object_path = g_strdup (specific_object_path); - if (device_path && strcmp (device_path, "/")) - pending->device_path = g_strdup (device_path); - - return pending; -} - -static void -pending_auth_done (NMAuthChain *chain, - GError *error, - DBusGMethodInvocation *context, - gpointer user_data) -{ - PendingActivation *pending = user_data; - NMAuthCallResult result; - GError *tmp_error = NULL; - - /* Caller has had a chance to obtain authorization, so we only need to - * check for 'yes' here. - */ - result = GPOINTER_TO_UINT (nm_auth_chain_get_data (chain, NM_AUTH_PERMISSION_NETWORK_CONTROL)); - if (result != NM_AUTH_CALL_RESULT_YES) { - tmp_error = g_error_new_literal (NM_MANAGER_ERROR, - NM_MANAGER_ERROR_PERMISSION_DENIED, - "Not authorized to control networking."); - goto out; - } - - if (pending->wifi_shared_permission) { - result = nm_auth_chain_get_result (chain, pending->wifi_shared_permission); - if (result != NM_AUTH_CALL_RESULT_YES) { - tmp_error = g_error_new_literal (NM_MANAGER_ERROR, - NM_MANAGER_ERROR_PERMISSION_DENIED, - "Not authorized to share connections via wifi."); - goto out; - } - } - - /* Otherwise authorized and available to activate */ - -out: - pending->callback (pending, tmp_error); - g_clear_error (&tmp_error); -} - -static void -pending_activation_check_authorized (PendingActivation *pending, - NMDBusManager *dbus_mgr) -{ - NMManagerPrivate *priv; - char *error_desc = NULL; - gulong sender_uid = G_MAXULONG; - GError *error; - const char *wifi_permission = NULL; - NMConnection *connection; - - g_return_if_fail (pending != NULL); - g_return_if_fail (dbus_mgr != NULL); - - priv = NM_MANAGER_GET_PRIVATE (pending->manager); - - if (!nm_auth_get_caller_uid (pending->context, - dbus_mgr, - &sender_uid, - &error_desc)) { - error = g_error_new_literal (NM_MANAGER_ERROR, - NM_MANAGER_ERROR_PERMISSION_DENIED, - error_desc); - pending->callback (pending, error); - g_error_free (error); - g_free (error_desc); - return; - } - - /* Yay for root */ - if (0 == sender_uid) { - pending->callback (pending, NULL); - return; - } - - /* By this point we have an auto-completed connection (for AddAndActivate) - * or an existing connection (for Activate). - */ - connection = pending->connection; - if (!connection) - connection = (NMConnection *) nm_settings_get_connection_by_path (priv->settings, pending->connection_path); - - if (!connection) { - error = g_error_new_literal (NM_MANAGER_ERROR, - NM_MANAGER_ERROR_UNKNOWN_CONNECTION, - "Connection could not be found."); - pending->callback (pending, error); - g_error_free (error); - return; - } - - /* Ensure the subject has permissions for this connection */ - if (!nm_auth_uid_in_acl (connection, - priv->session_monitor, - sender_uid, - &error_desc)) { - error = g_error_new_literal (NM_MANAGER_ERROR, - NM_MANAGER_ERROR_PERMISSION_DENIED, - error_desc); - pending->callback (pending, error); - g_error_free (error); - g_free (error_desc); - return; - } - - /* First check if the user is allowed to use networking at all, giving - * the user a chance to authenticate to gain the permission. - */ - pending->chain = nm_auth_chain_new (pending->context, - NULL, - pending_auth_done, - pending); - g_assert (pending->chain); - nm_auth_chain_add_call (pending->chain, NM_AUTH_PERMISSION_NETWORK_CONTROL, TRUE); - - /* Shared wifi connections require special permissions too */ - wifi_permission = nm_utils_get_shared_wifi_permission (connection); - if (wifi_permission) { - pending->wifi_shared_permission = wifi_permission; - nm_auth_chain_add_call (pending->chain, wifi_permission, TRUE); - } -} - -static void -pending_activation_destroy (PendingActivation *pending, - GError *error, - NMActiveConnection *ac) -{ - g_return_if_fail (pending != NULL); - - if (error) - dbus_g_method_return_error (pending->context, error); - else if (ac) { - if (pending->connection) { - dbus_g_method_return (pending->context, - pending->connection_path, - nm_active_connection_get_path (ac)); - } else { - dbus_g_method_return (pending->context, - nm_active_connection_get_path (ac)); - } - } - - g_free (pending->connection_path); - g_free (pending->specific_object_path); - g_free (pending->device_path); - if (pending->connection) - g_object_unref (pending->connection); - - if (pending->chain) - nm_auth_chain_unref (pending->chain); - - memset (pending, 0, sizeof (PendingActivation)); - g_slice_free (PendingActivation, pending); -} - -/*******************************************************************/ -/* Settings stuff via NMSettings */ -/*******************************************************************/ - -static NMDevice * -get_device_from_hwaddr (NMManager *self, NMConnection *connection) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - GSList *iter; - - for (iter = priv->devices; iter; iter = g_slist_next (iter)) { - if (nm_device_hwaddr_matches (NM_DEVICE (iter->data), connection, NULL, 0, TRUE)) - return iter->data; - } - return NULL; -} - -static NMDevice* -find_vlan_parent (NMManager *self, - NMConnection *connection, - gboolean check_hwaddr) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMSettingVlan *s_vlan; - NMConnection *parent_connection; - const char *parent_iface; - NMDevice *parent = NULL; - GSList *iter; - - /* The 'parent' property could be either an interface name, a connection - * UUID, or even given by the MAC address of the connection's ethernet - * or WiFi setting. - */ - s_vlan = nm_connection_get_setting_vlan (connection); - g_return_val_if_fail (s_vlan != NULL, NULL); + s_wired = nm_connection_get_setting_wired (connection); + setting_mac = s_wired ? nm_setting_wired_get_mac_address (s_wired) : NULL; parent_iface = nm_setting_vlan_get_parent (s_vlan); if (parent_iface) { @@ -1114,18 +909,37 @@ find_vlan_parent (NMManager *self, } /* Check the hardware address of the parent connection */ - if (check_hwaddr) - return get_device_from_hwaddr (self, parent_connection); + return get_device_from_hwaddr (self, setting_mac); } return NULL; } } /* Try the hardware address from the VLAN connection's hardware setting */ - if (check_hwaddr) - return get_device_from_hwaddr (self, connection); + return get_device_from_hwaddr (self, setting_mac); +} - return NULL; +static NMDevice * +find_infiniband_parent (NMManager *self, + NMConnection *connection) +{ + NMSettingInfiniband *s_infiniband; + const char *parent_iface; + NMDevice *parent = NULL; + const GByteArray *setting_mac; + + s_infiniband = nm_connection_get_setting_infiniband (connection); + g_return_val_if_fail (s_infiniband != NULL, NULL); + + parent_iface = nm_setting_infiniband_get_parent (s_infiniband); + if (parent_iface) { + parent = find_device_by_ip_iface (self, parent_iface); + if (parent) + return parent; + } + + setting_mac = nm_setting_infiniband_get_mac_address (s_infiniband); + return get_device_from_hwaddr (self, setting_mac); } /** @@ -1146,7 +960,6 @@ get_virtual_iface_name (NMManager *self, NMConnection *connection, NMDevice **out_parent) { - char *vname = NULL; NMDevice *parent = NULL; if (out_parent) @@ -1155,17 +968,21 @@ get_virtual_iface_name (NMManager *self, if (nm_connection_is_type (connection, NM_SETTING_BOND_SETTING_NAME)) return g_strdup (nm_connection_get_virtual_iface_name (connection)); + if (nm_connection_is_type (connection, NM_SETTING_TEAM_SETTING_NAME)) + return g_strdup (nm_connection_get_virtual_iface_name (connection)); + if (nm_connection_is_type (connection, NM_SETTING_BRIDGE_SETTING_NAME)) return g_strdup (nm_connection_get_virtual_iface_name (connection)); if (nm_connection_is_type (connection, NM_SETTING_VLAN_SETTING_NAME)) { NMSettingVlan *s_vlan; const char *ifname; + char *vname; s_vlan = nm_connection_get_setting_vlan (connection); g_return_val_if_fail (s_vlan != NULL, NULL); - parent = find_vlan_parent (self, connection, TRUE); + parent = find_vlan_parent (self, connection); if (parent) { ifname = nm_connection_get_virtual_iface_name (connection); @@ -1189,113 +1006,56 @@ get_virtual_iface_name (NMManager *self, } if (out_parent) *out_parent = parent; + return vname; + } + } + + if (nm_connection_is_type (connection, NM_SETTING_INFINIBAND_SETTING_NAME)) { + const char *ifname; + char *name; + + parent = find_infiniband_parent (self, connection); + if (parent) { + ifname = nm_connection_get_virtual_iface_name (connection); + if (ifname) + name = g_strdup (ifname); + else { + NMSettingInfiniband *s_infiniband; + int p_key; + + ifname = nm_device_get_iface (parent); + s_infiniband = nm_connection_get_setting_infiniband (connection); + p_key = nm_setting_infiniband_get_p_key (s_infiniband); + name = g_strdup_printf ("%s.%04x", ifname, p_key); + } + if (out_parent) + *out_parent = parent; + return name; } } - return vname; + return NULL; } static gboolean connection_needs_virtual_device (NMConnection *connection) { if ( nm_connection_is_type (connection, NM_SETTING_BOND_SETTING_NAME) + || nm_connection_is_type (connection, NM_SETTING_TEAM_SETTING_NAME) || nm_connection_is_type (connection, NM_SETTING_BRIDGE_SETTING_NAME) || nm_connection_is_type (connection, NM_SETTING_VLAN_SETTING_NAME)) return TRUE; - return FALSE; -} - -static char * -get_virtual_iface_placeholder_udi (void) -{ - static guint32 id = 0; - - return g_strdup_printf ("/virtual/device/placeholder/%d", id++); -} - -/***************************/ - -/* FIXME: remove when we handle bridges non-destructively */ - -#define NM_BRIDGE_FILE NMRUNDIR "/nm-bridges" - -static void -read_nm_created_bridges (NMManager *self) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - char *contents; - char **lines, **iter; - GTimeVal tv; - glong ts; - - if (!g_file_get_contents (NM_BRIDGE_FILE, &contents, NULL, NULL)) - return; - - g_get_current_time (&tv); - - lines = g_strsplit_set (contents, "\n", 0); - g_free (contents); - - for (iter = lines; iter && *iter; iter++) { - if (g_str_has_prefix (*iter, "ts=")) { - errno = 0; - ts = strtol (*iter + 3, NULL, 10); - /* allow 30 minutes time difference before we ignore the file */ - if (errno || ABS (tv.tv_sec - ts) > 1800) - goto out; - } else if (g_str_has_prefix (*iter, "iface=")) - g_hash_table_insert (priv->nm_bridges, g_strdup (*iter + 6), GUINT_TO_POINTER (1)); - } - -out: - g_strfreev (lines); - unlink (NM_BRIDGE_FILE); -} - -static void -write_nm_created_bridges (NMManager *self) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - GString *br_list; - GSList *iter; - GError *error = NULL; - GTimeVal tv; - gboolean found = FALSE; - - /* write out nm-created bridges list */ - br_list = g_string_sized_new (50); - - /* Timestamp is first line */ - g_get_current_time (&tv); - g_string_append_printf (br_list, "ts=%ld\n", tv.tv_sec); - - for (iter = priv->devices; iter; iter = g_slist_next (iter)) { - NMDevice *device = iter->data; - - if (nm_device_get_device_type (device) == NM_DEVICE_TYPE_BRIDGE) { - g_string_append_printf (br_list, "iface=%s\n", nm_device_get_iface (device)); - found = TRUE; - } - } + if (nm_connection_is_type (connection, NM_SETTING_INFINIBAND_SETTING_NAME)) { + NMSettingInfiniband *s_infiniband; - if (found) { - if (!g_file_set_contents (NM_BRIDGE_FILE, br_list->str, -1, &error)) { - nm_log_warn (LOGD_BRIDGE, "Failed to write NetworkManager-created bridge list; " - "on restart bridges may not be recognized. (%s)", - error ? error->message : "unknown"); - g_clear_error (&error); - } + s_infiniband = nm_connection_get_setting_infiniband (connection); + g_return_val_if_fail (s_infiniband != NULL, FALSE); + if (nm_setting_infiniband_get_p_key (s_infiniband) != -1) + return TRUE; } - g_string_free (br_list, TRUE); -} - -static gboolean -bridge_created_by_nm (NMManager *self, const char *iface) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - return (priv->nm_bridges && g_hash_table_lookup (priv->nm_bridges, iface)); + return FALSE; } /***************************/ @@ -1315,7 +1075,7 @@ system_create_virtual_device (NMManager *self, NMConnection *connection) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); GSList *iter; - char *iface = NULL, *udi; + char *iface = NULL; NMDevice *device = NULL, *parent = NULL; iface = get_virtual_iface_name (self, connection, &parent); @@ -1328,60 +1088,37 @@ system_create_virtual_device (NMManager *self, NMConnection *connection) /* Make sure we didn't create a device for this connection already */ for (iter = priv->devices; iter; iter = g_slist_next (iter)) { NMDevice *candidate = iter->data; - GError *error = NULL; if ( g_strcmp0 (nm_device_get_iface (candidate), iface) == 0 - || nm_device_check_connection_compatible (candidate, connection, &error)) { - g_clear_error (&error); + || nm_device_check_connection_compatible (candidate, connection)) goto out; - } - g_clear_error (&error); } - if (nm_connection_is_type (connection, NM_SETTING_BOND_SETTING_NAME)) { - if (!nm_system_add_bonding_master (iface)) { - nm_log_warn (LOGD_DEVICE, "(%s): failed to add bonding master interface for '%s'", - iface, nm_connection_get_id (connection)); - goto out; - } + /* Block notification of link added since we're creating the device + * explicitly here, otherwise adding the platform/kernel device would + * create it before this function can do the rest of the setup. + */ + priv->ignore_link_added_cb++; - udi = get_virtual_iface_placeholder_udi (); - device = nm_device_bond_new (udi, iface); - g_free (udi); + if (nm_connection_is_type (connection, NM_SETTING_BOND_SETTING_NAME)) { + device = nm_device_bond_new_for_connection (connection); + } else if (nm_connection_is_type (connection, NM_SETTING_TEAM_SETTING_NAME)) { + device = nm_device_team_new_for_connection (connection); } else if (nm_connection_is_type (connection, NM_SETTING_BRIDGE_SETTING_NAME)) { - gboolean exists = FALSE; - - if (!nm_system_create_bridge (iface, &exists)) { - nm_log_warn (LOGD_DEVICE, "(%s): failed to add bridging interface for '%s'", - iface, nm_connection_get_id (connection)); - goto out; - } - - /* FIXME: remove when we handle bridges non-destructively */ - if (exists && !bridge_created_by_nm (self, iface)) { - nm_log_warn (LOGD_DEVICE, "(%s): cannot use existing bridge for '%s'", - iface, nm_connection_get_id (connection)); - goto out; - } - - udi = get_virtual_iface_placeholder_udi (); - device = nm_device_bridge_new (udi, iface); - g_free (udi); + device = nm_device_bridge_new_for_connection (connection); } else if (nm_connection_is_type (connection, NM_SETTING_VLAN_SETTING_NAME)) { - g_return_val_if_fail (parent != NULL, FALSE); + device = nm_device_vlan_new_for_connection (connection, parent); + } else if (nm_connection_is_type (connection, NM_SETTING_INFINIBAND_SETTING_NAME)) { + device = nm_device_infiniband_new_partition (connection, parent); + } - if (!nm_system_add_vlan_iface (connection, iface, nm_device_get_ip_ifindex (parent))) { - nm_log_warn (LOGD_DEVICE, "(%s): failed to add VLAN interface for '%s'", - iface, nm_connection_get_id (connection)); - goto out; - } - udi = get_virtual_iface_placeholder_udi (); - device = nm_device_vlan_new (udi, iface, parent); - g_free (udi); + if (device) { + nm_device_set_nm_owned (device); + add_device (self, device, FALSE); + g_object_unref (device); } - if (device) - add_device (self, device); + priv->ignore_link_added_cb--; out: g_free (iface); @@ -1399,14 +1136,11 @@ system_create_virtual_devices (NMManager *self) connections = nm_settings_get_connections (priv->settings); for (iter = connections; iter; iter = g_slist_next (iter)) { NMConnection *connection = iter->data; - NMSettingConnection *s_con = nm_connection_get_setting_connection (connection); - g_assert (s_con); - if (connection_needs_virtual_device (connection)) { - /* We only create a virtual interface if the connection can autoconnect */ - if (nm_setting_connection_get_autoconnect (s_con)) - system_create_virtual_device (self, connection); - } + /* We only create a virtual interface if the connection can autoconnect */ + if ( connection_needs_virtual_device (connection) + && nm_settings_connection_can_autoconnect (NM_SETTINGS_CONNECTION (connection))) + system_create_virtual_device (self, connection); } g_slist_free (connections); } @@ -1458,13 +1192,14 @@ system_unmanaged_devices_changed_cb (NMSettings *settings, unmanaged_specs = nm_settings_get_unmanaged_specs (priv->settings); for (iter = priv->devices; iter; iter = g_slist_next (iter)) { NMDevice *device = NM_DEVICE (iter->data); - gboolean managed; + gboolean unmanaged; - managed = !nm_device_spec_match_list (device, unmanaged_specs); - nm_device_set_managed (device, - managed, - managed ? NM_DEVICE_STATE_REASON_NOW_MANAGED : - NM_DEVICE_STATE_REASON_NOW_UNMANAGED); + unmanaged = nm_device_spec_match_list (device, unmanaged_specs); + nm_device_set_unmanaged (device, + NM_UNMANAGED_USER, + unmanaged, + unmanaged ? NM_DEVICE_STATE_REASON_NOW_UNMANAGED : + NM_DEVICE_STATE_REASON_NOW_MANAGED); } } @@ -1487,6 +1222,8 @@ system_hostname_changed_cb (NMSettings *settings, priv->hostname = (hostname && strlen (hostname)) ? g_strdup (hostname) : NULL; g_object_notify (G_OBJECT (self), NM_MANAGER_HOSTNAME); + nm_dhcp_manager_set_default_hostname (nm_dhcp_manager_get (), priv->hostname); + g_free (hostname); } @@ -1517,8 +1254,6 @@ write_value_to_state_file (const char *filename, FALSE); key_file = g_key_file_new (); - if (!key_file) - return FALSE; g_key_file_set_list_separator (key_file, ','); g_key_file_load_from_file (key_file, filename, G_KEY_FILE_KEEP_COMMENTS, NULL); @@ -1550,11 +1285,8 @@ radio_enabled_for_rstate (RadioState *rstate, gboolean check_changeable) gboolean enabled; enabled = rstate->user_enabled && rstate->hw_enabled; - if (check_changeable) { + if (check_changeable) enabled &= rstate->sw_enabled; - if (rstate->daemon_enabled_func) - enabled &= rstate->daemon_enabled; - } return enabled; } @@ -1598,149 +1330,46 @@ manager_update_radio_enabled (NMManager *self, } static void -manager_hidden_ap_found (NMDevice *device, - NMAccessPoint *ap, - gpointer user_data) +update_rstate_from_rfkill (NMRfkillManager *rfkill_mgr, RadioState *rstate) { - NMManager *manager = NM_MANAGER (user_data); - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); - const struct ether_addr *bssid; - GSList *iter; - GSList *connections; - gboolean done = FALSE; - - g_return_if_fail (nm_ap_get_ssid (ap) == NULL); - - bssid = nm_ap_get_address (ap); - g_assert (bssid); - - /* Look for this AP's BSSID in the seen-bssids list of a connection, - * and if a match is found, copy over the SSID */ - connections = nm_settings_get_connections (priv->settings); - for (iter = connections; iter && !done; iter = g_slist_next (iter)) { - NMConnection *connection = NM_CONNECTION (iter->data); - NMSettingWireless *s_wifi; - - s_wifi = nm_connection_get_setting_wireless (connection); - if (s_wifi) { - if (nm_settings_connection_has_seen_bssid (NM_SETTINGS_CONNECTION (connection), bssid)) - nm_ap_set_ssid (ap, nm_setting_wireless_get_ssid (s_wifi)); - } + switch (nm_rfkill_manager_get_rfkill_state (rfkill_mgr, rstate->rtype)) { + case RFKILL_UNBLOCKED: + rstate->sw_enabled = TRUE; + rstate->hw_enabled = TRUE; + break; + case RFKILL_SOFT_BLOCKED: + rstate->sw_enabled = FALSE; + rstate->hw_enabled = TRUE; + break; + case RFKILL_HARD_BLOCKED: + rstate->sw_enabled = FALSE; + rstate->hw_enabled = FALSE; + break; + default: + g_warn_if_reached (); + break; } - g_slist_free (connections); } -static RfKillState -nm_manager_get_ipw_rfkill_state (NMManager *self) +static void +manager_rfkill_update_one_type (NMManager *self, + RadioState *rstate, + RfKillType rtype) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - GSList *iter; - RfKillState ipw_state = RFKILL_UNBLOCKED; + gboolean old_enabled, new_enabled, old_rfkilled, new_rfkilled, old_hwe; - for (iter = priv->devices; iter; iter = g_slist_next (iter)) { - NMDevice *candidate = NM_DEVICE (iter->data); - RfKillState candidate_state; + old_enabled = radio_enabled_for_rstate (rstate, TRUE); + old_rfkilled = rstate->hw_enabled && rstate->sw_enabled; + old_hwe = rstate->hw_enabled; - if (nm_device_get_device_type (candidate) == NM_DEVICE_TYPE_WIFI) { - candidate_state = nm_device_wifi_get_ipw_rfkill_state (NM_DEVICE_WIFI (candidate)); - - if (candidate_state > ipw_state) - ipw_state = candidate_state; - } - } - - return ipw_state; -} - -static RfKillState -nm_manager_get_modem_enabled_state (NMManager *self) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - GSList *iter; - RfKillState wwan_state = RFKILL_UNBLOCKED; - - for (iter = priv->devices; iter; iter = g_slist_next (iter)) { - NMDevice *candidate = NM_DEVICE (iter->data); - RfKillState candidate_state = RFKILL_UNBLOCKED; - - if (nm_device_get_rfkill_type (candidate) == RFKILL_TYPE_WWAN) { - if (!nm_device_get_enabled (candidate)) - candidate_state = RFKILL_SOFT_BLOCKED; - - if (candidate_state > wwan_state) - wwan_state = candidate_state; - } - } - - return wwan_state; -} - -static void -update_rstate_from_rfkill (RadioState *rstate, RfKillState rfkill) -{ - if (rfkill == RFKILL_UNBLOCKED) { - rstate->sw_enabled = TRUE; - rstate->hw_enabled = TRUE; - } else if (rfkill == RFKILL_SOFT_BLOCKED) { - rstate->sw_enabled = FALSE; - rstate->hw_enabled = TRUE; - } else if (rfkill == RFKILL_HARD_BLOCKED) { - rstate->sw_enabled = FALSE; - rstate->hw_enabled = FALSE; - } -} - -static void -manager_rfkill_update_one_type (NMManager *self, - RadioState *rstate, - RfKillType rtype) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - RfKillState udev_state = RFKILL_UNBLOCKED; - RfKillState other_state = RFKILL_UNBLOCKED; - RfKillState composite; - gboolean old_enabled, new_enabled, old_rfkilled, new_rfkilled; - gboolean old_hwe, old_daemon_enabled = FALSE; - - old_enabled = radio_enabled_for_rstate (rstate, TRUE); - old_rfkilled = rstate->hw_enabled && rstate->sw_enabled; - old_hwe = rstate->hw_enabled; - - udev_state = nm_udev_manager_get_rfkill_state (priv->udev_mgr, rtype); - - if (rstate->other_enabled_func) - other_state = rstate->other_enabled_func (self); - - /* The composite state is the "worst" of either udev or other states */ - if (udev_state == RFKILL_HARD_BLOCKED || other_state == RFKILL_HARD_BLOCKED) - composite = RFKILL_HARD_BLOCKED; - else if (udev_state == RFKILL_SOFT_BLOCKED || other_state == RFKILL_SOFT_BLOCKED) - composite = RFKILL_SOFT_BLOCKED; - else - composite = RFKILL_UNBLOCKED; - - update_rstate_from_rfkill (rstate, composite); - - /* If the device has a management daemon that can affect enabled state, check that now */ - if (rstate->daemon_enabled_func) { - old_daemon_enabled = rstate->daemon_enabled; - rstate->daemon_enabled = (rstate->daemon_enabled_func (self) == RFKILL_UNBLOCKED); - if (old_daemon_enabled != rstate->daemon_enabled) { - nm_log_info (LOGD_RFKILL, "%s now %s by management service", - rstate->desc, - rstate->daemon_enabled ? "enabled" : "disabled"); - } - } + /* recheck kernel rfkill state */ + update_rstate_from_rfkill (priv->rfkill_mgr, rstate); /* Print out all states affecting device enablement */ if (rstate->desc) { - if (rstate->daemon_enabled_func) { - nm_log_dbg (LOGD_RFKILL, "%s hw-enabled %d sw-enabled %d daemon-enabled %d", - rstate->desc, rstate->hw_enabled, rstate->sw_enabled, rstate->daemon_enabled); - } else { - nm_log_dbg (LOGD_RFKILL, "%s hw-enabled %d sw-enabled %d", - rstate->desc, rstate->hw_enabled, rstate->sw_enabled); - } + nm_log_dbg (LOGD_RFKILL, "%s hw-enabled %d sw-enabled %d", + rstate->desc, rstate->hw_enabled, rstate->sw_enabled); } /* Log new killswitch state */ @@ -1782,20 +1411,6 @@ nm_manager_rfkill_update (NMManager *self, RfKillType rtype) } } -static void -manager_ipw_rfkill_state_changed (NMDeviceWifi *device, - GParamSpec *pspec, - gpointer user_data) -{ - nm_manager_rfkill_update (NM_MANAGER (user_data), RFKILL_TYPE_WLAN); -} - -static void -manager_modem_enabled_changed (NMDevice *device, gpointer user_data) -{ - nm_manager_rfkill_update (NM_MANAGER (user_data), RFKILL_TYPE_WWAN); -} - static void device_auth_done_cb (NMAuthChain *chain, GError *auth_error, @@ -1810,6 +1425,8 @@ device_auth_done_cb (NMAuthChain *chain, const char *permission; NMDeviceAuthRequestFunc callback; + g_assert (context); + priv->auth_chains = g_slist_remove (priv->auth_chains, chain); permission = nm_auth_chain_get_data (chain, "requested-permission"); @@ -1819,7 +1436,8 @@ device_auth_done_cb (NMAuthChain *chain, device = nm_auth_chain_get_data (chain, "device"); g_assert (device); - result = GPOINTER_TO_UINT (nm_auth_chain_get_data (chain, permission)); + result = nm_auth_chain_get_result (chain, permission); + if (auth_error) { /* translate the auth error into a manager permission denied error */ nm_log_dbg (LOGD_CORE, "%s request failed: %s", permission, auth_error->message); @@ -1858,112 +1476,283 @@ device_auth_request_cb (NMDevice *device, { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); GError *error = NULL; - gulong sender_uid = G_MAXULONG; + NMAuthSubject *subject = NULL; char *error_desc = NULL; NMAuthChain *chain; - /* Get the caller's UID for the root check */ - if (!nm_auth_get_caller_uid (context, priv->dbus_mgr, &sender_uid, &error_desc)) { + /* Validate the caller */ + subject = nm_auth_subject_new_from_context (context); + if (!subject) { error = g_error_new_literal (NM_MANAGER_ERROR, NM_MANAGER_ERROR_PERMISSION_DENIED, - error_desc); - callback (device, context, error, user_data); - g_error_free (error); - g_free (error_desc); - return; + "Failed to get request UID."); + goto done; } /* Ensure the subject has permissions for this connection */ - if (!nm_auth_uid_in_acl (connection, - priv->session_monitor, - sender_uid, - &error_desc)) { + if (connection && !nm_auth_uid_in_acl (connection, + nm_session_monitor_get (), + nm_auth_subject_get_uid (subject), + &error_desc)) { error = g_error_new_literal (NM_MANAGER_ERROR, NM_MANAGER_ERROR_PERMISSION_DENIED, error_desc); + g_free (error_desc); + goto done; + } + + /* Validate the request */ + chain = nm_auth_chain_new_subject (subject, context, device_auth_done_cb, self); + if (!chain) { + error = g_error_new_literal (NM_MANAGER_ERROR, + NM_MANAGER_ERROR_PERMISSION_DENIED, + "Unable to authenticate request."); + goto done; + } + + priv->auth_chains = g_slist_append (priv->auth_chains, chain); + nm_auth_chain_set_data (chain, "device", g_object_ref (device), g_object_unref); + nm_auth_chain_set_data (chain, "requested-permission", g_strdup (permission), g_free); + nm_auth_chain_set_data (chain, "callback", callback, NULL); + nm_auth_chain_set_data (chain, "user-data", user_data, NULL); + nm_auth_chain_add_call (chain, permission, allow_interaction); + +done: + g_clear_object (&subject); + if (error) callback (device, context, error, user_data); + g_clear_error (&error); +} + +/* This should really be moved to gsystem. */ +#define free_slist __attribute__ ((cleanup(local_slist_free))) +static void +local_slist_free (void *loc) +{ + GSList **location = loc; + + if (location) + g_slist_free (*location); +} + +static gboolean +match_connection_filter (NMConnection *connection, gpointer user_data) +{ + return nm_device_check_connection_compatible (NM_DEVICE (user_data), connection); +} + +/** + * get_existing_connection: + * @manager: #NMManager instance + * @device: #NMDevice instance + * + * Returns: a #NMSettingsConnection to be assumed by the device, or %NULL if + * the device does not support assuming existing connections. + */ +static NMConnection * +get_existing_connection (NMManager *manager, NMDevice *device) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); + free_slist GSList *connections = nm_manager_get_activatable_connections (manager); + NMConnection *connection = NULL, *matched; + NMSettingsConnection *added = NULL; + GError *error = NULL; + + nm_device_capture_initial_config (device); + + /* The core of the API is nm_device_generate_connection() function and + * update_connection() virtual method and the convenient connection_type + * class attribute. Subclasses supporting the new API must have + * update_connection() implemented, otherwise nm_device_generate_connection() + * returns NULL. + */ + connection = nm_device_generate_connection (device); + if (!connection) + return NULL; + + /* Now we need to compare the generated connection to each configured + * connection. The comparison function is the heart of the connection + * assumption implementation and it must compare the connections very + * carefully to sort out various corner cases. Also, the comparison is + * not entirely symmetric. + * + * When no configured connection matches the generated connection, we keep + * the generated connection instead. + */ + connections = g_slist_reverse (g_slist_sort (connections, nm_settings_sort_connections)); + matched = nm_utils_match_connection (connections, + connection, + nm_device_has_carrier (device), + match_connection_filter, + device); + if (matched) { + nm_log_info (LOGD_DEVICE, "(%s): found matching connection '%s'", + nm_device_get_iface (device), + nm_connection_get_id (matched)); + g_object_unref (connection); + return matched; + } + + nm_log_dbg (LOGD_DEVICE, "(%s): generated connection '%s'", + nm_device_get_iface (device), + nm_connection_get_id (connection)); + + added = nm_settings_add_connection (priv->settings, connection, FALSE, &error); + if (added) + nm_settings_connection_set_nm_generated (added); + else { + nm_log_warn (LOGD_SETTINGS, "(%s) Couldn't save generated connection '%s': %s", + nm_device_get_iface (device), + nm_connection_get_id (connection), + (error && error->message) ? error->message : "(unknown)"); + g_clear_error (&error); + } + g_object_unref (connection); + + return added ? NM_CONNECTION (added) : NULL; +} + +static gboolean +assume_connection (NMManager *self, NMDevice *device, NMConnection *connection) +{ + NMActiveConnection *active, *master_ac; + NMAuthSubject *subject; + GError *error = NULL; + + nm_log_dbg (LOGD_DEVICE, "(%s): will attempt to assume connection", + nm_device_get_iface (device)); + + /* Move device to DISCONNECTED to activate the connection */ + if (nm_device_get_state (device) == NM_DEVICE_STATE_UNAVAILABLE) { + nm_device_state_changed (device, + NM_DEVICE_STATE_DISCONNECTED, + NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED); + } + g_return_val_if_fail (nm_device_get_state (device) >= NM_DEVICE_STATE_DISCONNECTED, FALSE); + + subject = nm_auth_subject_new_internal (); + active = _new_active_connection (self, connection, NULL, device, subject, &error); + g_object_unref (subject); + + if (!active) { + nm_log_warn (LOGD_DEVICE, "assumed connection %s failed to activate: (%d) %s", + nm_connection_get_path (connection), + error ? error->code : -1, + error && error->message ? error->message : "(unknown)"); g_error_free (error); - g_free (error_desc); + return FALSE; + } + + /* If the device is a slave or VLAN, find the master ActiveConnection */ + master_ac = NULL; + if (find_master (self, connection, device, NULL, NULL, &master_ac, NULL) && master_ac) + nm_active_connection_set_master (active, master_ac); + + nm_active_connection_set_assumed (active, TRUE); + nm_active_connection_export (active); + active_connection_add (self, active); + nm_device_queue_activation (device, NM_ACT_REQUEST (active)); + g_object_unref (active); + + return TRUE; +} + +static void +recheck_assume_connection (NMDevice *device, gpointer user_data) +{ + NMManager *self = user_data; + NMConnection *connection; + gboolean was_unmanaged = FALSE; + + if (manager_sleeping (self)) + return; + if (nm_device_get_unmanaged_flag (device, NM_UNMANAGED_USER)) + return; + + connection = get_existing_connection (self, device); + if (!connection) { + nm_log_dbg (LOGD_DEVICE, "(%s): can't assume; no connection", + nm_device_get_iface (device)); return; } - /* Yay for root */ - if (0 == sender_uid) - callback (device, context, NULL, user_data); - else { - /* Otherwise validate the non-root request */ - chain = nm_auth_chain_new (context, NULL, device_auth_done_cb, self); - g_assert (chain); - priv->auth_chains = g_slist_append (priv->auth_chains, chain); + if (nm_device_get_state (device) == NM_DEVICE_STATE_UNMANAGED) { + was_unmanaged = TRUE; + nm_device_state_changed (device, + NM_DEVICE_STATE_UNAVAILABLE, + NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED); + } - nm_auth_chain_set_data (chain, "device", g_object_ref (device), g_object_unref); - nm_auth_chain_set_data (chain, "requested-permission", g_strdup (permission), g_free); - nm_auth_chain_set_data (chain, "callback", callback, NULL); - nm_auth_chain_set_data (chain, "user-data", user_data, NULL); - nm_auth_chain_add_call (chain, permission, allow_interaction); + if (!assume_connection (self, device, connection)) { + if (was_unmanaged) { + nm_device_state_changed (device, + NM_DEVICE_STATE_UNAVAILABLE, + NM_DEVICE_STATE_REASON_CONFIG_FAILED); + nm_device_state_changed (device, + NM_DEVICE_STATE_UNMANAGED, + NM_DEVICE_STATE_REASON_CONFIG_FAILED); + } } } +/** + * add_device: + * @self: the #NMManager + * @device: the #NMDevice to add + * @generate_con: %TRUE if existing connection (if any) should be assumed + * + * If successful, this function will increase the references count of @device. + * Callers should decrease the reference count. + */ static void -add_device (NMManager *self, NMDevice *device) +add_device (NMManager *self, NMDevice *device, gboolean generate_con) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); const char *iface, *driver, *type_desc; - char *path; - static guint32 devcount = 0; const GSList *unmanaged_specs; - NMConnection *existing = NULL; - gboolean managed = FALSE, enabled = FALSE; + gboolean user_unmanaged, sleeping; + NMConnection *connection = NULL; + gboolean enabled = FALSE; RfKillType rtype; - NMDeviceType devtype; - - iface = nm_device_get_ip_iface (device); - g_assert (iface); + GSList *iter, *remove = NULL; - devtype = nm_device_get_device_type (device); + /* No duplicates */ + if (nm_manager_get_device_by_udi (self, nm_device_get_udi (device))) + return; - /* Ignore the device if we already know about it. But some modems will - * provide pseudo-ethernet devices that NM has already claimed while - * ModemManager is still detecting the modem's serial ports, so when the - * MM modem object finally shows up it may have the same IP interface as the - * ethernet interface we've already detected. In this case we skip the - * check for an existing device with the same IP interface name and kill - * the ethernet device later in favor of the modem device. + /* Remove existing devices owned by the new device; eg remove ethernet + * ports that are owned by a WWAN modem, since udev may announce them + * before the modem is fully discovered. + * + * FIXME: use parent/child device relationships instead of removing + * the child NMDevice entirely */ - if ((devtype != NM_DEVICE_TYPE_MODEM) && find_device_by_ip_iface (self, iface)) { - g_object_unref (device); - return; + for (iter = priv->devices; iter; iter = iter->next) { + iface = nm_device_get_ip_iface (iter->data); + if (nm_device_owns_iface (device, iface)) + remove = g_slist_prepend (remove, iter->data); } + for (iter = remove; iter; iter = iter->next) + remove_device (self, NM_DEVICE (iter->data), FALSE); + g_slist_free (remove); - nm_device_set_connection_provider (device, NM_CONNECTION_PROVIDER (priv->settings)); - - priv->devices = g_slist_append (priv->devices, device); + priv->devices = g_slist_append (priv->devices, g_object_ref (device)); g_signal_connect (device, "state-changed", - G_CALLBACK (manager_device_state_changed), - self); + G_CALLBACK (manager_device_state_changed), + self); g_signal_connect (device, NM_DEVICE_AUTH_REQUEST, G_CALLBACK (device_auth_request_cb), self); - if (devtype == NM_DEVICE_TYPE_WIFI) { - /* Attach to the access-point-added signal so that the manager can fill - * non-SSID-broadcasting APs with an SSID. - */ - g_signal_connect (device, "hidden-ap-found", - G_CALLBACK (manager_hidden_ap_found), - self); + g_signal_connect (device, NM_DEVICE_REMOVED, + G_CALLBACK (device_removed_cb), + self); - /* Hook up rfkill handling for ipw-based cards until they get converted - * to use the kernel's rfkill subsystem in 2.6.33. - */ - g_signal_connect (device, "notify::" NM_DEVICE_WIFI_IPW_RFKILL_STATE, - G_CALLBACK (manager_ipw_rfkill_state_changed), - self); - } else if (devtype == NM_DEVICE_TYPE_MODEM) { - g_signal_connect (device, NM_DEVICE_MODEM_ENABLE_CHANGED, - G_CALLBACK (manager_modem_enabled_changed), + if (priv->startup) { + g_signal_connect (device, "notify::" NM_DEVICE_HAS_PENDING_ACTION, + G_CALLBACK (device_has_pending_action_changed), self); } @@ -1978,6 +1767,9 @@ add_device (NMManager *self, NMDevice *device) nm_device_set_enabled (device, enabled); } + iface = nm_device_get_iface (device); + g_assert (iface); + type_desc = nm_device_get_type_desc (device); g_assert (type_desc); driver = nm_device_get_driver (device); @@ -1986,121 +1778,47 @@ add_device (NMManager *self, NMDevice *device) nm_log_info (LOGD_HW, "(%s): new %s device (driver: '%s' ifindex: %d)", iface, type_desc, driver, nm_device_get_ifindex (device)); - path = g_strdup_printf ("/org/freedesktop/NetworkManager/Devices/%d", devcount++); - nm_device_set_path (device, path); - dbus_g_connection_register_g_object (nm_dbus_manager_get_connection (priv->dbus_mgr), - path, - G_OBJECT (device)); - nm_log_info (LOGD_CORE, "(%s): exported as %s", iface, path); - g_free (path); + unmanaged_specs = nm_settings_get_unmanaged_specs (priv->settings); + user_unmanaged = nm_device_spec_match_list (device, unmanaged_specs); + nm_device_set_initial_unmanaged_flag (device, NM_UNMANAGED_USER, user_unmanaged); - /* Check if we should assume the device's active connection by matching its - * config with an existing system connection. - */ - if (nm_device_can_assume_connections (device)) { - GSList *connections = NULL; + sleeping = manager_sleeping (self); + nm_device_set_initial_unmanaged_flag (device, NM_UNMANAGED_INTERNAL, sleeping); - connections = nm_settings_get_connections (priv->settings); - existing = nm_device_connection_match_config (device, (const GSList *) connections); - g_slist_free (connections); + nm_device_dbus_export (device); - if (existing) - nm_log_dbg (LOGD_DEVICE, "(%s): found existing device connection '%s'", - nm_device_get_iface (device), - nm_connection_get_id (existing)); - } + /* Don't generate a connection e.g. for devices NM just created, or + * for the loopback, or when we're sleeping. */ + if (generate_con && !user_unmanaged && !sleeping) + connection = get_existing_connection (self, device); - /* Start the device if it's supposed to be managed */ - unmanaged_specs = nm_settings_get_unmanaged_specs (priv->settings); - if ( !manager_sleeping (self) - && !nm_device_spec_match_list (device, unmanaged_specs)) { - nm_device_set_managed (device, - TRUE, - existing ? NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED : - NM_DEVICE_STATE_REASON_NOW_MANAGED); - managed = TRUE; + /* Start the device if it's supposed to be managed. Note that this will + * manage default-unmanaged devices if they have a generated connection. + */ + if (nm_device_get_managed (device) || connection) { + nm_device_state_changed (device, + NM_DEVICE_STATE_UNAVAILABLE, + connection ? NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED : + NM_DEVICE_STATE_REASON_NOW_MANAGED); } nm_settings_device_added (priv->settings, device); g_signal_emit (self, signals[DEVICE_ADDED], 0, device); + g_object_notify (G_OBJECT (self), NM_MANAGER_DEVICES); /* New devices might be master interfaces for virtual interfaces; so we may * need to create new virtual interfaces now. */ system_create_virtual_devices (self); - /* If the device has a connection it can assume, do that now */ - if (existing && managed && nm_device_is_available (device)) { - NMActiveConnection *ac; - GError *error = NULL; - - nm_log_dbg (LOGD_DEVICE, "(%s): will attempt to assume existing connection", - nm_device_get_iface (device)); - - ac = internal_activate_device (self, device, existing, NULL, FALSE, 0, NULL, TRUE, NULL, &error); - if (!ac) { - nm_log_warn (LOGD_DEVICE, "assumed connection %s failed to activate: (%d) %s", - nm_connection_get_path (existing), - error ? error->code : -1, - error && error->message ? error->message : "(unknown)"); - g_error_free (error); - } - } -} - -static void -bluez_manager_bdaddr_added_cb (NMBluezManager *bluez_mgr, - NMBluezDevice *bt_device, - const char *bdaddr, - const char *name, - const char *object_path, - guint32 capabilities, - NMManager *manager) -{ - NMDevice *device; - gboolean has_dun = (capabilities & NM_BT_CAPABILITY_DUN); - gboolean has_nap = (capabilities & NM_BT_CAPABILITY_NAP); - - g_return_if_fail (bdaddr != NULL); - g_return_if_fail (name != NULL); - g_return_if_fail (object_path != NULL); - g_return_if_fail (capabilities != NM_BT_CAPABILITY_NONE); - g_return_if_fail (NM_IS_BLUEZ_DEVICE (bt_device)); - - /* Make sure the device is not already in the device list */ - if (nm_manager_get_device_by_udi (manager, object_path)) - return; - - device = nm_device_bt_new (bt_device, object_path, bdaddr, name, capabilities, FALSE); - if (device) { - nm_log_info (LOGD_HW, "BT device %s (%s) added (%s%s%s)", - name, - bdaddr, - has_dun ? "DUN" : "", - has_dun && has_nap ? " " : "", - has_nap ? "NAP" : ""); - - add_device (manager, device); - } -} - -static void -bluez_manager_bdaddr_removed_cb (NMBluezManager *bluez_mgr, - const char *bdaddr, - const char *object_path, - gpointer user_data) -{ - NMManager *self = NM_MANAGER (user_data); - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMDevice *device; - - g_return_if_fail (bdaddr != NULL); - g_return_if_fail (object_path != NULL); - - device = nm_manager_get_device_by_udi (self, object_path); - if (device) { - nm_log_info (LOGD_HW, "BT device %s removed", bdaddr); - priv->devices = remove_one_device (self, priv->devices, device, FALSE); + /* If the device has a connection it can assume, do that now. If it's a + * device that we might ever want to assume a connection on, then set that up. + */ + if (connection) + assume_connection (self, device, connection); + if (generate_con) { + g_signal_connect (device, NM_DEVICE_RECHECK_ASSUME, + G_CALLBACK (recheck_assume_connection), self); } } @@ -2134,25 +1852,33 @@ find_device_by_ifindex (NMManager *self, guint32 ifindex) return NULL; } -#define PLUGIN_PREFIX "libnm-device-plugin-" - -typedef struct { - NMDeviceType t; - guint priority; - NMDeviceFactoryCreateFunc create_func; -} PluginInfo; +static void +factory_device_added_cb (NMDeviceFactory *factory, + NMDevice *device, + gpointer user_data) +{ + add_device (NM_MANAGER (user_data), device, FALSE); +} -static gint -plugin_sort (PluginInfo *a, PluginInfo *b) +static gboolean +factory_component_added_cb (NMDeviceFactory *factory, + GObject *component, + gpointer user_data) { - /* Higher priority means sort earlier in the list (ie, return -1) */ - if (a->priority > b->priority) - return -1; - else if (a->priority < b->priority) - return 1; - return 0; + NMManager *self = NM_MANAGER (user_data); + GSList *iter; + + for (iter = NM_MANAGER_GET_PRIVATE (self)->devices; iter; iter = iter->next) { + if (nm_device_notify_component_added (NM_DEVICE (iter->data), component)) + return TRUE; + } + return FALSE; } +#define PLUGIN_PREFIX "libnm-device-plugin-" +#define PLUGIN_PATH_TAG "NMManager-plugin-path" +#define PLUGIN_TYPEFUNC_TAG "typefunc" + static void load_device_factories (NMManager *self) { @@ -2161,7 +1887,7 @@ load_device_factories (NMManager *self) GError *error = NULL; const char *item; char *path; - GSList *list = NULL, *iter; + GSList *iter; dir = g_dir_open (NMPLUGINDIR, 0, &error); if (!dir) { @@ -2174,14 +1900,16 @@ load_device_factories (NMManager *self) while ((item = g_dir_read_name (dir))) { GModule *plugin; + NMDeviceFactory *factory; NMDeviceFactoryCreateFunc create_func; - NMDeviceFactoryPriorityFunc priority_func; - NMDeviceFactoryTypeFunc type_func; - PluginInfo *info = NULL; - NMDeviceType plugin_type; + NMDeviceFactoryDeviceTypeFunc type_func; + NMDeviceType dev_type; + const char *found = NULL; if (!g_str_has_prefix (item, PLUGIN_PREFIX)) continue; + if (g_str_has_suffix (item, ".la")) + continue; path = g_module_build_path (NMPLUGINDIR, item); g_assert (path); @@ -2193,158 +1921,92 @@ load_device_factories (NMManager *self) continue; } - if (!g_module_symbol (plugin, "nm_device_factory_get_type", (gpointer) (&type_func))) { - nm_log_warn (LOGD_HW, "(%s): failed to find device factory: %s", item, g_module_error ()); + if (!g_module_symbol (plugin, "nm_device_factory_get_device_type", (gpointer) &type_func)) { + nm_log_warn (LOGD_HW, "(%s): failed to find device factory type: %s", item, g_module_error ()); g_module_close (plugin); continue; } /* Make sure we don't double-load plugins */ - plugin_type = type_func (); - for (iter = list; iter; iter = g_slist_next (iter)) { - PluginInfo *candidate = iter->data; + dev_type = type_func (); + for (iter = priv->factories; iter; iter = iter->next) { + NMDeviceFactoryDeviceTypeFunc loaded_type_func; - if (plugin_type == candidate->t) { - info = candidate; + loaded_type_func = g_object_get_data (G_OBJECT (iter->data), PLUGIN_TYPEFUNC_TAG); + if (dev_type == loaded_type_func ()) { + found = g_object_get_data (G_OBJECT (iter->data), PLUGIN_PATH_TAG); break; } } - if (info) { + if (found) { + nm_log_warn (LOGD_HW, "Found multiple device plugins for same type: %s vs %s", + found, g_module_name (plugin)); g_module_close (plugin); continue; } - if (!g_module_symbol (plugin, "nm_device_factory_create_device", (gpointer) (&create_func))) { - nm_log_warn (LOGD_HW, "(%s): failed to find device creator: %s", item, g_module_error ()); + if (!g_module_symbol (plugin, "nm_device_factory_create", (gpointer) &create_func)) { + nm_log_warn (LOGD_HW, "(%s): failed to find device factory creator: %s", item, g_module_error ()); g_module_close (plugin); continue; } - info = g_malloc0 (sizeof (*info)); - info->create_func = create_func; - info->t = plugin_type; - - /* Grab priority; higher number equals higher priority */ - if (g_module_symbol (plugin, "nm_device_factory_get_priority", (gpointer) (&priority_func))) - info->priority = priority_func (); - else { - nm_log_dbg (LOGD_HW, "(%s): failed to find device factory priority func: %s", - item, g_module_error ()); + factory = create_func (&error); + if (!factory) { + nm_log_warn (LOGD_HW, "(%s): failed to initialize device factory: %s", + item, error ? error->message : "unknown"); + g_clear_error (&error); + g_module_close (plugin); + continue; } + g_clear_error (&error); g_module_make_resident (plugin); - list = g_slist_insert_sorted (list, info, (GCompareFunc) plugin_sort); + priv->factories = g_slist_prepend (priv->factories, factory); + + g_signal_connect (factory, + NM_DEVICE_FACTORY_DEVICE_ADDED, + G_CALLBACK (factory_device_added_cb), + self); + g_signal_connect (factory, + NM_DEVICE_FACTORY_COMPONENT_ADDED, + G_CALLBACK (factory_component_added_cb), + self); + g_object_set_data_full (G_OBJECT (factory), PLUGIN_PATH_TAG, + g_strdup (g_module_name (plugin)), g_free); + g_object_set_data (G_OBJECT (factory), PLUGIN_TYPEFUNC_TAG, type_func); - nm_log_info (LOGD_HW, "Loaded device factory: %s", g_module_name (plugin)); + nm_log_info (LOGD_HW, "Loaded device plugin: %s", g_module_name (plugin)); }; g_dir_close (dir); - /* Ditch the priority info and copy the factory functions to our private data */ - for (iter = list; iter; iter = g_slist_next (iter)) { - PluginInfo *info = iter->data; - - priv->factories = g_slist_append (priv->factories, info->create_func); - g_free (info); - } - g_slist_free (list); + priv->factories = g_slist_reverse (priv->factories); } -static gboolean -is_wireless (GUdevDevice *device) +static void +platform_link_added (NMManager *self, + int ifindex, + NMPlatformLink *plink, + NMPlatformReason reason) { - const char *tmp; - - /* Check devtype, newer kernels (2.6.32+) have this */ - tmp = g_udev_device_get_property (device, "DEVTYPE"); - if (g_strcmp0 (tmp, "wlan") == 0) - return TRUE; + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + NMDevice *device = NULL; + GSList *iter; + GError *error = NULL; - /* Otherwise hit up WEXT directly */ - return wifi_utils_is_wifi (g_udev_device_get_name (device), - g_udev_device_get_sysfs_path (device)); -} + g_return_if_fail (ifindex > 0); -static gboolean -is_olpc_mesh (GUdevDevice *device) -{ - const gchar *prop = g_udev_device_get_property (device, "ID_NM_OLPC_MESH"); - return (prop != NULL); -} + if (priv->ignore_link_added_cb > 0) + return; -static gboolean -is_infiniband (GUdevDevice *device) -{ - gint etype = g_udev_device_get_sysfs_attr_as_int (device, "type"); - return etype == ARPHRD_INFINIBAND; -} + if (find_device_by_ifindex (self, ifindex)) + return; -static gboolean -is_bond (int ifindex) -{ - return (nm_system_get_iface_type (ifindex, NULL) == NM_IFACE_TYPE_BOND); -} + /* Try registered device factories */ + for (iter = priv->factories; iter; iter = iter->next) { + NMDeviceFactory *factory = NM_DEVICE_FACTORY (iter->data); -static gboolean -is_bridge (int ifindex) -{ - return (nm_system_get_iface_type (ifindex, NULL) == NM_IFACE_TYPE_BRIDGE); -} - -static gboolean -is_vlan (int ifindex) -{ - return (nm_system_get_iface_type (ifindex, NULL) == NM_IFACE_TYPE_VLAN); -} - -static gboolean -is_adsl (GUdevDevice *device) -{ - return (g_strcmp0 (g_udev_device_get_subsystem (device), "atm") == 0); -} - -static void -udev_device_added_cb (NMUdevManager *udev_mgr, - GUdevDevice *udev_device, - const char *iface, - const char *sysfs_path, - const char *driver, - int ifindex, - gpointer user_data) -{ - NMManager *self = NM_MANAGER (user_data); - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMDevice *device = NULL; - GSList *iter; - GError *error = NULL; - - g_return_if_fail (udev_device != NULL); - g_return_if_fail (iface != NULL); - g_return_if_fail (sysfs_path != NULL); - g_return_if_fail (driver != NULL); - - /* Most devices will have an ifindex here */ - if (ifindex > 0) { - device = find_device_by_ifindex (self, ifindex); - if (device) { - /* If it's a virtual device we may need to update its UDI */ - if (nm_system_get_iface_type (ifindex, iface) != NM_IFACE_TYPE_UNSPEC) - g_object_set (G_OBJECT (device), NM_DEVICE_UDI, sysfs_path, NULL); - return; - } - } else { - /* But ATM/ADSL devices don't */ - g_return_if_fail (is_adsl (udev_device)); - device = find_device_by_ip_iface (self, iface); - if (device) - return; - } - - /* Try registered device factories */ - for (iter = priv->factories; iter; iter = g_slist_next (iter)) { - NMDeviceFactoryCreateFunc create_func = iter->data; - - g_clear_error (&error); - device = (NMDevice *) create_func (udev_device, sysfs_path, iface, driver, &error); + device = nm_device_factory_new_link (factory, plink, &error); if (device && NM_IS_DEVICE (device)) { g_assert_no_error (error); break; /* success! */ @@ -2352,7 +2014,7 @@ udev_device_added_cb (NMUdevManager *udev_mgr, if (error) { nm_log_warn (LOGD_HW, "%s: factory failed to create device: (%d) %s", - sysfs_path, + plink->udi, error ? error->code : -1, error ? error->message : "(unknown)"); g_clear_error (&error); @@ -2360,102 +2022,128 @@ udev_device_added_cb (NMUdevManager *udev_mgr, } } + /* Ignore Bluetooth PAN interfaces; they are handled by their NMDeviceBt + * parent and don't get a separate interface. + */ + if (!strncmp (plink->name, "bnep", STRLEN ("bnep"))) + return; + if (device == NULL) { - if (is_olpc_mesh (udev_device)) /* must be before is_wireless */ - device = nm_device_olpc_mesh_new (sysfs_path, iface, driver); - else if (is_wireless (udev_device)) - device = nm_device_wifi_new (sysfs_path, iface, driver); - else if (is_infiniband (udev_device)) - device = nm_device_infiniband_new (sysfs_path, iface, driver); - else if (is_bond (ifindex)) - device = nm_device_bond_new (sysfs_path, iface); - else if (is_bridge (ifindex)) { - - /* FIXME: always create device when we handle bridges non-destructively */ - if (bridge_created_by_nm (self, iface)) - device = nm_device_bridge_new (sysfs_path, iface); - else - nm_log_info (LOGD_BRIDGE, "(%s): ignoring bridge not created by NetworkManager", iface); - } else if (is_vlan (ifindex)) { - int parent_ifindex = -1; - NMDevice *parent; + int parent_ifindex = -1; + NMDevice *parent; + switch (plink->type) { + case NM_LINK_TYPE_ETHERNET: + device = nm_device_ethernet_new (plink); + break; + case NM_LINK_TYPE_INFINIBAND: + device = nm_device_infiniband_new (plink); + break; + case NM_LINK_TYPE_BOND: + device = nm_device_bond_new (plink); + break; + case NM_LINK_TYPE_TEAM: + device = nm_device_team_new (plink); + break; + case NM_LINK_TYPE_BRIDGE: + device = nm_device_bridge_new (plink); + break; + case NM_LINK_TYPE_VLAN: /* Have to find the parent device */ - if (nm_system_get_iface_vlan_info (ifindex, &parent_ifindex, NULL)) { + if (nm_platform_vlan_get_info (ifindex, &parent_ifindex, NULL)) { parent = find_device_by_ifindex (self, parent_ifindex); if (parent) - device = nm_device_vlan_new (sysfs_path, iface, parent); + device = nm_device_vlan_new (plink, parent); else { /* If udev signaled the VLAN interface before it signaled * the VLAN's parent at startup we may not know about the * parent device yet. But we'll find it on the second pass * from nm_manager_start(). */ - nm_log_dbg (LOGD_HW, "(%s): VLAN parent interface unknown", iface); + nm_log_dbg (LOGD_HW, "(%s): VLAN parent interface unknown", plink->name); } } else - nm_log_err (LOGD_HW, "(%s): failed to get VLAN parent ifindex", iface); - } else if (is_adsl (udev_device)) - device = nm_device_adsl_new (sysfs_path, iface, driver); - else - device = nm_device_ethernet_new (sysfs_path, iface, driver); + nm_log_err (LOGD_HW, "(%s): failed to get VLAN parent ifindex", plink->name); + break; + case NM_LINK_TYPE_VETH: + device = nm_device_veth_new (plink); + break; + case NM_LINK_TYPE_TUN: + case NM_LINK_TYPE_TAP: + device = nm_device_tun_new (plink); + break; + case NM_LINK_TYPE_MACVLAN: + case NM_LINK_TYPE_MACVTAP: + device = nm_device_macvlan_new (plink); + break; + case NM_LINK_TYPE_VXLAN: + device = nm_device_vxlan_new (plink); + break; + case NM_LINK_TYPE_GRE: + case NM_LINK_TYPE_GRETAP: + device = nm_device_gre_new (plink); + break; + + case NM_LINK_TYPE_WWAN_ETHERNET: + /* WWAN pseudo-ethernet interfaces are handled automatically by + * their NMDeviceModem and don't get a separate NMDevice object. + */ + break; + + case NM_LINK_TYPE_OLPC_MESH: + case NM_LINK_TYPE_WIFI: + case NM_LINK_TYPE_WIMAX: + nm_log_info (LOGD_HW, "(%s): '%s' plugin not available; creating generic device", + plink->name, plink->type_name); + /* fall through */ + default: + device = nm_device_generic_new (plink); + break; + } } - if (device) - add_device (self, device); + if (device) { + add_device (self, device, plink->type != NM_LINK_TYPE_LOOPBACK); + g_object_unref (device); + } } static void -udev_device_removed_cb (NMUdevManager *manager, - GUdevDevice *udev_device, - gpointer user_data) -{ - NMManager *self = NM_MANAGER (user_data); - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMDevice *device; - guint32 ifindex; - - ifindex = g_udev_device_get_property_as_int (udev_device, "IFINDEX"); - device = find_device_by_ifindex (self, ifindex); - if (!device) { - GSList *iter; - const char *iface = g_udev_device_get_name (udev_device); - - /* On removal we aren't always be able to read properties like IFINDEX - * anymore, as they may have already been removed from sysfs. So we - * have to fall back on device name (eg, interface name). - * - * Also, some devices (namely PPPoE (pppX), ADSL (nasX, pppX), and - * mobile broadband (pppX, bnepX)) create a kernel netdevice for IP - * communication (called the "IP interface" in NM) as part of the - * connection process and thus the IP interface lifetime does not - * correspond to the NMDevice lifetime. For these devices we must - * ignore removal events for the IP interface name otherwise the - * NMDevice would be removed. Hence the usage here of - * nm_device_get_iface() rather than nm_device_get_ip_iface(). - */ - for (iter = priv->devices; iter; iter = g_slist_next (iter)) { - if (g_strcmp0 (nm_device_get_iface (NM_DEVICE (iter->data)), iface) == 0) { - device = iter->data; - break; - } - } - } +platform_link_cb (NMPlatform *platform, + int ifindex, + NMPlatformLink *plink, + NMPlatformSignalChangeType change_type, + NMPlatformReason reason, + gpointer user_data) +{ + switch (change_type) { + case NM_PLATFORM_SIGNAL_ADDED: + platform_link_added (NM_MANAGER (user_data), ifindex, plink, reason); + break; + case NM_PLATFORM_SIGNAL_REMOVED: { + NMManager *self = NM_MANAGER (user_data); + NMDevice *device; - if (device) - priv->devices = remove_one_device (self, priv->devices, device, FALSE); + device = find_device_by_ifindex (self, ifindex); + if (device) + remove_device (self, device, FALSE); + break; + } + default: + break; + } } static void -udev_manager_rfkill_changed_cb (NMUdevManager *udev_mgr, - RfKillType rtype, - RfKillState udev_state, - gpointer user_data) +rfkill_manager_rfkill_changed_cb (NMRfkillManager *rfkill_mgr, + RfKillType rtype, + RfKillState udev_state, + gpointer user_data) { nm_manager_rfkill_update (NM_MANAGER (user_data), rtype); } -GSList * +const GSList * nm_manager_get_devices (NMManager *manager) { g_return_val_if_fail (NM_IS_MANAGER (manager), NULL); @@ -2503,54 +2191,18 @@ impl_manager_get_device_by_ip_iface (NMManager *self, return path ? TRUE : FALSE; } -static NMActiveConnection * -internal_activate_device (NMManager *manager, - NMDevice *device, - NMConnection *connection, - const char *specific_object, - gboolean user_requested, - gulong sender_uid, - const char *dbus_sender, - gboolean assumed, - NMActiveConnection *master, - GError **error) +static gboolean +is_compatible_with_slave (NMConnection *master, NMConnection *slave) { - NMActRequest *req; - NMDevice *master_device = NULL; - - g_return_val_if_fail (NM_IS_MANAGER (manager), NULL); - g_return_val_if_fail (NM_IS_DEVICE (device), NULL); - g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); - - /* Ensure the requested connection is compatible with the device */ - if (!nm_device_check_connection_compatible (device, connection, error)) - return NULL; - - /* Tear down any existing connection */ - if (nm_device_get_act_request (device)) { - nm_log_info (LOGD_DEVICE, "(%s): disconnecting for new activation request.", - nm_device_get_iface (device)); - nm_device_state_changed (device, - NM_DEVICE_STATE_DISCONNECTED, - NM_DEVICE_STATE_REASON_NONE); - } + NMSettingConnection *s_con; - if (master) - master_device = nm_active_connection_get_device (master); + g_return_val_if_fail (master, FALSE); + g_return_val_if_fail (slave, FALSE); - req = nm_act_request_new (connection, - specific_object, - user_requested, - sender_uid, - dbus_sender, - assumed, - device, - master_device); - g_assert (req); - active_connection_add (manager, NM_ACTIVE_CONNECTION (req)); - nm_device_activate (device, req); + s_con = nm_connection_get_setting_connection (slave); + g_assert (s_con); - return NM_ACTIVE_CONNECTION (req); + return nm_connection_is_type (master, nm_setting_connection_get_slave_type (s_con)); } /** @@ -2562,14 +2214,35 @@ internal_activate_device (NMManager *manager, * that master connection was found * @out_master_device: on success, the master device of @connection if that * master device was found + * @out_master_ac: on success, the master ActiveConnection of @connection if + * there already is one + * @error: the error, if an error occurred + * + * Given an #NMConnection, attempts to find its master. If @connection has + * no master, this will return %TRUE and @out_master_connection and + * @out_master_device will be untouched. + * + * If @connection does have a master, then the outputs depend on what is in its + * #NMSettingConnection:master property: * - * Given an #NMConnection, attempts to find its master connection and/or its - * master device. This function may return a master connection, a master device, - * or both. If only a connection is returned, that master connection is not - * currently active on any device. If only a device is returned, that device - * is not currently activated with any connection. If both are returned, then - * the device is currently activated or activating with the returned master - * connection. + * If "master" is the ifname of an existing #NMDevice, and that device has a + * compatible master connection activated or activating on it, then + * @out_master_device, @out_master_connection, and @out_master_ac will all be + * set. If the device exists and is idle, only @out_master_device will be set. + * If the device exists and has an incompatible connection on it, an error + * will be returned. + * + * If "master" is the ifname of a non-existent device, then @out_master_device + * will be %NULL, and @out_master_connection will be a connection whose + * activation would cause the creation of that device. @out_master_ac MAY be + * set in this case as well (if the connection has started activating, but has + * not yet created its device). + * + * If "master" is the UUID of a compatible master connection, then + * @out_master_connection will be the identified connection, and @out_master_device + * and/or @out_master_ac will be set if the connection is currently activating. + * (@out_master_device will not be set if the device exists but does not have + * @out_master_connection active/activating on it.) * * Returns: %TRUE if the master device and/or connection could be found or if * the connection did not require a master, %FALSE otherwise @@ -2579,7 +2252,9 @@ find_master (NMManager *self, NMConnection *connection, NMDevice *device, NMConnection **out_master_connection, - NMDevice **out_master_device) + NMDevice **out_master_device, + NMActiveConnection **out_master_ac, + GError **error) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); NMSettingConnection *s_con; @@ -2598,9 +2273,20 @@ find_master (NMManager *self, /* Try as an interface name first */ master_device = find_device_by_ip_iface (self, master); if (master_device) { - /* A device obviously can't be its own master */ - if (master_device == device) + if (master_device == device) { + g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_DEPENDENCY_FAILED, + "Device cannot be its own master"); + return FALSE; + } + + master_connection = nm_device_get_connection (master_device); + if (master_connection && !is_compatible_with_slave (master_connection, connection)) { + g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_DEPENDENCY_FAILED, + "The active connection on %s is not a valid master for '%s'", + nm_device_get_iface (master_device), + nm_connection_get_id (connection)); return FALSE; + } } else { /* Try master as a connection UUID */ master_connection = (NMConnection *) nm_settings_get_connection_by_uuid (priv->settings, master); @@ -2623,14 +2309,15 @@ find_master (NMManager *self, * virtual interfaces and see if one of their virtual interface * names matches the master. */ - connections = nm_settings_get_connections (priv->settings); + connections = nm_manager_get_activatable_connections (self); for (iter = connections; iter && !master_connection; iter = g_slist_next (iter)) { NMConnection *candidate = iter->data; char *vname; if (connection_needs_virtual_device (candidate)) { vname = get_virtual_iface_name (self, candidate, NULL); - if (g_strcmp0 (master, vname) == 0) + if ( g_strcmp0 (master, vname) == 0 + && is_compatible_with_slave (candidate, connection)) master_connection = candidate; g_free (vname); } @@ -2643,46 +2330,49 @@ find_master (NMManager *self, *out_master_connection = master_connection; if (out_master_device) *out_master_device = master_device; + if (out_master_ac && master_connection) + *out_master_ac = find_ac_for_connection (self, master_connection); - return master_device || master_connection; -} - -static gboolean -is_compatible_with_slave (NMConnection *master, NMConnection *slave) -{ - NMSettingConnection *s_con; - - g_return_val_if_fail (master, FALSE); - g_return_val_if_fail (slave, FALSE); - - s_con = nm_connection_get_setting_connection (slave); - g_assert (s_con); - - return nm_connection_is_type (master, nm_setting_connection_get_slave_type (s_con)); + if (master_device || master_connection) + return TRUE; + else { + g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_DEVICE, + "Master connection not found or invalid"); + return FALSE; + } } /** * ensure_master_active_connection: - * * @self: the #NMManager - * @dbus_sender: if the request was initiated by a user via D-Bus, the - * dbus sender name of the client that requested the activation; for auto - * activated connections use %NULL + * @subject: the #NMAuthSubject representing the requestor of this activation * @connection: the connection that should depend on @master_connection * @device: the #NMDevice, if any, which will activate @connection - * @master_connection: the master connection - * @master_device: the master device + * @master_connection: the master connection, or %NULL + * @master_device: the master device, or %NULL * @error: the error, if an error occurred * * Determines whether a given #NMConnection depends on another connection to * be activated, and if so, finds that master connection or creates it. * + * If @master_device and @master_connection are both set then @master_connection + * MUST already be activated or activating on @master_device, and the function will + * return the existing #NMActiveConnection. + * + * If only @master_device is set, and it has an #NMActiveConnection, then the + * function will return it if it is a compatible master, or an error if not. If it + * doesn't have an AC, then the function will create one if a compatible master + * connection exists, or return an error if not. + * + * If only @master_connection is set, then this will try to find or create a compatible + * #NMDevice, and either activate @master_connection on that device or return an error. + * * Returns: the master #NMActiveConnection that the caller should depend on, or * %NULL if an error occurred */ static NMActiveConnection * ensure_master_active_connection (NMManager *self, - const char *dbus_sender, + NMAuthSubject *subject, NMConnection *connection, NMDevice *device, NMConnection *master_connection, @@ -2701,20 +2391,29 @@ ensure_master_active_connection (NMManager *self, * compatible connection. If it's already activating we can just proceed. */ if (master_device) { + NMConnection *device_connection = nm_device_get_connection (master_device); + /* If we're passed a connection and a device, we require that connection * be already activated on the device, eg returned from find_master(). */ - if (master_connection) - g_assert (nm_device_get_connection (master_device) == master_connection); + g_assert (!master_connection || master_connection == device_connection); + if (device_connection && !is_compatible_with_slave (device_connection, connection)) { + g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_DEPENDENCY_FAILED, + "The active connection on %s is not a valid master for '%s'", + nm_device_get_iface (master_device), + nm_connection_get_id (connection)); + return NULL; + } master_state = nm_device_get_state (master_device); if ( (master_state == NM_DEVICE_STATE_ACTIVATED) || nm_device_is_activating (master_device)) { /* Device already using master_connection */ + g_assert (device_connection); return NM_ACTIVE_CONNECTION (nm_device_get_act_request (master_device)); } - /* If the device is disconnected, find a compabile connection and + /* If the device is disconnected, find a compatible connection and * activate it on the device. */ if (master_state == NM_DEVICE_STATE_DISCONNECTED) { @@ -2723,20 +2422,22 @@ ensure_master_active_connection (NMManager *self, g_assert (master_connection == NULL); /* Find a compatible connection and activate this device using it */ - connections = nm_settings_get_connections (priv->settings); + connections = nm_manager_get_activatable_connections (self); for (iter = connections; iter; iter = g_slist_next (iter)) { NMConnection *candidate = NM_CONNECTION (iter->data); - /* Ensure eg bond slave and the candidate master is a bond master */ + /* Ensure eg bond/team slave and the candidate master is a + * bond/team master + */ if (!is_compatible_with_slave (candidate, connection)) continue; - if (nm_device_check_connection_compatible (master_device, candidate, NULL)) { + if (nm_device_connection_is_available (master_device, candidate, TRUE)) { master_ac = nm_manager_activate_connection (self, candidate, NULL, - nm_device_get_path (master_device), - dbus_sender, + master_device, + subject, error); if (!master_ac) g_prefix_error (error, "%s", "Master device activation failed: "); @@ -2772,7 +2473,7 @@ ensure_master_active_connection (NMManager *self, continue; } - if (!nm_device_check_connection_compatible (candidate, master_connection, NULL)) + if (!nm_device_connection_is_available (candidate, master_connection, TRUE)) continue; found_device = TRUE; @@ -2783,8 +2484,8 @@ ensure_master_active_connection (NMManager *self, master_ac = nm_manager_activate_connection (self, master_connection, NULL, - nm_device_get_path (candidate), - dbus_sender, + candidate, + subject, error); if (!master_ac) g_prefix_error (error, "%s", "Master device activation failed: "); @@ -2799,7 +2500,7 @@ ensure_master_active_connection (NMManager *self, master_connection, NULL, NULL, - dbus_sender, + subject, error); if (!master_ac) g_prefix_error (error, "%s", "Master device activation failed: "); @@ -2817,247 +2518,141 @@ ensure_master_active_connection (NMManager *self, return NULL; } -static NMActiveConnection * -activate_vpn_connection (NMManager *self, - NMConnection *connection, - const char *specific_object, - gulong sender_uid, - GError **error) +static gboolean +_internal_activate_vpn (NMManager *self, NMActiveConnection *active, GError **error) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMActiveConnection *parent = NULL, *ac; - NMDevice *device = NULL; - GSList *iter; - - if (specific_object) { - /* Find the specifc connection the client requested we use */ - parent = active_connection_get_by_path (self, specific_object); - if (!parent) { - g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_CONNECTION_NOT_ACTIVE, - "Base connection for VPN connection not active."); - return NULL; - } - } else { - for (iter = priv->active_connections; iter; iter = g_slist_next (iter)) { - NMActiveConnection *candidate = iter->data; - - if (nm_active_connection_get_default (candidate)) { - parent = candidate; - break; - } - } - } + gboolean success; - if (!parent) { - g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_CONNECTION, - "Could not find source connection."); - return NULL; - } + g_assert (NM_IS_VPN_CONNECTION (active)); - device = nm_active_connection_get_device (parent); - if (!device) { - g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_DEVICE, - "Source connection had no active device."); - return NULL; + success = nm_vpn_manager_activate_connection (NM_MANAGER_GET_PRIVATE (self)->vpn_manager, + NM_VPN_CONNECTION (active), + error); + if (success) { + nm_active_connection_export (active); + g_object_notify (G_OBJECT (self), NM_MANAGER_ACTIVE_CONNECTIONS); } - - ac = nm_vpn_manager_activate_connection (priv->vpn_manager, - connection, - device, - nm_active_connection_get_path (parent), - TRUE, - sender_uid, - error); - if (ac) - active_connection_add (self, ac); - return ac; + return success; } -NMActiveConnection * -nm_manager_activate_connection (NMManager *manager, - NMConnection *connection, - const char *specific_object, - const char *device_path, - const char *dbus_sender, - GError **error) +static gboolean +_internal_activate_device (NMManager *self, NMActiveConnection *active, GError **error) { - NMManagerPrivate *priv; - NMDevice *device = NULL; - gulong sender_uid = 0; - DBusError dbus_error; - NMDeviceState state; - char *iface; - NMDevice *master_device = NULL; + NMDevice *device, *master_device = NULL; + NMConnection *connection; NMConnection *master_connection = NULL; - NMConnection *existing_connection = NULL; NMActiveConnection *master_ac = NULL; - gboolean matched; - char *error_desc = NULL; - g_return_val_if_fail (manager != NULL, NULL); - g_return_val_if_fail (connection != NULL, NULL); - g_return_val_if_fail (error != NULL, NULL); - g_return_val_if_fail (*error == NULL, NULL); + g_return_val_if_fail (NM_IS_MANAGER (self), FALSE); + g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (active), FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); - priv = NM_MANAGER_GET_PRIVATE (manager); + g_assert (NM_IS_VPN_CONNECTION (active) == FALSE); - /* Get the UID of the user that originated the request, if any */ - if (dbus_sender) { - dbus_error_init (&dbus_error); - sender_uid = dbus_bus_get_unix_user (nm_dbus_manager_get_dbus_connection (priv->dbus_mgr), - dbus_sender, - &dbus_error); - if (dbus_error_is_set (&dbus_error)) { - g_set_error_literal (error, - NM_MANAGER_ERROR, NM_MANAGER_ERROR_PERMISSION_DENIED, - "Failed to get unix user for dbus sender"); - dbus_error_free (&dbus_error); - return NULL; + connection = nm_active_connection_get_connection (active); + g_assert (connection); + + device = nm_active_connection_get_device (active); + if (!device) { + if (!connection_needs_virtual_device (connection)) { + NMSettingConnection *s_con = nm_connection_get_setting_connection (connection); + + g_assert (s_con); + g_set_error (error, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_UNKNOWN_DEVICE, + "Unsupported virtual interface type '%s'", + nm_setting_connection_get_connection_type (s_con)); + return FALSE; } - /* Ensure the subject has permissions for this connection */ - if (!nm_auth_uid_in_acl (connection, - priv->session_monitor, - sender_uid, - &error_desc)) { + device = system_create_virtual_device (self, connection); + if (!device) { g_set_error_literal (error, NM_MANAGER_ERROR, - NM_MANAGER_ERROR_PERMISSION_DENIED, - error_desc); - g_free (error_desc); - return NULL; + NM_MANAGER_ERROR_UNKNOWN_DEVICE, + "Failed to create virtual interface"); + return FALSE; } - } - /* VPN ? */ - if (nm_connection_is_type (connection, NM_SETTING_VPN_SETTING_NAME)) - return activate_vpn_connection (manager, connection, specific_object, sender_uid, error); - - /* Device-based connection */ - if (device_path) { - device = nm_manager_get_device_by_path (manager, device_path); - if (!device) { - g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_DEVICE, - "Device not found"); - return NULL; + if (!nm_active_connection_set_device (active, device)) { + g_set_error_literal (error, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_UNKNOWN_DEVICE, + "The device could not be activated with this connection"); + return FALSE; } - /* If it's a virtual interface make sure the device given by the - * path matches the connection's interface details. + /* A newly created device, if allowed to be managed by NM, will be + * in the UNAVAILABLE state here. To ensure it can be activated + * immediately, we transition it to DISCONNECTED. */ - if (connection_needs_virtual_device (connection)) { - iface = get_virtual_iface_name (manager, connection, NULL); - if (!iface) { - g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_DEVICE, - "Failed to determine connection's virtual interface name"); - return NULL; - } - - matched = g_str_equal (iface, nm_device_get_ip_iface (device)); - g_free (iface); - if (!matched) { - g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_DEVICE, - "Device given by path did not match connection's virtual interface name"); - return NULL; - } + if ( nm_device_is_available (device) + && (nm_device_get_state (device) == NM_DEVICE_STATE_UNAVAILABLE)) { + nm_device_state_changed (device, + NM_DEVICE_STATE_DISCONNECTED, + NM_DEVICE_STATE_REASON_NONE); } } else { - /* Virtual connections (VLAN, bond, etc) may not specify a device - * path because the device may not be created yet, or it be given - * by the connection's properties instead. Find the device the - * connection refers to, or create it if needed. - */ - if (!connection_needs_virtual_device (connection)) { - g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_DEVICE, - "This connection requires an existing device."); - return NULL; - } - - iface = get_virtual_iface_name (manager, connection, NULL); - if (!iface) { - g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_DEVICE, - "Failed to determine connection's virtual interface name"); - return NULL; - } - - device = find_device_by_ip_iface (manager, iface); - g_free (iface); - if (!device) { - /* Create it */ - device = system_create_virtual_device (manager, connection); - if (!device) { - g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_DEVICE, - "Failed to create virtual interface"); - return NULL; - } - - /* A newly created device, if allowed to be managed by NM, will be - * in the UNAVAILABLE state here. Since we want to use it right - * away, we transition it immediately to DISCONNECTED. - */ - if ( nm_device_is_available (device) - && (nm_device_get_state (device) == NM_DEVICE_STATE_UNAVAILABLE)) { - nm_device_state_changed (device, - NM_DEVICE_STATE_DISCONNECTED, - NM_DEVICE_STATE_REASON_NONE); - } - } - } - - state = nm_device_get_state (device); - if (state < NM_DEVICE_STATE_DISCONNECTED) { - g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNMANAGED_DEVICE, - "Device not managed by NetworkManager or unavailable"); - return NULL; - } - - /* If this is an autoconnect request, but the device isn't allowing autoconnect - * right now, we reject it. - */ - if (!dbus_sender && !nm_device_autoconnect_allowed (device)) { - g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_AUTOCONNECT_NOT_ALLOWED, - "%s does not allow automatic connections at this time", - nm_device_get_iface (device)); - return NULL; - } + NMConnection *existing_connection = NULL; + NMAuthSubject *subject; + char *error_desc = NULL; - if (dbus_sender) { /* If the device is active and its connection is not visible to the * user that's requesting this new activation, fail, since other users * should not be allowed to implicitly deactivate private connections * by activating a connection of their own. */ existing_connection = nm_device_get_connection (device); + subject = nm_active_connection_get_subject (active); if (existing_connection && !nm_auth_uid_in_acl (existing_connection, - priv->session_monitor, - sender_uid, - &error_desc)) { + nm_session_monitor_get (), + nm_auth_subject_get_uid (subject), + &error_desc)) { g_set_error (error, - NM_MANAGER_ERROR, - NM_MANAGER_ERROR_PERMISSION_DENIED, - "Private connection already active on the device: %s", - error_desc); + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_PERMISSION_DENIED, + "Private connection already active on the device: %s", + error_desc); g_free (error_desc); return FALSE; } } - /* Try to find the master connection/device if the connection has a dependency */ - if (!find_master (manager, connection, device, &master_connection, &master_device)) { - g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_DEVICE, - "Master connection not found or invalid"); - return NULL; + /* Final connection must be available on device */ + if (!nm_device_connection_is_available (device, connection, TRUE)) { + g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_CONNECTION, + "Connection '%s' is not available on the device %s at this time.", + nm_connection_get_id (connection), nm_device_get_iface (device)); + return FALSE; } - /* Ensure there's a master active connection the new connection we're - * activating can depend on. + /* If this is an autoconnect request, but the device isn't allowing autoconnect + * right now, we reject it. */ - if (master_connection || master_device) { - if (master_connection) { - nm_log_dbg (LOGD_CORE, "Activation of '%s' requires master connection '%s'", - nm_connection_get_id (connection), - nm_connection_get_id (master_connection)); + if (!nm_active_connection_get_user_requested (active) && + !nm_device_autoconnect_allowed (device)) { + g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_AUTOCONNECT_NOT_ALLOWED, + "%s does not allow automatic connections at this time", + nm_device_get_iface (device)); + return FALSE; + } + + /* Try to find the master connection/device if the connection has a dependency */ + if (!find_master (self, connection, device, + &master_connection, &master_device, &master_ac, + error)) + return FALSE; + + /* Ensure there's a master active connection the new connection we're + * activating can depend on. + */ + if (master_connection || master_device) { + if (master_connection) { + nm_log_dbg (LOGD_CORE, "Activation of '%s' requires master connection '%s'", + nm_connection_get_id (connection), + nm_connection_get_id (master_connection)); } if (master_device) { nm_log_dbg (LOGD_CORE, "Activation of '%s' requires master device '%s'", @@ -3068,94 +2663,395 @@ nm_manager_activate_connection (NMManager *manager, /* Ensure eg bond slave and the candidate master is a bond master */ if (master_connection && !is_compatible_with_slave (master_connection, connection)) { g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_DEPENDENCY_FAILED, - "The master connection was not compatible"); - return NULL; + "The master connection was not compatible"); + return FALSE; } - master_ac = ensure_master_active_connection (manager, - dbus_sender, - connection, - device, - master_connection, - master_device, - error); if (!master_ac) { - if (error) - g_assert (*error); - return NULL; + master_ac = ensure_master_active_connection (self, + nm_active_connection_get_subject (active), + connection, + device, + master_connection, + master_device, + error); + if (!master_ac) { + if (error) + g_assert (*error); + return FALSE; + } } + nm_active_connection_set_master (active, master_ac); nm_log_dbg (LOGD_CORE, "Activation of '%s' depends on active connection %s", nm_connection_get_id (connection), nm_active_connection_get_path (master_ac)); } - return internal_activate_device (manager, - device, + /* Export the new ActiveConnection to clients and start it on the device */ + nm_active_connection_export (active); + g_object_notify (G_OBJECT (self), NM_MANAGER_ACTIVE_CONNECTIONS); + nm_device_queue_activation (device, NM_ACT_REQUEST (active)); + return TRUE; +} + +static gboolean +_internal_activate_generic (NMManager *self, NMActiveConnection *active, GError **error) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + gboolean success = FALSE; + + /* Ensure activation request is still valid, eg that its device hasn't gone + * away or that some other dependency has not failed. + */ + if (nm_active_connection_get_state (active) >= NM_ACTIVE_CONNECTION_STATE_DEACTIVATING) { + g_set_error_literal (error, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_DEPENDENCY_FAILED, + "Activation failed because dependencies failed."); + return FALSE; + } + + if (NM_IS_VPN_CONNECTION (active)) + success = _internal_activate_vpn (self, active, error); + else + success = _internal_activate_device (self, active, error); + + if (success) { + /* Force an update of the Manager's activating-connection property. + * The device changes state before the AC gets exported, which causes + * the manager's 'activating-connection' property to be NULL since the + * AC only gets a D-Bus path when it's exported. So now that the AC + * is exported, make sure the manager's activating-connection property + * is up-to-date. + */ + policy_activating_device_changed (G_OBJECT (priv->policy), NULL, self); + } + + return success; +} + +static NMActiveConnection * +_new_vpn_active_connection (NMManager *self, + NMConnection *connection, + const char *specific_object, + NMAuthSubject *subject, + GError **error) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + NMActiveConnection *parent = NULL; + NMDevice *device = NULL; + + if (specific_object) { + /* Find the specific connection the client requested we use */ + parent = active_connection_get_by_path (self, specific_object); + if (!parent) { + g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_CONNECTION_NOT_ACTIVE, + "Base connection for VPN connection not active."); + return NULL; + } + } else + parent = priv->primary_connection; + + if (!parent) { + g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_CONNECTION, + "Could not find source connection."); + return NULL; + } + + device = nm_active_connection_get_device (parent); + if (!device) { + g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_DEVICE, + "Source connection had no active device."); + return NULL; + } + + return (NMActiveConnection *) nm_vpn_connection_new (connection, + device, + nm_active_connection_get_path (parent), + subject); +} + +static NMActiveConnection * +_new_active_connection (NMManager *self, + NMConnection *connection, + const char *specific_object, + NMDevice *device, + NMAuthSubject *subject, + GError **error) +{ + NMActiveConnection *existing_ac; + + g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); + g_return_val_if_fail (NM_IS_AUTH_SUBJECT (subject), NULL); + + /* Can't create new AC for already-active connection */ + existing_ac = find_ac_for_connection (self, connection); + if (NM_IS_VPN_CONNECTION (existing_ac)) { + g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_CONNECTION_ALREADY_ACTIVE, + "Connection '%s' is already active", + nm_connection_get_id (connection)); + return NULL; + } + + if (existing_ac) { + NMDevice *existing_device = nm_active_connection_get_device (existing_ac); + + if (existing_device != device) { + g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_CONNECTION_ALREADY_ACTIVE, + "Connection '%s' is already active on %s", + nm_connection_get_id (connection), + nm_device_get_iface (existing_device)); + return NULL; + } + } + + /* Normalize the specific object */ + if (specific_object && g_strcmp0 (specific_object, "/") == 0) + specific_object = NULL; + + if (nm_connection_is_type (connection, NM_SETTING_VPN_SETTING_NAME)) { + return _new_vpn_active_connection (self, + connection, + specific_object, + subject, + error); + } + + return (NMActiveConnection *) nm_act_request_new (connection, + specific_object, + subject, + device); +} + +static void +_internal_activation_failed (NMManager *self, + NMActiveConnection *active, + const char *error_desc) +{ + nm_log_warn (LOGD_CORE, "Failed to activate '%s': %s", + nm_connection_get_id (nm_active_connection_get_connection (active)), + error_desc); + + if (nm_active_connection_get_state (active) <= NM_ACTIVE_CONNECTION_STATE_ACTIVATED) { + nm_active_connection_set_state (active, NM_ACTIVE_CONNECTION_STATE_DEACTIVATING); + nm_active_connection_set_state (active, NM_ACTIVE_CONNECTION_STATE_DEACTIVATED); + } + active_connection_remove (self, active); +} + +static void +_internal_activation_auth_done (NMActiveConnection *active, + gboolean success, + const char *error_desc, + gpointer user_data1, + gpointer user_data2) +{ + NMManager *self = user_data1; + GError *error = NULL; + + if (success) { + if (_internal_activate_generic (self, active, &error)) { + g_object_unref (active); + return; + } + } + + g_assert (error_desc || error); + _internal_activation_failed (self, active, error_desc ? error_desc : error->message); + g_object_unref (active); + g_clear_error (&error); +} + +/** + * nm_manager_activate_connection(): + * @self: the #NMManager + * @connection: the #NMConnection to activate on @device + * @specific_object: the specific object path, if any, for the activation + * @device: the #NMDevice to activate @connection on + * @subject: the subject which requested activation + * @error: return location for an error + * + * Begins a new internally-initiated activation of @connection on @device. + * @subject should be the subject of the activation that triggered this + * one, or if this is an autoconnect request, a new internal subject. + * The returned #NMActiveConnection is owned by the Manager and should be + * referenced by the caller if the caller continues to use it. + * + * Returns: (transfer none): the new #NMActiveConnection that tracks + * activation of @connection on @device + */ +NMActiveConnection * +nm_manager_activate_connection (NMManager *self, + NMConnection *connection, + const char *specific_object, + NMDevice *device, + NMAuthSubject *subject, + GError **error) +{ + NMActiveConnection *active; + char *error_desc = NULL; + + g_return_val_if_fail (self != NULL, NULL); + g_return_val_if_fail (connection != NULL, NULL); + g_return_val_if_fail (error != NULL, NULL); + g_return_val_if_fail (*error == NULL, NULL); + + /* Ensure the subject has permissions for this connection */ + if (!nm_auth_uid_in_acl (connection, + nm_session_monitor_get (), + nm_auth_subject_get_uid (subject), + &error_desc)) { + g_set_error_literal (error, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_PERMISSION_DENIED, + error_desc); + g_free (error_desc); + return NULL; + } + + active = _new_active_connection (self, connection, specific_object, - dbus_sender ? TRUE : FALSE, - dbus_sender ? sender_uid : 0, - dbus_sender, - FALSE, - master_ac, + device, + subject, error); + if (active) { + nm_active_connection_authorize (active, _internal_activation_auth_done, self, NULL); + active_connection_add (self, active); + } + return active; } -/* - * TODO this function was created and named in the era of user settings, where - * we could get activation requests for a connection before we got the settings - * data of that connection. Now that user settings are gone, flatten or rename - * it. - */ -static void -pending_activate (NMManager *self, PendingActivation *pending) +static NMAuthSubject * +validate_activation_request (NMManager *self, + DBusGMethodInvocation *context, + NMConnection *connection, + const char *device_path, + NMDevice **out_device, + gboolean *out_vpn, + GError **error) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMSettingsConnection *connection; - NMActiveConnection *ac = NULL; - GError *error = NULL; - char *sender; + NMDevice *device = NULL; + gboolean vpn = FALSE; + NMAuthSubject *subject = NULL; + char *error_desc = NULL; - /* Ok, we're authorized */ + g_assert (connection); + g_assert (out_device); + g_assert (out_vpn); - connection = nm_settings_get_connection_by_path (priv->settings, pending->connection_path); - if (!connection) { - error = g_error_new_literal (NM_MANAGER_ERROR, - NM_MANAGER_ERROR_UNKNOWN_CONNECTION, - "Connection could not be found."); - goto out; + /* Validate the caller */ + subject = nm_auth_subject_new_from_context (context); + if (!subject) { + g_set_error_literal (error, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_PERMISSION_DENIED, + "Failed to get request UID."); + return NULL; } - sender = dbus_g_method_get_sender (pending->context); - g_assert (sender); - ac = nm_manager_activate_connection (self, - NM_CONNECTION (connection), - pending->specific_object_path, - pending->device_path, - sender, - &error); - g_free (sender); + /* Ensure the subject has permissions for this connection */ + if (!nm_auth_uid_in_acl (connection, + nm_session_monitor_get (), + nm_auth_subject_get_uid (subject), + &error_desc)) { + g_set_error_literal (error, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_PERMISSION_DENIED, + error_desc); + g_free (error_desc); + goto error; + } - if (!ac) { - nm_log_warn (LOGD_CORE, "connection %s failed to activate: (%d) %s", - pending->connection_path, - error ? error->code : -1, - error && error->message ? error->message : "(unknown)"); + /* Check whether it's a VPN or not */ + if ( nm_connection_get_setting_vpn (connection) + || nm_connection_is_type (connection, NM_SETTING_VPN_SETTING_NAME)) + vpn = TRUE; + + /* Normalize device path */ + if (device_path && g_strcmp0 (device_path, "/") == 0) + device_path = NULL; + + /* And validate it */ + if (device_path) { + device = nm_manager_get_device_by_path (self, device_path); + if (!device) { + g_set_error_literal (error, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_UNKNOWN_DEVICE, + "Device not found"); + goto error; + } + } else { + gboolean is_software = connection_needs_virtual_device (connection); + + /* VPN and software-device connections don't need a device yet */ + if (!vpn && !is_software) { + g_set_error_literal (error, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_UNKNOWN_DEVICE, + "This connection requires an existing device."); + goto error; + } + + if (is_software) { + /* Look for an existing device with the connection's interface name */ + char *iface; + + iface = get_virtual_iface_name (self, connection, NULL); + if (!iface) { + g_set_error_literal (error, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_UNKNOWN_DEVICE, + "Failed to determine connection's virtual interface name"); + goto error; + } + + device = find_device_by_ip_iface (self, iface); + g_free (iface); + } } -out: - pending_activation_destroy (pending, error, ac); - g_clear_error (&error); + *out_device = device; + *out_vpn = vpn; + return subject; + +error: + g_object_unref (subject); + return NULL; } +/***********************************************************************/ + static void -activation_auth_done (PendingActivation *pending, GError *error) -{ - if (error) - pending_activation_destroy (pending, error, NULL); - else - pending_activate (pending->manager, pending); +_activation_auth_done (NMActiveConnection *active, + gboolean success, + const char *error_desc, + gpointer user_data1, + gpointer user_data2) +{ + NMManager *self = user_data1; + DBusGMethodInvocation *context = user_data2; + GError *error = NULL; + + if (success) { + if (_internal_activate_generic (self, active, &error)) { + dbus_g_method_return (context, nm_active_connection_get_path (active)); + g_object_unref (active); + return; + } + } else { + error = g_error_new_literal (NM_MANAGER_ERROR, + NM_MANAGER_ERROR_PERMISSION_DENIED, + error_desc); + } + + g_assert (error); + dbus_g_method_return_error (context, error); + _internal_activation_failed (self, active, error->message); + g_object_unref (active); + g_error_free (error); } static void @@ -3166,64 +3062,185 @@ impl_manager_activate_connection (NMManager *self, DBusGMethodInvocation *context) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - PendingActivation *pending; + NMActiveConnection *active = NULL; + NMAuthSubject *subject = NULL; + NMConnection *connection; + NMDevice *device = NULL; + gboolean is_vpn = FALSE; GError *error = NULL; - /* Need to check the caller's permissions and stuff before we can - * activate the connection. + /* Normalize object paths */ + if (g_strcmp0 (connection_path, "/") == 0) + connection_path = NULL; + if (g_strcmp0 (specific_object_path, "/") == 0) + specific_object_path = NULL; + if (g_strcmp0 (device_path, "/") == 0) + device_path = NULL; + + /* If the connection path is given and valid, that connection is activated. + * Otherwise the "best" connection for the device is chosen and activated, + * regardless of whether that connection is autoconnect-enabled or not + * (since this is an explicit request, not an auto-activation request). */ - pending = pending_activation_new (self, - context, - device_path, - connection_path, - NULL, - specific_object_path, - activation_auth_done, - &error); - if (pending) - pending_activation_check_authorized (pending, priv->dbus_mgr); - else { - g_assert (error); - dbus_g_method_return_error (context, error); - g_error_free (error); + if (!connection_path) { + GPtrArray *available; + guint64 best_timestamp = 0; + guint i; + + /* If no connection is given, find a suitable connection for the given device path */ + if (!device_path) { + error = g_error_new_literal (NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_DEVICE, + "Only devices may be activated without a specifying a connection"); + goto error; + } + device = nm_manager_get_device_by_path (self, device_path); + if (!device) { + error = g_error_new (NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_DEVICE, + "Cannot activate unknown device %s", device_path); + goto error; + } + + available = nm_device_get_available_connections (device, specific_object_path); + for (i = 0; available && i < available->len; i++) { + NMSettingsConnection *candidate = g_ptr_array_index (available, i); + guint64 candidate_timestamp = 0; + + nm_settings_connection_get_timestamp (candidate, &candidate_timestamp); + if (!connection_path || (candidate_timestamp > best_timestamp)) { + connection_path = nm_connection_get_path (NM_CONNECTION (candidate)); + best_timestamp = candidate_timestamp; + } + } + + if (available) + g_ptr_array_free (available, TRUE); + + if (!connection_path) { + error = g_error_new_literal (NM_MANAGER_ERROR, + NM_MANAGER_ERROR_UNKNOWN_CONNECTION, + "The device has no connections available."); + goto error; + } + } + + g_assert (connection_path); + connection = (NMConnection *) nm_settings_get_connection_by_path (priv->settings, connection_path); + if (!connection) { + error = g_error_new_literal (NM_MANAGER_ERROR, + NM_MANAGER_ERROR_UNKNOWN_CONNECTION, + "Connection could not be found."); + goto error; } + + subject = validate_activation_request (self, + context, + connection, + device_path, + &device, + &is_vpn, + &error); + if (!subject) + goto error; + + active = _new_active_connection (self, + connection, + specific_object_path, + device, + subject, + &error); + if (!active) + goto error; + + nm_active_connection_authorize (active, _activation_auth_done, self, context); + active_connection_add (self, active); + g_clear_object (&subject); + return; + +error: + g_clear_object (&active); + g_clear_object (&subject); + + g_assert (error); + dbus_g_method_return_error (context, error); + g_error_free (error); } +/***********************************************************************/ + +typedef struct { + NMManager *manager; + NMActiveConnection *active; +} AddAndActivateInfo; + static void activation_add_done (NMSettings *self, - NMSettingsConnection *connection, + NMSettingsConnection *new_connection, GError *error, DBusGMethodInvocation *context, gpointer user_data) { - PendingActivation *pending = user_data; + AddAndActivateInfo *info = user_data; + GError *local = NULL; - if (error) - pending_activation_destroy (pending, error, NULL); - else { - /* Save the new connection's D-Bus path */ - pending->connection_path = g_strdup (nm_connection_get_path (NM_CONNECTION (connection))); + if (!error) { + nm_active_connection_set_connection (info->active, NM_CONNECTION (new_connection)); - /* And activate it */ - pending_activate (pending->manager, pending); + if (_internal_activate_generic (info->manager, info->active, &local)) { + dbus_g_method_return (context, + nm_connection_get_path (NM_CONNECTION (new_connection)), + nm_active_connection_get_path (info->active)); + goto done; + } + error = local; } + + g_assert (error); + _internal_activation_failed (info->manager, info->active, error->message); + dbus_g_method_return_error (context, error); + g_clear_error (&local); + +done: + g_object_unref (info->active); + g_free (info); } static void -add_and_activate_auth_done (PendingActivation *pending, GError *error) +_add_and_activate_auth_done (NMActiveConnection *active, + gboolean success, + const char *error_desc, + gpointer user_data1, + gpointer user_data2) { - if (error) - pending_activation_destroy (pending, error, NULL); - else { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (pending->manager); + NMManager *self = user_data1; + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + DBusGMethodInvocation *context = user_data2; + AddAndActivateInfo *info; + GError *error = NULL; + + if (success) { + info = g_malloc0 (sizeof (*info)); + info->manager = self; + info->active = g_object_ref (active); /* Basic sender auth checks performed; try to add the connection */ - nm_settings_add_connection (priv->settings, - pending->connection, - pending->context, - activation_add_done, - pending); + nm_settings_add_connection_dbus (priv->settings, + nm_active_connection_get_connection (active), + TRUE, + context, + activation_add_done, + info); + } else { + active_connection_remove (self, active); + + g_assert (error_desc); + error = g_error_new_literal (NM_MANAGER_ERROR, + NM_MANAGER_ERROR_PERMISSION_DENIED, + error_desc); + dbus_g_method_return_error (context, error); + g_error_free (error); } + + g_object_unref (active); } static void @@ -3234,29 +3251,105 @@ impl_manager_add_and_activate_connection (NMManager *self, DBusGMethodInvocation *context) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - PendingActivation *pending; + NMConnection *connection = NULL; + GSList *all_connections = NULL; + NMActiveConnection *active = NULL; + NMAuthSubject *subject = NULL; GError *error = NULL; + NMDevice *device = NULL; + gboolean vpn = FALSE; + + /* Normalize object paths */ + if (g_strcmp0 (specific_object_path, "/") == 0) + specific_object_path = NULL; + if (g_strcmp0 (device_path, "/") == 0) + device_path = NULL; - /* Need to check the caller's permissions and stuff before we can - * activate the connection. + /* Try to create a new connection with the given settings. + * We allow empty settings for AddAndActivateConnection(). In that case, + * the connection will be completed in nm_utils_complete_generic() or + * nm_device_complete_connection() below. Just make sure we don't expect + * specific data being in the connection till then (especially in + * validate_activation_request()). */ - pending = pending_activation_new (self, - context, - device_path, - NULL, - settings, - specific_object_path, - add_and_activate_auth_done, - &error); - if (pending) - pending_activation_check_authorized (pending, priv->dbus_mgr); - else { - g_assert (error); - dbus_g_method_return_error (context, error); - g_error_free (error); - } + connection = nm_connection_new (); + if (settings && g_hash_table_size (settings)) + nm_connection_replace_settings (connection, settings, NULL); + + subject = validate_activation_request (self, + context, + connection, + device_path, + &device, + &vpn, + &error); + if (!subject) + goto error; + + /* AddAndActivate() requires a device to complete the connection with */ + if (!device) { + error = g_error_new_literal (NM_MANAGER_ERROR, + NM_MANAGER_ERROR_UNKNOWN_DEVICE, + "This connection requires an existing device."); + goto error; + } + + all_connections = nm_settings_get_connections (priv->settings); + if (vpn) { + /* Try to fill the VPN's connection setting and name at least */ + if (!nm_connection_get_setting_vpn (connection)) { + error = g_error_new_literal (NM_MANAGER_ERROR, + NM_MANAGER_ERROR_UNSUPPORTED_CONNECTION_TYPE, + "VPN connections require a 'vpn' setting"); + goto error; + } + + nm_utils_complete_generic (connection, + NM_SETTING_VPN_SETTING_NAME, + all_connections, + _("VPN connection %d"), + NULL, + FALSE); /* No IPv6 by default for now */ + } else { + /* Let each device subclass complete the connection */ + if (!nm_device_complete_connection (device, + connection, + specific_object_path, + all_connections, + &error)) + goto error; + } + g_slist_free (all_connections); + all_connections = NULL; + + active = _new_active_connection (self, + connection, + specific_object_path, + device, + subject, + &error); + if (!active) + goto error; + + nm_active_connection_authorize (active, _add_and_activate_auth_done, self, context); + active_connection_add (self, active); + g_object_unref (connection); + g_object_unref (subject); + return; + +error: + g_clear_object (&connection); + g_slist_free (all_connections); + g_clear_object (&subject); + g_clear_object (&active); + + g_assert (error); + dbus_g_method_return_error (context, error); + g_error_free (error); } +/***********************************************************************/ + gboolean nm_manager_deactivate_connection (NMManager *manager, const char *connection_path, @@ -3286,9 +3379,8 @@ nm_manager_deactivate_connection (NMManager *manager, "The VPN connection was not active."); } else { g_assert (NM_IS_ACT_REQUEST (active)); - /* FIXME: use DEACTIVATING state */ nm_device_state_changed (nm_active_connection_get_device (active), - NM_DEVICE_STATE_DISCONNECTED, + NM_DEVICE_STATE_DEACTIVATING, reason); success = TRUE; } @@ -3309,11 +3401,13 @@ deactivate_net_auth_done_cb (NMAuthChain *chain, NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); GError *error = NULL; NMAuthCallResult result; - const char *active_path; + + g_assert (context); priv->auth_chains = g_slist_remove (priv->auth_chains, chain); - result = GPOINTER_TO_UINT (nm_auth_chain_get_data (chain, NM_AUTH_PERMISSION_NETWORK_CONTROL)); + result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_NETWORK_CONTROL); + if (auth_error) { nm_log_dbg (LOGD_CORE, "Disconnect request failed: %s", auth_error->message); error = g_error_new (NM_MANAGER_ERROR, @@ -3326,9 +3420,8 @@ deactivate_net_auth_done_cb (NMAuthChain *chain, "Not authorized to deactivate connections"); } else { /* success; deactivation allowed */ - active_path = nm_auth_chain_get_data (chain, "path"); if (!nm_manager_deactivate_connection (self, - active_path, + nm_auth_chain_get_data (chain, "path"), NM_DEVICE_STATE_REASON_USER_REQUESTED, &error)) g_assert (error); @@ -3351,9 +3444,9 @@ impl_manager_deactivate_connection (NMManager *self, NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); NMConnection *connection = NULL; GError *error = NULL; + NMAuthSubject *subject = NULL; GSList *iter; NMAuthChain *chain; - gulong sender_uid = G_MAXULONG; char *error_desc = NULL; /* Find the connection by its object path */ @@ -3370,85 +3463,100 @@ impl_manager_deactivate_connection (NMManager *self, error = g_error_new_literal (NM_MANAGER_ERROR, NM_MANAGER_ERROR_CONNECTION_NOT_ACTIVE, "The connection was not active."); - dbus_g_method_return_error (context, error); - g_error_free (error); - return; + goto done; } - /* Need to check the caller's permissions and stuff before we can - * deactivate the connection. - */ - if (!nm_auth_get_caller_uid (context, - priv->dbus_mgr, - &sender_uid, - &error_desc)) { + /* Validate the caller */ + subject = nm_auth_subject_new_from_context (context); + if (!subject) { error = g_error_new_literal (NM_MANAGER_ERROR, NM_MANAGER_ERROR_PERMISSION_DENIED, - error_desc); - dbus_g_method_return_error (context, error); - g_error_free (error); - g_free (error_desc); - return; + "Failed to get request UID."); + goto done; } /* Ensure the subject has permissions for this connection */ if (!nm_auth_uid_in_acl (connection, - priv->session_monitor, - sender_uid, + nm_session_monitor_get (), + nm_auth_subject_get_uid (subject), &error_desc)) { error = g_error_new_literal (NM_MANAGER_ERROR, NM_MANAGER_ERROR_PERMISSION_DENIED, error_desc); - dbus_g_method_return_error (context, error); - g_error_free (error); g_free (error_desc); - return; + goto done; } - /* Yay for root */ - if (0 == sender_uid) { - if (!nm_manager_deactivate_connection (self, - active_path, - NM_DEVICE_STATE_REASON_USER_REQUESTED, - &error)) { - dbus_g_method_return_error (context, error); - g_clear_error (&error); - } else - dbus_g_method_return (context); - - return; + /* Validate the user request */ + chain = nm_auth_chain_new_subject (subject, context, deactivate_net_auth_done_cb, self); + if (!chain) { + error = g_error_new_literal (NM_MANAGER_ERROR, + NM_MANAGER_ERROR_PERMISSION_DENIED, + "Unable to authenticate request."); + goto done; } - /* Otherwise validate the user request */ - chain = nm_auth_chain_new (context, NULL, deactivate_net_auth_done_cb, self); - g_assert (chain); priv->auth_chains = g_slist_append (priv->auth_chains, chain); - nm_auth_chain_set_data (chain, "path", g_strdup (active_path), g_free); nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_NETWORK_CONTROL, TRUE); + +done: + g_clear_object (&subject); + if (error) + dbus_g_method_return_error (context, error); + g_clear_error (&error); +} + +static gboolean +device_is_wake_on_lan (NMDevice *device) +{ + return nm_platform_link_get_wake_on_lan (nm_device_get_ip_ifindex (device)); } static void -do_sleep_wake (NMManager *self) +do_sleep_wake (NMManager *self, gboolean sleeping_changed) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - const GSList *unmanaged_specs; + gboolean suspending, waking_from_suspend; GSList *iter; + suspending = sleeping_changed && priv->sleeping; + waking_from_suspend = sleeping_changed && !priv->sleeping; + if (manager_sleeping (self)) { - nm_log_info (LOGD_SUSPEND, "sleeping or disabling..."); + nm_log_info (LOGD_SUSPEND, suspending ? "sleeping..." : "disabling..."); - /* Just deactivate and down all devices from the device list, - * to keep things fast the device list will get resynced when - * the manager wakes up. + /* FIXME: are there still hardware devices that need to be disabled around + * suspend/resume? */ - for (iter = priv->devices; iter; iter = iter->next) - nm_device_set_managed (NM_DEVICE (iter->data), FALSE, NM_DEVICE_STATE_REASON_SLEEPING); + for (iter = priv->devices; iter; iter = iter->next) { + NMDevice *device = iter->data; + + /* FIXME: shouldn't we be unmanaging software devices if !suspending? */ + if (nm_device_is_software (device)) + continue; + /* Wake-on-LAN devices will be taken down post-suspend rather than pre- */ + if (suspending && device_is_wake_on_lan (device)) + continue; + nm_device_set_unmanaged (device, NM_UNMANAGED_INTERNAL, TRUE, NM_DEVICE_STATE_REASON_SLEEPING); + } } else { - nm_log_info (LOGD_SUSPEND, "waking up and re-enabling..."); + nm_log_info (LOGD_SUSPEND, waking_from_suspend ? "waking up..." : "re-enabling..."); + + if (waking_from_suspend) { + /* Belatedly take down Wake-on-LAN devices; ideally we wouldn't have to do this + * but for now it's the only way to make sure we re-check their connectivity. + */ + for (iter = priv->devices; iter; iter = iter->next) { + NMDevice *device = iter->data; - unmanaged_specs = nm_settings_get_unmanaged_specs (priv->settings); + if (nm_device_is_software (device)) + continue; + if (device_is_wake_on_lan (device)) + nm_device_set_unmanaged (device, NM_UNMANAGED_INTERNAL, TRUE, NM_DEVICE_STATE_REASON_SLEEPING); + } + } /* Ensure rfkill state is up-to-date since we don't respond to state * changes during sleep. @@ -3460,6 +3568,9 @@ do_sleep_wake (NMManager *self) NMDevice *device = NM_DEVICE (iter->data); guint i; + if (nm_device_is_software (device)) + continue; + /* enable/disable wireless devices since that we don't respond * to killswitch changes during sleep. */ @@ -3479,10 +3590,7 @@ do_sleep_wake (NMManager *self) g_object_set (G_OBJECT (device), NM_DEVICE_AUTOCONNECT, TRUE, NULL); - if (nm_device_spec_match_list (device, unmanaged_specs)) - nm_device_set_managed (device, FALSE, NM_DEVICE_STATE_REASON_NOW_UNMANAGED); - else - nm_device_set_managed (device, TRUE, NM_DEVICE_STATE_REASON_NOW_MANAGED); + nm_device_set_unmanaged (device, NM_UNMANAGED_INTERNAL, FALSE, NM_DEVICE_STATE_REASON_NOW_MANAGED); } } @@ -3504,7 +3612,7 @@ _internal_sleep (NMManager *self, gboolean do_sleep) priv->sleeping = do_sleep; - do_sleep_wake (self); + do_sleep_wake (self, TRUE); g_object_notify (G_OBJECT (self), NM_MANAGER_SLEEPING); } @@ -3524,7 +3632,7 @@ sleep_auth_done_cb (NMAuthChain *chain, priv->auth_chains = g_slist_remove (priv->auth_chains, chain); - result = GPOINTER_TO_UINT (nm_auth_chain_get_data (chain, NM_AUTH_PERMISSION_SLEEP_WAKE)); + result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_SLEEP_WAKE); if (error) { nm_log_dbg (LOGD_SUSPEND, "Sleep/wake request failed: %s", error->message); ret_error = g_error_new (NM_MANAGER_ERROR, @@ -3559,7 +3667,6 @@ impl_manager_sleep (NMManager *self, GError *error = NULL; #if 0 NMAuthChain *chain; - gulong sender_uid = G_MAXULONG; const char *error_desc = NULL; #endif @@ -3589,28 +3696,18 @@ impl_manager_sleep (NMManager *self, return; #if 0 - if (!nm_auth_get_caller_uid (context, priv->dbus_mgr, &sender_uid, &error_desc)) { + chain = nm_auth_chain_new (context, sleep_auth_done_cb, self, &error_desc); + if (chain) { + priv->auth_chains = g_slist_append (priv->auth_chains, chain); + nm_auth_chain_set_data (chain, "sleep", GUINT_TO_POINTER (do_sleep), NULL); + nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_SLEEP_WAKE, TRUE); + } else { error = g_error_new_literal (NM_MANAGER_ERROR, NM_MANAGER_ERROR_PERMISSION_DENIED, error_desc); dbus_g_method_return_error (context, error); g_error_free (error); - return; } - - /* Root doesn't need PK authentication */ - if (0 == sender_uid) { - _internal_sleep (self, do_sleep); - dbus_g_method_return (context); - return; - } - - chain = nm_auth_chain_new (context, NULL, sleep_auth_done_cb, self); - g_assert (chain); - priv->auth_chains = g_slist_append (priv->auth_chains, chain); - - nm_auth_chain_set_data (chain, "sleep", GUINT_TO_POINTER (do_sleep), NULL); - nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_SLEEP_WAKE, TRUE); #endif } @@ -3655,7 +3752,7 @@ _internal_enable (NMManager *self, gboolean enable) priv->net_enabled = enable; - do_sleep_wake (self); + do_sleep_wake (self, FALSE); g_object_notify (G_OBJECT (self), NM_MANAGER_NETWORKING_ENABLED); } @@ -3668,27 +3765,25 @@ enable_net_done_cb (NMAuthChain *chain, { NMManager *self = NM_MANAGER (user_data); NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - GError *ret_error; + GError *ret_error = NULL; NMAuthCallResult result; gboolean enable; + g_assert (context); + priv->auth_chains = g_slist_remove (priv->auth_chains, chain); - result = GPOINTER_TO_UINT (nm_auth_chain_get_data (chain, NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK)); + result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK); if (error) { nm_log_dbg (LOGD_CORE, "Enable request failed: %s", error->message); ret_error = g_error_new (NM_MANAGER_ERROR, NM_MANAGER_ERROR_PERMISSION_DENIED, "Enable request failed: %s", error->message); - dbus_g_method_return_error (context, ret_error); - g_error_free (ret_error); } else if (result != NM_AUTH_CALL_RESULT_YES) { ret_error = g_error_new_literal (NM_MANAGER_ERROR, NM_MANAGER_ERROR_PERMISSION_DENIED, "Not authorized to enable/disable networking"); - dbus_g_method_return_error (context, ret_error); - g_error_free (ret_error); } else { /* Auth success */ enable = GPOINTER_TO_UINT (nm_auth_chain_get_data (chain, "enable")); @@ -3696,6 +3791,11 @@ enable_net_done_cb (NMAuthChain *chain, dbus_g_method_return (context); } + if (ret_error) { + dbus_g_method_return_error (context, ret_error); + g_error_free (ret_error); + } + nm_auth_chain_unref (chain); } @@ -3707,8 +3807,6 @@ impl_manager_enable (NMManager *self, NMManagerPrivate *priv; NMAuthChain *chain; GError *error = NULL; - gulong sender_uid = G_MAXULONG; - char *error_desc = NULL; g_return_if_fail (NM_IS_MANAGER (self)); @@ -3718,34 +3816,25 @@ impl_manager_enable (NMManager *self, error = g_error_new (NM_MANAGER_ERROR, NM_MANAGER_ERROR_ALREADY_ENABLED_OR_DISABLED, "Already %s", enable ? "enabled" : "disabled"); - dbus_g_method_return_error (context, error); - g_error_free (error); - return; + goto done; } - if (!nm_auth_get_caller_uid (context, priv->dbus_mgr, &sender_uid, &error_desc)) { + chain = nm_auth_chain_new_context (context, enable_net_done_cb, self); + if (!chain) { error = g_error_new_literal (NM_MANAGER_ERROR, NM_MANAGER_ERROR_PERMISSION_DENIED, - error_desc); - dbus_g_method_return_error (context, error); - g_error_free (error); - g_free (error_desc); - return; - } - - /* Root doesn't need PK authentication */ - if (0 == sender_uid) { - _internal_enable (self, enable); - dbus_g_method_return (context); - return; + "Unable to authenticate request."); + goto done; } - chain = nm_auth_chain_new (context, NULL, enable_net_done_cb, self); - g_assert (chain); priv->auth_chains = g_slist_append (priv->auth_chains, chain); - nm_auth_chain_set_data (chain, "enable", GUINT_TO_POINTER (enable), NULL); nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK, TRUE); + +done: + if (error) + dbus_g_method_return_error (context, error); + g_clear_error (&error); } /* Permissions */ @@ -3755,7 +3844,7 @@ get_perm_add_result (NMAuthChain *chain, GHashTable *results, const char *permis { NMAuthCallResult result; - result = GPOINTER_TO_UINT (nm_auth_chain_get_data (chain, permission)); + result = nm_auth_chain_get_result (chain, permission); if (result == NM_AUTH_CALL_RESULT_YES) g_hash_table_insert (results, (char *) permission, "yes"); else if (result == NM_AUTH_CALL_RESULT_NO) @@ -3778,6 +3867,8 @@ get_permissions_done_cb (NMAuthChain *chain, GError *ret_error; GHashTable *results; + g_assert (context); + priv->auth_chains = g_slist_remove (priv->auth_chains, chain); if (error) { nm_log_dbg (LOGD_CORE, "Permissions request failed: %s", error->message); @@ -3789,6 +3880,7 @@ get_permissions_done_cb (NMAuthChain *chain, g_error_free (ret_error); } else { results = g_hash_table_new (g_str_hash, g_str_equal); + get_perm_add_result (chain, results, NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK); get_perm_add_result (chain, results, NM_AUTH_PERMISSION_SLEEP_WAKE); get_perm_add_result (chain, results, NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI); @@ -3800,6 +3892,7 @@ get_permissions_done_cb (NMAuthChain *chain, get_perm_add_result (chain, results, NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM); get_perm_add_result (chain, results, NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN); get_perm_add_result (chain, results, NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME); + dbus_g_method_return (context, results); g_hash_table_destroy (results); } @@ -3813,11 +3906,19 @@ impl_manager_get_permissions (NMManager *self, { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); NMAuthChain *chain; + GError *error = NULL; - chain = nm_auth_chain_new (context, NULL, get_permissions_done_cb, self); - g_assert (chain); - priv->auth_chains = g_slist_append (priv->auth_chains, chain); + chain = nm_auth_chain_new_context (context, get_permissions_done_cb, self); + if (!chain) { + error = g_error_new_literal (NM_MANAGER_ERROR, + NM_MANAGER_ERROR_PERMISSION_DENIED, + "Unable to authenticate request."); + dbus_g_method_return_error (context, error); + g_clear_error (&error); + return; + } + priv->auth_chains = g_slist_append (priv->auth_chains, chain); nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK, FALSE); nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_SLEEP_WAKE, FALSE); nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI, FALSE); @@ -3839,22 +3940,46 @@ impl_manager_get_state (NMManager *manager, guint32 *state, GError **error) return TRUE; } -static gboolean +static void impl_manager_set_logging (NMManager *manager, const char *level, const char *domains, - GError **error) + DBusGMethodInvocation *context) { - if (nm_logging_setup (level, domains, error)) { + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); + GError *error = NULL; + gulong caller_uid = G_MAXULONG; + + if (!nm_dbus_manager_get_caller_info (priv->dbus_mgr, context, NULL, &caller_uid, NULL)) { + error = g_error_new_literal (NM_MANAGER_ERROR, + NM_MANAGER_ERROR_PERMISSION_DENIED, + "Failed to get request UID."); + goto done; + } + + if (0 != caller_uid) { + error = g_error_new_literal (NM_MANAGER_ERROR, + NM_MANAGER_ERROR_PERMISSION_DENIED, + "Permission denied"); + goto done; + } + + if (nm_logging_setup (level, domains, NULL, &error)) { + char *new_level = nm_logging_level_to_string (); char *new_domains = nm_logging_domains_to_string (); nm_log_info (LOGD_CORE, "logging: level '%s' domains '%s'", - nm_logging_level_to_string (), - new_domains); + new_level, new_domains); + g_free (new_level); g_free (new_domains); - return TRUE; } - return FALSE; + +done: + if (error) { + dbus_g_method_return_error (context, error); + g_error_free (error); + } else + dbus_g_method_return (context); } static void @@ -3862,8 +3987,8 @@ impl_manager_get_logging (NMManager *manager, char **level, char **domains) { - *level = g_strdup (nm_logging_level_to_string ()); - *domains = g_strdup (nm_logging_domains_to_string ()); + *level = nm_logging_level_to_string (); + *domains = nm_logging_domains_to_string (); } static void @@ -3929,37 +4054,20 @@ impl_manager_check_connectivity (NMManager *manager, { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); NMAuthChain *chain; - gulong sender_uid = G_MAXULONG; - char *error_desc = NULL; - GError *error; + GError *error = NULL; - /* Need to check the caller's permissions and stuff first */ - if (!nm_auth_get_caller_uid (context, - priv->dbus_mgr, - &sender_uid, - &error_desc)) { + /* Validate the request */ + chain = nm_auth_chain_new_context (context, check_connectivity_auth_done_cb, manager); + if (!chain) { error = g_error_new_literal (NM_MANAGER_ERROR, NM_MANAGER_ERROR_PERMISSION_DENIED, - error_desc); + "Unable to authenticate request."); dbus_g_method_return_error (context, error); - g_error_free (error); - g_free (error_desc); - return; - } - - /* Yay for root */ - if (0 == sender_uid) { - nm_connectivity_check_async (priv->connectivity, - connectivity_check_done, - context); + g_clear_error (&error); return; } - /* Validate the user request */ - chain = nm_auth_chain_new (context, NULL, check_connectivity_auth_done_cb, manager); - g_assert (chain); priv->auth_chains = g_slist_append (priv->auth_chains, chain); - nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_NETWORK_CONTROL, TRUE); } @@ -3972,14 +4080,13 @@ nm_manager_start (NMManager *self) /* Set initial radio enabled/disabled state */ for (i = 0; i < RFKILL_TYPE_MAX; i++) { RadioState *rstate = &priv->radio_states[i]; - RfKillState udev_state; gboolean enabled; if (!rstate->desc) continue; - udev_state = nm_udev_manager_get_rfkill_state (priv->udev_mgr, i); - update_rstate_from_rfkill (rstate, udev_state); + /* recheck kernel rfkill state */ + update_rstate_from_rfkill (priv->rfkill_mgr, rstate); if (rstate->desc) { nm_log_info (LOGD_RFKILL, "%s %s by radio killswitch; %s by state file", @@ -3998,23 +4105,7 @@ nm_manager_start (NMManager *self) system_unmanaged_devices_changed_cb (priv->settings, NULL, self); system_hostname_changed_cb (priv->settings, NULL, self); - /* FIXME: remove when we handle bridges non-destructively */ - /* Read a list of bridges NM managed when it last quit, and only - * manage those bridges to avoid conflicts with external tools. - */ - priv->nm_bridges = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); - read_nm_created_bridges (self); - - nm_udev_manager_query_devices (priv->udev_mgr); - nm_bluez_manager_query_devices (priv->bluez_mgr); - - /* Query devices again to ensure that we catch all virtual interfaces (like - * VLANs) that require a parent. If during the first pass the VLAN - * interface was detected first, the parent wouldn't exist yet and creating - * the VLAN would fail. The second query ensures that we'll have a valid - * parent for the VLAN during the second pass. - */ - nm_udev_manager_query_devices (priv->udev_mgr); + nm_platform_query_devices (); /* * Connections added before the manager is started do not emit @@ -4022,9 +4113,7 @@ nm_manager_start (NMManager *self) */ system_create_virtual_devices (self); - /* FIXME: remove when we handle bridges non-destructively */ - g_hash_table_unref (priv->nm_bridges); - priv->nm_bridges = NULL; + check_if_startup_complete (self); } static gboolean @@ -4089,9 +4178,7 @@ firmware_dir_changed (GFileMonitor *monitor, switch (event_type) { case G_FILE_MONITOR_EVENT_CREATED: case G_FILE_MONITOR_EVENT_CHANGED: -#if GLIB_CHECK_VERSION(2,23,4) case G_FILE_MONITOR_EVENT_MOVED: -#endif case G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED: case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT: if (!priv->fw_changed_id) { @@ -4129,7 +4216,7 @@ policy_default_device_changed (GObject *object, GParamSpec *pspec, gpointer user if (ac != priv->primary_connection) { g_clear_object (&priv->primary_connection); priv->primary_connection = ac ? g_object_ref (ac) : NULL; - nm_log_dbg (LOGD_CORE, "PrimaryConnection now %s", ac ? nm_active_connection_get_name (ac) : "(none)"); + nm_log_dbg (LOGD_CORE, "PrimaryConnection now %s", ac ? nm_active_connection_get_id (ac) : "(none)"); g_object_notify (G_OBJECT (self), NM_MANAGER_PRIMARY_CONNECTION); } } @@ -4162,7 +4249,7 @@ policy_activating_device_changed (GObject *object, GParamSpec *pspec, gpointer u if (ac != priv->activating_connection) { g_clear_object (&priv->activating_connection); priv->activating_connection = ac ? g_object_ref (ac) : NULL; - nm_log_dbg (LOGD_CORE, "ActivatingConnection now %s", ac ? nm_active_connection_get_name (ac) : "(none)"); + nm_log_dbg (LOGD_CORE, "ActivatingConnection now %s", ac ? nm_active_connection_get_id (ac) : "(none)"); g_object_notify (G_OBJECT (self), NM_MANAGER_ACTIVATING_CONNECTION); } } @@ -4176,428 +4263,160 @@ prop_set_auth_done_cb (NMAuthChain *chain, DBusGMethodInvocation *context, gpointer user_data) { - NMManager *self = NM_MANAGER (user_data); - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - DBusGConnection *bus; - DBusConnection *dbus_connection; - NMAuthCallResult result; - DBusMessage *reply = NULL, *request; - GError *ret_error; - const char *permission, *prop, *objpath; - gboolean set_enabled = TRUE; - gboolean is_device = FALSE; - size_t objpath_len; - size_t devpath_len; - - priv->auth_chains = g_slist_remove (priv->auth_chains, chain); - - request = nm_auth_chain_get_data (chain, "message"); - permission = nm_auth_chain_get_data (chain, "permission"); - prop = nm_auth_chain_get_data (chain, "prop"); - set_enabled = GPOINTER_TO_UINT (nm_auth_chain_get_data (chain, "enabled")); - objpath = nm_auth_chain_get_data (chain, "objectpath"); - - objpath_len = strlen (objpath); - devpath_len = strlen (NM_DBUS_PATH "/Devices"); - if ( strncmp (objpath, NM_DBUS_PATH "/Devices", devpath_len) == 0 - && objpath_len > devpath_len) - is_device = TRUE; - - if (error) { - reply = dbus_message_new_error (request, is_device ? DEV_PERM_DENIED_ERROR : NM_PERM_DENIED_ERROR, - "Not authorized to perform this operation"); - } else { - /* Caller has had a chance to obtain authorization, so we only need to - * check for 'yes' here. - */ - result = GPOINTER_TO_UINT (nm_auth_chain_get_data (chain, permission)); - if (result != NM_AUTH_CALL_RESULT_YES) { - reply = dbus_message_new_error (request, is_device ? DEV_PERM_DENIED_ERROR : NM_PERM_DENIED_ERROR, - "Not authorized to perform this operation"); - } else { - if (is_device) { - /* Find the device */ - NMDevice *device = nm_manager_get_device_by_path (self, objpath); - if (device) { - g_object_set (device, prop, set_enabled, NULL); - reply = dbus_message_new_method_return (request); - } - else { - ret_error = g_error_new_literal (NM_MANAGER_ERROR, - NM_MANAGER_ERROR_UNKNOWN_DEVICE, - "Can't find device for this operation"); - dbus_g_method_return_error (context, ret_error); - g_error_free (ret_error); - } - } else { - g_object_set (self, prop, set_enabled, NULL); - reply = dbus_message_new_method_return (request); - } - } - } - - if (reply) { - bus = nm_dbus_manager_get_connection (priv->dbus_mgr); - g_assert (bus); - dbus_connection = dbus_g_connection_get_connection (bus); - g_assert (dbus_connection); - - dbus_connection_send (dbus_connection, reply, NULL); - dbus_message_unref (reply); - } - nm_auth_chain_unref (chain); -} - -static DBusHandlerResult -prop_filter (DBusConnection *connection, - DBusMessage *message, - void *user_data) -{ - NMManager *self = NM_MANAGER (user_data); - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - DBusMessageIter iter; - DBusMessageIter sub; - const char *propiface = NULL; - const char *propname = NULL; - const char *sender = NULL; - const char *objpath = NULL; - const char *glib_propname = NULL, *permission = NULL; - DBusError dbus_error; - gulong uid = G_MAXULONG; - DBusMessage *reply = NULL; - gboolean set_enabled = FALSE; - NMAuthChain *chain; - - /* The sole purpose of this function is to validate property accesses - * on the NMManager object since dbus-glib doesn't yet give us this - * functionality. - */ - - if (!dbus_message_is_method_call (message, DBUS_INTERFACE_PROPERTIES, "Set")) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - - dbus_message_iter_init (message, &iter); - - /* Get the D-Bus interface of the property to set */ - if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - dbus_message_iter_get_basic (&iter, &propiface); - if (!propiface || (strcmp (propiface, NM_DBUS_INTERFACE) && strcmp (propiface, NM_DBUS_INTERFACE_DEVICE))) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - dbus_message_iter_next (&iter); - - /* Get the property name that's going to be set */ - if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - dbus_message_iter_get_basic (&iter, &propname); - dbus_message_iter_next (&iter); - - if (!strcmp (propname, "WirelessEnabled")) { - glib_propname = NM_MANAGER_WIRELESS_ENABLED; - permission = NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI; - } else if (!strcmp (propname, "WwanEnabled")) { - glib_propname = NM_MANAGER_WWAN_ENABLED; - permission = NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN; - } else if (!strcmp (propname, "WimaxEnabled")) { - glib_propname = NM_MANAGER_WIMAX_ENABLED; - permission = NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX; - } else if (!strcmp (propname, "Autoconnect")) { - glib_propname = NM_DEVICE_AUTOCONNECT; - permission = NM_AUTH_PERMISSION_NETWORK_CONTROL; - } else - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - - /* Get the new value for the property */ - if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_VARIANT) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - dbus_message_iter_recurse (&iter, &sub); - if (dbus_message_iter_get_arg_type (&sub) != DBUS_TYPE_BOOLEAN) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - dbus_message_iter_get_basic (&sub, &set_enabled); - - sender = dbus_message_get_sender (message); - if (!sender) { - reply = dbus_message_new_error (message, NM_PERM_DENIED_ERROR, - "Could not determine D-Bus requestor"); - goto out; - } - - objpath = dbus_message_get_path (message); - if (!objpath) { - reply = dbus_message_new_error (message, NM_PERM_DENIED_ERROR, - "Could not determine D-Bus object path"); - goto out; - } - - dbus_error_init (&dbus_error); - uid = dbus_bus_get_unix_user (connection, sender, &dbus_error); - if (dbus_error_is_set (&dbus_error)) { - reply = dbus_message_new_error (message, NM_PERM_DENIED_ERROR, - "Could not determine the user ID of the requestor"); - dbus_error_free (&dbus_error); - goto out; - } - - if (uid > 0) { - /* Otherwise validate the user request */ - chain = nm_auth_chain_new_raw_message (message, prop_set_auth_done_cb, self); - g_assert (chain); - priv->auth_chains = g_slist_append (priv->auth_chains, chain); - nm_auth_chain_set_data (chain, "prop", g_strdup (glib_propname), g_free); - nm_auth_chain_set_data (chain, "permission", g_strdup (permission), g_free); - nm_auth_chain_set_data (chain, "enabled", GUINT_TO_POINTER (set_enabled), NULL); - nm_auth_chain_set_data (chain, "message", dbus_message_ref (message), (GDestroyNotify) dbus_message_unref); - nm_auth_chain_set_data (chain, "objectpath", g_strdup (objpath), g_free); - nm_auth_chain_add_call (chain, permission, TRUE); - } else { - /* Yay for root */ - g_object_set (self, glib_propname, set_enabled, NULL); - reply = dbus_message_new_method_return (message); - } - -out: - if (reply) { - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - } - return DBUS_HANDLER_RESULT_HANDLED; -} - -static NMManager *singleton = NULL; - -NMManager * -nm_manager_get (void) -{ - g_assert (singleton); - return g_object_ref (singleton); -} - -NMManager * -nm_manager_new (NMSettings *settings, - const char *state_file, - gboolean initial_net_enabled, - gboolean initial_wifi_enabled, - gboolean initial_wwan_enabled, - gboolean initial_wimax_enabled, - const gchar *connectivity_uri, - gint connectivity_interval, - const gchar *connectivity_response, - GError **error) -{ - NMManagerPrivate *priv; - DBusGConnection *bus; - DBusConnection *dbus_connection; - - g_assert (settings); - - /* Can only be called once */ - g_assert (singleton == NULL); - singleton = (NMManager *) g_object_new (NM_TYPE_MANAGER, NULL); - g_assert (singleton); - - priv = NM_MANAGER_GET_PRIVATE (singleton); - - priv->policy = nm_policy_new (singleton, settings); - g_signal_connect (priv->policy, "notify::" NM_POLICY_DEFAULT_IP4_DEVICE, - G_CALLBACK (policy_default_device_changed), singleton); - g_signal_connect (priv->policy, "notify::" NM_POLICY_DEFAULT_IP6_DEVICE, - G_CALLBACK (policy_default_device_changed), singleton); - g_signal_connect (priv->policy, "notify::" NM_POLICY_ACTIVATING_IP4_DEVICE, - G_CALLBACK (policy_activating_device_changed), singleton); - g_signal_connect (priv->policy, "notify::" NM_POLICY_ACTIVATING_IP6_DEVICE, - G_CALLBACK (policy_activating_device_changed), singleton); - - priv->connectivity = nm_connectivity_new (connectivity_uri, connectivity_interval, connectivity_response); - g_signal_connect (priv->connectivity, "notify::" NM_CONNECTIVITY_STATE, - G_CALLBACK (connectivity_changed), singleton); - - bus = nm_dbus_manager_get_connection (priv->dbus_mgr); - g_assert (bus); - dbus_connection = dbus_g_connection_get_connection (bus); - g_assert (dbus_connection); - - if (!dbus_connection_add_filter (dbus_connection, prop_filter, singleton, NULL)) { - nm_log_err (LOGD_CORE, "failed to register DBus connection filter"); - g_object_unref (singleton); - return NULL; - } - - priv->settings = g_object_ref (settings); - - priv->state_file = g_strdup (state_file); - - priv->net_enabled = initial_net_enabled; - - priv->radio_states[RFKILL_TYPE_WLAN].user_enabled = initial_wifi_enabled; - priv->radio_states[RFKILL_TYPE_WWAN].user_enabled = initial_wwan_enabled; - priv->radio_states[RFKILL_TYPE_WIMAX].user_enabled = initial_wimax_enabled; - - g_signal_connect (priv->settings, "notify::" NM_SETTINGS_UNMANAGED_SPECS, - G_CALLBACK (system_unmanaged_devices_changed_cb), singleton); - g_signal_connect (priv->settings, "notify::" NM_SETTINGS_HOSTNAME, - G_CALLBACK (system_hostname_changed_cb), singleton); - g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_ADDED, - G_CALLBACK (connection_added), singleton); - g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_UPDATED, - G_CALLBACK (connection_changed), singleton); - g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_REMOVED, - G_CALLBACK (connection_removed), singleton); - g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_VISIBILITY_CHANGED, - G_CALLBACK (connection_changed), singleton); - - dbus_g_connection_register_g_object (bus, NM_DBUS_PATH, G_OBJECT (singleton)); - - priv->udev_mgr = nm_udev_manager_new (); - g_signal_connect (priv->udev_mgr, - "device-added", - G_CALLBACK (udev_device_added_cb), - singleton); - g_signal_connect (priv->udev_mgr, - "device-removed", - G_CALLBACK (udev_device_removed_cb), - singleton); - g_signal_connect (priv->udev_mgr, - "rfkill-changed", - G_CALLBACK (udev_manager_rfkill_changed_cb), - singleton); - - priv->bluez_mgr = nm_bluez_manager_get (NM_CONNECTION_PROVIDER (priv->settings)); - - g_signal_connect (priv->bluez_mgr, - NM_BLUEZ_MANAGER_BDADDR_ADDED, - G_CALLBACK (bluez_manager_bdaddr_added_cb), - singleton); - - g_signal_connect (priv->bluez_mgr, - NM_BLUEZ_MANAGER_BDADDR_REMOVED, - G_CALLBACK (bluez_manager_bdaddr_removed_cb), - singleton); - - priv->session_monitor = nm_session_monitor_get (); - - /* Force kernel WiFi rfkill state to follow NM saved wifi state in case - * the BIOS doesn't save rfkill state, and to be consistent with user - * changes to the WirelessEnabled property which toggles kernel rfkill. - */ - rfkill_change_wifi (priv->radio_states[RFKILL_TYPE_WLAN].desc, initial_wifi_enabled); - - return singleton; -} - -static void -authority_changed_cb (gpointer user_data) -{ - /* Let clients know they should re-check their authorization */ - g_signal_emit (NM_MANAGER (user_data), signals[CHECK_PERMISSIONS], 0); -} - -static void -dispose (GObject *object) -{ - NMManager *manager = NM_MANAGER (object); - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); - DBusGConnection *bus; - DBusConnection *dbus_connection; - GSList *iter; - - if (priv->disposed) { - G_OBJECT_CLASS (nm_manager_parent_class)->dispose (object); - return; - } - priv->disposed = TRUE; - - g_slist_foreach (priv->auth_chains, (GFunc) nm_auth_chain_unref, NULL); - g_slist_free (priv->auth_chains); - - nm_auth_changed_func_unregister (authority_changed_cb, manager); + NMManager *self = NM_MANAGER (user_data); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + DBusConnection *connection; + NMAuthCallResult result; + DBusMessage *reply = NULL, *message; + const char *permission, *prop; + GObject *obj; + gboolean set_enabled = TRUE; - /* FIXME: remove when we handle bridges non-destructively */ - write_nm_created_bridges (manager); + priv->auth_chains = g_slist_remove (priv->auth_chains, chain); - /* Remove all devices */ - while (g_slist_length (priv->devices)) { - priv->devices = remove_one_device (manager, - priv->devices, - NM_DEVICE (priv->devices->data), - TRUE); - } + message = nm_auth_chain_get_data (chain, "message"); + permission = nm_auth_chain_get_data (chain, "permission"); + prop = nm_auth_chain_get_data (chain, "prop"); + set_enabled = GPOINTER_TO_UINT (nm_auth_chain_get_data (chain, "enabled")); + obj = nm_auth_chain_get_data (chain, "object"); - if (priv->ac_cleanup_id) { - g_source_remove (priv->ac_cleanup_id); - priv->ac_cleanup_id = 0; + result = nm_auth_chain_get_result (chain, permission); + if (error || (result != NM_AUTH_CALL_RESULT_YES)) { + reply = dbus_message_new_error (message, + NM_IS_DEVICE (obj) ? DEV_PERM_DENIED_ERROR : NM_PERM_DENIED_ERROR, + "Not authorized to perform this operation"); + } else { + g_object_set (obj, prop, set_enabled, NULL); + reply = dbus_message_new_method_return (message); } - for (iter = priv->active_connections; iter; iter = g_slist_next (iter)) - active_connection_removed (manager, NM_ACTIVE_CONNECTION (iter->data)); - g_slist_free (priv->active_connections); - priv->active_connections = NULL; - g_clear_object (&priv->primary_connection); - g_clear_object (&priv->activating_connection); + g_assert (reply); + connection = nm_auth_chain_get_data (chain, "connection"); + g_assert (connection); + dbus_connection_send (connection, reply, NULL); + dbus_message_unref (reply); - g_clear_object (&priv->connectivity); + nm_auth_chain_unref (chain); +} - g_free (priv->hostname); +static DBusHandlerResult +prop_filter (DBusConnection *connection, + DBusMessage *message, + void *user_data) +{ + NMManager *self = NM_MANAGER (user_data); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + DBusMessageIter iter; + DBusMessageIter sub; + const char *propiface = NULL; + const char *propname = NULL; + const char *glib_propname = NULL, *permission = NULL; + DBusMessage *reply = NULL; + gboolean set_enabled = FALSE; + NMAuthSubject *subject = NULL; + NMAuthChain *chain; + GObject *obj; - g_signal_handlers_disconnect_by_func (priv->policy, G_CALLBACK (policy_default_device_changed), singleton); - g_signal_handlers_disconnect_by_func (priv->policy, G_CALLBACK (policy_activating_device_changed), singleton); - g_object_unref (priv->policy); + /* The sole purpose of this function is to validate property accesses + * on the NMManager object since dbus-glib doesn't yet give us this + * functionality. + */ - g_object_unref (priv->settings); - g_object_unref (priv->vpn_manager); - g_object_unref (priv->session_monitor); + if (!dbus_message_is_method_call (message, DBUS_INTERFACE_PROPERTIES, "Set")) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - if (priv->modem_added_id) { - g_source_remove (priv->modem_added_id); - priv->modem_added_id = 0; - } - if (priv->modem_removed_id) { - g_source_remove (priv->modem_removed_id); - priv->modem_removed_id = 0; - } - g_object_unref (priv->modem_manager); + dbus_message_iter_init (message, &iter); - /* Unregister property filter */ - bus = nm_dbus_manager_get_connection (priv->dbus_mgr); - if (bus) { - dbus_connection = dbus_g_connection_get_connection (bus); - g_assert (dbus_connection); - dbus_connection_remove_filter (dbus_connection, prop_filter, manager); - } - g_signal_handler_disconnect (priv->dbus_mgr, priv->dbus_connection_changed_id); - g_object_unref (priv->dbus_mgr); + /* Get the D-Bus interface of the property to set */ + if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + dbus_message_iter_get_basic (&iter, &propiface); + if (!propiface || (strcmp (propiface, NM_DBUS_INTERFACE) && strcmp (propiface, NM_DBUS_INTERFACE_DEVICE))) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + dbus_message_iter_next (&iter); - if (priv->bluez_mgr) - g_object_unref (priv->bluez_mgr); + /* Get the property name that's going to be set */ + if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + dbus_message_iter_get_basic (&iter, &propname); + dbus_message_iter_next (&iter); - if (priv->aipd_proxy) - g_object_unref (priv->aipd_proxy); + if (!strcmp (propname, "WirelessEnabled")) { + glib_propname = NM_MANAGER_WIRELESS_ENABLED; + permission = NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI; + } else if (!strcmp (propname, "WwanEnabled")) { + glib_propname = NM_MANAGER_WWAN_ENABLED; + permission = NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN; + } else if (!strcmp (propname, "WimaxEnabled")) { + glib_propname = NM_MANAGER_WIMAX_ENABLED; + permission = NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX; + } else if (!strcmp (propname, "Autoconnect")) { + glib_propname = NM_DEVICE_AUTOCONNECT; + permission = NM_AUTH_PERMISSION_NETWORK_CONTROL; + } else + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - if (priv->sleep_monitor) - g_object_unref (priv->sleep_monitor); + /* Get the new value for the property */ + if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_VARIANT) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + dbus_message_iter_recurse (&iter, &sub); + if (dbus_message_iter_get_arg_type (&sub) != DBUS_TYPE_BOOLEAN) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + dbus_message_iter_get_basic (&sub, &set_enabled); - if (priv->fw_monitor) { - if (priv->fw_monitor_id) - g_signal_handler_disconnect (priv->fw_monitor, priv->fw_monitor_id); + /* Make sure the object exists */ + obj = dbus_g_connection_lookup_g_object (dbus_connection_get_g_connection (connection), + dbus_message_get_path (message)); + if (!obj) { + reply = dbus_message_new_error (message, NM_PERM_DENIED_ERROR, + "Object does not exist"); + goto out; + } - if (priv->fw_changed_id) - g_source_remove (priv->fw_changed_id); + subject = nm_auth_subject_new_from_message (connection, message); + if (!subject) { + reply = dbus_message_new_error (message, NM_PERM_DENIED_ERROR, + "Could not determine request UID."); + goto out; + } - g_file_monitor_cancel (priv->fw_monitor); - g_object_unref (priv->fw_monitor); + /* Validate the user request */ + chain = nm_auth_chain_new_subject (subject, NULL, prop_set_auth_done_cb, self); + if (!chain) { + reply = dbus_message_new_error (message, NM_PERM_DENIED_ERROR, + "Could not authenticate request."); + goto out; } - g_slist_free (priv->factories); + priv->auth_chains = g_slist_append (priv->auth_chains, chain); + nm_auth_chain_set_data (chain, "prop", g_strdup (glib_propname), g_free); + nm_auth_chain_set_data (chain, "permission", g_strdup (permission), g_free); + nm_auth_chain_set_data (chain, "enabled", GUINT_TO_POINTER (set_enabled), NULL); + nm_auth_chain_set_data (chain, "message", dbus_message_ref (message), (GDestroyNotify) dbus_message_unref); + nm_auth_chain_set_data (chain, "connection", dbus_connection_ref (connection), (GDestroyNotify) dbus_connection_unref); + nm_auth_chain_set_data (chain, "object", g_object_ref (obj), (GDestroyNotify) g_object_unref); + nm_auth_chain_add_call (chain, permission, TRUE); - if (priv->timestamp_update_id) { - g_source_remove (priv->timestamp_update_id); - priv->timestamp_update_id = 0; +out: + if (reply) { + dbus_connection_send (connection, reply, NULL); + dbus_message_unref (reply); } + g_clear_object (&subject); - G_OBJECT_CLASS (nm_manager_parent_class)->dispose (object); + return DBUS_HANDLER_RESULT_HANDLED; +} + +static void +authority_changed_cb (gpointer user_data) +{ + /* Let clients know they should re-check their authorization */ + g_signal_emit (NM_MANAGER (user_data), signals[CHECK_PERMISSIONS], 0); } #define KERN_RFKILL_OP_CHANGE_ALL 3 #define KERN_RFKILL_TYPE_WLAN 1 +#define KERN_RFKILL_TYPE_WWAN 5 struct rfkill_event { __u32 idx; __u8 type; @@ -4606,18 +4425,19 @@ struct rfkill_event { } __attribute__((packed)); static void -rfkill_change_wifi (const char *desc, gboolean enabled) +rfkill_change (const char *desc, RfKillType rtype, gboolean enabled) { int fd; struct rfkill_event event; ssize_t len; + g_return_if_fail (rtype == RFKILL_TYPE_WLAN || rtype == RFKILL_TYPE_WWAN); + errno = 0; fd = open ("/dev/rfkill", O_RDWR); if (fd < 0) { if (errno == EACCES) - nm_log_warn (LOGD_RFKILL, "(%s): failed to open killswitch device " - "for WiFi radio control", desc); + nm_log_warn (LOGD_RFKILL, "(%s): failed to open killswitch device", desc); return; } @@ -4630,7 +4450,16 @@ rfkill_change_wifi (const char *desc, gboolean enabled) memset (&event, 0, sizeof (event)); event.op = KERN_RFKILL_OP_CHANGE_ALL; - event.type = KERN_RFKILL_TYPE_WLAN; + switch (rtype) { + case RFKILL_TYPE_WLAN: + event.type = KERN_RFKILL_TYPE_WLAN; + break; + case RFKILL_TYPE_WWAN: + event.type = KERN_RFKILL_TYPE_WWAN; + break; + default: + g_assert_not_reached (); + } event.soft = enabled ? 0 : 1; len = write (fd, &event, sizeof (event)); @@ -4657,6 +4486,10 @@ manager_radio_user_toggled (NMManager *self, GError *error = NULL; gboolean old_enabled, new_enabled; + /* Don't touch devices if asleep/networking disabled */ + if (manager_sleeping (self)) + return; + if (rstate->desc) { nm_log_dbg (LOGD_RFKILL, "(%s): setting radio %s by user", rstate->desc, @@ -4690,151 +4523,174 @@ manager_radio_user_toggled (NMManager *self, rstate->user_enabled = enabled; new_enabled = radio_enabled_for_rstate (rstate, FALSE); if (new_enabled != old_enabled) { - manager_update_radio_enabled (self, rstate, new_enabled); + /* Try to change the kernel rfkill state */ + if (rstate->rtype == RFKILL_TYPE_WLAN || rstate->rtype == RFKILL_TYPE_WWAN) + rfkill_change (rstate->desc, rstate->rtype, new_enabled); - /* For WiFi only (for now) set the actual kernel rfkill state */ - if (rstate->rtype == RFKILL_TYPE_WLAN) - rfkill_change_wifi (rstate->desc, new_enabled); + manager_update_radio_enabled (self, rstate, new_enabled); } } -static void -set_property (GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec) +static gboolean +periodic_update_active_connection_timestamps (gpointer user_data) { - NMManager *self = NM_MANAGER (object); - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + NMManager *manager = NM_MANAGER (user_data); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); + GSList *iter; - switch (prop_id) { - case PROP_NETWORKING_ENABLED: - /* Construct only for now */ - priv->net_enabled = g_value_get_boolean (value); - break; - case PROP_WIRELESS_ENABLED: - manager_radio_user_toggled (NM_MANAGER (object), - &priv->radio_states[RFKILL_TYPE_WLAN], - g_value_get_boolean (value)); - break; - case PROP_WWAN_ENABLED: - manager_radio_user_toggled (NM_MANAGER (object), - &priv->radio_states[RFKILL_TYPE_WWAN], - g_value_get_boolean (value)); - break; - case PROP_WIMAX_ENABLED: - manager_radio_user_toggled (NM_MANAGER (object), - &priv->radio_states[RFKILL_TYPE_WIMAX], - g_value_get_boolean (value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; + for (iter = priv->active_connections; iter; iter = g_slist_next (iter)) { + NMActiveConnection *ac = iter->data; + NMSettingsConnection *connection; + + if (nm_active_connection_get_state (ac) == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) { + connection = NM_SETTINGS_CONNECTION (nm_active_connection_get_connection (ac)); + nm_settings_connection_update_timestamp (connection, (guint64) time (NULL), FALSE); + } } + + return TRUE; } static void -get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) +dbus_connection_changed_cb (NMDBusManager *dbus_mgr, + DBusConnection *dbus_connection, + gpointer user_data) { - NMManager *self = NM_MANAGER (object); - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - GSList *iter; - GPtrArray *active; - const char *path; + NMManager *self = NM_MANAGER (user_data); + gboolean success = FALSE; - switch (prop_id) { - case PROP_VERSION: - g_value_set_string (value, VERSION); - break; - case PROP_STATE: - nm_manager_update_state (self); - g_value_set_uint (value, priv->state); - break; - case PROP_NETWORKING_ENABLED: - g_value_set_boolean (value, priv->net_enabled); - break; - case PROP_WIRELESS_ENABLED: - g_value_set_boolean (value, radio_enabled_for_type (self, RFKILL_TYPE_WLAN, TRUE)); - break; - case PROP_WIRELESS_HARDWARE_ENABLED: - g_value_set_boolean (value, priv->radio_states[RFKILL_TYPE_WLAN].hw_enabled); - break; - case PROP_WWAN_ENABLED: - g_value_set_boolean (value, radio_enabled_for_type (self, RFKILL_TYPE_WWAN, TRUE)); - break; - case PROP_WWAN_HARDWARE_ENABLED: - g_value_set_boolean (value, priv->radio_states[RFKILL_TYPE_WWAN].hw_enabled); - break; - case PROP_WIMAX_ENABLED: - g_value_set_boolean (value, radio_enabled_for_type (self, RFKILL_TYPE_WIMAX, TRUE)); - break; - case PROP_WIMAX_HARDWARE_ENABLED: - g_value_set_boolean (value, priv->radio_states[RFKILL_TYPE_WIMAX].hw_enabled); - break; - case PROP_ACTIVE_CONNECTIONS: - active = g_ptr_array_sized_new (3); - for (iter = priv->active_connections; iter; iter = g_slist_next (iter)) { - path = nm_active_connection_get_path (NM_ACTIVE_CONNECTION (iter->data)); - g_ptr_array_add (active, g_strdup (path)); - } - g_value_take_boxed (value, active); - break; - case PROP_CONNECTIVITY: - g_value_set_uint (value, nm_connectivity_get_state (priv->connectivity)); - break; - case PROP_PRIMARY_CONNECTION: - path = priv->primary_connection ? nm_active_connection_get_path (priv->primary_connection) : "/"; - g_value_set_boxed (value, path); - break; - case PROP_ACTIVATING_CONNECTION: - path = priv->activating_connection ? nm_active_connection_get_path (priv->activating_connection) : "/"; - g_value_set_boxed (value, path); - break; - case PROP_HOSTNAME: - g_value_set_string (value, priv->hostname); - break; - case PROP_SLEEPING: - g_value_set_boolean (value, priv->sleeping); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; + if (dbus_connection) { + /* Register property filter on new connection; there's no reason this + * should fail except out-of-memory or program error; if it does fail + * then there's no Manager property access control, which is bad. + */ + success = dbus_connection_add_filter (dbus_connection, prop_filter, self, NULL); + g_assert (success); } + NM_MANAGER_GET_PRIVATE (self)->prop_filter_added = success; } -static gboolean -periodic_update_active_connection_timestamps (gpointer user_data) +/**********************************************************************/ + +static NMManager *singleton = NULL; + +NMManager * +nm_manager_get (void) +{ + g_assert (singleton); + return singleton; +} + +NMConnectionProvider * +nm_connection_provider_get (void) +{ + g_assert (singleton); + g_assert (NM_MANAGER_GET_PRIVATE (singleton)->settings); + return NM_CONNECTION_PROVIDER (NM_MANAGER_GET_PRIVATE (singleton)->settings); +} + +NMManager * +nm_manager_new (NMSettings *settings, + const char *state_file, + gboolean initial_net_enabled, + gboolean initial_wifi_enabled, + gboolean initial_wwan_enabled, + gboolean initial_wimax_enabled, + GError **error) { - NMManager *manager = NM_MANAGER (user_data); - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); - GSList *iter; + NMManagerPrivate *priv; + DBusGConnection *bus; + DBusConnection *dbus_connection; - for (iter = priv->active_connections; iter; iter = g_slist_next (iter)) { - NMActiveConnection *ac = iter->data; - NMSettingsConnection *connection; + g_assert (settings); - if (nm_active_connection_get_state (ac) == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) { - connection = NM_SETTINGS_CONNECTION (nm_active_connection_get_connection (ac)); - nm_settings_connection_update_timestamp (connection, (guint64) time (NULL), FALSE); - } + /* Can only be called once */ + g_assert (singleton == NULL); + singleton = (NMManager *) g_object_new (NM_TYPE_MANAGER, NULL); + g_assert (singleton); + + priv = NM_MANAGER_GET_PRIVATE (singleton); + + bus = nm_dbus_manager_get_connection (priv->dbus_mgr); + if (!bus) { + g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_INTERNAL, + "Failed to initialize D-Bus connection"); + g_object_unref (singleton); + return NULL; } - return TRUE; -} + dbus_connection = dbus_g_connection_get_connection (bus); + g_assert (dbus_connection); -static void -dbus_connection_changed_cb (NMDBusManager *dbus_mgr, - DBusConnection *dbus_connection, - gpointer user_data) -{ - NMManager *self = NM_MANAGER (user_data); + priv->policy = nm_policy_new (singleton, settings); + g_signal_connect (priv->policy, "notify::" NM_POLICY_DEFAULT_IP4_DEVICE, + G_CALLBACK (policy_default_device_changed), singleton); + g_signal_connect (priv->policy, "notify::" NM_POLICY_DEFAULT_IP6_DEVICE, + G_CALLBACK (policy_default_device_changed), singleton); + g_signal_connect (priv->policy, "notify::" NM_POLICY_ACTIVATING_IP4_DEVICE, + G_CALLBACK (policy_activating_device_changed), singleton); + g_signal_connect (priv->policy, "notify::" NM_POLICY_ACTIVATING_IP6_DEVICE, + G_CALLBACK (policy_activating_device_changed), singleton); - if (dbus_connection) { - /* Register property filter on new connection; there's no reason this - * should fail except out-of-memory or program error; if it does fail - * then there's no Manager property access control, which is bad. - */ - g_assert (dbus_connection_add_filter (dbus_connection, prop_filter, self, NULL)); + priv->connectivity = nm_connectivity_new (); + g_signal_connect (priv->connectivity, "notify::" NM_CONNECTIVITY_STATE, + G_CALLBACK (connectivity_changed), singleton); + + if (!dbus_connection_add_filter (dbus_connection, prop_filter, singleton, NULL)) { + g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_INTERNAL, + "Failed to register DBus connection filter"); + g_object_unref (singleton); + return NULL; } + priv->prop_filter_added = TRUE; + + priv->settings = g_object_ref (settings); + + priv->state_file = g_strdup (state_file); + + priv->net_enabled = initial_net_enabled; + + priv->radio_states[RFKILL_TYPE_WLAN].user_enabled = initial_wifi_enabled; + priv->radio_states[RFKILL_TYPE_WWAN].user_enabled = initial_wwan_enabled; + priv->radio_states[RFKILL_TYPE_WIMAX].user_enabled = initial_wimax_enabled; + + g_signal_connect (priv->settings, "notify::" NM_SETTINGS_UNMANAGED_SPECS, + G_CALLBACK (system_unmanaged_devices_changed_cb), singleton); + g_signal_connect (priv->settings, "notify::" NM_SETTINGS_HOSTNAME, + G_CALLBACK (system_hostname_changed_cb), singleton); + g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_ADDED, + G_CALLBACK (connection_added), singleton); + g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_UPDATED, + G_CALLBACK (connection_changed), singleton); + g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_REMOVED, + G_CALLBACK (connection_removed), singleton); + g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_VISIBILITY_CHANGED, + G_CALLBACK (connection_changed), singleton); + + nm_dbus_manager_register_object (priv->dbus_mgr, NM_DBUS_PATH, singleton); + + g_signal_connect (nm_platform_get (), + NM_PLATFORM_SIGNAL_LINK_CHANGED, + G_CALLBACK (platform_link_cb), + singleton); + + priv->rfkill_mgr = nm_rfkill_manager_new (); + g_signal_connect (priv->rfkill_mgr, + "rfkill-changed", + G_CALLBACK (rfkill_manager_rfkill_changed_cb), + singleton); + + /* Force kernel WiFi/WWAN rfkill state to follow NM saved WiFi/WWAN state + * in case the BIOS doesn't save rfkill state, and to be consistent with user + * changes to the WirelessEnabled/WWANEnabled properties which toggle kernel + * rfkill. + */ + rfkill_change (priv->radio_states[RFKILL_TYPE_WLAN].desc, RFKILL_TYPE_WLAN, initial_wifi_enabled); + rfkill_change (priv->radio_states[RFKILL_TYPE_WWAN].desc, RFKILL_TYPE_WWAN, initial_wwan_enabled); + + load_device_factories (singleton); + + return singleton; } static void @@ -4853,7 +4709,6 @@ nm_manager_init (NMManager *manager) priv->radio_states[RFKILL_TYPE_WLAN].prop = NM_MANAGER_WIRELESS_ENABLED; priv->radio_states[RFKILL_TYPE_WLAN].hw_prop = NM_MANAGER_WIRELESS_HARDWARE_ENABLED; priv->radio_states[RFKILL_TYPE_WLAN].desc = "WiFi"; - priv->radio_states[RFKILL_TYPE_WLAN].other_enabled_func = nm_manager_get_ipw_rfkill_state; priv->radio_states[RFKILL_TYPE_WLAN].rtype = RFKILL_TYPE_WLAN; priv->radio_states[RFKILL_TYPE_WWAN].user_enabled = TRUE; @@ -4861,7 +4716,6 @@ nm_manager_init (NMManager *manager) priv->radio_states[RFKILL_TYPE_WWAN].prop = NM_MANAGER_WWAN_ENABLED; priv->radio_states[RFKILL_TYPE_WWAN].hw_prop = NM_MANAGER_WWAN_HARDWARE_ENABLED; priv->radio_states[RFKILL_TYPE_WWAN].desc = "WWAN"; - priv->radio_states[RFKILL_TYPE_WWAN].daemon_enabled_func = nm_manager_get_modem_enabled_state; priv->radio_states[RFKILL_TYPE_WWAN].rtype = RFKILL_TYPE_WWAN; priv->radio_states[RFKILL_TYPE_WIMAX].user_enabled = TRUE; @@ -4869,7 +4723,6 @@ nm_manager_init (NMManager *manager) priv->radio_states[RFKILL_TYPE_WIMAX].prop = NM_MANAGER_WIMAX_ENABLED; priv->radio_states[RFKILL_TYPE_WIMAX].hw_prop = NM_MANAGER_WIMAX_HARDWARE_ENABLED; priv->radio_states[RFKILL_TYPE_WIMAX].desc = "WiMAX"; - priv->radio_states[RFKILL_TYPE_WIMAX].other_enabled_func = NULL; priv->radio_states[RFKILL_TYPE_WIMAX].rtype = RFKILL_TYPE_WIMAX; for (i = 0; i < RFKILL_TYPE_MAX; i++) @@ -4877,18 +4730,13 @@ nm_manager_init (NMManager *manager) priv->sleeping = FALSE; priv->state = NM_STATE_DISCONNECTED; + priv->startup = TRUE; priv->dbus_mgr = nm_dbus_manager_get (); - priv->dbus_connection_changed_id = g_signal_connect (priv->dbus_mgr, - NM_DBUS_MANAGER_DBUS_CONNECTION_CHANGED, - G_CALLBACK (dbus_connection_changed_cb), - manager); - - priv->modem_manager = nm_modem_manager_get (); - priv->modem_added_id = g_signal_connect (priv->modem_manager, "modem-added", - G_CALLBACK (modem_added), manager); - priv->modem_removed_id = g_signal_connect (priv->modem_manager, "modem-removed", - G_CALLBACK (modem_removed), manager); + g_signal_connect (priv->dbus_mgr, + NM_DBUS_MANAGER_DBUS_CONNECTION_CHANGED, + G_CALLBACK (dbus_connection_changed_cb), + manager); priv->vpn_manager = nm_vpn_manager_get (); @@ -4900,7 +4748,7 @@ nm_manager_init (NMManager *manager) "/", NM_AUTOIP_DBUS_IFACE); if (priv->aipd_proxy) { - dbus_g_object_register_marshaller (_nm_marshal_VOID__STRING_STRING_STRING, + dbus_g_object_register_marshaller (g_cclosure_marshal_generic, G_TYPE_NONE, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID); @@ -4935,9 +4783,9 @@ nm_manager_init (NMManager *manager) } if (priv->fw_monitor) { - priv->fw_monitor_id = g_signal_connect (priv->fw_monitor, "changed", - G_CALLBACK (firmware_dir_changed), - manager); + g_signal_connect (priv->fw_monitor, "changed", + G_CALLBACK (firmware_dir_changed), + manager); nm_log_info (LOGD_CORE, "monitoring kernel firmware directory '%s'.", KERNEL_FIRMWARE_DIR); } else { @@ -4945,12 +4793,213 @@ nm_manager_init (NMManager *manager) KERNEL_FIRMWARE_DIR); } - load_device_factories (manager); - /* Update timestamps in active connections */ priv->timestamp_update_id = g_timeout_add_seconds (300, (GSourceFunc) periodic_update_active_connection_timestamps, manager); } +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMManager *self = NM_MANAGER (object); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + GSList *iter; + GPtrArray *array; + const char *path; + + switch (prop_id) { + case PROP_VERSION: + g_value_set_string (value, VERSION); + break; + case PROP_STATE: + nm_manager_update_state (self); + g_value_set_uint (value, priv->state); + break; + case PROP_STARTUP: + g_value_set_boolean (value, priv->startup); + break; + case PROP_NETWORKING_ENABLED: + g_value_set_boolean (value, priv->net_enabled); + break; + case PROP_WIRELESS_ENABLED: + g_value_set_boolean (value, radio_enabled_for_type (self, RFKILL_TYPE_WLAN, TRUE)); + break; + case PROP_WIRELESS_HARDWARE_ENABLED: + g_value_set_boolean (value, priv->radio_states[RFKILL_TYPE_WLAN].hw_enabled); + break; + case PROP_WWAN_ENABLED: + g_value_set_boolean (value, radio_enabled_for_type (self, RFKILL_TYPE_WWAN, TRUE)); + break; + case PROP_WWAN_HARDWARE_ENABLED: + g_value_set_boolean (value, priv->radio_states[RFKILL_TYPE_WWAN].hw_enabled); + break; + case PROP_WIMAX_ENABLED: + g_value_set_boolean (value, radio_enabled_for_type (self, RFKILL_TYPE_WIMAX, TRUE)); + break; + case PROP_WIMAX_HARDWARE_ENABLED: + g_value_set_boolean (value, priv->radio_states[RFKILL_TYPE_WIMAX].hw_enabled); + break; + case PROP_ACTIVE_CONNECTIONS: + array = g_ptr_array_sized_new (3); + for (iter = priv->active_connections; iter; iter = g_slist_next (iter)) { + path = nm_active_connection_get_path (NM_ACTIVE_CONNECTION (iter->data)); + if (path) + g_ptr_array_add (array, g_strdup (path)); + } + g_value_take_boxed (value, array); + break; + case PROP_CONNECTIVITY: + g_value_set_uint (value, nm_connectivity_get_state (priv->connectivity)); + break; + case PROP_PRIMARY_CONNECTION: + path = priv->primary_connection ? nm_active_connection_get_path (priv->primary_connection) : NULL; + g_value_set_boxed (value, path ? path : "/"); + break; + case PROP_ACTIVATING_CONNECTION: + path = priv->activating_connection ? nm_active_connection_get_path (priv->activating_connection) : NULL; + g_value_set_boxed (value, path ? path : "/"); + break; + case PROP_HOSTNAME: + g_value_set_string (value, priv->hostname); + break; + case PROP_SLEEPING: + g_value_set_boolean (value, priv->sleeping); + break; + case PROP_DEVICES: + array = g_ptr_array_sized_new (5); + for (iter = priv->devices; iter; iter = g_slist_next (iter)) { + path = nm_device_get_path (NM_DEVICE (iter->data)); + if (path) + g_ptr_array_add (array, g_strdup (path)); + } + g_value_take_boxed (value, array); + 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) +{ + NMManager *self = NM_MANAGER (object); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + + switch (prop_id) { + case PROP_NETWORKING_ENABLED: + /* Construct only for now */ + priv->net_enabled = g_value_get_boolean (value); + break; + case PROP_WIRELESS_ENABLED: + manager_radio_user_toggled (NM_MANAGER (object), + &priv->radio_states[RFKILL_TYPE_WLAN], + g_value_get_boolean (value)); + break; + case PROP_WWAN_ENABLED: + manager_radio_user_toggled (NM_MANAGER (object), + &priv->radio_states[RFKILL_TYPE_WWAN], + g_value_get_boolean (value)); + break; + case PROP_WIMAX_ENABLED: + manager_radio_user_toggled (NM_MANAGER (object), + &priv->radio_states[RFKILL_TYPE_WIMAX], + g_value_get_boolean (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +dispose (GObject *object) +{ + NMManager *manager = NM_MANAGER (object); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); + DBusGConnection *bus; + DBusConnection *dbus_connection; + GSList *iter; + + g_slist_free_full (priv->auth_chains, (GDestroyNotify) nm_auth_chain_unref); + priv->auth_chains = NULL; + + nm_auth_changed_func_unregister (authority_changed_cb, manager); + + /* Remove all devices */ + while (priv->devices) + remove_device (manager, NM_DEVICE (priv->devices->data), TRUE); + + if (priv->ac_cleanup_id) { + g_source_remove (priv->ac_cleanup_id); + priv->ac_cleanup_id = 0; + } + + while (priv->active_connections) + active_connection_remove (manager, NM_ACTIVE_CONNECTION (priv->active_connections->data)); + g_clear_pointer (&priv->active_connections, g_slist_free); + g_clear_object (&priv->primary_connection); + g_clear_object (&priv->activating_connection); + + g_clear_object (&priv->connectivity); + + g_free (priv->hostname); + + if (priv->policy) { + g_signal_handlers_disconnect_by_func (priv->policy, policy_default_device_changed, manager); + g_signal_handlers_disconnect_by_func (priv->policy, policy_activating_device_changed, manager); + g_clear_object (&priv->policy); + } + + g_clear_object (&priv->settings); + g_clear_object (&priv->vpn_manager); + + /* Unregister property filter */ + if (priv->dbus_mgr) { + bus = nm_dbus_manager_get_connection (priv->dbus_mgr); + if (bus) { + dbus_connection = dbus_g_connection_get_connection (bus); + if (dbus_connection && priv->prop_filter_added) { + dbus_connection_remove_filter (dbus_connection, prop_filter, manager); + priv->prop_filter_added = FALSE; + } + } + g_signal_handlers_disconnect_by_func (priv->dbus_mgr, dbus_connection_changed_cb, manager); + priv->dbus_mgr = NULL; + } + + g_clear_object (&priv->aipd_proxy); + g_clear_object (&priv->sleep_monitor); + + if (priv->fw_monitor) { + g_signal_handlers_disconnect_by_func (priv->fw_monitor, firmware_dir_changed, manager); + + if (priv->fw_changed_id) { + g_source_remove (priv->fw_changed_id); + priv->fw_changed_id = 0; + } + + g_file_monitor_cancel (priv->fw_monitor); + g_clear_object (&priv->fw_monitor); + } + + for (iter = priv->factories; iter; iter = iter->next) { + NMDeviceFactory *factory = iter->data; + + g_signal_handlers_disconnect_matched (factory, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, manager); + g_object_unref (factory); + } + g_clear_pointer (&priv->factories, g_slist_free); + + if (priv->timestamp_update_id) { + g_source_remove (priv->timestamp_update_id); + priv->timestamp_update_id = 0; + } + + G_OBJECT_CLASS (nm_manager_parent_class)->dispose (object); +} + static void nm_manager_class_init (NMManagerClass *manager_class) { @@ -4980,6 +5029,14 @@ nm_manager_class_init (NMManagerClass *manager_class) 0, NM_STATE_DISCONNECTED, 0, G_PARAM_READABLE)); + g_object_class_install_property + (object_class, PROP_STARTUP, + g_param_spec_boolean (NM_MANAGER_STARTUP, + "Startup", + "Is NetworkManager still starting up", + TRUE, + G_PARAM_READABLE)); + g_object_class_install_property (object_class, PROP_NETWORKING_ENABLED, g_param_spec_boolean (NM_MANAGER_NETWORKING_ENABLED, @@ -5075,7 +5132,7 @@ nm_manager_class_init (NMManagerClass *manager_class) "Hostname", "Hostname", NULL, - G_PARAM_READABLE | NM_PROPERTY_PARAM_NO_EXPORT)); + G_PARAM_READABLE)); /* Sleeping is not exported over D-Bus */ g_object_class_install_property @@ -5084,7 +5141,15 @@ nm_manager_class_init (NMManagerClass *manager_class) "Sleeping", "Sleeping", FALSE, - G_PARAM_READABLE | NM_PROPERTY_PARAM_NO_EXPORT)); + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_DEVICES, + g_param_spec_boxed (NM_MANAGER_DEVICES, + "Devices", + "Devices", + DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH, + G_PARAM_READABLE)); /* signals */ signals[DEVICE_ADDED] = @@ -5092,8 +5157,7 @@ nm_manager_class_init (NMManagerClass *manager_class) G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (NMManagerClass, device_added), - NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, + NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_OBJECT); signals[DEVICE_REMOVED] = @@ -5101,8 +5165,7 @@ nm_manager_class_init (NMManagerClass *manager_class) G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (NMManagerClass, device_removed), - NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, + NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_OBJECT); signals[STATE_CHANGED] = @@ -5110,48 +5173,40 @@ nm_manager_class_init (NMManagerClass *manager_class) G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (NMManagerClass, state_changed), - NULL, NULL, - g_cclosure_marshal_VOID__UINT, + NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_UINT); - signals[PROPERTIES_CHANGED] = - nm_properties_changed_signal_new (object_class, - G_STRUCT_OFFSET (NMManagerClass, properties_changed)); - signals[CHECK_PERMISSIONS] = g_signal_new ("check-permissions", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST, - 0, NULL, NULL, - g_cclosure_marshal_VOID__VOID, + 0, NULL, NULL, NULL, G_TYPE_NONE, 0); signals[USER_PERMISSIONS_CHANGED] = g_signal_new ("user-permissions-changed", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST, - 0, NULL, NULL, - g_cclosure_marshal_VOID__VOID, + 0, NULL, NULL, NULL, G_TYPE_NONE, 0); signals[ACTIVE_CONNECTION_ADDED] = g_signal_new (NM_MANAGER_ACTIVE_CONNECTION_ADDED, G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST, - 0, NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, + 0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_OBJECT); signals[ACTIVE_CONNECTION_REMOVED] = g_signal_new (NM_MANAGER_ACTIVE_CONNECTION_REMOVED, G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST, - 0, NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, + 0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_OBJECT); - dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (manager_class), - &dbus_glib_nm_manager_object_info); + nm_dbus_manager_register_exported_type (nm_dbus_manager_get (), + G_TYPE_FROM_CLASS (manager_class), + &dbus_glib_nm_manager_object_info); dbus_g_error_domain_register (NM_MANAGER_ERROR, NULL, NM_TYPE_MANAGER_ERROR); dbus_g_error_domain_register (NM_LOGGING_ERROR, "org.freedesktop.NetworkManager.Logging", NM_TYPE_LOGGING_ERROR); diff --git a/src/nm-manager.h b/src/nm-manager.h index 9884d050..81eefc7b 100644 --- a/src/nm-manager.h +++ b/src/nm-manager.h @@ -27,6 +27,7 @@ #include #include "nm-device.h" #include "nm-settings.h" +#include "nm-auth-subject.h" #define NM_TYPE_MANAGER (nm_manager_get_type ()) #define NM_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_MANAGER, NMManager)) @@ -47,10 +48,13 @@ typedef enum { NM_MANAGER_ERROR_UNSUPPORTED_CONNECTION_TYPE, /*< nick=UnsupportedConnectionType >*/ NM_MANAGER_ERROR_DEPENDENCY_FAILED, /*< nick=DependencyFailed >*/ NM_MANAGER_ERROR_AUTOCONNECT_NOT_ALLOWED, /*< nick=AutoconnectNotAllowed >*/ + NM_MANAGER_ERROR_CONNECTION_ALREADY_ACTIVE, /*< nick=ConnectionAlreadyActive >*/ + NM_MANAGER_ERROR_INTERNAL, /*< nick=Internal >*/ } NMManagerError; #define NM_MANAGER_VERSION "version" #define NM_MANAGER_STATE "state" +#define NM_MANAGER_STARTUP "startup" #define NM_MANAGER_NETWORKING_ENABLED "networking-enabled" #define NM_MANAGER_WIRELESS_ENABLED "wireless-enabled" #define NM_MANAGER_WIRELESS_HARDWARE_ENABLED "wireless-hardware-enabled" @@ -62,6 +66,7 @@ typedef enum { #define NM_MANAGER_CONNECTIVITY "connectivity" #define NM_MANAGER_PRIMARY_CONNECTION "primary-connection" #define NM_MANAGER_ACTIVATING_CONNECTION "activating-connection" +#define NM_MANAGER_DEVICES "devices" /* Not exported */ #define NM_MANAGER_HOSTNAME "hostname" @@ -83,7 +88,6 @@ typedef struct { void (*device_added) (NMManager *manager, NMDevice *device); void (*device_removed) (NMManager *manager, NMDevice *device); void (*state_changed) (NMManager *manager, guint state); - void (*properties_changed) (NMManager *manager, GHashTable *properties); } NMManagerClass; GType nm_manager_get_type (void); @@ -95,9 +99,6 @@ NMManager *nm_manager_new (NMSettings *settings, gboolean initial_wifi_enabled, gboolean initial_wwan_enabled, gboolean initial_wimax_enabled, - const gchar *connectivity_uri, - gint connectivity_interval, - const gchar *connectivity_response, GError **error); NMManager *nm_manager_get (void); @@ -105,20 +106,23 @@ NMManager *nm_manager_get (void); void nm_manager_start (NMManager *manager); const GSList *nm_manager_get_active_connections (NMManager *manager); +GSList *nm_manager_get_activatable_connections (NMManager *manager); /* Device handling */ -GSList *nm_manager_get_devices (NMManager *manager); +const GSList *nm_manager_get_devices (NMManager *manager); NMDevice *nm_manager_get_device_by_master (NMManager *manager, - const char *master, - const char *driver); + const char *master, + const char *driver); +NMDevice *nm_manager_get_device_by_ifindex (NMManager *manager, + int ifindex); NMActiveConnection *nm_manager_activate_connection (NMManager *manager, NMConnection *connection, const char *specific_object, - const char *device_path, - const char *dbus_sender, /* NULL if automatic */ + NMDevice *device, + NMAuthSubject *subject, GError **error); gboolean nm_manager_deactivate_connection (NMManager *manager, diff --git a/src/nm-netlink-compat.c b/src/nm-netlink-compat.c deleted file mode 100644 index 9c90eabe..00000000 --- a/src/nm-netlink-compat.c +++ /dev/null @@ -1,85 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2011 Caixa Magica Software. - */ - -#include - -#include "nm-netlink-compat.h" - -static struct rtnl_nexthop * -nm_netlink_get_nh (struct rtnl_route * route) -{ - int hops; - - hops = rtnl_route_get_nnexthops (route); - g_return_val_if_fail(hops > 0, NULL); - return rtnl_route_nexthop_n (route, 0); -} - -int -rtnl_route_get_oif (struct rtnl_route * route) -{ - struct rtnl_nexthop * nh; - - nh = nm_netlink_get_nh(route); - g_return_val_if_fail(nh, -NLE_OBJ_NOTFOUND); - return rtnl_route_nh_get_ifindex (nh); -} - -int -rtnl_route_set_oif (struct rtnl_route * route, int ifindex) -{ - struct rtnl_nexthop * nh; - - nh = rtnl_route_nh_alloc(); - rtnl_route_nh_set_ifindex(nh, ifindex); - rtnl_route_add_nexthop(route, nh); - return 0; -} - -struct nl_addr * -rtnl_route_get_gateway (struct rtnl_route * route) -{ - struct rtnl_nexthop * nh; - - nh = nm_netlink_get_nh(route); - g_return_val_if_fail(nh, NULL); - return rtnl_route_nh_get_gateway(nh); -} - -int -rtnl_route_set_gateway (struct rtnl_route * route, struct nl_addr * gw_addr) -{ - struct rtnl_nexthop * nh; - - nh = nm_netlink_get_nh(route); - g_return_val_if_fail(nh, -NLE_OBJ_NOTFOUND); - - rtnl_route_nh_set_gateway(nh, gw_addr); - return 0; -} - -int -rtnl_route_get_dst_len(struct rtnl_route * rtnlroute) -{ - struct nl_addr * dst; - - dst = rtnl_route_get_dst(rtnlroute); - return nl_addr_get_prefixlen(dst); -} diff --git a/src/nm-netlink-compat.h b/src/nm-netlink-compat.h deleted file mode 100644 index a844e9f2..00000000 --- a/src/nm-netlink-compat.h +++ /dev/null @@ -1,34 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2011 Caixa Magica Software. - * Copyright (C) 2011 - 2012 Red Hat, Inc. - */ - -#ifndef NM_NETLINK_COMPAT_H -#define NM_NETLINK_COMPAT_H - -#include - -/* libnl-1 API compatibility for libnl-3 */ -int rtnl_route_get_oif(struct rtnl_route *); -int rtnl_route_set_oif(struct rtnl_route *, int); -int rtnl_route_set_gateway(struct rtnl_route *, struct nl_addr *); -int rtnl_route_get_dst_len(struct rtnl_route *); -struct nl_addr * rtnl_route_get_gateway(struct rtnl_route *); - -#endif /* NM_NETLINK_COMPAT_H */ diff --git a/src/nm-netlink-monitor.c b/src/nm-netlink-monitor.c deleted file mode 100644 index ba8053e9..00000000 --- a/src/nm-netlink-monitor.c +++ /dev/null @@ -1,943 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2005 - 2010 Red Hat, Inc. - * Copyright (C) 2005 - 2008 Novell, Inc. - * Copyright (C) 2005 Ray Strode - * - * Some code borrowed from HAL: - * - * Copyright (C) 2003 David Zeuthen, - * Copyright (C) 2004 Novell, Inc. - */ - -/* for struct ucred and LIBNL_NEEDS_ADDR_CACHING_WORKAROUND */ -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "nm-netlink-compat.h" -#include "nm-netlink-monitor.h" -#include "nm-logging.h" - -#define EVENT_CONDITIONS ((GIOCondition) (G_IO_IN | G_IO_PRI)) -#define ERROR_CONDITIONS ((GIOCondition) (G_IO_ERR | G_IO_NVAL)) -#define DISCONNECT_CONDITIONS ((GIOCondition) (G_IO_HUP)) - -#define NM_NETLINK_MONITOR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \ - NM_TYPE_NETLINK_MONITOR, \ - NMNetlinkMonitorPrivate)) - -typedef struct { - /* Async event listener connection */ - struct nl_sock *nlh_event; - GIOChannel * io_channel; - guint event_id; - - /* Sync/blocking request/response connection */ - struct nl_sock *nlh_sync; - struct nl_cache * link_cache; - - guint request_status_id; - - GHashTable *subscriptions; -} NMNetlinkMonitorPrivate; - -enum { - NOTIFICATION = 0, - CARRIER_ON, - CARRIER_OFF, - LAST_SIGNAL -}; -static guint signals[LAST_SIGNAL] = { 0 }; - - -G_DEFINE_TYPE (NMNetlinkMonitor, nm_netlink_monitor, G_TYPE_OBJECT); - -/****************************************************************/ - -static gboolean -detach_monitor (gpointer data) -{ - nm_log_warn (LOGD_HW, "detaching netlink event monitor"); - nm_netlink_monitor_detach (NM_NETLINK_MONITOR (data)); - return FALSE; -} - -static void -log_error_limited (NMNetlinkMonitor *monitor, guint32 code, const char *fmt, ...) -{ - static time_t rl_time = 0; - static guint32 rl_code = 0; - static guint32 rl_count = 0; - va_list args; - char *msg; - time_t now; - - g_return_if_fail (monitor != NULL); - - now = time (NULL); - - if ((code != rl_code) || (now > rl_time + 10)) { - va_start (args, fmt); - msg = g_strdup_vprintf (fmt, args); - va_end (args); - - nm_log_warn (LOGD_HW, "error monitoring device for netlink events: %s\n", msg); - g_free (msg); - - rl_time = now; - rl_code = code; - rl_count = 0; - } - - rl_count++; - if (rl_count > 100) { - /* Broken drivers will sometimes cause a flood of netlink errors. - * rh #459205, novell #443429, lp #284507 - */ - nm_log_warn (LOGD_HW, "excessive netlink errors ocurred, disabling netlink monitor."); - nm_log_warn (LOGD_HW, "link change events will not be processed."); - g_idle_add_full (G_PRIORITY_HIGH, detach_monitor, monitor, NULL); - } -} - -/****************************************************************/ - -static void -link_msg_handler (struct nl_object *obj, void *arg) -{ - NMNetlinkMonitor *self = NM_NETLINK_MONITOR (arg); - struct rtnl_link *filter; - struct rtnl_link *link_obj; - guint flags; - guint ifidx; - - filter = rtnl_link_alloc (); - if (!filter) { - log_error_limited (self, NM_NETLINK_MONITOR_ERROR_BAD_ALLOC, - _("error processing netlink message: %s"), - nl_geterror (ENOMEM)); - return; - } - - /* Ensure it's a link object */ - if (nl_object_match_filter (obj, OBJ_CAST (filter)) == 0) { - rtnl_link_put (filter); - return; - } - - link_obj = (struct rtnl_link *) obj; - flags = rtnl_link_get_flags (link_obj); - ifidx = rtnl_link_get_ifindex (link_obj); - - nm_log_dbg (LOGD_HW, "netlink link message: iface idx %d flags 0x%X", ifidx, flags); - - /* IFF_LOWER_UP is the indicator of carrier status since kernel commit - * b00055aacdb172c05067612278ba27265fcd05ce in 2.6.17. - */ - if (flags & IFF_LOWER_UP) - g_signal_emit (self, signals[CARRIER_ON], 0, ifidx); - else - g_signal_emit (self, signals[CARRIER_OFF], 0, ifidx); - - rtnl_link_put (filter); -} - -static int -event_msg_recv (struct nl_msg *msg, void *arg) -{ - struct nl_sock *nlh = arg; - struct nlmsghdr *hdr = nlmsg_hdr (msg); - struct ucred *creds = nlmsg_get_creds (msg); - const struct sockaddr_nl *snl; - guint32 local_port; - gboolean accept_msg = FALSE; - - /* Only messages sent from the kernel */ - if (!creds || creds->uid != 0) { - nm_log_dbg (LOGD_HW, "ignoring netlink message from UID %d", - creds ? creds->uid : -1); - return NL_SKIP; - } - - snl = nlmsg_get_src (msg); - g_assert (snl); - - /* Accept any messages from the kernel */ - if (hdr->nlmsg_pid == 0 || snl->nl_pid == 0) - accept_msg = TRUE; - - /* And any multicast message directed to our netlink PID, since multicast - * currently requires CAP_ADMIN to use. - */ - local_port = nl_socket_get_local_port (nlh); - if ((hdr->nlmsg_pid == local_port) && snl->nl_groups) - accept_msg = TRUE; - - if (accept_msg == FALSE) { - nm_log_dbg (LOGD_HW, "ignoring netlink message from PID %d (local PID %d, multicast %d)", - hdr->nlmsg_pid, - local_port, - (hdr->nlmsg_flags & NLM_F_MULTI)); - return NL_SKIP; - } - - return NL_OK; -} - -static int -event_msg_ready (struct nl_msg *msg, void *arg) -{ - NMNetlinkMonitor *self = NM_NETLINK_MONITOR (arg); - - /* By the time the message gets here we've already checked the sender - * and we're sure it's safe to parse this message. - */ - - /* Let clients handle generic messages */ - g_signal_emit (self, signals[NOTIFICATION], 0, msg); - - /* Parse carrier messages */ - nl_msg_parse (msg, &link_msg_handler, self); - - return NL_OK; -} - -static gboolean -event_handler (GIOChannel *channel, - GIOCondition io_condition, - gpointer user_data) -{ - NMNetlinkMonitor *self = (NMNetlinkMonitor *) user_data; - NMNetlinkMonitorPrivate *priv; - int err; - - g_return_val_if_fail (NM_IS_NETLINK_MONITOR (self), TRUE); - - priv = NM_NETLINK_MONITOR_GET_PRIVATE (self); - g_return_val_if_fail (priv->event_id > 0, TRUE); - - if (io_condition & ERROR_CONDITIONS) { - const char *err_msg = _("error occurred while waiting for data on socket"); - int err_code = 0; - socklen_t err_len = sizeof (err_code); - - /* Grab error information */ - if (getsockopt (g_io_channel_unix_get_fd (channel), - SOL_SOCKET, SO_ERROR, - (void *) &err_code, &err_len) == 0) - err_msg = strerror (err_code); - - log_error_limited (self, NM_NETLINK_MONITOR_ERROR_WAITING_FOR_SOCKET_DATA, "%s", err_msg); - return TRUE; - } else if (io_condition & DISCONNECT_CONDITIONS) - return FALSE; - - g_return_val_if_fail (!(io_condition & ~EVENT_CONDITIONS), FALSE); - - /* Process the netlink messages */ - err = nl_recvmsgs_default (priv->nlh_event); - if (err < 0) { - log_error_limited (self, NM_NETLINK_MONITOR_ERROR_PROCESSING_MESSAGE, - _("error processing netlink message: %s"), - nl_geterror (err)); - } - - return TRUE; -} - -static gboolean -nlh_setup (struct nl_sock *nlh, - nl_recvmsg_msg_cb_t valid_func, - gpointer cb_data, - GError **error) -{ - int err; - - nl_socket_modify_cb (nlh, NL_CB_MSG_IN, NL_CB_CUSTOM, event_msg_recv, cb_data); - - if (valid_func) - nl_socket_modify_cb (nlh, NL_CB_VALID, NL_CB_CUSTOM, valid_func, cb_data); - - err = nl_connect (nlh, NETLINK_ROUTE); - if (err < 0) { - g_set_error (error, NM_NETLINK_MONITOR_ERROR, - NM_NETLINK_MONITOR_ERROR_NETLINK_CONNECT, - _("unable to connect to netlink for monitoring link status: %s"), - nl_geterror (err)); - return FALSE; - } - - /* Enable unix socket peer credentials which we use for verifying that the - * sender of the message is actually the kernel. - */ - if (nl_socket_set_passcred (nlh, 1) < 0) { - g_set_error (error, NM_NETLINK_MONITOR_ERROR, - NM_NETLINK_MONITOR_ERROR_NETLINK_CONNECT, - _("unable to enable netlink handle credential passing: %s"), - nl_geterror (err)); - return FALSE; - } - - return TRUE; -} - -static gboolean -event_connection_setup (NMNetlinkMonitor *self, GError **error) -{ - NMNetlinkMonitorPrivate *priv = NM_NETLINK_MONITOR_GET_PRIVATE (self); - GError *channel_error = NULL; - GIOFlags channel_flags; - int fd; - - g_return_val_if_fail (priv->io_channel == NULL, FALSE); - - /* Set up the event listener connection */ - priv->nlh_event = nl_socket_alloc (); - if (!priv->nlh_event) { - g_set_error (error, NM_NETLINK_MONITOR_ERROR, - NM_NETLINK_MONITOR_ERROR_NETLINK_ALLOC_HANDLE, - _("unable to allocate netlink handle for monitoring link status: %s"), - nl_geterror (ENOMEM)); - goto error; - } - - if (!nlh_setup (priv->nlh_event, event_msg_ready, self, error)) - goto error; - - nl_socket_disable_seq_check (priv->nlh_event); - - /* Subscribe to the LINK group for internal carrier signals */ - if (!nm_netlink_monitor_subscribe (self, RTNLGRP_LINK, error)) - goto error; - - fd = nl_socket_get_fd (priv->nlh_event); - priv->io_channel = g_io_channel_unix_new (fd); - - g_io_channel_set_encoding (priv->io_channel, NULL, &channel_error); - /* Encoding is NULL, so no conversion error can possibly occur */ - g_assert (channel_error == NULL); - - g_io_channel_set_close_on_unref (priv->io_channel, TRUE); - channel_flags = g_io_channel_get_flags (priv->io_channel); - channel_error = NULL; - g_io_channel_set_flags (priv->io_channel, - channel_flags | G_IO_FLAG_NONBLOCK, - &channel_error); - if (channel_error != NULL) { - g_propagate_error (error, channel_error); - goto error; - } - - return TRUE; - -error: - if (priv->io_channel) - nm_netlink_monitor_close_connection (self); - - if (priv->nlh_event) { - nl_socket_free (priv->nlh_event); - priv->nlh_event = NULL; - } - - return FALSE; -} - -static gboolean -sync_connection_setup (NMNetlinkMonitor *self, GError **error) -{ - NMNetlinkMonitorPrivate *priv = NM_NETLINK_MONITOR_GET_PRIVATE (self); -#ifdef LIBNL_NEEDS_ADDR_CACHING_WORKAROUND - struct nl_cache *addr_cache; -#endif - int err; - - /* Set up the event listener connection */ - priv->nlh_sync = nl_socket_alloc (); - if (!priv->nlh_sync) { - g_set_error (error, NM_NETLINK_MONITOR_ERROR, - NM_NETLINK_MONITOR_ERROR_NETLINK_ALLOC_HANDLE, - _("unable to allocate netlink handle for monitoring link status: %s"), - nl_geterror (ENOMEM)); - goto error; - } - - if (!nlh_setup (priv->nlh_sync, NULL, self, error)) - goto error; - -#ifdef LIBNL_NEEDS_ADDR_CACHING_WORKAROUND - /* Work around apparent libnl bug; rtnl_addr requires that all - * addresses have the "peer" attribute set in order to be compared - * for equality, but this attribute is not normally set. As a - * result, most addresses will not compare as equal even to - * themselves, busting caching. - */ - rtnl_addr_alloc_cache (priv->nlh_sync, &addr_cache); - g_warn_if_fail (addr_cache != NULL); - nl_cache_get_ops (addr_cache)->co_obj_ops->oo_id_attrs &= ~0x80; - nl_cache_free (addr_cache); -#endif - - err = rtnl_link_alloc_cache (priv->nlh_sync, AF_UNSPEC, &priv->link_cache); - if (err < 0) { - g_set_error (error, NM_NETLINK_MONITOR_ERROR, - NM_NETLINK_MONITOR_ERROR_NETLINK_ALLOC_LINK_CACHE, - _("unable to allocate netlink link cache for monitoring link status: %s"), - nl_geterror (err)); - goto error; - } - nl_cache_mngt_provide (priv->link_cache); - - return TRUE; - -error: - if (priv->link_cache) { - nl_cache_free (priv->link_cache); - priv->link_cache = NULL; - } - - if (priv->nlh_sync) { - nl_socket_free (priv->nlh_sync); - priv->nlh_sync = NULL; - } - - return FALSE; -} - -gboolean -nm_netlink_monitor_open_connection (NMNetlinkMonitor *self, GError **error) -{ - g_return_val_if_fail (self != NULL, FALSE); - g_return_val_if_fail (NM_IS_NETLINK_MONITOR (self), FALSE); - - if (!event_connection_setup (self, error)) - return FALSE; - - if (!sync_connection_setup (self, error)) - return FALSE; - - return TRUE; -} - -void -nm_netlink_monitor_close_connection (NMNetlinkMonitor *self) -{ - NMNetlinkMonitorPrivate *priv; - - g_return_if_fail (NM_IS_NETLINK_MONITOR (self)); - - priv = NM_NETLINK_MONITOR_GET_PRIVATE (self); - g_return_if_fail (priv->io_channel != NULL); - - if (priv->event_id) - nm_netlink_monitor_detach (self); - - g_io_channel_shutdown (priv->io_channel, - TRUE /* flush pending data */, - NULL); - g_io_channel_unref (priv->io_channel); - priv->io_channel = NULL; -} - -void -nm_netlink_monitor_attach (NMNetlinkMonitor *self) -{ - NMNetlinkMonitorPrivate *priv; - - g_return_if_fail (NM_IS_NETLINK_MONITOR (self)); - - priv = NM_NETLINK_MONITOR_GET_PRIVATE (self); - g_return_if_fail (priv->nlh_event != NULL); - g_return_if_fail (priv->event_id == 0); - - priv->event_id = g_io_add_watch (priv->io_channel, - (EVENT_CONDITIONS | ERROR_CONDITIONS | DISCONNECT_CONDITIONS), - event_handler, self); -} - -void -nm_netlink_monitor_detach (NMNetlinkMonitor *self) -{ - NMNetlinkMonitorPrivate *priv; - - g_return_if_fail (NM_IS_NETLINK_MONITOR (self)); - - priv = NM_NETLINK_MONITOR_GET_PRIVATE (self); - g_return_if_fail (priv->event_id > 0); - - g_source_remove (priv->event_id); - priv->event_id = 0; -} - -static int -get_subs (NMNetlinkMonitor *self, int group) -{ - NMNetlinkMonitorPrivate *priv = NM_NETLINK_MONITOR_GET_PRIVATE (self); - - return GPOINTER_TO_INT (g_hash_table_lookup (priv->subscriptions, - GINT_TO_POINTER (group))); -} - -static void -set_subs (NMNetlinkMonitor *self, int group, int new_subs) -{ - NMNetlinkMonitorPrivate *priv = NM_NETLINK_MONITOR_GET_PRIVATE (self); - - g_hash_table_insert (priv->subscriptions, - GINT_TO_POINTER (group), - GINT_TO_POINTER (new_subs)); -} - -gboolean -nm_netlink_monitor_subscribe (NMNetlinkMonitor *self, int group, GError **error) -{ - NMNetlinkMonitorPrivate *priv; - int subs, err; - - g_return_val_if_fail (NM_IS_NETLINK_MONITOR (self), FALSE); - - priv = NM_NETLINK_MONITOR_GET_PRIVATE (self); - - if (!priv->nlh_event) { - if (!nm_netlink_monitor_open_connection (self, error)) - return FALSE; - } - - subs = get_subs (self, group) + 1; - if (subs == 1) { - err = nl_socket_add_membership (priv->nlh_event, group); - if (err < 0) { - g_set_error (error, NM_NETLINK_MONITOR_ERROR, - NM_NETLINK_MONITOR_ERROR_NETLINK_JOIN_GROUP, - _("unable to join netlink group: %s"), - nl_geterror (err)); - return FALSE; - } - } - - /* Update # of subscriptions for this group */ - set_subs (self, group, subs); - - return TRUE; -} - -void -nm_netlink_monitor_unsubscribe (NMNetlinkMonitor *self, int group) -{ - NMNetlinkMonitorPrivate *priv; - int subs; - - g_return_if_fail (self != NULL); - g_return_if_fail (NM_IS_NETLINK_MONITOR (self)); - - priv = NM_NETLINK_MONITOR_GET_PRIVATE (self); - g_return_if_fail (priv->nlh_event != NULL); - - subs = get_subs (self, group) - 1; - if (subs == 0) - nl_socket_drop_membership (priv->nlh_event, group); - - /* Update # of subscriptions for this group */ - set_subs (self, group, subs); -} - -/***************************************************************/ - -gboolean -nm_netlink_monitor_request_ip6_info (NMNetlinkMonitor *self, GError **error) -{ - NMNetlinkMonitorPrivate *priv; - - g_return_val_if_fail (self != NULL, FALSE); - g_return_val_if_fail (NM_IS_NETLINK_MONITOR (self), FALSE); - - priv = NM_NETLINK_MONITOR_GET_PRIVATE (self); - - /* FIXME: nl_rtgen_request() gets the return value screwed up with - * libnl-1.1; revisit this and return a proper error when we port to - * a later libnl. - */ - nl_rtgen_request (priv->nlh_event, RTM_GETLINK, AF_INET6, NLM_F_DUMP); - - return TRUE; -} - -gboolean -nm_netlink_monitor_request_bridge_info (NMNetlinkMonitor *self, GError **error) -{ - NMNetlinkMonitorPrivate *priv; - - g_return_val_if_fail (self != NULL, FALSE); - g_return_val_if_fail (NM_IS_NETLINK_MONITOR (self), FALSE); - - priv = NM_NETLINK_MONITOR_GET_PRIVATE (self); - - /* FIXME: nl_rtgen_request() gets the return value screwed up with - * libnl-1.1; revisit this and return a proper error when we port to - * a later libnl. - */ - nl_rtgen_request (priv->nlh_event, RTM_GETLINK, AF_BRIDGE, NLM_F_DUMP); - - return TRUE; -} - -static gboolean -deferred_emit_carrier_state (gpointer user_data) -{ - NMNetlinkMonitor *self = NM_NETLINK_MONITOR (user_data); - NMNetlinkMonitorPrivate *priv = NM_NETLINK_MONITOR_GET_PRIVATE (self); - int err; - - priv->request_status_id = 0; - - /* Update the link cache with latest state, and if there are no errors - * emit the link states for all the interfaces in the cache. - */ - err = nl_cache_refill (priv->nlh_sync, priv->link_cache); - if (err < 0) - nm_log_err (LOGD_HW, "error updating link cache: %s", nl_geterror (err)); - else - nl_cache_foreach_filter (priv->link_cache, NULL, link_msg_handler, self); - - return FALSE; -} - -void -nm_netlink_monitor_request_status (NMNetlinkMonitor *self) -{ - NMNetlinkMonitorPrivate *priv; - - g_return_if_fail (NM_IS_NETLINK_MONITOR (self)); - - priv = NM_NETLINK_MONITOR_GET_PRIVATE (self); - - /* Schedule the carrier state emission */ - if (!priv->request_status_id) - priv->request_status_id = g_idle_add (deferred_emit_carrier_state, self); -} - -typedef struct { - NMNetlinkMonitor *self; - struct rtnl_link *filter; - GError *error; - guint32 flags; -} GetFlagsInfo; - -static void -get_flags_sync_cb (struct nl_object *obj, void *arg) -{ - GetFlagsInfo *info = arg; - - /* Ensure this cache item matches our filter */ - if (nl_object_match_filter (obj, OBJ_CAST (info->filter)) != 0) - info->flags = rtnl_link_get_flags ((struct rtnl_link *) obj); -} - -gboolean -nm_netlink_monitor_get_flags_sync (NMNetlinkMonitor *self, - guint32 ifindex, - guint32 *ifflags, - GError **error) -{ - NMNetlinkMonitorPrivate *priv; - GetFlagsInfo info; - struct rtnl_link *filter; - int err; - - g_return_val_if_fail (self != NULL, FALSE); - g_return_val_if_fail (NM_IS_NETLINK_MONITOR (self), FALSE); - g_return_val_if_fail (ifflags != NULL, FALSE); - - priv = NM_NETLINK_MONITOR_GET_PRIVATE (self); - - /* Update the link cache with the latest information */ - err = nl_cache_refill (priv->nlh_sync, priv->link_cache); - if (err < 0) { - g_set_error (error, - NM_NETLINK_MONITOR_ERROR, - NM_NETLINK_MONITOR_ERROR_LINK_CACHE_UPDATE, - _("error updating link cache: %s"), - nl_geterror (err)); - return FALSE; - } - - /* HACK: Apparently to get it working we have to refill the cache twice; - * otherwise some kernels (or maybe libnl?) only send a few of the - * interfaces in the refill request. - */ - if (nl_cache_refill (priv->nlh_sync, priv->link_cache)) { - g_set_error (error, - NM_NETLINK_MONITOR_ERROR, - NM_NETLINK_MONITOR_ERROR_LINK_CACHE_UPDATE, - _("error updating link cache: %s"), - nl_geterror (err)); - return FALSE; - } - - /* Set up the filter */ - filter = rtnl_link_alloc (); - if (!filter) { - g_set_error (error, - NM_NETLINK_MONITOR_ERROR, - NM_NETLINK_MONITOR_ERROR_BAD_ALLOC, - _("error processing netlink message: %s"), - nl_geterror (err)); - return FALSE; - } - rtnl_link_set_ifindex (filter, ifindex); - - memset (&info, 0, sizeof (info)); - info.self = self; - info.filter = filter; - info.error = NULL; - nl_cache_foreach_filter (priv->link_cache, NULL, get_flags_sync_cb, &info); - - rtnl_link_put (filter); - - if (info.error) { - if (error) - *error = info.error; - else - g_error_free (info.error); - return FALSE; - } else - *ifflags = info.flags; - - return TRUE; /* success */ -} - -/***************************************************************/ - -struct nl_sock * -nm_netlink_get_default_handle (void) -{ - NMNetlinkMonitor *self; - struct nl_sock *nlh; - - self = nm_netlink_monitor_get (); - nlh = NM_NETLINK_MONITOR_GET_PRIVATE (self)->nlh_sync; - g_object_unref (self); - - return nlh; -} - -int -nm_netlink_iface_to_index (const char *iface) -{ - NMNetlinkMonitor *self; - NMNetlinkMonitorPrivate *priv; - int idx; - - g_return_val_if_fail (iface != NULL, -1); - - self = nm_netlink_monitor_get (); - priv = NM_NETLINK_MONITOR_GET_PRIVATE (self); - - nl_cache_refill (priv->nlh_sync, priv->link_cache); - idx = rtnl_link_name2i (priv->link_cache, iface); - g_object_unref (self); - - return idx; -} - -/** - * nm_netlink_index_to_iface: - * @idx: kernel interface index - * - * Returns: the device name corresponding to the kernel interface index; caller - * owns returned value and must free it when it is no longer required - **/ -#define MAX_IFACE_LEN 33 -char * -nm_netlink_index_to_iface (int idx) -{ - NMNetlinkMonitor *self; - NMNetlinkMonitorPrivate *priv; - char *buf = NULL; - - g_return_val_if_fail (idx >= 0, NULL); - - self = nm_netlink_monitor_get (); - priv = NM_NETLINK_MONITOR_GET_PRIVATE (self); - - buf = g_malloc0 (MAX_IFACE_LEN); - g_assert (buf); - - nl_cache_refill (priv->nlh_sync, priv->link_cache); - if (!rtnl_link_i2name (priv->link_cache, idx, buf, MAX_IFACE_LEN - 1)) { - nm_log_warn (LOGD_HW, "(%d) failed to find interface name for index", idx); - g_free (buf); - buf = NULL; - } - - g_object_unref (self); - return buf; -} - -struct rtnl_link * -nm_netlink_index_to_rtnl_link (int idx) -{ - NMNetlinkMonitor *self; - NMNetlinkMonitorPrivate *priv; - struct rtnl_link *ret = NULL; - - if (idx <= 0) - return NULL; - - self = nm_netlink_monitor_get (); - priv = NM_NETLINK_MONITOR_GET_PRIVATE (self); - - nl_cache_refill (priv->nlh_sync, priv->link_cache); - ret = rtnl_link_get (priv->link_cache, idx); - g_object_unref (self); - - return ret; -} - -/***************************************************************/ - -NMNetlinkMonitor * -nm_netlink_monitor_get (void) -{ - static NMNetlinkMonitor *singleton = NULL; - GError *error = NULL; - - if (!singleton) { - singleton = (NMNetlinkMonitor *) g_object_new (NM_TYPE_NETLINK_MONITOR, NULL); - g_return_val_if_fail (singleton != NULL, NULL); - - if (nm_netlink_monitor_open_connection (singleton, &error)) { - nm_netlink_monitor_attach (singleton); - /* Request initial status of cards */ - nm_netlink_monitor_request_status (singleton); - } else { - nm_log_warn (LOGD_HW, "Failed to connect to netlink: (%d) %s", - error ? error->code : 0, - (error && error->message) ? error->message : "(unknown)"); - g_clear_error (&error); - - g_object_unref (singleton); - singleton = NULL; - } - } else - g_object_ref (singleton); - - return singleton; -} - -static void -nm_netlink_monitor_init (NMNetlinkMonitor *self) -{ - NMNetlinkMonitorPrivate *priv = NM_NETLINK_MONITOR_GET_PRIVATE (self); - - priv->subscriptions = g_hash_table_new (g_direct_hash, g_direct_equal); -} - -static void -finalize (GObject *object) -{ - NMNetlinkMonitorPrivate *priv = NM_NETLINK_MONITOR_GET_PRIVATE (object); - - if (priv->request_status_id) - g_source_remove (priv->request_status_id); - - if (priv->io_channel) - nm_netlink_monitor_close_connection (NM_NETLINK_MONITOR (object)); - - if (priv->link_cache) { - nl_cache_free (priv->link_cache); - priv->link_cache = NULL; - } - - if (priv->nlh_event) { - nl_socket_free (priv->nlh_event); - priv->nlh_event = NULL; - } - - if (priv->nlh_sync) { - nl_socket_free (priv->nlh_sync); - priv->nlh_sync = NULL; - } - - g_hash_table_destroy (priv->subscriptions); - - G_OBJECT_CLASS (nm_netlink_monitor_parent_class)->finalize (object); -} - -static void -nm_netlink_monitor_class_init (NMNetlinkMonitorClass *monitor_class) -{ - GObjectClass *object_class = G_OBJECT_CLASS (monitor_class); - - g_type_class_add_private (monitor_class, sizeof (NMNetlinkMonitorPrivate)); - - /* Virtual methods */ - object_class->finalize = finalize; - - /* Signals */ - signals[NOTIFICATION] = - g_signal_new ("notification", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMNetlinkMonitorClass, notification), - NULL, NULL, g_cclosure_marshal_VOID__POINTER, - G_TYPE_NONE, 1, G_TYPE_POINTER); - - signals[CARRIER_ON] = - g_signal_new ("carrier-on", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMNetlinkMonitorClass, carrier_on), - NULL, NULL, g_cclosure_marshal_VOID__INT, - G_TYPE_NONE, 1, G_TYPE_INT); - - signals[CARRIER_OFF] = - g_signal_new ("carrier-off", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMNetlinkMonitorClass, carrier_off), - NULL, NULL, g_cclosure_marshal_VOID__INT, - G_TYPE_NONE, 1, G_TYPE_INT); -} - -GQuark -nm_netlink_monitor_error_quark (void) -{ - static GQuark error_quark = 0; - - if (G_UNLIKELY (error_quark == 0)) - error_quark = g_quark_from_static_string ("nm-netlink-monitor-error-quark"); - return error_quark; -} - diff --git a/src/nm-netlink-monitor.h b/src/nm-netlink-monitor.h deleted file mode 100644 index b9468fdc..00000000 --- a/src/nm-netlink-monitor.h +++ /dev/null @@ -1,102 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2005 - 2010 Red Hat, Inc. - * Copyright (C) 2005 - 2008 Novell, Inc. - * Copyright (C) 2005 Ray Strode - */ - -#ifndef NM_NETLINK_MONITOR_H -#define NM_NETLINK_MONITOR_H - -#include -#include -#include - -#define NM_TYPE_NETLINK_MONITOR (nm_netlink_monitor_get_type ()) -#define NM_NETLINK_MONITOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_NETLINK_MONITOR, NMNetlinkMonitor)) -#define NM_NETLINK_MONITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_NETLINK_MONITOR, NMNetlinkMonitorClass)) -#define NM_IS_NETLINK_MONITOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_NETLINK_MONITOR)) -#define NM_IS_NETLINK_MONITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_NETLINK_MONITOR)) -#define NM_NETLINK_MONITOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_NETLINK_MONITOR, NMNetlinkMonitorClass)) - -typedef enum { - NM_NETLINK_MONITOR_ERROR_GENERIC = 0, - NM_NETLINK_MONITOR_ERROR_NETLINK_ALLOC_HANDLE, - NM_NETLINK_MONITOR_ERROR_NETLINK_CONNECT, - NM_NETLINK_MONITOR_ERROR_NETLINK_JOIN_GROUP, - NM_NETLINK_MONITOR_ERROR_NETLINK_ALLOC_LINK_CACHE, - NM_NETLINK_MONITOR_ERROR_PROCESSING_MESSAGE, - NM_NETLINK_MONITOR_ERROR_BAD_ALLOC, - NM_NETLINK_MONITOR_ERROR_WAITING_FOR_SOCKET_DATA, - NM_NETLINK_MONITOR_ERROR_LINK_CACHE_UPDATE -} NMNetlinkMonitorError; - -typedef struct { - GObject parent; -} NMNetlinkMonitor; - -typedef struct { - GObjectClass parent_class; - - /* Signals */ - void (*notification) (NMNetlinkMonitor *monitor, struct nl_msg *msg); - void (*carrier_on) (NMNetlinkMonitor *monitor, int index); - void (*carrier_off) (NMNetlinkMonitor *monitor, int index); -} NMNetlinkMonitorClass; - - -#define NM_NETLINK_MONITOR_ERROR (nm_netlink_monitor_error_quark ()) -GType nm_netlink_monitor_get_type (void) G_GNUC_CONST; -GQuark nm_netlink_monitor_error_quark (void) G_GNUC_CONST; - -NMNetlinkMonitor *nm_netlink_monitor_get (void); - -gboolean nm_netlink_monitor_open_connection (NMNetlinkMonitor *monitor, - GError **error); -void nm_netlink_monitor_close_connection (NMNetlinkMonitor *monitor); -void nm_netlink_monitor_attach (NMNetlinkMonitor *monitor); -void nm_netlink_monitor_detach (NMNetlinkMonitor *monitor); - -gboolean nm_netlink_monitor_subscribe (NMNetlinkMonitor *monitor, - int group, - GError **error); -void nm_netlink_monitor_unsubscribe (NMNetlinkMonitor *monitor, - int group); - -gboolean nm_netlink_monitor_request_ip6_info (NMNetlinkMonitor *monitor, - GError **error); - -gboolean nm_netlink_monitor_request_bridge_info (NMNetlinkMonitor *monitor, - GError **error); - -void nm_netlink_monitor_request_status (NMNetlinkMonitor *monitor); - -gboolean nm_netlink_monitor_get_flags_sync (NMNetlinkMonitor *monitor, - guint32 ifindex, - guint32 *ifflags, - GError **error); - -#include "nm-netlink-compat.h" - -/* Generic utility functions */ -int nm_netlink_iface_to_index (const char *iface); -char * nm_netlink_index_to_iface (int idx); -struct rtnl_link *nm_netlink_index_to_rtnl_link (int idx); -struct nl_sock * nm_netlink_get_default_handle (void); - -#endif /* NM_NETLINK_MONITOR_H */ diff --git a/src/nm-netlink-utils.c b/src/nm-netlink-utils.c deleted file mode 100644 index 0ec53897..00000000 --- a/src/nm-netlink-utils.c +++ /dev/null @@ -1,465 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2011 Red Hat, Inc. - */ - -#include "logging/nm-logging.h" -#include "nm-netlink-utils.h" -#include "nm-netlink-monitor.h" -#include "nm-netlink-compat.h" - -#include -#include -#include - -typedef struct { - int ifindex; - int family; - void *addr; - int addrlen; - int prefix; - gboolean found; -} FindAddrInfo; - -static void -find_one_address (struct nl_object *object, void *user_data) -{ - FindAddrInfo *info = user_data; - struct rtnl_addr *addr = (struct rtnl_addr *) object; - struct nl_addr *local; - void *binaddr; - - if (info->found) - return; - - if (rtnl_addr_get_ifindex (addr) != info->ifindex) - return; - if (rtnl_addr_get_family (addr) != info->family) - return; - - if (rtnl_addr_get_prefixlen (addr) != info->prefix) - return; - - local = rtnl_addr_get_local (addr); - if (nl_addr_get_family (local) != info->family) - return; - if (nl_addr_get_len (local) != info->addrlen) - return; - binaddr = nl_addr_get_binary_addr (local); - if (binaddr) { - if (memcmp (binaddr, info->addr, info->addrlen) == 0) - info->found = TRUE; /* Yay, found it */ - } -} - -/** - * nm_netlink_find_address: - * @ifindex: interface index - * @family: address family, either AF_INET or AF_INET6 - * @addr: binary address, either struct in_addr* or struct in6_addr* - * @prefix: prefix length - * - * Searches for a matching address on the given interface. - * - * Returns: %TRUE if the given address was found on the interface, %FALSE if it - * was not found or an error occurred. - **/ -gboolean -nm_netlink_find_address (int ifindex, - int family, - void *addr, /* struct in_addr or struct in6_addr */ - int prefix) -{ - struct nl_sock *nlh = NULL; - struct nl_cache *cache = NULL; - FindAddrInfo info; - - g_return_val_if_fail (ifindex > 0, FALSE); - g_return_val_if_fail (family == AF_INET || family == AF_INET6, FALSE); - g_return_val_if_fail (addr != NULL, FALSE); - g_return_val_if_fail (prefix >= 0, FALSE); - - memset (&info, 0, sizeof (info)); - info.ifindex = ifindex; - info.family = family; - info.prefix = prefix; - info.addr = addr; - if (family == AF_INET) - info.addrlen = sizeof (struct in_addr); - else if (family == AF_INET6) - info.addrlen = sizeof (struct in6_addr); - else - g_assert_not_reached (); - - nlh = nm_netlink_get_default_handle (); - if (nlh) { - rtnl_addr_alloc_cache(nlh, &cache); - if (cache) { - nl_cache_mngt_provide (cache); - nl_cache_foreach (cache, find_one_address, &info); - nl_cache_free (cache); - } - } - return info.found; -} - -struct rtnl_route * -nm_netlink_route_new (int ifindex, - int family, - int mss, - ...) -{ - va_list var_args; - struct rtnl_route *route; - NmNlProp prop = NMNL_PROP_INVALID; - int value; - - route = rtnl_route_alloc (); - g_return_val_if_fail (route != NULL, NULL); - - if (ifindex > 0) - rtnl_route_set_oif (route, ifindex); - if (family != AF_UNSPEC) - rtnl_route_set_family (route, family); - if (mss > 0) - rtnl_route_set_metric (route, RTAX_ADVMSS, mss); - - va_start (var_args, mss); - prop = va_arg (var_args, NmNlProp); - while (prop != NMNL_PROP_INVALID) { - value = va_arg (var_args, int); - - if (prop == NMNL_PROP_PROT && value != RTPROT_UNSPEC) - rtnl_route_set_protocol (route, value); - else if (prop == NMNL_PROP_TABLE && value != RT_TABLE_UNSPEC) - rtnl_route_set_table (route, value); - else if (prop == NMNL_PROP_SCOPE && value != RT_SCOPE_NOWHERE) - rtnl_route_set_scope (route, value); - else if (prop == NMNL_PROP_PRIO && value > 0) - rtnl_route_set_priority (route, value); - - prop = va_arg (var_args, NmNlProp); - } - va_end (var_args); - - return route; -} - -/** - * _route_add: - * @route: the route to add - * @family: address family, either %AF_INET or %AF_INET6 - * @dest: the route destination address, either a struct in_addr or a struct - * in6_addr depending on @family - * @dest_prefix: the CIDR prefix of @dest - * @gateway: the gateway through which to reach @dest, if any; given as a - * struct in_addr or struct in6_addr depending on @family - * @flags: flags to pass to rtnl_route_add(), eg %NLM_F_REPLACE - * - * Returns: zero if succeeded or the netlink error otherwise. - **/ -static int -_route_add (struct rtnl_route *route, - int family, - const void *dest, /* in_addr or in6_addr */ - int dest_prefix, - const void *gateway, /* in_addr or in6_addr */ - int flags) -{ - struct nl_sock *sk; - struct nl_addr *dest_addr, *gw_addr; - void *tmp_addr; - int addrlen, err, log; - - if (family == AF_INET) { - addrlen = sizeof (struct in_addr); - log = LOGD_IP4; - } else if (family == AF_INET6) { - addrlen = sizeof (struct in6_addr); - log = LOGD_IP6; - } else - g_assert_not_reached (); - - sk = nm_netlink_get_default_handle (); - - /* Build up the destination address */ - if (dest) { - /* Copy to preserve const */ - tmp_addr = g_malloc0 (addrlen); - memcpy (tmp_addr, dest, addrlen); - - dest_addr = nl_addr_build (family, tmp_addr, addrlen); - g_free (tmp_addr); - - g_return_val_if_fail (dest_addr != NULL, -NLE_INVAL); - nl_addr_set_prefixlen (dest_addr, dest_prefix); - - rtnl_route_set_dst (route, dest_addr); - nl_addr_put (dest_addr); - } - - /* Build up the gateway address */ - if (gateway) { - tmp_addr = g_malloc0 (addrlen); - memcpy (tmp_addr, gateway, addrlen); - - gw_addr = nl_addr_build (family, tmp_addr, addrlen); - g_free (tmp_addr); - - if (gw_addr) { - nl_addr_set_prefixlen (gw_addr, 0); - rtnl_route_set_gateway (route, gw_addr); - rtnl_route_set_scope (route, RT_SCOPE_UNIVERSE); - nl_addr_put (gw_addr); - } else - nm_log_err (LOGD_DEVICE | log, "Invalid gateway"); - } - - err = rtnl_route_add (sk, route, flags); - - /* LIBNL Bug: Aliased ESRCH */ - if (err == -NLE_FAILURE) - err = -NLE_OBJ_NOTFOUND; - - return err; -} - -/** - * nm_netlink_route4_add: - * @route: the route to add - * @dest: the route destination address in network byte order - * @dest_prefix: the CIDR prefix of @dest - * @gateway: the gateway through which to reach @dest, if any, in network byte order - * @flags: flags to pass to rtnl_route_add(), eg %NLM_F_REPLACE - * - * Adds an IPv4 route with the given parameters. - * - * Returns: zero if succeeded or the netlink error otherwise. - **/ -int -nm_netlink_route4_add (struct rtnl_route *route, - guint32 *dst, - int prefix, - guint32 *gw, - int flags) -{ - return _route_add (route, AF_INET, dst, prefix, gw, flags); -} - -/** - * nm_netlink_route6_add: - * @route: the route to add - * @dest: the route destination address - * @dest_prefix: the CIDR prefix of @dest - * @gateway: the gateway through which to reach @dest, if any - * @flags: flags to pass to rtnl_route_add(), eg %NLM_F_REPLACE - * - * Adds an IPv6 route with the given parameters. - * - * Returns: zero if succeeded or the netlink error otherwise. - **/ -int -nm_netlink_route6_add (struct rtnl_route *route, - const struct in6_addr *dst, - int prefix, - const struct in6_addr *gw, - int flags) -{ - return _route_add (route, AF_INET6, dst, prefix, gw, flags); -} - -/** - * nm_netlink_route_delete: - * @route: the route to delete - * - * Returns: %TRUE if the request was successful, %FALSE if it failed - **/ -gboolean -nm_netlink_route_delete (struct rtnl_route *route) -{ - struct nl_sock *nlh; - int err = 0; - - g_return_val_if_fail (route != NULL, FALSE); - - nlh = nm_netlink_get_default_handle (); - err = rtnl_route_delete (nlh, route, 0); - - if (err) - nm_log_dbg (LOGD_IP4 | LOGD_IP6, "%s (%d)", nl_geterror(err), err); - - /* Workaround libnl BUG: ESRCH is aliased to generic NLE_FAILURE - * See: http://git.kernel.org/?p=libs/netlink/libnl.git;a=commit;h=7e9d5f */ - if (err == -NLE_FAILURE) - err = -NLE_OBJ_NOTFOUND; - - return (err && (err != -NLE_OBJ_NOTFOUND) && (err != -NLE_RANGE) ) ? FALSE : TRUE; -} - - -static void -dump_route (struct rtnl_route *route) -{ - char buf6[INET6_ADDRSTRLEN]; - char buf4[INET_ADDRSTRLEN]; - struct nl_addr *nl; - struct in6_addr *addr6 = NULL; - struct in_addr *addr4 = NULL; - int prefixlen = 0; - const char *sf = "UNSPEC"; - int family = rtnl_route_get_family (route); - guint32 log_level = LOGD_IP4 | LOGD_IP6; - - memset (buf6, 0, sizeof (buf6)); - memset (buf4, 0, sizeof (buf4)); - nl = rtnl_route_get_dst (route); - if (nl) { - if (nl_addr_get_family (nl) == AF_INET) { - addr4 = nl_addr_get_binary_addr (nl); - if (addr4) - inet_ntop (AF_INET, addr4, &buf4[0], sizeof (buf4)); - } else if (nl_addr_get_family (nl) == AF_INET6) { - addr6 = nl_addr_get_binary_addr (nl); - if (addr6) - inet_ntop (AF_INET6, addr6, &buf6[0], sizeof (buf6)); - } - prefixlen = nl_addr_get_prefixlen (nl); - } - - if (family == AF_INET) { - sf = "INET"; - log_level = LOGD_IP4; - } else if (family == AF_INET6) { - sf = "INET6"; - log_level = LOGD_IP6; - } - - nm_log_dbg (log_level, " route idx %d family %s (%d) addr %s/%d", - rtnl_route_get_oif (route), - sf, family, - strlen (buf4) ? buf4 : (strlen (buf6) ? buf6 : ""), - prefixlen); -} - - -typedef struct { - int ifindex; - int family; - int scope; - gboolean ignore_inet6_ll_mc; - char *iface; - NlRouteForeachFunc callback; - gpointer user_data; - struct rtnl_route *out_route; -} ForeachRouteInfo; - -static void -foreach_route_cb (struct nl_object *object, void *user_data) -{ - ForeachRouteInfo *info = user_data; - struct rtnl_route *route = (struct rtnl_route *) object; - struct nl_addr *dst; - - if (info->out_route) - return; - - if (nm_logging_level_enabled (LOGL_DEBUG)) - dump_route (route); - - if ( info->ifindex > 0 - && rtnl_route_get_oif (route) != info->ifindex) - return; - - if ( info->scope != RT_SCOPE_UNIVERSE - && rtnl_route_get_scope (route) != info->scope) - return; - - if ( info->family != AF_UNSPEC - && rtnl_route_get_family (route) != info->family) - return; - - dst = rtnl_route_get_dst (route); - - /* Check for IPv6 LL and MC routes that might need to be ignored */ - if ( (info->family == AF_INET6 || info->family == AF_UNSPEC) - && (rtnl_route_get_family (route) == AF_INET6)) { - struct in6_addr *addr = NULL; - - if (dst) - addr = nl_addr_get_binary_addr (dst); - if (addr) { - if ( IN6_IS_ADDR_LINKLOCAL (addr) - || IN6_IS_ADDR_MC_LINKLOCAL (addr) - || (IN6_IS_ADDR_MULTICAST (addr) && (nl_addr_get_prefixlen (dst) == 8))) - return; - } - } - - info->out_route = info->callback (route, dst, info->iface, info->user_data); - if (info->out_route) { - /* Ref the route so it sticks around after the cache is cleared */ - rtnl_route_get (info->out_route); - } -} - -/** - * nm_netlink_foreach_route: - * @ifindex: the interface index to filter routes for - * @family: the address family to filter routes for - * @scope: route scope, eg RT_SCOPE_LINK - * @ignore_inet6_ll_mc: if %TRUE ignore IPv6 link-local and multi-cast routes - * @callback: function called when a route matches the filter - * @user_data: data passed to @callback - * - * Filters each route in the routing table against the given @ifindex and - * @family (if given) and calls @callback for each matching route. - * - * Returns: a route if @callback returned one; the caller must dispose of the - * route using rtnl_route_put() when it is no longer required. - **/ -struct rtnl_route * -nm_netlink_foreach_route (int ifindex, - int family, - int scope, - gboolean ignore_inet6_ll_mc, - NlRouteForeachFunc callback, - gpointer user_data) -{ - struct nl_cache *cache; - ForeachRouteInfo info; - - memset (&info, 0, sizeof (info)); - info.ifindex = ifindex; - info.family = family; - info.scope = scope; - info.ignore_inet6_ll_mc = ignore_inet6_ll_mc; - info.callback = callback; - info.user_data = user_data; - info.iface = nm_netlink_index_to_iface (ifindex); - - rtnl_route_alloc_cache (nm_netlink_get_default_handle (), family, 0, &cache); - g_warn_if_fail (cache != NULL); - if (cache) { - nl_cache_foreach (cache, foreach_route_cb, &info); - nl_cache_free (cache); - } - g_free (info.iface); - return info.out_route; -} - - diff --git a/src/nm-netlink-utils.h b/src/nm-netlink-utils.h deleted file mode 100644 index 1f7c6796..00000000 --- a/src/nm-netlink-utils.h +++ /dev/null @@ -1,83 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2011 Red Hat, Inc. - */ - -#ifndef NM_NETLINK_UTILS_H -#define NM_NETLINK_UTILS_H - -#include - -gboolean nm_netlink_find_address (int ifindex, - int family, - void *addr, /* struct in_addr or struct in6_addr */ - int prefix_); - -typedef enum { - NMNL_PROP_INVALID = 0, - NMNL_PROP_PROT, - NMNL_PROP_SCOPE, - NMNL_PROP_TABLE, - NMNL_PROP_PRIO, -} NmNlProp; - -struct rtnl_route * nm_netlink_route_new (int ifindex, - int family, - int mss, - ...) __attribute__((__sentinel__)); - -int nm_netlink_route4_add (struct rtnl_route *route, - guint32 *dst, - int prefix, - guint32 *gw, - int flags); - -int nm_netlink_route6_add (struct rtnl_route *route, - const struct in6_addr *dst, - int prefix, - const struct in6_addr *gw, - int flags); - -gboolean nm_netlink_route_delete (struct rtnl_route *route); - -/** - * NlRouteForeachFunc: - * @route: the route being processed - * @dst: the route's destination address - * @iface: the interface name of the index passed to nm_netlink_foreach_route() - * @in_family: the address family passed to nm_netlink_foreach_route() - * @user_data: the user data pointer passed to nm_netlink_foreach_route() - * - * Returns: a route to return to the caller of nm_netlink_foreach_route() which - * terminates routing table iteration, or NULL to continue iterating the - * routing table. - **/ -typedef struct rtnl_route * (*NlRouteForeachFunc) (struct rtnl_route *route, - struct nl_addr *dst, - const char *iface, - gpointer user_data); - -struct rtnl_route * nm_netlink_foreach_route (int ifindex, - int family, - int scope, - gboolean ignore_inet6_ll_mc, - NlRouteForeachFunc callback, - gpointer user_data); - -#endif /* NM_NETLINK_UTILS_H */ - diff --git a/src/nm-policy-hostname.c b/src/nm-policy-hostname.c deleted file mode 100644 index 0ea16158..00000000 --- a/src/nm-policy-hostname.c +++ /dev/null @@ -1,264 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2004 - 2012 Red Hat, Inc. - * Copyright (C) 2007 - 2008 Novell, Inc. - */ - -#include -#include -#include -#include -#include - -#include - -#include "nm-logging.h" -#include "nm-policy-hostname.h" - -/************************************************************************/ - -struct HostnameThread { - GThread *thread; - -#if GLIB_CHECK_VERSION (2,31,0) - GMutex lock; -#else - GMutex *lock; -#endif - gboolean dead; - int ret; - - struct sockaddr_in addr4; - struct sockaddr_in6 addr6; - struct sockaddr *addr; - size_t addr_size; - char hostname[NI_MAXHOST + 1]; - - HostnameThreadCallback callback; - gpointer user_data; -}; - -/* - * GMutex API has changed: - * http://developer.gnome.org/glib/2.31/glib-Threads.html#GMutex - * http://developer.gnome.org/glib/2.31/glib-Deprecated-Thread-APIs.html -*/ -#if GLIB_CHECK_VERSION (2,31,0) -#define X_MUTEX_LOCK(mutex) g_mutex_lock (&(mutex)) -#define X_MUTEX_UNLOCK(mutex) g_mutex_unlock (&(mutex)) -#define X_MUTEX_INIT(mutex) g_mutex_init (&(mutex)) -#define X_MUTEX_CLEAR(mutex) g_mutex_clear (&(mutex)) -#define X_THREAD_CREATE(func,data) g_thread_try_new ("hostname-thread", func, data, NULL); -#else -#define X_MUTEX_LOCK(mutex) g_mutex_lock (mutex) -#define X_MUTEX_UNLOCK(mutex) g_mutex_unlock (mutex) -#define X_MUTEX_INIT(mutex) mutex = g_mutex_new () -#define X_MUTEX_CLEAR(mutex) g_mutex_free (mutex) -#define X_THREAD_CREATE(func,data) g_thread_create (func, data, FALSE, NULL); -#endif - -static gboolean -hostname_thread_run_cb (gpointer user_data) -{ - HostnameThread *ht = (HostnameThread *) user_data; - const char *hostname = NULL; - - if (strlen (ht->hostname) && strcmp (ht->hostname, ".")) - hostname = ht->hostname; - - nm_log_dbg (LOGD_DNS, "(%p) calling address reverse-lookup result handler", ht); - (*ht->callback) (ht, ht->ret, hostname, ht->user_data); - return FALSE; -} - -static gpointer -hostname_thread_worker (gpointer data) -{ - HostnameThread *ht = (HostnameThread *) data; - int i; - - nm_log_dbg (LOGD_DNS, "(%p) starting address reverse-lookup", ht); - - X_MUTEX_LOCK (ht->lock); - if (ht->dead) { - X_MUTEX_UNLOCK (ht->lock); - return (gpointer) NULL; - } - X_MUTEX_UNLOCK (ht->lock); - - ht->ret = getnameinfo (ht->addr, ht->addr_size, ht->hostname, NI_MAXHOST, NULL, 0, NI_NAMEREQD); - if (ht->ret == 0) { - nm_log_dbg (LOGD_DNS, "(%p) address reverse-lookup returned hostname '%s'", - ht, ht->hostname); - for (i = 0; i < strlen (ht->hostname); i++) - ht->hostname[i] = g_ascii_tolower (ht->hostname[i]); - } else { - nm_log_dbg (LOGD_DNS, "(%p) address reverse-lookup failed: (%d) %s", - ht, ht->ret, gai_strerror (ht->ret)); - } - - /* Don't track the idle handler ID because by the time the g_idle_add() - * returns the ID, the handler may already have run and freed the - * HostnameThread. - */ - nm_log_dbg (LOGD_DNS, "(%p) scheduling address reverse-lookup result handler", ht); - g_idle_add (hostname_thread_run_cb, ht); - return (gpointer) TRUE; -} - -void -hostname_thread_free (HostnameThread *ht) -{ - g_return_if_fail (ht != NULL); - - nm_log_dbg (LOGD_DNS, "(%p) freeing reverse-lookup thread", ht); - - X_MUTEX_CLEAR (ht->lock); - memset (ht, 0, sizeof (HostnameThread)); - g_free (ht); -} - -HostnameThread * -hostname4_thread_new (guint32 ip4_addr, - HostnameThreadCallback callback, - gpointer user_data) -{ - HostnameThread *ht; - char buf[INET_ADDRSTRLEN + 1]; - - ht = g_malloc0 (sizeof (HostnameThread)); - g_assert (ht); - - X_MUTEX_INIT (ht->lock); - ht->callback = callback; - ht->user_data = user_data; - - ht->addr4.sin_family = AF_INET; - ht->addr4.sin_addr.s_addr = ip4_addr; - ht->addr = (struct sockaddr *) &ht->addr4; - ht->addr_size = sizeof (ht->addr4); - - ht->thread = X_THREAD_CREATE (hostname_thread_worker, ht); - if (!ht->thread) { - hostname_thread_free (ht); - return NULL; - } - - if (!inet_ntop (AF_INET, &ht->addr4.sin_addr, buf, sizeof (buf))) - strcpy (buf, "(unknown)"); - - nm_log_dbg (LOGD_DNS, "(%p) started IPv4 reverse-lookup thread for address '%s'", - ht, buf); - - return ht; -} - -HostnameThread * -hostname6_thread_new (const struct in6_addr *ip6_addr, - HostnameThreadCallback callback, - gpointer user_data) -{ - HostnameThread *ht; - char buf[INET6_ADDRSTRLEN + 1]; - - ht = g_malloc0 (sizeof (HostnameThread)); - g_assert (ht); - - X_MUTEX_INIT (ht->lock); - ht->callback = callback; - ht->user_data = user_data; - - ht->addr6.sin6_family = AF_INET6; - ht->addr6.sin6_addr = *ip6_addr; - ht->addr = (struct sockaddr *) &ht->addr6; - ht->addr_size = sizeof (ht->addr6); - - ht->thread = X_THREAD_CREATE (hostname_thread_worker, ht); - if (!ht->thread) { - hostname_thread_free (ht); - return NULL; - } - - if (!inet_ntop (AF_INET, ip6_addr, buf, sizeof (buf))) - strcpy (buf, "(unknown)"); - - nm_log_dbg (LOGD_DNS, "(%p) started IPv6 reverse-lookup thread for address '%s'", - ht, buf); - - return ht; -} - -void -hostname_thread_kill (HostnameThread *ht) -{ - g_return_if_fail (ht != NULL); - - nm_log_dbg (LOGD_DNS, "(%p) stopping reverse-lookup thread", ht); - - X_MUTEX_LOCK (ht->lock); - ht->dead = TRUE; - X_MUTEX_UNLOCK (ht->lock); -} - -gboolean -hostname_thread_is_dead (HostnameThread *ht) -{ - g_return_val_if_fail (ht != NULL, TRUE); - - return ht->dead; -} - -/************************************************************************/ - -#define FALLBACK_HOSTNAME4 "localhost.localdomain" - -gboolean -nm_policy_set_system_hostname (const char *new_hostname, const char *msg) -{ - char old_hostname[HOST_NAME_MAX + 1]; - const char *name; - int ret; - - if (new_hostname) - g_warn_if_fail (strlen (new_hostname)); - - old_hostname[HOST_NAME_MAX] = '\0'; - errno = 0; - ret = gethostname (old_hostname, HOST_NAME_MAX); - if (ret != 0) { - nm_log_warn (LOGD_DNS, "couldn't get the system hostname: (%d) %s", - errno, strerror (errno)); - } else { - /* Don't set the hostname if it isn't actually changing */ - if ( (new_hostname && !strcmp (old_hostname, new_hostname)) - || (!new_hostname && !strcmp (old_hostname, FALLBACK_HOSTNAME4))) - return FALSE; - } - - name = (new_hostname && strlen (new_hostname)) ? new_hostname : FALLBACK_HOSTNAME4; - - nm_log_info (LOGD_DNS, "Setting system hostname to '%s' (%s)", name, msg); - ret = sethostname (name, strlen (name)); - if (ret != 0) { - nm_log_warn (LOGD_DNS, "couldn't set the system hostname to '%s': (%d) %s", - name, errno, strerror (errno)); - } - - return (ret == 0); -} - diff --git a/src/nm-policy-hostname.h b/src/nm-policy-hostname.h deleted file mode 100644 index e76713f1..00000000 --- a/src/nm-policy-hostname.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2004 - 2010 Red Hat, Inc. - * Copyright (C) 2007 - 2008 Novell, Inc. - */ - -#ifndef NM_POLICY_HOSTNAME_H -#define NM_POLICY_HOSTNAME_H - -#include - -gboolean nm_policy_set_system_hostname (const char *new_hostname, const char *msg); - - -typedef struct HostnameThread HostnameThread; - -typedef void (*HostnameThreadCallback) (HostnameThread *ht, - int error, - const char *hostname, - gpointer user_data); - -HostnameThread * hostname4_thread_new (guint32 ip4_addr, - HostnameThreadCallback callback, - gpointer user_data); - -HostnameThread * hostname6_thread_new (const struct in6_addr *ip6_addr, - HostnameThreadCallback callback, - gpointer user_data); - -void hostname_thread_free (HostnameThread *ht); - -gboolean hostname_thread_is_dead (HostnameThread *ht); - -void hostname_thread_kill (HostnameThread *ht); - -#endif /* NM_POLICY_HOSTNAME_H */ diff --git a/src/nm-policy-hosts.c b/src/nm-policy-hosts.c deleted file mode 100644 index 3f3fb35c..00000000 --- a/src/nm-policy-hosts.c +++ /dev/null @@ -1,95 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2004 - 2010 Red Hat, Inc. - */ - -#include -#include - -#include "nm-policy-hosts.h" -#include "nm-logging.h" - -#define ADDED_TAG "# Added by NetworkManager" - -GString * -nm_policy_get_etc_hosts (const char *contents, gsize contents_len) -{ - char **lines = NULL, **iter; - GString *new_contents = NULL; - - if (contents_len == 0 || !strstr (contents, ADDED_TAG)) - return NULL; - - new_contents = g_string_sized_new (contents_len); - - /* Remove "# Added ..." lines */ - lines = g_strsplit_set (contents, "\n\r", -1); - for (iter = lines; iter && *iter; iter++) { - if (!strstr (*iter, ADDED_TAG)) { - g_string_append (new_contents, *iter); - g_string_append_c (new_contents, '\n'); - } - } - g_strfreev (lines); - - /* Remove last blank line at end of file, if one exists; this is - * an artifact of how g_strsplit_set() works. - */ - if ( (new_contents->len > 2) - && (new_contents->str[new_contents->len - 1] == '\n')) - g_string_truncate (new_contents, new_contents->len - 1); - - return new_contents; -} - -/* remove any leftover "# Added by NetworkManager" lines */ -void -nm_policy_hosts_clean_etc_hosts (void) -{ - char *contents = NULL; - gsize contents_len = 0; - GError *error = NULL; - GString *new; - - if (!g_file_get_contents (SYSCONFDIR "/hosts", &contents, &contents_len, &error)) { - nm_log_dbg (LOGD_DNS, "couldn't read " SYSCONFDIR "/hosts: (%d) %s", - error ? error->code : 0, - (error && error->message) ? error->message : "(unknown)"); - g_clear_error (&error); - return; - } - - new = nm_policy_get_etc_hosts (contents, contents_len); - g_free (contents); - - if (new && new->len) { - nm_log_dbg (LOGD_DNS, "Cleaning leftovers from /etc/hosts"); - - g_clear_error (&error); - if (!g_file_set_contents (SYSCONFDIR "/hosts", new->str, -1, &error)) { - nm_log_dbg (LOGD_DNS, "couldn't update " SYSCONFDIR "/hosts: (%d) %s", - error ? error->code : 0, - (error && error->message) ? error->message : "(unknown)"); - g_clear_error (&error); - } - } - - if (new) - g_string_free (new, TRUE); -} - diff --git a/src/nm-policy-hosts.h b/src/nm-policy-hosts.h deleted file mode 100644 index 9f4bf9a9..00000000 --- a/src/nm-policy-hosts.h +++ /dev/null @@ -1,32 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2004 - 2010 Red Hat, Inc. - */ - -#ifndef NM_POLICY_HOSTS_H -#define NM_POLICT_HOSTS_H - -#include - -void nm_policy_hosts_clean_etc_hosts (void); - -/* Only for testcases; don't use outside of nm-policy-hosts.c */ -GString *nm_policy_get_etc_hosts (const char *contents, gsize contents_len); - -#endif /* NM_POLICY_HOSTS_H */ - diff --git a/src/nm-policy.c b/src/nm-policy.c index f95caf93..d46aca04 100644 --- a/src/nm-policy.c +++ b/src/nm-policy.c @@ -25,23 +25,24 @@ #include #include +#include + #include "nm-policy.h" #include "NetworkManagerUtils.h" -#include "nm-wifi-ap.h" #include "nm-activation-request.h" #include "nm-logging.h" #include "nm-device.h" #include "nm-dbus-manager.h" #include "nm-setting-ip4-config.h" #include "nm-setting-connection.h" -#include "nm-system.h" +#include "nm-platform.h" #include "nm-dns-manager.h" #include "nm-vpn-manager.h" -#include "nm-policy-hostname.h" #include "nm-manager-auth.h" #include "nm-firewall-manager.h" #include "nm-dispatcher.h" #include "nm-utils.h" +#include "nm-glib-compat.h" typedef struct { NMManager *manager; @@ -61,9 +62,9 @@ typedef struct { NMDevice *default_device4, *activating_device4; NMDevice *default_device6, *activating_device6; - HostnameThread *lookup; - guint32 lookup_ipv4_addr; /* IPv4 for reverse lookup */ - struct in6_addr *lookup_ipv6_addr; /* IPv6 for reverse lookup */ + GResolver *resolver; + GInetAddress *lookup_addr; + GCancellable *lookup_cancellable; NMDnsManager *dns_manager; gulong config_changed_id; @@ -87,12 +88,6 @@ enum { PROP_ACTIVATING_IP6_DEVICE }; -#define RETRIES_TAG "autoconnect-retries" -#define RETRIES_DEFAULT 4 -#define RESET_RETRIES_TIMESTAMP_TAG "reset-retries-timestamp-tag" -#define RESET_RETRIES_TIMER 300 -#define FAILURE_REASON_TAG "failure-reason" - static void schedule_activate_all (NMPolicy *policy); @@ -100,22 +95,18 @@ static NMDevice * get_best_ip4_device (NMPolicy *self, gboolean fully_activated) { NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); - GSList *devices, *iter; + const GSList *iter; NMDevice *best = NULL; int best_prio = G_MAXINT; - devices = nm_manager_get_devices (priv->manager); - for (iter = devices; iter; iter = g_slist_next (iter)) { + for (iter = nm_manager_get_devices (priv->manager); iter; iter = g_slist_next (iter)) { NMDevice *dev = NM_DEVICE (iter->data); NMDeviceType devtype = nm_device_get_device_type (dev); NMDeviceState state = nm_device_get_state (dev); NMActRequest *req; NMConnection *connection; - NMIP4Config *ip4_config; NMSettingIP4Config *s_ip4; int prio; - guint i; - gboolean can_default = FALSE; const char *method = NULL; if ( state <= NM_DEVICE_STATE_DISCONNECTED @@ -125,44 +116,38 @@ get_best_ip4_device (NMPolicy *self, gboolean fully_activated) if (fully_activated && state < NM_DEVICE_STATE_SECONDARIES) continue; - ip4_config = nm_device_get_ip4_config (dev); - if (ip4_config) { - /* Make sure at least one of this device's IP addresses has a gateway */ - for (i = 0; i < nm_ip4_config_get_num_addresses (ip4_config); i++) { - NMIP4Address *addr; + if (fully_activated) { + NMIP4Config *ip4_config; - addr = nm_ip4_config_get_address (ip4_config, i); - if (nm_ip4_address_get_gateway (addr)) { - can_default = TRUE; - break; - } - } + ip4_config = nm_device_get_ip4_config (dev); + if (!ip4_config) + continue; - if (!can_default && (devtype != NM_DEVICE_TYPE_MODEM)) + /* Make sure the device has a gateway */ + if (!nm_ip4_config_get_gateway (ip4_config) && (devtype != NM_DEVICE_TYPE_MODEM)) continue; /* 'never-default' devices can't ever be the default */ if (nm_ip4_config_get_never_default (ip4_config)) continue; - } else if (fully_activated) - continue; + } req = nm_device_get_act_request (dev); g_assert (req); connection = nm_act_request_get_connection (req); g_assert (connection); - s_ip4 = nm_connection_get_setting_ip4_config (connection); - if (s_ip4) { - /* Never set the default route through an IPv4LL-addressed device */ - method = nm_setting_ip4_config_get_method (s_ip4); - if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL)) - continue; + method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP4_CONFIG); + /* If IPv4 is disabled or link-local-only, it can't be the default */ + if ( !strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED) + || !strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL)) + continue; - /* 'never-default' devices can't ever be the default */ - if (nm_setting_ip4_config_get_never_default (s_ip4)) - continue; - } + /* 'never-default' devices can't ever be the default */ + s_ip4 = nm_connection_get_setting_ip4_config (connection); + g_assert (s_ip4); + if (nm_setting_ip4_config_get_never_default (s_ip4)) + continue; prio = nm_device_get_priority (dev); if ( prio < best_prio @@ -194,22 +179,18 @@ static NMDevice * get_best_ip6_device (NMPolicy *self, gboolean fully_activated) { NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); - GSList *devices, *iter; + const GSList *iter; NMDevice *best = NULL; int best_prio = G_MAXINT; - devices = nm_manager_get_devices (priv->manager); - for (iter = devices; iter; iter = g_slist_next (iter)) { + for (iter = nm_manager_get_devices (priv->manager); iter; iter = g_slist_next (iter)) { NMDevice *dev = NM_DEVICE (iter->data); NMDeviceType devtype = nm_device_get_device_type (dev); NMDeviceState state = nm_device_get_state (dev); NMActRequest *req; NMConnection *connection; - NMIP6Config *ip6_config; NMSettingIP6Config *s_ip6; int prio; - guint i; - gboolean can_default = FALSE; const char *method = NULL; if ( state <= NM_DEVICE_STATE_DISCONNECTED @@ -219,40 +200,34 @@ get_best_ip6_device (NMPolicy *self, gboolean fully_activated) if (fully_activated && state < NM_DEVICE_STATE_SECONDARIES) continue; - ip6_config = nm_device_get_ip6_config (dev); - if (ip6_config) { - for (i = 0; i < nm_ip6_config_get_num_addresses (ip6_config); i++) { - NMIP6Address *addr; + if (fully_activated) { + NMIP6Config *ip6_config; - addr = nm_ip6_config_get_address (ip6_config, i); - if (nm_ip6_address_get_gateway (addr)) { - can_default = TRUE; - break; - } - } + ip6_config = nm_device_get_ip6_config (dev); + if (!ip6_config) + continue; - if (!can_default && (devtype != NM_DEVICE_TYPE_MODEM)) + if (!nm_ip6_config_get_gateway (ip6_config) && (devtype != NM_DEVICE_TYPE_MODEM)) continue; if (nm_ip6_config_get_never_default (ip6_config)) continue; - } else if (fully_activated) - continue; + } req = nm_device_get_act_request (dev); g_assert (req); connection = nm_act_request_get_connection (req); g_assert (connection); - s_ip6 = nm_connection_get_setting_ip6_config (connection); - if (s_ip6) { - method = nm_setting_ip6_config_get_method (s_ip6); - if (!strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL)) - continue; + method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP6_CONFIG); + if ( !strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE) + || !strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL)) + continue; - if (nm_setting_ip6_config_get_never_default (s_ip6)) - continue; - } + s_ip6 = nm_connection_get_setting_ip6_config (connection); + g_assert (s_ip6); + if (nm_setting_ip6_config_get_never_default (s_ip6)) + continue; prio = nm_device_get_priority (dev); if ( prio < best_prio @@ -280,6 +255,43 @@ get_best_ip6_device (NMPolicy *self, gboolean fully_activated) return best; } +#define FALLBACK_HOSTNAME4 "localhost.localdomain" + +static gboolean +set_system_hostname (const char *new_hostname, const char *msg) +{ + char old_hostname[HOST_NAME_MAX + 1]; + const char *name; + int ret; + + if (new_hostname) + g_warn_if_fail (strlen (new_hostname)); + + old_hostname[HOST_NAME_MAX] = '\0'; + errno = 0; + ret = gethostname (old_hostname, HOST_NAME_MAX); + if (ret != 0) { + nm_log_warn (LOGD_DNS, "couldn't get the system hostname: (%d) %s", + errno, strerror (errno)); + } else { + /* Don't set the hostname if it isn't actually changing */ + if ( (new_hostname && !strcmp (old_hostname, new_hostname)) + || (!new_hostname && !strcmp (old_hostname, FALLBACK_HOSTNAME4))) + return FALSE; + } + + name = (new_hostname && strlen (new_hostname)) ? new_hostname : FALLBACK_HOSTNAME4; + + nm_log_info (LOGD_DNS, "Setting system hostname to '%s' (%s)", name, msg); + ret = sethostname (name, strlen (name)); + if (ret != 0) { + nm_log_warn (LOGD_DNS, "couldn't set the system hostname to '%s': (%d) %s", + name, errno, strerror (errno)); + } + + return (ret == 0); +} + static void _set_hostname (NMPolicy *policy, const char *new_hostname, @@ -293,14 +305,11 @@ _set_hostname (NMPolicy *policy, * there was no valid hostname to start with. */ - /* Clear lookup adresses if we have a hostname, so that we didn't - * restart reverse lookup thread later. + /* Clear lookup adresses if we have a hostname, so that we don't + * restart the reverse lookup thread later. */ - if (new_hostname) { - priv->lookup_ipv4_addr = 0; - g_free (priv->lookup_ipv6_addr); - priv->lookup_ipv6_addr = NULL; - } + if (new_hostname) + g_clear_object (&priv->lookup_addr); /* Don't change the hostname or update DNS this is the first time we're * trying to change the hostname, and it's not actually changing. @@ -322,32 +331,35 @@ _set_hostname (NMPolicy *policy, nm_dns_manager_set_hostname (priv->dns_manager, priv->cur_hostname); - if (nm_policy_set_system_hostname (priv->cur_hostname, msg)) - nm_dispatcher_call (DISPATCHER_ACTION_HOSTNAME, NULL, NULL, NULL, NULL); + if (set_system_hostname (priv->cur_hostname, msg)) + nm_dispatcher_call (DISPATCHER_ACTION_HOSTNAME, NULL, NULL, NULL, NULL, NULL); } static void -lookup_callback (HostnameThread *thread, - int result, - const char *hostname, +lookup_callback (GObject *source, + GAsyncResult *result, gpointer user_data) { NMPolicy *policy = (NMPolicy *) user_data; NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); - char *msg; - - /* Update the hostname if the calling lookup thread is the in-progress one */ - if (!hostname_thread_is_dead (thread) && (thread == priv->lookup)) { - priv->lookup = NULL; - if (!hostname) { - /* Fall back to localhost.localdomain */ - msg = g_strdup_printf ("address lookup failed: %d", result); - _set_hostname (policy, NULL, msg); - g_free (msg); - } else - _set_hostname (policy, hostname, "from address lookup"); + const char *hostname; + GError *error = NULL; + + hostname = g_resolver_lookup_by_address_finish (G_RESOLVER (source), result, &error); + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + /* Don't touch policy; it may have been freed already */ + g_error_free (error); + return; } - hostname_thread_free (thread); + + if (hostname) + _set_hostname (policy, hostname, "from address lookup"); + else { + _set_hostname (policy, NULL, error->message); + g_error_free (error); + } + + g_clear_object (&priv->lookup_cancellable); } static void @@ -356,12 +368,14 @@ update_system_hostname (NMPolicy *policy, NMDevice *best4, NMDevice *best6) NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); char *configured_hostname = NULL; const char *dhcp_hostname, *p; + NMIP4Config *ip4_config; + NMIP6Config *ip6_config; g_return_if_fail (policy != NULL); - if (priv->lookup) { - hostname_thread_kill (priv->lookup); - priv->lookup = NULL; + if (priv->lookup_cancellable) { + g_cancellable_cancel (priv->lookup_cancellable); + g_clear_object (&priv->lookup_cancellable); } /* Hostname precedence order: @@ -446,51 +460,32 @@ update_system_hostname (NMPolicy *policy, NMDevice *best4, NMDevice *best6) /* No configured hostname, no automatically determined hostname, and no * bootup hostname. Start reverse DNS of the current IPv4 or IPv6 address. */ - if (best4) { - NMIP4Config *ip4_config; - NMIP4Address *addr4; - - ip4_config = nm_device_get_ip4_config (best4); - if ( !ip4_config - || (nm_ip4_config_get_num_nameservers (ip4_config) == 0) - || (nm_ip4_config_get_num_addresses (ip4_config) == 0)) { - /* No valid IP4 config (!!); fall back to localhost.localdomain */ - _set_hostname (policy, NULL, "no IPv4 config"); - return; - } + ip4_config = best4 ? nm_device_get_ip4_config (best4) : NULL; + ip6_config = best6 ? nm_device_get_ip6_config (best6) : NULL; - addr4 = nm_ip4_config_get_address (ip4_config, 0); - g_assert (addr4); /* checked for > 1 address above */ + if (ip4_config && nm_ip4_config_get_num_addresses (ip4_config) > 0) { + const NMPlatformIP4Address *addr4; - /* Start the hostname lookup thread */ - priv->lookup_ipv4_addr = nm_ip4_address_get_address (addr4); - priv->lookup = hostname4_thread_new (priv->lookup_ipv4_addr, lookup_callback, policy); - } else if (best6) { - NMIP6Config *ip6_config; - NMIP6Address *addr6; - - ip6_config = nm_device_get_ip6_config (best6); - if ( !ip6_config - || (nm_ip6_config_get_num_nameservers (ip6_config) == 0) - || (nm_ip6_config_get_num_addresses (ip6_config) == 0)) { - /* No valid IP6 config (!!); fall back to localhost.localdomain */ - _set_hostname (policy, NULL, "no IPv6 config"); - return; - } + addr4 = nm_ip4_config_get_address (ip4_config, 0); + priv->lookup_addr = g_inet_address_new_from_bytes ((guint8 *) &addr4->address, + G_SOCKET_FAMILY_IPV4); + } else if (ip6_config && nm_ip6_config_get_num_addresses (ip6_config) > 0) { + const NMPlatformIP6Address *addr6; addr6 = nm_ip6_config_get_address (ip6_config, 0); - g_assert (addr6); /* checked for > 1 address above */ - - /* Start the hostname lookup thread */ - priv->lookup_ipv6_addr = g_malloc0 (sizeof (struct in6_addr)); - memcpy (priv->lookup_ipv6_addr, nm_ip6_address_get_address (addr6), sizeof (struct in6_addr)); - priv->lookup = hostname6_thread_new (priv->lookup_ipv6_addr, lookup_callback, policy); + priv->lookup_addr = g_inet_address_new_from_bytes ((guint8 *) &addr6->address, + G_SOCKET_FAMILY_IPV6); + } else { + /* No valid IP config; fall back to localhost.localdomain */ + _set_hostname (policy, NULL, "no IP config"); + return; } - if (!priv->lookup) { - /* Fall back to 'localhost.localdomain' */ - _set_hostname (policy, NULL, "error starting hostname thread"); - } + priv->lookup_cancellable = g_cancellable_new (); + g_resolver_lookup_by_address_async (priv->resolver, + priv->lookup_addr, + priv->lookup_cancellable, + lookup_callback, policy); } static void @@ -564,7 +559,7 @@ get_best_ip4_config (NMPolicy *policy, /* Check the user's preference from the NMConnection */ s_ip4 = nm_connection_get_setting_ip4_config (tmp); - if (s_ip4 && nm_setting_ip4_config_get_never_default (s_ip4)) + if (nm_setting_ip4_config_get_never_default (s_ip4)) continue; } @@ -627,15 +622,14 @@ static void update_ip4_routing (NMPolicy *policy, gboolean force_update) { NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); - NMDevice *best = NULL, *parent, *default_device; + NMDevice *best = NULL, *default_device; NMConnection *connection = NULL; NMVPNConnection *vpn = NULL; NMActiveConnection *best_ac = NULL; - NMIP4Config *ip4_config = NULL, *parent_ip4; + NMIP4Config *ip4_config = NULL; const char *ip_iface = NULL; int ip_ifindex = -1; - guint32 gw_addr = 0, parent_mss; - guint32 i; + guint32 gw_addr = 0; /* Note that we might have an IPv4 VPN tunneled over an IPv6-only device, * so we can get (vpn != NULL && best == NULL). @@ -656,35 +650,50 @@ update_ip4_routing (NMPolicy *policy, gboolean force_update) if (!force_update && best && (best == priv->default_device4)) return; - /* We set the default route to the first gateway we find. If we don't find - * a gateway (WWAN, point-to-point, etc) then we just use 0.0.0.0 - */ - for (i = 0; i < nm_ip4_config_get_num_addresses (ip4_config); i++) { - NMIP4Address *addr; + gw_addr = nm_ip4_config_get_gateway (ip4_config); - addr = nm_ip4_config_get_address (ip4_config, i); - if (nm_ip4_address_get_gateway (addr)) { - gw_addr = nm_ip4_address_get_gateway (addr); - break; + if (vpn) { + NMDevice *parent = nm_active_connection_get_device (NM_ACTIVE_CONNECTION (vpn)); + int parent_ifindex = nm_device_get_ip_ifindex (parent); + NMIP4Config *parent_ip4 = nm_device_get_ip4_config (parent); + guint32 parent_mss = parent_ip4 ? nm_ip4_config_get_mss (parent_ip4) : 0; + in_addr_t int_gw = nm_vpn_connection_get_ip4_internal_gateway (vpn); + int mss = nm_ip4_config_get_mss (ip4_config); + + /* If no VPN interface, use the parent interface */ + if (ip_ifindex <= 0) + ip_ifindex = parent_ifindex; + + if (!nm_platform_ip4_route_add (ip_ifindex, NM_PLATFORM_SOURCE_VPN, + 0, 0, int_gw, + NM_PLATFORM_ROUTE_METRIC_DEFAULT, mss)) { + (void) nm_platform_ip4_route_add (parent_ifindex, NM_PLATFORM_SOURCE_VPN, + gw_addr, 32, 0, + NM_PLATFORM_ROUTE_METRIC_DEFAULT, parent_mss); + if (!nm_platform_ip4_route_add (ip_ifindex, NM_PLATFORM_SOURCE_VPN, + 0, 0, int_gw, + NM_PLATFORM_ROUTE_METRIC_DEFAULT, mss)) + nm_log_err (LOGD_IP4 | LOGD_VPN, "Failed to set default route."); } - } - if (vpn) { - parent = nm_vpn_connection_get_parent_device (vpn); - parent_ip4 = nm_device_get_ip4_config (parent); - parent_mss = parent_ip4 ? nm_ip4_config_get_mss (parent_ip4) : 0; - - nm_system_replace_default_ip4_route_vpn (ip_ifindex, - gw_addr, - nm_vpn_connection_get_ip4_internal_gateway (vpn), - nm_ip4_config_get_mss (ip4_config), - nm_device_get_ip_ifindex (parent), - parent_mss); - default_device = parent; + default_device = nm_active_connection_get_device (NM_ACTIVE_CONNECTION (vpn)); } else { - nm_system_replace_default_ip4_route (ip_ifindex, - gw_addr, - nm_ip4_config_get_mss (ip4_config)); + int mss = nm_ip4_config_get_mss (ip4_config); + + g_assert (ip_iface); + if (!nm_platform_ip4_route_add (ip_ifindex, NM_PLATFORM_SOURCE_USER, + 0, 0, gw_addr, + NM_PLATFORM_ROUTE_METRIC_DEFAULT, mss)) { + (void) nm_platform_ip4_route_add (ip_ifindex, NM_PLATFORM_SOURCE_USER, + gw_addr, 32, 0, + NM_PLATFORM_ROUTE_METRIC_DEFAULT, mss); + if (!nm_platform_ip4_route_add (ip_ifindex, NM_PLATFORM_SOURCE_USER, + 0, 0, gw_addr, + NM_PLATFORM_ROUTE_METRIC_DEFAULT, mss)) { + nm_log_err (LOGD_IP4, "Failed to set default route."); + } + } + default_device = best; } @@ -748,7 +757,7 @@ get_best_ip6_config (NMPolicy *policy, /* Check the user's preference from the NMConnection */ s_ip6 = nm_connection_get_setting_ip6_config (tmp); - if (s_ip6 && nm_setting_ip6_config_get_never_default (s_ip6)) + if (nm_setting_ip6_config_get_never_default (s_ip6)) continue; } @@ -811,15 +820,13 @@ static void update_ip6_routing (NMPolicy *policy, gboolean force_update) { NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); - NMDevice *best = NULL, *parent, *default_device6; + NMDevice *best = NULL, *default_device6; NMConnection *connection = NULL; NMVPNConnection *vpn = NULL; NMActiveConnection *best_ac = NULL; - NMIP6Config *ip6_config = NULL, *parent_ip6; + NMIP6Config *ip6_config = NULL; const char *ip_iface = NULL; int ip_ifindex = -1; - guint32 parent_mss; - guint32 i; const struct in6_addr *gw_addr; /* Note that we might have an IPv6 VPN tunneled over an IPv4-only device, @@ -844,41 +851,54 @@ update_ip6_routing (NMPolicy *policy, gboolean force_update) /* If no better gateway is found, use ::; not all configurations will * have a gateway, especially WWAN/Point-to-Point connections. */ - gw_addr = &in6addr_any; - - /* Look for a gateway paired with one of the addresses */ - for (i = 0; i < nm_ip6_config_get_num_addresses (ip6_config); i++) { - NMIP6Address *addr; + gw_addr = nm_ip6_config_get_gateway (ip6_config); + if (!gw_addr) + gw_addr = &in6addr_any; - addr = nm_ip6_config_get_address (ip6_config, i); - if (nm_ip6_address_get_gateway (addr)) { - gw_addr = nm_ip6_address_get_gateway (addr); - break; + if (vpn) { + NMDevice *parent = nm_active_connection_get_device (NM_ACTIVE_CONNECTION (vpn)); + int parent_ifindex = nm_device_get_ip_ifindex (parent); + NMIP6Config *parent_ip6 = nm_device_get_ip6_config (parent); + guint32 parent_mss = parent_ip6 ? nm_ip6_config_get_mss (parent_ip6) : 0; + const struct in6_addr *int_gw = nm_vpn_connection_get_ip6_internal_gateway (vpn); + int mss = nm_ip6_config_get_mss (ip6_config); + + if (!int_gw) + int_gw = &in6addr_any; + + /* If no VPN interface, use the parent interface */ + if (ip_ifindex <= 0) + ip_ifindex = parent_ifindex; + + if (!nm_platform_ip6_route_add (ip_ifindex, NM_PLATFORM_SOURCE_VPN, + in6addr_any, 0, *int_gw, + NM_PLATFORM_ROUTE_METRIC_DEFAULT, mss)) { + (void) nm_platform_ip6_route_add (parent_ifindex, NM_PLATFORM_SOURCE_VPN, + *gw_addr, 128, in6addr_any, + NM_PLATFORM_ROUTE_METRIC_DEFAULT, parent_mss); + if (!nm_platform_ip6_route_add (ip_ifindex, NM_PLATFORM_SOURCE_VPN, + in6addr_any, 0, *int_gw, + NM_PLATFORM_ROUTE_METRIC_DEFAULT, mss)) { + nm_log_err (LOGD_IP6 | LOGD_VPN, "Failed to set default route."); + } } - } - - /* If we don't find a paired gateway, try the generic IPv6 gateway */ - if ( IN6_IS_ADDR_UNSPECIFIED (gw_addr) - && nm_ip6_config_get_gateway (ip6_config)) - gw_addr = nm_ip6_config_get_gateway (ip6_config); - if (vpn) { - parent = nm_vpn_connection_get_parent_device (vpn); - parent_ip6 = nm_device_get_ip6_config (parent); - parent_mss = parent_ip6 ? nm_ip6_config_get_mss (parent_ip6) : 0; - - nm_system_replace_default_ip6_route_vpn (ip_ifindex, - gw_addr, - nm_vpn_connection_get_ip6_internal_gateway (vpn), - nm_ip6_config_get_mss (ip6_config), - nm_device_get_ip_ifindex (parent), - parent_mss); - default_device6 = parent; + default_device6 = nm_active_connection_get_device (NM_ACTIVE_CONNECTION (vpn)); } else { - if (gw_addr) - nm_system_replace_default_ip6_route (ip_ifindex, gw_addr); - else - nm_log_dbg (LOGD_IP6, "missing default IPv6 gateway"); + int mss = nm_ip6_config_get_mss (ip6_config); + + if (!nm_platform_ip6_route_add (ip_ifindex, NM_PLATFORM_SOURCE_USER, + in6addr_any, 0, *gw_addr, + NM_PLATFORM_ROUTE_METRIC_DEFAULT, mss)) { + (void) nm_platform_ip6_route_add (ip_ifindex, NM_PLATFORM_SOURCE_USER, + *gw_addr, 128, in6addr_any, + NM_PLATFORM_ROUTE_METRIC_DEFAULT, mss); + if (!nm_platform_ip6_route_add (ip_ifindex, NM_PLATFORM_SOURCE_USER, + in6addr_any, 0, *gw_addr, + NM_PLATFORM_ROUTE_METRIC_DEFAULT, mss)) + nm_log_err (LOGD_IP6, "Failed to set default route."); + } + default_device6 = best; } @@ -898,13 +918,11 @@ static void update_routing_and_dns (NMPolicy *policy, gboolean force_update) { NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); - NMDnsManager *mgr; - mgr = nm_dns_manager_get (NULL); - nm_dns_manager_begin_updates (mgr, __func__); + nm_dns_manager_begin_updates (priv->dns_manager, __func__); - update_ip4_dns (policy, mgr); - update_ip6_dns (policy, mgr); + update_ip4_dns (policy, priv->dns_manager); + update_ip6_dns (policy, priv->dns_manager); update_ip4_routing (policy, force_update); update_ip6_routing (policy, force_update); @@ -912,8 +930,7 @@ update_routing_and_dns (NMPolicy *policy, gboolean force_update) /* Update the system hostname */ update_system_hostname (policy, priv->default_device4, priv->default_device6); - nm_dns_manager_end_updates (mgr, __func__); - g_object_unref (mgr); + nm_dns_manager_end_updates (priv->dns_manager, __func__); } static void @@ -940,33 +957,23 @@ check_activating_devices (NMPolicy *policy) g_object_thaw_notify (object); } -static void -set_connection_auto_retries (NMConnection *connection, guint retries) -{ - /* add +1 so that the tag still exists if the # retries is 0 */ - g_object_set_data (G_OBJECT (connection), RETRIES_TAG, GUINT_TO_POINTER (retries + 1)); -} - -static guint32 -get_connection_auto_retries (NMConnection *connection) -{ - /* subtract 1 to handle the +1 from set_connection_auto_retries() */ - return GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (connection), RETRIES_TAG)) - 1; -} - typedef struct { NMPolicy *policy; NMDevice *device; - guint id; + guint autoactivate_id; } ActivateData; static void activate_data_free (ActivateData *data) { - if (data->id) - g_source_remove (data->id); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (data->policy); + + nm_device_remove_pending_action (data->device, "autoactivate", TRUE); + priv->pending_activation_checks = g_slist_remove (priv->pending_activation_checks, data); + + if (data->autoactivate_id) + g_source_remove (data->autoactivate_id); g_object_unref (data->device); - memset (data, 0, sizeof (*data)); g_free (data); } @@ -984,8 +991,7 @@ auto_activate_device (gpointer user_data) policy = data->policy; priv = NM_POLICY_GET_PRIVATE (policy); - data->id = 0; - priv->pending_activation_checks = g_slist_remove (priv->pending_activation_checks, data); + data->autoactivate_id = 0; // FIXME: if a device is already activating (or activated) with a connection // but another connection now overrides the current one for that device, @@ -994,47 +1000,32 @@ auto_activate_device (gpointer user_data) if (nm_device_get_act_request (data->device)) goto out; - iter = connections = nm_settings_get_connections (priv->settings); + iter = connections = nm_manager_get_activatable_connections (priv->manager); /* Remove connections that shouldn't be auto-activated */ while (iter) { NMSettingsConnection *candidate = NM_SETTINGS_CONNECTION (iter->data); - gboolean remove_it = FALSE; - const char *permission; /* Grab next item before we possibly delete the current item */ iter = g_slist_next (iter); - /* Ignore connections that were tried too many times or are not visible - * to any logged-in users. Also ignore shared wifi connections for - * which no user has the shared wifi permission. - */ - if ( get_connection_auto_retries (NM_CONNECTION (candidate)) == 0 - || nm_settings_connection_is_visible (candidate) == FALSE) - remove_it = TRUE; - else { - permission = nm_utils_get_shared_wifi_permission (NM_CONNECTION (candidate)); - if (permission) { - if (nm_settings_connection_check_permission (candidate, permission) == FALSE) - remove_it = TRUE; - } - } - - if (remove_it) + if (!nm_settings_connection_can_autoconnect (candidate)) connections = g_slist_remove (connections, candidate); } best_connection = nm_device_get_best_auto_connection (data->device, connections, &specific_object); if (best_connection) { GError *error = NULL; + NMAuthSubject *subject; nm_log_info (LOGD_DEVICE, "Auto-activating connection '%s'.", nm_connection_get_id (best_connection)); + subject = nm_auth_subject_new_internal (); if (!nm_manager_activate_connection (priv->manager, best_connection, specific_object, - nm_device_get_path (data->device), - NULL, + data->device, + subject, &error)) { nm_log_info (LOGD_DEVICE, "Connection '%s' auto-activation failed: (%d) %s", nm_connection_get_id (best_connection), @@ -1042,28 +1033,14 @@ auto_activate_device (gpointer user_data) error ? error->message : "(none)"); g_error_free (error); } + g_object_unref (subject); } g_slist_free (connections); out: activate_data_free (data); - return FALSE; -} - -static ActivateData * -activate_data_new (NMPolicy *policy, NMDevice *device, guint delay_seconds) -{ - ActivateData *data; - - data = g_malloc0 (sizeof (ActivateData)); - data->policy = policy; - data->device = g_object_ref (device); - if (delay_seconds > 0) - data->id = g_timeout_add_seconds (delay_seconds, auto_activate_device, data); - else - data->id = g_idle_add (auto_activate_device, data); - return data; + return G_SOURCE_REMOVE; } static ActivateData * @@ -1100,7 +1077,7 @@ static void pending_secondary_data_free (PendingSecondaryData *data) { g_object_unref (data->device); - nm_utils_slist_free (data->secondaries, g_free); + g_slist_free_full (data->secondaries, g_object_unref); memset (data, 0, sizeof (*data)); g_free (data); } @@ -1111,51 +1088,50 @@ process_secondaries (NMPolicy *policy, gboolean connected) { NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); - NMDevice *device = NULL; - const char *ac_path; GSList *iter, *iter2; - nm_log_dbg (LOGD_DEVICE, "Secondary connection '%s' %s; active path '%s'", - nm_active_connection_get_name (active), - connected ? "SUCCEEDED" : "FAILED", - nm_active_connection_get_path (active)); - - ac_path = nm_active_connection_get_path (active); - - if (NM_IS_VPN_CONNECTION (active)) - device = nm_vpn_connection_get_parent_device (NM_VPN_CONNECTION (active)); - + /* Loop through devices waiting for secondary connections to activate */ for (iter = priv->pending_secondaries; iter; iter = g_slist_next (iter)) { PendingSecondaryData *secondary_data = (PendingSecondaryData *) iter->data; NMDevice *item_device = secondary_data->device; - if (!device || item_device == device) { - for (iter2 = secondary_data->secondaries; iter2; iter2 = g_slist_next (iter2)) { - char *list_ac_path = (char *) iter2->data; - - if (g_strcmp0 (ac_path, list_ac_path) == 0) { - if (connected) { - /* Secondary connection activated */ - secondary_data->secondaries = g_slist_remove (secondary_data->secondaries, list_ac_path); - g_free (list_ac_path); - if (!secondary_data->secondaries) { - /* None secondary UUID remained -> remove the secondary data item */ - priv->pending_secondaries = g_slist_remove (priv->pending_secondaries, secondary_data); - pending_secondary_data_free (secondary_data); - nm_device_state_changed (item_device, NM_DEVICE_STATE_ACTIVATED, NM_DEVICE_STATE_REASON_NONE); - return; - } - } else { - /* Secondary connection failed -> do not watch other connections */ - priv->pending_secondaries = g_slist_remove (priv->pending_secondaries, secondary_data); - pending_secondary_data_free (secondary_data); - nm_device_state_changed (item_device, NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_SECONDARY_CONNECTION_FAILED); - return; - } + /* Look for 'active' in each device's secondary connections list */ + for (iter2 = secondary_data->secondaries; iter2; iter2 = g_slist_next (iter2)) { + NMActiveConnection *secondary_active = NM_ACTIVE_CONNECTION (iter2->data); + + if (active != secondary_active) + continue; + + if (connected) { + nm_log_dbg (LOGD_DEVICE, "Secondary connection '%s' SUCCEEDED; active path '%s'", + nm_active_connection_get_id (active), + nm_active_connection_get_path (active)); + + /* Secondary connection activated */ + secondary_data->secondaries = g_slist_remove (secondary_data->secondaries, secondary_active); + g_object_unref (secondary_active); + if (!secondary_data->secondaries) { + /* No secondary UUID remained -> remove the secondary data item */ + priv->pending_secondaries = g_slist_remove (priv->pending_secondaries, secondary_data); + pending_secondary_data_free (secondary_data); + if (nm_device_get_state (item_device) == NM_DEVICE_STATE_SECONDARIES) + nm_device_state_changed (item_device, NM_DEVICE_STATE_ACTIVATED, NM_DEVICE_STATE_REASON_NONE); + break; } + } else { + nm_log_dbg (LOGD_DEVICE, "Secondary connection '%s' FAILED; active path '%s'", + nm_active_connection_get_id (active), + nm_active_connection_get_path (active)); + + /* Secondary connection failed -> do not watch other connections */ + priv->pending_secondaries = g_slist_remove (priv->pending_secondaries, secondary_data); + pending_secondary_data_free (secondary_data); + if ( nm_device_get_state (item_device) == NM_DEVICE_STATE_SECONDARIES + || nm_device_get_state (item_device) == NM_DEVICE_STATE_ACTIVATED) + nm_device_state_changed (item_device, NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_SECONDARY_CONNECTION_FAILED); + break; } - return; } } } @@ -1172,42 +1148,76 @@ hostname_changed (NMManager *manager, GParamSpec *pspec, gpointer user_data) } static void -reset_retries_all (NMSettings *settings, NMDevice *device) +reset_autoconnect_all (NMPolicy *policy, NMDevice *device) { + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); GSList *connections, *iter; - GError *error = NULL; - connections = nm_settings_get_connections (settings); + if (device) { + nm_log_dbg (LOGD_DEVICE, "Re-enabling autoconnect for all connections on %s", + nm_device_get_iface (device)); + } else + nm_log_dbg (LOGD_DEVICE, "Re-enabling autoconnect for all connections"); + + connections = nm_settings_get_connections (priv->settings); for (iter = connections; iter; iter = g_slist_next (iter)) { - if (!device || nm_device_check_connection_compatible (device, iter->data, &error)) - set_connection_auto_retries (NM_CONNECTION (iter->data), RETRIES_DEFAULT); - g_clear_error (&error); + if (!device || nm_device_check_connection_compatible (device, iter->data)) { + nm_settings_connection_reset_autoconnect_retries (iter->data); + nm_settings_connection_set_autoconnect_blocked_reason (iter->data, NM_DEVICE_STATE_REASON_NONE); + } } g_slist_free (connections); } static void -reset_retries_for_failed_secrets (NMSettings *settings) +reset_autoconnect_for_failed_secrets (NMPolicy *policy) { + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); GSList *connections, *iter; - connections = nm_settings_get_connections (settings); + nm_log_dbg (LOGD_DEVICE, "Re-enabling autoconnect for all connections with failed secrets"); + + connections = nm_settings_get_connections (priv->settings); for (iter = connections; iter; iter = g_slist_next (iter)) { - NMDeviceStateReason reason = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (iter->data), FAILURE_REASON_TAG)); + NMSettingsConnection *connection = NM_SETTINGS_CONNECTION (iter->data); - if (reason == NM_DEVICE_STATE_REASON_NO_SECRETS) { - set_connection_auto_retries (NM_CONNECTION (iter->data), RETRIES_DEFAULT); - g_object_set_data (G_OBJECT (iter->data), FAILURE_REASON_TAG, GUINT_TO_POINTER (0)); + if (nm_settings_connection_get_autoconnect_blocked_reason (connection) == NM_DEVICE_STATE_REASON_NO_SECRETS) { + nm_settings_connection_reset_autoconnect_retries (connection); + nm_settings_connection_set_autoconnect_blocked_reason (connection, NM_DEVICE_STATE_REASON_NONE); } } g_slist_free (connections); } +static void +block_autoconnect_for_device (NMPolicy *policy, NMDevice *device) +{ + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + GSList *connections, *iter; + + nm_log_dbg (LOGD_DEVICE, "Blocking autoconnect for all connections on %s", + nm_device_get_iface (device)); + + /* NMDevice keeps its own autoconnect-able-ness state; we only need to + * explicitly block connections for software devices, where the NMDevice + * might be destroyed and recreated later. + */ + if (!nm_device_is_software (device)) + return; + + connections = nm_settings_get_connections (priv->settings); + for (iter = connections; iter; iter = g_slist_next (iter)) { + if (nm_device_check_connection_compatible (device, iter->data)) { + nm_settings_connection_set_autoconnect_blocked_reason (NM_SETTINGS_CONNECTION (iter->data), + NM_DEVICE_STATE_REASON_USER_REQUESTED); + } + } +} + static void sleeping_changed (NMManager *manager, GParamSpec *pspec, gpointer user_data) { NMPolicy *policy = user_data; - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); gboolean sleeping = FALSE, enabled = FALSE; g_object_get (G_OBJECT (manager), NM_MANAGER_SLEEPING, &sleeping, NULL); @@ -1215,34 +1225,52 @@ sleeping_changed (NMManager *manager, GParamSpec *pspec, gpointer user_data) /* Reset retries on all connections so they'll checked on wakeup */ if (sleeping || !enabled) - reset_retries_all (priv->settings, NULL); + reset_autoconnect_all (policy, NULL); } static void -schedule_activate_check (NMPolicy *policy, NMDevice *device, guint delay_seconds) +schedule_activate_check (NMPolicy *policy, NMDevice *device) { NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); ActivateData *data; - NMDeviceState state; + const GSList *active_connections, *iter; if (nm_manager_get_state (priv->manager) == NM_STATE_ASLEEP) return; - state = nm_device_get_state (device); - if (state < NM_DEVICE_STATE_DISCONNECTED) - return; - if (!nm_device_get_enabled (device)) return; if (!nm_device_autoconnect_allowed (device)) return; - /* Schedule an auto-activation if there isn't one already for this device */ - if (find_pending_activation (priv->pending_activation_checks, device) == NULL) { - data = activate_data_new (policy, device, delay_seconds); - priv->pending_activation_checks = g_slist_append (priv->pending_activation_checks, data); + if (find_pending_activation (priv->pending_activation_checks, device)) + return; + + active_connections = nm_manager_get_active_connections (priv->manager); + for (iter = active_connections; iter; iter = iter->next) { + if (nm_active_connection_get_device (NM_ACTIVE_CONNECTION (iter->data)) == device) + return; } + + nm_device_add_pending_action (device, "autoactivate", TRUE); + + data = g_malloc0 (sizeof (ActivateData)); + data->policy = policy; + data->device = g_object_ref (device); + data->autoactivate_id = g_idle_add (auto_activate_device, data); + priv->pending_activation_checks = g_slist_append (priv->pending_activation_checks, data); +} + +static void +clear_pending_activate_check (NMPolicy *policy, NMDevice *device) +{ + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + ActivateData *data; + + data = find_pending_activation (priv->pending_activation_checks, device); + if (data && data->autoactivate_id) + activate_data_free (data); } static gboolean @@ -1251,31 +1279,32 @@ reset_connections_retries (gpointer user_data) NMPolicy *policy = (NMPolicy *) user_data; NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); GSList *connections, *iter; - time_t con_stamp, min_stamp, now; + gint32 con_stamp, min_stamp, now; gboolean changed = FALSE; priv->reset_retries_id = 0; - min_stamp = now = time (NULL); + min_stamp = 0; + now = nm_utils_get_monotonic_timestamp_s (); connections = nm_settings_get_connections (priv->settings); for (iter = connections; iter; iter = g_slist_next (iter)) { - con_stamp = GPOINTER_TO_SIZE (g_object_get_data (G_OBJECT (iter->data), RESET_RETRIES_TIMESTAMP_TAG)); + NMSettingsConnection *connection = NM_SETTINGS_CONNECTION (iter->data); + + con_stamp = nm_settings_connection_get_autoconnect_retry_time (connection); if (con_stamp == 0) continue; - if (con_stamp + RESET_RETRIES_TIMER <= now) { - set_connection_auto_retries (NM_CONNECTION (iter->data), RETRIES_DEFAULT); - g_object_set_data (G_OBJECT (iter->data), RESET_RETRIES_TIMESTAMP_TAG, GSIZE_TO_POINTER (0)); + + if (con_stamp <= now) { + nm_settings_connection_reset_autoconnect_retries (connection); changed = TRUE; - continue; - } - if (con_stamp < min_stamp) + } else if (min_stamp == 0 || min_stamp > con_stamp) min_stamp = con_stamp; } g_slist_free (connections); /* Schedule the handler again if there are some stamps left */ - if (min_stamp != now) - priv->reset_retries_id = g_timeout_add_seconds (RESET_RETRIES_TIMER - (now - min_stamp), reset_connections_retries, policy); + if (min_stamp != 0) + priv->reset_retries_id = g_timeout_add_seconds (min_stamp - now, reset_connections_retries, policy); /* If anything changed, try to activate the newly re-enabled connections */ if (changed) @@ -1287,29 +1316,37 @@ reset_connections_retries (gpointer user_data) static void schedule_activate_all (NMPolicy *policy); static void -activate_slave_connections (NMPolicy *policy, NMConnection *connection, - NMDevice *device) +activate_slave_connections (NMPolicy *policy, NMDevice *device) { NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); - const char *master_device; + const char *master_device, *master_uuid = NULL; GSList *connections, *iter; + NMActRequest *req; master_device = nm_device_get_iface (device); g_assert (master_device); + req = nm_device_get_act_request (device); + if (req) + master_uuid = nm_active_connection_get_uuid (NM_ACTIVE_CONNECTION (req)); + connections = nm_settings_get_connections (priv->settings); for (iter = connections; iter; iter = g_slist_next (iter)) { NMConnection *slave; NMSettingConnection *s_slave_con; + const char *slave_master; slave = NM_CONNECTION (iter->data); g_assert (slave); s_slave_con = nm_connection_get_setting_connection (slave); g_assert (s_slave_con); + slave_master = nm_setting_connection_get_master (s_slave_con); + if (!slave_master) + continue; - if (!g_strcmp0 (nm_setting_connection_get_master (s_slave_con), master_device)) - set_connection_auto_retries (slave, RETRIES_DEFAULT); + if (!g_strcmp0 (slave_master, master_device) || !g_strcmp0 (slave_master, master_uuid)) + nm_settings_connection_reset_autoconnect_retries (NM_SETTINGS_CONNECTION (slave)); } g_slist_free (connections); @@ -1337,46 +1374,52 @@ activate_secondary_connections (NMPolicy *policy, for (i = 0; i < nm_setting_connection_get_num_secondaries (s_con); i++) { const char *sec_uuid = nm_setting_connection_get_secondary (s_con, i); + NMActRequest *req; settings_con = nm_settings_get_connection_by_uuid (priv->settings, sec_uuid); - if (settings_con) { - NMActRequest *req = nm_device_get_act_request (device); - g_assert (req); - - nm_log_dbg (LOGD_DEVICE, "Activating secondary connection '%s (%s)' for base connection '%s (%s)'", - nm_connection_get_id (NM_CONNECTION (settings_con)), sec_uuid, - nm_connection_get_id (connection), nm_connection_get_uuid (connection)); - ac = nm_manager_activate_connection (priv->manager, - NM_CONNECTION (settings_con), - nm_active_connection_get_path (NM_ACTIVE_CONNECTION (req)), - nm_device_get_path (device), - nm_act_request_get_dbus_sender (req), - &error); - if (ac) { - secondary_ac_list = g_slist_append (secondary_ac_list, - g_strdup (nm_active_connection_get_path (ac))); - } else { - nm_log_warn (LOGD_DEVICE, "Secondary connection '%s' auto-activation failed: (%d) %s", - sec_uuid, - error ? error->code : 0, - (error && error->message) ? error->message : "unknown"); - g_clear_error (&error); - success = FALSE; - break; - } - } else { + if (!settings_con) { nm_log_warn (LOGD_DEVICE, "Secondary connection '%s' auto-activation failed: The connection doesn't exist.", sec_uuid); success = FALSE; break; } + if (!nm_connection_is_type (NM_CONNECTION (settings_con), NM_SETTING_VPN_SETTING_NAME)) { + nm_log_warn (LOGD_DEVICE, "Secondary connection '%s (%s)' auto-activation failed: The connection is not a VPN.", + nm_connection_get_id (NM_CONNECTION (settings_con)), sec_uuid); + success = FALSE; + break; + } + + req = nm_device_get_act_request (device); + g_assert (req); + + nm_log_dbg (LOGD_DEVICE, "Activating secondary connection '%s (%s)' for base connection '%s (%s)'", + nm_connection_get_id (NM_CONNECTION (settings_con)), sec_uuid, + nm_connection_get_id (connection), nm_connection_get_uuid (connection)); + ac = nm_manager_activate_connection (priv->manager, + NM_CONNECTION (settings_con), + nm_active_connection_get_path (NM_ACTIVE_CONNECTION (req)), + device, + nm_active_connection_get_subject (NM_ACTIVE_CONNECTION (req)), + &error); + if (ac) + secondary_ac_list = g_slist_append (secondary_ac_list, g_object_ref (ac)); + else { + nm_log_warn (LOGD_DEVICE, "Secondary connection '%s (%s)' auto-activation failed: (%d) %s", + nm_connection_get_id (NM_CONNECTION (settings_con)), sec_uuid, + error ? error->code : 0, + (error && error->message) ? error->message : "unknown"); + g_clear_error (&error); + success = FALSE; + break; + } } if (success && secondary_ac_list != NULL) { secondary_data = pending_secondary_data_new (device, secondary_ac_list); priv->pending_secondaries = g_slist_append (priv->pending_secondaries, secondary_data); } else - nm_utils_slist_free (secondary_ac_list, g_free); + g_slist_free_full (secondary_ac_list, g_object_unref); return success; } @@ -1390,14 +1433,11 @@ device_state_changed (NMDevice *device, { NMPolicy *policy = (NMPolicy *) user_data; NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); - NMConnection *connection = nm_device_get_connection (device); + NMSettingsConnection *connection = NM_SETTINGS_CONNECTION (nm_device_get_connection (device)); const char *ip_iface = nm_device_get_ip_iface (device); NMIP4Config *ip4_config; NMIP6Config *ip6_config; - NMSettingConnection *s_con; - - if (connection) - g_object_set_data (G_OBJECT (connection), FAILURE_REASON_TAG, GUINT_TO_POINTER (0)); + NMSettingConnection *s_con = NULL; switch (new_state) { case NM_DEVICE_STATE_FAILED: @@ -1407,47 +1447,42 @@ device_state_changed (NMDevice *device, if ( connection && old_state >= NM_DEVICE_STATE_PREPARE && old_state <= NM_DEVICE_STATE_ACTIVATED) { - guint32 tries = get_connection_auto_retries (connection); + guint32 tries = nm_settings_connection_get_autoconnect_retries (connection); if (reason == NM_DEVICE_STATE_REASON_NO_SECRETS) { - /* If the connection couldn't get the secrets it needed (ex because - * the user canceled, or no secrets exist), there's no point in - * automatically retrying because it's just going to fail anyway. - */ - set_connection_auto_retries (connection, 0); - - /* Mark the connection as failed due to missing secrets so that we can reset - * RETRIES_TAG and automatically re-try when an secret agent registers. - */ - g_object_set_data (G_OBJECT (connection), FAILURE_REASON_TAG, GUINT_TO_POINTER (NM_DEVICE_STATE_REASON_NO_SECRETS)); + nm_log_dbg (LOGD_DEVICE, "Connection '%s' now blocked from autoconnect due to no secrets", + nm_connection_get_id (NM_CONNECTION (connection))); + + nm_settings_connection_set_autoconnect_blocked_reason (connection, NM_DEVICE_STATE_REASON_NO_SECRETS); } else if (tries > 0) { - /* Otherwise if it's a random failure, just decrease the number - * of automatic retries so that the connection gets tried again - * if it still has a retry count. - */ - set_connection_auto_retries (connection, tries - 1); + nm_log_dbg (LOGD_DEVICE, "Connection '%s' failed to autoconnect; %d tries left", + nm_connection_get_id (NM_CONNECTION (connection)), tries); + nm_settings_connection_set_autoconnect_retries (connection, tries - 1); } - if (get_connection_auto_retries (connection) == 0) { - nm_log_info (LOGD_DEVICE, "Marking connection '%s' invalid.", nm_connection_get_id (connection)); + if (nm_settings_connection_get_autoconnect_retries (connection) == 0) { + nm_log_info (LOGD_DEVICE, "Disabling autoconnect for connection '%s'.", + nm_connection_get_id (NM_CONNECTION (connection))); /* Schedule a handler to reset retries count */ - g_object_set_data (G_OBJECT (connection), RESET_RETRIES_TIMESTAMP_TAG, GSIZE_TO_POINTER ((gsize) time (NULL))); - if (!priv->reset_retries_id) - priv->reset_retries_id = g_timeout_add_seconds (RESET_RETRIES_TIMER, reset_connections_retries, policy); + if (!priv->reset_retries_id) { + gint32 retry_time = nm_settings_connection_get_autoconnect_retry_time (connection); + + g_warn_if_fail (retry_time != 0); + priv->reset_retries_id = g_timeout_add_seconds (MAX (0, retry_time - nm_utils_get_monotonic_timestamp_s ()), reset_connections_retries, policy); + } } - nm_connection_clear_secrets (connection); + nm_connection_clear_secrets (NM_CONNECTION (connection)); } - schedule_activate_check (policy, device, 3); break; case NM_DEVICE_STATE_ACTIVATED: if (connection) { /* Reset auto retries back to default since connection was successful */ - set_connection_auto_retries (connection, RETRIES_DEFAULT); + nm_settings_connection_reset_autoconnect_retries (connection); /* And clear secrets so they will always be requested from the * settings service when the next connection is made. */ - nm_connection_clear_secrets (connection); + nm_connection_clear_secrets (NM_CONNECTION (connection)); } /* Add device's new IPv4 and IPv6 configs to DNS */ @@ -1470,32 +1505,55 @@ device_state_changed (NMDevice *device, if (old_state > NM_DEVICE_STATE_DISCONNECTED) update_routing_and_dns (policy, FALSE); break; + case NM_DEVICE_STATE_DEACTIVATING: + if (reason == NM_DEVICE_STATE_REASON_USER_REQUESTED) { + if (!nm_device_get_autoconnect (device)) { + /* The device was disconnected; block all connections on it */ + block_autoconnect_for_device (policy, device); + } else { + if (connection) { + /* The connection was deactivated, so block just this connection */ + nm_log_dbg (LOGD_DEVICE, "Blocking autoconnect of connection '%s' by user request", + nm_connection_get_id (NM_CONNECTION (connection))); + nm_settings_connection_set_autoconnect_blocked_reason (connection, + NM_DEVICE_STATE_REASON_USER_REQUESTED); + } + } + } + break; case NM_DEVICE_STATE_DISCONNECTED: - /* Reset RETRIES_TAG when carrier on. If cable was unplugged - * and plugged again, we should try to reconnect */ + /* Reset retry counts for a device's connections when carrier on; if cable + * was unplugged and plugged in again, we should try to reconnect. + */ if (reason == NM_DEVICE_STATE_REASON_CARRIER && old_state == NM_DEVICE_STATE_UNAVAILABLE) - reset_retries_all (priv->settings, device); + reset_autoconnect_all (policy, device); if (old_state > NM_DEVICE_STATE_DISCONNECTED) update_routing_and_dns (policy, FALSE); /* Device is now available for auto-activation */ - schedule_activate_check (policy, device, 0); + schedule_activate_check (policy, device); break; case NM_DEVICE_STATE_PREPARE: /* Reset auto-connect retries of all slaves and schedule them for * activation. */ - activate_slave_connections (policy, connection, device); + activate_slave_connections (policy, device); + break; + case NM_DEVICE_STATE_IP_CONFIG: + /* We must have secrets if we got here. */ + if (connection) + nm_settings_connection_set_autoconnect_blocked_reason (connection, NM_DEVICE_STATE_REASON_NONE); break; case NM_DEVICE_STATE_SECONDARIES: - s_con = nm_connection_get_setting_connection (connection); + if (connection) + s_con = nm_connection_get_setting_connection (NM_CONNECTION (connection)); if (s_con && nm_setting_connection_get_num_secondaries (s_con) > 0) { /* Make routes and DNS up-to-date before activating dependent connections */ update_routing_and_dns (policy, FALSE); /* Activate secondary (VPN) connections */ - if (!activate_secondary_connections (policy, connection, device)) + if (!activate_secondary_connections (policy, NM_CONNECTION (connection), device)) nm_device_queue_state (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_SECONDARY_CONNECTION_FAILED); } else @@ -1519,27 +1577,26 @@ device_ip4_config_changed (NMDevice *device, NMPolicy *policy = user_data; NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); const char *ip_iface = nm_device_get_ip_iface (device); - NMIP4ConfigCompareFlags diff = NM_IP4_COMPARE_FLAG_ALL; nm_dns_manager_begin_updates (priv->dns_manager, __func__); - /* Old configs get removed immediately */ - if (old_config) - nm_dns_manager_remove_ip4_config (priv->dns_manager, old_config); - /* Ignore IP config changes while the device is activating, because we'll * catch all the changes when the device moves to ACTIVATED state. * Prevents unecessary changes to DNS information. */ if (!nm_device_is_activating (device)) { - if (new_config) - nm_dns_manager_add_ip4_config (priv->dns_manager, ip_iface, new_config, NM_DNS_IP_CONFIG_TYPE_DEFAULT); + if (old_config != new_config) { + if (old_config) + nm_dns_manager_remove_ip4_config (priv->dns_manager, old_config); + if (new_config) + nm_dns_manager_add_ip4_config (priv->dns_manager, ip_iface, new_config, NM_DNS_IP_CONFIG_TYPE_DEFAULT); + } update_ip4_dns (policy, priv->dns_manager); - - /* Only change routing if something actually changed */ - diff = nm_ip4_config_diff (new_config, old_config); - if (diff & (NM_IP4_COMPARE_FLAG_ADDRESSES | NM_IP4_COMPARE_FLAG_PTP_ADDRESS | NM_IP4_COMPARE_FLAG_ROUTES)) - update_ip4_routing (policy, TRUE); + update_ip4_routing (policy, TRUE); + } else { + /* Old configs get removed immediately */ + if (old_config) + nm_dns_manager_remove_ip4_config (priv->dns_manager, old_config); } nm_dns_manager_end_updates (priv->dns_manager, __func__); @@ -1554,27 +1611,26 @@ device_ip6_config_changed (NMDevice *device, NMPolicy *policy = user_data; NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); const char *ip_iface = nm_device_get_ip_iface (device); - NMIP4ConfigCompareFlags diff = NM_IP4_COMPARE_FLAG_ALL; nm_dns_manager_begin_updates (priv->dns_manager, __func__); - /* Old configs get removed immediately */ - if (old_config) - nm_dns_manager_remove_ip6_config (priv->dns_manager, old_config); - /* Ignore IP config changes while the device is activating, because we'll * catch all the changes when the device moves to ACTIVATED state. * Prevents unecessary changes to DNS information. */ if (!nm_device_is_activating (device)) { - if (new_config) - nm_dns_manager_add_ip6_config (priv->dns_manager, ip_iface, new_config, NM_DNS_IP_CONFIG_TYPE_DEFAULT); + if (old_config != new_config) { + if (old_config) + nm_dns_manager_remove_ip6_config (priv->dns_manager, old_config); + if (new_config) + nm_dns_manager_add_ip6_config (priv->dns_manager, ip_iface, new_config, NM_DNS_IP_CONFIG_TYPE_DEFAULT); + } update_ip6_dns (policy, priv->dns_manager); - - /* Only change routing if something actually changed */ - diff = nm_ip6_config_diff (new_config, old_config); - if (diff & (NM_IP6_COMPARE_FLAG_ADDRESSES | NM_IP6_COMPARE_FLAG_PTP_ADDRESS | NM_IP6_COMPARE_FLAG_ROUTES)) - update_ip6_routing (policy, TRUE); + update_ip6_routing (policy, TRUE); + } else { + /* Old configs get removed immediately */ + if (old_config) + nm_dns_manager_remove_ip6_config (priv->dns_manager, old_config); } nm_dns_manager_end_updates (priv->dns_manager, __func__); @@ -1586,25 +1642,13 @@ device_autoconnect_changed (NMDevice *device, gpointer user_data) { if (nm_device_get_autoconnect (device)) - schedule_activate_check ((NMPolicy *) user_data, device, 0); + schedule_activate_check ((NMPolicy *) user_data, device); } static void -wireless_networks_changed (NMDevice *device, GObject *ap, gpointer user_data) +device_recheck_auto_activate (NMDevice *device, gpointer user_data) { - schedule_activate_check ((NMPolicy *) user_data, device, 0); -} - -static void -nsps_changed (NMDevice *device, GObject *nsp, gpointer user_data) -{ - schedule_activate_check ((NMPolicy *) user_data, device, 0); -} - -static void -modem_enabled_changed (NMDevice *device, gpointer user_data) -{ - schedule_activate_check ((NMPolicy *) (user_data), device, 0); + schedule_activate_check (NM_POLICY (user_data), device); } typedef struct { @@ -1613,14 +1657,21 @@ typedef struct { } DeviceSignalId; static void -_connect_device_signal (NMPolicy *policy, NMDevice *device, const char *name, gpointer callback) +_connect_device_signal (NMPolicy *policy, + NMDevice *device, + const char *name, + gpointer callback, + gboolean after) { NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); DeviceSignalId *data; data = g_slice_new0 (DeviceSignalId); g_assert (data); - data->id = g_signal_connect (device, name, callback, policy); + if (after) + data->id = g_signal_connect_after (device, name, callback, policy); + else + data->id = g_signal_connect (device, name, callback, policy); data->device = device; priv->dev_ids = g_slist_prepend (priv->dev_ids, data); } @@ -1630,26 +1681,12 @@ device_added (NMManager *manager, NMDevice *device, gpointer user_data) { NMPolicy *policy = (NMPolicy *) user_data; - _connect_device_signal (policy, device, "state-changed", device_state_changed); - _connect_device_signal (policy, device, NM_DEVICE_IP4_CONFIG_CHANGED, device_ip4_config_changed); - _connect_device_signal (policy, device, NM_DEVICE_IP6_CONFIG_CHANGED, device_ip6_config_changed); - _connect_device_signal (policy, device, "notify::" NM_DEVICE_AUTOCONNECT, device_autoconnect_changed); - - switch (nm_device_get_device_type (device)) { - case NM_DEVICE_TYPE_WIFI: - _connect_device_signal (policy, device, "access-point-added", wireless_networks_changed); - _connect_device_signal (policy, device, "access-point-removed", wireless_networks_changed); - break; - case NM_DEVICE_TYPE_WIMAX: - _connect_device_signal (policy, device, "nsp-added", nsps_changed); - _connect_device_signal (policy, device, "nsp-removed", nsps_changed); - break; - case NM_DEVICE_TYPE_MODEM: - _connect_device_signal (policy, device, "enable-changed", modem_enabled_changed); - break; - default: - break; - } + /* Connect state-changed with _after, so that the handler is invoked after other handlers. */ + _connect_device_signal (policy, device, "state-changed", device_state_changed, TRUE); + _connect_device_signal (policy, device, NM_DEVICE_IP4_CONFIG_CHANGED, device_ip4_config_changed, FALSE); + _connect_device_signal (policy, device, NM_DEVICE_IP6_CONFIG_CHANGED, device_ip6_config_changed, FALSE); + _connect_device_signal (policy, device, "notify::" NM_DEVICE_AUTOCONNECT, device_autoconnect_changed, FALSE); + _connect_device_signal (policy, device, NM_DEVICE_RECHECK_AUTO_ACTIVATE, device_recheck_auto_activate, FALSE); } static void @@ -1657,15 +1694,10 @@ device_removed (NMManager *manager, NMDevice *device, gpointer user_data) { NMPolicy *policy = (NMPolicy *) user_data; NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); - ActivateData *tmp; GSList *iter; /* Clear any idle callbacks for this device */ - tmp = find_pending_activation (priv->pending_activation_checks, device); - if (tmp) { - priv->pending_activation_checks = g_slist_remove (priv->pending_activation_checks, tmp); - activate_data_free (tmp); - } + clear_pending_activate_check (policy, device); /* Clear any signal handlers for this device */ iter = priv->dev_ids; @@ -1691,13 +1723,12 @@ device_removed (NMManager *manager, NMDevice *device, gpointer user_data) static void vpn_connection_activated (NMPolicy *policy, NMVPNConnection *vpn) { - NMDnsManager *mgr; + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); NMIP4Config *ip4_config; NMIP6Config *ip6_config; const char *ip_iface; - mgr = nm_dns_manager_get (NULL); - nm_dns_manager_begin_updates (mgr, __func__); + nm_dns_manager_begin_updates (priv->dns_manager, __func__); ip_iface = nm_vpn_connection_get_ip_iface (vpn); @@ -1705,81 +1736,58 @@ vpn_connection_activated (NMPolicy *policy, NMVPNConnection *vpn) ip4_config = nm_vpn_connection_get_ip4_config (vpn); if (ip4_config) - nm_dns_manager_add_ip4_config (mgr, ip_iface, ip4_config, NM_DNS_IP_CONFIG_TYPE_VPN); + nm_dns_manager_add_ip4_config (priv->dns_manager, ip_iface, ip4_config, NM_DNS_IP_CONFIG_TYPE_VPN); ip6_config = nm_vpn_connection_get_ip6_config (vpn); if (ip6_config) - nm_dns_manager_add_ip6_config (mgr, ip_iface, ip6_config, NM_DNS_IP_CONFIG_TYPE_VPN); + nm_dns_manager_add_ip6_config (priv->dns_manager, ip_iface, ip6_config, NM_DNS_IP_CONFIG_TYPE_VPN); update_routing_and_dns (policy, TRUE); - nm_dns_manager_end_updates (mgr, __func__); - - process_secondaries (policy, NM_ACTIVE_CONNECTION (vpn), TRUE); + nm_dns_manager_end_updates (priv->dns_manager, __func__); } static void vpn_connection_deactivated (NMPolicy *policy, NMVPNConnection *vpn) { - NMDnsManager *mgr; - NMIP4Config *ip4_config, *parent_ip4 = NULL; - NMIP6Config *ip6_config, *parent_ip6 = NULL; - const char *ip_iface; - NMDevice *parent; - - mgr = nm_dns_manager_get (NULL); - nm_dns_manager_begin_updates (mgr, __func__); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMIP4Config *ip4_config; + NMIP6Config *ip6_config; - ip_iface = nm_vpn_connection_get_ip_iface (vpn); - parent = nm_vpn_connection_get_parent_device (vpn); + nm_dns_manager_begin_updates (priv->dns_manager, __func__); ip4_config = nm_vpn_connection_get_ip4_config (vpn); if (ip4_config) { /* Remove the VPN connection's IP4 config from DNS */ - nm_dns_manager_remove_ip4_config (mgr, ip4_config); - - /* Re-apply routes and addresses of the VPN connection's parent interface, - * which the VPN might have overridden. - */ - if (parent) { - parent_ip4 = nm_device_get_ip4_config (parent); - if (parent_ip4) { - if (!nm_system_apply_ip4_config (nm_device_get_ip_ifindex (parent), - parent_ip4, - nm_device_get_priority (parent), - NM_IP4_COMPARE_FLAG_ADDRESSES | NM_IP4_COMPARE_FLAG_ROUTES)) { - nm_log_err (LOGD_VPN, "failed to re-apply VPN parent device IPv4 addresses and routes."); - } - } - } + nm_dns_manager_remove_ip4_config (priv->dns_manager, ip4_config); } ip6_config = nm_vpn_connection_get_ip6_config (vpn); if (ip6_config) { /* Remove the VPN connection's IP6 config from DNS */ - nm_dns_manager_remove_ip6_config (mgr, ip6_config); - - /* Re-apply routes and addresses of the VPN connection's parent interface, - * which the VPN might have overridden. - */ - if (parent) { - parent_ip6 = nm_device_get_ip6_config (parent); - if (parent_ip6) { - if (!nm_system_apply_ip6_config (nm_device_get_ip_ifindex (parent), - parent_ip6, - nm_device_get_priority (parent), - NM_IP6_COMPARE_FLAG_ADDRESSES | NM_IP6_COMPARE_FLAG_ROUTES)) { - nm_log_err (LOGD_VPN, "failed to re-apply VPN parent device IPv6 addresses and routes."); - } - } - } + nm_dns_manager_remove_ip6_config (priv->dns_manager, ip6_config); } update_routing_and_dns (policy, TRUE); - nm_dns_manager_end_updates (mgr, __func__); + nm_dns_manager_end_updates (priv->dns_manager, __func__); +} - process_secondaries (policy, NM_ACTIVE_CONNECTION (vpn), FALSE); +static void +vpn_connection_state_changed (NMVPNConnection *vpn, + NMVPNConnectionState new_state, + NMVPNConnectionState old_state, + NMVPNConnectionStateReason reason, + NMPolicy *policy) +{ + if (new_state == NM_VPN_CONNECTION_STATE_ACTIVATED) + vpn_connection_activated (policy, vpn); + else if (new_state >= NM_VPN_CONNECTION_STATE_FAILED) { + /* Only clean up IP/DNS if the connection ever got past IP_CONFIG */ + if (old_state >= NM_VPN_CONNECTION_STATE_IP_CONFIG_GET && + old_state <= NM_VPN_CONNECTION_STATE_ACTIVATED) + vpn_connection_deactivated (policy, vpn); + } } static void @@ -1787,18 +1795,12 @@ active_connection_state_changed (NMActiveConnection *active, GParamSpec *pspec, NMPolicy *policy) { - switch (nm_active_connection_get_state (active)) { - case NM_ACTIVE_CONNECTION_STATE_ACTIVATED: - if (NM_IS_VPN_CONNECTION (active)) - vpn_connection_activated (policy, NM_VPN_CONNECTION (active)); - break; - case NM_ACTIVE_CONNECTION_STATE_DEACTIVATED: - if (NM_IS_VPN_CONNECTION (active)) - vpn_connection_deactivated (policy, NM_VPN_CONNECTION (active)); - break; - default: - break; - } + NMActiveConnectionState state = nm_active_connection_get_state (active); + + if (state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) + process_secondaries (policy, active, TRUE); + else if (state == NM_ACTIVE_CONNECTION_STATE_DEACTIVATED) + process_secondaries (policy, active, FALSE); } static void @@ -1806,7 +1808,13 @@ active_connection_added (NMManager *manager, NMActiveConnection *active, gpointer user_data) { - NMPolicy *policy = (NMPolicy *) user_data; + NMPolicy *policy = NM_POLICY (user_data); + + if (NM_IS_VPN_CONNECTION (active)) { + g_signal_connect (active, NM_VPN_CONNECTION_INTERNAL_STATE_CHANGED, + G_CALLBACK (vpn_connection_state_changed), + policy); + } g_signal_connect (active, "notify::" NM_ACTIVE_CONNECTION_STATE, G_CALLBACK (active_connection_state_changed), @@ -1818,9 +1826,14 @@ active_connection_removed (NMManager *manager, NMActiveConnection *active, gpointer user_data) { + NMPolicy *policy = NM_POLICY (user_data); + + g_signal_handlers_disconnect_by_func (active, + vpn_connection_state_changed, + policy); g_signal_handlers_disconnect_by_func (active, active_connection_state_changed, - (NMPolicy *) user_data); + policy); } /**************************************************************************/ @@ -1829,33 +1842,20 @@ static void schedule_activate_all (NMPolicy *policy) { NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); - GSList *iter, *devices; + const GSList *iter; - devices = nm_manager_get_devices (priv->manager); - for (iter = devices; iter; iter = g_slist_next (iter)) - schedule_activate_check (policy, NM_DEVICE (iter->data), 0); + for (iter = nm_manager_get_devices (priv->manager); iter; iter = g_slist_next (iter)) + schedule_activate_check (policy, NM_DEVICE (iter->data)); } static void connection_added (NMSettings *settings, - NMConnection *connection, + NMSettingsConnection *connection, gpointer user_data) { - set_connection_auto_retries (connection, RETRIES_DEFAULT); - schedule_activate_all ((NMPolicy *) user_data); -} - -static void -connections_loaded (NMSettings *settings, gpointer user_data) -{ - // FIXME: "connections-loaded" signal is emmitted *before* we connect to it - // in nm_policy_new(). So this function is never called. Currently we work around - // that by calling reset_retries_all() in nm_policy_new() - - /* Initialize connections' auto-retries */ - reset_retries_all (settings, NULL); + NMPolicy *policy = NM_POLICY (user_data); - schedule_activate_all ((NMPolicy *) user_data); + schedule_activate_all (policy); } static void @@ -1875,11 +1875,10 @@ firewall_update_zone (NMPolicy *policy, NMConnection *connection) { NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); NMSettingConnection *s_con = nm_connection_get_setting_connection (connection); - GSList *iter, *devices; + const GSList *iter; - devices = nm_manager_get_devices (priv->manager); /* find dev with passed connection and change zone its interface belongs to */ - for (iter = devices; iter; iter = g_slist_next (iter)) { + for (iter = nm_manager_get_devices (priv->manager); iter; iter = g_slist_next (iter)) { NMDevice *dev = NM_DEVICE (iter->data); if ( (nm_device_get_connection (dev) == connection) @@ -1902,20 +1901,22 @@ firewall_started (NMFirewallManager *manager, NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); NMConnection *connection; NMSettingConnection *s_con; - GSList *iter, *devices; + const GSList *iter; - devices = nm_manager_get_devices (priv->manager); /* add interface of each device to correct zone */ - for (iter = devices; iter; iter = g_slist_next (iter)) { + for (iter = nm_manager_get_devices (priv->manager); iter; iter = g_slist_next (iter)) { NMDevice *dev = NM_DEVICE (iter->data); connection = nm_device_get_connection (dev); + if (!connection) + continue; + s_con = nm_connection_get_setting_connection (connection); if (nm_device_get_state (dev) == NM_DEVICE_STATE_ACTIVATED) { nm_firewall_manager_add_or_change_zone (priv->fw_manager, nm_device_get_ip_iface (dev), nm_setting_connection_get_zone (s_con), - TRUE, /* add zone */ + FALSE, /* still change zone */ add_or_change_zone_cb, g_object_ref (dev)); } @@ -1934,29 +1935,23 @@ dns_config_changed (NMDnsManager *dns_manager, gpointer user_data) */ /* Stop a lookup thread if any. */ - if (priv->lookup) { - hostname_thread_kill (priv->lookup); - priv->lookup = NULL; + if (priv->lookup_cancellable) { + g_cancellable_cancel (priv->lookup_cancellable); + g_clear_object (&priv->lookup_cancellable); } /* Re-start the hostname lookup thread if we don't have hostname yet. */ - if (priv->lookup_ipv4_addr) { - char buf[INET_ADDRSTRLEN]; - struct in_addr addr = { .s_addr = priv->lookup_ipv4_addr }; - - if (!inet_ntop (AF_INET, &addr, buf, sizeof (buf))) - strcpy (buf, "(unknown)"); - nm_log_dbg (LOGD_DNS, "restarting IPv4 reverse-lookup thread for address %s'", buf); - - priv->lookup = hostname4_thread_new (priv->lookup_ipv4_addr, lookup_callback, policy); - } else if (priv->lookup_ipv6_addr) { - char buf[INET6_ADDRSTRLEN]; - - if (!inet_ntop (AF_INET6, priv->lookup_ipv6_addr, buf, sizeof (buf))) - strcpy (buf, "(unknown)"); - nm_log_dbg (LOGD_DNS, "restarting IPv6 reverse-lookup thread for address %s'", buf); - - priv->lookup = hostname6_thread_new (priv->lookup_ipv6_addr, lookup_callback, policy); + if (priv->lookup_addr) { + char *str = g_inet_address_to_string (priv->lookup_addr); + + nm_log_dbg (LOGD_DNS, "restarting reverse-lookup thread for address %s", str); + g_free (str); + + priv->lookup_cancellable = g_cancellable_new (); + g_resolver_lookup_by_address_async (priv->resolver, + priv->lookup_addr, + priv->lookup_cancellable, + lookup_callback, policy); } } @@ -1969,12 +1964,18 @@ connection_updated (NMSettings *settings, firewall_update_zone (policy, connection); - /* Reset auto retries back to default since connection was updated */ - set_connection_auto_retries (connection, RETRIES_DEFAULT); - schedule_activate_all (policy); } +static void +connection_updated_by_user (NMSettings *settings, + NMSettingsConnection *connection, + gpointer user_data) +{ + /* Reset auto retries back to default since connection was updated */ + nm_settings_connection_reset_autoconnect_retries (connection); +} + static void _deactivate_if_active (NMManager *manager, NMConnection *connection) { @@ -2032,12 +2033,14 @@ secret_agent_registered (NMSettings *settings, NMSecretAgent *agent, gpointer user_data) { + NMPolicy *policy = NM_POLICY (user_data); + /* The registered secret agent may provide some missing secrets. Thus we * reset retries count here and schedule activation, so that the * connections failed due to missing secrets may re-try auto-connection. */ - reset_retries_for_failed_secrets (settings); - schedule_activate_all ((NMPolicy *) user_data); + reset_autoconnect_for_failed_secrets (policy); + schedule_activate_all (policy); } static void @@ -2094,9 +2097,12 @@ nm_policy_new (NMManager *manager, NMSettings *settings) G_CALLBACK (firewall_started), policy); priv->fw_started_id = id; - priv->dns_manager = nm_dns_manager_get (NULL); + priv->dns_manager = nm_dns_manager_get (); + nm_dns_manager_set_initial_hostname (priv->dns_manager, priv->orig_hostname); priv->config_changed_id = g_signal_connect (priv->dns_manager, "config-changed", - G_CALLBACK (dns_config_changed), policy); + G_CALLBACK (dns_config_changed), policy); + + priv->resolver = g_resolver_get_default (); _connect_manager_signal (policy, "state-changed", global_state_changed); _connect_manager_signal (policy, "notify::" NM_MANAGER_HOSTNAME, hostname_changed); @@ -2107,17 +2113,14 @@ nm_policy_new (NMManager *manager, NMSettings *settings) _connect_manager_signal (policy, NM_MANAGER_ACTIVE_CONNECTION_ADDED, active_connection_added); _connect_manager_signal (policy, NM_MANAGER_ACTIVE_CONNECTION_REMOVED, active_connection_removed); - _connect_settings_signal (policy, NM_SETTINGS_SIGNAL_CONNECTIONS_LOADED, connections_loaded); _connect_settings_signal (policy, NM_SETTINGS_SIGNAL_CONNECTION_ADDED, connection_added); _connect_settings_signal (policy, NM_SETTINGS_SIGNAL_CONNECTION_UPDATED, connection_updated); + _connect_settings_signal (policy, NM_SETTINGS_SIGNAL_CONNECTION_UPDATED_BY_USER, connection_updated_by_user); _connect_settings_signal (policy, NM_SETTINGS_SIGNAL_CONNECTION_REMOVED, connection_removed); _connect_settings_signal (policy, NM_SETTINGS_SIGNAL_CONNECTION_VISIBILITY_CHANGED, connection_visibility_changed); _connect_settings_signal (policy, NM_SETTINGS_SIGNAL_AGENT_REGISTERED, secret_agent_registered); - /* Initialize connections' auto-retries */ - reset_retries_all (priv->settings, NULL); - initialized = TRUE; return policy; } @@ -2184,17 +2187,16 @@ dispose (GObject *object) NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); const GSList *connections, *iter; - /* Tell any existing hostname lookup thread to die, it'll get cleaned up - * by the lookup thread callback. - */ - if (priv->lookup) { - hostname_thread_kill (priv->lookup); - priv->lookup = NULL; + /* Tell any existing hostname lookup thread to die. */ + if (priv->lookup_cancellable) { + g_cancellable_cancel (priv->lookup_cancellable); + g_clear_object (&priv->lookup_cancellable); } - g_free (priv->lookup_ipv6_addr); + g_clear_object (&priv->lookup_addr); + g_clear_object (&priv->resolver); - g_slist_free_full (priv->pending_activation_checks, (GDestroyNotify) activate_data_free); - priv->pending_activation_checks = NULL; + while (priv->pending_activation_checks) + activate_data_free (priv->pending_activation_checks->data); g_slist_free_full (priv->pending_secondaries, (GDestroyNotify) pending_secondary_data_free); priv->pending_secondaries = NULL; @@ -2207,19 +2209,16 @@ dispose (GObject *object) if (priv->dns_manager) { g_signal_handler_disconnect (priv->dns_manager, priv->config_changed_id); - g_object_unref (priv->dns_manager); priv->dns_manager = NULL; } for (iter = priv->manager_ids; iter; iter = g_slist_next (iter)) g_signal_handler_disconnect (priv->manager, GPOINTER_TO_UINT (iter->data)); - g_slist_free (priv->manager_ids); - priv->manager_ids = NULL; + g_clear_pointer (&priv->manager_ids, g_slist_free); for (iter = priv->settings_ids; iter; iter = g_slist_next (iter)) g_signal_handler_disconnect (priv->settings, GPOINTER_TO_UINT (iter->data)); - g_slist_free (priv->settings_ids); - priv->settings_ids = NULL; + g_clear_pointer (&priv->settings_ids, g_slist_free); for (iter = priv->dev_ids; iter; iter = g_slist_next (iter)) { DeviceSignalId *data = iter->data; @@ -2227,8 +2226,7 @@ dispose (GObject *object) g_signal_handler_disconnect (data->device, data->id); g_slice_free (DeviceSignalId, data); } - g_slist_free (priv->dev_ids); - priv->dev_ids = NULL; + g_clear_pointer (&priv->dev_ids, g_slist_free); /* The manager should have disposed of ActiveConnections already, which * will have called active_connection_removed() and thus we don't need @@ -2242,10 +2240,8 @@ dispose (GObject *object) priv->reset_retries_id = 0; } - g_free (priv->orig_hostname); - priv->orig_hostname = NULL; - g_free (priv->cur_hostname); - priv->cur_hostname = NULL; + g_clear_pointer (&priv->orig_hostname, g_free); + g_clear_pointer (&priv->cur_hostname, g_free); g_clear_object (&priv->settings); diff --git a/src/nm-ppp-manager-glue.h b/src/nm-ppp-manager-glue.h new file mode 100644 index 00000000..4b215165 --- /dev/null +++ b/src/nm-ppp-manager-glue.h @@ -0,0 +1,174 @@ +/* Generated by dbus-binding-tool; do not edit! */ + + +#ifndef __dbus_glib_marshal_nm_ppp_manager_MARSHAL_H__ +#define __dbus_glib_marshal_nm_ppp_manager_MARSHAL_H__ + +#include + +G_BEGIN_DECLS + +#ifdef G_ENABLE_DEBUG +#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v) +#define g_marshal_value_peek_char(v) g_value_get_schar (v) +#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v) +#define g_marshal_value_peek_int(v) g_value_get_int (v) +#define g_marshal_value_peek_uint(v) g_value_get_uint (v) +#define g_marshal_value_peek_long(v) g_value_get_long (v) +#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v) +#define g_marshal_value_peek_int64(v) g_value_get_int64 (v) +#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v) +#define g_marshal_value_peek_enum(v) g_value_get_enum (v) +#define g_marshal_value_peek_flags(v) g_value_get_flags (v) +#define g_marshal_value_peek_float(v) g_value_get_float (v) +#define g_marshal_value_peek_double(v) g_value_get_double (v) +#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v) +#define g_marshal_value_peek_param(v) g_value_get_param (v) +#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v) +#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v) +#define g_marshal_value_peek_object(v) g_value_get_object (v) +#define g_marshal_value_peek_variant(v) g_value_get_variant (v) +#else /* !G_ENABLE_DEBUG */ +/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API. + * Do not access GValues directly in your code. Instead, use the + * g_value_get_*() functions + */ +#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int +#define g_marshal_value_peek_char(v) (v)->data[0].v_int +#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint +#define g_marshal_value_peek_int(v) (v)->data[0].v_int +#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint +#define g_marshal_value_peek_long(v) (v)->data[0].v_long +#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 +#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 +#define g_marshal_value_peek_enum(v) (v)->data[0].v_long +#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_float(v) (v)->data[0].v_float +#define g_marshal_value_peek_double(v) (v)->data[0].v_double +#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer +#endif /* !G_ENABLE_DEBUG */ + + +/* NONE:POINTER */ +#define dbus_glib_marshal_nm_ppp_manager_VOID__POINTER g_cclosure_marshal_VOID__POINTER +#define dbus_glib_marshal_nm_ppp_manager_NONE__POINTER dbus_glib_marshal_nm_ppp_manager_VOID__POINTER + +/* BOOLEAN:UINT,POINTER */ +extern void dbus_glib_marshal_nm_ppp_manager_BOOLEAN__UINT_POINTER (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); +void +dbus_glib_marshal_nm_ppp_manager_BOOLEAN__UINT_POINTER (GClosure *closure, + GValue *return_value G_GNUC_UNUSED, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint G_GNUC_UNUSED, + gpointer marshal_data) +{ + typedef gboolean (*GMarshalFunc_BOOLEAN__UINT_POINTER) (gpointer data1, + guint arg_1, + gpointer arg_2, + gpointer data2); + register GMarshalFunc_BOOLEAN__UINT_POINTER callback; + register GCClosure *cc = (GCClosure*) closure; + register gpointer data1, data2; + gboolean v_return; + + g_return_if_fail (return_value != NULL); + g_return_if_fail (n_param_values == 3); + + if (G_CCLOSURE_SWAP_DATA (closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer (param_values + 0); + } + else + { + data1 = g_value_peek_pointer (param_values + 0); + data2 = closure->data; + } + callback = (GMarshalFunc_BOOLEAN__UINT_POINTER) (marshal_data ? marshal_data : cc->callback); + + v_return = callback (data1, + g_marshal_value_peek_uint (param_values + 1), + g_marshal_value_peek_pointer (param_values + 2), + data2); + + g_value_set_boolean (return_value, v_return); +} + +/* BOOLEAN:BOXED,POINTER */ +extern void dbus_glib_marshal_nm_ppp_manager_BOOLEAN__BOXED_POINTER (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); +void +dbus_glib_marshal_nm_ppp_manager_BOOLEAN__BOXED_POINTER (GClosure *closure, + GValue *return_value G_GNUC_UNUSED, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint G_GNUC_UNUSED, + gpointer marshal_data) +{ + typedef gboolean (*GMarshalFunc_BOOLEAN__BOXED_POINTER) (gpointer data1, + gpointer arg_1, + gpointer arg_2, + gpointer data2); + register GMarshalFunc_BOOLEAN__BOXED_POINTER callback; + register GCClosure *cc = (GCClosure*) closure; + register gpointer data1, data2; + gboolean v_return; + + g_return_if_fail (return_value != NULL); + g_return_if_fail (n_param_values == 3); + + if (G_CCLOSURE_SWAP_DATA (closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer (param_values + 0); + } + else + { + data1 = g_value_peek_pointer (param_values + 0); + data2 = closure->data; + } + callback = (GMarshalFunc_BOOLEAN__BOXED_POINTER) (marshal_data ? marshal_data : cc->callback); + + v_return = callback (data1, + g_marshal_value_peek_boxed (param_values + 1), + g_marshal_value_peek_pointer (param_values + 2), + data2); + + g_value_set_boolean (return_value, v_return); +} + +G_END_DECLS + +#endif /* __dbus_glib_marshal_nm_ppp_manager_MARSHAL_H__ */ + +#include +static const DBusGMethodInfo dbus_glib_nm_ppp_manager_methods[] = { + { (GCallback) impl_ppp_manager_need_secrets, dbus_glib_marshal_nm_ppp_manager_NONE__POINTER, 0 }, + { (GCallback) impl_ppp_manager_set_ip4_config, dbus_glib_marshal_nm_ppp_manager_BOOLEAN__BOXED_POINTER, 84 }, + { (GCallback) impl_ppp_manager_set_state, dbus_glib_marshal_nm_ppp_manager_BOOLEAN__UINT_POINTER, 150 }, +}; + +const DBusGObjectInfo dbus_glib_nm_ppp_manager_object_info = { 1, + dbus_glib_nm_ppp_manager_methods, + 3, +"org.freedesktop.NetworkManager.PPP\0NeedSecrets\0A\0username\0O\0F\0N\0s\0password\0O\0F\0N\0s\0\0org.freedesktop.NetworkManager.PPP\0SetIp4Config\0S\0config\0I\0a{sv}\0\0org.freedesktop.NetworkManager.PPP\0SetState\0S\0state\0I\0u\0\0\0", +"\0", +"\0" +}; + diff --git a/src/nm-properties-changed-signal.c b/src/nm-properties-changed-signal.c index 871d1bb0..6e07c257 100644 --- a/src/nm-properties-changed-signal.c +++ b/src/nm-properties-changed-signal.c @@ -23,19 +23,31 @@ #include #include -#ifdef DEBUG #include "nm-logging.h" -#endif #include "nm-properties-changed-signal.h" #include "nm-dbus-glib-types.h" -#define NM_DBUS_PROPERTY_CHANGED "NM_DBUS_PROPERTY_CHANGED" +typedef struct { + GHashTable *exported_props; + guint signal_id; +} NMPropertiesChangedClassInfo; typedef struct { GHashTable *hash; - gulong signal_id; + guint signal_id; guint idle_id; -} PropertiesChangedInfo; +} NMPropertiesChangedInfo; + +static GQuark +nm_properties_changed_signal_quark (void) +{ + static GQuark q; + + if (G_UNLIKELY (q == 0)) + q = g_quark_from_static_string ("nm-properties-changed-signal"); + + return q; +} static void destroy_value (gpointer data) @@ -46,72 +58,57 @@ destroy_value (gpointer data) g_slice_free (GValue, val); } -static PropertiesChangedInfo * -properties_changed_info_new (void) -{ - PropertiesChangedInfo *info; - - info = g_slice_new0 (PropertiesChangedInfo); - info->hash = g_hash_table_new_full (g_str_hash, g_str_equal, - (GDestroyNotify) g_free, - destroy_value); - return info; -} - static void properties_changed_info_destroy (gpointer data) { - PropertiesChangedInfo *info = (PropertiesChangedInfo *) data; + NMPropertiesChangedInfo *info = data; if (info->idle_id) g_source_remove (info->idle_id); g_hash_table_destroy (info->hash); - g_slice_free (PropertiesChangedInfo, info); + g_slice_free (NMPropertiesChangedInfo, info); } -#ifdef DEBUG static void add_to_string (gpointer key, gpointer value, gpointer user_data) { - char *buf = (char *) user_data; - GValue str_val = { 0, }; + const char *name = (const char *) key; + GString *buf = user_data; + GValue str_val = G_VALUE_INIT; g_value_init (&str_val, G_TYPE_STRING); if (!g_value_transform ((GValue *) value, &str_val)) { if (G_VALUE_HOLDS_OBJECT (value)) { GObject *obj = g_value_get_object (value); - if (g_value_get_object (value)) { - sprintf (buf + strlen (buf), "{%s: %p (%s)}, ", - (const char *) key, obj, G_OBJECT_TYPE_NAME (obj)); - } else { - sprintf (buf + strlen (buf), "{%s: %p}, ", (const char *) key, obj); - } + if (obj) { + g_string_append_printf (buf, "{%s: %p (%s)}, ", name, obj, + G_OBJECT_TYPE_NAME (obj)); + } else + g_string_append_printf (buf, "{%s: %p}, ", name, obj); } else - sprintf (buf + strlen (buf), "{%s: }, ", (const char *) key); - } else { - sprintf (buf + strlen (buf), "{%s: %s}, ", (const char *) key, g_value_get_string (&str_val)); - } + g_string_append_printf (buf, "{%s: }, ", name); + } else + g_string_append_printf (buf, "{%s: %s}, ", name, g_value_get_string (&str_val)); g_value_unset (&str_val); } -#endif static gboolean properties_changed (gpointer data) { GObject *object = G_OBJECT (data); - PropertiesChangedInfo *info = (PropertiesChangedInfo *) g_object_get_data (object, NM_DBUS_PROPERTY_CHANGED); + NMPropertiesChangedInfo *info = g_object_get_qdata (object, nm_properties_changed_signal_quark ()); g_assert (info); -#ifdef DEBUG - { - char buf[2048] = { 0, }; - g_hash_table_foreach (info->hash, add_to_string, &buf); - nm_log_dbg (LOGD_CORE, "%s -> %s", G_OBJECT_TYPE_NAME (object), buf); + if (nm_logging_enabled (LOGL_DEBUG, LOGD_DBUS_PROPS)) { + GString *buf = g_string_new (NULL); + + g_hash_table_foreach (info->hash, add_to_string, buf); + nm_log_dbg (LOGD_DBUS_PROPS, "%s -> %s", G_OBJECT_TYPE_NAME (object), buf->str); + g_string_free (buf, TRUE); } -#endif g_signal_emit (object, info->signal_id, 0, info->hash); g_hash_table_remove_all (info->hash); @@ -123,82 +120,122 @@ static void idle_id_reset (gpointer data) { GObject *object = G_OBJECT (data); - PropertiesChangedInfo *info = (PropertiesChangedInfo *) g_object_get_data (object, NM_DBUS_PROPERTY_CHANGED); + NMPropertiesChangedInfo *info = g_object_get_qdata (object, nm_properties_changed_signal_quark ()); /* info is unset when the object is being destroyed */ if (info) info->idle_id = 0; } -static char* -uscore_to_wincaps (const char *uscore) -{ - const char *p; - GString *str; - gboolean last_was_uscore; - - last_was_uscore = TRUE; - - str = g_string_new (NULL); - p = uscore; - while (p && *p) { - if (*p == '-' || *p == '_') - last_was_uscore = TRUE; - else { - if (last_was_uscore) { - g_string_append_c (str, g_ascii_toupper (*p)); - last_was_uscore = FALSE; - } else - g_string_append_c (str, *p); - } - ++p; - } - - return g_string_free (str, FALSE); -} - static void notify (GObject *object, GParamSpec *pspec) { - PropertiesChangedInfo *info; + NMPropertiesChangedClassInfo *classinfo; + NMPropertiesChangedInfo *info; + const char *dbus_property_name = NULL; GValue *value; + GType type; - /* Ignore properties that shouldn't be exported */ - if (pspec->flags & NM_PROPERTY_PARAM_NO_EXPORT) + for (type = G_OBJECT_TYPE (object); type; type = g_type_parent (type)) { + classinfo = g_type_get_qdata (type, nm_properties_changed_signal_quark ()); + if (!classinfo) + continue; + + dbus_property_name = g_hash_table_lookup (classinfo->exported_props, pspec->name); + if (dbus_property_name) + break; + } + if (!dbus_property_name) { + nm_log_dbg (LOGD_DBUS_PROPS, "ignoring notification for prop %s on type %s", + pspec->name, G_OBJECT_TYPE_NAME (object)); return; + } - info = (PropertiesChangedInfo *) g_object_get_data (object, NM_DBUS_PROPERTY_CHANGED); + info = g_object_get_qdata (object, nm_properties_changed_signal_quark ()); if (!info) { - info = properties_changed_info_new (); - g_object_set_data_full (object, NM_DBUS_PROPERTY_CHANGED, info, properties_changed_info_destroy); - info->signal_id = g_signal_lookup ("properties-changed", G_OBJECT_TYPE (object)); - g_assert (info->signal_id); + info = g_slice_new0 (NMPropertiesChangedInfo); + info->hash = g_hash_table_new_full (g_str_hash, g_str_equal, + NULL, destroy_value); + info->signal_id = classinfo->signal_id; + + g_object_set_qdata_full (object, nm_properties_changed_signal_quark (), + info, properties_changed_info_destroy); } value = g_slice_new0 (GValue); g_value_init (value, pspec->value_type); g_object_get_property (object, pspec->name, value); - g_hash_table_insert (info->hash, uscore_to_wincaps (pspec->name), value); + g_hash_table_insert (info->hash, (char *) dbus_property_name, value); if (!info->idle_id) info->idle_id = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, properties_changed, object, idle_id_reset); } -guint -nm_properties_changed_signal_new (GObjectClass *object_class, - guint class_offset) +static NMPropertiesChangedClassInfo * +nm_properties_changed_signal_setup_type (GType type) { - guint id; + NMPropertiesChangedClassInfo *classinfo; + NMPropertiesChangedClassInfo *parent_classinfo = NULL; + GObjectClass *object_class; + GType parent; + classinfo = g_slice_new (NMPropertiesChangedClassInfo); + g_type_set_qdata (type, nm_properties_changed_signal_quark (), classinfo); + + object_class = g_type_class_ref (type); object_class->notify = notify; + g_type_class_unref (object_class); + + classinfo->exported_props = g_hash_table_new (g_str_hash, g_str_equal); + + /* See if we've already added the signal to a parent class. (We can't just use + * g_signal_lookup() here because it prints a warning if the signal doesn't exist!) + */ + parent = g_type_parent (type); + while (parent) { + parent_classinfo = g_type_get_qdata (parent, nm_properties_changed_signal_quark ()); + if (parent_classinfo) + break; + parent = g_type_parent (parent); + } - id = g_signal_new ("properties-changed", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - class_offset, - NULL, NULL, - g_cclosure_marshal_VOID__BOXED, - G_TYPE_NONE, 1, DBUS_TYPE_G_MAP_OF_VARIANT); + if (parent_classinfo) + classinfo->signal_id = parent_classinfo->signal_id; + else { + classinfo->signal_id = g_signal_new ("properties-changed", + type, + G_SIGNAL_RUN_FIRST, + 0, + NULL, NULL, + g_cclosure_marshal_VOID__BOXED, + G_TYPE_NONE, 1, DBUS_TYPE_G_MAP_OF_VARIANT); + } + + return classinfo; +} + +void +nm_properties_changed_signal_add_property (GType type, + const char *dbus_property_name, + const char *gobject_property_name) +{ + NMPropertiesChangedClassInfo *classinfo; + char *hyphen_name, *p; + + classinfo = g_type_get_qdata (type, nm_properties_changed_signal_quark ()); + if (!classinfo) + classinfo = nm_properties_changed_signal_setup_type (type); - return id; + g_hash_table_insert (classinfo->exported_props, + (char *) gobject_property_name, + (char *) dbus_property_name); + + hyphen_name = g_strdup (gobject_property_name); + for (p = hyphen_name; *p; p++) { + if (*p == '_') + *p = '-'; + } + g_hash_table_insert (classinfo->exported_props, + hyphen_name, + (char *) dbus_property_name); } diff --git a/src/nm-properties-changed-signal.h b/src/nm-properties-changed-signal.h index b87e34e1..97a3b2c0 100644 --- a/src/nm-properties-changed-signal.h +++ b/src/nm-properties-changed-signal.h @@ -24,9 +24,8 @@ #include -#define NM_PROPERTY_PARAM_NO_EXPORT (1 << (0 + G_PARAM_USER_SHIFT)) - -guint nm_properties_changed_signal_new (GObjectClass *object_class, - guint class_offset); +void nm_properties_changed_signal_add_property (GType type, + const char *dbus_property_name, + const char *gobject_property_name); #endif /* _NM_PROPERTIES_CHANGED_SIGNAL_H_ */ diff --git a/src/nm-rfkill-manager.c b/src/nm-rfkill-manager.c new file mode 100644 index 00000000..b02f85f5 --- /dev/null +++ b/src/nm-rfkill-manager.c @@ -0,0 +1,422 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2009 - 2013 Red Hat, Inc. + */ + +#include + +#include +#include + +#include "nm-rfkill-manager.h" +#include "nm-logging.h" + +typedef struct { + GUdevClient *client; + + /* Authoritative rfkill state (RFKILL_* enum) */ + RfKillState rfkill_states[RFKILL_TYPE_MAX]; + GSList *killswitches; + +} NMRfkillManagerPrivate; + +#define NM_RFKILL_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_RFKILL_MANAGER, NMRfkillManagerPrivate)) + +G_DEFINE_TYPE (NMRfkillManager, nm_rfkill_manager, G_TYPE_OBJECT) + +enum { + RFKILL_CHANGED, + + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + + +typedef struct { + char *name; + guint64 seqnum; + char *path; + char *driver; + RfKillType rtype; + gint state; + gboolean platform; +} Killswitch; + +RfKillState +nm_rfkill_manager_get_rfkill_state (NMRfkillManager *self, RfKillType rtype) +{ + g_return_val_if_fail (self != NULL, RFKILL_UNBLOCKED); + g_return_val_if_fail (rtype < RFKILL_TYPE_MAX, RFKILL_UNBLOCKED); + + return NM_RFKILL_MANAGER_GET_PRIVATE (self)->rfkill_states[rtype]; +} + +static const char * +rfkill_type_to_desc (RfKillType rtype) +{ + if (rtype == 0) + return "WiFi"; + else if (rtype == 1) + return "WWAN"; + else if (rtype == 2) + return "WiMAX"; + return "unknown"; +} + +static const char * +rfkill_state_to_desc (RfKillState rstate) +{ + if (rstate == 0) + return "unblocked"; + else if (rstate == 1) + return "soft-blocked"; + else if (rstate == 2) + return "hard-blocked"; + return "unknown"; +} + +static Killswitch * +killswitch_new (GUdevDevice *device, RfKillType rtype) +{ + Killswitch *ks; + GUdevDevice *parent = NULL, *grandparent = NULL; + const char *driver, *subsys, *parent_subsys = NULL; + + ks = g_malloc0 (sizeof (Killswitch)); + ks->name = g_strdup (g_udev_device_get_name (device)); + ks->seqnum = g_udev_device_get_seqnum (device); + ks->path = g_strdup (g_udev_device_get_sysfs_path (device)); + ks->rtype = rtype; + + driver = g_udev_device_get_property (device, "DRIVER"); + subsys = g_udev_device_get_subsystem (device); + + /* Check parent for various attributes */ + parent = g_udev_device_get_parent (device); + if (parent) { + parent_subsys = g_udev_device_get_subsystem (parent); + if (!driver) + driver = g_udev_device_get_property (parent, "DRIVER"); + if (!driver) { + /* Sigh; try the grandparent */ + grandparent = g_udev_device_get_parent (parent); + if (grandparent) + driver = g_udev_device_get_property (grandparent, "DRIVER"); + } + } + + if (!driver) + driver = "(unknown)"; + ks->driver = g_strdup (driver); + + if ( g_strcmp0 (subsys, "platform") == 0 + || g_strcmp0 (parent_subsys, "platform") == 0 + || g_strcmp0 (subsys, "acpi") == 0 + || g_strcmp0 (parent_subsys, "acpi") == 0) + ks->platform = TRUE; + + if (grandparent) + g_object_unref (grandparent); + if (parent) + g_object_unref (parent); + return ks; +} + +static void +killswitch_destroy (Killswitch *ks) +{ + g_return_if_fail (ks != NULL); + + g_free (ks->name); + g_free (ks->path); + g_free (ks->driver); + memset (ks, 0, sizeof (Killswitch)); + g_free (ks); +} + +NMRfkillManager * +nm_rfkill_manager_new (void) +{ + return NM_RFKILL_MANAGER (g_object_new (NM_TYPE_RFKILL_MANAGER, NULL)); +} + +static RfKillState +sysfs_state_to_nm_state (gint sysfs_state) +{ + switch (sysfs_state) { + case 0: + return RFKILL_SOFT_BLOCKED; + case 1: + return RFKILL_UNBLOCKED; + case 2: + return RFKILL_HARD_BLOCKED; + default: + nm_log_warn (LOGD_RFKILL, "unhandled rfkill state %d", sysfs_state); + break; + } + return RFKILL_UNBLOCKED; +} + +static void +recheck_killswitches (NMRfkillManager *self) +{ + NMRfkillManagerPrivate *priv = NM_RFKILL_MANAGER_GET_PRIVATE (self); + GSList *iter; + RfKillState poll_states[RFKILL_TYPE_MAX]; + RfKillState platform_states[RFKILL_TYPE_MAX]; + gboolean platform_checked[RFKILL_TYPE_MAX]; + int i; + + /* Default state is unblocked */ + for (i = 0; i < RFKILL_TYPE_MAX; i++) { + poll_states[i] = RFKILL_UNBLOCKED; + platform_states[i] = RFKILL_UNBLOCKED; + platform_checked[i] = FALSE; + } + + /* Poll the states of all killswitches */ + for (iter = priv->killswitches; iter; iter = g_slist_next (iter)) { + Killswitch *ks = iter->data; + GUdevDevice *device; + RfKillState dev_state; + int sysfs_state; + + device = g_udev_client_query_by_subsystem_and_name (priv->client, "rfkill", ks->name); + if (device) { + sysfs_state = g_udev_device_get_property_as_int (device, "RFKILL_STATE"); + dev_state = sysfs_state_to_nm_state (sysfs_state); + + nm_log_dbg (LOGD_RFKILL, "%s rfkill%s switch %s state now %d/%u", + rfkill_type_to_desc (ks->rtype), + ks->platform ? " platform" : "", + ks->name, + sysfs_state, + dev_state); + + if (ks->platform == FALSE) { + if (dev_state > poll_states[ks->rtype]) + poll_states[ks->rtype] = dev_state; + } else { + platform_checked[ks->rtype] = TRUE; + if (dev_state > platform_states[ks->rtype]) + platform_states[ks->rtype] = dev_state; + } + g_object_unref (device); + } + } + + /* Log and emit change signal for final rfkill states */ + for (i = 0; i < RFKILL_TYPE_MAX; i++) { + if (platform_checked[i] == TRUE) { + /* blocked platform switch state overrides device state, otherwise + * let the device state stand. (bgo #655773) + */ + if (platform_states[i] != RFKILL_UNBLOCKED) + poll_states[i] = platform_states[i]; + } + + if (poll_states[i] != priv->rfkill_states[i]) { + nm_log_dbg (LOGD_RFKILL, "%s rfkill state now '%s'", + rfkill_type_to_desc (i), + rfkill_state_to_desc (poll_states[i])); + + priv->rfkill_states[i] = poll_states[i]; + g_signal_emit (self, signals[RFKILL_CHANGED], 0, i, priv->rfkill_states[i]); + } + } +} + +static Killswitch * +killswitch_find_by_name (NMRfkillManager *self, const char *name) +{ + NMRfkillManagerPrivate *priv = NM_RFKILL_MANAGER_GET_PRIVATE (self); + GSList *iter; + + g_return_val_if_fail (name != NULL, NULL); + + for (iter = priv->killswitches; iter; iter = g_slist_next (iter)) { + Killswitch *candidate = iter->data; + + if (!strcmp (name, candidate->name)) + return candidate; + } + return NULL; +} + +static const RfKillType +rfkill_type_to_enum (const char *str) +{ + g_return_val_if_fail (str != NULL, RFKILL_TYPE_UNKNOWN); + + if (!strcmp (str, "wlan")) + return RFKILL_TYPE_WLAN; + else if (!strcmp (str, "wwan")) + return RFKILL_TYPE_WWAN; + else if (!strcmp (str, "wimax")) + return RFKILL_TYPE_WIMAX; + + return RFKILL_TYPE_UNKNOWN; +} + +static void +add_one_killswitch (NMRfkillManager *self, GUdevDevice *device) +{ + NMRfkillManagerPrivate *priv = NM_RFKILL_MANAGER_GET_PRIVATE (self); + const char *str_type; + RfKillType rtype; + Killswitch *ks; + + str_type = g_udev_device_get_property (device, "RFKILL_TYPE"); + rtype = rfkill_type_to_enum (str_type); + if (rtype == RFKILL_TYPE_UNKNOWN) + return; + + ks = killswitch_new (device, rtype); + priv->killswitches = g_slist_prepend (priv->killswitches, ks); + + nm_log_info (LOGD_RFKILL, "%s: found %s radio killswitch (at %s) (%sdriver %s)", + ks->name, + rfkill_type_to_desc (rtype), + ks->path, + ks->platform ? "platform " : "", + ks->driver ? ks->driver : ""); +} + +static void +rfkill_add (NMRfkillManager *self, GUdevDevice *device) +{ + const char *name; + + g_return_if_fail (device != NULL); + name = g_udev_device_get_name (device); + g_return_if_fail (name != NULL); + + if (!killswitch_find_by_name (self, name)) + add_one_killswitch (self, device); +} + +static void +rfkill_remove (NMRfkillManager *self, + GUdevDevice *device) +{ + NMRfkillManagerPrivate *priv = NM_RFKILL_MANAGER_GET_PRIVATE (self); + GSList *iter; + const char *name; + + g_return_if_fail (device != NULL); + name = g_udev_device_get_name (device); + g_return_if_fail (name != NULL); + + for (iter = priv->killswitches; iter; iter = g_slist_next (iter)) { + Killswitch *ks = iter->data; + + if (!strcmp (ks->name, name)) { + nm_log_info (LOGD_RFKILL, "radio killswitch %s disappeared", ks->path); + priv->killswitches = g_slist_remove (priv->killswitches, ks); + killswitch_destroy (ks); + break; + } + } +} + +static void +handle_uevent (GUdevClient *client, + const char *action, + GUdevDevice *device, + gpointer user_data) +{ + NMRfkillManager *self = NM_RFKILL_MANAGER (user_data); + const char *subsys; + + g_return_if_fail (action != NULL); + + /* A bit paranoid */ + subsys = g_udev_device_get_subsystem (device); + g_return_if_fail (!g_strcmp0 (subsys, "rfkill")); + + nm_log_dbg (LOGD_HW, "udev rfkill event: action '%s' device '%s'", + action, g_udev_device_get_name (device)); + + if (!strcmp (action, "add")) + rfkill_add (self, device); + else if (!strcmp (action, "remove")) + rfkill_remove (self, device); + + recheck_killswitches (self); +} + +static void +nm_rfkill_manager_init (NMRfkillManager *self) +{ + NMRfkillManagerPrivate *priv = NM_RFKILL_MANAGER_GET_PRIVATE (self); + const char *subsys[] = { "rfkill", NULL }; + GList *switches, *iter; + guint32 i; + + for (i = 0; i < RFKILL_TYPE_MAX; i++) + priv->rfkill_states[i] = RFKILL_UNBLOCKED; + + priv->client = g_udev_client_new (subsys); + g_signal_connect (priv->client, "uevent", G_CALLBACK (handle_uevent), self); + + switches = g_udev_client_query_by_subsystem (priv->client, "rfkill"); + for (iter = switches; iter; iter = g_list_next (iter)) { + add_one_killswitch (self, G_UDEV_DEVICE (iter->data)); + g_object_unref (G_UDEV_DEVICE (iter->data)); + } + g_list_free (switches); + + recheck_killswitches (self); +} + +static void +dispose (GObject *object) +{ + NMRfkillManager *self = NM_RFKILL_MANAGER (object); + NMRfkillManagerPrivate *priv = NM_RFKILL_MANAGER_GET_PRIVATE (self); + + g_clear_object (&priv->client); + + if (priv->killswitches) { + g_slist_free_full (priv->killswitches, (GDestroyNotify) killswitch_destroy); + priv->killswitches = NULL; + } + + G_OBJECT_CLASS (nm_rfkill_manager_parent_class)->dispose (object); +} + +static void +nm_rfkill_manager_class_init (NMRfkillManagerClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (NMRfkillManagerPrivate)); + + /* virtual methods */ + object_class->dispose = dispose; + + /* Signals */ + signals[RFKILL_CHANGED] = + g_signal_new ("rfkill-changed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMRfkillManagerClass, rfkill_changed), + NULL, NULL, NULL, + G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT); +} diff --git a/src/nm-rfkill-manager.h b/src/nm-rfkill-manager.h new file mode 100644 index 00000000..b26261b8 --- /dev/null +++ b/src/nm-rfkill-manager.h @@ -0,0 +1,72 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2007 - 2008 Novell, Inc. + * Copyright (C) 2007 - 2013 Red Hat, Inc. + */ + +#include + +#ifndef NM_RFKILL_MANAGER_H +#define NM_RFKILL_MANAGER_H + +typedef enum { + RFKILL_UNBLOCKED = 0, + RFKILL_SOFT_BLOCKED = 1, + RFKILL_HARD_BLOCKED = 2 +} RfKillState; + +typedef enum { + RFKILL_TYPE_WLAN = 0, + RFKILL_TYPE_WWAN = 1, + RFKILL_TYPE_WIMAX = 2, + + /* UNKNOWN and MAX should always be 1 more than + * the last rfkill type since RFKILL_TYPE_MAX is + * used as an array size. + */ + RFKILL_TYPE_UNKNOWN = 3, /* KEEP LAST */ + RFKILL_TYPE_MAX = RFKILL_TYPE_UNKNOWN +} RfKillType; + + +#define NM_TYPE_RFKILL_MANAGER (nm_rfkill_manager_get_type ()) +#define NM_RFKILL_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_RFKILL_MANAGER, NMRfkillManager)) +#define NM_RFKILL_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_RFKILL_MANAGER, NMRfkillManagerClass)) +#define NM_IS_RFKILL_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_RFKILL_MANAGER)) +#define NM_IS_RFKILL_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_RFKILL_MANAGER)) +#define NM_RFKILL_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_RFKILL_MANAGER, NMRfkillManagerClass)) + +typedef struct { + GObject parent; +} NMRfkillManager; + +typedef struct { + GObjectClass parent; + + /* signals */ + void (*rfkill_changed) (NMRfkillManager *manager, RfKillType rtype, RfKillState state); +} NMRfkillManagerClass; + +GType nm_rfkill_manager_get_type (void); + +NMRfkillManager *nm_rfkill_manager_new (void); + +RfKillState nm_rfkill_manager_get_rfkill_state (NMRfkillManager *manager, RfKillType rtype); + +#endif /* NM_RFKILL_MANAGER_H */ + diff --git a/src/nm-rfkill.h b/src/nm-rfkill.h deleted file mode 100644 index d3cd7774..00000000 --- a/src/nm-rfkill.h +++ /dev/null @@ -1,45 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2007 - 2008 Novell, Inc. - * Copyright (C) 2007 - 2008 Red Hat, Inc. - */ - -#ifndef NM_RFKILL_H -#define NM_RFKILL_H - -typedef enum { - RFKILL_UNBLOCKED = 0, - RFKILL_SOFT_BLOCKED = 1, - RFKILL_HARD_BLOCKED = 2 -} RfKillState; - -typedef enum { - RFKILL_TYPE_WLAN = 0, - RFKILL_TYPE_WWAN = 1, - RFKILL_TYPE_WIMAX = 2, - - /* UNKNOWN and MAX should always be 1 more than - * the last rfkill type since RFKILL_TYPE_MAX is - * used as an array size. - */ - RFKILL_TYPE_UNKNOWN = 3, /* KEEP LAST */ - RFKILL_TYPE_MAX = RFKILL_TYPE_UNKNOWN -} RfKillType; - -#endif /* NM_RFKILL_H */ - diff --git a/src/nm-session-monitor-ck.c b/src/nm-session-monitor-ck.c index 02e2d06e..75e1c927 100644 --- a/src/nm-session-monitor-ck.c +++ b/src/nm-session-monitor-ck.c @@ -354,10 +354,8 @@ nm_session_monitor_get (void) { static NMSessionMonitor *singleton = NULL; - if (singleton) - return g_object_ref (singleton); - - singleton = NM_SESSION_MONITOR (g_object_new (NM_TYPE_SESSION_MONITOR, NULL)); + if (!singleton) + singleton = NM_SESSION_MONITOR (g_object_new (NM_TYPE_SESSION_MONITOR, NULL)); return singleton; } diff --git a/src/nm-session-monitor-null.c b/src/nm-session-monitor-null.c index beabcf21..5d8ecaaf 100644 --- a/src/nm-session-monitor-null.c +++ b/src/nm-session-monitor-null.c @@ -81,11 +81,8 @@ nm_session_monitor_get (void) { static NMSessionMonitor *singleton = NULL; - if (singleton) - return g_object_ref (singleton); - - singleton = NM_SESSION_MONITOR (g_object_new (NM_TYPE_SESSION_MONITOR, NULL)); - g_assert (singleton); + if (!singleton) + singleton = g_object_new (NM_TYPE_SESSION_MONITOR, NULL); return singleton; } diff --git a/src/nm-session-monitor-systemd.c b/src/nm-session-monitor-systemd.c index f9fb075d..f195c1e7 100644 --- a/src/nm-session-monitor-systemd.c +++ b/src/nm-session-monitor-systemd.c @@ -193,11 +193,8 @@ nm_session_monitor_get (void) { static NMSessionMonitor *singleton = NULL; - if (singleton) - return g_object_ref (singleton); - - singleton = NM_SESSION_MONITOR (g_object_new (NM_TYPE_SESSION_MONITOR, NULL)); - g_assert (singleton); + if (!singleton) + singleton = g_object_new (NM_TYPE_SESSION_MONITOR, NULL); return singleton; } @@ -237,18 +234,19 @@ nm_session_monitor_uid_has_session (NMSessionMonitor *monitor, const char **out_user, GError **error) { - int ret; + int num_sessions; if (!nm_session_uid_to_user (uid, out_user, error)) return FALSE; - ret = sd_uid_get_sessions (uid, FALSE, NULL) > 0; - if (ret < 0) { + /* Get all sessions (including inactive ones) for the user */ + num_sessions = sd_uid_get_sessions (uid, 0, NULL); + if (num_sessions < 0) { nm_log_warn (LOGD_CORE, "Failed to get systemd sessions for uid %d: %d", - uid, ret); + uid, num_sessions); return FALSE; } - return ret > 0 ? TRUE : FALSE; + return num_sessions > 0; } gboolean @@ -256,13 +254,14 @@ nm_session_monitor_uid_active (NMSessionMonitor *monitor, uid_t uid, GError **error) { - int ret; + int num_sessions; - ret = sd_uid_get_sessions (uid, TRUE, NULL) > 0; - if (ret < 0) { + /* Get active sessions for the user */ + num_sessions = sd_uid_get_sessions (uid, 1, NULL); + if (num_sessions < 0) { nm_log_warn (LOGD_CORE, "Failed to get active systemd sessions for uid %d: %d", - uid, ret); + uid, num_sessions); return FALSE; } - return ret > 0 ? TRUE : FALSE; + return num_sessions > 0; } diff --git a/src/nm-settings-connection-glue.h b/src/nm-settings-connection-glue.h new file mode 100644 index 00000000..8cace513 --- /dev/null +++ b/src/nm-settings-connection-glue.h @@ -0,0 +1,171 @@ +/* Generated by dbus-binding-tool; do not edit! */ + + +#ifndef __dbus_glib_marshal_nm_settings_connection_MARSHAL_H__ +#define __dbus_glib_marshal_nm_settings_connection_MARSHAL_H__ + +#include + +G_BEGIN_DECLS + +#ifdef G_ENABLE_DEBUG +#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v) +#define g_marshal_value_peek_char(v) g_value_get_schar (v) +#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v) +#define g_marshal_value_peek_int(v) g_value_get_int (v) +#define g_marshal_value_peek_uint(v) g_value_get_uint (v) +#define g_marshal_value_peek_long(v) g_value_get_long (v) +#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v) +#define g_marshal_value_peek_int64(v) g_value_get_int64 (v) +#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v) +#define g_marshal_value_peek_enum(v) g_value_get_enum (v) +#define g_marshal_value_peek_flags(v) g_value_get_flags (v) +#define g_marshal_value_peek_float(v) g_value_get_float (v) +#define g_marshal_value_peek_double(v) g_value_get_double (v) +#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v) +#define g_marshal_value_peek_param(v) g_value_get_param (v) +#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v) +#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v) +#define g_marshal_value_peek_object(v) g_value_get_object (v) +#define g_marshal_value_peek_variant(v) g_value_get_variant (v) +#else /* !G_ENABLE_DEBUG */ +/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API. + * Do not access GValues directly in your code. Instead, use the + * g_value_get_*() functions + */ +#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int +#define g_marshal_value_peek_char(v) (v)->data[0].v_int +#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint +#define g_marshal_value_peek_int(v) (v)->data[0].v_int +#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint +#define g_marshal_value_peek_long(v) (v)->data[0].v_long +#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 +#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 +#define g_marshal_value_peek_enum(v) (v)->data[0].v_long +#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_float(v) (v)->data[0].v_float +#define g_marshal_value_peek_double(v) (v)->data[0].v_double +#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer +#endif /* !G_ENABLE_DEBUG */ + + +/* NONE:POINTER */ +#define dbus_glib_marshal_nm_settings_connection_VOID__POINTER g_cclosure_marshal_VOID__POINTER +#define dbus_glib_marshal_nm_settings_connection_NONE__POINTER dbus_glib_marshal_nm_settings_connection_VOID__POINTER + +/* NONE:STRING,POINTER */ +extern void dbus_glib_marshal_nm_settings_connection_VOID__STRING_POINTER (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); +void +dbus_glib_marshal_nm_settings_connection_VOID__STRING_POINTER (GClosure *closure, + GValue *return_value G_GNUC_UNUSED, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint G_GNUC_UNUSED, + gpointer marshal_data) +{ + typedef void (*GMarshalFunc_VOID__STRING_POINTER) (gpointer data1, + gpointer arg_1, + gpointer arg_2, + gpointer data2); + register GMarshalFunc_VOID__STRING_POINTER callback; + register GCClosure *cc = (GCClosure*) closure; + register gpointer data1, data2; + + g_return_if_fail (n_param_values == 3); + + if (G_CCLOSURE_SWAP_DATA (closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer (param_values + 0); + } + else + { + data1 = g_value_peek_pointer (param_values + 0); + data2 = closure->data; + } + callback = (GMarshalFunc_VOID__STRING_POINTER) (marshal_data ? marshal_data : cc->callback); + + callback (data1, + g_marshal_value_peek_string (param_values + 1), + g_marshal_value_peek_pointer (param_values + 2), + data2); +} +#define dbus_glib_marshal_nm_settings_connection_NONE__STRING_POINTER dbus_glib_marshal_nm_settings_connection_VOID__STRING_POINTER + +/* NONE:BOXED,POINTER */ +extern void dbus_glib_marshal_nm_settings_connection_VOID__BOXED_POINTER (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); +void +dbus_glib_marshal_nm_settings_connection_VOID__BOXED_POINTER (GClosure *closure, + GValue *return_value G_GNUC_UNUSED, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint G_GNUC_UNUSED, + gpointer marshal_data) +{ + typedef void (*GMarshalFunc_VOID__BOXED_POINTER) (gpointer data1, + gpointer arg_1, + gpointer arg_2, + gpointer data2); + register GMarshalFunc_VOID__BOXED_POINTER callback; + register GCClosure *cc = (GCClosure*) closure; + register gpointer data1, data2; + + g_return_if_fail (n_param_values == 3); + + if (G_CCLOSURE_SWAP_DATA (closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer (param_values + 0); + } + else + { + data1 = g_value_peek_pointer (param_values + 0); + data2 = closure->data; + } + callback = (GMarshalFunc_VOID__BOXED_POINTER) (marshal_data ? marshal_data : cc->callback); + + callback (data1, + g_marshal_value_peek_boxed (param_values + 1), + g_marshal_value_peek_pointer (param_values + 2), + data2); +} +#define dbus_glib_marshal_nm_settings_connection_NONE__BOXED_POINTER dbus_glib_marshal_nm_settings_connection_VOID__BOXED_POINTER + +G_END_DECLS + +#endif /* __dbus_glib_marshal_nm_settings_connection_MARSHAL_H__ */ + +#include +static const DBusGMethodInfo dbus_glib_nm_settings_connection_methods[] = { + { (GCallback) impl_settings_connection_update, dbus_glib_marshal_nm_settings_connection_NONE__BOXED_POINTER, 0 }, + { (GCallback) impl_settings_connection_update_unsaved, dbus_glib_marshal_nm_settings_connection_NONE__BOXED_POINTER, 84 }, + { (GCallback) impl_settings_connection_delete, dbus_glib_marshal_nm_settings_connection_NONE__POINTER, 175 }, + { (GCallback) impl_settings_connection_get_settings, dbus_glib_marshal_nm_settings_connection_NONE__POINTER, 236 }, + { (GCallback) impl_settings_connection_get_secrets, dbus_glib_marshal_nm_settings_connection_NONE__STRING_POINTER, 327 }, + { (GCallback) impl_settings_connection_save, dbus_glib_marshal_nm_settings_connection_NONE__POINTER, 433 }, +}; + +const DBusGObjectInfo dbus_glib_nm_settings_connection_object_info = { 1, + dbus_glib_nm_settings_connection_methods, + 6, +"org.freedesktop.NetworkManager.Settings.Connection\0Update\0A\0properties\0I\0a{sa{sv}}\0\0org.freedesktop.NetworkManager.Settings.Connection\0UpdateUnsaved\0A\0properties\0I\0a{sa{sv}}\0\0org.freedesktop.NetworkManager.Settings.Connection\0Delete\0A\0\0org.freedesktop.NetworkManager.Settings.Connection\0GetSettings\0A\0settings\0O\0F\0N\0a{sa{sv}}\0\0org.freedesktop.NetworkManager.Settings.Connection\0GetSecrets\0A\0setting_name\0I\0s\0secrets\0O\0F\0N\0a{sa{sv}}\0\0org.freedesktop.NetworkManager.Settings.Connection\0Save\0A\0\0\0", +"org.freedesktop.NetworkManager.Settings.Connection\0Updated\0org.freedesktop.NetworkManager.Settings.Connection\0Removed\0org.freedesktop.NetworkManager.Settings.Connection\0PropertiesChanged\0\0", +"org.freedesktop.NetworkManager.Settings.Connection\0Unsaved\0unsaved\0read\0\0" +}; + diff --git a/src/nm-settings-glue.h b/src/nm-settings-glue.h new file mode 100644 index 00000000..631f4530 --- /dev/null +++ b/src/nm-settings-glue.h @@ -0,0 +1,219 @@ +/* Generated by dbus-binding-tool; do not edit! */ + + +#ifndef __dbus_glib_marshal_nm_settings_MARSHAL_H__ +#define __dbus_glib_marshal_nm_settings_MARSHAL_H__ + +#include + +G_BEGIN_DECLS + +#ifdef G_ENABLE_DEBUG +#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v) +#define g_marshal_value_peek_char(v) g_value_get_schar (v) +#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v) +#define g_marshal_value_peek_int(v) g_value_get_int (v) +#define g_marshal_value_peek_uint(v) g_value_get_uint (v) +#define g_marshal_value_peek_long(v) g_value_get_long (v) +#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v) +#define g_marshal_value_peek_int64(v) g_value_get_int64 (v) +#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v) +#define g_marshal_value_peek_enum(v) g_value_get_enum (v) +#define g_marshal_value_peek_flags(v) g_value_get_flags (v) +#define g_marshal_value_peek_float(v) g_value_get_float (v) +#define g_marshal_value_peek_double(v) g_value_get_double (v) +#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v) +#define g_marshal_value_peek_param(v) g_value_get_param (v) +#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v) +#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v) +#define g_marshal_value_peek_object(v) g_value_get_object (v) +#define g_marshal_value_peek_variant(v) g_value_get_variant (v) +#else /* !G_ENABLE_DEBUG */ +/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API. + * Do not access GValues directly in your code. Instead, use the + * g_value_get_*() functions + */ +#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int +#define g_marshal_value_peek_char(v) (v)->data[0].v_int +#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint +#define g_marshal_value_peek_int(v) (v)->data[0].v_int +#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint +#define g_marshal_value_peek_long(v) (v)->data[0].v_long +#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 +#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 +#define g_marshal_value_peek_enum(v) (v)->data[0].v_long +#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_float(v) (v)->data[0].v_float +#define g_marshal_value_peek_double(v) (v)->data[0].v_double +#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer +#endif /* !G_ENABLE_DEBUG */ + + +/* NONE:POINTER */ +#define dbus_glib_marshal_nm_settings_VOID__POINTER g_cclosure_marshal_VOID__POINTER +#define dbus_glib_marshal_nm_settings_NONE__POINTER dbus_glib_marshal_nm_settings_VOID__POINTER + +/* BOOLEAN:POINTER,POINTER */ +extern void dbus_glib_marshal_nm_settings_BOOLEAN__POINTER_POINTER (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); +void +dbus_glib_marshal_nm_settings_BOOLEAN__POINTER_POINTER (GClosure *closure, + GValue *return_value G_GNUC_UNUSED, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint G_GNUC_UNUSED, + gpointer marshal_data) +{ + typedef gboolean (*GMarshalFunc_BOOLEAN__POINTER_POINTER) (gpointer data1, + gpointer arg_1, + gpointer arg_2, + gpointer data2); + register GMarshalFunc_BOOLEAN__POINTER_POINTER callback; + register GCClosure *cc = (GCClosure*) closure; + register gpointer data1, data2; + gboolean v_return; + + g_return_if_fail (return_value != NULL); + g_return_if_fail (n_param_values == 3); + + if (G_CCLOSURE_SWAP_DATA (closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer (param_values + 0); + } + else + { + data1 = g_value_peek_pointer (param_values + 0); + data2 = closure->data; + } + callback = (GMarshalFunc_BOOLEAN__POINTER_POINTER) (marshal_data ? marshal_data : cc->callback); + + v_return = callback (data1, + g_marshal_value_peek_pointer (param_values + 1), + g_marshal_value_peek_pointer (param_values + 2), + data2); + + g_value_set_boolean (return_value, v_return); +} + +/* NONE:STRING,POINTER */ +extern void dbus_glib_marshal_nm_settings_VOID__STRING_POINTER (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); +void +dbus_glib_marshal_nm_settings_VOID__STRING_POINTER (GClosure *closure, + GValue *return_value G_GNUC_UNUSED, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint G_GNUC_UNUSED, + gpointer marshal_data) +{ + typedef void (*GMarshalFunc_VOID__STRING_POINTER) (gpointer data1, + gpointer arg_1, + gpointer arg_2, + gpointer data2); + register GMarshalFunc_VOID__STRING_POINTER callback; + register GCClosure *cc = (GCClosure*) closure; + register gpointer data1, data2; + + g_return_if_fail (n_param_values == 3); + + if (G_CCLOSURE_SWAP_DATA (closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer (param_values + 0); + } + else + { + data1 = g_value_peek_pointer (param_values + 0); + data2 = closure->data; + } + callback = (GMarshalFunc_VOID__STRING_POINTER) (marshal_data ? marshal_data : cc->callback); + + callback (data1, + g_marshal_value_peek_string (param_values + 1), + g_marshal_value_peek_pointer (param_values + 2), + data2); +} +#define dbus_glib_marshal_nm_settings_NONE__STRING_POINTER dbus_glib_marshal_nm_settings_VOID__STRING_POINTER + +/* NONE:BOXED,POINTER */ +extern void dbus_glib_marshal_nm_settings_VOID__BOXED_POINTER (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); +void +dbus_glib_marshal_nm_settings_VOID__BOXED_POINTER (GClosure *closure, + GValue *return_value G_GNUC_UNUSED, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint G_GNUC_UNUSED, + gpointer marshal_data) +{ + typedef void (*GMarshalFunc_VOID__BOXED_POINTER) (gpointer data1, + gpointer arg_1, + gpointer arg_2, + gpointer data2); + register GMarshalFunc_VOID__BOXED_POINTER callback; + register GCClosure *cc = (GCClosure*) closure; + register gpointer data1, data2; + + g_return_if_fail (n_param_values == 3); + + if (G_CCLOSURE_SWAP_DATA (closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer (param_values + 0); + } + else + { + data1 = g_value_peek_pointer (param_values + 0); + data2 = closure->data; + } + callback = (GMarshalFunc_VOID__BOXED_POINTER) (marshal_data ? marshal_data : cc->callback); + + callback (data1, + g_marshal_value_peek_boxed (param_values + 1), + g_marshal_value_peek_pointer (param_values + 2), + data2); +} +#define dbus_glib_marshal_nm_settings_NONE__BOXED_POINTER dbus_glib_marshal_nm_settings_VOID__BOXED_POINTER + +G_END_DECLS + +#endif /* __dbus_glib_marshal_nm_settings_MARSHAL_H__ */ + +#include +static const DBusGMethodInfo dbus_glib_nm_settings_methods[] = { + { (GCallback) impl_settings_list_connections, dbus_glib_marshal_nm_settings_BOOLEAN__POINTER_POINTER, 0 }, + { (GCallback) impl_settings_get_connection_by_uuid, dbus_glib_marshal_nm_settings_NONE__STRING_POINTER, 80 }, + { (GCallback) impl_settings_add_connection, dbus_glib_marshal_nm_settings_NONE__BOXED_POINTER, 171 }, + { (GCallback) impl_settings_add_connection_unsaved, dbus_glib_marshal_nm_settings_NONE__BOXED_POINTER, 264 }, + { (GCallback) impl_settings_load_connections, dbus_glib_marshal_nm_settings_NONE__BOXED_POINTER, 364 }, + { (GCallback) impl_settings_reload_connections, dbus_glib_marshal_nm_settings_NONE__POINTER, 471 }, + { (GCallback) impl_settings_save_hostname, dbus_glib_marshal_nm_settings_NONE__STRING_POINTER, 547 }, +}; + +const DBusGObjectInfo dbus_glib_nm_settings_object_info = { 1, + dbus_glib_nm_settings_methods, + 7, +"org.freedesktop.NetworkManager.Settings\0ListConnections\0S\0connections\0O\0F\0N\0ao\0\0org.freedesktop.NetworkManager.Settings\0GetConnectionByUuid\0A\0uuid\0I\0s\0connection\0O\0F\0N\0o\0\0org.freedesktop.NetworkManager.Settings\0AddConnection\0A\0connection\0I\0a{sa{sv}}\0path\0O\0F\0N\0o\0\0org.freedesktop.NetworkManager.Settings\0AddConnectionUnsaved\0A\0connection\0I\0a{sa{sv}}\0path\0O\0F\0N\0o\0\0org.freedesktop.NetworkManager.Settings\0LoadConnections\0A\0filenames\0I\0as\0status\0O\0F\0N\0b\0failures\0O\0F\0N\0as\0\0org.freedesktop.NetworkManager.Settings\0ReloadConnections\0A\0status\0O\0F\0N\0b\0\0org.freedesktop.NetworkManager.Settings\0SaveHostname\0A\0hostname\0I\0s\0\0\0", +"org.freedesktop.NetworkManager.Settings\0PropertiesChanged\0org.freedesktop.NetworkManager.Settings\0NewConnection\0org.freedesktop.NetworkManager.Settings\0ConnectionRemoved\0\0", +"org.freedesktop.NetworkManager.Settings\0Connections\0connections\0read\0org.freedesktop.NetworkManager.Settings\0Hostname\0hostname\0read\0org.freedesktop.NetworkManager.Settings\0CanModify\0can_modify\0read\0\0" +}; + diff --git a/src/nm-sleep-monitor-systemd.c b/src/nm-sleep-monitor-systemd.c index 576cb141..55134c48 100644 --- a/src/nm-sleep-monitor-systemd.c +++ b/src/nm-sleep-monitor-systemd.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -35,20 +36,11 @@ #define SD_PATH "/org/freedesktop/login1" #define SD_INTERFACE "org.freedesktop.login1.Manager" -/* Do we have GDBus (glib >= 2.26) and GUnixFDList (glib >= 2.30) support ? */ -#if GLIB_CHECK_VERSION(2,30,0) -#define IS_GDBUS_UNIXFD_AVAILABLE 1 -#endif - struct _NMSleepMonitor { GObject parent_instance; -#if defined(IS_GDBUS_UNIXFD_AVAILABLE) GDBusProxy *sd_proxy; -#else - DBusGProxy *sd_proxy; -#endif gint inhibit_fd; }; @@ -83,8 +75,6 @@ drop_inhibitor (NMSleepMonitor *self) return FALSE; } -#if defined(IS_GDBUS_UNIXFD_AVAILABLE) -/* Great! We have GDBus (glib >= 2.26) and GUnixFDList (glib >= 2.30) */ static void inhibit_done (GObject *source, GAsyncResult *result, @@ -122,8 +112,8 @@ take_inhibitor (NMSleepMonitor *self) "Inhibit", g_variant_new ("(ssss)", "sleep", - g_get_user_name (), - "inhibited", + "NetworkManager", + _("NetworkManager needs to turn off networks"), "delay"), 0, G_MAXINT, @@ -171,136 +161,6 @@ sleep_setup (NMSleepMonitor *self) g_signal_connect (self->sd_proxy, "g-signal", G_CALLBACK (signal_cb), self); } -#else - -/* GDBus nor GUnixFDList available. We have to get by with dbus-glib and libdbus */ -static void -inhibit_done (DBusPendingCall *pending, - gpointer user_data) -{ - NMSleepMonitor *self = user_data; - DBusMessage *reply; - DBusError error; - int mtype; - - dbus_error_init (&error); - reply = dbus_pending_call_steal_reply (pending); - g_assert (reply); - - mtype = dbus_message_get_type (reply); - switch (mtype) { - case DBUS_MESSAGE_TYPE_ERROR: - dbus_set_error_from_message (&error, reply); - nm_log_warn (LOGD_SUSPEND, "Inhibit() failed: %s", error.message ? error.message : "unknown"); - break; - case DBUS_MESSAGE_TYPE_METHOD_RETURN: - if (!dbus_message_get_args (reply, - &error, - DBUS_TYPE_UNIX_FD, &self->inhibit_fd, - DBUS_TYPE_INVALID)) { - nm_log_warn (LOGD_SUSPEND, "Inhibit() reply parsing failed: %s", - error.message ? error.message : "unknown"); - break; - } - nm_log_dbg (LOGD_SUSPEND, "Inhibitor fd is %d", self->inhibit_fd); - break; - default: - nm_log_warn (LOGD_SUSPEND, "Invalid Inhibit() reply message type %d", mtype); - break; - } - - dbus_message_unref (reply); - dbus_error_free (&error); -} - -static void -take_inhibitor (NMSleepMonitor *self) -{ - NMDBusManager *dbus_mgr; - DBusConnection *bus; - DBusMessage *message = NULL; - DBusPendingCall *pending = NULL; - const char *arg_what = "sleep"; - const char *arg_who = g_get_user_name (); - const char *arg_why = "inhibited"; - const char *arg_mode = "delay"; - - g_assert (self->inhibit_fd == -1); - - nm_log_dbg (LOGD_SUSPEND, "Taking systemd sleep inhibitor"); - - dbus_mgr = nm_dbus_manager_get (); - bus = nm_dbus_manager_get_dbus_connection (dbus_mgr); - g_assert (bus); - g_object_unref (dbus_mgr); - - if (!(message = dbus_message_new_method_call (SD_NAME, - SD_PATH, - SD_INTERFACE, - "Inhibit"))) { - nm_log_warn (LOGD_SUSPEND, "Unable to call Inhibit()"); - return; - } - if (!dbus_message_append_args (message, - DBUS_TYPE_STRING, &arg_what, - DBUS_TYPE_STRING, &arg_who, - DBUS_TYPE_STRING, &arg_why, - DBUS_TYPE_STRING, &arg_mode, - DBUS_TYPE_INVALID)) { - nm_log_warn (LOGD_SUSPEND, "Unable to call Inhibit()"); - goto done; - } - - if (!dbus_connection_send_with_reply (bus, message, &pending, -1)) - goto done; - - if (!dbus_pending_call_set_notify (pending, inhibit_done, self, NULL)) { - dbus_pending_call_cancel (pending); - dbus_pending_call_unref (pending); - } - -done: - if (message) - dbus_message_unref (message); -} - -static void -signal_cb (DBusGProxy *proxy, gboolean about_to_suspend, gpointer data) -{ - NMSleepMonitor *self = data; - - nm_log_dbg (LOGD_SUSPEND, "Received PrepareForSleep signal: %d", about_to_suspend); - - if (about_to_suspend) { - g_signal_emit (self, signals[SLEEPING], 0); - drop_inhibitor (self); - } else { - take_inhibitor (self); - g_signal_emit (self, signals[RESUMING], 0); - } -} - -static void -sleep_setup (NMSleepMonitor *self) -{ - NMDBusManager *dbus_mgr; - DBusGConnection *bus; - - dbus_mgr = nm_dbus_manager_get (); - bus = nm_dbus_manager_get_connection (dbus_mgr); - self->sd_proxy = dbus_g_proxy_new_for_name (bus, SD_NAME, SD_PATH, SD_INTERFACE); - g_object_unref (dbus_mgr); - - if (self->sd_proxy) { - dbus_g_proxy_add_signal (self->sd_proxy, "PrepareForSleep", G_TYPE_BOOLEAN, G_TYPE_INVALID); - dbus_g_proxy_connect_signal (self->sd_proxy, "PrepareForSleep", - G_CALLBACK (signal_cb), - self, NULL); - } else - nm_log_warn (LOGD_SUSPEND, "could not initialize systemd-logind D-Bus proxy"); -} -#endif /* IS_GDBUS_UNIXFD_AVAILABLE */ - static void nm_sleep_monitor_init (NMSleepMonitor *self) { diff --git a/src/nm-sleep-monitor-upower.c b/src/nm-sleep-monitor-upower.c index 3c93f663..58402abd 100644 --- a/src/nm-sleep-monitor-upower.c +++ b/src/nm-sleep-monitor-upower.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include "nm-logging.h" @@ -73,11 +72,9 @@ upower_resuming_cb (DBusGProxy *proxy, gpointer user_data) static void nm_sleep_monitor_init (NMSleepMonitor *self) { - NMDBusManager *dbus_mgr; DBusGConnection *bus; - dbus_mgr = nm_dbus_manager_get (); - bus = nm_dbus_manager_get_connection (dbus_mgr); + bus = nm_dbus_manager_get_connection (nm_dbus_manager_get ()); self->upower_proxy = dbus_g_proxy_new_for_name (bus, UPOWER_DBUS_SERVICE, "/org/freedesktop/UPower", @@ -94,7 +91,6 @@ nm_sleep_monitor_init (NMSleepMonitor *self) self, NULL); } else nm_log_warn (LOGD_SUSPEND, "could not initialize UPower D-Bus proxy"); - g_object_unref (dbus_mgr); } static void diff --git a/src/nm-system.c b/src/nm-system.c deleted file mode 100644 index 39983424..00000000 --- a/src/nm-system.c +++ /dev/null @@ -1,2603 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2004 - 2012 Red Hat, Inc. - * Copyright (C) 2005 - 2008 Novell, Inc. - * Copyright (C) 1996 - 1997 Yoichi Hariguchi - * Copyright (C) January, 1998 Sergei Viznyuk - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "nm-system.h" -#include "nm-device.h" -#include "NetworkManagerUtils.h" -#include "nm-utils.h" -#include "nm-logging.h" -#include "nm-netlink-monitor.h" -#include "nm-netlink-utils.h" -#include "nm-netlink-compat.h" - -#include -#include -#include -#include -#include -#include -#include - -#if !HAVE_VLAN_FLAG_LOOSE_BINDING -/* Older kernels don't have this flag */ -#define VLAN_FLAG_LOOSE_BINDING 0x04 -#endif - -static void nm_system_device_set_priority (int ifindex, - NMIP4Config *config, - int priority); - -static gboolean -ip4_dest_in_same_subnet (NMIP4Config *config, guint32 dest, guint32 dest_prefix) -{ - int num; - int i; - - num = nm_ip4_config_get_num_addresses (config); - for (i = 0; i < num; i++) { - NMIP4Address *addr = nm_ip4_config_get_address (config, i); - guint32 prefix = nm_ip4_address_get_prefix (addr); - guint32 address = nm_ip4_address_get_address (addr); - - if (prefix <= dest_prefix) { - guint32 masked_addr = ntohl(address) >> (32 - prefix); - guint32 masked_dest = ntohl(dest) >> (32 - prefix); - - if (masked_addr == masked_dest) - return TRUE; - } - } - - return FALSE; -} - -static struct rtnl_route * -nm_system_device_set_ip4_route (int ifindex, - guint32 ip4_dest, - guint32 ip4_prefix, - guint32 ip4_gateway, - guint32 metric, - int mss) -{ - struct nl_sock *nlh; - struct rtnl_route *route; - int err; - - g_return_val_if_fail (ifindex > 0, NULL); - - nlh = nm_netlink_get_default_handle (); - g_return_val_if_fail (nlh != NULL, NULL); - - route = nm_netlink_route_new (ifindex, AF_INET, mss, - NMNL_PROP_PRIO, metric, - NULL); - g_return_val_if_fail (route != NULL, NULL); - - /* Add the route */ - err = nm_netlink_route4_add (route, &ip4_dest, ip4_prefix, &ip4_gateway, 0); - if (err == -NLE_OBJ_NOTFOUND && ip4_gateway) { - /* Gateway might be over a bridge; try adding a route to gateway first */ - struct rtnl_route *route2; - - route2 = nm_netlink_route_new (ifindex, AF_INET, mss, NULL); - if (route2) { - /* Add route to gateway over bridge */ - err = nm_netlink_route4_add (route2, &ip4_gateway, 32, NULL, 0); - if (!err) { - err = nm_netlink_route4_add (route, &ip4_dest, ip4_prefix, &ip4_gateway, 0); - if (err) - nm_netlink_route_delete (route2); - } - rtnl_route_put (route2); - } - } - - if (err) { - char *iface = nm_netlink_index_to_iface (ifindex); - - nm_log_err (LOGD_DEVICE | LOGD_IP4, - "(%s): failed to set IPv4 route: %s", - iface ? iface : "unknown", nl_geterror (err)); - g_free (iface); - - rtnl_route_put (route); - route = NULL; - } - - return route; -} - -static gboolean -sync_addresses (int ifindex, - int family, - struct rtnl_addr **addrs, - int num_addrs) -{ - struct nl_sock *nlh; - struct nl_cache *addr_cache = NULL; - struct rtnl_addr *filter_addr = NULL, *match_addr; - struct nl_object *match; - struct nl_addr *nladdr; - int i, err; - guint32 log_domain = (family == AF_INET) ? LOGD_IP4 : LOGD_IP6; - char buf[INET6_ADDRSTRLEN + 1]; - char *iface = NULL; - gboolean success = FALSE; - - log_domain |= LOGD_DEVICE; - - nlh = nm_netlink_get_default_handle (); - if (!nlh) - return FALSE; - - err = rtnl_addr_alloc_cache (nlh, &addr_cache); - if (err < 0) - return FALSE; - - filter_addr = rtnl_addr_alloc (); - if (!filter_addr) - goto out; - - rtnl_addr_set_ifindex (filter_addr, ifindex); - if (family) - rtnl_addr_set_family (filter_addr, family); - - iface = nm_netlink_index_to_iface (ifindex); - if (!iface) - goto out; - - nm_log_dbg (log_domain, "(%s): syncing addresses (family %d)", iface, family); - - /* Walk through the cache, comparing the addresses already on - * the interface to the addresses in addrs. - */ - for (match = nl_cache_get_first (addr_cache); match; match = nl_cache_get_next (match)) { - gboolean buf_valid = FALSE; - match_addr = (struct rtnl_addr *) match; - - /* Skip addresses not on our interface */ - if (!nl_object_match_filter (match, (struct nl_object *) filter_addr)) - continue; - - if (addrs) { - for (i = 0; i < num_addrs; i++) { - if (addrs[i] && nl_object_identical (match, (struct nl_object *) addrs[i])) - break; - } - - if (addrs[i]) { - /* match == addrs[i], so remove it from addrs so we don't - * try to add it to the interface again below. - */ - rtnl_addr_put (addrs[i]); - addrs[i] = NULL; - continue; - } - } - - nladdr = rtnl_addr_get_local (match_addr); - - /* Don't delete IPv6 link-local addresses; they don't belong to NM */ - if (rtnl_addr_get_family (match_addr) == AF_INET6) { - struct in6_addr *tmp; - - if (rtnl_addr_get_scope (match_addr) == RT_SCOPE_LINK) { - nm_log_dbg (log_domain, "(%s): ignoring IPv6 link-local address", iface); - continue; - } - - tmp = nl_addr_get_binary_addr (nladdr); - if (inet_ntop (AF_INET6, tmp, buf, sizeof (buf))) - buf_valid = TRUE; - } else if (rtnl_addr_get_family (match_addr) == AF_INET) { - struct in_addr *tmp; - - tmp = nl_addr_get_binary_addr (nladdr); - if (inet_ntop (AF_INET, tmp, buf, sizeof (buf))) - buf_valid = TRUE; - } - - if (buf_valid) { - nm_log_dbg (log_domain, "(%s): removing address '%s/%d'", - iface, buf, rtnl_addr_get_prefixlen (match_addr)); - } - - /* Otherwise, match_addr should be removed from the interface. */ - err = rtnl_addr_delete (nlh, match_addr, 0); - if (err < 0) { - nm_log_err (log_domain, "(%s): error %d returned from rtnl_addr_delete(): %s", - iface, err, nl_geterror (err)); - } - } - - /* Now add the remaining new addresses */ - for (i = 0; i < num_addrs; i++) { - struct in6_addr *in6tmp; - struct in_addr *in4tmp; - gboolean buf_valid = FALSE; - - if (!addrs[i]) - continue; - - nladdr = rtnl_addr_get_local (addrs[i]); - if (rtnl_addr_get_family (addrs[i]) == AF_INET6) { - in6tmp = nl_addr_get_binary_addr (nladdr); - if (inet_ntop (AF_INET6, in6tmp, buf, sizeof (buf))) - buf_valid = TRUE; - } else if (rtnl_addr_get_family (addrs[i]) == AF_INET) { - in4tmp = nl_addr_get_binary_addr (nladdr); - if (inet_ntop (AF_INET, in4tmp, buf, sizeof (buf))) - buf_valid = TRUE; - } - - if (buf_valid) { - nm_log_dbg (log_domain, "(%s): adding address '%s/%d'", - iface, buf, nl_addr_get_prefixlen (nladdr)); - } - - err = rtnl_addr_add (nlh, addrs[i], 0); - if (err < 0 && (err != -NLE_EXIST)) { - nm_log_err (log_domain, - "(%s): error %d returned from rtnl_addr_add():\n%s", - iface, err, nl_geterror (err)); - } - - rtnl_addr_put (addrs[i]); - } - g_free (addrs); - success = TRUE; - -out: - if (filter_addr) - rtnl_addr_put (filter_addr); - if (addr_cache) - nl_cache_free (addr_cache); - g_free (iface); - return success; -} - -static gboolean -add_ip4_addresses (NMIP4Config *config, int ifindex) -{ - char *iface; - int num_addrs, i; - guint32 flags = 0; - gboolean did_gw = FALSE; - struct rtnl_addr **addrs; - - g_return_val_if_fail (ifindex > 0, FALSE); - - iface = nm_netlink_index_to_iface (ifindex); - if (!iface) - return FALSE; - - num_addrs = nm_ip4_config_get_num_addresses (config); - addrs = g_new0 (struct rtnl_addr *, num_addrs + 1); - - for (i = 0; i < num_addrs; i++) { - NMIP4Address *addr; - - addr = nm_ip4_config_get_address (config, i); - g_assert (addr); - - flags = NM_RTNL_ADDR_DEFAULT; - if (nm_ip4_address_get_gateway (addr) && !did_gw) { - if (nm_ip4_config_get_ptp_address (config)) - flags |= NM_RTNL_ADDR_PTP_ADDR; - did_gw = TRUE; - } - - addrs[i] = nm_ip4_config_to_rtnl_addr (config, i, flags); - if (!addrs[i]) { - nm_log_warn (LOGD_DEVICE | LOGD_IP4, - "(%s): couldn't create rtnl address!", - iface ? iface : "unknown"); - continue; - } - rtnl_addr_set_ifindex (addrs[i], ifindex); - } - g_free (iface); - - return sync_addresses (ifindex, AF_INET, addrs, num_addrs); -} - -struct rtnl_route * -nm_system_add_ip4_vpn_gateway_route (NMDevice *parent_device, guint32 vpn_gw) -{ - NMIP4Config *parent_config; - guint32 parent_gw = 0, parent_prefix = 0, i; - NMIP4Address *tmp; - struct rtnl_route *route = NULL; - - g_return_val_if_fail (NM_IS_DEVICE (parent_device), NULL); - g_return_val_if_fail (vpn_gw != 0, NULL); - - /* Set up a route to the VPN gateway's public IP address through the default - * network device if the VPN gateway is on a different subnet. - */ - - parent_config = nm_device_get_ip4_config (parent_device); - g_return_val_if_fail (parent_config != NULL, NULL); - - for (i = 0; i < nm_ip4_config_get_num_addresses (parent_config); i++) { - tmp = nm_ip4_config_get_address (parent_config, i); - if (nm_ip4_address_get_gateway (tmp)) { - parent_gw = nm_ip4_address_get_gateway (tmp); - parent_prefix = nm_ip4_address_get_prefix (tmp); - break; - } - } - - if (!parent_gw) - return NULL; - - /* If the VPN gateway is in the same subnet as one of the parent device's - * IP addresses, don't add the host route to it, but a route through the - * parent device. - */ - if (ip4_dest_in_same_subnet (parent_config, vpn_gw, parent_prefix)) { - route = nm_system_device_set_ip4_route (nm_device_get_ip_ifindex (parent_device), - vpn_gw, 32, 0, 0, nm_ip4_config_get_mss (parent_config)); - } else { - route = nm_system_device_set_ip4_route (nm_device_get_ip_ifindex (parent_device), - vpn_gw, 32, parent_gw, 0, nm_ip4_config_get_mss (parent_config)); - } - - return route; -} - -/* - * nm_system_apply_ip4_config - * - * Set IPv4 configuration of the device from an NMIP4Config object. - * - */ -gboolean -nm_system_apply_ip4_config (int ifindex, - NMIP4Config *config, - int priority, - NMIP4ConfigCompareFlags flags) -{ - int i; - - g_return_val_if_fail (ifindex > 0, FALSE); - g_return_val_if_fail (config != NULL, FALSE); - - if (flags & NM_IP4_COMPARE_FLAG_ADDRESSES) { - if (!add_ip4_addresses (config, ifindex)) - return FALSE; - sleep (1); - } - - if (flags & NM_IP4_COMPARE_FLAG_ROUTES) { - for (i = 0; i < nm_ip4_config_get_num_routes (config); i++) { - NMIP4Route *route = nm_ip4_config_get_route (config, i); - struct rtnl_route *tmp; - - /* Don't add the route if it's more specific than one of the subnets - * the device already has an IP address on. - */ - if (ip4_dest_in_same_subnet (config, - nm_ip4_route_get_dest (route), - nm_ip4_route_get_prefix (route))) - continue; - - /* Don't add the route if it doesn't have a gateway and the connection - * is never supposed to be the default connection. - */ - if ( nm_ip4_config_get_never_default (config) - && nm_ip4_route_get_dest (route) == 0) - continue; - - tmp = nm_system_device_set_ip4_route (ifindex, - nm_ip4_route_get_dest (route), - nm_ip4_route_get_prefix (route), - nm_ip4_route_get_next_hop (route), - nm_ip4_route_get_metric (route), - nm_ip4_config_get_mss (config)); - rtnl_route_put (tmp); - } - } - - if (flags & NM_IP4_COMPARE_FLAG_MTU) { - if (nm_ip4_config_get_mtu (config)) - nm_system_iface_set_mtu (ifindex, nm_ip4_config_get_mtu (config)); - } - - if (priority > 0) - nm_system_device_set_priority (ifindex, config, priority); - - return TRUE; -} - -int -nm_system_set_ip6_route (int ifindex, - const struct in6_addr *ip6_dest, - guint32 ip6_prefix, - const struct in6_addr *ip6_gateway, - guint32 metric, - int mss, - int protocol, - int table, - struct rtnl_route **out_route) -{ - struct nl_sock *nlh; - struct rtnl_route *route; - int err = 0; - - g_return_val_if_fail (ifindex > 0, -1); - - nlh = nm_netlink_get_default_handle (); - g_return_val_if_fail (nlh != NULL, -1); - - route = nm_netlink_route_new (ifindex, AF_INET6, mss, - NMNL_PROP_PROT, protocol, - NMNL_PROP_PRIO, metric, - NMNL_PROP_TABLE, table, - NULL); - g_return_val_if_fail (route != NULL, -1); - - /* Add the route */ - err = nm_netlink_route6_add (route, ip6_dest, ip6_prefix, ip6_gateway, 0); - if (err == -NLE_OBJ_NOTFOUND && ip6_gateway) { - /* Gateway might be over a bridge; try adding a route to gateway first */ - struct rtnl_route *route2; - - route2 = nm_netlink_route_new (ifindex, AF_INET6, mss, NULL); - if (route2) { - err = nm_netlink_route6_add (route, ip6_gateway, 128, NULL, 0); - /* Add route to gateway over bridge */ - if (!err) { - /* Try adding the route again */ - err = nm_netlink_route6_add (route, ip6_dest, ip6_prefix, ip6_gateway, 0); - if (err) - nm_netlink_route_delete (route2); - } - rtnl_route_put (route2); - } - } - - if (out_route) - *out_route = route; - else - rtnl_route_put (route); - - return err; -} - -static gboolean -ip6_dest_in_same_subnet (NMIP6Config *config, const struct in6_addr *dest, guint32 dest_prefix) -{ - int num; - int i; - - num = nm_ip6_config_get_num_addresses (config); - for (i = 0; i < num; i++) { - NMIP6Address *addr = nm_ip6_config_get_address (config, i); - guint32 prefix = nm_ip6_address_get_prefix (addr); - const struct in6_addr *address = nm_ip6_address_get_address (addr); - - if (prefix <= dest_prefix) { - const guint8 *maskbytes = (const guint8 *)address; - const guint8 *addrbytes = (const guint8 *)dest; - int nbytes, nbits; - - /* Copied from g_inet_address_mask_matches() */ - nbytes = prefix / 8; - if (nbytes != 0 && memcmp (maskbytes, addrbytes, nbytes) != 0) - continue; - - nbits = prefix % 8; - if (nbits == 0) - return TRUE; - - if (maskbytes[nbytes] == (addrbytes[nbytes] & (0xFF << (8 - nbits)))) - return TRUE; - } - } - - return FALSE; -} - -struct rtnl_route * -nm_system_add_ip6_vpn_gateway_route (NMDevice *parent_device, - const struct in6_addr *vpn_gw) -{ - NMIP6Config *parent_config; - const struct in6_addr *parent_gw = NULL; - guint32 parent_prefix = 0; - int i, err; - NMIP6Address *tmp; - struct rtnl_route *route = NULL; - - g_return_val_if_fail (NM_IS_DEVICE (parent_device), NULL); - g_return_val_if_fail (vpn_gw != NULL, NULL); - - /* This is all just the same as - * nm_system_add_ip4_vpn_gateway_route(), except with an IPv6 - * address for the VPN gateway. - */ - - parent_config = nm_device_get_ip6_config (parent_device); - g_return_val_if_fail (parent_config != NULL, NULL); - - for (i = 0; i < nm_ip6_config_get_num_addresses (parent_config); i++) { - tmp = nm_ip6_config_get_address (parent_config, i); - if (nm_ip6_address_get_gateway (tmp)) { - parent_gw = nm_ip6_address_get_gateway (tmp); - parent_prefix = nm_ip6_address_get_prefix (tmp); - break; - } - } - - if (!parent_gw) - return NULL; - - if (ip6_dest_in_same_subnet (parent_config, vpn_gw, parent_prefix)) { - err = nm_system_set_ip6_route (nm_device_get_ip_ifindex (parent_device), - vpn_gw, 128, NULL, 0, - nm_ip6_config_get_mss (parent_config), - RTPROT_UNSPEC, RT_TABLE_UNSPEC, - &route); - } else { - err = nm_system_set_ip6_route (nm_device_get_ip_ifindex (parent_device), - vpn_gw, 128, parent_gw, 0, - nm_ip6_config_get_mss (parent_config), - RTPROT_UNSPEC, RT_TABLE_UNSPEC, - &route); - } - - if (err) { - nm_log_err (LOGD_DEVICE | LOGD_IP6, - "(%s): failed to add IPv6 route to VPN gateway (%d)", - nm_device_get_iface (parent_device), err); - } - return route; -} - -static gboolean -add_ip6_addresses (NMIP6Config *config, int ifindex) -{ - char *iface; - int num_addrs, i; - struct rtnl_addr **addrs; - - g_return_val_if_fail (ifindex > 0, FALSE); - - iface = nm_netlink_index_to_iface (ifindex); - if (!iface) - return FALSE; - - num_addrs = nm_ip6_config_get_num_addresses (config); - addrs = g_new0 (struct rtnl_addr *, num_addrs + 1); - - for (i = 0; i < num_addrs; i++) { - NMIP6Address *addr; - - addr = nm_ip6_config_get_address (config, i); - g_assert (addr); - - addrs[i] = nm_ip6_config_to_rtnl_addr (config, i, NM_RTNL_ADDR_DEFAULT); - if (!addrs[i]) { - nm_log_warn (LOGD_DEVICE | LOGD_IP6, - "(%s): couldn't create rtnl address!", - iface ? iface : "unknown"); - continue; - } - rtnl_addr_set_ifindex (addrs[i], ifindex); - } - g_free (iface); - - return sync_addresses (ifindex, AF_INET6, addrs, num_addrs); -} - -/* - * nm_system_apply_ip6_config - * - * Set IPv6 configuration of the device from an NMIP6Config object. - * - */ -gboolean -nm_system_apply_ip6_config (int ifindex, - NMIP6Config *config, - int priority, - NMIP6ConfigCompareFlags flags) -{ - int i; - - g_return_val_if_fail (ifindex > 0, FALSE); - g_return_val_if_fail (config != NULL, FALSE); - - if (flags & NM_IP6_COMPARE_FLAG_ADDRESSES) { - if (!add_ip6_addresses (config, ifindex)) - return FALSE; - sleep (1); // FIXME? - } - - if (flags & NM_IP6_COMPARE_FLAG_ROUTES) { - char *iface = nm_netlink_index_to_iface (ifindex); - - for (i = 0; i < nm_ip6_config_get_num_routes (config); i++) { - NMIP6Route *route = nm_ip6_config_get_route (config, i); - int err; - - /* Don't add the route if it doesn't have a gateway and the connection - * is never supposed to be the default connection. - */ - if ( nm_ip6_config_get_never_default (config) - && IN6_IS_ADDR_UNSPECIFIED (nm_ip6_route_get_dest (route))) - continue; - - err = nm_system_set_ip6_route (ifindex, - nm_ip6_route_get_dest (route), - nm_ip6_route_get_prefix (route), - nm_ip6_route_get_next_hop (route), - nm_ip6_route_get_metric (route), - nm_ip6_config_get_mss (config), - RTPROT_UNSPEC, - RT_TABLE_UNSPEC, - NULL); - if (err && (err != -NLE_EXIST)) { - nm_log_err (LOGD_DEVICE | LOGD_IP6, - "(%s): failed to set IPv6 route: %s", - iface ? iface : "unknown", - nl_geterror (err)); - } - } - g_free (iface); - } - -// FIXME -// if (priority > 0) -// nm_system_device_set_priority (iface, config, priority); - - return TRUE; -} - -/** - * nm_system_iface_set_up: - * @ifindex: interface index - * @up: %TRUE to bring interface up, or %FALSE to take it down - * @no_firmware: on return, %TRUE if the operation may have failed due to - * missing firmware - * - * Bring the interface up or take it down. - * - * Returns: %TRUE on success, %FALSE on failure - **/ -gboolean -nm_system_iface_set_up (int ifindex, - gboolean up, - gboolean *no_firmware) -{ - struct rtnl_link *request = NULL, *old = NULL; - struct nl_sock *nlh; - gboolean success = FALSE; - int err; - - g_return_val_if_fail (ifindex > 0, FALSE); - if (no_firmware) - g_return_val_if_fail (*no_firmware == FALSE, FALSE); - - if (!(request = rtnl_link_alloc ())) - return FALSE; - - if (up) - rtnl_link_set_flags (request, IFF_UP); - else - rtnl_link_unset_flags (request, IFF_UP); - - old = nm_netlink_index_to_rtnl_link (ifindex); - if (old) { - nlh = nm_netlink_get_default_handle (); - if (nlh) { - err = rtnl_link_change (nlh, old, request, 0); - if (err == 0) { - success = TRUE; - } else { - if ((err == -NLE_OBJ_NOTFOUND) && no_firmware && up) - *no_firmware = TRUE; - } - } - } - - rtnl_link_put (old); - rtnl_link_put (request); - return success; -} - -guint32 -nm_system_iface_get_flags (int ifindex) -{ - struct rtnl_link *l; - guint32 flags; - - g_return_val_if_fail (ifindex > 0, FALSE); - - l = nm_netlink_index_to_rtnl_link (ifindex); - if (l == NULL) { - char *iface = nm_netlink_index_to_iface (ifindex); - - g_warn_if_fail (iface != NULL); - nm_log_err (LOGD_HW, "(%s): failed to get interface link object", - iface ? iface : "unknown"); - g_free (iface); - return FALSE; - } - - flags = rtnl_link_get_flags (l); - rtnl_link_put (l); - - return flags; -} - -/** - * nm_system_iface_is_up: - * @ifindex: interface index - * - * Returns: %TRUE if the interface is up, %FALSE if it was down or the check - * failed. - **/ -gboolean -nm_system_iface_is_up (int ifindex) -{ - return nm_system_iface_get_flags (ifindex) & IFF_UP; -} - -/** - * nm_system_iface_set_mtu: - * @ifindex: interface index - * @mtu: the new MTU - * - * Returns: %TRUE if the request was successful, %FALSE if it failed - **/ -gboolean -nm_system_iface_set_mtu (int ifindex, guint32 mtu) -{ - struct rtnl_link *old; - struct rtnl_link *new; - gboolean success = FALSE; - struct nl_sock *nlh; - int err; - - g_return_val_if_fail (ifindex > 0, FALSE); - g_return_val_if_fail (mtu > 0, FALSE); - - new = rtnl_link_alloc (); - if (!new) - return FALSE; - - old = nm_netlink_index_to_rtnl_link (ifindex); - if (old) { - rtnl_link_set_mtu (new, mtu); - nlh = nm_netlink_get_default_handle (); - if (nlh) { - err = rtnl_link_change (nlh, old, new, 0); - if (err == 0) - success = TRUE; - else { - char *iface = nm_netlink_index_to_iface (ifindex); - - nm_log_warn (LOGD_HW, "(%s): failed to change interface MTU", - iface ? iface : "unknown"); - g_free (iface); - } - } - rtnl_link_put (old); - } - rtnl_link_put (new); - - return success; -} - -/** - * nm_system_iface_set_mac: - * @ifindex: interface index - * @mac: new MAC address - * - * Attempts to change the interface's MAC address to the requested value, - * ie MAC spoofing or cloning. - * - * Returns: %TRUE if the request succeeded, %FALSE if it failed. - **/ -gboolean -nm_system_iface_set_mac (int ifindex, const struct ether_addr *mac) -{ - struct rtnl_link *old, *new; - gboolean success = FALSE; - struct nl_sock *nlh; - char *iface; - struct nl_addr *addr = NULL; - int err; - - g_return_val_if_fail (ifindex > 0, FALSE); - g_return_val_if_fail (mac != NULL, FALSE); - - new = rtnl_link_alloc (); - if (!new) - return FALSE; - - iface = nm_netlink_index_to_iface (ifindex); - if (!iface) - goto out; - - old = nm_netlink_index_to_rtnl_link (ifindex); - if (old) { - addr = nl_addr_build (AF_LLC, (void *) mac, ETH_ALEN); - if (!addr) { - nm_log_err (LOGD_HW, "(%s): failed to allocate memory for MAC address change", iface); - rtnl_link_put (old); - rtnl_link_put (new); - return FALSE; - } - rtnl_link_set_addr (new, addr); - nl_addr_put (addr); - nlh = nm_netlink_get_default_handle (); - if (nlh) { - err = rtnl_link_change (nlh, old, new, 0); - if (err == 0) - success = TRUE; - else - nm_log_warn (LOGD_HW, "(%s): failed to change interface MAC address", iface); - } - rtnl_link_put (old); - } - -out: - rtnl_link_put (new); - g_free (iface); - return success; -} - -/** - * nm_system_iface_set_arp: - * @ifindex: interface index - * @enable: %TRUE to enable ARP, or %FALSE to disable - * - * Sets a flag to indicate that ARP should or should not be used on the - * interface. Point-to-point or IPv4 /32 interfaces often require that ARP - * be disabled. - * - * Returns: %TRUE on success, %FALSE on failure - **/ -gboolean -nm_system_iface_set_arp (int ifindex, gboolean enable) -{ - struct rtnl_link *request = NULL, *old = NULL; - struct nl_sock *nlh; - gboolean success = FALSE; - int err; - - g_return_val_if_fail (ifindex > 0, FALSE); - - if (!(request = rtnl_link_alloc ())) - return FALSE; - - if (enable) - rtnl_link_unset_flags (request, IFF_NOARP); - else - rtnl_link_set_flags (request, IFF_NOARP); - - old = nm_netlink_index_to_rtnl_link (ifindex); - if (old) { - nlh = nm_netlink_get_default_handle (); - if (nlh) { - err = rtnl_link_change (nlh, old, request, 0); - if (err == 0) - success = TRUE; - } - } - - rtnl_link_put (old); - rtnl_link_put (request); - return success; -} - -static struct rtnl_route * -add_ip4_route_to_gateway (int ifindex, guint32 gw, guint32 mss) -{ - struct nl_sock *nlh; - struct rtnl_route *route = NULL; - int err; - - nlh = nm_netlink_get_default_handle (); - g_return_val_if_fail (nlh != NULL, NULL); - - /* Gateway might be over a bridge; try adding a route to gateway first */ - route = nm_netlink_route_new (ifindex, AF_INET, mss, - NMNL_PROP_SCOPE, RT_SCOPE_LINK, - NMNL_PROP_TABLE, RT_TABLE_MAIN, - NULL); - g_return_val_if_fail (route != NULL, NULL); - - /* Add direct route to the gateway */ - err = nm_netlink_route4_add (route, &gw, 32, NULL, 0); - if (err) { - char *iface = nm_netlink_index_to_iface (ifindex); - - nm_log_err (LOGD_DEVICE | LOGD_IP4, - "(%s): failed to add IPv4 route to gateway (%d)", - iface ? iface : "unknown", err); - g_free (iface); - goto error; - } - - return route; - -error: - rtnl_route_put (route); - return NULL; -} - -static int -replace_default_ip4_route (int ifindex, guint32 gw, guint32 mss) -{ - struct rtnl_route *route = NULL; - struct nl_sock *nlh; - int err = -1; - guint32 dst = 0; - - g_return_val_if_fail (ifindex > 0, -ENODEV); - - nlh = nm_netlink_get_default_handle (); - g_return_val_if_fail (nlh != NULL, -ENOMEM); - - route = nm_netlink_route_new (ifindex, AF_INET, mss, - NMNL_PROP_SCOPE, RT_SCOPE_UNIVERSE, - NMNL_PROP_TABLE, RT_TABLE_MAIN, - NULL); - g_return_val_if_fail (route != NULL, -ENOMEM); - - /* Add the new default route */ - err = nm_netlink_route4_add (route, &dst, 0, &gw, NLM_F_REPLACE); - if (err == -NLE_EXIST) - err = 0; - - rtnl_route_put (route); - return err; -} - -/* - * nm_system_replace_default_ip4_route_vpn - * - * Replace default IPv4 route with one via the current device - * - */ -gboolean -nm_system_replace_default_ip4_route_vpn (int ifindex, - guint32 ext_gw, - guint32 int_gw, - guint32 mss, - int parent_ifindex, - guint32 parent_mss) -{ - struct rtnl_route *gw_route = NULL; - struct nl_sock *nlh; - gboolean success = FALSE; - int err; - char *iface; - - nlh = nm_netlink_get_default_handle (); - g_return_val_if_fail (nlh != NULL, FALSE); - - err = replace_default_ip4_route (ifindex, int_gw, mss); - if (err == 0) - return TRUE; - - iface = nm_netlink_index_to_iface (ifindex); - if (!iface) - goto out; - - if ((err != -NLE_OBJ_NOTFOUND) && (err != -NLE_FAILURE)) { - nm_log_err (LOGD_DEVICE | LOGD_VPN | LOGD_IP4, - "(%s): failed to set IPv4 default route: %d", - iface, err); - goto out; - } - - /* Try adding a direct route to the gateway first */ - gw_route = add_ip4_route_to_gateway (parent_ifindex, ext_gw, parent_mss); - if (!gw_route) - goto out; - - /* Try adding the original route again */ - err = replace_default_ip4_route (ifindex, int_gw, mss); - if (err != 0) { - nm_netlink_route_delete (gw_route); - nm_log_err (LOGD_DEVICE | LOGD_VPN | LOGD_IP4, - "(%s): failed to set IPv4 default route (pass #2): %d", - iface, err); - } else - success = TRUE; - -out: - if (gw_route) - rtnl_route_put (gw_route); - g_free (iface); - return success; -} - -/* - * nm_system_replace_default_ip4_route - * - * Replace default IPv4 route with one via the current device - * - */ -gboolean -nm_system_replace_default_ip4_route (int ifindex, guint32 gw, guint32 mss) -{ - struct rtnl_route *gw_route = NULL; - gboolean success = FALSE; - char *iface; - int err; - - err = replace_default_ip4_route (ifindex, gw, mss); - if (err == 0) - return TRUE; - - iface = nm_netlink_index_to_iface (ifindex); - if (!iface) - goto out; - - if (err != -NLE_OBJ_NOTFOUND) { - nm_log_err (LOGD_DEVICE | LOGD_IP4, - "(%s): failed to set IPv4 default route: %d", - iface, err); - goto out; - } - - /* Try adding a direct route to the gateway first */ - gw_route = add_ip4_route_to_gateway (ifindex, gw, mss); - if (!gw_route) - goto out; - - /* Try adding the original route again */ - err = replace_default_ip4_route (ifindex, gw, mss); - if (err != 0) { - nm_netlink_route_delete (gw_route); - nm_log_err (LOGD_DEVICE | LOGD_IP4, - "(%s): failed to set IPv4 default route (pass #2): %d", - iface, err); - } else - success = TRUE; - -out: - if (gw_route) - rtnl_route_put (gw_route); - g_free (iface); - return success; -} - -static struct rtnl_route * -add_ip6_route_to_gateway (int ifindex, const struct in6_addr *gw, int mss) -{ - struct nl_sock *nlh; - struct rtnl_route *route = NULL; - int err; - - nlh = nm_netlink_get_default_handle (); - g_return_val_if_fail (nlh != NULL, NULL); - - /* Gateway might be over a bridge; try adding a route to gateway first */ - route = nm_netlink_route_new (ifindex, AF_INET6, mss, - NMNL_PROP_SCOPE, RT_SCOPE_LINK, - NMNL_PROP_TABLE, RT_TABLE_MAIN, - NULL); - g_return_val_if_fail (route != NULL, NULL); - - /* Add direct route to the gateway */ - err = nm_netlink_route6_add (route, gw, 128, NULL, 0); - if (err) { - char *iface = nm_netlink_index_to_iface (ifindex); - - nm_log_err (LOGD_DEVICE | LOGD_IP6, - "(%s): failed to add IPv6 route to gateway (%d)", - iface ? iface : "unknown", err); - g_free (iface); - - rtnl_route_put (route); - route = NULL; - } - - return route; -} - -static int -add_default_ip6_route (int ifindex, const struct in6_addr *gw, int mss) -{ - struct rtnl_route *route = NULL; - struct nl_sock *nlh; - int err = -1; - - g_return_val_if_fail (ifindex > 0, FALSE); - - nlh = nm_netlink_get_default_handle (); - g_return_val_if_fail (nlh != NULL, -ENOMEM); - - route = nm_netlink_route_new (ifindex, AF_INET6, mss, - NMNL_PROP_SCOPE, RT_SCOPE_UNIVERSE, - NMNL_PROP_TABLE, RT_TABLE_MAIN, - NMNL_PROP_PRIO, 1, - NULL); - g_return_val_if_fail (route != NULL, -ENOMEM); - - /* Add the new default route */ - err = nm_netlink_route6_add (route, &in6addr_any, 0, gw, NLM_F_CREATE | NLM_F_REPLACE); - if (err == -NLE_EXIST) - err = 0; - - rtnl_route_put (route); - return err; -} - -static struct rtnl_route * -find_static_default_routes (struct rtnl_route *route, - struct nl_addr *dst, - const char *iface, - gpointer user_data) -{ - GList **def_routes = user_data; - - if ( nl_addr_get_prefixlen (dst) == 0 - && rtnl_route_get_protocol (route) == RTPROT_STATIC) { - rtnl_route_get (route); - *def_routes = g_list_prepend (*def_routes, route); - } - - return NULL; -} - -static int -replace_default_ip6_route (int ifindex, const struct in6_addr *gw, int mss) -{ - GList *def_routes, *iter; - struct rtnl_route *route; - char *iface; - char gw_str[INET6_ADDRSTRLEN + 1]; - - g_return_val_if_fail (ifindex > 0, FALSE); - - if (nm_logging_level_enabled (LOGL_DEBUG)) { - if (gw) { - memset (gw_str, 0, sizeof (gw_str)); - if (inet_ntop (AF_INET6, gw, gw_str, sizeof (gw_str) - 1)) - nm_log_dbg (LOGD_IP6, "Setting IPv6 default route via %s", gw_str); - } else { - nm_log_dbg (LOGD_IP6, "Setting IPv6 default route via %s", - nm_netlink_index_to_iface (ifindex)); - } - } - - /* We can't just use NLM_F_REPLACE here like in the IPv4 case, because - * the kernel doesn't like it if we replace the default routes it - * creates. (See rh#785772.) So we delete any non-kernel default routes, - * and then add a new default route of our own with a lower metric than - * the kernel ones. - */ - def_routes = NULL; - nm_netlink_foreach_route (ifindex, AF_INET6, RT_SCOPE_UNIVERSE, TRUE, - find_static_default_routes, &def_routes); - for (iter = def_routes; iter; iter = iter->next) { - route = iter->data; - if (!nm_netlink_route_delete (route)) { - iface = nm_netlink_index_to_iface (ifindex); - nm_log_err (LOGD_DEVICE | LOGD_IP6, - "(%s): failed to delete existing IPv6 default route", - iface); - g_free (iface); - } - rtnl_route_put (route); - } - g_list_free (def_routes); - - return add_default_ip6_route (ifindex, gw, mss); -} - -/* - * nm_system_replace_default_ip6_route - * - * Replace default IPv6 route with one via the given gateway - * - */ -gboolean -nm_system_replace_default_ip6_route (int ifindex, const struct in6_addr *gw) -{ - struct rtnl_route *gw_route = NULL; - gboolean success = FALSE; - char *iface; - int err; - - err = replace_default_ip6_route (ifindex, gw, 0); - if (err == 0 || err == -NLE_EXIST) - return TRUE; - - iface = nm_netlink_index_to_iface (ifindex); - if (!iface) - goto out; - - if (err != -NLE_OBJ_NOTFOUND) { - nm_log_err (LOGD_DEVICE | LOGD_IP6, - "(%s): failed to set IPv6 default route: %d", - iface, err); - goto out; - } - - /* Try adding a direct route to the gateway first */ - gw_route = add_ip6_route_to_gateway (ifindex, gw, 0); - if (!gw_route) - goto out; - - /* Try adding the original route again */ - err = replace_default_ip6_route (ifindex, gw, 0); - if (err != 0) { - nm_netlink_route_delete (gw_route); - nm_log_err (LOGD_DEVICE | LOGD_IP6, - "(%s): failed to set IPv6 default route (pass #2): %d", - iface, err); - } else - success = TRUE; - -out: - if (gw_route) - rtnl_route_put (gw_route); - g_free (iface); - return success; -} - -gboolean -nm_system_replace_default_ip6_route_vpn (int ifindex, - const struct in6_addr *ext_gw, - const struct in6_addr *int_gw, - guint32 mss, - int parent_ifindex, - guint32 parent_mss) -{ - struct rtnl_route *gw_route = NULL; - struct nl_sock *nlh; - gboolean success = FALSE; - int err; - char *iface; - - nlh = nm_netlink_get_default_handle (); - g_return_val_if_fail (nlh != NULL, FALSE); - - err = replace_default_ip6_route (ifindex, int_gw, mss); - if (err == 0) - return TRUE; - - iface = nm_netlink_index_to_iface (ifindex); - if (!iface) - goto out; - - if ((err != -NLE_OBJ_NOTFOUND) && (err != -NLE_FAILURE)) { - nm_log_err (LOGD_DEVICE | LOGD_VPN | LOGD_IP6, - "(%s): failed to set IPv6 default route: %d", - iface, err); - goto out; - } - - /* Try adding a direct route to the gateway first */ - gw_route = add_ip6_route_to_gateway (parent_ifindex, ext_gw, parent_mss); - if (!gw_route) - goto out; - - /* Try adding the original route again */ - err = replace_default_ip6_route (ifindex, int_gw, mss); - if (err != 0) { - nm_netlink_route_delete (gw_route); - nm_log_err (LOGD_DEVICE | LOGD_VPN | LOGD_IP6, - "(%s): failed to set IPv6 default route (pass #2): %d", - iface, err); - } else - success = TRUE; - -out: - if (gw_route) - rtnl_route_put (gw_route); - g_free (iface); - return success; -} - -/* - * nm_system_iface_flush_addresses - * - * Flush all network addresses associated with a network device - * - */ -gboolean -nm_system_iface_flush_addresses (int ifindex, int family) -{ - g_return_val_if_fail (ifindex > 0, FALSE); - return sync_addresses (ifindex, family, NULL, 0); -} - - -static struct rtnl_route * -delete_one_route (struct rtnl_route *route, - struct nl_addr *dst, - const char *iface, - gpointer user_data) -{ - guint32 log_level = GPOINTER_TO_UINT (user_data); - - nm_log_dbg (log_level, " deleting route"); - if (!nm_netlink_route_delete (route)) - nm_log_err (LOGD_DEVICE, "(%s): failed to delete route", iface); - - return NULL; -} - -/** - * nm_system_iface_flush_routes: - * @ifindex: interface index - * @family: address family, i.e. AF_INET, AF_INET6, or AF_UNSPEC - * - * Flush all network addresses associated with a network device. - * - * Returns: %TRUE on success, %FALSE on failure - **/ -gboolean -nm_system_iface_flush_routes (int ifindex, int family) -{ - guint32 log_level = LOGD_IP4 | LOGD_IP6; - const char *sf = "UNSPEC"; - char *iface; - - g_return_val_if_fail (ifindex > 0, FALSE); - - iface = nm_netlink_index_to_iface (ifindex); - g_return_val_if_fail (iface != NULL, FALSE); - - if (family == AF_INET) { - log_level = LOGD_IP4; - sf = "INET"; - } else if (family == AF_INET6) { - log_level = LOGD_IP6; - sf = "INET6"; - } - nm_log_dbg (log_level, "(%s): flushing routes ifindex %d family %s (%d)", - iface, ifindex, sf, family); - - /* We don't want to flush IPv6 link-local routes that may exist on the - * the interface since the LL address and routes should normally stay - * assigned all the time. - */ - nm_netlink_foreach_route (ifindex, family, RT_SCOPE_UNIVERSE, TRUE, delete_one_route, GUINT_TO_POINTER (log_level)); - - g_free (iface); - return TRUE; -} - -static struct rtnl_route * -find_route (struct rtnl_route *route, - struct nl_addr *dst, - const char *iface, - gpointer user_data) -{ - NMIP4Config *config = user_data; - struct in_addr *dst_addr; - int num; - int i; - - if (dst && (nl_addr_get_family (dst) != AF_INET)) - return NULL; - - /* Find the first route that handles a subnet of at least one of the - * device's IPv4 addresses. - */ - dst_addr = nl_addr_get_binary_addr (dst); - num = nm_ip4_config_get_num_addresses (config); - for (i = 0; i < num; i++) { - NMIP4Address *addr = nm_ip4_config_get_address (config, i); - guint32 prefix = nm_ip4_address_get_prefix (addr); - guint32 address = nm_ip4_address_get_address (addr); - - if ( prefix == nl_addr_get_prefixlen (dst) - && (address & nm_utils_ip4_prefix_to_netmask (prefix)) == dst_addr->s_addr) - return route; - } - return NULL; -} - -static void -nm_system_device_set_priority (int ifindex, - NMIP4Config *config, - int priority) -{ - struct nl_sock *nlh; - struct rtnl_route *found; - - found = nm_netlink_foreach_route (ifindex, AF_INET, RT_SCOPE_LINK, FALSE, find_route, config); - if (found) { - nlh = nm_netlink_get_default_handle (); - nm_netlink_route_delete (found); - rtnl_route_set_priority (found, priority); - rtnl_route_add (nlh, found, 0); - rtnl_route_put (found); - } -} - -static const struct { - const char *option; - const char *default_value; -} bonding_defaults[] = { - { "mode", "balance-rr" }, - { "arp_interval", "0" }, - { "miimon", "0" }, - - { "ad_select", "stable" }, - { "arp_validate", "none" }, - { "downdelay", "0" }, - { "fail_over_mac", "none" }, - { "lacp_rate", "slow" }, - { "min_links", "0" }, - { "num_grat_arp", "1" }, - { "num_unsol_na", "1" }, - { "primary", "" }, - { "primary_reselect", "always" }, - { "resend_igmp", "1" }, - { "updelay", "0" }, - { "use_carrier", "1" }, - { "xmit_hash_policy", "layer2" }, - { NULL, NULL } -}; - -static void -remove_bonding_entries (const char *iface, const char *path) -{ - char cmd[20]; - char *value, **entries; - gboolean ret; - int i; - - if (!g_file_get_contents (path, &value, NULL, NULL)) - return; - - entries = g_strsplit (value, " ", -1); - for (i = 0; entries[i]; i++) { - snprintf (cmd, sizeof (cmd), "-%s", g_strstrip (entries[i])); - ret = nm_utils_do_sysctl (path, cmd); - if (!ret) { - nm_log_warn (LOGD_HW, "(%s): failed to remove entry '%s' from '%s'", - iface, entries[i], path); - } - } - g_strfreev (entries); -} - -static gboolean -option_valid_for_nm_setting (const char *option, const char **valid_opts) -{ - while (*valid_opts) { - if (strcmp (option, *valid_opts) == 0) - return TRUE; - valid_opts++; - } - return FALSE; -} - -gboolean -nm_system_apply_bonding_config (const char *iface, NMSettingBond *s_bond) -{ - const char **valid_opts; - const char *option, *value; - char path[FILENAME_MAX]; - char *current, *space; - gboolean ret; - int i; - - g_return_val_if_fail (iface != NULL, FALSE); - - /* Remove old slaves and arp_ip_targets */ - snprintf (path, sizeof (path), "/sys/class/net/%s/bonding/arp_ip_target", iface); - remove_bonding_entries (iface, path); - snprintf (path, sizeof (path), "/sys/class/net/%s/bonding/slaves", iface); - remove_bonding_entries (iface, path); - - /* Apply config/defaults */ - valid_opts = nm_setting_bond_get_valid_options (s_bond); - for (i = 0; bonding_defaults[i].option; i++) { - option = bonding_defaults[i].option; - if (option_valid_for_nm_setting (option, valid_opts)) - value = nm_setting_bond_get_option_by_name (s_bond, option); - else - value = NULL; - if (!value) - value = bonding_defaults[i].default_value; - - snprintf (path, sizeof (path), "/sys/class/net/%s/bonding/%s", iface, option); - if (g_file_get_contents (path, ¤t, NULL, NULL)) { - g_strstrip (current); - space = strchr (current, ' '); - if (space) - *space = '\0'; - if (strcmp (current, value) != 0) { - ret = nm_utils_do_sysctl (path, value); - if (!ret) { - nm_log_warn (LOGD_HW, "(%s): failed to set bonding attribute " - "'%s' to '%s'", iface, option, value); - } - } - } - } - - /* Handle arp_ip_target */ - value = nm_setting_bond_get_option_by_name (s_bond, "arp_ip_target"); - if (value) { - char **addresses, cmd[20]; - - snprintf (path, sizeof (path), "/sys/class/net/%s/bonding/arp_ip_target", iface); - addresses = g_strsplit (value, ",", -1); - for (i = 0; addresses[i]; i++) { - snprintf (cmd, sizeof (cmd), "+%s", g_strstrip (addresses[i])); - ret = nm_utils_do_sysctl (path, cmd); - if (!ret) { - nm_log_warn (LOGD_HW, "(%s): failed to add arp_ip_target '%s'", - iface, addresses[i]); - } - } - g_strfreev (addresses); - } - - return TRUE; -} - -/** - * nm_system_add_bonding_master: - * @iface: the interface name for the new bond master - * - * Adds a virtual bonding device if it does not exist yet. - * - * Returns: %TRUE on success, %FALSE on failure - */ -gboolean -nm_system_add_bonding_master (const char *iface) -{ - struct nl_sock *sock; - int err; - - g_return_val_if_fail (iface != NULL, FALSE); - - /* When the kernel loads the bond module, either via explicit modprobe - * or automatically in response to creating a bond master, it will also - * create a 'bond0' interface. Since the bond we're about to create may - * or may not be named 'bond0' prevent potential confusion about a bond - * that the user didn't want by telling the bonding module not to create - * bond0 automatically. - */ - if (!g_file_test ("/sys/class/net/bonding_masters", G_FILE_TEST_EXISTS)) - nm_spawn_process ("modprobe bonding max_bonds=0"); - - sock = nm_netlink_get_default_handle (); - - /* Existing bonding devices with matching name will be reused */ - err = rtnl_link_bond_add (sock, iface, NULL); - if (err < 0) { - nm_log_err (LOGD_DEVICE, "(%s): error %d returned from " - "rtnl_link_bond_add(): %s", - iface, err, nl_geterror (err)); - return FALSE; - } - return TRUE; -} - -static gboolean -nm_system_bond_compat_enslave (const char *master_iface, const char *slave_iface) -{ - struct ifreq ifr; - int fd; - gboolean ret = FALSE; - - memset (&ifr, 0, sizeof (ifr)); - - fd = socket (PF_INET, SOCK_DGRAM, 0); - if (fd < 0) { - nm_log_err (LOGD_DEVICE, "couldn't open control socket."); - return FALSE; - } - - strncpy (ifr.ifr_name, master_iface, IFNAMSIZ); - strncpy (ifr.ifr_slave, slave_iface, IFNAMSIZ); - - if (ioctl (fd, SIOCBONDENSLAVE, &ifr) < 0 && - ioctl (fd, BOND_ENSLAVE_OLD, &ifr) < 0) { - nm_log_err (LOGD_DEVICE, "(%s): error enslaving %s: %d (%s)", - master_iface, slave_iface, errno, strerror (errno)); - } else - ret = TRUE; - - close (fd); - - return ret; -} - -/** - * nm_system_bond_enslave: - * @master_ifindex: master device interface index - * @master_iface: master device interface name - * @slave_ifindex: slave device interface index - * @slave_iface: slave device interface name - * - * Enslaves the 'slave' to 'master. This function targets implementing a - * generic interface to attaching all kinds of slaves to masters. Currently - * only bonding is properly supported due to the backwards compatibility - * function being bonding specific. - * - * The slave device needs to be down as a prerequisite. - * - * Returns: %TRUE on success, or %FALSE - */ -gboolean -nm_system_bond_enslave (gint master_ifindex, - const char *master_iface, - gint slave_ifindex, - const char *slave_iface) -{ - struct nl_sock *sock; - int err; - - g_return_val_if_fail (master_ifindex > 0, FALSE); - g_return_val_if_fail (master_iface != NULL, FALSE); - g_return_val_if_fail (slave_ifindex > 0, FALSE); - g_return_val_if_fail (slave_iface != NULL, FALSE); - - sock = nm_netlink_get_default_handle (); - - if (!(nm_system_iface_get_flags (master_ifindex) & IFF_MASTER)) { - nm_log_err (LOGD_DEVICE, "(%s): interface is not a master", master_iface); - return FALSE; - } - - g_assert (!nm_system_iface_is_up (slave_ifindex)); - - if (nm_system_iface_get_flags (slave_ifindex) & IFF_SLAVE) { - struct rtnl_link *lk; - int existing_master = -1; - - /* Get the ifindex of the existing master device */ - lk = nm_netlink_index_to_rtnl_link (slave_ifindex); - g_warn_if_fail (lk != NULL); - if (lk) { - existing_master = rtnl_link_get_master (lk); - rtnl_link_put (lk); - } - - if (existing_master > 0) { - /* Fail if the device is already a slave of a different master */ - if (existing_master != master_ifindex) { - nm_log_err (LOGD_DEVICE, "(%s): already a slave of a different master", - slave_iface); - return FALSE; - } - - nm_log_dbg (LOGD_DEVICE, "(%s): %s is already enslaved", - master_iface, slave_iface); - return TRUE; - } - } - - err = rtnl_link_bond_enslave_ifindex (sock, master_ifindex, slave_ifindex); - if (err == -NLE_OPNOTSUPP) - return nm_system_bond_compat_enslave (master_iface, slave_iface); - - if (err < 0) { - nm_log_err (LOGD_DEVICE, "(%s): error enslaving %s: %d (%s)", - master_iface, slave_iface, err, nl_geterror (err)); - return FALSE; - } - - return TRUE; -} - -static gboolean -nm_system_bond_compat_release (const char *master_iface, const char *slave_iface) -{ - struct ifreq ifr; - int fd; - gboolean ret = FALSE; - - memset (&ifr, 0, sizeof (ifr)); - - fd = socket (PF_INET, SOCK_DGRAM, 0); - if (fd < 0) { - nm_log_err (LOGD_DEVICE, "couldn't open control socket."); - return FALSE; - } - - strncpy (ifr.ifr_name, master_iface, IFNAMSIZ); - strncpy (ifr.ifr_slave, slave_iface, IFNAMSIZ); - - if (ioctl (fd, SIOCBONDRELEASE, &ifr) < 0 && - ioctl (fd, BOND_RELEASE_OLD, &ifr) < 0) { - nm_log_err (LOGD_DEVICE, "(%s): error releasing slave %s: %d (%s)", - master_iface, slave_iface, errno, strerror (errno)); - } else - ret = TRUE; - - close (fd); - return ret; -} - -/** - * nm_system_bond_release: - * @master_ifindex: master device interface index - * @master_iface: master device interface name - * @slave_ifindex: slave device interface index - * @slave_iface: slave device interface name - * - * Releases the 'slave' which is attached to 'master. This function targets - * implementing a generic interface to releasing all kinds of slaves. Currently - * only bonding is properly supported due to the backwards compatibility - * function being bonding specific. - * - * Returns: %TRUE on success, or %FALSE - */ -gboolean -nm_system_bond_release (gint master_ifindex, - const char *master_iface, - gint slave_ifindex, - const char *slave_iface) -{ - struct nl_sock *sock; - int err; - - g_return_val_if_fail (master_ifindex > 0, FALSE); - g_return_val_if_fail (master_iface != NULL, FALSE); - g_return_val_if_fail (slave_ifindex > 0, FALSE); - g_return_val_if_fail (slave_iface != NULL, FALSE); - - sock = nm_netlink_get_default_handle (); - - /* Only release if this is actually a slave */ - if (!(nm_system_iface_get_flags (slave_ifindex) & IFF_SLAVE)) - return TRUE; - - err = rtnl_link_bond_release_ifindex (sock, slave_ifindex); - if (err == -NLE_OPNOTSUPP) - return nm_system_bond_compat_release (master_iface, slave_iface); - else if (err < 0) { - nm_log_err (LOGD_DEVICE, "(%s): error releasing slave %s: %d (%s)", - master_iface, slave_iface, err, nl_geterror (err)); - return FALSE; - } - - return TRUE; -} - -/** - * nm_system_compat_get_iface_type: - * @ifindex: interface index - * @name: name of interface - * - * Lookup the type of an interface. At least one of @ifindex or @name must - * be provided. - * - * Returns: Interface type (NM_IFACE_TYPE_*) or NM_IFACE_TYPE_UNSPEC. - **/ -static int -nm_system_compat_get_iface_type (int ifindex, const char *name) -{ - int res = NM_IFACE_TYPE_UNSPEC; - char *ifname = NULL, *path = NULL; - struct vlan_ioctl_args ifv; - struct ifreq ifr; - struct ifbond ifb; - struct stat st; - int fd; - - g_return_val_if_fail (ifindex > 0 || name, NM_IFACE_TYPE_UNSPEC); - - if ((fd = socket (AF_INET, SOCK_STREAM, 0)) < 0) { - nm_log_err (LOGD_DEVICE, "couldn't open control socket."); - goto out; - } - - if (!name) { - g_assert (ifindex > 0); - ifname = nm_netlink_index_to_iface (ifindex); - } - - /* Check VLAN */ - memset (&ifv, 0, sizeof (ifv)); - ifv.cmd = GET_VLAN_VID_CMD; - strncpy (ifv.device1, ifname ? ifname : name, sizeof (ifv.device1) - 1); - if (ioctl (fd, SIOCGIFVLAN, &ifv) == 0) { - res = NM_IFACE_TYPE_VLAN; - goto out; - } - - /* and bond */ - memset (&ifr, 0, sizeof (ifr)); - strncpy (ifr.ifr_name, ifname ? ifname : name, sizeof (ifr.ifr_name) - 1); - memset (&ifb, 0, sizeof (ifb)); - ifr.ifr_data = (caddr_t) &ifb; - if (ioctl (fd, SIOCBONDINFOQUERY, &ifr) == 0) { - res = NM_IFACE_TYPE_BOND; - goto out; - } - - /* and bridge */ - path = g_strdup_printf ("/sys/class/net/%s/bridge", ifname ? ifname : name); - if ((stat (path, &st) == 0) && S_ISDIR (st.st_mode)) { - res = NM_IFACE_TYPE_BRIDGE; - goto out; - } - -out: - g_free (path); - close (fd); - g_free (ifname); - return res; -} - -/** - * nm_system_get_iface_type: - * @ifindex: interface index - * @name: name of interface - * - * Lookup the type of an interface. At least one of @ifindex or @name must - * be provided. - * - * Returns: Interface type (NM_IFACE_TYPE_*) or NM_IFACE_TYPE_UNSPEC. - **/ -int -nm_system_get_iface_type (int ifindex, const char *name) -{ - struct rtnl_link *result; - struct nl_sock *nlh; - char *type; - int res = NM_IFACE_TYPE_UNSPEC; - int err; - - g_return_val_if_fail (ifindex > 0 || name, NM_IFACE_TYPE_UNSPEC); - - nlh = nm_netlink_get_default_handle (); - if (!nlh) - goto out; - - /* Prefer interface indexes to names */ - err = rtnl_link_get_kernel (nlh, ifindex, ifindex <= 0 ? name : NULL, &result); - if (err < 0) { - if (err == -NLE_OPNOTSUPP) - res = nm_system_compat_get_iface_type (ifindex, name); - goto out; - } - - type = rtnl_link_get_type (result); - - if (!g_strcmp0 (type, "bond")) - res = NM_IFACE_TYPE_BOND; - else if (!g_strcmp0 (type, "vlan")) - res = NM_IFACE_TYPE_VLAN; - else if (!g_strcmp0 (type, "bridge")) - res = NM_IFACE_TYPE_BRIDGE; - else if (!g_strcmp0 (type, "dummy")) - res = NM_IFACE_TYPE_DUMMY; - - rtnl_link_put (result); -out: - return res; -} - -/** - * nm_system_get_iface_vlan_info: - * @ifindex: the VLAN interface index - * @out_parent_ifindex: on success, the interface index of the parent interface of - * @iface - * @out_vlan_id: on success, the VLAN ID of @iface - * - * Gets the VLAN parent interface name and VLAN ID. - * - * Returns: %TRUE if the interface is a VLAN device and no error occurred; - * %FALSE if the interface was not a VLAN interface or an error occurred - **/ -gboolean -nm_system_get_iface_vlan_info (int ifindex, - int *out_parent_ifindex, - int *out_vlan_id) -{ - struct nl_sock *nlh; - struct rtnl_link *lk; - struct nl_cache *cache = NULL; - gboolean success = FALSE; - int ret; - - if (nm_system_get_iface_type (ifindex, NULL) != NM_IFACE_TYPE_VLAN) - return FALSE; - - nlh = nm_netlink_get_default_handle (); - if (!nlh) - return FALSE; - - ret = rtnl_link_alloc_cache (nlh, AF_UNSPEC, &cache); - g_return_val_if_fail (ret == 0, FALSE); - g_return_val_if_fail (cache != NULL, FALSE); - - lk = rtnl_link_get (cache, ifindex); - if (lk) { - if (out_parent_ifindex) - *out_parent_ifindex = rtnl_link_get_link (lk); - if (out_vlan_id) - *out_vlan_id = rtnl_link_vlan_get_id (lk); - - rtnl_link_put (lk); - success = TRUE; - } - - nl_cache_free (cache); - return success; -} - -static gboolean -nm_system_iface_compat_set_name (const char *old_name, const char *new_name) -{ - int fd; - struct ifreq ifr; - - if ((fd = socket (AF_INET, SOCK_STREAM, 0)) < 0) { - nm_log_err (LOGD_DEVICE, "couldn't open control socket."); - return -1; - } - - memset (&ifr, 0, sizeof (struct ifreq)); - strncpy (ifr.ifr_name, old_name, sizeof (ifr.ifr_name)); - strncpy (ifr.ifr_newname, new_name, sizeof (ifr.ifr_newname)); - - if (ioctl (fd, SIOCSIFNAME, &ifr) < 0) { - nm_log_err (LOGD_DEVICE, "cann't change %s with %s.", old_name, new_name); - close (fd); - return FALSE; - } - - close (fd); - return TRUE; -} - -static gboolean -nm_system_iface_compat_set_vlan_name_type (int name_type) -{ - int fd; - struct vlan_ioctl_args if_request; - - if ((fd = socket (AF_INET, SOCK_STREAM, 0)) < 0) { - nm_log_err (LOGD_DEVICE, "couldn't open control socket."); - return -1; - } - - memset (&if_request, 0, sizeof (struct vlan_ioctl_args)); - if_request.cmd = SET_VLAN_NAME_TYPE_CMD; - if_request.u.name_type = name_type; - - if (ioctl (fd, SIOCSIFVLAN, &if_request) < 0) { - nm_log_err (LOGD_DEVICE, "couldn't set name type."); - close (fd); - return FALSE; - } - - close (fd); - return TRUE; -} - -static gboolean -nm_system_iface_compat_add_vlan_device (const char *master, int vid) -{ - int fd; - struct vlan_ioctl_args if_request; - - g_return_val_if_fail (master, FALSE); - g_return_val_if_fail (vid < 4096, FALSE); - - /* - * use VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD as default, - * we will overwrite it with rtnl_link_set_name() later. - */ - if (!nm_system_iface_compat_set_vlan_name_type (VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD)) - return FALSE; - - if ((fd = socket (AF_INET, SOCK_STREAM, 0)) < 0) { - nm_log_err (LOGD_DEVICE, "couldn't open control socket."); - return -1; - } - - memset (&if_request, 0, sizeof (struct vlan_ioctl_args)); - g_strlcpy (if_request.device1, master, sizeof (if_request.device1)); - if_request.cmd = ADD_VLAN_CMD; - if_request.u.VID = vid; - - if (ioctl (fd, SIOCSIFVLAN, &if_request) < 0) { - nm_log_err (LOGD_DEVICE, "couldn't add vlan device %s vid %d: %d.", master, vid, errno); - close (fd); - return FALSE; - } - - close (fd); - return TRUE; -} - -static gboolean -nm_system_iface_compat_rem_vlan_device (const char *iface) -{ - int fd; - struct vlan_ioctl_args if_request; - - if ((fd = socket (AF_INET, SOCK_STREAM, 0)) < 0) { - nm_log_err (LOGD_DEVICE, "couldn't open control socket."); - return -1; - } - - memset (&if_request, 0, sizeof (struct vlan_ioctl_args)); - g_strlcpy (if_request.device1, iface, sizeof (if_request.device1)); - if_request.cmd = DEL_VLAN_CMD; - - if (ioctl (fd, SIOCSIFVLAN, &if_request) < 0) { - nm_log_err (LOGD_DEVICE, "couldn't rem vlan device %s.", iface); - close (fd); - return FALSE; - } - - close (fd); - return TRUE; -} - -static gboolean -nm_system_iface_compat_add_vlan (NMConnection *connection, - const char *iface, - int master_ifindex) -{ - NMSettingVlan *s_vlan; - int vlan_id; - guint32 vlan_flags = 0; - guint32 num, i, from, to; - int ifindex; - struct rtnl_link *new_link = NULL; - char *master = nm_netlink_index_to_iface (master_ifindex); - int itype; - gboolean created = FALSE; - - s_vlan = nm_connection_get_setting_vlan (connection); - g_return_val_if_fail (s_vlan, FALSE); - - vlan_id = nm_setting_vlan_get_id (s_vlan); - - if (!iface) { - iface = nm_connection_get_virtual_iface_name (connection); - g_return_val_if_fail (iface != NULL, FALSE); - } - - itype = nm_system_get_iface_type (-1, iface); - if (itype == NM_IFACE_TYPE_UNSPEC) { - char *name; - - /* Create the VLAN interface. Use VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD as - * default and change the name later via nm_system_iface_compat_set_name(). - * The old ioctl-based VLAN kernel API has no ability to directly return - * the new interface's name or index, so we have to create it with a - * known name and do the rename dance instead. - */ - if (!nm_system_iface_compat_add_vlan_device (master, vlan_id)) - return FALSE; - - /* And rename it to what the connection wants */ - name = nm_utils_new_vlan_name (master, vlan_id); - if (strcmp (name, iface) != 0) { - if (!nm_system_iface_compat_set_name (name, iface)) { - nm_system_iface_compat_rem_vlan_device (name); - g_free (name); - return FALSE; - } - } - g_free (name); - created = TRUE; - } else if (itype != NM_IFACE_TYPE_VLAN) { - nm_log_err (LOGD_DEVICE, "(%s): already exists but is not a VLAN interface.", iface); - return FALSE; - } else { - int tmp_vlan_id = -1, tmp_master_ifindex = -1; - - /* VLAN interface with this name already exists. Be a bit paranoid and - * double-check the VLAN ID and parent ifindex. - */ - ifindex = nm_netlink_iface_to_index (iface); - if (ifindex <= 0) - return FALSE; - - if (!nm_system_get_iface_vlan_info (ifindex, &tmp_master_ifindex, &tmp_vlan_id)) { - nm_log_err (LOGD_DEVICE, "(%s): failed to get VLAN interface info.", iface); - return FALSE; - } - - if (tmp_master_ifindex != master_ifindex) { - nm_log_err (LOGD_DEVICE, "(%s): master ifindex (%d) does match expected (%d).", - iface, tmp_master_ifindex, master_ifindex); - return FALSE; - } - - if (tmp_vlan_id != vlan_id) { - nm_log_err (LOGD_DEVICE, "(%s): VLAN ID %d does match expected ID %d.", - iface, tmp_vlan_id, vlan_id); - return FALSE; - } - - nm_log_dbg (LOGD_DEVICE, "(%s): found existing VLAN interface.", iface); - } - - ifindex = nm_netlink_iface_to_index (iface); - if (ifindex <= 0) - goto error; - - new_link = nm_netlink_index_to_rtnl_link (ifindex); - if (!new_link) - goto error; - - /* vconfig set_flag */ - vlan_flags = nm_setting_vlan_get_flags (s_vlan); - if (vlan_flags) { - if (rtnl_link_vlan_set_flags (new_link, vlan_flags)) - goto error_new_link; - } - - /* vconfig set_ingress_map */ - num = nm_setting_vlan_get_num_priorities (s_vlan, NM_VLAN_INGRESS_MAP); - for (i = 0; i < num; i++) { - if (nm_setting_vlan_get_priority (s_vlan, NM_VLAN_INGRESS_MAP, i, &from, &to)) { - if (rtnl_link_vlan_set_ingress_map (new_link, from, to)) - goto error_new_link; - } - } - - /* vconfig set_egress_map */ - num = nm_setting_vlan_get_num_priorities (s_vlan, NM_VLAN_EGRESS_MAP); - for (i = 0; i < num; i++) { - if (nm_setting_vlan_get_priority (s_vlan, NM_VLAN_EGRESS_MAP, i, &from, &to)) { - if (rtnl_link_vlan_set_egress_map (new_link, from, to)) - goto error_new_link; - } - } - - rtnl_link_put (new_link); - return TRUE; - -error_new_link: - rtnl_link_put (new_link); - /* fall through */ - -error: - if (created) - nm_system_iface_compat_rem_vlan_device (iface); - return FALSE; -} - -/** - * nm_system_add_vlan_iface: - * @connection: the #NMConnection that describes the VLAN interface - * @iface: the interface name of the new VLAN interface - * @parent_ifindex: the interface index of the new VLAN interface's master - * interface - * - * Add a VLAN device named @iface and specified in @connection. - * - * Returns: %TRUE on success, %FALSE on failure - */ -gboolean -nm_system_add_vlan_iface (NMConnection *connection, - const char *iface, - int parent_ifindex) -{ - NMSettingVlan *s_vlan; - int ret = -1; - struct rtnl_link *new_link = NULL; - struct nl_sock *nlh = NULL; - guint32 vlan_id = 0; - guint32 vlan_flags = 0; - guint32 num, i, from, to; - - g_return_val_if_fail (parent_ifindex > 0, FALSE); - - nlh = nm_netlink_get_default_handle (); - g_return_val_if_fail (nlh != NULL, FALSE); - - s_vlan = nm_connection_get_setting_vlan (connection); - g_return_val_if_fail (s_vlan, FALSE); - - vlan_id = nm_setting_vlan_get_id (s_vlan); - - if (!iface) { - iface = nm_connection_get_virtual_iface_name (connection); - g_return_val_if_fail (iface != NULL, FALSE); - } - - new_link = rtnl_link_alloc (); - if (!new_link) { - g_warn_if_fail (new_link != NULL); - goto out; - } - - ret = rtnl_link_set_type (new_link, "vlan"); - if (ret == -NLE_OPNOTSUPP) { - /* - * There is no linbl3, try ioctl. - */ - ret = -1; - if (nm_system_iface_compat_add_vlan (connection, iface, parent_ifindex)) - ret = 0; - goto out; - } - - rtnl_link_set_link (new_link, parent_ifindex); - rtnl_link_set_name (new_link, iface); - rtnl_link_vlan_set_id (new_link, vlan_id); - - vlan_flags = nm_setting_vlan_get_flags (s_vlan); - if (vlan_flags) { - guint kernel_flags = 0; - - if (vlan_flags & NM_VLAN_FLAG_REORDER_HEADERS) - kernel_flags |= VLAN_FLAG_REORDER_HDR; - if (vlan_flags & NM_VLAN_FLAG_GVRP) - kernel_flags |= VLAN_FLAG_GVRP; - if (vlan_flags & NM_VLAN_FLAG_LOOSE_BINDING) - kernel_flags |= VLAN_FLAG_LOOSE_BINDING; - - rtnl_link_vlan_set_flags (new_link, kernel_flags); - } - - num = nm_setting_vlan_get_num_priorities (s_vlan, NM_VLAN_INGRESS_MAP); - for (i = 0; i < num; i++) { - if (nm_setting_vlan_get_priority (s_vlan, NM_VLAN_INGRESS_MAP, i, &from, &to)) - rtnl_link_vlan_set_ingress_map (new_link, (int) from, (int) to); - } - - num = nm_setting_vlan_get_num_priorities (s_vlan, NM_VLAN_EGRESS_MAP); - for (i = 0; i < num; i++) { - if (nm_setting_vlan_get_priority (s_vlan, NM_VLAN_EGRESS_MAP, i, &from, &to)) - rtnl_link_vlan_set_egress_map (new_link, (int) from, (int) to); - } - - ret = rtnl_link_add (nlh, new_link, NLM_F_CREATE); - -out: - if (new_link) - rtnl_link_put (new_link); - return (ret == 0); -} - -/** - * nm_system_del_vlan_iface: - * @iface: the interface name - * - * Delete a VLAN interface specified by @iface. - * - * Returns: %TRUE on success, or %FALSE - */ -gboolean -nm_system_del_vlan_iface (const char *iface) -{ - int ret = 0; - struct nl_sock *nlh = NULL; - struct nl_cache *cache = NULL; - struct rtnl_link *new_link = NULL; - int itype; - - g_return_val_if_fail (iface != NULL, FALSE); - - itype = nm_system_get_iface_type (-1, iface); - g_return_val_if_fail (itype == NM_IFACE_TYPE_VLAN, FALSE); - - nlh = nm_netlink_get_default_handle (); - g_return_val_if_fail (nlh != NULL, FALSE); - - ret = rtnl_link_alloc_cache (nlh, AF_UNSPEC, &cache); - g_return_val_if_fail (ret == 0, FALSE); - g_return_val_if_fail (cache != NULL, FALSE); - - new_link = rtnl_link_get_by_name (cache, iface); - if (new_link) { - ret = rtnl_link_delete (nlh, new_link); - if (ret == -NLE_OPNOTSUPP) { - /* - * There is no linbl3, try ioctl. - */ - ret = -1; - if (nm_system_iface_compat_rem_vlan_device (iface)) - ret = 0; - } - } - - rtnl_link_put (new_link); - nl_cache_free (cache); - return (ret == 0) ? TRUE : FALSE; -} - -static int -_bridge_create_compat (const char *iface) -{ - int ret = 0, fd; - - if ((fd = socket (AF_LOCAL, SOCK_STREAM, 0)) < 0) { - nm_log_err (LOGD_DEVICE, "couldn't open control socket."); - return -EBADF; - } - - if (ioctl (fd, SIOCBRADDBR, iface) < 0) - ret = -errno; - - close (fd); - return ret; -} - -/** - * nm_system_create_bridge: - * @iface: Name bridging device to create - * @out_exists: on return, %TRUE if the bridge already exists - * - * Creates a new bridging device in the kernel. If a bridging device with - * the specified name already exists, it is reused and no error is returned, - * but @out_exists is set to %TRUE. - * - * Returns: %TRUE on success, %FALSE on error. - */ -gboolean -nm_system_create_bridge (const char *iface, gboolean *out_exists) -{ - int err; - - /* FIXME: use netlink */ - err = _bridge_create_compat (iface); - if (err < 0 && err != -EEXIST) { - nm_log_err (LOGD_DEVICE, "(%s): error while adding bridge: %s", - iface, strerror (-err)); - return FALSE; - } - if (out_exists && err == -EEXIST) - *out_exists = TRUE; - return TRUE; -} - -static int -_bridge_del_compat (const char *iface) -{ - int ret = 0, fd; - - if ((fd = socket (AF_LOCAL, SOCK_STREAM, 0)) < 0) { - nm_log_err (LOGD_DEVICE, "couldn't open control socket."); - return -EBADF; - } - - if (ioctl (fd, SIOCBRDELBR, iface) < 0) - ret = -errno; - - close (fd); - return ret; -} - -/** - * nm_system_del_bridge: - * @iface: Name of bridging device to delete - * - * Deletes the specified bridging device in the kernel. - * - * Returns: %TRUE on success, %FALSE on error. - */ -gboolean -nm_system_del_bridge (const char *iface) -{ - int err; - - /* FIXME: use netlink */ - err = _bridge_del_compat (iface); - if (err < 0 && err != -ENXIO) { - nm_log_err (LOGD_DEVICE, "(%s): error while deleting bridge: %s ", - iface, strerror (-err)); - return FALSE; - } - return TRUE; -} - -static int -_bridge_attach_compat (int master_ifindex, - const char *master_iface, - int slave_ifindex, - const char *slave_iface) -{ - int ret = 0, fd; - struct ifreq ifr; - - if ((fd = socket (AF_LOCAL, SOCK_STREAM, 0)) < 0) { - nm_log_err (LOGD_DEVICE, "couldn't open control socket."); - return -EBADF; - } - - memset (&ifr, 0, sizeof (ifr)); - strncpy (ifr.ifr_name, master_iface, IFNAMSIZ); - ifr.ifr_ifindex = slave_ifindex; - if (ioctl (fd, SIOCBRADDIF, &ifr) < 0) - ret = -errno; - - close (fd); - return ret; -} - -static int -_bridge_detach_compat (int master_ifindex, - const char *master_iface, - int slave_ifindex, - const char *slave_iface) -{ - int ret = 0, fd; - struct ifreq ifr; - - if ((fd = socket (AF_LOCAL, SOCK_STREAM, 0)) < 0) { - nm_log_err (LOGD_DEVICE, "couldn't open control socket."); - return -EBADF; - } - - memset (&ifr, 0, sizeof(ifr)); - strncpy (ifr.ifr_name, master_iface, IFNAMSIZ); - ifr.ifr_ifindex = slave_ifindex; - if (ioctl (fd, SIOCBRDELIF, &ifr) < 0) - ret = -errno; - - close (fd); - return ret; -} - -/** - * nm_system_bridge_attach: - * @master_ifindex: master device interface index - * @master_iface: master device interface name - * @slave_ifindex: slave device interface index - * @slave_iface: slave device interface name - * - * Attaches interface 'slave' to bridge 'master' - * - * Returns: %TRUE on success, or %FALSE - */ -gboolean -nm_system_bridge_attach (int master_ifindex, - const char *master_iface, - int slave_ifindex, - const char *slave_iface) -{ - char *mif = NULL, *sif = NULL; - int err = -1; - - g_return_val_if_fail (master_ifindex >= 0, FALSE); - g_return_val_if_fail (slave_ifindex >= 0, FALSE); - - if (!master_iface) { - mif = nm_netlink_index_to_iface (master_ifindex); - if (mif == NULL) { - nm_log_err (LOGD_DEVICE, "interface name lookup failed for index %d", master_ifindex); - goto out; - } - } - - if (!slave_ifindex) { - sif = nm_netlink_index_to_iface (slave_ifindex); - if (sif == NULL) { - nm_log_err (LOGD_DEVICE, "interface name lookup failed for index %d", slave_ifindex); - goto out; - } - } - - /* FIXME: long term plan is to use netlink for this */ - err = _bridge_attach_compat (master_ifindex, - mif ? mif : master_iface, - slave_ifindex, - sif ? sif : slave_iface); - if (err < 0) { - if (err == -EBUSY) { - /* Interface already attached to the given bridge */ - err = 0; - } else { - nm_log_err (LOGD_DEVICE, "(%s): failed to attach slave %s: %s", - master_iface, slave_iface, strerror (-err)); - } - } - -out: - g_free (sif); - g_free (mif); - return err == 0 ? TRUE : FALSE; -} - -/** - * nm_system_bridge_detach: - * @master_ifindex: master device interface index - * @master_iface: master device interface name - * @slave_ifindex: slave device interface index - * @slave_iface: slave device interface name - * - * Detaches the interface 'slave' from the bridge 'master'. - * - * Returns: %TRUE on success, or %FALSE - */ -gboolean -nm_system_bridge_detach (int master_ifindex, - const char *master_iface, - int slave_ifindex, - const char *slave_iface) -{ - char *mif = NULL, *sif = NULL; - int err = -1; - - g_return_val_if_fail (master_ifindex >= 0, FALSE); - g_return_val_if_fail (slave_ifindex >= 0, FALSE); - - if (!master_iface) { - mif = nm_netlink_index_to_iface (master_ifindex); - if (mif == NULL) { - nm_log_err (LOGD_DEVICE, "interface name lookup failed for index %d", master_ifindex); - goto out; - } - } - - if (!slave_ifindex) { - sif = nm_netlink_index_to_iface (slave_ifindex); - if (sif == NULL) { - nm_log_err (LOGD_DEVICE, "interface name lookup failed for index %d", slave_ifindex); - goto out; - } - } - - /* FIXME: long term plan is to use netlink for this */ - err = _bridge_detach_compat (master_ifindex, - mif ? mif : master_iface, - slave_ifindex, - sif ? sif : slave_iface); - /* Kernel doesn't return an error detaching an already-detached interface */ - if (err < 0) { - nm_log_err (LOGD_DEVICE, "(%s): failed to detach slave %s: %s", - master_iface, slave_iface, strerror (-err)); - } - -out: - g_free (mif); - g_free (sif); - return err == 0 ? TRUE : FALSE; -} diff --git a/src/nm-system.h b/src/nm-system.h deleted file mode 100644 index 632786d3..00000000 --- a/src/nm-system.h +++ /dev/null @@ -1,143 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2004 - 2010 Red Hat, Inc. - * Copyright (C) 2005 - 2008 Novell, Inc. - */ - -#ifndef NETWORK_MANAGER_SYSTEM_H -#define NETWORK_MANAGER_SYSTEM_H - -#include -#include - -#include - -#include -#include "nm-device.h" -#include "nm-ip4-config.h" -#include "nm-setting-bond.h" -#include "nm-setting-vlan.h" - -gboolean nm_system_iface_flush_routes (int ifindex, int family); - -gboolean nm_system_replace_default_ip4_route (int ifindex, - guint32 gw, - guint32 mss); - -gboolean nm_system_replace_default_ip6_route (int ifindex, - const struct in6_addr *gw); - -gboolean nm_system_replace_default_ip4_route_vpn (int ifindex, - guint32 ext_gw, - guint32 int_gw, - guint32 mss, - int parent_ifindex, - guint32 parent_mss); - -gboolean nm_system_replace_default_ip6_route_vpn (int ifindex, - const struct in6_addr *ext_gw, - const struct in6_addr *int_gw, - guint32 mss, - int parent_ifindex, - guint32 parent_mss); - -struct rtnl_route *nm_system_add_ip4_vpn_gateway_route (NMDevice *parent_device, - guint32 vpn_gw); -struct rtnl_route *nm_system_add_ip6_vpn_gateway_route (NMDevice *parent_device, - const struct in6_addr *vpn_gw); - -gboolean nm_system_iface_flush_addresses (int ifindex, int family); - -gboolean nm_system_apply_ip4_config (int ifindex, - NMIP4Config *config, - int priority, - NMIP4ConfigCompareFlags flags); - -int nm_system_set_ip6_route (int ifindex, - const struct in6_addr *ip6_dest, - guint32 ip6_prefix, - const struct in6_addr *ip6_gateway, - guint32 metric, - int mss, - int protocol, - int table, - struct rtnl_route **out_route); - -gboolean nm_system_apply_ip6_config (int ifindex, - NMIP6Config *config, - int priority, - NMIP6ConfigCompareFlags flags); - -gboolean nm_system_iface_set_up (int ifindex, - gboolean up, - gboolean *no_firmware); - -guint32 nm_system_iface_get_flags (int ifindex); -gboolean nm_system_iface_is_up (int ifindex); - -gboolean nm_system_iface_set_mtu (int ifindex, guint32 mtu); - -gboolean nm_system_iface_set_mac (int ifindex, const struct ether_addr *mac); - -gboolean nm_system_iface_set_arp (int ifindex, gboolean arp); - -gboolean nm_system_apply_bonding_config (const char *iface, - NMSettingBond *s_bond); -gboolean nm_system_add_bonding_master (const char *iface); - -gboolean nm_system_bond_enslave (gint master_ifindex, - const char *master_iface, - gint slave_ifindex, - const char *slave_iface); -gboolean nm_system_bond_release (gint master_ifindex, - const char *master_iface, - gint slave_ifindex, - const char *slave_iface); - -enum { - NM_IFACE_TYPE_UNSPEC = 0, - NM_IFACE_TYPE_BOND, - NM_IFACE_TYPE_VLAN, - NM_IFACE_TYPE_BRIDGE, - NM_IFACE_TYPE_DUMMY -}; - -int nm_system_get_iface_type (int ifindex, const char *name); - -gboolean nm_system_get_iface_vlan_info (int ifindex, - int *out_parent_ifindex, - int *out_vlan_id); - -gboolean nm_system_add_vlan_iface (NMConnection *connection, - const char *iface, - int parent_ifindex); -gboolean nm_system_del_vlan_iface (const char *iface); - -gboolean nm_system_create_bridge (const char *iface, gboolean *out_exists); -gboolean nm_system_del_bridge (const char *iface); - -gboolean nm_system_bridge_attach (int master_ifindex, - const char *master_iface, - int slave_ifindex, - const char *slave_iface); -gboolean nm_system_bridge_detach (int master_ifindex, - const char *master_iface, - int slave_ifindex, - const char *slave_iface); - -#endif diff --git a/src/nm-udev-manager.c b/src/nm-udev-manager.c deleted file mode 100644 index 7e867406..00000000 --- a/src/nm-udev-manager.c +++ /dev/null @@ -1,674 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2009 - 2012 Red Hat, Inc. - */ - -#include -#include - -#include -#include - -#include "nm-udev-manager.h" -#include "nm-marshal.h" -#include "nm-logging.h" -#include "nm-system.h" - -typedef struct { - GUdevClient *client; - - /* Authoritative rfkill state (RFKILL_* enum) */ - RfKillState rfkill_states[RFKILL_TYPE_MAX]; - GSList *killswitches; - - gboolean disposed; -} NMUdevManagerPrivate; - -#define NM_UDEV_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_UDEV_MANAGER, NMUdevManagerPrivate)) - -G_DEFINE_TYPE (NMUdevManager, nm_udev_manager, G_TYPE_OBJECT) - -enum { - DEVICE_ADDED, - DEVICE_REMOVED, - RFKILL_CHANGED, - - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - - -typedef struct { - char *name; - guint64 seqnum; - char *path; - char *driver; - RfKillType rtype; - gint state; - gboolean platform; -} Killswitch; - -RfKillState -nm_udev_manager_get_rfkill_state (NMUdevManager *self, RfKillType rtype) -{ - g_return_val_if_fail (self != NULL, RFKILL_UNBLOCKED); - g_return_val_if_fail (rtype < RFKILL_TYPE_MAX, RFKILL_UNBLOCKED); - - return NM_UDEV_MANAGER_GET_PRIVATE (self)->rfkill_states[rtype]; -} - -static const char * -rfkill_type_to_desc (RfKillType rtype) -{ - if (rtype == 0) - return "WiFi"; - else if (rtype == 1) - return "WWAN"; - else if (rtype == 2) - return "WiMAX"; - return "unknown"; -} - -static const char * -rfkill_state_to_desc (RfKillState rstate) -{ - if (rstate == 0) - return "unblocked"; - else if (rstate == 1) - return "soft-blocked"; - else if (rstate == 2) - return "hard-blocked"; - return "unknown"; -} - -static Killswitch * -killswitch_new (GUdevDevice *device, RfKillType rtype) -{ - Killswitch *ks; - GUdevDevice *parent = NULL, *grandparent = NULL; - const char *driver, *subsys, *parent_subsys = NULL; - - ks = g_malloc0 (sizeof (Killswitch)); - ks->name = g_strdup (g_udev_device_get_name (device)); - ks->seqnum = g_udev_device_get_seqnum (device); - ks->path = g_strdup (g_udev_device_get_sysfs_path (device)); - ks->rtype = rtype; - - driver = g_udev_device_get_property (device, "DRIVER"); - subsys = g_udev_device_get_subsystem (device); - - /* Check parent for various attributes */ - parent = g_udev_device_get_parent (device); - if (parent) { - parent_subsys = g_udev_device_get_subsystem (parent); - if (!driver) - driver = g_udev_device_get_property (parent, "DRIVER"); - if (!driver) { - /* Sigh; try the grandparent */ - grandparent = g_udev_device_get_parent (parent); - if (grandparent) - driver = g_udev_device_get_property (grandparent, "DRIVER"); - } - } - - if (!driver) - driver = "(unknown)"; - ks->driver = g_strdup (driver); - - if ( g_strcmp0 (subsys, "platform") == 0 - || g_strcmp0 (parent_subsys, "platform") == 0 - || g_strcmp0 (subsys, "acpi") == 0 - || g_strcmp0 (parent_subsys, "acpi") == 0) - ks->platform = TRUE; - - if (grandparent) - g_object_unref (grandparent); - if (parent) - g_object_unref (parent); - return ks; -} - -static void -killswitch_destroy (Killswitch *ks) -{ - g_return_if_fail (ks != NULL); - - g_free (ks->name); - g_free (ks->path); - g_free (ks->driver); - memset (ks, 0, sizeof (Killswitch)); - g_free (ks); -} - -NMUdevManager * -nm_udev_manager_new (void) -{ - return NM_UDEV_MANAGER (g_object_new (NM_TYPE_UDEV_MANAGER, NULL)); -} - -static RfKillState -sysfs_state_to_nm_state (gint sysfs_state) -{ - switch (sysfs_state) { - case 0: - return RFKILL_SOFT_BLOCKED; - case 1: - return RFKILL_UNBLOCKED; - case 2: - return RFKILL_HARD_BLOCKED; - default: - nm_log_warn (LOGD_RFKILL, "unhandled rfkill state %d", sysfs_state); - break; - } - return RFKILL_UNBLOCKED; -} - -static void -recheck_killswitches (NMUdevManager *self) -{ - NMUdevManagerPrivate *priv = NM_UDEV_MANAGER_GET_PRIVATE (self); - GSList *iter; - RfKillState poll_states[RFKILL_TYPE_MAX]; - RfKillState platform_states[RFKILL_TYPE_MAX]; - gboolean platform_checked[RFKILL_TYPE_MAX]; - int i; - - /* Default state is unblocked */ - for (i = 0; i < RFKILL_TYPE_MAX; i++) { - poll_states[i] = RFKILL_UNBLOCKED; - platform_states[i] = RFKILL_UNBLOCKED; - platform_checked[i] = FALSE; - } - - /* Poll the states of all killswitches */ - for (iter = priv->killswitches; iter; iter = g_slist_next (iter)) { - Killswitch *ks = iter->data; - GUdevDevice *device; - RfKillState dev_state; - int sysfs_state; - - device = g_udev_client_query_by_subsystem_and_name (priv->client, "rfkill", ks->name); - if (device) { - sysfs_state = g_udev_device_get_property_as_int (device, "RFKILL_STATE"); - dev_state = sysfs_state_to_nm_state (sysfs_state); - - nm_log_dbg (LOGD_RFKILL, "%s rfkill%s switch %s state now %d/%u", - rfkill_type_to_desc (ks->rtype), - ks->platform ? " platform" : "", - ks->name, - sysfs_state, - dev_state); - - if (ks->platform == FALSE) { - if (dev_state > poll_states[ks->rtype]) - poll_states[ks->rtype] = dev_state; - } else { - platform_checked[ks->rtype] = TRUE; - if (dev_state > platform_states[ks->rtype]) - platform_states[ks->rtype] = dev_state; - } - g_object_unref (device); - } - } - - /* Log and emit change signal for final rfkill states */ - for (i = 0; i < RFKILL_TYPE_MAX; i++) { - if (platform_checked[i] == TRUE) { - /* blocked platform switch state overrides device state, otherwise - * let the device state stand. (bgo #655773) - */ - if (platform_states[i] != RFKILL_UNBLOCKED) - poll_states[i] = platform_states[i]; - } - - if (poll_states[i] != priv->rfkill_states[i]) { - nm_log_dbg (LOGD_RFKILL, "%s rfkill state now '%s'", - rfkill_type_to_desc (i), - rfkill_state_to_desc (poll_states[i])); - - priv->rfkill_states[i] = poll_states[i]; - g_signal_emit (self, signals[RFKILL_CHANGED], 0, i, priv->rfkill_states[i]); - } - } -} - -static Killswitch * -killswitch_find_by_name (NMUdevManager *self, const char *name) -{ - NMUdevManagerPrivate *priv = NM_UDEV_MANAGER_GET_PRIVATE (self); - GSList *iter; - - g_return_val_if_fail (name != NULL, NULL); - - for (iter = priv->killswitches; iter; iter = g_slist_next (iter)) { - Killswitch *candidate = iter->data; - - if (!strcmp (name, candidate->name)) - return candidate; - } - return NULL; -} - -static const RfKillType -rfkill_type_to_enum (const char *str) -{ - g_return_val_if_fail (str != NULL, RFKILL_TYPE_UNKNOWN); - - if (!strcmp (str, "wlan")) - return RFKILL_TYPE_WLAN; - else if (!strcmp (str, "wwan")) - return RFKILL_TYPE_WWAN; - else if (!strcmp (str, "wimax")) - return RFKILL_TYPE_WIMAX; - - return RFKILL_TYPE_UNKNOWN; -} - -static void -add_one_killswitch (NMUdevManager *self, GUdevDevice *device) -{ - NMUdevManagerPrivate *priv = NM_UDEV_MANAGER_GET_PRIVATE (self); - const char *str_type; - RfKillType rtype; - Killswitch *ks; - - str_type = g_udev_device_get_property (device, "RFKILL_TYPE"); - rtype = rfkill_type_to_enum (str_type); - if (rtype == RFKILL_TYPE_UNKNOWN) - return; - - ks = killswitch_new (device, rtype); - priv->killswitches = g_slist_prepend (priv->killswitches, ks); - - nm_log_info (LOGD_RFKILL, "%s: found %s radio killswitch (at %s) (%sdriver %s)", - ks->name, - rfkill_type_to_desc (rtype), - ks->path, - ks->platform ? "platform " : "", - ks->driver ? ks->driver : ""); -} - -static void -rfkill_add (NMUdevManager *self, GUdevDevice *device) -{ - const char *name; - - g_return_if_fail (device != NULL); - name = g_udev_device_get_name (device); - g_return_if_fail (name != NULL); - - if (!killswitch_find_by_name (self, name)) - add_one_killswitch (self, device); -} - -static void -rfkill_remove (NMUdevManager *self, - GUdevDevice *device) -{ - NMUdevManagerPrivate *priv = NM_UDEV_MANAGER_GET_PRIVATE (self); - GSList *iter; - const char *name; - - g_return_if_fail (device != NULL); - name = g_udev_device_get_name (device); - g_return_if_fail (name != NULL); - - for (iter = priv->killswitches; iter; iter = g_slist_next (iter)) { - Killswitch *ks = iter->data; - - if (!strcmp (ks->name, name)) { - nm_log_info (LOGD_RFKILL, "radio killswitch %s disappeared", ks->path); - priv->killswitches = g_slist_remove (priv->killswitches, ks); - killswitch_destroy (ks); - break; - } - } -} - -static gboolean -dev_get_attrs (GUdevDevice *udev_device, - const char **out_ifname, - const char **out_path, - char **out_driver, - int *out_ifindex) -{ - GUdevDevice *parent = NULL, *grandparent = NULL; - const char *ifname, *driver, *path, *subsys; - gint ifindex = -1; - gboolean success = FALSE; - - g_return_val_if_fail (udev_device != NULL, FALSE); - g_return_val_if_fail (out_ifname != NULL, FALSE); - g_return_val_if_fail (out_path != NULL, FALSE); - g_return_val_if_fail (out_driver != NULL, FALSE); - g_return_val_if_fail (out_ifindex != NULL, FALSE); - - ifname = g_udev_device_get_name (udev_device); - if (!ifname) { - nm_log_dbg (LOGD_HW, "failed to get device's interface"); - return FALSE; - } - - path = g_udev_device_get_sysfs_path (udev_device); - if (!path) { - nm_log_warn (LOGD_HW, "couldn't determine device path; ignoring..."); - return FALSE; - } - - driver = g_udev_device_get_driver (udev_device); - if (!driver) { - /* Try the parent */ - parent = g_udev_device_get_parent (udev_device); - if (parent) { - driver = g_udev_device_get_driver (parent); - if (!driver) { - /* try the grandparent if it's an ibmebus device or if the - * subsys is NULL which usually indicates some sort of - * platform device like a 'gadget' net interface. - */ - subsys = g_udev_device_get_subsystem (parent); - if ( (g_strcmp0 (subsys, "ibmebus") == 0) - || (subsys == NULL)) { - grandparent = g_udev_device_get_parent (parent); - if (grandparent) - driver = g_udev_device_get_driver (grandparent); - } - } - } - } - - if (g_udev_device_get_sysfs_attr (udev_device, "ifindex")) - ifindex = g_udev_device_get_sysfs_attr_as_int (udev_device, "ifindex"); - - if (!driver) { - switch (nm_system_get_iface_type (ifindex, ifname)) { - case NM_IFACE_TYPE_BOND: - driver = "bonding"; - break; - case NM_IFACE_TYPE_BRIDGE: - driver = "bridge"; - break; - case NM_IFACE_TYPE_VLAN: - driver = "8021q"; - break; - default: - if (g_str_has_prefix (ifname, "easytether")) - driver = "easytether"; - break; - } - - if (!driver) { - nm_log_warn (LOGD_HW, "%s: couldn't determine device driver; ignoring...", path); - goto out; - } - } - - *out_ifname = ifname; - *out_path = path; - *out_driver = g_strdup (driver); - *out_ifindex = ifindex; - success = TRUE; - -out: - if (grandparent) - g_object_unref (grandparent); - if (parent) - g_object_unref (parent); - - return success; -} - -static void -net_add (NMUdevManager *self, GUdevDevice *udev_device) -{ - gint ifindex = -1; - gint etype; - const char *ifname = NULL, *path = NULL, *tmp; - char *driver = NULL; - gboolean is_ctc; - - g_return_if_fail (udev_device != NULL); - - if (!dev_get_attrs (udev_device, &ifname, &path, &driver, &ifindex)) - return; - - if (ifindex < 0) { - nm_log_warn (LOGD_HW, "%s: device had invalid ifindex %d; ignoring...", path, ifindex); - goto out; - } - - etype = g_udev_device_get_sysfs_attr_as_int (udev_device, "type"); - is_ctc = (strncmp (ifname, "ctc", 3) == 0) && (etype == 256); - - /* Ignore devices that don't report Ethernet encapsulation, except for - * s390 CTC-type devices that report 256 for some reason. - * FIXME: use something other than interface name to detect CTC here. - */ - if ((etype != ARPHRD_ETHER) && (etype != ARPHRD_INFINIBAND) && (is_ctc == FALSE)) { - nm_log_dbg (LOGD_HW, "(%s): ignoring interface with type %d", ifname, etype); - goto out; - } - - /* Not all ethernet devices are immediately usable; newer mobile broadband - * devices (Ericsson, Option, Sierra) require setup on the tty before the - * ethernet device is usable. 2.6.33 and later kernels set the 'DEVTYPE' - * uevent variable which we can use to ignore the interface as a NMDevice - * subclass. ModemManager will pick it up though and so we'll handle it - * through the mobile broadband stuff. - */ - tmp = g_udev_device_get_property (udev_device, "DEVTYPE"); - if (g_strcmp0 (tmp, "wwan") == 0) { - nm_log_dbg (LOGD_HW, "(%s): ignoring interface with devtype '%s'", ifname, tmp); - goto out; - } - - g_signal_emit (self, signals[DEVICE_ADDED], 0, udev_device, ifname, path, driver, ifindex); - -out: - g_free (driver); -} - -static void -net_remove (NMUdevManager *self, GUdevDevice *device) -{ - g_signal_emit (self, signals[DEVICE_REMOVED], 0, device); -} - -static void -adsl_add (NMUdevManager *self, GUdevDevice *udev_device) -{ - gint ifindex = -1; - const char *ifname = NULL, *path = NULL; - char *driver = NULL; - - g_return_if_fail (udev_device != NULL); - - nm_log_dbg (LOGD_HW, "adsl_add: ATM Device detected from udev. Adding .."); - - if (dev_get_attrs (udev_device, &ifname, &path, &driver, &ifindex)) - g_signal_emit (self, signals[DEVICE_ADDED], 0, udev_device, ifname, path, driver, ifindex); - g_free (driver); -} - -static void -adsl_remove (NMUdevManager *self, GUdevDevice *device) -{ - nm_log_dbg (LOGD_HW, "adsl_remove: Removing ATM Device"); - - g_signal_emit (self, signals[DEVICE_REMOVED], 0, device); -} - -void -nm_udev_manager_query_devices (NMUdevManager *self) -{ - NMUdevManagerPrivate *priv = NM_UDEV_MANAGER_GET_PRIVATE (self); - GUdevEnumerator *enumerator; - GList *devices, *iter; - - g_return_if_fail (self != NULL); - g_return_if_fail (NM_IS_UDEV_MANAGER (self)); - - enumerator = g_udev_enumerator_new (priv->client); - g_udev_enumerator_add_match_subsystem (enumerator, "net"); - g_udev_enumerator_add_match_is_initialized (enumerator); - - devices = g_udev_enumerator_execute (enumerator); - for (iter = devices; iter; iter = g_list_next (iter)) { - net_add (self, G_UDEV_DEVICE (iter->data)); - g_object_unref (G_UDEV_DEVICE (iter->data)); - } - g_list_free (devices); - g_object_unref (enumerator); - - - enumerator = g_udev_enumerator_new (priv->client); - g_udev_enumerator_add_match_subsystem (enumerator, "atm"); - g_udev_enumerator_add_match_is_initialized (enumerator); - devices = g_udev_enumerator_execute (enumerator); - for (iter = devices; iter; iter = g_list_next (iter)) { - adsl_add (self, G_UDEV_DEVICE (iter->data)); - g_object_unref (G_UDEV_DEVICE (iter->data)); - } - g_list_free (devices); - g_object_unref (enumerator); -} - -static void -handle_uevent (GUdevClient *client, - const char *action, - GUdevDevice *device, - gpointer user_data) -{ - NMUdevManager *self = NM_UDEV_MANAGER (user_data); - const char *subsys; - - g_return_if_fail (action != NULL); - - /* A bit paranoid */ - subsys = g_udev_device_get_subsystem (device); - g_return_if_fail (subsys != NULL); - - nm_log_dbg (LOGD_HW, "UDEV event: action '%s' subsys '%s' device '%s'", - action, subsys, g_udev_device_get_name (device)); - - g_return_if_fail (!strcmp (subsys, "rfkill") || !strcmp (subsys, "net") || - !strcmp (subsys, "atm")); - - if (!strcmp (action, "add")) { - if (!strcmp (subsys, "rfkill")) - rfkill_add (self, device); - else if (!strcmp (subsys, "net")) - net_add (self, device); - else if (!strcmp (subsys, "atm")) - adsl_add (self, device); - } else if (!strcmp (action, "remove")) { - if (!strcmp (subsys, "rfkill")) - rfkill_remove (self, device); - else if (!strcmp (subsys, "net")) - net_remove (self, device); - else if (!strcmp (subsys, "atm")) - adsl_remove (self, device); - } - - recheck_killswitches (self); -} - -static void -nm_udev_manager_init (NMUdevManager *self) -{ - NMUdevManagerPrivate *priv = NM_UDEV_MANAGER_GET_PRIVATE (self); - const char *subsys[4] = { "rfkill", "net", "atm", NULL }; - GList *switches, *iter; - guint32 i; - - for (i = 0; i < RFKILL_TYPE_MAX; i++) - priv->rfkill_states[i] = RFKILL_UNBLOCKED; - - priv->client = g_udev_client_new (subsys); - g_signal_connect (priv->client, "uevent", G_CALLBACK (handle_uevent), self); - - switches = g_udev_client_query_by_subsystem (priv->client, "rfkill"); - for (iter = switches; iter; iter = g_list_next (iter)) { - add_one_killswitch (self, G_UDEV_DEVICE (iter->data)); - g_object_unref (G_UDEV_DEVICE (iter->data)); - } - g_list_free (switches); - - recheck_killswitches (self); -} - -static void -dispose (GObject *object) -{ - NMUdevManager *self = NM_UDEV_MANAGER (object); - NMUdevManagerPrivate *priv = NM_UDEV_MANAGER_GET_PRIVATE (self); - - if (priv->disposed) { - G_OBJECT_CLASS (nm_udev_manager_parent_class)->dispose (object); - return; - } - priv->disposed = TRUE; - - g_object_unref (priv->client); - - g_slist_foreach (priv->killswitches, (GFunc) killswitch_destroy, NULL); - g_slist_free (priv->killswitches); - - G_OBJECT_CLASS (nm_udev_manager_parent_class)->dispose (object); -} - -static void -nm_udev_manager_class_init (NMUdevManagerClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - g_type_class_add_private (klass, sizeof (NMUdevManagerPrivate)); - - /* virtual methods */ - object_class->dispose = dispose; - - /* Signals */ - signals[DEVICE_ADDED] = - g_signal_new ("device-added", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMUdevManagerClass, device_added), - NULL, NULL, - _nm_marshal_VOID__POINTER_POINTER_POINTER_POINTER_INT, - G_TYPE_NONE, 5, G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_INT); - - signals[DEVICE_REMOVED] = - g_signal_new ("device-removed", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMUdevManagerClass, device_removed), - NULL, NULL, - g_cclosure_marshal_VOID__POINTER, - G_TYPE_NONE, 1, G_TYPE_POINTER); - - signals[RFKILL_CHANGED] = - g_signal_new ("rfkill-changed", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMUdevManagerClass, rfkill_changed), - NULL, NULL, - _nm_marshal_VOID__UINT_UINT, - G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT); -} - diff --git a/src/nm-udev-manager.h b/src/nm-udev-manager.h deleted file mode 100644 index 2c982e6d..00000000 --- a/src/nm-udev-manager.h +++ /dev/null @@ -1,74 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2007 - 2008 Novell, Inc. - * Copyright (C) 2007 - 2012 Red Hat, Inc. - */ - -#ifndef NM_UDEV_MANAGER_H -#define NM_UDEV_MANAGER_H - -#include -#include - -#include - -#include "nm-rfkill.h" - -G_BEGIN_DECLS - -#define NM_TYPE_UDEV_MANAGER (nm_udev_manager_get_type ()) -#define NM_UDEV_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_UDEV_MANAGER, NMUdevManager)) -#define NM_UDEV_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_UDEV_MANAGER, NMUdevManagerClass)) -#define NM_IS_UDEV_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_UDEV_MANAGER)) -#define NM_IS_UDEV_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_UDEV_MANAGER)) -#define NM_UDEV_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_UDEV_MANAGER, NMUdevManagerClass)) - -typedef struct { - GObject parent; -} NMUdevManager; - -typedef GObject *(*NMDeviceCreatorFn) (NMUdevManager *manager, - GUdevDevice *device, - gboolean sleeping); - -typedef struct { - GObjectClass parent; - - /* Virtual functions */ - void (*device_added) (NMUdevManager *manager, - GUdevDevice *device, - const char *iface, - const char *sysfs_path, - const char *driver, - int ifindex); - - void (*device_removed) (NMUdevManager *manager, GUdevDevice *device); - - void (*rfkill_changed) (NMUdevManager *manager, RfKillType rtype, RfKillState state); -} NMUdevManagerClass; - -GType nm_udev_manager_get_type (void); - -NMUdevManager *nm_udev_manager_new (void); - -void nm_udev_manager_query_devices (NMUdevManager *manager); - -RfKillState nm_udev_manager_get_rfkill_state (NMUdevManager *manager, RfKillType rtype); - -#endif /* NM_UDEV_MANAGER_H */ - diff --git a/src/nm-vpn-connection-glue.h b/src/nm-vpn-connection-glue.h new file mode 100644 index 00000000..74b8c7dc --- /dev/null +++ b/src/nm-vpn-connection-glue.h @@ -0,0 +1,73 @@ +/* Generated by dbus-binding-tool; do not edit! */ + + +#ifndef __dbus_glib_marshal_nm_vpn_connection_MARSHAL_H__ +#define __dbus_glib_marshal_nm_vpn_connection_MARSHAL_H__ + +#include + +G_BEGIN_DECLS + +#ifdef G_ENABLE_DEBUG +#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v) +#define g_marshal_value_peek_char(v) g_value_get_schar (v) +#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v) +#define g_marshal_value_peek_int(v) g_value_get_int (v) +#define g_marshal_value_peek_uint(v) g_value_get_uint (v) +#define g_marshal_value_peek_long(v) g_value_get_long (v) +#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v) +#define g_marshal_value_peek_int64(v) g_value_get_int64 (v) +#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v) +#define g_marshal_value_peek_enum(v) g_value_get_enum (v) +#define g_marshal_value_peek_flags(v) g_value_get_flags (v) +#define g_marshal_value_peek_float(v) g_value_get_float (v) +#define g_marshal_value_peek_double(v) g_value_get_double (v) +#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v) +#define g_marshal_value_peek_param(v) g_value_get_param (v) +#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v) +#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v) +#define g_marshal_value_peek_object(v) g_value_get_object (v) +#define g_marshal_value_peek_variant(v) g_value_get_variant (v) +#else /* !G_ENABLE_DEBUG */ +/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API. + * Do not access GValues directly in your code. Instead, use the + * g_value_get_*() functions + */ +#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int +#define g_marshal_value_peek_char(v) (v)->data[0].v_int +#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint +#define g_marshal_value_peek_int(v) (v)->data[0].v_int +#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint +#define g_marshal_value_peek_long(v) (v)->data[0].v_long +#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 +#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 +#define g_marshal_value_peek_enum(v) (v)->data[0].v_long +#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_float(v) (v)->data[0].v_float +#define g_marshal_value_peek_double(v) (v)->data[0].v_double +#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer +#endif /* !G_ENABLE_DEBUG */ + + +G_END_DECLS + +#endif /* __dbus_glib_marshal_nm_vpn_connection_MARSHAL_H__ */ + +#include +static const DBusGMethodInfo dbus_glib_nm_vpn_connection_methods[] = { +}; + +const DBusGObjectInfo dbus_glib_nm_vpn_connection_object_info = { 1, + dbus_glib_nm_vpn_connection_methods, + 0, +"\0", +"org.freedesktop.NetworkManager.VPN.Connection\0PropertiesChanged\0org.freedesktop.NetworkManager.VPN.Connection\0VpnStateChanged\0\0", +"org.freedesktop.NetworkManager.VPN.Connection\0VpnState\0vpn_state\0read\0org.freedesktop.NetworkManager.VPN.Connection\0Banner\0banner\0read\0\0" +}; + diff --git a/src/nm-wifi-ap-utils.c b/src/nm-wifi-ap-utils.c deleted file mode 100644 index 29aa52a4..00000000 --- a/src/nm-wifi-ap-utils.c +++ /dev/null @@ -1,728 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * (C) Copyright 2011 Red Hat, Inc. - */ - -#include -#include -#include - -#include "nm-wifi-ap-utils.h" - -static gboolean -verify_no_wep (NMSettingWirelessSecurity *s_wsec, const char *tag, GError **error) -{ - if ( nm_setting_wireless_security_get_wep_key (s_wsec, 0) - || nm_setting_wireless_security_get_wep_key (s_wsec, 1) - || nm_setting_wireless_security_get_wep_key (s_wsec, 2) - || nm_setting_wireless_security_get_wep_key (s_wsec, 3) - || nm_setting_wireless_security_get_wep_tx_keyidx (s_wsec) - || nm_setting_wireless_security_get_wep_key_type (s_wsec)) { - /* Dynamic WEP cannot have any WEP keys set */ - g_set_error (error, - NM_SETTING_WIRELESS_SECURITY_ERROR, - NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, - "%s is incompatible with static WEP keys", tag); - return FALSE; - } - - return TRUE; -} - -static gboolean -verify_leap (NMSettingWirelessSecurity *s_wsec, - NMSetting8021x *s_8021x, - gboolean adhoc, - GError **error) -{ - const char *key_mgmt, *auth_alg, *leap_username; - - key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wsec); - auth_alg = nm_setting_wireless_security_get_auth_alg (s_wsec); - leap_username = nm_setting_wireless_security_get_leap_username (s_wsec); - - /* One (or both) of two things indicates we want LEAP: - * 1) auth_alg == 'leap' - * 2) valid leap_username - * - * LEAP always requires a LEAP username. - */ - - if (auth_alg) { - if (!strcmp (auth_alg, "leap")) { - /* LEAP authentication requires at least a LEAP username */ - if (!leap_username) { - g_set_error_literal (error, - NM_SETTING_WIRELESS_SECURITY_ERROR, - NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_USERNAME, - "LEAP requires a LEAP username"); - return FALSE; - } - } else if (leap_username) { - /* Leap username requires 'leap' auth */ - g_set_error_literal (error, - NM_SETTING_WIRELESS_SECURITY_ERROR, - NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, - "LEAP requires 'leap' authentication"); - return FALSE; - } - } - - if (leap_username) { - if (key_mgmt && strcmp (key_mgmt, "ieee8021x")) { - /* LEAP requires ieee8021x key management */ - g_set_error_literal (error, - NM_SETTING_WIRELESS_SECURITY_ERROR, - NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_802_1X, - "LEAP requires IEEE 802.1x key management"); - return FALSE; - } - } - - /* At this point if auth_alg is set it must be 'leap', and if key_mgmt - * is set it must be 'ieee8021x'. - */ - if (leap_username) { - if (auth_alg) - g_assert (strcmp (auth_alg, "leap") == 0); - if (key_mgmt) - g_assert (strcmp (key_mgmt, "ieee8021x") == 0); - - if (adhoc) { - g_set_error_literal (error, - NM_SETTING_WIRELESS_SECURITY_ERROR, - NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, - "LEAP incompatible with Ad-Hoc mode"); - return FALSE; - } - - if (!verify_no_wep (s_wsec, "LEAP", error)) - return FALSE; - - if (s_8021x) { - g_set_error_literal (error, - NM_SETTING_WIRELESS_SECURITY_ERROR, - NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_USERNAME, - "LEAP incompatible with 802.1x setting"); - return FALSE; - } - } - - return TRUE; -} - -static gboolean -verify_no_wpa (NMSettingWirelessSecurity *s_wsec, - const char *tag, - GError **error) -{ - const char *key_mgmt; - int n, i; - - key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wsec); - if (key_mgmt && !strncmp (key_mgmt, "wpa", 3)) { - g_set_error (error, - NM_SETTING_WIRELESS_SECURITY_ERROR, - NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, - "%s incompatible with any WPA key management", tag); - return FALSE; - } - - if (nm_setting_wireless_security_get_num_protos (s_wsec)) { - g_set_error (error, - NM_SETTING_WIRELESS_SECURITY_ERROR, - NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, - "%s incompatible with any 'proto' setting", tag); - return FALSE; - } - - n = nm_setting_wireless_security_get_num_pairwise (s_wsec); - for (i = 0; i < n; i++) { - const char *pw; - - pw = nm_setting_wireless_security_get_pairwise (s_wsec, i); - if (strcmp (pw, "wep40") && strcmp (pw, "wep104")) { - g_set_error (error, - NM_SETTING_WIRELESS_SECURITY_ERROR, - NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, - "%s is incompatible with WPA pairwise ciphers", tag); - return FALSE; - } - } - - n = nm_setting_wireless_security_get_num_groups (s_wsec); - for (i = 0; i < n; i++) { - const char *gr; - - gr = nm_setting_wireless_security_get_group (s_wsec, i); - if (strcmp (gr, "wep40") && strcmp (gr, "wep104")) { - g_set_error (error, - NM_SETTING_WIRELESS_SECURITY_ERROR, - NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, - "%s is incompatible with WPA group ciphers", tag); - return FALSE; - } - } - - if (nm_setting_wireless_security_get_psk (s_wsec)) { - g_set_error (error, - NM_SETTING_WIRELESS_SECURITY_ERROR, - NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, - "%s is incompatible with a WPA Pre-Shared Key", tag); - return FALSE; - } - - return TRUE; -} - -static gboolean -verify_dynamic_wep (NMSettingWirelessSecurity *s_wsec, - NMSetting8021x *s_8021x, - gboolean adhoc, - GError **error) -{ - const char *key_mgmt, *auth_alg, *leap_username; - - key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wsec); - auth_alg = nm_setting_wireless_security_get_auth_alg (s_wsec); - leap_username = nm_setting_wireless_security_get_leap_username (s_wsec); - - g_return_val_if_fail (leap_username == NULL, TRUE); - - if (key_mgmt) { - if (!strcmp (key_mgmt, "ieee8021x")) { - if (!s_8021x) { - /* 802.1x key management requires an 802.1x setting */ - g_set_error_literal (error, - NM_SETTING_WIRELESS_SECURITY_ERROR, - NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, - "Dynamic WEP requires an 802.1x setting"); - return FALSE; - } - - if (auth_alg && strcmp (auth_alg, "open")) { - /* 802.1x key management must use "open" authentication */ - g_set_error_literal (error, - NM_SETTING_WIRELESS_SECURITY_ERROR, - NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, - "Dynamic WEP requires 'open' authentication"); - return FALSE; - } - - /* Dynamic WEP incompatible with anything static WEP related */ - if (!verify_no_wep (s_wsec, "Dynamic WEP", error)) - return FALSE; - } else if (!strcmp (key_mgmt, "none")) { - if (s_8021x) { - /* 802.1x setting requires 802.1x key management */ - g_set_error_literal (error, - NM_SETTING_WIRELESS_SECURITY_ERROR, - NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, - "Dynamic WEP requires 'ieee8021x' key management"); - return FALSE; - } - } - } else if (s_8021x) { - /* 802.1x setting incompatible with anything but 'open' auth */ - if (auth_alg && strcmp (auth_alg, "open")) { - /* 802.1x key management must use "open" authentication */ - g_set_error_literal (error, - NM_SETTING_WIRELESS_SECURITY_ERROR, - NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, - "Dynamic WEP requires 'open' authentication"); - return FALSE; - } - - /* Dynamic WEP incompatible with anything static WEP related */ - if (!verify_no_wep (s_wsec, "Dynamic WEP", error)) - return FALSE; - } - - return TRUE; -} - -static gboolean -verify_wpa_psk (NMSettingWirelessSecurity *s_wsec, - NMSetting8021x *s_8021x, - gboolean adhoc, - guint32 wpa_flags, - guint32 rsn_flags, - GError **error) -{ - const char *key_mgmt, *auth_alg, *tmp; - int n; - - key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wsec); - auth_alg = nm_setting_wireless_security_get_auth_alg (s_wsec); - - if (key_mgmt) { - if (!strcmp (key_mgmt, "wpa-psk") || !strcmp (key_mgmt, "wpa-none")) { - if (s_8021x) { - g_set_error_literal (error, - NM_SETTING_WIRELESS_SECURITY_ERROR, - NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, - "WPA-PSK incompatible with 802.1x"); - return FALSE; - } - - if (auth_alg && strcmp (auth_alg, "open")) { - /* WPA must use "open" authentication */ - g_set_error_literal (error, - NM_SETTING_WIRELESS_SECURITY_ERROR, - NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, - "WPA-PSK requires 'open' authentication"); - return FALSE; - } - } - - if (!strcmp (key_mgmt, "wpa-none")) { - if (!adhoc) { - g_set_error_literal (error, - NM_SETTING_WIRELESS_SECURITY_ERROR, - NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, - "WPA Ad-Hoc requires an Ad-Hoc mode AP"); - return FALSE; - } - - /* Ad-Hoc WPA requires 'wpa' proto, 'none' pairwise, and 'tkip' group */ - n = nm_setting_wireless_security_get_num_protos (s_wsec); - tmp = (n > 0) ? nm_setting_wireless_security_get_proto (s_wsec, 0) : NULL; - if (n > 1 || strcmp (tmp, "wpa")) { - g_set_error_literal (error, - NM_SETTING_WIRELESS_SECURITY_ERROR, - NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, - "WPA Ad-Hoc requires 'wpa' proto"); - return FALSE; - } - - n = nm_setting_wireless_security_get_num_pairwise (s_wsec); - tmp = (n > 0) ? nm_setting_wireless_security_get_pairwise (s_wsec, 0) : NULL; - if (n > 1 || strcmp (tmp, "none")) { - g_set_error_literal (error, - NM_SETTING_WIRELESS_SECURITY_ERROR, - NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, - "WPA Ad-Hoc requires 'none' pairwise cipher"); - return FALSE; - } - - n = nm_setting_wireless_security_get_num_groups (s_wsec); - tmp = (n > 0) ? nm_setting_wireless_security_get_group (s_wsec, 0) : NULL; - if (n > 1 || strcmp (tmp, "tkip")) { - g_set_error_literal (error, - NM_SETTING_WIRELESS_SECURITY_ERROR, - NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, - "WPA Ad-Hoc requires 'tkip' group cipher"); - return FALSE; - } - } - - if (!strcmp (key_mgmt, "wpa-psk")) { - /* Make sure the AP's capabilities support WPA-PSK */ - if ( !(wpa_flags & NM_802_11_AP_SEC_KEY_MGMT_PSK) - && !(rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_PSK)) { - g_set_error_literal (error, - NM_SETTING_WIRELESS_SECURITY_ERROR, - NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, - "AP does not support PSK but setting requires it"); - return FALSE; - } - } - } - - return TRUE; -} - -static gboolean -verify_wpa_eap (NMSettingWirelessSecurity *s_wsec, - NMSetting8021x *s_8021x, - guint32 wpa_flags, - guint32 rsn_flags, - GError **error) -{ - const char *key_mgmt, *auth_alg; - gboolean is_wpa_eap = FALSE; - - key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wsec); - auth_alg = nm_setting_wireless_security_get_auth_alg (s_wsec); - - if (key_mgmt) { - if (!strcmp (key_mgmt, "wpa-eap")) { - if (!s_8021x) { - g_set_error_literal (error, - NM_SETTING_WIRELESS_SECURITY_ERROR, - NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, - "WPA-EAP requires an 802.1x setting"); - return FALSE; - } - - if (auth_alg && strcmp (auth_alg, "open")) { - /* WPA must use "open" authentication */ - g_set_error_literal (error, - NM_SETTING_WIRELESS_SECURITY_ERROR, - NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, - "WPA-EAP requires 'open' authentication"); - return FALSE; - } - - is_wpa_eap = TRUE; - } else if (s_8021x) { - g_set_error_literal (error, - NM_SETTING_WIRELESS_SECURITY_ERROR, - NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, - "Setting requires 802.1x but does not use 'wpa-eap' key management"); - return FALSE; - } - } - - if (is_wpa_eap || s_8021x) { - /* Make sure the AP's capabilities support WPA-EAP */ - if ( !(wpa_flags & NM_802_11_AP_SEC_KEY_MGMT_802_1X) - && !(rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) { - g_set_error_literal (error, - NM_SETTING_WIRELESS_SECURITY_ERROR, - NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, - "AP does not support 802.1x but setting requires it"); - return FALSE; - } - } - - return TRUE; -} - -static gboolean -verify_adhoc (NMSettingWirelessSecurity *s_wsec, - NMSetting8021x *s_8021x, - gboolean adhoc, - GError **error) -{ - const char *key_mgmt = NULL, *leap_username = NULL, *auth_alg = NULL; - - if (s_wsec) { - key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wsec); - auth_alg = nm_setting_wireless_security_get_auth_alg (s_wsec); - leap_username = nm_setting_wireless_security_get_leap_username (s_wsec); - } - - if (adhoc) { - if (key_mgmt && strcmp (key_mgmt, "wpa-none") && strcmp (key_mgmt, "none")) { - g_set_error_literal (error, - NM_SETTING_WIRELESS_SECURITY_ERROR, - NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, - "AP mode is Ad-Hoc but setting requires Infrastructure security"); - return FALSE; - } - - if (s_8021x) { - g_set_error_literal (error, - NM_SETTING_WIRELESS_SECURITY_ERROR, - NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, - "Ad-Hoc mode incompatible with 802.1x security"); - return FALSE; - } - - if (leap_username) { - g_set_error_literal (error, - NM_SETTING_WIRELESS_SECURITY_ERROR, - NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, - "Ad-Hoc mode incompatible with LEAP security"); - return FALSE; - } - - if (auth_alg && strcmp (auth_alg, "open")) { - g_set_error_literal (error, - NM_SETTING_WIRELESS_SECURITY_ERROR, - NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, - "Ad-Hoc mode requires 'open' authentication"); - return FALSE; - } - } else { - if (key_mgmt && !strcmp (key_mgmt, "wpa-none")) { - g_set_error_literal (error, - NM_SETTING_WIRELESS_SECURITY_ERROR, - NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, - "AP mode is Infrastructure but setting requires Ad-Hoc security"); - return FALSE; - } - } - - return TRUE; -} - -gboolean -nm_ap_utils_complete_connection (const GByteArray *ap_ssid, - const guint8 ap_bssid[ETH_ALEN], - NM80211Mode ap_mode, - guint32 ap_flags, - guint32 ap_wpa_flags, - guint32 ap_rsn_flags, - NMConnection *connection, - gboolean lock_bssid, - GError **error) -{ - NMSettingWireless *s_wifi; - NMSettingWirelessSecurity *s_wsec; - NMSetting8021x *s_8021x; - const GByteArray *ssid; - const char *mode, *key_mgmt, *auth_alg, *leap_username; - gboolean adhoc = FALSE; - - s_wifi = nm_connection_get_setting_wireless (connection); - g_assert (s_wifi); - s_wsec = nm_connection_get_setting_wireless_security (connection); - s_8021x = nm_connection_get_setting_802_1x (connection); - - /* Fill in missing SSID */ - ssid = nm_setting_wireless_get_ssid (s_wifi); - if (!ssid) - g_object_set (G_OBJECT (s_wifi), NM_SETTING_WIRELESS_SSID, ap_ssid, NULL); - else if ( ssid->len != ap_ssid->len - || memcmp (ssid->data, ap_ssid->data, ssid->len)) { - g_set_error_literal (error, - NM_SETTING_WIRELESS_ERROR, - NM_SETTING_WIRELESS_ERROR_INVALID_PROPERTY, - "Setting SSID did not match AP SSID"); - return FALSE; - } - - if (lock_bssid && !nm_setting_wireless_get_bssid (s_wifi)) { - GByteArray *bssid; - - bssid = g_byte_array_sized_new (ETH_ALEN); - g_byte_array_append (bssid, ap_bssid, ETH_ALEN); - g_object_set (G_OBJECT (s_wifi), NM_SETTING_WIRELESS_BSSID, bssid, NULL); - g_byte_array_free (bssid, TRUE); - } - - /* And mode */ - mode = nm_setting_wireless_get_mode (s_wifi); - if (mode) { - gboolean valid = FALSE; - - /* Make sure the supplied mode matches the AP's */ - if ( !strcmp (mode, NM_SETTING_WIRELESS_MODE_INFRA) - || !strcmp (mode, NM_SETTING_WIRELESS_MODE_AP)) { - if (ap_mode == NM_802_11_MODE_INFRA) - valid = TRUE; - } else if (!strcmp (mode, NM_SETTING_WIRELESS_MODE_ADHOC)) { - if (ap_mode == NM_802_11_MODE_ADHOC) - valid = TRUE; - adhoc = TRUE; - } - - if (valid == FALSE) { - g_set_error (error, - NM_SETTING_WIRELESS_ERROR, - NM_SETTING_WIRELESS_ERROR_INVALID_PROPERTY, - NM_SETTING_WIRELESS_MODE); - return FALSE; - } - } else { - mode = NM_SETTING_WIRELESS_MODE_INFRA; - if (ap_mode == NM_802_11_MODE_ADHOC) { - mode = NM_SETTING_WIRELESS_MODE_ADHOC; - adhoc = TRUE; - } - g_object_set (G_OBJECT (s_wifi), NM_SETTING_WIRELESS_MODE, mode, NULL); - } - - /* Security */ - - /* Open */ - if ( !(ap_flags & NM_802_11_AP_FLAGS_PRIVACY) - && (ap_wpa_flags == NM_802_11_AP_SEC_NONE) - && (ap_rsn_flags == NM_802_11_AP_SEC_NONE)) { - /* Make sure the connection doesn't specify security */ - if (nm_setting_wireless_get_security (s_wifi) || s_wsec || s_8021x) { - g_set_error_literal (error, - NM_SETTING_WIRELESS_SECURITY_ERROR, - NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, - "AP is unencrypted but setting specifies security"); - return FALSE; - } - return TRUE; - } - - /* Everything else requires security */ - g_object_set (G_OBJECT (s_wifi), - NM_SETTING_WIRELESS_SEC, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, - NULL); - if (!s_wsec) { - s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new (); - nm_connection_add_setting (connection, NM_SETTING (s_wsec)); - } - - key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wsec); - auth_alg = nm_setting_wireless_security_get_auth_alg (s_wsec); - leap_username = nm_setting_wireless_security_get_leap_username (s_wsec); - - /* Ad-Hoc checks */ - if (!verify_adhoc (s_wsec, s_8021x, adhoc, error)) - return FALSE; - - /* Static WEP, Dynamic WEP, or LEAP */ - if ( (ap_flags & NM_802_11_AP_FLAGS_PRIVACY) - && (ap_wpa_flags == NM_802_11_AP_SEC_NONE) - && (ap_rsn_flags == NM_802_11_AP_SEC_NONE)) { - const char *tag = "WEP"; - gboolean is_dynamic_wep = FALSE; - - if (!verify_leap (s_wsec, s_8021x, adhoc, error)) - return FALSE; - - if (leap_username) { - tag = "LEAP"; - } else { - /* Static or Dynamic WEP */ - if (!verify_dynamic_wep (s_wsec, s_8021x, adhoc, error)) - return FALSE; - - if (s_8021x || (key_mgmt && !strcmp (key_mgmt, "ieee8021x"))) { - is_dynamic_wep = TRUE; - tag = "Dynamic WEP"; - } - } - - /* Nothing WPA-related can be set */ - if (!verify_no_wpa (s_wsec, tag, error)) - return FALSE; - - if (leap_username) { - /* LEAP */ - g_object_set (s_wsec, - NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x", - NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "leap", - NULL); - } else if (is_dynamic_wep) { - /* Dynamic WEP */ - g_object_set (s_wsec, - NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x", - NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "open", - NULL); - nm_setting_wireless_security_add_pairwise (s_wsec, "wep40"); - nm_setting_wireless_security_add_pairwise (s_wsec, "wep104"); - nm_setting_wireless_security_add_group (s_wsec, "wep40"); - nm_setting_wireless_security_add_group (s_wsec, "wep104"); - - if (s_8021x) { - /* Dynamic WEP requires a valid 802.1x setting since we can't - * autocomplete 802.1x. - */ - if (!nm_setting_verify (NM_SETTING (s_8021x), NULL, error)) - return FALSE; - } - } else { - /* Static WEP */ - g_object_set (s_wsec, - NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "none", - NULL); - } - - return TRUE; - } - - /* WPA/RSN */ - g_assert (ap_wpa_flags || ap_rsn_flags); - - /* Ensure key management is valid for WPA */ - if ((key_mgmt && !strcmp (key_mgmt, "ieee8021x")) || leap_username) { - g_set_error_literal (error, - NM_SETTING_WIRELESS_SECURITY_ERROR, - NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, - "WPA incompatible with non-EAP (original) LEAP or Dynamic WEP"); - return FALSE; - } - - /* 'shared' auth incompatible with any type of WPA */ - if (auth_alg && strcmp (auth_alg, "open")) { - g_set_error_literal (error, - NM_SETTING_WIRELESS_SECURITY_ERROR, - NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, - "WPA incompatible with Shared Key authentication"); - return FALSE; - } - - if (!verify_no_wep (s_wsec, "WPA", error)) - return FALSE; - - if (!verify_wpa_psk (s_wsec, s_8021x, adhoc, ap_wpa_flags, ap_rsn_flags, error)) - return FALSE; - - if (!adhoc && !verify_wpa_eap (s_wsec, s_8021x, ap_wpa_flags, ap_rsn_flags, error)) - return FALSE; - - if (adhoc) { - g_object_set (s_wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-none", NULL); - /* Ad-Hoc does not support RSN/WPA2 */ - nm_setting_wireless_security_add_proto (s_wsec, "wpa"); - nm_setting_wireless_security_add_pairwise (s_wsec, "none"); - nm_setting_wireless_security_add_group (s_wsec, "tkip"); - } else if (s_8021x) { - g_object_set (s_wsec, - NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-eap", - NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "open", - NULL); - /* Leave proto/pairwise/group as client set them; if they are unset the - * supplicant will figure out the best combination at connect time. - */ - - /* 802.1x also requires the client to completely fill in the 8021x - * setting. Since there's so much configuration required for it, there's - * no way it can be automatically completed. - */ - } else if ( (key_mgmt && !strcmp (key_mgmt, "wpa-psk")) - || (ap_wpa_flags & NM_802_11_AP_SEC_KEY_MGMT_PSK) - || (ap_rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_PSK)) { - g_object_set (s_wsec, - NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-psk", - NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "open", - NULL); - /* Leave proto/pairwise/group as client set them; if they are unset the - * supplicant will figure out the best combination at connect time. - */ - } else { - g_set_error_literal (error, - NM_SETTING_WIRELESS_SECURITY_ERROR, - NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, - "Failed to determine AP security information"); - return FALSE; - } - - return TRUE; -} - -guint32 -nm_ap_utils_level_to_quality (gint val) -{ - if (val < 0) { - /* Assume dBm already; rough conversion: best = -40, worst = -100 */ - val = abs (CLAMP (val, -100, -40) + 40); /* normalize to 0 */ - val = 100 - (int) ((100.0 * (double) val) / 60.0); - } else if (val > 110 && val < 256) { - /* assume old-style WEXT 8-bit unsigned signal level */ - val -= 256; /* subtract 256 to convert to dBm */ - val = abs (CLAMP (val, -100, -40) + 40); /* normalize to 0 */ - val = 100 - (int) ((100.0 * (double) val) / 60.0); - } else { - /* Assume signal is a "quality" percentage */ - val = CLAMP (val, 0, 100); - } - g_assert (val >= 0); - - return (guint32) val; -} - diff --git a/src/nm-wifi-ap-utils.h b/src/nm-wifi-ap-utils.h deleted file mode 100644 index 992b839d..00000000 --- a/src/nm-wifi-ap-utils.h +++ /dev/null @@ -1,45 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * (C) Copyright 2011 Red Hat, Inc. - */ - -#ifndef NM_WIFI_AP_UTILS_H -#define NM_WIFI_AP_UTILS_H - -#include - -#include -#include -#include -#include -#include - -gboolean nm_ap_utils_complete_connection (const GByteArray *ssid, - const guint8 bssid[ETH_ALEN], - NM80211Mode mode, - guint32 flags, - guint32 wpa_flags, - guint32 rsn_flags, - NMConnection *connection, - gboolean lock_bssid, - GError **error); - -guint32 nm_ap_utils_level_to_quality (gint val); - -#endif /* NM_WIFI_AP_UTILS_H */ - diff --git a/src/nm-wifi-ap.c b/src/nm-wifi-ap.c deleted file mode 100644 index e6db6920..00000000 --- a/src/nm-wifi-ap.c +++ /dev/null @@ -1,1319 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2004 - 2011 Red Hat, Inc. - * Copyright (C) 2006 - 2008 Novell, Inc. - */ - -#include -#include -#include - -#include "nm-wifi-ap.h" -#include "nm-wifi-ap-utils.h" -#include "NetworkManagerUtils.h" -#include "nm-utils.h" -#include "nm-logging.h" -#include "nm-dbus-manager.h" - -#include "nm-properties-changed-signal.h" -#include "nm-setting-wireless.h" -#include "nm-glib-compat.h" - -#include "nm-access-point-glue.h" - -/* - * Encapsulates Access Point information - */ -typedef struct -{ - char *dbus_path; - char *supplicant_path; /* D-Bus object path of this AP from wpa_supplicant */ - - /* Scanned or cached values */ - GByteArray * ssid; - struct ether_addr address; - NM80211Mode mode; - gint8 strength; - guint32 freq; /* Frequency in MHz; ie 2412 (== 2.412 GHz) */ - guint32 max_bitrate;/* Maximum bitrate of the AP in Kbit/s (ie 54000 Kb/s == 54Mbit/s) */ - - NM80211ApFlags flags; /* General flags */ - NM80211ApSecurityFlags wpa_flags; /* WPA-related flags */ - NM80211ApSecurityFlags rsn_flags; /* RSN (WPA2) -related flags */ - - /* Non-scanned attributes */ - gboolean fake; /* Whether or not the AP is from a scan */ - gboolean hotspot; /* Whether the AP is a local device's hotspot network */ - gboolean broadcast; /* Whether or not the AP is broadcasting (hidden) */ - glong last_seen; /* Last time the AP was seen in a scan in seconds */ -} NMAccessPointPrivate; - -#define NM_AP_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_AP, NMAccessPointPrivate)) - -G_DEFINE_TYPE (NMAccessPoint, nm_ap, G_TYPE_OBJECT) - -enum { - PROPERTIES_CHANGED, - - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -enum { - PROP_0, - PROP_FLAGS, - PROP_WPA_FLAGS, - PROP_RSN_FLAGS, - PROP_SSID, - PROP_FREQUENCY, - PROP_HW_ADDRESS, - PROP_MODE, - PROP_MAX_BITRATE, - PROP_STRENGTH, - LAST_PROP -}; - -static void -nm_ap_init (NMAccessPoint *ap) -{ - NMAccessPointPrivate *priv = NM_AP_GET_PRIVATE (ap); - - priv->dbus_path = NULL; - priv->mode = NM_802_11_MODE_INFRA; - priv->flags = NM_802_11_AP_FLAGS_NONE; - priv->wpa_flags = NM_802_11_AP_SEC_NONE; - priv->rsn_flags = NM_802_11_AP_SEC_NONE; - priv->broadcast = TRUE; -} - -static void -finalize (GObject *object) -{ - NMAccessPointPrivate *priv = NM_AP_GET_PRIVATE (object); - - g_free (priv->dbus_path); - g_free (priv->supplicant_path); - if (priv->ssid) - g_byte_array_free (priv->ssid, TRUE); - - G_OBJECT_CLASS (nm_ap_parent_class)->finalize (object); -} - -static void -set_property (GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec) -{ - NMAccessPoint *ap = NM_AP (object); - - switch (prop_id) { - case PROP_FLAGS: - nm_ap_set_flags (ap, g_value_get_uint (value)); - break; - case PROP_WPA_FLAGS: - nm_ap_set_wpa_flags (ap, g_value_get_uint (value)); - break; - case PROP_RSN_FLAGS: - nm_ap_set_rsn_flags (ap, g_value_get_uint (value)); - break; - case PROP_SSID: - nm_ap_set_ssid (ap, (GByteArray *) g_value_get_boxed (value)); - break; - case PROP_FREQUENCY: - nm_ap_set_freq (ap, g_value_get_uint (value)); - break; - case PROP_MODE: - nm_ap_set_mode (ap, g_value_get_uint (value)); - break; - case PROP_MAX_BITRATE: - nm_ap_set_max_bitrate (ap, g_value_get_uint (value)); - break; - case PROP_STRENGTH: - nm_ap_set_strength (ap, g_value_get_schar (value)); - break; - case PROP_HW_ADDRESS: - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) -{ - NMAccessPointPrivate *priv = NM_AP_GET_PRIVATE (object); - GArray * ssid; - int len; - int i; - - switch (prop_id) { - case PROP_FLAGS: - g_value_set_uint (value, priv->flags); - break; - case PROP_WPA_FLAGS: - g_value_set_uint (value, priv->wpa_flags); - break; - case PROP_RSN_FLAGS: - g_value_set_uint (value, priv->rsn_flags); - break; - case PROP_SSID: - len = priv->ssid ? priv->ssid->len : 0; - ssid = g_array_sized_new (FALSE, TRUE, sizeof (unsigned char), len); - for (i = 0; i < len; i++) - g_array_append_val (ssid, priv->ssid->data[i]); - g_value_set_boxed (value, ssid); - g_array_free (ssid, TRUE); - break; - case PROP_FREQUENCY: - g_value_set_uint (value, priv->freq); - break; - case PROP_HW_ADDRESS: - g_value_take_string (value, nm_utils_hwaddr_ntoa (&priv->address, ARPHRD_ETHER)); - break; - case PROP_MODE: - g_value_set_uint (value, priv->mode); - break; - case PROP_MAX_BITRATE: - g_value_set_uint (value, priv->max_bitrate); - break; - case PROP_STRENGTH: - g_value_set_schar (value, priv->strength); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -nm_ap_class_init (NMAccessPointClass *ap_class) -{ - GObjectClass *object_class = G_OBJECT_CLASS (ap_class); - const NM80211ApSecurityFlags all_sec_flags = NM_802_11_AP_SEC_NONE - | NM_802_11_AP_SEC_PAIR_WEP40 - | NM_802_11_AP_SEC_PAIR_WEP104 - | NM_802_11_AP_SEC_PAIR_TKIP - | NM_802_11_AP_SEC_PAIR_CCMP - | NM_802_11_AP_SEC_GROUP_WEP40 - | NM_802_11_AP_SEC_GROUP_WEP104 - | NM_802_11_AP_SEC_GROUP_TKIP - | NM_802_11_AP_SEC_GROUP_CCMP - | NM_802_11_AP_SEC_KEY_MGMT_PSK - | NM_802_11_AP_SEC_KEY_MGMT_802_1X; - - g_type_class_add_private (ap_class, sizeof (NMAccessPointPrivate)); - - /* virtual methods */ - object_class->set_property = set_property; - object_class->get_property = get_property; - object_class->finalize = finalize; - - /* properties */ - g_object_class_install_property - (object_class, PROP_FLAGS, - g_param_spec_uint (NM_AP_FLAGS, - "Flags", - "Flags", - NM_802_11_AP_FLAGS_NONE, - NM_802_11_AP_FLAGS_PRIVACY, - NM_802_11_AP_FLAGS_NONE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - g_object_class_install_property - (object_class, PROP_WPA_FLAGS, - g_param_spec_uint (NM_AP_WPA_FLAGS, - "WPA Flags", - "WPA Flags", - NM_802_11_AP_SEC_NONE, - all_sec_flags, - NM_802_11_AP_SEC_NONE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - g_object_class_install_property - (object_class, PROP_RSN_FLAGS, - g_param_spec_uint (NM_AP_RSN_FLAGS, - "RSN Flags", - "RSN Flags", - NM_802_11_AP_SEC_NONE, - all_sec_flags, - NM_802_11_AP_SEC_NONE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - g_object_class_install_property - (object_class, PROP_SSID, - g_param_spec_boxed (NM_AP_SSID, - "SSID", - "SSID", - DBUS_TYPE_G_UCHAR_ARRAY, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - g_object_class_install_property - (object_class, PROP_FREQUENCY, - g_param_spec_uint (NM_AP_FREQUENCY, - "Frequency", - "Frequency", - 0, 10000, 0, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - g_object_class_install_property - (object_class, PROP_HW_ADDRESS, - g_param_spec_string (NM_AP_HW_ADDRESS, - "MAC Address", - "Hardware MAC address", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - g_object_class_install_property - (object_class, PROP_MODE, - g_param_spec_uint (NM_AP_MODE, - "Mode", - "Mode", - NM_802_11_MODE_ADHOC, NM_802_11_MODE_INFRA, NM_802_11_MODE_INFRA, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - g_object_class_install_property - (object_class, PROP_MAX_BITRATE, - g_param_spec_uint (NM_AP_MAX_BITRATE, - "Max Bitrate", - "Max Bitrate", - 0, G_MAXUINT16, 0, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - g_object_class_install_property - (object_class, PROP_STRENGTH, - g_param_spec_char (NM_AP_STRENGTH, - "Strength", - "Strength", - G_MININT8, G_MAXINT8, 0, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - /* Signals */ - signals[PROPERTIES_CHANGED] = - nm_properties_changed_signal_new (object_class, - G_STRUCT_OFFSET (NMAccessPointClass, properties_changed)); - - dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (ap_class), - &dbus_glib_nm_access_point_object_info); -} - -void -nm_ap_export_to_dbus (NMAccessPoint *ap) -{ - NMAccessPointPrivate *priv; - NMDBusManager *mgr; - DBusGConnection *g_connection; - static guint32 counter = 0; - - g_return_if_fail (NM_IS_AP (ap)); - - priv = NM_AP_GET_PRIVATE (ap); - - if (priv->dbus_path) { - nm_log_err (LOGD_CORE, "Tried to export AP %s twice.", priv->dbus_path); - return; - } - - mgr = nm_dbus_manager_get (); - g_assert (mgr); - - g_connection = nm_dbus_manager_get_connection (mgr); - g_assert (g_connection); - - priv->dbus_path = g_strdup_printf (NM_DBUS_PATH_ACCESS_POINT "/%d", counter++); - dbus_g_connection_register_g_object (g_connection, priv->dbus_path, G_OBJECT (ap)); - - g_object_unref (mgr); -} - -/* - * nm_ap_new - * - * Create a new, blank user access point info structure - * - */ -static NMAccessPoint * -nm_ap_new (void) -{ - return (NMAccessPoint *) g_object_new (NM_TYPE_AP, NULL); -} - -static NM80211ApSecurityFlags -pair_to_flags (const char *str) -{ - g_return_val_if_fail (str != NULL, NM_802_11_AP_SEC_NONE); - - if (strcmp (str, "wep40") == 0) - return NM_802_11_AP_SEC_PAIR_WEP40; - if (strcmp (str, "wep104") == 0) - return NM_802_11_AP_SEC_PAIR_WEP104; - if (strcmp (str, "tkip") == 0) - return NM_802_11_AP_SEC_PAIR_TKIP; - if (strcmp (str, "ccmp") == 0) - return NM_802_11_AP_SEC_PAIR_CCMP; - return NM_802_11_AP_SEC_NONE; -} - -static NM80211ApSecurityFlags -group_to_flags (const char *str) -{ - g_return_val_if_fail (str != NULL, NM_802_11_AP_SEC_NONE); - - if (strcmp (str, "wep40") == 0) - return NM_802_11_AP_SEC_GROUP_WEP40; - if (strcmp (str, "wep104") == 0) - return NM_802_11_AP_SEC_GROUP_WEP104; - if (strcmp (str, "tkip") == 0) - return NM_802_11_AP_SEC_GROUP_TKIP; - if (strcmp (str, "ccmp") == 0) - return NM_802_11_AP_SEC_GROUP_CCMP; - return NM_802_11_AP_SEC_NONE; -} - -static NM80211ApSecurityFlags -security_from_dict (GHashTable *security) -{ - GValue *value; - NM80211ApSecurityFlags flags = NM_802_11_AP_SEC_NONE; - const char **items, **iter; - - value = g_hash_table_lookup (security, "KeyMgmt"); - if (value) { - items = g_value_get_boxed (value); - for (iter = items; iter && *iter; iter++) { - if (strcmp (*iter, "wpa-psk") == 0) - flags |= NM_802_11_AP_SEC_KEY_MGMT_PSK; - else if (strcmp (*iter, "wpa-eap") == 0) - flags |= NM_802_11_AP_SEC_KEY_MGMT_802_1X; - } - } - - value = g_hash_table_lookup (security, "Pairwise"); - if (value) { - items = g_value_get_boxed (value); - for (iter = items; iter && *iter; iter++) - flags |= pair_to_flags (*iter); - } - - value = g_hash_table_lookup (security, "Group"); - if (value) - flags |= group_to_flags (g_value_get_string (value)); - - return flags; -} - -static void -foreach_property_cb (gpointer key, gpointer value, gpointer user_data) -{ - GValue *variant = (GValue *) value; - NMAccessPoint *ap = (NMAccessPoint *) user_data; - - if (G_VALUE_HOLDS_BOXED (variant)) { - GArray *array = g_value_get_boxed (variant); - - if (!strcmp (key, "SSID")) { - guint32 len = MIN (32, array->len); - GByteArray *ssid; - - /* Stupid ieee80211 layer uses */ - if (((len == 8) || (len == 9)) - && (memcmp (array->data, "", 8) == 0)) - return; - - if (nm_utils_is_empty_ssid ((const guint8 *) array->data, len)) - return; - - ssid = g_byte_array_sized_new (len); - g_byte_array_append (ssid, (const guint8 *) array->data, len); - nm_ap_set_ssid (ap, ssid); - g_byte_array_free (ssid, TRUE); - } else if (!strcmp (key, "BSSID")) { - struct ether_addr addr; - - if (array->len != ETH_ALEN) - return; - memset (&addr, 0, sizeof (struct ether_addr)); - memcpy (&addr, array->data, ETH_ALEN); - nm_ap_set_address (ap, &addr); - } else if (!strcmp (key, "Rates")) { - guint32 maxrate = 0; - int i; - - /* Find the max AP rate */ - for (i = 0; i < array->len; i++) { - guint32 r = g_array_index (array, guint32, i); - - if (r > maxrate) { - maxrate = r; - nm_ap_set_max_bitrate (ap, r / 1000); - } - } - } else if (!strcmp (key, "WPA")) { - NM80211ApSecurityFlags flags = nm_ap_get_wpa_flags (ap); - - flags |= security_from_dict (g_value_get_boxed (variant)); - nm_ap_set_wpa_flags (ap, flags); - } else if (!strcmp (key, "RSN")) { - NM80211ApSecurityFlags flags = nm_ap_get_rsn_flags (ap); - - flags |= security_from_dict (g_value_get_boxed (variant)); - nm_ap_set_rsn_flags (ap, flags); - } - } else if (G_VALUE_HOLDS_UINT (variant)) { - guint32 val = g_value_get_uint (variant); - - if (!strcmp (key, "Frequency")) - nm_ap_set_freq (ap, val); - } else if (G_VALUE_HOLDS_INT (variant)) { - gint val = g_value_get_int (variant); - - if (!strcmp (key, "Signal")) - nm_ap_set_strength (ap, nm_ap_utils_level_to_quality (val)); - } else if (G_VALUE_HOLDS_STRING (variant)) { - const char *val = g_value_get_string (variant); - - if (val && !strcmp (key, "Mode")) { - if (strcmp (val, "infrastructure") == 0) - nm_ap_set_mode (ap, NM_802_11_MODE_INFRA); - else if (strcmp (val, "ad-hoc") == 0) - nm_ap_set_mode (ap, NM_802_11_MODE_ADHOC); - } - } else if (G_VALUE_HOLDS_BOOLEAN (variant)) { - gboolean val = g_value_get_boolean (variant); - - if (strcmp (key, "Privacy") == 0) { - if (val) { - NM80211ApFlags flags = nm_ap_get_flags (ap); - nm_ap_set_flags (ap, flags | NM_802_11_AP_FLAGS_PRIVACY); - } - } - } -} - -NMAccessPoint * -nm_ap_new_from_properties (const char *supplicant_path, GHashTable *properties) -{ - NMAccessPoint *ap; - const struct ether_addr * addr; - const char bad_bssid1[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - const char bad_bssid2[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; - - g_return_val_if_fail (properties != NULL, NULL); - - ap = nm_ap_new (); - - g_object_freeze_notify (G_OBJECT (ap)); - g_hash_table_foreach (properties, foreach_property_cb, ap); - - nm_ap_set_supplicant_path (ap, supplicant_path); - - /* ignore APs with invalid BSSIDs */ - addr = nm_ap_get_address (ap); - if ( !(memcmp (addr->ether_addr_octet, bad_bssid1, ETH_ALEN)) - || !(memcmp (addr->ether_addr_octet, bad_bssid2, ETH_ALEN))) { - g_object_unref (ap); - return NULL; - } - - nm_ap_set_last_seen (ap, (guint32) time (NULL)); - - if (!nm_ap_get_ssid (ap)) - nm_ap_set_broadcast (ap, FALSE); - - g_object_thaw_notify (G_OBJECT (ap)); - - return ap; -} - -#define PROTO_WPA "wpa" -#define PROTO_RSN "rsn" - -static gboolean -has_proto (NMSettingWirelessSecurity *sec, const char *proto) -{ - guint32 num_protos = nm_setting_wireless_security_get_num_protos (sec); - guint32 i; - - if (num_protos == 0) - return TRUE; /* interpret no protos as "all" */ - - for (i = 0; i < num_protos; i++) { - if (!strcmp (nm_setting_wireless_security_get_proto (sec, i), proto)) - return TRUE; - } - return FALSE; -} - -static void -add_pair_ciphers (NMAccessPoint *ap, NMSettingWirelessSecurity *sec) -{ - guint32 num = nm_setting_wireless_security_get_num_pairwise (sec); - NM80211ApSecurityFlags flags = NM_802_11_AP_SEC_NONE; - guint32 i; - - /* If no ciphers are specified, that means "all" WPA ciphers */ - if (num == 0) { - flags |= NM_802_11_AP_SEC_PAIR_TKIP | NM_802_11_AP_SEC_PAIR_CCMP; - } else { - for (i = 0; i < num; i++) { - const char *cipher = nm_setting_wireless_security_get_pairwise (sec, i); - - if (!strcmp (cipher, "tkip")) - flags |= NM_802_11_AP_SEC_PAIR_TKIP; - else if (!strcmp (cipher, "ccmp")) - flags |= NM_802_11_AP_SEC_PAIR_CCMP; - } - } - - if (has_proto (sec, PROTO_WPA)) - nm_ap_set_wpa_flags (ap, nm_ap_get_wpa_flags (ap) | flags); - if (has_proto (sec, PROTO_RSN)) - nm_ap_set_rsn_flags (ap, nm_ap_get_rsn_flags (ap) | flags); -} - -static void -add_group_ciphers (NMAccessPoint *ap, NMSettingWirelessSecurity *sec) -{ - guint32 num = nm_setting_wireless_security_get_num_groups (sec); - NM80211ApSecurityFlags flags = NM_802_11_AP_SEC_NONE; - guint32 i; - - /* If no ciphers are specified, that means "all" WPA ciphers */ - if (num == 0) { - flags |= NM_802_11_AP_SEC_GROUP_TKIP | NM_802_11_AP_SEC_GROUP_CCMP; - } else { - for (i = 0; i < num; i++) { - const char *cipher = nm_setting_wireless_security_get_group (sec, i); - - if (!strcmp (cipher, "wep40")) - flags |= NM_802_11_AP_SEC_GROUP_WEP40; - else if (!strcmp (cipher, "wep104")) - flags |= NM_802_11_AP_SEC_GROUP_WEP104; - else if (!strcmp (cipher, "tkip")) - flags |= NM_802_11_AP_SEC_GROUP_TKIP; - else if (!strcmp (cipher, "ccmp")) - flags |= NM_802_11_AP_SEC_GROUP_CCMP; - } - } - - if (has_proto (sec, PROTO_WPA)) - nm_ap_set_wpa_flags (ap, nm_ap_get_wpa_flags (ap) | flags); - if (has_proto (sec, PROTO_RSN)) - nm_ap_set_rsn_flags (ap, nm_ap_get_rsn_flags (ap) | flags); -} - -NMAccessPoint * -nm_ap_new_fake_from_connection (NMConnection *connection) -{ - NMAccessPoint *ap; - NMSettingWireless *s_wireless; - NMSettingWirelessSecurity *s_wireless_sec; - const GByteArray *ssid; - const char *mode, *band, *key_mgmt; - guint32 channel; - NM80211ApSecurityFlags flags; - gboolean psk = FALSE, eap = FALSE; - - g_return_val_if_fail (connection != NULL, NULL); - - s_wireless = nm_connection_get_setting_wireless (connection); - g_return_val_if_fail (s_wireless != NULL, NULL); - - ssid = nm_setting_wireless_get_ssid (s_wireless); - g_return_val_if_fail (ssid != NULL, NULL); - g_return_val_if_fail (ssid->len > 0, NULL); - - ap = nm_ap_new (); - nm_ap_set_fake (ap, TRUE); - nm_ap_set_ssid (ap, ssid); - - // FIXME: bssid too? - - mode = nm_setting_wireless_get_mode (s_wireless); - if (mode) { - if (!strcmp (mode, "infrastructure")) - nm_ap_set_mode (ap, NM_802_11_MODE_INFRA); - else if (!strcmp (mode, "adhoc")) - nm_ap_set_mode (ap, NM_802_11_MODE_ADHOC); - else if (!strcmp (mode, "ap")) { - nm_ap_set_mode (ap, NM_802_11_MODE_INFRA); - NM_AP_GET_PRIVATE (ap)->hotspot = TRUE; - } else - goto error; - } else { - nm_ap_set_mode (ap, NM_802_11_MODE_INFRA); - } - - band = nm_setting_wireless_get_band (s_wireless); - channel = nm_setting_wireless_get_channel (s_wireless); - - if (band && channel) { - guint32 freq = nm_utils_wifi_channel_to_freq (channel, band); - - if (freq == 0) - goto error; - - nm_ap_set_freq (ap, freq); - } - - s_wireless_sec = nm_connection_get_setting_wireless_security (connection); - /* Assume presence of a security setting means the AP is encrypted */ - if (!s_wireless_sec) - goto done; - - key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wireless_sec); - - /* Everything below here uses encryption */ - nm_ap_set_flags (ap, nm_ap_get_flags (ap) | NM_802_11_AP_FLAGS_PRIVACY); - - /* Static & Dynamic WEP */ - if (!strcmp (key_mgmt, "none") || !strcmp (key_mgmt, "ieee8021x")) - goto done; - - psk = !strcmp (key_mgmt, "wpa-psk"); - eap = !strcmp (key_mgmt, "wpa-eap"); - if (psk || eap) { - if (has_proto (s_wireless_sec, PROTO_WPA)) { - flags = nm_ap_get_wpa_flags (ap); - flags |= eap ? NM_802_11_AP_SEC_KEY_MGMT_802_1X : NM_802_11_AP_SEC_KEY_MGMT_PSK; - nm_ap_set_wpa_flags (ap, flags); - } - if (has_proto (s_wireless_sec, PROTO_RSN)) { - flags = nm_ap_get_rsn_flags (ap); - flags |= eap ? NM_802_11_AP_SEC_KEY_MGMT_802_1X : NM_802_11_AP_SEC_KEY_MGMT_PSK; - nm_ap_set_rsn_flags (ap, flags); - } - - add_pair_ciphers (ap, s_wireless_sec); - add_group_ciphers (ap, s_wireless_sec); - } else if (!strcmp (key_mgmt, "wpa-none")) { - guint32 i; - - /* Ad-Hoc has special requirements: proto=WPA, pairwise=(none), and - * group=TKIP/CCMP (but not both). - */ - - flags = nm_ap_get_wpa_flags (ap); - flags |= NM_802_11_AP_SEC_KEY_MGMT_PSK; - - /* Clear ciphers; pairwise must be unset anyway, and group gets set below */ - flags &= ~( NM_802_11_AP_SEC_PAIR_WEP40 - | NM_802_11_AP_SEC_PAIR_WEP104 - | NM_802_11_AP_SEC_PAIR_TKIP - | NM_802_11_AP_SEC_PAIR_CCMP - | NM_802_11_AP_SEC_GROUP_WEP40 - | NM_802_11_AP_SEC_GROUP_WEP104 - | NM_802_11_AP_SEC_GROUP_TKIP - | NM_802_11_AP_SEC_GROUP_CCMP); - - for (i = 0; i < nm_setting_wireless_security_get_num_groups (s_wireless_sec); i++) { - if (!strcmp (nm_setting_wireless_security_get_group (s_wireless_sec, i), "ccmp")) { - flags |= NM_802_11_AP_SEC_GROUP_CCMP; - break; - } - } - - /* Default to TKIP since not all WPA-capable cards can do CCMP */ - if (!(flags & NM_802_11_AP_SEC_GROUP_CCMP)) - flags |= NM_802_11_AP_SEC_GROUP_TKIP; - - nm_ap_set_wpa_flags (ap, flags); - - /* Don't use Ad-Hoc RSN yet */ - nm_ap_set_rsn_flags (ap, NM_802_11_AP_SEC_NONE); - } - -done: - return ap; - -error: - g_object_unref (ap); - return NULL; -} - - -#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x" -#define MAC_ARG(x) ((guint8*)(x))[0],((guint8*)(x))[1],((guint8*)(x))[2],((guint8*)(x))[3],((guint8*)(x))[4],((guint8*)(x))[5] - -void -nm_ap_dump (NMAccessPoint *ap, const char *prefix) -{ - NMAccessPointPrivate *priv; - - g_return_if_fail (ap != NULL); - g_return_if_fail (NM_IS_AP (ap)); - - priv = NM_AP_GET_PRIVATE (ap); - - nm_log_dbg (LOGD_WIFI_SCAN, "%s'%s' (%p)", - prefix, - priv->ssid ? nm_utils_escape_ssid (priv->ssid->data, priv->ssid->len) : "(none)", - ap); - nm_log_dbg (LOGD_WIFI_SCAN, " BSSID " MAC_FMT, MAC_ARG (priv->address.ether_addr_octet)); - nm_log_dbg (LOGD_WIFI_SCAN, " mode %d", priv->mode); - nm_log_dbg (LOGD_WIFI_SCAN, " flags 0x%X", priv->flags); - nm_log_dbg (LOGD_WIFI_SCAN, " wpa flags 0x%X", priv->wpa_flags); - nm_log_dbg (LOGD_WIFI_SCAN, " rsn flags 0x%X", priv->rsn_flags); - nm_log_dbg (LOGD_WIFI_SCAN, " quality %d", priv->strength); - nm_log_dbg (LOGD_WIFI_SCAN, " frequency %d", priv->freq); - nm_log_dbg (LOGD_WIFI_SCAN, " max rate %d", priv->max_bitrate); - nm_log_dbg (LOGD_WIFI_SCAN, " last-seen %ld", priv->last_seen); -} - -const char * -nm_ap_get_dbus_path (NMAccessPoint *ap) -{ - g_return_val_if_fail (NM_IS_AP (ap), NULL); - - return NM_AP_GET_PRIVATE (ap)->dbus_path; -} - -const char * -nm_ap_get_supplicant_path (NMAccessPoint *ap) -{ - g_return_val_if_fail (NM_IS_AP (ap), NULL); - - return NM_AP_GET_PRIVATE (ap)->supplicant_path; -} - -void -nm_ap_set_supplicant_path (NMAccessPoint *ap, const char *path) -{ - g_return_if_fail (NM_IS_AP (ap)); - g_return_if_fail (path != NULL); - - g_free (NM_AP_GET_PRIVATE (ap)->supplicant_path); - NM_AP_GET_PRIVATE (ap)->supplicant_path = g_strdup (path); -} - -/* - * Get/set functions for ssid - * - */ -const GByteArray * nm_ap_get_ssid (const NMAccessPoint *ap) -{ - g_return_val_if_fail (NM_IS_AP (ap), NULL); - - return NM_AP_GET_PRIVATE (ap)->ssid; -} - -void -nm_ap_set_ssid (NMAccessPoint *ap, const GByteArray * ssid) -{ - NMAccessPointPrivate *priv; - - g_return_if_fail (NM_IS_AP (ap)); - - priv = NM_AP_GET_PRIVATE (ap); - - if ((ssid == priv->ssid) && ssid == NULL) - return; - - /* same SSID */ - if ((ssid && priv->ssid) && (ssid->len == priv->ssid->len)) { - if (!memcmp (ssid->data, priv->ssid->data, ssid->len)) - return; - } - - if (priv->ssid) { - g_byte_array_free (priv->ssid, TRUE); - priv->ssid = NULL; - } - - if (ssid) { - /* Should never get zero-length SSIDs */ - g_warn_if_fail (ssid->len > 0); - - if (ssid->len) { - priv->ssid = g_byte_array_sized_new (ssid->len); - priv->ssid->len = ssid->len; - memcpy (priv->ssid->data, ssid->data, ssid->len); - } - } - - g_object_notify (G_OBJECT (ap), NM_AP_SSID); -} - - -NM80211ApFlags -nm_ap_get_flags (NMAccessPoint *ap) -{ - g_return_val_if_fail (NM_IS_AP (ap), NM_802_11_AP_SEC_NONE); - - return NM_AP_GET_PRIVATE (ap)->flags; -} - - -void -nm_ap_set_flags (NMAccessPoint *ap, NM80211ApFlags flags) -{ - NMAccessPointPrivate *priv; - - g_return_if_fail (NM_IS_AP (ap)); - - priv = NM_AP_GET_PRIVATE (ap); - - if (priv->flags != flags) { - priv->flags = flags; - g_object_notify (G_OBJECT (ap), NM_AP_FLAGS); - } -} - -NM80211ApSecurityFlags -nm_ap_get_wpa_flags (NMAccessPoint *ap) -{ - g_return_val_if_fail (NM_IS_AP (ap), NM_802_11_AP_SEC_NONE); - - return NM_AP_GET_PRIVATE (ap)->wpa_flags; -} - - -void -nm_ap_set_wpa_flags (NMAccessPoint *ap, NM80211ApSecurityFlags flags) -{ - NMAccessPointPrivate *priv; - - g_return_if_fail (NM_IS_AP (ap)); - - priv = NM_AP_GET_PRIVATE (ap); - if (priv->wpa_flags != flags) { - priv->wpa_flags = flags; - g_object_notify (G_OBJECT (ap), NM_AP_WPA_FLAGS); - } -} - -NM80211ApSecurityFlags -nm_ap_get_rsn_flags (NMAccessPoint *ap) -{ - g_return_val_if_fail (NM_IS_AP (ap), NM_802_11_AP_SEC_NONE); - - return NM_AP_GET_PRIVATE (ap)->rsn_flags; -} - - -void -nm_ap_set_rsn_flags (NMAccessPoint *ap, NM80211ApSecurityFlags flags) -{ - NMAccessPointPrivate *priv; - - g_return_if_fail (NM_IS_AP (ap)); - - priv = NM_AP_GET_PRIVATE (ap); - if (priv->rsn_flags != flags) { - priv->rsn_flags = flags; - g_object_notify (G_OBJECT (ap), NM_AP_RSN_FLAGS); - } -} - -/* - * Get/set functions for address - * - */ -const struct ether_addr * nm_ap_get_address (const NMAccessPoint *ap) -{ - g_return_val_if_fail (NM_IS_AP (ap), NULL); - - return &NM_AP_GET_PRIVATE (ap)->address; -} - -void nm_ap_set_address (NMAccessPoint *ap, const struct ether_addr * addr) -{ - NMAccessPointPrivate *priv; - - g_return_if_fail (NM_IS_AP (ap)); - g_return_if_fail (addr != NULL); - - priv = NM_AP_GET_PRIVATE (ap); - - if (memcmp (addr, &priv->address, sizeof (priv->address))) { - memcpy (&NM_AP_GET_PRIVATE (ap)->address, addr, sizeof (struct ether_addr)); - g_object_notify (G_OBJECT (ap), NM_AP_HW_ADDRESS); - } -} - - -/* - * Get/set functions for mode (ie Ad-Hoc, Infrastructure, etc) - * - */ -NM80211Mode nm_ap_get_mode (NMAccessPoint *ap) -{ - NM80211Mode mode; - - g_return_val_if_fail (NM_IS_AP (ap), -1); - - g_object_get (ap, NM_AP_MODE, &mode, NULL); - - return mode; -} - -void nm_ap_set_mode (NMAccessPoint *ap, const NM80211Mode mode) -{ - NMAccessPointPrivate *priv; - - g_return_if_fail (NM_IS_AP (ap)); - g_return_if_fail ( mode == NM_802_11_MODE_ADHOC - || mode == NM_802_11_MODE_INFRA); - - priv = NM_AP_GET_PRIVATE (ap); - - if (priv->mode != mode) { - priv->mode = mode; - g_object_notify (G_OBJECT (ap), NM_AP_MODE); - } -} - -gboolean -nm_ap_is_hotspot (NMAccessPoint *ap) -{ - g_return_val_if_fail (NM_IS_AP (ap), FALSE); - - return NM_AP_GET_PRIVATE (ap)->hotspot; -} - -/* - * Get/set functions for strength - * - */ -gint8 nm_ap_get_strength (NMAccessPoint *ap) -{ - gint8 strength; - - g_return_val_if_fail (NM_IS_AP (ap), 0); - - g_object_get (ap, NM_AP_STRENGTH, &strength, NULL); - - return strength; -} - -void nm_ap_set_strength (NMAccessPoint *ap, const gint8 strength) -{ - NMAccessPointPrivate *priv; - - g_return_if_fail (NM_IS_AP (ap)); - - priv = NM_AP_GET_PRIVATE (ap); - - if (priv->strength != strength) { - priv->strength = strength; - g_object_notify (G_OBJECT (ap), NM_AP_STRENGTH); - } -} - - -/* - * Get/set functions for frequency - * - */ -guint32 -nm_ap_get_freq (NMAccessPoint *ap) -{ - guint32 freq; - - g_return_val_if_fail (NM_IS_AP (ap), 0); - - g_object_get (ap, NM_AP_FREQUENCY, &freq, NULL); - - return freq; -} - -void -nm_ap_set_freq (NMAccessPoint *ap, - const guint32 freq) -{ - NMAccessPointPrivate *priv; - - g_return_if_fail (NM_IS_AP (ap)); - - priv = NM_AP_GET_PRIVATE (ap); - - if (priv->freq != freq) { - priv->freq = freq; - g_object_notify (G_OBJECT (ap), NM_AP_FREQUENCY); - } -} - - -/* - * Get/set functions for max bitrate - * - */ -guint32 nm_ap_get_max_bitrate (NMAccessPoint *ap) -{ - guint32 rate; - - g_return_val_if_fail (NM_IS_AP (ap), 0); - - g_object_get (ap, NM_AP_MAX_BITRATE, &rate, NULL); - - return rate; -} - -void -nm_ap_set_max_bitrate (NMAccessPoint *ap, guint32 bitrate) -{ - NMAccessPointPrivate *priv; - - g_return_if_fail (NM_IS_AP (ap)); - - priv = NM_AP_GET_PRIVATE (ap); - - if (priv->max_bitrate != bitrate) { - priv->max_bitrate = bitrate; - g_object_notify (G_OBJECT (ap), NM_AP_MAX_BITRATE); - } -} - -/* - * Get/Set functions to indicate that an access point is 'fake', ie whether - * or not it was created from scan results - */ -gboolean nm_ap_get_fake (const NMAccessPoint *ap) -{ - g_return_val_if_fail (NM_IS_AP (ap), FALSE); - - return NM_AP_GET_PRIVATE (ap)->fake; -} - -void nm_ap_set_fake (NMAccessPoint *ap, gboolean fake) -{ - g_return_if_fail (NM_IS_AP (ap)); - - NM_AP_GET_PRIVATE (ap)->fake = fake; -} - - -/* - * Get/Set functions to indicate whether an AP broadcasts its SSID. - */ -gboolean nm_ap_get_broadcast (NMAccessPoint *ap) -{ - g_return_val_if_fail (NM_IS_AP (ap), TRUE); - - return NM_AP_GET_PRIVATE (ap)->broadcast; -} - - -void nm_ap_set_broadcast (NMAccessPoint *ap, gboolean broadcast) -{ - g_return_if_fail (NM_IS_AP (ap)); - - NM_AP_GET_PRIVATE (ap)->broadcast = broadcast; -} - - -/* - * Get/Set functions for how long ago the AP was last seen in a scan. - * APs older than a certain date are dropped from the list. - * - */ -glong nm_ap_get_last_seen (const NMAccessPoint *ap) -{ - g_return_val_if_fail (NM_IS_AP (ap), FALSE); - - return NM_AP_GET_PRIVATE (ap)->last_seen; -} - -void nm_ap_set_last_seen (NMAccessPoint *ap, const glong last_seen) -{ - g_return_if_fail (NM_IS_AP (ap)); - - NM_AP_GET_PRIVATE (ap)->last_seen = last_seen; -} - -gboolean -nm_ap_check_compatible (NMAccessPoint *self, - NMConnection *connection) -{ - NMAccessPointPrivate *priv; - NMSettingWireless *s_wireless; - NMSettingWirelessSecurity *s_wireless_sec; - const char *mode; - const char *band; - const GByteArray *bssid; - guint32 channel; - - g_return_val_if_fail (NM_IS_AP (self), FALSE); - g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE); - - priv = NM_AP_GET_PRIVATE (self); - - s_wireless = nm_connection_get_setting_wireless (connection); - if (s_wireless == NULL) - return FALSE; - - if (!nm_utils_same_ssid (nm_setting_wireless_get_ssid (s_wireless), priv->ssid, TRUE)) - return FALSE; - - bssid = nm_setting_wireless_get_bssid (s_wireless); - if (bssid && memcmp (bssid->data, &priv->address, ETH_ALEN)) - return FALSE; - - mode = nm_setting_wireless_get_mode (s_wireless); - if (mode) { - if (!strcmp (mode, "infrastructure") && (priv->mode != NM_802_11_MODE_INFRA)) - return FALSE; - if (!strcmp (mode, "adhoc") && (priv->mode != NM_802_11_MODE_ADHOC)) - return FALSE; - if ( !strcmp (mode, "ap") - && (priv->mode != NM_802_11_MODE_INFRA || priv->hotspot != TRUE)) - return FALSE; - } - - band = nm_setting_wireless_get_band (s_wireless); - if (band) { - if (!strcmp (band, "a")) { - if (priv->freq < 4915 || priv->freq > 5825) - return FALSE; - } else if (!strcmp (band, "bg")) { - if (priv->freq < 2412 || priv->freq > 2484) - return FALSE; - } - } - - channel = nm_setting_wireless_get_channel (s_wireless); - if (channel) { - guint32 ap_chan = nm_utils_wifi_freq_to_channel (priv->freq); - - if (channel != ap_chan) - return FALSE; - } - - s_wireless_sec = nm_connection_get_setting_wireless_security (connection); - - return nm_setting_wireless_ap_security_compatible (s_wireless, - s_wireless_sec, - nm_ap_get_flags (self), - nm_ap_get_wpa_flags (self), - nm_ap_get_rsn_flags (self), - nm_ap_get_mode (self)); -} - -gboolean -nm_ap_complete_connection (NMAccessPoint *self, - NMConnection *connection, - gboolean lock_bssid, - GError **error) -{ - NMAccessPointPrivate *priv = NM_AP_GET_PRIVATE (self); - - g_return_val_if_fail (connection != NULL, FALSE); - - return nm_ap_utils_complete_connection (priv->ssid, - priv->address.ether_addr_octet, - priv->mode, - priv->flags, - priv->wpa_flags, - priv->rsn_flags, - connection, - lock_bssid, - error); -} - -static gboolean -capabilities_compatible (NM80211ApSecurityFlags a_flags, NM80211ApSecurityFlags b_flags) -{ - if (a_flags == b_flags) - return TRUE; - - /* Make sure there's a common key management method */ - if (!((a_flags & 0x300) & (b_flags & 0x300))) - return FALSE; - - /* Ensure common pairwise ciphers */ - if (!((a_flags & 0xF) & (b_flags & 0xF))) - return FALSE; - - /* Ensure common group ciphers */ - if (!((a_flags & 0xF0) & (b_flags & 0xF0))) - return FALSE; - - return TRUE; -} - -NMAccessPoint * -nm_ap_match_in_list (NMAccessPoint *find_ap, - GSList *ap_list, - gboolean strict_match) -{ - GSList *iter; - - g_return_val_if_fail (find_ap != NULL, NULL); - - for (iter = ap_list; iter; iter = g_slist_next (iter)) { - NMAccessPoint * list_ap = NM_AP (iter->data); - const GByteArray * list_ssid = nm_ap_get_ssid (list_ap); - const struct ether_addr * list_addr = nm_ap_get_address (list_ap); - - const GByteArray * find_ssid = nm_ap_get_ssid (find_ap); - const struct ether_addr * find_addr = nm_ap_get_address (find_ap); - - /* SSID match; if both APs are hiding their SSIDs, - * let matching continue on BSSID and other properties - */ - if ( (!list_ssid && find_ssid) - || (list_ssid && !find_ssid) - || !nm_utils_same_ssid (list_ssid, find_ssid, TRUE)) - continue; - - /* BSSID match */ - if ( (strict_match || nm_ethernet_address_is_valid (find_addr)) - && nm_ethernet_address_is_valid (list_addr) - && memcmp (list_addr->ether_addr_octet, - find_addr->ether_addr_octet, - ETH_ALEN) != 0) { - continue; - } - - /* mode match */ - if (nm_ap_get_mode (list_ap) != nm_ap_get_mode (find_ap)) - continue; - - /* Frequency match */ - if (nm_ap_get_freq (list_ap) != nm_ap_get_freq (find_ap)) - continue; - - /* AP flags */ - if (nm_ap_get_flags (list_ap) != nm_ap_get_flags (find_ap)) - continue; - - if (strict_match) { - if (nm_ap_get_wpa_flags (list_ap) != nm_ap_get_wpa_flags (find_ap)) - continue; - - if (nm_ap_get_rsn_flags (list_ap) != nm_ap_get_rsn_flags (find_ap)) - continue; - } else { - NM80211ApSecurityFlags list_wpa_flags = nm_ap_get_wpa_flags (list_ap); - NM80211ApSecurityFlags find_wpa_flags = nm_ap_get_wpa_flags (find_ap); - NM80211ApSecurityFlags list_rsn_flags = nm_ap_get_rsn_flags (list_ap); - NM80211ApSecurityFlags find_rsn_flags = nm_ap_get_rsn_flags (find_ap); - - /* Just ensure that there is overlap in the capabilities */ - if ( !capabilities_compatible (list_wpa_flags, find_wpa_flags) - && !capabilities_compatible (list_rsn_flags, find_rsn_flags)) - continue; - } - - return list_ap; - } - - return NULL; -} - diff --git a/src/nm-wifi-ap.h b/src/nm-wifi-ap.h deleted file mode 100644 index a1a0da92..00000000 --- a/src/nm-wifi-ap.h +++ /dev/null @@ -1,123 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2004 - 2011 Red Hat, Inc. - * Copyright (C) 2006 - 2008 Novell, Inc. - */ - -#ifndef NM_ACCESS_POINT_H -#define NM_ACCESS_POINT_H - -#include -#include -#include "NetworkManager.h" -#include "nm-connection.h" - -#define NM_TYPE_AP (nm_ap_get_type ()) -#define NM_AP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_AP, NMAccessPoint)) -#define NM_AP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_AP, NMAccessPointClass)) -#define NM_IS_AP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_AP)) -#define NM_IS_AP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_AP)) -#define NM_AP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_AP, NMAccessPointClass)) - -#define NM_AP_FLAGS "flags" -#define NM_AP_WPA_FLAGS "wpa-flags" -#define NM_AP_RSN_FLAGS "rsn-flags" -#define NM_AP_SSID "ssid" -#define NM_AP_FREQUENCY "frequency" -#define NM_AP_HW_ADDRESS "hw-address" -#define NM_AP_MODE "mode" -#define NM_AP_MAX_BITRATE "max-bitrate" -#define NM_AP_STRENGTH "strength" - -typedef struct { - GObject parent; -} NMAccessPoint; - -typedef struct { - GObjectClass parent; - - /* Signals */ - void (*properties_changed) (NMAccessPoint *ap, GHashTable *properties); -} NMAccessPointClass; - -GType nm_ap_get_type (void); - -NMAccessPoint * nm_ap_new_from_properties (const char *supplicant_path, - GHashTable *properties); -NMAccessPoint * nm_ap_new_fake_from_connection (NMConnection *connection); -void nm_ap_export_to_dbus (NMAccessPoint *ap); - -const char * nm_ap_get_dbus_path (NMAccessPoint *ap); - -const char * nm_ap_get_supplicant_path (NMAccessPoint *ap); -void nm_ap_set_supplicant_path (NMAccessPoint *ap, - const char *path); - -const GByteArray * nm_ap_get_ssid (const NMAccessPoint * ap); -void nm_ap_set_ssid (NMAccessPoint * ap, const GByteArray * ssid); - -NM80211ApFlags nm_ap_get_flags (NMAccessPoint *ap); -void nm_ap_set_flags (NMAccessPoint *ap, NM80211ApFlags flags); - -NM80211ApSecurityFlags nm_ap_get_wpa_flags (NMAccessPoint *ap); -void nm_ap_set_wpa_flags (NMAccessPoint *ap, NM80211ApSecurityFlags flags); - -NM80211ApSecurityFlags nm_ap_get_rsn_flags (NMAccessPoint *ap); -void nm_ap_set_rsn_flags (NMAccessPoint *ap, NM80211ApSecurityFlags flags); - -const struct ether_addr * nm_ap_get_address (const NMAccessPoint *ap); -void nm_ap_set_address (NMAccessPoint *ap, const struct ether_addr *addr); - -NM80211Mode nm_ap_get_mode (NMAccessPoint *ap); -void nm_ap_set_mode (NMAccessPoint *ap, const NM80211Mode mode); - -gboolean nm_ap_is_hotspot (NMAccessPoint *ap); - -gint8 nm_ap_get_strength (NMAccessPoint *ap); -void nm_ap_set_strength (NMAccessPoint *ap, gint8 strength); - -guint32 nm_ap_get_freq (NMAccessPoint *ap); -void nm_ap_set_freq (NMAccessPoint *ap, guint32 freq); - -guint32 nm_ap_get_max_bitrate (NMAccessPoint *ap); -void nm_ap_set_max_bitrate (NMAccessPoint *ap, guint32 bitrate); - -gboolean nm_ap_get_fake (const NMAccessPoint *ap); -void nm_ap_set_fake (NMAccessPoint *ap, gboolean fake); - -gboolean nm_ap_get_broadcast (NMAccessPoint *ap); -void nm_ap_set_broadcast (NMAccessPoint *ap, gboolean broadcast); - -glong nm_ap_get_last_seen (const NMAccessPoint *ap); -void nm_ap_set_last_seen (NMAccessPoint *ap, const glong last_seen); - -gboolean nm_ap_check_compatible (NMAccessPoint *self, - NMConnection *connection); - -gboolean nm_ap_complete_connection (NMAccessPoint *self, - NMConnection *connection, - gboolean lock_bssid, - GError **error); - -NMAccessPoint * nm_ap_match_in_list (NMAccessPoint *find_ap, - GSList *ap_list, - gboolean strict_match); - -void nm_ap_dump (NMAccessPoint *ap, const char *prefix); - -#endif /* NM_ACCESS_POINT_H */ diff --git a/src/org.freedesktop.NetworkManager.conf b/src/org.freedesktop.NetworkManager.conf index db68374c..bdfe3e67 100644 --- a/src/org.freedesktop.NetworkManager.conf +++ b/src/org.freedesktop.NetworkManager.conf @@ -26,93 +26,99 @@ - - + + + + + - + - + send_interface="org.freedesktop.NetworkManager.Device.Adsl"/> - + send_interface="org.freedesktop.NetworkManager.Device.Bond"/> - + send_interface="org.freedesktop.NetworkManager.Device.Bridge"/> - + send_interface="org.freedesktop.NetworkManager.Device.Bluetooth"/> + + + + + + + + + + + + + + send_interface="org.freedesktop.NetworkManager.Device.WiMax"/> + - + + - + - + + - - - - - - - - - - - - - - + send_interface="org.freedesktop.NetworkManager"/> + + - - - - - - - - + + + + + + + + + diff --git a/src/platform/Makefile.am b/src/platform/Makefile.am new file mode 100644 index 00000000..3c6155b9 --- /dev/null +++ b/src/platform/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = tests diff --git a/src/platform/Makefile.in b/src/platform/Makefile.in new file mode 100644 index 00000000..9358879f --- /dev/null +++ b/src/platform/Makefile.in @@ -0,0 +1,753 @@ +# Makefile.in generated by automake 1.13.4 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/platform +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_lib_readline.m4 \ + $(top_srcdir)/m4/compiler_warnings.m4 \ + $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/gnome-code-coverage.m4 \ + $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ + $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \ + $(top_srcdir)/m4/introspection.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ + $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ + $(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +ALL_LINGUAS = @ALL_LINGUAS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CKDB_PATH = @CKDB_PATH@ +CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@ +CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@ +CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIRNAME = @DATADIRNAME@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_100_CFLAGS = @DBUS_GLIB_100_CFLAGS@ +DBUS_GLIB_100_LIBS = @DBUS_GLIB_100_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DHCLIENT_PATH = @DHCLIENT_PATH@ +DHCPCD_PATH = @DHCPCD_PATH@ +DISTRO_NETWORK_SERVICE = @DISTRO_NETWORK_SERVICE@ +DLLTOOL = @DLLTOOL@ +DNSMASQ_PATH = @DNSMASQ_PATH@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GENHTML = @GENHTML@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MAKEFILE = @GLIB_MAKEFILE@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ +GNUTLS_LIBS = @GNUTLS_LIBS@ +GREP = @GREP@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GUDEV_CFLAGS = @GUDEV_CFLAGS@ +GUDEV_LIBS = @GUDEV_LIBS@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_PERL = @INTLTOOL_PERL@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ +INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ +INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ +INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +IPTABLES_PATH = @IPTABLES_PATH@ +IWMX_SDK_CFLAGS = @IWMX_SDK_CFLAGS@ +IWMX_SDK_LIBS = @IWMX_SDK_LIBS@ +KERNEL_FIRMWARE_DIR = @KERNEL_FIRMWARE_DIR@ +LCOV = @LCOV@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDL = @LIBDL@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBM = @LIBM@ +LIBNDP_CFLAGS = @LIBNDP_CFLAGS@ +LIBNDP_LIBS = @LIBNDP_LIBS@ +LIBNL_CFLAGS = @LIBNL_CFLAGS@ +LIBNL_LIBS = @LIBNL_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@ +LIBSOUP_LIBS = @LIBSOUP_LIBS@ +LIBTEAMDCTL_CFLAGS = @LIBTEAMDCTL_CFLAGS@ +LIBTEAMDCTL_LIBS = @LIBTEAMDCTL_LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MM_GLIB_CFLAGS = @MM_GLIB_CFLAGS@ +MM_GLIB_LIBS = @MM_GLIB_LIBS@ +MOC = @MOC@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NEWT_CFLAGS = @NEWT_CFLAGS@ +NEWT_LIBS = @NEWT_LIBS@ +NM = @NM@ +NMEDIT = @NMEDIT@ +NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ +NM_MICRO_VERSION = @NM_MICRO_VERSION@ +NM_MINOR_VERSION = @NM_MINOR_VERSION@ +NM_MODIFY_SYSTEM_POLICY = @NM_MODIFY_SYSTEM_POLICY@ +NM_VERSION = @NM_VERSION@ +NSS_CFLAGS = @NSS_CFLAGS@ +NSS_LIBS = @NSS_LIBS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +POLKIT_CFLAGS = @POLKIT_CFLAGS@ +POLKIT_LIBS = @POLKIT_LIBS@ +POSUB = @POSUB@ +PPPD_PATH = @PPPD_PATH@ +PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@ +PPPOE_PATH = @PPPOE_PATH@ +QT_CFLAGS = @QT_CFLAGS@ +QT_LIBS = @QT_LIBS@ +RANLIB = @RANLIB@ +READLINE_LIBS = @READLINE_LIBS@ +SED = @SED@ +SELINUX_CFLAGS = @SELINUX_CFLAGS@ +SELINUX_LIBS = @SELINUX_LIBS@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SYSTEMD_200_CFLAGS = @SYSTEMD_200_CFLAGS@ +SYSTEMD_200_LIBS = @SYSTEMD_200_LIBS@ +SYSTEMD_INHIBIT_CFLAGS = @SYSTEMD_INHIBIT_CFLAGS@ +SYSTEMD_INHIBIT_LIBS = @SYSTEMD_INHIBIT_LIBS@ +SYSTEMD_LOGIN_CFLAGS = @SYSTEMD_LOGIN_CFLAGS@ +SYSTEMD_LOGIN_LIBS = @SYSTEMD_LOGIN_LIBS@ +SYSTEM_CA_PATH = @SYSTEM_CA_PATH@ +UDEV_BASE_DIR = @UDEV_BASE_DIR@ +USE_NLS = @USE_NLS@ +UUID_CFLAGS = @UUID_CFLAGS@ +UUID_LIBS = @UUID_LIBS@ +VALGRIND_RULES = @VALGRIND_RULES@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ +VERSION = @VERSION@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +intltool__v_merge_options_ = @intltool__v_merge_options_@ +intltool__v_merge_options_0 = @intltool__v_merge_options_0@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +nmbinary = @nmbinary@ +nmconfdir = @nmconfdir@ +nmdatadir = @nmdatadir@ +nmrundir = @nmrundir@ +nmstatedir = @nmstatedir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +with_dhclient = @with_dhclient@ +with_dhcpcd = @with_dhcpcd@ +with_netconfig = @with_netconfig@ +with_resolvconf = @with_resolvconf@ +with_valgrind = @with_valgrind@ +SUBDIRS = tests +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/platform/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/platform/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am clean clean-generic clean-libtool cscopelist-am ctags \ + ctags-am distclean distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags tags-am uninstall uninstall-am + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/platform/nm-fake-platform.c b/src/platform/nm-fake-platform.c new file mode 100644 index 00000000..46272217 --- /dev/null +++ b/src/platform/nm-fake-platform.c @@ -0,0 +1,1352 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* nm-platform-fake.c - Fake platform interaction code for testing NetworkManager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2012–2013 Red Hat, Inc. + */ + +#include +#include +#include +#include + +#include "NetworkManagerUtils.h" +#include "nm-fake-platform.h" +#include "nm-logging.h" + +#define debug(format, ...) nm_log_dbg (LOGD_PLATFORM, format, __VA_ARGS__) + +typedef struct { + GHashTable *options; + GArray *links; + GArray *ip4_addresses; + GArray *ip6_addresses; + GArray *ip4_routes; + GArray *ip6_routes; +} NMFakePlatformPrivate; + +typedef struct { + NMPlatformLink link; + + char *udi; + GBytes *address; + int vlan_id; +} NMFakePlatformLink; + +#define NM_FAKE_PLATFORM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_FAKE_PLATFORM, NMFakePlatformPrivate)) + +G_DEFINE_TYPE (NMFakePlatform, nm_fake_platform, NM_TYPE_PLATFORM) + +/******************************************************************/ + +void +nm_fake_platform_setup (void) +{ + nm_platform_setup (NM_TYPE_FAKE_PLATFORM); +} + +/******************************************************************/ + +static gboolean +sysctl_set (NMPlatform *platform, const char *path, const char *value) +{ + NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform); + + g_hash_table_insert (priv->options, g_strdup (path), g_strdup (value)); + + return TRUE; +} + +static char * +sysctl_get (NMPlatform *platform, const char *path) +{ + NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform); + + return g_strdup (g_hash_table_lookup (priv->options, path)); +} + +static const char * +type_to_type_name (NMLinkType type) +{ + switch (type) { + case NM_LINK_TYPE_UNKNOWN: + return "unknown"; + case NM_LINK_TYPE_LOOPBACK: + return "loopback"; + case NM_LINK_TYPE_ETHERNET: + return "ethernet"; + case NM_LINK_TYPE_DUMMY: + return "dummy"; + case NM_LINK_TYPE_BRIDGE: + return "bridge"; + case NM_LINK_TYPE_BOND: + return "bond"; + case NM_LINK_TYPE_TEAM: + return "team"; + case NM_LINK_TYPE_VLAN: + return "vlan"; + case NM_LINK_TYPE_NONE: + default: + return NULL; + } +} + +static void +link_init (NMFakePlatformLink *device, int ifindex, int type, const char *name) +{ + g_assert (!name || strlen (name) < sizeof(device->link.name)); + + memset (device, 0, sizeof (*device)); + + device->link.ifindex = name ? ifindex : 0; + device->link.type = type; + device->link.type_name = type_to_type_name (type); + device->link.driver = type_to_type_name (type); + device->link.udi = device->udi = g_strdup_printf ("fake:%d", ifindex); + if (name) + strcpy (device->link.name, name); + switch (device->link.type) { + case NM_LINK_TYPE_DUMMY: + device->link.arp = FALSE; + break; + default: + device->link.arp = TRUE; + } + device->address = NULL; +} + +static NMFakePlatformLink * +link_get (NMPlatform *platform, int ifindex) +{ + NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform); + NMFakePlatformLink *device; + + if (ifindex >= priv->links->len) + goto not_found; + device = &g_array_index (priv->links, NMFakePlatformLink, ifindex); + if (!device->link.ifindex) + goto not_found; + + return device; +not_found: + debug ("link not found: %d", ifindex); + platform->error = NM_PLATFORM_ERROR_NOT_FOUND; + return NULL; +} + +static GArray * +link_get_all (NMPlatform *platform) +{ + NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform); + GArray *links = g_array_sized_new (TRUE, TRUE, sizeof (NMPlatformLink), priv->links->len); + int i; + + for (i = 0; i < priv->links->len; i++) + if (g_array_index (priv->links, NMFakePlatformLink, i).link.ifindex) + g_array_append_val (links, g_array_index (priv->links, NMFakePlatformLink, i).link); + + return links; +} + +static gboolean +_nm_platform_link_get (NMPlatform *platform, int ifindex, NMPlatformLink *link) +{ + NMFakePlatformLink *device = link_get (platform, ifindex); + + if (device) + *link = device->link; + return !!device; +} + +static gboolean +link_add (NMPlatform *platform, const char *name, NMLinkType type, const void *address, size_t address_len) +{ + NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform); + NMFakePlatformLink device; + + link_init (&device, priv->links->len, type, name); + + g_array_append_val (priv->links, device); + + if (device.link.ifindex) + g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_LINK_CHANGED, device.link.ifindex, &device, NM_PLATFORM_SIGNAL_ADDED, NM_PLATFORM_REASON_INTERNAL); + + return TRUE; +} + +static gboolean +link_delete (NMPlatform *platform, int ifindex) +{ + NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform); + NMFakePlatformLink *device = link_get (platform, ifindex); + NMPlatformLink deleted_device; + int i; + + if (!device || !device->link.ifindex) + return FALSE; + + memcpy (&deleted_device, &device->link, sizeof (deleted_device)); + memset (&device->link, 0, sizeof (device->link)); + + /* Remove addresses and routes which belong to the deleted interface */ + for (i = 0; i < priv->ip4_addresses->len; i++) { + NMPlatformIP4Address *address = &g_array_index (priv->ip4_addresses, NMPlatformIP4Address, i); + + if (address->ifindex == ifindex) + memset (address, 0, sizeof (*address)); + } + for (i = 0; i < priv->ip6_addresses->len; i++) { + NMPlatformIP6Address *address = &g_array_index (priv->ip6_addresses, NMPlatformIP6Address, i); + + if (address->ifindex == ifindex) + memset (address, 0, sizeof (*address)); + } + for (i = 0; i < priv->ip4_routes->len; i++) { + NMPlatformIP4Route *route = &g_array_index (priv->ip4_routes, NMPlatformIP4Route, i); + + if (route->ifindex == ifindex) + memset (route, 0, sizeof (*route)); + } + for (i = 0; i < priv->ip6_routes->len; i++) { + NMPlatformIP6Route *route = &g_array_index (priv->ip6_routes, NMPlatformIP6Route, i); + + if (route->ifindex == ifindex) + memset (route, 0, sizeof (*route)); + } + + g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_LINK_CHANGED, ifindex, &deleted_device, NM_PLATFORM_SIGNAL_REMOVED, NM_PLATFORM_REASON_INTERNAL); + + return TRUE; +} + +static int +link_get_ifindex (NMPlatform *platform, const char *name) +{ + NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform); + int i; + + for (i = 0; i < priv->links->len; i++) { + NMFakePlatformLink *device = &g_array_index (priv->links, NMFakePlatformLink, i); + + if (device && !g_strcmp0 (device->link.name, name)) + return device->link.ifindex; + } + + return 0; +} + +static const char * +link_get_name (NMPlatform *platform, int ifindex) +{ + NMFakePlatformLink *device = link_get (platform, ifindex); + + return device ? device->link.name : NULL; +} + +static NMLinkType +link_get_type (NMPlatform *platform, int ifindex) +{ + NMFakePlatformLink *device = link_get (platform, ifindex); + + return device ? device->link.type : NM_LINK_TYPE_NONE; +} + +static const char * +link_get_type_name (NMPlatform *platform, int ifindex) +{ + return type_to_type_name (link_get_type (platform, ifindex)); +} + +static void +link_changed (NMPlatform *platform, NMFakePlatformLink *device) +{ + NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform); + int i; + + g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_LINK_CHANGED, device->link.ifindex, &device->link, NM_PLATFORM_SIGNAL_CHANGED, NM_PLATFORM_REASON_INTERNAL); + + if (device->link.master) { + NMFakePlatformLink *master = link_get (platform, device->link.master); + + g_return_if_fail (master != device); + + master->link.connected = FALSE; + for (i = 0; i < priv->links->len; i++) { + NMFakePlatformLink *slave = &g_array_index (priv->links, NMFakePlatformLink, i); + + if (slave && slave->link.master == master->link.ifindex && slave->link.connected) + master->link.connected = TRUE; + } + + link_changed (platform, master); + } +} + +static gboolean +link_set_up (NMPlatform *platform, int ifindex) +{ + NMFakePlatformLink *device = link_get (platform, ifindex); + + if (!device) + return FALSE; + + device->link.up = TRUE; + switch (device->link.type) { + case NM_LINK_TYPE_DUMMY: + case NM_LINK_TYPE_VLAN: + device->link.connected = TRUE; + break; + case NM_LINK_TYPE_BRIDGE: + case NM_LINK_TYPE_BOND: + case NM_LINK_TYPE_TEAM: + device->link.connected = FALSE; + break; + default: + device->link.connected = FALSE; + g_error ("Unexpected device type: %d", device->link.type); + } + + link_changed (platform, device); + + return TRUE; +} + +static gboolean +link_set_down (NMPlatform *platform, int ifindex) +{ + NMFakePlatformLink *device = link_get (platform, ifindex); + + if (!device) + return FALSE; + + device->link.up = FALSE; + device->link.connected = FALSE; + + link_changed (platform, device); + + return TRUE; +} + +static gboolean +link_set_arp (NMPlatform *platform, int ifindex) +{ + NMFakePlatformLink *device = link_get (platform, ifindex); + + if (!device) + return FALSE; + + device->link.arp = TRUE; + + link_changed (platform, device); + + return TRUE; +} + +static gboolean +link_set_noarp (NMPlatform *platform, int ifindex) +{ + NMFakePlatformLink *device = link_get (platform, ifindex); + + if (!device) + return FALSE; + + device->link.arp = FALSE; + + link_changed (platform, device); + + return TRUE; +} + +static gboolean +link_is_up (NMPlatform *platform, int ifindex) +{ + NMFakePlatformLink *device = link_get (platform, ifindex); + + return device ? device->link.up : FALSE; +} + +static gboolean +link_is_connected (NMPlatform *platform, int ifindex) +{ + NMFakePlatformLink *device = link_get (platform, ifindex); + + return device ? device->link.connected : FALSE; +} + +static gboolean +link_uses_arp (NMPlatform *platform, int ifindex) +{ + NMFakePlatformLink *device = link_get (platform, ifindex); + + return device ? device->link.arp : FALSE; +} + +static gboolean +link_set_address (NMPlatform *platform, int ifindex, gconstpointer addr, size_t len) +{ + NMFakePlatformLink *device = link_get (platform, ifindex); + + if (device->address) + g_bytes_unref (device->address); + + device->address = g_bytes_new (addr, len); + + link_changed (platform, link_get (platform, ifindex)); + + return TRUE; +} + +static gconstpointer +link_get_address (NMPlatform *platform, int ifindex, size_t *length) +{ + NMFakePlatformLink *device = link_get (platform, ifindex); + + if (!device || !device->address) { + if (length) + *length = 0; + return NULL; + } + + return g_bytes_get_data (device->address, length); +} + +static gboolean +link_set_mtu (NMPlatform *platform, int ifindex, guint32 mtu) +{ + NMFakePlatformLink *device = link_get (platform, ifindex); + + if (device) { + device->link.mtu = mtu; + link_changed (platform, device); + } + + return !!device; +} + +static guint32 +link_get_mtu (NMPlatform *platform, int ifindex) +{ + NMFakePlatformLink *device = link_get (platform, ifindex); + + return device ? device->link.mtu : 0; +} + +static char * +link_get_physical_port_id (NMPlatform *platform, int ifindex) +{ + /* We call link_get just to cause an error to be set if @ifindex is bad. */ + link_get (platform, ifindex); + + return NULL; +} + +static gboolean +link_get_wake_on_lan (NMPlatform *platform, int ifindex) +{ + /* We call link_get just to cause an error to be set if @ifindex is bad. */ + link_get (platform, ifindex); + + return FALSE; +} + +static gboolean +link_supports_carrier_detect (NMPlatform *platform, int ifindex) +{ + NMFakePlatformLink *device = link_get (platform, ifindex); + + if (!device) + return FALSE; + + switch (device->link.type) { + case NM_LINK_TYPE_DUMMY: + return FALSE; + default: + return TRUE; + } +} + +static gboolean +link_supports_vlans (NMPlatform *platform, int ifindex) +{ + NMFakePlatformLink *device = link_get (platform, ifindex); + + if (!device) + return FALSE; + + switch (device->link.type) { + case NM_LINK_TYPE_LOOPBACK: + return FALSE; + default: + return TRUE; + } +} + +static gboolean +link_enslave (NMPlatform *platform, int master, int slave) +{ + NMFakePlatformLink *device = link_get (platform, slave); + + g_return_val_if_fail (device, FALSE); + + device->link.master = master; + + link_changed (platform, device); + + return TRUE; +} + +static gboolean +link_release (NMPlatform *platform, int master_idx, int slave_idx) +{ + NMFakePlatformLink *master = link_get (platform, master_idx); + NMFakePlatformLink *slave = link_get (platform, slave_idx); + + g_return_val_if_fail (master, FALSE); + g_return_val_if_fail (slave, FALSE); + + if (slave->link.master != master->link.ifindex) { + platform->error = NM_PLATFORM_ERROR_NOT_SLAVE; + return FALSE; + } + + slave->link.master = 0; + + link_changed (platform, slave); + link_changed (platform, master); + + return TRUE; +} + +static int +link_get_master (NMPlatform *platform, int slave) +{ + NMFakePlatformLink *device = link_get (platform, slave); + + g_return_val_if_fail (device, FALSE); + + return device->link.master; +} + +static gboolean +master_set_option (NMPlatform *platform, int master, const char *option, const char *value) +{ + auto_g_free char *path = g_strdup_printf ("master:%d:%s", master, option); + + return sysctl_set (platform, path, value); +} + +static char * +master_get_option (NMPlatform *platform, int master, const char *option) +{ + auto_g_free char *path = g_strdup_printf ("master:%d:%s", master, option); + + return sysctl_get (platform, path); +} + +static gboolean +slave_set_option (NMPlatform *platform, int slave, const char *option, const char *value) +{ + auto_g_free char *path = g_strdup_printf ("slave:%d:%s", slave, option); + + return sysctl_set (platform, path, value); +} + +static char * +slave_get_option (NMPlatform *platform, int slave, const char *option) +{ + auto_g_free char *path = g_strdup_printf ("slave:%d:%s", slave, option); + + return sysctl_get (platform, path); +} + +static gboolean +vlan_add (NMPlatform *platform, const char *name, int parent, int vlan_id, guint32 vlan_flags) +{ + NMFakePlatformLink *device; + + if (!link_add (platform, name, NM_LINK_TYPE_VLAN, NULL, 0)) + return FALSE; + + device = link_get (platform, link_get_ifindex (platform, name)); + + g_return_val_if_fail (device, FALSE); + + device->vlan_id = vlan_id; + device->link.parent = parent; + + return TRUE; +} + +static gboolean +vlan_get_info (NMPlatform *platform, int ifindex, int *parent, int *vlan_id) +{ + NMFakePlatformLink *device = link_get (platform, ifindex); + + g_return_val_if_fail (device, FALSE); + + if (parent) + *parent = device->link.parent; + if (vlan_id) + *vlan_id = device->vlan_id; + + return TRUE; +} + +static gboolean +vlan_set_ingress_map (NMPlatform *platform, int ifindex, int from, int to) +{ + return !!link_get (platform, ifindex); +} + +static gboolean +vlan_set_egress_map (NMPlatform *platform, int ifindex, int from, int to) +{ + return !!link_get (platform, ifindex); +} + +static gboolean +infiniband_partition_add (NMPlatform *platform, int parent, int p_key) +{ + NMFakePlatformLink *parent_device; + char *name; + gboolean success; + + parent_device = link_get (platform, parent); + g_return_val_if_fail (parent_device != NULL, FALSE); + + name = g_strdup_printf ("%s.%04x", parent_device->link.name, p_key); + success = link_add (platform, name, NM_LINK_TYPE_INFINIBAND, NULL, 0); + g_free (name); + + return success; +} + +static gboolean +veth_get_properties (NMPlatform *platform, int ifindex, NMPlatformVethProperties *props) +{ + return FALSE; +} + +static gboolean +tun_get_properties (NMPlatform *platform, int ifindex, NMPlatformTunProperties *props) +{ + return FALSE; +} + +static gboolean +macvlan_get_properties (NMPlatform *platform, int ifindex, NMPlatformMacvlanProperties *props) +{ + return FALSE; +} + +static gboolean +vxlan_get_properties (NMPlatform *platform, int ifindex, NMPlatformVxlanProperties *props) +{ + return FALSE; +} + +static gboolean +gre_get_properties (NMPlatform *platform, int ifindex, NMPlatformGreProperties *props) +{ + return FALSE; +} + +static gboolean +wifi_get_capabilities (NMPlatform *platform, int ifindex, NMDeviceWifiCapabilities *caps) +{ + NMFakePlatformLink *device = link_get (platform, ifindex); + + g_return_val_if_fail (device, FALSE); + + if (device->link.type != NM_LINK_TYPE_WIFI) + return FALSE; + + if (caps) { + *caps = ( NM_WIFI_DEVICE_CAP_CIPHER_WEP40 + | NM_WIFI_DEVICE_CAP_CIPHER_WEP104 + | NM_WIFI_DEVICE_CAP_CIPHER_TKIP + | NM_WIFI_DEVICE_CAP_CIPHER_CCMP + | NM_WIFI_DEVICE_CAP_WPA + | NM_WIFI_DEVICE_CAP_RSN + | NM_WIFI_DEVICE_CAP_AP + | NM_WIFI_DEVICE_CAP_ADHOC); + } + return TRUE; +} + +static gboolean +wifi_get_bssid (NMPlatform *platform, int ifindex, struct ether_addr *bssid) +{ + return FALSE; +} + +static GByteArray * +wifi_get_ssid (NMPlatform *platform, int ifindex) +{ + return NULL; +} + +static guint32 +wifi_get_frequency (NMPlatform *platform, int ifindex) +{ + return 0; +} + +static int +wifi_get_quality (NMPlatform *platform, int ifindex) +{ + return 0; +} + +static guint32 +wifi_get_rate (NMPlatform *platform, int ifindex) +{ + return 0; +} + +static NM80211Mode +wifi_get_mode (NMPlatform *platform, int ifindex) +{ + return NM_802_11_MODE_UNKNOWN; +} + +static void +wifi_set_mode (NMPlatform *platform, int ifindex, NM80211Mode mode) +{ + ; +} + +static guint32 +wifi_find_frequency (NMPlatform *platform, int ifindex, const guint32 *freqs) +{ + return freqs[0]; +} + +static void +wifi_indicate_addressing_running (NMPlatform *platform, int ifindex, gboolean running) +{ + ; +} + +static guint32 +mesh_get_channel (NMPlatform *platform, int ifindex) +{ + return 0; +} + +static gboolean +mesh_set_channel (NMPlatform *platform, int ifindex, guint32 channel) +{ + return FALSE; +} + +static gboolean +mesh_set_ssid (NMPlatform *platform, int ifindex, const GByteArray *ssid) +{ + return FALSE; +} + +/******************************************************************/ + +static GArray * +ip4_address_get_all (NMPlatform *platform, int ifindex) +{ + NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform); + GArray *addresses; + NMPlatformIP4Address *address; + int count = 0, i; + + /* Count addresses */ + for (i = 0; i < priv->ip4_addresses->len; i++) { + address = &g_array_index (priv->ip4_addresses, NMPlatformIP4Address, i); + if (address && address->ifindex == ifindex) + count++; + } + + addresses = g_array_sized_new (TRUE, TRUE, sizeof (NMPlatformIP4Address), count); + + /* Fill addresses */ + for (i = 0; i < priv->ip4_addresses->len; i++) { + address = &g_array_index (priv->ip4_addresses, NMPlatformIP4Address, i); + if (address && address->ifindex == ifindex) + g_array_append_val (addresses, *address); + } + + return addresses; +} + +static GArray * +ip6_address_get_all (NMPlatform *platform, int ifindex) +{ + NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform); + GArray *addresses; + NMPlatformIP6Address *address; + int count = 0, i; + + /* Count addresses */ + for (i = 0; i < priv->ip6_addresses->len; i++) { + address = &g_array_index (priv->ip6_addresses, NMPlatformIP6Address, i); + if (address && address->ifindex == ifindex) + count++; + } + + addresses = g_array_sized_new (TRUE, TRUE, sizeof (NMPlatformIP6Address), count); + + /* Fill addresses */ + count = 0; + for (i = 0; i < priv->ip6_addresses->len; i++) { + address = &g_array_index (priv->ip6_addresses, NMPlatformIP6Address, i); + if (address && address->ifindex == ifindex) + g_array_append_val (addresses, *address); + } + + return addresses; +} + +static gboolean +ip4_address_add (NMPlatform *platform, int ifindex, + in_addr_t addr, in_addr_t peer_addr, + int plen, guint32 lifetime, guint32 preferred, + const char *label) +{ + NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform); + NMPlatformIP4Address address; + int i; + + memset (&address, 0, sizeof (address)); + address.source = NM_PLATFORM_SOURCE_KERNEL; + address.ifindex = ifindex; + address.address = addr; + address.peer_address = peer_addr; + address.plen = plen; + address.timestamp = nm_utils_get_monotonic_timestamp_s (); + address.lifetime = lifetime; + address.preferred = preferred; + if (label) + g_strlcpy (address.label, label, sizeof (address.label)); + + for (i = 0; i < priv->ip4_addresses->len; i++) { + NMPlatformIP4Address *item = &g_array_index (priv->ip4_addresses, NMPlatformIP4Address, i); + + if (item->ifindex != address.ifindex) + continue; + if (item->address != address.address) + continue; + if (item->plen != address.plen) + continue; + + memcpy (item, &address, sizeof (address)); + g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED, ifindex, &address, NM_PLATFORM_SIGNAL_CHANGED, NM_PLATFORM_REASON_INTERNAL); + return TRUE; + } + + g_array_append_val (priv->ip4_addresses, address); + g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED, ifindex, &address, NM_PLATFORM_SIGNAL_ADDED, NM_PLATFORM_REASON_INTERNAL); + + return TRUE; +} + +static gboolean +ip6_address_add (NMPlatform *platform, int ifindex, + struct in6_addr addr, struct in6_addr peer_addr, + int plen, guint32 lifetime, guint32 preferred, guint flags) +{ + NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform); + NMPlatformIP6Address address; + int i; + + memset (&address, 0, sizeof (address)); + address.source = NM_PLATFORM_SOURCE_KERNEL; + address.ifindex = ifindex; + address.address = addr; + address.peer_address = peer_addr; + address.plen = plen; + address.timestamp = nm_utils_get_monotonic_timestamp_s (); + address.lifetime = lifetime; + address.preferred = preferred; + address.flags = flags; + + for (i = 0; i < priv->ip6_addresses->len; i++) { + NMPlatformIP6Address *item = &g_array_index (priv->ip6_addresses, NMPlatformIP6Address, i); + + if (item->ifindex != address.ifindex) + continue; + if (!IN6_ARE_ADDR_EQUAL (&item->address, &address.address)) + continue; + if (item->plen != address.plen) + continue; + + memcpy (item, &address, sizeof (address)); + g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED, ifindex, &address, NM_PLATFORM_SIGNAL_CHANGED, NM_PLATFORM_REASON_INTERNAL); + return TRUE; + } + + g_array_append_val (priv->ip6_addresses, address); + g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED, ifindex, &address, NM_PLATFORM_SIGNAL_ADDED, NM_PLATFORM_REASON_INTERNAL); + + return TRUE; +} + +static gboolean +ip4_address_delete (NMPlatform *platform, int ifindex, in_addr_t addr, int plen) +{ + NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform); + int i; + + for (i = 0; i < priv->ip4_addresses->len; i++) { + NMPlatformIP4Address *address = &g_array_index (priv->ip4_addresses, NMPlatformIP4Address, i); + + if (address->ifindex == ifindex && address->plen == plen && address->address == addr) { + NMPlatformIP4Address deleted_address; + + memcpy (&deleted_address, address, sizeof (deleted_address)); + memset (address, 0, sizeof (*address)); + g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED, ifindex, &deleted_address, NM_PLATFORM_SIGNAL_REMOVED, NM_PLATFORM_REASON_INTERNAL); + return TRUE; + } + } + + return TRUE; +} + +static gboolean +ip6_address_delete (NMPlatform *platform, int ifindex, struct in6_addr addr, int plen) +{ + NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform); + int i; + + for (i = 0; i < priv->ip6_addresses->len; i++) { + NMPlatformIP6Address *address = &g_array_index (priv->ip6_addresses, NMPlatformIP6Address, i); + + if (address->ifindex == ifindex && address->plen == plen + && IN6_ARE_ADDR_EQUAL (&address->address, &addr)) { + NMPlatformIP6Address deleted_address; + + memcpy (&deleted_address, address, sizeof (deleted_address)); + memset (address, 0, sizeof (*address)); + g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED, ifindex, &deleted_address, NM_PLATFORM_SIGNAL_REMOVED, NM_PLATFORM_REASON_INTERNAL); + return TRUE; + } + } + + return TRUE; +} + +static gboolean +ip4_address_exists (NMPlatform *platform, int ifindex, in_addr_t addr, int plen) +{ + NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform); + int i; + + for (i = 0; i < priv->ip4_addresses->len; i++) { + NMPlatformIP4Address *address = &g_array_index (priv->ip4_addresses, NMPlatformIP4Address, i); + + if (address->ifindex == ifindex && address->plen == plen && address->address == addr) + return TRUE; + } + + return FALSE; +} + +static gboolean +ip6_address_exists (NMPlatform *platform, int ifindex, struct in6_addr addr, int plen) +{ + NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform); + int i; + + for (i = 0; i < priv->ip6_addresses->len; i++) { + NMPlatformIP6Address *address = &g_array_index (priv->ip6_addresses, NMPlatformIP6Address, i); + + if (address->ifindex == ifindex && address->plen == plen && + IN6_ARE_ADDR_EQUAL (&address->address, &addr)) + return TRUE; + } + + return FALSE; +} + +/******************************************************************/ + +static GArray * +ip4_route_get_all (NMPlatform *platform, int ifindex, gboolean include_default) +{ + NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform); + GArray *routes; + NMPlatformIP4Route *route; + int count = 0, i; + + /* Count routes */ + for (i = 0; i < priv->ip4_routes->len; i++) { + route = &g_array_index (priv->ip4_routes, NMPlatformIP4Route, i); + if (route && route->ifindex == ifindex) + count++; + } + + routes = g_array_sized_new (TRUE, TRUE, sizeof (NMPlatformIP4Route), count); + + /* Fill routes */ + for (i = 0; i < priv->ip4_routes->len; i++) { + route = &g_array_index (priv->ip4_routes, NMPlatformIP4Route, i); + if (route && route->ifindex == ifindex) { + if (route->plen != 0 || include_default) + g_array_append_val (routes, *route); + } + } + + return routes; +} + +static GArray * +ip6_route_get_all (NMPlatform *platform, int ifindex, gboolean include_default) +{ + NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform); + GArray *routes; + NMPlatformIP6Route *route; + int count = 0, i; + + /* Count routes */ + for (i = 0; i < priv->ip6_routes->len; i++) { + route = &g_array_index (priv->ip6_routes, NMPlatformIP6Route, i); + if (route && route->ifindex == ifindex) + count++; + } + + routes = g_array_sized_new (TRUE, TRUE, sizeof (NMPlatformIP6Route), count); + + /* Fill routes */ + for (i = 0; i < priv->ip6_routes->len; i++) { + route = &g_array_index (priv->ip6_routes, NMPlatformIP6Route, i); + if (route && route->ifindex == ifindex) { + if (route->plen != 0 || include_default) + g_array_append_val (routes, *route); + } + } + + return routes; +} + +static gboolean +ip4_route_add (NMPlatform *platform, int ifindex, NMPlatformSource source, + in_addr_t network, int plen, in_addr_t gateway, + int metric, int mss) +{ + NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform); + NMPlatformIP4Route route; + guint i; + + memset (&route, 0, sizeof (route)); + route.source = NM_PLATFORM_SOURCE_KERNEL; + route.ifindex = ifindex; + route.source = source; + route.network = network; + route.plen = plen; + route.gateway = gateway; + route.metric = metric; + route.mss = mss; + + for (i = 0; i < priv->ip4_routes->len; i++) { + NMPlatformIP4Route *item = &g_array_index (priv->ip4_routes, NMPlatformIP4Route, i); + + if (item->ifindex != route.ifindex) + continue; + if (item->network != route.network) + continue; + if (item->plen != route.plen) + continue; + + memcpy (item, &route, sizeof (route)); + g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, ifindex, &route, NM_PLATFORM_SIGNAL_CHANGED, NM_PLATFORM_REASON_INTERNAL); + return TRUE; + } + + g_array_append_val (priv->ip4_routes, route); + g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, ifindex, &route, NM_PLATFORM_SIGNAL_ADDED, NM_PLATFORM_REASON_INTERNAL); + + return TRUE; +} + +static gboolean +ip6_route_add (NMPlatform *platform, int ifindex, NMPlatformSource source, + struct in6_addr network, int plen, struct in6_addr gateway, + int metric, int mss) +{ + NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform); + NMPlatformIP6Route route; + guint i; + + memset (&route, 0, sizeof (route)); + route.source = NM_PLATFORM_SOURCE_KERNEL; + route.ifindex = ifindex; + route.source = source; + route.network = network; + route.plen = plen; + route.gateway = gateway; + route.metric = metric; + route.mss = mss; + + for (i = 0; i < priv->ip6_routes->len; i++) { + NMPlatformIP6Route *item = &g_array_index (priv->ip6_routes, NMPlatformIP6Route, i); + + if (item->ifindex != route.ifindex) + continue; + if (!IN6_ARE_ADDR_EQUAL (&item->network, &route.network)) + continue; + if (item->plen != route.plen) + continue; + + memcpy (item, &route, sizeof (route)); + g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, ifindex, &route, NM_PLATFORM_SIGNAL_CHANGED, NM_PLATFORM_REASON_INTERNAL); + return TRUE; + } + + g_array_append_val (priv->ip6_routes, route); + g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, ifindex, &route, NM_PLATFORM_SIGNAL_ADDED, NM_PLATFORM_REASON_INTERNAL); + + return TRUE; +} + +static NMPlatformIP4Route * +ip4_route_get (NMPlatform *platform, int ifindex, in_addr_t network, int plen, int metric) +{ + NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform); + int i; + + for (i = 0; i < priv->ip4_routes->len; i++) { + NMPlatformIP4Route *route = &g_array_index (priv->ip4_routes, NMPlatformIP4Route, i); + + if (route->ifindex == ifindex + && route->network == network + && route->plen == plen + && route->metric == metric) + return route; + } + + return NULL; +} + +static NMPlatformIP6Route * +ip6_route_get (NMPlatform *platform, int ifindex, struct in6_addr network, int plen, int metric) +{ + NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform); + int i; + + for (i = 0; i < priv->ip6_routes->len; i++) { + NMPlatformIP6Route *route = &g_array_index (priv->ip6_routes, NMPlatformIP6Route, i); + + if (route->ifindex == ifindex + && IN6_ARE_ADDR_EQUAL (&route->network, &network) + && route->plen == plen + && route->metric == metric) + return route; + } + + return NULL; +} + +static gboolean +ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, int plen, int metric) +{ + NMPlatformIP4Route *route = ip4_route_get (platform, ifindex, network, plen, metric); + NMPlatformIP4Route deleted_route; + + if (route) { + memcpy (&deleted_route, route, sizeof (deleted_route)); + memset (route, 0, sizeof (*route)); + g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, ifindex, &deleted_route, NM_PLATFORM_SIGNAL_REMOVED, NM_PLATFORM_REASON_INTERNAL); + } + + return TRUE; +} + +static gboolean +ip6_route_delete (NMPlatform *platform, int ifindex, struct in6_addr network, int plen, int metric) +{ + NMPlatformIP6Route *route = ip6_route_get (platform, ifindex, network, plen, metric); + NMPlatformIP6Route deleted_route; + + if (route) { + memcpy (&deleted_route, route, sizeof (deleted_route)); + memset (route, 0, sizeof (*route)); + g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, ifindex, &deleted_route, NM_PLATFORM_SIGNAL_REMOVED, NM_PLATFORM_REASON_INTERNAL); + } + + return TRUE; +} + +static gboolean +ip4_route_exists (NMPlatform *platform, int ifindex, in_addr_t network, int plen, int metric) +{ + return !!ip4_route_get (platform, ifindex, network, plen, metric); +} + +static gboolean +ip6_route_exists (NMPlatform *platform, int ifindex, struct in6_addr network, int plen, int metric) +{ + return !!ip6_route_get (platform, ifindex, network, plen, metric); +} + +/******************************************************************/ + +static void +nm_fake_platform_init (NMFakePlatform *fake_platform) +{ + NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (fake_platform); + + priv->options = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); + priv->links = g_array_new (TRUE, TRUE, sizeof (NMFakePlatformLink)); + priv->ip4_addresses = g_array_new (TRUE, TRUE, sizeof (NMPlatformIP4Address)); + priv->ip6_addresses = g_array_new (TRUE, TRUE, sizeof (NMPlatformIP6Address)); + priv->ip4_routes = g_array_new (TRUE, TRUE, sizeof (NMPlatformIP4Route)); + priv->ip6_routes = g_array_new (TRUE, TRUE, sizeof (NMPlatformIP6Route)); +} + +static gboolean +setup (NMPlatform *platform) +{ + /* skip zero element */ + link_add (platform, NULL, NM_LINK_TYPE_NONE, NULL, 0); + + /* add loopback interface */ + link_add (platform, "lo", NM_LINK_TYPE_LOOPBACK, NULL, 0); + + /* add some ethernets */ + link_add (platform, "eth0", NM_LINK_TYPE_ETHERNET, NULL, 0); + link_add (platform, "eth1", NM_LINK_TYPE_ETHERNET, NULL, 0); + link_add (platform, "eth2", NM_LINK_TYPE_ETHERNET, NULL, 0); + + return TRUE; +} + +static void +nm_fake_platform_finalize (GObject *object) +{ + NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (object); + int i; + + g_hash_table_unref (priv->options); + for (i = 0; i < priv->links->len; i++) { + NMFakePlatformLink *device = &g_array_index (priv->links, NMFakePlatformLink, i); + + g_bytes_unref (device->address); + g_free (device->udi); + } + g_array_unref (priv->links); + g_array_unref (priv->ip4_addresses); + g_array_unref (priv->ip6_addresses); + g_array_unref (priv->ip4_routes); + g_array_unref (priv->ip6_routes); + + G_OBJECT_CLASS (nm_fake_platform_parent_class)->finalize (object); +} + +static void +nm_fake_platform_class_init (NMFakePlatformClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMPlatformClass *platform_class = NM_PLATFORM_CLASS (klass); + + g_type_class_add_private (klass, sizeof (NMFakePlatformPrivate)); + + /* virtual methods */ + object_class->finalize = nm_fake_platform_finalize; + + platform_class->setup = setup; + + platform_class->sysctl_set = sysctl_set; + platform_class->sysctl_get = sysctl_get; + + platform_class->link_get = _nm_platform_link_get; + platform_class->link_get_all = link_get_all; + platform_class->link_add = link_add; + platform_class->link_delete = link_delete; + platform_class->link_get_ifindex = link_get_ifindex; + platform_class->link_get_name = link_get_name; + platform_class->link_get_type = link_get_type; + platform_class->link_get_type_name = link_get_type_name; + + platform_class->link_set_up = link_set_up; + platform_class->link_set_down = link_set_down; + platform_class->link_set_arp = link_set_arp; + platform_class->link_set_noarp = link_set_noarp; + platform_class->link_is_up = link_is_up; + platform_class->link_is_connected = link_is_connected; + platform_class->link_uses_arp = link_uses_arp; + + platform_class->link_set_address = link_set_address; + platform_class->link_get_address = link_get_address; + platform_class->link_get_mtu = link_get_mtu; + platform_class->link_set_mtu = link_set_mtu; + + platform_class->link_get_physical_port_id = link_get_physical_port_id; + platform_class->link_get_wake_on_lan = link_get_wake_on_lan; + + platform_class->link_supports_carrier_detect = link_supports_carrier_detect; + platform_class->link_supports_vlans = link_supports_vlans; + + platform_class->link_enslave = link_enslave; + platform_class->link_release = link_release; + platform_class->link_get_master = link_get_master; + platform_class->master_set_option = master_set_option; + platform_class->master_get_option = master_get_option; + platform_class->slave_set_option = slave_set_option; + platform_class->slave_get_option = slave_get_option; + + platform_class->vlan_add = vlan_add; + platform_class->vlan_get_info = vlan_get_info; + platform_class->vlan_set_ingress_map = vlan_set_ingress_map; + platform_class->vlan_set_egress_map = vlan_set_egress_map; + + platform_class->infiniband_partition_add = infiniband_partition_add; + + platform_class->veth_get_properties = veth_get_properties; + platform_class->tun_get_properties = tun_get_properties; + platform_class->macvlan_get_properties = macvlan_get_properties; + platform_class->vxlan_get_properties = vxlan_get_properties; + platform_class->gre_get_properties = gre_get_properties; + + platform_class->wifi_get_capabilities = wifi_get_capabilities; + platform_class->wifi_get_bssid = wifi_get_bssid; + platform_class->wifi_get_ssid = wifi_get_ssid; + platform_class->wifi_get_frequency = wifi_get_frequency; + platform_class->wifi_get_quality = wifi_get_quality; + platform_class->wifi_get_rate = wifi_get_rate; + platform_class->wifi_get_mode = wifi_get_mode; + platform_class->wifi_set_mode = wifi_set_mode; + platform_class->wifi_find_frequency = wifi_find_frequency; + platform_class->wifi_indicate_addressing_running = wifi_indicate_addressing_running; + + platform_class->mesh_get_channel = mesh_get_channel; + platform_class->mesh_set_channel = mesh_set_channel; + platform_class->mesh_set_ssid = mesh_set_ssid; + + platform_class->ip4_address_get_all = ip4_address_get_all; + platform_class->ip6_address_get_all = ip6_address_get_all; + platform_class->ip4_address_add = ip4_address_add; + platform_class->ip6_address_add = ip6_address_add; + platform_class->ip4_address_delete = ip4_address_delete; + platform_class->ip6_address_delete = ip6_address_delete; + platform_class->ip4_address_exists = ip4_address_exists; + platform_class->ip6_address_exists = ip6_address_exists; + + platform_class->ip4_route_get_all = ip4_route_get_all; + platform_class->ip6_route_get_all = ip6_route_get_all; + platform_class->ip4_route_add = ip4_route_add; + platform_class->ip6_route_add = ip6_route_add; + platform_class->ip4_route_delete = ip4_route_delete; + platform_class->ip6_route_delete = ip6_route_delete; + platform_class->ip4_route_exists = ip4_route_exists; + platform_class->ip6_route_exists = ip6_route_exists; +} diff --git a/src/platform/nm-fake-platform.h b/src/platform/nm-fake-platform.h new file mode 100644 index 00000000..c9fa42eb --- /dev/null +++ b/src/platform/nm-fake-platform.h @@ -0,0 +1,49 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* nm-fake-platform.h - Fake platform interaction code for testing NetworkManager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2012 Red Hat, Inc. + */ + +#ifndef NM_FAKE_PLATFORM_H +#define NM_FAKE_PLATFORM_H + +#include "nm-platform.h" + +#define NM_TYPE_FAKE_PLATFORM (nm_fake_platform_get_type ()) +#define NM_FAKE_PLATFORM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_FAKE_PLATFORM, NMFakePlatform)) +#define NM_FAKE_PLATFORM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_FAKE_PLATFORM, NMFakePlatformClass)) +#define NM_IS_FAKE_PLATFORM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_FAKE_PLATFORM)) +#define NM_IS_FAKE_PLATFORM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_FAKE_PLATFORM)) +#define NM_FAKE_PLATFORM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_FAKE_PLATFORM, NMFakePlatformClass)) + +/******************************************************************/ + +typedef struct { + NMPlatform parent; +} NMFakePlatform; + +typedef struct { + NMPlatformClass parent; +} NMFakePlatformClass; + +/******************************************************************/ + +GType nm_fake_platform_get_type (void); + +void nm_fake_platform_setup (void); + +#endif /* NM_FAKE_PLATFORM_H */ diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c new file mode 100644 index 00000000..f73ff320 --- /dev/null +++ b/src/platform/nm-linux-platform.c @@ -0,0 +1,4180 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* nm-linux-platform.c - Linux kernel & udev network configuration layer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2012-2013 Red Hat, Inc. + */ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "NetworkManagerUtils.h" +#include "nm-linux-platform.h" +#include "NetworkManagerUtils.h" +#include "nm-utils.h" +#include "nm-logging.h" +#include "wifi/wifi-utils.h" +#include "wifi/wifi-utils-wext.h" + +/* This is only included for the translation of VLAN flags */ +#include "nm-setting-vlan.h" + +#define debug(...) nm_log_dbg (LOGD_PLATFORM, __VA_ARGS__) +#define warning(...) nm_log_warn (LOGD_PLATFORM, __VA_ARGS__) +#define error(...) nm_log_err (LOGD_PLATFORM, __VA_ARGS__) + + +struct libnl_vtable +{ + void *handle; + + int (*f_nl_has_capability) (int capability); +}; + + +typedef struct { + struct nl_sock *nlh; + struct nl_sock *nlh_event; + struct nl_cache *link_cache; + struct nl_cache *address_cache; + struct nl_cache *route_cache; + GIOChannel *event_channel; + guint event_id; + + GUdevClient *udev_client; + GHashTable *udev_devices; + + GHashTable *wifi_data; + + int support_kernel_extended_ifa_flags; +} NMLinuxPlatformPrivate; + +#define NM_LINUX_PLATFORM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_LINUX_PLATFORM, NMLinuxPlatformPrivate)) + +G_DEFINE_TYPE (NMLinuxPlatform, nm_linux_platform, NM_TYPE_PLATFORM) + +static const char *to_string_object (NMPlatform *platform, struct nl_object *obj); + +void +nm_linux_platform_setup (void) +{ + nm_platform_setup (NM_TYPE_LINUX_PLATFORM); +} + +/******************************************************************/ + +static int +_nl_f_nl_has_capability (int capability) +{ + return FALSE; +} + +static struct libnl_vtable * +_nl_get_vtable () +{ + static struct libnl_vtable vtable; + + if (G_UNLIKELY (!vtable.f_nl_has_capability)) { + void *handle; + + handle = dlopen ("libnl-3.so", RTLD_LAZY | RTLD_NOLOAD); + if (handle) { + vtable.handle = handle; + vtable.f_nl_has_capability = dlsym (handle, "nl_has_capability"); + } + + if (!vtable.f_nl_has_capability) + vtable.f_nl_has_capability = &_nl_f_nl_has_capability; + + g_return_val_if_fail (vtable.handle, &vtable); + } + + return &vtable; +} + +static gboolean +_nl_has_capability (int capability) +{ + return (_nl_get_vtable ()->f_nl_has_capability) (capability); +} + +/******************************************************************/ + +static guint32 +_get_expiry (guint32 now_s, guint32 lifetime_s) +{ + gint64 t = ((gint64) now_s) + ((gint64) lifetime_s); + + return MIN (t, NM_PLATFORM_LIFETIME_PERMANENT - 1); +} + +/* The rtnl_addr object contains relative lifetimes @valid and @preferred + * that count in seconds, starting from the moment when the kernel constructed + * the netlink message. + * + * There is also a field rtnl_addr_last_update_time(), which is the absolute + * time in 1/100th of a second of clock_gettime (CLOCK_MONOTONIC) when the address + * was modified (wrapping every 497 days). + * Immediately at the time when the address was last modified, #NOW and @last_update_time + * are the same, so (only) in that case @valid and @preferred are anchored at @last_update_time. + * However, this is not true in general. As time goes by, whenever kernel sends a new address + * via netlink, the lifetimes keep counting down. + * + * As we cache the rtnl_addr object we must know the absolute expiries. + * As a hack, modify the relative timestamps valid and preferred into absolute + * timestamps of scale nm_utils_get_monotonic_timestamp_s(). + **/ +static void +_rtnl_addr_hack_lifetimes_rel_to_abs (struct rtnl_addr *rtnladdr) +{ + guint32 a_valid = rtnl_addr_get_valid_lifetime (rtnladdr); + guint32 a_preferred = rtnl_addr_get_preferred_lifetime (rtnladdr); + guint32 now; + + if (a_valid == NM_PLATFORM_LIFETIME_PERMANENT && + a_preferred == NM_PLATFORM_LIFETIME_PERMANENT) + return; + + now = (guint32) nm_utils_get_monotonic_timestamp_s (); + + if (a_preferred > a_valid) + a_preferred = a_valid; + + if (a_valid != NM_PLATFORM_LIFETIME_PERMANENT) + rtnl_addr_set_valid_lifetime (rtnladdr, _get_expiry (now, a_valid)); + rtnl_addr_set_preferred_lifetime (rtnladdr, _get_expiry (now, a_preferred)); +} + +/******************************************************************/ + +/* libnl library workarounds and additions */ + +/* Automatic deallocation of local variables */ +#define auto_nl_cache __attribute__((cleanup(put_nl_cache))) +static void +put_nl_cache (void *ptr) +{ + struct nl_cache **cache = ptr; + + if (cache && *cache) { + nl_cache_free (*cache); + *cache = NULL; + } +} + +#define auto_nl_object __attribute__((cleanup(put_nl_object))) +static void +put_nl_object (void *ptr) +{ + struct nl_object **object = ptr; + + if (object && *object) { + nl_object_put (*object); + *object = NULL; + } +} + +#define auto_nl_addr __attribute__((cleanup(put_nl_addr))) +static void +put_nl_addr (void *ptr) +{ + struct nl_addr **object = ptr; + + if (object && *object) { + nl_addr_put (*object); + *object = NULL; + } +} + +/*******************************************************************/ + +/* wrap the libnl alloc functions and abort on out-of-memory*/ + +static struct nl_addr * +_nm_nl_addr_build (int family, const void *buf, size_t size) +{ + struct nl_addr *addr; + + addr = nl_addr_build (family, (void *) buf, size); + if (!addr) + g_error ("nl_addr_build() failed with out of memory"); + + return addr; +} + +static struct rtnl_link * +_nm_rtnl_link_alloc (int ifindex, const char*name) +{ + struct rtnl_link *rtnllink; + + rtnllink = rtnl_link_alloc (); + if (!rtnllink) + g_error ("rtnl_link_alloc() failed with out of memory"); + + if (ifindex > 0) + rtnl_link_set_ifindex (rtnllink, ifindex); + if (name) + rtnl_link_set_name (rtnllink, name); + return rtnllink; +} + +static struct rtnl_addr * +_nm_rtnl_addr_alloc (int ifindex) +{ + struct rtnl_addr *rtnladdr; + + rtnladdr = rtnl_addr_alloc (); + if (!rtnladdr) + g_error ("rtnl_addr_alloc() failed with out of memory"); + if (ifindex > 0) + rtnl_addr_set_ifindex (rtnladdr, ifindex); + return rtnladdr; +} + +static struct rtnl_route * +_nm_rtnl_route_alloc () +{ + struct rtnl_route *rtnlroute = rtnl_route_alloc (); + + if (!rtnlroute) + g_error ("rtnl_route_alloc() failed with out of memory"); + return rtnlroute; +} + +static struct rtnl_nexthop * +_nm_rtnl_route_nh_alloc () +{ + struct rtnl_nexthop *nexthop; + + nexthop = rtnl_route_nh_alloc (); + if (!nexthop) + g_error ("rtnl_route_nh_alloc () failed with out of memory"); + return nexthop; +} + +/*******************************************************************/ + +/* rtnl_addr_set_prefixlen fails to update the nl_addr prefixlen */ +static void +nm_rtnl_addr_set_prefixlen (struct rtnl_addr *rtnladdr, int plen) +{ + struct nl_addr *nladdr; + + rtnl_addr_set_prefixlen (rtnladdr, plen); + + nladdr = rtnl_addr_get_local (rtnladdr); + if (nladdr) + nl_addr_set_prefixlen (nladdr, plen); +} +#define rtnl_addr_set_prefixlen nm_rtnl_addr_set_prefixlen + +typedef enum { + OBJECT_TYPE_UNKNOWN, + OBJECT_TYPE_LINK, + OBJECT_TYPE_IP4_ADDRESS, + OBJECT_TYPE_IP6_ADDRESS, + OBJECT_TYPE_IP4_ROUTE, + OBJECT_TYPE_IP6_ROUTE, + __OBJECT_TYPE_LAST, +} ObjectType; + +static ObjectType +object_type_from_nl_object (const struct nl_object *object) +{ + const char *type_str; + + if (!object || !(type_str = nl_object_get_type (object))) + return OBJECT_TYPE_UNKNOWN; + + if (!strcmp (type_str, "route/link")) + return OBJECT_TYPE_LINK; + else if (!strcmp (type_str, "route/addr")) { + switch (rtnl_addr_get_family ((struct rtnl_addr *) object)) { + case AF_INET: + return OBJECT_TYPE_IP4_ADDRESS; + case AF_INET6: + return OBJECT_TYPE_IP6_ADDRESS; + default: + return OBJECT_TYPE_UNKNOWN; + } + } else if (!strcmp (type_str, "route/route")) { + switch (rtnl_route_get_family ((struct rtnl_route *) object)) { + case AF_INET: + return OBJECT_TYPE_IP4_ROUTE; + case AF_INET6: + return OBJECT_TYPE_IP6_ROUTE; + default: + return OBJECT_TYPE_UNKNOWN; + } + } else + return OBJECT_TYPE_UNKNOWN; +} + +static void +_nl_link_family_unset (struct nl_object *obj, int *family) +{ + if (!obj || object_type_from_nl_object (obj) != OBJECT_TYPE_LINK) + *family = AF_UNSPEC; + else { + *family = rtnl_link_get_family ((struct rtnl_link *) obj); + + /* Always explicitly set the family to AF_UNSPEC, even if rtnl_link_get_family() might + * already return %AF_UNSPEC. The reason is, that %AF_UNSPEC is the default family + * and libnl nl_object_identical() function will only succeed, if the family is + * explicitly set (which we cannot be sure, unless setting it). */ + rtnl_link_set_family ((struct rtnl_link *) obj, AF_UNSPEC); + } +} + +/* In our link cache, we coerce the family of all link objects to AF_UNSPEC. + * Thus, before searching for an object, we fixup @needle to have the right + * id (by resetting the family). */ +static struct nl_object * +nm_nl_cache_search (struct nl_cache *cache, struct nl_object *needle) +{ + int family; + struct nl_object *obj; + + _nl_link_family_unset (needle, &family); + obj = nl_cache_search (cache, needle); + if (family != AF_UNSPEC) { + /* restore the family of the @needle instance. If the family was + * unset before, we cannot make it unset again. Thus, in that case + * we cannot undo _nl_link_family_unset() entirely. */ + rtnl_link_set_family ((struct rtnl_link *) needle, family); + } + + return obj; +} + +/* Ask the kernel for an object identical (as in nl_cache_identical) to the + * needle argument. This is a kernel counterpart for nl_cache_search. + * + * The returned object must be freed by the caller with nl_object_put(). + */ +static struct nl_object * +get_kernel_object (struct nl_sock *sock, struct nl_object *needle) +{ + struct nl_object *object = NULL; + ObjectType type = object_type_from_nl_object (needle); + + switch (type) { + case OBJECT_TYPE_LINK: + { + int ifindex = rtnl_link_get_ifindex ((struct rtnl_link *) needle); + const char *name = rtnl_link_get_name ((struct rtnl_link *) needle); + int nle; + + nle = rtnl_link_get_kernel (sock, ifindex, name, (struct rtnl_link **) &object); + switch (nle) { + case -NLE_SUCCESS: + if (nm_logging_enabled (LOGL_DEBUG, LOGD_PLATFORM)) { + name = rtnl_link_get_name ((struct rtnl_link *) object); + debug ("get_kernel_object for link: %s (%d, family %d)", + name ? name : "(unknown)", + rtnl_link_get_ifindex ((struct rtnl_link *) object), + rtnl_link_get_family ((struct rtnl_link *) object)); + } + + _nl_link_family_unset (object, &nle); + return object; + case -NLE_NODEV: + debug ("get_kernel_object for link %s (%d) had no result", + name ? name : "(unknown)", ifindex); + return NULL; + default: + error ("get_kernel_object for link %s (%d) failed: %s (%d)", + name ? name : "(unknown)", ifindex, nl_geterror (nle), nle); + return NULL; + } + } + case OBJECT_TYPE_IP4_ADDRESS: + case OBJECT_TYPE_IP6_ADDRESS: + case OBJECT_TYPE_IP4_ROUTE: + case OBJECT_TYPE_IP6_ROUTE: + /* Fallback to a one-time cache allocation. */ + { + struct nl_cache *cache; + int nle; + + /* FIXME: every time we refresh *one* object, we request an + * entire dump. E.g. check_cache_items() gets O(n2) complexitly. */ + + nle = nl_cache_alloc_and_fill ( + nl_cache_ops_lookup (nl_object_get_type (needle)), + sock, &cache); + if (nle) { + error ("get_kernel_object for type %d failed: %s (%d)", + type, nl_geterror (nle), nle); + return NULL; + } + + object = nl_cache_search (cache, needle); + + nl_cache_free (cache); + + if (object && (type == OBJECT_TYPE_IP4_ADDRESS || type == OBJECT_TYPE_IP6_ADDRESS)) + _rtnl_addr_hack_lifetimes_rel_to_abs ((struct rtnl_addr *) object); + + if (object) + debug ("get_kernel_object for type %d returned %p", type, object); + else + debug ("get_kernel_object for type %d had no result", type); + return object; + } + default: + g_return_val_if_reached (NULL); + return NULL; + } +} + +/* libnl 3.2 doesn't seem to provide such a generic way to add libnl-route objects. */ +static int +add_kernel_object (struct nl_sock *sock, struct nl_object *object) +{ + switch (object_type_from_nl_object (object)) { + case OBJECT_TYPE_LINK: + return rtnl_link_add (sock, (struct rtnl_link *) object, NLM_F_CREATE); + case OBJECT_TYPE_IP4_ADDRESS: + case OBJECT_TYPE_IP6_ADDRESS: + return rtnl_addr_add (sock, (struct rtnl_addr *) object, NLM_F_CREATE | NLM_F_REPLACE); + case OBJECT_TYPE_IP4_ROUTE: + case OBJECT_TYPE_IP6_ROUTE: + return rtnl_route_add (sock, (struct rtnl_route *) object, NLM_F_CREATE | NLM_F_REPLACE); + default: + g_return_val_if_reached (-NLE_INVAL); + return -NLE_INVAL; + } +} + +/* nm_rtnl_link_parse_info_data(): Re-fetches a link from the kernel + * and parses its IFLA_INFO_DATA using a caller-provided parser. + * + * Code is stolen from rtnl_link_get_kernel(), nl_pickup(), and link_msg_parser(). + */ + +typedef int (*NMNLInfoDataParser) (struct nlattr *info_data, gpointer parser_data); + +typedef struct { + NMNLInfoDataParser parser; + gpointer parser_data; +} NMNLInfoDataClosure; + +static struct nla_policy info_data_link_policy[IFLA_MAX + 1] = { + [IFLA_LINKINFO] = { .type = NLA_NESTED }, +}; + +static struct nla_policy info_data_link_info_policy[IFLA_INFO_MAX + 1] = { + [IFLA_INFO_DATA] = { .type = NLA_NESTED }, +}; + +static int +info_data_parser (struct nl_msg *msg, void *arg) +{ + NMNLInfoDataClosure *closure = arg; + struct nlmsghdr *n = nlmsg_hdr (msg); + struct nlattr *tb[IFLA_MAX + 1]; + struct nlattr *li[IFLA_INFO_MAX + 1]; + int err; + + if (!nlmsg_valid_hdr (n, sizeof (struct ifinfomsg))) + return -NLE_MSG_TOOSHORT; + + err = nlmsg_parse (n, sizeof (struct ifinfomsg), tb, IFLA_MAX, info_data_link_policy); + if (err < 0) + return err; + + if (!tb[IFLA_LINKINFO]) + return -NLE_MISSING_ATTR; + + err = nla_parse_nested (li, IFLA_INFO_MAX, tb[IFLA_LINKINFO], info_data_link_info_policy); + if (err < 0) + return err; + + if (!li[IFLA_INFO_DATA]) + return -NLE_MISSING_ATTR; + + return closure->parser (li[IFLA_INFO_DATA], closure->parser_data); +} + +static int +nm_rtnl_link_parse_info_data (struct nl_sock *sk, int ifindex, + NMNLInfoDataParser parser, gpointer parser_data) +{ + NMNLInfoDataClosure data = { .parser = parser, .parser_data = parser_data }; + struct nl_msg *msg = NULL; + struct nl_cb *cb; + int err; + + err = rtnl_link_build_get_request (ifindex, NULL, &msg); + if (err < 0) + return err; + + err = nl_send_auto (sk, msg); + nlmsg_free (msg); + if (err < 0) + return err; + + cb = nl_cb_clone (nl_socket_get_cb (sk)); + if (cb == NULL) + return -NLE_NOMEM; + nl_cb_set (cb, NL_CB_VALID, NL_CB_CUSTOM, info_data_parser, &data); + + err = nl_recvmsgs (sk, cb); + nl_cb_put (cb); + if (err < 0) + return err; + + nl_wait_for_ack (sk); + return 0; +} + +/******************************************************************/ + +static gboolean +ethtool_get (const char *name, gpointer edata) +{ + struct ifreq ifr; + int fd; + + memset (&ifr, 0, sizeof (ifr)); + strncpy (ifr.ifr_name, name, IFNAMSIZ); + ifr.ifr_data = edata; + + fd = socket (PF_INET, SOCK_DGRAM, 0); + if (fd < 0) { + error ("ethtool: Could not open socket."); + return FALSE; + } + + if (ioctl (fd, SIOCETHTOOL, &ifr) < 0) { + debug ("ethtool: Request failed: %s", strerror (errno)); + close (fd); + return FALSE; + } + + close (fd); + return TRUE; +} + +static int +ethtool_get_stringset_index (const char *ifname, int stringset_id, const char *string) +{ + auto_g_free struct ethtool_sset_info *info = NULL; + auto_g_free struct ethtool_gstrings *strings = NULL; + guint32 len, i; + + info = g_malloc0 (sizeof (*info) + sizeof (guint32)); + info->cmd = ETHTOOL_GSSET_INFO; + info->reserved = 0; + info->sset_mask = 1ULL << stringset_id; + + if (!ethtool_get (ifname, info)) + return -1; + if (!info->sset_mask) + return -1; + + len = info->data[0]; + + strings = g_malloc0 (sizeof (*strings) + len * ETH_GSTRING_LEN); + strings->cmd = ETHTOOL_GSTRINGS; + strings->string_set = stringset_id; + strings->len = len; + if (!ethtool_get (ifname, strings)) + return -1; + + for (i = 0; i < len; i++) { + if (!strcmp ((char *) &strings->data[i * ETH_GSTRING_LEN], string)) + return i; + } + + return -1; +} + +/******************************************************************/ + +static void +_check_support_kernel_extended_ifa_flags_init (NMLinuxPlatformPrivate *priv, struct nl_msg *msg) +{ + struct nlmsghdr *msg_hdr = nlmsg_hdr (msg); + + g_return_if_fail (priv->support_kernel_extended_ifa_flags == 0); + g_return_if_fail (msg_hdr->nlmsg_type == RTM_NEWADDR); + + /* the extended address flags are only set for AF_INET6 */ + if (((struct ifaddrmsg *) nlmsg_data (msg_hdr))->ifa_family != AF_INET6) + return; + + /* see if the nl_msg contains the IFA_FLAGS attribute. If it does, + * we assume, that the kernel supports extended flags, IFA_F_MANAGETEMPADDR + * and IFA_F_NOPREFIXROUTE (they were added together). + **/ + priv->support_kernel_extended_ifa_flags = + nlmsg_find_attr (msg_hdr, sizeof (struct ifaddrmsg), 8 /* IFA_FLAGS */) + ? 1 : -1; +} + +static gboolean +check_support_kernel_extended_ifa_flags (NMPlatform *platform) +{ + NMLinuxPlatformPrivate *priv; + + g_return_val_if_fail (NM_IS_LINUX_PLATFORM (platform), FALSE); + + priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); + + if (priv->support_kernel_extended_ifa_flags == 0) { + nm_log_warn (LOGD_PLATFORM, "Unable to detect kernel support for extended IFA_FLAGS. Assume no kernel support."); + priv->support_kernel_extended_ifa_flags = -1; + } + + return priv->support_kernel_extended_ifa_flags > 0; +} + + +/* Object type specific utilities */ + +static const char * +type_to_string (NMLinkType type) +{ + /* Note that this only has to support virtual types */ + switch (type) { + case NM_LINK_TYPE_DUMMY: + return "dummy"; + case NM_LINK_TYPE_GRE: + return "gre"; + case NM_LINK_TYPE_GRETAP: + return "gretap"; + case NM_LINK_TYPE_IFB: + return "ifb"; + case NM_LINK_TYPE_MACVLAN: + return "macvlan"; + case NM_LINK_TYPE_MACVTAP: + return "macvtap"; + case NM_LINK_TYPE_TAP: + return "tap"; + case NM_LINK_TYPE_TUN: + return "tun"; + case NM_LINK_TYPE_VETH: + return "veth"; + case NM_LINK_TYPE_VLAN: + return "vlan"; + case NM_LINK_TYPE_VXLAN: + return "vxlan"; + case NM_LINK_TYPE_BRIDGE: + return "bridge"; + case NM_LINK_TYPE_BOND: + return "bond"; + case NM_LINK_TYPE_TEAM: + return "team"; + default: + g_warning ("Wrong type: %d", type); + return NULL; + } +} + +#define return_type(t, name) \ + G_STMT_START { \ + if (out_name) \ + *out_name = name; \ + return t; \ + } G_STMT_END + +static NMLinkType +link_type_from_udev (NMPlatform *platform, int ifindex, const char *ifname, int arptype, const char **out_name) +{ + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); + GUdevDevice *udev_device; + const char *prop, *sysfs_path; + + g_assert (ifname); + + udev_device = g_hash_table_lookup (priv->udev_devices, GINT_TO_POINTER (ifindex)); + if (!udev_device) + return_type (NM_LINK_TYPE_UNKNOWN, "unknown"); + + if ( g_udev_device_get_property (udev_device, "ID_NM_OLPC_MESH") + || g_udev_device_get_sysfs_attr (udev_device, "anycast_mask")) + return_type (NM_LINK_TYPE_OLPC_MESH, "olpc-mesh"); + + prop = g_udev_device_get_property (udev_device, "DEVTYPE"); + sysfs_path = g_udev_device_get_sysfs_path (udev_device); + if (g_strcmp0 (prop, "wlan") == 0 || wifi_utils_is_wifi (ifname, sysfs_path)) + return_type (NM_LINK_TYPE_WIFI, "wifi"); + else if (g_strcmp0 (prop, "wwan") == 0) + return_type (NM_LINK_TYPE_WWAN_ETHERNET, "wwan"); + else if (g_strcmp0 (prop, "wimax") == 0) + return_type (NM_LINK_TYPE_WIMAX, "wimax"); + + if (arptype == ARPHRD_ETHER) + return_type (NM_LINK_TYPE_ETHERNET, "ethernet"); + + return_type (NM_LINK_TYPE_UNKNOWN, "unknown"); +} + +static gboolean +link_is_software (struct rtnl_link *rtnllink) +{ + const char *type; + + /* FIXME: replace somehow with NMLinkType or nm_platform_is_software(), but + * solve the infinite callstack problems that getting the type of a TUN/TAP + * device causes. + */ + + if ( rtnl_link_get_arptype (rtnllink) == ARPHRD_INFINIBAND + && strchr (rtnl_link_get_name (rtnllink), '.')) + return TRUE; + + type = rtnl_link_get_type (rtnllink); + if (type == NULL) + return FALSE; + + if (!strcmp (type, "dummy") || + !strcmp (type, "gre") || + !strcmp (type, "gretap") || + !strcmp (type, "macvlan") || + !strcmp (type, "macvtap") || + !strcmp (type, "tun") || + !strcmp (type, "veth") || + !strcmp (type, "vlan") || + !strcmp (type, "vxlan") || + !strcmp (type, "bridge") || + !strcmp (type, "bond") || + !strcmp (type, "team")) + return TRUE; + + return FALSE; +} + +static const char * +ethtool_get_driver (const char *ifname) +{ + struct ethtool_drvinfo drvinfo = { 0 }; + + g_return_val_if_fail (ifname != NULL, NULL); + + drvinfo.cmd = ETHTOOL_GDRVINFO; + if (!ethtool_get (ifname, &drvinfo)) + return NULL; + + if (!*drvinfo.driver) + return NULL; + + return g_intern_string (drvinfo.driver); +} + +static gboolean +link_is_announceable (NMPlatform *platform, struct rtnl_link *rtnllink) +{ + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); + + /* Software devices are always visible outside the platform */ + if (link_is_software (rtnllink)) + return TRUE; + + /* Hardware devices must be found by udev so rules get run and tags set */ + if (g_hash_table_lookup (priv->udev_devices, + GINT_TO_POINTER (rtnl_link_get_ifindex (rtnllink)))) + return TRUE; + + return FALSE; +} + +static NMLinkType +link_extract_type (NMPlatform *platform, struct rtnl_link *rtnllink, const char **out_name) +{ + const char *type; + + if (!rtnllink) + return_type (NM_LINK_TYPE_NONE, NULL); + + type = rtnl_link_get_type (rtnllink); + + if (!type) { + int arptype = rtnl_link_get_arptype (rtnllink); + const char *driver; + const char *ifname; + + if (arptype == ARPHRD_LOOPBACK) + return_type (NM_LINK_TYPE_LOOPBACK, "loopback"); + else if (arptype == ARPHRD_INFINIBAND) + return_type (NM_LINK_TYPE_INFINIBAND, "infiniband"); + + ifname = rtnl_link_get_name (rtnllink); + if (!ifname) + return_type (NM_LINK_TYPE_UNKNOWN, type); + + if (arptype == 256) { + /* Some s390 CTC-type devices report 256 for the encapsulation type + * for some reason, but we need to call them Ethernet. FIXME: use + * something other than interface name to detect CTC here. + */ + if (g_str_has_prefix (ifname, "ctc")) + return_type (NM_LINK_TYPE_ETHERNET, "ethernet"); + } + + driver = ethtool_get_driver (ifname); + if (!g_strcmp0 (driver, "openvswitch")) + return_type (NM_LINK_TYPE_OPENVSWITCH, "openvswitch"); + + return link_type_from_udev (platform, + rtnl_link_get_ifindex (rtnllink), + ifname, + arptype, + out_name); + } else if (!strcmp (type, "dummy")) + return_type (NM_LINK_TYPE_DUMMY, "dummy"); + else if (!strcmp (type, "gre")) + return_type (NM_LINK_TYPE_GRE, "gre"); + else if (!strcmp (type, "gretap")) + return_type (NM_LINK_TYPE_GRETAP, "gretap"); + else if (!strcmp (type, "ifb")) + return_type (NM_LINK_TYPE_IFB, "ifb"); + else if (!strcmp (type, "macvlan")) + return_type (NM_LINK_TYPE_MACVLAN, "macvlan"); + else if (!strcmp (type, "macvtap")) + return_type (NM_LINK_TYPE_MACVTAP, "macvtap"); + else if (!strcmp (type, "tun")) { + NMPlatformTunProperties props; + guint flags; + + if (nm_platform_tun_get_properties (rtnl_link_get_ifindex (rtnllink), &props)) { + if (!g_strcmp0 (props.mode, "tap")) + return_type (NM_LINK_TYPE_TAP, "tap"); + if (!g_strcmp0 (props.mode, "tun")) + return_type (NM_LINK_TYPE_TUN, "tun"); + } + flags = rtnl_link_get_flags (rtnllink); + + nm_log_dbg (LOGD_PLATFORM, "Failed to read tun properties for interface %d (link flags: %X)", + rtnl_link_get_ifindex (rtnllink), flags); + + /* try guessing the type using the link flags instead... */ + if (flags & IFF_POINTOPOINT) + return_type (NM_LINK_TYPE_TUN, "tun"); + return_type (NM_LINK_TYPE_TAP, "tap"); + } else if (!strcmp (type, "veth")) + return_type (NM_LINK_TYPE_VETH, "veth"); + else if (!strcmp (type, "vlan")) + return_type (NM_LINK_TYPE_VLAN, "vlan"); + else if (!strcmp (type, "vxlan")) + return_type (NM_LINK_TYPE_VXLAN, "vxlan"); + else if (!strcmp (type, "bridge")) + return_type (NM_LINK_TYPE_BRIDGE, "bridge"); + else if (!strcmp (type, "bond")) + return_type (NM_LINK_TYPE_BOND, "bond"); + else if (!strcmp (type, "team")) + return_type (NM_LINK_TYPE_TEAM, "team"); + + return_type (NM_LINK_TYPE_UNKNOWN, type); +} + +static const char * +udev_get_driver (NMPlatform *platform, GUdevDevice *device, int ifindex) +{ + GUdevDevice *parent = NULL, *grandparent = NULL; + const char *driver, *subsys; + + driver = g_udev_device_get_driver (device); + if (driver) + return driver; + + /* Try the parent */ + parent = g_udev_device_get_parent (device); + if (parent) { + driver = g_udev_device_get_driver (parent); + if (!driver) { + /* Try the grandparent if it's an ibmebus device or if the + * subsys is NULL which usually indicates some sort of + * platform device like a 'gadget' net interface. + */ + subsys = g_udev_device_get_subsystem (parent); + if ( (g_strcmp0 (subsys, "ibmebus") == 0) + || (subsys == NULL)) { + grandparent = g_udev_device_get_parent (parent); + if (grandparent) { + driver = g_udev_device_get_driver (grandparent); + } + } + } + } + + /* Intern the string so we don't have to worry about memory + * management in NMPlatformLink. + */ + if (driver) + driver = g_intern_string (driver); + + g_clear_object (&parent); + g_clear_object (&grandparent); + + return driver; +} + +static gboolean +init_link (NMPlatform *platform, NMPlatformLink *info, struct rtnl_link *rtnllink) +{ + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); + GUdevDevice *udev_device; + const char *name; + + g_return_val_if_fail (rtnllink, FALSE); + + name = rtnl_link_get_name (rtnllink); + memset (info, 0, sizeof (*info)); + + info->ifindex = rtnl_link_get_ifindex (rtnllink); + if (name) + g_strlcpy (info->name, name, sizeof (info->name)); + else + info->name[0] = '\0'; + info->type = link_extract_type (platform, rtnllink, &info->type_name); + info->up = !!(rtnl_link_get_flags (rtnllink) & IFF_UP); + info->connected = !!(rtnl_link_get_flags (rtnllink) & IFF_LOWER_UP); + info->arp = !(rtnl_link_get_flags (rtnllink) & IFF_NOARP); + info->master = rtnl_link_get_master (rtnllink); + info->parent = rtnl_link_get_link (rtnllink); + info->mtu = rtnl_link_get_mtu (rtnllink); + + udev_device = g_hash_table_lookup (priv->udev_devices, GINT_TO_POINTER (info->ifindex)); + if (udev_device) { + info->driver = udev_get_driver (platform, udev_device, info->ifindex); + if (!info->driver) + info->driver = rtnl_link_get_type (rtnllink); + if (!info->driver) + info->driver = ethtool_get_driver (info->name); + if (!info->driver) + info->driver = "unknown"; + info->udi = g_udev_device_get_sysfs_path (udev_device); + } + + return TRUE; +} + +/* Hack: Empty bridges and bonds have IFF_LOWER_UP flag and therefore they break + * the carrier detection. This hack makes nm-platform think they don't have the + * IFF_LOWER_UP flag. This seems to also apply to bonds (specifically) with all + * slaves down. + * + * Note: This is still a bit racy but when NetworkManager asks for enslaving a slave, + * nm-platform will do that synchronously and will immediately ask for both master + * and slave information after the enslaving request. After the synchronous call, the + * master carrier is already updated with the slave carrier in mind. + * + * https://bugzilla.redhat.com/show_bug.cgi?id=910348 + */ +static void +hack_empty_master_iff_lower_up (NMPlatform *platform, struct nl_object *object) +{ + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); + struct rtnl_link *rtnllink; + int ifindex; + struct nl_object *slave; + const char *type; + + if (!object) + return; + if (strcmp (nl_object_get_type (object), "route/link")) + return; + + rtnllink = (struct rtnl_link *) object; + + ifindex = rtnl_link_get_ifindex (rtnllink); + + type = rtnl_link_get_type (rtnllink); + if (!type || (strcmp (type, "bridge") != 0 && strcmp (type, "bond") != 0)) + return; + + for (slave = nl_cache_get_first (priv->link_cache); slave; slave = nl_cache_get_next (slave)) { + struct rtnl_link *rtnlslave = (struct rtnl_link *) slave; + if (rtnl_link_get_master (rtnlslave) == ifindex + && rtnl_link_get_flags (rtnlslave) & IFF_LOWER_UP) + return; + } + + rtnl_link_unset_flags (rtnllink, IFF_LOWER_UP); +} + +static guint32 +_get_remaining_time (guint32 start_timestamp, guint32 end_timestamp) +{ + /* Return the remaining time between @start_timestamp until @end_timestamp. + * + * If @end_timestamp is NM_PLATFORM_LIFETIME_PERMANENT, it returns + * NM_PLATFORM_LIFETIME_PERMANENT. If @start_timestamp already passed + * @end_timestamp it returns 0. Beware, NMPlatformIPAddress treats a @lifetime + * of 0 as permanent. + */ + if (end_timestamp == NM_PLATFORM_LIFETIME_PERMANENT) + return NM_PLATFORM_LIFETIME_PERMANENT; + if (start_timestamp >= end_timestamp) + return 0; + return end_timestamp - start_timestamp; +} + +/* _timestamp_nl_to_ms: + * @timestamp_nl: a timestamp from ifa_cacheinfo. + * @monotonic_ms: *now* in CLOCK_MONOTONIC. Needed to estimate the current + * uptime and how often timestamp_nl wrapped. + * + * Convert the timestamp from ifa_cacheinfo to CLOCK_MONOTONIC milliseconds. + * The ifa_cacheinfo fields tstamp and cstamp contains timestamps that counts + * with in 1/100th of a second of clock_gettime(CLOCK_MONOTONIC). However, + * the uint32 counter wraps every 497 days of uptime, so we have to compensate + * for that. */ +static gint64 +_timestamp_nl_to_ms (guint32 timestamp_nl, gint64 monotonic_ms) +{ + const gint64 WRAP_INTERVAL = (((gint64) G_MAXUINT32) + 1) * (1000 / 100); + gint64 timestamp_nl_ms; + + /* convert timestamp from 1/100th of a second to msec. */ + timestamp_nl_ms = ((gint64) timestamp_nl) * (1000 / 100); + + /* timestamp wraps every 497 days. Try to compensate for that.*/ + if (timestamp_nl_ms > monotonic_ms) { + /* timestamp_nl_ms is in the future. Truncate it to *now* */ + timestamp_nl_ms = monotonic_ms; + } else if (monotonic_ms >= WRAP_INTERVAL) { + timestamp_nl_ms += (monotonic_ms / WRAP_INTERVAL) * WRAP_INTERVAL; + if (timestamp_nl_ms > monotonic_ms) + timestamp_nl_ms -= WRAP_INTERVAL; + } + + return timestamp_nl_ms; +} + +static guint32 +_rtnl_addr_last_update_time_to_nm (const struct rtnl_addr *rtnladdr) +{ + guint32 last_update_time = rtnl_addr_get_last_update_time ((struct rtnl_addr *) rtnladdr); + struct timespec tp; + gint64 now_nl, now_nm, result; + + /* timestamp is unset. Default to 1. */ + if (!last_update_time) + return 1; + + /* do all the calculations in milliseconds scale */ + + clock_gettime (CLOCK_MONOTONIC, &tp); + now_nm = nm_utils_get_monotonic_timestamp_ms (); + now_nl = (((gint64) tp.tv_sec) * ((gint64) 1000)) + + (tp.tv_nsec / (NM_UTILS_NS_PER_SECOND/1000)); + + result = now_nm - (now_nl - _timestamp_nl_to_ms (last_update_time, now_nl)); + + /* converting the last_update_time into nm_utils_get_monotonic_timestamp_ms() scale is + * a good guess but fails in the following situations: + * + * - If the address existed before start of the process, the timestamp in nm scale would + * be negative or zero. In this case we default to 1. + * - during hibernation, the CLOCK_MONOTONIC/last_update_time drifts from + * nm_utils_get_monotonic_timestamp_ms() scale. + */ + if (result <= 1000) + return 1; + + if (result > now_nm) + return now_nm / 1000; + + return result / 1000; +} + +static void +_init_ip_address_lifetime (NMPlatformIPAddress *address, const struct rtnl_addr *rtnladdr) +{ + guint32 a_valid = rtnl_addr_get_valid_lifetime ((struct rtnl_addr *) rtnladdr); + guint32 a_preferred = rtnl_addr_get_preferred_lifetime ((struct rtnl_addr *) rtnladdr); + + /* the meaning of the valid and preferred lifetimes is different from the + * original meaning. See _rtnl_addr_hack_lifetimes_rel_to_abs(). + * Beware: this function expects hacked rtnl_addr objects. + */ + + if (a_valid == NM_PLATFORM_LIFETIME_PERMANENT && + a_preferred == NM_PLATFORM_LIFETIME_PERMANENT) { + address->timestamp = 0; + address->lifetime = NM_PLATFORM_LIFETIME_PERMANENT; + address->preferred = NM_PLATFORM_LIFETIME_PERMANENT; + return; + } + + /* The valies are hacked and absolute expiry times. They must + * be positive and preferred<=valid. */ + g_assert (a_preferred <= a_valid && + a_valid > 0 && + a_preferred > 0); + + if (a_valid <= 1) { + /* Since we want to have positive @timestamp and @valid != 0, + * we must handle this case special. */ + address->timestamp = 1; + address->lifetime = 1; /* Extend the lifetime by one second */ + address->preferred = 0; /* no longer preferred. */ + return; + } + + /* _rtnl_addr_last_update_time_to_nm() might be wrong, so don't rely on + * timestamp to have any meaning beyond anchoring the relative durations + * @lifetime and @preferred. + */ + address->timestamp = _rtnl_addr_last_update_time_to_nm (rtnladdr); + + /* We would expect @timestamp to be less then @a_valid. Just to be sure, + * fix it up. */ + address->timestamp = MIN (address->timestamp, a_valid - 1); + address->lifetime = _get_remaining_time (address->timestamp, a_valid); + address->preferred = _get_remaining_time (address->timestamp, a_preferred); +} + +static gboolean +init_ip4_address (NMPlatformIP4Address *address, struct rtnl_addr *rtnladdr) +{ + struct nl_addr *nladdr = rtnl_addr_get_local (rtnladdr); + struct nl_addr *nlpeer = rtnl_addr_get_peer (rtnladdr); + const char *label; + + g_return_val_if_fail (nladdr, FALSE); + + memset (address, 0, sizeof (*address)); + + address->source = NM_PLATFORM_SOURCE_KERNEL; + address->ifindex = rtnl_addr_get_ifindex (rtnladdr); + address->plen = rtnl_addr_get_prefixlen (rtnladdr); + _init_ip_address_lifetime ((NMPlatformIPAddress *) address, rtnladdr); + if (!nladdr || nl_addr_get_len (nladdr) != sizeof (address->address)) { + g_return_val_if_reached (FALSE); + return FALSE; + } + memcpy (&address->address, nl_addr_get_binary_addr (nladdr), sizeof (address->address)); + if (nlpeer) { + if (nl_addr_get_len (nlpeer) != sizeof (address->peer_address)) { + g_return_val_if_reached (FALSE); + return FALSE; + } + memcpy (&address->peer_address, nl_addr_get_binary_addr (nlpeer), sizeof (address->peer_address)); + } + label = rtnl_addr_get_label (rtnladdr); + /* Check for ':'; we're only interested in labels used as interface aliases */ + if (label && strchr (label, ':')) + g_strlcpy (address->label, label, sizeof (address->label)); + + return TRUE; +} + +static gboolean +init_ip6_address (NMPlatformIP6Address *address, struct rtnl_addr *rtnladdr) +{ + struct nl_addr *nladdr = rtnl_addr_get_local (rtnladdr); + struct nl_addr *nlpeer = rtnl_addr_get_peer (rtnladdr); + + memset (address, 0, sizeof (*address)); + + address->source = NM_PLATFORM_SOURCE_KERNEL; + address->ifindex = rtnl_addr_get_ifindex (rtnladdr); + address->plen = rtnl_addr_get_prefixlen (rtnladdr); + _init_ip_address_lifetime ((NMPlatformIPAddress *) address, rtnladdr); + address->flags = rtnl_addr_get_flags (rtnladdr); + if (!nladdr || nl_addr_get_len (nladdr) != sizeof (address->address)) { + g_return_val_if_reached (FALSE); + return FALSE; + } + memcpy (&address->address, nl_addr_get_binary_addr (nladdr), sizeof (address->address)); + if (nlpeer) { + if (nl_addr_get_len (nlpeer) != sizeof (address->peer_address)) { + g_return_val_if_reached (FALSE); + return FALSE; + } + memcpy (&address->peer_address, nl_addr_get_binary_addr (nlpeer), sizeof (address->peer_address)); + } + + return TRUE; +} + +static guint +source_to_rtprot (NMPlatformSource source) +{ + switch (source) { + case NM_PLATFORM_SOURCE_UNKNOWN: + return RTPROT_UNSPEC; + case NM_PLATFORM_SOURCE_KERNEL: + return RTPROT_KERNEL; + case NM_PLATFORM_SOURCE_DHCP: + return RTPROT_DHCP; + case NM_PLATFORM_SOURCE_RDISC: + return RTPROT_RA; + + default: + return RTPROT_STATIC; + } +} + +static NMPlatformSource +rtprot_to_source (guint rtprot) +{ + switch (rtprot) { + case RTPROT_UNSPEC: + return NM_PLATFORM_SOURCE_UNKNOWN; + case RTPROT_REDIRECT: + case RTPROT_KERNEL: + return NM_PLATFORM_SOURCE_KERNEL; + case RTPROT_RA: + return NM_PLATFORM_SOURCE_RDISC; + case RTPROT_DHCP: + return NM_PLATFORM_SOURCE_DHCP; + + default: + return NM_PLATFORM_SOURCE_USER; + } +} + +static gboolean +init_ip4_route (NMPlatformIP4Route *route, struct rtnl_route *rtnlroute) +{ + struct nl_addr *dst, *gw; + struct rtnl_nexthop *nexthop; + + memset (route, 0, sizeof (*route)); + + /* Multi-hop routes not supported. */ + if (rtnl_route_get_nnexthops (rtnlroute) != 1) + return FALSE; + + nexthop = rtnl_route_nexthop_n (rtnlroute, 0); + dst = rtnl_route_get_dst (rtnlroute); + gw = rtnl_route_nh_get_gateway (nexthop); + + route->ifindex = rtnl_route_nh_get_ifindex (nexthop); + route->plen = nl_addr_get_prefixlen (dst); + /* Workaround on previous workaround for libnl default route prefixlen bug. */ + if (nl_addr_get_len (dst)) { + if (nl_addr_get_len (dst) != sizeof (route->network)) { + g_return_val_if_reached (FALSE); + return FALSE; + } + memcpy (&route->network, nl_addr_get_binary_addr (dst), sizeof (route->network)); + } + if (gw) { + if (nl_addr_get_len (gw) != sizeof (route->network)) { + g_return_val_if_reached (FALSE); + return FALSE; + } + memcpy (&route->gateway, nl_addr_get_binary_addr (gw), sizeof (route->gateway)); + } + route->metric = rtnl_route_get_priority (rtnlroute); + rtnl_route_get_metric (rtnlroute, RTAX_ADVMSS, &route->mss); + route->source = rtprot_to_source (rtnl_route_get_protocol (rtnlroute)); + + return TRUE; +} + +static gboolean +init_ip6_route (NMPlatformIP6Route *route, struct rtnl_route *rtnlroute) +{ + struct nl_addr *dst, *gw; + struct rtnl_nexthop *nexthop; + + memset (route, 0, sizeof (*route)); + + /* Multi-hop routes not supported. */ + if (rtnl_route_get_nnexthops (rtnlroute) != 1) + return FALSE; + + nexthop = rtnl_route_nexthop_n (rtnlroute, 0); + dst = rtnl_route_get_dst (rtnlroute); + gw = rtnl_route_nh_get_gateway (nexthop); + + route->ifindex = rtnl_route_nh_get_ifindex (nexthop); + route->plen = nl_addr_get_prefixlen (dst); + /* Workaround on previous workaround for libnl default route prefixlen bug. */ + if (nl_addr_get_len (dst)) { + if (nl_addr_get_len (dst) != sizeof (route->network)) { + g_return_val_if_reached (FALSE); + return FALSE; + } + memcpy (&route->network, nl_addr_get_binary_addr (dst), sizeof (route->network)); + } + if (gw) { + if (nl_addr_get_len (gw) != sizeof (route->network)) { + g_return_val_if_reached (FALSE); + return FALSE; + } + memcpy (&route->gateway, nl_addr_get_binary_addr (gw), sizeof (route->gateway)); + } + route->metric = rtnl_route_get_priority (rtnlroute); + rtnl_route_get_metric (rtnlroute, RTAX_ADVMSS, &route->mss); + route->source = rtprot_to_source (rtnl_route_get_protocol (rtnlroute)); + + return TRUE; +} + +static char to_string_buffer[255]; + +#define SET_AND_RETURN_STRING_BUFFER(...) \ + G_STMT_START { \ + g_snprintf (to_string_buffer, sizeof (to_string_buffer), ## __VA_ARGS__); \ + g_return_val_if_reached (to_string_buffer); \ + return to_string_buffer; \ + } G_STMT_END + +static const char * +to_string_link (NMPlatform *platform, struct rtnl_link *obj) +{ + NMPlatformLink pl_obj; + + if (init_link (platform, &pl_obj, obj)) + return nm_platform_link_to_string (&pl_obj); + SET_AND_RETURN_STRING_BUFFER ("(invalid link %p)", obj); +} + +static const char * +to_string_ip4_address (struct rtnl_addr *obj) +{ + NMPlatformIP4Address pl_obj; + + if (init_ip4_address (&pl_obj, obj)) + return nm_platform_ip4_address_to_string (&pl_obj); + SET_AND_RETURN_STRING_BUFFER ("(invalid ip4 address %p)", obj); +} + +static const char * +to_string_ip6_address (struct rtnl_addr *obj) +{ + NMPlatformIP6Address pl_obj; + + if (init_ip6_address (&pl_obj, obj)) + return nm_platform_ip6_address_to_string (&pl_obj); + SET_AND_RETURN_STRING_BUFFER ("(invalid ip6 address %p)", obj); +} + +static const char * +to_string_ip4_route (struct rtnl_route *obj) +{ + NMPlatformIP4Route pl_obj; + + if (init_ip4_route (&pl_obj, obj)) + return nm_platform_ip4_route_to_string (&pl_obj); + SET_AND_RETURN_STRING_BUFFER ("(invalid ip4 route %p)", obj); +} + +static const char * +to_string_ip6_route (struct rtnl_route *obj) +{ + NMPlatformIP6Route pl_obj; + + if (init_ip6_route (&pl_obj, obj)) + return nm_platform_ip6_route_to_string (&pl_obj); + SET_AND_RETURN_STRING_BUFFER ("(invalid ip6 route %p)", obj); +} + +static const char * +to_string_object_with_type (NMPlatform *platform, struct nl_object *obj, ObjectType type) +{ + switch (type) { + case OBJECT_TYPE_LINK: + return to_string_link (platform, (struct rtnl_link *) obj); + case OBJECT_TYPE_IP4_ADDRESS: + return to_string_ip4_address ((struct rtnl_addr *) obj); + case OBJECT_TYPE_IP6_ADDRESS: + return to_string_ip6_address ((struct rtnl_addr *) obj); + case OBJECT_TYPE_IP4_ROUTE: + return to_string_ip4_route ((struct rtnl_route *) obj); + case OBJECT_TYPE_IP6_ROUTE: + return to_string_ip6_route ((struct rtnl_route *) obj); + default: + SET_AND_RETURN_STRING_BUFFER ("(unknown netlink object %p)", obj); + } +} + +static const char * +to_string_object (NMPlatform *platform, struct nl_object *obj) +{ + return to_string_object_with_type (platform, obj, object_type_from_nl_object (obj)); +} + +#undef SET_AND_RETURN_STRING_BUFFER + +/******************************************************************/ + +/* Object and cache manipulation */ + +static const char *signal_by_type_and_status[__OBJECT_TYPE_LAST] = { + [OBJECT_TYPE_LINK] = NM_PLATFORM_SIGNAL_LINK_CHANGED, + [OBJECT_TYPE_IP4_ADDRESS] = NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED, + [OBJECT_TYPE_IP6_ADDRESS] = NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED, + [OBJECT_TYPE_IP4_ROUTE] = NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, + [OBJECT_TYPE_IP6_ROUTE] = NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, +}; + +static struct nl_cache * +choose_cache_by_type (NMPlatform *platform, ObjectType object_type) +{ + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); + + switch (object_type) { + case OBJECT_TYPE_LINK: + return priv->link_cache; + case OBJECT_TYPE_IP4_ADDRESS: + case OBJECT_TYPE_IP6_ADDRESS: + return priv->address_cache; + case OBJECT_TYPE_IP4_ROUTE: + case OBJECT_TYPE_IP6_ROUTE: + return priv->route_cache; + default: + g_return_val_if_reached (NULL); + return NULL; + } +} + +static struct nl_cache * +choose_cache (NMPlatform *platform, struct nl_object *object) +{ + return choose_cache_by_type (platform, object_type_from_nl_object (object)); +} + +static gboolean +object_has_ifindex (struct nl_object *object, int ifindex) +{ + switch (object_type_from_nl_object (object)) { + case OBJECT_TYPE_IP4_ADDRESS: + case OBJECT_TYPE_IP6_ADDRESS: + return ifindex == rtnl_addr_get_ifindex ((struct rtnl_addr *) object); + case OBJECT_TYPE_IP4_ROUTE: + case OBJECT_TYPE_IP6_ROUTE: + { + struct rtnl_route *rtnlroute = (struct rtnl_route *) object; + struct rtnl_nexthop *nexthop; + + if (rtnl_route_get_nnexthops (rtnlroute) != 1) + return FALSE; + nexthop = rtnl_route_nexthop_n (rtnlroute, 0); + + return ifindex == rtnl_route_nh_get_ifindex (nexthop); + } + default: + g_assert_not_reached (); + } +} + +static gboolean refresh_object (NMPlatform *platform, struct nl_object *object, gboolean removed, NMPlatformReason reason); + +static void +check_cache_items (NMPlatform *platform, struct nl_cache *cache, int ifindex) +{ + auto_nl_cache struct nl_cache *cloned_cache = nl_cache_clone (cache); + struct nl_object *object; + GPtrArray *objects_to_refresh = g_ptr_array_new_with_free_func ((GDestroyNotify) nl_object_put); + guint i; + + for (object = nl_cache_get_first (cloned_cache); object; object = nl_cache_get_next (object)) { + if (object_has_ifindex (object, ifindex)) { + nl_object_get (object); + g_ptr_array_add (objects_to_refresh, object); + } + } + + for (i = 0; i < objects_to_refresh->len; i++) + refresh_object (platform, objects_to_refresh->pdata[i], TRUE, NM_PLATFORM_REASON_CACHE_CHECK); + + g_ptr_array_free (objects_to_refresh, TRUE); +} + +static void +announce_object (NMPlatform *platform, const struct nl_object *object, NMPlatformSignalChangeType change_type, NMPlatformReason reason) +{ + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); + ObjectType object_type = object_type_from_nl_object (object); + const char *sig = signal_by_type_and_status[object_type]; + + switch (object_type) { + case OBJECT_TYPE_LINK: + { + NMPlatformLink device; + struct rtnl_link *rtnl_link = (struct rtnl_link *) object; + + if (!init_link (platform, &device, rtnl_link)) + return; + + /* Skip hardware devices not yet discovered by udev. They will be + * announced by udev_device_added(). This doesn't apply to removed + * devices, as those come either from udev_device_removed(), + * event_notification() or link_delete() which block the announcment + * themselves when appropriate. + */ + switch (change_type) { + case NM_PLATFORM_SIGNAL_ADDED: + case NM_PLATFORM_SIGNAL_CHANGED: + if (!link_is_software (rtnl_link) && !device.driver) + return; + break; + default: + break; + } + + /* Link deletion or setting down is sometimes accompanied by address + * and/or route deletion. + * + * More precisely, kernel removes routes when interface goes !IFF_UP and + * removes both addresses and routes when interface is removed. + */ + switch (change_type) { + case NM_PLATFORM_SIGNAL_CHANGED: + if (!device.connected) + check_cache_items (platform, priv->route_cache, device.ifindex); + break; + case NM_PLATFORM_SIGNAL_REMOVED: + check_cache_items (platform, priv->address_cache, device.ifindex); + check_cache_items (platform, priv->route_cache, device.ifindex); + g_hash_table_remove (priv->wifi_data, GINT_TO_POINTER (device.ifindex)); + break; + default: + break; + } + + g_signal_emit_by_name (platform, sig, device.ifindex, &device, change_type, reason); + } + return; + case OBJECT_TYPE_IP4_ADDRESS: + { + NMPlatformIP4Address address; + + if (!init_ip4_address (&address, (struct rtnl_addr *) object)) + return; + + /* Address deletion is sometimes accompanied by route deletion. We need to + * check all routes belonging to the same interface. + */ + switch (change_type) { + case NM_PLATFORM_SIGNAL_REMOVED: + check_cache_items (platform, priv->route_cache, address.ifindex); + break; + default: + break; + } + + g_signal_emit_by_name (platform, sig, address.ifindex, &address, change_type, reason); + } + return; + case OBJECT_TYPE_IP6_ADDRESS: + { + NMPlatformIP6Address address; + + if (!init_ip6_address (&address, (struct rtnl_addr *) object)) + return; + g_signal_emit_by_name (platform, sig, address.ifindex, &address, change_type, reason); + } + return; + case OBJECT_TYPE_IP4_ROUTE: + { + NMPlatformIP4Route route; + + if (init_ip4_route (&route, (struct rtnl_route *) object)) + g_signal_emit_by_name (platform, sig, route.ifindex, &route, change_type, reason); + } + return; + case OBJECT_TYPE_IP6_ROUTE: + { + NMPlatformIP6Route route; + + if (init_ip6_route (&route, (struct rtnl_route *) object)) + g_signal_emit_by_name (platform, sig, route.ifindex, &route, change_type, reason); + } + return; + default: + g_return_if_reached (); + } +} + +static struct nl_object * build_rtnl_link (int ifindex, const char *name, NMLinkType type); + +static gboolean +refresh_object (NMPlatform *platform, struct nl_object *object, gboolean removed, NMPlatformReason reason) +{ + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); + auto_nl_object struct nl_object *cached_object = NULL; + auto_nl_object struct nl_object *kernel_object = NULL; + struct nl_cache *cache; + int nle; + + cache = choose_cache (platform, object); + cached_object = nm_nl_cache_search (cache, object); + kernel_object = get_kernel_object (priv->nlh, object); + + if (removed) { + if (kernel_object) + return TRUE; + + /* Only announce object if it was still in the cache. */ + if (cached_object) { + nl_cache_remove (cached_object); + + announce_object (platform, cached_object, NM_PLATFORM_SIGNAL_REMOVED, reason); + } + } else { + if (!kernel_object) + return FALSE; + + hack_empty_master_iff_lower_up (platform, kernel_object); + + if (cached_object) + nl_cache_remove (cached_object); + nle = nl_cache_add (cache, kernel_object); + if (nle) { + nm_log_dbg (LOGD_PLATFORM, "refresh_object(reason %d) failed during nl_cache_add with %d", reason, nle); + return FALSE; + } + + announce_object (platform, kernel_object, cached_object ? NM_PLATFORM_SIGNAL_CHANGED : NM_PLATFORM_SIGNAL_ADDED, reason); + + /* Refresh the master device (even on enslave/release) */ + if (object_type_from_nl_object (kernel_object) == OBJECT_TYPE_LINK) { + int kernel_master = rtnl_link_get_master ((struct rtnl_link *) kernel_object); + int cached_master = cached_object ? rtnl_link_get_master ((struct rtnl_link *) cached_object) : 0; + struct nl_object *master_object; + + if (kernel_master) { + master_object = build_rtnl_link (kernel_master, NULL, NM_LINK_TYPE_NONE); + refresh_object (platform, master_object, FALSE, NM_PLATFORM_REASON_INTERNAL); + nl_object_put (master_object); + } + if (cached_master && cached_master != kernel_master) { + master_object = build_rtnl_link (cached_master, NULL, NM_LINK_TYPE_NONE); + refresh_object (platform, master_object, FALSE, NM_PLATFORM_REASON_INTERNAL); + nl_object_put (master_object); + } + } + } + + return TRUE; +} + +/* Decreases the reference count if @obj for convenience */ +static gboolean +add_object (NMPlatform *platform, struct nl_object *obj) +{ + auto_nl_object struct nl_object *object = obj; + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); + int nle; + struct nl_dump_params dp = { + .dp_type = NL_DUMP_DETAILS, + .dp_fd = stderr, + }; + + g_return_val_if_fail (object, FALSE); + + nle = add_kernel_object (priv->nlh, object); + + /* NLE_EXIST is considered equivalent to success to avoid race conditions. You + * never know when something sends an identical object just before + * NetworkManager. + */ + switch (nle) { + case -NLE_SUCCESS: + case -NLE_EXIST: + break; + default: + error ("Netlink error adding %s: %s", to_string_object (platform, object), nl_geterror (nle)); + nl_object_dump (object, &dp); + return FALSE; + } + + return refresh_object (platform, object, FALSE, NM_PLATFORM_REASON_INTERNAL); +} + +/* Decreases the reference count if @obj for convenience */ +static gboolean +delete_object (NMPlatform *platform, struct nl_object *obj, gboolean do_refresh_object) +{ + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); + auto_nl_object struct nl_object *obj_cleanup = obj; + struct nl_object *object = obj; + int object_type; + int nle; + + object_type = object_type_from_nl_object (obj); + g_return_val_if_fail (object_type != OBJECT_TYPE_UNKNOWN, FALSE); + + switch (object_type) { + case OBJECT_TYPE_LINK: + nle = rtnl_link_delete (priv->nlh, (struct rtnl_link *) object); + break; + case OBJECT_TYPE_IP4_ADDRESS: + case OBJECT_TYPE_IP6_ADDRESS: + nle = rtnl_addr_delete (priv->nlh, (struct rtnl_addr *) object, 0); + break; + case OBJECT_TYPE_IP4_ROUTE: + case OBJECT_TYPE_IP6_ROUTE: + nle = rtnl_route_delete (priv->nlh, (struct rtnl_route *) object, 0); + break; + default: + g_assert_not_reached (); + } + + switch (nle) { + case -NLE_SUCCESS: + break; + case -NLE_OBJ_NOTFOUND: + debug("delete_object failed with \"%s\" (%d), meaning the object was already removed", + nl_geterror (nle), nle); + break; + case -NLE_FAILURE: + if (object_type == OBJECT_TYPE_IP6_ADDRESS) { + /* On RHEL7 kernel, deleting a non existing address fails with ENXIO (which libnl maps to NLE_FAILURE) */ + debug("delete_object for address failed with \"%s\" (%d), meaning the address was already removed", + nl_geterror (nle), nle); + break; + } + goto DEFAULT; + case -NLE_NOADDR: + if (object_type == OBJECT_TYPE_IP4_ADDRESS || object_type == OBJECT_TYPE_IP6_ADDRESS) { + debug("delete_object for address failed with \"%s\" (%d), meaning the address was already removed", + nl_geterror (nle), nle); + break; + } + goto DEFAULT; + DEFAULT: + default: + error ("Netlink error deleting %s: %s (%d)", to_string_object (platform, obj), nl_geterror (nle), nle); + return FALSE; + } + + if (do_refresh_object) + refresh_object (platform, object, TRUE, NM_PLATFORM_REASON_INTERNAL); + + return TRUE; +} + +static void +ref_object (struct nl_object *obj, void *data) +{ + struct nl_object **out = data; + + nl_object_get (obj); + *out = obj; +} + +static gboolean +_rtnl_addr_timestamps_equal_fuzzy (guint32 ts1, guint32 ts2) +{ + guint32 diff; + + if (ts1 == ts2) + return TRUE; + if (ts1 == NM_PLATFORM_LIFETIME_PERMANENT || + ts2 == NM_PLATFORM_LIFETIME_PERMANENT) + return FALSE; + + /** accept the timestamps as equal if they are within two seconds. */ + diff = ts1 > ts2 ? ts1 - ts2 : ts2 - ts1; + return diff <= 2; +} + +/* This function does all the magic to avoid race conditions caused + * by concurrent usage of synchronous commands and an asynchronous cache. This + * might be a nice future addition to libnl but it requires to do all operations + * through the cache manager. In this case, nm-linux-platform serves as the + * cache manager instead of the one provided by libnl. + */ +static int +event_notification (struct nl_msg *msg, gpointer user_data) +{ + NMPlatform *platform = NM_PLATFORM (user_data); + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); + struct nl_cache *cache; + auto_nl_object struct nl_object *object = NULL; + auto_nl_object struct nl_object *cached_object = NULL; + auto_nl_object struct nl_object *kernel_object = NULL; + int event; + int nle; + ObjectType type; + + event = nlmsg_hdr (msg)->nlmsg_type; + + if (priv->support_kernel_extended_ifa_flags == 0 && event == RTM_NEWADDR) { + /* if kernel support for extended ifa flags is still undecided, use the opportunity + * now and use @msg to decide it. This saves a blocking net link request. + **/ + _check_support_kernel_extended_ifa_flags_init (priv, msg); + } + + nl_msg_parse (msg, ref_object, &object); + g_return_val_if_fail (object, NL_OK); + + type = object_type_from_nl_object (object); + + if (nm_logging_enabled (LOGL_DEBUG, LOGD_PLATFORM)) { + if (type == OBJECT_TYPE_LINK) { + const char *name = rtnl_link_get_name ((struct rtnl_link *) object); + + debug ("netlink event (type %d) for link: %s (%d, family %d)", + event, name ? name : "(unknown)", + rtnl_link_get_ifindex ((struct rtnl_link *) object), + rtnl_link_get_family ((struct rtnl_link *) object)); + } else + debug ("netlink event (type %d)", event); + } + + cache = choose_cache_by_type (platform, type); + cached_object = nm_nl_cache_search (cache, object); + kernel_object = get_kernel_object (priv->nlh, object); + + hack_empty_master_iff_lower_up (platform, kernel_object); + + /* Removed object */ + switch (event) { + case RTM_DELLINK: + case RTM_DELADDR: + case RTM_DELROUTE: + /* Ignore inconsistent deletion + * + * Quick external deletion and addition can be occasionally + * seen as just a change. + */ + if (kernel_object) + return NL_OK; + /* Ignore internal deletion */ + if (!cached_object) + return NL_OK; + + nl_cache_remove (cached_object); + /* Don't announce removed interfaces that are not recognized by + * udev. They were either not yet discovered or they have been + * already removed and announced. + */ + if (event == RTM_DELLINK) { + if (!link_is_announceable (platform, (struct rtnl_link *) cached_object)) + return NL_OK; + } + announce_object (platform, cached_object, NM_PLATFORM_SIGNAL_REMOVED, NM_PLATFORM_REASON_EXTERNAL); + + return NL_OK; + case RTM_NEWLINK: + case RTM_NEWADDR: + case RTM_NEWROUTE: + /* Ignore inconsistent addition or change (kernel will send a good one) + * + * Quick sequence of RTM_NEWLINK notifications can be occasionally + * collapsed to just one addition or deletion, depending of whether we + * already have the object in cache. + */ + if (!kernel_object) + return NL_OK; + /* Handle external addition */ + if (!cached_object) { + nle = nl_cache_add (cache, kernel_object); + if (nle) { + error ("netlink cache error: %s", nl_geterror (nle)); + return NL_OK; + } + announce_object (platform, kernel_object, NM_PLATFORM_SIGNAL_ADDED, NM_PLATFORM_REASON_EXTERNAL); + return NL_OK; + } + /* Ignore non-change + * + * This also catches notifications for internal addition or change, unless + * another action occured very soon after it. + */ + if (!nl_object_diff (kernel_object, cached_object)) { + if (type == OBJECT_TYPE_IP4_ADDRESS || type == OBJECT_TYPE_IP6_ADDRESS) { + struct rtnl_addr *c = (struct rtnl_addr *) cached_object; + struct rtnl_addr *k = (struct rtnl_addr *) kernel_object; + + /* libnl nl_object_diff() ignores differences in timestamp. Let's care about + * them (if they are large enough). + * + * Note that these valid and preferred timestamps are absolute, after + * _rtnl_addr_hack_lifetimes_rel_to_abs(). */ + if ( _rtnl_addr_timestamps_equal_fuzzy (rtnl_addr_get_preferred_lifetime (c), + rtnl_addr_get_preferred_lifetime (k)) + && _rtnl_addr_timestamps_equal_fuzzy (rtnl_addr_get_valid_lifetime (c), + rtnl_addr_get_valid_lifetime (k))) + return NL_OK; + } else + return NL_OK; + } + /* Handle external change */ + nl_cache_remove (cached_object); + nle = nl_cache_add (cache, kernel_object); + if (nle) { + error ("netlink cache error: %s", nl_geterror (nle)); + return NL_OK; + } + announce_object (platform, kernel_object, NM_PLATFORM_SIGNAL_CHANGED, NM_PLATFORM_REASON_EXTERNAL); + + return NL_OK; + default: + error ("Unknown netlink event: %d", event); + return NL_OK; + } +} + +/******************************************************************/ + +static void +_log_dbg_sysctl_set_impl (const char *path, const char *value) +{ + GError *error = NULL; + char *contents, *contents_escaped; + char *value_escaped = g_strescape (value, NULL); + + if (!g_file_get_contents (path, &contents, NULL, &error)) { + debug ("sysctl: setting '%s' to '%s' (current value cannot be read: %s)", path, value_escaped, error->message); + g_clear_error (&error); + } else { + g_strstrip (contents); + contents_escaped = g_strescape (contents, NULL); + if (strcmp (contents, value) == 0) + debug ("sysctl: setting '%s' to '%s' (current value is identical)", path, value_escaped); + else + debug ("sysctl: setting '%s' to '%s' (current value is '%s')", path, value_escaped, contents_escaped); + g_free (contents); + g_free (contents_escaped); + } + g_free (value_escaped); +} + +#define _log_dbg_sysctl_set(path, value) \ + G_STMT_START { \ + if (nm_logging_enabled (LOGL_DEBUG, LOGD_PLATFORM)) { \ + _log_dbg_sysctl_set_impl (path, value); \ + } \ + } G_STMT_END + +static gboolean +sysctl_set (NMPlatform *platform, const char *path, const char *value) +{ + int fd, len, nwrote, tries; + char *actual; + + g_return_val_if_fail (path != NULL, FALSE); + g_return_val_if_fail (value != NULL, FALSE); + + /* Don't write outside known locations */ + g_assert (g_str_has_prefix (path, "/proc/sys/") + || g_str_has_prefix (path, "/sys/")); + /* Don't write to suspicious locations */ + g_assert (!strstr (path, "/../")); + + fd = open (path, O_WRONLY | O_TRUNC); + if (fd == -1) { + if (errno == ENOENT) { + debug ("sysctl: failed to open '%s': (%d) %s", + path, errno, strerror (errno)); + } else { + error ("sysctl: failed to open '%s': (%d) %s", + path, errno, strerror (errno)); + } + return FALSE; + } + + _log_dbg_sysctl_set (path, value); + + /* Most sysfs and sysctl options don't care about a trailing LF, while some + * (like infiniband) do. So always add the LF. Also, neither sysfs nor + * sysctl support partial writes so the LF must be added to the string we're + * about to write. + */ + actual = g_strdup_printf ("%s\n", value); + + /* Try to write the entire value three times if a partial write occurs */ + len = strlen (actual); + for (tries = 0, nwrote = 0; tries < 3 && nwrote != len; tries++) { + nwrote = write (fd, actual, len); + if (nwrote == -1) { + if (errno == EINTR) { + debug ("sysctl: interrupted, will try again"); + continue; + } + break; + } + } + if (nwrote == -1 && errno != EEXIST) { + error ("sysctl: failed to set '%s' to '%s': (%d) %s", + path, value, errno, strerror (errno)); + } else if (nwrote < len) { + error ("sysctl: failed to set '%s' to '%s' after three attempts", + path, value); + } + + g_free (actual); + close (fd); + return (nwrote == len); +} + +static GHashTable *sysctl_get_prev_values; + +static void +_log_dbg_sysctl_get_impl (const char *path, const char *contents) +{ + const char *prev_value = NULL; + + if (!sysctl_get_prev_values) + sysctl_get_prev_values = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); + else + prev_value = g_hash_table_lookup (sysctl_get_prev_values, path); + + if (prev_value) { + if (strcmp (prev_value, contents) != 0) { + char *contents_escaped = g_strescape (contents, NULL); + char *prev_value_escaped = g_strescape (prev_value, NULL); + + debug ("sysctl: reading '%s': '%s' (changed from '%s' on last read)", path, contents_escaped, prev_value_escaped); + g_free (contents_escaped); + g_free (prev_value_escaped); + g_hash_table_insert (sysctl_get_prev_values, g_strdup (path), g_strdup (contents)); + } + } else { + char *contents_escaped = g_strescape (contents, NULL); + + debug ("sysctl: reading '%s': '%s'", path, contents_escaped); + g_free (contents_escaped); + g_hash_table_insert (sysctl_get_prev_values, g_strdup (path), g_strdup (contents)); + } +} + +#define _log_dbg_sysctl_get(path, contents) \ + G_STMT_START { \ + if (nm_logging_enabled (LOGL_DEBUG, LOGD_PLATFORM)) { \ + _log_dbg_sysctl_get_impl (path, contents); \ + } else if (sysctl_get_prev_values) { \ + g_hash_table_destroy (sysctl_get_prev_values); \ + sysctl_get_prev_values = NULL; \ + } \ + } G_STMT_END + +static char * +sysctl_get (NMPlatform *platform, const char *path) +{ + GError *error = NULL; + char *contents; + + /* Don't write outside known locations */ + g_assert (g_str_has_prefix (path, "/proc/sys/") + || g_str_has_prefix (path, "/sys/")); + /* Don't write to suspicious locations */ + g_assert (!strstr (path, "/../")); + + if (!g_file_get_contents (path, &contents, NULL, &error)) { + /* We assume FAILED means EOPNOTSUP */ + if ( g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT) + || g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_FAILED)) + debug ("error reading %s: %s", path, error->message); + else + error ("error reading %s: %s", path, error->message); + g_clear_error (&error); + return NULL; + } + + g_strstrip (contents); + + _log_dbg_sysctl_get (path, contents); + + return contents; +} + +/******************************************************************/ + +static GArray * +link_get_all (NMPlatform *platform) +{ + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); + GArray *links = g_array_sized_new (FALSE, FALSE, sizeof (NMPlatformLink), nl_cache_nitems (priv->link_cache)); + NMPlatformLink device; + struct nl_object *object; + + for (object = nl_cache_get_first (priv->link_cache); object; object = nl_cache_get_next (object)) { + struct rtnl_link *rtnl_link = (struct rtnl_link *) object; + + if (link_is_announceable (platform, rtnl_link)) { + if (init_link (platform, &device, rtnl_link)) + g_array_append_val (links, device); + } + } + + return links; +} + +static gboolean +_nm_platform_link_get (NMPlatform *platform, int ifindex, NMPlatformLink *link) +{ + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); + auto_nl_object struct rtnl_link *rtnllink = NULL; + + rtnllink = rtnl_link_get (priv->link_cache, ifindex); + if (rtnllink) { + if (link_is_announceable (platform, rtnllink)) { + if (init_link (platform, link, rtnllink)) + return TRUE; + } + } + return FALSE; +} + +static struct nl_object * +build_rtnl_link (int ifindex, const char *name, NMLinkType type) +{ + struct rtnl_link *rtnllink; + int nle; + + rtnllink = _nm_rtnl_link_alloc (ifindex, name); + if (type) { + nle = rtnl_link_set_type (rtnllink, type_to_string (type)); + g_assert (!nle); + } + return (struct nl_object *) rtnllink; +} + +static gboolean +link_add (NMPlatform *platform, const char *name, NMLinkType type, const void *address, size_t address_len) +{ + int r; + struct nl_object *link; + + if (type == NM_LINK_TYPE_BOND) { + /* When the kernel loads the bond module, either via explicit modprobe + * or automatically in response to creating a bond master, it will also + * create a 'bond0' interface. Since the bond we're about to create may + * or may not be named 'bond0' prevent potential confusion about a bond + * that the user didn't want by telling the bonding module not to create + * bond0 automatically. + */ + if (!g_file_test ("/sys/class/net/bonding_masters", G_FILE_TEST_EXISTS)) + /* Ignore return value to shut up the compiler */ + r = system ("modprobe bonding max_bonds=0"); + } + + debug ("link: add link '%s' of type '%s' (%d)", + name, type_to_string (type), (int) type); + + link = build_rtnl_link (0, name, type); + + g_assert ( (address != NULL) ^ (address_len == 0) ); + if (address) { + auto_nl_addr struct nl_addr *nladdr = _nm_nl_addr_build (AF_LLC, address, address_len); + + rtnl_link_set_addr ((struct rtnl_link *) link, nladdr); + } + return add_object (platform, link); +} + +static struct rtnl_link * +link_get (NMPlatform *platform, int ifindex) +{ + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); + struct rtnl_link *rtnllink = rtnl_link_get (priv->link_cache, ifindex); + + if (!rtnllink) { + platform->error = NM_PLATFORM_ERROR_NOT_FOUND; + return NULL; + } + + /* physical interfaces must be found by udev before they can be used */ + if (!link_is_announceable (platform, rtnllink)) { + platform->error = NM_PLATFORM_ERROR_NOT_FOUND; + rtnl_link_put (rtnllink); + return NULL; + } + + return rtnllink; +} + +static gboolean +link_change (NMPlatform *platform, int ifindex, struct rtnl_link *change) +{ + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); + auto_nl_object struct rtnl_link *rtnllink = link_get (platform, ifindex); + int nle; + + if (!rtnllink) + return FALSE; + g_return_val_if_fail (rtnl_link_get_ifindex (change) > 0, FALSE); + + nle = rtnl_link_change (priv->nlh, rtnllink, change, 0); + + /* NLE_EXIST is considered equivalent to success to avoid race conditions. You + * never know when something sends an identical object just before + * NetworkManager. + * + * When netlink returns NLE_OBJ_NOTFOUND, it usually means it failed to find + * firmware for the device, especially on nm_platform_link_set_up (). + * This is basically the same check as in the original code and could + * potentially be improved. + */ + switch (nle) { + case -NLE_SUCCESS: + case -NLE_EXIST: + break; + case -NLE_OBJ_NOTFOUND: + error ("Firmware not found for changing link %s; Netlink error: %s)", to_string_link (platform, change), nl_geterror (nle)); + platform->error = NM_PLATFORM_ERROR_NO_FIRMWARE; + return FALSE; + default: + error ("Netlink error changing link %s: %s", to_string_link (platform, change), nl_geterror (nle)); + return FALSE; + } + + return refresh_object (platform, (struct nl_object *) rtnllink, FALSE, NM_PLATFORM_REASON_INTERNAL); +} + +static gboolean +link_delete (NMPlatform *platform, int ifindex) +{ + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); + struct rtnl_link *rtnllink = rtnl_link_get (priv->link_cache, ifindex); + + if (!rtnllink) { + platform->error = NM_PLATFORM_ERROR_NOT_FOUND; + return FALSE; + } + + return delete_object (platform, build_rtnl_link (ifindex, NULL, NM_LINK_TYPE_NONE), TRUE); +} + +static int +link_get_ifindex (NMPlatform *platform, const char *ifname) +{ + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); + + return rtnl_link_name2i (priv->link_cache, ifname); +} + +static const char * +link_get_name (NMPlatform *platform, int ifindex) +{ + auto_nl_object struct rtnl_link *rtnllink = link_get (platform, ifindex); + + return rtnllink ? rtnl_link_get_name (rtnllink) : NULL; +} + +static NMLinkType +link_get_type (NMPlatform *platform, int ifindex) +{ + auto_nl_object struct rtnl_link *rtnllink = link_get (platform, ifindex); + + return link_extract_type (platform, rtnllink, NULL); +} + +static const char * +link_get_type_name (NMPlatform *platform, int ifindex) +{ + auto_nl_object struct rtnl_link *rtnllink = link_get (platform, ifindex); + const char *type; + + link_extract_type (platform, rtnllink, &type); + return type; +} + +static guint32 +link_get_flags (NMPlatform *platform, int ifindex) +{ + auto_nl_object struct rtnl_link *rtnllink = link_get (platform, ifindex); + + if (!rtnllink) + return IFF_NOARP; + + return rtnl_link_get_flags (rtnllink); +} + +static gboolean +link_refresh (NMPlatform *platform, int ifindex) +{ + auto_nl_object struct rtnl_link *rtnllink = _nm_rtnl_link_alloc (ifindex, NULL); + + return refresh_object (platform, (struct nl_object *) rtnllink, FALSE, NM_PLATFORM_REASON_EXTERNAL); +} + +static gboolean +link_is_up (NMPlatform *platform, int ifindex) +{ + return !!(link_get_flags (platform, ifindex) & IFF_UP); +} + +static gboolean +link_is_connected (NMPlatform *platform, int ifindex) +{ + return !!(link_get_flags (platform, ifindex) & IFF_LOWER_UP); +} + +static gboolean +link_uses_arp (NMPlatform *platform, int ifindex) +{ + return !(link_get_flags (platform, ifindex) & IFF_NOARP); +} + +static gboolean +link_change_flags (NMPlatform *platform, int ifindex, unsigned int flags, gboolean value) +{ + auto_nl_object struct rtnl_link *change = _nm_rtnl_link_alloc (ifindex, NULL); + + if (value) + rtnl_link_set_flags (change, flags); + else + rtnl_link_unset_flags (change, flags); + + if (nm_logging_enabled (LOGL_DEBUG, LOGD_PLATFORM)) { + char buf[512]; + + rtnl_link_flags2str (flags, buf, sizeof (buf)); + debug ("link: change %d: flags %s '%s' (%d)", ifindex, value ? "set" : "unset", buf, flags); + } + + return link_change (platform, ifindex, change); +} + +static gboolean +link_set_up (NMPlatform *platform, int ifindex) +{ + return link_change_flags (platform, ifindex, IFF_UP, TRUE); +} + +static gboolean +link_set_down (NMPlatform *platform, int ifindex) +{ + return link_change_flags (platform, ifindex, IFF_UP, FALSE); +} + +static gboolean +link_set_arp (NMPlatform *platform, int ifindex) +{ + return link_change_flags (platform, ifindex, IFF_NOARP, FALSE); +} + +static gboolean +link_set_noarp (NMPlatform *platform, int ifindex) +{ + return link_change_flags (platform, ifindex, IFF_NOARP, TRUE); +} + +static gboolean +supports_ethtool_carrier_detect (const char *ifname) +{ + struct ethtool_cmd edata = { .cmd = ETHTOOL_GLINK }; + + /* We ignore the result. If the ETHTOOL_GLINK call succeeded, then we + * assume the device supports carrier-detect, otherwise we assume it + * doesn't. + */ + return ethtool_get (ifname, &edata); +} + +static gboolean +supports_mii_carrier_detect (const char *ifname) +{ + int fd; + struct ifreq ifr; + struct mii_ioctl_data *mii; + gboolean supports_mii = FALSE; + + fd = socket (PF_INET, SOCK_DGRAM, 0); + if (fd < 0) { + nm_log_err (LOGD_PLATFORM, "couldn't open control socket."); + return FALSE; + } + + memset (&ifr, 0, sizeof (struct ifreq)); + strncpy (ifr.ifr_name, ifname, IFNAMSIZ); + + errno = 0; + if (ioctl (fd, SIOCGMIIPHY, &ifr) < 0) { + nm_log_dbg (LOGD_PLATFORM, "SIOCGMIIPHY failed: %d", errno); + goto out; + } + + /* If we can read the BMSR register, we assume that the card supports MII link detection */ + mii = (struct mii_ioctl_data *) &ifr.ifr_ifru; + mii->reg_num = MII_BMSR; + + if (ioctl (fd, SIOCGMIIREG, &ifr) == 0) { + nm_log_dbg (LOGD_PLATFORM, "SIOCGMIIREG result 0x%X", mii->val_out); + supports_mii = TRUE; + } else { + nm_log_dbg (LOGD_PLATFORM, "SIOCGMIIREG failed: %d", errno); + } + + out: + close (fd); + nm_log_dbg (LOGD_PLATFORM, "MII %s supported", supports_mii ? "is" : "not"); + return supports_mii; +} + +static gboolean +link_supports_carrier_detect (NMPlatform *platform, int ifindex) +{ + const char *name = nm_platform_link_get_name (ifindex); + + if (!name) + return FALSE; + + /* We use netlink for the actual carrier detection, but netlink can't tell + * us whether the device actually supports carrier detection in the first + * place. We assume any device that does implements one of these two APIs. + */ + return supports_ethtool_carrier_detect (name) || supports_mii_carrier_detect (name); +} + +static gboolean +link_supports_vlans (NMPlatform *platform, int ifindex) +{ + auto_nl_object struct rtnl_link *rtnllink = link_get (platform, ifindex); + const char *name = nm_platform_link_get_name (ifindex); + auto_g_free struct ethtool_gfeatures *features = NULL; + int idx, block, bit, size; + + /* Only ARPHRD_ETHER links can possibly support VLANs. */ + if (!rtnllink || rtnl_link_get_arptype (rtnllink) != ARPHRD_ETHER) + return FALSE; + + if (!name) + return FALSE; + + idx = ethtool_get_stringset_index (name, ETH_SS_FEATURES, "vlan-challenged"); + if (idx == -1) { + debug ("vlan-challenged ethtool feature does not exist?"); + return FALSE; + } + + block = idx / 32; + bit = idx % 32; + size = block + 1; + + features = g_malloc0 (sizeof (*features) + size * sizeof (struct ethtool_get_features_block)); + features->cmd = ETHTOOL_GFEATURES; + features->size = size; + + if (!ethtool_get (name, features)) + return FALSE; + + return !(features->features[block].active & (1 << bit)); +} + +static gboolean +link_set_address (NMPlatform *platform, int ifindex, gconstpointer address, size_t length) +{ + auto_nl_object struct rtnl_link *change = _nm_rtnl_link_alloc (ifindex, NULL); + auto_nl_addr struct nl_addr *nladdr = _nm_nl_addr_build (AF_LLC, address, length); + + rtnl_link_set_addr (change, nladdr); + + if (nm_logging_enabled (LOGL_DEBUG, LOGD_PLATFORM)) { + char *mac = nm_utils_hwaddr_ntoa_len (address, length); + + debug ("link: change %d: address %s (%lu bytes)", ifindex, mac, (unsigned long) length); + g_free (mac); + } + + return link_change (platform, ifindex, change); +} + +static gconstpointer +link_get_address (NMPlatform *platform, int ifindex, size_t *length) +{ + auto_nl_object struct rtnl_link *rtnllink = link_get (platform, ifindex); + struct nl_addr *nladdr; + + nladdr = rtnllink ? rtnl_link_get_addr (rtnllink) : NULL; + + if (length) + *length = nladdr ? nl_addr_get_len (nladdr) : 0; + + return nladdr ? nl_addr_get_binary_addr (nladdr) : NULL; +} + +static gboolean +link_set_mtu (NMPlatform *platform, int ifindex, guint32 mtu) +{ + auto_nl_object struct rtnl_link *change = _nm_rtnl_link_alloc (ifindex, NULL); + + rtnl_link_set_mtu (change, mtu); + debug ("link: change %d: mtu %lu", ifindex, (unsigned long)mtu); + + return link_change (platform, ifindex, change); +} + +static guint32 +link_get_mtu (NMPlatform *platform, int ifindex) +{ + auto_nl_object struct rtnl_link *rtnllink = link_get (platform, ifindex); + + return rtnllink ? rtnl_link_get_mtu (rtnllink) : 0; +} + +static char * +link_get_physical_port_id (NMPlatform *platform, int ifindex) +{ + const char *ifname; + char *path, *id; + + ifname = nm_platform_link_get_name (ifindex); + if (!ifname) + return NULL; + + ifname = ASSERT_VALID_PATH_COMPONENT (ifname); + + path = g_strdup_printf ("/sys/class/net/%s/phys_port_id", ifname); + id = sysctl_get (platform, path); + g_free (path); + + return id; +} + +static int +vlan_add (NMPlatform *platform, const char *name, int parent, int vlan_id, guint32 vlan_flags) +{ + struct nl_object *object = build_rtnl_link (0, name, NM_LINK_TYPE_VLAN); + struct rtnl_link *rtnllink = (struct rtnl_link *) object; + unsigned int kernel_flags; + + kernel_flags = 0; + if (vlan_flags & NM_VLAN_FLAG_REORDER_HEADERS) + kernel_flags |= VLAN_FLAG_REORDER_HDR; + if (vlan_flags & NM_VLAN_FLAG_GVRP) + kernel_flags |= VLAN_FLAG_GVRP; + if (vlan_flags & NM_VLAN_FLAG_LOOSE_BINDING) + kernel_flags |= VLAN_FLAG_LOOSE_BINDING; + + rtnl_link_set_link (rtnllink, parent); + rtnl_link_vlan_set_id (rtnllink, vlan_id); + rtnl_link_vlan_set_flags (rtnllink, kernel_flags); + + debug ("link: add vlan '%s', parent %d, vlan id %d, flags %X (native: %X)", + name, parent, vlan_id, (unsigned int) vlan_flags, kernel_flags); + + return add_object (platform, object); +} + +static gboolean +vlan_get_info (NMPlatform *platform, int ifindex, int *parent, int *vlan_id) +{ + auto_nl_object struct rtnl_link *rtnllink = link_get (platform, ifindex); + + if (parent) + *parent = rtnllink ? rtnl_link_get_link (rtnllink) : 0; + if (vlan_id) + *vlan_id = rtnllink ? rtnl_link_vlan_get_id (rtnllink) : 0; + + return !!rtnllink; +} + +static gboolean +vlan_set_ingress_map (NMPlatform *platform, int ifindex, int from, int to) +{ + /* We have to use link_get() because a "blank" rtnl_link won't have the + * right data structures to be able to call rtnl_link_vlan_set_ingress_map() + * on it. (Likewise below in vlan_set_egress_map().) + */ + auto_nl_object struct rtnl_link *change = link_get (platform, ifindex); + + if (!change) + return FALSE; + rtnl_link_vlan_set_ingress_map (change, from, to); + + debug ("link: change %d: vlan ingress map %d -> %d", ifindex, from, to); + + return link_change (platform, ifindex, change); +} + +static gboolean +vlan_set_egress_map (NMPlatform *platform, int ifindex, int from, int to) +{ + auto_nl_object struct rtnl_link *change = link_get (platform, ifindex); + + if (!change) + return FALSE; + rtnl_link_vlan_set_egress_map (change, from, to); + + debug ("link: change %d: vlan egress map %d -> %d", ifindex, from, to); + + return link_change (platform, ifindex, change); +} + +static gboolean +link_enslave (NMPlatform *platform, int master, int slave) +{ + auto_nl_object struct rtnl_link *change = _nm_rtnl_link_alloc (slave, NULL); + + rtnl_link_set_master (change, master); + debug ("link: change %d: enslave to master %d", slave, master); + + return link_change (platform, slave, change); +} + +static gboolean +link_release (NMPlatform *platform, int master, int slave) +{ + return link_enslave (platform, 0, slave); +} + +static int +link_get_master (NMPlatform *platform, int slave) +{ + auto_nl_object struct rtnl_link *rtnllink = link_get (platform, slave); + + return rtnllink ? rtnl_link_get_master (rtnllink) : 0; +} + +static char * +link_option_path (int master, const char *category, const char *option) +{ + const char *name = nm_platform_link_get_name (master); + + if (!name || !category || !option) + return NULL; + + return g_strdup_printf ("/sys/class/net/%s/%s/%s", + ASSERT_VALID_PATH_COMPONENT (name), + ASSERT_VALID_PATH_COMPONENT (category), + ASSERT_VALID_PATH_COMPONENT (option)); +} + +static gboolean +link_set_option (int master, const char *category, const char *option, const char *value) +{ + auto_g_free char *path = link_option_path (master, category, option); + + return path && nm_platform_sysctl_set (path, value); +} + +static char * +link_get_option (int master, const char *category, const char *option) +{ + auto_g_free char *path = link_option_path (master, category, option); + + return path ? nm_platform_sysctl_get (path) : NULL; +} + +static const char * +master_category (NMPlatform *platform, int master) +{ + switch (link_get_type (platform, master)) { + case NM_LINK_TYPE_BRIDGE: + return "bridge"; + case NM_LINK_TYPE_BOND: + return "bonding"; + default: + g_return_val_if_reached (NULL); + return NULL; + } +} + +static const char * +slave_category (NMPlatform *platform, int slave) +{ + int master = link_get_master (platform, slave); + + if (master <= 0) { + platform->error = NM_PLATFORM_ERROR_NOT_SLAVE; + return NULL; + } + + switch (link_get_type (platform, master)) { + case NM_LINK_TYPE_BRIDGE: + return "brport"; + default: + g_return_val_if_reached (NULL); + return NULL; + } +} + +static gboolean +master_set_option (NMPlatform *platform, int master, const char *option, const char *value) +{ + return link_set_option (master, master_category (platform, master), option, value); +} + +static char * +master_get_option (NMPlatform *platform, int master, const char *option) +{ + return link_get_option (master, master_category (platform, master), option); +} + +static gboolean +slave_set_option (NMPlatform *platform, int slave, const char *option, const char *value) +{ + return link_set_option (slave, slave_category (platform, slave), option, value); +} + +static char * +slave_get_option (NMPlatform *platform, int slave, const char *option) +{ + return link_get_option (slave, slave_category (platform, slave), option); +} + +static gboolean +infiniband_partition_add (NMPlatform *platform, int parent, int p_key) +{ + const char *parent_name; + char *path, *id; + gboolean success; + + parent_name = nm_platform_link_get_name (parent); + g_return_val_if_fail (parent_name != NULL, FALSE); + + path = g_strdup_printf ("/sys/class/net/%s/create_child", ASSERT_VALID_PATH_COMPONENT (parent_name)); + id = g_strdup_printf ("0x%04x", p_key); + success = nm_platform_sysctl_set (path, id); + g_free (id); + g_free (path); + + if (success) { + auto_g_free char *ifname = g_strdup_printf ("%s.%04x", parent_name, p_key); + auto_nl_object struct rtnl_link *rtnllink = _nm_rtnl_link_alloc (0, ifname); + + success = refresh_object (platform, (struct nl_object *) rtnllink, FALSE, NM_PLATFORM_REASON_INTERNAL); + } + + return success; +} + +static gboolean +veth_get_properties (NMPlatform *platform, int ifindex, NMPlatformVethProperties *props) +{ + const char *ifname; + auto_g_free struct ethtool_stats *stats = NULL; + int peer_ifindex_stat; + + ifname = nm_platform_link_get_name (ifindex); + if (!ifname) + return FALSE; + + peer_ifindex_stat = ethtool_get_stringset_index (ifname, ETH_SS_STATS, "peer_ifindex"); + if (peer_ifindex_stat == -1) { + debug ("%s: peer_ifindex ethtool stat does not exist?", ifname); + return FALSE; + } + + stats = g_malloc0 (sizeof (*stats) + (peer_ifindex_stat + 1) * sizeof (guint64)); + stats->cmd = ETHTOOL_GSTATS; + stats->n_stats = peer_ifindex_stat + 1; + if (!ethtool_get (ifname, stats)) + return FALSE; + + props->peer = stats->data[peer_ifindex_stat]; + return TRUE; +} + +static gboolean +tun_get_properties (NMPlatform *platform, int ifindex, NMPlatformTunProperties *props) +{ + const char *ifname; + char *path, *val; + gboolean success = TRUE; + + g_return_val_if_fail (props, FALSE); + + memset (props, 0, sizeof (*props)); + props->owner = -1; + props->group = -1; + + ifname = nm_platform_link_get_name (ifindex); + if (!ifname || !nm_utils_iface_valid_name (ifname)) + return FALSE; + ifname = ASSERT_VALID_PATH_COMPONENT (ifname); + + path = g_strdup_printf ("/sys/class/net/%s/owner", ifname); + val = nm_platform_sysctl_get (path); + g_free (path); + if (val) { + props->owner = nm_utils_ascii_str_to_int64 (val, 10, -1, G_MAXINT64, -1); + if (errno) + success = FALSE; + g_free (val); + } else + success = FALSE; + + path = g_strdup_printf ("/sys/class/net/%s/group", ifname); + val = nm_platform_sysctl_get (path); + g_free (path); + if (val) { + props->group = nm_utils_ascii_str_to_int64 (val, 10, -1, G_MAXINT64, -1); + if (errno) + success = FALSE; + g_free (val); + } else + success = FALSE; + + path = g_strdup_printf ("/sys/class/net/%s/tun_flags", ifname); + val = nm_platform_sysctl_get (path); + g_free (path); + if (val) { + gint64 flags; + + flags = nm_utils_ascii_str_to_int64 (val, 16, 0, G_MAXINT64, 0); + if (!errno) { +#ifndef IFF_MULTI_QUEUE + const int IFF_MULTI_QUEUE = 0x0100; +#endif + props->mode = ((flags & TUN_TYPE_MASK) == TUN_TUN_DEV) ? "tun" : "tap"; + props->no_pi = !!(flags & IFF_NO_PI); + props->vnet_hdr = !!(flags & IFF_VNET_HDR); + props->multi_queue = !!(flags & IFF_MULTI_QUEUE); + } else + success = FALSE; + g_free (val); + } else + success = FALSE; + + return success; +} + +static const struct nla_policy macvlan_info_policy[IFLA_MACVLAN_MAX + 1] = { + [IFLA_MACVLAN_MODE] = { .type = NLA_U32 }, +#ifdef MACVLAN_FLAG_NOPROMISC + [IFLA_MACVLAN_FLAGS] = { .type = NLA_U16 }, +#endif +}; + +static int +macvlan_info_data_parser (struct nlattr *info_data, gpointer parser_data) +{ + NMPlatformMacvlanProperties *props = parser_data; + struct nlattr *tb[IFLA_MACVLAN_MAX + 1]; + int err; + + err = nla_parse_nested (tb, IFLA_MACVLAN_MAX, info_data, + (struct nla_policy *) macvlan_info_policy); + if (err < 0) + return err; + + switch (nla_get_u32 (tb[IFLA_MACVLAN_MODE])) { + case MACVLAN_MODE_PRIVATE: + props->mode = "private"; + break; + case MACVLAN_MODE_VEPA: + props->mode = "vepa"; + break; + case MACVLAN_MODE_BRIDGE: + props->mode = "bridge"; + break; + case MACVLAN_MODE_PASSTHRU: + props->mode = "passthru"; + break; + default: + return -NLE_PARSE_ERR; + } + +#ifdef MACVLAN_FLAG_NOPROMISC + props->no_promisc = !!(nla_get_u16 (tb[IFLA_MACVLAN_FLAGS]) & MACVLAN_FLAG_NOPROMISC); +#else + props->no_promisc = FALSE; +#endif + + return 0; +} + +static gboolean +macvlan_get_properties (NMPlatform *platform, int ifindex, NMPlatformMacvlanProperties *props) +{ + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); + auto_nl_object struct rtnl_link *rtnllink = NULL; + int err; + + rtnllink = link_get (platform, ifindex); + if (!rtnllink) + return FALSE; + + props->parent_ifindex = rtnl_link_get_link (rtnllink); + + err = nm_rtnl_link_parse_info_data (priv->nlh, ifindex, + macvlan_info_data_parser, props); + if (err != 0) { + warning ("(%s) could not read properties: %s", + rtnl_link_get_name (rtnllink), nl_geterror (err)); + } + return (err == 0); +} + +/* The installed kernel headers might not have VXLAN stuff at all, or + * they might have the original properties, but not PORT, GROUP6, or LOCAL6. + * So until we depend on kernel >= 3.11, we just ignore the actual enum + * in if_link.h and define the values ourselves. + */ +#define IFLA_VXLAN_UNSPEC 0 +#define IFLA_VXLAN_ID 1 +#define IFLA_VXLAN_GROUP 2 +#define IFLA_VXLAN_LINK 3 +#define IFLA_VXLAN_LOCAL 4 +#define IFLA_VXLAN_TTL 5 +#define IFLA_VXLAN_TOS 6 +#define IFLA_VXLAN_LEARNING 7 +#define IFLA_VXLAN_AGEING 8 +#define IFLA_VXLAN_LIMIT 9 +#define IFLA_VXLAN_PORT_RANGE 10 +#define IFLA_VXLAN_PROXY 11 +#define IFLA_VXLAN_RSC 12 +#define IFLA_VXLAN_L2MISS 13 +#define IFLA_VXLAN_L3MISS 14 +#define IFLA_VXLAN_PORT 15 +#define IFLA_VXLAN_GROUP6 16 +#define IFLA_VXLAN_LOCAL6 17 +#undef IFLA_VXLAN_MAX +#define IFLA_VXLAN_MAX IFLA_VXLAN_LOCAL6 + +static const struct nla_policy vxlan_info_policy[IFLA_VXLAN_MAX + 1] = { + [IFLA_VXLAN_ID] = { .type = NLA_U32 }, + [IFLA_VXLAN_GROUP] = { .type = NLA_U32 }, + [IFLA_VXLAN_GROUP6] = { .type = NLA_UNSPEC, + .minlen = sizeof (struct in6_addr) }, + [IFLA_VXLAN_LINK] = { .type = NLA_U32 }, + [IFLA_VXLAN_LOCAL] = { .type = NLA_U32 }, + [IFLA_VXLAN_LOCAL6] = { .type = NLA_UNSPEC, + .minlen = sizeof (struct in6_addr) }, + [IFLA_VXLAN_TOS] = { .type = NLA_U8 }, + [IFLA_VXLAN_TTL] = { .type = NLA_U8 }, + [IFLA_VXLAN_LEARNING] = { .type = NLA_U8 }, + [IFLA_VXLAN_AGEING] = { .type = NLA_U32 }, + [IFLA_VXLAN_LIMIT] = { .type = NLA_U32 }, + [IFLA_VXLAN_PORT_RANGE] = { .type = NLA_UNSPEC, + .minlen = sizeof (struct ifla_vxlan_port_range) }, + [IFLA_VXLAN_PROXY] = { .type = NLA_U8 }, + [IFLA_VXLAN_RSC] = { .type = NLA_U8 }, + [IFLA_VXLAN_L2MISS] = { .type = NLA_U8 }, + [IFLA_VXLAN_L3MISS] = { .type = NLA_U8 }, + [IFLA_VXLAN_PORT] = { .type = NLA_U16 }, +}; + +static int +vxlan_info_data_parser (struct nlattr *info_data, gpointer parser_data) +{ + NMPlatformVxlanProperties *props = parser_data; + struct nlattr *tb[IFLA_VXLAN_MAX + 1]; + struct ifla_vxlan_port_range *range; + int err; + + err = nla_parse_nested (tb, IFLA_VXLAN_MAX, info_data, + (struct nla_policy *) vxlan_info_policy); + if (err < 0) + return err; + + memset (props, 0, sizeof (*props)); + + props->parent_ifindex = tb[IFLA_VXLAN_LINK] ? nla_get_u32 (tb[IFLA_VXLAN_LINK]) : 0; + props->id = nla_get_u32 (tb[IFLA_VXLAN_ID]); + if (tb[IFLA_VXLAN_GROUP]) + props->group = nla_get_u32 (tb[IFLA_VXLAN_GROUP]); + if (tb[IFLA_VXLAN_LOCAL]) + props->local = nla_get_u32 (tb[IFLA_VXLAN_LOCAL]); + if (tb[IFLA_VXLAN_GROUP6]) + memcpy (&props->group6, nla_data (tb[IFLA_VXLAN_GROUP6]), sizeof (props->group6)); + if (tb[IFLA_VXLAN_LOCAL6]) + memcpy (&props->local6, nla_data (tb[IFLA_VXLAN_LOCAL6]), sizeof (props->local6)); + + props->ageing = nla_get_u32 (tb[IFLA_VXLAN_AGEING]); + props->limit = nla_get_u32 (tb[IFLA_VXLAN_LIMIT]); + props->tos = nla_get_u8 (tb[IFLA_VXLAN_TOS]); + props->ttl = nla_get_u8 (tb[IFLA_VXLAN_TTL]); + + props->dst_port = nla_get_u16 (tb[IFLA_VXLAN_PORT]); + range = nla_data (tb[IFLA_VXLAN_PORT_RANGE]); + props->src_port_min = range->low; + props->src_port_max = range->high; + + props->learning = !!nla_get_u8 (tb[IFLA_VXLAN_LEARNING]); + props->proxy = !!nla_get_u8 (tb[IFLA_VXLAN_PROXY]); + props->rsc = !!nla_get_u8 (tb[IFLA_VXLAN_RSC]); + props->l2miss = !!nla_get_u8 (tb[IFLA_VXLAN_L2MISS]); + props->l3miss = !!nla_get_u8 (tb[IFLA_VXLAN_L3MISS]); + + return 0; +} + +static gboolean +vxlan_get_properties (NMPlatform *platform, int ifindex, NMPlatformVxlanProperties *props) +{ + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); + int err; + + err = nm_rtnl_link_parse_info_data (priv->nlh, ifindex, + vxlan_info_data_parser, props); + if (err != 0) { + warning ("(%s) could not read properties: %s", + link_get_name (platform, ifindex), nl_geterror (err)); + } + return (err == 0); +} + +static const struct nla_policy gre_info_policy[IFLA_GRE_MAX + 1] = { + [IFLA_GRE_LINK] = { .type = NLA_U32 }, + [IFLA_GRE_IFLAGS] = { .type = NLA_U16 }, + [IFLA_GRE_OFLAGS] = { .type = NLA_U16 }, + [IFLA_GRE_IKEY] = { .type = NLA_U32 }, + [IFLA_GRE_OKEY] = { .type = NLA_U32 }, + [IFLA_GRE_LOCAL] = { .type = NLA_U32 }, + [IFLA_GRE_REMOTE] = { .type = NLA_U32 }, + [IFLA_GRE_TTL] = { .type = NLA_U8 }, + [IFLA_GRE_TOS] = { .type = NLA_U8 }, + [IFLA_GRE_PMTUDISC] = { .type = NLA_U8 }, +}; + +static int +gre_info_data_parser (struct nlattr *info_data, gpointer parser_data) +{ + NMPlatformGreProperties *props = parser_data; + struct nlattr *tb[IFLA_GRE_MAX + 1]; + int err; + + err = nla_parse_nested (tb, IFLA_GRE_MAX, info_data, + (struct nla_policy *) gre_info_policy); + if (err < 0) + return err; + + props->parent_ifindex = tb[IFLA_GRE_LINK] ? nla_get_u32 (tb[IFLA_GRE_LINK]) : 0; + props->input_flags = nla_get_u16 (tb[IFLA_GRE_IFLAGS]); + props->output_flags = nla_get_u16 (tb[IFLA_GRE_OFLAGS]); + props->input_key = (props->input_flags & GRE_KEY) ? nla_get_u32 (tb[IFLA_GRE_IKEY]) : 0; + props->output_key = (props->output_flags & GRE_KEY) ? nla_get_u32 (tb[IFLA_GRE_OKEY]) : 0; + props->local = nla_get_u32 (tb[IFLA_GRE_LOCAL]); + props->remote = nla_get_u32 (tb[IFLA_GRE_REMOTE]); + props->tos = nla_get_u8 (tb[IFLA_GRE_TOS]); + props->ttl = nla_get_u8 (tb[IFLA_GRE_TTL]); + props->path_mtu_discovery = !!nla_get_u8 (tb[IFLA_GRE_PMTUDISC]); + + return 0; +} + +static gboolean +gre_get_properties (NMPlatform *platform, int ifindex, NMPlatformGreProperties *props) +{ + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); + int err; + + err = nm_rtnl_link_parse_info_data (priv->nlh, ifindex, + gre_info_data_parser, props); + if (err != 0) { + warning ("(%s) could not read properties: %s", + link_get_name (platform, ifindex), nl_geterror (err)); + } + return (err == 0); +} + +static WifiData * +wifi_get_wifi_data (NMPlatform *platform, int ifindex) +{ + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); + WifiData *wifi_data; + + wifi_data = g_hash_table_lookup (priv->wifi_data, GINT_TO_POINTER (ifindex)); + if (!wifi_data) { + NMLinkType type; + const char *ifname; + + type = link_get_type (platform, ifindex); + ifname = link_get_name (platform, ifindex); + + if (type == NM_LINK_TYPE_WIFI) + wifi_data = wifi_utils_init (ifname, ifindex, TRUE); + else if (type == NM_LINK_TYPE_OLPC_MESH) { + /* The kernel driver now uses nl80211, but we force use of WEXT because + * the cfg80211 interactions are not quite ready to support access to + * mesh control through nl80211 just yet. + */ +#if HAVE_WEXT + wifi_data = wifi_wext_init (ifname, ifindex, FALSE); +#endif + } + + if (wifi_data) + g_hash_table_insert (priv->wifi_data, GINT_TO_POINTER (ifindex), wifi_data); + } + + return wifi_data; +} + +static gboolean +wifi_get_capabilities (NMPlatform *platform, int ifindex, NMDeviceWifiCapabilities *caps) +{ + WifiData *wifi_data = wifi_get_wifi_data (platform, ifindex); + + if (!wifi_data) + return FALSE; + + if (caps) + *caps = wifi_utils_get_caps (wifi_data); + return TRUE; +} + +static gboolean +wifi_get_bssid (NMPlatform *platform, int ifindex, struct ether_addr *bssid) +{ + WifiData *wifi_data = wifi_get_wifi_data (platform, ifindex); + + if (!wifi_data) + return FALSE; + return wifi_utils_get_bssid (wifi_data, bssid); +} + +static GByteArray * +wifi_get_ssid (NMPlatform *platform, int ifindex) +{ + WifiData *wifi_data = wifi_get_wifi_data (platform, ifindex); + + if (!wifi_data) + return NULL; + return wifi_utils_get_ssid (wifi_data); +} + +static guint32 +wifi_get_frequency (NMPlatform *platform, int ifindex) +{ + WifiData *wifi_data = wifi_get_wifi_data (platform, ifindex); + + if (!wifi_data) + return 0; + return wifi_utils_get_freq (wifi_data); +} + +static gboolean +wifi_get_quality (NMPlatform *platform, int ifindex) +{ + WifiData *wifi_data = wifi_get_wifi_data (platform, ifindex); + + if (!wifi_data) + return FALSE; + return wifi_utils_get_qual (wifi_data); +} + +static guint32 +wifi_get_rate (NMPlatform *platform, int ifindex) +{ + WifiData *wifi_data = wifi_get_wifi_data (platform, ifindex); + + if (!wifi_data) + return FALSE; + return wifi_utils_get_rate (wifi_data); +} + +static NM80211Mode +wifi_get_mode (NMPlatform *platform, int ifindex) +{ + WifiData *wifi_data = wifi_get_wifi_data (platform, ifindex); + + if (!wifi_data) + return NM_802_11_MODE_UNKNOWN; + + return wifi_utils_get_mode (wifi_data); +} + +static void +wifi_set_mode (NMPlatform *platform, int ifindex, NM80211Mode mode) +{ + WifiData *wifi_data = wifi_get_wifi_data (platform, ifindex); + + if (wifi_data) + wifi_utils_set_mode (wifi_data, mode); +} + +static guint32 +wifi_find_frequency (NMPlatform *platform, int ifindex, const guint32 *freqs) +{ + WifiData *wifi_data = wifi_get_wifi_data (platform, ifindex); + + if (!wifi_data) + return 0; + + return wifi_utils_find_freq (wifi_data, freqs); +} + +static void +wifi_indicate_addressing_running (NMPlatform *platform, int ifindex, gboolean running) +{ + WifiData *wifi_data = wifi_get_wifi_data (platform, ifindex); + + if (wifi_data) + wifi_utils_indicate_addressing_running (wifi_data, running); +} + + +static guint32 +mesh_get_channel (NMPlatform *platform, int ifindex) +{ + WifiData *wifi_data = wifi_get_wifi_data (platform, ifindex); + + if (!wifi_data) + return 0; + + return wifi_utils_get_mesh_channel (wifi_data); +} + +static gboolean +mesh_set_channel (NMPlatform *platform, int ifindex, guint32 channel) +{ + WifiData *wifi_data = wifi_get_wifi_data (platform, ifindex); + + if (!wifi_data) + return FALSE; + + return wifi_utils_set_mesh_channel (wifi_data, channel); +} + +static gboolean +mesh_set_ssid (NMPlatform *platform, int ifindex, const GByteArray *ssid) +{ + WifiData *wifi_data = wifi_get_wifi_data (platform, ifindex); + + if (!wifi_data) + return FALSE; + + return wifi_utils_set_mesh_ssid (wifi_data, ssid); +} + +static gboolean +link_get_wake_on_lan (NMPlatform *platform, int ifindex) +{ + NMLinkType type = link_get_type (platform, ifindex); + + if (type == NM_LINK_TYPE_ETHERNET) { + struct ethtool_wolinfo wol; + + memset (&wol, 0, sizeof (wol)); + wol.cmd = ETHTOOL_GWOL; + if (!ethtool_get (link_get_name (platform, ifindex), &wol)) + return FALSE; + + return wol.wolopts != 0; + } else if (type == NM_LINK_TYPE_WIFI) { + WifiData *wifi_data = wifi_get_wifi_data (platform, ifindex); + + if (!wifi_data) + return FALSE; + + return wifi_utils_get_wowlan (wifi_data); + } else + return FALSE; +} + +/******************************************************************/ + +static gboolean +_address_match (struct rtnl_addr *addr, int family, int ifindex) +{ + g_return_val_if_fail (addr, FALSE); + + return rtnl_addr_get_family (addr) == family && + rtnl_addr_get_ifindex (addr) == ifindex; +} + +static GArray * +ip4_address_get_all (NMPlatform *platform, int ifindex) +{ + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); + GArray *addresses; + NMPlatformIP4Address address; + struct nl_object *object; + + addresses = g_array_new (FALSE, FALSE, sizeof (NMPlatformIP4Address)); + + for (object = nl_cache_get_first (priv->address_cache); object; object = nl_cache_get_next (object)) { + if (_address_match ((struct rtnl_addr *) object, AF_INET, ifindex)) { + if (init_ip4_address (&address, (struct rtnl_addr *) object)) + g_array_append_val (addresses, address); + } + } + + return addresses; +} + +static GArray * +ip6_address_get_all (NMPlatform *platform, int ifindex) +{ + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); + GArray *addresses; + NMPlatformIP6Address address; + struct nl_object *object; + + addresses = g_array_new (FALSE, FALSE, sizeof (NMPlatformIP6Address)); + + for (object = nl_cache_get_first (priv->address_cache); object; object = nl_cache_get_next (object)) { + if (_address_match ((struct rtnl_addr *) object, AF_INET6, ifindex)) { + if (init_ip6_address (&address, (struct rtnl_addr *) object)) + g_array_append_val (addresses, address); + } + } + + return addresses; +} + +#define IPV4LL_NETWORK (htonl (0xA9FE0000L)) +#define IPV4LL_NETMASK (htonl (0xFFFF0000L)) + +static gboolean +ip4_is_link_local (const struct in_addr *src) +{ + return (src->s_addr & IPV4LL_NETMASK) == IPV4LL_NETWORK; +} + +static struct nl_object * +build_rtnl_addr (int family, + int ifindex, + gconstpointer addr, + gconstpointer peer_addr, + int plen, + guint32 lifetime, + guint32 preferred, + guint flags, + const char *label) +{ + auto_nl_addr struct rtnl_addr *rtnladdr = _nm_rtnl_addr_alloc (ifindex); + struct rtnl_addr *rtnladdr_copy; + int addrlen = family == AF_INET ? sizeof (in_addr_t) : sizeof (struct in6_addr); + auto_nl_addr struct nl_addr *nladdr = _nm_nl_addr_build (family, addr, addrlen); + int nle; + + /* IP address */ + nle = rtnl_addr_set_local (rtnladdr, nladdr); + if (nle) { + error ("build_rtnl_addr(): rtnl_addr_set_local failed with %s (%d)", nl_geterror (nle), nle); + return NULL; + } + + /* Tighten scope (IPv4 only) */ + if (family == AF_INET && ip4_is_link_local (addr)) + rtnl_addr_set_scope (rtnladdr, rtnl_str2scope ("link")); + + /* IPv4 Broadcast address */ + if (family == AF_INET) { + in_addr_t bcast; + auto_nl_addr struct nl_addr *bcaddr = NULL; + + bcast = *((in_addr_t *) addr) | ~nm_utils_ip4_prefix_to_netmask (plen); + bcaddr = _nm_nl_addr_build (family, &bcast, addrlen); + g_assert (bcaddr); + rtnl_addr_set_broadcast (rtnladdr, bcaddr); + } + + /* Peer/point-to-point address */ + if (peer_addr) { + auto_nl_addr struct nl_addr *nlpeer = _nm_nl_addr_build (family, peer_addr, addrlen); + + nle = rtnl_addr_set_peer (rtnladdr, nlpeer); + if (nle && nle != -NLE_AF_NOSUPPORT) { + /* IPv6 doesn't support peer addresses yet */ + error ("build_rtnl_addr(): rtnl_addr_set_peer failed with %s (%d)", nl_geterror (nle), nle); + return NULL; + } + } + + rtnl_addr_set_prefixlen (rtnladdr, plen); + if (lifetime) { + /* note that here we set the relative timestamps (ticking from *now*). + * Contrary to the rtnl_addr objects from our cache, which have absolute + * timestamps (see _rtnl_addr_hack_lifetimes_rel_to_abs()). + * + * This is correct, because we only use build_rtnl_addr() for + * add_object(), delete_object() and cache search (ip_address_exists). */ + rtnl_addr_set_valid_lifetime (rtnladdr, lifetime); + rtnl_addr_set_preferred_lifetime (rtnladdr, preferred); + } + if (flags) { + if ((flags & ~0xFF) && !check_support_kernel_extended_ifa_flags (nm_platform_get ())) { + /* Older kernels don't accept unknown netlink attributes. + * + * With commit libnl commit 5206c050504f8676a24854519b9c351470fb7cc6, libnl will only set + * the extended address flags attribute IFA_FLAGS when necessary (> 8 bit). But it's up to + * us not to shove those extended flags on to older kernels. + * + * Just silently clear them. The kernel should ignore those unknown flags anyway. */ + flags &= 0xFF; + } + rtnl_addr_set_flags (rtnladdr, flags); + } + if (label && *label) + rtnl_addr_set_label (rtnladdr, label); + + rtnladdr_copy = rtnladdr; + rtnladdr = NULL; + return (struct nl_object *) rtnladdr_copy; +} + +static gboolean +ip4_address_add (NMPlatform *platform, + int ifindex, + in_addr_t addr, + in_addr_t peer_addr, + int plen, + guint32 lifetime, + guint32 preferred, + const char *label) +{ + return add_object (platform, build_rtnl_addr (AF_INET, ifindex, &addr, + peer_addr ? &peer_addr : NULL, + plen, lifetime, preferred, 0, + label)); +} + +static gboolean +ip6_address_add (NMPlatform *platform, + int ifindex, + struct in6_addr addr, + struct in6_addr peer_addr, + int plen, + guint32 lifetime, + guint32 preferred, + guint flags) +{ + return add_object (platform, build_rtnl_addr (AF_INET6, ifindex, &addr, + IN6_IS_ADDR_UNSPECIFIED (&peer_addr) ? NULL : &peer_addr, + plen, lifetime, preferred, flags, + NULL)); +} + +static gboolean +ip4_address_delete (NMPlatform *platform, int ifindex, in_addr_t addr, int plen) +{ + return delete_object (platform, build_rtnl_addr (AF_INET, ifindex, &addr, NULL, plen, 0, 0, 0, NULL), TRUE); +} + +static gboolean +ip6_address_delete (NMPlatform *platform, int ifindex, struct in6_addr addr, int plen) +{ + return delete_object (platform, build_rtnl_addr (AF_INET6, ifindex, &addr, NULL, plen, 0, 0, 0, NULL), TRUE); +} + +static gboolean +ip_address_exists (NMPlatform *platform, int family, int ifindex, gconstpointer addr, int plen) +{ + auto_nl_object struct nl_object *object = build_rtnl_addr (family, ifindex, addr, NULL, plen, 0, 0, 0, NULL); + auto_nl_object struct nl_object *cached_object = nl_cache_search (choose_cache (platform, object), object); + + return !!cached_object; +} + +static gboolean +ip4_address_exists (NMPlatform *platform, int ifindex, in_addr_t addr, int plen) +{ + return ip_address_exists (platform, AF_INET, ifindex, &addr, plen); +} + +static gboolean +ip6_address_exists (NMPlatform *platform, int ifindex, struct in6_addr addr, int plen) +{ + return ip_address_exists (platform, AF_INET6, ifindex, &addr, plen); +} + +/******************************************************************/ + +static gboolean +_route_match (struct rtnl_route *rtnlroute, int family, int ifindex) +{ + struct rtnl_nexthop *nexthop; + + g_return_val_if_fail (rtnlroute, FALSE); + + if (rtnl_route_get_type (rtnlroute) != RTN_UNICAST || + rtnl_route_get_table (rtnlroute) != RT_TABLE_MAIN || + rtnl_route_get_protocol (rtnlroute) == RTPROT_KERNEL || + rtnl_route_get_family (rtnlroute) != family || + rtnl_route_get_nnexthops (rtnlroute) != 1) + return FALSE; + + nexthop = rtnl_route_nexthop_n (rtnlroute, 0); + return rtnl_route_nh_get_ifindex (nexthop) == ifindex; +} + +static GArray * +ip4_route_get_all (NMPlatform *platform, int ifindex, gboolean include_default) +{ + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); + GArray *routes; + NMPlatformIP4Route route; + struct nl_object *object; + + routes = g_array_new (FALSE, FALSE, sizeof (NMPlatformIP4Route)); + + for (object = nl_cache_get_first (priv->route_cache); object; object = nl_cache_get_next (object)) { + if (_route_match ((struct rtnl_route *) object, AF_INET, ifindex)) { + if (init_ip4_route (&route, (struct rtnl_route *) object)) { + if (route.plen != 0 || include_default) + g_array_append_val (routes, route); + } + } + } + + return routes; +} + +static GArray * +ip6_route_get_all (NMPlatform *platform, int ifindex, gboolean include_default) +{ + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); + GArray *routes; + NMPlatformIP6Route route; + struct nl_object *object; + + routes = g_array_new (FALSE, FALSE, sizeof (NMPlatformIP6Route)); + + for (object = nl_cache_get_first (priv->route_cache); object; object = nl_cache_get_next (object)) { + if (_route_match ((struct rtnl_route *) object, AF_INET6, ifindex)) { + if (init_ip6_route (&route, (struct rtnl_route *) object)) { + if (route.plen != 0 || include_default) + g_array_append_val (routes, route); + } + } + } + + return routes; +} + +static void +clear_host_address (int family, const void *network, int plen, void *dst) +{ + g_return_if_fail (plen == (guint8)plen); + g_return_if_fail (network); + + switch (family) { + case AF_INET: + *((in_addr_t *) dst) = nm_utils_ip4_address_clear_host_address (*((in_addr_t *) network), plen); + break; + case AF_INET6: + nm_utils_ip6_address_clear_host_address ((struct in6_addr *) dst, (const struct in6_addr *) network, plen); + break; + default: + g_assert_not_reached (); + } +} + +static struct nl_object * +build_rtnl_route (int family, int ifindex, NMPlatformSource source, + gconstpointer network, int plen, gconstpointer gateway, + int metric, int mss) +{ + guint32 network_clean[4]; + struct rtnl_route *rtnlroute; + struct rtnl_nexthop *nexthop; + int addrlen = (family == AF_INET) ? sizeof (in_addr_t) : sizeof (struct in6_addr); + /* Workaround a libnl bug by using zero destination address length for default routes */ + auto_nl_addr struct nl_addr *dst = NULL; + auto_nl_addr struct nl_addr *gw = gateway ? _nm_nl_addr_build (family, gateway, addrlen) : NULL; + + /* There seem to be problems adding a route with non-zero host identifier. + * Adding IPv6 routes is simply ignored, without error message. + * In the IPv4 case, we got an error. Thus, we have to make sure, that + * the address is sane. */ + clear_host_address (family, network, plen, network_clean); + dst = _nm_nl_addr_build (family, network_clean, plen ? addrlen : 0); + nl_addr_set_prefixlen (dst, plen); + + rtnlroute = _nm_rtnl_route_alloc (); + rtnl_route_set_table (rtnlroute, RT_TABLE_MAIN); + rtnl_route_set_tos (rtnlroute, 0); + rtnl_route_set_dst (rtnlroute, dst); + rtnl_route_set_priority (rtnlroute, metric); + rtnl_route_set_family (rtnlroute, family); + rtnl_route_set_protocol (rtnlroute, source_to_rtprot (source)); + + nexthop = _nm_rtnl_route_nh_alloc (); + rtnl_route_nh_set_ifindex (nexthop, ifindex); + if (gw && !nl_addr_iszero (gw)) + rtnl_route_nh_set_gateway (nexthop, gw); + rtnl_route_add_nexthop (rtnlroute, nexthop); + + if (mss > 0) + rtnl_route_set_metric (rtnlroute, RTAX_ADVMSS, mss); + + return (struct nl_object *) rtnlroute; +} + +static gboolean +ip4_route_add (NMPlatform *platform, int ifindex, NMPlatformSource source, + in_addr_t network, int plen, in_addr_t gateway, + int metric, int mss) +{ + return add_object (platform, build_rtnl_route (AF_INET, ifindex, source, &network, plen, &gateway, metric, mss)); +} + +static gboolean +ip6_route_add (NMPlatform *platform, int ifindex, NMPlatformSource source, + struct in6_addr network, int plen, struct in6_addr gateway, + int metric, int mss) +{ + return add_object (platform, build_rtnl_route (AF_INET6, ifindex, source, &network, plen, &gateway, metric, mss)); +} + +static struct rtnl_route * +route_search_cache (struct nl_cache *cache, int family, int ifindex, const void *network, int plen, int metric) +{ + guint32 network_clean[4], dst_clean[4]; + struct nl_object *object; + + clear_host_address (family, network, plen, network_clean); + + for (object = nl_cache_get_first (cache); object; object = nl_cache_get_next (object)) { + struct nl_addr *dst; + struct rtnl_route *rtnlroute = (struct rtnl_route *) object; + + if (!_route_match (rtnlroute, family, ifindex)) + continue; + + if (metric && metric != rtnl_route_get_priority (rtnlroute)) + continue; + + dst = rtnl_route_get_dst (rtnlroute); + if ( !dst + || nl_addr_get_family (dst) != family + || nl_addr_get_prefixlen (dst) != plen) + continue; + + clear_host_address (family, nl_addr_get_binary_addr (dst), plen, dst_clean); + if (memcmp (dst_clean, network_clean, + family == AF_INET ? sizeof (guint32) : sizeof (struct in6_addr)) != 0) + continue; + + rtnl_route_get (rtnlroute); + return rtnlroute; + } + return NULL; +} + +static gboolean +refresh_route (NMPlatform *platform, int family, int ifindex, const void *network, int plen, int metric) +{ + struct nl_cache *cache; + auto_nl_object struct rtnl_route *cached_object = NULL; + + cache = choose_cache_by_type (platform, family == AF_INET ? OBJECT_TYPE_IP4_ROUTE : OBJECT_TYPE_IP6_ROUTE); + cached_object = route_search_cache (cache, family, ifindex, network, plen, metric); + + if (cached_object) + return refresh_object (platform, (struct nl_object *) cached_object, TRUE, NM_PLATFORM_REASON_INTERNAL); + return TRUE; +} + +static gboolean +ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, int plen, int metric) +{ + in_addr_t gateway = 0; + struct rtnl_route *cached_object; + struct nl_object *route = build_rtnl_route (AF_INET, ifindex, NM_PLATFORM_SOURCE_UNKNOWN, &network, plen, &gateway, metric, 0); + uint8_t scope = RT_SCOPE_NOWHERE; + struct nl_cache *cache; + + g_return_val_if_fail (route, FALSE); + + cache = choose_cache_by_type (platform, OBJECT_TYPE_IP4_ROUTE); + + /* when deleting an IPv4 route, several fields of the provided route must match. + * Lookup in the cache so that we hopefully get the right values. */ + cached_object = (struct rtnl_route *) nl_cache_search (cache, route); + if (!cached_object) + cached_object = route_search_cache (cache, AF_INET, ifindex, &network, plen, metric); + + if (!_nl_has_capability (1 /* NL_CAPABILITY_ROUTE_BUILD_MSG_SET_SCOPE */)) { + /* When searching for a matching IPv4 route to delete, the kernel + * searches for a matching scope, unless the RTM_DELROUTE message + * specifies RT_SCOPE_NOWHERE (see fib_table_delete()). + * + * However, if we set the scope of @rtnlroute to RT_SCOPE_NOWHERE (or + * leave it unset), rtnl_route_build_msg() will reset the scope to + * rtnl_route_guess_scope() -- which probably guesses wrong. + * + * As a workaround, we look at the cached route and use that scope. + * + * Newer versions of libnl, no longer reset the scope if explicitly set to RT_SCOPE_NOWHERE. + * So, this workaround is only needed unless we have NL_CAPABILITY_ROUTE_BUILD_MSG_SET_SCOPE. + **/ + + if (cached_object) + scope = rtnl_route_get_scope (cached_object); + + if (scope == RT_SCOPE_NOWHERE) { + /* If we would set the scope to RT_SCOPE_NOWHERE, libnl would guess the scope. + * But probably it will guess 'link' because we set the next hop of the route + * to zero (0.0.0.0). A better guess is 'global'. */ + scope = RT_SCOPE_UNIVERSE; + } + } + rtnl_route_set_scope ((struct rtnl_route *) route, scope); + + if (cached_object) + rtnl_route_set_tos ((struct rtnl_route *) route, rtnl_route_get_tos (cached_object)); + + /* The following fields are also relevant when comparing the route, but the default values + * are already as we want them: + * + * type: RTN_UNICAST (setting to zero would ignore the type, but we only want to delete RTN_UNICAST) + * pref_src: NULL + */ + + rtnl_route_put (cached_object); + return delete_object (platform, route, FALSE) && refresh_route (platform, AF_INET, ifindex, &network, plen, metric); +} + +static gboolean +ip6_route_delete (NMPlatform *platform, int ifindex, struct in6_addr network, int plen, int metric) +{ + struct in6_addr gateway = IN6ADDR_ANY_INIT; + + return delete_object (platform, build_rtnl_route (AF_INET6, ifindex, NM_PLATFORM_SOURCE_UNKNOWN ,&network, plen, &gateway, metric, 0), FALSE) && + refresh_route (platform, AF_INET6, ifindex, &network, plen, metric); +} + +static gboolean +ip_route_exists (NMPlatform *platform, int family, int ifindex, gpointer network, int plen, int metric) +{ + auto_nl_object struct nl_object *object = build_rtnl_route (family, ifindex, + NM_PLATFORM_SOURCE_UNKNOWN, + network, plen, NULL, metric, 0); + struct nl_cache *cache = choose_cache (platform, object); + auto_nl_object struct nl_object *cached_object = nl_cache_search (cache, object); + + if (!cached_object) + cached_object = (struct nl_object *) route_search_cache (cache, family, ifindex, network, plen, metric); + return !!cached_object; +} + +static gboolean +ip4_route_exists (NMPlatform *platform, int ifindex, in_addr_t network, int plen, int metric) +{ + return ip_route_exists (platform, AF_INET, ifindex, &network, plen, metric); +} + +static gboolean +ip6_route_exists (NMPlatform *platform, int ifindex, struct in6_addr network, int plen, int metric) +{ + return ip_route_exists (platform, AF_INET6, ifindex, &network, plen, metric); +} + +/******************************************************************/ + +#define EVENT_CONDITIONS ((GIOCondition) (G_IO_IN | G_IO_PRI)) +#define ERROR_CONDITIONS ((GIOCondition) (G_IO_ERR | G_IO_NVAL)) +#define DISCONNECT_CONDITIONS ((GIOCondition) (G_IO_HUP)) + +static int +verify_source (struct nl_msg *msg, gpointer user_data) +{ + struct ucred *creds = nlmsg_get_creds (msg); + + if (!creds || creds->pid || creds->uid || creds->gid) { + if (creds) + warning ("netlink: received non-kernel message (pid %d uid %d gid %d)", + creds->pid, creds->uid, creds->gid); + else + warning ("netlink: received message without credentials"); + return NL_STOP; + } + + return NL_OK; +} + +static gboolean +event_handler (GIOChannel *channel, + GIOCondition io_condition, + gpointer user_data) +{ + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (user_data); + int nle; + + nle = nl_recvmsgs_default (priv->nlh_event); + if (nle < 0) + switch (nle) { + case -NLE_DUMP_INTR: + /* this most likely happens due to our request (RTM_GETADDR, AF_INET6, NLM_F_DUMP) + * to detect support for support_kernel_extended_ifa_flags. This is not critical + * and can happen easily. */ + debug ("Uncritical failure to retrieve incoming events: %s (%d)", nl_geterror (nle), nle); + break; + default: + error ("Failed to retrieve incoming events: %s (%d)", nl_geterror (nle), nle); + break; + } + return TRUE; +} + +static struct nl_sock * +setup_socket (gboolean event, gpointer user_data) +{ + struct nl_sock *sock; + int nle; + + sock = nl_socket_alloc (); + g_return_val_if_fail (sock, NULL); + + /* Only ever accept messages from kernel */ + nle = nl_socket_modify_cb (sock, NL_CB_MSG_IN, NL_CB_CUSTOM, verify_source, user_data); + g_assert (!nle); + + /* Dispatch event messages (event socket only) */ + if (event) { + nl_socket_modify_cb (sock, NL_CB_VALID, NL_CB_CUSTOM, event_notification, user_data); + nl_socket_disable_seq_check (sock); + } + + nle = nl_connect (sock, NETLINK_ROUTE); + g_assert (!nle); + nle = nl_socket_set_passcred (sock, 1); + g_assert (!nle); + + return sock; +} + +/******************************************************************/ + +static void +udev_device_added (NMPlatform *platform, + GUdevDevice *udev_device) +{ + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); + auto_nl_object struct rtnl_link *rtnllink = NULL; + const char *ifname; + int ifindex; + gboolean was_announceable = FALSE; + + ifname = g_udev_device_get_name (udev_device); + if (!ifname) { + debug ("udev-add: failed to get device's interface"); + return; + } + + if (g_udev_device_get_property (udev_device, "IFINDEX")) + ifindex = g_udev_device_get_property_as_int (udev_device, "IFINDEX"); + else { + warning ("(%s): udev-add: failed to get device's ifindex", ifname); + return; + } + if (ifindex <= 0) { + warning ("(%s): udev-add: retrieved invalid IFINDEX=%d", ifname, ifindex); + return; + } + + if (!g_udev_device_get_sysfs_path (udev_device)) { + debug ("(%s): udev-add: couldn't determine device path; ignoring...", ifname); + return; + } + + rtnllink = rtnl_link_get (priv->link_cache, ifindex); + if (rtnllink) + was_announceable = link_is_announceable (platform, rtnllink); + + g_hash_table_insert (priv->udev_devices, GINT_TO_POINTER (ifindex), + g_object_ref (udev_device)); + + /* Announce devices only if they also have been discovered via Netlink. */ + if (rtnllink && link_is_announceable (platform, rtnllink)) + announce_object (platform, (struct nl_object *) rtnllink, was_announceable ? NM_PLATFORM_SIGNAL_CHANGED : NM_PLATFORM_SIGNAL_ADDED, NM_PLATFORM_REASON_EXTERNAL); +} + +static void +udev_device_removed (NMPlatform *platform, + GUdevDevice *udev_device) +{ + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); + auto_nl_object struct rtnl_link *rtnllink = NULL; + int ifindex = 0; + gboolean was_announceable = FALSE; + + if (g_udev_device_get_property (udev_device, "IFINDEX")) + ifindex = g_udev_device_get_property_as_int (udev_device, "IFINDEX"); + else { + GHashTableIter iter; + gpointer key, value; + + /* This should not happen, but just to be sure. + * If we can't get IFINDEX, go through the devices and + * compare the pointers. + */ + g_hash_table_iter_init (&iter, priv->udev_devices); + while (g_hash_table_iter_next (&iter, &key, &value)) { + if ((GUdevDevice *)value == udev_device) { + ifindex = GPOINTER_TO_INT (key); + break; + } + } + } + + debug ("udev-remove: IFINDEX=%d", ifindex); + if (ifindex <= 0) + return; + + rtnllink = rtnl_link_get (priv->link_cache, ifindex); + if (rtnllink) + was_announceable = link_is_announceable (platform, rtnllink); + + g_hash_table_remove (priv->udev_devices, GINT_TO_POINTER (ifindex)); + + /* Announce device removal if it is no longer announceable. */ + if (was_announceable && !link_is_announceable (platform, rtnllink)) + announce_object (platform, (struct nl_object *) rtnllink, NM_PLATFORM_SIGNAL_REMOVED, NM_PLATFORM_REASON_EXTERNAL); +} + +static void +handle_udev_event (GUdevClient *client, + const char *action, + GUdevDevice *udev_device, + gpointer user_data) +{ + NMPlatform *platform = NM_PLATFORM (user_data); + const char *subsys; + const char *ifindex; + guint64 seqnum; + + g_return_if_fail (action != NULL); + + /* A bit paranoid */ + subsys = g_udev_device_get_subsystem (udev_device); + g_return_if_fail (!g_strcmp0 (subsys, "net")); + + ifindex = g_udev_device_get_property (udev_device, "IFINDEX"); + seqnum = g_udev_device_get_seqnum (udev_device); + debug ("UDEV event: action '%s' subsys '%s' device '%s' (%s); seqnum=%" G_GUINT64_FORMAT, + action, subsys, g_udev_device_get_name (udev_device), + ifindex ? ifindex : "unknown", seqnum); + + if (!strcmp (action, "add") || !strcmp (action, "move")) + udev_device_added (platform, udev_device); + if (!strcmp (action, "remove")) + udev_device_removed (platform, udev_device); +} + +/******************************************************************/ + +static void +nm_linux_platform_init (NMLinuxPlatform *platform) +{ +} + +static gboolean +setup (NMPlatform *platform) +{ + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); + const char *udev_subsys[] = { "net", NULL }; + GUdevEnumerator *enumerator; + GList *devices, *iter; + int channel_flags; + gboolean status; + int nle; + struct nl_object *object; + + /* Initialize netlink socket for requests */ + priv->nlh = setup_socket (FALSE, platform); + g_assert (priv->nlh); + debug ("Netlink socket for requests established: %d", nl_socket_get_local_port (priv->nlh)); + + /* Initialize netlink socket for events */ + priv->nlh_event = setup_socket (TRUE, platform); + g_assert (priv->nlh_event); + /* The default buffer size wasn't enough for the testsuites. It might just + * as well happen with NetworkManager itself. For now let's hope 128KB is + * good enough. + */ + nle = nl_socket_set_buffer_size (priv->nlh_event, 131072, 0); + g_assert (!nle); + nle = nl_socket_add_memberships (priv->nlh_event, + RTNLGRP_LINK, + RTNLGRP_IPV4_IFADDR, RTNLGRP_IPV6_IFADDR, + RTNLGRP_IPV4_ROUTE, RTNLGRP_IPV6_ROUTE, + 0); + g_assert (!nle); + debug ("Netlink socket for events established: %d", nl_socket_get_local_port (priv->nlh_event)); + + priv->event_channel = g_io_channel_unix_new (nl_socket_get_fd (priv->nlh_event)); + g_io_channel_set_encoding (priv->event_channel, NULL, NULL); + g_io_channel_set_close_on_unref (priv->event_channel, TRUE); + + channel_flags = g_io_channel_get_flags (priv->event_channel); + status = g_io_channel_set_flags (priv->event_channel, + channel_flags | G_IO_FLAG_NONBLOCK, NULL); + g_assert (status); + priv->event_id = g_io_add_watch (priv->event_channel, + (EVENT_CONDITIONS | ERROR_CONDITIONS | DISCONNECT_CONDITIONS), + event_handler, platform); + + /* Allocate netlink caches */ + rtnl_link_alloc_cache (priv->nlh, AF_UNSPEC, &priv->link_cache); + rtnl_addr_alloc_cache (priv->nlh, &priv->address_cache); + rtnl_route_alloc_cache (priv->nlh, AF_UNSPEC, 0, &priv->route_cache); + g_assert (priv->link_cache && priv->address_cache && priv->route_cache); + + for (object = nl_cache_get_first (priv->address_cache); object; object = nl_cache_get_next (object)) + _rtnl_addr_hack_lifetimes_rel_to_abs ((struct rtnl_addr *) object); + + /* Set up udev monitoring */ + priv->udev_client = g_udev_client_new (udev_subsys); + g_signal_connect (priv->udev_client, "uevent", G_CALLBACK (handle_udev_event), platform); + priv->udev_devices = g_hash_table_new_full (NULL, NULL, NULL, g_object_unref); + + /* And read initial device list */ + enumerator = g_udev_enumerator_new (priv->udev_client); + g_udev_enumerator_add_match_subsystem (enumerator, "net"); + g_udev_enumerator_add_match_is_initialized (enumerator); + + devices = g_udev_enumerator_execute (enumerator); + for (iter = devices; iter; iter = g_list_next (iter)) { + udev_device_added (platform, G_UDEV_DEVICE (iter->data)); + g_object_unref (G_UDEV_DEVICE (iter->data)); + } + g_list_free (devices); + g_object_unref (enumerator); + + /* request all IPv6 addresses (hopeing that there is at least one), to check for + * the IFA_FLAGS attribute. */ + nle = nl_rtgen_request (priv->nlh_event, RTM_GETADDR, AF_INET6, NLM_F_DUMP); + if (nle < 0) + nm_log_warn (LOGD_PLATFORM, "Netlink error: requesting RTM_GETADDR failed with %s", nl_geterror (nle)); + + priv->wifi_data = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify) wifi_utils_deinit); + + return TRUE; +} + +static void +nm_linux_platform_finalize (GObject *object) +{ + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (object); + + /* Free netlink resources */ + g_source_remove (priv->event_id); + g_io_channel_unref (priv->event_channel); + nl_socket_free (priv->nlh); + nl_socket_free (priv->nlh_event); + nl_cache_free (priv->link_cache); + nl_cache_free (priv->address_cache); + nl_cache_free (priv->route_cache); + + g_object_unref (priv->udev_client); + g_hash_table_unref (priv->udev_devices); + g_hash_table_unref (priv->wifi_data); + + G_OBJECT_CLASS (nm_linux_platform_parent_class)->finalize (object); +} + +#define OVERRIDE(function) platform_class->function = function + +static void +nm_linux_platform_class_init (NMLinuxPlatformClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMPlatformClass *platform_class = NM_PLATFORM_CLASS (klass); + + g_type_class_add_private (klass, sizeof (NMLinuxPlatformPrivate)); + + /* virtual methods */ + object_class->finalize = nm_linux_platform_finalize; + + platform_class->setup = setup; + + platform_class->sysctl_set = sysctl_set; + platform_class->sysctl_get = sysctl_get; + + platform_class->link_get = _nm_platform_link_get; + platform_class->link_get_all = link_get_all; + platform_class->link_add = link_add; + platform_class->link_delete = link_delete; + platform_class->link_get_ifindex = link_get_ifindex; + platform_class->link_get_name = link_get_name; + platform_class->link_get_type = link_get_type; + platform_class->link_get_type_name = link_get_type_name; + + platform_class->link_refresh = link_refresh; + + platform_class->link_set_up = link_set_up; + platform_class->link_set_down = link_set_down; + platform_class->link_set_arp = link_set_arp; + platform_class->link_set_noarp = link_set_noarp; + platform_class->link_is_up = link_is_up; + platform_class->link_is_connected = link_is_connected; + platform_class->link_uses_arp = link_uses_arp; + + platform_class->link_get_address = link_get_address; + platform_class->link_set_address = link_set_address; + platform_class->link_get_mtu = link_get_mtu; + platform_class->link_set_mtu = link_set_mtu; + + platform_class->link_get_physical_port_id = link_get_physical_port_id; + platform_class->link_get_wake_on_lan = link_get_wake_on_lan; + + platform_class->link_supports_carrier_detect = link_supports_carrier_detect; + platform_class->link_supports_vlans = link_supports_vlans; + + platform_class->link_enslave = link_enslave; + platform_class->link_release = link_release; + platform_class->link_get_master = link_get_master; + platform_class->master_set_option = master_set_option; + platform_class->master_get_option = master_get_option; + platform_class->slave_set_option = slave_set_option; + platform_class->slave_get_option = slave_get_option; + + platform_class->vlan_add = vlan_add; + platform_class->vlan_get_info = vlan_get_info; + platform_class->vlan_set_ingress_map = vlan_set_ingress_map; + platform_class->vlan_set_egress_map = vlan_set_egress_map; + + platform_class->infiniband_partition_add = infiniband_partition_add; + + platform_class->veth_get_properties = veth_get_properties; + platform_class->tun_get_properties = tun_get_properties; + platform_class->macvlan_get_properties = macvlan_get_properties; + platform_class->vxlan_get_properties = vxlan_get_properties; + platform_class->gre_get_properties = gre_get_properties; + + platform_class->wifi_get_capabilities = wifi_get_capabilities; + platform_class->wifi_get_bssid = wifi_get_bssid; + platform_class->wifi_get_ssid = wifi_get_ssid; + platform_class->wifi_get_frequency = wifi_get_frequency; + platform_class->wifi_get_quality = wifi_get_quality; + platform_class->wifi_get_rate = wifi_get_rate; + platform_class->wifi_get_mode = wifi_get_mode; + platform_class->wifi_set_mode = wifi_set_mode; + platform_class->wifi_find_frequency = wifi_find_frequency; + platform_class->wifi_indicate_addressing_running = wifi_indicate_addressing_running; + + platform_class->mesh_get_channel = mesh_get_channel; + platform_class->mesh_set_channel = mesh_set_channel; + platform_class->mesh_set_ssid = mesh_set_ssid; + + platform_class->ip4_address_get_all = ip4_address_get_all; + platform_class->ip6_address_get_all = ip6_address_get_all; + platform_class->ip4_address_add = ip4_address_add; + platform_class->ip6_address_add = ip6_address_add; + platform_class->ip4_address_delete = ip4_address_delete; + platform_class->ip6_address_delete = ip6_address_delete; + platform_class->ip4_address_exists = ip4_address_exists; + platform_class->ip6_address_exists = ip6_address_exists; + + platform_class->ip4_route_get_all = ip4_route_get_all; + platform_class->ip6_route_get_all = ip6_route_get_all; + platform_class->ip4_route_add = ip4_route_add; + platform_class->ip6_route_add = ip6_route_add; + platform_class->ip4_route_delete = ip4_route_delete; + platform_class->ip6_route_delete = ip6_route_delete; + platform_class->ip4_route_exists = ip4_route_exists; + platform_class->ip6_route_exists = ip6_route_exists; + + platform_class->check_support_kernel_extended_ifa_flags = check_support_kernel_extended_ifa_flags; +} diff --git a/src/platform/nm-linux-platform.h b/src/platform/nm-linux-platform.h new file mode 100644 index 00000000..53ea75e6 --- /dev/null +++ b/src/platform/nm-linux-platform.h @@ -0,0 +1,49 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* nm-linux-platform.h - Linux kernel & udev network configuration layer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2012 Red Hat, Inc. + */ + +#ifndef NM_LINUX_PLATFORM_H +#define NM_LINUX_PLATFORM_H + +#include "nm-platform.h" + +#define NM_TYPE_LINUX_PLATFORM (nm_linux_platform_get_type ()) +#define NM_LINUX_PLATFORM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_LINUX_PLATFORM, NMLinuxPlatform)) +#define NM_LINUX_PLATFORM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_LINUX_PLATFORM, NMLinuxPlatformClass)) +#define NM_IS_LINUX_PLATFORM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_LINUX_PLATFORM)) +#define NM_IS_LINUX_PLATFORM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_LINUX_PLATFORM)) +#define NM_LINUX_PLATFORM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_LINUX_PLATFORM, NMLinuxPlatformClass)) + +/******************************************************************/ + +typedef struct { + NMPlatform parent; +} NMLinuxPlatform; + +typedef struct { + NMPlatformClass parent; +} NMLinuxPlatformClass; + +/******************************************************************/ + +GType nm_linux_platform_get_type (void); + +void nm_linux_platform_setup (void); + +#endif /* NM_LINUX_PLATFORM_H */ diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c new file mode 100644 index 00000000..542b0faa --- /dev/null +++ b/src/platform/nm-platform.c @@ -0,0 +1,2618 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* nm-platform.c - Handle runtime kernel networking configuration + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2012 Red Hat, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "NetworkManagerUtils.h" +#include "nm-utils.h" +#include "nm-platform.h" +#include "NetworkManagerUtils.h" +#include "nm-logging.h" +#include "nm-enum-types.h" + +#define debug(...) nm_log_dbg (LOGD_PLATFORM, __VA_ARGS__) + +#define NM_PLATFORM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_PLATFORM, NMPlatformPrivate)) + +G_DEFINE_TYPE (NMPlatform, nm_platform, G_TYPE_OBJECT) + +/* NMPlatform signals */ +enum { + SIGNAL_LINK_CHANGED, + SIGNAL_IP4_ADDRESS_CHANGED, + SIGNAL_IP6_ADDRESS_CHANGED, + SIGNAL_IP4_ROUTE_CHANGED, + SIGNAL_IP6_ROUTE_CHANGED, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +/******************************************************************/ + +/* Singleton NMPlatform subclass instance and cached class object */ +static NMPlatform *platform = NULL; +static NMPlatformClass *klass = NULL; + +/** + * nm_platform_setup: + * @type: The #GType for a subclass of #NMPlatform + * + * Do not use this function directly, it is intended to be called by + * NMPlatform subclasses. For the linux platform initialization use + * nm_linux_platform_setup() instead. + * + * Failing to set up #NMPlatform singleton results in a fatal error, + * as well as trying to initialize it multiple times without freeing + * it. + * + * NetworkManager will typically use only one platform object during + * its run. Test programs might want to switch platform implementations, + * though. This is done with a combination of nm_platform_free() and + * nm_*_platform_setup(). + */ +void +nm_platform_setup (GType type) +{ + gboolean status; + + g_assert (platform == NULL); + + platform = g_object_new (type, NULL); + g_assert (NM_IS_PLATFORM (platform)); + + klass = NM_PLATFORM_GET_CLASS (platform); + g_assert (klass->setup); + + status = klass->setup (platform); + g_assert (status); +} + +/** + * nm_platform_free: + * + * Free #NMPlatform singleton created by nm_*_platform_setup(). + */ +void +nm_platform_free (void) +{ + g_assert (platform); + + g_object_unref (platform); + platform = NULL; +} + +/** + * nm_platform_get: + * + * Retrieve #NMPlatform singleton. Use this whenever you want to connect to + * #NMPlatform signals. It is an error to call it before nm_*_platform_setup() + * or after nm_platform_free(). + * + * Returns: (transfer none): The #NMPlatform singleton reference. + */ +NMPlatform * +nm_platform_get (void) +{ + g_assert (platform); + + return platform; +} + +/******************************************************************/ + +/** + * nm_platform_set_error: + * @error: The error code + * + * Convenience function to falsify platform->error. It can be used for example + * by functions that want to save the error, execute some operations and + * restore it. + */ +void nm_platform_set_error (NMPlatformError error) +{ + platform->error = error; +} + +/** + * nm_platform_get_error: + * + * Convenience function to quickly retrieve the error code of the last + * operation. + * + * Returns: Integer error code. + */ +NMPlatformError +nm_platform_get_error (void) +{ + g_assert (platform); + + return platform->error; +} + +/** + * nm_platform_get_error_message: + * + * Returns: Static human-readable string for the error. Don't free. + */ +const char * +nm_platform_get_error_msg (void) +{ + g_assert (platform); + + switch (platform->error) { + case NM_PLATFORM_ERROR_NONE: + return "unknown error"; + case NM_PLATFORM_ERROR_NOT_FOUND: + return "object not found"; + case NM_PLATFORM_ERROR_EXISTS: + return "object already exists"; + case NM_PLATFORM_ERROR_WRONG_TYPE: + return "object is wrong type"; + case NM_PLATFORM_ERROR_NOT_SLAVE: + return "link not a slave"; + case NM_PLATFORM_ERROR_NO_FIRMWARE: + return "firmware not found"; + default: + return "invalid error number"; + } +} + +static void +reset_error (void) +{ + g_assert (platform); + platform->error = NM_PLATFORM_ERROR_NONE; +} + +#define IFA_F_MANAGETEMPADDR_STR "mngtmpaddr" +#define IFA_F_NOPREFIXROUTE_STR "noprefixroute" +gboolean +nm_platform_check_support_libnl_extended_ifa_flags () +{ + static int supported = -1; + + /* support for extended ifa-flags was added together + * with the IFA_F_MANAGETEMPADDR flag. So, check if libnl + * is able to parse this flag. */ + if (supported == -1) + supported = rtnl_addr_str2flags (IFA_F_MANAGETEMPADDR_STR) == IFA_F_MANAGETEMPADDR; + + return supported; +} + +gboolean +nm_platform_check_support_kernel_extended_ifa_flags () +{ + g_return_val_if_fail (NM_IS_PLATFORM (platform), FALSE); + + if (!klass->check_support_kernel_extended_ifa_flags) + return FALSE; + + return klass->check_support_kernel_extended_ifa_flags (platform); +} + +/******************************************************************/ + +/** + * nm_platform_sysctl_set: + * @path: Absolute option path + * @value: Value to write + * + * This function is intended to be used for writing values to sysctl-style + * virtual runtime configuration files. This includes not only /proc/sys + * but also for example /sys/class. + * + * Returns: %TRUE on success. + */ +gboolean +nm_platform_sysctl_set (const char *path, const char *value) +{ + reset_error (); + + g_return_val_if_fail (path, FALSE); + g_return_val_if_fail (value, FALSE); + g_return_val_if_fail (klass->sysctl_set, FALSE); + + return klass->sysctl_set (platform, path, value); +} + +/** + * nm_platform_sysctl_get: + * @path: Absolute path to sysctl + * + * Returns: (transfer full): Contents of the virtual sysctl file. + */ +char * +nm_platform_sysctl_get (const char *path) +{ + reset_error (); + + g_return_val_if_fail (path, NULL); + g_return_val_if_fail (klass->sysctl_get, NULL); + + return klass->sysctl_get (platform, path); +} + +/** + * nm_platform_sysctl_get_int32: + * @path: Absolute path to sysctl + * @fallback: default value, if the content of path could not be read + * as decimal integer. + * + * Returns: contents of the sysctl file parsed as s32 integer, or + * @fallback on error. On error, %errno will be set to a non-zero + * value, on success %errno will be set to zero. + */ +gint32 +nm_platform_sysctl_get_int32 (const char *path, gint32 fallback) +{ + return nm_platform_sysctl_get_int_checked (path, 10, G_MININT32, G_MAXINT32, fallback); +} + +/** + * nm_platform_sysctl_get_int_checked: + * @path: Absolute path to sysctl + * @base: base of numeric conversion + * @min: minimal value that is still valid + * @max: maximal value that is still valid + * @fallback: default value, if the content of path could not be read + * as valid integer. + * + * Returns: contents of the sysctl file parsed as s64 integer, or + * @fallback on error. On error, %errno will be set to a non-zero + * value. On success, %errno will be set to zero. The returned value + * will always be in the range between @min and @max + * (inclusive) or @fallback. + */ +gint64 +nm_platform_sysctl_get_int_checked (const char *path, guint base, gint64 min, gint64 max, gint64 fallback) +{ + char *value = NULL; + gint32 ret; + + g_return_val_if_fail (path, fallback); + + if (path) + value = nm_platform_sysctl_get (path); + + if (!value) { + errno = EINVAL; + return fallback; + } + + ret = nm_utils_ascii_str_to_int64 (value, base, min, max, fallback); + g_free (value); + return ret; +} + +/******************************************************************/ + +/** + * nm_platform_query_devices: + * + * Emit #NMPlatform:link-changed ADDED signals for all currently-known links. + * Should only be called at startup. + */ +void +nm_platform_query_devices (void) +{ + GArray *links_array; + NMPlatformLink *links; + int i; + + links_array = nm_platform_link_get_all (); + links = (NMPlatformLink *) links_array->data; + for (i = 0; i < links_array->len; i++) { + g_signal_emit (platform, signals[SIGNAL_LINK_CHANGED], 0, + links[i].ifindex, &links[i], NM_PLATFORM_SIGNAL_ADDED, + NM_PLATFORM_REASON_INTERNAL); + } + g_array_unref (links_array); +} + +/** + * nm_platform_link_get_all: + * + * Retrieve a snapshot of configuration for all links at once. The result is + * owned by the caller and should be freed with g_array_unref(). + */ +GArray * +nm_platform_link_get_all (void) +{ + GArray *links, *result; + guint i, j, nresult; + GHashTable *unseen; + NMPlatformLink *item; + + reset_error (); + + g_return_val_if_fail (klass->link_get_all, NULL); + + links = klass->link_get_all (platform); + + if (!links || links->len == 0) + return links; + + unseen = g_hash_table_new (g_direct_hash, g_direct_equal); + for (i = 0; i < links->len; i++) { + item = &g_array_index (links, NMPlatformLink, i); + + if (item->ifindex <= 0 || g_hash_table_contains (unseen, GINT_TO_POINTER (item->ifindex))) { + g_warn_if_reached (); + item->ifindex = 0; + continue; + } + + g_hash_table_insert (unseen, GINT_TO_POINTER (item->ifindex), NULL); + } + +#ifndef G_DISABLE_ASSERT + /* Ensure that link_get_all returns a consistent and valid result. */ + for (i = 0; i < links->len; i++) { + item = &g_array_index (links, NMPlatformLink, i); + + if (!item->ifindex) + continue; + if (item->master != 0) { + g_warn_if_fail (item->master > 0); + g_warn_if_fail (item->master != item->ifindex); + g_warn_if_fail (g_hash_table_contains (unseen, GINT_TO_POINTER (item->master))); + } + if (item->parent != 0) { + g_warn_if_fail (item->parent > 0); + g_warn_if_fail (item->parent != item->ifindex); + g_warn_if_fail (g_hash_table_contains (unseen, GINT_TO_POINTER (item->parent))); + } + } +#endif + + /* Re-order the links list such that children/slaves come after all ancestors */ + nresult = g_hash_table_size (unseen); + result = g_array_sized_new (TRUE, TRUE, sizeof (NMPlatformLink), nresult); + g_array_set_size (result, nresult); + + j = 0; + do { + gboolean found_something = FALSE; + guint first_idx = G_MAXUINT; + + for (i = 0; i < links->len; i++) { + item = &g_array_index (links, NMPlatformLink, i); + + if (!item->ifindex) + continue; + + if (first_idx == G_MAXUINT) + first_idx = i; + + g_assert (g_hash_table_contains (unseen, GINT_TO_POINTER (item->ifindex))); + + if (item->master > 0 && g_hash_table_contains (unseen, GINT_TO_POINTER (item->master))) + continue; + if (item->parent > 0 && g_hash_table_contains (unseen, GINT_TO_POINTER (item->parent))) + continue; + + g_hash_table_remove (unseen, GINT_TO_POINTER (item->ifindex)); + g_array_index (result, NMPlatformLink, j++) = *item; + item->ifindex = 0; + found_something = TRUE; + } + + if (!found_something) { + /* there is a circle, pop the first (remaining) element from the list */ + g_warn_if_reached (); + item = &g_array_index (links, NMPlatformLink, first_idx); + + g_hash_table_remove (unseen, GINT_TO_POINTER (item->ifindex)); + g_array_index (result, NMPlatformLink, j++) = *item; + item->ifindex = 0; + } + } while (j < nresult); + + g_hash_table_destroy (unseen); + g_array_free (links, TRUE); + + return result; +} + +/** + * nm_platform_link_get: + * @ifindex: ifindex of the link + * @link: (out): output NMPlatformLink structure. + * + * If a link with given @ifindex exists, fill the given NMPlatformLink + * structure. + * + * Returns: %TRUE, if such a link exists, %FALSE otherwise. + * If the link does not exist, the content of @link is undefined. + **/ +gboolean +nm_platform_link_get (int ifindex, NMPlatformLink *link) +{ + g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail (link, FALSE); + + g_return_val_if_fail (klass->link_get, FALSE); + return !!klass->link_get (platform, ifindex, link); +} + +/** + * nm_platform_link_add: + * @name: Interface name + * @type: Interface type + * @address: (allow-none): set the mac address of the link + * @address_len: the length of the @address + * + * Add a software interface. Sets platform->error to NM_PLATFORM_ERROR_EXISTS + * if interface is already already exists. Any link-changed ADDED signal will be + * emitted directly, before this function finishes. + */ +static gboolean +nm_platform_link_add (const char *name, NMLinkType type, const void *address, size_t address_len) +{ + reset_error (); + + g_return_val_if_fail (name, FALSE); + g_return_val_if_fail (klass->link_add, FALSE); + g_return_val_if_fail ( (address != NULL) ^ (address_len == 0) , FALSE); + + if (nm_platform_link_exists (name)) { + debug ("link: already exists"); + platform->error = NM_PLATFORM_ERROR_EXISTS; + return FALSE; + } + + return klass->link_add (platform, name, type, address, address_len); +} + +/** + * nm_platform_dummy_add: + * @name: New interface name + * + * Create a software ethernet-like interface + */ +gboolean +nm_platform_dummy_add (const char *name) +{ + g_return_val_if_fail (name, FALSE); + + debug ("link: adding dummy '%s'", name); + return nm_platform_link_add (name, NM_LINK_TYPE_DUMMY, NULL, 0); +} + +/** + * nm_platform_link_exists: + * @name: Interface name + * + * Returns: %TRUE if an interface of this name exists, %FALSE otherwise. + */ +gboolean +nm_platform_link_exists (const char *name) +{ + int ifindex = nm_platform_link_get_ifindex (name); + + reset_error(); + return ifindex > 0; +} + +/** + * nm_platform_link_delete: + * @ifindex: Interface index + * + * Delete a software interface. Sets platform->error to + * NM_PLATFORM_ERROR_NOT_FOUND if ifindex not available. + */ +gboolean +nm_platform_link_delete (int ifindex) +{ + const char *name; + + reset_error (); + + g_return_val_if_fail (klass->link_delete, FALSE); + + name = nm_platform_link_get_name (ifindex); + + if (!name) + return FALSE; + + debug ("link: deleting '%s' (%d)", name, ifindex); + return klass->link_delete (platform, ifindex); +} + +/** + * nm_platform_link_get_index: + * @name: Interface name + * + * Returns: The interface index corresponding to the given interface name + * or 0. Inteface name is owned by #NMPlatform, don't free it. + */ +int +nm_platform_link_get_ifindex (const char *name) +{ + int ifindex; + + reset_error (); + + g_return_val_if_fail (name, 0); + g_return_val_if_fail (klass->link_get_ifindex, 0); + + ifindex = klass->link_get_ifindex (platform, name); + + if (!ifindex) { + debug ("link not found: %s", name); + platform->error = NM_PLATFORM_ERROR_NOT_FOUND; + } + + return ifindex; +} + +/** + * nm_platform_link_get_name: + * @name: Interface name + * + * Returns: The interface name corresponding to the given interface index + * or %NULL. + */ +const char * +nm_platform_link_get_name (int ifindex) +{ + const char *name; + + reset_error (); + + g_return_val_if_fail (klass->link_get_name, NULL); + + name = klass->link_get_name (platform, ifindex); + + if (!name) { + debug ("link not found: %d", ifindex); + platform->error = NM_PLATFORM_ERROR_NOT_FOUND; + return FALSE; + } + + return name; +} + +/** + * nm_platform_link_get_type: + * @ifindex: Interface index. + * + * Returns: Link type constant as defined in nm-platform.h. On error, + * NM_LINK_TYPE_NONE is returned. + */ +NMLinkType +nm_platform_link_get_type (int ifindex) +{ + reset_error (); + + g_return_val_if_fail (klass->link_get_type, NM_LINK_TYPE_NONE); + + return klass->link_get_type (platform, ifindex); +} + +/** + * nm_platform_link_get_type_name: + * @ifindex: Interface index. + * + * Returns: A string describing the type of link. In some cases this + * may be more specific than nm_platform_link_get_type(), but in + * other cases it may not. On error, %NULL is returned. + */ +const char * +nm_platform_link_get_type_name (int ifindex) +{ + reset_error (); + + g_return_val_if_fail (klass->link_get_type_name, NULL); + + return klass->link_get_type_name (platform, ifindex); +} + +/** + * nm_platform_link_is_software: + * @ifindex: Interface index. + * + * Returns: %TRUE if ifindex belongs to a software interface, not backed by + * a physical device. + */ +gboolean +nm_platform_link_is_software (int ifindex) +{ + return (nm_platform_link_get_type (ifindex) & 0x10000); +} + +/** + * nm_platform_link_supports_slaves: + * @ifindex: Interface index. + * + * Returns: %TRUE if ifindex belongs to an interface capable of enslaving + * other interfaces. + */ +gboolean +nm_platform_link_supports_slaves (int ifindex) +{ + return (nm_platform_link_get_type (ifindex) & 0x20000); +} + +/** + * nm_platform_link_refresh: + * @ifindex: Interface index + * + * Reload the cache for ifindex synchronously. + */ +gboolean +nm_platform_link_refresh (int ifindex) +{ + reset_error (); + + g_return_val_if_fail (ifindex > 0, FALSE); + + if (klass->link_refresh) + return klass->link_refresh (platform, ifindex); + + return TRUE; +} + +/** + * nm_platform_link_is_up: + * @ifindex: Interface index + * + * Check if the interface is up. + */ +gboolean +nm_platform_link_is_up (int ifindex) +{ + reset_error (); + + g_return_val_if_fail (ifindex >= 0, FALSE); + g_return_val_if_fail (klass->link_is_up, FALSE); + + return klass->link_is_up (platform, ifindex); +} + +/** + * nm_platform_link_is_connected: + * @ifindex: Interface index + * + * Check if the interface is connected. + */ +gboolean +nm_platform_link_is_connected (int ifindex) +{ + reset_error (); + + g_return_val_if_fail (ifindex >= 0, FALSE); + g_return_val_if_fail (klass->link_is_connected, FALSE); + + return klass->link_is_connected (platform, ifindex); +} + +/** + * nm_platform_link_uses_arp: + * @ifindex: Interface index + * + * Check if the interface is configured to use ARP. + */ +gboolean +nm_platform_link_uses_arp (int ifindex) +{ + reset_error (); + + g_return_val_if_fail (ifindex >= 0, FALSE); + g_return_val_if_fail (klass->link_uses_arp, FALSE); + + return klass->link_uses_arp (platform, ifindex); +} + +/** + * nm_platform_link_set_address: + * @ifindex: Interface index + * @address: The new MAC address + * + * Set interface MAC address. + */ +gboolean +nm_platform_link_set_address (int ifindex, gconstpointer address, size_t length) +{ + reset_error (); + + g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail (address, FALSE); + g_return_val_if_fail (length > 0, FALSE); + g_return_val_if_fail (klass->link_set_address, FALSE); + + debug ("link: setting '%s' (%d) hardware address", nm_platform_link_get_name (ifindex), ifindex); + return klass->link_set_address (platform, ifindex, address, length); +} + +/** + * nm_platform_link_get_address: + * @ifindex: Interface index + * @length: Pointer to a variable to store address length + * + * Saves interface hardware address to @address. + */ +gconstpointer +nm_platform_link_get_address (int ifindex, size_t *length) +{ + reset_error (); + + if (length) + *length = 0; + + g_return_val_if_fail (ifindex > 0, NULL); + g_return_val_if_fail (klass->link_get_address, NULL); + + return klass->link_get_address (platform, ifindex, length); +} + +gboolean +nm_platform_link_supports_carrier_detect (int ifindex) +{ + g_return_val_if_fail (ifindex >= 0, FALSE); + g_return_val_if_fail (klass->link_supports_carrier_detect, FALSE); + + return klass->link_supports_carrier_detect (platform, ifindex); +} + +gboolean +nm_platform_link_supports_vlans (int ifindex) +{ + g_return_val_if_fail (ifindex >= 0, FALSE); + g_return_val_if_fail (klass->link_supports_vlans, FALSE); + + return klass->link_supports_vlans (platform, ifindex); +} + +/** + * nm_platform_link_set_up: + * @ifindex: Interface index + * + * Bring the interface up. + */ +gboolean +nm_platform_link_set_up (int ifindex) +{ + reset_error (); + + g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail (klass->link_set_up, FALSE); + + debug ("link: setting up '%s' (%d)", nm_platform_link_get_name (ifindex), ifindex); + return klass->link_set_up (platform, ifindex); +} + +/** + * nm_platform_link_set_down: + * @ifindex: Interface index + * + * Take the interface down. + */ +gboolean +nm_platform_link_set_down (int ifindex) +{ + reset_error (); + + g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail (klass->link_set_down, FALSE); + + debug ("link: setting down '%s' (%d)", nm_platform_link_get_name (ifindex), ifindex); + return klass->link_set_down (platform, ifindex); +} + +/** + * nm_platform_link_set_arp: + * @ifindex: Interface index + * + * Enable ARP on the interface. + */ +gboolean +nm_platform_link_set_arp (int ifindex) +{ + reset_error (); + + g_return_val_if_fail (ifindex >= 0, FALSE); + g_return_val_if_fail (klass->link_set_arp, FALSE); + + debug ("link: setting arp '%s' (%d)", nm_platform_link_get_name (ifindex), ifindex); + return klass->link_set_arp (platform, ifindex); +} + +/** + * nm_platform_link_set_noarp: + * @ifindex: Interface index + * + * Disable ARP on the interface. + */ +gboolean +nm_platform_link_set_noarp (int ifindex) +{ + reset_error (); + + g_return_val_if_fail (ifindex >= 0, FALSE); + g_return_val_if_fail (klass->link_set_noarp, FALSE); + + debug ("link: setting noarp '%s' (%d)", nm_platform_link_get_name (ifindex), ifindex); + return klass->link_set_noarp (platform, ifindex); +} + +/** + * nm_platform_link_set_mtu: + * @ifindex: Interface index + * @mtu: The new MTU value + * + * Set interface MTU. + */ +gboolean +nm_platform_link_set_mtu (int ifindex, guint32 mtu) +{ + reset_error (); + + g_return_val_if_fail (ifindex >= 0, FALSE); + g_return_val_if_fail (mtu > 0, FALSE); + g_return_val_if_fail (klass->link_set_mtu, FALSE); + + debug ("link: setting '%s' (%d) mtu %d", nm_platform_link_get_name (ifindex), ifindex, mtu); + return klass->link_set_mtu (platform, ifindex, mtu); +} + +/** + * nm_platform_link_get_mtu: + * @ifindex: Interface index + * + * Returns: MTU value for the interface or 0 on error. + */ +guint32 +nm_platform_link_get_mtu (int ifindex) +{ + reset_error (); + + g_return_val_if_fail (ifindex >= 0, 0); + g_return_val_if_fail (klass->link_get_mtu, 0); + + return klass->link_get_mtu (platform, ifindex); +} + +/** + * nm_platform_link_get_mtu: + * @ifindex: Interface index + * + * Returns: physical port ID for the interface, or %NULL on error + * or if the interface has no physical port ID. + */ +char * +nm_platform_link_get_physical_port_id (int ifindex) +{ + reset_error (); + + g_return_val_if_fail (ifindex >= 0, NULL); + g_return_val_if_fail (klass->link_get_physical_port_id, NULL); + + return klass->link_get_physical_port_id (platform, ifindex); +} + +/** + * nm_platform_link_get_wake_onlan: + * @ifindex: Interface index + * + * Returns: the "Wake-on-LAN" status for @ifindex. + */ +gboolean +nm_platform_link_get_wake_on_lan (int ifindex) +{ + reset_error (); + + g_return_val_if_fail (ifindex >= 0, FALSE); + g_return_val_if_fail (klass->link_get_wake_on_lan, FALSE); + + return klass->link_get_wake_on_lan (platform, ifindex); +} + +/** + * nm_platform_link_enslave: + * @master: Interface index of the master + * @slave: Interface index of the slave + * + * Enslave @slave to @master. + */ +gboolean +nm_platform_link_enslave (int master, int slave) +{ + reset_error (); + + g_assert (platform); + g_return_val_if_fail (master > 0, FALSE); + g_return_val_if_fail (slave> 0, FALSE); + g_return_val_if_fail (klass->link_enslave, FALSE); + + debug ("link: enslaving '%s' (%d) to master '%s' (%d)", + nm_platform_link_get_name (slave), slave, + nm_platform_link_get_name (master), master); + return klass->link_enslave (platform, master, slave); +} + +/** + * nm_platform_link_release: + * @master: Interface index of the master + * @slave: Interface index of the slave + * + * Release @slave from @master. + */ +gboolean +nm_platform_link_release (int master, int slave) +{ + reset_error (); + + g_assert (platform); + g_return_val_if_fail (master > 0, FALSE); + g_return_val_if_fail (slave > 0, FALSE); + g_return_val_if_fail (klass->link_release, FALSE); + + if (nm_platform_link_get_master (slave) != master) { + platform->error = NM_PLATFORM_ERROR_NOT_SLAVE; + return FALSE; + } + + debug ("link: releasing '%s' (%d) from master '%s' (%d)", + nm_platform_link_get_name (slave), slave, + nm_platform_link_get_name (master), master); + return klass->link_release (platform, master, slave); +} + +/** + * nm_platform_link_get_master: + * @slave: Interface index of the slave. + * + * Returns: Interfase index of the slave's master. + */ +int +nm_platform_link_get_master (int slave) +{ + reset_error (); + + g_assert (platform); + g_return_val_if_fail (slave >= 0, FALSE); + g_return_val_if_fail (klass->link_get_master, FALSE); + + if (!nm_platform_link_get_name (slave)) { + platform->error = NM_PLATFORM_ERROR_NOT_FOUND; + return 0; + } + return klass->link_get_master (platform, slave); +} + +/** + * nm_platform_bridge_add: + * @name: New interface name + * @address: (allow-none): set the mac address of the new bridge + * @address_len: the length of the @address + * + * Create a software bridge. + */ +gboolean +nm_platform_bridge_add (const char *name, const void *address, size_t address_len) +{ + debug ("link: adding bridge '%s'", name); + return nm_platform_link_add (name, NM_LINK_TYPE_BRIDGE, address, address_len); +} + +/** + * nm_platform_bond_add: + * @name: New interface name + * + * Create a software bonding device. + */ +gboolean +nm_platform_bond_add (const char *name) +{ + debug ("link: adding bond '%s'", name); + return nm_platform_link_add (name, NM_LINK_TYPE_BOND, NULL, 0); +} + +/** + * nm_platform_team_add: + * @name: New interface name + * + * Create a software teaming device. + */ +gboolean +nm_platform_team_add (const char *name) +{ + debug ("link: adding team '%s'", name); + return nm_platform_link_add (name, NM_LINK_TYPE_TEAM, NULL, 0); +} + +/** + * nm_platform_vlan_add: + * @name: New interface name + * @vlanid: VLAN identifier + * @vlanflags: VLAN flags from libnm-util + * + * Create a software VLAN device. + */ +gboolean +nm_platform_vlan_add (const char *name, int parent, int vlanid, guint32 vlanflags) +{ + reset_error (); + + g_assert (platform); + g_return_val_if_fail (parent >= 0, FALSE); + g_return_val_if_fail (vlanid >= 0, FALSE); + g_return_val_if_fail (name, FALSE); + g_return_val_if_fail (klass->vlan_add, FALSE); + + if (nm_platform_link_exists (name)) { + debug ("link already exists: %s", name); + platform->error = NM_PLATFORM_ERROR_EXISTS; + return FALSE; + } + + debug ("link: adding vlan '%s' parent %d vlanid %d vlanflags %x", + name, parent, vlanid, vlanflags); + return klass->vlan_add (platform, name, parent, vlanid, vlanflags); +} + +gboolean +nm_platform_master_set_option (int ifindex, const char *option, const char *value) +{ + reset_error (); + + g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail (option, FALSE); + g_return_val_if_fail (value, FALSE); + g_return_val_if_fail (klass->master_set_option, FALSE); + + return klass->master_set_option (platform, ifindex, option, value); +} + +char * +nm_platform_master_get_option (int ifindex, const char *option) +{ + reset_error (); + + g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail (option, FALSE); + g_return_val_if_fail (klass->master_set_option, FALSE); + + return klass->master_get_option (platform, ifindex, option); +} + +gboolean +nm_platform_slave_set_option (int ifindex, const char *option, const char *value) +{ + reset_error (); + + g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail (option, FALSE); + g_return_val_if_fail (value, FALSE); + g_return_val_if_fail (klass->slave_set_option, FALSE); + + return klass->slave_set_option (platform, ifindex, option, value); +} + +char * +nm_platform_slave_get_option (int ifindex, const char *option) +{ + reset_error (); + + g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail (option, FALSE); + g_return_val_if_fail (klass->slave_set_option, FALSE); + + return klass->slave_get_option (platform, ifindex, option); +} + +gboolean +nm_platform_vlan_get_info (int ifindex, int *parent, int *vlanid) +{ + reset_error (); + + g_assert (platform); + g_return_val_if_fail (klass->vlan_get_info, FALSE); + + if (parent) + *parent = 0; + if (vlanid) + *vlanid = 0; + + if (nm_platform_link_get_type (ifindex) != NM_LINK_TYPE_VLAN) + return FALSE; + + return klass->vlan_get_info (platform, ifindex, parent, vlanid); +} + +gboolean +nm_platform_vlan_set_ingress_map (int ifindex, int from, int to) +{ + reset_error (); + + g_assert (platform); + g_return_val_if_fail (klass->vlan_set_ingress_map, FALSE); + + debug ("link: setting vlan ingress map for %d from %d to %d", ifindex, from, to); + return klass->vlan_set_ingress_map (platform, ifindex, from, to); +} + +gboolean +nm_platform_vlan_set_egress_map (int ifindex, int from, int to) +{ + reset_error (); + + g_assert (platform); + g_return_val_if_fail (klass->vlan_set_egress_map, FALSE); + + debug ("link: setting vlan egress map for %d from %d to %d", ifindex, from, to); + return klass->vlan_set_egress_map (platform, ifindex, from, to); +} + +gboolean +nm_platform_infiniband_partition_add (int parent, int p_key) +{ + const char *parent_name; + char *name; + + reset_error (); + + g_return_val_if_fail (parent >= 0, FALSE); + g_return_val_if_fail (p_key >= 0, FALSE); + g_return_val_if_fail (klass->infiniband_partition_add, FALSE); + + if (nm_platform_link_get_type (parent) != NM_LINK_TYPE_INFINIBAND) { + platform->error = NM_PLATFORM_ERROR_WRONG_TYPE; + return FALSE; + } + + parent_name = nm_platform_link_get_name (parent); + name = g_strdup_printf ("%s.%04x", parent_name, p_key); + if (nm_platform_link_exists (name)) { + debug ("infiniband: already exists"); + platform->error = NM_PLATFORM_ERROR_EXISTS; + g_free (name); + return FALSE; + } + g_free (name); + + return klass->infiniband_partition_add (platform, parent, p_key); +} + +gboolean +nm_platform_veth_get_properties (int ifindex, NMPlatformVethProperties *props) +{ + reset_error (); + + g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail (props != NULL, FALSE); + + return klass->veth_get_properties (platform, ifindex, props); +} + +gboolean +nm_platform_tun_get_properties (int ifindex, NMPlatformTunProperties *props) +{ + reset_error (); + + g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail (props != NULL, FALSE); + + return klass->tun_get_properties (platform, ifindex, props); +} + +gboolean +nm_platform_macvlan_get_properties (int ifindex, NMPlatformMacvlanProperties *props) +{ + reset_error (); + + g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail (props != NULL, FALSE); + + return klass->macvlan_get_properties (platform, ifindex, props); +} + +gboolean +nm_platform_vxlan_get_properties (int ifindex, NMPlatformVxlanProperties *props) +{ + reset_error (); + + g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail (props != NULL, FALSE); + + return klass->vxlan_get_properties (platform, ifindex, props); +} + +gboolean +nm_platform_gre_get_properties (int ifindex, NMPlatformGreProperties *props) +{ + reset_error (); + + g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail (props != NULL, FALSE); + + return klass->gre_get_properties (platform, ifindex, props); +} + +gboolean +nm_platform_wifi_get_capabilities (int ifindex, NMDeviceWifiCapabilities *caps) +{ + reset_error (); + + g_return_val_if_fail (ifindex > 0, FALSE); + + return klass->wifi_get_capabilities (platform, ifindex, caps); +} + +gboolean +nm_platform_wifi_get_bssid (int ifindex, struct ether_addr *bssid) +{ + reset_error (); + + g_return_val_if_fail (ifindex > 0, FALSE); + + return klass->wifi_get_bssid (platform, ifindex, bssid); +} + +GByteArray * +nm_platform_wifi_get_ssid (int ifindex) +{ + reset_error (); + + g_return_val_if_fail (ifindex > 0, NULL); + + return klass->wifi_get_ssid (platform, ifindex); +} + +guint32 +nm_platform_wifi_get_frequency (int ifindex) +{ + reset_error (); + + g_return_val_if_fail (ifindex > 0, 0); + + return klass->wifi_get_frequency (platform, ifindex); +} + +int +nm_platform_wifi_get_quality (int ifindex) +{ + reset_error (); + + g_return_val_if_fail (ifindex > 0, 0); + + return klass->wifi_get_quality (platform, ifindex); +} + +guint32 +nm_platform_wifi_get_rate (int ifindex) +{ + reset_error (); + + g_return_val_if_fail (ifindex > 0, 0); + + return klass->wifi_get_rate (platform, ifindex); +} + +NM80211Mode +nm_platform_wifi_get_mode (int ifindex) +{ + reset_error (); + + g_return_val_if_fail (ifindex > 0, NM_802_11_MODE_UNKNOWN); + + return klass->wifi_get_mode (platform, ifindex); +} + +void +nm_platform_wifi_set_mode (int ifindex, NM80211Mode mode) +{ + reset_error (); + + g_return_if_fail (ifindex > 0); + + klass->wifi_set_mode (platform, ifindex, mode); +} + +guint32 +nm_platform_wifi_find_frequency (int ifindex, const guint32 *freqs) +{ + reset_error (); + + g_return_val_if_fail (ifindex > 0, 0); + g_return_val_if_fail (freqs != NULL, 0); + + return klass->wifi_find_frequency (platform, ifindex, freqs); +} + +void +nm_platform_wifi_indicate_addressing_running (int ifindex, gboolean running) +{ + reset_error (); + + g_return_if_fail (ifindex > 0); + + klass->wifi_indicate_addressing_running (platform, ifindex, running); +} + +guint32 +nm_platform_mesh_get_channel (int ifindex) +{ + reset_error (); + + g_return_val_if_fail (ifindex > 0, 0); + + return klass->mesh_get_channel (platform, ifindex); +} + +gboolean +nm_platform_mesh_set_channel (int ifindex, guint32 channel) +{ + reset_error (); + + g_return_val_if_fail (ifindex > 0, FALSE); + + return klass->mesh_set_channel (platform, ifindex, channel); +} + +gboolean +nm_platform_mesh_set_ssid (int ifindex, const GByteArray *ssid) +{ + reset_error (); + + g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail (ssid != NULL, FALSE); + + return klass->mesh_set_ssid (platform, ifindex, ssid); +} + +/******************************************************************/ + +GArray * +nm_platform_ip4_address_get_all (int ifindex) +{ + reset_error (); + + g_return_val_if_fail (ifindex > 0, NULL); + g_return_val_if_fail (klass->ip4_address_get_all, NULL); + + return klass->ip4_address_get_all (platform, ifindex); +} + +GArray * +nm_platform_ip6_address_get_all (int ifindex) +{ + reset_error (); + + g_return_val_if_fail (ifindex > 0, NULL); + g_return_val_if_fail (klass->ip6_address_get_all, NULL); + + return klass->ip6_address_get_all (platform, ifindex); +} + +gboolean +nm_platform_ip4_address_add (int ifindex, + in_addr_t address, + in_addr_t peer_address, + int plen, + guint32 lifetime, + guint32 preferred, + const char *label) +{ + reset_error (); + + g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail (plen > 0, FALSE); + g_return_val_if_fail (lifetime > 0, FALSE); + g_return_val_if_fail (preferred <= lifetime, FALSE); + g_return_val_if_fail (klass->ip4_address_add, FALSE); + g_return_val_if_fail (!label || strlen (label) < sizeof (((NMPlatformIP4Address *) NULL)->label), FALSE); + + if (nm_logging_enabled (LOGL_DEBUG, LOGD_PLATFORM)) { + NMPlatformIP4Address addr = { 0 }; + + addr.ifindex = ifindex; + addr.address = address; + addr.peer_address = peer_address; + addr.plen = plen; + addr.timestamp = 0; /* set it at zero, which to_string will treat as *now* */ + addr.lifetime = lifetime; + addr.preferred = preferred; + if (label) + g_strlcpy (addr.label, label, sizeof (addr.label)); + + debug ("address: adding or updating IPv4 address: %s", nm_platform_ip4_address_to_string (&addr)); + } + return klass->ip4_address_add (platform, ifindex, address, peer_address, plen, lifetime, preferred, label); +} + +gboolean +nm_platform_ip6_address_add (int ifindex, + struct in6_addr address, + struct in6_addr peer_address, + int plen, + guint32 lifetime, + guint32 preferred, + guint flags) +{ + reset_error (); + + g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail (plen > 0, FALSE); + g_return_val_if_fail (lifetime > 0, FALSE); + g_return_val_if_fail (preferred <= lifetime, FALSE); + g_return_val_if_fail (klass->ip6_address_add, FALSE); + + if (nm_logging_enabled (LOGL_DEBUG, LOGD_PLATFORM)) { + NMPlatformIP6Address addr = { 0 }; + + addr.ifindex = ifindex; + addr.address = address; + addr.peer_address = peer_address; + addr.plen = plen; + addr.timestamp = 0; /* set it to zero, which to_string will treat as *now* */ + addr.lifetime = lifetime; + addr.preferred = preferred; + addr.flags = flags; + + debug ("address: adding or updating IPv6 address: %s", nm_platform_ip6_address_to_string (&addr)); + } + return klass->ip6_address_add (platform, ifindex, address, peer_address, plen, lifetime, preferred, flags); +} + +gboolean +nm_platform_ip4_address_delete (int ifindex, in_addr_t address, int plen) +{ + reset_error (); + + g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail (plen > 0, FALSE); + g_return_val_if_fail (klass->ip4_address_delete, FALSE); + + debug ("address: deleting IPv4 address %s/%d", nm_utils_inet4_ntop (address, NULL), plen); + return klass->ip4_address_delete (platform, ifindex, address, plen); +} + +gboolean +nm_platform_ip6_address_delete (int ifindex, struct in6_addr address, int plen) +{ + reset_error (); + + g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail (plen > 0, FALSE); + g_return_val_if_fail (klass->ip6_address_delete, FALSE); + + debug ("address: deleting IPv6 address %s/%d", nm_utils_inet6_ntop (&address, NULL), plen); + return klass->ip6_address_delete (platform, ifindex, address, plen); +} + +gboolean +nm_platform_ip4_address_exists (int ifindex, in_addr_t address, int plen) +{ + reset_error (); + + g_return_val_if_fail (plen > 0, FALSE); + g_return_val_if_fail (klass->ip4_address_exists, FALSE); + + return klass->ip4_address_exists (platform, ifindex, address, plen); +} + +gboolean +nm_platform_ip6_address_exists (int ifindex, struct in6_addr address, int plen) +{ + reset_error (); + + g_return_val_if_fail (plen > 0, FALSE); + g_return_val_if_fail (klass->ip6_address_exists, FALSE); + + return klass->ip6_address_exists (platform, ifindex, address, plen); +} + +static gboolean +array_contains_ip4_address (const GArray *addresses, const NMPlatformIP4Address *address) +{ + guint len = addresses ? addresses->len : 0; + guint i; + + for (i = 0; i < len; i++) { + NMPlatformIP4Address *candidate = &g_array_index (addresses, NMPlatformIP4Address, i); + + if (candidate->address == address->address && candidate->plen == address->plen) + return TRUE; + } + + return FALSE; +} + +static gboolean +array_contains_ip6_address (const GArray *addresses, const NMPlatformIP6Address *address) +{ + guint len = addresses ? addresses->len : 0; + guint i; + + for (i = 0; i < len; i++) { + NMPlatformIP6Address *candidate = &g_array_index (addresses, NMPlatformIP6Address, i); + + if (IN6_ARE_ADDR_EQUAL (&candidate->address, &address->address) && candidate->plen == address->plen) + return TRUE; + } + + return FALSE; +} + +/** + * Takes a pair @timestamp and @duration, and returns the remaining duration based + * on the new timestamp @now. + */ +static guint32 +_rebase_relative_time_on_now (guint32 timestamp, guint32 duration, guint32 now, guint32 padding) +{ + gint64 t; + + if (duration == NM_PLATFORM_LIFETIME_PERMANENT) + return NM_PLATFORM_LIFETIME_PERMANENT; + + if (timestamp == 0) { + /* if the @timestamp is zero, assume it was just left unset and that the relative + * @duration starts counting from @now. This is convenient to construct an address + * and print it in nm_platform_ip4_address_to_string(). + * + * In general it does not make sense to set the @duration without anchoring at + * @timestamp because you don't know the absolute expiration time when looking + * at the address at a later moment. */ + timestamp = now; + } + + /* For timestamp > now, just accept it and calculate the expected(?) result. */ + t = (gint64) timestamp + (gint64) duration - (gint64) now; + + /* Optional padding to avoid potential races. */ + t += (gint64) padding; + + if (t <= 0) + return 0; + if (t >= NM_PLATFORM_LIFETIME_PERMANENT) + return NM_PLATFORM_LIFETIME_PERMANENT - 1; + return t; +} + +static gboolean +_address_get_lifetime (const NMPlatformIPAddress *address, guint32 now, guint32 padding, guint32 *out_lifetime, guint32 *out_preferred) +{ + gint32 lifetime, preferred; + + if (address->lifetime == 0) { + *out_lifetime = NM_PLATFORM_LIFETIME_PERMANENT; + *out_preferred = NM_PLATFORM_LIFETIME_PERMANENT; + } else { + lifetime = _rebase_relative_time_on_now (address->timestamp, address->lifetime, now, padding); + if (!lifetime) + return FALSE; + preferred = _rebase_relative_time_on_now (address->timestamp, address->preferred, now, padding); + + *out_lifetime = lifetime; + *out_preferred = MIN (preferred, lifetime); + + /* Assert that non-permanent addresses have a (positive) @timestamp. _rebase_relative_time_on_now() + * treats addresses with timestamp 0 as *now*. Addresses passed to _address_get_lifetime() always + * should have a valid @timestamp, otherwise on every re-sync, their lifetime will be extended anew. + */ + g_return_val_if_fail ( address->timestamp != 0 + || ( address->lifetime == NM_PLATFORM_LIFETIME_PERMANENT + && address->preferred == NM_PLATFORM_LIFETIME_PERMANENT), TRUE); + g_return_val_if_fail (preferred <= lifetime, TRUE); + } + return TRUE; +} + +/** + * nm_platform_ip4_address_sync: + * @ifindex: Interface index + * @known_addresses: List of addresses + * + * A convenience function to synchronize addresses for a specific interface + * with the least possible disturbance. It simply removes addresses that are + * not listed and adds addresses that are. + * + * Returns: %TRUE on success. + */ +gboolean +nm_platform_ip4_address_sync (int ifindex, const GArray *known_addresses) +{ + GArray *addresses; + NMPlatformIP4Address *address; + guint32 now = nm_utils_get_monotonic_timestamp_s (); + int i; + + /* Delete unknown addresses */ + addresses = nm_platform_ip4_address_get_all (ifindex); + for (i = 0; i < addresses->len; i++) { + address = &g_array_index (addresses, NMPlatformIP4Address, i); + + if (!array_contains_ip4_address (known_addresses, address)) + nm_platform_ip4_address_delete (ifindex, address->address, address->plen); + } + g_array_free (addresses, TRUE); + + if (!known_addresses) + return TRUE; + + /* Add missing addresses */ + for (i = 0; i < known_addresses->len; i++) { + const NMPlatformIP4Address *known_address = &g_array_index (known_addresses, NMPlatformIP4Address, i); + guint32 lifetime, preferred; + + /* add a padding of 5 seconds to avoid potential races. */ + if (!_address_get_lifetime ((NMPlatformIPAddress *) known_address, now, 5, &lifetime, &preferred)) + continue; + + if (!nm_platform_ip4_address_add (ifindex, known_address->address, known_address->peer_address, known_address->plen, lifetime, preferred, known_address->label)) + return FALSE; + } + + return TRUE; +} + +/** + * nm_platform_ip6_address_sync: + * @ifindex: Interface index + * @known_addresses: List of addresses + * + * A convenience function to synchronize addresses for a specific interface + * with the least possible disturbance. It simply removes addresses that are + * not listed and adds addresses that are. + * + * Returns: %TRUE on success. + */ +gboolean +nm_platform_ip6_address_sync (int ifindex, const GArray *known_addresses) +{ + GArray *addresses; + NMPlatformIP6Address *address; + guint32 now = nm_utils_get_monotonic_timestamp_s (); + int i; + + /* Delete unknown addresses */ + addresses = nm_platform_ip6_address_get_all (ifindex); + for (i = 0; i < addresses->len; i++) { + address = &g_array_index (addresses, NMPlatformIP6Address, i); + + /* Leave link local address management to the kernel */ + if (IN6_IS_ADDR_LINKLOCAL (&address->address)) + continue; + + if (!array_contains_ip6_address (known_addresses, address)) + nm_platform_ip6_address_delete (ifindex, address->address, address->plen); + } + g_array_free (addresses, TRUE); + + if (!known_addresses) + return TRUE; + + /* Add missing addresses */ + for (i = 0; i < known_addresses->len; i++) { + const NMPlatformIP6Address *known_address = &g_array_index (known_addresses, NMPlatformIP6Address, i); + guint32 lifetime, preferred; + + /* add a padding of 5 seconds to avoid potential races. */ + if (!_address_get_lifetime ((NMPlatformIPAddress *) known_address, now, 5, &lifetime, &preferred)) + continue; + + if (!nm_platform_ip6_address_add (ifindex, known_address->address, + known_address->peer_address, known_address->plen, + lifetime, preferred, known_address->flags)) + return FALSE; + } + + return TRUE; +} + +gboolean +nm_platform_address_flush (int ifindex) +{ + return nm_platform_ip4_address_sync (ifindex, NULL) + && nm_platform_ip6_address_sync (ifindex, NULL); +} + +/******************************************************************/ + +GArray * +nm_platform_ip4_route_get_all (int ifindex, gboolean include_default) +{ + reset_error (); + + g_return_val_if_fail (ifindex > 0, NULL); + g_return_val_if_fail (klass->ip4_route_get_all, NULL); + + return klass->ip4_route_get_all (platform, ifindex, include_default); +} + +GArray * +nm_platform_ip6_route_get_all (int ifindex, gboolean include_default) +{ + reset_error (); + + g_return_val_if_fail (ifindex > 0, NULL); + g_return_val_if_fail (klass->ip6_route_get_all, NULL); + + return klass->ip6_route_get_all (platform, ifindex, include_default); +} + +gboolean +nm_platform_ip4_route_add (int ifindex, NMPlatformSource source, + in_addr_t network, int plen, + in_addr_t gateway, int metric, int mss) +{ + reset_error (); + + g_return_val_if_fail (platform, FALSE); + g_return_val_if_fail (0 <= plen && plen <= 32, FALSE); + g_return_val_if_fail (metric >= 0, FALSE); + g_return_val_if_fail (mss >= 0, FALSE); + g_return_val_if_fail (klass->ip4_route_add, FALSE); + + if (nm_logging_enabled (LOGL_DEBUG, LOGD_PLATFORM)) { + NMPlatformIP4Route route = { 0 }; + + route.ifindex = ifindex; + route.source = source; + route.network = network; + route.plen = plen; + route.gateway = gateway; + route.metric = metric; + route.mss = mss; + + debug ("route: adding or updating IPv4 route: %s", nm_platform_ip4_route_to_string (&route)); + } + return klass->ip4_route_add (platform, ifindex, source, network, plen, gateway, metric, mss); +} + +gboolean +nm_platform_ip6_route_add (int ifindex, NMPlatformSource source, + struct in6_addr network, int plen, struct in6_addr gateway, + int metric, int mss) +{ + g_return_val_if_fail (platform, FALSE); + g_return_val_if_fail (0 <= plen && plen <= 128, FALSE); + g_return_val_if_fail (metric >= 0, FALSE); + g_return_val_if_fail (mss >= 0, FALSE); + g_return_val_if_fail (klass->ip6_route_add, FALSE); + + if (nm_logging_enabled (LOGL_DEBUG, LOGD_PLATFORM)) { + NMPlatformIP6Route route = { 0 }; + + route.ifindex = ifindex; + route.source = source; + route.network = network; + route.plen = plen; + route.gateway = gateway; + route.metric = metric; + route.mss = mss; + + debug ("route: adding or updating IPv6 route: %s", nm_platform_ip6_route_to_string (&route)); + } + return klass->ip6_route_add (platform, ifindex, source, network, plen, gateway, metric, mss); +} + +gboolean +nm_platform_ip4_route_delete (int ifindex, in_addr_t network, int plen, int metric) +{ + reset_error (); + + g_return_val_if_fail (platform, FALSE); + g_return_val_if_fail (klass->ip4_route_delete, FALSE); + + debug ("route: deleting IPv4 route %s/%d, metric=%d", nm_utils_inet4_ntop (network, NULL), plen, metric); + return klass->ip4_route_delete (platform, ifindex, network, plen, metric); +} + +gboolean +nm_platform_ip6_route_delete (int ifindex, struct in6_addr network, int plen, int metric) +{ + reset_error (); + + g_return_val_if_fail (platform, FALSE); + g_return_val_if_fail (klass->ip6_route_delete, FALSE); + + debug ("route: deleting IPv6 route %s/%d, metric=%d", nm_utils_inet6_ntop (&network, NULL), plen, metric); + return klass->ip6_route_delete (platform, ifindex, network, plen, metric); +} + +gboolean +nm_platform_ip4_route_exists (int ifindex, in_addr_t network, int plen, int metric) +{ + reset_error (); + + g_return_val_if_fail (platform, FALSE); + g_return_val_if_fail (klass->ip4_route_exists, FALSE); + + return klass->ip4_route_exists (platform,ifindex, network, plen, metric); +} + +gboolean +nm_platform_ip6_route_exists (int ifindex, struct in6_addr network, int plen, int metric) +{ + reset_error (); + + g_return_val_if_fail (platform, FALSE); + g_return_val_if_fail (klass->ip6_route_exists, FALSE); + + return klass->ip6_route_exists (platform, ifindex, network, plen, metric); +} + +static gboolean +array_contains_ip4_route (const GArray *routes, const NMPlatformIP4Route *route) +{ + guint len = routes ? routes->len : 0; + guint i; + + for (i = 0; i < len; i++) { + NMPlatformIP4Route *c = &g_array_index (routes, NMPlatformIP4Route, i); + + if (route->network == c->network && + route->plen == c->plen && + route->gateway == c->gateway && + route->metric == c->metric) + return TRUE; + } + + return FALSE; +} + +static gboolean +array_contains_ip6_route (const GArray *routes, const NMPlatformIP6Route *route) +{ + guint len = routes ? routes->len : 0; + guint i; + + for (i = 0; i < len; i++) { + NMPlatformIP6Route *c = &g_array_index (routes, NMPlatformIP6Route, i); + + if (IN6_ARE_ADDR_EQUAL (&route->network, &c->network) && + route->plen == c->plen && + IN6_ARE_ADDR_EQUAL (&route->gateway, &c->gateway) && + route->metric == c->metric) + return TRUE; + } + + return FALSE; +} + +/** + * nm_platform_ip4_route_sync: + * @ifindex: Interface index + * @known_routes: List of routes + * + * A convenience function to synchronize routes for a specific interface + * with the least possible disturbance. It simply removes routes that are + * not listed and adds routes that are. + * + * Returns: %TRUE on success. + */ +gboolean +nm_platform_ip4_route_sync (int ifindex, const GArray *known_routes) +{ + GArray *routes; + NMPlatformIP4Route *route; + const NMPlatformIP4Route *known_route; + gboolean success; + int i, i_type; + + /* Delete unknown routes */ + routes = nm_platform_ip4_route_get_all (ifindex, FALSE); + for (i = 0; i < routes->len; i++) { + route = &g_array_index (routes, NMPlatformIP4Route, i); + + if (!array_contains_ip4_route (known_routes, route)) + nm_platform_ip4_route_delete (ifindex, route->network, route->plen, route->metric); + } + + if (!known_routes) { + g_array_free (routes, TRUE); + return TRUE; + } + + /* Add missing routes */ + for (i_type = 0, success = TRUE; i_type < 2 && success; i_type++) { + for (i = 0; i < known_routes->len && success; i++) { + known_route = &g_array_index (known_routes, NMPlatformIP4Route, i); + + if ((known_route->gateway == 0) ^ (i_type != 0)) { + /* Make two runs over the list of routes. On the first, only add + * device routes, on the second the others (gateway routes). */ + continue; + } + + /* Ignore routes that already exist */ + if (!array_contains_ip4_route (routes, known_route)) { + success = nm_platform_ip4_route_add (ifindex, + known_route->source, + known_route->network, + known_route->plen, + known_route->gateway, + known_route->metric, + known_route->mss); + if (!success && known_route->source < NM_PLATFORM_SOURCE_USER) { + nm_log_dbg (LOGD_PLATFORM, "ignore error adding IPv4 route to kernel: %s", + nm_platform_ip4_route_to_string (known_route)); + success = TRUE; + } + } + } + } + + g_array_free (routes, TRUE); + return success; +} + +/** + * nm_platform_ip6_route_sync: + * @ifindex: Interface index + * @known_routes: List of routes + * + * A convenience function to synchronize routes for a specific interface + * with the least possible disturbance. It simply removes routes that are + * not listed and adds routes that are. + * + * Returns: %TRUE on success. + */ +gboolean +nm_platform_ip6_route_sync (int ifindex, const GArray *known_routes) +{ + GArray *routes; + NMPlatformIP6Route *route; + const NMPlatformIP6Route *known_route; + gboolean success; + int i, i_type; + + /* Delete unknown routes */ + routes = nm_platform_ip6_route_get_all (ifindex, FALSE); + for (i = 0; i < routes->len; i++) { + route = &g_array_index (routes, NMPlatformIP6Route, i); + route->ifindex = 0; + + if (!array_contains_ip6_route (known_routes, route)) + nm_platform_ip6_route_delete (ifindex, route->network, route->plen, route->metric); + } + + if (!known_routes) { + g_array_free (routes, TRUE); + return TRUE; + } + + /* Add missing routes */ + for (i_type = 0, success = TRUE; i_type < 2 && success; i_type++) { + for (i = 0; i < known_routes->len && success; i++) { + known_route = &g_array_index (known_routes, NMPlatformIP6Route, i); + + if (IN6_IS_ADDR_UNSPECIFIED (&known_route->gateway) ^ (i_type != 0)) { + /* Make two runs over the list of routes. On the first, only add + * device routes, on the second the others (gateway routes). */ + continue; + } + + /* Ignore routes that already exist */ + if (!array_contains_ip6_route (routes, known_route)) { + success = nm_platform_ip6_route_add (ifindex, + known_route->source, + known_route->network, + known_route->plen, + known_route->gateway, + known_route->metric, + known_route->mss); + if (!success && known_route->source < NM_PLATFORM_SOURCE_USER) { + nm_log_dbg (LOGD_PLATFORM, "ignore error adding IPv6 route to kernel: %s", + nm_platform_ip6_route_to_string (known_route)); + success = TRUE; + } + } + } + } + + g_array_free (routes, TRUE); + return success; +} + +gboolean +nm_platform_route_flush (int ifindex) +{ + return nm_platform_ip4_route_sync (ifindex, NULL) + && nm_platform_ip6_route_sync (ifindex, NULL); +} + +/******************************************************************/ + +static const char * +source_to_string (NMPlatformSource source) +{ + switch (source) { + case NM_PLATFORM_SOURCE_KERNEL: + return "kernel"; + case NM_PLATFORM_SOURCE_SHARED: + return "shared"; + case NM_PLATFORM_SOURCE_IP4LL: + return "ipv4ll"; + case NM_PLATFORM_SOURCE_PPP: + return "ppp"; + case NM_PLATFORM_SOURCE_WWAN: + return "wwan"; + case NM_PLATFORM_SOURCE_VPN: + return "vpn"; + case NM_PLATFORM_SOURCE_DHCP: + return "dhcp"; + case NM_PLATFORM_SOURCE_RDISC: + return "rdisc"; + case NM_PLATFORM_SOURCE_USER: + return "user"; + default: + break; + } + return "unknown"; +} + +#define TO_STRING_DEV_BUF_SIZE (5+15+1) +static void +_to_string_dev (int ifindex, char *buf, size_t size) +{ + g_assert (buf && size >= TO_STRING_DEV_BUF_SIZE); + + if (ifindex){ + const char *name = ifindex > 0 ? nm_platform_link_get_name (ifindex) : NULL; + + strcpy (buf, " dev "); + buf += 5; + size -= 5; + + if (name) + g_strlcpy (buf, name, size); + else + g_snprintf (buf, size, "%d", ifindex); + } else + buf[0] = 0; +} + +static const char * +_lifetime_to_string (guint32 timestamp, guint32 lifetime, gint32 now, char *buf, size_t buf_size) +{ + if (lifetime == NM_PLATFORM_LIFETIME_PERMANENT) + return "forever"; + + g_snprintf (buf, buf_size, "%usec", + _rebase_relative_time_on_now (timestamp, lifetime, now, 0)); + return buf; +} + + +static const char * +_lifetime_summary_to_string (gint32 now, guint32 timestamp, guint32 preferred, guint32 lifetime, char *buf, size_t buf_size) +{ + g_snprintf (buf, buf_size, " lifetime %d-%u[%u,%u]", + (signed) now, (unsigned) timestamp, (unsigned) preferred, (unsigned) lifetime); + return buf; +} + +static char to_string_buffer[256]; + +const char * +nm_platform_link_to_string (const NMPlatformLink *link) +{ + char master[20]; + char parent[20]; + char *driver, *udi, *type; + GString *str; + + if (!link) + return "(unknown link)"; + + str = g_string_new (NULL); + if (!link->arp) + g_string_append (str, "NOARP,"); + if (link->up) + g_string_append (str, "UP"); + else + g_string_append (str, "DOWN"); + if (link->connected) + g_string_append (str, ",LOWER_UP"); + + if (link->master) + g_snprintf (master, sizeof (master), " master %d", link->master); + else + master[0] = 0; + + if (link->parent) + g_snprintf (parent, sizeof (master), "@%d", link->parent); + else + parent[0] = 0; + + driver = link->driver ? g_strdup_printf (" driver '%s'", link->driver) : NULL; + udi = link->udi ? g_strdup_printf (" udi '%s'", link->udi) : NULL; + type = link->type_name ? NULL : g_strdup_printf ("(%d)", link->type); + + g_snprintf (to_string_buffer, sizeof (to_string_buffer), "%d: %s%s <%s> mtu %d%s %s%s%s", + link->ifindex, link->name, parent, str->str, + link->mtu, master, link->type_name ? link->type_name : type, + driver ? driver : "", udi ? udi : ""); + g_string_free (str, TRUE); + g_free (driver); + g_free (udi); + g_free (type); + return to_string_buffer; +} + +/** + * nm_platform_ip4_address_to_string: + * @route: pointer to NMPlatformIP4Address address structure + * + * A method for converting an address struct into a string representation. + * + * Example output: "" + * + * Returns: a string representation of the address. The returned string + * is an internal buffer, so do not keep or free the returned string. + * Also, this function is not thread safe. + */ +const char * +nm_platform_ip4_address_to_string (const NMPlatformIP4Address *address) +{ + char s_address[INET_ADDRSTRLEN]; + char s_peer[INET_ADDRSTRLEN]; + char str_dev[TO_STRING_DEV_BUF_SIZE]; + char str_label[32]; + char str_lft[30], str_pref[30], str_time[50]; + char *str_peer = NULL; + const char *str_lft_p, *str_pref_p, *str_time_p; + gint32 now = nm_utils_get_monotonic_timestamp_s (); + + g_return_val_if_fail (address, "(unknown)"); + + inet_ntop (AF_INET, &address->address, s_address, sizeof (s_address)); + + if (address->peer_address) { + inet_ntop (AF_INET, &address->peer_address, s_peer, sizeof (s_peer)); + str_peer = g_strconcat (" ptp ", s_peer, NULL); + } + + _to_string_dev (address->ifindex, str_dev, sizeof (str_dev)); + + if (*address->label) + g_snprintf (str_label, sizeof (str_label), " label %s", address->label); + else + str_label[0] = 0; + + str_lft_p = _lifetime_to_string (address->timestamp, + address->lifetime ? address->lifetime : NM_PLATFORM_LIFETIME_PERMANENT, + now, str_lft, sizeof (str_lft)), + str_pref_p = (address->lifetime == address->preferred) + ? str_lft_p + : ( _lifetime_to_string (address->timestamp, + address->lifetime ? MIN (address->preferred, address->lifetime) : NM_PLATFORM_LIFETIME_PERMANENT, + now, str_pref, sizeof (str_pref)) ); + str_time_p = _lifetime_summary_to_string (now, address->timestamp, address->preferred, address->lifetime, str_time, sizeof (str_time)); + + g_snprintf (to_string_buffer, sizeof (to_string_buffer), "%s/%d lft %s pref %s%s%s%s%s src %s", + s_address, address->plen, str_lft_p, str_pref_p, str_time_p, + str_peer ? str_peer : "", + str_dev, + str_label, + source_to_string (address->source)); + g_free (str_peer); + return to_string_buffer; +} + +/** + * nm_platform_addr_flags2str: wrapper for rtnl_addr_flags2str(), + * which might not yet support some recent address flags. + **/ +void +nm_platform_addr_flags2str (int flags, char *buf, size_t size) +{ + rtnl_addr_flags2str(flags, buf, size); + + /* There are two recent flags IFA_F_MANAGETEMPADDR and IFA_F_NOPREFIXROUTE. + * If libnl does not yet support them, add them by hand. + * These two flags were introduced together with the extended ifa_flags, + * so, check for that. + */ + if ((flags & IFA_F_MANAGETEMPADDR) && !nm_platform_check_support_libnl_extended_ifa_flags ()) { + strncat (buf, buf[0] ? "," IFA_F_MANAGETEMPADDR_STR : IFA_F_MANAGETEMPADDR_STR, + size - strlen (buf) - 1); + } + if ((flags & IFA_F_NOPREFIXROUTE) && !nm_platform_check_support_libnl_extended_ifa_flags ()) { + strncat (buf, buf[0] ? "," IFA_F_NOPREFIXROUTE_STR : IFA_F_NOPREFIXROUTE_STR, + size - strlen (buf) - 1); + } +} + +/** + * nm_platform_ip6_address_to_string: + * @route: pointer to NMPlatformIP6Address address structure + * + * A method for converting an address struct into a string representation. + * + * Example output: "2001:db8:0:f101::1/64 lft 4294967295 pref 4294967295 time 16922666 on dev em1" + * + * Returns: a string representation of the address. The returned string + * is an internal buffer, so do not keep or free the returned string. + * Also, this function is not thread safe. + */ +const char * +nm_platform_ip6_address_to_string (const NMPlatformIP6Address *address) +{ + char s_flags[256]; + char s_address[INET6_ADDRSTRLEN]; + char s_peer[INET6_ADDRSTRLEN]; + char str_lft[30], str_pref[30], str_time[50]; + char str_dev[TO_STRING_DEV_BUF_SIZE]; + char *str_flags; + char *str_peer = NULL; + const char *str_lft_p, *str_pref_p, *str_time_p; + gint32 now = nm_utils_get_monotonic_timestamp_s (); + + g_return_val_if_fail (address, "(unknown)"); + + inet_ntop (AF_INET6, &address->address, s_address, sizeof (s_address)); + + if (!IN6_IS_ADDR_UNSPECIFIED (&address->peer_address)) { + inet_ntop (AF_INET6, &address->peer_address, s_peer, sizeof (s_peer)); + str_peer = g_strconcat (" ptp ", s_peer, NULL); + } + + _to_string_dev (address->ifindex, str_dev, sizeof (str_dev)); + + nm_platform_addr_flags2str (address->flags, s_flags, sizeof (s_flags)); + + str_flags = s_flags[0] ? g_strconcat (" flags ", s_flags, NULL) : NULL; + + str_lft_p = _lifetime_to_string (address->timestamp, + address->lifetime ? address->lifetime : NM_PLATFORM_LIFETIME_PERMANENT, + now, str_lft, sizeof (str_lft)), + str_pref_p = (address->lifetime == address->preferred) + ? str_lft_p + : ( _lifetime_to_string (address->timestamp, + address->lifetime ? MIN (address->preferred, address->lifetime) : NM_PLATFORM_LIFETIME_PERMANENT, + now, str_pref, sizeof (str_pref)) ); + str_time_p = _lifetime_summary_to_string (now, address->timestamp, address->preferred, address->lifetime, str_time, sizeof (str_time)); + + g_snprintf (to_string_buffer, sizeof (to_string_buffer), "%s/%d lft %s pref %s%s%s%s%s src %s", + s_address, address->plen, str_lft_p, str_pref_p, str_time_p, + str_peer ? str_peer : "", + str_dev, + str_flags ? str_flags : "", + source_to_string (address->source)); + g_free (str_flags); + g_free (str_peer); + return to_string_buffer; +} + +/** + * nm_platform_ip4_route_to_string: + * @route: pointer to NMPlatformIP4Route route structure + * + * A method for converting a route struct into a string representation. + * + * Example output: "192.168.1.0/24 via 0.0.0.0 dev em1 metric 0 mss 0" + * + * Returns: a string representation of the route. The returned string + * is an internal buffer, so do not keep or free the returned string. + * Also, this function is not thread safe. + */ +const char * +nm_platform_ip4_route_to_string (const NMPlatformIP4Route *route) +{ + char s_network[INET_ADDRSTRLEN], s_gateway[INET_ADDRSTRLEN]; + char str_dev[TO_STRING_DEV_BUF_SIZE]; + + g_return_val_if_fail (route, "(unknown)"); + + inet_ntop (AF_INET, &route->network, s_network, sizeof(s_network)); + inet_ntop (AF_INET, &route->gateway, s_gateway, sizeof(s_gateway)); + + _to_string_dev (route->ifindex, str_dev, sizeof (str_dev)); + + g_snprintf (to_string_buffer, sizeof (to_string_buffer), "%s/%d via %s%s metric %u mss %u src %s", + s_network, route->plen, s_gateway, + str_dev, + route->metric, route->mss, + source_to_string (route->source)); + return to_string_buffer; +} + +/** + * nm_platform_ip6_route_to_string: + * @route: pointer to NMPlatformIP6Route route structure + * + * A method for converting a route struct into a string representation. + * + * Example output: "ff02::fb/128 via :: dev em1 metric 0" + * + * Returns: a string representation of the route. The returned string + * is an internal buffer, so do not keep or free the returned string. + * Also, this function is not thread safe. + */ +const char * +nm_platform_ip6_route_to_string (const NMPlatformIP6Route *route) +{ + char s_network[INET6_ADDRSTRLEN], s_gateway[INET6_ADDRSTRLEN]; + char str_dev[TO_STRING_DEV_BUF_SIZE]; + + g_return_val_if_fail (route, "(unknown)"); + + inet_ntop (AF_INET6, &route->network, s_network, sizeof(s_network)); + inet_ntop (AF_INET6, &route->gateway, s_gateway, sizeof(s_gateway)); + + _to_string_dev (route->ifindex, str_dev, sizeof (str_dev)); + + g_snprintf (to_string_buffer, sizeof (to_string_buffer), "%s/%d via %s%s metric %u mss %u src %s", + s_network, route->plen, s_gateway, + str_dev, + route->metric, route->mss, + source_to_string (route->source)); + return to_string_buffer; +} + +#define _CMP_POINTER(a, b) \ + G_STMT_START { \ + if ((a) == (b)) \ + return 0; \ + if (!(a)) \ + return -1; \ + if (!(b)) \ + return 1; \ + } G_STMT_END + +#define _CMP_FIELD(a, b, field) \ + G_STMT_START { \ + if (((a)->field) != ((b)->field)) \ + return (((a)->field) < ((b)->field)) ? -1 : 1; \ + } G_STMT_END + +#define _CMP_FIELD_STR(a, b, field) \ + G_STMT_START { \ + int c = strcmp ((a)->field, (b)->field); \ + if (c != 0) \ + return c < 0 ? -1 : 1; \ + } G_STMT_END + +#define _CMP_FIELD_STR0(a, b, field) \ + G_STMT_START { \ + int c = g_strcmp0 ((a)->field, (b)->field); \ + if (c != 0) \ + return c < 0 ? -1 : 1; \ + } G_STMT_END + +#define _CMP_FIELD_MEMCMP(a, b, field) \ + G_STMT_START { \ + int c = memcmp (&((a)->field), &((b)->field), \ + sizeof ((a)->field)); \ + if (c != 0) \ + return c < 0 ? -1 : 1; \ + } G_STMT_END + +int +nm_platform_link_cmp (const NMPlatformLink *a, const NMPlatformLink *b) +{ + _CMP_POINTER (a, b); + _CMP_FIELD (a, b, type); + _CMP_FIELD_STR (a, b, name); + _CMP_FIELD (a, b, master); + _CMP_FIELD (a, b, parent); + _CMP_FIELD (a, b, up); + _CMP_FIELD (a, b, connected); + _CMP_FIELD (a, b, arp); + _CMP_FIELD (a, b, mtu); + _CMP_FIELD_STR0 (a, b, type_name); + _CMP_FIELD_STR0 (a, b, udi); + _CMP_FIELD_STR0 (a, b, driver); + return 0; +} + +int +nm_platform_ip4_address_cmp (const NMPlatformIP4Address *a, const NMPlatformIP4Address *b) +{ + _CMP_POINTER (a, b); + _CMP_FIELD (a, b, ifindex); + _CMP_FIELD (a, b, source); + _CMP_FIELD (a, b, address); + _CMP_FIELD (a, b, peer_address); + _CMP_FIELD (a, b, plen); + _CMP_FIELD (a, b, timestamp); + _CMP_FIELD (a, b, lifetime); + _CMP_FIELD (a, b, preferred); + _CMP_FIELD_STR (a, b, label); + return 0; +} + +int +nm_platform_ip6_address_cmp (const NMPlatformIP6Address *a, const NMPlatformIP6Address *b) +{ + _CMP_POINTER (a, b); + _CMP_FIELD (a, b, ifindex); + _CMP_FIELD (a, b, source); + _CMP_FIELD_MEMCMP (a, b, address); + _CMP_FIELD_MEMCMP (a, b, peer_address); + _CMP_FIELD (a, b, plen); + _CMP_FIELD (a, b, timestamp); + _CMP_FIELD (a, b, lifetime); + _CMP_FIELD (a, b, preferred); + _CMP_FIELD (a, b, flags); + return 0; +} + +int +nm_platform_ip4_route_cmp (const NMPlatformIP4Route *a, const NMPlatformIP4Route *b) +{ + _CMP_POINTER (a, b); + _CMP_FIELD (a, b, ifindex); + _CMP_FIELD (a, b, source); + _CMP_FIELD (a, b, network); + _CMP_FIELD (a, b, plen); + _CMP_FIELD (a, b, gateway); + _CMP_FIELD (a, b, metric); + _CMP_FIELD (a, b, mss); + return 0; +} + +int +nm_platform_ip6_route_cmp (const NMPlatformIP6Route *a, const NMPlatformIP6Route *b) +{ + _CMP_POINTER (a, b); + _CMP_FIELD (a, b, ifindex); + _CMP_FIELD (a, b, source); + _CMP_FIELD_MEMCMP (a, b, network); + _CMP_FIELD (a, b, plen); + _CMP_FIELD_MEMCMP (a, b, gateway); + _CMP_FIELD (a, b, metric); + _CMP_FIELD (a, b, mss); + return 0; +} + +#undef _CMP_FIELD +#undef _CMP_FIELD_MEMCMP + +/** + * nm_platform_ip_address_cmp_expiry: + * @a: a NMPlatformIPAddress to compare + * @b: the other NMPlatformIPAddress to compare + * + * Compares two addresses and returns which one has a longer remaining lifetime. + * If both addresses have the same lifetime, look at the remaining preferred time. + * + * For comparison, only the timestamp, lifetime and preferred fields are considered. + * If they compare equal (== 0), their other fields were not considered. + * + * Returns: -1, 0, or 1 according to the comparison + **/ +int +nm_platform_ip_address_cmp_expiry (const NMPlatformIPAddress *a, const NMPlatformIPAddress *b) +{ + gint64 ta = 0, tb = 0; + + _CMP_POINTER (a, b); + + if (a->lifetime == NM_PLATFORM_LIFETIME_PERMANENT || a->lifetime == 0) + ta = G_MAXINT64; + else if (a->timestamp) + ta = ((gint64) a->timestamp) + a->lifetime; + + if (b->lifetime == NM_PLATFORM_LIFETIME_PERMANENT || b->lifetime == 0) + tb = G_MAXINT64; + else if (b->timestamp) + tb = ((gint64) b->timestamp) + b->lifetime; + + if (ta == tb) { + /* if the lifetime is equal, compare the preferred time. */ + ta = tb = 0; + + if (a->preferred == NM_PLATFORM_LIFETIME_PERMANENT || a->lifetime == 0 /* liftime==0 means permanent! */) + ta = G_MAXINT64; + else if (a->timestamp) + ta = ((gint64) a->timestamp) + a->preferred; + + if (b->preferred == NM_PLATFORM_LIFETIME_PERMANENT|| b->lifetime == 0) + tb = G_MAXINT64; + else if (b->timestamp) + tb = ((gint64) b->timestamp) + b->preferred; + + if (ta == tb) + return 0; + } + + return ta < tb ? -1 : 1; +} + +#undef _CMP_POINTER + +static const char * +_change_type_to_string (NMPlatformSignalChangeType change_type) +{ + switch (change_type) { + case NM_PLATFORM_SIGNAL_ADDED: + return "added"; + case NM_PLATFORM_SIGNAL_CHANGED: + return "changed"; + case NM_PLATFORM_SIGNAL_REMOVED: + return "removed"; + default: + g_return_val_if_reached ("UNKNOWN"); + } +} + +static void +log_link (NMPlatform *p, int ifindex, NMPlatformLink *device, NMPlatformSignalChangeType change_type, gpointer user_data) +{ + + debug ("signal: link %7s: %s", _change_type_to_string (change_type), nm_platform_link_to_string (device)); +} + +static void +log_ip4_address (NMPlatform *p, int ifindex, NMPlatformIP4Address *address, NMPlatformSignalChangeType change_type, gpointer user_data) +{ + debug ("signal: address 4 %7s: %s", _change_type_to_string (change_type), nm_platform_ip4_address_to_string (address)); +} + +static void +log_ip6_address (NMPlatform *p, int ifindex, NMPlatformIP6Address *address, NMPlatformSignalChangeType change_type, gpointer user_data) +{ + debug ("signal: address 6 %7s: %s", _change_type_to_string (change_type), nm_platform_ip6_address_to_string (address)); +} + +static void +log_ip4_route (NMPlatform *p, int ifindex, NMPlatformIP4Route *route, NMPlatformSignalChangeType change_type, gpointer user_data) +{ + debug ("signal: route 4 %7s: %s", _change_type_to_string (change_type), nm_platform_ip4_route_to_string (route)); +} + +static void +log_ip6_route (NMPlatform *p, int ifindex, NMPlatformIP6Route *route, NMPlatformSignalChangeType change_type, gpointer user_data) +{ + debug ("signal: route 6 %7s: %s", _change_type_to_string (change_type), nm_platform_ip6_route_to_string (route)); +} + +/******************************************************************/ + +static void +nm_platform_init (NMPlatform *object) +{ +} + +#define SIGNAL(signal_id, method) signals[signal_id] = \ + g_signal_new_class_handler (NM_PLATFORM_ ## signal_id, \ + G_OBJECT_CLASS_TYPE (object_class), \ + G_SIGNAL_RUN_FIRST, \ + G_CALLBACK (method), \ + NULL, NULL, NULL, \ + G_TYPE_NONE, 4, G_TYPE_INT, G_TYPE_POINTER, NM_TYPE_PLATFORM_SIGNAL_CHANGE_TYPE, NM_TYPE_PLATFORM_REASON); + +static void +nm_platform_class_init (NMPlatformClass *platform_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (platform_class); + + /* Signals */ + SIGNAL (SIGNAL_LINK_CHANGED, log_link) + SIGNAL (SIGNAL_IP4_ADDRESS_CHANGED, log_ip4_address) + SIGNAL (SIGNAL_IP6_ADDRESS_CHANGED, log_ip6_address) + SIGNAL (SIGNAL_IP4_ROUTE_CHANGED, log_ip4_route) + SIGNAL (SIGNAL_IP6_ROUTE_CHANGED, log_ip6_route) +} diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h new file mode 100644 index 00000000..96b6cfab --- /dev/null +++ b/src/platform/nm-platform.h @@ -0,0 +1,634 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* nm-platform.c - Handle runtime kernel networking configuration + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2009 - 2010 Red Hat, Inc. + */ + +#ifndef NM_PLATFORM_H +#define NM_PLATFORM_H + +#include +#include "nm-glib-compat.h" +#include +#include +#include +#include + +#include + +#define NM_TYPE_PLATFORM (nm_platform_get_type ()) +#define NM_PLATFORM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_PLATFORM, NMPlatform)) +#define NM_PLATFORM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_PLATFORM, NMPlatformClass)) +#define NM_IS_PLATFORM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_PLATFORM)) +#define NM_IS_PLATFORM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_PLATFORM)) +#define NM_PLATFORM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_PLATFORM, NMPlatformClass)) + +/******************************************************************/ + +/* workaround for older libnl version, that does not define these flags. */ +#ifndef IFA_F_MANAGETEMPADDR +#define IFA_F_MANAGETEMPADDR 0x100 +#endif +#ifndef IFA_F_NOPREFIXROUTE +#define IFA_F_NOPREFIXROUTE 0x200 +#endif + +typedef enum { + /* no error specified, sometimes this means the arguments were wrong */ + NM_PLATFORM_ERROR_NONE, + /* object was not found */ + NM_PLATFORM_ERROR_NOT_FOUND, + /* object already exists */ + NM_PLATFORM_ERROR_EXISTS, + /* object is wrong type */ + NM_PLATFORM_ERROR_WRONG_TYPE, + /* object is not a slave */ + NM_PLATFORM_ERROR_NOT_SLAVE, + /* firmware is not found */ + NM_PLATFORM_ERROR_NO_FIRMWARE +} NMPlatformError; + +typedef enum { + NM_PLATFORM_REASON_NONE, + /* Event was requested by NetworkManager. */ + NM_PLATFORM_REASON_INTERNAL, + /* Event came from the kernel. */ + NM_PLATFORM_REASON_EXTERNAL, + /* Event is a result of cache checking and cleanups. */ + NM_PLATFORM_REASON_CACHE_CHECK +} NMPlatformReason; + +typedef enum { + /* Please don't interpret type numbers outside nm-platform and use functions + * like nm_platform_link_is_software() and nm_platform_supports_slaves(). + * + * type & 0x10000 -> Software device type + * type & 0x20000 -> Type supports slaves + */ + + /* No type, used as error value */ + NM_LINK_TYPE_NONE, + + /* Unknown type */ + NM_LINK_TYPE_UNKNOWN, + + /* Hardware types */ + NM_LINK_TYPE_ETHERNET, + NM_LINK_TYPE_INFINIBAND, + NM_LINK_TYPE_OLPC_MESH, + NM_LINK_TYPE_WIFI, + NM_LINK_TYPE_WWAN_ETHERNET, /* WWAN pseudo-ethernet */ + NM_LINK_TYPE_WIMAX, + + /* Software types */ + NM_LINK_TYPE_DUMMY = 0x10000, + NM_LINK_TYPE_GRE, + NM_LINK_TYPE_GRETAP, + NM_LINK_TYPE_IFB, + NM_LINK_TYPE_LOOPBACK, + NM_LINK_TYPE_MACVLAN, + NM_LINK_TYPE_MACVTAP, + NM_LINK_TYPE_OPENVSWITCH, + NM_LINK_TYPE_TAP, + NM_LINK_TYPE_TUN, + NM_LINK_TYPE_VETH, + NM_LINK_TYPE_VLAN, + NM_LINK_TYPE_VXLAN, + + /* Software types with slaves */ + NM_LINK_TYPE_BRIDGE = 0x10000 | 0x20000, + NM_LINK_TYPE_BOND, + NM_LINK_TYPE_TEAM, +} NMLinkType; + +#define __NMPlatformObject_COMMON \ + int ifindex; \ + ; + +typedef struct { + __NMPlatformObject_COMMON; + char name[IFNAMSIZ]; + NMLinkType type; + const char *type_name; + const char *udi; + const char *driver; + int master; + int parent; + gboolean up; + gboolean connected; + gboolean arp; + guint mtu; +} NMPlatformLink; + +typedef enum { + NM_PLATFORM_SIGNAL_ADDED, + NM_PLATFORM_SIGNAL_CHANGED, + NM_PLATFORM_SIGNAL_REMOVED, +} NMPlatformSignalChangeType; + +#define NM_PLATFORM_LIFETIME_PERMANENT G_MAXUINT32 + +typedef enum { + /* In priority order; higher number == higher priority */ + NM_PLATFORM_SOURCE_UNKNOWN, + NM_PLATFORM_SOURCE_KERNEL, + NM_PLATFORM_SOURCE_SHARED, + NM_PLATFORM_SOURCE_IP4LL, + NM_PLATFORM_SOURCE_PPP, + NM_PLATFORM_SOURCE_WWAN, + NM_PLATFORM_SOURCE_VPN, + NM_PLATFORM_SOURCE_DHCP, + NM_PLATFORM_SOURCE_RDISC, + NM_PLATFORM_SOURCE_USER, +} NMPlatformSource; + + +typedef struct { + __NMPlatformObject_COMMON; +} NMPlatformObject; + + +#define __NMPlatformIPAddress_COMMON \ + __NMPlatformObject_COMMON; \ + NMPlatformSource source; \ + \ + /* Timestamp in seconds in the reference system of nm_utils_get_monotonic_timestamp_*(). + * + * The rules are: + * 1 @lifetime==0: @timestamp and @preferred is irrelevant (but mostly set to 0 too). Such addresses + * are permanent. This rule is so that unset addresses (calloc) are permanent by default. + * 2 @lifetime==@preferred==NM_PLATFORM_LIFETIME_PERMANENT: @timestamp is irrelevant (but mostly + * set to 0). Such addresses are permanent. + * 3 Non permanent addreses should (almost) always have @timestamp > 0. 0 is not a valid timestamp + * and never returned by nm_utils_get_monotonic_timestamp_s(). In this case @valid/@preferred + * is anchored at @timestamp. + * 4 Non permanent addresses with @timestamp == 0 are implicitely anchored at *now*, thus the time + * moves as time goes by. This is usually not useful, except e.g. nm_platform_ip[46]_address_add(). + * + * Non permanent addresses from DHCP/RA might have the @timestamp set to the moment of when the + * lease was received. Addresses from kernel might have the @timestamp based on the last modification + * time of the addresses. But don't rely on this behaviour, the @timestamp is only defined for anchoring + * @lifetime and @preferred. + */ \ + guint32 timestamp; \ + guint32 lifetime; /* seconds since timestamp */ \ + guint32 preferred; /* seconds since timestamp */ \ + int plen; \ + ; + +/** + * NMPlatformIPAddress: + * + * Common parts of NMPlatformIP4Address and NMPlatformIP6Address. + **/ +typedef struct { + __NMPlatformIPAddress_COMMON; + union { + guint8 address_ptr[1]; + guint32 __dummy_for_32bit_alignment; + }; +} NMPlatformIPAddress; + +/** + * NMPlatformIP4Address: + * @timestamp: timestamp as returned by nm_utils_get_monotonic_timestamp_s() + **/ +typedef struct { + __NMPlatformIPAddress_COMMON; + in_addr_t address; + in_addr_t peer_address; /* PTP peer address */ + char label[IFNAMSIZ]; +} NMPlatformIP4Address; +G_STATIC_ASSERT (G_STRUCT_OFFSET (NMPlatformIPAddress, address_ptr) == G_STRUCT_OFFSET (NMPlatformIP4Address, address)); + +/** + * NMPlatformIP6Address: + * @timestamp: timestamp as returned by nm_utils_get_monotonic_timestamp_s() + **/ +typedef struct { + __NMPlatformIPAddress_COMMON; + struct in6_addr address; + struct in6_addr peer_address; + guint flags; /* ifa_flags from , field type "unsigned int" is as used in rtnl_addr_get_flags. */ +} NMPlatformIP6Address; +G_STATIC_ASSERT (G_STRUCT_OFFSET (NMPlatformIPAddress, address_ptr) == G_STRUCT_OFFSET (NMPlatformIP6Address, address)); + +#undef __NMPlatformIPAddress_COMMON + + +#define NM_PLATFORM_ROUTE_METRIC_DEFAULT 1024 + +#define __NMPlatformIPRoute_COMMON \ + __NMPlatformObject_COMMON; \ + NMPlatformSource source; \ + int plen; \ + guint metric; \ + guint mss; \ + ; + +typedef struct { + __NMPlatformIPRoute_COMMON; + union { + guint8 network_ptr[1]; + guint32 __dummy_for_32bit_alignment; + }; +} NMPlatformIPRoute; + +typedef struct { + __NMPlatformIPRoute_COMMON; + in_addr_t network; + in_addr_t gateway; +} NMPlatformIP4Route; +G_STATIC_ASSERT (G_STRUCT_OFFSET (NMPlatformIPRoute, network_ptr) == G_STRUCT_OFFSET (NMPlatformIP4Route, network)); + +typedef struct { + __NMPlatformIPRoute_COMMON; + struct in6_addr network; + struct in6_addr gateway; +} NMPlatformIP6Route; +G_STATIC_ASSERT (G_STRUCT_OFFSET (NMPlatformIPRoute, network_ptr) == G_STRUCT_OFFSET (NMPlatformIP6Route, network)); + +#undef __NMPlatformIPRoute_COMMON + + +#undef __NMPlatformObject_COMMON + + +typedef struct { + int peer; +} NMPlatformVethProperties; + +typedef struct { + gint64 owner; + gint64 group; + const char *mode; + gboolean no_pi; + gboolean vnet_hdr; + gboolean multi_queue; +} NMPlatformTunProperties; + +typedef struct { + int parent_ifindex; + const char *mode; + gboolean no_promisc; +} NMPlatformMacvlanProperties; + +typedef struct { + int parent_ifindex; + guint32 id; + in_addr_t group; + in_addr_t local; + struct in6_addr group6; + struct in6_addr local6; + guint8 tos; + guint8 ttl; + gboolean learning; + guint32 ageing; + guint32 limit; + guint16 dst_port; + guint16 src_port_min; + guint16 src_port_max; + gboolean proxy; + gboolean rsc; + gboolean l2miss; + gboolean l3miss; +} NMPlatformVxlanProperties; + +typedef struct { + int parent_ifindex; + guint16 input_flags; + guint16 output_flags; + guint32 input_key; + guint32 output_key; + in_addr_t local; + in_addr_t remote; + guint8 ttl; + guint8 tos; + gboolean path_mtu_discovery; +} NMPlatformGreProperties; + +/******************************************************************/ + +/* NMPlatform abstract class and its implementations provide a layer between + * networkmanager's device management classes and the operating system kernel. + * + * How it works, is best seen in tests/nm-platform-test.c source file. + * + * NMPlatform provides interface to configure kernel interfaces and receive + * notifications about both internal and external configuration changes. It + * respects the following rules: + * + * 1) Every change made through NMPlatform is readily available and the respective + * signals are called synchronously. + * + * 2) State of an object retrieved from NMPlatform (through functions or events) + * is at least as recent than the state retrieved before. + * + * Any failure of the above rules should be fixed in NMPlatform implementations + * and tested in nm-platform-test. Synchronization hacks should never be put + * to any other code. That's why NMPlatform was created and that's why the + * testing code was written for it. + * + * In future, parts of linux platform implementation may be moved to the libnl + * library. + * + * If you have any problems related to NMPlatform on your system, you should + * always first run tests/nm-linux-platform-test as root and with all + * network configuration daemons stopped. Look at the code first. + */ + +typedef struct { + GObject parent; + + NMPlatformError error; +} NMPlatform; + +typedef struct { + GObjectClass parent; + + gboolean (*setup) (NMPlatform *); + + gboolean (*sysctl_set) (NMPlatform *, const char *path, const char *value); + char * (*sysctl_get) (NMPlatform *, const char *path); + + gboolean (*link_get) (NMPlatform *platform, int ifindex, NMPlatformLink *link); + GArray *(*link_get_all) (NMPlatform *); + gboolean (*link_add) (NMPlatform *, const char *name, NMLinkType type, const void *address, size_t address_len); + gboolean (*link_delete) (NMPlatform *, int ifindex); + int (*link_get_ifindex) (NMPlatform *, const char *name); + const char *(*link_get_name) (NMPlatform *, int ifindex); + NMLinkType (*link_get_type) (NMPlatform *, int ifindex); + const char *(*link_get_type_name) (NMPlatform *, int ifindex); + + gboolean (*link_refresh) (NMPlatform *, int ifindex); + + gboolean (*link_set_up) (NMPlatform *, int ifindex); + gboolean (*link_set_down) (NMPlatform *, int ifindex); + gboolean (*link_set_arp) (NMPlatform *, int ifindex); + gboolean (*link_set_noarp) (NMPlatform *, int ifindex); + gboolean (*link_is_up) (NMPlatform *, int ifindex); + gboolean (*link_is_connected) (NMPlatform *, int ifindex); + gboolean (*link_uses_arp) (NMPlatform *, int ifindex); + + gconstpointer (*link_get_address) (NMPlatform *, int ifindex, size_t *length); + gboolean (*link_set_address) (NMPlatform *, int ifindex, gconstpointer address, size_t length); + guint32 (*link_get_mtu) (NMPlatform *, int ifindex); + gboolean (*link_set_mtu) (NMPlatform *, int ifindex, guint32 mtu); + + char * (*link_get_physical_port_id) (NMPlatform *, int ifindex); + gboolean (*link_get_wake_on_lan) (NMPlatform *, int ifindex); + + gboolean (*link_supports_carrier_detect) (NMPlatform *, int ifindex); + gboolean (*link_supports_vlans) (NMPlatform *, int ifindex); + + gboolean (*link_enslave) (NMPlatform *, int master, int slave); + gboolean (*link_release) (NMPlatform *, int master, int slave); + gboolean (*link_get_master) (NMPlatform *, int slave); + gboolean (*master_set_option) (NMPlatform *, int ifindex, const char *option, const char *value); + char * (*master_get_option) (NMPlatform *, int ifindex, const char *option); + gboolean (*slave_set_option) (NMPlatform *, int ifindex, const char *option, const char *value); + char * (*slave_get_option) (NMPlatform *, int ifindex, const char *option); + + gboolean (*vlan_add) (NMPlatform *, const char *name, int parent, int vlanid, guint32 vlanflags); + gboolean (*vlan_get_info) (NMPlatform *, int ifindex, int *parent, int *vlan_id); + gboolean (*vlan_set_ingress_map) (NMPlatform *, int ifindex, int from, int to); + gboolean (*vlan_set_egress_map) (NMPlatform *, int ifindex, int from, int to); + + gboolean (*infiniband_partition_add) (NMPlatform *, int parent, int p_key); + + gboolean (*veth_get_properties) (NMPlatform *, int ifindex, NMPlatformVethProperties *properties); + gboolean (*tun_get_properties) (NMPlatform *, int ifindex, NMPlatformTunProperties *properties); + gboolean (*macvlan_get_properties) (NMPlatform *, int ifindex, NMPlatformMacvlanProperties *props); + gboolean (*vxlan_get_properties) (NMPlatform *, int ifindex, NMPlatformVxlanProperties *props); + gboolean (*gre_get_properties) (NMPlatform *, int ifindex, NMPlatformGreProperties *props); + + gboolean (*wifi_get_capabilities) (NMPlatform *, int ifindex, NMDeviceWifiCapabilities *caps); + gboolean (*wifi_get_bssid) (NMPlatform *, int ifindex, struct ether_addr *bssid); + GByteArray *(*wifi_get_ssid) (NMPlatform *, int ifindex); + guint32 (*wifi_get_frequency) (NMPlatform *, int ifindex); + int (*wifi_get_quality) (NMPlatform *, int ifindex); + guint32 (*wifi_get_rate) (NMPlatform *, int ifindex); + NM80211Mode (*wifi_get_mode) (NMPlatform *, int ifindex); + void (*wifi_set_mode) (NMPlatform *, int ifindex, NM80211Mode mode); + guint32 (*wifi_find_frequency) (NMPlatform *, int ifindex, const guint32 *freqs); + void (*wifi_indicate_addressing_running) (NMPlatform *, int ifindex, gboolean running); + + guint32 (*mesh_get_channel) (NMPlatform *, int ifindex); + gboolean (*mesh_set_channel) (NMPlatform *, int ifindex, guint32 channel); + gboolean (*mesh_set_ssid) (NMPlatform *, int ifindex, const GByteArray *ssid); + + GArray * (*ip4_address_get_all) (NMPlatform *, int ifindex); + GArray * (*ip6_address_get_all) (NMPlatform *, int ifindex); + gboolean (*ip4_address_add) (NMPlatform *, int ifindex, + in_addr_t address, in_addr_t peer_address, int plen, + guint32 lifetime, guint32 preferred_lft, + const char *label); + gboolean (*ip6_address_add) (NMPlatform *, int ifindex, + struct in6_addr address, struct in6_addr peer_address, int plen, + guint32 lifetime, guint32 preferred_lft, guint flags); + gboolean (*ip4_address_delete) (NMPlatform *, int ifindex, in_addr_t address, int plen); + gboolean (*ip6_address_delete) (NMPlatform *, int ifindex, struct in6_addr address, int plen); + gboolean (*ip4_address_exists) (NMPlatform *, int ifindex, in_addr_t address, int plen); + gboolean (*ip6_address_exists) (NMPlatform *, int ifindex, struct in6_addr address, int plen); + + GArray * (*ip4_route_get_all) (NMPlatform *, int ifindex, gboolean include_default); + GArray * (*ip6_route_get_all) (NMPlatform *, int ifindex, gboolean include_default); + gboolean (*ip4_route_add) (NMPlatform *, int ifindex, NMPlatformSource source, + in_addr_t network, int plen, in_addr_t gateway, + int prio, int mss); + gboolean (*ip6_route_add) (NMPlatform *, int ifindex, NMPlatformSource source, + struct in6_addr network, int plen, struct in6_addr gateway, + int prio, int mss); + gboolean (*ip4_route_delete) (NMPlatform *, int ifindex, in_addr_t network, int plen, int metric); + gboolean (*ip6_route_delete) (NMPlatform *, int ifindex, struct in6_addr network, int plen, int metric); + gboolean (*ip4_route_exists) (NMPlatform *, int ifindex, in_addr_t network, int plen, int metric); + gboolean (*ip6_route_exists) (NMPlatform *, int ifindex, struct in6_addr network, int plen, int metric); + + gboolean (*check_support_kernel_extended_ifa_flags) (NMPlatform *); +} NMPlatformClass; + +/* NMPlatform signals + * + * Each signal handler is called with a type-specific object that provides + * key attributes that constitute identity of the object. They may also + * provide additional attributes for convenience. + * + * The object only intended to be used by the signal handler to determine + * the current values. It is no longer valid after the signal handler exits + * but you are free to copy the provided information and use it for later + * reference. + */ +#define NM_PLATFORM_SIGNAL_LINK_CHANGED "link-changed" +#define NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED "ip4-address-changed" +#define NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED "ip6-address-changed" +#define NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED "ip4-route-changed" +#define NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED "ip6-route-changed" + +/******************************************************************/ + +GType nm_platform_get_type (void); + +void nm_platform_setup (GType type); +NMPlatform *nm_platform_get (void); +void nm_platform_free (void); + +/******************************************************************/ + +void nm_platform_set_error (NMPlatformError error); +NMPlatformError nm_platform_get_error (void); +const char *nm_platform_get_error_msg (void); + +void nm_platform_query_devices (void); + +gboolean nm_platform_sysctl_set (const char *path, const char *value); +char *nm_platform_sysctl_get (const char *path); +gint32 nm_platform_sysctl_get_int32 (const char *path, gint32 fallback); +gint64 nm_platform_sysctl_get_int_checked (const char *path, guint base, gint64 min, gint64 max, gint64 fallback); + +gboolean nm_platform_link_get (int ifindex, NMPlatformLink *link); +GArray *nm_platform_link_get_all (void); +gboolean nm_platform_dummy_add (const char *name); +gboolean nm_platform_bridge_add (const char *name, const void *address, size_t address_len); +gboolean nm_platform_bond_add (const char *name); +gboolean nm_platform_team_add (const char *name); +gboolean nm_platform_link_exists (const char *name); +gboolean nm_platform_link_delete (int ifindex); +int nm_platform_link_get_ifindex (const char *name); +const char *nm_platform_link_get_name (int ifindex); +NMLinkType nm_platform_link_get_type (int ifindex); +const char *nm_platform_link_get_type_name (int ifindex); +gboolean nm_platform_link_is_software (int ifindex); +gboolean nm_platform_link_supports_slaves (int ifindex); + +gboolean nm_platform_link_refresh (int ifindex); + +gboolean nm_platform_link_set_up (int ifindex); +gboolean nm_platform_link_set_down (int ifindex); +gboolean nm_platform_link_set_arp (int ifindex); +gboolean nm_platform_link_set_noarp (int ifindex); +gboolean nm_platform_link_is_up (int ifindex); +gboolean nm_platform_link_is_connected (int ifindex); +gboolean nm_platform_link_uses_arp (int ifindex); + +gconstpointer nm_platform_link_get_address (int ifindex, size_t *length); +gboolean nm_platform_link_set_address (int ifindex, const void *address, size_t length); +guint32 nm_platform_link_get_mtu (int ifindex); +gboolean nm_platform_link_set_mtu (int ifindex, guint32 mtu); + +char *nm_platform_link_get_physical_port_id (int ifindex); +gboolean nm_platform_link_get_wake_on_lan (int ifindex); + +gboolean nm_platform_link_supports_carrier_detect (int ifindex); +gboolean nm_platform_link_supports_vlans (int ifindex); + +gboolean nm_platform_link_enslave (int master, int slave); +gboolean nm_platform_link_release (int master, int slave); +int nm_platform_link_get_master (int slave); +gboolean nm_platform_master_set_option (int ifindex, const char *option, const char *value); +char *nm_platform_master_get_option (int ifindex, const char *option); +gboolean nm_platform_slave_set_option (int ifindex, const char *option, const char *value); +char *nm_platform_slave_get_option (int ifindex, const char *option); + +gboolean nm_platform_vlan_add (const char *name, int parent, int vlanid, guint32 vlanflags); +gboolean nm_platform_vlan_get_info (int ifindex, int *parent, int *vlanid); +gboolean nm_platform_vlan_set_ingress_map (int ifindex, int from, int to); +gboolean nm_platform_vlan_set_egress_map (int ifindex, int from, int to); + +gboolean nm_platform_infiniband_partition_add (int parent, int p_key); + +gboolean nm_platform_veth_get_properties (int ifindex, NMPlatformVethProperties *properties); +gboolean nm_platform_tun_get_properties (int ifindex, NMPlatformTunProperties *properties); +gboolean nm_platform_macvlan_get_properties (int ifindex, NMPlatformMacvlanProperties *props); +gboolean nm_platform_vxlan_get_properties (int ifindex, NMPlatformVxlanProperties *props); +gboolean nm_platform_gre_get_properties (int ifindex, NMPlatformGreProperties *props); + +gboolean nm_platform_wifi_get_capabilities (int ifindex, NMDeviceWifiCapabilities *caps); +gboolean nm_platform_wifi_get_bssid (int ifindex, struct ether_addr *bssid); +GByteArray *nm_platform_wifi_get_ssid (int ifindex); +guint32 nm_platform_wifi_get_frequency (int ifindex); +int nm_platform_wifi_get_quality (int ifindex); +guint32 nm_platform_wifi_get_rate (int ifindex); +NM80211Mode nm_platform_wifi_get_mode (int ifindex); +void nm_platform_wifi_set_mode (int ifindex, NM80211Mode mode); +guint32 nm_platform_wifi_find_frequency (int ifindex, const guint32 *freqs); +void nm_platform_wifi_indicate_addressing_running (int ifindex, gboolean running); + +guint32 nm_platform_mesh_get_channel (int ifindex); +gboolean nm_platform_mesh_set_channel (int ifindex, guint32 channel); +gboolean nm_platform_mesh_set_ssid (int ifindex, const GByteArray *ssid); + +GArray *nm_platform_ip4_address_get_all (int ifindex); +GArray *nm_platform_ip6_address_get_all (int ifindex); +gboolean nm_platform_ip4_address_add (int ifindex, + in_addr_t address, in_addr_t peer_address, int plen, + guint32 lifetime, guint32 preferred_lft, + const char *label); +gboolean nm_platform_ip6_address_add (int ifindex, + struct in6_addr address, struct in6_addr peer_address, int plen, + guint32 lifetime, guint32 preferred_lft, guint flags); +gboolean nm_platform_ip4_address_delete (int ifindex, in_addr_t address, int plen); +gboolean nm_platform_ip6_address_delete (int ifindex, struct in6_addr address, int plen); +gboolean nm_platform_ip4_address_exists (int ifindex, in_addr_t address, int plen); +gboolean nm_platform_ip6_address_exists (int ifindex, struct in6_addr address, int plen); +gboolean nm_platform_ip4_address_sync (int ifindex, const GArray *known_addresses); +gboolean nm_platform_ip6_address_sync (int ifindex, const GArray *known_addresses); +gboolean nm_platform_address_flush (int ifindex); + +GArray *nm_platform_ip4_route_get_all (int ifindex, gboolean include_default); +GArray *nm_platform_ip6_route_get_all (int ifindex, gboolean include_default); +gboolean nm_platform_route_set_metric (int ifindex, int metric); +gboolean nm_platform_ip4_route_add (int ifindex, NMPlatformSource source, + in_addr_t network, int plen, in_addr_t gateway, + int metric, int mss); +gboolean nm_platform_ip6_route_add (int ifindex, NMPlatformSource source, + struct in6_addr network, int plen, struct in6_addr gateway, + int metric, int mss); +gboolean nm_platform_ip4_route_delete (int ifindex, in_addr_t network, int plen, int metric); +gboolean nm_platform_ip6_route_delete (int ifindex, struct in6_addr network, int plen, int metric); +gboolean nm_platform_ip4_route_exists (int ifindex, in_addr_t network, int plen, int metric); +gboolean nm_platform_ip6_route_exists (int ifindex, struct in6_addr network, int plen, int metric); +gboolean nm_platform_ip4_route_sync (int ifindex, const GArray *known_routes); +gboolean nm_platform_ip6_route_sync (int ifindex, const GArray *known_routes); +gboolean nm_platform_route_flush (int ifindex); + +const char *nm_platform_link_to_string (const NMPlatformLink *link); +const char *nm_platform_ip4_address_to_string (const NMPlatformIP4Address *address); +const char *nm_platform_ip6_address_to_string (const NMPlatformIP6Address *address); +const char *nm_platform_ip4_route_to_string (const NMPlatformIP4Route *route); +const char *nm_platform_ip6_route_to_string (const NMPlatformIP6Route *route); + +int nm_platform_link_cmp (const NMPlatformLink *a, const NMPlatformLink *b); +int nm_platform_ip4_address_cmp (const NMPlatformIP4Address *a, const NMPlatformIP4Address *b); +int nm_platform_ip6_address_cmp (const NMPlatformIP6Address *a, const NMPlatformIP6Address *b); +int nm_platform_ip4_route_cmp (const NMPlatformIP4Route *a, const NMPlatformIP4Route *b); +int nm_platform_ip6_route_cmp (const NMPlatformIP6Route *a, const NMPlatformIP6Route *b); + +gboolean nm_platform_check_support_libnl_extended_ifa_flags (void); +gboolean nm_platform_check_support_kernel_extended_ifa_flags (void); + +void nm_platform_addr_flags2str (int flags, char *buf, size_t size); + +int nm_platform_ip_address_cmp_expiry (const NMPlatformIPAddress *a, const NMPlatformIPAddress *b); + +#define auto_g_free __attribute__((cleanup(put_g_free))) +static void __attribute__((unused)) +put_g_free (void *ptr) +{ + g_clear_pointer ((gpointer *) ptr, g_free); +} + +#endif /* NM_PLATFORM_H */ diff --git a/src/platform/tests/Makefile.am b/src/platform/tests/Makefile.am new file mode 100644 index 00000000..9b10ea7b --- /dev/null +++ b/src/platform/tests/Makefile.am @@ -0,0 +1,116 @@ +AM_CPPFLAGS = \ + -I${top_srcdir} \ + -I${top_srcdir}/include \ + -I${top_builddir}/include \ + -I${top_srcdir}/src \ + -I${top_builddir}/src \ + -I${top_srcdir}/src/logging \ + -I${top_srcdir}/libnm-util \ + -I${top_builddir}/libnm-util \ + -I${srcdir}/.. \ + -DG_LOG_DOMAIN=\""NetworkManager"\" \ + -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \ + $(GLIB_CFLAGS) \ + $(GUDEV_CFLAGS) \ + $(LIBNL_CFLAGS) + +if REQUIRE_ROOT_TESTS +AM_CPPFLAGS += -DREQUIRE_ROOT_TESTS=1 +endif + +PLATFORM_SOURCES = \ + ../nm-platform.c \ + ../nm-fake-platform.c \ + ../nm-linux-platform.c +TEST_SOURCES = $(PLATFORM_SOURCES) test-common.c test-common.h +AM_CFLAGS = $(CODE_COVERAGE_CFLAGS) +AM_LDFLAGS = $(GLIB_LIBS) $(GUDEV_LIBS) $(LIBNL_LIBS) $(CODE_COVERAGE_LDFLAGS) +PLATFORM_LDADD = \ + $(top_builddir)/src/libNetworkManager.la + +@GNOME_CODE_COVERAGE_RULES@ + +noinst_PROGRAMS = \ + dump \ + monitor \ + platform \ + test-link-fake \ + test-link-linux \ + test-address-fake \ + test-address-linux \ + test-route-fake \ + test-route-linux \ + test-cleanup-fake \ + test-cleanup-linux + +EXTRA_DIST = test-common.h + +monitor_SOURCES = monitor.c $(PLATFORM_SOURCES) +monitor_LDADD = $(PLATFORM_LDADD) + +dump_SOURCES = dump.c $(PLATFORM_SOURCES) +dump_LDADD = $(PLATFORM_LDADD) + +platform_SOURCES = platform.c $(PLATFORM_SOURCES) +platform_LDADD = $(PLATFORM_LDADD) + +test_link_fake_SOURCES = test-link.c $(TEST_SOURCES) +test_link_fake_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + -DSETUP=nm_fake_platform_setup \ + -DKERNEL_HACKS=0 +test_link_fake_LDADD = $(PLATFORM_LDADD) + +test_link_linux_SOURCES = test-link.c $(TEST_SOURCES) +test_link_linux_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + -DSETUP=nm_linux_platform_setup \ + -DKERNEL_HACKS=1 +test_link_linux_LDADD = $(PLATFORM_LDADD) + +test_address_fake_SOURCES = test-address.c $(TEST_SOURCES) +test_address_fake_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + -DSETUP=nm_fake_platform_setup \ + -DKERNEL_HACKS=0 +test_address_fake_LDADD = $(PLATFORM_LDADD) + +test_address_linux_SOURCES = test-address.c $(TEST_SOURCES) +test_address_linux_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + -DSETUP=nm_linux_platform_setup \ + -DKERNEL_HACKS=1 +test_address_linux_LDADD = $(PLATFORM_LDADD) + +test_route_fake_SOURCES = test-route.c $(TEST_SOURCES) +test_route_fake_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + -DSETUP=nm_fake_platform_setup \ + -DKERNEL_HACKS=0 +test_route_fake_LDADD = $(PLATFORM_LDADD) + +test_route_linux_SOURCES = test-route.c $(TEST_SOURCES) +test_route_linux_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + -DSETUP=nm_linux_platform_setup \ + -DKERNEL_HACKS=1 +test_route_linux_LDADD = $(PLATFORM_LDADD) + +test_cleanup_fake_SOURCES = test-cleanup.c $(TEST_SOURCES) +test_cleanup_fake_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + -DSETUP=nm_fake_platform_setup \ + -DKERNEL_HACKS=0 +test_cleanup_fake_LDADD = $(PLATFORM_LDADD) + +test_cleanup_linux_SOURCES = test-cleanup.c $(TEST_SOURCES) +test_cleanup_linux_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + -DSETUP=nm_linux_platform_setup \ + -DKERNEL_HACKS=1 +test_cleanup_linux_LDADD = $(PLATFORM_LDADD) + +#@VALGRIND_RULES@ +TESTS = test-link-fake test-address-fake test-route-fake test-cleanup-fake test-link-linux test-address-linux test-route-linux test-cleanup-linux + + diff --git a/src/platform/tests/Makefile.in b/src/platform/tests/Makefile.in new file mode 100644 index 00000000..6b03e315 --- /dev/null +++ b/src/platform/tests/Makefile.in @@ -0,0 +1,1702 @@ +# Makefile.in generated by automake 1.13.4 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +@REQUIRE_ROOT_TESTS_TRUE@am__append_1 = -DREQUIRE_ROOT_TESTS=1 +noinst_PROGRAMS = dump$(EXEEXT) monitor$(EXEEXT) platform$(EXEEXT) \ + test-link-fake$(EXEEXT) test-link-linux$(EXEEXT) \ + test-address-fake$(EXEEXT) test-address-linux$(EXEEXT) \ + test-route-fake$(EXEEXT) test-route-linux$(EXEEXT) \ + test-cleanup-fake$(EXEEXT) test-cleanup-linux$(EXEEXT) +TESTS = test-link-fake$(EXEEXT) test-address-fake$(EXEEXT) \ + test-route-fake$(EXEEXT) test-cleanup-fake$(EXEEXT) \ + test-link-linux$(EXEEXT) test-address-linux$(EXEEXT) \ + test-route-linux$(EXEEXT) test-cleanup-linux$(EXEEXT) +subdir = src/platform/tests +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(top_srcdir)/build-aux/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_lib_readline.m4 \ + $(top_srcdir)/m4/compiler_warnings.m4 \ + $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/gnome-code-coverage.m4 \ + $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ + $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \ + $(top_srcdir)/m4/introspection.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ + $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ + $(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +PROGRAMS = $(noinst_PROGRAMS) +am__objects_1 = nm-platform.$(OBJEXT) nm-fake-platform.$(OBJEXT) \ + nm-linux-platform.$(OBJEXT) +am_dump_OBJECTS = dump.$(OBJEXT) $(am__objects_1) +dump_OBJECTS = $(am_dump_OBJECTS) +dump_DEPENDENCIES = $(PLATFORM_LDADD) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +am_monitor_OBJECTS = monitor.$(OBJEXT) $(am__objects_1) +monitor_OBJECTS = $(am_monitor_OBJECTS) +monitor_DEPENDENCIES = $(PLATFORM_LDADD) +am_platform_OBJECTS = platform.$(OBJEXT) $(am__objects_1) +platform_OBJECTS = $(am_platform_OBJECTS) +platform_DEPENDENCIES = $(PLATFORM_LDADD) +am__objects_2 = test_address_fake-nm-platform.$(OBJEXT) \ + test_address_fake-nm-fake-platform.$(OBJEXT) \ + test_address_fake-nm-linux-platform.$(OBJEXT) +am__objects_3 = $(am__objects_2) \ + test_address_fake-test-common.$(OBJEXT) +am_test_address_fake_OBJECTS = \ + test_address_fake-test-address.$(OBJEXT) $(am__objects_3) +test_address_fake_OBJECTS = $(am_test_address_fake_OBJECTS) +test_address_fake_DEPENDENCIES = $(PLATFORM_LDADD) +am__objects_4 = test_address_linux-nm-platform.$(OBJEXT) \ + test_address_linux-nm-fake-platform.$(OBJEXT) \ + test_address_linux-nm-linux-platform.$(OBJEXT) +am__objects_5 = $(am__objects_4) \ + test_address_linux-test-common.$(OBJEXT) +am_test_address_linux_OBJECTS = \ + test_address_linux-test-address.$(OBJEXT) $(am__objects_5) +test_address_linux_OBJECTS = $(am_test_address_linux_OBJECTS) +test_address_linux_DEPENDENCIES = $(PLATFORM_LDADD) +am__objects_6 = test_cleanup_fake-nm-platform.$(OBJEXT) \ + test_cleanup_fake-nm-fake-platform.$(OBJEXT) \ + test_cleanup_fake-nm-linux-platform.$(OBJEXT) +am__objects_7 = $(am__objects_6) \ + test_cleanup_fake-test-common.$(OBJEXT) +am_test_cleanup_fake_OBJECTS = \ + test_cleanup_fake-test-cleanup.$(OBJEXT) $(am__objects_7) +test_cleanup_fake_OBJECTS = $(am_test_cleanup_fake_OBJECTS) +test_cleanup_fake_DEPENDENCIES = $(PLATFORM_LDADD) +am__objects_8 = test_cleanup_linux-nm-platform.$(OBJEXT) \ + test_cleanup_linux-nm-fake-platform.$(OBJEXT) \ + test_cleanup_linux-nm-linux-platform.$(OBJEXT) +am__objects_9 = $(am__objects_8) \ + test_cleanup_linux-test-common.$(OBJEXT) +am_test_cleanup_linux_OBJECTS = \ + test_cleanup_linux-test-cleanup.$(OBJEXT) $(am__objects_9) +test_cleanup_linux_OBJECTS = $(am_test_cleanup_linux_OBJECTS) +test_cleanup_linux_DEPENDENCIES = $(PLATFORM_LDADD) +am__objects_10 = test_link_fake-nm-platform.$(OBJEXT) \ + test_link_fake-nm-fake-platform.$(OBJEXT) \ + test_link_fake-nm-linux-platform.$(OBJEXT) +am__objects_11 = $(am__objects_10) \ + test_link_fake-test-common.$(OBJEXT) +am_test_link_fake_OBJECTS = test_link_fake-test-link.$(OBJEXT) \ + $(am__objects_11) +test_link_fake_OBJECTS = $(am_test_link_fake_OBJECTS) +test_link_fake_DEPENDENCIES = $(PLATFORM_LDADD) +am__objects_12 = test_link_linux-nm-platform.$(OBJEXT) \ + test_link_linux-nm-fake-platform.$(OBJEXT) \ + test_link_linux-nm-linux-platform.$(OBJEXT) +am__objects_13 = $(am__objects_12) \ + test_link_linux-test-common.$(OBJEXT) +am_test_link_linux_OBJECTS = test_link_linux-test-link.$(OBJEXT) \ + $(am__objects_13) +test_link_linux_OBJECTS = $(am_test_link_linux_OBJECTS) +test_link_linux_DEPENDENCIES = $(PLATFORM_LDADD) +am__objects_14 = test_route_fake-nm-platform.$(OBJEXT) \ + test_route_fake-nm-fake-platform.$(OBJEXT) \ + test_route_fake-nm-linux-platform.$(OBJEXT) +am__objects_15 = $(am__objects_14) \ + test_route_fake-test-common.$(OBJEXT) +am_test_route_fake_OBJECTS = test_route_fake-test-route.$(OBJEXT) \ + $(am__objects_15) +test_route_fake_OBJECTS = $(am_test_route_fake_OBJECTS) +test_route_fake_DEPENDENCIES = $(PLATFORM_LDADD) +am__objects_16 = test_route_linux-nm-platform.$(OBJEXT) \ + test_route_linux-nm-fake-platform.$(OBJEXT) \ + test_route_linux-nm-linux-platform.$(OBJEXT) +am__objects_17 = $(am__objects_16) \ + test_route_linux-test-common.$(OBJEXT) +am_test_route_linux_OBJECTS = test_route_linux-test-route.$(OBJEXT) \ + $(am__objects_17) +test_route_linux_OBJECTS = $(am_test_route_linux_OBJECTS) +test_route_linux_DEPENDENCIES = $(PLATFORM_LDADD) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(dump_SOURCES) $(monitor_SOURCES) $(platform_SOURCES) \ + $(test_address_fake_SOURCES) $(test_address_linux_SOURCES) \ + $(test_cleanup_fake_SOURCES) $(test_cleanup_linux_SOURCES) \ + $(test_link_fake_SOURCES) $(test_link_linux_SOURCES) \ + $(test_route_fake_SOURCES) $(test_route_linux_SOURCES) +DIST_SOURCES = $(dump_SOURCES) $(monitor_SOURCES) $(platform_SOURCES) \ + $(test_address_fake_SOURCES) $(test_address_linux_SOURCES) \ + $(test_cleanup_fake_SOURCES) $(test_cleanup_linux_SOURCES) \ + $(test_link_fake_SOURCES) $(test_link_linux_SOURCES) \ + $(test_route_fake_SOURCES) $(test_route_linux_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__tty_colors_dummy = \ + mgn= red= grn= lgn= blu= brg= std=; \ + am__color_tests=no +am__tty_colors = { \ + $(am__tty_colors_dummy); \ + if test "X$(AM_COLOR_TESTS)" = Xno; then \ + am__color_tests=no; \ + elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ + am__color_tests=yes; \ + elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ + am__color_tests=yes; \ + fi; \ + if test $$am__color_tests = yes; then \ + red=''; \ + grn=''; \ + lgn=''; \ + blu=''; \ + mgn=''; \ + brg=''; \ + std=''; \ + fi; \ +} +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALL_LINGUAS = @ALL_LINGUAS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CKDB_PATH = @CKDB_PATH@ +CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@ +CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@ +CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIRNAME = @DATADIRNAME@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_100_CFLAGS = @DBUS_GLIB_100_CFLAGS@ +DBUS_GLIB_100_LIBS = @DBUS_GLIB_100_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DHCLIENT_PATH = @DHCLIENT_PATH@ +DHCPCD_PATH = @DHCPCD_PATH@ +DISTRO_NETWORK_SERVICE = @DISTRO_NETWORK_SERVICE@ +DLLTOOL = @DLLTOOL@ +DNSMASQ_PATH = @DNSMASQ_PATH@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GENHTML = @GENHTML@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MAKEFILE = @GLIB_MAKEFILE@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ +GNUTLS_LIBS = @GNUTLS_LIBS@ +GREP = @GREP@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GUDEV_CFLAGS = @GUDEV_CFLAGS@ +GUDEV_LIBS = @GUDEV_LIBS@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_PERL = @INTLTOOL_PERL@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ +INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ +INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ +INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +IPTABLES_PATH = @IPTABLES_PATH@ +IWMX_SDK_CFLAGS = @IWMX_SDK_CFLAGS@ +IWMX_SDK_LIBS = @IWMX_SDK_LIBS@ +KERNEL_FIRMWARE_DIR = @KERNEL_FIRMWARE_DIR@ +LCOV = @LCOV@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDL = @LIBDL@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBM = @LIBM@ +LIBNDP_CFLAGS = @LIBNDP_CFLAGS@ +LIBNDP_LIBS = @LIBNDP_LIBS@ +LIBNL_CFLAGS = @LIBNL_CFLAGS@ +LIBNL_LIBS = @LIBNL_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@ +LIBSOUP_LIBS = @LIBSOUP_LIBS@ +LIBTEAMDCTL_CFLAGS = @LIBTEAMDCTL_CFLAGS@ +LIBTEAMDCTL_LIBS = @LIBTEAMDCTL_LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MM_GLIB_CFLAGS = @MM_GLIB_CFLAGS@ +MM_GLIB_LIBS = @MM_GLIB_LIBS@ +MOC = @MOC@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NEWT_CFLAGS = @NEWT_CFLAGS@ +NEWT_LIBS = @NEWT_LIBS@ +NM = @NM@ +NMEDIT = @NMEDIT@ +NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ +NM_MICRO_VERSION = @NM_MICRO_VERSION@ +NM_MINOR_VERSION = @NM_MINOR_VERSION@ +NM_MODIFY_SYSTEM_POLICY = @NM_MODIFY_SYSTEM_POLICY@ +NM_VERSION = @NM_VERSION@ +NSS_CFLAGS = @NSS_CFLAGS@ +NSS_LIBS = @NSS_LIBS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +POLKIT_CFLAGS = @POLKIT_CFLAGS@ +POLKIT_LIBS = @POLKIT_LIBS@ +POSUB = @POSUB@ +PPPD_PATH = @PPPD_PATH@ +PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@ +PPPOE_PATH = @PPPOE_PATH@ +QT_CFLAGS = @QT_CFLAGS@ +QT_LIBS = @QT_LIBS@ +RANLIB = @RANLIB@ +READLINE_LIBS = @READLINE_LIBS@ +SED = @SED@ +SELINUX_CFLAGS = @SELINUX_CFLAGS@ +SELINUX_LIBS = @SELINUX_LIBS@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SYSTEMD_200_CFLAGS = @SYSTEMD_200_CFLAGS@ +SYSTEMD_200_LIBS = @SYSTEMD_200_LIBS@ +SYSTEMD_INHIBIT_CFLAGS = @SYSTEMD_INHIBIT_CFLAGS@ +SYSTEMD_INHIBIT_LIBS = @SYSTEMD_INHIBIT_LIBS@ +SYSTEMD_LOGIN_CFLAGS = @SYSTEMD_LOGIN_CFLAGS@ +SYSTEMD_LOGIN_LIBS = @SYSTEMD_LOGIN_LIBS@ +SYSTEM_CA_PATH = @SYSTEM_CA_PATH@ +UDEV_BASE_DIR = @UDEV_BASE_DIR@ +USE_NLS = @USE_NLS@ +UUID_CFLAGS = @UUID_CFLAGS@ +UUID_LIBS = @UUID_LIBS@ +VALGRIND_RULES = @VALGRIND_RULES@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ +VERSION = @VERSION@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +intltool__v_merge_options_ = @intltool__v_merge_options_@ +intltool__v_merge_options_0 = @intltool__v_merge_options_0@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +nmbinary = @nmbinary@ +nmconfdir = @nmconfdir@ +nmdatadir = @nmdatadir@ +nmrundir = @nmrundir@ +nmstatedir = @nmstatedir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +with_dhclient = @with_dhclient@ +with_dhcpcd = @with_dhcpcd@ +with_netconfig = @with_netconfig@ +with_resolvconf = @with_resolvconf@ +with_valgrind = @with_valgrind@ +AM_CPPFLAGS = -I${top_srcdir} -I${top_srcdir}/include \ + -I${top_builddir}/include -I${top_srcdir}/src \ + -I${top_builddir}/src -I${top_srcdir}/src/logging \ + -I${top_srcdir}/libnm-util -I${top_builddir}/libnm-util \ + -I${srcdir}/.. -DG_LOG_DOMAIN=\""NetworkManager"\" \ + -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE $(GLIB_CFLAGS) \ + $(GUDEV_CFLAGS) $(LIBNL_CFLAGS) $(am__append_1) +PLATFORM_SOURCES = \ + ../nm-platform.c \ + ../nm-fake-platform.c \ + ../nm-linux-platform.c + +TEST_SOURCES = $(PLATFORM_SOURCES) test-common.c test-common.h +AM_CFLAGS = $(CODE_COVERAGE_CFLAGS) +AM_LDFLAGS = $(GLIB_LIBS) $(GUDEV_LIBS) $(LIBNL_LIBS) $(CODE_COVERAGE_LDFLAGS) +PLATFORM_LDADD = \ + $(top_builddir)/src/libNetworkManager.la + +EXTRA_DIST = test-common.h +monitor_SOURCES = monitor.c $(PLATFORM_SOURCES) +monitor_LDADD = $(PLATFORM_LDADD) +dump_SOURCES = dump.c $(PLATFORM_SOURCES) +dump_LDADD = $(PLATFORM_LDADD) +platform_SOURCES = platform.c $(PLATFORM_SOURCES) +platform_LDADD = $(PLATFORM_LDADD) +test_link_fake_SOURCES = test-link.c $(TEST_SOURCES) +test_link_fake_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + -DSETUP=nm_fake_platform_setup \ + -DKERNEL_HACKS=0 + +test_link_fake_LDADD = $(PLATFORM_LDADD) +test_link_linux_SOURCES = test-link.c $(TEST_SOURCES) +test_link_linux_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + -DSETUP=nm_linux_platform_setup \ + -DKERNEL_HACKS=1 + +test_link_linux_LDADD = $(PLATFORM_LDADD) +test_address_fake_SOURCES = test-address.c $(TEST_SOURCES) +test_address_fake_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + -DSETUP=nm_fake_platform_setup \ + -DKERNEL_HACKS=0 + +test_address_fake_LDADD = $(PLATFORM_LDADD) +test_address_linux_SOURCES = test-address.c $(TEST_SOURCES) +test_address_linux_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + -DSETUP=nm_linux_platform_setup \ + -DKERNEL_HACKS=1 + +test_address_linux_LDADD = $(PLATFORM_LDADD) +test_route_fake_SOURCES = test-route.c $(TEST_SOURCES) +test_route_fake_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + -DSETUP=nm_fake_platform_setup \ + -DKERNEL_HACKS=0 + +test_route_fake_LDADD = $(PLATFORM_LDADD) +test_route_linux_SOURCES = test-route.c $(TEST_SOURCES) +test_route_linux_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + -DSETUP=nm_linux_platform_setup \ + -DKERNEL_HACKS=1 + +test_route_linux_LDADD = $(PLATFORM_LDADD) +test_cleanup_fake_SOURCES = test-cleanup.c $(TEST_SOURCES) +test_cleanup_fake_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + -DSETUP=nm_fake_platform_setup \ + -DKERNEL_HACKS=0 + +test_cleanup_fake_LDADD = $(PLATFORM_LDADD) +test_cleanup_linux_SOURCES = test-cleanup.c $(TEST_SOURCES) +test_cleanup_linux_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + -DSETUP=nm_linux_platform_setup \ + -DKERNEL_HACKS=1 + +test_cleanup_linux_LDADD = $(PLATFORM_LDADD) +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/platform/tests/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/platform/tests/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +dump$(EXEEXT): $(dump_OBJECTS) $(dump_DEPENDENCIES) $(EXTRA_dump_DEPENDENCIES) + @rm -f dump$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(dump_OBJECTS) $(dump_LDADD) $(LIBS) + +monitor$(EXEEXT): $(monitor_OBJECTS) $(monitor_DEPENDENCIES) $(EXTRA_monitor_DEPENDENCIES) + @rm -f monitor$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(monitor_OBJECTS) $(monitor_LDADD) $(LIBS) + +platform$(EXEEXT): $(platform_OBJECTS) $(platform_DEPENDENCIES) $(EXTRA_platform_DEPENDENCIES) + @rm -f platform$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(platform_OBJECTS) $(platform_LDADD) $(LIBS) + +test-address-fake$(EXEEXT): $(test_address_fake_OBJECTS) $(test_address_fake_DEPENDENCIES) $(EXTRA_test_address_fake_DEPENDENCIES) + @rm -f test-address-fake$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_address_fake_OBJECTS) $(test_address_fake_LDADD) $(LIBS) + +test-address-linux$(EXEEXT): $(test_address_linux_OBJECTS) $(test_address_linux_DEPENDENCIES) $(EXTRA_test_address_linux_DEPENDENCIES) + @rm -f test-address-linux$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_address_linux_OBJECTS) $(test_address_linux_LDADD) $(LIBS) + +test-cleanup-fake$(EXEEXT): $(test_cleanup_fake_OBJECTS) $(test_cleanup_fake_DEPENDENCIES) $(EXTRA_test_cleanup_fake_DEPENDENCIES) + @rm -f test-cleanup-fake$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_cleanup_fake_OBJECTS) $(test_cleanup_fake_LDADD) $(LIBS) + +test-cleanup-linux$(EXEEXT): $(test_cleanup_linux_OBJECTS) $(test_cleanup_linux_DEPENDENCIES) $(EXTRA_test_cleanup_linux_DEPENDENCIES) + @rm -f test-cleanup-linux$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_cleanup_linux_OBJECTS) $(test_cleanup_linux_LDADD) $(LIBS) + +test-link-fake$(EXEEXT): $(test_link_fake_OBJECTS) $(test_link_fake_DEPENDENCIES) $(EXTRA_test_link_fake_DEPENDENCIES) + @rm -f test-link-fake$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_link_fake_OBJECTS) $(test_link_fake_LDADD) $(LIBS) + +test-link-linux$(EXEEXT): $(test_link_linux_OBJECTS) $(test_link_linux_DEPENDENCIES) $(EXTRA_test_link_linux_DEPENDENCIES) + @rm -f test-link-linux$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_link_linux_OBJECTS) $(test_link_linux_LDADD) $(LIBS) + +test-route-fake$(EXEEXT): $(test_route_fake_OBJECTS) $(test_route_fake_DEPENDENCIES) $(EXTRA_test_route_fake_DEPENDENCIES) + @rm -f test-route-fake$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_route_fake_OBJECTS) $(test_route_fake_LDADD) $(LIBS) + +test-route-linux$(EXEEXT): $(test_route_linux_OBJECTS) $(test_route_linux_DEPENDENCIES) $(EXTRA_test_route_linux_DEPENDENCIES) + @rm -f test-route-linux$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_route_linux_OBJECTS) $(test_route_linux_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dump.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/monitor.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-fake-platform.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-linux-platform.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-platform.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/platform.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_address_fake-nm-fake-platform.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_address_fake-nm-linux-platform.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_address_fake-nm-platform.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_address_fake-test-address.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_address_fake-test-common.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_address_linux-nm-fake-platform.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_address_linux-nm-linux-platform.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_address_linux-nm-platform.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_address_linux-test-address.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_address_linux-test-common.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_cleanup_fake-nm-fake-platform.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_cleanup_fake-nm-linux-platform.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_cleanup_fake-nm-platform.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_cleanup_fake-test-cleanup.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_cleanup_fake-test-common.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_cleanup_linux-nm-fake-platform.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_cleanup_linux-nm-linux-platform.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_cleanup_linux-nm-platform.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_cleanup_linux-test-cleanup.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_cleanup_linux-test-common.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_link_fake-nm-fake-platform.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_link_fake-nm-linux-platform.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_link_fake-nm-platform.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_link_fake-test-common.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_link_fake-test-link.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_link_linux-nm-fake-platform.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_link_linux-nm-linux-platform.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_link_linux-nm-platform.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_link_linux-test-common.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_link_linux-test-link.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_route_fake-nm-fake-platform.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_route_fake-nm-linux-platform.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_route_fake-nm-platform.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_route_fake-test-common.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_route_fake-test-route.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_route_linux-nm-fake-platform.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_route_linux-nm-linux-platform.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_route_linux-nm-platform.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_route_linux-test-common.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_route_linux-test-route.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +nm-platform.o: ../nm-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-platform.o -MD -MP -MF $(DEPDIR)/nm-platform.Tpo -c -o nm-platform.o `test -f '../nm-platform.c' || echo '$(srcdir)/'`../nm-platform.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-platform.Tpo $(DEPDIR)/nm-platform.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-platform.c' object='nm-platform.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-platform.o `test -f '../nm-platform.c' || echo '$(srcdir)/'`../nm-platform.c + +nm-platform.obj: ../nm-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-platform.obj -MD -MP -MF $(DEPDIR)/nm-platform.Tpo -c -o nm-platform.obj `if test -f '../nm-platform.c'; then $(CYGPATH_W) '../nm-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-platform.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-platform.Tpo $(DEPDIR)/nm-platform.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-platform.c' object='nm-platform.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-platform.obj `if test -f '../nm-platform.c'; then $(CYGPATH_W) '../nm-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-platform.c'; fi` + +nm-fake-platform.o: ../nm-fake-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-fake-platform.o -MD -MP -MF $(DEPDIR)/nm-fake-platform.Tpo -c -o nm-fake-platform.o `test -f '../nm-fake-platform.c' || echo '$(srcdir)/'`../nm-fake-platform.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-fake-platform.Tpo $(DEPDIR)/nm-fake-platform.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-fake-platform.c' object='nm-fake-platform.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-fake-platform.o `test -f '../nm-fake-platform.c' || echo '$(srcdir)/'`../nm-fake-platform.c + +nm-fake-platform.obj: ../nm-fake-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-fake-platform.obj -MD -MP -MF $(DEPDIR)/nm-fake-platform.Tpo -c -o nm-fake-platform.obj `if test -f '../nm-fake-platform.c'; then $(CYGPATH_W) '../nm-fake-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-fake-platform.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-fake-platform.Tpo $(DEPDIR)/nm-fake-platform.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-fake-platform.c' object='nm-fake-platform.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-fake-platform.obj `if test -f '../nm-fake-platform.c'; then $(CYGPATH_W) '../nm-fake-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-fake-platform.c'; fi` + +nm-linux-platform.o: ../nm-linux-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-linux-platform.o -MD -MP -MF $(DEPDIR)/nm-linux-platform.Tpo -c -o nm-linux-platform.o `test -f '../nm-linux-platform.c' || echo '$(srcdir)/'`../nm-linux-platform.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-linux-platform.Tpo $(DEPDIR)/nm-linux-platform.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-linux-platform.c' object='nm-linux-platform.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-linux-platform.o `test -f '../nm-linux-platform.c' || echo '$(srcdir)/'`../nm-linux-platform.c + +nm-linux-platform.obj: ../nm-linux-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-linux-platform.obj -MD -MP -MF $(DEPDIR)/nm-linux-platform.Tpo -c -o nm-linux-platform.obj `if test -f '../nm-linux-platform.c'; then $(CYGPATH_W) '../nm-linux-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-linux-platform.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-linux-platform.Tpo $(DEPDIR)/nm-linux-platform.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-linux-platform.c' object='nm-linux-platform.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-linux-platform.obj `if test -f '../nm-linux-platform.c'; then $(CYGPATH_W) '../nm-linux-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-linux-platform.c'; fi` + +test_address_fake-test-address.o: test-address.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_address_fake-test-address.o -MD -MP -MF $(DEPDIR)/test_address_fake-test-address.Tpo -c -o test_address_fake-test-address.o `test -f 'test-address.c' || echo '$(srcdir)/'`test-address.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_address_fake-test-address.Tpo $(DEPDIR)/test_address_fake-test-address.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-address.c' object='test_address_fake-test-address.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_address_fake-test-address.o `test -f 'test-address.c' || echo '$(srcdir)/'`test-address.c + +test_address_fake-test-address.obj: test-address.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_address_fake-test-address.obj -MD -MP -MF $(DEPDIR)/test_address_fake-test-address.Tpo -c -o test_address_fake-test-address.obj `if test -f 'test-address.c'; then $(CYGPATH_W) 'test-address.c'; else $(CYGPATH_W) '$(srcdir)/test-address.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_address_fake-test-address.Tpo $(DEPDIR)/test_address_fake-test-address.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-address.c' object='test_address_fake-test-address.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_address_fake-test-address.obj `if test -f 'test-address.c'; then $(CYGPATH_W) 'test-address.c'; else $(CYGPATH_W) '$(srcdir)/test-address.c'; fi` + +test_address_fake-nm-platform.o: ../nm-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_address_fake-nm-platform.o -MD -MP -MF $(DEPDIR)/test_address_fake-nm-platform.Tpo -c -o test_address_fake-nm-platform.o `test -f '../nm-platform.c' || echo '$(srcdir)/'`../nm-platform.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_address_fake-nm-platform.Tpo $(DEPDIR)/test_address_fake-nm-platform.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-platform.c' object='test_address_fake-nm-platform.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_address_fake-nm-platform.o `test -f '../nm-platform.c' || echo '$(srcdir)/'`../nm-platform.c + +test_address_fake-nm-platform.obj: ../nm-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_address_fake-nm-platform.obj -MD -MP -MF $(DEPDIR)/test_address_fake-nm-platform.Tpo -c -o test_address_fake-nm-platform.obj `if test -f '../nm-platform.c'; then $(CYGPATH_W) '../nm-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-platform.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_address_fake-nm-platform.Tpo $(DEPDIR)/test_address_fake-nm-platform.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-platform.c' object='test_address_fake-nm-platform.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_address_fake-nm-platform.obj `if test -f '../nm-platform.c'; then $(CYGPATH_W) '../nm-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-platform.c'; fi` + +test_address_fake-nm-fake-platform.o: ../nm-fake-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_address_fake-nm-fake-platform.o -MD -MP -MF $(DEPDIR)/test_address_fake-nm-fake-platform.Tpo -c -o test_address_fake-nm-fake-platform.o `test -f '../nm-fake-platform.c' || echo '$(srcdir)/'`../nm-fake-platform.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_address_fake-nm-fake-platform.Tpo $(DEPDIR)/test_address_fake-nm-fake-platform.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-fake-platform.c' object='test_address_fake-nm-fake-platform.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_address_fake-nm-fake-platform.o `test -f '../nm-fake-platform.c' || echo '$(srcdir)/'`../nm-fake-platform.c + +test_address_fake-nm-fake-platform.obj: ../nm-fake-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_address_fake-nm-fake-platform.obj -MD -MP -MF $(DEPDIR)/test_address_fake-nm-fake-platform.Tpo -c -o test_address_fake-nm-fake-platform.obj `if test -f '../nm-fake-platform.c'; then $(CYGPATH_W) '../nm-fake-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-fake-platform.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_address_fake-nm-fake-platform.Tpo $(DEPDIR)/test_address_fake-nm-fake-platform.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-fake-platform.c' object='test_address_fake-nm-fake-platform.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_address_fake-nm-fake-platform.obj `if test -f '../nm-fake-platform.c'; then $(CYGPATH_W) '../nm-fake-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-fake-platform.c'; fi` + +test_address_fake-nm-linux-platform.o: ../nm-linux-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_address_fake-nm-linux-platform.o -MD -MP -MF $(DEPDIR)/test_address_fake-nm-linux-platform.Tpo -c -o test_address_fake-nm-linux-platform.o `test -f '../nm-linux-platform.c' || echo '$(srcdir)/'`../nm-linux-platform.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_address_fake-nm-linux-platform.Tpo $(DEPDIR)/test_address_fake-nm-linux-platform.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-linux-platform.c' object='test_address_fake-nm-linux-platform.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_address_fake-nm-linux-platform.o `test -f '../nm-linux-platform.c' || echo '$(srcdir)/'`../nm-linux-platform.c + +test_address_fake-nm-linux-platform.obj: ../nm-linux-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_address_fake-nm-linux-platform.obj -MD -MP -MF $(DEPDIR)/test_address_fake-nm-linux-platform.Tpo -c -o test_address_fake-nm-linux-platform.obj `if test -f '../nm-linux-platform.c'; then $(CYGPATH_W) '../nm-linux-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-linux-platform.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_address_fake-nm-linux-platform.Tpo $(DEPDIR)/test_address_fake-nm-linux-platform.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-linux-platform.c' object='test_address_fake-nm-linux-platform.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_address_fake-nm-linux-platform.obj `if test -f '../nm-linux-platform.c'; then $(CYGPATH_W) '../nm-linux-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-linux-platform.c'; fi` + +test_address_fake-test-common.o: test-common.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_address_fake-test-common.o -MD -MP -MF $(DEPDIR)/test_address_fake-test-common.Tpo -c -o test_address_fake-test-common.o `test -f 'test-common.c' || echo '$(srcdir)/'`test-common.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_address_fake-test-common.Tpo $(DEPDIR)/test_address_fake-test-common.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-common.c' object='test_address_fake-test-common.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_address_fake-test-common.o `test -f 'test-common.c' || echo '$(srcdir)/'`test-common.c + +test_address_fake-test-common.obj: test-common.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_address_fake-test-common.obj -MD -MP -MF $(DEPDIR)/test_address_fake-test-common.Tpo -c -o test_address_fake-test-common.obj `if test -f 'test-common.c'; then $(CYGPATH_W) 'test-common.c'; else $(CYGPATH_W) '$(srcdir)/test-common.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_address_fake-test-common.Tpo $(DEPDIR)/test_address_fake-test-common.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-common.c' object='test_address_fake-test-common.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_address_fake-test-common.obj `if test -f 'test-common.c'; then $(CYGPATH_W) 'test-common.c'; else $(CYGPATH_W) '$(srcdir)/test-common.c'; fi` + +test_address_linux-test-address.o: test-address.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_address_linux-test-address.o -MD -MP -MF $(DEPDIR)/test_address_linux-test-address.Tpo -c -o test_address_linux-test-address.o `test -f 'test-address.c' || echo '$(srcdir)/'`test-address.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_address_linux-test-address.Tpo $(DEPDIR)/test_address_linux-test-address.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-address.c' object='test_address_linux-test-address.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_address_linux-test-address.o `test -f 'test-address.c' || echo '$(srcdir)/'`test-address.c + +test_address_linux-test-address.obj: test-address.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_address_linux-test-address.obj -MD -MP -MF $(DEPDIR)/test_address_linux-test-address.Tpo -c -o test_address_linux-test-address.obj `if test -f 'test-address.c'; then $(CYGPATH_W) 'test-address.c'; else $(CYGPATH_W) '$(srcdir)/test-address.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_address_linux-test-address.Tpo $(DEPDIR)/test_address_linux-test-address.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-address.c' object='test_address_linux-test-address.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_address_linux-test-address.obj `if test -f 'test-address.c'; then $(CYGPATH_W) 'test-address.c'; else $(CYGPATH_W) '$(srcdir)/test-address.c'; fi` + +test_address_linux-nm-platform.o: ../nm-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_address_linux-nm-platform.o -MD -MP -MF $(DEPDIR)/test_address_linux-nm-platform.Tpo -c -o test_address_linux-nm-platform.o `test -f '../nm-platform.c' || echo '$(srcdir)/'`../nm-platform.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_address_linux-nm-platform.Tpo $(DEPDIR)/test_address_linux-nm-platform.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-platform.c' object='test_address_linux-nm-platform.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_address_linux-nm-platform.o `test -f '../nm-platform.c' || echo '$(srcdir)/'`../nm-platform.c + +test_address_linux-nm-platform.obj: ../nm-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_address_linux-nm-platform.obj -MD -MP -MF $(DEPDIR)/test_address_linux-nm-platform.Tpo -c -o test_address_linux-nm-platform.obj `if test -f '../nm-platform.c'; then $(CYGPATH_W) '../nm-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-platform.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_address_linux-nm-platform.Tpo $(DEPDIR)/test_address_linux-nm-platform.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-platform.c' object='test_address_linux-nm-platform.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_address_linux-nm-platform.obj `if test -f '../nm-platform.c'; then $(CYGPATH_W) '../nm-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-platform.c'; fi` + +test_address_linux-nm-fake-platform.o: ../nm-fake-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_address_linux-nm-fake-platform.o -MD -MP -MF $(DEPDIR)/test_address_linux-nm-fake-platform.Tpo -c -o test_address_linux-nm-fake-platform.o `test -f '../nm-fake-platform.c' || echo '$(srcdir)/'`../nm-fake-platform.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_address_linux-nm-fake-platform.Tpo $(DEPDIR)/test_address_linux-nm-fake-platform.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-fake-platform.c' object='test_address_linux-nm-fake-platform.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_address_linux-nm-fake-platform.o `test -f '../nm-fake-platform.c' || echo '$(srcdir)/'`../nm-fake-platform.c + +test_address_linux-nm-fake-platform.obj: ../nm-fake-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_address_linux-nm-fake-platform.obj -MD -MP -MF $(DEPDIR)/test_address_linux-nm-fake-platform.Tpo -c -o test_address_linux-nm-fake-platform.obj `if test -f '../nm-fake-platform.c'; then $(CYGPATH_W) '../nm-fake-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-fake-platform.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_address_linux-nm-fake-platform.Tpo $(DEPDIR)/test_address_linux-nm-fake-platform.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-fake-platform.c' object='test_address_linux-nm-fake-platform.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_address_linux-nm-fake-platform.obj `if test -f '../nm-fake-platform.c'; then $(CYGPATH_W) '../nm-fake-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-fake-platform.c'; fi` + +test_address_linux-nm-linux-platform.o: ../nm-linux-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_address_linux-nm-linux-platform.o -MD -MP -MF $(DEPDIR)/test_address_linux-nm-linux-platform.Tpo -c -o test_address_linux-nm-linux-platform.o `test -f '../nm-linux-platform.c' || echo '$(srcdir)/'`../nm-linux-platform.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_address_linux-nm-linux-platform.Tpo $(DEPDIR)/test_address_linux-nm-linux-platform.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-linux-platform.c' object='test_address_linux-nm-linux-platform.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_address_linux-nm-linux-platform.o `test -f '../nm-linux-platform.c' || echo '$(srcdir)/'`../nm-linux-platform.c + +test_address_linux-nm-linux-platform.obj: ../nm-linux-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_address_linux-nm-linux-platform.obj -MD -MP -MF $(DEPDIR)/test_address_linux-nm-linux-platform.Tpo -c -o test_address_linux-nm-linux-platform.obj `if test -f '../nm-linux-platform.c'; then $(CYGPATH_W) '../nm-linux-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-linux-platform.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_address_linux-nm-linux-platform.Tpo $(DEPDIR)/test_address_linux-nm-linux-platform.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-linux-platform.c' object='test_address_linux-nm-linux-platform.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_address_linux-nm-linux-platform.obj `if test -f '../nm-linux-platform.c'; then $(CYGPATH_W) '../nm-linux-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-linux-platform.c'; fi` + +test_address_linux-test-common.o: test-common.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_address_linux-test-common.o -MD -MP -MF $(DEPDIR)/test_address_linux-test-common.Tpo -c -o test_address_linux-test-common.o `test -f 'test-common.c' || echo '$(srcdir)/'`test-common.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_address_linux-test-common.Tpo $(DEPDIR)/test_address_linux-test-common.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-common.c' object='test_address_linux-test-common.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_address_linux-test-common.o `test -f 'test-common.c' || echo '$(srcdir)/'`test-common.c + +test_address_linux-test-common.obj: test-common.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_address_linux-test-common.obj -MD -MP -MF $(DEPDIR)/test_address_linux-test-common.Tpo -c -o test_address_linux-test-common.obj `if test -f 'test-common.c'; then $(CYGPATH_W) 'test-common.c'; else $(CYGPATH_W) '$(srcdir)/test-common.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_address_linux-test-common.Tpo $(DEPDIR)/test_address_linux-test-common.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-common.c' object='test_address_linux-test-common.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_address_linux-test-common.obj `if test -f 'test-common.c'; then $(CYGPATH_W) 'test-common.c'; else $(CYGPATH_W) '$(srcdir)/test-common.c'; fi` + +test_cleanup_fake-test-cleanup.o: test-cleanup.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_cleanup_fake-test-cleanup.o -MD -MP -MF $(DEPDIR)/test_cleanup_fake-test-cleanup.Tpo -c -o test_cleanup_fake-test-cleanup.o `test -f 'test-cleanup.c' || echo '$(srcdir)/'`test-cleanup.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_cleanup_fake-test-cleanup.Tpo $(DEPDIR)/test_cleanup_fake-test-cleanup.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-cleanup.c' object='test_cleanup_fake-test-cleanup.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_cleanup_fake-test-cleanup.o `test -f 'test-cleanup.c' || echo '$(srcdir)/'`test-cleanup.c + +test_cleanup_fake-test-cleanup.obj: test-cleanup.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_cleanup_fake-test-cleanup.obj -MD -MP -MF $(DEPDIR)/test_cleanup_fake-test-cleanup.Tpo -c -o test_cleanup_fake-test-cleanup.obj `if test -f 'test-cleanup.c'; then $(CYGPATH_W) 'test-cleanup.c'; else $(CYGPATH_W) '$(srcdir)/test-cleanup.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_cleanup_fake-test-cleanup.Tpo $(DEPDIR)/test_cleanup_fake-test-cleanup.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-cleanup.c' object='test_cleanup_fake-test-cleanup.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_cleanup_fake-test-cleanup.obj `if test -f 'test-cleanup.c'; then $(CYGPATH_W) 'test-cleanup.c'; else $(CYGPATH_W) '$(srcdir)/test-cleanup.c'; fi` + +test_cleanup_fake-nm-platform.o: ../nm-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_cleanup_fake-nm-platform.o -MD -MP -MF $(DEPDIR)/test_cleanup_fake-nm-platform.Tpo -c -o test_cleanup_fake-nm-platform.o `test -f '../nm-platform.c' || echo '$(srcdir)/'`../nm-platform.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_cleanup_fake-nm-platform.Tpo $(DEPDIR)/test_cleanup_fake-nm-platform.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-platform.c' object='test_cleanup_fake-nm-platform.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_cleanup_fake-nm-platform.o `test -f '../nm-platform.c' || echo '$(srcdir)/'`../nm-platform.c + +test_cleanup_fake-nm-platform.obj: ../nm-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_cleanup_fake-nm-platform.obj -MD -MP -MF $(DEPDIR)/test_cleanup_fake-nm-platform.Tpo -c -o test_cleanup_fake-nm-platform.obj `if test -f '../nm-platform.c'; then $(CYGPATH_W) '../nm-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-platform.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_cleanup_fake-nm-platform.Tpo $(DEPDIR)/test_cleanup_fake-nm-platform.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-platform.c' object='test_cleanup_fake-nm-platform.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_cleanup_fake-nm-platform.obj `if test -f '../nm-platform.c'; then $(CYGPATH_W) '../nm-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-platform.c'; fi` + +test_cleanup_fake-nm-fake-platform.o: ../nm-fake-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_cleanup_fake-nm-fake-platform.o -MD -MP -MF $(DEPDIR)/test_cleanup_fake-nm-fake-platform.Tpo -c -o test_cleanup_fake-nm-fake-platform.o `test -f '../nm-fake-platform.c' || echo '$(srcdir)/'`../nm-fake-platform.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_cleanup_fake-nm-fake-platform.Tpo $(DEPDIR)/test_cleanup_fake-nm-fake-platform.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-fake-platform.c' object='test_cleanup_fake-nm-fake-platform.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_cleanup_fake-nm-fake-platform.o `test -f '../nm-fake-platform.c' || echo '$(srcdir)/'`../nm-fake-platform.c + +test_cleanup_fake-nm-fake-platform.obj: ../nm-fake-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_cleanup_fake-nm-fake-platform.obj -MD -MP -MF $(DEPDIR)/test_cleanup_fake-nm-fake-platform.Tpo -c -o test_cleanup_fake-nm-fake-platform.obj `if test -f '../nm-fake-platform.c'; then $(CYGPATH_W) '../nm-fake-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-fake-platform.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_cleanup_fake-nm-fake-platform.Tpo $(DEPDIR)/test_cleanup_fake-nm-fake-platform.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-fake-platform.c' object='test_cleanup_fake-nm-fake-platform.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_cleanup_fake-nm-fake-platform.obj `if test -f '../nm-fake-platform.c'; then $(CYGPATH_W) '../nm-fake-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-fake-platform.c'; fi` + +test_cleanup_fake-nm-linux-platform.o: ../nm-linux-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_cleanup_fake-nm-linux-platform.o -MD -MP -MF $(DEPDIR)/test_cleanup_fake-nm-linux-platform.Tpo -c -o test_cleanup_fake-nm-linux-platform.o `test -f '../nm-linux-platform.c' || echo '$(srcdir)/'`../nm-linux-platform.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_cleanup_fake-nm-linux-platform.Tpo $(DEPDIR)/test_cleanup_fake-nm-linux-platform.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-linux-platform.c' object='test_cleanup_fake-nm-linux-platform.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_cleanup_fake-nm-linux-platform.o `test -f '../nm-linux-platform.c' || echo '$(srcdir)/'`../nm-linux-platform.c + +test_cleanup_fake-nm-linux-platform.obj: ../nm-linux-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_cleanup_fake-nm-linux-platform.obj -MD -MP -MF $(DEPDIR)/test_cleanup_fake-nm-linux-platform.Tpo -c -o test_cleanup_fake-nm-linux-platform.obj `if test -f '../nm-linux-platform.c'; then $(CYGPATH_W) '../nm-linux-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-linux-platform.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_cleanup_fake-nm-linux-platform.Tpo $(DEPDIR)/test_cleanup_fake-nm-linux-platform.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-linux-platform.c' object='test_cleanup_fake-nm-linux-platform.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_cleanup_fake-nm-linux-platform.obj `if test -f '../nm-linux-platform.c'; then $(CYGPATH_W) '../nm-linux-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-linux-platform.c'; fi` + +test_cleanup_fake-test-common.o: test-common.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_cleanup_fake-test-common.o -MD -MP -MF $(DEPDIR)/test_cleanup_fake-test-common.Tpo -c -o test_cleanup_fake-test-common.o `test -f 'test-common.c' || echo '$(srcdir)/'`test-common.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_cleanup_fake-test-common.Tpo $(DEPDIR)/test_cleanup_fake-test-common.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-common.c' object='test_cleanup_fake-test-common.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_cleanup_fake-test-common.o `test -f 'test-common.c' || echo '$(srcdir)/'`test-common.c + +test_cleanup_fake-test-common.obj: test-common.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_cleanup_fake-test-common.obj -MD -MP -MF $(DEPDIR)/test_cleanup_fake-test-common.Tpo -c -o test_cleanup_fake-test-common.obj `if test -f 'test-common.c'; then $(CYGPATH_W) 'test-common.c'; else $(CYGPATH_W) '$(srcdir)/test-common.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_cleanup_fake-test-common.Tpo $(DEPDIR)/test_cleanup_fake-test-common.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-common.c' object='test_cleanup_fake-test-common.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_cleanup_fake-test-common.obj `if test -f 'test-common.c'; then $(CYGPATH_W) 'test-common.c'; else $(CYGPATH_W) '$(srcdir)/test-common.c'; fi` + +test_cleanup_linux-test-cleanup.o: test-cleanup.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_cleanup_linux-test-cleanup.o -MD -MP -MF $(DEPDIR)/test_cleanup_linux-test-cleanup.Tpo -c -o test_cleanup_linux-test-cleanup.o `test -f 'test-cleanup.c' || echo '$(srcdir)/'`test-cleanup.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_cleanup_linux-test-cleanup.Tpo $(DEPDIR)/test_cleanup_linux-test-cleanup.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-cleanup.c' object='test_cleanup_linux-test-cleanup.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_cleanup_linux-test-cleanup.o `test -f 'test-cleanup.c' || echo '$(srcdir)/'`test-cleanup.c + +test_cleanup_linux-test-cleanup.obj: test-cleanup.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_cleanup_linux-test-cleanup.obj -MD -MP -MF $(DEPDIR)/test_cleanup_linux-test-cleanup.Tpo -c -o test_cleanup_linux-test-cleanup.obj `if test -f 'test-cleanup.c'; then $(CYGPATH_W) 'test-cleanup.c'; else $(CYGPATH_W) '$(srcdir)/test-cleanup.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_cleanup_linux-test-cleanup.Tpo $(DEPDIR)/test_cleanup_linux-test-cleanup.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-cleanup.c' object='test_cleanup_linux-test-cleanup.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_cleanup_linux-test-cleanup.obj `if test -f 'test-cleanup.c'; then $(CYGPATH_W) 'test-cleanup.c'; else $(CYGPATH_W) '$(srcdir)/test-cleanup.c'; fi` + +test_cleanup_linux-nm-platform.o: ../nm-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_cleanup_linux-nm-platform.o -MD -MP -MF $(DEPDIR)/test_cleanup_linux-nm-platform.Tpo -c -o test_cleanup_linux-nm-platform.o `test -f '../nm-platform.c' || echo '$(srcdir)/'`../nm-platform.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_cleanup_linux-nm-platform.Tpo $(DEPDIR)/test_cleanup_linux-nm-platform.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-platform.c' object='test_cleanup_linux-nm-platform.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_cleanup_linux-nm-platform.o `test -f '../nm-platform.c' || echo '$(srcdir)/'`../nm-platform.c + +test_cleanup_linux-nm-platform.obj: ../nm-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_cleanup_linux-nm-platform.obj -MD -MP -MF $(DEPDIR)/test_cleanup_linux-nm-platform.Tpo -c -o test_cleanup_linux-nm-platform.obj `if test -f '../nm-platform.c'; then $(CYGPATH_W) '../nm-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-platform.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_cleanup_linux-nm-platform.Tpo $(DEPDIR)/test_cleanup_linux-nm-platform.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-platform.c' object='test_cleanup_linux-nm-platform.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_cleanup_linux-nm-platform.obj `if test -f '../nm-platform.c'; then $(CYGPATH_W) '../nm-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-platform.c'; fi` + +test_cleanup_linux-nm-fake-platform.o: ../nm-fake-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_cleanup_linux-nm-fake-platform.o -MD -MP -MF $(DEPDIR)/test_cleanup_linux-nm-fake-platform.Tpo -c -o test_cleanup_linux-nm-fake-platform.o `test -f '../nm-fake-platform.c' || echo '$(srcdir)/'`../nm-fake-platform.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_cleanup_linux-nm-fake-platform.Tpo $(DEPDIR)/test_cleanup_linux-nm-fake-platform.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-fake-platform.c' object='test_cleanup_linux-nm-fake-platform.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_cleanup_linux-nm-fake-platform.o `test -f '../nm-fake-platform.c' || echo '$(srcdir)/'`../nm-fake-platform.c + +test_cleanup_linux-nm-fake-platform.obj: ../nm-fake-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_cleanup_linux-nm-fake-platform.obj -MD -MP -MF $(DEPDIR)/test_cleanup_linux-nm-fake-platform.Tpo -c -o test_cleanup_linux-nm-fake-platform.obj `if test -f '../nm-fake-platform.c'; then $(CYGPATH_W) '../nm-fake-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-fake-platform.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_cleanup_linux-nm-fake-platform.Tpo $(DEPDIR)/test_cleanup_linux-nm-fake-platform.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-fake-platform.c' object='test_cleanup_linux-nm-fake-platform.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_cleanup_linux-nm-fake-platform.obj `if test -f '../nm-fake-platform.c'; then $(CYGPATH_W) '../nm-fake-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-fake-platform.c'; fi` + +test_cleanup_linux-nm-linux-platform.o: ../nm-linux-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_cleanup_linux-nm-linux-platform.o -MD -MP -MF $(DEPDIR)/test_cleanup_linux-nm-linux-platform.Tpo -c -o test_cleanup_linux-nm-linux-platform.o `test -f '../nm-linux-platform.c' || echo '$(srcdir)/'`../nm-linux-platform.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_cleanup_linux-nm-linux-platform.Tpo $(DEPDIR)/test_cleanup_linux-nm-linux-platform.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-linux-platform.c' object='test_cleanup_linux-nm-linux-platform.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_cleanup_linux-nm-linux-platform.o `test -f '../nm-linux-platform.c' || echo '$(srcdir)/'`../nm-linux-platform.c + +test_cleanup_linux-nm-linux-platform.obj: ../nm-linux-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_cleanup_linux-nm-linux-platform.obj -MD -MP -MF $(DEPDIR)/test_cleanup_linux-nm-linux-platform.Tpo -c -o test_cleanup_linux-nm-linux-platform.obj `if test -f '../nm-linux-platform.c'; then $(CYGPATH_W) '../nm-linux-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-linux-platform.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_cleanup_linux-nm-linux-platform.Tpo $(DEPDIR)/test_cleanup_linux-nm-linux-platform.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-linux-platform.c' object='test_cleanup_linux-nm-linux-platform.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_cleanup_linux-nm-linux-platform.obj `if test -f '../nm-linux-platform.c'; then $(CYGPATH_W) '../nm-linux-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-linux-platform.c'; fi` + +test_cleanup_linux-test-common.o: test-common.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_cleanup_linux-test-common.o -MD -MP -MF $(DEPDIR)/test_cleanup_linux-test-common.Tpo -c -o test_cleanup_linux-test-common.o `test -f 'test-common.c' || echo '$(srcdir)/'`test-common.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_cleanup_linux-test-common.Tpo $(DEPDIR)/test_cleanup_linux-test-common.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-common.c' object='test_cleanup_linux-test-common.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_cleanup_linux-test-common.o `test -f 'test-common.c' || echo '$(srcdir)/'`test-common.c + +test_cleanup_linux-test-common.obj: test-common.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_cleanup_linux-test-common.obj -MD -MP -MF $(DEPDIR)/test_cleanup_linux-test-common.Tpo -c -o test_cleanup_linux-test-common.obj `if test -f 'test-common.c'; then $(CYGPATH_W) 'test-common.c'; else $(CYGPATH_W) '$(srcdir)/test-common.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_cleanup_linux-test-common.Tpo $(DEPDIR)/test_cleanup_linux-test-common.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-common.c' object='test_cleanup_linux-test-common.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_cleanup_linux-test-common.obj `if test -f 'test-common.c'; then $(CYGPATH_W) 'test-common.c'; else $(CYGPATH_W) '$(srcdir)/test-common.c'; fi` + +test_link_fake-test-link.o: test-link.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_link_fake-test-link.o -MD -MP -MF $(DEPDIR)/test_link_fake-test-link.Tpo -c -o test_link_fake-test-link.o `test -f 'test-link.c' || echo '$(srcdir)/'`test-link.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_link_fake-test-link.Tpo $(DEPDIR)/test_link_fake-test-link.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-link.c' object='test_link_fake-test-link.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_link_fake-test-link.o `test -f 'test-link.c' || echo '$(srcdir)/'`test-link.c + +test_link_fake-test-link.obj: test-link.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_link_fake-test-link.obj -MD -MP -MF $(DEPDIR)/test_link_fake-test-link.Tpo -c -o test_link_fake-test-link.obj `if test -f 'test-link.c'; then $(CYGPATH_W) 'test-link.c'; else $(CYGPATH_W) '$(srcdir)/test-link.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_link_fake-test-link.Tpo $(DEPDIR)/test_link_fake-test-link.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-link.c' object='test_link_fake-test-link.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_link_fake-test-link.obj `if test -f 'test-link.c'; then $(CYGPATH_W) 'test-link.c'; else $(CYGPATH_W) '$(srcdir)/test-link.c'; fi` + +test_link_fake-nm-platform.o: ../nm-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_link_fake-nm-platform.o -MD -MP -MF $(DEPDIR)/test_link_fake-nm-platform.Tpo -c -o test_link_fake-nm-platform.o `test -f '../nm-platform.c' || echo '$(srcdir)/'`../nm-platform.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_link_fake-nm-platform.Tpo $(DEPDIR)/test_link_fake-nm-platform.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-platform.c' object='test_link_fake-nm-platform.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_link_fake-nm-platform.o `test -f '../nm-platform.c' || echo '$(srcdir)/'`../nm-platform.c + +test_link_fake-nm-platform.obj: ../nm-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_link_fake-nm-platform.obj -MD -MP -MF $(DEPDIR)/test_link_fake-nm-platform.Tpo -c -o test_link_fake-nm-platform.obj `if test -f '../nm-platform.c'; then $(CYGPATH_W) '../nm-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-platform.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_link_fake-nm-platform.Tpo $(DEPDIR)/test_link_fake-nm-platform.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-platform.c' object='test_link_fake-nm-platform.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_link_fake-nm-platform.obj `if test -f '../nm-platform.c'; then $(CYGPATH_W) '../nm-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-platform.c'; fi` + +test_link_fake-nm-fake-platform.o: ../nm-fake-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_link_fake-nm-fake-platform.o -MD -MP -MF $(DEPDIR)/test_link_fake-nm-fake-platform.Tpo -c -o test_link_fake-nm-fake-platform.o `test -f '../nm-fake-platform.c' || echo '$(srcdir)/'`../nm-fake-platform.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_link_fake-nm-fake-platform.Tpo $(DEPDIR)/test_link_fake-nm-fake-platform.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-fake-platform.c' object='test_link_fake-nm-fake-platform.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_link_fake-nm-fake-platform.o `test -f '../nm-fake-platform.c' || echo '$(srcdir)/'`../nm-fake-platform.c + +test_link_fake-nm-fake-platform.obj: ../nm-fake-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_link_fake-nm-fake-platform.obj -MD -MP -MF $(DEPDIR)/test_link_fake-nm-fake-platform.Tpo -c -o test_link_fake-nm-fake-platform.obj `if test -f '../nm-fake-platform.c'; then $(CYGPATH_W) '../nm-fake-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-fake-platform.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_link_fake-nm-fake-platform.Tpo $(DEPDIR)/test_link_fake-nm-fake-platform.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-fake-platform.c' object='test_link_fake-nm-fake-platform.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_link_fake-nm-fake-platform.obj `if test -f '../nm-fake-platform.c'; then $(CYGPATH_W) '../nm-fake-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-fake-platform.c'; fi` + +test_link_fake-nm-linux-platform.o: ../nm-linux-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_link_fake-nm-linux-platform.o -MD -MP -MF $(DEPDIR)/test_link_fake-nm-linux-platform.Tpo -c -o test_link_fake-nm-linux-platform.o `test -f '../nm-linux-platform.c' || echo '$(srcdir)/'`../nm-linux-platform.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_link_fake-nm-linux-platform.Tpo $(DEPDIR)/test_link_fake-nm-linux-platform.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-linux-platform.c' object='test_link_fake-nm-linux-platform.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_link_fake-nm-linux-platform.o `test -f '../nm-linux-platform.c' || echo '$(srcdir)/'`../nm-linux-platform.c + +test_link_fake-nm-linux-platform.obj: ../nm-linux-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_link_fake-nm-linux-platform.obj -MD -MP -MF $(DEPDIR)/test_link_fake-nm-linux-platform.Tpo -c -o test_link_fake-nm-linux-platform.obj `if test -f '../nm-linux-platform.c'; then $(CYGPATH_W) '../nm-linux-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-linux-platform.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_link_fake-nm-linux-platform.Tpo $(DEPDIR)/test_link_fake-nm-linux-platform.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-linux-platform.c' object='test_link_fake-nm-linux-platform.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_link_fake-nm-linux-platform.obj `if test -f '../nm-linux-platform.c'; then $(CYGPATH_W) '../nm-linux-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-linux-platform.c'; fi` + +test_link_fake-test-common.o: test-common.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_link_fake-test-common.o -MD -MP -MF $(DEPDIR)/test_link_fake-test-common.Tpo -c -o test_link_fake-test-common.o `test -f 'test-common.c' || echo '$(srcdir)/'`test-common.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_link_fake-test-common.Tpo $(DEPDIR)/test_link_fake-test-common.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-common.c' object='test_link_fake-test-common.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_link_fake-test-common.o `test -f 'test-common.c' || echo '$(srcdir)/'`test-common.c + +test_link_fake-test-common.obj: test-common.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_link_fake-test-common.obj -MD -MP -MF $(DEPDIR)/test_link_fake-test-common.Tpo -c -o test_link_fake-test-common.obj `if test -f 'test-common.c'; then $(CYGPATH_W) 'test-common.c'; else $(CYGPATH_W) '$(srcdir)/test-common.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_link_fake-test-common.Tpo $(DEPDIR)/test_link_fake-test-common.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-common.c' object='test_link_fake-test-common.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_link_fake-test-common.obj `if test -f 'test-common.c'; then $(CYGPATH_W) 'test-common.c'; else $(CYGPATH_W) '$(srcdir)/test-common.c'; fi` + +test_link_linux-test-link.o: test-link.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_link_linux-test-link.o -MD -MP -MF $(DEPDIR)/test_link_linux-test-link.Tpo -c -o test_link_linux-test-link.o `test -f 'test-link.c' || echo '$(srcdir)/'`test-link.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_link_linux-test-link.Tpo $(DEPDIR)/test_link_linux-test-link.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-link.c' object='test_link_linux-test-link.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_link_linux-test-link.o `test -f 'test-link.c' || echo '$(srcdir)/'`test-link.c + +test_link_linux-test-link.obj: test-link.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_link_linux-test-link.obj -MD -MP -MF $(DEPDIR)/test_link_linux-test-link.Tpo -c -o test_link_linux-test-link.obj `if test -f 'test-link.c'; then $(CYGPATH_W) 'test-link.c'; else $(CYGPATH_W) '$(srcdir)/test-link.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_link_linux-test-link.Tpo $(DEPDIR)/test_link_linux-test-link.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-link.c' object='test_link_linux-test-link.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_link_linux-test-link.obj `if test -f 'test-link.c'; then $(CYGPATH_W) 'test-link.c'; else $(CYGPATH_W) '$(srcdir)/test-link.c'; fi` + +test_link_linux-nm-platform.o: ../nm-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_link_linux-nm-platform.o -MD -MP -MF $(DEPDIR)/test_link_linux-nm-platform.Tpo -c -o test_link_linux-nm-platform.o `test -f '../nm-platform.c' || echo '$(srcdir)/'`../nm-platform.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_link_linux-nm-platform.Tpo $(DEPDIR)/test_link_linux-nm-platform.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-platform.c' object='test_link_linux-nm-platform.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_link_linux-nm-platform.o `test -f '../nm-platform.c' || echo '$(srcdir)/'`../nm-platform.c + +test_link_linux-nm-platform.obj: ../nm-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_link_linux-nm-platform.obj -MD -MP -MF $(DEPDIR)/test_link_linux-nm-platform.Tpo -c -o test_link_linux-nm-platform.obj `if test -f '../nm-platform.c'; then $(CYGPATH_W) '../nm-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-platform.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_link_linux-nm-platform.Tpo $(DEPDIR)/test_link_linux-nm-platform.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-platform.c' object='test_link_linux-nm-platform.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_link_linux-nm-platform.obj `if test -f '../nm-platform.c'; then $(CYGPATH_W) '../nm-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-platform.c'; fi` + +test_link_linux-nm-fake-platform.o: ../nm-fake-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_link_linux-nm-fake-platform.o -MD -MP -MF $(DEPDIR)/test_link_linux-nm-fake-platform.Tpo -c -o test_link_linux-nm-fake-platform.o `test -f '../nm-fake-platform.c' || echo '$(srcdir)/'`../nm-fake-platform.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_link_linux-nm-fake-platform.Tpo $(DEPDIR)/test_link_linux-nm-fake-platform.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-fake-platform.c' object='test_link_linux-nm-fake-platform.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_link_linux-nm-fake-platform.o `test -f '../nm-fake-platform.c' || echo '$(srcdir)/'`../nm-fake-platform.c + +test_link_linux-nm-fake-platform.obj: ../nm-fake-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_link_linux-nm-fake-platform.obj -MD -MP -MF $(DEPDIR)/test_link_linux-nm-fake-platform.Tpo -c -o test_link_linux-nm-fake-platform.obj `if test -f '../nm-fake-platform.c'; then $(CYGPATH_W) '../nm-fake-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-fake-platform.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_link_linux-nm-fake-platform.Tpo $(DEPDIR)/test_link_linux-nm-fake-platform.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-fake-platform.c' object='test_link_linux-nm-fake-platform.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_link_linux-nm-fake-platform.obj `if test -f '../nm-fake-platform.c'; then $(CYGPATH_W) '../nm-fake-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-fake-platform.c'; fi` + +test_link_linux-nm-linux-platform.o: ../nm-linux-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_link_linux-nm-linux-platform.o -MD -MP -MF $(DEPDIR)/test_link_linux-nm-linux-platform.Tpo -c -o test_link_linux-nm-linux-platform.o `test -f '../nm-linux-platform.c' || echo '$(srcdir)/'`../nm-linux-platform.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_link_linux-nm-linux-platform.Tpo $(DEPDIR)/test_link_linux-nm-linux-platform.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-linux-platform.c' object='test_link_linux-nm-linux-platform.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_link_linux-nm-linux-platform.o `test -f '../nm-linux-platform.c' || echo '$(srcdir)/'`../nm-linux-platform.c + +test_link_linux-nm-linux-platform.obj: ../nm-linux-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_link_linux-nm-linux-platform.obj -MD -MP -MF $(DEPDIR)/test_link_linux-nm-linux-platform.Tpo -c -o test_link_linux-nm-linux-platform.obj `if test -f '../nm-linux-platform.c'; then $(CYGPATH_W) '../nm-linux-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-linux-platform.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_link_linux-nm-linux-platform.Tpo $(DEPDIR)/test_link_linux-nm-linux-platform.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-linux-platform.c' object='test_link_linux-nm-linux-platform.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_link_linux-nm-linux-platform.obj `if test -f '../nm-linux-platform.c'; then $(CYGPATH_W) '../nm-linux-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-linux-platform.c'; fi` + +test_link_linux-test-common.o: test-common.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_link_linux-test-common.o -MD -MP -MF $(DEPDIR)/test_link_linux-test-common.Tpo -c -o test_link_linux-test-common.o `test -f 'test-common.c' || echo '$(srcdir)/'`test-common.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_link_linux-test-common.Tpo $(DEPDIR)/test_link_linux-test-common.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-common.c' object='test_link_linux-test-common.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_link_linux-test-common.o `test -f 'test-common.c' || echo '$(srcdir)/'`test-common.c + +test_link_linux-test-common.obj: test-common.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_link_linux-test-common.obj -MD -MP -MF $(DEPDIR)/test_link_linux-test-common.Tpo -c -o test_link_linux-test-common.obj `if test -f 'test-common.c'; then $(CYGPATH_W) 'test-common.c'; else $(CYGPATH_W) '$(srcdir)/test-common.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_link_linux-test-common.Tpo $(DEPDIR)/test_link_linux-test-common.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-common.c' object='test_link_linux-test-common.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_link_linux-test-common.obj `if test -f 'test-common.c'; then $(CYGPATH_W) 'test-common.c'; else $(CYGPATH_W) '$(srcdir)/test-common.c'; fi` + +test_route_fake-test-route.o: test-route.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_route_fake-test-route.o -MD -MP -MF $(DEPDIR)/test_route_fake-test-route.Tpo -c -o test_route_fake-test-route.o `test -f 'test-route.c' || echo '$(srcdir)/'`test-route.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_route_fake-test-route.Tpo $(DEPDIR)/test_route_fake-test-route.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-route.c' object='test_route_fake-test-route.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_route_fake-test-route.o `test -f 'test-route.c' || echo '$(srcdir)/'`test-route.c + +test_route_fake-test-route.obj: test-route.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_route_fake-test-route.obj -MD -MP -MF $(DEPDIR)/test_route_fake-test-route.Tpo -c -o test_route_fake-test-route.obj `if test -f 'test-route.c'; then $(CYGPATH_W) 'test-route.c'; else $(CYGPATH_W) '$(srcdir)/test-route.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_route_fake-test-route.Tpo $(DEPDIR)/test_route_fake-test-route.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-route.c' object='test_route_fake-test-route.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_route_fake-test-route.obj `if test -f 'test-route.c'; then $(CYGPATH_W) 'test-route.c'; else $(CYGPATH_W) '$(srcdir)/test-route.c'; fi` + +test_route_fake-nm-platform.o: ../nm-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_route_fake-nm-platform.o -MD -MP -MF $(DEPDIR)/test_route_fake-nm-platform.Tpo -c -o test_route_fake-nm-platform.o `test -f '../nm-platform.c' || echo '$(srcdir)/'`../nm-platform.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_route_fake-nm-platform.Tpo $(DEPDIR)/test_route_fake-nm-platform.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-platform.c' object='test_route_fake-nm-platform.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_route_fake-nm-platform.o `test -f '../nm-platform.c' || echo '$(srcdir)/'`../nm-platform.c + +test_route_fake-nm-platform.obj: ../nm-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_route_fake-nm-platform.obj -MD -MP -MF $(DEPDIR)/test_route_fake-nm-platform.Tpo -c -o test_route_fake-nm-platform.obj `if test -f '../nm-platform.c'; then $(CYGPATH_W) '../nm-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-platform.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_route_fake-nm-platform.Tpo $(DEPDIR)/test_route_fake-nm-platform.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-platform.c' object='test_route_fake-nm-platform.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_route_fake-nm-platform.obj `if test -f '../nm-platform.c'; then $(CYGPATH_W) '../nm-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-platform.c'; fi` + +test_route_fake-nm-fake-platform.o: ../nm-fake-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_route_fake-nm-fake-platform.o -MD -MP -MF $(DEPDIR)/test_route_fake-nm-fake-platform.Tpo -c -o test_route_fake-nm-fake-platform.o `test -f '../nm-fake-platform.c' || echo '$(srcdir)/'`../nm-fake-platform.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_route_fake-nm-fake-platform.Tpo $(DEPDIR)/test_route_fake-nm-fake-platform.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-fake-platform.c' object='test_route_fake-nm-fake-platform.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_route_fake-nm-fake-platform.o `test -f '../nm-fake-platform.c' || echo '$(srcdir)/'`../nm-fake-platform.c + +test_route_fake-nm-fake-platform.obj: ../nm-fake-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_route_fake-nm-fake-platform.obj -MD -MP -MF $(DEPDIR)/test_route_fake-nm-fake-platform.Tpo -c -o test_route_fake-nm-fake-platform.obj `if test -f '../nm-fake-platform.c'; then $(CYGPATH_W) '../nm-fake-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-fake-platform.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_route_fake-nm-fake-platform.Tpo $(DEPDIR)/test_route_fake-nm-fake-platform.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-fake-platform.c' object='test_route_fake-nm-fake-platform.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_route_fake-nm-fake-platform.obj `if test -f '../nm-fake-platform.c'; then $(CYGPATH_W) '../nm-fake-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-fake-platform.c'; fi` + +test_route_fake-nm-linux-platform.o: ../nm-linux-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_route_fake-nm-linux-platform.o -MD -MP -MF $(DEPDIR)/test_route_fake-nm-linux-platform.Tpo -c -o test_route_fake-nm-linux-platform.o `test -f '../nm-linux-platform.c' || echo '$(srcdir)/'`../nm-linux-platform.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_route_fake-nm-linux-platform.Tpo $(DEPDIR)/test_route_fake-nm-linux-platform.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-linux-platform.c' object='test_route_fake-nm-linux-platform.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_route_fake-nm-linux-platform.o `test -f '../nm-linux-platform.c' || echo '$(srcdir)/'`../nm-linux-platform.c + +test_route_fake-nm-linux-platform.obj: ../nm-linux-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_route_fake-nm-linux-platform.obj -MD -MP -MF $(DEPDIR)/test_route_fake-nm-linux-platform.Tpo -c -o test_route_fake-nm-linux-platform.obj `if test -f '../nm-linux-platform.c'; then $(CYGPATH_W) '../nm-linux-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-linux-platform.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_route_fake-nm-linux-platform.Tpo $(DEPDIR)/test_route_fake-nm-linux-platform.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-linux-platform.c' object='test_route_fake-nm-linux-platform.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_route_fake-nm-linux-platform.obj `if test -f '../nm-linux-platform.c'; then $(CYGPATH_W) '../nm-linux-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-linux-platform.c'; fi` + +test_route_fake-test-common.o: test-common.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_route_fake-test-common.o -MD -MP -MF $(DEPDIR)/test_route_fake-test-common.Tpo -c -o test_route_fake-test-common.o `test -f 'test-common.c' || echo '$(srcdir)/'`test-common.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_route_fake-test-common.Tpo $(DEPDIR)/test_route_fake-test-common.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-common.c' object='test_route_fake-test-common.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_route_fake-test-common.o `test -f 'test-common.c' || echo '$(srcdir)/'`test-common.c + +test_route_fake-test-common.obj: test-common.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_route_fake-test-common.obj -MD -MP -MF $(DEPDIR)/test_route_fake-test-common.Tpo -c -o test_route_fake-test-common.obj `if test -f 'test-common.c'; then $(CYGPATH_W) 'test-common.c'; else $(CYGPATH_W) '$(srcdir)/test-common.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_route_fake-test-common.Tpo $(DEPDIR)/test_route_fake-test-common.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-common.c' object='test_route_fake-test-common.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_route_fake-test-common.obj `if test -f 'test-common.c'; then $(CYGPATH_W) 'test-common.c'; else $(CYGPATH_W) '$(srcdir)/test-common.c'; fi` + +test_route_linux-test-route.o: test-route.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_route_linux-test-route.o -MD -MP -MF $(DEPDIR)/test_route_linux-test-route.Tpo -c -o test_route_linux-test-route.o `test -f 'test-route.c' || echo '$(srcdir)/'`test-route.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_route_linux-test-route.Tpo $(DEPDIR)/test_route_linux-test-route.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-route.c' object='test_route_linux-test-route.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_route_linux-test-route.o `test -f 'test-route.c' || echo '$(srcdir)/'`test-route.c + +test_route_linux-test-route.obj: test-route.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_route_linux-test-route.obj -MD -MP -MF $(DEPDIR)/test_route_linux-test-route.Tpo -c -o test_route_linux-test-route.obj `if test -f 'test-route.c'; then $(CYGPATH_W) 'test-route.c'; else $(CYGPATH_W) '$(srcdir)/test-route.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_route_linux-test-route.Tpo $(DEPDIR)/test_route_linux-test-route.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-route.c' object='test_route_linux-test-route.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_route_linux-test-route.obj `if test -f 'test-route.c'; then $(CYGPATH_W) 'test-route.c'; else $(CYGPATH_W) '$(srcdir)/test-route.c'; fi` + +test_route_linux-nm-platform.o: ../nm-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_route_linux-nm-platform.o -MD -MP -MF $(DEPDIR)/test_route_linux-nm-platform.Tpo -c -o test_route_linux-nm-platform.o `test -f '../nm-platform.c' || echo '$(srcdir)/'`../nm-platform.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_route_linux-nm-platform.Tpo $(DEPDIR)/test_route_linux-nm-platform.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-platform.c' object='test_route_linux-nm-platform.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_route_linux-nm-platform.o `test -f '../nm-platform.c' || echo '$(srcdir)/'`../nm-platform.c + +test_route_linux-nm-platform.obj: ../nm-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_route_linux-nm-platform.obj -MD -MP -MF $(DEPDIR)/test_route_linux-nm-platform.Tpo -c -o test_route_linux-nm-platform.obj `if test -f '../nm-platform.c'; then $(CYGPATH_W) '../nm-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-platform.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_route_linux-nm-platform.Tpo $(DEPDIR)/test_route_linux-nm-platform.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-platform.c' object='test_route_linux-nm-platform.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_route_linux-nm-platform.obj `if test -f '../nm-platform.c'; then $(CYGPATH_W) '../nm-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-platform.c'; fi` + +test_route_linux-nm-fake-platform.o: ../nm-fake-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_route_linux-nm-fake-platform.o -MD -MP -MF $(DEPDIR)/test_route_linux-nm-fake-platform.Tpo -c -o test_route_linux-nm-fake-platform.o `test -f '../nm-fake-platform.c' || echo '$(srcdir)/'`../nm-fake-platform.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_route_linux-nm-fake-platform.Tpo $(DEPDIR)/test_route_linux-nm-fake-platform.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-fake-platform.c' object='test_route_linux-nm-fake-platform.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_route_linux-nm-fake-platform.o `test -f '../nm-fake-platform.c' || echo '$(srcdir)/'`../nm-fake-platform.c + +test_route_linux-nm-fake-platform.obj: ../nm-fake-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_route_linux-nm-fake-platform.obj -MD -MP -MF $(DEPDIR)/test_route_linux-nm-fake-platform.Tpo -c -o test_route_linux-nm-fake-platform.obj `if test -f '../nm-fake-platform.c'; then $(CYGPATH_W) '../nm-fake-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-fake-platform.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_route_linux-nm-fake-platform.Tpo $(DEPDIR)/test_route_linux-nm-fake-platform.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-fake-platform.c' object='test_route_linux-nm-fake-platform.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_route_linux-nm-fake-platform.obj `if test -f '../nm-fake-platform.c'; then $(CYGPATH_W) '../nm-fake-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-fake-platform.c'; fi` + +test_route_linux-nm-linux-platform.o: ../nm-linux-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_route_linux-nm-linux-platform.o -MD -MP -MF $(DEPDIR)/test_route_linux-nm-linux-platform.Tpo -c -o test_route_linux-nm-linux-platform.o `test -f '../nm-linux-platform.c' || echo '$(srcdir)/'`../nm-linux-platform.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_route_linux-nm-linux-platform.Tpo $(DEPDIR)/test_route_linux-nm-linux-platform.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-linux-platform.c' object='test_route_linux-nm-linux-platform.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_route_linux-nm-linux-platform.o `test -f '../nm-linux-platform.c' || echo '$(srcdir)/'`../nm-linux-platform.c + +test_route_linux-nm-linux-platform.obj: ../nm-linux-platform.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_route_linux-nm-linux-platform.obj -MD -MP -MF $(DEPDIR)/test_route_linux-nm-linux-platform.Tpo -c -o test_route_linux-nm-linux-platform.obj `if test -f '../nm-linux-platform.c'; then $(CYGPATH_W) '../nm-linux-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-linux-platform.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_route_linux-nm-linux-platform.Tpo $(DEPDIR)/test_route_linux-nm-linux-platform.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-linux-platform.c' object='test_route_linux-nm-linux-platform.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_route_linux-nm-linux-platform.obj `if test -f '../nm-linux-platform.c'; then $(CYGPATH_W) '../nm-linux-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-linux-platform.c'; fi` + +test_route_linux-test-common.o: test-common.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_route_linux-test-common.o -MD -MP -MF $(DEPDIR)/test_route_linux-test-common.Tpo -c -o test_route_linux-test-common.o `test -f 'test-common.c' || echo '$(srcdir)/'`test-common.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_route_linux-test-common.Tpo $(DEPDIR)/test_route_linux-test-common.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-common.c' object='test_route_linux-test-common.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_route_linux-test-common.o `test -f 'test-common.c' || echo '$(srcdir)/'`test-common.c + +test_route_linux-test-common.obj: test-common.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_route_linux-test-common.obj -MD -MP -MF $(DEPDIR)/test_route_linux-test-common.Tpo -c -o test_route_linux-test-common.obj `if test -f 'test-common.c'; then $(CYGPATH_W) 'test-common.c'; else $(CYGPATH_W) '$(srcdir)/test-common.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_route_linux-test-common.Tpo $(DEPDIR)/test_route_linux-test-common.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-common.c' object='test_route_linux-test-common.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_route_linux-test-common.obj `if test -f 'test-common.c'; then $(CYGPATH_W) 'test-common.c'; else $(CYGPATH_W) '$(srcdir)/test-common.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +check-TESTS: $(TESTS) + @failed=0; all=0; xfail=0; xpass=0; skip=0; \ + srcdir=$(srcdir); export srcdir; \ + list=' $(TESTS) '; \ + $(am__tty_colors); \ + if test -n "$$list"; then \ + for tst in $$list; do \ + if test -f ./$$tst; then dir=./; \ + elif test -f $$tst; then dir=; \ + else dir="$(srcdir)/"; fi; \ + if $(TESTS_ENVIRONMENT) $${dir}$$tst $(AM_TESTS_FD_REDIRECT); then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$tst[\ \ ]*) \ + xpass=`expr $$xpass + 1`; \ + failed=`expr $$failed + 1`; \ + col=$$red; res=XPASS; \ + ;; \ + *) \ + col=$$grn; res=PASS; \ + ;; \ + esac; \ + elif test $$? -ne 77; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$tst[\ \ ]*) \ + xfail=`expr $$xfail + 1`; \ + col=$$lgn; res=XFAIL; \ + ;; \ + *) \ + failed=`expr $$failed + 1`; \ + col=$$red; res=FAIL; \ + ;; \ + esac; \ + else \ + skip=`expr $$skip + 1`; \ + col=$$blu; res=SKIP; \ + fi; \ + echo "$${col}$$res$${std}: $$tst"; \ + done; \ + if test "$$all" -eq 1; then \ + tests="test"; \ + All=""; \ + else \ + tests="tests"; \ + All="All "; \ + fi; \ + if test "$$failed" -eq 0; then \ + if test "$$xfail" -eq 0; then \ + banner="$$All$$all $$tests passed"; \ + else \ + if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \ + banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \ + fi; \ + else \ + if test "$$xpass" -eq 0; then \ + banner="$$failed of $$all $$tests failed"; \ + else \ + if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \ + banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \ + fi; \ + fi; \ + dashes="$$banner"; \ + skipped=""; \ + if test "$$skip" -ne 0; then \ + if test "$$skip" -eq 1; then \ + skipped="($$skip test was not run)"; \ + else \ + skipped="($$skip tests were not run)"; \ + fi; \ + test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$skipped"; \ + fi; \ + report=""; \ + if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ + report="Please report to $(PACKAGE_BUGREPORT)"; \ + test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$report"; \ + fi; \ + dashes=`echo "$$dashes" | sed s/./=/g`; \ + if test "$$failed" -eq 0; then \ + col="$$grn"; \ + else \ + col="$$red"; \ + fi; \ + echo "$${col}$$dashes$${std}"; \ + echo "$${col}$$banner$${std}"; \ + test -z "$$skipped" || echo "$${col}$$skipped$${std}"; \ + test -z "$$report" || echo "$${col}$$report$${std}"; \ + echo "$${col}$$dashes$${std}"; \ + test "$$failed" -eq 0; \ + else :; fi + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: check-am install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ + clean-generic clean-libtool clean-noinstPROGRAMS cscopelist-am \ + ctags ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + + +@GNOME_CODE_COVERAGE_RULES@ + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/platform/tests/dump.c b/src/platform/tests/dump.c new file mode 100644 index 00000000..e97ef138 --- /dev/null +++ b/src/platform/tests/dump.c @@ -0,0 +1,136 @@ +#include +#include +#include + +#include "nm-platform.h" +#include "nm-linux-platform.h" +#include "nm-fake-platform.h" + +static void +dump_interface (NMPlatformLink *link) +{ + GArray *ip6_addresses; + GArray *ip4_addresses; + const NMPlatformIP6Address *ip6_address; + const NMPlatformIP4Address *ip4_address; + GArray *ip6_routes; + GArray *ip4_routes; + const NMPlatformIP6Route *ip6_route; + const NMPlatformIP4Route *ip4_route; + char networkstr[INET6_ADDRSTRLEN]; + char gatewaystr[INET6_ADDRSTRLEN]; + int vlan_id, vlan_parent; + const char *address; + size_t addrlen; + int i; + + g_assert (link->up || !link->connected); + + printf ("%d: %s: %s", link->ifindex, link->name, link->type_name); + if (link->up) + printf (" %s", link->connected ? "CONNECTED" : "DISCONNECTED"); + else + printf (" DOWN"); + if (!link->arp) + printf (" noarp"); + if (link->master) + printf (" master %d", link->master); + if (link->parent) + printf (" parent %d", link->parent); + printf (" mtu %d", link->mtu); + printf ("\n"); + if (link->driver) + printf (" driver: %s\n", link->driver); + printf (" UDI: %s\n", link->udi); + if (!nm_platform_vlan_get_info (link->ifindex, &vlan_parent, &vlan_id)) + g_assert_not_reached (); + if (vlan_parent) + printf (" vlan parent %d id %d\n", vlan_parent, vlan_id); + + if (nm_platform_link_is_software (link->ifindex)) + printf (" class software\n"); + if (nm_platform_link_supports_slaves (link->ifindex)) + printf (" class supports-slaves\n"); + if (nm_platform_link_supports_carrier_detect (link->ifindex)) + printf (" feature carrier-detect\n"); + if (nm_platform_link_supports_vlans (link->ifindex)) + printf (" feature vlans\n"); + + address = nm_platform_link_get_address (link->ifindex, &addrlen); + if (address) { + printf (" link-address "); + for (i = 0; i < addrlen; i++) + printf ("%s%02hhx", i ? ":" : "", address[i]); + printf ("\n"); + } + + ip4_addresses = nm_platform_ip4_address_get_all (link->ifindex); + ip6_addresses = nm_platform_ip6_address_get_all (link->ifindex); + + g_assert (ip4_addresses); + g_assert (ip6_addresses); + + for (i = 0; i < ip4_addresses->len; i++) { + ip4_address = &g_array_index (ip4_addresses, NMPlatformIP4Address, i); + printf (" ip4-address %s\n", nm_platform_ip4_address_to_string (ip4_address)); + } + + for (i = 0; i < ip6_addresses->len; i++) { + ip6_address = &g_array_index (ip6_addresses, NMPlatformIP6Address, i); + printf (" ip6-address %s\n", nm_platform_ip6_address_to_string (ip6_address)); + } + + g_array_unref (ip4_addresses); + g_array_unref (ip6_addresses); + + ip4_routes = nm_platform_ip4_route_get_all (link->ifindex, TRUE); + ip6_routes = nm_platform_ip6_route_get_all (link->ifindex, TRUE); + + g_assert (ip4_routes); + g_assert (ip6_routes); + + for (i = 0; i < ip4_routes->len; i++) { + ip4_route = &g_array_index (ip4_routes, NMPlatformIP4Route, i); + inet_ntop (AF_INET, &ip4_route->network, networkstr, sizeof (networkstr)); + inet_ntop (AF_INET, &ip4_route->gateway, gatewaystr, sizeof (gatewaystr)); + printf (" ip4-route %s/%d via %s\n", networkstr, ip4_route->plen, gatewaystr); + } + + for (i = 0; i < ip6_routes->len; i++) { + ip6_route = &g_array_index (ip6_routes, NMPlatformIP6Route, i); + inet_ntop (AF_INET6, &ip6_route->network, networkstr, sizeof (networkstr)); + inet_ntop (AF_INET6, &ip6_route->gateway, gatewaystr, sizeof (gatewaystr)); + printf (" ip6-route %s/%d via %s\n", networkstr, ip6_route->plen, gatewaystr); + } + + g_array_unref (ip4_routes); + g_array_unref (ip6_routes); +} + +static void +dump_all (void) +{ + GArray *links = nm_platform_link_get_all (); + int i; + + for (i = 0; i < links->len; i++) + dump_interface (&g_array_index (links, NMPlatformLink, i)); +} + +int +main (int argc, char **argv) +{ +#if !GLIB_CHECK_VERSION (2, 35, 0) + g_type_init (); +#endif + + g_assert (argc <= 2); + if (argc > 1 && !g_strcmp0 (argv[1], "--fake")) + nm_fake_platform_setup (); + else + nm_linux_platform_setup (); + + dump_all (); + + return EXIT_SUCCESS; +} diff --git a/src/platform/tests/monitor.c b/src/platform/tests/monitor.c new file mode 100644 index 00000000..d56cc2bf --- /dev/null +++ b/src/platform/tests/monitor.c @@ -0,0 +1,30 @@ +#include +#include + +#include "nm-fake-platform.h" +#include "nm-linux-platform.h" +#include "nm-logging.h" + +int +main (int argc, char **argv) +{ + GMainLoop *loop; + +#if !GLIB_CHECK_VERSION (2, 35, 0) + g_type_init (); +#endif + + loop = g_main_loop_new (NULL, FALSE); + nm_logging_setup ("debug", NULL, NULL, NULL); + openlog (G_LOG_DOMAIN, LOG_CONS | LOG_PERROR, LOG_DAEMON); + + g_assert (argc <= 2); + if (argc > 1 && !g_strcmp0 (argv[1], "--fake")) + nm_fake_platform_setup (); + else + nm_linux_platform_setup (); + + g_main_loop_run (loop); + + return EXIT_SUCCESS; +} diff --git a/src/platform/tests/platform.c b/src/platform/tests/platform.c new file mode 100644 index 00000000..ea8bd0e3 --- /dev/null +++ b/src/platform/tests/platform.c @@ -0,0 +1,897 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* nm-platform.c - Handle runtime kernel networking configuration + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2013 Red Hat, Inc. + */ + +#include +#include +#include +#include +#include + +#include "nm-platform.h" +#include "nm-linux-platform.h" +#include "nm-fake-platform.h" + +#define error(...) fprintf (stderr, __VA_ARGS__) + +typedef gboolean boolean_t; +typedef int decimal_t; +typedef const char *string_t; + +#define print_boolean(value) printf ("%s\n", value ? "yes" : "no") +#define print_decimal(value) printf ("%d\n", value) +#define print_string(value) printf ("%s\n", value) + +static gboolean +do_sysctl_set (char **argv) +{ + return nm_platform_sysctl_set (argv[0], argv[1]); +} + +static gboolean +do_sysctl_get (char **argv) +{ + auto_g_free char *value = nm_platform_sysctl_get (argv[0]); + + printf ("%s\n", value); + + return !!value; +} + +static int +parse_ifindex (const char *str) +{ + char *endptr; + int ifindex = 0; + + ifindex = strtol (str, &endptr, 10); + + if (*endptr) { + ifindex = nm_platform_link_get_ifindex (str); + } + + return ifindex; +} + +static gboolean +do_link_get_all (char **argv) +{ + GArray *links; + NMPlatformLink *device; + int i; + + links = nm_platform_link_get_all (); + for (i = 0; i < links->len; i++) { + device = &g_array_index (links, NMPlatformLink, i); + + printf ("%d: %s type %d\n", device->ifindex, device->name, device->type); + } + g_array_unref (links); + + return TRUE; +} + +static gboolean +do_dummy_add (char **argv) +{ + return nm_platform_dummy_add (argv[0]); +} + +static gboolean +do_bridge_add (char **argv) +{ + return nm_platform_bridge_add (argv[0], NULL, 0); +} + +static gboolean +do_bond_add (char **argv) +{ + return nm_platform_bond_add (argv[0]); +} + +static gboolean +do_team_add (char **argv) +{ + return nm_platform_team_add (argv[0]); +} + +static gboolean +do_vlan_add (char **argv) +{ + const char *name = *argv++; + int parent = parse_ifindex (*argv++); + int vlanid = strtol (*argv++, NULL, 10); + guint32 vlan_flags = strtol (*argv++, NULL, 10); + + return nm_platform_vlan_add (name, parent, vlanid, vlan_flags); +} + +static gboolean +do_link_exists (char **argv) +{ + gboolean value = nm_platform_link_exists (argv[0]); + + print_boolean (value); + + return TRUE; +} + +#define LINK_CMD(cmdname) \ + static gboolean \ + do_link_##cmdname (char **argv) \ + { \ + int ifindex = parse_ifindex (argv[0]); \ + return ifindex ? nm_platform_link_##cmdname (ifindex) : FALSE; \ + } + +#define LINK_CMD_GET_FULL(cmdname, type, cond) \ + static gboolean \ + do_link_##cmdname (char **argv) \ + { \ + int ifindex = parse_ifindex (argv[0]); \ + if (ifindex) { \ + type##_t value = nm_platform_link_##cmdname (ifindex); \ + if (cond) { \ + print_##type (value); \ + return TRUE; \ + } \ + } \ + return FALSE; \ + } +#define LINK_CMD_GET(cmdname, type) LINK_CMD_GET_FULL (cmdname, type, TRUE); + +LINK_CMD (delete) + +/* do_link_delete_by_ifname: + * + * We don't need this as we allow ifname instead of ifindex anyway. + */ + +static gboolean +do_link_get_ifindex (char **argv) +{ + int ifindex = nm_platform_link_get_ifindex (argv[0]); + + if (ifindex) + printf ("%d\n", ifindex); + + return !!ifindex; +} + +LINK_CMD_GET_FULL (get_name, string, value) +LINK_CMD_GET_FULL (get_type, decimal, value > 0) +LINK_CMD_GET (is_software, boolean) +LINK_CMD_GET (supports_slaves, boolean) + +LINK_CMD (set_up) +LINK_CMD (set_down) +LINK_CMD (set_arp) +LINK_CMD (set_noarp) +LINK_CMD_GET (is_up, boolean) +LINK_CMD_GET (is_connected, boolean) +LINK_CMD_GET (uses_arp, boolean) + +static gboolean +do_link_set_address (char **argv) +{ + int ifindex = parse_ifindex (*argv++); + char *hex = *argv++; + int hexlen = strlen (hex); + char address[hexlen/2]; + char *endptr; + int i; + + g_assert (!(hexlen % 2)); + + for (i = 0; i < sizeof (address); i++) { + char digit[3]; + + digit[0] = hex[2*i]; + digit[1] = hex[2*i+1]; + digit[2] = '\0'; + + address[i] = strtoul (digit, &endptr, 16); + g_assert (!*endptr); + } + + return nm_platform_link_set_address (ifindex, address, sizeof (address)); +} + +static gboolean +do_link_get_address (char **argv) +{ + int ifindex = parse_ifindex (*argv++); + const char *address; + size_t length; + int i; + + address = nm_platform_link_get_address (ifindex, &length); + + if (!address || length <= 0) + return FALSE; + + for (i = 0; i < length; i++) + printf ("%02x", address[i]); + printf ("\n"); + + return TRUE; +} + +static gboolean +do_link_set_mtu (char **argv) +{ + int ifindex = parse_ifindex (*argv++); + int mtu = strtoul (*argv++, NULL, 10); + + return nm_platform_link_set_mtu (ifindex, mtu); +} + +LINK_CMD_GET (get_mtu, decimal); +LINK_CMD_GET (supports_carrier_detect, boolean) +LINK_CMD_GET (supports_vlans, boolean) + +static gboolean +do_link_enslave (char **argv) +{ + int master = parse_ifindex (*argv++); + int slave = parse_ifindex (*argv++); + + return nm_platform_link_enslave (master, slave); +} + +static gboolean +do_link_release (char **argv) +{ + int master = parse_ifindex (*argv++); + int slave = parse_ifindex (*argv++); + + return nm_platform_link_release (master, slave); +} + +LINK_CMD_GET (get_master, decimal) + +static gboolean +do_master_set_option (char **argv) +{ + int ifindex = parse_ifindex (*argv++); + const char *option = *argv++; + const char *value = *argv++; + + return nm_platform_master_set_option (ifindex, option, value); +} + +static gboolean +do_master_get_option (char **argv) +{ + int ifindex = parse_ifindex (*argv++); + const char *option = *argv++; + auto_g_free char *value = nm_platform_master_get_option (ifindex, option); + + printf ("%s\n", value); + + return !!value; +} + +static gboolean +do_slave_set_option (char **argv) +{ + int ifindex = parse_ifindex (*argv++); + const char *option = *argv++; + const char *value = *argv++; + + return nm_platform_slave_set_option (ifindex, option, value); +} + +static gboolean +do_slave_get_option (char **argv) +{ + int ifindex = parse_ifindex (*argv++); + const char *option = *argv++; + auto_g_free char *value = nm_platform_slave_get_option (ifindex, option); + + printf ("%s\n", value); + + return !!value; +} + +static gboolean +do_vlan_get_info (char **argv) +{ + int ifindex = parse_ifindex (*argv++); + int parent; + int vlanid; + + if (!nm_platform_vlan_get_info (ifindex, &parent, &vlanid)) + return FALSE; + + printf ("%d %d\n", parent, vlanid); + + return TRUE; +} + +static gboolean +do_vlan_set_ingress_map (char **argv) +{ + int ifindex = parse_ifindex (*argv++); + int from = strtol (*argv++, NULL, 10); + int to = strtol (*argv++, NULL, 10); + + return nm_platform_vlan_set_ingress_map (ifindex, from, to); +} + +static gboolean +do_vlan_set_egress_map (char **argv) +{ + int ifindex = parse_ifindex (*argv++); + int from = strtol (*argv++, NULL, 10); + int to = strtol (*argv++, NULL, 10); + + return nm_platform_vlan_set_egress_map (ifindex, from, to); +} + +static gboolean +do_veth_get_properties (char **argv) +{ + int ifindex = parse_ifindex (*argv++); + NMPlatformVethProperties props; + + if (!nm_platform_veth_get_properties (ifindex, &props)) + return FALSE; + + printf ("peer: %d\n", props.peer); + + return TRUE; +} + +static gboolean +do_tun_get_properties (char **argv) +{ + int ifindex = parse_ifindex (*argv++); + NMPlatformTunProperties props; + + if (!nm_platform_tun_get_properties (ifindex, &props)) + return FALSE; + + printf ("mode: %s\n", props.mode); + if (props.owner == -1) + printf ("owner: none\n"); + else + printf ("owner: %lu\n", (gulong) props.owner); + if (props.group == -1) + printf ("group: none\n"); + else + printf ("group: %lu\n", (gulong) props.group); + printf ("no-pi: "); + print_boolean (props.no_pi); + printf ("vnet-hdr: "); + print_boolean (props.vnet_hdr); + printf ("multi-queue: "); + print_boolean (props.multi_queue); + + return TRUE; +} + +static gboolean +do_macvlan_get_properties (char **argv) +{ + int ifindex = parse_ifindex (*argv++); + NMPlatformMacvlanProperties props; + + if (!nm_platform_macvlan_get_properties (ifindex, &props)) + return FALSE; + + printf ("parent: %d\n", props.parent_ifindex); + printf ("mode: %s\n", props.mode); + printf ("no-promisc: "); + print_boolean (props.no_promisc); + return TRUE; +} + +static gboolean +do_vxlan_get_properties (char **argv) +{ + int ifindex = parse_ifindex (*argv++); + NMPlatformVxlanProperties props; + char addrstr[INET6_ADDRSTRLEN]; + + if (!nm_platform_vxlan_get_properties (ifindex, &props)) + return FALSE; + + printf ("parent-ifindex: %u\n", props.parent_ifindex); + printf ("id: %u\n", props.id); + if (props.group) + inet_ntop (AF_INET, &props.group, addrstr, sizeof (addrstr)); + else if (props.group6.s6_addr[0]) + inet_ntop (AF_INET6, &props.group6, addrstr, sizeof (addrstr)); + else + strcpy (addrstr, "-"); + printf ("group: %s\n", addrstr); + if (props.local) + inet_ntop (AF_INET, &props.local, addrstr, sizeof (addrstr)); + else if (props.local6.s6_addr[0]) + inet_ntop (AF_INET6, &props.local6, addrstr, sizeof (addrstr)); + else + strcpy (addrstr, "-"); + printf ("local: %s\n", addrstr); + printf ("tos: %u\n", props.tos); + printf ("ttl: %u\n", props.ttl); + printf ("learning: "); + print_boolean (props.learning); + printf ("ageing: %u\n", props.ageing); + printf ("limit: %u\n", props.limit); + printf ("dst-port: %u\n", props.dst_port); + printf ("src-port-min: %u\n", props.src_port_min); + printf ("src-port-max: %u\n", props.src_port_max); + printf ("proxy: "); + print_boolean (props.proxy); + printf ("rsc: "); + print_boolean (props.rsc); + printf ("l2miss: "); + print_boolean (props.l2miss); + printf ("l3miss: "); + print_boolean (props.l3miss); + + return TRUE; +} + +static gboolean +do_gre_get_properties (char **argv) +{ + int ifindex = parse_ifindex (*argv++); + NMPlatformGreProperties props; + char addrstr[INET_ADDRSTRLEN]; + + if (!nm_platform_gre_get_properties (ifindex, &props)) + return FALSE; + + printf ("parent-ifindex: %u\n", props.parent_ifindex); + printf ("input-flags: %u\n", props.input_flags); + printf ("output-flags: %u\n", props.input_flags); + printf ("input-key: %u\n", props.input_key); + printf ("output-key: %u\n", props.output_key); + if (props.local) + inet_ntop (AF_INET, &props.local, addrstr, sizeof (addrstr)); + else + strcpy (addrstr, "-"); + printf ("local: %s\n", addrstr); + if (props.remote) + inet_ntop (AF_INET, &props.remote, addrstr, sizeof (addrstr)); + else + strcpy (addrstr, "-"); + printf ("remote: %s\n", addrstr); + printf ("ttl: %u\n", props.ttl); + printf ("tos: %u\n", props.tos); + printf ("path-mtu-discovery: "); + print_boolean (props.path_mtu_discovery); + + return TRUE; +} + +static gboolean +do_ip4_address_get_all (char **argv) +{ + int ifindex = parse_ifindex (argv[0]); + GArray *addresses; + NMPlatformIP4Address *address; + char addrstr[INET_ADDRSTRLEN]; + int i; + + if (ifindex) { + addresses = nm_platform_ip4_address_get_all (ifindex); + for (i = 0; i < addresses->len; i++) { + address = &g_array_index (addresses, NMPlatformIP4Address, i); + inet_ntop (AF_INET, &address->address, addrstr, sizeof (addrstr)); + printf ("%s/%d\n", addrstr, address->plen); + } + g_array_unref (addresses); + } + + return !!ifindex; +} + +static gboolean +do_ip6_address_get_all (char **argv) +{ + int ifindex = parse_ifindex (argv[0]); + GArray *addresses; + NMPlatformIP6Address *address; + char addrstr[INET6_ADDRSTRLEN]; + int i; + + if (ifindex) { + addresses = nm_platform_ip6_address_get_all (ifindex); + for (i = 0; i < addresses->len; i++) { + address = &g_array_index (addresses, NMPlatformIP6Address, i); + inet_ntop (AF_INET6, &address->address, addrstr, sizeof (addrstr)); + printf ("%s/%d\n", addrstr, address->plen); + } + g_array_unref (addresses); + } + + return !!ifindex; +} + +static gboolean +parse_ip_address (int family, char *str, gpointer address, int *plen) +{ + char *endptr; + + if (plen) { + char *ptr = strchr (str, '/'); + if (ptr) { + *ptr++ = '\0'; + *plen = strtol (ptr, &endptr, 10); + if (*endptr) + ptr = NULL; + } + if (!ptr) { + error ("Bad format of IP address, expected address/plen.\n"); + return FALSE; + } + } + + if (inet_pton (family, str, address)) + return TRUE; + + error ("Bad format of IP address, expected address%s.\n", plen ? "/plen" : ""); + return FALSE; +} + +typedef in_addr_t ip4_t; +typedef struct in6_addr ip6_t; + +#define parse_ip4_address(s, a, p) parse_ip_address (AF_INET, s, a, p) +#define parse_ip6_address(s, a, p) parse_ip_address (AF_INET6, s, a, p) + +static gboolean +do_ip4_address_add (char **argv) +{ + int ifindex = parse_ifindex (*argv++); + ip4_t address; + int plen; + + if (ifindex && parse_ip4_address (*argv++, &address, &plen)) { + guint32 lifetime = strtol (*argv++, NULL, 10); + guint32 preferred = strtol (*argv++, NULL, 10); + + gboolean value = nm_platform_ip4_address_add (ifindex, address, 0, plen, lifetime, preferred, NULL); + return value; + } else + return FALSE; +} + +static gboolean +do_ip6_address_add (char **argv) +{ + int ifindex = parse_ifindex (*argv++); + ip6_t address; + int plen; + + if (ifindex && parse_ip6_address (*argv++, &address, &plen)) { + guint32 lifetime = strtol (*argv++, NULL, 10); + guint32 preferred = strtol (*argv++, NULL, 10); + guint flags = (*argv) ? rtnl_addr_str2flags (*argv++) : 0; + + gboolean value = nm_platform_ip6_address_add (ifindex, address, in6addr_any, plen, lifetime, preferred, flags); + return value; + } else + return FALSE; +} + +#define ADDR_CMD_FULL(v, cmdname, print) \ + static gboolean \ + do_##v##_address_##cmdname (char **argv) \ + { \ + int ifindex = parse_ifindex (*argv++); \ + v##_t address; \ + int plen; \ + if (ifindex && parse_##v##_address (*argv++, &address, &plen)) { \ + gboolean value = nm_platform_##v##_address_##cmdname (ifindex, address, plen); \ + if (print) { \ + print_boolean (value); \ + return TRUE; \ + } else \ + return value; \ + } else \ + return FALSE; \ + } +#define ADDR_CMD(cmdname) ADDR_CMD_FULL (ip4, cmdname, FALSE) ADDR_CMD_FULL (ip6, cmdname, FALSE) +#define ADDR_CMD_PRINT(cmdname) ADDR_CMD_FULL (ip4, cmdname, TRUE) ADDR_CMD_FULL (ip6, cmdname, TRUE) + +ADDR_CMD (delete) +ADDR_CMD_PRINT (exists) + +static gboolean +do_ip4_route_get_all (char **argv) +{ + int ifindex = parse_ifindex (argv[0]); + GArray *routes; + NMPlatformIP4Route *route; + char networkstr[INET_ADDRSTRLEN], gatewaystr[INET_ADDRSTRLEN]; + int i; + + if (ifindex) { + routes = nm_platform_ip4_route_get_all (ifindex, TRUE); + for (i = 0; i < routes->len; i++) { + route = &g_array_index (routes, NMPlatformIP4Route, i); + inet_ntop (AF_INET, &route->network, networkstr, sizeof (networkstr)); + inet_ntop (AF_INET, &route->gateway, gatewaystr, sizeof (gatewaystr)); + printf ("%s/%d via %s metric %d\n", + networkstr, route->plen, gatewaystr, route->metric); + } + g_array_unref (routes); + } + + return !!ifindex; +} + +static gboolean +do_ip6_route_get_all (char **argv) +{ + int ifindex = parse_ifindex (argv[0]); + GArray *routes; + NMPlatformIP6Route *route; + char networkstr[INET6_ADDRSTRLEN], gatewaystr[INET6_ADDRSTRLEN]; + int i; + + if (ifindex) { + routes = nm_platform_ip6_route_get_all (ifindex, TRUE); + for (i = 0; i < routes->len; i++) { + route = &g_array_index (routes, NMPlatformIP6Route, i); + inet_ntop (AF_INET6, &route->network, networkstr, sizeof (networkstr)); + inet_ntop (AF_INET6, &route->gateway, gatewaystr, sizeof (gatewaystr)); + printf ("%s/%d via %s metric %d\n", + networkstr, route->plen, gatewaystr, route->metric); + } + g_array_unref (routes); + } + + return !!ifindex; +} + +static gboolean +do_ip4_route_add (char **argv) +{ + int ifindex = parse_ifindex (*argv++); + in_addr_t network, gateway; + int plen, metric, mss; + + parse_ip4_address (*argv++, &network, &plen); + parse_ip4_address (*argv++, &gateway, NULL); + metric = strtol (*argv++, NULL, 10); + mss = strtol (*argv++, NULL, 10); + + return nm_platform_ip4_route_add (ifindex, NM_PLATFORM_SOURCE_USER, + network, plen, gateway, + metric, mss); +} + +static gboolean +do_ip6_route_add (char **argv) +{ + int ifindex = parse_ifindex (*argv++); + struct in6_addr network, gateway; + int plen, metric, mss; + + parse_ip6_address (*argv++, &network, &plen); + parse_ip6_address (*argv++, &gateway, NULL); + metric = strtol (*argv++, NULL, 10); + mss = strtol (*argv++, NULL, 10); + return nm_platform_ip6_route_add (ifindex, NM_PLATFORM_SOURCE_USER, + network, plen, gateway, + metric, mss); +} + +static gboolean +do_ip4_route_delete (char **argv) +{ + int ifindex = parse_ifindex (*argv++); + in_addr_t network; + int plen, metric; + + parse_ip4_address (*argv++, &network, &plen); + metric = strtol (*argv++, NULL, 10); + + return nm_platform_ip4_route_delete (ifindex, network, plen, metric); +} + +static gboolean +do_ip6_route_delete (char **argv) +{ + int ifindex = parse_ifindex (*argv++); + struct in6_addr network; + int plen, metric; + + parse_ip6_address (*argv++, &network, &plen); + metric = strtol (*argv++, NULL, 10); + + return nm_platform_ip6_route_delete (ifindex, network, plen, metric); +} + +static gboolean +do_ip4_route_exists (char **argv) +{ + int ifindex = parse_ifindex (*argv++); + in_addr_t network; + int plen, metric; + + parse_ip4_address (*argv++, &network, &plen); + metric = strtol (*argv++, NULL, 10); + + print_boolean (nm_platform_ip4_route_exists (ifindex, network, plen, metric)); + return TRUE; +} + +static gboolean +do_ip6_route_exists (char **argv) +{ + int ifindex = parse_ifindex (*argv++); + struct in6_addr network; + int plen, metric; + + parse_ip6_address (*argv++, &network, &plen); + metric = strtol (*argv++, NULL, 10); + + print_boolean (nm_platform_ip6_route_exists (ifindex, network, plen, metric)); + return TRUE; +} + +typedef struct { + const char *name; + const char *help; + int (*handler) (char **argv); + int argc; + const char *arghelp; +} command_t; + +static const command_t commands[] = { + { "sysctl-set", "get /proc/sys or /sys value", do_sysctl_set, 2, " " }, + { "sysctl-get", "get /proc/sys or /sys value", do_sysctl_get, 1, "" }, + { "link-get-all", "print all links", do_link_get_all, 0, "" }, + { "dummy-add", "add dummy interface", do_dummy_add, 1, "" }, + { "bridge-add", "add bridge interface", do_bridge_add, 1, "" }, + { "bond-add", "add bond interface", do_bond_add, 1, "" }, + { "team-add", "add team interface", do_team_add, 1, "" }, + { "vlan-add", "add vlan interface", do_vlan_add, 4, " " }, + { "link-exists", "check ifname for existance", do_link_exists, 1, "" }, + { "link-delete", "delete interface", do_link_delete, 1, "" }, + { "link-get-ifindex>", "get interface index", do_link_get_ifindex, 1, "" }, + { "link-get-name", "get interface name", do_link_get_name, 1, "" }, + { "link-get-type", "get interface type", do_link_get_type, 1, "" }, + { "link-is-software", "check if interface is a software one", do_link_is_software, 1, "" }, + { "link-supports-slaves", "check if interface supports slaves", do_link_supports_slaves, 1, "" }, + { "link-set-up", "set interface up", do_link_set_up, 1, "" }, + { "link-set-down", "set interface down", do_link_set_down, 1, "" }, + { "link-set-arp", "activate interface arp", do_link_set_arp, 1, "" }, + { "link-set-noarp", "deactivate interface arp", do_link_set_noarp, 1, "" }, + { "link-is-up", "check if interface is up", do_link_is_up, 1, "" }, + { "link-is-connected", "check interface carrier", do_link_is_connected, 1, "" }, + { "link-uses-arp", "check whether interface uses arp", do_link_uses_arp, 1, "" }, + { "link-get-address", "print link address", do_link_get_address, 1, "" }, + { "link-set-address", "set link address", do_link_set_address, 2, " " }, + { "link-get-mtu", "print link mtu", do_link_get_mtu, 1, "" }, + { "link-set-mtu", "set link mtu", do_link_set_mtu, 2, " " }, + { "link-supports-carrier-detect", "check whether interface supports carrier detect", + do_link_supports_carrier_detect, 1, "" }, + { "link-supports-vlans", "check whether interface supports VLANs", + do_link_supports_vlans, 1, "" }, + { "link-enslave", "enslave slave interface with master", do_link_enslave, 2, " " }, + { "link-release", "release save interface from master", do_link_release, 2, " " }, + { "link-get-master", "print master interface of a slave", do_link_get_master, 1, "" }, + { "link-master-set-option", "set master option", do_master_set_option, 3, + "