using System; using System.Linq; using System.Net; using System.Runtime.InteropServices; using Vanara.Extensions; using Vanara.InteropServices; #pragma warning disable IDE1006 // Naming Styles namespace Vanara.PInvoke { public static partial class Ws2_32 { /// Flags that indicate options used in the GetAddrInfoW function. [PInvokeData("ws2def.h", MSDNShortId = "a4896eac-68ae-4a08-8647-36be65fe4478")] [Flags] public enum ADDRINFO_FLAGS : uint { /// The socket address will be used in a call to the bindfunction. AI_PASSIVE = 0x01, /// The canonical name is returned in the first ai_canonname member. AI_CANONNAME = 0x02, /// The nodename parameter passed to the GetAddrInfoW function must be a numeric string. AI_NUMERICHOST = 0x04, /// Servicename must be a numeric port number. AI_NUMERICSERV = 0x08, /// /// If this bit is set, a request is made for IPv6 addresses and IPv4 addresses with AI_V4MAPPED. /// This option is supported on Windows Vista and later. /// AI_ALL = 0x0100, /// /// The GetAddrInfoW will resolve only if a global address is configured. The IPv6 and IPv4 loopback address is not considered a /// valid global address. This option is only supported on Windows Vista and later. /// AI_ADDRCONFIG = 0x0400, /// /// If the GetAddrInfoW request for an IPv6 addresses fails, a name service request is made for IPv4 addresses and these /// addresses are converted to IPv4-mapped IPv6 address format. /// This option is supported on Windows Vista and later. /// AI_V4MAPPED = 0x0800, /// /// The address information can be from a non-authoritative namespace provider. /// This option is only supported on Windows Vista and later for the NS_EMAIL namespace. /// AI_NON_AUTHORITATIVE = 0x04000, /// /// The address information is from a secure channel. /// This option is only supported on Windows Vista and later for the NS_EMAIL namespace. /// AI_SECURE = 0x08000, /// /// The address information is for a preferred name for a user. /// This option is only supported on Windows Vista and later for the NS_EMAIL namespace. /// AI_RETURN_PREFERRED_NAMES = 0x010000, /// /// If a flat name (single label) is specified, GetAddrInfoW will return the fully qualified domain name that the name /// eventually resolved to. The fully qualified domain name is returned in the ai_canonname member. /// /// This is different than AI_CANONNAME bit flag that returns the canonical name registered in DNS which may be different than /// the fully qualified domain name that the flat name resolved to. /// /// /// Only one of the AI_FQDN and AI_CANONNAME bits can be set. The GetAddrInfoW function will fail if both flags are present with EAI_BADFLAGS. /// /// This option is supported on Windows 7, Windows Server 2008 R2, and later. /// AI_FQDN = 0x00020000, /// /// A hint to the namespace provider that the hostname being queried is being used in a file share scenario. The namespace /// provider may ignore this hint. /// This option is supported on Windows 7, Windows Server 2008 R2, and later. /// AI_FILESERVER = 0x00040000, /// /// Disable the automatic International Domain Name encoding using Punycode in the name resolution functions called by the /// GetAddrInfoW function. /// This option is supported on Windows 8, Windows Server 2012, and later. /// AI_DISABLE_IDN_ENCODING = 0x00080000, /// Indicates this is extended ADDRINFOEX(2/..) struct AI_EXTENDED = 0x80000000, /// Request resolution handle AI_RESOLUTION_HANDLE = 0x40000000, } /// Protocols. The IPv6 defines are specified in RFC 2292. [PInvokeData("ws2def.h")] public enum IPPROTO { /// IPPROTO_IP = 0, /// IPPROTO_HOPOPTS = 0, /// /// The Internet Control Message Protocol (ICMP). This is a possible value when the af parameter is AF_UNSPEC, AF_INET, or /// AF_INET6 and the type parameter is SOCK_RAW or unspecified. /// This protocol value is supported on Windows XP and later. /// IPPROTO_ICMP = 1, /// /// The Internet Group Management Protocol (IGMP). This is a possible value when the af parameter is AF_UNSPEC, AF_INET, or /// AF_INET6 and the type parameter is SOCK_RAW or unspecified. /// This protocol value is supported on Windows XP and later. /// IPPROTO_IGMP = 2, /// /// The Bluetooth Radio Frequency Communications (Bluetooth RFCOMM) protocol. This is a possible value when the af parameter is /// AF_BTH and the type parameter is SOCK_STREAM. /// This protocol value is supported on Windows XP with SP2 or later. /// IPPROTO_GGP = 3, /// IPPROTO_IPV4 = 4, /// IPPROTO_ST = 5, /// /// The Transmission Control Protocol (TCP). This is a possible value when the af parameter is AF_INET or AF_INET6 and the type /// parameter is SOCK_STREAM. /// IPPROTO_TCP = 6, /// IPPROTO_CBT = 7, /// IPPROTO_EGP = 8, /// IPPROTO_IGP = 9, /// IPPROTO_PUP = 12, /// /// The User Datagram Protocol (UDP). This is a possible value when the af parameter is AF_INET or AF_INET6 and the type /// parameter is SOCK_DGRAM. /// IPPROTO_UDP = 17, /// IPPROTO_IDP = 22, /// IPPROTO_RDP = 27, /// IPPROTO_IPV6 = 41, /// IPPROTO_ROUTING = 43, /// IPPROTO_FRAGMENT = 44, /// IPPROTO_ESP = 50, /// IPPROTO_AH = 51, /// /// The Internet Control Message Protocol Version 6 (ICMPv6). This is a possible value when the af parameter is AF_UNSPEC, /// AF_INET, or AF_INET6 and the type parameter is SOCK_RAW or unspecified. /// This protocol value is supported on Windows XP and later. /// IPPROTO_ICMPV6 = 58, /// IPPROTO_NONE = 59, /// IPPROTO_DSTOPTS = 60, /// IPPROTO_ND = 77, /// IPPROTO_ICLFXBM = 78, /// IPPROTO_PIM = 103, /// /// The PGM protocol for reliable multicast. This is a possible value when the af parameter is AF_INET and the type parameter is /// SOCK_RDM. On the Windows SDK released for Windows Vista and later, this protocol is also called IPPROTO_PGM. /// This protocol value is only supported if the Reliable Multicast Protocol is installed. /// IPPROTO_PGM = 113, /// IPPROTO_L2TP = 115, /// IPPROTO_SCTP = 132, /// IPPROTO_RAW = 255, /// IPPROTO_MAX = 256, /// IPPROTO_RESERVED_RAW = 257, /// IPPROTO_RESERVED_IPSEC = 258, /// IPPROTO_RESERVED_IPSECOFFLOAD = 259, /// IPPROTO_RESERVED_WNV = 260, /// IPPROTO_RESERVED_MAX = 261 } /// Customize processing of the GetNameInfoW function. [PInvokeData("ws2def.h", MSDNShortId = "5630a49a-c182-440c-ad54-6ff3ba4274c6")] public enum NI { /// Results in local hosts having only their Relative Distinguished Name (RDN) returned in the pNodeBuffer parameter. NI_NOFQDN = 0x01 /* Only return nodename portion for local hosts */, /// /// Returns the numeric form of the host name instead of its name. The numeric form of the host name is also returned if the /// host name cannot be resolved by DNS. /// NI_NUMERICHOST = 0x02 /* Return numeric form of the host's address */, /// A host name that cannot be resolved by the DNS results in an error. NI_NAMEREQD = 0x04 /* Error if the host's name not in DNS */, /// /// Returns the port number of the service instead of its name. Also, if a host name is not found for an IP address (127.0.0.2, /// for example), the hostname is returned as the IP address. /// NI_NUMERICSERV = 0x08 /* Return numeric form of the service (port #) */, /// /// Indicates that the service is a datagram service. This flag is necessary for the few services that provide different port /// numbers for UDP and TCP service. /// NI_DGRAM = 0x10 /* Service is a datagram service */, } /// The scope of the IPv6 transport address. [PInvokeData("ws2def.h")] public enum SCOPE_LEVEL { /// The transport address has interface-local scope. ScopeLevelInterface = 1, /// The transport address has link-local scope. ScopeLevelLink = 2, /// The transport address has subnet-local scope. ScopeLevelSubnet = 3, /// The transport address has admin-local scope. ScopeLevelAdmin = 4, /// The transport address has site-local scope. ScopeLevelSite = 5, /// The transport address has organization-local scope. ScopeLevelOrganization = 8, /// The transport address has global scope. ScopeLevelGlobal = 14, /// The scope level count. ScopeLevelCount = 16 } /// Gets the size, in bytes, of a given a number of address. /// The address count. /// The size, in bytes, required to hold the structure. This does not include allocation for the addresses pointed to by each . [PInvokeData("ws2def.h")] public static SizeT SIZEOF_SOCKET_ADDRESS_LIST(SizeT AddressCount) => Marshal.OffsetOf(typeof(SOCKET_ADDRESS_LIST), "Address").ToInt32() + Marshal.SizeOf(typeof(SOCKET_ADDRESS)) * AddressCount; #if x64 public static readonly SizeT MAX_NATURAL_ALIGNMENT = sizeof(ulong); #else /// The maximum natural alignment public static readonly SizeT MAX_NATURAL_ALIGNMENT = sizeof(uint); #endif [StructLayout(LayoutKind.Sequential)] private struct AlignedStruct where T : struct { private readonly byte b; public readonly T type; } /// Returns the alignment in bytes of the specified type as a value of type . /// The type for which to get the alignment. /// The alignment in bytes of the specified type. public static SizeT TYPE_ALIGNMENT() where T : struct => Marshal.OffsetOf(typeof(AlignedStruct), "type").ToInt64(); /// Returns the alignment in bytes of padding as a value of type . /// The padding length. /// The alignment in bytes. public static SizeT WSA_CMSGDATA_ALIGN(SizeT length) => (length + MAX_NATURAL_ALIGNMENT-1) & (~(MAX_NATURAL_ALIGNMENT-1)); /// Returns the alignment in bytes of WSACMSGHDR with padding as a value of type . /// The padding length. /// The alignment in bytes. public static SizeT WSA_CMSGHDR_ALIGN(SizeT length) => (length + TYPE_ALIGNMENT()-1) & (~(TYPE_ALIGNMENT()-1)); /// /// Returns a pointer to the first byte of data (what is referred to as the cmsg_data member though it is not defined in the structure). /// /// The WSACMSGHDR instance. /// The pointer. public static unsafe byte* WSA_CMSG_DATA(WSACMSGHDR* cmsg) => (byte*)cmsg + WSA_CMSGDATA_ALIGN(Marshal.SizeOf(typeof(WSACMSGHDR))); /// /// Returns the first ancillary data object, or a null if there is no ancillary data in the control buffer of the WSAMSG structure. /// /// The message. /// The first ancillary data object, or a null. public static unsafe WSACMSGHDR* WSA_CMSG_FIRSTHDR(in WSAMSG msg) => (msg.Control.len >= Marshal.SizeOf(typeof(WSACMSGHDR))) ? (WSACMSGHDR*)msg.Control.buf : default; /// Returns the value to store in cmsg_len given the amount of data. /// The length. /// The data length. public static SizeT WSA_CMSG_LEN(SizeT length) => WSA_CMSGDATA_ALIGN(Marshal.SizeOf(typeof(WSACMSGHDR))) + length; /// Returns the next ancillary data object, or a null if there are no more data objects. /// The message. /// The message header. /// The next header. public static unsafe WSACMSGHDR* WSA_CMSG_NXTHDR(in WSAMSG msg, WSACMSGHDR* cmsg) { if (cmsg is null) return WSA_CMSG_FIRSTHDR(msg); unsafe { var len = (byte*)cmsg + WSA_CMSGHDR_ALIGN(cmsg->cmsg_len) + Marshal.SizeOf(typeof(WSACMSGHDR)); return len > (byte*)msg.Control.buf + msg.Control.len ? null : (WSACMSGHDR*)((byte*)cmsg + WSA_CMSGHDR_ALIGN(cmsg->cmsg_len)); } } /// Returns total size of an ancillary data object given the amount of data. Used to allocate the correct amount of space. /// The length. /// Total size public static SizeT WSA_CMSG_SPACE(SizeT length) => WSA_CMSGDATA_ALIGN(Marshal.SizeOf(typeof(WSACMSGHDR)) + WSA_CMSGHDR_ALIGN(length)); /// /// The addrinfoex2 structure is used by the GetAddrInfoEx function to hold host address information when both a canonical name and /// a fully qualified domain name have been requested. /// // https://docs.microsoft.com/en-us/windows/win32/api/ws2def/ns-ws2def-addrinfoex2w typedef struct addrinfoex2W { int ai_flags; int // ai_family; int ai_socktype; int ai_protocol; size_t ai_addrlen; PWSTR ai_canonname; struct sockaddr *ai_addr; void *ai_blob; // size_t ai_bloblen; LPGUID ai_provider; struct addrinfoex2W *ai_next; int ai_version; PWSTR ai_fqdn; } ADDRINFOEX2W, // *PADDRINFOEX2W, *LPADDRINFOEX2W; [PInvokeData("ws2def.h", MSDNShortId = "9CB33347-A838-473D-B5CD-1149D6632CF2")] [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] public struct ADDRINFOEX2W { /// /// Flags that indicate options used in the GetAddrInfoEx function. /// /// Supported values for the ai_flags member are defined in the Winsock2.h include file and can be a combination of the /// following options. /// /// /// /// Value /// Meaning /// /// /// AI_PASSIVE 0x01 /// The socket address will be used in a call to the bindfunction. /// /// /// AI_CANONNAME 0x02 /// The canonical name is returned in the first ai_canonname member. /// /// /// AI_NUMERICHOST 0x04 /// The nodename parameter passed to the GetAddrInfoEx function must be a numeric string. /// /// /// AI_ALL 0x0100 /// /// If this bit is set, a request is made for IPv6 addresses and IPv4 addresses with AI_V4MAPPED. This option is supported on /// Windows Vista and later. /// /// /// /// AI_ADDRCONFIG 0x0400 /// /// The GetAddrInfoEx will resolve only if a global address is configured. The IPv6 and IPv4 loopback address is not considered /// a valid global address. This option is supported on Windows Vista and later. /// /// /// /// AI_V4MAPPED 0x0800 /// /// If the GetAddrInfoEx request for an IPv6 addresses fails, a name service request is made for IPv4 addresses and these /// addresses are converted to IPv4-mapped IPv6 address format. This option is supported on Windows Vista and later. /// /// /// /// AI_NON_AUTHORITATIVE 0x04000 /// /// The address information is from non-authoritative results. When this option is set in the pHints parameter of GetAddrInfoEx, /// the NS_EMAIL namespace provider returns both authoritative and non-authoritative results. If this option is not set, then /// only authoritative results are returned. This option is only supported on Windows Vista and later for the NS_EMAIL namespace. /// /// /// /// AI_SECURE 0x08000 /// /// The address information is from a secure channel. If the AI_SECURE bit is set, the NS_EMAIL namespace provider will return /// results that were obtained with enhanced security to minimize possible spoofing. When this option is set in the pHints /// parameter of GetAddrInfoEx, the NS_EMAIL namespace provider returns only results that were obtained with enhanced security /// to minimize possible spoofing. This option is only supported on Windows Vista and later for the NS_EMAIL namespace. /// /// /// /// AI_RETURN_PREFERRED_NAMES 0x010000 /// /// The address information is for a preferred names for publication with a specific namespace. When this option is set in the /// pHints parameter of GetAddrInfoEx, no name should be provided in the pName parameter and the NS_EMAIL namespace provider /// will return preferred names for publication. This option is only supported on Windows Vista and later for the NS_EMAIL namespace. /// /// /// /// AI_FQDN 0x00020000 /// /// The fully qualified domain name is returned in the first ai_fqdn member. When this option is set in the pHints parameter of /// GetAddrInfoEx and a flat name (single label) is specified in the pName parameter, the fully qualified domain name that the /// name eventually resolved to will be returned. This option is supported on Windows 7, Windows Server 2008 R2, and later. /// /// /// /// AI_FILESERVER 0x00040000 /// /// A hint to the namespace provider that the hostname being queried is being used in a file share scenario. The namespace /// provider may ignore this hint. This option is supported on Windows 7, Windows Server 2008 R2, and later. /// /// /// /// AI_DISABLE_IDN_ENCODING 0x00080000 /// /// Disable the automatic International Domain Name encoding using Punycode in the name resolution functions called by the /// GetAddrInfoEx function. This option is supported on Windows 8, Windows Server 2012, and later. /// /// /// /// public ADDRINFO_FLAGS ai_flags; private uint _ai_family; /// /// Type: int /// The address family. Possible values for the address family are defined in the Winsock2.h include file. /// /// On the Windows SDK released for Windows Vista and later,, the organization of header files has changed and the possible /// values for the address family are defined in the Ws2def.h header file. Note that the Ws2def.h header file is automatically /// included in Winsock2.h, and should never be used directly. /// /// /// The values currently supported are AF_INET or AF_INET6, which are the Internet address family formats for IPv4 /// and IPv6. Other options for address family ( AF_NETBIOS for use with NetBIOS, for example) are supported if a Windows /// Sockets service provider for the address family is installed. Note that the values for the AF_ address family and PF_ /// protocol family constants are identical (for example, AF_UNSPEC and PF_UNSPEC), so either constant can be used. /// /// The table below lists common values for the address family although many other values are possible. /// /// /// Value /// Meaning /// /// /// AF_UNSPEC 0 /// The address family is unspecified. /// /// /// AF_INET 2 /// The Internet Protocol version 4 (IPv4) address family. /// /// /// AF_NETBIOS 17 /// The NetBIOS address family. This address family is only supported if a Windows Sockets provider for NetBIOS is installed. /// /// /// AF_INET6 23 /// The Internet Protocol version 6 (IPv6) address family. /// /// /// AF_IRDA 26 /// /// The Infrared Data Association (IrDA) address family. This address family is only supported if the computer has an infrared /// port and driver installed. /// /// /// /// AF_BTH 32 /// /// The Bluetooth address family. This address family is only supported if a Bluetooth adapter is installed on Windows Server /// 2003 or later. /// /// /// /// public ADDRESS_FAMILY ai_family { get => (ADDRESS_FAMILY)_ai_family; set => _ai_family = (ushort)value; } /// /// The socket type. Possible values for the socket type are defined in the Winsock2.h include file. /// The following table lists the possible values for the socket type supported for Windows Sockets 2: /// /// /// Value /// Meaning /// /// /// SOCK_STREAM 1 /// /// Provides sequenced, reliable, two-way, connection-based byte streams with an OOB data transmission mechanism. Uses the /// Transmission Control Protocol (TCP) for the Internet address family (AF_INET or AF_INET6). If the ai_family member is /// AF_IRDA, then SOCK_STREAM is the only supported socket type. /// /// /// /// SOCK_DGRAM 2 /// /// Supports datagrams, which are connectionless, unreliable buffers of a fixed (typically small) maximum length. Uses the User /// Datagram Protocol (UDP) for the Internet address family (AF_INET or AF_INET6). /// /// /// /// SOCK_RAW 3 /// /// Provides a raw socket that allows an application to manipulate the next upper-layer protocol header. To manipulate the IPv4 /// header, the IP_HDRINCL socket option must be set on the socket. To manipulate the IPv6 header, the IPV6_HDRINCL socket /// option must be set on the socket. /// /// /// /// SOCK_RDM 4 /// /// Provides a reliable message datagram. An example of this type is the Pragmatic General Multicast (PGM) multicast protocol /// implementation in Windows, often referred to as reliable multicast programming. /// /// /// /// SOCK_SEQPACKET 5 /// Provides a pseudo-stream packet based on datagrams. /// /// /// /// In Windows Sockets 2, new socket types were introduced. An application can dynamically discover the attributes of each /// available transport protocol through the WSAEnumProtocols function. So an application can determine the possible socket type /// and protocol options for an address family and use this information when specifying this parameter. Socket type definitions /// in the Winsock2.h and Ws2def.h header files will be periodically updated as new socket types, address families, and /// protocols are defined. /// /// In Windows Sockets 1.1, the only possible socket types are SOCK_DATAGRAM and SOCK_STREAM. /// public SOCK ai_socktype; /// /// /// The protocol type. The possible options are specific to the address family and socket type specified. Possible values for /// the ai_protocol are defined in Winsock2.h and the Wsrm.h header files. /// /// /// On the Windows SDK released for Windows Vista and later,, the organization of header files has changed and this member can /// be one of the values from the IPPROTO enumeration type defined in the Ws2def.h header file. Note that the Ws2def.h /// header file is automatically included in Winsock2.h, and should never be used directly. /// /// /// If a value of 0 is specified for ai_protocol, the caller does not wish to specify a protocol and the service provider /// will choose the ai_protocol to use. For protocols other than IPv4 and IPv6, set ai_protocol to zero. /// /// The following table lists common values for the ai_protocol member although many other values are possible. /// /// /// Value /// Meaning /// /// /// IPPROTO_TCP 6 /// /// The Transmission Control Protocol (TCP). This is a possible value when the ai_family member is AF_INET or AF_INET6 and the /// ai_socktype member is SOCK_STREAM. /// /// /// /// IPPROTO_UDP 17 /// /// The User Datagram Protocol (UDP). This is a possible value when the ai_family member is AF_INET or AF_INET6 and the type /// parameter is SOCK_DGRAM. /// /// /// /// IPPROTO_RM 113 /// /// The PGM protocol for reliable multicast. This is a possible value when the ai_family member is AF_INET and the ai_socktype /// member is SOCK_RDM. On the Windows SDK released for Windows Vista and later, this value is also called IPPROTO_PGM. /// /// /// /// If the ai_family member is AF_IRDA, then the ai_protocol must be 0. /// public IPPROTO ai_protocol; /// The length, in bytes, of the buffer pointed to by the ai_addr member. public SizeT ai_addrlen; /// The canonical name for the host. public StrPtrUni ai_canonname; /// /// A pointer to a sockaddr structure. The ai_addr member in each returned addrinfoex2 structure points to a /// filled-in socket address structure. The length, in bytes, of each returned addrinfoex2 structure is specified in the /// ai_addrlen member. /// public IntPtr ai_addr; /// /// A pointer to data that is used to return provider-specific namespace information that is associated with the name beyond a /// list of addresses. The length, in bytes, of the buffer pointed to by ai_blob must be specified in the /// ai_bloblen member. /// public IntPtr ai_blob; /// The length, in bytes, of the ai_blob member. public SizeT ai_bloblen; /// A pointer to the GUID of a specific namespace provider. public GuidPtr ai_provider; /// /// A pointer to the next structure in a linked list. This parameter is set to NULL in the last addrinfoex2 /// structure of a linked list. /// public IntPtr ai_next; /// The version number of this structure. The value currently used for this version of the structure is 2. public int ai_version; /// The fully qualified domain name for the host. public StrPtrUni ai_fqdn; /// /// Type: struct sockaddr* /// /// A pointer to a sockaddr structure. The ai_addr member in each returned ADDRINFOW structure points to a filled-in /// socket address structure. The length, in bytes, of each returned ADDRINFOW structure is specified in the /// ai_addrlen member. /// /// public SOCKADDR addr => new(ai_addr, false, ai_addrlen); /// public override string ToString() => $"{ai_fqdn}::{ai_canonname}:{ai_flags},{ai_family},{ai_socktype},{ai_protocol},{addr}"; } /// The addrinfoex structure is used by the GetAddrInfoEx function to hold host address information. /// /// /// The addrinfoex structure is used by the GetAddrInfoEx function to hold host address information. The addrinfoex /// structure is an enhanced version of the addrinfo and addrinfoW structures. The extra structure members are for blob data and the /// GUID for the namespace provider. The blob data is used to return additional provider-specific namespace information associated /// with a name. The format of data in the ai_blob member is specific to a particular namespace provider. Currently, blob /// data is used by the NS_EMAIL namespace provider to supply additional information. /// /// /// The addrinfoex structure is an enhanced version of the addrinfo and addrinfoW structure used with GetAddrInfoEx function. /// The GetAddrInfoEx function allows specifying the namespace provider to resolve the query. For use with the IPv6 and IPv4 /// protocol, name resolution can be by the Domain Name System (DNS), a local hosts file, an email provider (the NS_EMAIL /// namespace), or by other naming mechanisms. /// /// /// When UNICODE or _UNICODE is defined, addrinfoex is defined to addrinfoexW, the Unicode version of this structure. /// The string parameters are defined to the PWSTR data type and the addrinfoexW structure is used. /// /// /// When UNICODE or _UNICODE is not defined, addrinfoex is defined to addrinfoexA, the ANSI version of this structure. /// The string parameters are of the PCSTR data type and the addrinfoexA structure is used. /// /// /// Upon a successful call to GetAddrInfoEx, a linked list of addrinfoex structures is returned in the ppResult parameter /// passed to the GetAddrInfoEx function. The list can be processed by following the pointer provided in the ai_next /// member of each returned addrinfoex structure until a NULL pointer is encountered. In each returned /// addrinfoex structure, the ai_family, ai_socktype, and ai_protocol members correspond to respective /// arguments in a socket or WSASocket function call. Also, the ai_addr member in each returned addrinfoex structure /// points to a filled-in socket address structure, the length of which is specified in its ai_addrlen member. /// /// Examples /// The following example demonstrates the use of the addrinfoex structure. /// /// Note Ensure that the development environment targets the newest version of Ws2tcpip.h which includes structure and /// function definitions for ADDRINFOEX and GetAddrInfoEx, respectively. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/ws2def/ns-ws2def-addrinfoexa typedef struct addrinfoexA { int ai_flags; int // ai_family; int ai_socktype; int ai_protocol; size_t ai_addrlen; char *ai_canonname; struct sockaddr *ai_addr; void *ai_blob; // size_t ai_bloblen; LPGUID ai_provider; struct addrinfoexA *ai_next; } ADDRINFOEXA, *PADDRINFOEXA, *LPADDRINFOEXA; [PInvokeData("ws2def.h", MSDNShortId = "1077e03d-a1a4-45ab-a5d2-29a67e03f5df")] [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] public unsafe struct ADDRINFOEXW { /// /// Type: int /// Flags that indicate options used in the GetAddrInfoEx function. /// /// Supported values for the ai_flags member are defined in the Winsock2.h include file and can be a combination of the /// following options. /// /// /// /// Value /// Meaning /// /// /// AI_PASSIVE 0x01 /// The socket address will be used in a call to the bindfunction. /// /// /// AI_CANONNAME 0x02 /// /// The canonical name is returned in the first ai_canonname member. When both the AI_CANONNAME and AI_FQDN bits are set, an /// addrinfoex2 structure is returned not the addrinfoex structure. /// /// /// /// AI_NUMERICHOST 0x04 /// The nodename parameter passed to the GetAddrInfoEx function must be a numeric string. /// /// /// AI_ALL 0x0100 /// /// If this bit is set, a request is made for IPv6 addresses and IPv4 addresses with AI_V4MAPPED. This option is supported on /// Windows Vista and later. /// /// /// /// AI_ADDRCONFIG 0x0400 /// /// The GetAddrInfoEx will resolve only if a global address is configured. The IPv6 and IPv4 loopback address is not considered /// a valid global address. This option is only supported on Windows Vista and later. /// /// /// /// AI_V4MAPPED 0x0800 /// /// If the GetAddrInfoEx request for an IPv6 addresses fails, a name service request is made for IPv4 addresses and these /// addresses are converted to IPv4-mapped IPv6 address format. This option is supported on Windows Vista and later. /// /// /// /// AI_NON_AUTHORITATIVE 0x04000 /// /// The address information is from non-authoritative results. When this option is set in the pHints parameter of GetAddrInfoEx, /// the NS_EMAIL namespace provider returns both authoritative and non-authoritative results. If this option is not set, then /// only authoritative results are returned. In the ppResults parameter returned by GetAddrInfoEx, this flag is set in the /// ai_flags member of the addrinfoex structure for non-authoritative results. This option is only supported on Windows Vista /// and later for the NS_EMAIL namespace. /// /// /// /// AI_SECURE 0x08000 /// /// The address information is from a secure channel. If the AI_SECURE bit is set, the NS_EMAIL namespace provider will return /// results that were obtained with enhanced security to minimize possible spoofing. When this option is set in the pHints /// parameter of GetAddrInfoEx, the NS_EMAIL namespace provider returns only results that were obtained with enhanced security /// to minimize possible spoofing. In the ppResults parameter returned by GetAddrInfoEx, this flag is set in the ai_flags member /// of the addrinfoex structure for results returned with enhanced security to minimize possible spoofing. This option is only /// supported on Windows Vista and later for the NS_EMAIL namespace. /// /// /// /// AI_RETURN_PREFERRED_NAMES 0x010000 /// /// The address information is for a preferred names for publication with a specific namespace. When this option is set in the /// pHints parameter of GetAddrInfoEx, no name should be provided in the pName parameter and the NS_EMAIL namespace provider /// will return preferred names for publication. In the ppResults parameter returned by GetAddrInfoEx, this flag is set in the /// ai_flags member of the addrinfoex structure for results returned for preferred names for publication. This option is only /// supported on Windows Vista and later for the NS_EMAIL namespace. /// /// /// /// AI_FQDN 0x00020000 /// /// The fully qualified domain name is returned in the first ai_canonicalname member. When this option is set in the pHints /// parameter of GetAddrInfoEx and a flat name (single label) is specified in the pName parameter, the fully qualified domain /// name that the name eventually resolved to will be returned. When both the AI_CANONNAME and AI_FQDN bits are set, an /// addrinfoex2 structure is returned not the addrinfoex structure. This option is supported on Windows 7, Windows Server 2008 /// R2, and later. /// /// /// /// AI_FILESERVER 0x00040000 /// /// A hint to the namespace provider that the hostname being queried is being used in a file share scenario. The namespace /// provider may ignore this hint. This option is supported on Windows 7, Windows Server 2008 R2, and later. /// /// /// /// AI_DISABLE_IDN_ENCODING 0x00080000 /// /// Disable the automatic International Domain Name encoding using Punycode in the name resolution functions called by the /// GetAddrInfoEx function. This option is supported on Windows 8, Windows Server 2012, and later. /// /// /// /// public ADDRINFO_FLAGS ai_flags; private uint _ai_family; /// /// Type: int /// The address family. Possible values for the address family are defined in the Winsock2.h include file. /// /// On the Windows SDK released for Windows Vista and later,, the organization of header files has changed and the possible /// values for the address family are defined in the Ws2def.h header file. Note that the Ws2def.h header file is automatically /// included in Winsock2.h, and should never be used directly. /// /// /// The values currently supported are AF_INET or AF_INET6, which are the Internet address family formats for IPv4 /// and IPv6. Other options for address family ( AF_NETBIOS for use with NetBIOS, for example) are supported if a Windows /// Sockets service provider for the address family is installed. Note that the values for the AF_ address family and PF_ /// protocol family constants are identical (for example, AF_UNSPEC and PF_UNSPEC), so either constant can be used. /// /// The table below lists common values for the address family although many other values are possible. /// /// /// Value /// Meaning /// /// /// AF_UNSPEC 0 /// The address family is unspecified. /// /// /// AF_INET 2 /// The Internet Protocol version 4 (IPv4) address family. /// /// /// AF_NETBIOS 17 /// The NetBIOS address family. This address family is only supported if a Windows Sockets provider for NetBIOS is installed. /// /// /// AF_INET6 23 /// The Internet Protocol version 6 (IPv6) address family. /// /// /// AF_IRDA 26 /// /// The Infrared Data Association (IrDA) address family. This address family is only supported if the computer has an infrared /// port and driver installed. /// /// /// /// AF_BTH 32 /// /// The Bluetooth address family. This address family is only supported if a Bluetooth adapter is installed on Windows Server /// 2003 or later. /// /// /// /// public ADDRESS_FAMILY ai_family { get => (ADDRESS_FAMILY)_ai_family; set => _ai_family = (ushort)value; } /// /// Type: int /// The socket type. Possible values for the socket type are defined in the Winsock2.h include file. /// The following table lists the possible values for the socket type supported for Windows Sockets 2: /// /// /// Value /// Meaning /// /// /// SOCK_STREAM 1 /// /// Provides sequenced, reliable, two-way, connection-based byte streams with an OOB data transmission mechanism. Uses the /// Transmission Control Protocol (TCP) for the Internet address family (AF_INET or AF_INET6). If the ai_family member is /// AF_IRDA, then SOCK_STREAM is the only supported socket type. /// /// /// /// SOCK_DGRAM 2 /// /// Supports datagrams, which are connectionless, unreliable buffers of a fixed (typically small) maximum length. Uses the User /// Datagram Protocol (UDP) for the Internet address family (AF_INET or AF_INET6). /// /// /// /// SOCK_RAW 3 /// /// Provides a raw socket that allows an application to manipulate the next upper-layer protocol header. To manipulate the IPv4 /// header, the IP_HDRINCL socket option must be set on the socket. To manipulate the IPv6 header, the IPV6_HDRINCL socket /// option must be set on the socket. /// /// /// /// SOCK_RDM 4 /// /// Provides a reliable message datagram. An example of this type is the Pragmatic General Multicast (PGM) multicast protocol /// implementation in Windows, often referred to as reliable multicast programming. /// /// /// /// SOCK_SEQPACKET 5 /// Provides a pseudo-stream packet based on datagrams. /// /// /// /// In Windows Sockets 2, new socket types were introduced. An application can dynamically discover the attributes of each /// available transport protocol through the WSAEnumProtocols function. So an application can determine the possible socket type /// and protocol options for an address family and use this information when specifying this parameter. Socket type definitions /// in the Winsock2.h and Ws2def.h header files will be periodically updated as new socket types, address families, and /// protocols are defined. /// /// In Windows Sockets 1.1, the only possible socket types are SOCK_DATAGRAM and SOCK_STREAM. /// public SOCK ai_socktype; /// /// Type: int /// /// The protocol type. The possible options are specific to the address family and socket type specified. Possible values for /// the ai_protocol are defined in Winsock2.h and the Wsrm.h header files. /// /// /// On the Windows SDK released for Windows Vista and later,, the organization of header files has changed and this member can /// be one of the values from the IPPROTO enumeration type defined in the Ws2def.h header file. Note that the Ws2def.h /// header file is automatically included in Winsock2.h, and should never be used directly. /// /// /// If a value of 0 is specified for ai_protocol, the caller does not wish to specify a protocol and the service provider /// will choose the ai_protocol to use. For protocols other than IPv4 and IPv6, set ai_protocol to zero. /// /// The following table lists common values for the ai_protocol member although many other values are possible. /// /// /// Value /// Meaning /// /// /// IPPROTO_TCP 6 /// /// The Transmission Control Protocol (TCP). This is a possible value when the ai_family member is AF_INET or AF_INET6 and the /// ai_socktype member is SOCK_STREAM. /// /// /// /// IPPROTO_UDP 17 /// /// The User Datagram Protocol (UDP). This is a possible value when the ai_family member is AF_INET or AF_INET6 and the type /// parameter is SOCK_DGRAM. /// /// /// /// IPPROTO_RM 113 /// /// The PGM protocol for reliable multicast. This is a possible value when the ai_family member is AF_INET and the ai_socktype /// member is SOCK_RDM. On the Windows SDK released for Windows Vista and later, this value is also called IPPROTO_PGM. /// /// /// /// If the ai_family member is AF_IRDA, then the ai_protocol must be 0. /// public IPPROTO ai_protocol; /// /// Type: size_t /// The length, in bytes, of the buffer pointed to by the ai_addr member. /// public SizeT ai_addrlen; /// /// Type: PCTSTR /// The canonical name for the host. /// public StrPtrUni ai_canonname; /// /// Type: struct sockaddr* /// /// A pointer to a sockaddr structure. The ai_addr member in each returned addrinfoex structure points to a /// filled-in socket address structure. The length, in bytes, of each returned addrinfoex structure is specified in the /// ai_addrlen member. /// /// public IntPtr ai_addr; /// /// Type: void* /// /// A pointer to data that is used to return provider-specific namespace information that is associated with the name beyond a /// list of addresses. The length, in bytes, of the buffer pointed to by ai_blob must be specified in the /// ai_bloblen member. /// /// public IntPtr ai_blob; /// /// Type: size_t /// The length, in bytes, of the ai_blob member. /// public SizeT ai_bloblen; /// /// Type: LPGUID /// A pointer to the GUID of a specific namespace provider. /// public Guid* ai_provider; /// /// Type: struct addrinfoex* /// /// A pointer to the next structure in a linked list. This parameter is set to NULL in the last addrinfoex /// structure of a linked list. /// /// public IntPtr ai_next; /// /// Type: struct sockaddr* /// /// A pointer to a sockaddr structure. The ai_addr member in each returned ADDRINFOW structure points to a filled-in /// socket address structure. The length, in bytes, of each returned ADDRINFOW structure is specified in the /// ai_addrlen member. /// /// public SOCKADDR addr => new(ai_addr, false, ai_addrlen); /// public override string ToString() => $"{ai_canonname}:{ai_flags},{ai_family},{ai_socktype},{ai_protocol},{addr}"; } /// /// The addrinfoex2 structure is used by the GetAddrInfoEx function to hold host address information when both a canonical /// name and a fully qualified domain name have been requested. /// /// /// The addrinfoex2 structure is supported on Windows 8 and Windows Server 2012 /// /// The addrinfoex2 structure is used by the GetAddrInfoEx function to hold host address information when both the /// AI_FQDN and AI_CANONNAME bits are set in the ai_flags member of the optional addrinfoex structure provided /// in the hints parameter to the GetAddrInfoEx function. The addrinfoex2 structure is an enhanced version of the /// addrinfoex structure that can return both the canonical name and the fully qualified domain name for the host. The extra /// structure members are for a version number of the structure and the fully qualified domain name for the host. /// /// /// The addrinfoex2 structure used with GetAddrInfoEx function is an enhanced version of the addrinfo and addrinfoW /// structures used with the getaddrinfo and GetAddrInfoW functions. The GetAddrInfoEx function allows specifying the /// namespace provider to resolve the query. For use with the IPv6 and IPv4 protocol, name resolution can be by the Domain Name /// System (DNS), a local hosts file, an email provider (the NS_EMAIL namespace), or by other naming mechanisms. /// /// /// The blob data in tha ai_blob member is used to return additional provider-specific namespace information associated with /// a name. The format of data in the ai_blob member is specific to a particular namespace provider. Currently, blob data is /// used by the NS_EMAIL namespace provider to supply additional information. /// /// /// When UNICODE or _UNICODE is defined, addrinfoex2 is defined to addrinfoex2W, the Unicode version of this /// structure. The string parameters are defined to the PWSTR data type and the addrinfoex2W structure is used. /// /// /// When UNICODE or _UNICODE is not defined, addrinfoex2 is defined to addrinfoex2A, the ANSI version of this /// structure. The string parameters are of the char * data type and the addrinfoex2A structure is used. /// /// /// Upon a successful call to GetAddrInfoEx, a linked list of addrinfoex2 structures is returned in the ppResult parameter /// passed to the GetAddrInfoEx function. The list can be processed by following the pointer provided in the ai_next /// member of each returned addrinfoex2 structure until a NULL pointer is encountered. In each returned /// addrinfoex2 structure, the ai_family, ai_socktype, and ai_protocol members correspond to respective /// arguments in a socket or WSASocket function call. Also, the ai_addr member in each returned addrinfoex2 structure /// points to a filled-in socket address structure, the length of which is specified in its ai_addrlen member. /// /// /// The addrinfo structure is used by the getaddrinfo function to hold host address information. /// /// The addrinfo structure is used by the ANSI getaddrinfo function to hold host address information. /// The addrinfoW structure is the version of this structure used by the Unicode GetAddrInfoW function. /// /// Macros in the Ws2tcpip.h header file define a ADDRINFOT structure and a mixed-case function name of GetAddrInfo. /// The GetAddrInfo function should be called with the nodename and servname parameters of a pointer of type TCHAR and /// the hints and res parameters of a pointer of type ADDRINFOT. When UNICODE or _UNICODE is not defined, ADDRINFOT is /// defined to the addrinfo structure and GetAddrInfo is defined to getaddrinfo, the ANSI version of this function. /// When UNICODE or _UNICODE is defined, ADDRINFOT is defined to the addrinfoW structure and GetAddrInfo is defined to /// GetAddrInfoW, the Unicode version of this function. /// /// /// Upon a successful call to getaddrinfo, a linked list of addrinfo structures is returned in the res parameter passed to /// the getaddrinfo function. The list can be processed by following the pointer provided in the ai_next member of /// each returned addrinfo structure until a NULL pointer is encountered. In each returned addrinfo structure, /// the ai_family, ai_socktype, and ai_protocol members correspond to respective arguments in a socket or /// WSASocket function call. Also, the ai_addr member in each returned addrinfo structure points to a filled-in socket /// address structure, the length of which is specified in its ai_addrlen member. /// /// Support for getaddrinfo and the addrinfo struct on older versions of Windows /// /// The getaddrinfo function that uses the addrinfo structure was added to the Ws2_32.dll on Windows XP and later. The /// addrinfo structure is defined in the Ws2tcpip.h header file included with the Platform SDK released for Windows XP and /// later and the Windows SDK released for Windows Vista and later. /// /// /// To execute an application that uses the getaddrinfo function and the addrinfo structure on earlier versions of Windows /// (Windows 2000), then you need to include the Ws2tcpip.h and Wspiapi.h files. When the Wspiapi.h include file is added, the /// getaddrinfo function is defined to the WspiapiGetAddrInfo inline function in the Wspiapi.h file. At runtime, the /// WspiapiGetAddrInfo function is implemented in such a way that if the Ws2_32.dll or the Wship6.dll (the file containing /// getaddrinfo in the IPv6 Technology Preview for Windows 2000) does not include getaddrinfo, then a version of /// getaddrinfo is implemented inline based on code in the Wspiapi.h header file. This inline code will be used on older /// Windows platforms that do not natively support the getaddrinfo function. /// /// /// The IPv6 protocol is supported on Windows 2000 when the IPv6 Technology Preview for Windows 2000 is installed. Otherwise /// getaddrinfo support on versions of Windows earlier than Windows XP is limited to handling IPv4 name resolution. /// /// /// The GetAddrInfoW function that uses the addrinfoW structure is the Unicode version of the getaddrinfo function and associated /// addrinfo structure. The GetAddrInfoW function was added to the Ws2_32.dll in Windows XP with Service Pack 2 (SP2). /// The GetAddrInfoW function and the addrinfoW structure cannot be used on versions of Windows earlier than Windows /// XP with SP2. /// /// Examples /// The following code example shows the use of the addrinfo structure. /// // https://docs.microsoft.com/en-us/windows/win32/api/ws2def/ns-ws2def-addrinfoa typedef struct addrinfo { int ai_flags; int // ai_family; int ai_socktype; int ai_protocol; size_t ai_addrlen; char *ai_canonname; struct sockaddr *ai_addr; struct addrinfo // *ai_next; } ADDRINFOA, *PADDRINFOA; [PInvokeData("ws2def.h", MSDNShortId = "4df914ab-59b0-4110-bc81-59e5f6722b8d")] [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] public struct ADDRINFOW { /// /// Type: int /// Flags that indicate options used in the getaddrinfo function. /// /// Supported values for the ai_flags member are defined in the Ws2def.h header file on the Windows SDK for Windows 7 and /// later. These values are defined in the Ws2tcpip.h header file on the Windows SDK for Windows Server 2008 and Windows Vista. /// These values are defined in the Ws2tcpip.h header file on the Platform SDK for Windows Server 2003, and Windows XP. /// Supported values for the ai_flags member can be a combination of the following options. /// /// /// /// Value /// Meaning /// /// /// AI_PASSIVE 0x01 /// The socket address will be used in a call to the bindfunction. /// /// /// AI_CANONNAME 0x02 /// The canonical name is returned in the first ai_canonname member. /// /// /// AI_NUMERICHOST 0x04 /// The nodename parameter passed to the getaddrinfo function must be a numeric string. /// /// /// AI_ALL 0x0100 /// /// If this bit is set, a request is made for IPv6 addresses and IPv4 addresses with AI_V4MAPPED. This option is supported on /// Windows Vista and later. /// /// /// /// AI_ADDRCONFIG 0x0400 /// /// The getaddrinfo will resolve only if a global address is configured. The IPv6 and IPv4 loopback address is not considered a /// valid global address. This option is supported on Windows Vista and later. /// /// /// /// AI_V4MAPPED 0x0800 /// /// If the getaddrinfo request for IPv6 addresses fails, a name service request is made for IPv4 addresses and these addresses /// are converted to IPv4-mapped IPv6 address format. This option is supported on Windows Vista and later. /// /// /// /// AI_NON_AUTHORITATIVE 0x04000 /// /// The address information can be from a non-authoritative namespace provider. This option is only supported on Windows Vista /// and later for the NS_EMAIL namespace. /// /// /// /// AI_SECURE 0x08000 /// /// The address information is from a secure channel. This option is only supported on Windows Vista and later for the NS_EMAIL namespace. /// /// /// /// AI_RETURN_PREFERRED_NAMES 0x010000 /// /// The address information is for a preferred name for a user. This option is only supported on Windows Vista and later for the /// NS_EMAIL namespace. /// /// /// /// AI_FQDN 0x00020000 /// /// If a flat name (single label) is specified, getaddrinfo will return the fully qualified domain name that the name eventually /// resolved to. The fully qualified domain name is returned in the ai_canonname member. This is different than AI_CANONNAME bit /// flag that returns the canonical name registered in DNS which may be different than the fully qualified domain name that the /// flat name resolved to. Only one of the AI_FQDN and AI_CANONNAME bits can be set. The getaddrinfo function will fail if both /// flags are present with EAI_BADFLAGS. This option is supported on Windows 7, Windows Server 2008 R2, and later. /// /// /// /// AI_FILESERVER 0x00040000 /// /// A hint to the namespace provider that the hostname being queried is being used in a file share scenario. The namespace /// provider may ignore this hint. This option is supported on Windows 7, Windows Server 2008 R2, and later. /// /// /// /// public ADDRINFO_FLAGS ai_flags; private uint _ai_family; /// /// Type: int /// The address family. Possible values for the address family are defined in the Winsock2.h include file. /// /// On the Windows SDK released for Windows Vista and later,, the organization of header files has changed and the possible /// values for the address family are defined in the Ws2def.h header file. Note that the Ws2def.h header file is automatically /// included in Winsock2.h, and should never be used directly. /// /// /// The values currently supported are AF_INET or AF_INET6, which are the Internet address family formats for IPv4 /// and IPv6. Other options for address family ( AF_NETBIOS for use with NetBIOS, for example) are supported if a Windows /// Sockets service provider for the address family is installed. Note that the values for the AF_ address family and PF_ /// protocol family constants are identical (for example, AF_UNSPEC and PF_UNSPEC), so either constant can be used. /// /// The table below lists common values for the address family although many other values are possible. /// /// /// Value /// Meaning /// /// /// AF_UNSPEC 0 /// The address family is unspecified. /// /// /// AF_INET 2 /// The Internet Protocol version 4 (IPv4) address family. /// /// /// AF_NETBIOS 17 /// The NetBIOS address family. This address family is only supported if a Windows Sockets provider for NetBIOS is installed. /// /// /// AF_INET6 23 /// The Internet Protocol version 6 (IPv6) address family. /// /// /// AF_IRDA 26 /// /// The Infrared Data Association (IrDA) address family. This address family is only supported if the computer has an infrared /// port and driver installed. /// /// /// /// AF_BTH 32 /// /// The Bluetooth address family. This address family is only supported if a Bluetooth adapter is installed on Windows Server /// 2003 or later. /// /// /// /// public ADDRESS_FAMILY ai_family { get => (ADDRESS_FAMILY)_ai_family; set => _ai_family = (ushort)value; } /// /// Type: int /// The socket type. Possible values for the socket type are defined in the Winsock2.h header file. /// The following table lists the possible values for the socket type supported for Windows Sockets 2: /// /// /// Value /// Meaning /// /// /// SOCK_STREAM 1 /// /// Provides sequenced, reliable, two-way, connection-based byte streams with an OOB data transmission mechanism. Uses the /// Transmission Control Protocol (TCP) for the Internet address family (AF_INET or AF_INET6). If the ai_family member is /// AF_IRDA, then SOCK_STREAM is the only supported socket type. /// /// /// /// SOCK_DGRAM 2 /// /// Supports datagrams, which are connectionless, unreliable buffers of a fixed (typically small) maximum length. Uses the User /// Datagram Protocol (UDP) for the Internet address family (AF_INET or AF_INET6). /// /// /// /// SOCK_RAW 3 /// /// Provides a raw socket that allows an application to manipulate the next upper-layer protocol header. To manipulate the IPv4 /// header, the IP_HDRINCL socket option must be set on the socket. To manipulate the IPv6 header, the IPV6_HDRINCL socket /// option must be set on the socket. /// /// /// /// SOCK_RDM 4 /// /// Provides a reliable message datagram. An example of this type is the Pragmatic General Multicast (PGM) multicast protocol /// implementation in Windows, often referred to as reliable multicast programming. /// /// /// /// SOCK_SEQPACKET 5 /// Provides a pseudo-stream packet based on datagrams. /// /// /// /// In Windows Sockets 2, new socket types were introduced. An application can dynamically discover the attributes of each /// available transport protocol through the WSAEnumProtocols function. So an application can determine the possible socket type /// and protocol options for an address family and use this information when specifying this parameter. Socket type definitions /// in the Winsock2.h and Ws2def.h header files will be periodically updated as new socket types, address families, and /// protocols are defined. /// /// In Windows Sockets 1.1, the only possible socket types are SOCK_DATAGRAM and SOCK_STREAM. /// public SOCK ai_socktype; /// /// Type: int /// /// The protocol type. The possible options are specific to the address family and socket type specified. Possible values for /// the ai_protocol are defined in the Winsock2.h and Wsrm.h header files. /// /// /// On the Windows SDK released for Windows Vista and later, the organization of header files has changed and this member can be /// one of the values from the IPPROTO enumeration type defined in the Ws2def.h header file. Note that the Ws2def.h /// header file is automatically included in Winsock2.h, and should never be used directly. /// /// /// If a value of 0 is specified for ai_protocol, the caller does not wish to specify a protocol and the service provider /// will choose the ai_protocol to use. For protocols other than IPv4 and IPv6, set ai_protocol to zero. /// /// The following table lists common values for the ai_protocol member although many other values are possible. /// /// /// Value /// Meaning /// /// /// IPPROTO_TCP 6 /// /// The Transmission Control Protocol (TCP). This is a possible value when the ai_family member is AF_INET or AF_INET6 and the /// ai_socktype member is SOCK_STREAM. /// /// /// /// IPPROTO_UDP 17 /// /// The User Datagram Protocol (UDP). This is a possible value when the ai_family member is AF_INET or AF_INET6 and the type /// parameter is SOCK_DGRAM. /// /// /// /// IPPROTO_RM 113 /// /// The PGM protocol for reliable multicast. This is a possible value when the ai_family member is AF_INET and the ai_socktype /// member is SOCK_RDM. On the Windows SDK released for Windows Vista and later, this value is also called IPPROTO_PGM. /// /// /// /// If the ai_family member is AF_IRDA, then the ai_protocol must be 0. /// public IPPROTO ai_protocol; /// /// Type: size_t /// The length, in bytes, of the buffer pointed to by the ai_addr member. /// public SizeT ai_addrlen; /// /// Type: char* /// The canonical name for the host. /// public StrPtrUni ai_canonname; /// /// Type: struct sockaddr* /// /// A pointer to a sockaddr structure. The ai_addr member in each returned addrinfo structure points to a /// filled-in socket address structure. The length, in bytes, of each returned addrinfo structure is specified in the /// ai_addrlen member. /// /// public IntPtr ai_addr; /// /// Type: struct addrinfo* /// /// A pointer to the next structure in a linked list. This parameter is set to NULL in the last addrinfo structure /// of a linked list. /// /// public IntPtr ai_next; /// /// Type: struct sockaddr* /// /// A pointer to a sockaddr structure. The ai_addr member in each returned ADDRINFOW structure points to a filled-in /// socket address structure. The length, in bytes, of each returned ADDRINFOW structure is specified in the /// ai_addrlen member. /// /// public SOCKADDR addr => new(ai_addr, false, ai_addrlen); /// public override string ToString() => $"{ai_canonname}:{ai_flags},{ai_family},{ai_socktype},{ai_protocol},{addr}"; } /// The scope identifier for the IPv6 transport address. [PInvokeData("ws2def.h")] [StructLayout(LayoutKind.Sequential)] public struct SCOPE_ID { /// A ULONG representation of the IPv6 scope identifier. public uint Value; /// /// /// The zone index that identifies the zone to which the transport address pertains. Zones of the different scopes are /// instantiated as follows: /// /// /// Each interface on a node comprises a single zone of interface-local scope. /// Each link, and the interfaces attached to that link, comprise a single zone of link-local scope. /// There is a single zone of global scope that comprises all of the links and interfaces in the Internet. /// The boundaries of zones of scope other than interface-local, link-local, and global are defined by network administrators. /// /// A value of zero specifies the default zone. /// /// The zone index. public uint Zone { get => BitHelper.GetBits(Value, 0, 28); set => BitHelper.SetBits(ref Value, 0, 28, value); } /// /// /// The scope of the IPv6 transport address. This scope must be the same as the IPv6 scope value that is embedded in the IPv6 /// transport address. This member can be one of the following: /// /// ScopeLevelInterface /// The transport address has interface-local scope. /// ScopeLevelLink /// The transport address has link-local scope. /// ScopeLevelSubnet /// The transport address has subnet-local scope. /// ScopeLevelAdmin /// The transport address has admin-local scope. /// ScopeLevelSite /// The transport address has site-local scope. /// ScopeLevelOrganization /// The transport address has organization-local scope. /// ScopeLevelGlobal /// The transport address has global scope. /// /// The level. public byte Level { get => (byte)BitHelper.GetBits(Value, 28, 4); set => BitHelper.SetBits(ref Value, 28, 4, value); } } /// The SOCKADDR_IN structure specifies a transport address and port for the AF_INET address family. /// /// All of the data in the SOCKADDR_IN structure, except for the address family, must be specified in network-byte-order (big-endian). /// // https://docs.microsoft.com/en-us/windows/win32/api/ws2def/ns-ws2def-sockaddr_in typedef struct sockaddr_in { #if ... short // sin_family; #else ADDRESS_FAMILY sin_family; #endif USHORT sin_port; IN_ADDR sin_addr; CHAR sin_zero[8]; } SOCKADDR_IN, *PSOCKADDR_IN; [PInvokeData("ws2def.h", MSDNShortId = "96379562-403f-451c-ac7a-f0eec34bfe5e")] [StructLayout(LayoutKind.Sequential, Pack = 2)] public struct SOCKADDR_IN { /// The address family for the transport address. This member should always be set to AF_INET. public ADDRESS_FAMILY sin_family; /// A transport protocol port number. public ushort sin_port; /// An IN_ADDR structure that contains an IPv4 transport address. public IN_ADDR sin_addr; /// Reserved for system use. A WSK application should set the contents of this array to zero. public ulong sin_zero; /// Initializes a new instance of the struct. /// An IN_ADDR structure that contains an IPv4 transport address. /// A transport protocol port number. public SOCKADDR_IN(IN_ADDR addr, ushort port = 0) { sin_family = ADDRESS_FAMILY.AF_INET; sin_port = port; sin_addr = addr; sin_zero = 0; } /// Performs an implicit conversion from to . /// The addr. /// The resulting instance from the conversion. public static implicit operator SOCKADDR_IN(IN_ADDR addr) => new(addr); /// Performs an explicit conversion from to . /// The ipv4 address. /// The resulting instance from the conversion. public static explicit operator SOCKADDR_IN6(SOCKADDR_IN ipv4) => new(ipv4); /// Converts to string. /// A that represents this instance. public override string ToString() => $"{sin_addr}:{sin_port}"; } /// The SOCKADDR_STORAGE structure is a generic structure that specifies a transport address. /// /// A WSK application typically does not directly access any of the members of the SOCKADDR_STORAGE structure except for the /// ss_family member. Instead, a pointer to a SOCKADDR_STORAGE structure is normally cast to a pointer to the specific /// SOCKADDR structure type that corresponds to a particular address family. /// // https://docs.microsoft.com/ja-jp/windows/desktop/api/ws2def/ns-ws2def-sockaddr_storage_lh typedef struct sockaddr_storage { // ADDRESS_FAMILY ss_family; CHAR __ss_pad1[_SS_PAD1SIZE]; __int64 __ss_align; CHAR __ss_pad2[_SS_PAD2SIZE]; } SOCKADDR_STORAGE_LH, // *PSOCKADDR_STORAGE_LH, *LPSOCKADDR_STORAGE_LH; [PInvokeData("ws2def.h", MSDNShortId = "27e56c1a-ce11-4cdb-9be8-25ed2f94fb37")] [StructLayout(LayoutKind.Sequential, Pack = 8)] public struct SOCKADDR_STORAGE { /// /// The address family for the transport address. For more information about supported address families, see WSK Address Families. /// public ADDRESS_FAMILY ss_family; /// A padding of 6 bytes that puts the __ss_align member on an eight-byte boundary within the structure. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] public byte[] __ss_pad1; /// A 64-bit value that forces the structure to be 8-byte aligned. public long __ss_align; /// A padding of an additional 112 bytes that brings the total size of the SOCKADDR_STORAGE structure to 128 bytes. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 112)] public byte[] __ss_pad2; /// Performs an explicit conversion from to . /// The address. /// The resulting instance from the conversion. public static explicit operator SOCKADDR_STORAGE(in SOCKADDR_IN6 addr) { using var mem = SafeHGlobalHandle.CreateFromStructure(addr); mem.Size = Marshal.SizeOf(typeof(SOCKADDR_STORAGE)); return mem.ToStructure(); } /// Performs an explicit conversion from to . /// The address. /// The resulting instance from the conversion. public static explicit operator SOCKADDR_STORAGE(in SOCKADDR_IN addr) { using var mem = SafeHGlobalHandle.CreateFromStructure(addr); mem.Size = Marshal.SizeOf(typeof(SOCKADDR_STORAGE)); return mem.ToStructure(); } /// Performs an explicit conversion from to . /// The address. /// The resulting instance from the conversion. public static explicit operator SOCKADDR_STORAGE(SOCKADDR addr) { using var mem = new SafeHGlobalHandle(addr.GetAddressBytes()); mem.Size = Marshal.SizeOf(typeof(SOCKADDR_STORAGE)); return mem.ToStructure(); } /// Performs an explicit conversion from to . /// The address. /// The resulting instance from the conversion. public static explicit operator SOCKADDR_STORAGE(IPAddress addr) { using var mem = new SafeHGlobalHandle(addr.GetAddressBytes()); mem.Size = Marshal.SizeOf(typeof(SOCKADDR_STORAGE)); return mem.ToStructure(); } /// Performs an explicit conversion from to . /// The address. /// The resulting instance from the conversion. public static explicit operator SOCKADDR_STORAGE(SOCKADDR_INET addr) { using var mem = SafeHGlobalHandle.CreateFromStructure(addr); mem.Size = Marshal.SizeOf(typeof(SOCKADDR_STORAGE)); return mem.ToStructure(); } /// Performs an explicit conversion from to . /// The addr. /// The resulting instance from the conversion. public static explicit operator SOCKADDR(SOCKADDR_STORAGE addr) => SOCKADDR.CreateFromStructure(addr); /// Performs an explicit conversion from to . /// The addr. /// The resulting instance from the conversion. public static explicit operator SOCKADDR_IN(SOCKADDR_STORAGE addr) => (SOCKADDR_IN)SOCKADDR.CreateFromStructure(addr); /// Performs an explicit conversion from to . /// The addr. /// The resulting instance from the conversion. public static explicit operator SOCKADDR_IN6(SOCKADDR_STORAGE addr) => (SOCKADDR_IN6)SOCKADDR.CreateFromStructure(addr); /// Performs an explicit conversion from to . /// The addr. /// The resulting instance from the conversion. public static explicit operator SOCKADDR_INET(SOCKADDR_STORAGE addr) => (SOCKADDR_INET)SOCKADDR.CreateFromStructure(addr); } /// The SOCKET_ADDRESS structure stores protocol-specific address information. /// /// /// The SOCKADDR structure pointed to by the lpSockaddr member varies depending on the protocol or address family selected. /// For example, the sockaddr_in6 structure is used for an IPv6 socket address while the sockaddr_in4 structure is /// used for an IPv4 socket address. The address family is the first member of all of the SOCKADDR structures. The address /// family is used to determine which structure is used. /// /// /// On the Microsoft Windows Software Development Kit (SDK) released for Windows Vista and later, the organization of header files /// has changed and the SOCKET_ADDRESS structure is defined in the Ws2def.h header file. Note that the Ws2def.h header file /// is automatically included in Winsock2.h, and should never be used directly. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/ws2def/ns-ws2def-socket_address typedef struct _SOCKET_ADDRESS { LPSOCKADDR // lpSockaddr; INT iSockaddrLength; } SOCKET_ADDRESS, *PSOCKET_ADDRESS, *LPSOCKET_ADDRESS; [PInvokeData("ws2def.h", MSDNShortId = "37fbcb96-a859-4eca-8928-8051f95407b9")] [StructLayout(LayoutKind.Sequential, #if x64 Size = 16)] #else Size = 8)] #endif public struct SOCKET_ADDRESS { /// A pointer to a socket address represented as a SOCKADDR structure. public IntPtr lpSockaddr; /// The length, in bytes, of the socket address. public int iSockaddrLength; /// Gets the from this instance. /// The value pointed to by this instance. public SOCKADDR_INET GetSOCKADDR() => lpSockaddr.ToStructure(); /// Converts to string. /// A that represents this instance. public override string ToString() => GetSOCKADDR().ToString(); } /// The SOCKET_ADDRESS_LIST structure defines a variable-sized list of transport addresses. /// /// /// A WSK application passes a buffer to the WskControlSocket function when the WSK application queries the current list of local /// transport addresses that match a socket's address family. If the call to the WskControlSocket function succeeds, the /// buffer contains a SOCKET_ADDRESS_LIST structure followed by the SOCKADDR structures for each of the local transport addresses /// that match the socket's address family. The WSK subsystem fills in the Address array and sets the iAddressCount /// member to the number of entries in the array. The lpSockaddr pointers in each of the SOCKET_ADDRESS structures in the /// array point to the specific SOCKADDR structure type that corresponds to the address family that the WSK application specified /// when it created the socket. /// /// For more information about querying the current list of local transport addresses, see SIO_ADDRESS_LIST_QUERY. /// // https://docs.microsoft.com/en-us/windows/win32/api/ws2def/ns-ws2def-socket_address_list typedef struct _SOCKET_ADDRESS_LIST { INT // iAddressCount; SOCKET_ADDRESS Address[1]; } SOCKET_ADDRESS_LIST, *PSOCKET_ADDRESS_LIST, *LPSOCKET_ADDRESS_LIST; [PInvokeData("ws2def.h", MSDNShortId = "b005200b-b0c2-4f19-8765-cd26fbfc0cff")] [VanaraMarshaler(typeof(SafeAnysizeStructMarshaler), nameof(iAddressCount))] [StructLayout(LayoutKind.Sequential)] public struct SOCKET_ADDRESS_LIST { /// The number of transport addresses in the list. public int iAddressCount; /// A variable-sized array of SOCKET_ADDRESS structures. The SOCKET_ADDRESS structure is defined as follows: [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)] public SOCKET_ADDRESS[] Address; /// Packs this instance into a single memory block so that it can be passed as a pointer to other API methods. /// /// A instance that contains this structure and all memeroy assigned to its elements. /// public SafeCoTaskMemStruct Pack() { var addrOffset = Marshal.OffsetOf(typeof(SOCKET_ADDRESS_LIST), "Address").ToInt32(); var eosOffset = addrOffset + iAddressCount * Marshal.SizeOf(typeof(SOCKET_ADDRESS)); var cbAddressList = eosOffset + Address.Sum(a => a.iSockaddrLength); var addressList = new SafeCoTaskMemStruct(cbAddressList); ((IntPtr)addressList).Write(iAddressCount); var newAddr = new SOCKET_ADDRESS[iAddressCount]; var ptr = ((IntPtr)addressList).Offset(eosOffset); for (int i = 0; i < iAddressCount; i++) { newAddr[i] = new SOCKET_ADDRESS { iSockaddrLength = Address[i].iSockaddrLength, lpSockaddr = ptr }; Address[i].lpSockaddr.CopyTo(ptr, Address[i].iSockaddrLength); ptr = ptr.Offset(Address[i].iSockaddrLength); } ((IntPtr)addressList).Write(newAddr, addrOffset); return addressList; } } /// /// The SOCKET_PROCESSOR_AFFINITY structure contains the association between a socket and an RSS processor core and NUMA node.. /// /// /// /// The SOCKET_PROCESSOR_AFFINITY structure is supported on Windows 8, and Windows Server 2012, and later versions of the /// operating system. /// /// /// The SIO_QUERY_RSS_PROCESSOR_INFO IOCTL is used to determine the association between a socket and an RSS processor core and NUMA /// node. This IOCTL returns a SOCKET_PROCESSOR_AFFINITY structure that contains the processor number and the NUMA node ID. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/ws2def/ns-ws2def-socket_processor_affinity typedef struct // _SOCKET_PROCESSOR_AFFINITY { PROCESSOR_NUMBER Processor; USHORT NumaNodeId; USHORT Reserved; } SOCKET_PROCESSOR_AFFINITY, *PSOCKET_PROCESSOR_AFFINITY; [PInvokeData("ws2def.h", MSDNShortId = "CB1E9F79-C6BD-40C2-8D0F-36B24B1BBBF4")] [StructLayout(LayoutKind.Sequential)] public struct SOCKET_PROCESSOR_AFFINITY { /// /// A structure to represent a system wide processor number. This PROCESSOR_NUMBER structure contains a group number and /// relative processor number within the group. /// public Kernel32.PROCESSOR_NUMBER Processor; /// The NUMA node ID. public ushort NumaNodeId; /// A value reserved for future use. public ushort Reserved; } /// The WSABUF structure enables the creation or manipulation of a data buffer used by some Winsock functions. // https://docs.microsoft.com/en-us/windows/desktop/api/ws2def/ns-ws2def-_wsabuf typedef struct _WSABUF { ULONG len; CHAR *buf; } // WSABUF, *LPWSABUF; [PInvokeData("ws2def.h", MSDNShortId = "a012c3ba-67fd-4fcf-84d1-85e9d495c29c")] [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] public struct WSABUF { /// The length of the buffer, in bytes. public uint len; /// A pointer to the buffer. public IntPtr buf; } /// The CMSGHDR structure defines the header for a control data object that is associated with a datagram. /// /// The control information data that is associated with a datagram is made up of one or more control data objects. Each object /// begins with a CMSGHDR structure. /// // https://docs.microsoft.com/en-us/windows/win32/api/ws2def/ns-ws2def-wsacmsghdr typedef struct _WSACMSGHDR { SIZE_T cmsg_len; INT // cmsg_level; INT cmsg_type; } WSACMSGHDR, *PWSACMSGHDR, *LPWSACMSGHDR; [PInvokeData("ws2def.h", MSDNShortId = "NS:ws2def._WSACMSGHDR")] [StructLayout(LayoutKind.Sequential)] public struct WSACMSGHDR { /// /// The number of bytes from the beginning of the CMSGHDR structure to the end of the control data. /// Note The value of the cmsg_len member does not account for any padding that may follow the control data. /// public SizeT cmsg_len; /// The protocol that originated the control information. public int cmsg_level; /// The protocol-specific type of control information. public int cmsg_type; } /// /// The WSAMSG structure is used with the WSARecvMsg and WSASendMsg functions to store address and optional control /// information about connected and unconnected sockets as well as an array of buffers used to store message data. /// /// /// /// In the Microsoft Windows Software Development Kit (SDK), the version of this structure for use on Windows Vistais defined with /// the data type for the dwBufferCount and dwFlags members as a ULONG. When compiling an application if the /// target platform is Windows Vista and later ( NTDDI_VERSION >= NTDDI_LONGHORN, _WIN32_WINNT >= 0x0600, or WINVER /// >= 0x0600), the data type for the dwBufferCount and dwFlags members is a ULONG. /// /// /// Windows Server 2003 and Windows XP: When compiling an application, the data type for the dwBufferCount and /// dwFlags members is a DWORD. /// /// /// On the Windows SDK released for Windows Vista and later, the WSAMSG structure is defined in the Ws2def.h header file. /// Note that the Ws2def.h header file is automatically included in Winsock2.h, and should never be used directly /// /// /// If the datagram or control data is truncated during the transmission, the function being used in association with the /// WSAMSG structure returns SOCKET_ERROR and a call to the WSAGetLastError function returns WSAEMSGSIZE. It is up to the /// application to determine what was truncated by checking for MSG_TRUNC and/or MSG_CTRUNC flags. /// /// Use of the Control Member /// /// The following table summarizes the various uses of control data available for use in the Control member for IPv4 and IPv6. /// /// /// /// Protocol /// cmsg_level /// cmsg_type /// Description /// /// /// IPv4 /// IPPROTO_IP /// IP_ORIGINAL_ARRIVAL_IF /// /// Receives the original IPv4 arrival interface where the packet was received for datagram sockets. This control data is used by /// firewalls when a Teredo, 6to4, or ISATAP tunnel is used for IPv4 NAT traversal. The cmsg_data[] member in the WSAMSG structure /// is a ULONG that contains the IF_INDEX defined in the Ifdef.h header file. For more information, see the IPPROTO_IP Socket /// Options for the IP_ORIGINAL_ARRIVAL_IF socket option. Windows Server 2008, Windows Vista, Windows Server 2003 and Windows XP: /// The IP_ORIGINAL_ARRIVAL_IF cmsg_type is not supported. /// /// /// /// IPv4 /// IPPROTO_IP /// IP_PKTINFO /// Specifies/receives packet information for an IPv4 socket. For more information, see the IP_PKTINFO socket option. /// /// /// IPv6 /// IPPROTO_IPV6 /// IPV6_DSTOPTS /// Specifies/receives destination options. /// /// /// IPv6 /// IPPROTO_IPV6 /// IPV6_HOPLIMIT /// Specifies/receives hop limit. For more information, see the IPPROTO_IPV6 Socket Options for the IPV6_HOPLIMIT socket option. /// /// /// IPv6 /// IPPROTO_IPV6 /// IPV6_HOPOPTS /// Specifies/receives hop-by-hop options. /// /// /// IPv6 /// IPPROTO_IPV6 /// IPV6_NEXTHOP /// Specifies next-hop address. /// /// /// IPv6 /// IPPROTO_IPV6 /// IPV6_PKTINFO /// Specifies/receives packet information for an IPv6 socket. For more information, see the IPV6_PKTINFO socket option. /// /// /// IPv6 /// IPPROTO_IPV6 /// IPV6_RTHDR /// Specifies/receives routing header. /// /// /// /// Control data is made up of one or more control data objects, each beginning with a WSACMSGHDR structure, defined as the following. /// /// /// Note The transport, not the application, fills out the header information in the WSACMSGHDR structure. The /// application simply sets the needed socket options and provides the adequate buffer size. /// /// The members of the WSACMSGHDR structure are as follows: /// /// /// Term /// Description /// /// /// cmsg_len /// /// The number of bytes of data starting from the beginning of the WSACMSGHDR to the end of data (excluding padding bytes that may /// follow data). /// /// /// /// cmsg_level /// The protocol that originated the control information. /// /// /// cmsg_type /// The protocol-specific type of control information. /// /// /// The following macros are used to navigate the data objects: /// /// Returns a pointer to the first control data object. Returns a NULL pointer if there is no control data in the /// WSAMSG structure, such as when the Control member is a NULL pointer. /// /// /// Returns a pointer to the next control data object, or NULL if there are no more data objects. If the pcmsg parameter is /// NULL, a pointer to the first control data object is returned. /// /// /// Returns a pointer to the first byte of data (referred to as the cmsg_data member, though it is not defined in the structure). /// /// /// Returns the total size of a control data object, given the amount of data. Used to allocate the correct amount of buffer space. /// Includes alignment padding. /// /// Returns the value in cmsg_len given the amount of data. Includes alignment padding. /// // https://docs.microsoft.com/en-us/windows/win32/api/ws2def/ns-ws2def-wsamsg typedef struct _WSAMSG { LPSOCKADDR name; INT namelen; // LPWSABUF lpBuffers; #if ... ULONG dwBufferCount; #else DWORD dwBufferCount; #endif WSABUF Control; #if ... ULONG dwFlags; #else // DWORD dwFlags; #endif } WSAMSG, *PWSAMSG, *LPWSAMSG; [PInvokeData("ws2def.h", MSDNShortId = "105a6e2c-1edf-4ec0-a1c2-ac0bcafeda30")] [StructLayout(LayoutKind.Sequential)] public struct WSAMSG { /// /// Type: LPSOCKADDR /// /// A pointer to a SOCKET_ADDRESS structure that stores information about the remote address. Used only with unconnected sockets. /// /// public IntPtr name; /// /// Type: INT /// /// The length, in bytes, of the SOCKET_ADDRESS structure pointed to in the pAddr member. Used only with unconnected sockets. /// /// public int namelen; /// /// Type: LPWSABUF /// /// An array of WSABUF structures used to receive the message data. The capability of the lpBuffers member to contain /// multiple buffers enables the use of scatter/gather I/O. /// /// public IntPtr lpBuffers; /// /// Type: DWORD /// The number of buffers pointed to in the lpBuffers member. /// public uint dwBufferCount; /// /// Type: WSABUF /// A structure of WSABUF type used to specify optional control data. See Remarks. /// public WSABUF Control; /// /// Type: DWORD /// /// One or more control flags, specified as the logical OR of values. The possible values for dwFlags member on /// input are defined in the Winsock2.h header file. The possible values for dwFlags member on output are defined in the /// Ws2def.h header file which is automatically included by the Winsock2.h header file. /// /// /// /// Flags on input /// Meaning /// /// /// MSG_PEEK /// /// Peek at the incoming data. The data is copied into the buffer, but is not removed from the input queue. This flag is valid /// only for non-overlapped sockets. /// /// /// /// /// /// Flag returned /// Meaning /// /// /// MSG_BCAST /// The datagram was received as a link-layer broadcast or with a destination IP address that is a broadcast address. /// /// /// MSG_MCAST /// The datagram was received with a destination IP address that is a multicast address. /// /// /// MSG_TRUNC /// The datagram was truncated. More data was present than the process allocated room for. /// /// /// MSG_CTRUNC /// The control (ancillary) data was truncated. More control data was present than the process allocated room for. /// /// /// public MsgFlags dwFlags; } /// /// /// Some of the socket IOCTL opcodes for Windows Sockets 2 are summarized in the following table. More detailed information is in /// the Winsock reference on Winsock IOCTLs and the WSPIoctl function. There are other new protocol-specific IOCTL /// opcodes that can be found in the protocol-specific annex. /// /// A complete list of Winsock IOCTLs are available in the Winsock reference. /// // https://docs.microsoft.com/en-us/windows/win32/winsock/summary-of-socket-ioctl-opcodes-2 [PInvokeData("ws2def.h", MSDNShortId = "fb6447b4-28f5-4ab7-bbdc-5a57ed38a994")] public static class WinSockIOControlCode { /// /// Determine the amount of data that can be read atomically from socket s. The lpvOutBuffer parameter points at an unsigned long /// in which WSAIoctl stores the result. /// /// If the socket passed in the s parameter is stream oriented(for example, type SOCK_STREAM), FIONREAD returns the total amount /// of data that can be read in a single receive operation; this is normally the same as the total amount of data queued on the /// socket(since a data stream is byte-oriented, this is not guaranteed). /// /// /// If the socket passed in the s parameter is message oriented(for example, type SOCK_DGRAM), FIONREAD returns the reports the /// total number of bytes available to read, not the size of the first datagram(message) queued on the socket. /// /// public static readonly uint FIONREAD = _IOR('f', 127); /* get # bytes to read */ /// /// Enable or disable non-blocking mode on socket s. The lpvInBuffer parameter points at an unsigned long (QoS), which is nonzero /// if non-blocking mode is to be enabled and zero if it is to be disabled. When a socket is created, it operates in blocking /// mode (that is, non-blocking mode is disabled). This is consistent with BSD sockets. /// /// The WSAAsyncSelect or WSAEventSelect routine automatically sets a socket to non-blocking mode.If WSAAsyncSelect or /// WSAEventSelect has been issued on a socket, then any attempt to use WSAIoctl to set the socket back to blocking mode will /// fail with WSAEINVAL. To set the socket back to blocking mode, an application must first disable WSAAsyncSelect by calling /// WSAAsyncSelect with the lEvent parameter equal to zero, or disable WSAEventSelect by calling WSAEventSelect with the /// lNetworkEvents parameter equal to zero. /// /// public static readonly uint FIONBIO = _IOW('f', 126); /* set/clear non-blocking i/o */ /// Enable notification for when data is waiting to be received. public static readonly uint FIOASYNC = _IOW('f', 125); /* set/clear async i/o */ /// Requests notification of changes in information reported through SIO_ADDRESS_LIST_QUERY public static readonly uint SIO_ADDRESS_LIST_CHANGE = _WSAIO(IOC_WS2, 23); /// /// Obtains a list of local transport addresses of the socket's protocol family to which the application can bind. The list of /// addresses varies based on address family and some addresses are excluded from the list. /// [CorrespondingType(typeof(SOCKET_ADDRESS), CorrespondingAction.Get)] public static readonly uint SIO_ADDRESS_LIST_QUERY = _WSAIOR(IOC_WS2, 22); /// /// Allows application developers to sort a list of IPv6 and IPv4 destination addresses to determine the best available address /// for making a connection. /// [CorrespondingType(typeof(SOCKET_ADDRESS_LIST), CorrespondingAction.GetSet)] public static readonly uint SIO_ADDRESS_LIST_SORT = _WSAIORW(IOC_WS2, 25); /// Associates the socket with the specified handle of a companion interface. public static readonly uint SIO_ASSOCIATE_HANDLE = _WSAIOW(IOC_WS2, 1); /// Enables circular queuing. public static readonly uint SIO_ENABLE_CIRCULAR_QUEUEING = _WSAIO(IOC_WS2, 2); /// Requests the route to the specified address to be discovered. [CorrespondingType(typeof(SOCKADDR), CorrespondingAction.Set)] public static readonly uint SIO_FIND_ROUTE = _WSAIOR(IOC_WS2, 3); /// Discards current contents of the sending queue. public static readonly uint SIO_FLUSH = _WSAIO(IOC_WS2, 4); /// Retrieves the protocol-specific broadcast address to be used in WSPSendTo. [CorrespondingType(typeof(SOCKADDR), CorrespondingAction.Get)] public static readonly uint SIO_GET_BROADCAST_ADDRESS = _WSAIOR(IOC_WS2, 5); /// Gets the function pointer for the WSASendMsg function obtained at run time. public static readonly uint SIO_GET_EXTENSION_FUNCTION_POINTER = _WSAIORW(IOC_WS2, 6); /// Reserved. [CorrespondingType(typeof(QOS), CorrespondingAction.Get)] public static readonly uint SIO_GET_GROUP_QOS = _WSAIORW(IOC_WS2, 8); /// Retrieves current flow specifications for the socket. [CorrespondingType(typeof(QOS), CorrespondingAction.Get)] public static readonly uint SIO_GET_QOS = _WSAIORW(IOC_WS2, 7); /// Specifies the scope over which multicast transmissions will occur. [CorrespondingType(typeof(int), CorrespondingAction.Set)] public static readonly uint SIO_MULTICAST_SCOPE = _WSAIOW(IOC_WS2, 10); /// Controls whether data sent in a multipoint session will also be received by the same socket on the local host. [CorrespondingType(typeof(BOOL), CorrespondingAction.Set)] public static readonly uint SIO_MULTIPOINT_LOOPBACK = _WSAIOW(IOC_WS2, 9); /// Queries the association between a socket and an RSS processor core and NUMA node. [CorrespondingType(typeof(SOCKET_PROCESSOR_AFFINITY), CorrespondingAction.Get)] public static readonly uint SIO_QUERY_RSS_PROCESSOR_INFO = _WSAIOR(IOC_WS2, 37); /// Obtains socket descriptor of the next provider in the chain on which current socket depends in regards to PnP. [CorrespondingType(typeof(SOCKET), CorrespondingAction.Get)] public static readonly uint SIO_QUERY_TARGET_PNP_HANDLE = _WSAIOR(IOC_WS2, 24); /// /// Requests notification of changes in information reported through SIO_ROUTING_INTERFACE_QUERY for the specified address. /// [CorrespondingType(typeof(SOCKADDR), CorrespondingAction.Set)] public static readonly uint SIO_ROUTING_INTERFACE_CHANGE = _WSAIOW(IOC_WS2, 21); /// Obtains the address of the local interface that should be used to send to the specified address. [CorrespondingType(typeof(SOCKADDR), CorrespondingAction.GetSet)] public static readonly uint SIO_ROUTING_INTERFACE_QUERY = _WSAIORW(IOC_WS2, 20); /// Reserved. [CorrespondingType(typeof(QOS), CorrespondingAction.Set)] public static readonly uint SIO_SET_GROUP_QOS = _WSAIOW(IOC_WS2, 12); /// Establishes new flow specifications for the socket. [CorrespondingType(typeof(QOS), CorrespondingAction.Set)] public static readonly uint SIO_SET_QOS = _WSAIOW(IOC_WS2, 11); /// Obtains a corresponding handle for socket s that is valid in the context of a companion interface. [CorrespondingType(typeof(int), CorrespondingAction.Set)] public static readonly uint SIO_TRANSLATE_HANDLE = _WSAIORW(IOC_WS2, 13); /// set high watermark public static readonly uint SIOCSHIWAT = _IOW('s', 0); /* set high watermark */ /// get high watermark public static readonly uint SIOCGHIWAT = _IOR('s', 1); /* get high watermark */ /// set low watermark public static readonly uint SIOCSLOWAT = _IOW('s', 2); /* set low watermark */ /// get low watermark public static readonly uint SIOCGLOWAT = _IOR('s', 3); /* get low watermark */ /// /// Determine whether or not all OOB data has been read. This applies only to a socket of stream-style (for example, type /// SOCK_STREAM) that has been configured for inline reception of any OOB data (SO_OOBINLINE). If no OOB data is waiting to be /// read, the operation returns TRUE. Otherwise, it returns FALSE, and the next receive operation performed on the socket will /// retrieve some or all of the data preceding the mark; the application should use the SIOCATMARK operation to determine whether /// any remains. If there is any normal data preceding the urgent (out of band) data, it will be received in order. (Note that /// recv operations will never mix OOB and normal data in the same call.) lpvOutBuffer points at a BOOL in which WSAIoctl stores /// the result. /// public static readonly uint SIOCATMARK = _IOR('s', 7); /* at oob mark? */ private const uint IOCPARM_MASK = 0x7f; /* parameters must be < 128 bytes */ private const uint IOC_VOID = 0x20000000; /* no parameters */ private const uint IOC_OUT = 0x40000000; /* copy out parameters */ private const uint IOC_IN = 0x80000000; /* copy in parameters */ private const uint IOC_INOUT = IOC_IN|IOC_OUT; private const uint IOC_PROTOCOL = 0x10000000; private const uint IOC_UNIX = 0x00000000; private const uint IOC_VENDOR = 0x18000000; private const uint IOC_WS2 = 0x08000000; private const uint IOC_WSK = IOC_WS2 | 0x07000000; private static uint _IO(uint x, uint y) => (IOC_VOID|((x)<<8)|(y)); private static uint _IOR(uint x, uint y) => (IOC_OUT|((sizeof(uint)&IOCPARM_MASK)<<16)|((x)<<8)|(y)); private static uint _IOW(uint x, uint y) => (IOC_IN|((sizeof(uint)&IOCPARM_MASK)<<16)|((x)<<8)|(y)); private static uint _WSAIO(uint x, uint y) => IOC_VOID | (x) | (y); private static uint _WSAIOR(uint x, uint y) => IOC_OUT | (x) | (y); private static uint _WSAIORW(uint x, uint y) => IOC_INOUT | (x) | (y); private static uint _WSAIOW(uint x, uint y) => IOC_IN | (x) | (y); } } }