NetworkInterface.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724
  1. //
  2. // System.Net.NetworkInformation.NetworkInterface
  3. //
  4. // Authors:
  5. // Gonzalo Paniagua Javier ([email protected])
  6. // Atsushi Enomoto ([email protected])
  7. // Miguel de Icaza ([email protected])
  8. // Eric Butler ([email protected])
  9. // Marek Habersack ([email protected])
  10. //
  11. // Copyright (c) 2006-2008 Novell, Inc. (http://www.novell.com)
  12. //
  13. // Permission is hereby granted, free of charge, to any person obtaining
  14. // a copy of this software and associated documentation files (the
  15. // "Software"), to deal in the Software without restriction, including
  16. // without limitation the rights to use, copy, modify, merge, publish,
  17. // distribute, sublicense, and/or sell copies of the Software, and to
  18. // permit persons to whom the Software is furnished to do so, subject to
  19. // the following conditions:
  20. //
  21. // The above copyright notice and this permission notice shall be
  22. // included in all copies or substantial portions of the Software.
  23. //
  24. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  25. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  26. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  27. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  28. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  29. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  30. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  31. //
  32. using System;
  33. using System.Collections.Generic;
  34. using System.Collections;
  35. using System.Net;
  36. using System.Net.Sockets;
  37. using System.Runtime.InteropServices;
  38. using System.Text;
  39. using System.IO;
  40. using System.Globalization;
  41. namespace System.Net.NetworkInformation {
  42. public abstract class NetworkInterface {
  43. #if MONOTOUCH
  44. internal const bool runningOnUnix = true;
  45. #else
  46. static Version windowsVer51 = new Version (5, 1);
  47. static internal readonly bool runningOnUnix = (Environment.OSVersion.Platform == PlatformID.Unix);
  48. #endif
  49. protected NetworkInterface ()
  50. {
  51. }
  52. public static NetworkInterface [] GetAllNetworkInterfaces ()
  53. {
  54. #if MONOTOUCH
  55. return MacOsNetworkInterface.ImplGetAllNetworkInterfaces ();
  56. #else
  57. if (runningOnUnix) {
  58. try {
  59. if (Platform.IsMacOS)
  60. return MacOsNetworkInterface.ImplGetAllNetworkInterfaces ();
  61. else
  62. return LinuxNetworkInterface.ImplGetAllNetworkInterfaces ();
  63. } catch (SystemException ex) {
  64. throw ex;
  65. } catch {
  66. return new NetworkInterface [0];
  67. }
  68. } else {
  69. if (Environment.OSVersion.Version >= windowsVer51)
  70. return Win32NetworkInterface2.ImplGetAllNetworkInterfaces ();
  71. return new NetworkInterface [0];
  72. }
  73. #endif
  74. }
  75. [MonoTODO("Always returns true")]
  76. public static bool GetIsNetworkAvailable ()
  77. {
  78. return true;
  79. }
  80. internal static string ReadLine (string path)
  81. {
  82. using (FileStream fs = File.OpenRead (path)){
  83. using (StreamReader sr = new StreamReader (fs)){
  84. return sr.ReadLine ();
  85. }
  86. }
  87. }
  88. [MonoTODO("Only works on Linux. Returns 0 on other systems.")]
  89. public static int LoopbackInterfaceIndex {
  90. get {
  91. // Disable warning for code not reachable, due to runningOnUnix being always true on Monotouch
  92. #pragma warning disable 162
  93. if (runningOnUnix) {
  94. try {
  95. return UnixNetworkInterface.IfNameToIndex ("lo");
  96. } catch {
  97. return 0;
  98. }
  99. } else
  100. return 0;
  101. #pragma warning restore 162
  102. }
  103. }
  104. public abstract IPInterfaceProperties GetIPProperties ();
  105. public abstract IPv4InterfaceStatistics GetIPv4Statistics ();
  106. public abstract PhysicalAddress GetPhysicalAddress ();
  107. public abstract bool Supports (NetworkInterfaceComponent networkInterfaceComponent);
  108. public abstract string Description { get; }
  109. public abstract string Id { get; }
  110. public abstract bool IsReceiveOnly { get; }
  111. public abstract string Name { get; }
  112. public abstract NetworkInterfaceType NetworkInterfaceType { get; }
  113. public abstract OperationalStatus OperationalStatus { get; }
  114. public abstract long Speed { get; }
  115. public abstract bool SupportsMulticast { get; }
  116. }
  117. abstract class UnixNetworkInterface : NetworkInterface
  118. {
  119. [DllImport("libc")]
  120. static extern int if_nametoindex(string ifname);
  121. protected IPv4InterfaceStatistics ipv4stats;
  122. protected IPInterfaceProperties ipproperties;
  123. string name;
  124. //int index;
  125. protected List <IPAddress> addresses;
  126. byte[] macAddress;
  127. NetworkInterfaceType type;
  128. internal UnixNetworkInterface (string name)
  129. {
  130. this.name = name;
  131. addresses = new List<IPAddress> ();
  132. }
  133. public static int IfNameToIndex (string ifname)
  134. {
  135. return if_nametoindex(ifname);
  136. }
  137. internal void AddAddress (IPAddress address)
  138. {
  139. addresses.Add (address);
  140. }
  141. internal void SetLinkLayerInfo (int index, byte[] macAddress, NetworkInterfaceType type)
  142. {
  143. //this.index = index;
  144. this.macAddress = macAddress;
  145. this.type = type;
  146. }
  147. public override PhysicalAddress GetPhysicalAddress ()
  148. {
  149. if (macAddress != null)
  150. return new PhysicalAddress (macAddress);
  151. else
  152. return PhysicalAddress.None;
  153. }
  154. public override bool Supports (NetworkInterfaceComponent networkInterfaceComponent)
  155. {
  156. bool wantIPv4 = networkInterfaceComponent == NetworkInterfaceComponent.IPv4;
  157. bool wantIPv6 = wantIPv4 ? false : networkInterfaceComponent == NetworkInterfaceComponent.IPv6;
  158. foreach (IPAddress address in addresses) {
  159. if (wantIPv4 && address.AddressFamily == AddressFamily.InterNetwork)
  160. return true;
  161. else if (wantIPv6 && address.AddressFamily == AddressFamily.InterNetworkV6)
  162. return true;
  163. }
  164. return false;
  165. }
  166. public override string Description {
  167. get { return name; }
  168. }
  169. public override string Id {
  170. get { return name; }
  171. }
  172. public override bool IsReceiveOnly {
  173. get { return false; }
  174. }
  175. public override string Name {
  176. get { return name; }
  177. }
  178. public override NetworkInterfaceType NetworkInterfaceType {
  179. get { return type; }
  180. }
  181. [MonoTODO ("Parse dmesg?")]
  182. public override long Speed {
  183. get {
  184. // Bits/s
  185. return 1000000;
  186. }
  187. }
  188. }
  189. //
  190. // This class needs support from the libsupport.so library to fetch the
  191. // data using arch-specific ioctls.
  192. //
  193. // For this to work, we have to create this on the factory above.
  194. //
  195. class LinuxNetworkInterface : UnixNetworkInterface
  196. {
  197. [DllImport ("libc")]
  198. static extern int getifaddrs (out IntPtr ifap);
  199. [DllImport ("libc")]
  200. static extern void freeifaddrs (IntPtr ifap);
  201. const int AF_INET = 2;
  202. const int AF_INET6 = 10;
  203. const int AF_PACKET = 17;
  204. //NetworkInterfaceType type;
  205. string iface_path;
  206. string iface_operstate_path;
  207. string iface_flags_path;
  208. internal string IfacePath {
  209. get { return iface_path; }
  210. }
  211. public static NetworkInterface [] ImplGetAllNetworkInterfaces ()
  212. {
  213. var interfaces = new Dictionary <string, LinuxNetworkInterface> ();
  214. IntPtr ifap;
  215. if (getifaddrs (out ifap) != 0)
  216. throw new SystemException ("getifaddrs() failed");
  217. try {
  218. IntPtr next = ifap;
  219. while (next != IntPtr.Zero) {
  220. ifaddrs addr = (ifaddrs) Marshal.PtrToStructure (next, typeof (ifaddrs));
  221. IPAddress address = IPAddress.None;
  222. string name = addr.ifa_name;
  223. int index = -1;
  224. byte[] macAddress = null;
  225. NetworkInterfaceType type = NetworkInterfaceType.Unknown;
  226. if (addr.ifa_addr != IntPtr.Zero) {
  227. sockaddr_in sockaddr = (sockaddr_in) Marshal.PtrToStructure (addr.ifa_addr, typeof (sockaddr_in));
  228. if (sockaddr.sin_family == AF_INET6) {
  229. sockaddr_in6 sockaddr6 = (sockaddr_in6) Marshal.PtrToStructure (addr.ifa_addr, typeof (sockaddr_in6));
  230. address = new IPAddress (sockaddr6.sin6_addr.u6_addr8, sockaddr6.sin6_scope_id);
  231. } else if (sockaddr.sin_family == AF_INET) {
  232. address = new IPAddress (sockaddr.sin_addr);
  233. } else if (sockaddr.sin_family == AF_PACKET) {
  234. sockaddr_ll sockaddrll = (sockaddr_ll) Marshal.PtrToStructure (addr.ifa_addr, typeof (sockaddr_ll));
  235. if (((int)sockaddrll.sll_halen) > sockaddrll.sll_addr.Length){
  236. Console.Error.WriteLine ("Got a bad hardware address length for an AF_PACKET {0} {1}",
  237. sockaddrll.sll_halen, sockaddrll.sll_addr.Length);
  238. next = addr.ifa_next;
  239. continue;
  240. }
  241. macAddress = new byte [(int) sockaddrll.sll_halen];
  242. Array.Copy (sockaddrll.sll_addr, 0, macAddress, 0, macAddress.Length);
  243. index = sockaddrll.sll_ifindex;
  244. int hwtype = (int)sockaddrll.sll_hatype;
  245. if (Enum.IsDefined (typeof (LinuxArpHardware), hwtype)) {
  246. switch ((LinuxArpHardware)hwtype) {
  247. case LinuxArpHardware.EETHER:
  248. goto case LinuxArpHardware.ETHER;
  249. case LinuxArpHardware.ETHER:
  250. type = NetworkInterfaceType.Ethernet;
  251. break;
  252. case LinuxArpHardware.PRONET:
  253. type = NetworkInterfaceType.TokenRing;
  254. break;
  255. case LinuxArpHardware.ATM:
  256. type = NetworkInterfaceType.Atm;
  257. break;
  258. case LinuxArpHardware.SLIP:
  259. type = NetworkInterfaceType.Slip;
  260. break;
  261. case LinuxArpHardware.PPP:
  262. type = NetworkInterfaceType.Ppp;
  263. break;
  264. case LinuxArpHardware.LOOPBACK:
  265. type = NetworkInterfaceType.Loopback;
  266. macAddress = null;
  267. break;
  268. case LinuxArpHardware.FDDI:
  269. type = NetworkInterfaceType.Fddi;
  270. break;
  271. case LinuxArpHardware.TUNNEL6:
  272. goto case LinuxArpHardware.TUNNEL;
  273. case LinuxArpHardware.TUNNEL:
  274. type = NetworkInterfaceType.Tunnel;
  275. break;
  276. }
  277. }
  278. }
  279. }
  280. LinuxNetworkInterface iface = null;
  281. if (!interfaces.TryGetValue (name, out iface)) {
  282. iface = new LinuxNetworkInterface (name);
  283. interfaces.Add (name, iface);
  284. }
  285. if (!address.Equals (IPAddress.None))
  286. iface.AddAddress (address);
  287. if (macAddress != null || type == NetworkInterfaceType.Loopback) {
  288. if (type == NetworkInterfaceType.Ethernet) {
  289. if (Directory.Exists(iface.IfacePath + "wireless")) {
  290. type = NetworkInterfaceType.Wireless80211;
  291. }
  292. }
  293. iface.SetLinkLayerInfo (index, macAddress, type);
  294. }
  295. next = addr.ifa_next;
  296. }
  297. } finally {
  298. freeifaddrs (ifap);
  299. }
  300. NetworkInterface [] result = new NetworkInterface [interfaces.Count];
  301. int x = 0;
  302. foreach (NetworkInterface thisInterface in interfaces.Values) {
  303. result [x] = thisInterface;
  304. x++;
  305. }
  306. return result;
  307. }
  308. LinuxNetworkInterface (string name)
  309. : base (name)
  310. {
  311. iface_path = "/sys/class/net/" + name + "/";
  312. iface_operstate_path = iface_path + "operstate";
  313. iface_flags_path = iface_path + "flags";
  314. }
  315. public override IPInterfaceProperties GetIPProperties ()
  316. {
  317. if (ipproperties == null)
  318. ipproperties = new LinuxIPInterfaceProperties (this, addresses);
  319. return ipproperties;
  320. }
  321. public override IPv4InterfaceStatistics GetIPv4Statistics ()
  322. {
  323. if (ipv4stats == null)
  324. ipv4stats = new LinuxIPv4InterfaceStatistics (this);
  325. return ipv4stats;
  326. }
  327. public override OperationalStatus OperationalStatus {
  328. get {
  329. if (!Directory.Exists (iface_path))
  330. return OperationalStatus.Unknown;
  331. try {
  332. string s = ReadLine (iface_operstate_path);
  333. switch (s){
  334. case "unknown":
  335. return OperationalStatus.Unknown;
  336. case "notpresent":
  337. return OperationalStatus.NotPresent;
  338. case "down":
  339. return OperationalStatus.Down;
  340. case "lowerlayerdown":
  341. return OperationalStatus.LowerLayerDown;
  342. case "testing":
  343. return OperationalStatus.Testing;
  344. case "dormant":
  345. return OperationalStatus.Dormant;
  346. case "up":
  347. return OperationalStatus.Up;
  348. }
  349. } catch {
  350. }
  351. return OperationalStatus.Unknown;
  352. }
  353. }
  354. public override bool SupportsMulticast {
  355. get {
  356. if (!Directory.Exists (iface_path))
  357. return false;
  358. try {
  359. string s = ReadLine (iface_flags_path);
  360. if (s.Length > 2 && s [0] == '0' && s [1] == 'x')
  361. s = s.Substring (2);
  362. ulong f = UInt64.Parse (s, NumberStyles.HexNumber);
  363. // Hardcoded, only useful for Linux.
  364. return ((f & 0x1000) == 0x1000);
  365. } catch {
  366. return false;
  367. }
  368. }
  369. }
  370. }
  371. class MacOsNetworkInterface : UnixNetworkInterface
  372. {
  373. [DllImport ("libc")]
  374. static extern int getifaddrs (out IntPtr ifap);
  375. [DllImport ("libc")]
  376. static extern void freeifaddrs (IntPtr ifap);
  377. const int AF_INET = 2;
  378. const int AF_INET6 = 30;
  379. const int AF_LINK = 18;
  380. public static NetworkInterface [] ImplGetAllNetworkInterfaces ()
  381. {
  382. var interfaces = new Dictionary <string, MacOsNetworkInterface> ();
  383. IntPtr ifap;
  384. if (getifaddrs (out ifap) != 0)
  385. throw new SystemException ("getifaddrs() failed");
  386. try {
  387. IntPtr next = ifap;
  388. while (next != IntPtr.Zero) {
  389. MacOsStructs.ifaddrs addr = (MacOsStructs.ifaddrs) Marshal.PtrToStructure (next, typeof (MacOsStructs.ifaddrs));
  390. IPAddress address = IPAddress.None;
  391. string name = addr.ifa_name;
  392. int index = -1;
  393. byte[] macAddress = null;
  394. NetworkInterfaceType type = NetworkInterfaceType.Unknown;
  395. if (addr.ifa_addr != IntPtr.Zero) {
  396. MacOsStructs.sockaddr sockaddr = (MacOsStructs.sockaddr) Marshal.PtrToStructure (addr.ifa_addr, typeof (MacOsStructs.sockaddr));
  397. if (sockaddr.sa_family == AF_INET6) {
  398. MacOsStructs.sockaddr_in6 sockaddr6 = (MacOsStructs.sockaddr_in6) Marshal.PtrToStructure (addr.ifa_addr, typeof (MacOsStructs.sockaddr_in6));
  399. address = new IPAddress (sockaddr6.sin6_addr.u6_addr8, sockaddr6.sin6_scope_id);
  400. } else if (sockaddr.sa_family == AF_INET) {
  401. MacOsStructs.sockaddr_in sockaddrin = (MacOsStructs.sockaddr_in) Marshal.PtrToStructure (addr.ifa_addr, typeof (MacOsStructs.sockaddr_in));
  402. address = new IPAddress (sockaddrin.sin_addr);
  403. } else if (sockaddr.sa_family == AF_LINK) {
  404. MacOsStructs.sockaddr_dl sockaddrdl = new MacOsStructs.sockaddr_dl ();
  405. sockaddrdl.Read (addr.ifa_addr);
  406. macAddress = new byte [(int) sockaddrdl.sdl_alen];
  407. Array.Copy (sockaddrdl.sdl_data, sockaddrdl.sdl_nlen, macAddress, 0, Math.Min (macAddress.Length, sockaddrdl.sdl_data.Length - sockaddrdl.sdl_nlen));
  408. index = sockaddrdl.sdl_index;
  409. int hwtype = (int) sockaddrdl.sdl_type;
  410. if (Enum.IsDefined (typeof (MacOsArpHardware), hwtype)) {
  411. switch ((MacOsArpHardware) hwtype) {
  412. case MacOsArpHardware.ETHER:
  413. type = NetworkInterfaceType.Ethernet;
  414. break;
  415. case MacOsArpHardware.ATM:
  416. type = NetworkInterfaceType.Atm;
  417. break;
  418. case MacOsArpHardware.SLIP:
  419. type = NetworkInterfaceType.Slip;
  420. break;
  421. case MacOsArpHardware.PPP:
  422. type = NetworkInterfaceType.Ppp;
  423. break;
  424. case MacOsArpHardware.LOOPBACK:
  425. type = NetworkInterfaceType.Loopback;
  426. macAddress = null;
  427. break;
  428. case MacOsArpHardware.FDDI:
  429. type = NetworkInterfaceType.Fddi;
  430. break;
  431. }
  432. }
  433. }
  434. }
  435. MacOsNetworkInterface iface = null;
  436. if (!interfaces.TryGetValue (name, out iface)) {
  437. iface = new MacOsNetworkInterface (name);
  438. interfaces.Add (name, iface);
  439. }
  440. if (!address.Equals (IPAddress.None))
  441. iface.AddAddress (address);
  442. if (macAddress != null || type == NetworkInterfaceType.Loopback)
  443. iface.SetLinkLayerInfo (index, macAddress, type);
  444. next = addr.ifa_next;
  445. }
  446. } finally {
  447. freeifaddrs (ifap);
  448. }
  449. NetworkInterface [] result = new NetworkInterface [interfaces.Count];
  450. int x = 0;
  451. foreach (NetworkInterface thisInterface in interfaces.Values) {
  452. result [x] = thisInterface;
  453. x++;
  454. }
  455. return result;
  456. }
  457. MacOsNetworkInterface (string name)
  458. : base (name)
  459. {
  460. }
  461. public override IPInterfaceProperties GetIPProperties ()
  462. {
  463. if (ipproperties == null)
  464. ipproperties = new MacOsIPInterfaceProperties (this, addresses);
  465. return ipproperties;
  466. }
  467. public override IPv4InterfaceStatistics GetIPv4Statistics ()
  468. {
  469. if (ipv4stats == null)
  470. ipv4stats = new MacOsIPv4InterfaceStatistics (this);
  471. return ipv4stats;
  472. }
  473. public override OperationalStatus OperationalStatus {
  474. get {
  475. return OperationalStatus.Unknown;
  476. }
  477. }
  478. public override bool SupportsMulticast {
  479. get {
  480. return false;
  481. }
  482. }
  483. }
  484. class Win32NetworkInterface2 : NetworkInterface
  485. {
  486. [DllImport ("iphlpapi.dll", SetLastError = true)]
  487. static extern int GetAdaptersInfo (byte [] info, ref int size);
  488. [DllImport ("iphlpapi.dll", SetLastError = true)]
  489. static extern int GetAdaptersAddresses (uint family, uint flags, IntPtr reserved, byte [] info, ref int size);
  490. [DllImport ("iphlpapi.dll", SetLastError = true)]
  491. static extern int GetIfEntry (ref Win32_MIB_IFROW row);
  492. public static NetworkInterface [] ImplGetAllNetworkInterfaces ()
  493. {
  494. // Win32_IP_ADAPTER_INFO [] ai = GetAdaptersInfo ();
  495. Win32_IP_ADAPTER_ADDRESSES [] aa = GetAdaptersAddresses ();
  496. NetworkInterface [] ret = new NetworkInterface [aa.Length];
  497. for (int i = 0; i < ret.Length; i++)
  498. ret [i] = new Win32NetworkInterface2 (aa [i]);
  499. return ret;
  500. }
  501. public static Win32_IP_ADAPTER_INFO GetAdapterInfoByIndex (int index)
  502. {
  503. foreach (Win32_IP_ADAPTER_INFO info in GetAdaptersInfo ())
  504. if (info.Index == index)
  505. return info;
  506. return null;
  507. }
  508. unsafe static Win32_IP_ADAPTER_INFO [] GetAdaptersInfo ()
  509. {
  510. byte [] bytes = null;
  511. int len = 0;
  512. GetAdaptersInfo (bytes, ref len);
  513. bytes = new byte [len];
  514. int ret = GetAdaptersInfo (bytes, ref len);
  515. if (ret != 0)
  516. throw new NetworkInformationException (ret);
  517. List<Win32_IP_ADAPTER_INFO> l = new List<Win32_IP_ADAPTER_INFO> ();
  518. fixed (byte* ptr = bytes) {
  519. Win32_IP_ADAPTER_INFO info;
  520. for (IntPtr p = (IntPtr) ptr; p != IntPtr.Zero; p = info.Next) {
  521. info = new Win32_IP_ADAPTER_INFO ();
  522. Marshal.PtrToStructure (p, info);
  523. l.Add (info);
  524. }
  525. }
  526. return l.ToArray ();
  527. }
  528. unsafe static Win32_IP_ADAPTER_ADDRESSES [] GetAdaptersAddresses ()
  529. {
  530. byte [] bytes = null;
  531. int len = 0;
  532. GetAdaptersAddresses (0, 0, IntPtr.Zero, bytes, ref len);
  533. bytes = new byte [len];
  534. int ret = GetAdaptersAddresses (0, 0, IntPtr.Zero, bytes, ref len);
  535. if (ret != 0)
  536. throw new NetworkInformationException (ret);
  537. List<Win32_IP_ADAPTER_ADDRESSES> l = new List<Win32_IP_ADAPTER_ADDRESSES> ();
  538. fixed (byte* ptr = bytes) {
  539. Win32_IP_ADAPTER_ADDRESSES info;
  540. for (IntPtr p = (IntPtr) ptr; p != IntPtr.Zero; p = info.Next) {
  541. info = new Win32_IP_ADAPTER_ADDRESSES ();
  542. Marshal.PtrToStructure (p, info);
  543. l.Add (info);
  544. }
  545. }
  546. return l.ToArray ();
  547. }
  548. Win32_IP_ADAPTER_ADDRESSES addr;
  549. Win32_MIB_IFROW mib4, mib6;
  550. Win32IPv4InterfaceStatistics ip4stats;
  551. IPInterfaceProperties ip_if_props;
  552. Win32NetworkInterface2 (Win32_IP_ADAPTER_ADDRESSES addr)
  553. {
  554. this.addr = addr;
  555. mib4 = default (Win32_MIB_IFROW);
  556. mib4.Index = addr.Alignment.IfIndex;
  557. if (GetIfEntry (ref mib4) != 0)
  558. mib4.Index = -1; // unavailable;
  559. mib6 = default (Win32_MIB_IFROW);
  560. mib6.Index = addr.Ipv6IfIndex;
  561. if (GetIfEntry (ref mib6) != 0)
  562. mib6.Index = -1; // unavailable;
  563. ip4stats = new Win32IPv4InterfaceStatistics (mib4);
  564. ip_if_props = new Win32IPInterfaceProperties2 (addr, mib4, mib6);
  565. }
  566. public override IPInterfaceProperties GetIPProperties ()
  567. {
  568. return ip_if_props;
  569. }
  570. public override IPv4InterfaceStatistics GetIPv4Statistics ()
  571. {
  572. return ip4stats;
  573. }
  574. public override PhysicalAddress GetPhysicalAddress ()
  575. {
  576. byte [] bytes = new byte [addr.PhysicalAddressLength];
  577. Array.Copy (addr.PhysicalAddress, 0, bytes, 0, bytes.Length);
  578. return new PhysicalAddress (bytes);
  579. }
  580. public override bool Supports (NetworkInterfaceComponent networkInterfaceComponent)
  581. {
  582. switch (networkInterfaceComponent) {
  583. case NetworkInterfaceComponent.IPv4:
  584. return mib4.Index >= 0;
  585. case NetworkInterfaceComponent.IPv6:
  586. return mib6.Index >= 0;
  587. }
  588. return false;
  589. }
  590. public override string Description {
  591. get { return addr.Description; }
  592. }
  593. public override string Id {
  594. get { return addr.AdapterName; }
  595. }
  596. public override bool IsReceiveOnly {
  597. get { return addr.IsReceiveOnly; }
  598. }
  599. public override string Name {
  600. get { return addr.FriendlyName; }
  601. }
  602. public override NetworkInterfaceType NetworkInterfaceType {
  603. get { return addr.IfType; }
  604. }
  605. public override OperationalStatus OperationalStatus {
  606. get { return addr.OperStatus; }
  607. }
  608. public override long Speed {
  609. get { return mib6.Index >= 0 ? mib6.Speed : mib4.Speed; }
  610. }
  611. public override bool SupportsMulticast {
  612. get { return !addr.NoMulticast; }
  613. }
  614. }
  615. }