You've already forked linux-packaging-mono
Imported Upstream version 6.0.0.172
Former-commit-id: f3cc9b82f3e5bd8f0fd3ebc098f789556b44e9cd
This commit is contained in:
parent
8016999e4d
commit
64ac736ec5
@ -0,0 +1,337 @@
|
||||
//
|
||||
// System.Net.NetworkInformation.NetworkInterface
|
||||
//
|
||||
// Authors:
|
||||
// Gonzalo Paniagua Javier (gonzalo@novell.com)
|
||||
// Atsushi Enomoto (atsushi@ximian.com)
|
||||
// Miguel de Icaza (miguel@novell.com)
|
||||
// Eric Butler (eric@extremeboredom.net)
|
||||
// Marek Habersack (mhabersack@novell.com)
|
||||
// Marek Safar (marek.safar@gmail.com)
|
||||
// Calvin Buckley (calvin@cmpct.info)
|
||||
//
|
||||
// Copyright (c) 2006-2008 Novell, Inc. (http://www.novell.com)
|
||||
//
|
||||
// Copyright (c) 2018 Calvin Buckley
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace System.Net.NetworkInformation {
|
||||
internal class AixNetworkInterfaceAPI : UnixNetworkInterfaceAPI
|
||||
{
|
||||
const int SOCK_DGRAM = 2;
|
||||
|
||||
// AIX doesn't have getifaddrs, (i does though) so we instead query the painful way via ioctl. For IBM's docs on this, see:
|
||||
// https://www.ibm.com/support/knowledgecenter/en/ssw_aix_71/com.ibm.aix.commtrf2/ioctl_socket_control_operations.htm
|
||||
[DllImport("libc", SetLastError = true)]
|
||||
public static extern int socket (AixAddressFamily family, int type, int protocol);
|
||||
[DllImport("libc")]
|
||||
public static extern int close (int fd);
|
||||
// overloads to make usage less painful
|
||||
[DllImport("libc", SetLastError = true)]
|
||||
public static extern int ioctl (int fd, AixIoctlRequest request, IntPtr arg);
|
||||
[DllImport("libc", SetLastError = true)]
|
||||
public static extern int ioctl (int fd, AixIoctlRequest request, ref int arg);
|
||||
[DllImport("libc", SetLastError = true)]
|
||||
public static extern int ioctl (int fd, AixIoctlRequest request, ref AixStructs.ifconf arg);
|
||||
[DllImport("libc", SetLastError = true)]
|
||||
public static extern int ioctl (int fd, AixIoctlRequest request, ref AixStructs.ifreq_flags arg);
|
||||
[DllImport("libc", SetLastError = true)]
|
||||
public static extern int ioctl (int fd, AixIoctlRequest request, ref AixStructs.ifreq_mtu arg);
|
||||
[DllImport("libc", SetLastError = true)]
|
||||
public static extern int ioctl (int fd, AixIoctlRequest request, ref AixStructs.ifreq_addrin arg);
|
||||
|
||||
static unsafe void ByteArrayCopy (byte* dst, byte* src, int elements)
|
||||
{
|
||||
for (int i = 0; i < 16; i++)
|
||||
dst[i] = src[i];
|
||||
}
|
||||
|
||||
public override NetworkInterface [] GetAllNetworkInterfaces ()
|
||||
{
|
||||
var interfaces = new Dictionary <string, AixNetworkInterface> ();
|
||||
AixStructs.ifconf ifc;
|
||||
ifc.ifc_len = 0;
|
||||
ifc.ifc_buf = IntPtr.Zero;
|
||||
int sockfd = -1;
|
||||
|
||||
try {
|
||||
sockfd = socket (AixAddressFamily.AF_INET, SOCK_DGRAM, 0);
|
||||
if (sockfd == -1)
|
||||
throw new SystemException ("socket for SIOCGIFCONF failed");
|
||||
|
||||
if (ioctl (sockfd, AixIoctlRequest.SIOCGSIZIFCONF, ref ifc.ifc_len) < 0 || ifc.ifc_len < 1) {
|
||||
throw new SystemException ("ioctl for SIOCGSIZIFCONF failed");
|
||||
}
|
||||
ifc.ifc_buf = Marshal.AllocHGlobal(ifc.ifc_len);
|
||||
|
||||
if (ioctl (sockfd, AixIoctlRequest.SIOCGIFCONF, ref ifc) < 0)
|
||||
throw new SystemException ("ioctl for SIOCGIFCONF failed");
|
||||
|
||||
// this is required because the buffer is an array of VARIABLE LENGTH structures, so sane marshalling is impossible
|
||||
AixStructs.ifreq ifr;
|
||||
var curPos = ifc.ifc_buf;
|
||||
var endPos = ifc.ifc_buf.ToInt64() + ifc.ifc_len;
|
||||
for (ifr = (AixStructs.ifreq)Marshal.PtrToStructure (curPos, typeof (AixStructs.ifreq));
|
||||
curPos.ToInt64() < endPos;
|
||||
// name length + sockaddr length (SIOCGIFCONF only deals in those)
|
||||
curPos = curPos + (16 + ifr.ifru_addr.sa_len))
|
||||
{
|
||||
// update the structure for next increment
|
||||
ifr = (AixStructs.ifreq)Marshal.PtrToStructure (curPos, typeof (AixStructs.ifreq));
|
||||
|
||||
// the goods
|
||||
IPAddress address = IPAddress.None;
|
||||
string name = null;
|
||||
int index = -1;
|
||||
byte[] macAddress = null;
|
||||
var type = NetworkInterfaceType.Unknown;
|
||||
|
||||
unsafe {
|
||||
name = Marshal.PtrToStringAnsi(new IntPtr(ifr.ifr_name));
|
||||
}
|
||||
|
||||
if (Enum.IsDefined (typeof (AixAddressFamily), (int)ifr.ifru_addr.sa_family)) {
|
||||
switch ((AixAddressFamily)ifr.ifru_addr.sa_family) {
|
||||
case AixAddressFamily.AF_INET:
|
||||
AixStructs.sockaddr_in sockaddrin =
|
||||
(AixStructs.sockaddr_in)Marshal.PtrToStructure(curPos + 16, typeof (AixStructs.sockaddr_in));
|
||||
address = new IPAddress (sockaddrin.sin_addr);
|
||||
break;
|
||||
case AixAddressFamily.AF_INET6:
|
||||
AixStructs.sockaddr_in6 sockaddr6 =
|
||||
(AixStructs.sockaddr_in6) Marshal.PtrToStructure(curPos + 16, typeof (AixStructs.sockaddr_in6));
|
||||
address = new IPAddress (sockaddr6.sin6_addr.u6_addr8, sockaddr6.sin6_scope_id);
|
||||
break;
|
||||
// XXX: i never returns AF_LINK and SIOCGIFCONF under i doesn't return nameindex values; adapt MacOsNetworkInterface for Qp2getifaddrs instead
|
||||
case AixAddressFamily.AF_LINK:
|
||||
AixStructs.sockaddr_dl sockaddrdl = new AixStructs.sockaddr_dl();
|
||||
sockaddrdl.Read (curPos + 16);
|
||||
|
||||
macAddress = new byte [(int) sockaddrdl.sdl_alen];
|
||||
// copy mac address from sdl_data field starting at last index pos of interface name into array macaddress, starting
|
||||
// at index 0
|
||||
Array.Copy (sockaddrdl.sdl_data, sockaddrdl.sdl_nlen, macAddress, 0, Math.Min (macAddress.Length, sockaddrdl.sdl_data.Length - sockaddrdl.sdl_nlen));
|
||||
|
||||
index = sockaddrdl.sdl_index;
|
||||
|
||||
int hwtype = (int) sockaddrdl.sdl_type;
|
||||
if (Enum.IsDefined (typeof (AixArpHardware), hwtype)) {
|
||||
switch ((AixArpHardware) hwtype) {
|
||||
case AixArpHardware.ETHER:
|
||||
type = NetworkInterfaceType.Ethernet;
|
||||
break;
|
||||
|
||||
case AixArpHardware.ATM:
|
||||
type = NetworkInterfaceType.Atm;
|
||||
break;
|
||||
|
||||
case AixArpHardware.SLIP:
|
||||
type = NetworkInterfaceType.Slip;
|
||||
break;
|
||||
|
||||
case AixArpHardware.PPP:
|
||||
type = NetworkInterfaceType.Ppp;
|
||||
break;
|
||||
|
||||
case AixArpHardware.LOOPBACK:
|
||||
type = NetworkInterfaceType.Loopback;
|
||||
macAddress = null;
|
||||
break;
|
||||
|
||||
case AixArpHardware.FDDI:
|
||||
type = NetworkInterfaceType.Fddi;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
// get flags
|
||||
uint flags = 0;
|
||||
int mtu = 0;
|
||||
unsafe {
|
||||
AixStructs.ifreq_flags ifrFlags = new AixStructs.ifreq_flags ();
|
||||
ByteArrayCopy (ifrFlags.ifr_name, ifr.ifr_name, 16);
|
||||
if (ioctl (sockfd, AixIoctlRequest.SIOCGIFFLAGS, ref ifrFlags) < 0)
|
||||
throw new SystemException("ioctl for SIOCGIFFLAGS failed");
|
||||
else
|
||||
flags = ifrFlags.ifru_flags;
|
||||
|
||||
AixStructs.ifreq_mtu ifrMtu = new AixStructs.ifreq_mtu ();
|
||||
ByteArrayCopy (ifrMtu.ifr_name, ifr.ifr_name, 16);
|
||||
if (ioctl (sockfd, AixIoctlRequest.SIOCGIFMTU, ref ifrMtu) < 0) {
|
||||
// it's not the end of the world if we don't get it
|
||||
}
|
||||
else
|
||||
mtu = ifrMtu.ifru_mtu;
|
||||
}
|
||||
|
||||
AixNetworkInterface iface = null;
|
||||
|
||||
// create interface if not already present
|
||||
if (!interfaces.TryGetValue (name, out iface)) {
|
||||
iface = new AixNetworkInterface (name, flags, mtu);
|
||||
interfaces.Add (name, iface);
|
||||
}
|
||||
|
||||
// if a new address has been found, add it
|
||||
if (!address.Equals (IPAddress.None))
|
||||
iface.AddAddress (address);
|
||||
|
||||
// set link layer info, if iface has macaddress or is loopback device
|
||||
if (macAddress != null || type == NetworkInterfaceType.Loopback)
|
||||
iface.SetLinkLayerInfo (index, macAddress, type);
|
||||
}
|
||||
} finally {
|
||||
if (ifc.ifc_buf != IntPtr.Zero)
|
||||
Marshal.FreeHGlobal(ifc.ifc_buf);
|
||||
if (sockfd != -1)
|
||||
close (sockfd);
|
||||
}
|
||||
|
||||
NetworkInterface [] result = new NetworkInterface [interfaces.Count];
|
||||
int x = 0;
|
||||
foreach (NetworkInterface thisInterface in interfaces.Values) {
|
||||
result [x] = thisInterface;
|
||||
x++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public override int GetLoopbackInterfaceIndex ()
|
||||
{
|
||||
// XXX: "*LOOPBACK" on i
|
||||
return if_nametoindex ("lo0");
|
||||
}
|
||||
|
||||
public override IPAddress GetNetMask (IPAddress address)
|
||||
{
|
||||
AixStructs.ifconf ifc;
|
||||
ifc.ifc_len = 0;
|
||||
ifc.ifc_buf = IntPtr.Zero;
|
||||
int sockfd = -1;
|
||||
|
||||
try {
|
||||
sockfd = socket (AixAddressFamily.AF_INET, SOCK_DGRAM, 0);
|
||||
if (sockfd == -1)
|
||||
throw new SystemException ("socket for SIOCGIFCONF failed");
|
||||
|
||||
if (ioctl (sockfd, AixIoctlRequest.SIOCGSIZIFCONF, ref ifc.ifc_len) < 0 || ifc.ifc_len < 1)
|
||||
throw new SystemException ("ioctl for SIOCGSIZIFCONF failed");
|
||||
ifc.ifc_buf = Marshal.AllocHGlobal(ifc.ifc_len);
|
||||
|
||||
if (ioctl (sockfd, AixIoctlRequest.SIOCGIFCONF, ref ifc) < 0)
|
||||
throw new SystemException ("ioctl for SIOCGIFCONF failed");
|
||||
|
||||
// this is required because the buffer is an array of VARIABLE LENGTH structures, so sane marshalling is impossible
|
||||
AixStructs.ifreq ifr;
|
||||
var curPos = ifc.ifc_buf;
|
||||
var endPos = ifc.ifc_buf.ToInt64() + ifc.ifc_len;
|
||||
for (ifr = (AixStructs.ifreq)Marshal.PtrToStructure (curPos, typeof (AixStructs.ifreq));
|
||||
curPos.ToInt64() < endPos;
|
||||
// name length + sockaddr length (SIOCGIFCONF only deals in those)
|
||||
curPos += (16 + ifr.ifru_addr.sa_len))
|
||||
{
|
||||
// update the structure for next increment
|
||||
ifr = (AixStructs.ifreq)Marshal.PtrToStructure (curPos, typeof (AixStructs.ifreq));
|
||||
|
||||
if (Enum.IsDefined (typeof (AixAddressFamily), (int)ifr.ifru_addr.sa_family)) {
|
||||
switch ((AixAddressFamily)ifr.ifru_addr.sa_family) {
|
||||
case AixAddressFamily.AF_INET:
|
||||
AixStructs.sockaddr_in sockaddrin =
|
||||
(AixStructs.sockaddr_in)Marshal.PtrToStructure(curPos + 16, typeof (AixStructs.sockaddr_in));
|
||||
var saddress = new IPAddress (sockaddrin.sin_addr);
|
||||
if (address.Equals (saddress)) {
|
||||
AixStructs.ifreq_addrin ifrMask = new AixStructs.ifreq_addrin ();
|
||||
unsafe {
|
||||
ByteArrayCopy (ifrMask.ifr_name, ifr.ifr_name, 16);
|
||||
}
|
||||
// there's an IPv6 version of it too, but Mac OS doesn't try this, so
|
||||
if (ioctl (sockfd, AixIoctlRequest.SIOCGIFNETMASK, ref ifrMask) < 0)
|
||||
return new IPAddress(ifrMask.ifru_addr.sin_addr);
|
||||
else
|
||||
throw new SystemException("ioctl for SIOCGIFNETMASK failed");
|
||||
}
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if (ifc.ifc_buf != IntPtr.Zero)
|
||||
Marshal.FreeHGlobal(ifc.ifc_buf);
|
||||
if (sockfd != -1)
|
||||
close (sockfd);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
sealed class AixNetworkInterface : UnixNetworkInterface
|
||||
{
|
||||
private uint _ifa_flags;
|
||||
private int _ifru_mtu;
|
||||
|
||||
internal AixNetworkInterface (string name, uint ifa_flags, int ifru_mtu)
|
||||
: base (name)
|
||||
{
|
||||
_ifa_flags = ifa_flags;
|
||||
_ifru_mtu = ifru_mtu;
|
||||
}
|
||||
|
||||
public override IPInterfaceProperties GetIPProperties ()
|
||||
{
|
||||
if (ipproperties == null)
|
||||
ipproperties = new AixIPInterfaceProperties (this, addresses, _ifru_mtu);
|
||||
return ipproperties;
|
||||
}
|
||||
|
||||
public override IPv4InterfaceStatistics GetIPv4Statistics ()
|
||||
{
|
||||
if (ipv4stats == null)
|
||||
ipv4stats = new AixIPv4InterfaceStatistics (this);
|
||||
return ipv4stats;
|
||||
}
|
||||
|
||||
public override OperationalStatus OperationalStatus {
|
||||
get {
|
||||
if(((AixInterfaceFlags)_ifa_flags & AixInterfaceFlags.IFF_UP) == AixInterfaceFlags.IFF_UP){
|
||||
return OperationalStatus.Up;
|
||||
}
|
||||
return OperationalStatus.Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool SupportsMulticast {
|
||||
get {
|
||||
return ((AixInterfaceFlags)_ifa_flags & AixInterfaceFlags.IFF_MULTICAST) == AixInterfaceFlags.IFF_MULTICAST;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user