device: renew dhcp leases on awake for software devices
[NetworkManager.git] / TODO
diff --git a/TODO b/TODO
index f29f57b..96dc81b 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,16 +1,30 @@
 So you're interested in hacking on NetworkManager?  Here's some cool
 stuff you could do...
 
-* Internet Connectivity Detection
-
-This feature would consist of attempting to make an HTTP request to a known
-DNS address and compare the response to a well-known string, like Windows does.
-This feature and the server address should be configurable via an option in the
-/etc/NetworkManager/NetworkManager.conf config file.
-
-Once the device has successfully gotten an IPv4 or IPv6 address, it should
-enter the state NM_DEVICE_STATE_IP_CHECK, where this HTTP request would be
-performed.  After the check was done, the device would set a property in
+* Internet Connectivity Detection Enhancements
+
+Current connectivity checking is global, while what we really want is to check
+connectivity per-interface and update the global state based on the composite
+of each device's state.  Unfortunately that requires two things:
+
+1) latest libsoup and glib for using libsoup connection state signals, which
+   allow us to set socket options before the actual connection is made; here
+   we'd bind the socket to the specific IP address of the interface we're
+   using, and possibly set SO_BINDTODEVICE as well
+2) setting /proc/sys/net/ipv4/conf/<iface>/rp_filter to "2" which tells the
+   kernel to route the incoming and outgoing packet properly even though the
+   interface may not have the necessary routes
+
+The first is the largest obstacle, but ideally we implement this and enable it
+when we have the required glib and libsoup versions available.  One other
+complication is that this checking should be done during the
+NM_DEVICE_STATE_IP_CHECK phase (along with other operations like WiFi hotspot
+auto-login) while the current checks are done globally in nm-manager.c, so 
+keeping both code paths might be complex.
+
+But ideally, once the device has successfully gotten an IPv4 or IPv6 address, it
+should enter the state NM_DEVICE_STATE_IP_CHECK, where a connectivity check is
+started.  After the check returns, the device would set a property in
 NMDevicePrivate to indicate whether Internet access was successful or not, and
 advance to the NM_DEVICE_STATE_ACTIVATED state.
 
@@ -19,113 +33,6 @@ nm_manager_update_state() function, would query this property and set
 NM_STATE_CONNECTED_LOCAL, NM_STATE_CONNECTED_SITE, or NM_STATE_CONNECTED_GLOBAL
 based on it and the device's state.
 
