Ver Fonte

2007-08-29 Atsushi Enomoto <[email protected]>

	* System.dll.sources : added Win32NetworkInterfaceMarshal.cs.

	* NetworkInterface.cs,
	  IPv4InterfaceStatistics.cs
	  IPInterfaceProperties.cs
	  IPv4InterfaceProperties.cs
	  IPv6InterfaceProperties.cs
	  IPAddressCollection.cs
	  GatewayIPAddressInformation.cs
	  GatewayIPAddressInformationCollection.cs
	  IPAddressInformation.cs
	  IPAddressInformationCollection.cs
	  MulticastIPAddressInformation.cs
	  MulticastIPAddressInformationCollection.cs
	  UnicastIPAddressInformation.cs
	  UnicastIPAddressInformationCollection.cs
	  Win32NetworkInterfaceMarshal.cs (new) :
	  NetworkInterface implementation using Win32 API.

	  Not sure how MIB-based implementation (for Linux) is possible but
	  it will follow.


svn path=/trunk/mcs/; revision=85018
Atsushi Eno há 18 anos atrás
pai
commit
7fb299fbbe
18 ficheiros alterados com 1165 adições e 50 exclusões
  1. 4 0
      mcs/class/System/ChangeLog
  2. 22 0
      mcs/class/System/System.Net.NetworkInformation/ChangeLog
  3. 17 2
      mcs/class/System/System.Net.NetworkInformation/GatewayIPAddressInformation.cs
  4. 50 6
      mcs/class/System/System.Net.NetworkInformation/GatewayIPAddressInformationCollection.cs
  5. 84 6
      mcs/class/System/System.Net.NetworkInformation/IPAddressCollection.cs
  6. 28 2
      mcs/class/System/System.Net.NetworkInformation/IPAddressInformation.cs
  7. 46 6
      mcs/class/System/System.Net.NetworkInformation/IPAddressInformationCollection.cs
  8. 81 2
      mcs/class/System/System.Net.NetworkInformation/IPInterfaceProperties.cs
  9. 67 2
      mcs/class/System/System.Net.NetworkInformation/IPv4InterfaceProperties.cs
  10. 62 2
      mcs/class/System/System.Net.NetworkInformation/IPv4InterfaceStatistics.cs
  11. 21 2
      mcs/class/System/System.Net.NetworkInformation/IPv6InterfaceProperties.cs
  12. 56 2
      mcs/class/System/System.Net.NetworkInformation/MulticastIPAddressInformation.cs
  13. 46 6
      mcs/class/System/System.Net.NetworkInformation/MulticastIPAddressInformationCollection.cs
  14. 192 4
      mcs/class/System/System.Net.NetworkInformation/NetworkInterface.cs
  15. 58 2
      mcs/class/System/System.Net.NetworkInformation/UnicastIPAddressInformation.cs
  16. 43 6
      mcs/class/System/System.Net.NetworkInformation/UnicastIPAddressInformationCollection.cs
  17. 287 0
      mcs/class/System/System.Net.NetworkInformation/Win32NetworkInterfaceMarshal.cs
  18. 1 0
      mcs/class/System/System.dll.sources

+ 4 - 0
mcs/class/System/ChangeLog

@@ -1,3 +1,7 @@
+2007-08-29  Atsushi Enomoto  <[email protected]>
+
+	* System.dll.sources : added Win32NetworkInterfaceMarshal.cs.
+
 2007-08-24  Atsushi Enomoto  <[email protected]>
 
 	* Makefile : split PREBUILT_DEP from CONFIGURATION_DEP so that the

+ 22 - 0
mcs/class/System/System.Net.NetworkInformation/ChangeLog

@@ -1,3 +1,25 @@
+2007-08-29  Atsushi Enomoto  <[email protected]>
+
+	* NetworkInterface.cs,
+	  IPv4InterfaceStatistics.cs
+	  IPInterfaceProperties.cs
+	  IPv4InterfaceProperties.cs
+	  IPv6InterfaceProperties.cs
+	  IPAddressCollection.cs
+	  GatewayIPAddressInformation.cs
+	  GatewayIPAddressInformationCollection.cs
+	  IPAddressInformation.cs
+	  IPAddressInformationCollection.cs
+	  MulticastIPAddressInformation.cs
+	  MulticastIPAddressInformationCollection.cs
+	  UnicastIPAddressInformation.cs
+	  UnicastIPAddressInformationCollection.cs
+	  Win32NetworkInterfaceMarshal.cs (new) :
+	  NetworkInterface implementation using Win32 API.
+
+	  Not sure how MIB-based implementation (for Linux) is possible but
+	  it will follow.
+
 2007-08-27  Atsushi Enomoto  <[email protected]>
 
 	* IPGlobalProperties.cs : implemented remaining methods in

+ 17 - 2
mcs/class/System/System.Net.NetworkInformation/GatewayIPAddressInformation.cs

@@ -1,10 +1,11 @@
 //
 // System.Net.NetworkInformation.GatewayIPAddressInformation
 //
-// Author:
+// Authors:
 //	Gonzalo Paniagua Javier ([email protected])
+//	Atsushi Enomoto ([email protected])
 //
-// Copyright (c) 2006 Novell, Inc. (http://www.novell.com)
+// Copyright (c) 2006-2007 Novell, Inc. (http://www.novell.com)
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
@@ -34,6 +35,20 @@ namespace System.Net.NetworkInformation {
 		
 		public abstract IPAddress Address { get; }
 	}
+
+	class GatewayIPAddressInformationImpl : GatewayIPAddressInformation
+	{
+		IPAddress address;
+
+		public GatewayIPAddressInformationImpl (IPAddress address)
+		{
+			this.address = address;
+		}
+		
+		public override IPAddress Address {
+			get { return address; }
+		}
+	}
 }
 #endif
 

+ 50 - 6
mcs/class/System/System.Net.NetworkInformation/GatewayIPAddressInformationCollection.cs

@@ -1,10 +1,11 @@
 //
 // System.Net.NetworkInformation.GatewayIPAddressInformationCollection
 //
-// Author:
+// Authors:
 //	Gonzalo Paniagua Javier ([email protected])
+//	Atsushi Enomoto ([email protected])
 //
-// Copyright (c) 2006 Novell, Inc. (http://www.novell.com)
+// Copyright (c) 2006-2007 Novell, Inc. (http://www.novell.com)
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
@@ -28,10 +29,11 @@
 #if NET_2_0
 using System.Collections;
 using System.Collections.Generic;
