Created
December 17, 2012 10:18
-
-
Save Ummon/4317268 to your computer and use it in GitHub Desktop.
To control the Network Manager on Ubuntu with DBUS and C#/Mono. D-BUS documentation: * The D-BUS Network Manager: http://projects.gnome.org/NetworkManager/developers/api/09/spec.html#org.freedesktop.NetworkManager.Settings.Connection * The D-BUS C# free library: https://github.com/mono/dbus-sharp and http://www.ndesk.org/DBus_Documentation * D-B…
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Diagnostics; | |
using System.Linq; | |
using System.Net; | |
using DBus; | |
namespace IPChangerPrototype | |
{ | |
public enum Method | |
{ | |
Manual, | |
Auto, | |
AutoAddressesOnly, | |
} | |
/// <summary> | |
/// IP address extension. | |
/// Some useful methods to convert IP address to integer or to netmask. | |
/// All computations are using the little endian ordering. | |
/// </summary> | |
static class IPAddressExtension | |
{ | |
public static uint ToUint(this IPAddress ip) | |
{ | |
return (uint)ip.GetAddressBytes()[0] | (uint)ip.GetAddressBytes()[1] << 8 | (uint)ip.GetAddressBytes()[2] << 16 | (uint)ip.GetAddressBytes()[3] << 24; // Little endian. | |
} | |
static readonly uint[] mod37BitPosition = | |
{ | |
32, 0, 1, 26, 2, 23, 27, 0, 3, 16, 24, 30, 28, 11, 0, 13, 4, | |
7, 17, 0, 25, 22, 31, 15, 29, 10, 12, 6, 0, 21, 14, 9, 5, | |
20, 8, 19, 18 | |
}; | |
/// <summary> | |
/// The computation method of the number of trailing zero came from http://graphics.stanford.edu/~seander/bithacks.html#ZerosOnRightModLookup | |
/// </summary> | |
/// <returns> | |
/// The netmask. | |
/// </returns> | |
/// <param name='ip'> | |
/// Ip. | |
/// </param> | |
public static uint ToNetmask(this IPAddress ip) | |
{ | |
uint ipUint = ~ip.ToUint(); | |
return mod37BitPosition[(-ipUint & ipUint) % 37]; | |
} | |
public static IPAddress FromNetmask(uint netmask) | |
{ | |
return new IPAddress(uint.MaxValue >> 32 - (int)netmask); | |
} | |
} | |
/// <summary> | |
/// Connection to remotely control the netowrk manager via D-BUS. | |
/// | |
/// D-BUS documentation: | |
/// * The D-BUS Network Manager: http://projects.gnome.org/NetworkManager/developers/api/09/spec.html#org.freedesktop.NetworkManager.Settings.Connection | |
/// * The D-BUS C# free library: https://github.com/mono/dbus-sharp and http://www.ndesk.org/DBus_Documentation | |
/// * D-BUS tutorial: http://dbus.freedesktop.org/doc/dbus-tutorial.html | |
/// </summary> | |
class NewtworkManagerConnection | |
{ | |
readonly string BUS_NAME = "org.freedesktop.NetworkManager"; | |
public Method Method { get; set; } | |
public IPAddress IP { get; set; } | |
public IPAddress Netmask { get; set; } | |
public IPAddress Gateway { get; set; } | |
public IEnumerable<IPAddress> DNS { get; set; } | |
/// <summary> | |
/// Automatically load data from the current active connection. | |
/// </summary>/ | |
public NewtworkManagerConnection() | |
{ | |
this.LoadFromActiveConnection(); | |
} | |
public bool SetIP(string ipStr) | |
{ | |
IPAddress ip; | |
if (IPAddress.TryParse(ipStr, out ip)) | |
{ | |
this.IP = ip; | |
return true; | |
} | |
return false; | |
} | |
public bool SetNetmask(string netmaskStr) | |
{ | |
IPAddress ip; | |
if (IPAddress.TryParse(netmaskStr, out ip)) | |
{ | |
this.Netmask = ip; | |
return true; | |
} | |
return false; | |
} | |
public bool SetGateway(string gatewayStr) | |
{ | |
IPAddress ip; | |
if (IPAddress.TryParse(gatewayStr, out ip)) | |
{ | |
this.Gateway = ip; | |
return true; | |
} | |
return false; | |
} | |
public bool SetDNS(IEnumerable<string> dnsStr) | |
{ | |
IEnumerable<IPAddress> ips = dnsStr.Aggregate( | |
new List<IPAddress>(), | |
(list, dns) => | |
{ | |
IPAddress ip; | |
if (IPAddress.TryParse(dns, out ip)) | |
list.Add(ip); | |
return list; | |
} | |
); | |
if (ips.Any()) | |
{ | |
this.DNS = ips; | |
return true; | |
} | |
return false; | |
} | |
public void SaveToActiveConnection() | |
{ | |
var bus = Bus.System; | |
org.freedesktop.DBus.Properties networkManagerProperties = bus.GetObject<org.freedesktop.DBus.Properties>(BUS_NAME, new ObjectPath("/org/freedesktop/NetworkManager")); | |
ObjectPath[] objPathActiveConnections = networkManagerProperties.Get(BUS_NAME, "ActiveConnections") as ObjectPath[]; | |
if (objPathActiveConnections.Length > 0) | |
{ | |
org.freedesktop.DBus.Properties activeConnectionProperties = bus.GetObject<org.freedesktop.DBus.Properties>(BUS_NAME, objPathActiveConnections[0]); | |
ObjectPath objPathConnection = activeConnectionProperties.Get("org.freedesktop.NetworkManager.Connection.Active", "Connection") as ObjectPath; | |
IConnection connection = bus.GetObject<IConnection>(BUS_NAME, objPathConnection); | |
var settings = connection.GetSettings(); | |
IDictionary<string, object> settingIPv4 = settings["ipv4"]; | |
if (this.Method == Method.AutoAddressesOnly) | |
{ | |
settingIPv4["ignore-auto-dns"] = true; | |
settingIPv4["dns"] = this.DNSAddresses; | |
} | |
if (this.Method == Method.Auto || this.Method == Method.AutoAddressesOnly) | |
{ | |
settingIPv4["method"] = "auto"; | |
} | |
else | |
{ | |
settingIPv4["method"] = "manual"; | |
settingIPv4["addresses"] = new uint[][] { this.Address }; | |
settingIPv4["dns"] = this.DNSAddresses; | |
} | |
connection.Update(settings); | |
} | |
bus.Close(); | |
} | |
public override string ToString() | |
{ | |
return string.Format("[NewtworkManagerConnection: Method={0}, IP={1}, SubNetworkMask={2}, Gateway={3}, DNS={4}]", this.Method, this.IP, this.Netmask, this.Gateway, this.DNS); | |
} | |
[Interface("org.freedesktop.NetworkManager.Settings.Connection")] | |
interface IConnection | |
{ | |
IDictionary<string, IDictionary<string, object>> GetSettings(); | |
void Update(IDictionary<string, IDictionary<string, object>> settings); | |
} | |
void LoadFromActiveConnection() | |
{ | |
var bus = Bus.System; | |
org.freedesktop.DBus.Properties networkManagerProperties = bus.GetObject<org.freedesktop.DBus.Properties>(BUS_NAME, new ObjectPath("/org/freedesktop/NetworkManager")); | |
ObjectPath[] objPathActiveConnections = networkManagerProperties.Get(BUS_NAME, "ActiveConnections") as ObjectPath[]; | |
if (objPathActiveConnections.Length > 0) | |
{ | |
org.freedesktop.DBus.Properties activeConnectionProperties = bus.GetObject<org.freedesktop.DBus.Properties>(BUS_NAME, objPathActiveConnections[0]); | |
// First, set the IP/mask/gateway from the device of the current active connection. | |
ObjectPath[] objPathDevices = activeConnectionProperties.Get("org.freedesktop.NetworkManager.Connection.Active", "Devices") as ObjectPath[]; | |
if (objPathDevices.Length > 0) | |
{ | |
ObjectPath objPathIp4Config = bus.GetObject<org.freedesktop.DBus.Properties>(BUS_NAME, objPathDevices[0]).Get("org.freedesktop.NetworkManager.Device", "Ip4Config") as ObjectPath; | |
uint[][] addresses = bus.GetObject<org.freedesktop.DBus.Properties>(BUS_NAME, objPathIp4Config).Get("org.freedesktop.NetworkManager.IP4Config", "Addresses") as uint[][]; | |
if (addresses.Length > 0) | |
this.Address = addresses[0]; | |
uint[] dns = bus.GetObject<org.freedesktop.DBus.Properties>(BUS_NAME, objPathIp4Config).Get("org.freedesktop.NetworkManager.IP4Config", "Nameservers") as uint[]; | |
this.DNSAddresses = dns; | |
} | |
ObjectPath objPathConnection = activeConnectionProperties.Get("org.freedesktop.NetworkManager.Connection.Active", "Connection") as ObjectPath; | |
IConnection connection = bus.GetObject<IConnection>(BUS_NAME, objPathConnection); | |
var settings = connection.GetSettings(); | |
IDictionary<string, object> settingIPv4; | |
if (settings.TryGetValue("ipv4", out settingIPv4)) | |
{ | |
this.Method = Method.Manual; // Default method. | |
object method; | |
if (settingIPv4.TryGetValue("method", out method) && method is string) | |
{ | |
object ignoreAutoDns; | |
settingIPv4.TryGetValue("ignore-auto-dns", out ignoreAutoDns); | |
if (method as string == "auto") | |
this.Method = ignoreAutoDns is bool && (bool)ignoreAutoDns ? Method.AutoAddressesOnly : Method.Auto; | |
} | |
object addresses; | |
if (settingIPv4.TryGetValue("addresses", out addresses) && addresses is uint[][] && (addresses as uint[][]).Length > 0) | |
this.Address = (addresses as uint[][])[0]; | |
object dns; | |
if (settingIPv4.TryGetValue("dns", out dns) && dns is uint[] && (dns as uint[]).Length > 0) | |
this.DNSAddresses = dns as uint[]; | |
} | |
} | |
bus.Close(); | |
} | |
uint[] Address | |
{ | |
get | |
{ | |
uint[] result = new uint[3]; | |
result[0] = this.IP.ToUint(); | |
result[1] = this.Netmask.ToNetmask(); | |
result[2] = this.Gateway.ToUint(); | |
return result; | |
} | |
set | |
{ | |
Debug.Assert(value.Length == 3); | |
this.IP = new IPAddress(value[0]); | |
this.Netmask = IPAddressExtension.FromNetmask(value[1]); | |
this.Gateway = new IPAddress(value[2]); | |
} | |
} | |
uint[] DNSAddresses | |
{ | |
get | |
{ | |
return this.DNS.Select(ip => ip.ToUint()).ToArray(); | |
} | |
set | |
{ | |
this.DNS = value.Select(ip => new IPAddress(ip)); | |
} | |
} | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment