Merge pull request #4248 from Unity-Technologies/boehm-gc-alloc-fixed
[mono.git] / mcs / class / System / System.Net.NetworkInformation / Win32NetworkInterfaceMarshal.cs
1 //
2 // System.Net.NetworkInformation.NetworkInterface
3 //
4 // Author:
5 //      Atsushi Enomoto (atsushi@ximian.com)
6 //
7 // Copyright (c) 2007 Novell, Inc. (http://www.novell.com)
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 // 
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 // 
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28 using System;
29 using System.Collections.Generic;
30 using System.Net;
31 using System.Runtime.InteropServices;
32 using System.Text;
33
34 namespace System.Net.NetworkInformation
35 {
36
37
38         class Win32NetworkInterface {
39                                 // Can't have unresolvable pinvokes on ios
40 #if WIN_PLATFORM
41                 [DllImport ("iphlpapi.dll", SetLastError = true)]
42                 static extern int GetNetworkParams (IntPtr ptr, ref int size);
43 #endif
44
45                 static Win32_FIXED_INFO fixedInfo;
46                 static bool initialized = false;
47
48                 public static Win32_FIXED_INFO FixedInfo {
49                         get {
50                                 if (!initialized) {
51 #if WIN_PLATFORM
52                                         int len = 0;
53                                         IntPtr ptr = IntPtr.Zero;
54                                         GetNetworkParams (ptr, ref len);
55                                         ptr = Marshal.AllocHGlobal(len);
56                                         GetNetworkParams (ptr, ref len);
57                                         fixedInfo = Marshal.PtrToStructure<Win32_FIXED_INFO> (ptr);
58 #else
59                                         throw new NotImplementedException ();
60 #endif
61                                         initialized = true;
62                                 }
63                                 return fixedInfo;
64                         }
65                 }
66         }
67
68         // They are mostly defined in iptypes.h (included by iphlpapi.h).
69         // grep around /usr/include/w32api/* for identifiers you are curious.
70
71         [StructLayout (LayoutKind.Sequential)]
72         struct Win32_FIXED_INFO
73         {
74
75                 const int MAX_HOSTNAME_LEN = 128;
76                 const int MAX_DOMAIN_NAME_LEN = 128;
77                 const int MAX_SCOPE_ID_LEN = 256;
78                 [MarshalAs (UnmanagedType.ByValTStr, SizeConst = MAX_HOSTNAME_LEN + 4)]
79                 public string HostName;
80                 [MarshalAs (UnmanagedType.ByValTStr, SizeConst = MAX_DOMAIN_NAME_LEN + 4)]
81                 public string DomainName;
82                 public IntPtr CurrentDnsServer; // to Win32IP_ADDR_STRING
83                 public Win32_IP_ADDR_STRING DnsServerList;
84                 public NetBiosNodeType NodeType;
85                 [MarshalAs (UnmanagedType.ByValTStr, SizeConst = MAX_SCOPE_ID_LEN + 4)]
86                 public string ScopeId;
87                 public uint EnableRouting;
88                 public uint EnableProxy;
89                 public uint EnableDns;
90         }
91
92         [StructLayout (LayoutKind.Explicit)]
93         struct AlignmentUnion
94         {
95                 [FieldOffset (0)] // 1
96                 public ulong Alignment;
97                 [FieldOffset (0)] // 2-1
98                 public int Length;
99                 [FieldOffset (4)] // 2-2
100                 public int IfIndex;
101         }
102
103         [StructLayout (LayoutKind.Sequential, CharSet = CharSet.Unicode)]
104         struct Win32_IP_ADAPTER_ADDRESSES {
105                 public AlignmentUnion Alignment;
106                 public IntPtr Next; // to Win32_IP_ADAPTER_ADDRESSES
107                 [MarshalAs (UnmanagedType.LPStr)]
108                 public string AdapterName; // PCHAR
109                 public IntPtr FirstUnicastAddress; //to IP_ADAPTER_UNICAST_ADDRESS
110                 public IntPtr FirstAnycastAddress; // to IP_ADAPTER_ANYCAST_ADDRESS
111                 public IntPtr FirstMulticastAddress; // to IP_ADAPTER_MULTICAST_ADDRESS
112                 public IntPtr FirstDnsServerAddress; // to IP_ADAPTER_DNS_SERVER_ADDRESS
113                 public string DnsSuffix;
114                 public string Description;
115                 public string FriendlyName;
116                 [MarshalAs (UnmanagedType.ByValArray, SizeConst = MAX_ADAPTER_ADDRESS_LENGTH)]
117                 public byte [] PhysicalAddress;
118                 public uint PhysicalAddressLength;
119                 public uint Flags;
120                 public uint Mtu;
121                 public NetworkInterfaceType IfType;
122                 public OperationalStatus OperStatus;
123                 public int Ipv6IfIndex;
124                 [MarshalAs (UnmanagedType.ByValArray, SizeConst = 16 * 4)]
125                 public uint [] ZoneIndices;
126
127                 // Note that Vista-only members and XP-SP1-only member are
128                 // omitted.
129
130                 const int MAX_ADAPTER_ADDRESS_LENGTH = 8;
131
132                 const int IP_ADAPTER_DDNS_ENABLED = 1;
133                 const int IP_ADAPTER_RECEIVE_ONLY = 8;
134                 const int IP_ADAPTER_NO_MULTICAST = 0x10;
135
136                 public bool DdnsEnabled {
137                         get { return (Flags & IP_ADAPTER_DDNS_ENABLED) != 0; }
138                 }
139
140                 public bool IsReceiveOnly {
141                         get { return (Flags & IP_ADAPTER_RECEIVE_ONLY) != 0; }
142                 }
143
144                 public bool NoMulticast {
145                         get { return (Flags & IP_ADAPTER_NO_MULTICAST) != 0; }
146                 }
147         }
148
149         [StructLayout (LayoutKind.Sequential)]
150         struct Win32_IP_ADAPTER_INFO
151         {
152                 const int MAX_ADAPTER_NAME_LENGTH = 256;
153                 const int MAX_ADAPTER_DESCRIPTION_LENGTH = 128;
154                 const int MAX_ADAPTER_ADDRESS_LENGTH = 8;
155
156                 public IntPtr Next; // to Win32_IP_ADAPTER_INFO
157                 public int ComboIndex;
158                 [MarshalAs (UnmanagedType.ByValTStr, SizeConst = MAX_ADAPTER_NAME_LENGTH + 4)]
159                 public string AdapterName;
160                 [MarshalAs (UnmanagedType.ByValTStr, SizeConst = MAX_ADAPTER_DESCRIPTION_LENGTH + 4)]
161                 public string Description;
162                 public uint AddressLength;
163                 [MarshalAs (UnmanagedType.ByValArray, SizeConst = MAX_ADAPTER_ADDRESS_LENGTH)]
164                 public byte [] Address;
165                 public uint Index;
166                 public uint Type;
167                 public uint DhcpEnabled;
168                 public IntPtr CurrentIpAddress; // Win32_IP_ADDR_STRING
169                 public Win32_IP_ADDR_STRING IpAddressList;
170                 public Win32_IP_ADDR_STRING GatewayList;
171                 public Win32_IP_ADDR_STRING DhcpServer;
172                 public bool HaveWins;
173                 public Win32_IP_ADDR_STRING PrimaryWinsServer;
174                 public Win32_IP_ADDR_STRING SecondaryWinsServer;
175                 public long LeaseObtained;
176                 public long LeaseExpires;
177         }
178
179         [StructLayout (LayoutKind.Sequential)]
180         struct Win32_MIB_IFROW
181         {
182                 const int MAX_INTERFACE_NAME_LEN = 256;
183                 const int MAXLEN_PHYSADDR = 8;
184                 const int MAXLEN_IFDESCR = 256;
185
186                 [MarshalAs (UnmanagedType.ByValArray, SizeConst = MAX_INTERFACE_NAME_LEN * 2)]
187                 public char [] Name;
188                 public int Index;
189                 public NetworkInterfaceType Type;
190                 public int Mtu;
191                 public uint Speed;
192                 public int PhysAddrLen;
193                 [MarshalAs (UnmanagedType.ByValArray, SizeConst = MAXLEN_PHYSADDR)]
194                 public byte [] PhysAddr;
195                 public uint AdminStatus;
196                 public uint OperStatus;
197                 public uint LastChange;
198                 public int InOctets;
199                 public int InUcastPkts;
200                 public int InNUcastPkts;
201                 public int InDiscards;
202                 public int InErrors;
203                 public int InUnknownProtos;
204                 public int OutOctets;
205                 public int OutUcastPkts;
206                 public int OutNUcastPkts;
207                 public int OutDiscards;
208                 public int OutErrors;
209                 public int OutQLen;
210                 public int DescrLen;
211                 [MarshalAs (UnmanagedType.ByValArray, SizeConst = MAXLEN_IFDESCR)]
212                 public byte [] Descr;
213         }
214
215         [StructLayout (LayoutKind.Sequential)]
216         struct Win32_IP_ADDR_STRING
217         {
218                 public IntPtr Next; // to Win32_IP_ADDR_STRING
219                 [MarshalAs (UnmanagedType.ByValTStr, SizeConst = 16)]
220                 public string IpAddress;
221                 [MarshalAs (UnmanagedType.ByValTStr, SizeConst = 16)]
222                 public string IpMask;
223                 public uint Context;
224         }
225
226         [StructLayout (LayoutKind.Sequential)]
227         struct Win32LengthFlagsUnion
228         {
229                 const int IP_ADAPTER_ADDRESS_DNS_ELIGIBLE = 1;
230                 const int IP_ADAPTER_ADDRESS_TRANSIENT = 2;
231
232                 // union { struct {
233                 public uint Length;
234                 public uint Flags;
235                 // }; };
236
237                 public bool IsDnsEligible {
238                         get { return (Flags & IP_ADAPTER_ADDRESS_DNS_ELIGIBLE) != 0; }
239                 }
240
241                 public bool IsTransient {
242                         get { return (Flags & IP_ADAPTER_ADDRESS_TRANSIENT) != 0; }
243                 }
244         }
245
246         [StructLayout (LayoutKind.Sequential)]
247         struct Win32_IP_ADAPTER_ANYCAST_ADDRESS
248         {
249                 public Win32LengthFlagsUnion LengthFlags;
250                 public IntPtr Next; // to Win32_IP_ADAPTER_ANYCAST_ADDRESS
251                 public Win32_SOCKET_ADDRESS Address;
252         }
253
254         [StructLayout (LayoutKind.Sequential)]
255         struct Win32_IP_ADAPTER_DNS_SERVER_ADDRESS
256         {
257                 public Win32LengthFlagsUnion LengthFlags;
258                 public IntPtr Next; // to Win32_IP_ADAPTER_DNS_SERVER_ADDRESS
259                 public Win32_SOCKET_ADDRESS Address;
260         }
261
262         [StructLayout (LayoutKind.Sequential)]
263         struct Win32_IP_ADAPTER_MULTICAST_ADDRESS
264         {
265                 public Win32LengthFlagsUnion LengthFlags;
266                 public IntPtr Next; // to Win32_IP_ADAPTER_MULTICAST_ADDRESS
267                 public Win32_SOCKET_ADDRESS Address;
268         }
269
270         [StructLayout (LayoutKind.Sequential)]
271         struct Win32_IP_ADAPTER_UNICAST_ADDRESS
272         {
273                 public Win32LengthFlagsUnion LengthFlags;
274                 public IntPtr Next; // to Win32_IP_ADAPTER_UNICAST_ADDRESS
275                 public Win32_SOCKET_ADDRESS Address;
276                 public PrefixOrigin PrefixOrigin;
277                 public SuffixOrigin SuffixOrigin;
278                 public DuplicateAddressDetectionState DadState;
279                 public uint ValidLifetime;
280                 public uint PreferredLifetime;
281                 public uint LeaseLifetime;
282                 public byte OnLinkPrefixLength;
283
284         }
285
286         [StructLayout (LayoutKind.Sequential)]
287         struct Win32_SOCKADDR
288         {
289                 public ushort AddressFamily;
290                 [MarshalAs (UnmanagedType.ByValArray, SizeConst = 14 * 2)]
291                 public byte [] AddressData;
292         }
293
294         // FIXME: it somehow fails to marshal.
295         [StructLayout (LayoutKind.Sequential)]
296         struct Win32_SOCKET_ADDRESS
297         {
298                 public IntPtr Sockaddr; // to Win32_SOCKADDR
299                 public int SockaddrLength;
300
301                 public IPAddress GetIPAddress ()
302                 {
303                         Win32_SOCKADDR sa = (Win32_SOCKADDR) Marshal.PtrToStructure (Sockaddr, typeof (Win32_SOCKADDR));
304 //foreach (byte b in sa.AddressData) Console.Write ("{0:X02}", b); Console.WriteLine ();
305                         byte [] arr;
306                         if (sa.AddressFamily == AF_INET6) {
307                                 arr = new byte [16];
308                                 Array.Copy (sa.AddressData, 6, arr, 0, 16);
309                         } else {
310                                 arr = new byte [4];
311                                 Array.Copy (sa.AddressData, 2, arr, 0, 4);
312                         }
313 //foreach (byte b in arr) Console.Write ("{0:X02}", b); Console.WriteLine ();
314                         return new IPAddress (arr);
315                 }
316
317                 const int AF_INET6 = 23;
318         }
319 }
320