+using System.Runtime.InteropServices;
 
 namespace System.Net.NetworkInformation {
 	public class GatewayIPAddressInformationCollection : ICollection<GatewayIPAddressInformation>, IEnumerable<GatewayIPAddressInformation>, IEnumerable {
-		List<GatewayIPAddressInformation> list;
+		List<GatewayIPAddressInformation> list = new List<GatewayIPAddressInformation> ();
 		
 		protected GatewayIPAddressInformationCollection ()
 		{
@@ -39,12 +41,16 @@ namespace System.Net.NetworkInformation {
 
 		public virtual void Add (GatewayIPAddressInformation address)
 		{
-			throw new NotSupportedException ("The collection is read-only.");
+			if (IsReadOnly)
+				throw new NotSupportedException ("The collection is read-only.");
+			list.Add (address);
 		}
 
 		public virtual void Clear ()
 		{
-			throw new NotSupportedException ("The collection is read-only.");
+			if (IsReadOnly)
+				throw new NotSupportedException ("The collection is read-only.");
+			list.Clear ();
 		}
 
 		public virtual bool Contains (GatewayIPAddressInformation address)
@@ -64,7 +70,9 @@ namespace System.Net.NetworkInformation {
 
 		public virtual bool Remove (GatewayIPAddressInformation address)
 		{
-			throw new NotSupportedException ("The collection is read-only.");
+			if (IsReadOnly)
+				throw new NotSupportedException ("The collection is read-only.");
+			return list.Remove (address);
 		}
 
 		IEnumerator IEnumerable.GetEnumerator ()
@@ -84,6 +92,42 @@ namespace System.Net.NetworkInformation {
 			get { return list [index]; }
 		}
 	}
+
+	class Win32GatewayIPAddressInformationCollection : GatewayIPAddressInformationCollection
+	{
+		public static readonly Win32GatewayIPAddressInformationCollection Empty = new Win32GatewayIPAddressInformationCollection (true);
+
+		bool is_readonly;
+
+		private Win32GatewayIPAddressInformationCollection (bool isReadOnly)
+		{
+			this.is_readonly = isReadOnly;
+		}
+
+		public Win32GatewayIPAddressInformationCollection (params Win32_IP_ADDR_STRING [] al)
+		{
+			foreach (Win32_IP_ADDR_STRING a in al) {
+				if (String.IsNullOrEmpty (a.IpAddress))
+					continue;
+				Add (new GatewayIPAddressInformationImpl (IPAddress.Parse (a.IpAddress)));
+				AddSubsequently (a.Next);
+			}
+			is_readonly = true;
+		}
+
+		void AddSubsequently (IntPtr head)
+		{
+			Win32_IP_ADDR_STRING a;
+			for (IntPtr p = head; p != IntPtr.Zero; p = a.Next) {
+				a = (Win32_IP_ADDR_STRING) Marshal.PtrToStructure (p, typeof (Win32_IP_ADDR_STRING));
+				Add (new GatewayIPAddressInformationImpl (IPAddress.Parse (a.IpAddress)));
+			}
+		}
+
+		public override bool IsReadOnly {
+			get { return is_readonly; }
+		}
+	}
 }
 #endif
 

+ 84 - 6
mcs/class/System/System.Net.NetworkInformation/IPAddressCollection.cs

@@ -1,10 +1,11 @@
 //
 // System.Net.NetworkInformation.IPAddressCollection
 //
-// Author:
+// Authors:
 //	Gonzalo Paniagua Javier ([email protected])
+//	Atsushi Enomoto ([email protected])
 //
-// Copyright (c) 2006 Novell, Inc. (http://www.novell.com)
+// Copyright (c) 2006-2007 Novell, Inc. (http://www.novell.com)
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
@@ -29,10 +30,12 @@
 using System;
 using System.Collections;
 using System.Collections.Generic;
+using System.Net;
+using System.Runtime.InteropServices;
 
 namespace System.Net.NetworkInformation {
 	public class IPAddressCollection : ICollection<IPAddress>, IEnumerable<IPAddress>, IEnumerable {
-		List<IPAddress> list;
+		List<IPAddress> list = new List<IPAddress> ();
 
 		protected internal IPAddressCollection ()
 		{
@@ -40,12 +43,16 @@ namespace System.Net.NetworkInformation {
 
 		public virtual void Add (IPAddress address)
 		{
-			throw new NotSupportedException ("The collection is read-only.");
+			if (IsReadOnly)
+				throw new NotSupportedException ("The collection is read-only.");
+			list.Add (address);
 		}
 
 		public virtual void Clear ()
 		{
-			throw new NotSupportedException ("The collection is read-only.");
+			if (IsReadOnly)
+				throw new NotSupportedException ("The collection is read-only.");
+			list.Clear ();
 		}
 
 		public virtual bool Contains (IPAddress address)
@@ -65,7 +72,9 @@ namespace System.Net.NetworkInformation {
 
 		public virtual bool Remove (IPAddress address)
 		{
-			throw new NotSupportedException ("The collection is read-only.");
+			if (IsReadOnly)
+				throw new NotSupportedException ("The collection is read-only.");
+			return list.Remove (address);
 		}
 
 		IEnumerator IEnumerable.GetEnumerator ()
@@ -85,6 +94,75 @@ namespace System.Net.NetworkInformation {
 			get { return list [index]; }
 		}
 	}
+
+	class Win32IPAddressCollection : IPAddressCollection
+	{
+		public static readonly Win32IPAddressCollection Empty = new Win32IPAddressCollection (IntPtr.Zero);
+
+		bool is_readonly;
+
+		// for static methods
+		Win32IPAddressCollection ()
+		{
+		}
+
+		public Win32IPAddressCollection (params IntPtr [] heads)
+		{
+			foreach (IntPtr head in heads)
+				AddSubsequentlyString (head);
+			is_readonly = true;
+		}
+
+		public Win32IPAddressCollection (params Win32_IP_ADDR_STRING [] al)
+		{
+			foreach (Win32_IP_ADDR_STRING a in al) {
+				if (String.IsNullOrEmpty (a.IpAddress))
+					continue;
+				Add (IPAddress.Parse (a.IpAddress));
+				AddSubsequentlyString (a.Next);
+			}
+			is_readonly = true;
+		}
+
+		public static Win32IPAddressCollection FromAnycast (IntPtr ptr)
+		{
+			Win32IPAddressCollection c = new Win32IPAddressCollection ();
+			Win32_IP_ADAPTER_ANYCAST_ADDRESS a;
+			for (IntPtr p = ptr; p != IntPtr.Zero; p = a.Next) {
+				a = (Win32_IP_ADAPTER_ANYCAST_ADDRESS) Marshal.PtrToStructure (p, typeof (Win32_IP_ADAPTER_ANYCAST_ADDRESS));
+				c.Add (a.Address.GetIPAddress ());
+			}
+			c.is_readonly = true;
+			return c;
+		}
+
+		public static Win32IPAddressCollection FromDnsServer (IntPtr ptr)
+		{
+			Win32IPAddressCollection c = new Win32IPAddressCollection ();
+			Win32_IP_ADAPTER_DNS_SERVER_ADDRESS a;
+			for (IntPtr p = ptr; p != IntPtr.Zero; p = a.Next) {
+				a = (Win32_IP_ADAPTER_DNS_SERVER_ADDRESS) Marshal.PtrToStructure (p, typeof (Win32_IP_ADAPTER_DNS_SERVER_ADDRESS));
+// FIXME: It somehow fails here. Looks like there is something wrong.
+//if (a.Address.Sockaddr == IntPtr.Zero) throw new Exception ("pointer " + p + " a.length " + a.Address.SockaddrLength);
+				c.Add (a.Address.GetIPAddress ());
+			}
+			c.is_readonly = true;
+			return c;
+		}
+
+		void AddSubsequentlyString (IntPtr head)
+		{
+			Win32_IP_ADDR_STRING a;
+			for (IntPtr p = head; p != IntPtr.Zero; p = a.Next) {
+				a = (Win32_IP_ADDR_STRING) Marshal.PtrToStructure (p, typeof (Win32_IP_ADDR_STRING));
+				Add (IPAddress.Parse (a.IpAddress));
+			}
+		}
+
+		public override bool IsReadOnly {
+			get { return is_readonly; }
+		}
+	}
 }
 #endif
 

+ 28 - 2
mcs/class/System/System.Net.NetworkInformation/IPAddressInformation.cs

@@ -1,10 +1,11 @@
 //
 // System.Net.NetworkInformation.IPAddressInformation
 //
-// Author:
+// Authors:
 //	Gonzalo Paniagua Javier ([email protected])
+//	Atsushi Enomoto ([email protected])
 //
-// Copyright (c) 2006 Novell, Inc. (http://www.novell.com)
+// Copyright (c) 2006-2007 Novell, Inc. (http://www.novell.com)
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
@@ -38,6 +39,31 @@ namespace System.Net.NetworkInformation {
 		public abstract bool IsDnsEligible { get; }
 		public abstract bool IsTransient { get; }
 	}
+
+	class IPAddressInformationImpl : IPAddressInformation 
+	{
+		IPAddress address;
+		bool is_dns_eligible, is_transient;
+
+		public IPAddressInformationImpl (IPAddress address, bool isDnsEligible, bool isTransient)
+		{
+			this.address = address;
+			this.is_dns_eligible = isDnsEligible;
+			this.is_transient = isTransient;
+		}
+
+		public override IPAddress Address {
+			get { return address; }
+		}
+
+		public override bool IsDnsEligible {
+			get { return is_dns_eligible; }
+		}
+
+		public override bool IsTransient {
+			get { return is_transient; }
+		}
+	}
 }
 #endif
 

+ 46 - 6
mcs/class/System/System.Net.NetworkInformation/IPAddressInformationCollection.cs

@@ -1,10 +1,11 @@
 //
 // System.Net.NetworkInformation.IPAddressInformationCollection
 //
-// Author:
+// Authors:
 //	Gonzalo Paniagua Javier ([email protected])
+//	Atsushi Enomoto ([email protected])
 //
-// Copyright (c) 2006 Novell, Inc. (http://www.novell.com)
+// Copyright (c) 2006-2007 Novell, Inc. (http://www.novell.com)
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
@@ -29,10 +30,11 @@
 using System;
 using System.Collections;
 using System.Collections.Generic;
+using System.Runtime.InteropServices;
 
 namespace System.Net.NetworkInformation {
 	public class IPAddressInformationCollection : ICollection<IPAddressInformation>, IEnumerable<IPAddressInformation>, IEnumerable {
-		List <IPAddressInformation> list;
+		List <IPAddressInformation> list = new List <IPAddressInformation> ();
 
 		internal IPAddressInformationCollection ()
 		{
@@ -40,12 +42,16 @@ namespace System.Net.NetworkInformation {
 
 		public virtual void Add (IPAddressInformation address)
 		{
-			throw new NotSupportedException ("The collection is read-only.");
+			if (IsReadOnly)
+				throw new NotSupportedException ("The collection is read-only.");
+			list.Add (address);
 		}
 
 		public virtual void Clear ()
 		{
-			throw new NotSupportedException ("The collection is read-only.");
+			if (IsReadOnly)
+				throw new NotSupportedException ("The collection is read-only.");
+			list.Clear ();
 		}
 
 		public virtual bool Contains (IPAddressInformation address)
@@ -65,7 +71,9 @@ namespace System.Net.NetworkInformation {
 
 		public virtual bool Remove (IPAddressInformation address)
 		{
-			throw new NotSupportedException ("The collection is read-only.");
+			if (IsReadOnly)
+				throw new NotSupportedException ("The collection is read-only.");
+			return list.Remove (address);
 		}
 
 		IEnumerator IEnumerable.GetEnumerator ()
@@ -85,6 +93,38 @@ namespace System.Net.NetworkInformation {
 			get { return list [index]; }
 		}
 	}
+
+	class IPAddressInformationImplCollection : IPAddressInformationCollection
+	{
+		public static readonly IPAddressInformationImplCollection Empty = new IPAddressInformationImplCollection (true);
+
+		bool is_readonly;
+
+		// for static methods
+		IPAddressInformationImplCollection (bool isReadOnly)
+		{
+			is_readonly = isReadOnly;
+		}
+
+		public override bool IsReadOnly {
+			get { return is_readonly; }
+		}
+
+		public static IPAddressInformationImplCollection FromAnycast (IntPtr ptr)
+		{
+			IPAddressInformationImplCollection c = new IPAddressInformationImplCollection (false);
+			Win32_IP_ADAPTER_ANYCAST_ADDRESS a;
+			for (IntPtr p = ptr; p != IntPtr.Zero; p = a.Next) {
+				a = (Win32_IP_ADAPTER_ANYCAST_ADDRESS) Marshal.PtrToStructure (p, typeof (Win32_IP_ADAPTER_ANYCAST_ADDRESS));
+				c.Add (new IPAddressInformationImpl (
+				       a.Address.GetIPAddress (),
+				       a.LengthFlags.IsDnsEligible,
+				       a.LengthFlags.IsTransient));
+			}
+			c.is_readonly = true;
+			return c;
+		}
+	}
 }
 #endif
 

+ 81 - 2
mcs/class/System/System.Net.NetworkInformation/IPInterfaceProperties.cs

@@ -1,10 +1,11 @@
 //
 // System.Net.NetworkInformation.IPInterfaceProperties
 //
-// Author:
+// Authors:
 //	Gonzalo Paniagua Javier ([email protected])
+//	Atsushi Enomoto ([email protected])
 //
-// Copyright (c) 2006 Novell, Inc. (http://www.novell.com)
+// Copyright (c) 2006-2007 Novell, Inc. (http://www.novell.com)
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
@@ -46,6 +47,84 @@ namespace System.Net.NetworkInformation {
 		public abstract UnicastIPAddressInformationCollection UnicastAddresses { get; }
 		public abstract IPAddressCollection WinsServersAddresses { get; }
 	}
+
+	class Win32IPInterfaceProperties2 : IPInterfaceProperties
+	{
+		readonly Win32_IP_ADAPTER_ADDRESSES addr;
+		readonly Win32_MIB_IFROW mib4, mib6;
+
+		public Win32IPInterfaceProperties2 (Win32_IP_ADAPTER_ADDRESSES addr, Win32_MIB_IFROW mib4, Win32_MIB_IFROW mib6)
+		{
+			this.addr = addr;
+			this.mib4 = mib4;
+			this.mib6 = mib6;
+		}
+
+		public override IPv4InterfaceProperties GetIPv4Properties ()
+		{
+			Win32_IP_ADAPTER_INFO v4info = Win32NetworkInterface2.GetAdapterInfoByIndex (mib4.Index);
+			return v4info != null ? new Win32IPv4InterfaceProperties (v4info, mib4) : null;
+		}
+
+		public override IPv6InterfaceProperties GetIPv6Properties ()
+		{
+			Win32_IP_ADAPTER_INFO v6info = Win32NetworkInterface2.GetAdapterInfoByIndex (mib6.Index);
+			return v6info != null ? new Win32IPv6InterfaceProperties (mib6) : null;
+		}
+
+		public override IPAddressInformationCollection AnycastAddresses {
+			get { return IPAddressInformationImplCollection.FromAnycast (addr.FirstAnycastAddress); }
+		}
+
+		public override IPAddressCollection DhcpServerAddresses {
+			get {
+				Win32_IP_ADAPTER_INFO v4info = Win32NetworkInterface2.GetAdapterInfoByIndex (mib4.Index);
+				// FIXME: should ipv6 DhcpServer be considered?
+				return v4info != null ? new Win32IPAddressCollection (v4info.DhcpServer) : Win32IPAddressCollection.Empty;
+			}
+		}
+
+		public override IPAddressCollection DnsAddresses {
+			get { return Win32IPAddressCollection.FromDnsServer (addr.FirstDnsServerAddress); }
+		}
+
+		public override string DnsSuffix {
+			get { return addr.DnsSuffix; }
+		}
+
+		public override GatewayIPAddressInformationCollection GatewayAddresses {
+			get {
+				Win32_IP_ADAPTER_INFO v4info = Win32NetworkInterface2.GetAdapterInfoByIndex (mib4.Index);
+				// FIXME: should ipv6 DhcpServer be considered?
+				return v4info != null ? new Win32GatewayIPAddressInformationCollection (v4info.GatewayList) : Win32GatewayIPAddressInformationCollection.Empty;
+			}
+		}
+
+		public override bool IsDnsEnabled {
+			get { return Win32NetworkInterface2.FixedInfo.EnableDns != 0; }
+		}
+
+		public override bool IsDynamicDnsEnabled {
+			get { return addr.DdnsEnabled; }
+		}
+
+		public override MulticastIPAddressInformationCollection MulticastAddresses {
+			get { return Win32MulticastIPAddressInformationCollection.FromMulticast (addr.FirstMulticastAddress); }
+		}
+
+		public override UnicastIPAddressInformationCollection UnicastAddresses {
+			get { return Win32UnicastIPAddressInformationCollection.FromUnicast (addr.FirstUnicastAddress); }
+		}
+
+		public override IPAddressCollection WinsServersAddresses {
+			get {
+				Win32_IP_ADAPTER_INFO v4info = Win32NetworkInterface2.GetAdapterInfoByIndex (mib4.Index);
+				// FIXME: should ipv6 DhcpServer be considered?
+				return v4info != null ? new Win32IPAddressCollection (v4info.PrimaryWinsServer, v4info.SecondaryWinsServer) : Win32IPAddressCollection.Empty;
+			}
+		}
+
+	}
 }
 #endif
 

+ 67 - 2
mcs/class/System/System.Net.NetworkInformation/IPv4InterfaceProperties.cs

@@ -1,10 +1,11 @@
 //
 // System.Net.NetworkInformation.IPv4InterfaceProperties
 //
-// Author:
+// Authors:
 //	Gonzalo Paniagua Javier ([email protected])
+//	Atsushi Enomoto ([email protected])
 //
-// Copyright (c) 2006 Novell, Inc. (http://www.novell.com)
+// Copyright (c) 2006-2007 Novell, Inc. (http://www.novell.com)
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
@@ -26,6 +27,8 @@
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 #if NET_2_0
+using System.Runtime.InteropServices;
+
 namespace System.Net.NetworkInformation {
 	public abstract class IPv4InterfaceProperties {
 		protected IPv4InterfaceProperties ()
@@ -40,6 +43,68 @@ namespace System.Net.NetworkInformation {
 		public abstract int Mtu { get; }
 		public abstract bool UsesWins { get; }
 	}
+
+	class Win32IPv4InterfaceProperties : IPv4InterfaceProperties
+	{
+		[DllImport ("iphlpapi.dll")]
+		static extern int GetPerAdapterInfo (int IfIndex, Win32_IP_PER_ADAPTER_INFO pPerAdapterInfo, ref int pOutBufLen);
+
+		Win32_IP_ADAPTER_INFO ainfo;
+		Win32_IP_PER_ADAPTER_INFO painfo;
+		Win32_MIB_IFROW mib;
+
+		public Win32IPv4InterfaceProperties (Win32_IP_ADAPTER_INFO ainfo, Win32_MIB_IFROW mib)
+		{
+			this.ainfo = ainfo;
+			this.mib = mib;
+
+			// get per-adapter info.
+			int size = 0;
+			GetPerAdapterInfo (mib.Index, null, ref size);
+			painfo = new Win32_IP_PER_ADAPTER_INFO ();
+			int ret = GetPerAdapterInfo (mib.Index, painfo, ref size);
+			if (ret != 0)
+				throw new NetworkInformationException (ret);
+		}
+
+		public override int Index {
+			get { return mib.Index; }
+		}
+
+		public override bool IsAutomaticPrivateAddressingActive {
+			get { return painfo.AutoconfigActive != 0; }
+		}
+
+		public override bool IsAutomaticPrivateAddressingEnabled {
+			get { return painfo.AutoconfigEnabled != 0; }
+		}
+
+		public override bool IsDhcpEnabled {
+			get { return ainfo.DhcpEnabled != 0; }
+		}
+
+		public override bool IsForwardingEnabled {
+			// Is it the right answer? In Vista there is MIB_IPINTERFACEROW.ForwardingEnabled, but not in former versions.
+			get { return Win32NetworkInterface2.FixedInfo.EnableRouting != 0; }
+		}
+
+		public override int Mtu {
+			get { return mib.Mtu; }
+		}
+
+		public override bool UsesWins {
+			get { return ainfo.HaveWins; }
+		}
+	}
+
+	[StructLayout (LayoutKind.Sequential)]
+	class Win32_IP_PER_ADAPTER_INFO
+	{
+		public uint AutoconfigEnabled;
+		public uint AutoconfigActive;
+		public IntPtr CurrentDnsServer; // to Win32_IP_ADDR_STRING
+		public Win32_IP_ADDR_STRING DnsServerList;
+	}
 }
 #endif
 

+ 62 - 2
mcs/class/System/System.Net.NetworkInformation/IPv4InterfaceStatistics.cs

@@ -1,10 +1,11 @@
 //
 // System.Net.NetworkInformation.IPv4InterfaceStatistics
 //
-// Author:
+// Authors:
 //	Gonzalo Paniagua Javier ([email protected])
+//	Atsushi Enomoto ([email protected])
 //
-// Copyright (c) 2006 Novell, Inc. (http://www.novell.com)
+// Copyright (c) 2006-2007 Novell, Inc. (http://www.novell.com)
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
@@ -45,6 +46,65 @@ namespace System.Net.NetworkInformation {
 		public abstract long UnicastPacketsReceived { get; }
 		public abstract long UnicastPacketsSent { get; }
 	}
+
+	class Win32IPv4InterfaceStatistics : IPv4InterfaceStatistics
+	{
+		Win32_MIB_IFROW info;
+
+		public Win32IPv4InterfaceStatistics (Win32_MIB_IFROW info)
+		{
+			this.info = info;
+		}
+
+		public override long BytesReceived {
+			get { return info.InOctets; }
+		}
+
+		public override long BytesSent {
+			get { return info.OutOctets; }
+		}
+
+		public override long IncomingPacketsDiscarded {
+			get { return info.InDiscards; }
+		}
+
+		public override long IncomingPacketsWithErrors {
+			get { return info.InErrors; }
+		}
+
+		public override long IncomingUnknownProtocolPackets {
+			get { return info.InUnknownProtos; }
+		}
+
+		public override long NonUnicastPacketsReceived {
+			get { return info.InNUcastPkts; }
+		}
+
+		public override long NonUnicastPacketsSent {
+			get { return info.OutNUcastPkts; }
+		}
+
+		public override long OutgoingPacketsDiscarded {
+			get { return info.OutDiscards; }
+		}
+
+		public override long OutgoingPacketsWithErrors {
+			get { return info.OutErrors; }
+		}
+
+		public override long OutputQueueLength {
+			get { return info.OutQLen; }
+		}
+
+		public override long UnicastPacketsReceived {
+			get { return info.InUcastPkts; }
+		}
+
+		public override long UnicastPacketsSent {
+			get { return info.OutUcastPkts; }
+		}
+
+	}
 }
 #endif
 

+ 21 - 2
mcs/class/System/System.Net.NetworkInformation/IPv6InterfaceProperties.cs

@@ -1,10 +1,11 @@
 //
 // System.Net.NetworkInformation.IPv6InterfaceProperties
 //
-// Author:
+// Authors:
 //	Gonzalo Paniagua Javier ([email protected])
+//	Atsushi Enomoto ([email protected])
 //
-// Copyright (c) 2006 Novell, Inc. (http://www.novell.com)
+// Copyright (c) 2006-2007 Novell, Inc. (http://www.novell.com)
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
@@ -35,6 +36,24 @@ namespace System.Net.NetworkInformation {
 		public abstract int Index { get; }
 		public abstract int Mtu { get; }
 	}
+
+	class Win32IPv6InterfaceProperties : IPv6InterfaceProperties
+	{
+		Win32_MIB_IFROW mib;
+
+		public Win32IPv6InterfaceProperties (Win32_MIB_IFROW mib)
+		{
+			this.mib = mib;
+		}
+
+		public override int Index {
+			get { return mib.Index; }
+		}
+
+		public override int Mtu {
+			get { return mib.Mtu; }
+		}
+	}
 }
 #endif
 

+ 56 - 2
mcs/class/System/System.Net.NetworkInformation/MulticastIPAddressInformation.cs

@@ -1,10 +1,11 @@
 //
 // System.Net.NetworkInformation.MulticastIPAddressInformation
 //
-// Author:
+// Authors:
 //	Gonzalo Paniagua Javier ([email protected])
+//	Atsushi Enomoto ([email protected])
 //
-// Copyright (c) 2006 Novell, Inc. (http://www.novell.com)
+// Copyright (c) 2006-2007 Novell, Inc. (http://www.novell.com)
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
@@ -26,6 +27,8 @@
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 #if NET_2_0
+using System.Runtime.InteropServices;
+
 namespace System.Net.NetworkInformation {
 	public abstract class MulticastIPAddressInformation : IPAddressInformation {
 		protected MulticastIPAddressInformation ()
@@ -39,6 +42,57 @@ namespace System.Net.NetworkInformation {
 		public abstract PrefixOrigin PrefixOrigin { get; }
 		public abstract SuffixOrigin SuffixOrigin { get; }
 	}
+
+	// So, why are there many pointless members in the base class?
+	class Win32MulticastIPAddressInformation : MulticastIPAddressInformation
+	{
+		IPAddress address;
+		bool is_dns_eligible, is_transient;
+
+		public Win32MulticastIPAddressInformation (IPAddress address, bool isDnsEligible, bool isTransient)
+		{
+			this.address = address;
+			this.is_dns_eligible = isDnsEligible;
+			this.is_transient = isTransient;
+		}
+
+		public override IPAddress Address {
+			get { return address; }
+		}
+
+		public override bool IsDnsEligible {
+			get { return is_dns_eligible; }
+		}
+
+		public override bool IsTransient {
+			get { return is_transient; }
+		}
+
+		public override long AddressPreferredLifetime {
+			get { return 0; }
+		}
+
+		public override long AddressValidLifetime {
+			get { return 0; }
+		}
+
+		public override long DhcpLeaseLifetime {
+			get { return 0; }
+		}
+
+		public override DuplicateAddressDetectionState DuplicateAddressDetectionState {
+			get { return DuplicateAddressDetectionState.Invalid; }
+		}
+
+		public override PrefixOrigin PrefixOrigin {
+			get { return PrefixOrigin.Other; }
+		}
+
+		public override SuffixOrigin SuffixOrigin {
+			get { return SuffixOrigin.Other; }
+		}
+
+	}
 }
 #endif
 

+ 46 - 6
mcs/class/System/System.Net.NetworkInformation/MulticastIPAddressInformationCollection.cs

@@ -1,10 +1,11 @@
 //
 // System.Net.NetworkInformation.MulticastIPAddressInformationCollection
 //
-// Author:
+// Authors:
 //	Gonzalo Paniagua Javier ([email protected])
+//	Atsushi Enomoto ([email protected])
 //
-// Copyright (c) 2006 Novell, Inc. (http://www.novell.com)
+// Copyright (c) 2006-2007 Novell, Inc. (http://www.novell.com)
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
@@ -28,10 +29,11 @@
 #if NET_2_0
 using System.Collections;
 using System.Collections.Generic;
+using System.Runtime.InteropServices;
 
 namespace System.Net.NetworkInformation {
 	public class MulticastIPAddressInformationCollection : ICollection<MulticastIPAddressInformation>, IEnumerable<MulticastIPAddressInformation>, IEnumerable {
-		List<MulticastIPAddressInformation> list; // We want an internal ctor that fills this list up.
+		List<MulticastIPAddressInformation> list = new List<MulticastIPAddressInformation> ();
 		
 		protected internal MulticastIPAddressInformationCollection ()
 		{
@@ -39,12 +41,16 @@ namespace System.Net.NetworkInformation {
 
 		public virtual void Add (MulticastIPAddressInformation address)
 		{
-			throw new NotSupportedException ("The collection is read-only.");
+			if (IsReadOnly)
+				throw new NotSupportedException ("The collection is read-only.");
+			list.Add (address);
 		}
 
 		public virtual void Clear ()
 		{
-			throw new NotSupportedException ("The collection is read-only.");
+			if (IsReadOnly)
+				throw new NotSupportedException ("The collection is read-only.");
+			list.Clear ();
 		}
 
 		public virtual bool Contains (MulticastIPAddressInformation address)
@@ -64,7 +70,9 @@ namespace System.Net.NetworkInformation {
 
 		public virtual bool Remove (MulticastIPAddressInformation address)
 		{
-			throw new NotSupportedException ("The collection is read-only.");
+			if (IsReadOnly)
+				throw new NotSupportedException ("The collection is read-only.");
+			return list.Remove (address);
 		}
 
 		IEnumerator IEnumerable.GetEnumerator ()
@@ -84,6 +92,38 @@ namespace System.Net.NetworkInformation {
 			get { return list [index]; }
 		}
 	}
+
+	class Win32MulticastIPAddressInformationCollection : MulticastIPAddressInformationCollection
+	{
+		public static readonly Win32MulticastIPAddressInformationCollection Empty = new Win32MulticastIPAddressInformationCollection (true);
+
+		bool is_readonly;
+
+		// for static methods
+		Win32MulticastIPAddressInformationCollection (bool isReadOnly)
+		{
+			is_readonly = isReadOnly;
+		}
+
+		public override bool IsReadOnly {
+			get { return is_readonly; }
+		}
+
+		public static Win32MulticastIPAddressInformationCollection FromMulticast (IntPtr ptr)
+		{
+			Win32MulticastIPAddressInformationCollection c = new Win32MulticastIPAddressInformationCollection (false);
+			Win32_IP_ADAPTER_MULTICAST_ADDRESS a;
+			for (IntPtr p = ptr; p != IntPtr.Zero; p = a.Next) {
+				a = (Win32_IP_ADAPTER_MULTICAST_ADDRESS) Marshal.PtrToStructure (p, typeof (Win32_IP_ADAPTER_MULTICAST_ADDRESS));
+				c.Add (new Win32MulticastIPAddressInformation (
+				       a.Address.GetIPAddress (),
+				       a.LengthFlags.IsDnsEligible,
+				       a.LengthFlags.IsTransient));
+			}
+			c.is_readonly = true;
+			return c;
+		}
+	}
 }
 #endif
 

+ 192 - 4
mcs/class/System/System.Net.NetworkInformation/NetworkInterface.cs

@@ -1,10 +1,11 @@
 //
 // System.Net.NetworkInformation.NetworkInterface
 //
-// Author:
+// Authors:
 //	Gonzalo Paniagua Javier ([email protected])
+//	Atsushi Enomoto ([email protected])
 //
-// Copyright (c) 2006 Novell, Inc. (http://www.novell.com)
+// Copyright (c) 2006-2007 Novell, Inc. (http://www.novell.com)
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
@@ -27,7 +28,10 @@
 //
 #if NET_2_0
 using System;
+using System.Collections.Generic;
 using System.Net;
+using System.Runtime.InteropServices;
+using System.Text;
 
 namespace System.Net.NetworkInformation {
 	public abstract class NetworkInterface {
@@ -35,10 +39,17 @@ namespace System.Net.NetworkInformation {
 		{
 		}
 
-		[MonoTODO]
+		[MonoTODO ("unimplemented on Non-Windows")]
 		public static NetworkInterface [] GetAllNetworkInterfaces ()
 		{
-			return new NetworkInterface [0];
+			switch (Environment.OSVersion.Platform) {
+			case PlatformID.Unix:
+				throw new NotSupportedException ("This platform is not supported");
+			default:
+				if (Environment.OSVersion.Version >= new Version (5, 1))
+					return Win32NetworkInterface2.GetAllNetworkInterfaces ();
+				throw new NotImplementedException ();
+			}
 		}
 
 		[MonoTODO]
@@ -66,6 +77,183 @@ namespace System.Net.NetworkInformation {
 		public abstract long Speed { get; }
 		public abstract bool SupportsMulticast { get; }
 	}
+
+	class Win32NetworkInterface2 : NetworkInterface
+	{
+		[DllImport ("iphlpapi.dll", SetLastError = true)]
+		static extern int GetNetworkParams (byte [] bytes, ref int size);
+
+		[DllImport ("iphlpapi.dll", SetLastError = true)]
+		static extern int GetAdaptersInfo (byte [] info, ref int size);
+
+		[DllImport ("iphlpapi.dll", SetLastError = true)]
+		static extern int GetAdaptersAddresses (uint family, uint flags, IntPtr reserved, byte [] info, ref int size);
+
+		[DllImport ("iphlpapi.dll", SetLastError = true)]
+		static extern int GetIfEntry (ref Win32_MIB_IFROW row);
+
+		static Win32_FIXED_INFO fixed_info;
+
+		public static Win32_FIXED_INFO FixedInfo {
+			get {
+				if (fixed_info == null)
+					fixed_info = GetFixedInfo ();
+				return fixed_info;
+			}
+		}
+
+		static Win32_FIXED_INFO GetFixedInfo ()
+		{
+			int len = 0;
+			byte [] bytes = null;
+			GetNetworkParams (null, ref len);
+			bytes = new byte [len];
+			GetNetworkParams (bytes, ref len);
+			Win32_FIXED_INFO info = new Win32_FIXED_INFO ();
+			unsafe {
+				fixed (byte* ptr = bytes) {
+					Marshal.PtrToStructure ((IntPtr) ptr, info);
+				}
+			}
+			return info;
+		}
+
+		public static NetworkInterface [] GetAllNetworkInterfaces ()
+		{
+			Win32_IP_ADAPTER_INFO [] ai = GetAdaptersInfo ();
+			Win32_IP_ADAPTER_ADDRESSES [] aa = GetAdaptersAddresses ();
+			NetworkInterface [] ret = new NetworkInterface [aa.Length];
+			for (int i = 0; i < ret.Length; i++)
+				ret [i] = new Win32NetworkInterface2 (aa [i]);
+			return ret;
+		}
+
+		public static Win32_IP_ADAPTER_INFO GetAdapterInfoByIndex (int index)
+		{
+			foreach (Win32_IP_ADAPTER_INFO info in GetAdaptersInfo ())
+				if (info.Index == index)
+					return info;
+			return null;
+		}
+
+		unsafe static Win32_IP_ADAPTER_INFO [] GetAdaptersInfo ()
+		{
+			byte [] bytes = null;
+			int len = 0;
+			GetAdaptersInfo (bytes, ref len);
+			bytes = new byte [len];
+			int ret = GetAdaptersInfo (bytes, ref len);
+
+			if (ret != 0)
+				throw new NetworkInformationException (ret);
+
+			List<Win32_IP_ADAPTER_INFO> l = new List<Win32_IP_ADAPTER_INFO> ();
+			fixed (byte* ptr = bytes) {
+				Win32_IP_ADAPTER_INFO info;
+				for (IntPtr p = (IntPtr) ptr; p != IntPtr.Zero; p = info.Next) {
+					info = new Win32_IP_ADAPTER_INFO ();
+					Marshal.PtrToStructure (p, info);
+					l.Add (info);
+				}
+			}
+			return l.ToArray ();
+		}
+
+		unsafe static Win32_IP_ADAPTER_ADDRESSES [] GetAdaptersAddresses ()
+		{
+			byte [] bytes = null;
+			int len = 0;
+			GetAdaptersAddresses (0, 0, IntPtr.Zero, bytes, ref len);
+			bytes = new byte [len];
+			int ret = GetAdaptersAddresses (0, 0, IntPtr.Zero, bytes, ref len);
+			if (ret != 0)
+				throw new NetworkInformationException (ret);
+
+			List<Win32_IP_ADAPTER_ADDRESSES> l = new List<Win32_IP_ADAPTER_ADDRESSES> ();
+			fixed (byte* ptr = bytes) {
+				Win32_IP_ADAPTER_ADDRESSES info;
+				for (IntPtr p = (IntPtr) ptr; p != IntPtr.Zero; p = info.Next) {
+					info = new Win32_IP_ADAPTER_ADDRESSES ();
+					Marshal.PtrToStructure (p, info);
+					l.Add (info);
+				}
+			}
+			return l.ToArray ();
+		}
+
+		Win32_IP_ADAPTER_ADDRESSES addr;
+		Win32_MIB_IFROW mib4, mib6;
+		Win32IPv4InterfaceStatistics ip4stats;
+		IPInterfaceProperties ip_if_props;
+
+		Win32NetworkInterface2 (Win32_IP_ADAPTER_ADDRESSES addr)
+		{
+			this.addr = addr;
+			mib4 = default (Win32_MIB_IFROW);
+			mib4.Index = addr.Alignment.IfIndex;
+			if (GetIfEntry (ref mib4) != 0)
+				mib4.Index = -1; // unavailable;
+			mib6 = default (Win32_MIB_IFROW);
+			mib6.Index = addr.Ipv6IfIndex;
+			if (GetIfEntry (ref mib6) != 0)
+				mib6.Index = -1; // unavailable;
+			ip4stats = new Win32IPv4InterfaceStatistics (mib4);
+			ip_if_props = new Win32IPInterfaceProperties2 (addr, mib4, mib6);
+		}
+
+		public override IPInterfaceProperties GetIPProperties ()
+		{
+			return ip_if_props;
+		}
+
+		public override IPv4InterfaceStatistics GetIPv4Statistics ()
+		{
+			return ip4stats;
+		}
+
+		public override PhysicalAddress GetPhysicalAddress ()
+		{
+			byte [] bytes = new byte [addr.PhysicalAddressLength];
+			Array.Copy (addr.PhysicalAddress, 0, bytes, 0, bytes.Length);
+			return new PhysicalAddress (bytes);
+		}
+
+		public override bool Supports (NetworkInterfaceComponent networkInterfaceComponent)
+		{
+			switch (networkInterfaceComponent) {
+			case NetworkInterfaceComponent.IPv4:
+				return mib4.Index >= 0;
+			case NetworkInterfaceComponent.IPv6:
+				return mib6.Index >= 0;
+			}
+			return false;
+		}
+
+		public override string Description {
+			get { return addr.Description; }
+		}
+		public override string Id {
+			get { return addr.AdapterName; }
+		}
+		public override bool IsReceiveOnly {
+			get { return addr.IsReceiveOnly; }
+		}
+		public override string Name {
+			get { return addr.FriendlyName; }
+		}
+		public override NetworkInterfaceType NetworkInterfaceType {
+			get { return addr.IfType; }
+		}
+		public override OperationalStatus OperationalStatus {
+			get { return addr.OperStatus; }
+		}
+		public override long Speed {
+			get { return mib6.Index >= 0 ? mib6.Speed : mib4.Speed; }
+		}
+		public override bool SupportsMulticast {
+			get { return !addr.NoMulticast; }
+		}
+	}
 }
 #endif
 

+ 58 - 2
mcs/class/System/System.Net.NetworkInformation/UnicastIPAddressInformation.cs

@@ -1,10 +1,11 @@
 //
 // System.Net.NetworkInformation.UnicastIPAddressInformation
 //
-// Author:
+// Authors:
 //	Gonzalo Paniagua Javier ([email protected])
+//	Atsushi Enomoto ([email protected])
 //
-// Copyright (c) 2006 Novell, Inc. (http://www.novell.com)
+// Copyright (c) 2006-2007 Novell, Inc. (http://www.novell.com)
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
@@ -27,6 +28,7 @@
 //
 #if NET_2_0
 using System;
+using System.Runtime.InteropServices;
 
 namespace System.Net.NetworkInformation {
 	public abstract class UnicastIPAddressInformation : IPAddressInformation {
@@ -42,6 +44,60 @@ namespace System.Net.NetworkInformation {
 		public abstract PrefixOrigin PrefixOrigin { get; }
 		public abstract SuffixOrigin SuffixOrigin { get; }
 	}
+
+	class Win32UnicastIPAddressInformation : UnicastIPAddressInformation 
+	{
+		Win32_IP_ADAPTER_UNICAST_ADDRESS info;
+
+		public Win32UnicastIPAddressInformation (Win32_IP_ADAPTER_UNICAST_ADDRESS info)
+		{
+			this.info = info;
+		}
+
+		public override IPAddress Address {
+			get { return info.Address.GetIPAddress (); }
+		}
+
+		public override bool IsDnsEligible {
+			get { return info.LengthFlags.IsDnsEligible; }
+		}
+
+		public override bool IsTransient {
+			get { return info.LengthFlags.IsTransient; }
+		}
+
+		// UnicastIPAddressInformation members
+
+		public override long AddressPreferredLifetime {
+			get { return info.PreferredLifetime; }
+		}
+
+		public override long AddressValidLifetime {
+			get { return info.ValidLifetime; }
+		}
+
+		public override long DhcpLeaseLifetime {
+			get { return info.LeaseLifetime; }
+		}
+
+		public override DuplicateAddressDetectionState DuplicateAddressDetectionState {
+			get { return info.DadState; }
+		}
+
+		// FIXME: where to get this info?
+		public override IPAddress IPv4Mask {
+			get { throw new NotImplementedException (); }
+		}
+
+		public override PrefixOrigin PrefixOrigin {
+			get { return info.PrefixOrigin; }
+		}
+
+		public override SuffixOrigin SuffixOrigin {
+			get { return info.SuffixOrigin; }
+		}
+
+	}
 }
 #endif
 

+ 43 - 6
mcs/class/System/System.Net.NetworkInformation/UnicastIPAddressInformationCollection.cs

@@ -1,10 +1,11 @@
 //
 // System.Net.NetworkInformation.UnicastIPAddressInformationCollection
 //
-// Author:
+// Authors:
 //	Gonzalo Paniagua Javier ([email protected])
+//	Atsushi Enomoto ([email protected])
 //
-// Copyright (c) 2006 Novell, Inc. (http://www.novell.com)
+// Copyright (c) 2006-2007 Novell, Inc. (http://www.novell.com)
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
@@ -29,12 +30,13 @@
 using System;
 using System.Collections;
 using System.Collections.Generic;
+using System.Runtime.InteropServices;
 
 namespace System.Net.NetworkInformation {
 	public class UnicastIPAddressInformationCollection : ICollection<UnicastIPAddressInformation>,
 						IEnumerable<UnicastIPAddressInformation> {
 
-		List<UnicastIPAddressInformation> list;
+		List<UnicastIPAddressInformation> list = new List<UnicastIPAddressInformation> ();
 
 		protected internal UnicastIPAddressInformationCollection ()
 		{
@@ -42,12 +44,16 @@ namespace System.Net.NetworkInformation {
 
 		public virtual void Add (UnicastIPAddressInformation address)
 		{
-			throw new NotSupportedException ("The collection is read-only.");
+			if (IsReadOnly)
+				throw new NotSupportedException ("The collection is read-only.");
+			list.Add (address);
 		}
 
 		public virtual void Clear ()
 		{
-			throw new NotSupportedException ("The collection is read-only.");
+			if (IsReadOnly)
+				throw new NotSupportedException ("The collection is read-only.");
+			list.Clear ();
 		}
 
 		public virtual bool Contains (UnicastIPAddressInformation address)
@@ -67,7 +73,9 @@ namespace System.Net.NetworkInformation {
 
 		public virtual bool Remove (UnicastIPAddressInformation address)
 		{
-			throw new NotSupportedException ("The collection is read-only.");
+			if (IsReadOnly)
+				throw new NotSupportedException ("The collection is read-only.");
+			return list.Remove (address);
 		}
 
 		IEnumerator IEnumerable.GetEnumerator ()
@@ -87,6 +95,35 @@ namespace System.Net.NetworkInformation {
 			get { return list [index]; }
 		}
 	}
+
+	class Win32UnicastIPAddressInformationCollection : UnicastIPAddressInformationCollection
+	{
+		public static readonly Win32UnicastIPAddressInformationCollection Empty = new Win32UnicastIPAddressInformationCollection (true);
+
+		bool is_readonly;
+
+		// for static methods
+		Win32UnicastIPAddressInformationCollection (bool isReadOnly)
+		{
+			is_readonly = isReadOnly;
+		}
+
+		public override bool IsReadOnly {
+			get { return is_readonly; }
+		}
+
+		public static Win32UnicastIPAddressInformationCollection FromUnicast (IntPtr ptr)
+		{
+			Win32UnicastIPAddressInformationCollection c = new Win32UnicastIPAddressInformationCollection (false);
+			Win32_IP_ADAPTER_UNICAST_ADDRESS a;
+			for (IntPtr p = ptr; p != IntPtr.Zero; p = a.Next) {
+				a = (Win32_IP_ADAPTER_UNICAST_ADDRESS) Marshal.PtrToStructure (p, typeof (Win32_IP_ADAPTER_UNICAST_ADDRESS));
+				c.Add (new Win32UnicastIPAddressInformation (a));
+			}
+			c.is_readonly = true;
+			return c;
+		}
+	}
 }
 #endif
 

+ 287 - 0
mcs/class/System/System.Net.NetworkInformation/Win32NetworkInterfaceMarshal.cs

@@ -0,0 +1,287 @@
+//
+// System.Net.NetworkInformation.NetworkInterface
+//
+// Author:
+//	Atsushi Enomoto ([email protected])
+//
+// Copyright (c) 2007 Novell, Inc. (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+#if NET_2_0
+using System;
+using System.Collections.Generic;
+using System.Net;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace System.Net.NetworkInformation
+{
+	// They are mostly defined in iptypes.h (included by iphlpapi.h).
+	// grep around /usr/include/w32api/* for identifiers you are curious.
+
+	[StructLayout (LayoutKind.Sequential)]
+	class Win32_FIXED_INFO
+	{
+		const int MAX_HOSTNAME_LEN = 128;
+		const int MAX_DOMAIN_NAME_LEN = 128;
+		const int MAX_SCOPE_ID_LEN = 256;
+
+		[MarshalAs (UnmanagedType.ByValTStr, SizeConst = MAX_HOSTNAME_LEN + 4)]
+		public string HostName;
+		[MarshalAs (UnmanagedType.ByValTStr, SizeConst = MAX_DOMAIN_NAME_LEN + 4)]
+		public string DomainName;
+		public IntPtr CurrentDnsServer; // to Win32IP_ADDR_STRING
+		public Win32_IP_ADDR_STRING DnsServerList;
+		public uint NodeType;
+		[MarshalAs (UnmanagedType.ByValTStr, SizeConst = MAX_SCOPE_ID_LEN + 4)]
+		public string ScopeId;
+		public uint EnableRouting;
+		public uint EnableProxy;
+		public uint EnableDns;
+	}
+
+	[StructLayout (LayoutKind.Explicit)]
+	struct AlignmentUnion
+	{
+		[FieldOffset (0)] // 1
+		public ulong Alignment;
+		[FieldOffset (0)] // 2-1
+		public int Length;
+		[FieldOffset (4)] // 2-2
+		public int IfIndex;
+	}
+
+	[StructLayout (LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+	class Win32_IP_ADAPTER_ADDRESSES {
+		public AlignmentUnion Alignment;
+		public IntPtr Next; // to Win32_IP_ADAPTER_ADDRESSES
+		[MarshalAs (UnmanagedType.LPStr)]
+		public string AdapterName; // PCHAR
+		public IntPtr FirstUnicastAddress; //to IP_ADAPTER_UNICAST_ADDRESS
+		public IntPtr FirstAnycastAddress; // to IP_ADAPTER_ANYCAST_ADDRESS
+		public IntPtr FirstMulticastAddress; // to IP_ADAPTER_MULTICAST_ADDRESS
+		public IntPtr FirstDnsServerAddress; // to IP_ADAPTER_DNS_SERVER_ADDRESS
+		public string DnsSuffix;
+		public string Description;
+		public string FriendlyName;
+		[MarshalAs (UnmanagedType.ByValArray, SizeConst = MAX_ADAPTER_ADDRESS_LENGTH)]
+		public byte [] PhysicalAddress;
+		public uint PhysicalAddressLength;
+		public uint Flags;
+		public uint Mtu;
+		public NetworkInterfaceType IfType;
+		public OperationalStatus OperStatus;
+		public int Ipv6IfIndex;
+		[MarshalAs (UnmanagedType.ByValArray, SizeConst = 16 * 4)]
+		public uint [] ZoneIndices;
+
+		// Note that Vista-only members and XP-SP1-only member are
+		// omitted.
+
+		const int MAX_ADAPTER_ADDRESS_LENGTH = 8;
+
+		const int IP_ADAPTER_DDNS_ENABLED = 1;
+		const int IP_ADAPTER_RECEIVE_ONLY = 8;
+		const int IP_ADAPTER_NO_MULTICAST = 0x10;
+
+		public bool DdnsEnabled {
+			get { return (Flags & IP_ADAPTER_DDNS_ENABLED) != 0; }
+		}
+
+		public bool IsReceiveOnly {
+			get { return (Flags & IP_ADAPTER_RECEIVE_ONLY) != 0; }
+		}
+
+		public bool NoMulticast {
+			get { return (Flags & IP_ADAPTER_NO_MULTICAST) != 0; }
+		}
+	}
+
+	[StructLayout (LayoutKind.Sequential)]
+	class Win32_IP_ADAPTER_INFO
+	{
+		const int MAX_ADAPTER_NAME_LENGTH = 256;
+		const int MAX_ADAPTER_DESCRIPTION_LENGTH = 128;
+		const int MAX_ADAPTER_ADDRESS_LENGTH = 8;
+
+		public IntPtr Next; // to Win32_IP_ADAPTER_INFO
+		public int ComboIndex;
+		[MarshalAs (UnmanagedType.ByValTStr, SizeConst = MAX_ADAPTER_NAME_LENGTH + 4)]
+		public string AdapterName;
+		[MarshalAs (UnmanagedType.ByValTStr, SizeConst = MAX_ADAPTER_DESCRIPTION_LENGTH + 4)]
+		public string Description;
+		public uint AddressLength;
+		[MarshalAs (UnmanagedType.ByValArray, SizeConst = MAX_ADAPTER_ADDRESS_LENGTH)]
+		public byte [] Address;
+		public uint Index;
+		public uint Type;
+		public uint DhcpEnabled;
+		public IntPtr CurrentIpAddress; // Win32_IP_ADDR_STRING
+		public Win32_IP_ADDR_STRING IpAddressList;
+		public Win32_IP_ADDR_STRING GatewayList;
+		public Win32_IP_ADDR_STRING DhcpServer;
+		public bool HaveWins;
+		public Win32_IP_ADDR_STRING PrimaryWinsServer;
+		public Win32_IP_ADDR_STRING SecondaryWinsServer;
+		public long LeaseObtained;
+		public long LeaseExpires;
+	}
+
+	[StructLayout (LayoutKind.Sequential)]
+	struct Win32_MIB_IFROW
+	{
+		const int MAX_INTERFACE_NAME_LEN = 256;
+		const int MAXLEN_PHYSADDR = 8;
+		const int MAXLEN_IFDESCR = 256;
+
+		[MarshalAs (UnmanagedType.ByValArray, SizeConst = MAX_INTERFACE_NAME_LEN * 2)]
+		public char [] Name;
+		public int Index;
+		public NetworkInterfaceType Type;
+		public int Mtu;
+		public uint Speed;
+		public int PhysAddrLen;
+		[MarshalAs (UnmanagedType.ByValArray, SizeConst = MAXLEN_PHYSADDR)]
+		public byte [] PhysAddr;
+		public uint AdminStatus;
+		public uint OperStatus;
+		public uint LastChange;
+		public int InOctets;
+		public int InUcastPkts;
+		public int InNUcastPkts;
+		public int InDiscards;
+		public int InErrors;
+		public int InUnknownProtos;
+		public int OutOctets;
+		public int OutUcastPkts;
+		public int OutNUcastPkts;
+		public int OutDiscards;
+		public int OutErrors;
+		public int OutQLen;
+		public int DescrLen;
+		[MarshalAs (UnmanagedType.ByValArray, SizeConst = MAXLEN_IFDESCR)]
+		public byte [] Descr;
+	}
+
+	struct Win32_IP_ADDR_STRING
+	{
+		public IntPtr Next; // to Win32_IP_ADDR_STRING
+		[MarshalAs (UnmanagedType.ByValTStr, SizeConst = 16)]
+		public string IpAddress;
+		[MarshalAs (UnmanagedType.ByValTStr, SizeConst = 16)]
+		public string IpMask;
+		public uint Context;
+	}
+
+	[StructLayout (LayoutKind.Sequential)]
+	struct Win32LengthFlagsUnion
+	{
+		const int IP_ADAPTER_ADDRESS_DNS_ELIGIBLE = 1;
+		const int IP_ADAPTER_ADDRESS_TRANSIENT = 2;
+
+		// union { struct {
+		public uint Length;
+		public uint Flags;
+		// }; };
+
+		public bool IsDnsEligible {
+			get { return (Flags & IP_ADAPTER_ADDRESS_DNS_ELIGIBLE) != 0; }
+		}
+
+		public bool IsTransient {
+			get { return (Flags & IP_ADAPTER_ADDRESS_TRANSIENT) != 0; }
+		}
+	}
+
+	[StructLayout (LayoutKind.Sequential)]
+	struct Win32_IP_ADAPTER_ANYCAST_ADDRESS
+	{
+		public Win32LengthFlagsUnion LengthFlags;
+		public IntPtr Next; // to Win32_IP_ADAPTER_ANYCAST_ADDRESS
+		public Win32_SOCKET_ADDRESS Address;
+	}
+
+	[StructLayout (LayoutKind.Sequential)]
+	struct Win32_IP_ADAPTER_DNS_SERVER_ADDRESS
+	{
+		public Win32LengthFlagsUnion LengthFlags;
+		public IntPtr Next; // to Win32_IP_ADAPTER_DNS_SERVER_ADDRESS
+		public Win32_SOCKET_ADDRESS Address;
+	}
+
+	[StructLayout (LayoutKind.Sequential)]
+	struct Win32_IP_ADAPTER_MULTICAST_ADDRESS
+	{
+		public Win32LengthFlagsUnion LengthFlags;
+		public IntPtr Next; // to Win32_IP_ADAPTER_MULTICAST_ADDRESS
+		public Win32_SOCKET_ADDRESS Address;
+	}
+
+	[StructLayout (LayoutKind.Sequential)]
+	struct Win32_IP_ADAPTER_UNICAST_ADDRESS
+	{
+		public Win32LengthFlagsUnion LengthFlags;
+		public IntPtr Next; // to Win32_IP_ADAPTER_UNICAST_ADDRESS
+		public Win32_SOCKET_ADDRESS Address;
+		public PrefixOrigin PrefixOrigin;
+		public SuffixOrigin SuffixOrigin;
+		public DuplicateAddressDetectionState DadState;
+		public uint ValidLifetime;
+		public uint PreferredLifetime;
+		public uint LeaseLifetime;
+		public byte OnLinkPrefixLength;
+
+	}
+
+	struct Win32_SOCKADDR
+	{
+		public ushort AddressFamily;
+		[MarshalAs (UnmanagedType.ByValArray, SizeConst = 14 * 2)]
+		public byte [] AddressData;
+	}
+
+	// FIXME: it somehow fails to marshal.
+	struct Win32_SOCKET_ADDRESS
+	{
+		public IntPtr Sockaddr; // to Win32_SOCKADDR
+		public int SockaddrLength;
+
+		public IPAddress GetIPAddress ()
+		{
+			Win32_SOCKADDR sa = (Win32_SOCKADDR) Marshal.PtrToStructure (Sockaddr, typeof (Win32_SOCKADDR));
+//foreach (byte b in sa.AddressData) Console.Write ("{0:X02}", b); Console.WriteLine ();
+			byte [] arr;
+			if (sa.AddressFamily == AF_INET6) {
+				arr = new byte [16];
+				Array.Copy (sa.AddressData, 6, arr, 0, 16);
+			} else {
+				arr = new byte [4];
+				Array.Copy (sa.AddressData, 2, arr, 0, 4);
+			}
+//foreach (byte b in arr) Console.Write ("{0:X02}", b); Console.WriteLine ();
+			return new IPAddress (arr);
+		}
+
+		const int AF_INET6 = 23;
+	}
+}
+#endif
+

+ 1 - 0
mcs/class/System/System.dll.sources

@@ -773,6 +773,7 @@ System.Net.NetworkInformation/TcpStatistics.cs
 System.Net.NetworkInformation/UdpStatistics.cs
 System.Net.NetworkInformation/UnicastIPAddressInformationCollection.cs
 System.Net.NetworkInformation/UnicastIPAddressInformation.cs
+System.Net.NetworkInformation/Win32NetworkInterfaceMarshal.cs
 System.Net/NtlmClient.cs
 System/NetPipeStyleUriParser.cs
 System.Net/ProtocolViolationException.cs