Hi,
In the current version System.Net.NetworkInformation.NetworkInterface
provides limited information about network interfaces on the system
(their names only).
The attached patch adds support for NetworkInterfaceType and
GetPhysicalAddress() on Mac OS.
The outline of the changes is as follows:
- Used the same trick with uname as in MWF XplatUI to detect if running
Mac OS.
- In several places I've added base classes like UnixNetworkInterface to
derive Linux- and MacOs- implementation classes from them. Where
possible, common code moved to Unix- classes; in some places dummy
methods are used to return default "don't know" values (0, false, "").
- Added new file MacOsNetworkInterfaceMarshal to define MacOs-specific
(BSD) structs like sockaddr as they're slightly different from those
used in Linux.
Comments are welcome! :)
--
Cheers,
Alex
Index: System.dll.sources
===================================================================
--- System.dll.sources (revision 133967)
+++ System.dll.sources (working copy)
@@ -761,6 +761,7 @@
System.Net.NetworkInformation/IPv4InterfaceStatistics.cs
System.Net.NetworkInformation/IPv6InterfaceProperties.cs
System.Net.NetworkInformation/LinuxNetworkInterfaceMarshal.cs
+System.Net.NetworkInformation/MacOsNetworkInterfaceMarshal.cs
System.Net.NetworkInformation/MulticastIPAddressInformationCollection.cs
System.Net.NetworkInformation/MulticastIPAddressInformation.cs
System.Net.NetworkInformation/NetBiosNodeType.cs
Index: System.Net.NetworkInformation/IPv4InterfaceStatistics.cs
===================================================================
--- System.Net.NetworkInformation/IPv4InterfaceStatistics.cs (revision 133967)
+++ System.Net.NetworkInformation/IPv4InterfaceStatistics.cs (working copy)
@@ -201,8 +201,65 @@
return Read ("statistics/tx_packets");
}
}
+ }
+ // dummy class
+ class MacOsIPv4InterfaceStatistics : IPv4InterfaceStatistics
+ {
+ MacOsNetworkInterface macos;
+ public MacOsIPv4InterfaceStatistics (MacOsNetworkInterface parent)
+ {
+ macos = parent;
+ }
+
+ public override long BytesReceived {
+ get { return 0; }
+ }
+
+ public override long BytesSent {
+ get { return 0; }
+ }
+
+ public override long IncomingPacketsDiscarded {
+ get { return 0; }
+ }
+
+ public override long IncomingPacketsWithErrors {
+ get { return 0; }
+ }
+
+ public override long IncomingUnknownProtocolPackets {
+ get { return 0; }
+ }
+
+ public override long NonUnicastPacketsReceived {
+ get { return 0; }
+ }
+
+ public override long NonUnicastPacketsSent {
+ get { return 0; }
+ }
+
+ public override long OutgoingPacketsDiscarded {
+ get { return 0; }
+ }
+
+ public override long OutgoingPacketsWithErrors {
+ get { return 0; }
+ }
+
+ public override long OutputQueueLength {
+ get { return 0; }
+ }
+
+ public override long UnicastPacketsReceived {
+ get { return 0; }
+ }
+
+ public override long UnicastPacketsSent {
+ get { return 0; }
+ }
}
}
Index: System.Net.NetworkInformation/IPv4InterfaceProperties.cs
===================================================================
--- System.Net.NetworkInformation/IPv4InterfaceProperties.cs (revision 133967)
+++ System.Net.NetworkInformation/IPv4InterfaceProperties.cs (working copy)
@@ -46,17 +46,17 @@
public abstract bool UsesWins { get; }
}
- sealed class LinuxIPv4InterfaceProperties : IPv4InterfaceProperties
+ abstract class UnixIPv4InterfaceProperties : IPv4InterfaceProperties
{
- LinuxNetworkInterface iface;
+ protected UnixNetworkInterface iface;
- public LinuxIPv4InterfaceProperties (LinuxNetworkInterface iface)
+ public UnixIPv4InterfaceProperties (UnixNetworkInterface iface)
{
this.iface = iface;
}
public override int Index {
- get { return LinuxNetworkInterface.IfNameToIndex (iface.Name); }
+ get { return UnixNetworkInterface.IfNameToIndex (iface.Name); }
}
// TODO: how to discover that?
@@ -74,6 +74,18 @@
get { return false; }
}
+ public override bool UsesWins {
+ get { return false; }
+ }
+ }
+
+ sealed class LinuxIPv4InterfaceProperties : UnixIPv4InterfaceProperties
+ {
+ public LinuxIPv4InterfaceProperties (LinuxNetworkInterface iface)
+ : base (iface)
+ {
+ }
+
public override bool IsForwardingEnabled {
get {
string iface_path = "/proc/sys/net/ipv4/conf/" + iface.Name + "/forwarding";
@@ -87,9 +99,10 @@
return false;
}
}
+
public override int Mtu {
get {
- string iface_path = iface.IfacePath + "mtu";
+ string iface_path = (iface as LinuxNetworkInterface).IfacePath + "mtu";
int ret = 0;
if (File.Exists (iface_path)) {
@@ -105,10 +118,24 @@
}
}
-
- public override bool UsesWins {
+ }
+
+ sealed class MacOsIPv4InterfaceProperties : UnixIPv4InterfaceProperties
+ {
+ public MacOsIPv4InterfaceProperties (MacOsNetworkInterface iface)
+ : base (iface)
+ {
+ }
+
+ // dummy
+ public override bool IsForwardingEnabled {
get { return false; }
}
+
+ // dummy
+ public override int Mtu {
+ get { return 0; }
+ }
}
sealed class Win32IPv4InterfaceProperties : IPv4InterfaceProperties
Index: System.Net.NetworkInformation/IPInterfaceProperties.cs
===================================================================
--- System.Net.NetworkInformation/IPInterfaceProperties.cs (revision 133967)
+++ System.Net.NetworkInformation/IPInterfaceProperties.cs (working copy)
@@ -53,35 +53,26 @@
public abstract IPAddressCollection WinsServersAddresses { get; }
}
- class LinuxIPInterfaceProperties : IPInterfaceProperties
+ abstract class UnixIPInterfaceProperties : IPInterfaceProperties
{
- IPv4InterfaceProperties ipv4iface_properties;
- LinuxNetworkInterface iface;
+ protected IPv4InterfaceProperties ipv4iface_properties;
+ protected UnixNetworkInterface iface;
List <IPAddress> addresses;
IPAddressCollection dns_servers;
string dns_suffix;
DateTime last_parse;
- public LinuxIPInterfaceProperties (LinuxNetworkInterface iface, List <IPAddress> addresses)
+ public UnixIPInterfaceProperties (UnixNetworkInterface iface, List <IPAddress> addresses)
{
this.iface = iface;
this.addresses = addresses;
}
- public override IPv4InterfaceProperties GetIPv4Properties ()
- {
- if (ipv4iface_properties == null)
- ipv4iface_properties = new LinuxIPv4InterfaceProperties (iface);
-
- return ipv4iface_properties;
- }
-
public override IPv6InterfaceProperties GetIPv6Properties ()
{
throw new NotImplementedException ();
}
-
static Regex ns = new Regex (@"\s*nameserver\s+(?<address>.*)");
static Regex search = new Regex (@"\s*search\s+(?<domain>.*)");
void ParseResolvConf ()
@@ -234,6 +225,38 @@
}
}
+ class LinuxIPInterfaceProperties : UnixIPInterfaceProperties
+ {
+ public LinuxIPInterfaceProperties (LinuxNetworkInterface iface, List <IPAddress> addresses)
+ : base (iface, addresses)
+ {
+ }
+
+ public override IPv4InterfaceProperties GetIPv4Properties ()
+ {
+ if (ipv4iface_properties == null)
+ ipv4iface_properties = new LinuxIPv4InterfaceProperties (iface as LinuxNetworkInterface);
+
+ return ipv4iface_properties;
+ }
+ }
+
+ class MacOsIPInterfaceProperties : UnixIPInterfaceProperties
+ {
+ public MacOsIPInterfaceProperties (MacOsNetworkInterface iface, List <IPAddress> addresses)
+ : base (iface, addresses)
+ {
+ }
+
+ public override IPv4InterfaceProperties GetIPv4Properties ()
+ {
+ if (ipv4iface_properties == null)
+ ipv4iface_properties = new MacOsIPv4InterfaceProperties (iface as MacOsNetworkInterface);
+
+ return ipv4iface_properties;
+ }
+ }
+
class Win32IPInterfaceProperties2 : IPInterfaceProperties
{
readonly Win32_IP_ADAPTER_ADDRESSES addr;
Index: System.Net.NetworkInformation/NetworkInterface.cs
===================================================================
--- System.Net.NetworkInformation/NetworkInterface.cs (revision 133967)
+++ System.Net.NetworkInformation/NetworkInterface.cs (working copy)
@@ -42,6 +42,9 @@
namespace System.Net.NetworkInformation {
public abstract class NetworkInterface {
+ [DllImport ("libc")]
+ static extern int uname (IntPtr buf);
+
static Version windowsVer51 = new Version (5, 1);
static internal readonly bool runningOnUnix = (Environment.OSVersion.Platform == PlatformID.Unix);
@@ -53,8 +56,20 @@
public static NetworkInterface [] GetAllNetworkInterfaces ()
{
if (runningOnUnix) {
+ bool darwin = false;
+ IntPtr buf = Marshal.AllocHGlobal (8192);
+ if (uname (buf) == 0) {
+ string os = Marshal.PtrToStringAnsi (buf);
+ if (os == "Darwin")
+ darwin = true;
+ }
+ Marshal.FreeHGlobal (buf);
+
try {
- return LinuxNetworkInterface.ImplGetAllNetworkInterfaces ();
+ if (darwin)
+ return MacOsNetworkInterface.ImplGetAllNetworkInterfaces ();
+ else
+ return LinuxNetworkInterface.ImplGetAllNetworkInterfaces ();
} catch (SystemException ex) {
throw ex;
} catch {
@@ -87,7 +102,7 @@
get {
if (runningOnUnix) {
try {
- return LinuxNetworkInterface.IfNameToIndex ("lo");
+ return UnixNetworkInterface.IfNameToIndex ("lo");
} catch {
return 0;
}
@@ -111,17 +126,103 @@
public abstract bool SupportsMulticast { get; }
}
+ abstract class UnixNetworkInterface : NetworkInterface
+ {
+ [DllImport("libc")]
+ static extern int if_nametoindex(string ifname);
+
+ protected IPv4InterfaceStatistics ipv4stats;
+ protected IPInterfaceProperties ipproperties;
+
+ string name;
+ int index;
+ protected List <IPAddress> addresses;
+ byte[] macAddress;
+ NetworkInterfaceType type;
+
+ internal UnixNetworkInterface (string name)
+ {
+ this.name = name;
+ addresses = new List<IPAddress> ();
+ }
+
+ public static int IfNameToIndex (string ifname)
+ {
+ return if_nametoindex(ifname);
+ }
+
+ internal void AddAddress (IPAddress address)
+ {
+ addresses.Add (address);
+ }
+
+ internal void SetLinkLayerInfo (int index, byte[] macAddress, NetworkInterfaceType type)
+ {
+ this.index = index;
+ this.macAddress = macAddress;
+ this.type = type;
+ }
+
+ public override PhysicalAddress GetPhysicalAddress ()
+ {
+ if (macAddress != null)
+ return new PhysicalAddress (macAddress);
+ else
+ return PhysicalAddress.None;
+ }
+
+ public override bool Supports (NetworkInterfaceComponent networkInterfaceComponent)
+ {
+ bool wantIPv4 = networkInterfaceComponent == NetworkInterfaceComponent.IPv4;
+ bool wantIPv6 = wantIPv4 ? false : networkInterfaceComponent == NetworkInterfaceComponent.IPv6;
+
+ foreach (IPAddress address in addresses) {
+ if (wantIPv4 && address.AddressFamily == AddressFamily.InterNetwork)
+ return true;
+ else if (wantIPv6 && address.AddressFamily == AddressFamily.InterNetworkV6)
+ return true;
+ }
+
+ return false;
+ }
+
+ public override string Description {
+ get { return name; }
+ }
+
+ public override string Id {
+ get { return name; }
+ }
+
+ public override bool IsReceiveOnly {
+ get { return false; }
+ }
+
+ public override string Name {
+ get { return name; }
+ }
+
+ public override NetworkInterfaceType NetworkInterfaceType {
+ get { return type; }
+ }
+
+ [MonoTODO ("Parse dmesg?")]
+ public override long Speed {
+ get {
+ // Bits/s
+ return 1000000;
+ }
+ }
+ }
+
//
// This class needs support from the libsupport.so library to fetch the
// data using arch-specific ioctls.
//
// For this to work, we have to create this on the factory above.
//
- class LinuxNetworkInterface : NetworkInterface
+ class LinuxNetworkInterface : UnixNetworkInterface
{
- [DllImport("libc")]
- static extern int if_nametoindex(string ifname);
-
[DllImport ("libc")]
static extern int getifaddrs (out IntPtr ifap);
@@ -132,13 +233,6 @@
const int AF_INET6 = 10;
const int AF_PACKET = 17;
- IPv4InterfaceStatistics ipv4stats;
- IPInterfaceProperties ipproperties;
-
- string name;
- int index;
- List <IPAddress> addresses;
- byte[] macAddress;
NetworkInterfaceType type;
string iface_path;
string iface_operstate_path;
@@ -148,11 +242,6 @@
get { return iface_path; }
}
- public static int IfNameToIndex (string ifname)
- {
- return if_nametoindex(ifname);
- }
-
public static NetworkInterface [] ImplGetAllNetworkInterfaces ()
{
var interfaces = new Dictionary <string, LinuxNetworkInterface> ();
@@ -246,8 +335,14 @@
if (!address.Equals (IPAddress.None))
iface.AddAddress (address);
- if (macAddress != null || type == NetworkInterfaceType.Loopback)
+ if (macAddress != null || type == NetworkInterfaceType.Loopback) {
+ if (type == NetworkInterfaceType.Ethernet) {
+ if (Directory.Exists(iface.IfacePath + "wireless")) {
+ type = NetworkInterfaceType.Wireless80211;
+ }
+ }
iface.SetLinkLayerInfo (index, macAddress, type);
+ }
next = addr.ifa_next;
}
@@ -265,31 +360,13 @@
}
LinuxNetworkInterface (string name)
+ : base (name)
{
- this.name = name;
- addresses = new List<IPAddress> ();
iface_path = "/sys/class/net/" + name + "/";
iface_operstate_path = iface_path + "operstate";
iface_flags_path = iface_path + "flags";
}
- internal void AddAddress (IPAddress address)
- {
- addresses.Add (address);
- }
-
- internal void SetLinkLayerInfo (int index, byte[] macAddress, NetworkInterfaceType type)
- {
- this.index = index;
- this.macAddress = macAddress;
- if (type == NetworkInterfaceType.Ethernet) {
- if (Directory.Exists(iface_path + "wireless")) {
- type = NetworkInterfaceType.Wireless80211;
- }
- }
- this.type = type;
- }
-
public override IPInterfaceProperties GetIPProperties ()
{
if (ipproperties == null)
@@ -301,53 +378,9 @@
{
if (ipv4stats == null)
ipv4stats = new LinuxIPv4InterfaceStatistics (this);
-
return ipv4stats;
}
- public override PhysicalAddress GetPhysicalAddress ()
- {
- if (macAddress != null)
- return new PhysicalAddress (macAddress);
- else
- return PhysicalAddress.None;
- }
-
- public override bool Supports (NetworkInterfaceComponent networkInterfaceComponent)
- {
- bool wantIPv4 = networkInterfaceComponent == NetworkInterfaceComponent.IPv4;
- bool wantIPv6 = wantIPv4 ? false : networkInterfaceComponent == NetworkInterfaceComponent.IPv6;
-
- foreach (IPAddress address in addresses) {
- if (wantIPv4 && address.AddressFamily == AddressFamily.InterNetwork)
- return true;
- else if (wantIPv6 && address.AddressFamily == AddressFamily.InterNetworkV6)
- return true;
- }
-
- return false;
- }
-
- public override string Description {
- get { return name; }
- }
-
- public override string Id {
- get { return name; }
- }
-
- public override bool IsReceiveOnly {
- get { return false; }
- }
-
- public override string Name {
- get { return name; }
- }
-
- public override NetworkInterfaceType NetworkInterfaceType {
- get { return type; }
- }
-
public override OperationalStatus OperationalStatus {
get {
if (!Directory.Exists (iface_path))
@@ -384,14 +417,6 @@
}
}
- [MonoTODO ("Parse dmesg?")]
- public override long Speed {
- get {
- // Bits/s
- return 1000000;
- }
- }
-
public override bool SupportsMulticast {
get {
if (!Directory.Exists (iface_path))
@@ -413,6 +438,143 @@
}
}
+ class MacOsNetworkInterface : UnixNetworkInterface
+ {
+ [DllImport ("libc")]
+ static extern int getifaddrs (out IntPtr ifap);
+
+ [DllImport ("libc")]
+ static extern void freeifaddrs (IntPtr ifap);
+
+ const int AF_INET = 2;
+ const int AF_INET6 = 30;
+ const int AF_LINK = 18;
+
+ public static NetworkInterface [] ImplGetAllNetworkInterfaces ()
+ {
+ var interfaces = new Dictionary <string, MacOsNetworkInterface> ();
+ IntPtr ifap;
+ if (getifaddrs (out ifap) != 0)
+ throw new SystemException ("getifaddrs() failed");
+
+ try {
+ IntPtr next = ifap;
+ while (next != IntPtr.Zero) {
+ MacOsStructs.ifaddrs addr = (MacOsStructs.ifaddrs) Marshal.PtrToStructure (next, typeof (MacOsStructs.ifaddrs));
+ IPAddress address = IPAddress.None;
+ string name = addr.ifa_name;
+ int index = -1;
+ byte[] macAddress = null;
+ NetworkInterfaceType type = NetworkInterfaceType.Unknown;
+
+ if (addr.ifa_addr != IntPtr.Zero) {
+ MacOsStructs.sockaddr sockaddr = (MacOsStructs.sockaddr) Marshal.PtrToStructure (addr.ifa_addr, typeof (MacOsStructs.sockaddr));
+
+ if (sockaddr.sa_family == AF_INET6) {
+ //sockaddr_in6 sockaddr6 = (sockaddr_in6) Marshal.PtrToStructure (addr.ifa_addr, typeof (sockaddr_in6));
+ //address = new IPAddress (sockaddr6.sin6_addr.u6_addr8, sockaddr6.sin6_scope_id);
+ } else if (sockaddr.sa_family == AF_INET) {
+ MacOsStructs.sockaddr_in sockaddrin = (MacOsStructs.sockaddr_in) Marshal.PtrToStructure (addr.ifa_addr, typeof (MacOsStructs.sockaddr_in));
+ address = new IPAddress (sockaddrin.sin_addr);
+ } else if (sockaddr.sa_family == AF_LINK) {
+ MacOsStructs.sockaddr_dl sockaddrdl = (MacOsStructs.sockaddr_dl) Marshal.PtrToStructure (addr.ifa_addr, typeof (MacOsStructs.sockaddr_dl));
+
+ macAddress = new byte [(int) sockaddrdl.sdl_alen];
+ Array.Copy (sockaddrdl.sdl_data, sockaddrdl.sdl_nlen, macAddress, 0, macAddress.Length);
+ index = sockaddrdl.sdl_index;
+
+ int hwtype = (int) sockaddrdl.sdl_type;
+ if (Enum.IsDefined (typeof (MacOsArpHardware), hwtype)) {
+ switch ((MacOsArpHardware) hwtype) {
+ case MacOsArpHardware.ETHER:
+ type = NetworkInterfaceType.Ethernet;
+ break;
+
+ case MacOsArpHardware.ATM:
+ type = NetworkInterfaceType.Atm;
+ break;
+
+ case MacOsArpHardware.SLIP:
+ type = NetworkInterfaceType.Slip;
+ break;
+
+ case MacOsArpHardware.PPP:
+ type = NetworkInterfaceType.Ppp;
+ break;
+
+ case MacOsArpHardware.LOOPBACK:
+ type = NetworkInterfaceType.Loopback;
+ macAddress = null;
+ break;
+
+ case MacOsArpHardware.FDDI:
+ type = NetworkInterfaceType.Fddi;
+ break;
+ }
+ }
+ }
+ }
+
+ MacOsNetworkInterface iface = null;
+
+ if (!interfaces.TryGetValue (name, out iface)) {
+ iface = new MacOsNetworkInterface (name);
+ interfaces.Add (name, iface);
+ }
+
+ if (!address.Equals (IPAddress.None))
+ iface.AddAddress (address);
+
+ if (macAddress != null || type == NetworkInterfaceType.Loopback)
+ iface.SetLinkLayerInfo (index, macAddress, type);
+
+ next = addr.ifa_next;
+ }
+ } finally {
+ freeifaddrs (ifap);
+ }
+
+ NetworkInterface [] result = new NetworkInterface [interfaces.Count];
+ int x = 0;
+ foreach (NetworkInterface thisInterface in interfaces.Values) {
+ result [x] = thisInterface;
+ x++;
+ }
+ return result;
+ }
+
+ MacOsNetworkInterface (string name)
+ : base (name)
+ {
+ }
+
+ public override IPInterfaceProperties GetIPProperties ()
+ {
+ if (ipproperties == null)
+ ipproperties = new MacOsIPInterfaceProperties (this, addresses);
+ return ipproperties;
+ }
+
+ public override IPv4InterfaceStatistics GetIPv4Statistics ()
+ {
+ if (ipv4stats == null)
+ ipv4stats = new MacOsIPv4InterfaceStatistics (this);
+ return ipv4stats;
+ }
+
+ public override OperationalStatus OperationalStatus {
+ get {
+ return OperationalStatus.Unknown;
+ }
+ }
+
+ public override bool SupportsMulticast {
+ get {
+ return false;
+ }
+ }
+ }
+
class Win32NetworkInterface2 : NetworkInterface
{
[DllImport ("iphlpapi.dll", SetLastError = true)]
_______________________________________________
Mono-osx mailing list
Mono-osx@...
http://lists.ximian.com/mailman/listinfo/mono-osx