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