GetAdaptersAddresses (iphlpapi)
Last changed: -167.220.205.82

.
Summary
Gets information on the IP adapters on the machine.

C# Signature:

[DllImport("iphlpapi.dll")]
private static extern ERROR GetAdaptersAddresses(uint Family, uint Flags, IntPtr Reserved, IntPtr pAdapterAddresses, ref uint pOutBufLen);

User-Defined Types:

IP_ADAPTER_ADDRESSES

Alternative Managed API:

Some, but not, all the information provided by the P/Invoke are available from the managed System.Net.NetworkInformation.NetworkInterface (http://msdn.microsoft.com/en-us/library/system.net.networkinformation.networkinterface.aspx) class.

Sample Code:

using System;
using System.Text;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Net;
using System.Linq;

    public static class IPIntertop
    {
    public enum FAMILY : uint
    {
        /// <summary>IPv4</summary>
        AF_INET = 2,
        /// <summary>IPv6</summary>
        AF_INET6 = 23,
        /// <summary>Unpecified. Includes both IPv4 and IPv4</summary>
        AF_UNSPEC = 0
    }
    public enum FLAGS : uint
    {
        GAA_FLAG_DEFAULT = 0x0000,
        GAA_FLAG_SKIP_UNICAST = 0x0001,
        GAA_FLAG_SKIP_ANYCAST = 0x0002,
        GAA_FLAG_SKIP_MULTICAST = 0x0004,
        GAA_FLAG_SKIP_DNS_SERVER = 0x0008,
        GAA_FLAG_INCLUDE_PREFIX = 0x0010,
        GAA_FLAG_SKIP_FRIENDLY_NAME = 0x0020,
        GAA_FLAG_INCLUDE_WINS_INFO = 0x0040,
        GAA_FLAG_INCLUDE_GATEWAYS = 0x0080,
        GAA_FLAG_INCLUDE_ALL_INTERFACES = 0x0100,
        GAA_FLAG_INCLUDE_ALL_COMPARTMENTS = 0x0200,
        GAA_FLAG_INCLUDE_TUNNEL_BINDINGORDER = 0x0400,
        GAA_FLAG_SKIP_DNS_INFO = 0x0800
    }
    public enum ERROR : uint
    {
        ERROR_SUCCESS = 0,
        ERROR_NO_DATA = 232,
        ERROR_BUFFER_OVERFLOW = 111,
        ERROR_INVALID_PARAMETER = 87
    }
    public enum IF_OPER_STATUS : uint
    {
        IfOperStatusUp = 1,
        IfOperStatusDown,
        IfOperStatusTesting,
        IfOperStatusUnknown,
        IfOperStatusDormant,
        IfOperStatusNotPresent,
        IfOperStatusLowerLayerDown,
    }
    public enum IF_TYPE : uint
    {
        IF_TYPE_OTHER = 1,   // None of the below
        IF_TYPE_REGULAR_1822 = 2,
        IF_TYPE_HDH_1822 = 3,
        IF_TYPE_DDN_X25 = 4,
        IF_TYPE_RFC877_X25 = 5,
        IF_TYPE_ETHERNET_CSMACD = 6,
        IF_TYPE_IS088023_CSMACD = 7,
        IF_TYPE_ISO88024_TOKENBUS = 8,
        IF_TYPE_ISO88025_TOKENRING = 9,
        IF_TYPE_ISO88026_MAN = 10,
        IF_TYPE_STARLAN = 11,
        IF_TYPE_PROTEON_10MBIT = 12,
        IF_TYPE_PROTEON_80MBIT = 13,
        IF_TYPE_HYPERCHANNEL = 14,
        IF_TYPE_FDDI = 15,
        IF_TYPE_LAP_B = 16,
        IF_TYPE_SDLC = 17,
        IF_TYPE_DS1 = 18,  // DS1-MIB
        IF_TYPE_E1 = 19,  // Obsolete; see DS1-MIB
        IF_TYPE_BASIC_ISDN = 20,
        IF_TYPE_PRIMARY_ISDN = 21,
        IF_TYPE_PROP_POINT2POINT_SERIAL = 22,  // proprietary serial
        IF_TYPE_PPP = 23,
        IF_TYPE_SOFTWARE_LOOPBACK = 24,
        IF_TYPE_EON = 25,  // CLNP over IP
        IF_TYPE_ETHERNET_3MBIT = 26,
        IF_TYPE_NSIP = 27,  // XNS over IP
        IF_TYPE_SLIP = 28,  // Generic Slip
        IF_TYPE_ULTRA = 29,  // ULTRA Technologies
        IF_TYPE_DS3 = 30,  // DS3-MIB
        IF_TYPE_SIP = 31,  // SMDS, coffee
        IF_TYPE_FRAMERELAY = 32,  // DTE only
        IF_TYPE_RS232 = 33,
        IF_TYPE_PARA = 34,  // Parallel port
        IF_TYPE_ARCNET = 35,
        IF_TYPE_ARCNET_PLUS = 36,
        IF_TYPE_ATM = 37,  // ATM cells
        IF_TYPE_MIO_X25 = 38,
        IF_TYPE_SONET = 39,  // SONET or SDH
        IF_TYPE_X25_PLE = 40,
        IF_TYPE_ISO88022_LLC = 41,
        IF_TYPE_LOCALTALK = 42,
        IF_TYPE_SMDS_DXI = 43,
        IF_TYPE_FRAMERELAY_SERVICE = 44,  // FRNETSERV-MIB
        IF_TYPE_V35 = 45,
        IF_TYPE_HSSI = 46,
        IF_TYPE_HIPPI = 47,
        IF_TYPE_MODEM = 48,  // Generic Modem
        IF_TYPE_AAL5 = 49,  // AAL5 over ATM
        IF_TYPE_SONET_PATH = 50,
        IF_TYPE_SONET_VT = 51,
        IF_TYPE_SMDS_ICIP = 52,  // SMDS InterCarrier Interface
        IF_TYPE_PROP_VIRTUAL = 53,  // Proprietary virtual/internal
        IF_TYPE_PROP_MULTIPLEXOR = 54,  // Proprietary multiplexing
        IF_TYPE_IEEE80212 = 55,  // 100BaseVG
        IF_TYPE_FIBRECHANNEL = 56,
        IF_TYPE_HIPPIINTERFACE = 57,
        IF_TYPE_FRAMERELAY_INTERCONNECT = 58,  // Obsolete, use 32 or 44
        IF_TYPE_AFLANE_8023 = 59,  // ATM Emulated LAN for 802.3
        IF_TYPE_AFLANE_8025 = 60,  // ATM Emulated LAN for 802.5
        IF_TYPE_CCTEMUL = 61,  // ATM Emulated circuit
        IF_TYPE_FASTETHER = 62,  // Fast Ethernet (100BaseT)
        IF_TYPE_ISDN = 63,  // ISDN and X.25
        IF_TYPE_V11 = 64,  // CCITT V.11/X.21
        IF_TYPE_V36 = 65,  // CCITT V.36
        IF_TYPE_G703_64K = 66,  // CCITT G703 at 64Kbps
        IF_TYPE_G703_2MB = 67,  // Obsolete; see DS1-MIB
        IF_TYPE_QLLC = 68,  // SNA QLLC
        IF_TYPE_FASTETHER_FX = 69,  // Fast Ethernet (100BaseFX)
        IF_TYPE_CHANNEL = 70,
        IF_TYPE_IEEE80211 = 71,  // Radio spread spectrum
        IF_TYPE_IBM370PARCHAN = 72,  // IBM System 360/370 OEMI Channel
        IF_TYPE_ESCON = 73,  // IBM Enterprise Systems Connection
        IF_TYPE_DLSW = 74,  // Data Link Switching
        IF_TYPE_ISDN_S = 75,  // ISDN S/T interface
        IF_TYPE_ISDN_U = 76,  // ISDN U interface
        IF_TYPE_LAP_D = 77,  // Link Access Protocol D
        IF_TYPE_IPSWITCH = 78,  // IP Switching Objects
        IF_TYPE_RSRB = 79,  // Remote Source Route Bridging
        IF_TYPE_ATM_LOGICAL = 80,  // ATM Logical Port
        IF_TYPE_DS0 = 81,  // Digital Signal Level 0
        IF_TYPE_DS0_BUNDLE = 82,  // Group of ds0s on the same ds1
        IF_TYPE_BSC = 83,  // Bisynchronous Protocol
        IF_TYPE_ASYNC = 84,  // Asynchronous Protocol
        IF_TYPE_CNR = 85,  // Combat Net Radio
        IF_TYPE_ISO88025R_DTR = 86,  // ISO 802.5r DTR
        IF_TYPE_EPLRS = 87,  // Ext Pos Loc Report Sys
        IF_TYPE_ARAP = 88,  // Appletalk Remote Access Protocol
        IF_TYPE_PROP_CNLS = 89,  // Proprietary Connectionless Proto
        IF_TYPE_HOSTPAD = 90,  // CCITT-ITU X.29 PAD Protocol
        IF_TYPE_TERMPAD = 91,  // CCITT-ITU X.3 PAD Facility
        IF_TYPE_FRAMERELAY_MPI = 92,  // Multiproto Interconnect over FR
        IF_TYPE_X213 = 93,  // CCITT-ITU X213
        IF_TYPE_ADSL = 94,  // Asymmetric Digital Subscrbr Loop
        IF_TYPE_RADSL = 95,  // Rate-Adapt Digital Subscrbr Loop
        IF_TYPE_SDSL = 96,  // Symmetric Digital Subscriber Loop
        IF_TYPE_VDSL = 97,  // Very H-Speed Digital Subscrb Loop
        IF_TYPE_ISO88025_CRFPRINT = 98,  // ISO 802.5 CRFP
        IF_TYPE_MYRINET = 99,  // Myricom Myrinet
        IF_TYPE_VOICE_EM = 100,  // Voice recEive and transMit
        IF_TYPE_VOICE_FXO = 101,  // Voice Foreign Exchange Office
        IF_TYPE_VOICE_FXS = 102,  // Voice Foreign Exchange Station
        IF_TYPE_VOICE_ENCAP = 103,  // Voice encapsulation
        IF_TYPE_VOICE_OVERIP = 104,  // Voice over IP encapsulation
        IF_TYPE_ATM_DXI = 105,  // ATM DXI
        IF_TYPE_ATM_FUNI = 106,  // ATM FUNI
        IF_TYPE_ATM_IMA = 107,  // ATM IMA
        IF_TYPE_PPPMULTILINKBUNDLE = 108,  // PPP Multilink Bundle
        IF_TYPE_IPOVER_CDLC = 109,  // IBM ipOverCdlc
        IF_TYPE_IPOVER_CLAW = 110,  // IBM Common Link Access to Workstn
        IF_TYPE_STACKTOSTACK = 111,  // IBM stackToStack
        IF_TYPE_VIRTUALIPADDRESS = 112,  // IBM VIPA
        IF_TYPE_MPC = 113,  // IBM multi-proto channel support
        IF_TYPE_IPOVER_ATM = 114,  // IBM ipOverAtm
        IF_TYPE_ISO88025_FIBER = 115,  // ISO 802.5j Fiber Token Ring
        IF_TYPE_TDLC = 116,  // IBM twinaxial data link control
        IF_TYPE_GIGABITETHERNET = 117,
        IF_TYPE_HDLC = 118,
        IF_TYPE_LAP_F = 119,
        IF_TYPE_V37 = 120,
        IF_TYPE_X25_MLP = 121,  // Multi-Link Protocol
        IF_TYPE_X25_HUNTGROUP = 122,  // X.25 Hunt Group
        IF_TYPE_TRANSPHDLC = 123,
        IF_TYPE_INTERLEAVE = 124,  // Interleave channel
        IF_TYPE_FAST = 125,  // Fast channel
        IF_TYPE_IP = 126,  // IP (for APPN HPR in IP networks)
        IF_TYPE_DOCSCABLE_MACLAYER = 127,  // CATV Mac Layer
        IF_TYPE_DOCSCABLE_DOWNSTREAM = 128,  // CATV Downstream interface
        IF_TYPE_DOCSCABLE_UPSTREAM = 129,  // CATV Upstream interface
        IF_TYPE_A12MPPSWITCH = 130,  // Avalon Parallel Processor
        IF_TYPE_TUNNEL = 131,  // Encapsulation interface
        IF_TYPE_COFFEE = 132,  // Coffee pot
        IF_TYPE_CES = 133,  // Circuit Emulation Service
        IF_TYPE_ATM_SUBINTERFACE = 134,  // ATM Sub Interface
        IF_TYPE_L2_VLAN = 135,  // Layer 2 Virtual LAN using 802.1Q
        IF_TYPE_L3_IPVLAN = 136,  // Layer 3 Virtual LAN using IP
        IF_TYPE_L3_IPXVLAN = 137,  // Layer 3 Virtual LAN using IPX
        IF_TYPE_DIGITALPOWERLINE = 138,  // IP over Power Lines
        IF_TYPE_MEDIAMAILOVERIP = 139,  // Multimedia Mail over IP
        IF_TYPE_DTM = 140,  // Dynamic syncronous Transfer Mode
        IF_TYPE_DCN = 141,  // Data Communications Network
        IF_TYPE_IPFORWARD = 142,  // IP Forwarding Interface
        IF_TYPE_MSDSL = 143,  // Multi-rate Symmetric DSL
        IF_TYPE_IEEE1394 = 144,  // IEEE1394 High Perf Serial Bus
        IF_TYPE_RECEIVE_ONLY = 145 // TV adapter type
    }
    public enum IP_SUFFIX_ORIGIN : uint
    {
        /// IpSuffixOriginOther -> 0
        IpSuffixOriginOther = 0,
        IpSuffixOriginManual,
        IpSuffixOriginWellKnown,
        IpSuffixOriginDhcp,
        IpSuffixOriginLinkLayerAddress,
        IpSuffixOriginRandom,
    }
    public enum IP_PREFIX_ORIGIN : uint
    {
        /// IpPrefixOriginOther -> 0
        IpPrefixOriginOther = 0,
        IpPrefixOriginManual,
        IpPrefixOriginWellKnown,
        IpPrefixOriginDhcp,
        IpPrefixOriginRouterAdvertisement,
    }
    public enum IP_DAD_STATE : uint
    {
        /// IpDadStateInvalid -> 0
        IpDadStateInvalid = 0,
        IpDadStateTentative,
        IpDadStateDuplicate,
        IpDadStateDeprecated,
        IpDadStatePreferred,
    }

    public enum NET_IF_CONNECTION_TYPE : uint
    {
        NET_IF_CONNECTION_DEDICATED = 1,
        NET_IF_CONNECTION_PASSIVE = 2,
        NET_IF_CONNECTION_DEMAND = 3,
        NET_IF_CONNECTION_MAXIMUM = 4
    }

    public enum TUNNEL_TYPE : uint {
        TUNNEL_TYPE_NONE = 0,
        TUNNEL_TYPE_OTHER = 1,
        TUNNEL_TYPE_DIRECT = 2,
        TUNNEL_TYPE_6TO4 = 11,
        TUNNEL_TYPE_ISATAP = 13,
        TUNNEL_TYPE_TEREDO = 14,
        TUNNEL_TYPE_IPHTTPS = 15
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct GUID {
        uint Data1;
        ushort Data2;
        ushort Data3;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
        byte[] Data4;
    }

    private const int MAX_ADAPTER_ADDRESS_LENGTH = 8;
    private const int MAX_ADAPTER_NAME_LENGTH = 256;
    private const int MAX_DHCPV6_DUID_LENGTH = 130;

    [StructLayout(LayoutKind.Sequential)]
    public struct SOCKADDR
    {
        /// u_short->unsigned short
        public ushort sa_family;

        /// char[14]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 14)]
        public byte[] sa_data;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct SOCKET_ADDRESS
    {
        public IntPtr lpSockAddr;
        public int iSockaddrLength;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct IP_ADAPTER_UNICAST_ADDRESS
    {
        public UInt64 Alignment;
        public IntPtr Next;
        public SOCKET_ADDRESS Address;
        public IP_PREFIX_ORIGIN PrefixOrigin;
        public IP_SUFFIX_ORIGIN SuffixOrigin;
        public IP_DAD_STATE DadState;
        public uint ValidLifetime;
        public uint PreferredLifetime;
        public uint LeaseLifetime;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct IP_ADAPTER_ADDRESSES
    {
        public UInt64 Alignment;
        public IntPtr Next;
        [System.Runtime.InteropServices.MarshalAs(UnmanagedType.LPStr)]
        public string AdapterName;
        public IntPtr FirstUnicastAddress;
        public IntPtr FirstAnycastAddress;
        public IntPtr FirstMulticastAddress;
        public IntPtr FirstDnsServerAddress;
        [MarshalAs(UnmanagedType.LPWStr)]
        public string DnsSuffix;
        [System.Runtime.InteropServices.MarshalAs(UnmanagedType.LPWStr)]
        public string Description;
        [System.Runtime.InteropServices.MarshalAs(UnmanagedType.LPWStr)]
        public string FriendlyName;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_ADAPTER_ADDRESS_LENGTH)]
        public byte[] PhysicalAddress;
        public uint PhysicalAddressLength;
        public uint Flags;
        public uint Mtu;
        public IF_TYPE IfType;
        public IF_OPER_STATUS OperStatus;
        uint Ipv6IfIndex;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
        public uint[] ZoneIndices;
        public IntPtr FirstPrefix;

        // Items added for Vista
        // May need to be removed on Windows versions below Vista to work properly (?)
        public UInt64 TrasmitLinkSpeed;
        public UInt64 ReceiveLinkSpeed;
        public IntPtr FirstWinsServerAddress;
        public IntPtr FirstGatewayAddress;
        public uint Ipv4Metric;
        public uint Ipv6Metric;
        public UInt64 Luid;
        public SOCKET_ADDRESS Dhcpv4Server;
        public uint CompartmentId;
        public GUID NetworkGuid;
        public NET_IF_CONNECTION_TYPE ConnectionType;
        public TUNNEL_TYPE TunnelType;
        public SOCKET_ADDRESS Dhcpv6Server;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_DHCPV6_DUID_LENGTH)]
        public byte[] Dhcpv6ClientDuid;
        public uint Dhcpv6ClientDuidLength;
        public uint Dhcpv6Iaid;
        public uint FirstDnsSuffix;
    }

    [DllImport("iphlpapi.dll")]
    private static extern ERROR GetAdaptersAddresses(uint Family, uint Flags, IntPtr Reserved, IntPtr pAdapterAddresses, ref uint pOutBufLen);

    public static string MarshalString(IntPtr text)
    {
        // !!!: This should only be used with IP_ADAPTER_ADDRESSES.AdapterName since it can't be marshalled automatically
        byte[] cName = new byte[MAX_ADAPTER_NAME_LENGTH];
        Marshal.Copy(text, cName, 0, MAX_ADAPTER_NAME_LENGTH);
        string name = Encoding.ASCII.GetString(cName, 0, MAX_ADAPTER_NAME_LENGTH);

        return name;
    }

    public static IList<IP_ADAPTER_ADDRESSES> GetIPAdapters(FAMILY family)
    {
        List<IP_ADAPTER_ADDRESSES> adapters = new List<IP_ADAPTER_ADDRESSES>();
        uint outBufLen = 0;
        ERROR err = GetAdaptersAddresses((uint)family, (uint)0, IntPtr.Zero, IntPtr.Zero, ref outBufLen);

        //Note that the first call with zero buffer is expected to fail.
        if (ERROR.ERROR_BUFFER_OVERFLOW == err)
        {
        IntPtr pAdapterAddresses = Marshal.AllocHGlobal((int)outBufLen);
        try
        {
            err = GetAdaptersAddresses((uint)family, (uint)0, IntPtr.Zero, pAdapterAddresses, ref outBufLen);
            if (ERROR.ERROR_SUCCESS == err)
            {
            IntPtr currPtr = pAdapterAddresses;
            while (IntPtr.Zero != currPtr)
            {
                IP_ADAPTER_ADDRESSES addr = (IP_ADAPTER_ADDRESSES)Marshal.PtrToStructure(currPtr, typeof(IP_ADAPTER_ADDRESSES));
                adapters.Add(addr);

                currPtr = addr.Next;
            }
            }
        }
        finally
        {
            Marshal.FreeHGlobal(pAdapterAddresses);
        }
        }

        return adapters;
    }

    public static IList<IPAddress> GetIPAddresses(FAMILY family)
    {
        List<IPAddress> addresses = new List<IPAddress>();

        foreach (IP_ADAPTER_ADDRESSES addr in GetIPAdapters(family)) {
        if (IntPtr.Zero != addr.FirstUnicastAddress)
        {
            IP_ADAPTER_UNICAST_ADDRESS unicastAddr = (IP_ADAPTER_UNICAST_ADDRESS)Marshal.PtrToStructure(addr.FirstUnicastAddress, typeof(IP_ADAPTER_UNICAST_ADDRESS));
            if (IntPtr.Zero != unicastAddr.Address.lpSockAddr)
            {
            SOCKADDR socketAddr = (SOCKADDR)Marshal.PtrToStructure(unicastAddr.Address.lpSockAddr, typeof(SOCKADDR));
            byte[] saData = socketAddr.sa_data.Skip(2).Take(4).ToArray();
            IPAddress ipAddr = new IPAddress(saData);
            addresses.Add(ipAddr);
            }
        }
        }

        return addresses;
    }

    /// <summary>Logic to return MAC Address for both enabled and disabled adapters.</summary>
    public static List<string> GetAllMACAddresses()
    {
        List<string> lstMAC = new List<string>();

        //Note: Possibly need logic to also go back for FAMILY.AF_INET6.
        foreach (IP_ADAPTER_ADDRESSES thisAddress in GetIPAdapters(FAMILY.AF_INET, FLAGS.GAA_FLAG_INCLUDE_ALL_INTERFACES))
        {
        if (thisAddress.PhysicalAddressLength == 0)
        {
            continue;
        }
        else if (thisAddress.IfType != IF_TYPE.IF_TYPE_ETHERNET_CSMACD && thisAddress.IfType != IF_TYPE.IF_TYPE_IEEE80211)
        {
            continue;
        }
        else if (thisAddress.IfType == IF_TYPE.IF_TYPE_IEEE80211 && thisAddress.OperStatus == IF_OPER_STATUS.IfOperStatusUp && thisAddress.Ipv4Metric == 0 && thisAddress.Ipv6Metric == 0)
        { //Filtering Metrics only works when the adapter is enabled.
            continue;
        }
        else if (thisAddress.Description.Contains("Virtual"))
        {
            continue;
        }

        if (thisAddress.PhysicalAddressLength == 6)
        {
            lstMAC.Add(BitConverter.ToString(thisAddress.PhysicalAddress, 0, 6).Replace('-', ':'));
        }
        else if (thisAddress.PhysicalAddressLength == 8)
        {
            lstMAC.Add(BitConverter.ToString(thisAddress.PhysicalAddress).Replace('-', ':'));
        }
        }

        return lstMAC;
    }
    }

Notes:

AdapterName is an ASCII string, I was unable to Marshal automatically, you can use this code to get it:

byte[] cName = new byte[MAX_ADAPTER_NAME_LENGTH];
Marshal.Copy(addr.AdapterName, cName, 0, MAX_ADAPTER_NAME_LENGTH);
string name = Encoding.ASCII.GetString(cName, 0, MAX_ADAPTER_NAME_LENGTH);

Tips & Tricks:

A good starting point is to try calling with:

IList<System.Net.IPAddress> hello = IPIntertop.GetIPAddresses(IPIntertop.FAMILY.AF_INET, IPIntertop.FLAGS.GAA_FLAG_DEFAULT);

Documentation