-Ideally this feature would not require linking to an HTTP library like libcurl,
-but would use open-coded simple HTTP or libsoup for the request.  The request
-must be done asynchronously, of course.
-
-
-* ADSL support
-
-NetworkManager should natively support ADSL modems using one of the 3 main
-connection methods, PPP over ATM (pppoa), PPP over Ethernet (pppoe), or
-IP over ATM (ipoatm).  Initial support could be targeted at just pppoa and
-pppoe, and there is some code in NetworkManager already for pppoe.  More info
-about ADSL configuration on Linux in general is here:
-
-http://atm.eagle-usb.org/wakka.php?wiki=UeagleAtmDoc
-
-hicham started code for the configuration settings here:
-
-https://github.com/hicham-haouari/NetworkManager-ADSL-Support/commits/adsl
-
-After the libnm-util pieces, internally NM needs to be modified for ADSL
-support, of course.  That involves adding a new NM_DEVICE_TYPE_ADSL in
-NetworkManager.h, and then creating a new NMDeviceAdsl subclass in src/.  It's
-probably easiest to copy the nm-device-ethernet.c file and strip out stuff
-that's not required.  Like the nm-device-ethernet.c file handles the 'carrier'
-state though, the ADSL code should periodically poll the sysfs 'carrier'
-attribute of the DSL modem to detect when the modem has a link with the remote
-DSL concentrator, and only activate connections when the link is present.
-
-Detection of ADSL modems should be handled in nm-udev-manager.c checking for
-the "atm" subsystem.
-
-Code to manage br2684ctl will likely be required to be written for the PPPoE
-case before PPPoE is started on the bridge-created link "nasX".  There are
-quite a few examples of daemon management code in NetworkManager (dnsmasq,
-avahi-autoipd, ppp, dhclient, etc) so there should be a lot of code to
-copy and paste from.
-
-
-* Convert WEXT code to nl80211
-
-There's still some WEXT code in NetworkManager for signal strength reporting,
-mode, frequency, BSSID, etc.  This should all get converted to nl80211 code,
-possibly using libnl as a base.  It's not particularly hard, but some
-investigation on how to talk to netlink and how to use nl80211 and netlink
-attributes will need to be done.  Tools like 'iw' already do much of this work,
-but we *cannot* copy & paste code from them since the 'iw' license is not
-compatible with NetworkManager's GPL license.  For exmaple, the following code
-does the job, but should be reworked a bit to use the internal synchronous
-netlink connection from src/nm-netlink-manager.c instead of doing the
-netlink communication on its own with genl_connect() and such:
-
-http://mail.gnome.org/archives/networkmanager-list/2009-September/msg00214.html
-
-The same approach should be taken for signal strength reporting, etc.
-
-
-* Real Access Point mode support
-
-Now that NetworkManager requires wpa_supplicant 0.7.x or later, we can add
-full Access Point (AP) mode support.  NetworkManager currently implements
-connection sharing via AdHoc mode support, which has some limitations.  Instead,
-we should check whether the wifi device supports AP mode, and if so, use
-that mode instead.  wpa_supplicant has support for a "lightweight AP" mode which
-we should use.  Witold Sowa started this support a while ago and wrote the new
-D-Bus API for wpa_supplicant that makes all this possible, but some NM pieces
-are still missing.  If the wifi driver supports AP mode, then in
-src/supplicant-manager/ NM should send an AP-mode config instead of sending
-the adhoc config.
-
-
-* On-Demand WiFi Scan support
-
-Single-user and embedded devices often use a continuous wifi scan when the
-networking configuration interface is open to quickly allow users to find their
-wifi network.  NM periodically scans, but this could take as long as 2 mintues
-to update the list.  Note that WiFi scans require 2 - 10 seconds to complete,
-and during this time normal traffic (video, VOIP, streaming music, downloads,
-etc) is not transmitted, so a WiFi scan is a disruptive operation to the user.
-
-A D-Bus method should be added to the NMDeviceWifi device to allow user
-applications to request a scan.  This request should be rate-limited to no
-more than once every 10 seconds to give time for traffic to resume when the
-scan is done, and to lessen the effect of any DDoS by malicious user
-applications.  This request should also be restricted by one or more PolicyKit
-permissions like org.freedesktop.NetworkManager.network-control.
-
-To begin, a new method definition should be added to the
-introspection/nm-device-wifi.xml for a method called "RequestScan" which takes
-an argument called "options" of type of "a{sv}".  This argument will be used
-later.  An annotation (like the other functions have) should be added so that
-the method will be called "impl_device_request_scan".
-
-Next, the corresponding method implementation should be added to
-src/nm-device-wifi.c by adding the prototype for impl_device_request_scan
-near the top of the file, and implementing it below.  The implementation will
-recieve a GHashTable corresponding to the "a{sv}" argument list from the XML
-file, but we can ignore that for now.
-
-The incoming request should be authenticated using nm_auth_get_caller_uid()
-and additionally starting a PolicyKit authentication check with
-with nm_auth_chain_new().  See the function manager_device_disconnect_request()
-in src/nm-manager.c for an example of this.
-
-Only after the caller is authorized to scan should the request be checked
-against the last scan timestamp, and if the last scan was 10 seconds or more
-ago, a new scan should be requested.
-
 
 * Implement NM_DEVICE_STATE_DISCONNECTING
 
@@ -141,7 +48,65 @@ amount of time for each script to complete before allowing the device to
 proceed to the NM_DEVICE_STATE_DISCONNECTED state, fully implementing pre-down.
 
 
