PageRenderTime 64ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/mcs/class/System/System.Net.NetworkInformation/IPInterfaceProperties.cs

http://github.com/mono/mono
C# | 437 lines | 343 code | 53 blank | 41 comment | 53 complexity | aca7b59cfae98ede6c0d19b75278e17f MD5 | raw file
Possible License(s): GPL-2.0, CC-BY-SA-3.0, LGPL-2.0, MPL-2.0-no-copyleft-exception, LGPL-2.1, Unlicense, Apache-2.0
  1. //
  2. // System.Net.NetworkInformation.IPInterfaceProperties
  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. using System.Collections.Generic;
  30. using System.Globalization;
  31. using System.IO;
  32. using System.Net.Sockets;
  33. using System.Runtime.CompilerServices;
  34. using System.Text.RegularExpressions;
  35. using System.Runtime.InteropServices;
  36. namespace System.Net.NetworkInformation {
  37. abstract class UnixIPInterfaceProperties : IPInterfaceProperties
  38. {
  39. protected IPv4InterfaceProperties ipv4iface_properties;
  40. protected UnixNetworkInterface iface;
  41. List <IPAddress> addresses;
  42. IPAddressCollection dns_servers;
  43. string dns_suffix;
  44. DateTime last_parse;
  45. public UnixIPInterfaceProperties (UnixNetworkInterface iface, List <IPAddress> addresses)
  46. {
  47. this.iface = iface;
  48. this.addresses = addresses;
  49. }
  50. public override IPv6InterfaceProperties GetIPv6Properties ()
  51. {
  52. throw new NotImplementedException ();
  53. }
  54. static Regex ns = new Regex (@"\s*nameserver\s+(?<address>.*)");
  55. static Regex search = new Regex (@"\s*search\s+(?<domain>.*)");
  56. void ParseResolvConf ()
  57. {
  58. try {
  59. DateTime wt = File.GetLastWriteTime ("/etc/resolv.conf");
  60. if (wt <= last_parse)
  61. return;
  62. last_parse = wt;
  63. dns_suffix = "";
  64. dns_servers = new IPAddressCollection ();
  65. using (StreamReader reader = new StreamReader ("/etc/resolv.conf")) {
  66. string str;
  67. string line;
  68. while ((line = reader.ReadLine ()) != null) {
  69. line = line.Trim ();
  70. if (line.Length == 0 || line [0] == '#')
  71. continue;
  72. Match match = ns.Match (line);
  73. if (match.Success) {
  74. try {
  75. str = match.Groups ["address"].Value;
  76. str = str.Trim ();
  77. dns_servers.InternalAdd (IPAddress.Parse (str));
  78. } catch {
  79. }
  80. } else {
  81. match = search.Match (line);
  82. if (match.Success) {
  83. str = match.Groups ["domain"].Value;
  84. string [] parts = str.Split (',');
  85. dns_suffix = parts [0].Trim ();
  86. }
  87. }
  88. }
  89. }
  90. } catch {
  91. }
  92. }
  93. public override IPAddressInformationCollection AnycastAddresses {
  94. get {
  95. var c = new IPAddressInformationCollection ();
  96. foreach (IPAddress address in addresses) {
  97. c.InternalAdd (new SystemIPAddressInformation (address, false, false));
  98. }
  99. return c;
  100. }
  101. }
  102. [MonoTODO ("Always returns an empty collection.")]
  103. public override IPAddressCollection DhcpServerAddresses {
  104. get {
  105. // There are lots of different DHCP clients
  106. // that all store their configuration differently.
  107. // I'm not sure what to do here.
  108. IPAddressCollection coll = new IPAddressCollection ();
  109. return coll;
  110. }
  111. }
  112. public override IPAddressCollection DnsAddresses {
  113. get {
  114. ParseResolvConf ();
  115. return dns_servers;
  116. }
  117. }
  118. public override string DnsSuffix {
  119. get {
  120. ParseResolvConf ();
  121. return dns_suffix;
  122. }
  123. }
  124. [MonoTODO ("Always returns true")]
  125. public override bool IsDnsEnabled {
  126. get {
  127. return true;
  128. }
  129. }
  130. [MonoTODO ("Always returns false")]
  131. public override bool IsDynamicDnsEnabled {
  132. get {
  133. return false;
  134. }
  135. }
  136. public override MulticastIPAddressInformationCollection MulticastAddresses {
  137. get {
  138. var multicastAddresses = new MulticastIPAddressInformationCollection ();
  139. foreach (IPAddress address in addresses) {
  140. byte[] addressBytes = address.GetAddressBytes ();
  141. if (addressBytes[0] >= 224 && addressBytes[0] <= 239) {
  142. multicastAddresses.InternalAdd (new SystemMulticastIPAddressInformation (new SystemIPAddressInformation (address, true, false)));
  143. }
  144. }
  145. return multicastAddresses;
  146. }
  147. }
  148. public override UnicastIPAddressInformationCollection UnicastAddresses {
  149. get {
  150. var unicastAddresses = new UnicastIPAddressInformationCollection ();
  151. foreach (IPAddress address in addresses) {
  152. switch (address.AddressFamily) {
  153. case AddressFamily.InterNetwork:
  154. byte top = address.GetAddressBytes () [0];
  155. if (top >= 224 && top <= 239)
  156. continue;
  157. unicastAddresses.InternalAdd (new LinuxUnicastIPAddressInformation (address));
  158. break;
  159. case AddressFamily.InterNetworkV6:
  160. if (address.IsIPv6Multicast)
  161. continue;
  162. unicastAddresses.InternalAdd (new LinuxUnicastIPAddressInformation (address));
  163. break;
  164. }
  165. }
  166. return unicastAddresses;
  167. }
  168. }
  169. [MonoTODO ("Always returns an empty collection.")]
  170. public override IPAddressCollection WinsServersAddresses {
  171. get {
  172. // I do SUPPOSE we could scrape /etc/samba/smb.conf, but.. yeesh.
  173. return new IPAddressCollection ();
  174. }
  175. }
  176. }
  177. class LinuxIPInterfaceProperties : UnixIPInterfaceProperties
  178. {
  179. public LinuxIPInterfaceProperties (LinuxNetworkInterface iface, List <IPAddress> addresses)
  180. : base (iface, addresses)
  181. {
  182. }
  183. public override IPv4InterfaceProperties GetIPv4Properties ()
  184. {
  185. if (ipv4iface_properties == null)
  186. ipv4iface_properties = new LinuxIPv4InterfaceProperties (iface as LinuxNetworkInterface);
  187. return ipv4iface_properties;
  188. }
  189. IPAddressCollection ParseRouteInfo (string iface)
  190. {
  191. var col = new IPAddressCollection ();
  192. try {
  193. using (StreamReader reader = new StreamReader ("/proc/net/route")) {
  194. string line;
  195. reader.ReadLine (); // Ignore first line
  196. while ((line = reader.ReadLine ()) != null) {
  197. line = line.Trim ();
  198. if (line.Length == 0)
  199. continue;
  200. string [] parts = line.Split ('\t');
  201. if (parts.Length < 3)
  202. continue;
  203. string gw_address = parts [2].Trim ();
  204. byte [] ipbytes = new byte [4];
  205. if (gw_address.Length == 8 && iface.Equals (parts [0], StringComparison.OrdinalIgnoreCase)) {
  206. for (int i = 0; i < 4; i++) {
  207. if (!Byte.TryParse (gw_address.Substring (i * 2, 2), NumberStyles.HexNumber, null, out ipbytes [3 - i]))
  208. continue;
  209. }
  210. IPAddress ip = new IPAddress (ipbytes);
  211. if (!ip.Equals (IPAddress.Any) && !col.Contains (ip))
  212. col.InternalAdd (ip);
  213. }
  214. }
  215. }
  216. } catch {
  217. }
  218. return col;
  219. }
  220. public override GatewayIPAddressInformationCollection GatewayAddresses {
  221. get {
  222. return SystemGatewayIPAddressInformation.ToGatewayIpAddressInformationCollection (ParseRouteInfo (this.iface.Name.ToString()));
  223. }
  224. }
  225. }
  226. class MacOsIPInterfaceProperties : UnixIPInterfaceProperties
  227. {
  228. public MacOsIPInterfaceProperties (MacOsNetworkInterface iface, List <IPAddress> addresses)
  229. : base (iface, addresses)
  230. {
  231. }
  232. public override IPv4InterfaceProperties GetIPv4Properties ()
  233. {
  234. if (ipv4iface_properties == null)
  235. ipv4iface_properties = new MacOsIPv4InterfaceProperties (iface as MacOsNetworkInterface);
  236. return ipv4iface_properties;
  237. }
  238. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  239. private extern static bool ParseRouteInfo_internal(string iface, out string[] gw_addr_list);
  240. public override GatewayIPAddressInformationCollection GatewayAddresses {
  241. get {
  242. var gateways = new IPAddressCollection ();
  243. string[] gw_addrlist;
  244. if (!ParseRouteInfo_internal (this.iface.Name.ToString(), out gw_addrlist))
  245. return new GatewayIPAddressInformationCollection ();
  246. for(int i=0; i<gw_addrlist.Length; i++) {
  247. try {
  248. IPAddress ip = IPAddress.Parse(gw_addrlist[i]);
  249. if (!ip.Equals (IPAddress.Any) && !gateways.Contains (ip))
  250. gateways.InternalAdd (ip);
  251. } catch (ArgumentNullException) {
  252. /* Ignore this, as the
  253. * internal call might have
  254. * left some blank entries at
  255. * the end of the array
  256. */
  257. }
  258. }
  259. return SystemGatewayIPAddressInformation.ToGatewayIpAddressInformationCollection (gateways);
  260. }
  261. }
  262. }
  263. #if !MOBILE
  264. class Win32IPInterfaceProperties2 : IPInterfaceProperties
  265. {
  266. readonly Win32_IP_ADAPTER_ADDRESSES addr;
  267. readonly Win32_MIB_IFROW mib4, mib6;
  268. public Win32IPInterfaceProperties2 (Win32_IP_ADAPTER_ADDRESSES addr, Win32_MIB_IFROW mib4, Win32_MIB_IFROW mib6)
  269. {
  270. this.addr = addr;
  271. this.mib4 = mib4;
  272. this.mib6 = mib6;
  273. }
  274. public override IPv4InterfaceProperties GetIPv4Properties ()
  275. {
  276. Win32_IP_ADAPTER_INFO v4info = Win32NetworkInterface2.GetAdapterInfoByIndex (mib4.Index);
  277. return v4info != null ? new Win32IPv4InterfaceProperties (v4info, mib4) : null;
  278. }
  279. public override IPv6InterfaceProperties GetIPv6Properties ()
  280. {
  281. Win32_IP_ADAPTER_INFO v6info = Win32NetworkInterface2.GetAdapterInfoByIndex (mib6.Index);
  282. return v6info != null ? new Win32IPv6InterfaceProperties (mib6) : null;
  283. }
  284. public override IPAddressInformationCollection AnycastAddresses {
  285. get { return Win32FromAnycast (addr.FirstAnycastAddress); }
  286. }
  287. static IPAddressInformationCollection Win32FromAnycast (IntPtr ptr)
  288. {
  289. var c = new IPAddressInformationCollection ();
  290. Win32_IP_ADAPTER_ANYCAST_ADDRESS a;
  291. for (IntPtr p = ptr; p != IntPtr.Zero; p = a.Next) {
  292. a = (Win32_IP_ADAPTER_ANYCAST_ADDRESS) Marshal.PtrToStructure (p, typeof (Win32_IP_ADAPTER_ANYCAST_ADDRESS));
  293. c.InternalAdd (new SystemIPAddressInformation (
  294. a.Address.GetIPAddress (),
  295. a.LengthFlags.IsDnsEligible,
  296. a.LengthFlags.IsTransient));
  297. }
  298. return c;
  299. }
  300. public override IPAddressCollection DhcpServerAddresses {
  301. get {
  302. Win32_IP_ADAPTER_INFO v4info = Win32NetworkInterface2.GetAdapterInfoByIndex (mib4.Index);
  303. // FIXME: should ipv6 DhcpServer be considered?
  304. return v4info != null ? new Win32IPAddressCollection (v4info.DhcpServer) : Win32IPAddressCollection.Empty;
  305. }
  306. }
  307. public override IPAddressCollection DnsAddresses {
  308. get { return Win32IPAddressCollection.FromDnsServer (addr.FirstDnsServerAddress); }
  309. }
  310. public override string DnsSuffix {
  311. get { return addr.DnsSuffix; }
  312. }
  313. public override GatewayIPAddressInformationCollection GatewayAddresses {
  314. get {
  315. Win32_IP_ADAPTER_INFO v4info = Win32NetworkInterface2.GetAdapterInfoByIndex (mib4.Index);
  316. // FIXME: should ipv6 DhcpServer be considered?
  317. var col = new GatewayIPAddressInformationCollection ();
  318. if (v4info != null) {
  319. var a = v4info.GatewayList;
  320. if (!String.IsNullOrEmpty (a.IpAddress)) {
  321. col.InternalAdd(new SystemGatewayIPAddressInformation(IPAddress.Parse (a.IpAddress)));
  322. AddSubsequently (a.Next, col);
  323. }
  324. }
  325. return col;
  326. }
  327. }
  328. static void AddSubsequently (IntPtr head, GatewayIPAddressInformationCollection col)
  329. {
  330. Win32_IP_ADDR_STRING a;
  331. for (IntPtr p = head; p != IntPtr.Zero; p = a.Next) {
  332. a = (Win32_IP_ADDR_STRING) Marshal.PtrToStructure (p, typeof (Win32_IP_ADDR_STRING));
  333. col.InternalAdd (new SystemGatewayIPAddressInformation (IPAddress.Parse (a.IpAddress)));
  334. }
  335. }
  336. public override bool IsDnsEnabled {
  337. get { return Win32_FIXED_INFO.Instance.EnableDns != 0; }
  338. }
  339. public override bool IsDynamicDnsEnabled {
  340. get { return addr.DdnsEnabled; }
  341. }
  342. public override MulticastIPAddressInformationCollection MulticastAddresses {
  343. get { return Win32FromMulticast (addr.FirstMulticastAddress); }
  344. }
  345. static MulticastIPAddressInformationCollection Win32FromMulticast (IntPtr ptr)
  346. {
  347. var c = new MulticastIPAddressInformationCollection ();
  348. Win32_IP_ADAPTER_MULTICAST_ADDRESS a;
  349. for (IntPtr p = ptr; p != IntPtr.Zero; p = a.Next) {
  350. a = (Win32_IP_ADAPTER_MULTICAST_ADDRESS) Marshal.PtrToStructure (p, typeof (Win32_IP_ADAPTER_MULTICAST_ADDRESS));
  351. c.InternalAdd (new SystemMulticastIPAddressInformation (new SystemIPAddressInformation (
  352. a.Address.GetIPAddress (),
  353. a.LengthFlags.IsDnsEligible,
  354. a.LengthFlags.IsTransient)));
  355. }
  356. return c;
  357. }
  358. public override UnicastIPAddressInformationCollection UnicastAddresses {
  359. get {
  360. Win32_IP_ADAPTER_INFO ai = Win32NetworkInterface2.GetAdapterInfoByIndex (mib4.Index);
  361. // FIXME: should ipv6 DhcpServer be considered?
  362. return ai != null ? Win32FromUnicast ((int) ai.Index, addr.FirstUnicastAddress) : new UnicastIPAddressInformationCollection ();
  363. }
  364. }
  365. static UnicastIPAddressInformationCollection Win32FromUnicast (int ifIndex, IntPtr ptr)
  366. {
  367. UnicastIPAddressInformationCollection c = new UnicastIPAddressInformationCollection ();
  368. Win32_IP_ADAPTER_UNICAST_ADDRESS a;
  369. for (IntPtr p = ptr; p != IntPtr.Zero; p = a.Next) {
  370. a = (Win32_IP_ADAPTER_UNICAST_ADDRESS) Marshal.PtrToStructure (p, typeof (Win32_IP_ADAPTER_UNICAST_ADDRESS));
  371. c.InternalAdd (new Win32UnicastIPAddressInformation (ifIndex, a));
  372. }
  373. return c;
  374. }
  375. public override IPAddressCollection WinsServersAddresses {
  376. get {
  377. Win32_IP_ADAPTER_INFO v4info = Win32NetworkInterface2.GetAdapterInfoByIndex (mib4.Index);
  378. // FIXME: should ipv6 DhcpServer be considered?
  379. return v4info != null ? new Win32IPAddressCollection (v4info.PrimaryWinsServer, v4info.SecondaryWinsServer) : Win32IPAddressCollection.Empty;
  380. }
  381. }
  382. }
  383. #endif
  384. }