TODO 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. So you're interested in hacking on NetworkManager? Here's some cool
  2. stuff you could do...
  3. * Internet Connectivity Detection Enhancements
  4. Current connectivity checking is global, while what we really want is to check
  5. connectivity per-interface and update the global state based on the composite
  6. of each device's state. Unfortunately that requires two things:
  7. 1) latest libsoup and glib for using libsoup connection state signals, which
  8. allow us to set socket options before the actual connection is made; here
  9. we'd bind the socket to the specific IP address of the interface we're
  10. using, and possibly set SO_BINDTODEVICE as well
  11. 2) setting /proc/sys/net/ipv4/conf/<iface>/rp_filter to "2" which tells the
  12. kernel to route the incoming and outgoing packet properly even though the
  13. interface may not have the necessary routes
  14. The first is the largest obstacle, but ideally we implement this and enable it
  15. when we have the required glib and libsoup versions available. One other
  16. complication is that this checking should be done during the
  17. NM_DEVICE_STATE_IP_CHECK phase (along with other operations like WiFi hotspot
  18. auto-login) while the current checks are done globally in nm-manager.c, so
  19. keeping both code paths might be complex.
  20. But ideally, once the device has successfully gotten an IPv4 or IPv6 address, it
  21. should enter the state NM_DEVICE_STATE_IP_CHECK, where a connectivity check is
  22. started. After the check returns, the device would set a property in
  23. NMDevicePrivate to indicate whether Internet access was successful or not, and
  24. advance to the NM_DEVICE_STATE_ACTIVATED state.
  25. The NMManager object, when determining the overall NM_STATE_* state in the
  26. nm_manager_update_state() function, would query this property and set
  27. NM_STATE_CONNECTED_LOCAL, NM_STATE_CONNECTED_SITE, or NM_STATE_CONNECTED_GLOBAL
  28. based on it and the device's state.
  29. * Implement NM_DEVICE_STATE_DISCONNECTING
  30. To allow for "pre-down" scenarios, this state should be implemented before a
  31. device is taken down while it still has connectivity. If the device is
  32. taken down because its ethernet carrier was dropped, or because the WiFi
  33. connection was terminated by the supplicant, this state is pointless and should
  34. be skipped. But if the user requested a manual "disconnect", or NM is dropping
  35. connections on exit, etc, then this state should be entered. In the future
  36. this state should hook into a new dispatcher action in src/NetworkManagerUtils.c
  37. to exectue dispatcher scripts during the disconnection, and to wait a limited
  38. amount of time for each script to complete before allowing the device to
  39. proceed to the NM_DEVICE_STATE_DISCONNECTED state, fully implementing pre-down.
  40. * Ethernet Network Auto-detection
  41. There are various methods we can use to autodetect which wired network connection
  42. to use if the user connects to more than one wired network on a frequent basis.
  43. First, 802.1x enterprise switches broadcast frames which can be used to indicate
  44. that the switch supports 802.1x and thus allow NetworkManager to select an
  45. 802.1x connection instead of blindly trying DHCP. Second, NetworkManager could
  46. listen for traffic from a list of MAC addresses. Third, NetworkManager could
  47. integrate 'arping' functionality to determine if a given IP address matches a
  48. given MAC address, and thus automatically select that connection. All these
  49. methods can co-exist and be used in parallel.
  50. One small caveat is that MAC addresses are trivial to spoof, so just because
  51. NetworkManager has discovered a certain MAC address does not mean the network
  52. is authenticated; only 802.1x security can assure that a network is the network
  53. the user expects it to be.
  54. In any case, a new 'anchor-addresses' property of type string-array should be
  55. added to the NMSettingWired setting. Each string element of this property
  56. should be of the format "<ip>/<mac>" or simply "<mac>". The first format with
  57. an IP address would indicate that "arping"-type behavior should be used to
  58. actively detect the given MAC address; obviously if the given MAC address is
  59. used for passive discovery as well. The second format simply lists a MAC
  60. address to passively listen for.
  61. One drawback of listening or probing for known MAC addresses is an increase in
  62. latency during connections to ethernet networks. The probing/listening delay
  63. should be a reasonable amount of time, like 4 - 5 seconds or so, and should
  64. only be used when a visible connection has anchor addresses.
  65. Next a gboolean 'anchor-probing' variable should be added to the
  66. NMDeviceEthernetPrivate structure in src/nm-device-ethernet.c. This variable
  67. should be set to TRUE whenever the device's carrier turns on *and* there are
  68. visible NMConnections with anchor addresses (ie, connections which are system-
  69. wide or where one of the allowed users of that connection is logged in). Then
  70. probing and listening are started, which involves opening a low-level socket
  71. on the interface and starting the arping run or listening for MAC addresses.
  72. A timer is also started (don't forget to cache the timer's source ID in the
  73. NMDeviceEthernetPrivate data, and to cancel the timer whenever the device
  74. transitions to any state other than DISCONNECTED).
  75. If a known MAC address is discovered as a result of probing or listening, the
  76. probe/listen socket, timeout, and data are cleaned up, and NetworkManager
  77. would begin activation of the NMConnection that specified the found MAC address
  78. in the 'anchor-addresses' property. If two or more connections specify the
  79. same MAC address, the connection with the most recent timestamp should be
  80. preferred.
  81. Similarly, if the probing/listening process detects 802.1x frames the device
  82. should be marked as requiring 802.1x authentication until the carrier drops.
  83. This would be accomplished by adding a new property to the NMDeviceEthernet
  84. object and exporting that property through the
  85. introspection/nm-device-ethernet.xml file. This would allow clients like
  86. applets to ensure that users are aware that the device will not allow
  87. un-authenticated connections and that additional credentials are required to
  88. successfully connect to this network.
  89. * VPN re-connect (bgo #349151)
  90. NM should remember whether a VPN was connected if a connection disconnects
  91. (like WiFi drops out or short carrier drop) or if the laptop goes to sleep.
  92. Upon reconnect, if the same Connection is again active, the previously
  93. connected VPN should be activated again as well. Basically, don't just drop
  94. the VPN because WiFi choked for 10 seconds, but reconnect the VPN if it was
  95. connected before the drop.
  96. * VPN IP Methods
  97. Some VPNs (openvpn with TAP for example) require that DHCP is run on a
  98. pseudo-ethernet device to obtain addressing information. This is not currently
  99. possible, but NM already has all the code for DHCP. Thus, a new "method"
  100. key should be defined in include/NetworkManagerVPN.h to allow for DHCP to
  101. be performed if the VPN service daemon requests it in the IP4Config or IP6Config
  102. signals. In nm-vpn-connection.c, upon receipt of the D-Bus Ip4Config signal
  103. from the VPN plugin, NetworkManager would inspect the "method" property of the
  104. ip4 config dictionary. If that property was present and set to "auto" then
  105. DHCP would be started using the network interface returned in the dict. The
  106. nm_vpn_connection_ip4_config_get() function should be split up into two
  107. functions, one containing the existing code for static configuration, and a
  108. second for handling DHCP kickoff. Minimal parsing of the response should be
  109. handled in the newly reduced nm_vpn_connection_ip4_config_get() function.
  110. To handle DHCP, the NMVPNConnectionPrivate structure should have two members
  111. added:
  112. NMDHCPManager *dhcp_manager;
  113. NMDHCPClient *dhcp4_client;
  114. which would be initialized in the new DHCP handler code split off from
  115. nm_vpn_connection_ip4_config_get(). These new members would be disposed of in
  116. both vpn_cleanup() and dispose(), though remember to stop any ongoing DHCP
  117. transaction when doing so (see dhcp4_cleanup() in nm-device.c for example code).
  118. For basic code to start the DHCP transaction, see dhcp4_start() in nm-device.c
  119. as well. After calling nm_dhcp_manager_start_ip4() and connecting the signals
  120. to monitor success and failure, the VPN IP4 config handler would simply return
  121. without changing VPN state, unless a failure occurred.
  122. Then, when the DHCP transaction succeeds, which we'd know by checking the
  123. DHCP client state changes in the "state-changed" signal handler we attached to
  124. the DHCP client object returned from nm_dhcp_manager_start_ip4(), the code
  125. would retrieve the completed NMIP4Config object from the DHCP client using the
  126. nm_dhcp_client_get_ip4_config() function, and then proceed to execute
  127. essentially the bottom-half of the existing nm_vpn_connection_ip4_config_get()
  128. function to merge that config with user overrides and apply it to the VPN
  129. tunnel interface. Other state changes from the DHCP client might trigger a
  130. failure of the VPN connection, just like DHCP timeouts and lease-renewal
  131. failures do for other devices (see dhcp_state_changed() in nm-device.c).
  132. * VPN Service Daemon Secret Requests
  133. In addition to NM asking the service daemons whether more secrets are required,
  134. VPN service daemons (like nm-vpnc-service, nm-openvpn-service, etc) should be
  135. able to ask NetworkManager to provide secrets during the connection attempt. To
  136. do this, the plugin should advertise its ability to handle out-of-band secrets
  137. in its .service file via the key 'async-secrets=true'. NetworkManager would
  138. check that key and if present activate the VPN as normal, but skip the explicit
  139. NeedSecrets calls.
  140. Instead, a new "SecretsRequired" signal would be added to
  141. introspection/nm-vpn-plugin.xml (and corresponding helper code added to
  142. libnm-glib/nm-vpn-plugin.c) that would be emitted when the plugin determined
  143. that secrets were required. This signal would have D-Bus signature of "sas"
  144. for the arguments [ <s:uuid>, <as:secrets> ] with the <uuid> obviously being
  145. the connection UUID, and <secrets> being an array of strings of plugin-specific
  146. strings the plugin requires secrets for. This array of strings would then be
  147. passed as the "hints" parameter in nm-vpn-connection.c when secrets are
  148. requested from agents in a subsequent nm_settings_connection_get_secrets() call.
  149. At this time the agent code only allows one hint per request, so we may need to
  150. extend that to allow more than one hint.
  151. Thus when connecting if the plugin supported async secrets NetworkManager would
  152. still request existing secrets (without interactivity) and send them to the
  153. VPN service daemon in the Connect D-Bus method, then wait for the service daemon
  154. to either request secrets asynchronously via the SecretsRequired signal or to
  155. signal successful connection via the Ip4Config signal.
  156. The vpnc plugin would need to be reworked to open a pipe to vpnc's stdout and
  157. stdin file descriptors to capture any authentication messages, and to match
  158. these messages to known secrets request strings. When receiving one of these
  159. strings the plugin would determine which secret was being requested and then
  160. emit the SecretsRequired signal to NetworkManager. This would also imply that
  161. nm-vpnc-service exectutes vpnc with the "--xauth-inter" argument to enable
  162. challenge-response and does not use the "--non-inter" flag which suppresses that
  163. behavior.
  164. * WPS
  165. wpa_supplicant has support for WPS (Wifi Protected Setup, basically Bluetooth-
  166. like PIN codes for setting up a wifi connection) and we should add support for
  167. this to NetworkManager too. APs that support WPS will say so in their beacon
  168. IEs which are contained in the "WPA" and "RSN" properties of the BSS object
  169. exported by the supplicant, and can be processed in src/nm-wifi-ap.c's
  170. foreach_property_cb() function. We should add some private fields to the
  171. NMAccessPoint object (defined in nm-wifi-ap.c) to remember whether a specific
  172. AP supports WPS and what WPS methods it supports, and expose that over D-Bus to
  173. GUI clients as well.
  174. There are two common WPS setup methods: PIN and button. For PIN, the router
  175. either displays a random PIN on an LCD or the router's web UI, or a static PIN
  176. is printed on the router itself. The user enters that PIN instead of a PSK
  177. when connecting. For the "button" method, the router has a physical button that
  178. when pushed, allows any client to connect for a short period of time.
  179. We'll then need to add some properties to the NMSettingWirelessSecurity setting
  180. for the WPS PIN code so that when the user enters it through the GUI, it can
  181. be passed back to NM. And we'll need to figure out some mechanism for passing
  182. back an indication that the user pushed the button on the router for the
  183. pushbutton method.
  184. When connecting to a new access point that supports WPS, the GUI client would
  185. call the AddAndActivateConnection method and wait for NM to request secrets.
  186. NM would determine that the AP supports WPS, and request WPS secrets from the
  187. applet. The applet would ask the user for a PIN, or to push the button on the
  188. AP, instead of asking for a passphrase or PSK. When the user has entered the
  189. PIN or pushed the button, the applet returns this information to NM, which
  190. proceeds with the connection.
  191. NM sends the correct wpa_supplicant config for WPS to the supplicant, and waits
  192. for the connection to occur. WPS can only be used the *first* time, so after a
  193. first successful connection, NM must request the actual hexadecimal PSK from
  194. wpa_supplicant via D-Bus, and store that PSK in the connection, clear any WPS
  195. PIN code from the connection, and save the connection to backing storage.
  196. Any applet GUI should also allow the user to enter the PSK instead of completing
  197. association using WPS, since quite a few routers out there are broken, or
  198. because the user has no physical access to the router itself, but has been given
  199. as passphrase/PSK instead.
  200. * Better Tablet/Mobile Behavior
  201. There are a few components to this:
  202. 1) kernel driver and hardware capabilities: most mobile devices use periodic
  203. background scanning to quickly determine whether a known SSID is available and
  204. notify the connection manager to connect to it. This typically requires special
  205. capabilities and good powersave/sleep support from the WiFi kernel driver.
  206. There is a background scanning API in nl80211, but we need to determine how many
  207. SSIDs each driver allows for background scanning, and based on that number, give
  208. the driver the most recent N SSIDs. We still need to periodically wake the
  209. device up and do a full scan just in case the user is near a known SSID that was
  210. not in the N top recently used networks. This is also beneficial to normal
  211. desktop use-cases.
  212. wpa_supplicant doesn't currently provide an explicit interface for sending SSIDs
  213. to the driver for background scanning, but could simply send a list using
  214. configured networks. However, NM currently does not send *all* configured
  215. connections' SSIDs to the supplicant, so that's something we should do first
  216. to optimize connection times. To do this, NM would need to order all networks
  217. using the NM timestamp and convert that into a supplicant priority number, which
  218. would need to be adjusted periodically when the timestamp was updated. This
  219. would involve tracking each network (exposed by the supplicant as a D-Bus
  220. object) and making sure they were added, deleted, and updated when the backing
  221. NMConnection objects changed. One complication is that the supplicant
  222. requires secrets for various network types when the network is added via D-Bus,
  223. and NetworkManager might not have those secrets yet. We may need to modify
  224. the supplicant allow for *all* secrets (PSKs, WEP keys, etc) to be requested
  225. on-demand, not just EAP secrets like 802.1x passwords. We then need to fix
  226. up the supplicant's D-Bus interface to actually send requests for secrets out
  227. over D-Bus (like wpa_supplicant_eap_param_needed() does for the socket-based
  228. control interface) and to handle the resulting reply from a D-Bus client like
  229. wpa_supplicant_ctrl_iface_ctrl_rsp() does.
  230. With the secrets request stuff and priority handling in place, wpa_supplicant
  231. would control network selection and roaming (based on the priorities NM gave it
  232. of course) instead of NetworkManager itself, and hopefully lead to a faster WiFi
  233. connection process.
  234. 2) single-device-at-a-time with overlapping connections: this is also probably
  235. the best route to go for desktop use-cases as well. Instead of bringing all
  236. available connections up, only bring up the "best" connection at any given
  237. time based on the current priority list (which is roughly Ethernet > WiFi >
  238. 3G/Bluetooth). However, to ensure seamless connectivity, when one connection
  239. begins to degrade, the next-best connection should be started before the
  240. current one is terminated, such that there is a small amount of overlap.
  241. Consequently the same behavior should be used when a better connection becomes
  242. available. This behavior should be suspended when special connections like
  243. Internet Connection Sharing ones are started, where clearly the priorities
  244. are different (ie, for Mobile Hotspot 3G > WiFi).