Skip to content

Instantly share code, notes, and snippets.

@Ummon
Created December 17, 2012 10:18
Show Gist options
  • Save Ummon/4317268 to your computer and use it in GitHub Desktop.
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…
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