BindingFlags.Public needed here as Exception.HResult is now public in .NET 4.5. This...
[mono.git] / mcs / class / System / System.Net.NetworkInformation / NetworkInterface.cs
1 //
2 // System.Net.NetworkInformation.NetworkInterface
3 //
4 // Authors:
5 //      Gonzalo Paniagua Javier (gonzalo@novell.com)
6 //      Atsushi Enomoto (atsushi@ximian.com)
7 //      Miguel de Icaza (miguel@novell.com)
8 //      Eric Butler (eric@extremeboredom.net)
9 //      Marek Habersack (mhabersack@novell.com)
10 //
11 // Copyright (c) 2006-2008 Novell, Inc. (http://www.novell.com)
12 //
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
20 // 
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
23 // 
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 //
32 #if NET_2_0
33 using System;
34 using System.Collections.Generic;
35 using System.Collections;
36 using System.Net;
37 using System.Net.Sockets;
38 using System.Runtime.InteropServices;
39 using System.Text;
40 using System.IO;
41 using System.Globalization;
42
43 namespace System.Net.NetworkInformation {
44         public abstract class NetworkInterface {
45                 static Version windowsVer51 = new Version (5, 1);
46                 static internal readonly bool runningOnUnix = (Environment.OSVersion.Platform == PlatformID.Unix);
47                 
48                 protected NetworkInterface ()
49                 {
50                 }
51
52                 public static NetworkInterface [] GetAllNetworkInterfaces ()
53                 {
54                         if (runningOnUnix) {
55                                 try {
56                                         if (Platform.IsMacOS)
57                                                 return MacOsNetworkInterface.ImplGetAllNetworkInterfaces ();
58                                         else
59                                                 return LinuxNetworkInterface.ImplGetAllNetworkInterfaces ();
60                                 } catch (SystemException ex) {
61                                         throw ex;
62                                 } catch {
63                                         return new NetworkInterface [0];
64                                 }
65                         } else {
66                                 if (Environment.OSVersion.Version >= windowsVer51)
67                                         return Win32NetworkInterface2.ImplGetAllNetworkInterfaces ();
68                                 return new NetworkInterface [0];
69                         }
70                 }
71
72                 [MonoTODO("Always returns true")]
73                 public static bool GetIsNetworkAvailable ()
74                 {
75                         return true;
76                 }
77
78                 internal static string ReadLine (string path)
79                 {
80                         using (FileStream fs = File.OpenRead (path)){
81                                 using (StreamReader sr = new StreamReader (fs)){
82                                         return sr.ReadLine ();
83                                 }
84                         }
85                 }
86                 
87                 [MonoTODO("Only works on Linux. Returns 0 on other systems.")]
88                 public static int LoopbackInterfaceIndex {
89                         get {
90                                 if (runningOnUnix) {
91                                         try {
92                                                 return UnixNetworkInterface.IfNameToIndex ("lo");
93                                         } catch  {
94                                                 return 0;
95                                         }
96                                 } else
97                                         return 0;
98                         }
99                 }
100
101                 public abstract IPInterfaceProperties GetIPProperties ();
102                 public abstract IPv4InterfaceStatistics GetIPv4Statistics ();
103                 public abstract PhysicalAddress GetPhysicalAddress ();
104                 public abstract bool Supports (NetworkInterfaceComponent networkInterfaceComponent);
105
106                 public abstract string Description { get; }
107                 public abstract string Id { get; }
108                 public abstract bool IsReceiveOnly { get; }
109                 public abstract string Name { get; }
110                 public abstract NetworkInterfaceType NetworkInterfaceType { get; }
111                 public abstract OperationalStatus OperationalStatus { get; }
112                 public abstract long Speed { get; }
113                 public abstract bool SupportsMulticast { get; }
114         }
115
116         abstract class UnixNetworkInterface : NetworkInterface
117         {
118                 [DllImport("libc")]
119                 static extern int if_nametoindex(string ifname);
120
121                 protected IPv4InterfaceStatistics ipv4stats;
122                 protected IPInterfaceProperties ipproperties;
123                 
124                 string               name;
125                 //int                  index;
126                 protected List <IPAddress> addresses;
127                 byte[]               macAddress;
128                 NetworkInterfaceType type;
129                 
130                 internal UnixNetworkInterface (string name)
131                 {
132                         this.name = name;
133                         addresses = new List<IPAddress> ();
134                 }
135
136                 public static int IfNameToIndex (string ifname)
137                 {
138                         return if_nametoindex(ifname);
139                 }
140                 
141                 internal void AddAddress (IPAddress address)
142                 {
143                         addresses.Add (address);
144                 }
145
146                 internal void SetLinkLayerInfo (int index, byte[] macAddress, NetworkInterfaceType type)
147                 {
148                         //this.index = index;
149                         this.macAddress = macAddress;
150                         this.type = type;
151                 }
152
153                 public override PhysicalAddress GetPhysicalAddress ()
154                 {
155                         if (macAddress != null)
156                                 return new PhysicalAddress (macAddress);
157                         else
158                                 return PhysicalAddress.None;
159                 }
160
161                 public override bool Supports (NetworkInterfaceComponent networkInterfaceComponent)
162                 {
163                         bool wantIPv4 = networkInterfaceComponent == NetworkInterfaceComponent.IPv4;
164                         bool wantIPv6 = wantIPv4 ? false : networkInterfaceComponent == NetworkInterfaceComponent.IPv6;
165                                 
166                         foreach (IPAddress address in addresses) {
167                                 if (wantIPv4 && address.AddressFamily == AddressFamily.InterNetwork)
168                                         return true;
169                                 else if (wantIPv6 && address.AddressFamily == AddressFamily.InterNetworkV6)
170                                         return true;
171                         }
172                         
173                         return false;
174                 }
175
176                 public override string Description {
177                         get { return name; }
178                 }
179
180                 public override string Id {
181                         get { return name; }
182                 }
183
184                 public override bool IsReceiveOnly {
185                         get { return false; }
186                 }
187
188                 public override string Name {
189                         get { return name; }
190                 }
191                 
192                 public override NetworkInterfaceType NetworkInterfaceType {
193                         get { return type; }
194                 }
195                 
196                 [MonoTODO ("Parse dmesg?")]
197                 public override long Speed {
198                         get {
199                                 // Bits/s
200                                 return 1000000;
201                         }
202                 }
203         }
204
205         //
206         // This class needs support from the libsupport.so library to fetch the
207         // data using arch-specific ioctls.
208         //
209         // For this to work, we have to create this on the factory above.
210         //
211         class LinuxNetworkInterface : UnixNetworkInterface
212         {
213                 [DllImport ("libc")]
214                 static extern int getifaddrs (out IntPtr ifap);
215
216                 [DllImport ("libc")]
217                 static extern void freeifaddrs (IntPtr ifap);
218
219                 const int AF_INET   = 2;
220                 const int AF_INET6  = 10;
221                 const int AF_PACKET = 17;
222                 
223                 //NetworkInterfaceType type;
224                 string               iface_path;
225                 string               iface_operstate_path;
226                 string               iface_flags_path;          
227
228                 internal string IfacePath {
229                         get { return iface_path; }
230                 }
231                 
232                 public static NetworkInterface [] ImplGetAllNetworkInterfaces ()
233                 {
234                         var interfaces = new Dictionary <string, LinuxNetworkInterface> ();
235                         IntPtr ifap;
236                         if (getifaddrs (out ifap) != 0)
237                                 throw new SystemException ("getifaddrs() failed");
238
239                         try {
240                                 IntPtr next = ifap;
241                                 while (next != IntPtr.Zero) {
242                                         ifaddrs   addr = (ifaddrs) Marshal.PtrToStructure (next, typeof (ifaddrs));
243                                         IPAddress address = IPAddress.None;
244                                         string    name = addr.ifa_name;
245                                         int       index = -1;
246                                         byte[]    macAddress = null;
247                                         NetworkInterfaceType type = NetworkInterfaceType.Unknown;
248
249                                         if (addr.ifa_addr != IntPtr.Zero) {
250                                                 sockaddr_in sockaddr = (sockaddr_in) Marshal.PtrToStructure (addr.ifa_addr, typeof (sockaddr_in));
251
252                                                 if (sockaddr.sin_family == AF_INET6) {
253                                                         sockaddr_in6 sockaddr6 = (sockaddr_in6) Marshal.PtrToStructure (addr.ifa_addr, typeof (sockaddr_in6));
254                                                         address = new IPAddress (sockaddr6.sin6_addr.u6_addr8, sockaddr6.sin6_scope_id);
255                                                 } else if (sockaddr.sin_family == AF_INET) {
256                                                         address = new IPAddress (sockaddr.sin_addr);
257                                                 } else if (sockaddr.sin_family == AF_PACKET) {
258                                                         sockaddr_ll sockaddrll = (sockaddr_ll) Marshal.PtrToStructure (addr.ifa_addr, typeof (sockaddr_ll));
259                                                         if (((int)sockaddrll.sll_halen) > sockaddrll.sll_addr.Length){
260                                                                 Console.Error.WriteLine ("Got a bad hardware address length for an AF_PACKET {0} {1}",
261                                                                                          sockaddrll.sll_halen, sockaddrll.sll_addr.Length);
262                                                                 next = addr.ifa_next;
263                                                                 continue;
264                                                         }
265                                                         
266                                                         macAddress = new byte [(int) sockaddrll.sll_halen];
267                                                         Array.Copy (sockaddrll.sll_addr, 0, macAddress, 0, macAddress.Length);
268                                                         index = sockaddrll.sll_ifindex;
269
270                                                         int hwtype = (int)sockaddrll.sll_hatype;
271                                                         if (Enum.IsDefined (typeof (LinuxArpHardware), hwtype)) {
272                                                                 switch ((LinuxArpHardware)hwtype) {
273                                                                         case LinuxArpHardware.EETHER:
274                                                                                 goto case LinuxArpHardware.ETHER;
275                                                                                 
276                                                                         case LinuxArpHardware.ETHER:
277                                                                                 type = NetworkInterfaceType.Ethernet;
278                                                                                 break;
279
280                                                                         case LinuxArpHardware.PRONET:
281                                                                                 type = NetworkInterfaceType.TokenRing;
282                                                                                 break;
283
284                                                                         case LinuxArpHardware.ATM:
285                                                                                 type = NetworkInterfaceType.Atm;
286                                                                                 break;
287                                                                         
288                                                                         case LinuxArpHardware.SLIP:
289                                                                                 type = NetworkInterfaceType.Slip;
290                                                                                 break;
291                                                                         
292                                                                         case LinuxArpHardware.PPP:
293                                                                                 type = NetworkInterfaceType.Ppp;
294                                                                                 break;
295                                                                         
296                                                                         case LinuxArpHardware.LOOPBACK:
297                                                                                 type = NetworkInterfaceType.Loopback;
298                                                                                 macAddress = null;
299                                                                                 break;
300
301                                                                         case LinuxArpHardware.FDDI:
302                                                                                 type = NetworkInterfaceType.Fddi;
303                                                                                 break;
304
305                                                                         case LinuxArpHardware.TUNNEL6:
306                                                                                 goto case LinuxArpHardware.TUNNEL;
307                                                                                 
308                                                                         case LinuxArpHardware.TUNNEL:
309                                                                                 type = NetworkInterfaceType.Tunnel;
310                                                                                 break;
311                                                                 }
312                                                         }
313                                                 }
314                                         }
315
316                                         LinuxNetworkInterface iface = null;
317
318                                         if (!interfaces.TryGetValue (name, out iface)) {
319                                                 iface = new LinuxNetworkInterface (name);
320                                                 interfaces.Add (name, iface);
321                                         }
322
323                                         if (!address.Equals (IPAddress.None))
324                                                 iface.AddAddress (address);
325
326                                         if (macAddress != null || type == NetworkInterfaceType.Loopback) {
327                                                 if (type == NetworkInterfaceType.Ethernet) {
328                                                         if (Directory.Exists(iface.IfacePath + "wireless")) {
329                                                                 type = NetworkInterfaceType.Wireless80211;
330                                                         }
331                                                 }
332                                                 iface.SetLinkLayerInfo (index, macAddress, type);
333                                         }
334
335                                         next = addr.ifa_next;
336                                 }
337                         } finally {
338                                 freeifaddrs (ifap);
339                         }
340
341                         NetworkInterface [] result = new NetworkInterface [interfaces.Count];
342                         int x = 0;
343                         foreach (NetworkInterface thisInterface in interfaces.Values) {
344                                 result [x] = thisInterface;
345                                 x++;
346                         }
347                         return result;
348                 }
349                 
350                 LinuxNetworkInterface (string name)
351                         : base (name)
352                 {
353                         iface_path = "/sys/class/net/" + name + "/";
354                         iface_operstate_path = iface_path + "operstate";
355                         iface_flags_path = iface_path + "flags";
356                 }
357
358                 public override IPInterfaceProperties GetIPProperties ()
359                 {
360                         if (ipproperties == null)
361                                 ipproperties = new LinuxIPInterfaceProperties (this, addresses);
362                         return ipproperties;
363                 }
364
365                 public override IPv4InterfaceStatistics GetIPv4Statistics ()
366                 {
367                         if (ipv4stats == null)
368                                 ipv4stats = new LinuxIPv4InterfaceStatistics (this);
369                         return ipv4stats;
370                 }
371
372                 public override OperationalStatus OperationalStatus {
373                         get {
374                                 if (!Directory.Exists (iface_path))
375                                         return OperationalStatus.Unknown;
376                                 
377                                 try {
378                                         string s = ReadLine (iface_operstate_path);
379
380                                         switch (s){
381                                                 case "unknown":
382                                                         return OperationalStatus.Unknown;
383                                                 
384                                                 case "notpresent":
385                                                         return OperationalStatus.NotPresent;
386
387                                                 case "down":
388                                                         return OperationalStatus.Down;
389
390                                                 case "lowerlayerdown":
391                                                         return OperationalStatus.LowerLayerDown;
392
393                                                 case "testing":
394                                                         return OperationalStatus.Testing;
395
396                                                 case "dormant":
397                                                         return OperationalStatus.Dormant;
398
399                                                 case "up":
400                                                         return OperationalStatus.Up;
401                                         }
402                                 } catch {
403                                 }
404                                 return OperationalStatus.Unknown;
405                         }
406                 }
407
408                 public override bool SupportsMulticast {
409                         get {
410                                 if (!Directory.Exists (iface_path))
411                                         return false;
412                                 
413                                 try {
414                                         string s = ReadLine (iface_flags_path);
415                                         if (s.Length > 2 && s [0] == '0' && s [1] == 'x')
416                                                 s = s.Substring (2);
417                                         
418                                         ulong f = UInt64.Parse (s, NumberStyles.HexNumber);
419
420                                         // Hardcoded, only useful for Linux.
421                                         return ((f & 0x1000) == 0x1000);
422                                 } catch {
423                                         return false;
424                                 }
425                         }
426                 }
427         }
428
429         class MacOsNetworkInterface : UnixNetworkInterface
430         {
431                 [DllImport ("libc")]
432                 static extern int getifaddrs (out IntPtr ifap);
433
434                 [DllImport ("libc")]
435                 static extern void freeifaddrs (IntPtr ifap);
436
437                 const int AF_INET  = 2;
438                 const int AF_INET6 = 30;
439                 const int AF_LINK  = 18;
440                 
441                 public static NetworkInterface [] ImplGetAllNetworkInterfaces ()
442                 {
443                         var interfaces = new Dictionary <string, MacOsNetworkInterface> ();
444                         IntPtr ifap;
445                         if (getifaddrs (out ifap) != 0)
446                                 throw new SystemException ("getifaddrs() failed");
447
448                         try {
449                                 IntPtr next = ifap;
450                                 while (next != IntPtr.Zero) {
451                                         MacOsStructs.ifaddrs addr = (MacOsStructs.ifaddrs) Marshal.PtrToStructure (next, typeof (MacOsStructs.ifaddrs));
452                                         IPAddress address = IPAddress.None;
453                                         string    name = addr.ifa_name;
454                                         int       index = -1;
455                                         byte[]    macAddress = null;
456                                         NetworkInterfaceType type = NetworkInterfaceType.Unknown;
457
458                                         if (addr.ifa_addr != IntPtr.Zero) {
459                                                 MacOsStructs.sockaddr sockaddr = (MacOsStructs.sockaddr) Marshal.PtrToStructure (addr.ifa_addr, typeof (MacOsStructs.sockaddr));
460
461                                                 if (sockaddr.sa_family == AF_INET6) {
462                                                         MacOsStructs.sockaddr_in6 sockaddr6 = (MacOsStructs.sockaddr_in6) Marshal.PtrToStructure (addr.ifa_addr, typeof (MacOsStructs.sockaddr_in6));
463                                                         address = new IPAddress (sockaddr6.sin6_addr.u6_addr8, sockaddr6.sin6_scope_id);
464                                                 } else if (sockaddr.sa_family == AF_INET) {
465                                                         MacOsStructs.sockaddr_in sockaddrin = (MacOsStructs.sockaddr_in) Marshal.PtrToStructure (addr.ifa_addr, typeof (MacOsStructs.sockaddr_in));
466                                                         address = new IPAddress (sockaddrin.sin_addr);
467                                                 } else if (sockaddr.sa_family == AF_LINK) {
468                                                         MacOsStructs.sockaddr_dl sockaddrdl = (MacOsStructs.sockaddr_dl) Marshal.PtrToStructure (addr.ifa_addr, typeof (MacOsStructs.sockaddr_dl));
469
470                                                         macAddress = new byte [(int) sockaddrdl.sdl_alen];
471                                                         Array.Copy (sockaddrdl.sdl_data, sockaddrdl.sdl_nlen, macAddress, 0, Math.Min (macAddress.Length, sockaddrdl.sdl_data.Length - sockaddrdl.sdl_nlen));
472                                                         index = sockaddrdl.sdl_index;
473
474                                                         int hwtype = (int) sockaddrdl.sdl_type;
475                                                         if (Enum.IsDefined (typeof (MacOsArpHardware), hwtype)) {
476                                                                 switch ((MacOsArpHardware) hwtype) {
477                                                                         case MacOsArpHardware.ETHER:
478                                                                                 type = NetworkInterfaceType.Ethernet;
479                                                                                 break;
480
481                                                                         case MacOsArpHardware.ATM:
482                                                                                 type = NetworkInterfaceType.Atm;
483                                                                                 break;
484                                                                         
485                                                                         case MacOsArpHardware.SLIP:
486                                                                                 type = NetworkInterfaceType.Slip;
487                                                                                 break;
488                                                                         
489                                                                         case MacOsArpHardware.PPP:
490                                                                                 type = NetworkInterfaceType.Ppp;
491                                                                                 break;
492                                                                         
493                                                                         case MacOsArpHardware.LOOPBACK:
494                                                                                 type = NetworkInterfaceType.Loopback;
495                                                                                 macAddress = null;
496                                                                                 break;
497
498                                                                         case MacOsArpHardware.FDDI:
499                                                                                 type = NetworkInterfaceType.Fddi;
500                                                                                 break;
501                                                                 }
502                                                         }
503                                                 }
504                                         }
505
506                                         MacOsNetworkInterface iface = null;
507
508                                         if (!interfaces.TryGetValue (name, out iface)) {
509                                                 iface = new MacOsNetworkInterface (name);
510                                                 interfaces.Add (name, iface);
511                                         }
512
513                                         if (!address.Equals (IPAddress.None))
514                                                 iface.AddAddress (address);
515
516                                         if (macAddress != null || type == NetworkInterfaceType.Loopback)
517                                                 iface.SetLinkLayerInfo (index, macAddress, type);
518
519                                         next = addr.ifa_next;
520                                 }
521                         } finally {
522                                 freeifaddrs (ifap);
523                         }
524
525                         NetworkInterface [] result = new NetworkInterface [interfaces.Count];
526                         int x = 0;
527                         foreach (NetworkInterface thisInterface in interfaces.Values) {
528                                 result [x] = thisInterface;
529                                 x++;
530                         }
531                         return result;
532                 }
533                 
534                 MacOsNetworkInterface (string name)
535                         : base (name)
536                 {
537                 }
538
539                 public override IPInterfaceProperties GetIPProperties ()
540                 {
541                         if (ipproperties == null)
542                                 ipproperties = new MacOsIPInterfaceProperties (this, addresses);
543                         return ipproperties;
544                 }
545
546                 public override IPv4InterfaceStatistics GetIPv4Statistics ()
547                 {
548                         if (ipv4stats == null)
549                                 ipv4stats = new MacOsIPv4InterfaceStatistics (this);
550                         return ipv4stats;
551                 }
552
553                 public override OperationalStatus OperationalStatus {
554                         get {
555                                 return OperationalStatus.Unknown;
556                         }
557                 }
558
559                 public override bool SupportsMulticast {
560                         get {
561                                 return false;
562                         }
563                 }
564         }
565
566         class Win32NetworkInterface2 : NetworkInterface
567         {
568                 [DllImport ("iphlpapi.dll", SetLastError = true)]
569                 static extern int GetAdaptersInfo (byte [] info, ref int size);
570
571                 [DllImport ("iphlpapi.dll", SetLastError = true)]
572                 static extern int GetAdaptersAddresses (uint family, uint flags, IntPtr reserved, byte [] info, ref int size);
573
574                 [DllImport ("iphlpapi.dll", SetLastError = true)]
575                 static extern int GetIfEntry (ref Win32_MIB_IFROW row);
576
577                 public static NetworkInterface [] ImplGetAllNetworkInterfaces ()
578                 {
579 //                      Win32_IP_ADAPTER_INFO [] ai = GetAdaptersInfo ();
580                         Win32_IP_ADAPTER_ADDRESSES [] aa = GetAdaptersAddresses ();
581                         NetworkInterface [] ret = new NetworkInterface [aa.Length];
582                         for (int i = 0; i < ret.Length; i++)
583                                 ret [i] = new Win32NetworkInterface2 (aa [i]);
584                         return ret;
585                 }
586
587                 public static Win32_IP_ADAPTER_INFO GetAdapterInfoByIndex (int index)
588                 {
589                         foreach (Win32_IP_ADAPTER_INFO info in GetAdaptersInfo ())
590                                 if (info.Index == index)
591                                         return info;
592                         return null;
593                 }
594
595                 unsafe static Win32_IP_ADAPTER_INFO [] GetAdaptersInfo ()
596                 {
597                         byte [] bytes = null;
598                         int len = 0;
599                         GetAdaptersInfo (bytes, ref len);
600                         bytes = new byte [len];
601                         int ret = GetAdaptersInfo (bytes, ref len);
602
603                         if (ret != 0)
604                                 throw new NetworkInformationException (ret);
605
606                         List<Win32_IP_ADAPTER_INFO> l = new List<Win32_IP_ADAPTER_INFO> ();
607                         fixed (byte* ptr = bytes) {
608                                 Win32_IP_ADAPTER_INFO info;
609                                 for (IntPtr p = (IntPtr) ptr; p != IntPtr.Zero; p = info.Next) {
610                                         info = new Win32_IP_ADAPTER_INFO ();
611                                         Marshal.PtrToStructure (p, info);
612                                         l.Add (info);
613                                 }
614                         }
615                         return l.ToArray ();
616                 }
617
618                 unsafe static Win32_IP_ADAPTER_ADDRESSES [] GetAdaptersAddresses ()
619                 {
620                         byte [] bytes = null;
621                         int len = 0;
622                         GetAdaptersAddresses (0, 0, IntPtr.Zero, bytes, ref len);
623                         bytes = new byte [len];
624                         int ret = GetAdaptersAddresses (0, 0, IntPtr.Zero, bytes, ref len);
625                         if (ret != 0)
626                                 throw new NetworkInformationException (ret);
627
628                         List<Win32_IP_ADAPTER_ADDRESSES> l = new List<Win32_IP_ADAPTER_ADDRESSES> ();
629                         fixed (byte* ptr = bytes) {
630                                 Win32_IP_ADAPTER_ADDRESSES info;
631                                 for (IntPtr p = (IntPtr) ptr; p != IntPtr.Zero; p = info.Next) {
632                                         info = new Win32_IP_ADAPTER_ADDRESSES ();
633                                         Marshal.PtrToStructure (p, info);
634                                         l.Add (info);
635                                 }
636                         }
637                         return l.ToArray ();
638                 }
639
640                 Win32_IP_ADAPTER_ADDRESSES addr;
641                 Win32_MIB_IFROW mib4, mib6;
642                 Win32IPv4InterfaceStatistics ip4stats;
643                 IPInterfaceProperties ip_if_props;
644
645                 Win32NetworkInterface2 (Win32_IP_ADAPTER_ADDRESSES addr)
646                 {
647                         this.addr = addr;
648                         mib4 = default (Win32_MIB_IFROW);
649                         mib4.Index = addr.Alignment.IfIndex;
650                         if (GetIfEntry (ref mib4) != 0)
651                                 mib4.Index = -1; // unavailable;
652                         mib6 = default (Win32_MIB_IFROW);
653                         mib6.Index = addr.Ipv6IfIndex;
654                         if (GetIfEntry (ref mib6) != 0)
655                                 mib6.Index = -1; // unavailable;
656                         ip4stats = new Win32IPv4InterfaceStatistics (mib4);
657                         ip_if_props = new Win32IPInterfaceProperties2 (addr, mib4, mib6);
658                 }
659
660                 public override IPInterfaceProperties GetIPProperties ()
661                 {
662                         return ip_if_props;
663                 }
664
665                 public override IPv4InterfaceStatistics GetIPv4Statistics ()
666                 {
667                         return ip4stats;
668                 }
669
670                 public override PhysicalAddress GetPhysicalAddress ()
671                 {
672                         byte [] bytes = new byte [addr.PhysicalAddressLength];
673                         Array.Copy (addr.PhysicalAddress, 0, bytes, 0, bytes.Length);
674                         return new PhysicalAddress (bytes);
675                 }
676
677                 public override bool Supports (NetworkInterfaceComponent networkInterfaceComponent)
678                 {
679                         switch (networkInterfaceComponent) {
680                         case NetworkInterfaceComponent.IPv4:
681                                 return mib4.Index >= 0;
682                         case NetworkInterfaceComponent.IPv6:
683                                 return mib6.Index >= 0;
684                         }
685                         return false;
686                 }
687
688                 public override string Description {
689                         get { return addr.Description; }
690                 }
691                 public override string Id {
692                         get { return addr.AdapterName; }
693                 }
694                 public override bool IsReceiveOnly {
695                         get { return addr.IsReceiveOnly; }
696                 }
697                 public override string Name {
698                         get { return addr.FriendlyName; }
699                 }
700                 public override NetworkInterfaceType NetworkInterfaceType {
701                         get { return addr.IfType; }
702                 }
703                 public override OperationalStatus OperationalStatus {
704                         get { return addr.OperStatus; }
705                 }
706                 public override long Speed {
707                         get { return mib6.Index >= 0 ? mib6.Speed : mib4.Speed; }
708                 }
709                 public override bool SupportsMulticast {
710                         get { return !addr.NoMulticast; }
711                 }
712         }
713 }
714 #endif
715