Merge pull request #1156 from felfert/master
[mono.git] / mcs / class / System / System.Net.NetworkInformation / IPGlobalProperties.cs
1 //
2 // System.Net.NetworkInformation.IPGlobalProperties
3 //
4 // Authors:
5 //      Gonzalo Paniagua Javier (gonzalo@novell.com)
6 //      Atsushi Enomoto (atsushi@ximian.com)
7 //
8 // Copyright (c) 2006-2007 Novell, Inc. (http://www.novell.com)
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 // 
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 // 
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 //
29
30 using System.Collections.Generic;
31 using System.Collections.Specialized;
32 using System.Globalization;
33 using System.IO;
34 using System.Net.Sockets;
35 using System.Runtime.InteropServices;
36 using System.Text;
37
38 namespace System.Net.NetworkInformation {
39         public abstract class IPGlobalProperties {
40                 protected IPGlobalProperties ()
41                 {
42                 }
43
44                 public static IPGlobalProperties GetIPGlobalProperties ()
45                 {
46                         switch (Environment.OSVersion.Platform) {
47                         case PlatformID.Unix:
48                                 MibIPGlobalProperties impl = null;
49                                 if (Directory.Exists (MibIPGlobalProperties.ProcDir)) {
50                                         impl = new MibIPGlobalProperties (MibIPGlobalProperties.ProcDir);
51                                         if (File.Exists (impl.StatisticsFile))
52                                                 return impl;
53                                 }
54                                 if (Directory.Exists (MibIPGlobalProperties.CompatProcDir)) {
55                                         impl = new MibIPGlobalProperties (MibIPGlobalProperties.CompatProcDir);
56                                         if (File.Exists (impl.StatisticsFile))
57                                                 return impl;
58                                 }
59                                 return new UnixIPGlobalProperties ();
60                         default:
61                                 return new Win32IPGlobalProperties ();
62                         }
63                 }
64
65                 internal static IPGlobalProperties InternalGetIPGlobalProperties()
66                 {
67                         return GetIPGlobalProperties ();
68                 }
69
70                 public abstract TcpConnectionInformation [] GetActiveTcpConnections ();
71                 public abstract IPEndPoint [] GetActiveTcpListeners ();
72                 public abstract IPEndPoint [] GetActiveUdpListeners ();
73                 public abstract IcmpV4Statistics GetIcmpV4Statistics ();
74                 public abstract IcmpV6Statistics GetIcmpV6Statistics ();
75                 public abstract IPGlobalStatistics GetIPv4GlobalStatistics ();
76                 public abstract IPGlobalStatistics GetIPv6GlobalStatistics ();
77                 public abstract TcpStatistics GetTcpIPv4Statistics ();
78                 public abstract TcpStatistics GetTcpIPv6Statistics ();
79                 public abstract UdpStatistics GetUdpIPv4Statistics ();
80                 public abstract UdpStatistics GetUdpIPv6Statistics ();
81
82                 public abstract string DhcpScopeName { get; }
83                 public abstract string DomainName { get; }
84                 public abstract string HostName { get; }
85                 public abstract bool IsWinsProxy { get; }
86                 public abstract NetBiosNodeType NodeType { get; }
87         }
88
89         abstract class CommonUnixIPGlobalProperties : IPGlobalProperties
90         {
91                 [DllImport ("libc")]
92                 static extern int gethostname ([MarshalAs (UnmanagedType.LPArray, SizeParamIndex = 1)] byte [] name, int len);
93
94                 [DllImport ("libc")]
95                 static extern int getdomainname ([MarshalAs (UnmanagedType.LPArray, SizeParamIndex = 1)] byte [] name, int len);
96
97                 public override string DhcpScopeName {
98                         get { return String.Empty; }
99                 }
100
101                 public override string DomainName {
102                         get {
103                                 byte [] bytes = new byte [256];
104                                 if (getdomainname (bytes, 256) != 0)
105                                         throw new NetworkInformationException ();
106                                 int len = Array.IndexOf<byte> (bytes, 0);
107                                 return Encoding.ASCII.GetString (bytes, 0, len < 0 ? 256 : len);
108                         }
109                 }
110
111                 public override string HostName {
112                         get {
113                                 byte [] bytes = new byte [256];
114                                 if (gethostname (bytes, 256) != 0)
115                                         throw new NetworkInformationException ();
116                                 int len = Array.IndexOf<byte> (bytes, 0);
117                                 return Encoding.ASCII.GetString (bytes, 0, len < 0 ? 256 : len);
118                         }
119                 }
120
121                 public override bool IsWinsProxy {
122                         get { return false; } // no WINS
123                 }
124
125                 public override NetBiosNodeType NodeType {
126                         get { return NetBiosNodeType.Unknown; } // no NetBios
127                 }
128         }
129
130         class UnixIPGlobalProperties : CommonUnixIPGlobalProperties
131         {
132                 public override TcpConnectionInformation [] GetActiveTcpConnections ()
133                 {
134                         throw new NotImplementedException ();
135                 }
136
137                 public override IPEndPoint [] GetActiveTcpListeners ()
138                 {
139                         throw new NotImplementedException ();
140                 }
141
142                 public override IPEndPoint [] GetActiveUdpListeners ()
143                 {
144                         throw new NotImplementedException ();
145                 }
146
147                 public override IcmpV4Statistics GetIcmpV4Statistics ()
148                 {
149                         throw new NotImplementedException ();
150                 }
151
152                 public override IcmpV6Statistics GetIcmpV6Statistics ()
153                 {
154                         throw new NotImplementedException ();
155                 }
156
157                 public override IPGlobalStatistics GetIPv4GlobalStatistics ()
158                 {
159                         throw new NotImplementedException ();
160                 }
161
162                 public override IPGlobalStatistics GetIPv6GlobalStatistics ()
163                 {
164                         throw new NotImplementedException ();
165                 }
166
167                 public override TcpStatistics GetTcpIPv4Statistics ()
168                 {
169                         throw new NotImplementedException ();
170                 }
171
172                 public override TcpStatistics GetTcpIPv6Statistics ()
173                 {
174                         throw new NotImplementedException ();
175                 }
176
177                 public override UdpStatistics GetUdpIPv4Statistics ()
178                 {
179                         throw new NotImplementedException ();
180                 }
181
182                 public override UdpStatistics GetUdpIPv6Statistics ()
183                 {
184                         throw new NotImplementedException ();
185                 }
186         }
187
188         // It expects /proc/net/snmp (or /usr/compat/linux/proc/net/snmp),
189         // formatted like:
190         // http://www.linuxdevcenter.com/linux/2000/11/16/example5.html
191         // http://www.linuxdevcenter.com/linux/2000/11/16/example2.html
192         class MibIPGlobalProperties : UnixIPGlobalProperties
193         {
194                 public const string ProcDir = "/proc";
195                 public const string CompatProcDir = "/usr/compat/linux/proc";
196
197                 public readonly string StatisticsFile, StatisticsFileIPv6, TcpFile, Tcp6File, UdpFile, Udp6File;
198
199                 public MibIPGlobalProperties (string procDir)
200                 {
201                         StatisticsFile = Path.Combine (procDir, "net/snmp");
202                         StatisticsFileIPv6 = Path.Combine (procDir, "net/snmp6");
203                         TcpFile = Path.Combine (procDir,"net/tcp");
204                         Tcp6File = Path.Combine (procDir,"net/tcp6");
205                         UdpFile = Path.Combine (procDir,"net/udp");
206                         Udp6File = Path.Combine (procDir,"net/udp6");
207                 }
208
209                 StringDictionary GetProperties4 (string item)
210                 {
211                         string file = StatisticsFile;
212
213                         string head = item + ": ";
214                         using (StreamReader sr = new StreamReader (file, Encoding.ASCII)) {
215                                 string [] keys = null;
216                                 string [] values = null;
217                                 string s = String.Empty;
218                                 do {
219                                         s = sr.ReadLine ();
220                                         if (String.IsNullOrEmpty (s))
221                                                 continue;
222                                         if (s.Length <= head.Length || String.CompareOrdinal (s, 0, head, 0, head.Length) != 0)
223                                                 continue;
224                                         if (keys == null)
225                                                 keys = s.Substring (head.Length).Split (' ');
226                                         else if (values != null)
227                                                 // hmm, there may be better error type...
228                                                 throw CreateException (file, String.Format ("Found duplicate line for values for the same item '{0}'", item));
229                                         else {
230                                                 values = s.Substring (head.Length).Split (' ');
231                                                 break;
232                                         }
233                                 } while (!sr.EndOfStream);
234
235                                 if (values == null)
236                                         throw CreateException (file, String.Format ("No corresponding line was not found for '{0}'", item));
237                                 if (keys.Length != values.Length)
238                                         throw CreateException (file, String.Format ("The counts in the header line and the value line do not match for '{0}'", item));
239                                 StringDictionary dic = new StringDictionary ();
240                                 for (int i = 0; i < keys.Length; i++)
241                                         dic [keys [i]] = values [i];
242                                 return dic;
243                         }
244                 }
245
246                 StringDictionary GetProperties6 (string item)
247                 {
248                         if (!File.Exists (StatisticsFileIPv6))
249                                 throw new NetworkInformationException ();
250
251                         string file = StatisticsFileIPv6;
252
253                         string head = item;
254                         using (StreamReader sr = new StreamReader (file, Encoding.ASCII)) {
255                                 StringDictionary dic = new StringDictionary ();
256                                 string s = String.Empty;
257                                 do {
258                                         s = sr.ReadLine ();
259                                         if (String.IsNullOrEmpty (s))
260                                                 continue;
261                                         if (s.Length <= head.Length || String.CompareOrdinal (s, 0, head, 0, head.Length) != 0)
262                                                 continue;
263                                         int idx = s.IndexOfAny (wsChars, head.Length);
264                                         if (idx < 0)
265                                                 throw CreateException (file, null);
266                                         dic [s.Substring (head.Length, idx - head.Length)] = s.Substring (idx + 1).Trim (wsChars);
267                                 } while (!sr.EndOfStream);
268
269                                 return dic;
270                         }
271                 }
272
273                 static readonly char [] wsChars = new char [] {' ', '\t'};
274
275                 Exception CreateException (string file, string msg)
276                 {
277                         return new InvalidOperationException (String.Format ("Unsupported (unexpected) '{0}' file format. ", file) + msg);
278                 }
279                 IPEndPoint [] GetLocalAddresses (List<string []> list)
280                 {
281                         IPEndPoint [] ret = new IPEndPoint [list.Count];
282                         for (int i = 0; i < ret.Length; i++)
283                                 ret [i] = ToEndpoint (list [i] [1]);
284                         return ret;
285                 }
286
287                 IPEndPoint ToEndpoint (string s)
288                 {
289                         int idx = s.IndexOf (':');
290                         int port = int.Parse (s.Substring (idx + 1), NumberStyles.HexNumber);
291                         if (s.Length == 13)
292                                 return new IPEndPoint (long.Parse (s.Substring (0, idx), NumberStyles.HexNumber), port);
293                         else {
294                                 byte [] bytes = new byte [16];
295                                 for (int i = 0; (i << 1) < idx; i++)
296                                         bytes [i] = byte.Parse (s.Substring (i << 1, 2), NumberStyles.HexNumber);
297                                 return new IPEndPoint (new IPAddress (bytes), port);
298                         }
299                 }
300
301                 void GetRows (string file, List<string []> list)
302                 {
303                         if (!File.Exists (file))
304                                 return;
305                         using (StreamReader sr = new StreamReader (file, Encoding.ASCII)) {
306                                 sr.ReadLine (); // skip first line
307                                 while (!sr.EndOfStream) {
308                                         string [] item = sr.ReadLine ().Split (wsChars, StringSplitOptions.RemoveEmptyEntries);
309                                         if (item.Length < 4)
310                                                 throw CreateException (file, null);
311                                         list.Add (item);
312                                 }
313                         }
314                 }
315
316                 public override TcpConnectionInformation [] GetActiveTcpConnections ()
317                 {
318                         List<string []> list = new List<string []> ();
319                         GetRows (TcpFile, list);
320                         GetRows (Tcp6File, list);
321
322                         TcpConnectionInformation [] ret = new TcpConnectionInformation [list.Count];
323                         for (int i = 0; i < ret.Length; i++) {
324                                 // sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode
325                                 IPEndPoint local = ToEndpoint (list [i] [1]);
326                                 IPEndPoint remote = ToEndpoint (list [i] [2]);
327                                 TcpState state = (TcpState) int.Parse (list [i] [3], NumberStyles.HexNumber);
328                                 ret [i] = new TcpConnectionInformationImpl (local, remote, state);
329                         }
330                         return ret;
331                 }
332
333                 public override IPEndPoint [] GetActiveTcpListeners ()
334                 {
335                         List<string []> list = new List<string []> ();
336                         GetRows (TcpFile, list);
337                         GetRows (Tcp6File, list);
338                         return GetLocalAddresses (list);
339                 }
340
341                 public override IPEndPoint [] GetActiveUdpListeners ()
342                 {
343                         List<string []> list = new List<string []> ();
344                         GetRows (UdpFile, list);
345                         GetRows (Udp6File, list);
346                         return GetLocalAddresses (list);
347                 }
348
349                 public override IcmpV4Statistics GetIcmpV4Statistics ()
350                 {
351                         return new MibIcmpV4Statistics (GetProperties4 ("Icmp"));
352                 }
353
354                 public override IcmpV6Statistics GetIcmpV6Statistics ()
355                 {
356                         return new MibIcmpV6Statistics (GetProperties6 ("Icmp6"));
357                 }
358
359                 public override IPGlobalStatistics GetIPv4GlobalStatistics ()
360                 {
361                         return new MibIPGlobalStatistics (GetProperties4 ("Ip"));
362                 }
363
364                 public override IPGlobalStatistics GetIPv6GlobalStatistics ()
365                 {
366                         return new MibIPGlobalStatistics (GetProperties6 ("Ip6"));
367                 }
368
369                 public override TcpStatistics GetTcpIPv4Statistics ()
370                 {
371                         return new MibTcpStatistics (GetProperties4 ("Tcp"));
372                 }
373
374                 public override TcpStatistics GetTcpIPv6Statistics ()
375                 {
376                         // There is no TCP info in /proc/net/snmp,
377                         // so it is shared with IPv4 info.
378                         return new MibTcpStatistics (GetProperties4 ("Tcp"));
379                 }
380
381                 public override UdpStatistics GetUdpIPv4Statistics ()
382                 {
383                         return new MibUdpStatistics (GetProperties4 ("Udp"));
384                 }
385
386                 public override UdpStatistics GetUdpIPv6Statistics ()
387                 {
388                         return new MibUdpStatistics (GetProperties6 ("Udp6"));
389                 }
390         }
391
392         class Win32IPGlobalProperties : IPGlobalProperties
393         {
394                 public const int AF_INET = 2;
395                 public const int AF_INET6 = 23;
396
397                 // FIXME: it might be getting wrong table. I'm getting
398                 // different results from .NET 2.0.
399                 unsafe void FillTcpTable (out List<Win32_MIB_TCPROW> tab4, out List<Win32_MIB_TCP6ROW> tab6)
400                 {
401                         tab4 = new List<Win32_MIB_TCPROW> ();
402                         int size4 = 0;
403                         GetTcpTable (null, ref size4, true); // get size
404                         byte [] bytes4 = new byte [size4];
405                         GetTcpTable (bytes4, ref size4, true); // get list
406
407                         int structSize4 = Marshal.SizeOf (typeof (Win32_MIB_TCPROW));
408
409                         fixed (byte* ptr = bytes4) {
410                                 int count = Marshal.ReadInt32 ((IntPtr) ptr);
411                                 for (int i = 0; i < count; i++) {
412                                         Win32_MIB_TCPROW row = new Win32_MIB_TCPROW ();
413                                         Marshal.PtrToStructure ((IntPtr) (ptr + i * structSize4 + 4), row);
414                                         tab4.Add (row);
415                                 }
416                         }
417
418                         tab6 = new List<Win32_MIB_TCP6ROW> ();
419                         if (Environment.OSVersion.Version.Major >= 6) { // Vista
420                                 int size6 = 0;
421                                 GetTcp6Table (null, ref size6, true); // get size
422                                 byte [] bytes6 = new byte [size6];
423                                 GetTcp6Table (bytes6, ref size6, true); // get list
424
425                                 int structSize6 = Marshal.SizeOf (typeof (Win32_MIB_TCP6ROW));
426
427                                 fixed (byte* ptr = bytes6) {
428                                         int count = Marshal.ReadInt32 ((IntPtr) ptr);
429                                         for (int i = 0; i < count; i++) {
430                                                 Win32_MIB_TCP6ROW row = new Win32_MIB_TCP6ROW ();
431                                                 Marshal.PtrToStructure ((IntPtr) (ptr + i * structSize6 + 4), row);
432                                                 tab6.Add (row);
433                                         }
434                                 }
435                         }
436                 }
437
438                 bool IsListenerState (TcpState state)
439                 {
440                         switch (state) {
441                         case TcpState.SynSent:
442                         case TcpState.Listen:
443                         case TcpState.FinWait1:
444                         case TcpState.FinWait2:
445                         case TcpState.CloseWait:
446                                 return true;
447                         }
448                         return false;
449                 }
450
451                 public override TcpConnectionInformation [] GetActiveTcpConnections ()
452                 {
453                         List<Win32_MIB_TCPROW> tab4 = null;
454                         List<Win32_MIB_TCP6ROW> tab6 = null;
455                         FillTcpTable (out tab4, out tab6);
456                         int size4 = tab4.Count;
457
458                         TcpConnectionInformation [] ret = new TcpConnectionInformation [size4 + tab6.Count];
459                         for (int i = 0; i < size4; i++)
460                                 ret [i] = tab4 [i].TcpInfo;
461                         for (int i = 0; i < tab6.Count; i++)
462                                 ret [size4 + i] = tab6 [i].TcpInfo;
463                         return ret;
464                 }
465
466                 public override IPEndPoint [] GetActiveTcpListeners ()
467                 {
468                         List<Win32_MIB_TCPROW> tab4 = null;
469                         List<Win32_MIB_TCP6ROW> tab6 = null;
470                         FillTcpTable (out tab4, out tab6);
471
472                         List<IPEndPoint> ret = new List<IPEndPoint> ();
473                         for (int i = 0, count = tab4.Count; i < count; i++)
474                                 if (IsListenerState (tab4 [i].State))
475                                         ret.Add (tab4 [i].LocalEndPoint);
476                         for (int i = 0, count = tab6.Count; i < count; i++)
477                                 if (IsListenerState (tab6 [i].State))
478                                         ret.Add (tab6 [i].LocalEndPoint);
479                         return ret.ToArray ();
480                 }
481
482                 public unsafe override IPEndPoint [] GetActiveUdpListeners ()
483                 {
484                         List<IPEndPoint> list = new List<IPEndPoint> ();
485
486                         byte [] bytes4 = null;
487                         int size4 = 0;
488                         GetUdpTable (null, ref size4, true); // get size
489                         bytes4 = new byte [size4];
490                         GetUdpTable (bytes4, ref size4, true); // get list
491
492                         int structSize4 = Marshal.SizeOf (typeof (Win32_MIB_UDPROW));
493
494                         fixed (byte* ptr = bytes4) {
495                                 int count = Marshal.ReadInt32 ((IntPtr) ptr);
496                                 for (int i = 0; i < count; i++) {
497                                         Win32_MIB_UDPROW row = new Win32_MIB_UDPROW ();
498                                         Marshal.PtrToStructure ((IntPtr) (ptr + i * structSize4 + 4), row);
499                                         list.Add (row.LocalEndPoint);
500                                 }
501                         }
502
503                         if (Environment.OSVersion.Version.Major >= 6) { // Vista
504                                 byte [] bytes6 = null;
505                                 int size6 = 0;
506                                 GetUdp6Table (null, ref size6, true); // get size
507                                 bytes6 = new byte [size6];
508                                 GetUdp6Table (bytes6, ref size6, true); // get list
509
510                                 int structSize6 = Marshal.SizeOf (typeof (Win32_MIB_UDP6ROW));
511
512                                 fixed (byte* ptr = bytes6) {
513                                         int count = Marshal.ReadInt32 ((IntPtr) ptr);
514                                         for (int i = 0; i < count; i++) {
515                                                 Win32_MIB_UDP6ROW row = new Win32_MIB_UDP6ROW ();
516                                                 Marshal.PtrToStructure ((IntPtr) (ptr + i * structSize6 + 4), row);
517                                                 list.Add (row.LocalEndPoint);
518                                         }
519                                 }
520                         }
521
522                         return list.ToArray ();
523                 }
524
525                 public override IcmpV4Statistics GetIcmpV4Statistics ()
526                 {
527                         if (!Socket.SupportsIPv4)
528                                 throw new NetworkInformationException ();
529                         Win32_MIBICMPINFO stats;
530                         GetIcmpStatistics (out stats, AF_INET);
531                         return new Win32IcmpV4Statistics (stats);
532                 }
533
534                 public override IcmpV6Statistics GetIcmpV6Statistics ()
535                 {
536                         if (!Socket.OSSupportsIPv6)
537                                 throw new NetworkInformationException ();
538                         Win32_MIB_ICMP_EX stats;
539                         GetIcmpStatisticsEx (out stats, AF_INET6);
540                         return new Win32IcmpV6Statistics (stats);
541                 }
542
543                 public override IPGlobalStatistics GetIPv4GlobalStatistics ()
544                 {
545                         if (!Socket.SupportsIPv4)
546                                 throw new NetworkInformationException ();
547                         Win32_MIB_IPSTATS stats;
548                         GetIpStatisticsEx (out stats, AF_INET);
549                         return new Win32IPGlobalStatistics (stats);
550                 }
551
552                 public override IPGlobalStatistics GetIPv6GlobalStatistics ()
553                 {
554                         if (!Socket.OSSupportsIPv6)
555                                 throw new NetworkInformationException ();
556                         Win32_MIB_IPSTATS stats;
557                         GetIpStatisticsEx (out stats, AF_INET6);
558                         return new Win32IPGlobalStatistics (stats);
559                 }
560
561                 public override TcpStatistics GetTcpIPv4Statistics ()
562                 {
563                         if (!Socket.SupportsIPv4)
564                                 throw new NetworkInformationException ();
565                         Win32_MIB_TCPSTATS stats;
566                         GetTcpStatisticsEx (out stats, AF_INET);
567                         return new Win32TcpStatistics (stats);
568                 }
569
570                 public override TcpStatistics GetTcpIPv6Statistics ()
571                 {
572                         if (!Socket.OSSupportsIPv6)
573                                 throw new NetworkInformationException ();
574                         Win32_MIB_TCPSTATS stats;
575                         GetTcpStatisticsEx (out stats, AF_INET6);
576                         return new Win32TcpStatistics (stats);
577                 }
578
579                 public override UdpStatistics GetUdpIPv4Statistics ()
580                 {
581                         if (!Socket.SupportsIPv4)
582                                 throw new NetworkInformationException ();
583                         Win32_MIB_UDPSTATS stats;
584                         GetUdpStatisticsEx (out stats, AF_INET);
585                         return new Win32UdpStatistics (stats);
586                 }
587
588                 public override UdpStatistics GetUdpIPv6Statistics ()
589                 {
590                         if (!Socket.OSSupportsIPv6)
591                                 throw new NetworkInformationException ();
592                         Win32_MIB_UDPSTATS stats;
593                         GetUdpStatisticsEx (out stats, AF_INET6);
594                         return new Win32UdpStatistics (stats);
595                 }
596
597                 public override string DhcpScopeName {
598                         get { return Win32_FIXED_INFO.Instance.ScopeId; }
599                 }
600
601                 public override string DomainName {
602                         get { return Win32_FIXED_INFO.Instance.DomainName; }
603                 }
604
605                 public override string HostName {
606                         get { return Win32_FIXED_INFO.Instance.HostName; }
607                 }
608
609                 public override bool IsWinsProxy {
610                         get { return Win32_FIXED_INFO.Instance.EnableProxy != 0; }
611                 }
612
613                 public override NetBiosNodeType NodeType {
614                         get { return Win32_FIXED_INFO.Instance.NodeType; }
615                 }
616
617                 // PInvokes
618
619                 [DllImport ("iphlpapi.dll")]
620                 static extern int GetTcpTable (byte [] pTcpTable, ref int pdwSize, bool bOrder);
621
622                 [DllImport ("iphlpapi.dll")]
623                 static extern int GetTcp6Table (byte [] TcpTable, ref int SizePointer, bool Order);
624
625                 [DllImport ("iphlpapi.dll")]
626                 static extern int GetUdpTable (byte [] pUdpTable, ref int pdwSize, bool bOrder);
627
628                 [DllImport ("iphlpapi.dll")]
629                 static extern int GetUdp6Table (byte [] Udp6Table, ref int SizePointer, bool Order);
630
631                 [DllImport ("iphlpapi.dll")]
632                 static extern int GetTcpStatisticsEx (out Win32_MIB_TCPSTATS pStats, int dwFamily);
633
634                 [DllImport ("iphlpapi.dll")]
635                 static extern int GetUdpStatisticsEx (out Win32_MIB_UDPSTATS pStats, int dwFamily);
636
637                 [DllImport ("iphlpapi.dll")]
638                 static extern int GetIcmpStatistics (out Win32_MIBICMPINFO pStats, int dwFamily);
639
640                 [DllImport ("iphlpapi.dll")]
641                 static extern int GetIcmpStatisticsEx (out Win32_MIB_ICMP_EX pStats, int dwFamily);
642
643                 [DllImport ("iphlpapi.dll")]
644                 static extern int GetIpStatisticsEx (out Win32_MIB_IPSTATS pStats, int dwFamily);
645
646                 // Win32 structures
647
648                 [StructLayout (LayoutKind.Explicit)]
649                 struct Win32_IN6_ADDR
650                 {
651                         [FieldOffset (0)]
652                         [MarshalAs ( UnmanagedType.ByValArray, SizeConst = 16)]
653                         public byte [] Bytes;
654                 }
655
656                 [StructLayout (LayoutKind.Sequential)]
657                 class Win32_MIB_TCPROW
658                 {
659                         public TcpState State;
660                         public uint LocalAddr;
661                         public int LocalPort;
662                         public uint RemoteAddr;
663                         public int RemotePort;
664
665                         public IPEndPoint LocalEndPoint {
666                                 get { return new IPEndPoint (LocalAddr, LocalPort); }
667                         }
668
669                         public IPEndPoint RemoteEndPoint {
670                                 get { return new IPEndPoint (RemoteAddr, RemotePort); }
671                         }
672
673                         public TcpConnectionInformation TcpInfo {
674                                 get { return new TcpConnectionInformationImpl (LocalEndPoint, RemoteEndPoint, State); }
675                         }
676                 }
677
678                 [StructLayout (LayoutKind.Sequential)]
679                 class Win32_MIB_TCP6ROW
680                 {
681                         public TcpState State;
682                         public Win32_IN6_ADDR LocalAddr;
683                         public uint LocalScopeId;
684                         public int LocalPort;
685                         public Win32_IN6_ADDR RemoteAddr;
686                         public uint RemoteScopeId;
687                         public int RemotePort;
688
689                         public IPEndPoint LocalEndPoint {
690                                 get { return new IPEndPoint (new IPAddress (LocalAddr.Bytes, LocalScopeId), LocalPort); }
691                         }
692
693                         public IPEndPoint RemoteEndPoint {
694                                 get { return new IPEndPoint (new IPAddress (RemoteAddr.Bytes, RemoteScopeId), RemotePort); }
695                         }
696
697                         public TcpConnectionInformation TcpInfo {
698                                 get { return new TcpConnectionInformationImpl (LocalEndPoint, RemoteEndPoint, State); }
699                         }
700                 }
701
702                 [StructLayout (LayoutKind.Sequential)]
703                 class Win32_MIB_UDPROW
704                 {
705                         public uint LocalAddr;
706                         public int LocalPort;
707
708                         public IPEndPoint LocalEndPoint {
709                                 get { return new IPEndPoint (LocalAddr, LocalPort); }
710                         }
711                 }
712
713                 [StructLayout (LayoutKind.Sequential)]
714                 class Win32_MIB_UDP6ROW
715                 {
716                         public Win32_IN6_ADDR LocalAddr;
717                         public uint LocalScopeId;
718                         public int LocalPort;
719
720                         public IPEndPoint LocalEndPoint {
721                                 get { return new IPEndPoint (new IPAddress (LocalAddr.Bytes, LocalScopeId), LocalPort); }
722                         }
723                 }
724         }
725 }