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 NMDevicePrivate to indicate whether Internet access was successful or not, and advance to the NM_DEVICE_STATE_ACTIVATED state. The NMManager object, when determining the overall NM_STATE_* state in the 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. Note that some devices (airo, ipw2100, ipw2200, iwl3945, iwl4965, atmel, zd1201) will never support AP mode due to firmware limitations, so we clearly must still provide Ad-Hoc connection sharing support for those devices and switch between Ad-Hoc and AP mode depending on device capabilities. * 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 To allow for "pre-down" scenarios, this state should be implemented before a device is taken down while it still has connectivity. If the device is taken down because it's ethernet carrier was dropped, or because the WiFi connection was terminated by the supplicant, this state is pointless and should be skipped. But if the user requested a manual "disconnect", or NM is dropping connections on exit, etc, then this state should be entered. In the future this state should hook into a new dispatcher action in src/NetworkManagerUtils.c to exectue dispatcher scripts during the disconnection, and to wait a limited 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 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. Upon reconnect, if the same Connection is again active, the previously connected VPN should be activated again as well. Basically, don't just drop 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 pseudo-ethernet device to obtain addressing information. This is not currently possible, but NM already has all the code for DHCP. Thus, a new "method" key should be defined in include/NetworkManagerVPN.h to allow for DHCP to be performed if the VPN service daemon requests it in the IP4Config or IP6Config signals. A patch here: http://cgit.freedesktop.org/NetworkManager/NetworkManager/commit/?h=vpn-ip-method 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). * 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. 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 and send the results to the system. 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. The merged proxy configuration would then be sent to the system. There is no canonical proxy daemon in-use, so we should have plugins (if not separate shared libraries, then certainly encapsulated source files that implement a common glib GInterface or are subclasses of eg a parent NMProxyHandler class) that handle different system proxy handlers. Some of the proxy handlers are: libproxy: need to figure out how it gets proxy info and have NM write merged proxy config out to that location pacrunner: a D-Bus enabled daemon, NM would call D-Bus methods of the pacrunner service with the proxy information GNOME/KDE: how do these desktop environments retrieve proxy configuration? * Bridging and Bonding Support The largest complication here is that NetworkManager normally operates on physical interfaces, while bridging and bonding involve tying multiple physical interfaces together into a logical interface. This has interesting implications for the D-Bus API and the NM device model. The first complication is that we may need to do 802.1x port authentication on an interface before it can communicate with the other side of the link, and those credentials may be different for each interface; thus we may need to do separate 802.1x operations on each interface that is part of a bridge/bond before adding each one to the master bridge/bond interface. In this way bridge/bond interfaces may be treated the same way as NetworkManager treats VPN interfaces already; one or more physical interface NMConnections must be activated before the master bridge/bond interface's NMConnection can be activated, though this all happens internally. To enable bridging and bonding in the NMConnection itself, we should create new NMSettingBridge and NMSettingBond classes that contain information specific to each. Both settings would contain a 'components' property with an 'array of string' type which would contain the UUIDs of the Connections of physical interfaces that compose the bridge or bond. Thus NetworkManager would have the necessary information to tie lower-level interface configuration (802.1x, MTU, MAC address locking, duplex mode, speed, etc) to each physical interface that will be part of the bridge/bond, configure the interface with it, and then configure the master bridge/bond interface at upper layers using configuration specific for the bridge/bond interface (like IP details). Thus for a single active bridge, two or more NMConnections would be activated; one for each physical interface component of the bridge/bond, and one for the master bridge/bond interface itself. NMSettingBridge would contain at least the following keys: components: (array of string) UUIDs of component connections stp: (boolean) on to enable STP, off to disable NMSettingBond would contain at least the following keys: components: (array of string) UUIDs of component connections mode: (string) one of "balance-rr", "active-backup", "balance-xor", "broadcast", "802.3ad", "balance-tlb", or "balance-alb" monitor-interval: (uint) Specifies link monitoring interval (in milliseconds); NM will always enable netlink carrier monitoring if this value is non-zero so this property only affects speed and duplex checking In the future we may consider adding other bonding parameters like "up-delay" and "down-delay". Then we'd add a 'component' (boolean) property to NMSettingConnection to indicate that the component interface connections were in fact components of a bridge or bond and shouldn't be automatically started by NetworkManager or displayed as separate connections in the user interface. TO BE CONTINUED