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