From 00e64d13320f5848a757765c8541e8160aa8e3e2 Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Wed, 10 Oct 2018 23:30:46 +0200 Subject: [PATCH] core/devices: Add P2P Wifi device and peer tracking This only adds the new device type and simple peer list handling. --- Makefile.am | 134 +- clients/common/nm-client-utils.c | 1 + docs/api/Makefile.am | 59 +- docs/api/network-manager-docs.xml | 7 + introspection/meson.build | 2 + ...ktop.NetworkManager.Device.P2PWireless.xml | 65 + ...org.freedesktop.NetworkManager.P2PPeer.xml | 78 + libnm-core/nm-dbus-interface.h | 5 + src/devices/nm-device.c | 1 + src/devices/wifi/meson.build | 8 +- src/devices/wifi/nm-device-p2p-wifi.c | 1287 +++++++++++++++++ src/devices/wifi/nm-device-p2p-wifi.h | 56 + src/devices/wifi/nm-wifi-p2p-peer.c | 808 +++++++++++ src/devices/wifi/nm-wifi-p2p-peer.h | 114 ++ src/nm-types.h | 1 + src/org.freedesktop.NetworkManager.conf | 4 + 16 files changed, 2539 insertions(+), 91 deletions(-) create mode 100644 introspection/org.freedesktop.NetworkManager.Device.P2PWireless.xml create mode 100644 introspection/org.freedesktop.NetworkManager.P2PPeer.xml create mode 100644 src/devices/wifi/nm-device-p2p-wifi.c create mode 100644 src/devices/wifi/nm-device-p2p-wifi.h create mode 100644 src/devices/wifi/nm-wifi-p2p-peer.c create mode 100644 src/devices/wifi/nm-wifi-p2p-peer.h diff --git a/Makefile.am b/Makefile.am index f7f189b56c..1b7289c011 100644 --- a/Makefile.am +++ b/Makefile.am @@ -389,30 +389,32 @@ introspection_libnmdbus_la_CPPFLAGS = $(GLIB_CFLAGS) introspection_sources = \ introspection/org.freedesktop.NetworkManager.AccessPoint.c \ introspection/org.freedesktop.NetworkManager.AccessPoint.h \ - introspection/org.freedesktop.NetworkManager.Connection.Active.c \ - introspection/org.freedesktop.NetworkManager.Connection.Active.h \ introspection/org.freedesktop.NetworkManager.AgentManager.c \ introspection/org.freedesktop.NetworkManager.AgentManager.h \ introspection/org.freedesktop.NetworkManager.Checkpoint.c \ introspection/org.freedesktop.NetworkManager.Checkpoint.h \ + introspection/org.freedesktop.NetworkManager.Connection.Active.c \ + introspection/org.freedesktop.NetworkManager.Connection.Active.h \ + introspection/org.freedesktop.NetworkManager.DHCP4Config.c \ + introspection/org.freedesktop.NetworkManager.DHCP4Config.h \ + introspection/org.freedesktop.NetworkManager.DHCP6Config.c \ + introspection/org.freedesktop.NetworkManager.DHCP6Config.h \ introspection/org.freedesktop.NetworkManager.Device.Adsl.c \ introspection/org.freedesktop.NetworkManager.Device.Adsl.h \ + introspection/org.freedesktop.NetworkManager.Device.Bluetooth.c \ + introspection/org.freedesktop.NetworkManager.Device.Bluetooth.h \ introspection/org.freedesktop.NetworkManager.Device.Bond.c \ introspection/org.freedesktop.NetworkManager.Device.Bond.h \ introspection/org.freedesktop.NetworkManager.Device.Bridge.c \ introspection/org.freedesktop.NetworkManager.Device.Bridge.h \ - introspection/org.freedesktop.NetworkManager.Device.Bluetooth.c \ - introspection/org.freedesktop.NetworkManager.Device.Bluetooth.h \ introspection/org.freedesktop.NetworkManager.Device.Dummy.c \ introspection/org.freedesktop.NetworkManager.Device.Dummy.h \ - introspection/org.freedesktop.NetworkManager.Device.Wired.c \ - introspection/org.freedesktop.NetworkManager.Device.Wired.h \ introspection/org.freedesktop.NetworkManager.Device.Generic.c \ introspection/org.freedesktop.NetworkManager.Device.Generic.h \ - introspection/org.freedesktop.NetworkManager.Device.Infiniband.c \ - introspection/org.freedesktop.NetworkManager.Device.Infiniband.h \ introspection/org.freedesktop.NetworkManager.Device.IPTunnel.c \ introspection/org.freedesktop.NetworkManager.Device.IPTunnel.h \ + introspection/org.freedesktop.NetworkManager.Device.Infiniband.c \ + introspection/org.freedesktop.NetworkManager.Device.Infiniband.h \ introspection/org.freedesktop.NetworkManager.Device.Lowpan.c \ introspection/org.freedesktop.NetworkManager.Device.Lowpan.h \ introspection/org.freedesktop.NetworkManager.Device.Macsec.c \ @@ -423,12 +425,14 @@ introspection_sources = \ introspection/org.freedesktop.NetworkManager.Device.Modem.h \ introspection/org.freedesktop.NetworkManager.Device.OlpcMesh.c \ introspection/org.freedesktop.NetworkManager.Device.OlpcMesh.h \ + introspection/org.freedesktop.NetworkManager.Device.OvsBridge.c \ + introspection/org.freedesktop.NetworkManager.Device.OvsBridge.h \ introspection/org.freedesktop.NetworkManager.Device.OvsInterface.c \ introspection/org.freedesktop.NetworkManager.Device.OvsInterface.h \ introspection/org.freedesktop.NetworkManager.Device.OvsPort.c \ introspection/org.freedesktop.NetworkManager.Device.OvsPort.h \ - introspection/org.freedesktop.NetworkManager.Device.OvsBridge.c \ - introspection/org.freedesktop.NetworkManager.Device.OvsBridge.h \ + introspection/org.freedesktop.NetworkManager.Device.P2PWireless.c \ + introspection/org.freedesktop.NetworkManager.Device.P2PWireless.h \ introspection/org.freedesktop.NetworkManager.Device.Ppp.c \ introspection/org.freedesktop.NetworkManager.Device.Ppp.h \ introspection/org.freedesktop.NetworkManager.Device.Statistics.c \ @@ -443,28 +447,26 @@ introspection_sources = \ introspection/org.freedesktop.NetworkManager.Device.Vlan.h \ introspection/org.freedesktop.NetworkManager.Device.Vxlan.c \ introspection/org.freedesktop.NetworkManager.Device.Vxlan.h \ - introspection/org.freedesktop.NetworkManager.Device.WireGuard.c \ - introspection/org.freedesktop.NetworkManager.Device.WireGuard.h \ - introspection/org.freedesktop.NetworkManager.Device.Wireless.c \ - introspection/org.freedesktop.NetworkManager.Device.Wireless.h \ introspection/org.freedesktop.NetworkManager.Device.WiMax.c \ introspection/org.freedesktop.NetworkManager.Device.WiMax.h \ + introspection/org.freedesktop.NetworkManager.Device.WireGuard.c \ + introspection/org.freedesktop.NetworkManager.Device.WireGuard.h \ + introspection/org.freedesktop.NetworkManager.Device.Wired.c \ + introspection/org.freedesktop.NetworkManager.Device.Wired.h \ + introspection/org.freedesktop.NetworkManager.Device.Wireless.c \ + introspection/org.freedesktop.NetworkManager.Device.Wireless.h \ introspection/org.freedesktop.NetworkManager.Device.Wpan.c \ introspection/org.freedesktop.NetworkManager.Device.Wpan.h \ introspection/org.freedesktop.NetworkManager.Device.c \ introspection/org.freedesktop.NetworkManager.Device.h \ - introspection/org.freedesktop.NetworkManager.DHCP4Config.c \ - introspection/org.freedesktop.NetworkManager.DHCP4Config.h \ - introspection/org.freedesktop.NetworkManager.DHCP6Config.c \ - introspection/org.freedesktop.NetworkManager.DHCP6Config.h \ introspection/org.freedesktop.NetworkManager.DnsManager.c \ introspection/org.freedesktop.NetworkManager.DnsManager.h \ introspection/org.freedesktop.NetworkManager.IP4Config.c \ introspection/org.freedesktop.NetworkManager.IP4Config.h \ introspection/org.freedesktop.NetworkManager.IP6Config.c \ introspection/org.freedesktop.NetworkManager.IP6Config.h \ - introspection/org.freedesktop.NetworkManager.c \ - introspection/org.freedesktop.NetworkManager.h \ + introspection/org.freedesktop.NetworkManager.P2PPeer.c \ + introspection/org.freedesktop.NetworkManager.P2PPeer.h \ introspection/org.freedesktop.NetworkManager.PPP.c \ introspection/org.freedesktop.NetworkManager.PPP.h \ introspection/org.freedesktop.NetworkManager.SecretAgent.c \ @@ -476,56 +478,62 @@ introspection_sources = \ introspection/org.freedesktop.NetworkManager.VPN.Connection.c \ introspection/org.freedesktop.NetworkManager.VPN.Connection.h \ introspection/org.freedesktop.NetworkManager.VPN.Plugin.c \ - introspection/org.freedesktop.NetworkManager.VPN.Plugin.h + introspection/org.freedesktop.NetworkManager.VPN.Plugin.h \ + introspection/org.freedesktop.NetworkManager.c \ + introspection/org.freedesktop.NetworkManager.h \ + $(NULL) nodist_introspection_libnmdbus_la_SOURCES = $(introspection_sources) DBUS_INTERFACE_DOCS = \ docs/api/dbus-org.freedesktop.NetworkManager.AccessPoint.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.Connection.Active.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.AgentManager.xml \ docs/api/dbus-org.freedesktop.NetworkManager.Checkpoint.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.Device.Team.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.Connection.Active.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.DHCP4Config.xml \ docs/api/dbus-org.freedesktop.NetworkManager.DHCP6Config.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.Device.Wireless.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.VPN.Connection.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.SecretAgent.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.Device.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.VPN.Plugin.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.Device.Adsl.xml \ docs/api/dbus-org.freedesktop.NetworkManager.Device.Bluetooth.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.Device.Dummy.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.Device.Vxlan.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.Settings.Connection.xml \ docs/api/dbus-org.freedesktop.NetworkManager.Device.Bond.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.Device.Bridge.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.Device.Dummy.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.Device.Generic.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.Device.IPTunnel.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.Device.Infiniband.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.Device.Lowpan.xml \ docs/api/dbus-org.freedesktop.NetworkManager.Device.Macsec.xml \ docs/api/dbus-org.freedesktop.NetworkManager.Device.Macvlan.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.PPP.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.Device.Vlan.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.Device.Adsl.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.AgentManager.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.Device.WiMax.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.Device.Wpan.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.Device.IPTunnel.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.Device.Tun.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.Device.Bridge.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.Device.Modem.xml \ docs/api/dbus-org.freedesktop.NetworkManager.Device.OlpcMesh.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.Device.OvsBridge.xml \ docs/api/dbus-org.freedesktop.NetworkManager.Device.OvsInterface.xml \ docs/api/dbus-org.freedesktop.NetworkManager.Device.OvsPort.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.Device.OvsBridge.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.Device.P2PWireless.xml \ docs/api/dbus-org.freedesktop.NetworkManager.Device.Ppp.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.DHCP4Config.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.Device.Generic.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.Device.Infiniband.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.Device.Modem.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.IP6Config.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.Device.Veth.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.Settings.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.Device.Wired.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.Device.WireGuard.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.IP4Config.xml \ docs/api/dbus-org.freedesktop.NetworkManager.Device.Statistics.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.Device.Team.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.Device.Tun.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.Device.Veth.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.Device.Vlan.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.Device.Vxlan.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.Device.WiMax.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.Device.WireGuard.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.Device.Wired.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.Device.Wireless.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.Device.Wpan.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.Device.xml \ docs/api/dbus-org.freedesktop.NetworkManager.DnsManager.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.Device.Lowpan.xml + docs/api/dbus-org.freedesktop.NetworkManager.IP4Config.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.IP6Config.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.P2PPeer.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.PPP.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.SecretAgent.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.Settings.Connection.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.Settings.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.VPN.Connection.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.VPN.Plugin.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.xml \ + $(NULL) introspection/%.c: introspection/%.xml @$(MKDIR_P) introspection/ @@ -566,6 +574,7 @@ dbusinterfaces_DATA = \ introspection/org.freedesktop.NetworkManager.Device.OvsInterface.xml \ introspection/org.freedesktop.NetworkManager.Device.OvsPort.xml \ introspection/org.freedesktop.NetworkManager.Device.OvsBridge.xml \ + introspection/org.freedesktop.NetworkManager.Device.P2PWireless.xml \ introspection/org.freedesktop.NetworkManager.Device.Ppp.xml \ introspection/org.freedesktop.NetworkManager.Device.Statistics.xml \ introspection/org.freedesktop.NetworkManager.Device.Team.xml \ @@ -584,6 +593,7 @@ dbusinterfaces_DATA = \ introspection/org.freedesktop.NetworkManager.IP4Config.xml \ introspection/org.freedesktop.NetworkManager.IP6Config.xml \ introspection/org.freedesktop.NetworkManager.xml \ + introspection/org.freedesktop.NetworkManager.P2PPeer.xml \ introspection/org.freedesktop.NetworkManager.PPP.xml \ introspection/org.freedesktop.NetworkManager.SecretAgent.xml \ introspection/org.freedesktop.NetworkManager.Settings.Connection.xml \ @@ -3240,24 +3250,30 @@ if WITH_WIFI core_plugins += src/devices/wifi/libnm-device-plugin-wifi.la src_devices_wifi_libnm_device_plugin_wifi_la_SOURCES = \ - src/devices/wifi/nm-wifi-factory.c \ + src/devices/wifi/nm-device-olpc-mesh.c \ + src/devices/wifi/nm-device-olpc-mesh.h \ + src/devices/wifi/nm-device-p2p-wifi.c \ + src/devices/wifi/nm-device-p2p-wifi.h \ src/devices/wifi/nm-device-wifi.c \ src/devices/wifi/nm-device-wifi.h \ src/devices/wifi/nm-wifi-ap.c \ src/devices/wifi/nm-wifi-ap.h \ - src/devices/wifi/nm-wifi-utils.c \ - src/devices/wifi/nm-wifi-utils.h \ src/devices/wifi/nm-wifi-common.c \ src/devices/wifi/nm-wifi-common.h \ - src/devices/wifi/nm-device-olpc-mesh.c \ - src/devices/wifi/nm-device-olpc-mesh.h + src/devices/wifi/nm-wifi-factory.c \ + src/devices/wifi/nm-wifi-p2p-peer.c \ + src/devices/wifi/nm-wifi-p2p-peer.h \ + src/devices/wifi/nm-wifi-utils.c \ + src/devices/wifi/nm-wifi-utils.h \ + $(NULL) if WITH_IWD src_devices_wifi_libnm_device_plugin_wifi_la_SOURCES += \ src/devices/wifi/nm-device-iwd.c \ src/devices/wifi/nm-device-iwd.h \ src/devices/wifi/nm-iwd-manager.c \ - src/devices/wifi/nm-iwd-manager.h + src/devices/wifi/nm-iwd-manager.h \ + $(NULL) endif src_devices_wifi_libnm_device_plugin_wifi_la_CPPFLAGS = $(src_cppflags_device_plugin) diff --git a/clients/common/nm-client-utils.c b/clients/common/nm-client-utils.c index 8ba2453ee8..1241131a11 100644 --- a/clients/common/nm-client-utils.c +++ b/clients/common/nm-client-utils.c @@ -352,6 +352,7 @@ NM_UTILS_LOOKUP_STR_DEFINE (nmc_device_reason_to_string, NMDeviceStateReason, NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_IP_ADDRESS_DUPLICATE, N_("A duplicate IP address was detected")), NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_IP_METHOD_UNSUPPORTED, N_("The selected IP method is not supported")), NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_SRIOV_CONFIGURATION_FAILED, N_("Failed to configure SR-IOV parameters")), + NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_PEER_NOT_FOUND, N_("The Wi-Fi P2P peer could not be found")), ) NM_UTILS_LOOKUP_STR_DEFINE (nm_active_connection_state_reason_to_string, NMActiveConnectionStateReason, diff --git a/docs/api/Makefile.am b/docs/api/Makefile.am index 2baf40562f..7ec77963f2 100644 --- a/docs/api/Makefile.am +++ b/docs/api/Makefile.am @@ -42,42 +42,43 @@ MKHTML_OPTIONS=--path="$(abs_srcdir)" content_files = \ $(GENERATED_FILES) \ dbus-org.freedesktop.NetworkManager.AccessPoint.xml \ - dbus-org.freedesktop.NetworkManager.Connection.Active.xml \ - dbus-org.freedesktop.NetworkManager.Device.Team.xml \ - dbus-org.freedesktop.NetworkManager.DHCP6Config.xml \ - dbus-org.freedesktop.NetworkManager.Device.Wireless.xml \ - dbus-org.freedesktop.NetworkManager.xml \ - dbus-org.freedesktop.NetworkManager.VPN.Connection.xml \ - dbus-org.freedesktop.NetworkManager.SecretAgent.xml \ - dbus-org.freedesktop.NetworkManager.Device.xml \ - dbus-org.freedesktop.NetworkManager.VPN.Plugin.xml \ - dbus-org.freedesktop.NetworkManager.Device.Bluetooth.xml \ - dbus-org.freedesktop.NetworkManager.Device.Dummy.xml \ - dbus-org.freedesktop.NetworkManager.Device.Vxlan.xml \ - dbus-org.freedesktop.NetworkManager.Settings.Connection.xml \ - dbus-org.freedesktop.NetworkManager.Device.Bond.xml \ - dbus-org.freedesktop.NetworkManager.Device.Macvlan.xml \ - dbus-org.freedesktop.NetworkManager.Device.Macsec.xml \ - dbus-org.freedesktop.NetworkManager.PPP.xml \ - dbus-org.freedesktop.NetworkManager.Device.Vlan.xml \ - dbus-org.freedesktop.NetworkManager.Device.Adsl.xml \ dbus-org.freedesktop.NetworkManager.AgentManager.xml \ - dbus-org.freedesktop.NetworkManager.Device.IPTunnel.xml \ - dbus-org.freedesktop.NetworkManager.Device.Tun.xml \ - dbus-org.freedesktop.NetworkManager.Device.Bridge.xml \ - dbus-org.freedesktop.NetworkManager.Device.OlpcMesh.xml \ + dbus-org.freedesktop.NetworkManager.Connection.Active.xml \ dbus-org.freedesktop.NetworkManager.DHCP4Config.xml \ + dbus-org.freedesktop.NetworkManager.DHCP6Config.xml \ + dbus-org.freedesktop.NetworkManager.Device.Adsl.xml \ + dbus-org.freedesktop.NetworkManager.Device.Bluetooth.xml \ + dbus-org.freedesktop.NetworkManager.Device.Bond.xml \ + dbus-org.freedesktop.NetworkManager.Device.Bridge.xml \ + dbus-org.freedesktop.NetworkManager.Device.Dummy.xml \ dbus-org.freedesktop.NetworkManager.Device.Generic.xml \ + dbus-org.freedesktop.NetworkManager.Device.IPTunnel.xml \ dbus-org.freedesktop.NetworkManager.Device.Infiniband.xml \ + dbus-org.freedesktop.NetworkManager.Device.Macsec.xml \ + dbus-org.freedesktop.NetworkManager.Device.Macvlan.xml \ dbus-org.freedesktop.NetworkManager.Device.Modem.xml \ - dbus-org.freedesktop.NetworkManager.IP6Config.xml \ - dbus-org.freedesktop.NetworkManager.Device.Veth.xml \ - dbus-org.freedesktop.NetworkManager.Settings.xml \ - dbus-org.freedesktop.NetworkManager.Device.Wired.xml \ - dbus-org.freedesktop.NetworkManager.Device.WireGuard.xml \ - dbus-org.freedesktop.NetworkManager.IP4Config.xml \ + dbus-org.freedesktop.NetworkManager.Device.OlpcMesh.xml \ dbus-org.freedesktop.NetworkManager.Device.Statistics.xml \ + dbus-org.freedesktop.NetworkManager.Device.Team.xml \ + dbus-org.freedesktop.NetworkManager.Device.Tun.xml \ + dbus-org.freedesktop.NetworkManager.Device.Veth.xml \ + dbus-org.freedesktop.NetworkManager.Device.Vlan.xml \ + dbus-org.freedesktop.NetworkManager.Device.Vxlan.xml \ + dbus-org.freedesktop.NetworkManager.Device.WireGuard.xml \ + dbus-org.freedesktop.NetworkManager.Device.P2PWireless.xml \ + dbus-org.freedesktop.NetworkManager.Device.Wired.xml \ + dbus-org.freedesktop.NetworkManager.Device.Wireless.xml \ + dbus-org.freedesktop.NetworkManager.Device.xml \ dbus-org.freedesktop.NetworkManager.DnsManager.xml \ + dbus-org.freedesktop.NetworkManager.IP4Config.xml \ + dbus-org.freedesktop.NetworkManager.IP6Config.xml \ + dbus-org.freedesktop.NetworkManager.PPP.xml \ + dbus-org.freedesktop.NetworkManager.SecretAgent.xml \ + dbus-org.freedesktop.NetworkManager.Settings.Connection.xml \ + dbus-org.freedesktop.NetworkManager.Settings.xml \ + dbus-org.freedesktop.NetworkManager.VPN.Connection.xml \ + dbus-org.freedesktop.NetworkManager.VPN.Plugin.xml \ + dbus-org.freedesktop.NetworkManager.xml \ $(top_builddir)/libnm-core/nm-dbus-types.xml \ $(top_builddir)/libnm-core/nm-vpn-dbus-types.xml \ $(top_builddir)/man/nmcli.xml \ diff --git a/docs/api/network-manager-docs.xml b/docs/api/network-manager-docs.xml index 06ac37415d..8b7c8c6bf9 100644 --- a/docs/api/network-manager-docs.xml +++ b/docs/api/network-manager-docs.xml @@ -206,6 +206,7 @@ + @@ -247,6 +248,12 @@ + + The <literal>/org/freedesktop/NetworkManager/P2PPeer/*</literal> objects + + + + The <literal>/org/freedesktop/NetworkManager/Checkpoint/*</literal> objects diff --git a/introspection/meson.build b/introspection/meson.build index ef2ad9c1af..e5bbe2a284 100644 --- a/introspection/meson.build +++ b/introspection/meson.build @@ -23,6 +23,7 @@ ifaces = [ 'org.freedesktop.NetworkManager.Device.OvsInterface', 'org.freedesktop.NetworkManager.Device.OvsPort', 'org.freedesktop.NetworkManager.Device.OvsBridge', + 'org.freedesktop.NetworkManager.Device.P2PWireless', 'org.freedesktop.NetworkManager.Device.Ppp', 'org.freedesktop.NetworkManager.Device.Statistics', 'org.freedesktop.NetworkManager.Device.Team', @@ -42,6 +43,7 @@ ifaces = [ 'org.freedesktop.NetworkManager.IP4Config', 'org.freedesktop.NetworkManager.IP6Config', 'org.freedesktop.NetworkManager', + 'org.freedesktop.NetworkManager.P2PPeer', 'org.freedesktop.NetworkManager.PPP', 'org.freedesktop.NetworkManager.SecretAgent', 'org.freedesktop.NetworkManager.Settings.Connection', diff --git a/introspection/org.freedesktop.NetworkManager.Device.P2PWireless.xml b/introspection/org.freedesktop.NetworkManager.Device.P2PWireless.xml new file mode 100644 index 0000000000..fa85b83f9d --- /dev/null +++ b/introspection/org.freedesktop.NetworkManager.Device.P2PWireless.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/introspection/org.freedesktop.NetworkManager.P2PPeer.xml b/introspection/org.freedesktop.NetworkManager.P2PPeer.xml new file mode 100644 index 0000000000..1a1cf71308 --- /dev/null +++ b/introspection/org.freedesktop.NetworkManager.P2PPeer.xml @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libnm-core/nm-dbus-interface.h b/libnm-core/nm-dbus-interface.h index aac4d7eadd..924140edef 100644 --- a/libnm-core/nm-dbus-interface.h +++ b/libnm-core/nm-dbus-interface.h @@ -44,6 +44,7 @@ #define NM_DBUS_INTERFACE_DEVICE_WIRED NM_DBUS_INTERFACE_DEVICE ".Wired" #define NM_DBUS_INTERFACE_DEVICE_ADSL NM_DBUS_INTERFACE_DEVICE ".Adsl" #define NM_DBUS_INTERFACE_DEVICE_WIRELESS NM_DBUS_INTERFACE_DEVICE ".Wireless" +#define NM_DBUS_INTERFACE_DEVICE_P2P_WIRELESS NM_DBUS_INTERFACE_DEVICE ".P2PWireless" #define NM_DBUS_INTERFACE_DEVICE_BLUETOOTH NM_DBUS_INTERFACE_DEVICE ".Bluetooth" #define NM_DBUS_INTERFACE_DEVICE_OLPC_MESH NM_DBUS_INTERFACE_DEVICE ".OlpcMesh" #define NM_DBUS_INTERFACE_DEVICE_OVS_INTERFACE NM_DBUS_INTERFACE_DEVICE ".OvsInterface" @@ -51,6 +52,8 @@ #define NM_DBUS_INTERFACE_DEVICE_OVS_BRIDGE NM_DBUS_INTERFACE_DEVICE ".OvsBridge" #define NM_DBUS_PATH_ACCESS_POINT NM_DBUS_PATH "/AccessPoint" #define NM_DBUS_INTERFACE_ACCESS_POINT NM_DBUS_INTERFACE ".AccessPoint" +#define NM_DBUS_PATH_P2P_PEER NM_DBUS_PATH "/P2PPeer" +#define NM_DBUS_INTERFACE_P2P_PEER NM_DBUS_INTERFACE ".P2PPeer" #define NM_DBUS_INTERFACE_DEVICE_MODEM NM_DBUS_INTERFACE_DEVICE ".Modem" #define NM_DBUS_INTERFACE_DEVICE_WIMAX NM_DBUS_INTERFACE_DEVICE ".WiMax" #define NM_DBUS_INTERFACE_WIMAX_NSP NM_DBUS_INTERFACE ".WiMax.Nsp" @@ -563,6 +566,7 @@ typedef enum { * @NM_DEVICE_STATE_REASON_IP_ADDRESS_DUPLICATE: a duplicate IP address was detected * @NM_DEVICE_STATE_REASON_IP_METHOD_UNSUPPORTED: The selected IP method is not supported * @NM_DEVICE_STATE_REASON_SRIOV_CONFIGURATION_FAILED: configuration of SR-IOV parameters failed + * @NM_DEVICE_STATE_REASON_PEER_NOT_FOUND: The Wi-Fi P2P peer could not be found * * Device state change reason codes */ @@ -634,6 +638,7 @@ typedef enum { NM_DEVICE_STATE_REASON_IP_ADDRESS_DUPLICATE = 64, NM_DEVICE_STATE_REASON_IP_METHOD_UNSUPPORTED = 65, NM_DEVICE_STATE_REASON_SRIOV_CONFIGURATION_FAILED = 66, + NM_DEVICE_STATE_REASON_PEER_NOT_FOUND = 67, } NMDeviceStateReason; /** diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 17cc454603..c2396d77c8 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -742,6 +742,7 @@ NM_UTILS_LOOKUP_STR_DEFINE (nm_device_state_reason_to_str, NMDeviceStateReason, NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_IP_ADDRESS_DUPLICATE, "ip-address-duplicate"), NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_IP_METHOD_UNSUPPORTED, "ip-method-unsupported"), NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_SRIOV_CONFIGURATION_FAILED, "sriov-configuration-failed"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_PEER_NOT_FOUND, "peer-not-found"), ); #define reason_to_string_a(reason) NM_UTILS_LOOKUP_STR_A (nm_device_state_reason_to_str, reason) diff --git a/src/devices/wifi/meson.build b/src/devices/wifi/meson.build index dd2be5406b..d2b807fc95 100644 --- a/src/devices/wifi/meson.build +++ b/src/devices/wifi/meson.build @@ -1,13 +1,15 @@ common_sources = files( 'nm-wifi-ap.c', + 'nm-wifi-p2p-peer.c', 'nm-wifi-utils.c', ) sources = common_sources + files( - 'nm-wifi-factory.c', - 'nm-wifi-common.c', - 'nm-device-wifi.c', 'nm-device-olpc-mesh.c', + 'nm-device-p2p-wifi.c', + 'nm-device-wifi.c', + 'nm-wifi-common.c', + 'nm-wifi-factory.c', ) if enable_iwd diff --git a/src/devices/wifi/nm-device-p2p-wifi.c b/src/devices/wifi/nm-device-p2p-wifi.c new file mode 100644 index 0000000000..a57b2be089 --- /dev/null +++ b/src/devices/wifi/nm-device-p2p-wifi.c @@ -0,0 +1,1287 @@ +/* NetworkManager -- P2P Wi-Fi Device + * + * 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 2018 Red Hat, Inc. + */ + +#include "nm-default.h" + +#include "nm-device-p2p-wifi.h" + +#include + +#include "supplicant/nm-supplicant-manager.h" +#include "supplicant/nm-supplicant-interface.h" + +#include "nm-manager.h" +#include "nm-utils.h" +#include "nm-wifi-p2p-peer.h" +#include "NetworkManagerUtils.h" +#include "devices/nm-device-private.h" +#include "settings/nm-settings.h" +#include "nm-setting-p2p-wireless.h" +#include "nm-act-request.h" +#include "nm-ip4-config.h" +#include "platform/nm-platform.h" +#include "nm-manager.h" +#include "nm-core-internal.h" +#include "platform/nmp-object.h" + +#include "devices/nm-device-logging.h" +_LOG_DECLARE_SELF(NMDeviceP2PWifi); + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE (NMDeviceP2PWifi, + PROP_GROUP_OWNER, + //PROP_SSID, + //PROP_BSSID, + PROP_PEERS, + PROP_WFDIES, /* TODO: Make this a property of the setting and Find feature + * making the device stateless. + */ + + PROP_MGMT_IFACE, +); + +enum { + SCANNING_PROHIBITED, + + LAST_SIGNAL +}; + +//static guint signals[LAST_SIGNAL] = { 0 }; + +typedef struct { + NMSupplicantManager *sup_mgr; + + /* NOTE: In theory management and group ifaces could be identical. However, + * in practice, this cannot happen currently as NMDeviceP2PWifi is only + * created for existing non-P2P interfaces. + * (i.e. a single standalone P2P interface is not supported at this point) + */ + NMSupplicantInterface *mgmt_iface; + NMSupplicantInterface *group_iface; + + CList peers_lst_head; + GBytes *wfd_ies; + + guint sup_timeout_id; + guint peer_dump_id; + guint peer_missing_id; + + gboolean group_owner; +} NMDeviceP2PWifiPrivate; + +struct _NMDeviceP2PWifi { + NMDevice parent; + NMDeviceP2PWifiPrivate _priv; +}; + +struct _NMDeviceP2PWifiClass { + NMDeviceClass parent; +}; + +G_DEFINE_TYPE (NMDeviceP2PWifi, nm_device_p2p_wifi, NM_TYPE_DEVICE) + +#define NM_DEVICE_P2P_WIFI_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMDeviceP2PWifi, NM_IS_DEVICE_P2P_WIFI, NMDevice) + +/*****************************************************************************/ + +static const NMDBusInterfaceInfoExtended interface_info_device_p2p_wifi; +static const GDBusSignalInfo nm_signal_info_p2p_wireless_peer_added; +static const GDBusSignalInfo nm_signal_info_p2p_wireless_peer_removed; + +static void supplicant_group_interface_release (NMDeviceP2PWifi *self); +static void supplicant_interfaces_release (NMDeviceP2PWifi *self); + +/*****************************************************************************/ + +static void +_peer_dump (NMDeviceP2PWifi *self, + NMLogLevel log_level, + const NMWifiP2PPeer *peer, + const char *prefix, + gint32 now_s) +{ + char buf[1024]; + + _NMLOG (log_level, LOGD_WIFI_SCAN, "wifi-peer: %-7s %s", + prefix, + nm_wifi_p2p_peer_to_string (peer, buf, sizeof (buf), now_s)); +} + +static gboolean +peer_list_dump (gpointer user_data) +{ + NMDeviceP2PWifi *self = NM_DEVICE_P2P_WIFI (user_data); + NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self); + + priv->peer_dump_id = 0; + + if (_LOGD_ENABLED (LOGD_WIFI_SCAN)) { + NMWifiP2PPeer *peer; + gint32 now_s = nm_utils_get_monotonic_timestamp_s (); + + _LOGD (LOGD_WIFI_SCAN, "P2P Peers: [now:%u]", now_s); + c_list_for_each_entry (peer, &priv->peers_lst_head, peers_lst) + _peer_dump (self, LOGL_DEBUG, peer, "dump", now_s); + } + return G_SOURCE_REMOVE; +} + +static void +schedule_peer_list_dump (NMDeviceP2PWifi *self) +{ + NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self); + + if ( !priv->peer_dump_id + && _LOGD_ENABLED (LOGD_WIFI_SCAN)) + priv->peer_dump_id = g_timeout_add_seconds (1, peer_list_dump, self); +} + +/*****************************************************************************/ + +static gboolean +check_connection_peer_joined (NMDeviceP2PWifi *device) +{ + NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (device); + NMConnection *conn = nm_device_get_applied_connection (NM_DEVICE (device)); + NMWifiP2PPeer *peer; + const char* group; + const char * const * groups; + + if (!conn || !priv->group_iface) + return FALSE; + + /* Comparing the object path found on the group_iface with the peers + * found on the mgmt_iface is legal. */ + group = nm_supplicant_interface_get_p2p_group_path (priv->group_iface); + if (!group) + return FALSE; + + /* NOTE: We currently only support connections to a specific peer */ + peer = nm_wifi_p2p_peers_find_first_compatible (&priv->peers_lst_head, conn); + if (!peer) + return FALSE; + + groups = nm_wifi_p2p_peer_get_groups (peer); + if ( !groups + || !g_strv_contains (groups, group)) + return FALSE; + + return TRUE; +} + +static gboolean +disconnect_on_connection_peer_missing_cb (gpointer user_data) +{ + NMDevice *device = NM_DEVICE (user_data); + NMDeviceP2PWifi *self = NM_DEVICE_P2P_WIFI (device); + NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self); + + _LOGW (LOGD_WIFI, "Peer requested in connection is missing for too long, failing connection."); + + priv->peer_missing_id = 0; + + nm_device_state_changed (device, + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_PEER_NOT_FOUND); + return FALSE; +} + +static void +update_disconnect_on_connection_peer_missing (NMDeviceP2PWifi *self) +{ + NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self); + NMDeviceState state; + + state = nm_device_get_state (NM_DEVICE (self)); + if ( state < NM_DEVICE_STATE_IP_CONFIG + || state > NM_DEVICE_STATE_ACTIVATED) { + nm_clear_g_source (&priv->peer_missing_id); + return; + } + + if (check_connection_peer_joined (self)) { + if (nm_clear_g_source (&priv->peer_missing_id)) + _LOGD (LOGD_WIFI, "Peer requested in connection is joined, removing timeout"); + return; + } + + if (priv->peer_missing_id == 0) { + _LOGD (LOGD_WIFI, "Peer requested in connection is missing, adding timeout"); + priv->peer_missing_id = g_timeout_add_seconds (5, disconnect_on_connection_peer_missing_cb, self); + } +} + +static gboolean +is_available (NMDevice *device, NMDeviceCheckDevAvailableFlags flags) +{ + NMDeviceP2PWifi *self = NM_DEVICE_P2P_WIFI (device); + NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self); + NMSupplicantInterfaceState supplicant_state; + + if (!priv->mgmt_iface) + return FALSE; + + supplicant_state = nm_supplicant_interface_get_state (priv->mgmt_iface); + if ( supplicant_state < NM_SUPPLICANT_INTERFACE_STATE_READY + || supplicant_state > NM_SUPPLICANT_INTERFACE_STATE_COMPLETED) + return FALSE; + + return TRUE; +} + +static gboolean +check_connection_compatible (NMDevice *device, NMConnection *connection, GError **error) +{ + if (!NM_DEVICE_CLASS (nm_device_p2p_wifi_parent_class)->check_connection_compatible (device, connection, error)) + return FALSE; + + /* TODO: Allow limitting the interface using the HW-address? */ + + /* We don't need to check anything else here. The P2P device will only + * exists if we are able to establish a P2P connection, and there should + * be no further restrictions necessary. + */ + + return TRUE; +} + +static gboolean +complete_connection (NMDevice *device, + NMConnection *connection, + const char *specific_object, + NMConnection *const*existing_connections, + GError **error) +{ + NMDeviceP2PWifi *self = NM_DEVICE_P2P_WIFI (device); + gs_free char *setting_name = NULL; + NMSettingP2PWireless *s_p2p_wireless; + NMWifiP2PPeer *peer; + const char *setting_peer; + + s_p2p_wireless = NM_SETTING_P2P_WIRELESS (nm_connection_get_setting (connection, NM_TYPE_SETTING_P2P_WIRELESS)); + + if (!specific_object) { + /* If not given a specific object, we need at minimum a peer address */ + if (!s_p2p_wireless) { + g_set_error_literal (error, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_INVALID_CONNECTION, + "A 'p2p-wireless' setting is required if no Peer path was given."); + return FALSE; + } + + setting_peer = nm_setting_p2p_wireless_get_peer (s_p2p_wireless); + if (!setting_peer) { + g_set_error_literal (error, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_INVALID_CONNECTION, + "A 'p2p-wireless' setting with a valid Peer is required if no Peer path was given."); + return FALSE; + } + + } else { + peer = nm_wifi_p2p_peer_lookup_for_device (NM_DEVICE (self), specific_object); + if (!peer) { + g_set_error (error, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_SPECIFIC_OBJECT_NOT_FOUND, + "The P2P peer %s is unknown.", + specific_object); + return FALSE; + } + + setting_peer = nm_wifi_p2p_peer_get_address (peer); + g_assert (setting_peer); + } + + /* Add a P2P wifi setting if one doesn't exist yet */ + if (!s_p2p_wireless) { + s_p2p_wireless = NM_SETTING_P2P_WIRELESS (nm_setting_p2p_wireless_new ()); + nm_connection_add_setting (connection, NM_SETTING (s_p2p_wireless)); + } + + g_object_set (G_OBJECT (s_p2p_wireless), NM_SETTING_P2P_WIRELESS_PEER, setting_peer, NULL); + + setting_name = g_strdup_printf ("P2P Peer %s", setting_peer); + nm_utils_complete_generic (nm_device_get_platform (device), + connection, + NM_SETTING_P2P_WIRELESS_SETTING_NAME, + existing_connections, + setting_name, + setting_name, + NULL, + TRUE); + + return TRUE; +} + +/* + * supplicant_find_timeout_cb + * + * Called when the supplicant has been unable to find the peer we want to connect to. + */ +static gboolean +supplicant_find_timeout_cb (gpointer user_data) +{ + NMDevice *device = NM_DEVICE (user_data); + NMDeviceP2PWifi *self = NM_DEVICE_P2P_WIFI (user_data); + NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self); + + priv->sup_timeout_id = 0; + + nm_supplicant_interface_p2p_cancel_connect (priv->mgmt_iface); + + if (nm_device_is_activating (device)) { + _LOGW (LOGD_DEVICE | LOGD_WIFI, + "Activation: (p2p-wifi) could not find peer, failing activation"); + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_PEER_NOT_FOUND); + } + + return G_SOURCE_REMOVE; +} + +static NMActStageReturn +act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) +{ + NMDeviceP2PWifi *self = NM_DEVICE_P2P_WIFI (device); + NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self); + NMActStageReturn ret; + NMActRequest *req; + NMConnection *connection; + NMSettingP2PWireless *s_p2p_wireless; + NMWifiP2PPeer *peer; + + nm_clear_g_source (&priv->sup_timeout_id); + + ret = NM_DEVICE_CLASS (nm_device_p2p_wifi_parent_class)->act_stage1_prepare (device, out_failure_reason); + if (ret != NM_ACT_STAGE_RETURN_SUCCESS) + return ret; + + if (!priv->mgmt_iface) { + NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); + return NM_ACT_STAGE_RETURN_FAILURE; + } + + req = nm_device_get_act_request (NM_DEVICE (self)); + g_return_val_if_fail (req, NM_ACT_STAGE_RETURN_FAILURE); + + connection = nm_act_request_get_applied_connection (req); + g_return_val_if_fail (connection, NM_ACT_STAGE_RETURN_FAILURE); + + s_p2p_wireless = NM_SETTING_P2P_WIRELESS (nm_connection_get_setting (connection, NM_TYPE_SETTING_P2P_WIRELESS)); + g_return_val_if_fail (s_p2p_wireless, NM_ACT_STAGE_RETURN_FAILURE); + + peer = nm_wifi_p2p_peers_find_first_compatible (&priv->peers_lst_head, connection); + if (!peer) { + /* Set up a timeout on the find attempt and run a find for the same period of time */ + priv->sup_timeout_id = g_timeout_add_seconds (10, + supplicant_find_timeout_cb, + self); + + nm_supplicant_interface_p2p_start_find (priv->mgmt_iface, 10); + + return NM_ACT_STAGE_RETURN_POSTPONE; + } + + /* TODO: Set WFD IEs on supplicant manager here! */ + + return NM_ACT_STAGE_RETURN_SUCCESS; +} + +static void +cleanup_p2p_connect_attempt (NMDeviceP2PWifi *self, gboolean disconnect) +{ + NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self); + + nm_clear_g_source (&priv->sup_timeout_id); + nm_clear_g_source (&priv->peer_missing_id); + + if (priv->mgmt_iface) + nm_supplicant_interface_p2p_cancel_connect (priv->mgmt_iface); + + if (disconnect && priv->group_iface) + nm_supplicant_interface_p2p_disconnect (priv->group_iface); +} + +/* + * supplicant_connection_timeout_cb + * + * Called when the supplicant has been unable to connect to a peer + * within a specified period of time. + */ +static gboolean +supplicant_connection_timeout_cb (gpointer user_data) +{ + NMDevice *device = NM_DEVICE (user_data); + NMDeviceP2PWifi *self = NM_DEVICE_P2P_WIFI (user_data); + NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self); + + priv->sup_timeout_id = 0; + + nm_supplicant_interface_p2p_cancel_connect (priv->mgmt_iface); + + if (nm_device_is_activating (device)) { + _LOGW (LOGD_DEVICE | LOGD_WIFI, + "Activation: (p2p-wifi) connecting took too long, failing activation"); + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT); + } + + return G_SOURCE_REMOVE; +} + +static NMActStageReturn +act_stage2_config (NMDevice *device, NMDeviceStateReason *out_failure_reason) +{ + NMDeviceP2PWifi *self = NM_DEVICE_P2P_WIFI (device); + NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self); + NMConnection *connection; + NMWifiP2PPeer *peer; + + nm_clear_g_source (&priv->sup_timeout_id); + + connection = nm_device_get_applied_connection (device); + g_return_val_if_fail (connection, NM_ACT_STAGE_RETURN_FAILURE); + + nm_assert (NM_IS_SETTING_P2P_WIRELESS (nm_connection_get_setting (connection, NM_TYPE_SETTING_P2P_WIRELESS))); + + /* The prepare stage ensures that the peer has been found */ + peer = nm_wifi_p2p_peers_find_first_compatible (&priv->peers_lst_head, connection); + if (!peer) { + NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_PEER_NOT_FOUND); + return NM_ACT_STAGE_RETURN_FAILURE; + } + + /* TODO: Grab secrets if we don't have them yet! */ + + /* TODO: Fix "pbc" being hardcoded here! */ + nm_supplicant_interface_p2p_connect (priv->mgmt_iface, + nm_wifi_p2p_peer_get_supplicant_path (peer), + "pbc", NULL); + + /* Set up a timeout on the connect attempt */ + priv->sup_timeout_id = g_timeout_add_seconds (45, + supplicant_connection_timeout_cb, + self); + + /* We'll get stage3 started when the P2P group has been started */ + return NM_ACT_STAGE_RETURN_POSTPONE; +} + +/*****************************************************************************/ + +static void +emit_signal_p2p_peer_add_remove (NMDeviceP2PWifi *device, + NMWifiP2PPeer *peer, + gboolean is_added /* or else is_removed */) +{ + nm_dbus_object_emit_signal (NM_DBUS_OBJECT (device), + &interface_info_device_p2p_wifi, + is_added + ? &nm_signal_info_p2p_wireless_peer_added + : &nm_signal_info_p2p_wireless_peer_removed, + "(o)", + nm_dbus_object_get_path (NM_DBUS_OBJECT (peer))); +} + +static void +peer_add_remove (NMDeviceP2PWifi *self, + gboolean is_adding, /* or else removing */ + NMWifiP2PPeer *peer, + gboolean recheck_available_connections) +{ + NMDevice *device = NM_DEVICE (self); + NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self); + + if (is_adding) { + g_object_ref (peer); + peer->wifi_device = device; + c_list_link_tail (&priv->peers_lst_head, &peer->peers_lst); + nm_dbus_object_export (NM_DBUS_OBJECT (peer)); + _peer_dump (self, LOGL_DEBUG, peer, "added", 0); + + emit_signal_p2p_peer_add_remove (self, peer, TRUE); + } else { + peer->wifi_device = NULL; + c_list_unlink (&peer->peers_lst); + _peer_dump (self, LOGL_DEBUG, peer, "removed", 0); + } + + _notify (self, PROP_PEERS); + + if (!is_adding) { + emit_signal_p2p_peer_add_remove (self, peer, FALSE); + nm_dbus_object_clear_and_unexport (&peer); + } + + if (is_adding) { + /* If we are in prepare state, then we are currently runnign a find + * to search for the requested peer. */ + if (nm_device_get_state (device) == NM_DEVICE_STATE_PREPARE) { + NMConnection *connection; + + connection = nm_device_get_applied_connection (device); + g_assert (connection); + + peer = nm_wifi_p2p_peers_find_first_compatible (&priv->peers_lst_head, connection); + if (peer) { + /* A peer for the connection was found, cancel the timeout and go to configure state. */ + nm_clear_g_source (&priv->sup_timeout_id); + nm_device_activate_schedule_stage2_device_config (device); + } + } + + /* TODO: We may want to re-check auto-activation here, otherwise it will never work. */ + } + + update_disconnect_on_connection_peer_missing (self); + +#if 0 + nm_device_emit_recheck_auto_activate (NM_DEVICE (self)); + if (recheck_available_connections) + nm_device_recheck_available_connections (NM_DEVICE (self)); +#endif +} + +static void +remove_all_peers (NMDeviceP2PWifi *self) +{ + NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self); + NMWifiP2PPeer *peer; + + if (c_list_is_empty (&priv->peers_lst_head)) + return; + + while ((peer = c_list_first_entry (&priv->peers_lst_head, NMWifiP2PPeer, peers_lst))) + peer_add_remove (self, FALSE, peer, FALSE); + + nm_device_recheck_available_connections (NM_DEVICE (self)); +} + +/*****************************************************************************/ + + +static NMActStageReturn +act_stage3_ip4_config_start (NMDevice *device, + NMIP4Config **out_config, + NMDeviceStateReason *out_failure_reason) +{ + NMDeviceP2PWifi *self = NM_DEVICE_P2P_WIFI (device); + NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self); + NMConnection *connection; + NMSettingIPConfig *s_ip4; + const char *method = NM_SETTING_IP4_CONFIG_METHOD_AUTO; + + connection = nm_device_get_applied_connection (device); + g_return_val_if_fail (connection, NM_ACT_STAGE_RETURN_FAILURE); + + s_ip4 = nm_connection_get_setting_ip4_config (connection); + if (s_ip4) + method = nm_setting_ip_config_get_method (s_ip4); + + /* Indicate that a critical protocol is about to start */ + if ( !priv->group_owner + && nm_streq (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) + nm_platform_wifi_indicate_addressing_running (nm_device_get_platform (device), nm_device_get_ip_ifindex (device), TRUE); + + return NM_DEVICE_CLASS (nm_device_p2p_wifi_parent_class)->act_stage3_ip4_config_start (device, out_config, out_failure_reason); +} + +static NMActStageReturn +act_stage3_ip6_config_start (NMDevice *device, + NMIP6Config **out_config, + NMDeviceStateReason *out_failure_reason) +{ + NMConnection *connection; + NMSettingIPConfig *s_ip6; + const char *method = NM_SETTING_IP6_CONFIG_METHOD_AUTO; + + connection = nm_device_get_applied_connection (device); + g_return_val_if_fail (connection, NM_ACT_STAGE_RETURN_FAILURE); + + s_ip6 = nm_connection_get_setting_ip6_config (connection); + if (s_ip6) + method = nm_setting_ip_config_get_method (s_ip6); + + /* Indicate that a critical protocol is about to start */ + if (NM_IN_STRSET (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO + NM_SETTING_IP6_CONFIG_METHOD_DHCP)) + nm_platform_wifi_indicate_addressing_running (nm_device_get_platform (device), nm_device_get_ip_ifindex (device), TRUE); + + return NM_DEVICE_CLASS (nm_device_p2p_wifi_parent_class)->act_stage3_ip6_config_start (device, out_config, out_failure_reason); +} + +static void +deactivate (NMDevice *device) +{ + NMDeviceP2PWifi *self = NM_DEVICE_P2P_WIFI (device); + int ifindex = nm_device_get_ip_ifindex (device); + + cleanup_p2p_connect_attempt (self, TRUE); + + /* Clear any critical protocol notification in the Wi-Fi stack */ + if (ifindex > 0) + nm_platform_wifi_indicate_addressing_running (nm_device_get_platform (device), ifindex, FALSE); +} + +static guint32 +get_configured_mtu (NMDevice *device, NMDeviceMtuSource *out_source) +{ + *out_source = NM_DEVICE_MTU_SOURCE_NONE; + return 0; +} + +static const char * +get_auto_ip_config_method (NMDevice *device, int addr_family) +{ + NMDeviceP2PWifi *self = NM_DEVICE_P2P_WIFI (device); + NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self); + + /* Override the AUTO method to mean shared if we are group owner. */ + if ( priv->group_iface + && nm_supplicant_interface_get_p2p_group_owner (priv->group_iface)) { + if (addr_family == AF_INET) + return NM_SETTING_IP4_CONFIG_METHOD_SHARED; + + if (addr_family == AF_INET6) + return NM_SETTING_IP6_CONFIG_METHOD_SHARED; + } + + return NULL; +} + +static gboolean +unmanaged_on_quit (NMDevice *self) +{ + return TRUE; +} + +static void +supplicant_iface_state_cb (NMSupplicantInterface *iface, + int new_state_i, + int old_state_i, + int disconnect_reason, + gpointer user_data) +{ + NMDeviceP2PWifi *self = NM_DEVICE_P2P_WIFI (user_data); + NMDevice *device = NM_DEVICE (self); + NMSupplicantInterfaceState new_state = new_state_i; + NMSupplicantInterfaceState old_state = old_state_i; + + if (new_state == old_state) + return; + + _LOGI (LOGD_DEVICE | LOGD_WIFI, + "supplicant management interface state: %s -> %s", + nm_supplicant_interface_state_to_string (old_state), + nm_supplicant_interface_state_to_string (new_state)); + + switch (new_state) { + case NM_SUPPLICANT_INTERFACE_STATE_READY: + _LOGD (LOGD_WIFI, "supplicant ready"); + nm_device_queue_recheck_available (device, + NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE, + NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); + + if (old_state < NM_SUPPLICANT_INTERFACE_STATE_READY) + nm_device_remove_pending_action (device, NM_PENDING_ACTION_WAITING_FOR_SUPPLICANT, TRUE); + break; + case NM_SUPPLICANT_INTERFACE_STATE_DOWN: + nm_device_queue_recheck_available (device, + NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE, + NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); + + supplicant_interfaces_release (self); + break; + default: + break; + } +} + +static void +supplicant_iface_peer_updated_cb (NMSupplicantInterface *iface, + const char *object_path, + GVariant *properties, + NMDeviceP2PWifi *self) +{ + NMDeviceP2PWifiPrivate *priv; + NMWifiP2PPeer *found_peer; + + g_return_if_fail (self != NULL); + g_return_if_fail (object_path != NULL); + + priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self); + + found_peer = nm_wifi_p2p_peers_find_by_supplicant_path (&priv->peers_lst_head, object_path); + if (found_peer) { + if (!nm_wifi_p2p_peer_update_from_properties (found_peer, object_path, properties)) + return; + + update_disconnect_on_connection_peer_missing (self); + _peer_dump (self, LOGL_DEBUG, found_peer, "updated", 0); + } else { + gs_unref_object NMWifiP2PPeer *peer = NULL; + + peer = nm_wifi_p2p_peer_new_from_properties (object_path, properties); + if (!peer) { + _LOGD (LOGD_WIFI, "invalid P2P peer properties received for %s", object_path); + return; + } + + peer_add_remove (self, TRUE, peer, TRUE); + } + + schedule_peer_list_dump (self); +} + +static void +supplicant_iface_peer_removed_cb (NMSupplicantInterface *iface, + const char *object_path, + NMDeviceP2PWifi *self) +{ + NMDeviceP2PWifiPrivate *priv; + NMWifiP2PPeer *peer; + + g_return_if_fail (self != NULL); + g_return_if_fail (object_path != NULL); + + priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self); + peer = nm_wifi_p2p_peers_find_by_supplicant_path (&priv->peers_lst_head, object_path); + if (!peer) + return; + + peer_add_remove (self, FALSE, peer, TRUE); + schedule_peer_list_dump (self); +} + +static void +check_group_iface_ready (NMDeviceP2PWifi *self) +{ + NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self);; + + if (!priv->group_iface) + return; + + if (nm_supplicant_interface_get_state (priv->group_iface) < NM_SUPPLICANT_INTERFACE_STATE_READY) + return; + + if (!nm_supplicant_interface_get_p2p_group_joined (priv->group_iface)) + return; + + nm_clear_g_source (&priv->sup_timeout_id); + update_disconnect_on_connection_peer_missing (self); + + nm_device_activate_schedule_stage3_ip_config_start (NM_DEVICE (self)); +} + +static void +supplicant_group_iface_state_cb (NMSupplicantInterface *iface, + int new_state_i, + int old_state_i, + int disconnect_reason, + gpointer user_data) +{ + NMDeviceP2PWifi *self = NM_DEVICE_P2P_WIFI (user_data); + NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self); + NMDevice *device = NM_DEVICE (self); + NMSupplicantInterfaceState new_state = new_state_i; + NMSupplicantInterfaceState old_state = old_state_i; + + if (new_state == old_state) + return; + + _LOGI (LOGD_DEVICE | LOGD_WIFI, + "P2P Group supplicant interface state: %s -> %s", + nm_supplicant_interface_state_to_string (old_state), + nm_supplicant_interface_state_to_string (new_state)); + + switch (new_state) { + case NM_SUPPLICANT_INTERFACE_STATE_READY: + _LOGD (LOGD_WIFI, "P2P Group supplicant ready"); + + if (!nm_device_set_ip_iface (device, nm_supplicant_interface_get_ifname (priv->group_iface))) { + nm_device_state_changed (device, + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); + break; + } + + if (old_state < NM_SUPPLICANT_INTERFACE_STATE_READY) + nm_device_remove_pending_action (device, NM_PENDING_ACTION_WAITING_FOR_SUPPLICANT, TRUE); + + check_group_iface_ready (self); + break; + case NM_SUPPLICANT_INTERFACE_STATE_DOWN: + supplicant_group_interface_release (self); + + nm_device_state_changed (device, + NM_DEVICE_STATE_DISCONNECTED, + NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT); + break; + default: + break; + } +} + +static void +supplicant_group_iface_group_finished_cb (NMSupplicantInterface *iface, + void *user_data) +{ + NMDeviceP2PWifi *self = NM_DEVICE_P2P_WIFI (user_data); + + supplicant_group_interface_release (self); + + nm_device_state_changed (NM_DEVICE (self), + NM_DEVICE_STATE_DISCONNECTED, + NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT); +} + +static void +supplicant_iface_group_joined_updated_cb (NMSupplicantInterface *iface, + GParamSpec *pspec, + void *user_data) +{ + NMDeviceP2PWifi *self = NM_DEVICE_P2P_WIFI (user_data); + + check_group_iface_ready (self); +} + +static void +supplicant_iface_group_started_cb (NMSupplicantInterface *iface, + NMSupplicantInterface *group_iface, + NMDeviceP2PWifi *self) +{ + NMDeviceP2PWifiPrivate *priv; + + g_return_if_fail (self != NULL); + + if (!nm_device_is_activating (NM_DEVICE (self))) { + _LOGW (LOGD_DEVICE | LOGD_WIFI, "P2P: WPA supplicant notified a group start but we are not trying to connect! Ignoring the event."); + return; + } + + priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self); + + supplicant_group_interface_release (self); + priv->group_iface = g_object_ref (group_iface); + + /* We need to wait for the interface to be ready and the group + * information to be resolved. */ + g_signal_connect (priv->group_iface, + "notify::" NM_SUPPLICANT_INTERFACE_P2P_GROUP_JOINED, + G_CALLBACK (supplicant_iface_group_joined_updated_cb), + self); + + g_signal_connect (priv->group_iface, + NM_SUPPLICANT_INTERFACE_STATE, + G_CALLBACK (supplicant_group_iface_state_cb), + self); + + g_signal_connect (priv->group_iface, NM_SUPPLICANT_INTERFACE_GROUP_FINISHED, + G_CALLBACK (supplicant_group_iface_group_finished_cb), + self); + + if (nm_supplicant_interface_get_state (priv->group_iface) < NM_SUPPLICANT_INTERFACE_STATE_READY) + nm_device_add_pending_action (NM_DEVICE (self), NM_PENDING_ACTION_WAITING_FOR_SUPPLICANT, FALSE); + + check_group_iface_ready (self); +} + +static void +supplicant_group_interface_release (NMDeviceP2PWifi *self) +{ + NMDeviceP2PWifiPrivate *priv; + + g_return_if_fail (self != NULL); + + priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self); + + if (priv->group_iface) { + /* Tell the supplicant to disconnect from the current Group/Peer */ + nm_supplicant_interface_p2p_disconnect (priv->group_iface); + + /* Clear supplicant interface signal handlers */ + g_signal_handlers_disconnect_by_data (priv->group_iface, self); + + g_clear_object (&priv->group_iface); + } +} + +static void +supplicant_interfaces_release (NMDeviceP2PWifi *self) +{ + NMDeviceP2PWifiPrivate *priv; + + g_return_if_fail (self != NULL); + + priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self); + + _LOGD (LOGD_DEVICE | LOGD_WIFI, "P2P: Releasing WPA supplicant interfaces."); + + nm_clear_g_source (&priv->peer_dump_id); + remove_all_peers (self); + + if (priv->mgmt_iface) { + /* Clear supplicant interface signal handlers */ + g_signal_handlers_disconnect_by_data (priv->mgmt_iface, self); + + g_clear_object (&priv->mgmt_iface); + + nm_device_add_pending_action (NM_DEVICE (self), NM_PENDING_ACTION_WAITING_FOR_SUPPLICANT, FALSE); + } + + supplicant_group_interface_release (self); +} + +static void +device_state_changed (NMDevice *device, + NMDeviceState new_state, + NMDeviceState old_state, + NMDeviceStateReason reason) +{ + NMDeviceP2PWifi *self = NM_DEVICE_P2P_WIFI (device); + NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self); + +#if 0 + if (new_state > NM_DEVICE_STATE_ACTIVATED) + wifi_secrets_cancel (self); +#endif + + update_disconnect_on_connection_peer_missing (self); + + if (new_state <= NM_DEVICE_STATE_UNAVAILABLE) { + /* Clean up the supplicant interface because in these states the + * device cannot be used. + * Do not clean up for the UNMANAGED to UNAVAILABLE transition which + * will happen during initialization. + */ + if (priv->mgmt_iface && old_state > new_state) + supplicant_interfaces_release (self); + + /* TODO: More cleanup needed? */ + } else + nm_assert (priv->mgmt_iface != NULL); + + switch (new_state) { + case NM_DEVICE_STATE_UNMANAGED: + break; + case NM_DEVICE_STATE_UNAVAILABLE: + if (!priv->mgmt_iface || nm_supplicant_interface_get_state (priv->mgmt_iface) < NM_SUPPLICANT_INTERFACE_STATE_READY) + nm_device_add_pending_action (device, NM_PENDING_ACTION_WAITING_FOR_SUPPLICANT, FALSE); + + break; + case NM_DEVICE_STATE_NEED_AUTH: + /* Disconnect? */ + 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_platform (device), nm_device_get_ip_ifindex (device), FALSE); + break; + case NM_DEVICE_STATE_ACTIVATED: + //activation_success_handler (device); + break; + case NM_DEVICE_STATE_FAILED: + /* Clear any critical protocol notification in the wifi stack. + * At this point the IP device may have been removed already. */ + if (nm_device_get_ip_ifindex (device) > 0) + nm_platform_wifi_indicate_addressing_running (nm_device_get_platform (device), nm_device_get_ip_ifindex (device), FALSE); + break; + case NM_DEVICE_STATE_DISCONNECTED: + break; + default: + break; + } +} + +/*****************************************************************************/ + +NMSupplicantInterface * +nm_device_p2p_wifi_get_mgmt_iface (NMDeviceP2PWifi *self) +{ + NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self); + + return priv->mgmt_iface; +} + +void +nm_device_p2p_wifi_set_mgmt_iface (NMDeviceP2PWifi *self, + NMSupplicantInterface *iface) +{ + NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self); + + /* Don't do anything if nothing changed. */ + if (priv->mgmt_iface == iface) + return; + + supplicant_interfaces_release (self); + + if (iface == NULL) { + _LOGD (LOGD_DEVICE | LOGD_WIFI, "P2P: WPA supplicant management interface cleared."); + return; + } + + _LOGD (LOGD_DEVICE | LOGD_WIFI, "P2P: WPA supplicant management interface changed to %s.", nm_supplicant_interface_get_object_path (iface)); + + priv->mgmt_iface = g_object_ref (iface); + + /* We are not waiting on the supplicant anymore if the state is ready. */ + if (nm_supplicant_interface_get_state (priv->mgmt_iface) >= NM_SUPPLICANT_INTERFACE_STATE_READY) + nm_device_remove_pending_action (NM_DEVICE (self), NM_PENDING_ACTION_WAITING_FOR_SUPPLICANT, TRUE); + + g_signal_connect_object (priv->mgmt_iface, NM_SUPPLICANT_INTERFACE_STATE, + G_CALLBACK (supplicant_iface_state_cb), + self, + 0); + g_signal_connect_object (priv->mgmt_iface, NM_SUPPLICANT_INTERFACE_PEER_UPDATED, + G_CALLBACK (supplicant_iface_peer_updated_cb), + self, + 0); + g_signal_connect_object (priv->mgmt_iface, NM_SUPPLICANT_INTERFACE_PEER_REMOVED, + G_CALLBACK (supplicant_iface_peer_removed_cb), + self, + 0); + g_signal_connect_object (priv->mgmt_iface, NM_SUPPLICANT_INTERFACE_GROUP_STARTED, + G_CALLBACK (supplicant_iface_group_started_cb), + self, + 0); +} + +void +nm_device_p2p_wifi_remove (NMDeviceP2PWifi* self) +{ + g_signal_emit_by_name (self, NM_DEVICE_REMOVED); +} + +/*****************************************************************************/ + +static const GDBusSignalInfo nm_signal_info_p2p_wireless_peer_added = NM_DEFINE_GDBUS_SIGNAL_INFO_INIT ( + "PeerAdded", + .args = NM_DEFINE_GDBUS_ARG_INFOS ( + NM_DEFINE_GDBUS_ARG_INFO ("peer", "o"), + ), +); + +static const GDBusSignalInfo nm_signal_info_p2p_wireless_peer_removed = NM_DEFINE_GDBUS_SIGNAL_INFO_INIT ( + "PeerRemoved", + .args = NM_DEFINE_GDBUS_ARG_INFOS ( + NM_DEFINE_GDBUS_ARG_INFO ("peer", "o"), + ), +); + +static const NMDBusInterfaceInfoExtended interface_info_device_p2p_wifi = { + .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT ( + NM_DBUS_INTERFACE_DEVICE_P2P_WIRELESS, + .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS ( + &nm_signal_info_p2p_wireless_peer_added, + &nm_signal_info_p2p_wireless_peer_removed, + ), + .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS ( + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE ("HwAddress", "s", NM_DEVICE_HW_ADDRESS), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE ("GroupOwner", "b", NM_DEVICE_P2P_WIFI_GROUP_OWNER), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE ("Peers", "ao", NM_DEVICE_P2P_WIFI_PEERS), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE ("WFDIEs", "ay", NM_DEVICE_P2P_WIFI_WFDIES), + ), + ), + .legacy_property_changed = FALSE, +}; + +/*****************************************************************************/ + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMDeviceP2PWifi *self = NM_DEVICE_P2P_WIFI (object); + NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self); + const char **list; + + switch (prop_id) { + case PROP_MGMT_IFACE: + g_value_set_object (value, priv->mgmt_iface); + break; + case PROP_GROUP_OWNER: + g_value_set_boolean (value, priv->group_owner); + break; + case PROP_PEERS: + list = nm_wifi_p2p_peers_get_paths (&priv->peers_lst_head); + g_value_take_boxed (value, nm_utils_strv_make_deep_copied (list)); + break; + case PROP_WFDIES: + g_value_take_variant (value, nm_utils_gbytes_to_variant_ay (priv->wfd_ies)); + 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) +{ + NMDeviceP2PWifi *self = NM_DEVICE_P2P_WIFI (object); + + switch (prop_id) { + case PROP_MGMT_IFACE: + /* construct-only */ + nm_device_p2p_wifi_set_mgmt_iface (self, g_value_get_object (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_device_p2p_wifi_init (NMDeviceP2PWifi * self) +{ + NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self); + c_list_init (&priv->peers_lst_head); +} + +static void +constructed (GObject *object) +{ + NMDeviceP2PWifi *self = NM_DEVICE_P2P_WIFI (object); + NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self); + + G_OBJECT_CLASS (nm_device_p2p_wifi_parent_class)->constructed (object); + + /* Connect to the supplicant manager */ + priv->sup_mgr = g_object_ref (nm_supplicant_manager_get ()); + + nm_device_add_pending_action (NM_DEVICE (self), NM_PENDING_ACTION_WAITING_FOR_SUPPLICANT, FALSE); +} + +NMDevice* +nm_device_p2p_wifi_new (NMSupplicantInterface *mgmt_iface, const char *iface) +{ + return g_object_new (NM_TYPE_DEVICE_P2P_WIFI, + NM_DEVICE_IFACE, iface, + NM_DEVICE_TYPE_DESC, "802.11 P2P WiFi", + NM_DEVICE_DEVICE_TYPE, NM_TYPE_DEVICE_P2P_WIFI, + NM_DEVICE_LINK_TYPE, NM_LINK_TYPE_WIFI, + NM_DEVICE_RFKILL_TYPE, RFKILL_TYPE_WLAN, + NM_DEVICE_P2P_WIFI_MGMT_IFACE, mgmt_iface, + NULL); +} + +static void +dispose (GObject *object) +{ + NMDeviceP2PWifi *self = NM_DEVICE_P2P_WIFI (object); + NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (object); + + g_clear_object (&priv->sup_mgr); + + supplicant_interfaces_release (self); + + G_OBJECT_CLASS (nm_device_p2p_wifi_parent_class)->dispose (object); +} + +static void +finalize (GObject *object) +{ + NMDeviceP2PWifi *peer = NM_DEVICE_P2P_WIFI (object); + NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (peer); + + nm_assert (c_list_is_empty (&priv->peers_lst_head)); + + g_bytes_unref (priv->wfd_ies); + + G_OBJECT_CLASS (nm_device_p2p_wifi_parent_class)->finalize (object); +} + +static void +nm_device_p2p_wifi_class_init (NMDeviceP2PWifiClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); + + object_class->constructed = constructed; + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->dispose = dispose; + object_class->finalize = finalize; + + dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_p2p_wifi); + + device_class->connection_type_supported = NM_SETTING_P2P_WIRELESS_SETTING_NAME; + device_class->connection_type_check_compatible = NM_SETTING_P2P_WIRELESS_SETTING_NAME; + device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES (NM_LINK_TYPE_P2P_WIFI); + + /* Do we need compatibility checking or is the default good enough? */ + device_class->is_available = is_available; + device_class->check_connection_compatible = check_connection_compatible; + device_class->complete_connection = complete_connection; + + device_class->act_stage1_prepare = act_stage1_prepare; + device_class->act_stage2_config = act_stage2_config; + device_class->get_configured_mtu = get_configured_mtu; + device_class->get_auto_ip_config_method = get_auto_ip_config_method; + 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->deactivate = deactivate; + device_class->unmanaged_on_quit = unmanaged_on_quit; + + device_class->state_changed = device_state_changed; + + /*klass->scanning_prohibited = scanning_prohibited;*/ + + obj_properties[PROP_GROUP_OWNER] = + g_param_spec_boolean (NM_DEVICE_P2P_WIFI_GROUP_OWNER, "", "", + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_PEERS] = + g_param_spec_boxed (NM_DEVICE_P2P_WIFI_PEERS, "", "", + G_TYPE_STRV, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_WFDIES] = + g_param_spec_variant (NM_DEVICE_P2P_WIFI_WFDIES, "", "", + G_VARIANT_TYPE ("ay"), + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_MGMT_IFACE] = + g_param_spec_object (NM_DEVICE_P2P_WIFI_MGMT_IFACE, "", "", + NM_TYPE_SUPPLICANT_INTERFACE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + + /* obj_properties[PROP_SCANNING] = */ + /* g_param_spec_boolean (NM_DEVICE_WIFI_SCANNING, "", "", */ + /* FALSE, */ + /* G_PARAM_READABLE | */ + /* G_PARAM_STATIC_STRINGS); */ + + g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); +} diff --git a/src/devices/wifi/nm-device-p2p-wifi.h b/src/devices/wifi/nm-device-p2p-wifi.h new file mode 100644 index 0000000000..128914e055 --- /dev/null +++ b/src/devices/wifi/nm-device-p2p-wifi.h @@ -0,0 +1,56 @@ +/* NetworkManager -- P2P Wi-Fi Device + * + * 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 2018 Red Hat, Inc. + */ + +#ifndef __NM_DEVICE_P2P_WIFI_H__ +#define __NM_DEVICE_P2P_WIFI_H__ + +#include "devices/nm-device.h" +#include "supplicant/nm-supplicant-interface.h" + +#define NM_TYPE_DEVICE_P2P_WIFI (nm_device_p2p_wifi_get_type ()) +#define NM_DEVICE_P2P_WIFI(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_P2P_WIFI, NMDeviceP2PWifi)) +#define NM_DEVICE_P2P_WIFI_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_P2P_WIFI, NMDeviceP2PWifiClass)) +#define NM_IS_DEVICE_P2P_WIFI(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_P2P_WIFI)) +#define NM_IS_DEVICE_P2P_WIFI_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_P2P_WIFI)) +#define NM_DEVICE_P2P_WIFI_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_P2P_WIFI, NMDeviceP2PWifiClass)) + +#define NM_DEVICE_P2P_WIFI_GROUP_OWNER "group-owner" +#define NM_DEVICE_P2P_WIFI_PEERS "peers" +#define NM_DEVICE_P2P_WIFI_GROUPS "groups" +#define NM_DEVICE_P2P_WIFI_WFDIES "WFDIEs" + +#define NM_DEVICE_P2P_WIFI_MGMT_IFACE "mgmt-iface" + + +typedef struct _NMDeviceP2PWifi NMDeviceP2PWifi; +typedef struct _NMDeviceP2PWifiClass NMDeviceP2PWifiClass; + +GType nm_device_p2p_wifi_get_type (void); + +NMDevice* nm_device_p2p_wifi_new (NMSupplicantInterface *mgmt_iface, + const char* iface); + +NMSupplicantInterface * nm_device_p2p_wifi_get_mgmt_iface (NMDeviceP2PWifi *self); +void nm_device_p2p_wifi_set_mgmt_iface (NMDeviceP2PWifi *self, + NMSupplicantInterface *iface); + +void nm_device_p2p_wifi_remove (NMDeviceP2PWifi *self); + +#endif /* __NM_DEVICE_P2P_WIFI_H__ */ diff --git a/src/devices/wifi/nm-wifi-p2p-peer.c b/src/devices/wifi/nm-wifi-p2p-peer.c new file mode 100644 index 0000000000..417365907c --- /dev/null +++ b/src/devices/wifi/nm-wifi-p2p-peer.c @@ -0,0 +1,808 @@ +/* NetworkManager -- P2P Wi-Fi Peer + * + * 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. + * + * Copyright (C) 2018 Red Hat, Inc. + */ + +#include "nm-default.h" + +#include "nm-wifi-p2p-peer.h" + +#include +#include + +#include "nm-setting-wireless.h" + +#include "nm-wifi-utils.h" +#include "NetworkManagerUtils.h" +#include "nm-utils.h" +#include "nm-core-internal.h" +#include "platform/nm-platform.h" +#include "devices/nm-device.h" +#include "nm-dbus-manager.h" + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE (NMWifiP2PPeer, + PROP_NAME, + PROP_MANUFACTURER, + PROP_MODEL, + PROP_MODEL_NUMBER, + PROP_SERIAL, + //PROP_PRIMARY_DEVICE_TYPE, { "PrimaryDeviceType", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay", + // "devicecapability", WPAS_DBUS_NEW_IFACE_P2P_PEER, "y", + // "groupcapability", WPAS_DBUS_NEW_IFACE_P2P_PEER, "y", + // "SecondaryDeviceTypes", WPAS_DBUS_NEW_IFACE_P2P_PEER, "aay", + // "VendorExtension", WPAS_DBUS_NEW_IFACE_P2P_PEER, "aay", + PROP_WFD_IES, + PROP_GROUPS, + + PROP_HW_ADDRESS, + //PROP_MODE, + PROP_STRENGTH, + PROP_LAST_SEEN, + + //PROP_MAX_BITRATE, + // One of the following (FLAGS would simply mirror/use the same as AP flags) + PROP_FLAGS, + //PROP_CONFIG_METHOD, +); + +struct _NMWifiP2PPeerPrivate { + char *supplicant_path; /* D-Bus object path of this Peer from wpa_supplicant */ + + /* Scanned or cached values */ + char * name; + char * manufacturer; + char * model; + char * model_number; + char * serial; + + char * address; + + GBytes * wfd_ies; + char ** groups; + + guint8 strength; + + NM80211ApFlags flags; /* General flags */ + + /* Non-scanned attributes */ + gint32 last_seen; /* Timestamp when the Peer was seen lastly (obtained via nm_utils_get_monotonic_timestamp_s()) */ +}; + +typedef struct _NMWifiP2PPeerPrivate NMWifiP2PPeerPrivate; + +struct _NMWifiP2PPeerClass { + NMDBusObjectClass parent; +}; + +G_DEFINE_TYPE (NMWifiP2PPeer, nm_wifi_p2p_peer, NM_TYPE_DBUS_OBJECT) + +#define NM_WIFI_P2P_PEER_GET_PRIVATE(self) _NM_GET_PRIVATE_PTR(self, NMWifiP2PPeer, NM_IS_WIFI_P2P_PEER) + +/*****************************************************************************/ + +const char * +nm_wifi_p2p_peer_get_supplicant_path (NMWifiP2PPeer *peer) +{ + g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (peer), NULL); + + return NM_WIFI_P2P_PEER_GET_PRIVATE (peer)->supplicant_path; +} + +const char * +nm_wifi_p2p_peer_get_name (const NMWifiP2PPeer *peer) +{ + g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (peer), NULL); + + return NM_WIFI_P2P_PEER_GET_PRIVATE (peer)->name; +} + +gboolean +nm_wifi_p2p_peer_set_name (NMWifiP2PPeer *peer, const char *name) +{ + NMWifiP2PPeerPrivate *priv = NM_WIFI_P2P_PEER_GET_PRIVATE (peer); + g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (peer), FALSE); + + if (g_strcmp0 (name, priv->name) == 0) + return FALSE; + + g_clear_pointer (&priv->name, g_free); + if (name) + priv->name = g_strdup (name); + + _notify (peer, PROP_NAME); + return TRUE; +} + +const char * +nm_wifi_p2p_peer_get_manufacturer (const NMWifiP2PPeer *peer) +{ + g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (peer), NULL); + + return NM_WIFI_P2P_PEER_GET_PRIVATE (peer)->manufacturer; +} + +gboolean +nm_wifi_p2p_peer_set_manufacturer (NMWifiP2PPeer *peer, const char *manufacturer) +{ + NMWifiP2PPeerPrivate *priv = NM_WIFI_P2P_PEER_GET_PRIVATE (peer); + g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (peer), FALSE); + + if (g_strcmp0 (manufacturer, priv->manufacturer) == 0) + return FALSE; + + g_clear_pointer (&priv->manufacturer, g_free); + if (manufacturer) + priv->manufacturer = g_strdup (manufacturer); + + _notify (peer, PROP_MANUFACTURER); + return TRUE; +} + +const char * +nm_wifi_p2p_peer_get_model (const NMWifiP2PPeer *peer) +{ + g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (peer), NULL); + + return NM_WIFI_P2P_PEER_GET_PRIVATE (peer)->model; +} + +gboolean +nm_wifi_p2p_peer_set_model (NMWifiP2PPeer *peer, const char *model) +{ + NMWifiP2PPeerPrivate *priv = NM_WIFI_P2P_PEER_GET_PRIVATE (peer); + g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (peer), FALSE); + + if (g_strcmp0 (model, priv->model) == 0) + return FALSE; + + g_clear_pointer (&priv->model, g_free); + if (model) + priv->model = g_strdup (model); + + _notify (peer, PROP_MODEL); + return TRUE; +} + +const char * +nm_wifi_p2p_peer_get_model_number (const NMWifiP2PPeer *peer) +{ + g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (peer), NULL); + + return NM_WIFI_P2P_PEER_GET_PRIVATE (peer)->model_number; +} + +gboolean +nm_wifi_p2p_peer_set_model_number (NMWifiP2PPeer *peer, const char *model_number) +{ + NMWifiP2PPeerPrivate *priv = NM_WIFI_P2P_PEER_GET_PRIVATE (peer); + g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (peer), FALSE); + + if (g_strcmp0 (model_number, priv->model_number) == 0) + return FALSE; + + g_clear_pointer (&priv->model_number, g_free); + if (model_number) + priv->model_number = g_strdup (model_number); + + _notify (peer, PROP_MODEL_NUMBER); + return TRUE; +} + +const char * +nm_wifi_p2p_peer_get_serial (const NMWifiP2PPeer *peer) +{ + g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (peer), NULL); + + return NM_WIFI_P2P_PEER_GET_PRIVATE (peer)->serial; +} + +gboolean +nm_wifi_p2p_peer_set_serial (NMWifiP2PPeer *peer, const char *serial) +{ + NMWifiP2PPeerPrivate *priv = NM_WIFI_P2P_PEER_GET_PRIVATE (peer); + g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (peer), FALSE); + + if (g_strcmp0 (serial, priv->serial) == 0) + return FALSE; + + g_clear_pointer (&priv->serial, g_free); + if (serial) + priv->serial = g_strdup (serial); + + _notify (peer, PROP_SERIAL); + return TRUE; +} + +GBytes * +nm_wifi_p2p_peer_get_wfd_ies (const NMWifiP2PPeer *peer) +{ + g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (peer), NULL); + + return NM_WIFI_P2P_PEER_GET_PRIVATE (peer)->wfd_ies; +} + +gboolean +nm_wifi_p2p_peer_set_wfd_ies (NMWifiP2PPeer *peer, GBytes *wfd_ies) +{ + NMWifiP2PPeerPrivate *priv; + + g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (peer), FALSE); + + priv = NM_WIFI_P2P_PEER_GET_PRIVATE (peer); + + if (nm_gbytes_equal0 (priv->wfd_ies, wfd_ies)) + return FALSE; + + g_bytes_unref (priv->wfd_ies); + priv->wfd_ies = wfd_ies ? g_bytes_ref (wfd_ies) : NULL; + + _notify (peer, PROP_WFD_IES); + return TRUE; +} + +const char *const* +nm_wifi_p2p_peer_get_groups (const NMWifiP2PPeer *peer) +{ + g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (peer), NULL); + + return (const char * const*) NM_WIFI_P2P_PEER_GET_PRIVATE (peer)->groups; +} + +static gboolean +nm_wifi_p2p_peer_set_groups (NMWifiP2PPeer *peer, const char** groups) +{ + NMWifiP2PPeerPrivate *priv; + + g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (peer), FALSE); + g_return_val_if_fail (groups != NULL, FALSE); + + priv = NM_WIFI_P2P_PEER_GET_PRIVATE (peer); + + if (_nm_utils_strv_equal (priv->groups, (char **) groups)) + return FALSE; + + g_strfreev (priv->groups); + priv->groups = g_strdupv ((char**) groups); + + _notify (peer, PROP_GROUPS); + return TRUE; +} + +const char * +nm_wifi_p2p_peer_get_address (const NMWifiP2PPeer *peer) +{ + g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (peer), NULL); + + return NM_WIFI_P2P_PEER_GET_PRIVATE (peer)->address; +} + +static gboolean +nm_wifi_p2p_peer_set_address_bin (NMWifiP2PPeer *peer, const guint8 addr[static ETH_ALEN]) +{ + NMWifiP2PPeerPrivate *priv = NM_WIFI_P2P_PEER_GET_PRIVATE (peer); + + if ( priv->address + && nm_utils_hwaddr_matches (addr, ETH_ALEN, priv->address, -1)) + return FALSE; + + g_free (priv->address); + priv->address = nm_utils_hwaddr_ntoa (addr, ETH_ALEN); + _notify (peer, PROP_HW_ADDRESS); + return TRUE; +} + +gboolean +nm_wifi_p2p_peer_set_address (NMWifiP2PPeer *peer, const char *addr) +{ + guint8 addr_buf[ETH_ALEN]; + + g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (peer), FALSE); + + if ( !addr + || !nm_utils_hwaddr_aton (addr, addr_buf, sizeof (addr_buf))) + g_return_val_if_reached (FALSE); + + return nm_wifi_p2p_peer_set_address_bin (peer, addr_buf); +} + +gint8 +nm_wifi_p2p_peer_get_strength (NMWifiP2PPeer *peer) +{ + g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (peer), 0); + + return NM_WIFI_P2P_PEER_GET_PRIVATE (peer)->strength; +} + +gboolean +nm_wifi_p2p_peer_set_strength (NMWifiP2PPeer *peer, const gint8 strength) +{ + NMWifiP2PPeerPrivate *priv; + + g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (peer), FALSE); + + priv = NM_WIFI_P2P_PEER_GET_PRIVATE (peer); + + if (priv->strength != strength) { + priv->strength = strength; + _notify (peer, PROP_STRENGTH); + return TRUE; + } + return FALSE; +} + +NM80211ApFlags +nm_wifi_p2p_peer_get_flags (const NMWifiP2PPeer *peer) +{ + g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (peer), NM_802_11_AP_FLAGS_NONE); + + return NM_WIFI_P2P_PEER_GET_PRIVATE (peer)->flags; +} + +static gboolean +nm_wifi_p2p_peer_set_last_seen (NMWifiP2PPeer *peer, gint32 last_seen) +{ + NMWifiP2PPeerPrivate *priv; + + g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (peer), FALSE); + + priv = NM_WIFI_P2P_PEER_GET_PRIVATE (peer); + + if (priv->last_seen != last_seen) { + priv->last_seen = last_seen; + _notify (peer, PROP_LAST_SEEN); + return TRUE; + } + return FALSE; +} + + +/*****************************************************************************/ + +gboolean +nm_wifi_p2p_peer_update_from_properties (NMWifiP2PPeer *peer, + const char *supplicant_path, + GVariant *properties) +{ + NMWifiP2PPeerPrivate *priv; + const guint8 *bytes; + GVariant *v; + gsize len; + const char *s; + const char **sv; + gint32 i32; + gboolean changed = FALSE; + + g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (peer), FALSE); + g_return_val_if_fail (properties, FALSE); + + priv = NM_WIFI_P2P_PEER_GET_PRIVATE (peer); + + g_object_freeze_notify (G_OBJECT (peer)); + + if (g_variant_lookup (properties, "level", "i", &i32)) + changed |= nm_wifi_p2p_peer_set_strength (peer, nm_wifi_utils_level_to_quality (i32)); + + if (g_variant_lookup (properties, "DeviceName", "&s", &s)) + changed |= nm_wifi_p2p_peer_set_name (peer, s); + + if (g_variant_lookup (properties, "Manufacturer", "&s", &s)) + changed |= nm_wifi_p2p_peer_set_manufacturer (peer, s); + + if (g_variant_lookup (properties, "Model", "&s", &s)) + changed |= nm_wifi_p2p_peer_set_model (peer, s); + + if (g_variant_lookup (properties, "ModelNumber", "&s", &s)) + changed |= nm_wifi_p2p_peer_set_model_number (peer, s); + + if (g_variant_lookup (properties, "Serial", "&s", &s)) + changed |= nm_wifi_p2p_peer_set_serial (peer, s); + + v = g_variant_lookup_value (properties, "DeviceAddress", G_VARIANT_TYPE_BYTESTRING); + if (v) { + bytes = g_variant_get_fixed_array (v, &len, 1); + if ( len == ETH_ALEN + && memcmp (bytes, nm_ip_addr_zero.addr_eth, ETH_ALEN) != 0 + && memcmp (bytes, (char[ETH_ALEN]) { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, ETH_ALEN) != 0) + changed |= nm_wifi_p2p_peer_set_address_bin (peer, bytes); + g_variant_unref (v); + } + + /* The IEs property contains the WFD R1 subelements */ + v = g_variant_lookup_value (properties, "IEs", G_VARIANT_TYPE_BYTESTRING); + if (v) { + gs_unref_bytes GBytes *b = NULL; + + bytes = g_variant_get_fixed_array (v, &len, 1); + b = g_bytes_new (bytes, len); + changed |= nm_wifi_p2p_peer_set_wfd_ies (peer, b); + g_variant_unref (v); + } + + v = g_variant_lookup_value (properties, "Groups", G_VARIANT_TYPE_OBJECT_PATH_ARRAY); + if (v) { + sv = g_variant_get_objv (v, NULL); + changed |= nm_wifi_p2p_peer_set_groups (peer, sv); + g_free (sv); + } + + /*if (max_rate) + changed |= nm_wifi_p2p_peer_set_max_bitrate (peer, max_rate / 1000);*/ + + if (!priv->supplicant_path) { + priv->supplicant_path = g_strdup (supplicant_path); + changed = TRUE; + } + + changed |= nm_wifi_p2p_peer_set_last_seen (peer, nm_utils_get_monotonic_timestamp_s ()); + + g_object_thaw_notify (G_OBJECT (peer)); + + return changed; +} + +const char * +nm_wifi_p2p_peer_to_string (const NMWifiP2PPeer *self, + char *str_buf, + gsize buf_len, + gint32 now_s) +{ + const NMWifiP2PPeerPrivate *priv; + const char *supplicant_id = "-"; + const char* export_path; + + g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (self), NULL); + + priv = NM_WIFI_P2P_PEER_GET_PRIVATE (self); + + if (priv->supplicant_path) + supplicant_id = strrchr (priv->supplicant_path, '/') ?: supplicant_id; + + export_path = nm_dbus_object_get_path (NM_DBUS_OBJECT (self)); + if (export_path) + export_path = strrchr (export_path, '/') ?: export_path; + else + export_path = "/"; + + g_snprintf (str_buf, buf_len, + "%17s [n:%s, m:%s, mod:%s, mod_num:%s, ser:%s] %3us sup:%s [nm:%s]", + priv->address ?: "(none)", + priv->name, + priv->manufacturer, + priv->model, + priv->model_number, + priv->serial, + priv->last_seen > 0 ? ((now_s > 0 ? now_s : nm_utils_get_monotonic_timestamp_s ()) - priv->last_seen) : -1, + supplicant_id, + export_path); + + return str_buf; +} + +gboolean +nm_wifi_p2p_peer_check_compatible (NMWifiP2PPeer *self, + NMConnection *connection) +{ + NMWifiP2PPeerPrivate *priv; + NMSettingP2PWireless *s_p2p_wireless; + const char *hwaddr; + + g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (self), FALSE); + g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE); + + priv = NM_WIFI_P2P_PEER_GET_PRIVATE (self); + + s_p2p_wireless = NM_SETTING_P2P_WIRELESS (nm_connection_get_setting (connection, NM_TYPE_SETTING_P2P_WIRELESS)); + if (s_p2p_wireless == NULL) + return FALSE; + + hwaddr = nm_setting_p2p_wireless_get_peer (s_p2p_wireless); + if ( hwaddr + && ( !priv->address + || !nm_utils_hwaddr_matches (hwaddr, -1, priv->address, -1))) + return FALSE; + + return TRUE; +} + +/*****************************************************************************/ + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMWifiP2PPeer *self = NM_WIFI_P2P_PEER (object); + NMWifiP2PPeerPrivate *priv = NM_WIFI_P2P_PEER_GET_PRIVATE (self); + + switch (prop_id) { + case PROP_FLAGS: + g_value_set_uint (value, priv->flags); + break; + case PROP_NAME: + g_value_set_string (value, priv->name); + break; + case PROP_MANUFACTURER: + g_value_set_string (value, priv->manufacturer); + break; + case PROP_MODEL: + g_value_set_string (value, priv->model); + break; + case PROP_MODEL_NUMBER: + g_value_set_string (value, priv->model_number); + break; + case PROP_SERIAL: + g_value_set_string (value, priv->serial); + break; + case PROP_WFD_IES: + g_value_take_variant (value, nm_utils_gbytes_to_variant_ay (priv->wfd_ies)); + break; + case PROP_GROUPS: + g_value_set_variant (value, + g_variant_new_strv ( (const char*const*) priv->groups + ?: NM_PTRARRAY_EMPTY (const char *), + -1)); + break; + case PROP_HW_ADDRESS: + g_value_set_string (value, priv->address); + break; + case PROP_STRENGTH: + g_value_set_uchar (value, priv->strength); + break; + case PROP_LAST_SEEN: + g_value_set_int (value, + priv->last_seen > 0 + ? (int) nm_utils_monotonic_timestamp_as_boottime (priv->last_seen, NM_UTILS_NS_PER_SECOND) + : -1); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_wifi_p2p_peer_init (NMWifiP2PPeer *self) +{ + NMWifiP2PPeerPrivate *priv; + + priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NM_TYPE_WIFI_P2P_PEER, NMWifiP2PPeerPrivate); + + self->_priv = priv; + + c_list_init (&self->peers_lst); + + priv->flags = NM_802_11_AP_FLAGS_NONE; + priv->last_seen = -1; +} + +NMWifiP2PPeer * +nm_wifi_p2p_peer_new_from_properties (const char *supplicant_path, GVariant *properties) +{ + NMWifiP2PPeer *peer; + + g_return_val_if_fail (supplicant_path != NULL, NULL); + g_return_val_if_fail (properties != NULL, NULL); + + peer = (NMWifiP2PPeer *) g_object_new (NM_TYPE_WIFI_P2P_PEER, NULL); + nm_wifi_p2p_peer_update_from_properties (peer, supplicant_path, properties); + + /* ignore peers with invalid or missing address */ + if (!nm_wifi_p2p_peer_get_address (peer)) { + g_object_unref (peer); + return NULL; + } + + return peer; +} + +static void +finalize (GObject *object) +{ + NMWifiP2PPeer *self = NM_WIFI_P2P_PEER (object); + NMWifiP2PPeerPrivate *priv = NM_WIFI_P2P_PEER_GET_PRIVATE (self); + + nm_assert (!self->wifi_device); + nm_assert (c_list_is_empty (&self->peers_lst)); + + g_free (priv->supplicant_path); + g_free (priv->name); + g_free (priv->manufacturer); + g_free (priv->model); + g_free (priv->model_number); + g_free (priv->serial); + g_free (priv->address); + g_bytes_unref (priv->wfd_ies); + g_strfreev (priv->groups); + + G_OBJECT_CLASS (nm_wifi_p2p_peer_parent_class)->finalize (object); +} + +static const NMDBusInterfaceInfoExtended interface_info_p2p_peer = { + .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT ( + NM_DBUS_INTERFACE_P2P_PEER, + .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS ( + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE ("Flags", "u", NM_WIFI_P2P_PEER_FLAGS), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE ("Name", "s", NM_WIFI_P2P_PEER_NAME), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE ("Manufacturer", "s", NM_WIFI_P2P_PEER_MANUFACTURER), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE ("Model", "s", NM_WIFI_P2P_PEER_MODEL), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE ("ModelNumber", "s", NM_WIFI_P2P_PEER_MODEL_NUMBER), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE ("Serial", "s", NM_WIFI_P2P_PEER_SERIAL), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE ("WfdIEs", "ay", NM_WIFI_P2P_PEER_WFD_IES), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE ("Groups", "as", NM_WIFI_P2P_PEER_GROUPS), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE ("HwAddress", "s", NM_WIFI_P2P_PEER_HW_ADDRESS), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE ("Strength", "y", NM_WIFI_P2P_PEER_STRENGTH), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE ("LastSeen", "i", NM_WIFI_P2P_PEER_LAST_SEEN), + ), + ), + .legacy_property_changed = FALSE, +}; + +static void +nm_wifi_p2p_peer_class_init (NMWifiP2PPeerClass *p2p_peer_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (p2p_peer_class); + NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (p2p_peer_class); + + g_type_class_add_private (object_class, sizeof (NMWifiP2PPeerPrivate)); + + dbus_object_class->export_path = NM_DBUS_EXPORT_PATH_NUMBERED (NM_DBUS_PATH_P2P_PEER); + dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_p2p_peer); + + object_class->get_property = get_property; + object_class->finalize = finalize; + + obj_properties[PROP_FLAGS] = + g_param_spec_uint (NM_WIFI_P2P_PEER_FLAGS, "", "", + NM_802_11_AP_FLAGS_NONE, + NM_802_11_AP_FLAGS_PRIVACY, + NM_802_11_AP_FLAGS_NONE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_NAME] = + g_param_spec_string (NM_WIFI_P2P_PEER_NAME, "", "", + NULL, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_MANUFACTURER] = + g_param_spec_string (NM_WIFI_P2P_PEER_MANUFACTURER, "", "", + NULL, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_MODEL] = + g_param_spec_string (NM_WIFI_P2P_PEER_MODEL, "", "", + NULL, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_MODEL_NUMBER] = + g_param_spec_string (NM_WIFI_P2P_PEER_MODEL_NUMBER, "", "", + NULL, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_SERIAL] = + g_param_spec_string (NM_WIFI_P2P_PEER_SERIAL, "", "", + NULL, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_WFD_IES] = + g_param_spec_variant (NM_WIFI_P2P_PEER_WFD_IES, "", "", + G_VARIANT_TYPE ("ay"), + NULL, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_GROUPS] = + g_param_spec_variant (NM_WIFI_P2P_PEER_GROUPS, "", "", + G_VARIANT_TYPE ("as"), + NULL, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_HW_ADDRESS] = + g_param_spec_string (NM_WIFI_P2P_PEER_HW_ADDRESS, "", "", + NULL, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_STRENGTH] = + g_param_spec_uchar (NM_WIFI_P2P_PEER_STRENGTH, "", "", + 0, G_MAXINT8, 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_LAST_SEEN] = + g_param_spec_int (NM_WIFI_P2P_PEER_LAST_SEEN, "", "", + -1, G_MAXINT, -1, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); +} + +/*****************************************************************************/ + +const char ** +nm_wifi_p2p_peers_get_paths (const CList *peers_lst_head) +{ + NMWifiP2PPeer *peer; + const char **list; + const char *path; + gsize i, n; + + n = c_list_length (peers_lst_head); + list = g_new (const char *, n + 1); + + i = 0; + if (n > 0) { + c_list_for_each_entry (peer, peers_lst_head, peers_lst) { + nm_assert (i < n); + path = nm_dbus_object_get_path (NM_DBUS_OBJECT (peer)); + nm_assert (path); + + list[i++] = path; + } + nm_assert (i <= n); + } + list[i] = NULL; + return list; +} + +NMWifiP2PPeer * +nm_wifi_p2p_peers_find_first_compatible (const CList *peers_lst_head, + NMConnection *connection) +{ + NMWifiP2PPeer *peer; + + g_return_val_if_fail (connection, NULL); + + c_list_for_each_entry (peer, peers_lst_head, peers_lst) { + if (nm_wifi_p2p_peer_check_compatible (peer, connection)) + return peer; + } + return NULL; +} + +NMWifiP2PPeer * +nm_wifi_p2p_peers_find_by_supplicant_path (const CList *peers_lst_head, const char *path) +{ + NMWifiP2PPeer *peer; + + g_return_val_if_fail (path != NULL, NULL); + + c_list_for_each_entry (peer, peers_lst_head, peers_lst) { + if (nm_streq0 (path, nm_wifi_p2p_peer_get_supplicant_path (peer))) + return peer; + } + return NULL; +} + +/*****************************************************************************/ + +NMWifiP2PPeer * +nm_wifi_p2p_peer_lookup_for_device (NMDevice *device, const char *exported_path) +{ + NMWifiP2PPeer *peer; + + g_return_val_if_fail (NM_IS_DEVICE (device), NULL); + + peer = (NMWifiP2PPeer *) nm_dbus_manager_lookup_object (nm_dbus_object_get_manager (NM_DBUS_OBJECT (device)), + exported_path); + if ( !peer + || !NM_IS_WIFI_P2P_PEER (peer) + || peer->wifi_device != device) + return NULL; + + return peer; +} diff --git a/src/devices/wifi/nm-wifi-p2p-peer.h b/src/devices/wifi/nm-wifi-p2p-peer.h new file mode 100644 index 0000000000..13c4add6cd --- /dev/null +++ b/src/devices/wifi/nm-wifi-p2p-peer.h @@ -0,0 +1,114 @@ +/* NetworkManager -- P2P Wi-Fi Peer + * + * 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. + * + * Copyright (C) 2018 Red Hat, Inc. + */ + +#ifndef __NM_WIFI_P2P_PEER_H__ +#define __NM_WIFI_P2P_PEER_H__ + +#include "nm-dbus-object.h" +#include "nm-dbus-interface.h" +#include "nm-connection.h" + +#define NM_TYPE_WIFI_P2P_PEER (nm_wifi_p2p_peer_get_type ()) +#define NM_WIFI_P2P_PEER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_WIFI_P2P_PEER, NMWifiP2PPeer)) +#define NM_WIFI_P2P_PEER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_WIFI_P2P_PEER, NMWifiP2PPeerClass)) +#define NM_IS_WIFI_P2P_PEER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_WIFI_P2P_PEER)) +#define NM_IS_WIFI_P2P_PEER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_WIFI_P2P_PEER)) +#define NM_WIFI_P2P_PEER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_WIFI_P2P_PEER, NMWifiP2PPeerClass)) + +#define NM_WIFI_P2P_PEER_FLAGS "flags" +#define NM_WIFI_P2P_PEER_NAME "name" +#define NM_WIFI_P2P_PEER_MANUFACTURER "manufacturer" +#define NM_WIFI_P2P_PEER_MODEL "model" +#define NM_WIFI_P2P_PEER_MODEL_NUMBER "model-number" +#define NM_WIFI_P2P_PEER_SERIAL "serial" +#define NM_WIFI_P2P_PEER_WFD_IES "wfd-ies" +#define NM_WIFI_P2P_PEER_GROUPS "groups" +#define NM_WIFI_P2P_PEER_HW_ADDRESS "hw-address" +#define NM_WIFI_P2P_PEER_STRENGTH "strength" +#define NM_WIFI_P2P_PEER_LAST_SEEN "last-seen" + +typedef struct { + NMDBusObject parent; + NMDevice *wifi_device; + CList peers_lst; + struct _NMWifiP2PPeerPrivate *_priv; +} NMWifiP2PPeer; + +typedef struct _NMWifiP2PPeerClass NMWifiP2PPeerClass; + +GType nm_wifi_p2p_peer_get_type (void); + +NMWifiP2PPeer * nm_wifi_p2p_peer_new_from_properties (const char *supplicant_path, + GVariant *properties); + +gboolean nm_wifi_p2p_peer_update_from_properties (NMWifiP2PPeer *peer, + const char *supplicant_path, + GVariant *properties); + +gboolean nm_wifi_p2p_peer_check_compatible (NMWifiP2PPeer *self, + NMConnection *connection); + +const char * nm_wifi_p2p_peer_get_supplicant_path (NMWifiP2PPeer *peer); + +const char * nm_wifi_p2p_peer_get_name (const NMWifiP2PPeer *peer); +gboolean nm_wifi_p2p_peer_set_name (NMWifiP2PPeer *peer, + const char *name); +const char * nm_wifi_p2p_peer_get_manufacturer (const NMWifiP2PPeer *peer); +gboolean nm_wifi_p2p_peer_set_manufacturer (NMWifiP2PPeer *peer, + const char *manufacturer); +const char * nm_wifi_p2p_peer_get_model (const NMWifiP2PPeer *peer); +gboolean nm_wifi_p2p_peer_set_model (NMWifiP2PPeer *peer, + const char *model); +const char * nm_wifi_p2p_peer_get_model_number (const NMWifiP2PPeer *peer); +gboolean nm_wifi_p2p_peer_set_model_number (NMWifiP2PPeer *peer, + const char *number); +const char * nm_wifi_p2p_peer_get_serial (const NMWifiP2PPeer *peer); +gboolean nm_wifi_p2p_peer_set_serial (NMWifiP2PPeer *peer, + const char *serial); + +GBytes * nm_wifi_p2p_peer_get_wfd_ies (const NMWifiP2PPeer *peer); +gboolean nm_wifi_p2p_peer_set_wfd_ies (NMWifiP2PPeer *peer, + GBytes *bytes); + +const char *const*nm_wifi_p2p_peer_get_groups (const NMWifiP2PPeer *peer); + +const char * nm_wifi_p2p_peer_get_address (const NMWifiP2PPeer *peer); +gboolean nm_wifi_p2p_peer_set_address (NMWifiP2PPeer *peer, + const char *addr); +gint8 nm_wifi_p2p_peer_get_strength (NMWifiP2PPeer *peer); +gboolean nm_wifi_p2p_peer_set_strength (NMWifiP2PPeer *peer, + gint8 strength); +NM80211ApFlags nm_wifi_p2p_peer_get_flags (const NMWifiP2PPeer *self); + +const char *nm_wifi_p2p_peer_to_string (const NMWifiP2PPeer *self, + char *str_buf, + gsize buf_len, + gint32 now_s); + +const char **nm_wifi_p2p_peers_get_paths (const CList *peers_lst_head); + +NMWifiP2PPeer *nm_wifi_p2p_peers_find_first_compatible (const CList *peers_lst_head, + NMConnection *connection); + +NMWifiP2PPeer *nm_wifi_p2p_peers_find_by_supplicant_path (const CList *peers_lst_head, const char *path); + +NMWifiP2PPeer *nm_wifi_p2p_peer_lookup_for_device (NMDevice *device, const char *exported_path); + +#endif /* __NM_WIFI_P2P_PEER_H__ */ diff --git a/src/nm-types.h b/src/nm-types.h index 277e0f6ccf..9a384e5800 100644 --- a/src/nm-types.h +++ b/src/nm-types.h @@ -152,6 +152,7 @@ typedef enum { NM_LINK_TYPE_WIMAX, NM_LINK_TYPE_WPAN, NM_LINK_TYPE_6LOWPAN, + NM_LINK_TYPE_P2P_WIFI, /* Software types */ NM_LINK_TYPE_BNEP = 0x10000, /* Bluetooth Ethernet emulation */ diff --git a/src/org.freedesktop.NetworkManager.conf b/src/org.freedesktop.NetworkManager.conf index fa74b280de..2bc7b4de94 100644 --- a/src/org.freedesktop.NetworkManager.conf +++ b/src/org.freedesktop.NetworkManager.conf @@ -84,6 +84,8 @@ send_interface="org.freedesktop.NetworkManager.WiMax.Nsp"/> + +