-* VPN re-connect
+* Ethernet Network Auto-detection
+
+There are various methods we can use to autodetect which wired network connection
+to use if the user connects to more than one wired network on a frequent basis.
+First, 802.1x enterprise switches broadcast frames which can be used to indicate
+that the switch supports 802.1x and thus allow NetworkManager to select an
+802.1x connection instead of blindly trying DHCP.  Second, NetworkManager could
+listen for traffic from a list of MAC addresses.  Third, NetworkManager could
+integrate 'arping' functionality to determine if a given IP address matches a
+given MAC address, and thus automatically select that connection.  All these
+methods can co-exist and be used in parallel.
+
+One small caveat is that MAC addresses are trivial to spoof, so just because
+NetworkManager has discovered a certain MAC address does not mean the network
+is authenticated; only 802.1x security can assure that a network is the network
+the user expects it to be.
+
+In any case, a new 'anchor-addresses' property of type string-array should be
+added to the NMSettingWired setting.  Each string element of this property
+should be of the format "<ip>/<mac>" or simply "<mac>".  The first format with
+an IP address would indicate that "arping"-type behavior should be used to
+actively detect the given MAC address; obviously if the given MAC address is
+used for passive discovery as well.  The second format simply lists a MAC
+address to passively listen for.
+
+One drawback of listening or probing for known MAC addresses is an increase in
+latency during connections to ethernet networks.  The probing/listening delay
+should be a reasonable amount of time, like 4 - 5 seconds or so, and should
+only be used when a visible connection has anchor addresses.
+
+Next a gboolean 'anchor-probing' variable should be added to the
+NMDeviceEthernetPrivate structure in src/nm-device-ethernet.c.  This variable
+should be set to TRUE whenever the device's carrier turns on *and* there are
+visible NMConnections with anchor addresses (ie, connections which are system-
+wide or where one of the allowed users of that connection is logged in).  Then
+probing and listening are started, which involves opening a low-level socket
+on the interface and starting the arping run or listening for MAC addresses.
+A timer is also started (don't forget to cache the timer's source ID in the
+NMDeviceEthernetPrivate data, and to cancel the timer whenever the device
+transitions to any state other than DISCONNECTED).
+
+If a known MAC address is discovered as a result of probing or listening, the
+probe/listen socket, timeout, and data are cleaned up, and NetworkManager
+would begin activation of the NMConnection that specified the found MAC address
+in the 'anchor-addresses' property.  If two or more connections specify the
+same MAC address, the connection with the most recent timestamp should be
+preferred.
+
+Similarly, if the probing/listening process detects 802.1x frames the device
+should be marked as requring 802.1x authentication until the carrier drops.
+This would be accomplished by adding a new property to the NMDeviceEthernet
+object and exporting that property through the
+introspection/nm-device-ethernet.xml file.  This would allow clients like
+applets to ensure that users are aware that the device will not allow
+un-authenticated connections and that additional credentials are required to
+successfully connect to this network.
+
+
+* VPN re-connect (bgo #349151)
 
 NM should remember whether a VPN was connected if a connection disconnects
 (like WiFi drops out or short carrier drop) or if the laptop goes to sleep.
@@ -151,33 +116,6 @@ the VPN because WiFi choked for 10 seconds, but reconnect the VPN if it was
 connected before the drop.
 
 
-* VPN autoconnect
-
-We should add a property to the NMSettingConnection object in
-libnm-util/nm-setting-connection.c called "vpns" that is a string list,
-containing a list of Connection UUIDs that should be activated when the base
-connection itself is activated.  This will allow a VPN connection to be
-started every time another connection is started, so that if you choose you're
-always on the VPN in your favorite coffee shop.
-
-The NM_DEVICE_STATE_SECONDARIES state was added specifically for cases like
-this.  Thus, after the base device has IP connectivity, but before it has
-signaled that it's fully activated, the device should enter the SECONDARIES
-state and kick off activation of the given VPN connection.  Only after this
-VPN connection has successfully connected should the base device to the
-NM_DEVICE_STATE_ACTIVATED state.
-
-
-* VPN and IPv6
-
-The internal VPN capability should support IPv6.  Essentially, the D-Bus
-interface between NetworkManager and the VPN service daemons should be extended
-with an IP6Config signal that passes up the IPv6 addressing and routing details
-if the VPN daemon is IPv6 capable.  NM should then process those details like it
-does with IPv4.  include/NetworkManagerVPN.h should be updated with key/value
-pairs defining the various IPv6 attributes much like the IPv4 ones are defined.
-
-
 * VPN IP Methods
 
 Some VPNs (openvpn with TAP for example) require that DHCP is run on a
@@ -189,13 +127,230 @@ signals.  A patch here:
 
 http://cgit.freedesktop.org/NetworkManager/NetworkManager/commit/?h=vpn-ip-method
 
-shows that, but internally NM needs to process this request, and instead of
-applying given IPv4 or IPv6 configuration (since there isn't any yet) it should
-kick off a DHCP request and wait for the request to finish.  When it does
-finish it should apply the configuration to the interface.  Most of the DHCP
-code is already written, but src/vpn-manager/nm-vpn-connection.c would need
-updates to recognize the new "method" property of the IP4Config signal and
-handle the DHCP lifetime after that.  The base NMDevice class in nm-device.c
-has code for handling the DHCP lifetime, connecting to NMDHCPManager signals
-for renew and failure processing, etc, and could be used as an example.
-
+shows that.  In nm-vpn-connection.c, upon receipt of the D-Bus Ip4Config signal
+from the VPN plugin, NetworkManager would inspect the "method" property of the
+ip4 config dictionary.  If that property was present and set to "auto" then
+DHCP would be started using the network interface returned in the dict.  The
+nm_vpn_connection_ip4_config_get() function should be split up into two
+functions, one containing the existing code for static configuration, and a
+second for handling DHCP kickoff.  Minimal parsing of the response should be
+handled in the newly reduced nm_vpn_connection_ip4_config_get() function.
+
+To handle DHCP, the NMVPNConnectionPrivate structure should have two members
+added:
+
+    NMDHCPManager *dhcp_manager;
+    NMDHCPClient  *dhcp4_client;
+
+which would be initialized in the new DHCP handler code split off from
+nm_vpn_connection_ip4_config_get().  These new members would be disposed of in
+both vpn_cleanup() and dispose(), though remember to stop any ongoing DHCP
+transaction when doing so (see dhcp4_cleanup() in nm-device.c for example code).
+For basic code to start the DHCP transaction, see dhcp4_start() in nm-device.c
+as well.  After calling nm_dhcp_manager_start_ip4() and connecting the signals
+to monitor success and failure, the VPN IP4 config handler would simply return
+without changing VPN state, unless a failure occurred.
+
+Then, when the DHCP transaction succeeds, which we'd know by checking the
+DHCP client state changes in the "state-changed" signal handler we attached to
+the DHCP client object returned from nm_dhcp_manager_start_ip4(), the code
+would retrieve the completed NMIP4Config object from the DHCP client using the
+nm_dhcp_client_get_ip4_config() function, and then proceed to execute
+essentially the bottom-half of the existing nm_vpn_connection_ip4_config_get()
+function to merge that config with user overrides and apply it to the VPN
+tunnel interface.  Other state changes from the DHCP client might trigger a
+failure of the VPN connection, just like DHCP timeouts and lease-renewal
+failures do for other devices (see dhcp_state_changed() in nm-device.c).
+
+
+* VPN Service Daemon Secret Requests
+
+In addition to NM asking the service daemons whether more secrets are required,
+VPN service daemons (like nm-vpnc-service, nm-openvpn-service, etc) should be
+able to ask NetworkManager to provide secrets during the connection attempt. To
+do this, the plugin should advertise its ability to handle out-of-band secrets
+in its .service file via the key 'async-secrets=true'.  NetworkManager would
+check that key and if present activate the VPN as normal, but skip the explicit
+NeedSecrets calls.
+
+Instead, a new "SecretsRequired" signal would be added to
+introspection/nm-vpn-plugin.xml (and corresponding helper code added to
+libnm-glib/nm-vpn-plugin.c) that would be emitted when the plugin determined
+that secrets were required.  This signal would have D-Bus signature of "sas"
+for the arguments [ <s:uuid>, <as:secrets> ] with the <uuid> obviously being
+the connection UUID, and <secrets> being an array of strings of plugin-specific
+strings the plugin requires secrets for.  This array of strings would then be
+passed as the "hints" parameter in nm-vpn-connection.c when secrets are
+requested from agents in a subsequent nm_settings_connection_get_secrets() call.
+At this time the agent code only allows one hint per request, so we may need to
+extend that to allow more than one hint.
+
+Thus when connecting if the plugin supported async secrets NetworkManager would
+still request existing secrets (without interactivity) and send them to the
+VPN service daemon in the Connect D-Bus method, then wait for the service daemon
+to either request secrets asynchronously via the SecretsRequired signal or to
+signal successful connection via the Ip4Config signal.
+
+The vpnc plugin would need to be reworked to open a pipe to vpnc's stdout and
+stdin file descriptors to capture any authentication messages, and to match
+these messages to known secrets request strings.  When receiving one of these
+strings the plugin would determine which secret was being requested and then
+emit the SecretsRequired signal to NetworkManager.  This would also imply that
+nm-vpnc-service exectutes vpnc with the "--xauth-inter" argument to enable
+challenge-response and does not use the "--non-inter" flag which suppresses that
+behavior.
+
+
+* WPS
+
+wpa_supplicant has support for WPS (Wifi Protected Setup, basically Bluetooth-
+like PIN codes for setting up a wifi connection) and we should add support for
+this to NetworkManager too.  APs that support WPS will say so in their beacon
+IEs which are contained in the "WPA" and "RSN" properties of the BSS object
+exported by the supplicant, and can be processed in src/nm-wifi-ap.c's
+foreach_property_cb() function.  We should add some private fields to the
+NMAccessPoint object (defined in nm-wifi-ap.c) to remember whether a specific
+AP supports WPS and what WPS methods it supports, and expose that over D-Bus to
+GUI clients as well.
+
+There are two common WPS setup methods: PIN and button.  For PIN, the router
+either displays a random PIN on an LCD or the router's web UI, or a static PIN
+is printed on the router itself.  The user enters that PIN instead of a PSK
+when connecting.  For the "button" method, the router has a physical button that
+when pushed, allows any client to connect for a short period of time.
+
+We'll then need to add some properties to the NMSettingWirelessSecurity setting
+for the WPS PIN code so that when the user enters it through the GUI, it can
+be passed back to NM.  And we'll need to figure out some mechanism for passing
+back an indication that the user pushed the button on the router for the
+pushbutton method.
+
+When connecting to a new access point that supports WPS, the GUI client would
+call the AddAndActivateConnection method and wait for NM to request secrets.
+NM would determine that the AP supports WPS, and request WPS secrets from the
+applet.  The applet would ask the user for a PIN, or to push the button on the
+AP, instead of asking for a passphrase or PSK.  When the user has entered the
+PIN or pushed the button, the applet returns this information to NM, which
+proceeds with the connection.
+
+NM sends the correct wpa_supplicant config for WPS to the supplicant, and waits
+for the connection to occur.  WPS can only be used the *first* time, so after a
+first successfull connection, NM must request the actual hexadecimal PSK from 
+wpa_supplicant via D-Bus, and store that PSK in the connection, clear any WPS
+PIN code from the connection, and save the connection to backing storage.
+
+Any applet GUI should also allow the user to enter the PSK instead of completing
+association using WPS, since quite a few routers out there are broken, or
+because the user has no physical access to the router itself, but has been given
+as passphrase/PSK instead.
+
+
+* Proxies
+
+HTTP and other proxies are per-connection configuration.  It's highly unlikely
+that the same proxy you need to use at work is used at home or in a coffee shop.
+Thus, it makes sense that which proxy settings to use should be updated when
+network connections change.  NetworkManager is a perfect place to do this since
+it tracks which network connections are active, and it already queries the
+network for automatic proxy configuration via DHCP and WPAD.
+
+However, proxy handling is complicated and may require use of Javascript to
+parse PAC files provided by WPAD, and this is not something NetworkManager
+should do itself.  Instead, that should be left to "proxy handlers", or external
+utilities like libproxy or pacrunner that take raw proxy information, parse it,
+and tell applications what proxy server to use for a specific network resource.
+NetworkManager should provide all the proxy information it can find to these
+external proxy handlers via the D-Bus interface and dispatcher scripts.
+
+We should add a new NMSetting subclass called NMSettingProxy that holds
+necessary proxy configuration.  The properties of this setting should be a
+superset of what is provided in the Firefox proxy configuration screen and the
+various desktop environment proxy configuration tools like the GNOME Network
+Proxy control panel; this should include at a minimum:
+
+  method: "auto", "manual", "none"
+  default-proxy: string
+  default-proxy-port: uint
+  default-always: boolean (use default proxy for all protocols)
+  ssl-proxy: string
+  ssl-proxy-port: uint
+  ftp-proxy: string
+  ftp-proxy-port: uint
+  socks-proxy: string
+  socks-proxy-port: uint
+  socks-version: uint, either 4 or 5
+  no-proxy-for: array of strings (things not to use the proxy for, ie ".foobar.com",
+                 "192.168.0.1/24", an IPv6 address, etc)
+  pac-url: string (URL of PAC file, overrides DHCP-provided WPAD value)
+  (FIXME: proxy authentication?  do we need separate user/pass properties for
+    each protocol type?  should NM handle proxy auth or should it be punted
+    to each application?)
+
+After completing IP configuration but still during the NM_DEVICE_STATE_IP_CONFIG
+activation stage, NetworkManager would merge the automatically supplied proxy
+configuration (from DHCP's WPAD option) with user-provided overrides from the
+NMSettingProxy export the resulting proxy configuration via D-Bus and dispatcher
+scripts.  The 'default' connection's proxy configuration would be preferred, so
+we'd have to update proxy configuration from nm-policy.c the same time we update
+DNS information and the default route.
+
+Merged proxy information should be exposed in two places.  First, it should be
+exported over D-Bus as a property of the org.freedesktop.NetworkManager.Device
+interface.  This property should be named "ProxyInfo" and should have the
+D-Bus signature "a{sv}" (eg, dictionary) and should mirror the properties from
+the NMSettingProxy object.
+
+Second, it should be exported via the dispatcher to dispatcher scripts when
+with the "up" and "down" events.
+
+
+* Better Tablet/Mobile Behavior
+
+There are a few components to this:
+
+1) kernel driver and hardware capabilities: most mobile devices use periodic
+background scanning to quickly determine whether a known SSID is available and
+notify the connection manager to connect to it.  This typically requires special
+capabilities and good powersave/sleep support from the WiFi kernel driver.
+There is a background scanning API in nl80211, but we need to determine how many
+SSIDs each driver allows for background scanning, and based on that number, give
+the driver the most recent N SSIDs.  We still need to periodically wake the
+device up and do a full scan just in case the user is near a known SSID that was
+not in the N top recently used networks.  This is also beneficial to normal
+desktop use-cases.
+
+wpa_supplicant doesn't currently provide an explicit interface for sending SSIDs
+to the driver for background scanning, but could simply send a list using
+configured networks.  However, NM currently does not send *all* configured
+connections' SSIDs to the supplicant, so that's something we should do first
+to optimize connection times.  To do this, NM would need to order all networks
+using the NM timestamp and convert that into a supplicant priority number, which
+would need to be adjusted periodically when the timestamp was updated.  This
+would involve tracking each network (exposed by the supplicant as a D-Bus
+object) and making sure they were added, deleted, and updated when the backing
+NMConnection objects changed.  One complication is that the supplicant
+requires secrets for various network types when the network is added via D-Bus,
+and NetworkManager might not have those secrets yet.  We may need to modify
+the supplicant allow for *all* secrets (PSKs, WEP keys, etc) to be requested
+on-demand, not just EAP secrets like 802.1x passwords.  We then need to fix
+up the supplicant's D-Bus interface to actually send requests for secrets out
+over D-Bus (like wpa_supplicant_eap_param_needed() does for the socket-based
+control interface) and to handle the resulting reply from a D-Bus client like
+wpa_supplicant_ctrl_iface_ctrl_rsp() does.
+
+With the secrets request stuff and priority handling in place, wpa_supplicant
+would control network selection and roaming (based on the priorities NM gave it
+of course) instead of NetworkManager itself, and hopefully lead to a faster WiFi
+connection process.
+
+2) single-device-at-a-time with overlapping connections: this is also probably
+the best route to go for desktop use-cases as well.  Instead of bringing all
+available connections up, only bring up the "best" connection at any given
+time based on the current priority list (which is rougly Ethernet > WiFi >
+3G/Bluetooth).  However, to ensure seamless connectivity, when one connection
+begins to degrade, the next-best connection should be started before the
+current one is terminated, such that there is a small amount of overlap.
+Consequently the same behavior should be used when a better connection becomes
+available.  This behavior should be suspended when special connections like
+Internet Connection Sharing ones are started, where clearly the priorities
+are different (ie, for Mobile Hotspot 3G > WiFi).