wifi: add on-demand WiFi scan support
[NetworkManager.git] / TODO
1 So you're interested in hacking on NetworkManager?  Here's some cool
2 stuff you could do...
3
4 * Internet Connectivity Detection Enhancements
5
6 Current connectivity checking is global, while what we really want is to check
7 connectivity per-interface and update the global state based on the composite
8 of each device's state.  Unfortunately that requires two things:
9
10 1) latest libsoup and glib for using libsoup connection state signals, which
11    allow us to set socket options before the actual connection is made; here
12    we'd bind the socket to the specific IP address of the interface we're
13    using, and possibly set SO_BINDTODEVICE as well
14 2) setting /proc/sys/net/ipv4/conf/<iface>/rp_filter to "2" which tells the
15    kernel to route the incoming and outgoing packet properly even though the
16    interface may not have the necessary routes
17
18 The first is the largest obstacle, but ideally we implement this and enable it
19 when we have the required glib and libsoup versions available.  One other
20 complication is that this checking should be done during the
21 NM_DEVICE_STATE_IP_CHECK phase (along with other operations like WiFi hotspot
22 auto-login) while the current checks are done globally in nm-manager.c, so 
23 keeping both code paths might be complex.
24
25 But ideally, once the device has successfully gotten an IPv4 or IPv6 address, it
26 should enter the state NM_DEVICE_STATE_IP_CHECK, where a connectivity check is
27 started.  After the check returns, the device would set a property in
28 NMDevicePrivate to indicate whether Internet access was successful or not, and
29 advance to the NM_DEVICE_STATE_ACTIVATED state.
30
31 The NMManager object, when determining the overall NM_STATE_* state in the
32 nm_manager_update_state() function, would query this property and set
33 NM_STATE_CONNECTED_LOCAL, NM_STATE_CONNECTED_SITE, or NM_STATE_CONNECTED_GLOBAL
34 based on it and the device's state.
35
36
37 * Real Access Point mode support
38
39 Now that NetworkManager requires wpa_supplicant 0.7.x or later, we can add
40 full Access Point (AP) mode support.  NetworkManager currently implements
41 connection sharing via AdHoc mode support, which has some limitations.  Instead,
42 we should check whether the wifi device supports AP mode, and if so, use
43 that mode instead.  wpa_supplicant has support for a "lightweight AP" mode which
44 we should use.  Witold Sowa started this support a while ago and wrote the new
45 D-Bus API for wpa_supplicant that makes all this possible, but some NM pieces
46 are still missing.  If the wifi driver supports AP mode, then in
47 src/supplicant-manager/ NM should send an AP-mode config instead of sending
48 the adhoc config.
49
50 Note that some devices (airo, ipw2100, ipw2200, iwl3945, iwl4965, atmel, zd1201)
51 will never support AP mode due to firmware limitations, so we clearly must still
52 provide Ad-Hoc connection sharing support for those devices and switch between
53 Ad-Hoc and AP mode depending on device capabilities.
54
55
56 * Reconnect to WiFi Networks Only If They Succeeded Once
57
58 Currently, NetworkManager will attempt to connect to a previously attempted
59 WiFi network even if that network was never successfully connected to.  This
60 causes confusion because sometimes users will randomly try various WiFi networks
61 hoping to find an open AP, and then wonder why NM tries to reconnect to any of
62 those APs later when none of them worked originally due to AP-side MAC filtering
63 or other failures.  What should happen is that NetworkManager should set a flag
64 on a connection when that connection is successfully connected at least once,
65 and only autoconnect the wifi network if that flag is present *and* the
66 NMSettingConnection's 'autoconnect' property is TRUE.
67
68 This is a bit tricky because we want to consider all connections that don't have
69 this flag as having succeeded so that we don't break users' existing connections,
70 while holding all newly created connections to this policy.  This flag should
71 be determined and set for all connections, even if we only use it to determine
72 WiFi behavior for now.
73
74 This flag should be a new gboolean property on the NMSettingConnection object
75 called "connect-success", with a default value of TRUE.  It should default to
76 TRUE to ensure that existing connections are assumed to have connected
77 successfully in the past.  New connections created via the AddConnection and
78 AddAndActivateConnection D-Bus method calls should have the 'connect-success'
79 property explicitly set to FALSE.  Then, in nm-device.c's device_state_changed()
80 function where the NM_DEVICE_STATE_ACTIVATED state is handled, the
81 'connect-success' property should be set to TRUE.
82
83 For WiFi then, in nm-device-wifi.c's get_best_auto_connection() method, the
84 'connect-success' property should be checked and if it is FALSE, the connection
85 is not considered for auto-activation.
86
87
88 * Implement NM_DEVICE_STATE_DISCONNECTING
89
90 To allow for "pre-down" scenarios, this state should be implemented before a
91 device is taken down while it still has connectivity.  If the device is
92 taken down because it's ethernet carrier was dropped, or because the WiFi
93 connection was terminated by the supplicant, this state is pointless and should
94 be skipped.  But if the user requested a manual "disconnect", or NM is dropping
95 connections on exit, etc, then this state should be entered.  In the future
96 this state should hook into a new dispatcher action in src/NetworkManagerUtils.c
97 to exectue dispatcher scripts during the disconnection, and to wait a limited
98 amount of time for each script to complete before allowing the device to
99 proceed to the NM_DEVICE_STATE_DISCONNECTED state, fully implementing pre-down.
100
101
102 * Ethernet Network Auto-detection
103
104 There are various methods we can use to autodetect which wired network connection
105 to use if the user connects to more than one wired network on a frequent basis.
106 First, 802.1x enterprise switches broadcast frames which can be used to indicate
107 that the switch supports 802.1x and thus allow NetworkManager to select an
108 802.1x connection instead of blindly trying DHCP.  Second, NetworkManager could
109 listen for traffic from a list of MAC addresses.  Third, NetworkManager could
110 integrate 'arping' functionality to determine if a given IP address matches a
111 given MAC address, and thus automatically select that connection.  All these
112 methods can co-exist and be used in parallel.
113
114 One small caveat is that MAC addresses are trivial to spoof, so just because
115 NetworkManager has discovered a certain MAC address does not mean the network
116 is authenticated; only 802.1x security can assure that a network is the network
117 the user expects it to be.
118
119 In any case, a new 'anchor-addresses' property of type string-array should be
120 added to the NMSettingWired setting.  Each string element of this property
121 should be of the format "<ip>/<mac>" or simply "<mac>".  The first format with
122 an IP address would indicate that "arping"-type behavior should be used to
123 actively detect the given MAC address; obviously if the given MAC address is
124 used for passive discovery as well.  The second format simply lists a MAC
125 address to passively listen for.
126
127 One drawback of listening or probing for known MAC addresses is an increase in
128 latency during connections to ethernet networks.  The probing/listening delay
129 should be a reasonable amount of time, like 4 - 5 seconds or so, and should
130 only be used when a visible connection has anchor addresses.
131
132 Next a gboolean 'anchor-probing' variable should be added to the
133 NMDeviceEthernetPrivate structure in src/nm-device-ethernet.c.  This variable
134 should be set to TRUE whenever the device's carrier turns on *and* there are
135 visible NMConnections with anchor addresses (ie, connections which are system-
136 wide or where one of the allowed users of that connection is logged in).  Then
137 probing and listening are started, which involves opening a low-level socket
138 on the interface and starting the arping run or listening for MAC addresses.
139 A timer is also started (don't forget to cache the timer's source ID in the
140 NMDeviceEthernetPrivate data, and to cancel the timer whenever the device
141 transitions to any state other than DISCONNECTED).
142
143 If a known MAC address is discovered as a result of probing or listening, the
144 probe/listen socket, timeout, and data are cleaned up, and NetworkManager
145 would begin activation of the NMConnection that specified the found MAC address
146 in the 'anchor-addresses' property.  If two or more connections specify the
147 same MAC address, the connection with the most recent timestamp should be
148 preferred.
149
150 Similarly, if the probing/listening process detects 802.1x frames the device
151 should be marked as requring 802.1x authentication until the carrier drops.
152 This would be accomplished by adding a new property to the NMDeviceEthernet
153 object and exporting that property through the
154 introspection/nm-device-ethernet.xml file.  This would allow clients like
155 applets to ensure that users are aware that the device will not allow
156 un-authenticated connections and that additional credentials are required to
157 successfully connect to this network.
158
159
160 * VPN re-connect
161
162 NM should remember whether a VPN was connected if a connection disconnects
163 (like WiFi drops out or short carrier drop) or if the laptop goes to sleep.
164 Upon reconnect, if the same Connection is again active, the previously
165 connected VPN should be activated again as well.  Basically, don't just drop
166 the VPN because WiFi choked for 10 seconds, but reconnect the VPN if it was
167 connected before the drop.
168
169
170 * VPN autoconnect
171
172 We should add a property to the NMSettingConnection object in
173 libnm-util/nm-setting-connection.c called "vpns" that is a string list,
174 containing a list of Connection UUIDs that should be activated when the base
175 connection itself is activated.  This will allow a VPN connection to be
176 started every time another connection is started, so that if you choose you're
177 always on the VPN in your favorite coffee shop.
178
179 The NM_DEVICE_STATE_SECONDARIES state was added specifically for cases like
180 this.  Thus, after the base device has IP connectivity, but before it has
181 signaled that it's fully activated, the device should enter the SECONDARIES
182 state and kick off activation of the given VPN connection.  Only after this
183 VPN connection has successfully connected should the base device to the
184 NM_DEVICE_STATE_ACTIVATED state.
185
186
187 * VPN and IPv6
188
189 The internal VPN capability should support IPv6.  Essentially, the D-Bus
190 interface between NetworkManager and the VPN service daemons should be extended
191 with an IP6Config signal that passes up the IPv6 addressing and routing details
192 if the VPN daemon is IPv6 capable.  NM should then process those details like it
193 does with IPv4.  include/NetworkManagerVPN.h should be updated with key/value
194 pairs defining the various IPv6 attributes much like the IPv4 ones are defined.
195
196
197 * VPN IP Methods
198
199 Some VPNs (openvpn with TAP for example) require that DHCP is run on a
200 pseudo-ethernet device to obtain addressing information.  This is not currently
201 possible, but NM already has all the code for DHCP.  Thus, a new "method"
202 key should be defined in include/NetworkManagerVPN.h to allow for DHCP to
203 be performed if the VPN service daemon requests it in the IP4Config or IP6Config
204 signals.  A patch here:
205
206 http://cgit.freedesktop.org/NetworkManager/NetworkManager/commit/?h=vpn-ip-method
207
208 shows that.  In nm-vpn-connection.c, upon receipt of the D-Bus Ip4Config signal
209 from the VPN plugin, NetworkManager would inspect the "method" property of the
210 ip4 config dictionary.  If that property was present and set to "auto" then
211 DHCP would be started using the network interface returned in the dict.  The
212 nm_vpn_connection_ip4_config_get() function should be split up into two
213 functions, one containing the existing code for static configuration, and a
214 second for handling DHCP kickoff.  Minimal parsing of the response should be
215 handled in the newly reduced nm_vpn_connection_ip4_config_get() function.
216
217 To handle DHCP, the NMVPNConnectionPrivate structure should have two members
218 added:
219
220     NMDHCPManager *dhcp_manager;
221     NMDHCPClient  *dhcp4_client;
222
223 which would be initialized in the new DHCP handler code split off from
224 nm_vpn_connection_ip4_config_get().  These new members would be disposed of in
225 both vpn_cleanup() and dispose(), though remember to stop any ongoing DHCP
226 transaction when doing so (see dhcp4_cleanup() in nm-device.c for example code).
227 For basic code to start the DHCP transaction, see dhcp4_start() in nm-device.c
228 as well.  After calling nm_dhcp_manager_start_ip4() and connecting the signals
229 to monitor success and failure, the VPN IP4 config handler would simply return
230 without changing VPN state, unless a failure occurred.
231
232 Then, when the DHCP transaction succeeds, which we'd know by checking the
233 DHCP client state changes in the "state-changed" signal handler we attached to
234 the DHCP client object returned from nm_dhcp_manager_start_ip4(), the code
235 would retrieve the completed NMIP4Config object from the DHCP client using the
236 nm_dhcp_client_get_ip4_config() function, and then proceed to execute
237 essentially the bottom-half of the existing nm_vpn_connection_ip4_config_get()
238 function to merge that config with user overrides and apply it to the VPN
239 tunnel interface.  Other state changes from the DHCP client might trigger a
240 failure of the VPN connection, just like DHCP timeouts and lease-renewal
241 failures do for other devices (see dhcp_state_changed() in nm-device.c).
242
243
244 * VPN Service Daemon Secret Requests
245
246 In addition to NM asking the service daemons whether more secrets are required,
247 VPN service daemons (like nm-vpnc-service, nm-openvpn-service, etc) should be
248 able to ask NetworkManager to provide secrets during the connection attempt. To
249 do this, the plugin should advertise its ability to handle out-of-band secrets
250 in its .service file via the key 'async-secrets=true'.  NetworkManager would
251 check that key and if present activate the VPN as normal, but skip the explicit
252 NeedSecrets calls.
253
254 Instead, a new "SecretsRequired" signal would be added to
255 introspection/nm-vpn-plugin.xml (and corresponding helper code added to
256 libnm-glib/nm-vpn-plugin.c) that would be emitted when the plugin determined
257 that secrets were required.  This signal would have D-Bus signature of "sas"
258 for the arguments [ <s:uuid>, <as:secrets> ] with the <uuid> obviously being
259 the connection UUID, and <secrets> being an array of strings of plugin-specific
260 strings the plugin requires secrets for.  This array of strings would then be
261 passed as the "hints" parameter in nm-vpn-connection.c when secrets are
262 requested from agents in a subsequent nm_settings_connection_get_secrets() call.
263 At this time the agent code only allows one hint per request, so we may need to
264 extend that to allow more than one hint.
265
266 Thus when connecting if the plugin supported async secrets NetworkManager would
267 still request existing secrets (without interactivity) and send them to the
268 VPN service daemon in the Connect D-Bus method, then wait for the service daemon
269 to either request secrets asynchronously via the SecretsRequired signal or to
270 signal successful connection via the Ip4Config signal.
271
272 The vpnc plugin would need to be reworked to open a pipe to vpnc's stdout and
273 stdin file descriptors to capture any authentication messages, and to match
274 these messages to known secrets request strings.  When receiving one of these
275 strings the plugin would determine which secret was being requested and then
276 emit the SecretsRequired signal to NetworkManager.  This would also imply that
277 nm-vpnc-service exectutes vpnc with the "--xauth-inter" argument to enable
278 challenge-response and does not use the "--non-inter" flag which suppresses that
279 behavior.
280
281
282 * WPS
283
284 wpa_supplicant has support for WPS (Wifi Protected Setup, basically Bluetooth-
285 like PIN codes for setting up a wifi connection) and we should add support for
286 this to NetworkManager too.  APs that support WPS will say so in their beacon
287 IEs which are contained in the "WPA" and "RSN" properties of the BSS object
288 exported by the supplicant, and can be processed in src/nm-wifi-ap.c's
289 foreach_property_cb() function.  We should add some private fields to the
290 NMAccessPoint object (defined in nm-wifi-ap.c) to remember whether a specific
291 AP supports WPS and what WPS methods it supports, and expose that over D-Bus to
292 GUI clients as well.
293
294 There are two common WPS setup methods: PIN and button.  For PIN, the router
295 either displays a random PIN on an LCD or the router's web UI, or a static PIN
296 is printed on the router itself.  The user enters that PIN instead of a PSK
297 when connecting.  For the "button" method, the router has a physical button that
298 when pushed, allows any client to connect for a short period of time.
299
300 We'll then need to add some properties to the NMSettingWirelessSecurity setting
301 for the WPS PIN code so that when the user enters it through the GUI, it can
302 be passed back to NM.  And we'll need to figure out some mechanism for passing
303 back an indication that the user pushed the button on the router for the
304 pushbutton method.
305
306 When connecting to a new access point that supports WPS, the GUI client would
307 call the AddAndActivateConnection method and wait for NM to request secrets.
308 NM would determine that the AP supports WPS, and request WPS secrets from the
309 applet.  The applet would ask the user for a PIN, or to push the button on the
310 AP, instead of asking for a passphrase or PSK.  When the user has entered the
311 PIN or pushed the button, the applet returns this information to NM, which
312 proceeds with the connection.
313
314 NM sends the correct wpa_supplicant config for WPS to the supplicant, and waits
315 for the connection to occur.  WPS can only be used the *first* time, so after a
316 first successfull connection, NM must request the actual hexadecimal PSK from 
317 wpa_supplicant via D-Bus, and store that PSK in the connection, clear any WPS
318 PIN code from the connection, and save the connection to backing storage.
319
320 Any applet GUI should also allow the user to enter the PSK instead of completing
321 association using WPS, since quite a few routers out there are broken, or
322 because the user has no physical access to the router itself, but has been given
323 as passphrase/PSK instead.
324
325
326 * Proxies
327
328 HTTP and other proxies are per-connection configuration.  It's highly unlikely
329 that the same proxy you need to use at work is used at home or in a coffee shop.
330 Thus, it makes sense that which proxy settings to use should be updated when
331 network connections change.  NetworkManager is a perfect place to do this since
332 it tracks which network connections are active, and it already queries the
333 network for automatic proxy configuration via DHCP and WPAD.
334
335 We should add a new NMSetting subclass called NMSettingProxy that holds
336 necessary proxy configuration.  The properties of this setting should be a
337 superset of what is provided in the Firefox proxy configuration screen and the
338 various desktop environment proxy configuration tools like the GNOME Network
339 Proxy control panel; this should include at a minimum:
340
341   method: "auto", "manual", "none"
342   default-proxy: string
343   default-proxy-port: uint
344   default-always: boolean (use default proxy for all protocols)
345   ssl-proxy: string
346   ssl-proxy-port: uint
347   ftp-proxy: string
348   ftp-proxy-port: uint
349   socks-proxy: string
350   socks-proxy-port: uint
351   socks-version: uint, either 4 or 5
352   no-proxy-for: array of strings (things not to use the proxy for, ie ".foobar.com",
353                  "192.168.0.1/24", an IPv6 address, etc)
354   pac-url: string (URL of PAC file, overrides DHCP-provided WPAD value)
355   (FIXME: proxy authentication?  do we need separate user/pass properties for
356     each protocol type?  should NM handle proxy auth or should it be punted
357     to each application?)
358
359 After completing IP configuration but still during the NM_DEVICE_STATE_IP_CONFIG
360 activation stage, NetworkManager would merge the automatically supplied proxy
361 configuration (from DHCP's WPAD option) with user-provided overrides from the
362 NMSettingProxy and send the results to the system.  The 'default' connection's
363 proxy configuration would be preferred, so we'd have to update proxy
364 configuration from nm-policy.c the same time we update DNS information and the
365 default route.
366
367 The merged proxy configuration would then be sent to the system.  There is no
368 canonical proxy daemon in-use, so we should have plugins (if not separate
369 shared libraries, then certainly encapsulated source files that implement a
370 common glib GInterface or are subclasses of eg a parent NMProxyHandler class)
371 that handle different system proxy handlers.  Some of the proxy handlers are:
372
373   libproxy: need to figure out how it gets proxy info and have NM write merged
374              proxy config out to that location
375   pacrunner: a D-Bus enabled daemon, NM would call D-Bus methods of the
376                pacrunner service with the proxy information
377   GNOME/KDE: how do these desktop environments retrieve proxy configuration?
378
379
380 * Better Tablet/Mobile Behavior
381
382 There are a few components to this:
383
384 1) kernel driver and hardware capabilities: most mobile devices use periodic
385 background scanning to quickly determine whether a known SSID is available and
386 notify the connection manager to connect to it.  This typically requires special
387 capabilities and good powersave/sleep support from the WiFi kernel driver.
388 There is a background scanning API in nl80211, but we need to determine how many
389 SSIDs each driver allows for background scanning, and based on that number, give
390 the driver the most recent N SSIDs.  We still need to periodically wake the
391 device up and do a full scan just in case the user is near a known SSID that was
392 not in the N top recently used networks.  This is also beneficial to normal
393 desktop use-cases.
394
395 wpa_supplicant doesn't currently provide an explicit interface for sending SSIDs
396 to the driver for background scanning, but could simply send a list using
397 configured networks.  However, NM currently does not send *all* configured
398 connections' SSIDs to the supplicant, so that's something we should do first
399 to optimize connection times.  To do this, NM would need to order all networks
400 using the NM timestamp and convert that into a supplicant priority number, which
401 would need to be adjusted periodically when the timestamp was updated.  This
402 would involve tracking each network (exposed by the supplicant as a D-Bus
403 object) and making sure they were added, deleted, and updated when the backing
404 NMConnection objects changed.  One complication is that the supplicant
405 requires secrets for various network types when the network is added via D-Bus,
406 and NetworkManager might not have those secrets yet.  We may need to modify
407 the supplicant allow for *all* secrets (PSKs, WEP keys, etc) to be requested
408 on-demand, not just EAP secrets like 802.1x passwords.  We then need to fix
409 up the supplicant's D-Bus interface to actually send requests for secrets out
410 over D-Bus (like wpa_supplicant_eap_param_needed() does for the socket-based
411 control interface) and to handle the resulting reply from a D-Bus client like
412 wpa_supplicant_ctrl_iface_ctrl_rsp() does.
413
414 With the secrets request stuff and priority handling in place, wpa_supplicant
415 would control network selection and roaming (based on the priorities NM gave it
416 of course) instead of NetworkManager itself, and hopefully lead to a faster WiFi
417 connection process.
418
419 2) single-device-at-a-time with overlapping connections: this is also probably
420 the best route to go for desktop use-cases as well.  Instead of bringing all
421 available connections up, only bring up the "best" connection at any given
422 time based on the current priority list (which is rougly Ethernet > WiFi >
423 3G/Bluetooth/WiMAX).  However, to ensure seamless connectivity, when one
424 connection begins to degrade, the next-best connection should be started before
425 the current one is terminated, such that there is a small amount of overlap.
426 Consequently the same behavior should be used when a better connection becomes
427 available.  This behavior should be suspended when special connections like
428 Internet Connection Sharing ones are started, where clearly the priorities
429 are different (ie, for Mobile Hotspot 3G > WiFi).