' ########################################################################################
' Microsoft Windows
' File: mstcpip.inc
' Contents: Microsoft-specific extensions to the core Winsock definitions
' Copyright (c) 2011 Jos? Roca
' Portions Copyright (c) Microsoft Corporation.
' All Rights Reserved.
' THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
' EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
' MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
' ########################################################################################
#IF NOT %DEF(PBX_MSTcpIP_PBI)
#DEFINE PBX_MSTcpIP_PBI
%EQUATE `MSTCPIP_INC = 1
#INCLUDE ONCE "Legacy/System/nldef.inc"
#INCLUDE ONCE "Legacy/System/ws2def.inc"
#INCLUDE ONCE "Legacy/System/ws2ipdef.inc"
'#if (NTDDI_VERSION >= NTDDI_WIN7)
'// GUID definition for use with Secure Sockets API
'// aec2ef9c-3a4d-4d3e-8842-239942e39a47
$SOCKET_DEFAULT2_QM_POLICY = GUID$("{aec2ef9c-3a4d-4d3e-8842-239942e39a47}")
'#endif
'/* Argument structure for SIO_KEEPALIVE_VALS */
' // Size = 12 bytes
TYPE tcp_keepalive DWORD
 onoff AS DWORD ' ULONG
 keepalivetime AS DWORD ' ULONG
 keepaliveinterval AS DWORD ' ULONG
END TYPE
'//
'// New WSAIoctl Options
'//
'#define SIO_RCVALL _WSAIOW(IOC_VENDOR,1)
'#define SIO_RCVALL_MCAST _WSAIOW(IOC_VENDOR,2)
'#define SIO_RCVALL_IGMPMCAST _WSAIOW(IOC_VENDOR,3)
'#define SIO_KEEPALIVE_VALS _WSAIOW(IOC_VENDOR,4)
'#define SIO_ABSORB_RTRALERT _WSAIOW(IOC_VENDOR,5)
'#define SIO_UCAST_IF _WSAIOW(IOC_VENDOR,6)
'#define SIO_LIMIT_BROADCASTS _WSAIOW(IOC_VENDOR,7)
'#define SIO_INDEX_BIND _WSAIOW(IOC_VENDOR,8)
'#define SIO_INDEX_MCASTIF _WSAIOW(IOC_VENDOR,9)
'#define SIO_INDEX_ADD_MCAST _WSAIOW(IOC_VENDOR,10)
'#define SIO_INDEX_DEL_MCAST _WSAIOW(IOC_VENDOR,11)
'// SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12)
'#define SIO_RCVALL_MCAST_IF _WSAIOW(IOC_VENDOR,13)
'#define SIO_RCVALL_IF _WSAIOW(IOC_VENDOR,14)
%EQUATE `SIO_RCVALL = &H98000001
%EQUATE `SIO_RCVALL_MCAST = &H98000002
%EQUATE `SIO_RCVALL_IGMPMCAST = &H98000003
%EQUATE `SIO_KEEPALIVE_VALS = &H98000004
%EQUATE `SIO_ABSORB_RTRALERT = &H98000005
%EQUATE `SIO_UCAST_IF = &H98000006
%EQUATE `SIO_LIMIT_BROADCASTS = &H98000007
%EQUATE `SIO_INDEX_BIND = &H98000008
%EQUATE `SIO_INDEX_MCASTIF = &H98000009
%EQUATE `SIO_INDEX_ADD_MCAST = &H9800000A
%EQUATE `SIO_INDEX_DEL_MCAST = &H9800000B
'// %SIO_UDP_CONNRESET = &H9800000C
%EQUATE `SIO_RCVALL_MCAST_IF = &H9800000D
%EQUATE `SIO_RCVALL_IF = &H9800000E
'//
'// Values for use with SIO_RCVALL* options
'//
' enum RCVALL_VALUE
%EQUATE `RCVALL_OFF = 0
%EQUATE `RCVALL_ON = 1
%EQUATE `RCVALL_SOCKETLEVELONLY = 2
%EQUATE `RCVALL_IPLEVEL = 3
%EQUATE `RCVALL_MAX = %RCVALL_IPLEVEL
' // Size = 8 bytes
TYPE RCVALL_IF DWORD
 Mode AS DWORD ' RCVALL_VALUE
 Interface AS DWORD ' ULONG
END TYPE
'//
'// TCP/UDP port management definitions.
'//
'#define SIO_ACQUIRE_PORT_RESERVATION _WSAIOW(IOC_VENDOR, 100)
'#define SIO_RELEASE_PORT_RESERVATION _WSAIOW(IOC_VENDOR, 101)
'#define SIO_ASSOCIATE_PORT_RESERVATION _WSAIOW(IOC_VENDOR, 102)
%EQUATE `SIO_ACQUIRE_PORT_RESERVATION = &H98000064
%EQUATE `SIO_RELEASE_PORT_RESERVATION = &H98000065
%EQUATE `SIO_ASSOCIATE_PORT_RESERVATION = &H98000066
' // Size = 4 bytes
TYPE INET_PORT_RANGE WORD
 StartPort AS WORD ' USHORT
 NumberOfPorts AS WORD ' USHORT
END TYPE
MACRO INET_PORT_RESERVATION = INET_PORT_RANGE
' // Size = 8 bytes
TYPE INET_PORT_RESERVATION_TOKEN QWORD
 Token AS QUAD ' ULONG64
END TYPE
'#define INVALID_PORT_RESERVATION_TOKEN ((ULONG64)0)
%EQUATE `INVALID_PORT_RESERVATION_TOKEN = 0&&
' // Size = 16 bytes
TYPE INET_PORT_RESERVATION_INSTANCE QWORD
 Reservation AS INET_PORT_RESERVATION
 Token AS INET_PORT_RESERVATION_TOKEN
END TYPE
' // Size = 8 bytes
TYPE INET_PORT_RESERVATION_INFORMATION DWORD
 AssignmentCount AS DWORD ' ULONG
 OwningPid AS DWORD ' ULONG
END TYPE
'#ifdef _WS2DEF_
'#if (NTDDI_VERSION >= NTDDI_VISTA)
'#define _SECURE_SOCKET_TYPES_DEFINED_
'//
'// Secure socket API type definitions.
'//
'#define SIO_SET_SECURITY _WSAIOW(IOC_VENDOR, 200)
'#define SIO_QUERY_SECURITY _WSAIORW(IOC_VENDOR, 201)
'#define SIO_SET_PEER_TARGET_NAME _WSAIOW(IOC_VENDOR, 202)
'#define SIO_DELETE_PEER_TARGET_NAME _WSAIOW(IOC_VENDOR, 203)
%EQUATE `SIO_SET_SECURITY = &H980000C8
%EQUATE `SIO_QUERY_SECURITY = &HD80000C9
%EQUATE `SIO_SET_PEER_TARGET_NAME = &H980000CA
%EQUATE `SIO_DELETE_PEER_TARGET_NAME = &H980000CB
'//
'// iSCSI IOCTLS
'//
'#define SIO_SOCKET_USAGE_NOTIFICATION _WSAIOW(IOC_VENDOR, 204)
%EQUATE `SIO_SOCKET_USAGE_NOTIFICATION = &H980000CC
' enum SOCKET_USAGE_TYPE
%EQUATE `SYSTEM_CRITICAL_SOCKET = 1
'// Type of security protocol
' enum SOCKET_SECURITY_PROTOCOL
%EQUATE `SOCKET_SECURITY_PROTOCOL_DEFAULT = 0
%EQUATE `SOCKET_SECURITY_PROTOCOL_IPSEC = 1
'#if (NTDDI_VERSION >= NTDDI_WIN7)
%EQUATE `SOCKET_SECURITY_PROTOCOL_IPSEC2 = 2 ' // version 2 of secure socket apis
'#endif // (NTDDI_VERSION >= NTDDI_WIN7)
%EQUATE `SOCKET_SECURITY_PROTOCOL_INVALID = 3
'// Flags for generic security settings
%EQUATE `SOCKET_SETTINGS_GUARANTEE_ENCRYPTION = &H1
%EQUATE `SOCKET_SETTINGS_ALLOW_INSECURE = &H2
'// Common security settings for the socket
' // Size = 8 bytes
TYPE SOCKET_SECURITY_SETTINGS DWORD
 SecurityProtocol AS DWORD ' SOCKET_SECURITY_PROTOCOL
 SecurityFlags AS DWORD ' ULONG
END TYPE
'// Flags specific to IPsec security settings.
'// NOTE: these flags must be specified under the
'// SOCKET_SECURITY_SETTINGS_IPSEC->IpsecFlags field.
%EQUATE `SOCKET_SETTINGS_IPSEC_SKIP_FILTER_INSTANTIATION = &H1
'#if (NTDDI_VERSION >= NTDDI_WIN7)
%EQUATE `SOCKET_SETTINGS_IPSEC_OPTIONAL_PEER_NAME_VERIFICATION = &H2
%EQUATE `SOCKET_SETTINGS_IPSEC_ALLOW_FIRST_INBOUND_PKT_UNENCRYPTED = &H4
%EQUATE `SOCKET_SETTINGS_IPSEC_PEER_NAME_IS_RAW_FORMAT = &H8
'#endif // (NTDDI_VERSION >= NTDDI_WIN7)
'// IPsec specific security settings for the socket.
' // Size = 88 bytes
TYPE SOCKET_SECURITY_SETTINGS_IPSEC QWORD FILL
 SecurityProtocol AS DWORD ' SOCKET_SECURITY_PROTOCOL
 SecurityFlags AS DWORD ' ULONG
 IpsecFlags AS DWORD ' ULONG
 AuthipMMPolicyKey AS GUID ' GUID
 AuthipQMPolicyKey AS GUID ' GUID
 Reserved AS GUID ' GUID
 Reserved2 AS QUAD ' UINT64
 UserNameStringLen AS DWORD ' ULONG
 DomainNameStringLen AS DWORD ' ULONG
 PasswordStringLen AS DWORD ' ULONG
 AllStrings AS WSTRINGZ * 2 ' wchar_t[] - variable length
END TYPE
'// Common peer target name for the socket
' // Size = 144 bytes
TYPE SOCKET_PEER_TARGET_NAME QWORD FILL
 SecurityProtocol AS DWORD ' SOCKET_SECURITY_PROTOCOL
 PeerAddress AS SOCKADDR_STORAGE
 PeerTargetNameStringLen AS DWORD ' ULONG
 AllStrings AS WSTRINGZ * 2 ' wchar_t[] - variable length
END TYPE
'// Input for querying socket security
' // Size = 144 bytes
TYPE SOCKET_SECURITY_QUERY_TEMPLATE QWORD
 SecurityProtocol AS DWORD ' SOCKET_SECURITY_PROTOCOL
 PeerAddress AS SOCKADDR_STORAGE
 PeerTokenAccessMask AS DWORD ' ULONG
END TYPE
'#if (NTDDI_VERSION >= NTDDI_WIN7)
%EQUATE `SOCKET_QUERY_IPSEC2_ABORT_CONNECTION_ON_FIELD_CHANGE = &H1
%EQUATE `SOCKET_QUERY_IPSEC2_FIELD_MASK_MM_SA_ID = &H1
%EQUATE `SOCKET_QUERY_IPSEC2_FIELD_MASK_QM_SA_ID = &H2
'// Input for querying socket security
' // Size = 152 bytes
TYPE SOCKET_SECURITY_QUERY_TEMPLATE_IPSEC2 QWORD FILL
 SecurityProtocol AS DWORD ' SOCKET_SECURITY_PROTOCOL
 PeerAddress AS SOCKADDR_STORAGE
 PeerTokenAccessMask AS DWORD ' ULONG
 Flags AS DWORD ' ULONG
 FieldMask AS DWORD ' ULONG
 alignment__ AS DWORD
END TYPE
'#endif // (NTDDI_VERSION >= NTDDI_WIN7)
'// Flags corresponding to the security query info
%EQUATE `SOCKET_INFO_CONNECTION_SECURED = &H1
%EQUATE `SOCKET_INFO_CONNECTION_ENCRYPTED = &H2
%EQUATE `SOCKET_INFO_CONNECTION_IMPERSONATED = &H4
'// Common security query information from a socket
' // Size = 24 bytes
TYPE SOCKET_SECURITY_QUERY_INFO QWORD FILL
 SecurityProtocol AS DWORD ' SOCKET_SECURITY_PROTOCOL
 Flags AS DWORD ' ULONG
 PeerApplicationAccessTokenHandle AS QUAD ' UINT64
 PeerMachineAccessTokenHandle AS QUAD ' UINT64
END TYPE
'#if (NTDDI_VERSION >= NTDDI_WIN7)
'// Common security query information from a socket
' // Size = 64 bytes
TYPE SOCKET_SECURITY_QUERY_INFO_IPSEC2 QWORD FILL
 SecurityProtocol AS DWORD ' SOCKET_SECURITY_PROTOCOL
 Flags AS DWORD ' ULONG
 PeerApplicationAccessTokenHandle AS QUAD ' UINT64
 PeerMachineAccessTokenHandle AS QUAD ' UINT64
 MmSaId AS QUAD ' UINT64
 QmSaId AS QUAD ' UINT64
 NegotiationWinerr AS DWORD ' UINT32
 SaLookupContext AS GUID ' GUID
END TYPE
'#endif // (NTDDI_VERSION >= NTDDI_WIN7)
'//
'// WFP ALE endpoint handle query type definition
'//
'#define SIO_QUERY_WFP_ALE_ENDPOINT_HANDLE _WSAIOR(IOC_VENDOR, 205)
%EQUATE `SIO_QUERY_WFP_ALE_ENDPOINT_HANDLE = &H580000CD
'//
'// Scalability type definitions
'//
'#define SIO_QUERY_RSS_SCALABILITY_INFO _WSAIOR(IOC_VENDOR, 210)
%EQUATE `SIO_QUERY_RSS_SCALABILITY_INFO = &H580000CD
'// Scalability info for the transport
' // Size = 1 bytes
TYPE RSS_SCALABILITY_INFO BYTE
 RssEnabled AS BYTE ' BOOLEAN
END TYPE
'#endif // (NTDDI_VERSION >= NTDDI_VISTA)
'//
'// Microsoft-specific IPv4 definitions.
'//
'#define IN4_CLASSA(i) (((LONG)(i) & 0x00000080) == 0)
'#define IN4_CLASSB(i) (((LONG)(i) & 0x000000c0) == 0x00000080)
'#define IN4_CLASSC(i) (((LONG)(i) & 0x000000e0) == 0x000000c0)
'#define IN4_CLASSD(i) (((LONG)(i) & 0x000000f0) == 0x000000e0)
'#define IN4_MULTICAST(i) IN4_CLASSD(i)
MACRO IN4_CLASSA(i) = (BIT&(i) AND &H00000080) = 0)
MACRO IN4_CLASSB(i) = (BIT&(i) AND &H000000c0) = &H00000080)
MACRO IN4_CLASSC(i) = (BIT&(i) AND &H000000e0) = &H000000c0)
MACRO IN4_CLASSD(i) = (BIT&(i) AND &H000000f0) = &H000000e0)
MACRO IN4_MULTICAST(i) = (BIT&(i) AND &H00000080) = 0)
%EQUATE `IN4ADDR_ANY = %INADDR_ANY
%EQUATE `IN4ADDR_LOOPBACK = &H0100007f
%EQUATE `IN4ADDR_BROADCAST = %INADDR_BROADCAST
%EQUATE `IN4ADDR_NONE = %INADDR_NONE
%EQUATE `IN4ADDR_ANY_INIT = 0
'#define IN4ADDR_LOOPBACK_INIT { 0x7f, 0, 0, 1 }
'#define IN4ADDR_BROADCAST_INIT { 0xff, 0xff, 0xff, 0xff }
'#define IN4ADDR_ALLNODESONLINK_INIT { 0xe0, 0, 0, 1 }
'#define IN4ADDR_ALLROUTERSONLINK_INIT { 0xe0, 0, 0, 2 }
'#define IN4ADDR_ALLIGMPV3ROUTERSONLINK_INIT { 0xe0, 0, 0, 0x16 }
'#define IN4ADDR_ALLTEREDONODESONLINK_INIT { 0xe0, 0, 0, 0xfd }
'#define IN4ADDR_LINKLOCALPREFIX_INIT { 0xa9, 0xfe, }
'#define IN4ADDR_MULTICASTPREFIX_INIT { 0xe0, }
$IN4ADDR_LOOPBACK_INIT = CHR$(&H7f, 0, 0, 1)
$IN4ADDR_BROADCAST_INIT = CHR$(&Hff, &Hff, &Hff, &Hff)
$IN4ADDR_ALLNODESONLINK_INIT = CHR$(&He0, 0, 0, 1)
$IN4ADDR_ALLROUTERSONLINK_INIT = CHR$(&He0, 0, 0, 2)
$IN4ADDR_ALLIGMPV3ROUTERSONLINK_INIT = CHR$(&He0, 0, 0, &H16)
$IN4ADDR_ALLTEREDONODESONLINK_INIT = CHR$(&He0, 0, 0, &Hfd)
$IN4ADDR_LINKLOCALPREFIX_INIT = CHR$(&Ha9, &Hfe, 0, 0)
$IN4ADDR_MULTICASTPREFIX_INIT = CHR$(&He0, 0, 0, 0)
%EQUATE `IN4ADDR_LOOPBACKPREFIX_LENGTH = 8
%EQUATE `IN4ADDR_LINKLOCALPREFIX_LENGTH = 16
%EQUATE `IN4ADDR_MULTICASTPREFIX_LENGTH = 4
'#if (NTDDI_VERSION >= NTDDI_WIN2KSP1)
'MSTCPIP_INLINE
'BOOLEAN
'IN4_ADDR_EQUAL(__in CONST IN_ADDR *a, __in CONST IN_ADDR *b)
'{
' return (BOOLEAN)(a->s_addr == b->s_addr);
'}
MACRO IN4_ADDR_EQUAL (a, b) = (a.s_addr = b.s_addr)
'MSTCPIP_INLINE
'BOOLEAN
'IN4_UNALIGNED_ADDR_EQUAL(__in CONST IN_ADDR UNALIGNED *a, __in CONST IN_ADDR UNALIGNED *b)
'{
' return (BOOLEAN)(a->s_addr == b->s_addr);
'}
MACRO IN4_UNALIGNED_ADDR_EQUAL (a, b) = (a.s_addr = b.s_addr)
'MSTCPIP_INLINE
'BOOLEAN
'IN4_IS_ADDR_UNSPECIFIED(__in CONST IN_ADDR *a)
'{
' return (BOOLEAN)(a->s_addr == IN4ADDR_ANY);
'}
MACRO IN4_IS_ADDR_UNSPECIFIED(a) = (a.s_addr = %IN4ADDR_ANY)
'MSTCPIP_INLINE
'BOOLEAN
'IN4_IS_UNALIGNED_ADDR_UNSPECIFIED(__in CONST IN_ADDR UNALIGNED *a)
'{
' return (BOOLEAN)(a->s_addr == IN4ADDR_ANY);
'}
MACRO IN4_IS_UNALIGNED_ADDR_UNSPECIFIED(a) = (a.s_addr = %IN4ADDR_ANY)
'MSTCPIP_INLINE
'BOOLEAN
'IN4_IS_ADDR_LOOPBACK(__in CONST IN_ADDR *a)
'{
' return (BOOLEAN)(*((PUCHAR) a) == 0x7f); // 127/8
'}
MACRO IN4_IS_ADDR_LOOPBACK(a) = CVBYT(a.S_un_b)
'MSTCPIP_INLINE
'BOOLEAN
'IN4_IS_UNALIGNED_ADDR_LOOPBACK(__in CONST IN_ADDR UNALIGNED *a)
'{
' return (BOOLEAN)(*((PUCHAR) a) == 0x7f); // 127/8
'}
MACRO IN4_IS_UNALIGNED_ADDR_LOOPBACK(a) = CVBYT(a.S_un_b)
'MSTCPIP_INLINE
'BOOLEAN
'IN4_IS_ADDR_BROADCAST(__in CONST IN_ADDR *a)
'{
' return (BOOLEAN)(a->s_addr == IN4ADDR_BROADCAST);
'}
MACRO IN4_IS_ADDR_BROADCAST(a) = (a.s_addr = %IN4ADDR_BROADCAST)
'MSTCPIP_INLINE
'BOOLEAN
'IN4_IS_UNALIGNED_ADDR_BROADCAST(__in CONST IN_ADDR UNALIGNED *a)
'{
' return (BOOLEAN)(a->s_addr == IN4ADDR_BROADCAST);
'}
MACRO IN4_IS_UNALIGNED_ADDR_BROADCAST(a) = (a.s_addr = %IN4ADDR_BROADCAST)
'MSTCPIP_INLINE
'BOOLEAN
'IN4_IS_ADDR_MULTICAST(__in CONST IN_ADDR *a)
'{
' return (BOOLEAN)IN4_MULTICAST(a->s_addr);
'}
MACRO IN4_IS_ADDR_MULTICAST(a) = IN4_MULTICAST(a.s_addr)
'MSTCPIP_INLINE
'BOOLEAN
'IN4_IS_UNALIGNED_ADDR_MULTICAST(__in CONST IN_ADDR UNALIGNED *a)
'{
' return (BOOLEAN)IN4_MULTICAST(a->s_addr);
'}
MACRO IN4_IS_UNALIGNED_ADDR_MULTICAST(a) = IN4_MULTICAST(a.s_addr)
'MSTCPIP_INLINE
'BOOLEAN
'IN4_IS_ADDR_LINKLOCAL(__in CONST IN_ADDR *a)
'{
' return (BOOLEAN)((a->s_addr & 0xffff) == 0xfea9); // 169.254/16
'}
MACRO IN4_IS_ADDR_LINKLOCAL(a) = ((a.s_addr AND &HFFFF) = &HFEA9)
'MSTCPIP_INLINE
'BOOLEAN
'IN4_IS_UNALIGNED_ADDR_LINKLOCAL(__in CONST IN_ADDR UNALIGNED *a)
'{
' return (BOOLEAN)((a->s_addr & 0xffff) == 0xfea9); // 169.254/16
'}
MACRO IN4_IS_UNALIGNED_ADDR_LINKLOCAL(a) = ((a.s_addr AND &HFFFF) = &HFEA9)
'MSTCPIP_INLINE
'BOOLEAN
'IN4_IS_ADDR_SITELOCAL(__in CONST IN_ADDR *a)
'{
' //
' // For existing scenarios (e.g. ICS) to work as expected, RFC-1918 prefixes
' // are deemed to be global scoped. When appropriate, site border routers
' // must explicitly filter packets with these addresses.
' //
' UNREFERENCED_PARAMETER(a);
' return FALSE;
'}
'#define IN4_IS_UNALIGNED_ADDR_SITELOCAL IN4_IS_ADDR_SITELOCAL
'MSTCPIP_INLINE
'BOOLEAN
'IN4_IS_ADDR_RFC1918(__in CONST IN_ADDR *a)
'{
' return (BOOLEAN)(((a->s_addr & 0x00ff) == 0x0a) || // 10/8
' ((a->s_addr & 0xf0ff) == 0x10ac) || // 172.16/12
' ((a->s_addr & 0xffff) == 0xa8c0)); // 192.168/16
'}
MACRO IN4_IS_ADDR_RFC1918(a) = )((a.s_addr AND &H00FF) = &H0a) OR ((a.s_addr AND &HF0FF) = &H10ac) OR ((a.s_addr AND &HFFFF) = &Ha8c0)))
'MSTCPIP_INLINE
'BOOLEAN
'IN4_IS_UNALIGNED_ADDR_RFC1918(__in CONST IN_ADDR UNALIGNED *a)
'{
' IN_ADDR Ipv4Address = *a;
' return IN4_IS_ADDR_RFC1918(&Ipv4Address);
'}
'MSTCPIP_INLINE
'BOOLEAN
'IN4_IS_ADDR_MC_LINKLOCAL(__in CONST IN_ADDR *a)
'{
' return (BOOLEAN)((a->s_addr & 0xffffff) == 0xe0); // 224.0.0/24
'}
MACRO IN4_IS_ADDR_MC_LINKLOCAL(a) = ((a.s_addr AND &Hffffff) = &He0)
'MSTCPIP_INLINE
'BOOLEAN
'IN4_IS_ADDR_MC_ADMINLOCAL(__in CONST IN_ADDR *a)
'{
' return (BOOLEAN)((a->s_addr & 0xffff) == 0xffef); // 239.255/16
'}
MACRO IN4_IS_ADDR_MC_ADMINLOCAL(a) = ((a.s_addr AND &Hffff) = &Hffef)
'MSTCPIP_INLINE
'BOOLEAN
'IN4_IS_ADDR_MC_SITELOCAL(__in CONST IN_ADDR *a)
'{
' return (BOOLEAN)((a->s_addr & 0xff) == 0xef) &&
' !IN4_IS_ADDR_MC_ADMINLOCAL(a);
'}
MACRO IN4_IS_ADDR_MC_SITELOCAL(a) = ((a.s_addr AND &Hff) = &Hef) AND NOT IN4_IS_ADDR_MC_ADMINLOCAL(a))
'MSTCPIP_INLINE
'IN4ADDR_SETSOCKADDR(__out PSOCKADDR_IN a, __in CONST IN_ADDR *addr, __in USHORT port)
'{
' a->sin_family = AF_INET;
' a->sin_port = port;
' a->sin_addr = *addr;
' memset(a->sin_zero, 0, sizeof(a->sin_zero));
'}
MACRO IN4ADDR_SETSOCKADDR(a, xaddr, xport)
 a.sin_family = %AF_INET
 a.sin_port = xport
 a.sin_addr = xaddr
 a.sin_zero = CHR$(0,0,0,0,0,0,0,0)
END MACRO
'MSTCPIP_INLINE
'IN4ADDR_SETANY(__out PSOCKADDR_IN a)
'{
' a->sin_family = AF_INET;
' a->sin_port = 0;
' a->sin_addr.s_addr = IN4ADDR_ANY;
' memset(a->sin_zero, 0, sizeof(a->sin_zero));
'}
MACRO IN4ADDR_SETANY(a)
 a.sin_family = %AF_INET
 a.sin_port = 0
 a.sin_addr.s_addr = %IN4ADDR_ANY
 a.sin_zero = CHR$(0,0,0,0,0,0,0,0)
END MACRO
'MSTCPIP_INLINE
'IN4ADDR_SETLOOPBACK(__out PSOCKADDR_IN a)
'{
' a->sin_family = AF_INET;
' a->sin_port = 0;
' a->sin_addr.s_addr = IN4ADDR_LOOPBACK;
' memset(a->sin_zero, 0, sizeof(a->sin_zero));
'}
MACRO IN4ADDR_SETLOOPBACK(a)
 a.sin_family = %AF_INET
 a.sin_port = 0
 a.sin_addr.s_addr = %IN4ADDR_LOOPBACK
 a.sin_zero = CHR$(0,0,0,0,0,0,0,0)
END MACRO
'MSTCPIP_INLINE
'BOOLEAN
'IN4ADDR_ISANY(__in CONST SOCKADDR_IN *a)
'{
' ASSERT(a->sin_family == AF_INET);
' return IN4_IS_ADDR_UNSPECIFIED(&a->sin_addr);
'}
FUNCTION IN4ADDR_ISANY(BYREF a AS SOCKADDR_IN) AS LONG
 IF a.sin_family = %AF_INET THEN FUNCTION = IN4_IS_ADDR_UNSPECIFIED(a.sin_addr)
END FUNCTION
'MSTCPIP_INLINE
'BOOLEAN
'IN4ADDR_ISLOOPBACK(__in CONST SOCKADDR_IN *a)
'{
' ASSERT(a->sin_family == AF_INET);
' return IN4_IS_ADDR_LOOPBACK(&a->sin_addr);
'}
FUNCTION IN4ADDR_ISLOOPBACK(BYREF a AS SOCKADDR_IN) AS LONG
 IF a.sin_family = %AF_INET THEN FUNCTION = IN4_IS_ADDR_LOOPBACK(a.sin_addr)
END FUNCTION
'MSTCPIP_INLINE
'SCOPE_ID
'IN4ADDR_SCOPE_ID(__in CONST SOCKADDR_IN *a)
'{
' SCOPE_ID UnspecifiedScopeId = {0};
' UNREFERENCED_PARAMETER(a);
' return UnspecifiedScopeId;
'}
'MSTCPIP_INLINE
'BOOLEAN
'IN4ADDR_ISEQUAL(__in CONST SOCKADDR_IN *a, __in CONST SOCKADDR_IN *b)
'{
' ASSERT(a->sin_family == AF_INET);
' return (BOOLEAN)(IN4ADDR_SCOPE_ID(a).Value == IN4ADDR_SCOPE_ID(b).Value &&
' IN4_ADDR_EQUAL(&a->sin_addr, &b->sin_addr));
'}
'MSTCPIP_INLINE
'BOOLEAN
'IN4ADDR_ISUNSPECIFIED(__in CONST SOCKADDR_IN *a)
'{
' ASSERT(a->sin_family == AF_INET);
' return (BOOLEAN)(IN4ADDR_SCOPE_ID(a).Value == 0 &&
' IN4_IS_ADDR_UNSPECIFIED(&a->sin_addr));
'}
'#define INET_IS_ALIGNED(Pointer, Type) \
' (((ULONG_PTR)Pointer & (__builtin_alignof(Type)-1)) == 0)
'MSTCPIP_INLINE
'SCOPE_LEVEL
'Ipv4UnicastAddressScope(
' IN CONST UCHAR *Address
' )
'/*++
'Routine Description:
' Determines the scope of an IPv4 unicast address.
' For existing scenarios (e.g. ICS) to work as expected, RFC-1918 prefixes
' are deemed to be global scoped. When appropriate, site border routers
' must explicitly filter packets with these addresses.
'Arguments:
' Address - Supplies the IPv4 unicast address.
'Return Value:
' Returns the scope level of the address.
'Caller IRQL:
' May be called at PASSIVE through DISPATCH level.
'--*/
'{
' IN_ADDR Ipv4Address;
' if (!INET_IS_ALIGNED(Address, IN_ADDR)) {
' Ipv4Address = *(CONST IN_ADDR UNALIGNED *)Address;
' Address = (CONST UCHAR *) &Ipv4Address;
' }
' if (IN4_IS_ADDR_LINKLOCAL((PIN_ADDR) Address) ||
' IN4_IS_ADDR_LOOPBACK((PIN_ADDR) Address)) {
' return ScopeLevelLink;
' }
' return ScopeLevelGlobal;
'}
'MSTCPIP_INLINE
'SCOPE_LEVEL
'Ipv4MulticastAddressScope(
' )
'/*++
'Routine Description:
' Determines the scope of an IPv4 multicast address.
' See RFC 2365.
'Arguments:
' Address - Supplies the IPv4 multicast address.
'Return Value:
' Returns the scope level of the multicast address.
'Caller IRQL:
' May be called at PASSIVE through DISPATCH level.
'--*/
'{
' IN_ADDR Ipv4Address;
' if (!INET_IS_ALIGNED(Address, IN_ADDR)) {
' Ipv4Address = *(CONST IN_ADDR UNALIGNED *)Address;
' Address = (CONST UCHAR *) &Ipv4Address;
' }
' if (IN4_IS_ADDR_MC_LINKLOCAL((PIN_ADDR) Address)) {
' return ScopeLevelLink;
' } else if (IN4_IS_ADDR_MC_ADMINLOCAL((PIN_ADDR) Address)) {
' return ScopeLevelAdmin;
' } else if (IN4_IS_ADDR_MC_SITELOCAL((PIN_ADDR) Address)) {
' return ScopeLevelSite;
' } else {
' return ScopeLevelGlobal;
' }
'}
'MSTCPIP_INLINE
'SCOPE_LEVEL
'Ipv4AddressScope(
' )
'/*++
'Routine Description:
' Examines an IPv4 address and determines its scope.
'Arguments:
' Address - Supplies the address to test.
'Return Value:
' Returns the scope level of the address.
'Caller IRQL:
' May be called at PASSIVE through DISPATCH level.
'--*/
'{
' IN CONST IN_ADDR Ipv4Address = *(CONST IN_ADDR UNALIGNED *)Address;
' if (IN4_IS_ADDR_BROADCAST(&Ipv4Address)) {
' return ScopeLevelLink;
' } else if (IN4_IS_ADDR_MULTICAST(&Ipv4Address)) {
' return Ipv4MulticastAddressScope((UCHAR *) &Ipv4Address);
' } else {
' return Ipv4UnicastAddressScope((UCHAR *) &Ipv4Address);
' }
'}
'MSTCPIP_INLINE
'NL_ADDRESS_TYPE
'Ipv4AddressType(
' )
'{
' IN_ADDR Ipv4Address = *(CONST IN_ADDR UNALIGNED *) Address;
' if (IN4_IS_ADDR_MULTICAST(&Ipv4Address)) {
' return NlatMulticast;
' }
' if (IN4_IS_ADDR_BROADCAST(&Ipv4Address)) {
' return NlatBroadcast;
' }
' if (IN4_IS_ADDR_UNSPECIFIED(&Ipv4Address)) {
' return NlatUnspecified;
' }
' if (((Ipv4Address.s_addr & 0x000000ff) == 0) ||
' ((Ipv4Address.s_addr & 0x000000f0) == 240)) {
' //
' // Following prefixes are invalid:
' // 1. 0.0.0.0/8 (except 0.0.0.0/32).
' // 2. 240.0.0.0/4 (except 255.255.255.255/32).
' //
' return NlatInvalid;
' }
' //
' // Loopback and anycast addresses are treated as unicast.
' //
' return NlatUnicast;
'}
'MSTCPIP_INLINE
'IN4_UNCANONICALIZE_SCOPE_ID(
' )
'{
' SCOPE_LEVEL ScopeLevel = Ipv4AddressScope((CONST UCHAR *)Address);
' if ((IN4_IS_ADDR_LOOPBACK(Address)) || (ScopeLevel == ScopeLevelGlobal)) {
' ScopeId->Value = 0;
' }
' if ((SCOPE_LEVEL)ScopeId->Level == ScopeLevel) {
' ScopeId->Level = 0;
' }
'}
'MSTCPIP_INLINE
'BOOLEAN
'IN4_IS_ADDR_6TO4ELIGIBLE(__in CONST IN_ADDR *a)
'{
' return (BOOLEAN)((Ipv4AddressType((CONST UCHAR *) a) == NlatUnicast) &&
' !(IN4_IS_ADDR_LOOPBACK(a) ||
' IN4_IS_ADDR_LINKLOCAL(a) ||
' IN4_IS_ADDR_SITELOCAL(a) ||
' IN4_IS_ADDR_RFC1918(a)));
'}
'MSTCPIP_INLINE
'BOOLEAN
'IN4_IS_UNALIGNED_ADDR_6TO4ELIGIBLE(__in CONST IN_ADDR UNALIGNED *a)
'{
' IN_ADDR Ipv4Address = *a;
' return IN4_IS_ADDR_6TO4ELIGIBLE(&Ipv4Address);
'}
'#endif // _WS2DEF_
'//
'// Microsoft-specific IPv6 definitions.
'//
'#ifdef _WS2IPDEF_
'MSTCPIP_INLINE
'BOOLEAN
'IN6_PREFIX_EQUAL(__in CONST IN6_ADDR *a, __in CONST IN6_ADDR *b, __in UINT8 len)
'{
' UINT8 Bytes = len / 8;
' UINT8 Bits = len % 8;
' UINT8 Mask = 0xff << (8 - Bits);
' ASSERT(len <= (sizeof(IN6_ADDR) * 8));
' return (BOOLEAN)
' (((memcmp(a, b, Bytes)) == 0) &&
' ((Bits == 0) ||
' ((a->s6_bytes[Bytes] | Mask) == (b->s6_bytes[Bytes] | Mask))));
'}
'MSTCPIP_INLINE
'BOOLEAN
'IN6_IS_ADDR_ALLNODESONNODE(__in CONST IN6_ADDR *a)
'{
' return IN6_ADDR_EQUAL(a, &in6addr_allnodesonnode);
'}
'MSTCPIP_INLINE
'BOOLEAN
'IN6_IS_ADDR_ALLNODESONLINK(__in CONST IN6_ADDR *a)
'{
' return IN6_ADDR_EQUAL(a, &in6addr_allnodesonlink);
'}
'MSTCPIP_INLINE
'BOOLEAN
'IN6_IS_ADDR_ALLROUTERSONLINK(__in CONST IN6_ADDR *a)
'{
' return IN6_ADDR_EQUAL(a, &in6addr_allroutersonlink);
'}
'MSTCPIP_INLINE
'BOOLEAN
'IN6_IS_ADDR_SOLICITEDNODE(__in CONST IN6_ADDR *a)
'{
' return
' IN6_PREFIX_EQUAL(
' a,
' &in6addr_solicitednodemulticastprefix,
' IN6ADDR_SOLICITEDNODEMULTICASTPREFIX_LENGTH);
'}
'MSTCPIP_INLINE
'BOOLEAN
'IN6_IS_ADDR_ISATAP(__in CONST IN6_ADDR *a)
'{
' //
' // Disregard the u/g bit and compare the first byte of the interface id.
' //
' return (BOOLEAN)(((a->s6_words[4] & 0xfffd) == 0x0000) &&
' (a->s6_words[5] == 0xfe5e));
'}
FUNCTION IN6_IS_ADDR_ISATAP(BYREF a AS IN6_ADDR) AS LONG
 FUNCTION = ((a.word(4) AND &Hfffd) = &H0000) AND (a.word(5) = &Hfe5e)
END FUNCTION
'MSTCPIP_INLINE
'BOOLEAN
'IN6_IS_ADDR_6TO4(__in CONST IN6_ADDR *a)
'{
' C_ASSERT(IN6ADDR_6TO4PREFIX_LENGTH == RTL_BITS_OF(USHORT));
' return (BOOLEAN)(a->s6_words[0] == in6addr_6to4prefix.s6_words[0]);
'}
'MSTCPIP_INLINE
'BOOLEAN
'IN6_IS_ADDR_TEREDO(__in CONST IN6_ADDR *a)
'{
' C_ASSERT(IN6ADDR_TEREDOPREFIX_LENGTH == 2 * RTL_BITS_OF(USHORT));
' return (BOOLEAN)
' (((a->s6_words[0] == in6addr_teredoprefix.s6_words[0]) &&
' (a->s6_words[1] == in6addr_teredoprefix.s6_words[1])) ||
' ((a->s6_words[0] == in6addr_teredoprefix_old.s6_words[0]) &&
' (a->s6_words[1] == in6addr_teredoprefix_old.s6_words[1])));
'}
'MSTCPIP_INLINE
'BOOLEAN
'IN6ADDR_ISV4MAPPED(__in CONST SOCKADDR_IN6 *a)
'{
' ASSERT(a->sin6_family == AF_INET6);
' return IN6_IS_ADDR_V4MAPPED(&a->sin6_addr);
'}
'MSTCPIP_INLINE
'BOOLEAN
'IN6ADDR_ISISATAP(__in CONST SOCKADDR_IN6 *a)
'{
' ASSERT(a->sin6_family == AF_INET6);
' return IN6_IS_ADDR_ISATAP(&a->sin6_addr);
'}
FUNCTION IN6ADDR_ISISATAP (BYREF a AS SOCKADDR_IN6) AS LONG
 IF a.sin6_family = %AF_INET6 THEN FUNCTION = IN6_IS_ADDR_ISATAP(a.sin6_addr)
END FUNCTION
'MSTCPIP_INLINE
'BOOLEAN
'IN6ADDR_IS6TO4(__in CONST SOCKADDR_IN6 *a)
'{
' ASSERT(a->sin6_family == AF_INET6);
' return IN6_IS_ADDR_6TO4(&a->sin6_addr);
'}
'MSTCPIP_INLINE
'BOOLEAN
'IN6ADDR_ISTEREDO(__in CONST SOCKADDR_IN6 *a)
'{
' ASSERT(a->sin6_family == AF_INET6);
' return IN6_IS_ADDR_TEREDO(&a->sin6_addr);
'}
'MSTCPIP_INLINE
'CONST UCHAR*
'IN6_GET_ADDR_V4MAPPED(__in CONST IN6_ADDR *Ipv6Address)
'{
' return (CONST UCHAR *) (Ipv6Address->s6_words + 6);
'}
'MSTCPIP_INLINE
'CONST UCHAR*
'IN6_GET_ADDR_V4COMPAT(__in CONST IN6_ADDR *Ipv6Address)
'{
' return (CONST UCHAR *) (Ipv6Address->s6_words + 6);
'}
'MSTCPIP_INLINE
'CONST UCHAR*
'IN6_EXTRACT_V4ADDR_FROM_ISATAP(__in CONST IN6_ADDR *Ipv6Address)
'{
' return (CONST UCHAR *) (Ipv6Address->s6_words + 6);
'}
'MSTCPIP_INLINE
'CONST UCHAR*
'IN6_EXTRACT_V4ADDR_FROM_6TO4(__in CONST IN6_ADDR *Ipv6Address)
'{
' return (CONST UCHAR *) (Ipv6Address->s6_words + 1);
'}
'MSTCPIP_INLINE
'IN6_SET_ADDR_V4MAPPED(__out PIN6_ADDR a6, __in CONST IN_ADDR* a4)
'{
' *a6 = in6addr_v4mappedprefix;
' a6->s6_bytes[12] = ((CONST UCHAR *) a4)[0];
' a6->s6_bytes[13] = ((CONST UCHAR *) a4)[1];
' a6->s6_bytes[14] = ((CONST UCHAR *) a4)[2];
' a6->s6_bytes[15] = ((CONST UCHAR *) a4)[3];
'}
'MSTCPIP_INLINE
'IN6_SET_ADDR_V4COMPAT(__out PIN6_ADDR a6, __in CONST IN_ADDR* a4)
'{
' *a6 = in6addr_any;
' a6->s6_bytes[12] = ((CONST UCHAR *) a4)[0];
' a6->s6_bytes[13] = ((CONST UCHAR *) a4)[1];
' a6->s6_bytes[14] = ((CONST UCHAR *) a4)[2];
' a6->s6_bytes[15] = ((CONST UCHAR *) a4)[3];
'}
'MSTCPIP_INLINE
'IN6_SET_ADDR_SOLICITEDNODE(__out PIN6_ADDR Multicast, __in CONST IN6_ADDR *Unicast)
'{
' *Multicast = in6addr_solicitednodemulticastprefix;
' Multicast->s6_bytes[13] = Unicast->s6_bytes[13];
' Multicast->s6_bytes[14] = Unicast->s6_bytes[14];
' Multicast->s6_bytes[15] = Unicast->s6_bytes[15];
'}
'MSTCPIP_INLINE
'IN6_SET_ISATAP_IDENTIFIER(__inout IN6_ADDR *Ipv6Address, __in CONST IN_ADDR *Ipv4Address)
'{
' if (IN4_IS_ADDR_6TO4ELIGIBLE(Ipv4Address)) {
' Ipv6Address->s6_words[4] = 0x0002;
' } else {
' Ipv6Address->s6_words[4] = 0x0000;
' }
' //
' // 24-bit IANA OUI 00-00-5E and the 8-bit hex value 0xFE.
' // See section 6.1 of RFC 4214.
' //
' Ipv6Address->s6_words[5] = 0xFE5E;
' *((UNALIGNED IN_ADDR *) (Ipv6Address->s6_words + 6)) = *Ipv4Address;
'}
'MSTCPIP_INLINE
'IN6_SET_6TO4_PREFIX(__inout IN6_ADDR *Ipv6Address, __in CONST IN_ADDR *Ipv4Address)
'{
' Ipv6Address->s6_words[0] = 0x0220;
' *((UNALIGNED IN_ADDR *) (Ipv6Address->s6_words + 1)) = *Ipv4Address;
' Ipv6Address->s6_words[3] = 0x0000;
'}
'MSTCPIP_INLINE
'SCOPE_LEVEL
'Ipv6UnicastAddressScope(
' )
'/*++
'Routine Description:
' Examines a unicast address and determines its scope.
' Note that v4-compatible and 6to4 addresses are deemed to have global scope;
' it is not legal to derive them from non IN4_IS_ADDR_6TO4ELIGIBLE addresses
' (IPv4 loopback, link-local, site-local, and RFC-1918 addresses).
'Arguments:
' Address - Supplies an IPv6 unicast address.
'Return Value:
' Returns the scope level of the address.
'Caller IRQL:
' May be called at PASSIVE through DISPATCH level.
'--*/
'{
' IN6_ADDR Ipv6Address;
' if (!INET_IS_ALIGNED(Address, IN6_ADDR)) {
' Ipv6Address = *(CONST IN6_ADDR UNALIGNED *)Address;
' Address = (CONST UCHAR *) &Ipv6Address;
' }
' if (IN6_IS_ADDR_LINKLOCAL((PIN6_ADDR) Address) ||
' IN6_IS_ADDR_LOOPBACK((PIN6_ADDR) Address)) {
' return ScopeLevelLink;
' } else if (IN6_IS_ADDR_SITELOCAL((PIN6_ADDR) Address)) {
' return ScopeLevelSite;
' } else {
' return ScopeLevelGlobal;
' }
'}
'MSTCPIP_INLINE
'SCOPE_LEVEL
'IN6_MULTICAST_SCOPE(
' )
'{
' PIN6_ADDR Ipv6Address = (PIN6_ADDR) Address;
' return (SCOPE_LEVEL)(Ipv6Address->s6_bytes[1] & 0xf);
'}
'MSTCPIP_INLINE
'SCOPE_LEVEL
'Ipv6AddressScope(
' )
'/*++
'Routine Description:
' Examines an IPv6 address and determines its scope.
'Arguments:
' Address - Supplies an IPv6 address.
'Return Value:
' Returns the scope level of the address.
'Caller IRQL:
' May be called at PASSIVE through DISPATCH level.
'--*/
'{
' if (IN6_IS_ADDR_MULTICAST((CONST IN6_ADDR *) Address)) {
' return IN6_MULTICAST_SCOPE(Address);
' } else {
' return Ipv6UnicastAddressScope(Address);
' }
'}
'MSTCPIP_INLINE
'NL_ADDRESS_TYPE
'Ipv6AddressType(
' )
'{
' CONST IN6_ADDR *Ipv6Address = (CONST IN6_ADDR *) Address;
' CONST UCHAR *Ipv4Address;
' if (IN6_IS_ADDR_MULTICAST(Ipv6Address)) {
' return NlatMulticast;
' }
' if (IN6_IS_ADDR_UNSPECIFIED(Ipv6Address)) {
' return NlatUnspecified;
' }
' //
' // Extract embedded IPv4 address, if any.
' //
' if (IN6_IS_ADDR_ISATAP(Ipv6Address) ||
' IN6_IS_ADDR_V4COMPAT(Ipv6Address) ||
' IN6_IS_ADDR_V4MAPPED(Ipv6Address) ||
' IN6_IS_ADDR_V4TRANSLATED(Ipv6Address)) {
' Ipv4Address = IN6_EXTRACT_V4ADDR_FROM_ISATAP(Ipv6Address);
' } else if (IN6_IS_ADDR_6TO4(Ipv6Address)) {
' Ipv4Address = IN6_EXTRACT_V4ADDR_FROM_6TO4(Ipv6Address);
' } else {
' //
' // Anycast and loopback addresses are treated unicast address.
' //
' return NlatUnicast;
' }
' //
' // Ensure that the embedded IPv4 address is unicast.
' //
' if (Ipv4AddressType(Ipv4Address) != NlatUnicast) {
' return NlatInvalid;
' }
' return NlatUnicast;
'}
'MSTCPIP_INLINE
'IN6_UNCANONICALIZE_SCOPE_ID(
' )
'{
' SCOPE_LEVEL ScopeLevel = Ipv6AddressScope((CONST UCHAR *)Address);
' if ((IN6_IS_ADDR_LOOPBACK(Address)) || (ScopeLevel == ScopeLevelGlobal)) {
' ScopeId->Value = 0;
' }
' if ((SCOPE_LEVEL)ScopeId->Level == ScopeLevel) {
' ScopeId->Level = 0;
' }
'}
'#if (NTDDI_VERSION >= NTDDI_VISTA)
'MSTCPIP_INLINE
'IN6ADDR_SETSOCKADDR(__out PSOCKADDR_IN6 a, __in CONST IN6_ADDR *addr, __in SCOPE_ID scope,
'{
' a->sin6_family = AF_INET6;
' a->sin6_port = port;
' a->sin6_flowinfo = 0;
' RtlCopyMemory(&a->sin6_addr, addr, sizeof(IN6_ADDR));
' a->sin6_scope_struct = scope;
' IN6_UNCANONICALIZE_SCOPE_ID(&a->sin6_addr, &a->sin6_scope_struct);
'}
'MSTCPIP_INLINE
'IN6ADDR_SETV4MAPPED(__out PSOCKADDR_IN6 a6, __in CONST IN_ADDR* a4, __in SCOPE_ID scope,
'{
' a6->sin6_family = AF_INET6;
' a6->sin6_port = port;
' a6->sin6_flowinfo = 0;
' IN6_SET_ADDR_V4MAPPED(&a6->sin6_addr, a4);
' a6->sin6_scope_struct = scope;
' IN4_UNCANONICALIZE_SCOPE_ID(a4, &a6->sin6_scope_struct);
'}
'#endif
'//
'// Define address-family-independent routines.
'//
'MSTCPIP_INLINE
'BOOLEAN
'INET_ADDR_EQUAL(__in ADDRESS_FAMILY af, __in CONST VOID* a, __in CONST VOID* b)
'{
' if (af == AF_INET6) {
' return IN6_ADDR_EQUAL((CONST IN6_ADDR*)a, (CONST IN6_ADDR*)b);
' } else {
' ASSERT(af == AF_INET);
' return IN4_ADDR_EQUAL((CONST IN_ADDR*)a, (CONST IN_ADDR*)b);
' }
'}
'MSTCPIP_INLINE
'BOOLEAN
'INET_UNALIGNED_ADDR_EQUAL(__in ADDRESS_FAMILY af, __in CONST VOID* a, __in CONST VOID* b)
'{
' if (af == AF_INET6) {
' return IN6_ADDR_EQUAL((CONST IN6_ADDR*)a, (CONST IN6_ADDR*)b);
' } else {
' ASSERT(af == AF_INET);
' return IN4_UNALIGNED_ADDR_EQUAL((CONST IN_ADDR*)a, (CONST IN_ADDR*)b);
' }
'}
'MSTCPIP_INLINE
'BOOLEAN
'INET_IS_ADDR_UNSPECIFIED(__in ADDRESS_FAMILY af, __in CONST VOID* a)
'{
' if (af == AF_INET6) {
' return IN6_IS_ADDR_UNSPECIFIED((CONST IN6_ADDR*)a);
' } else {
' ASSERT(af == AF_INET);
' return IN4_IS_ADDR_UNSPECIFIED((CONST IN_ADDR*)a);
' }
'}
'MSTCPIP_INLINE
'BOOLEAN
'INET_IS_UNALIGNED_ADDR_UNSPECIFIED(__in ADDRESS_FAMILY af, __in CONST VOID* a)
'{
' if (af == AF_INET6) {
' return IN6_IS_ADDR_UNSPECIFIED((CONST IN6_ADDR*)a);
' } else {
' ASSERT(af == AF_INET);
' return IN4_IS_UNALIGNED_ADDR_UNSPECIFIED((CONST IN_ADDR UNALIGNED*)a);
' }
'}
'MSTCPIP_INLINE
'BOOLEAN
'INET_IS_ADDR_LOOPBACK(__in ADDRESS_FAMILY af, __in CONST VOID* a)
'{
' if (af == AF_INET6) {
' return IN6_IS_ADDR_LOOPBACK((CONST IN6_ADDR*)a);
' } else {
' ASSERT(af == AF_INET);
' return IN4_IS_ADDR_LOOPBACK((CONST IN_ADDR*)a);
' }
'}
'MSTCPIP_INLINE
'BOOLEAN
'INET_IS_ADDR_BROADCAST(__in ADDRESS_FAMILY af, __in CONST VOID* a)
'{
' if (af == AF_INET6) {
' return FALSE;
' } else {
' ASSERT(af == AF_INET);
' return IN4_IS_ADDR_BROADCAST((CONST IN_ADDR*)a);
' }
'}
'MSTCPIP_INLINE
'BOOLEAN
'INET_IS_ADDR_MULTICAST(__in ADDRESS_FAMILY af, __in CONST VOID* a)
'{
' if (af == AF_INET6) {
' return IN6_IS_ADDR_MULTICAST((CONST IN6_ADDR*)a);
' } else {
' ASSERT(af == AF_INET);
' return IN4_IS_ADDR_MULTICAST((CONST IN_ADDR*)a);
' }
'}
'MSTCPIP_INLINE
'CONST UCHAR*
'INET_ADDR_UNSPECIFIED(__in ADDRESS_FAMILY af)
'{
' if (af == AF_INET6) {
' return (CONST UCHAR*)&in6addr_any;
' } else {
' ASSERT(af == AF_INET);
' return (CONST UCHAR*)&in4addr_any;
' }
'}
'MSTCPIP_INLINE
'INET_SET_ADDRESS(__in ADDRESS_FAMILY Family, __out PUCHAR Address, __in CONST UCHAR *Value)
'{
' if (Family == AF_INET6) {
' *((PIN6_ADDR)Address) = *((PIN6_ADDR)Value);
' } else {
' ASSERT(Family == AF_INET);
' *((PIN_ADDR)Address) = *((PIN_ADDR)Value);
' }
'}
'MSTCPIP_INLINE
'SIZE_T
'INET_ADDR_LENGTH(__in ADDRESS_FAMILY af)
'{
' if (af == AF_INET6) {
' return sizeof(IN6_ADDR);
' } else {
' ASSERT(af == AF_INET);
' return sizeof(IN_ADDR);
' }
'}
'MSTCPIP_INLINE
'SIZE_T
'INET_SOCKADDR_LENGTH(__in ADDRESS_FAMILY af)
'{
' if (af == AF_INET6) {
' return sizeof(SOCKADDR_IN6);
' } else {
' ASSERT(af == AF_INET);
' return sizeof(SOCKADDR_IN);
' }
'}
'#if (NTDDI_VERSION >= NTDDI_VISTA)
'MSTCPIP_INLINE
'INETADDR_SETSOCKADDR(__in ADDRESS_FAMILY af, __out PSOCKADDR a, __in CONST VOID* addr,
'{
' if (af == AF_INET6) {
' IN6ADDR_SETSOCKADDR(
' (PSOCKADDR_IN6) a, (CONST IN6_ADDR *) addr, scope, port);
' } else {
' CONST IN_ADDR addr4 = *((IN_ADDR UNALIGNED *) addr);
' ASSERT(af == AF_INET);
' IN4ADDR_SETSOCKADDR(
' (PSOCKADDR_IN) a, (CONST IN_ADDR *) &addr4, port);
' }
'}
'#endif // (NTDDI_VERSION >= NTDDI_VISTA)
'MSTCPIP_INLINE
'INETADDR_SETANY(__out PSOCKADDR a)
'{
' if (a->sa_family == AF_INET6) {
' IN6ADDR_SETANY((PSOCKADDR_IN6)a);
' } else {
' ASSERT(a->sa_family == AF_INET);
' IN4ADDR_SETANY((PSOCKADDR_IN)a);
' }
'}
'MSTCPIP_INLINE
'INETADDR_SETLOOPBACK(__out PSOCKADDR a)
'{
' if (a->sa_family == AF_INET6) {
' IN6ADDR_SETLOOPBACK((PSOCKADDR_IN6)a);
' } else {
' ASSERT(a->sa_family == AF_INET);
' IN4ADDR_SETLOOPBACK((PSOCKADDR_IN)a);
' }
'}
'MSTCPIP_INLINE
'BOOLEAN
'INETADDR_ISANY(__in CONST SOCKADDR *a)
'{
' if (a->sa_family == AF_INET6) {
' return IN6ADDR_ISANY((CONST SOCKADDR_IN6*)a);
' } else {
' ASSERT(a->sa_family == AF_INET);
' return IN4ADDR_ISANY((CONST SOCKADDR_IN*)a);
' }
'}
'MSTCPIP_INLINE
'BOOLEAN
'INETADDR_ISLOOPBACK(__in CONST SOCKADDR *a)
'{
' if (a->sa_family == AF_INET6) {
' return IN6ADDR_ISLOOPBACK((CONST SOCKADDR_IN6*)a);
' } else {
' ASSERT(a->sa_family == AF_INET);
' return IN4ADDR_ISLOOPBACK((CONST SOCKADDR_IN*)a);
' }
'}
'MSTCPIP_INLINE
'BOOLEAN
'INETADDR_ISV4MAPPED(__in CONST SOCKADDR *a)
'{
' if (a->sa_family == AF_INET6) {
' return IN6ADDR_ISV4MAPPED((CONST SOCKADDR_IN6*)a);
' } else {
' return FALSE;
' }
'}
'MSTCPIP_INLINE
'BOOLEAN
'NL_ADDR_EQUAL(
' )
'{
' return (BOOLEAN)((sa.Value == sb.Value) && INET_ADDR_EQUAL(af, aa, ab));
'}
'MSTCPIP_INLINE
'BOOLEAN
'NL_IS_ADDR_UNSPECIFIED(
' )
'{
' return (BOOLEAN)((s.Value == 0) && INET_IS_ADDR_UNSPECIFIED(af, a));
'}
'MSTCPIP_INLINE
'BOOLEAN
'INETADDR_ISEQUAL(__in CONST SOCKADDR *a, __in CONST SOCKADDR *b)
'{
' if (a->sa_family == AF_INET6) {
' return (BOOLEAN)
' (b->sa_family == AF_INET6 &&
' IN6ADDR_ISEQUAL((CONST SOCKADDR_IN6*)a, (CONST SOCKADDR_IN6*)b));
' } else {
' ASSERT(a->sa_family == AF_INET);
' return (BOOLEAN)
' (b->sa_family == AF_INET &&
' IN4ADDR_ISEQUAL((CONST SOCKADDR_IN*)a, (CONST SOCKADDR_IN*)b));
' }
'}
'MSTCPIP_INLINE
'BOOLEAN
'INETADDR_ISUNSPECIFIED(__in CONST SOCKADDR *a)
'{
' if (a->sa_family == AF_INET6) {
' return IN6ADDR_ISUNSPECIFIED((CONST SOCKADDR_IN6*)a);
' } else {
' ASSERT(a->sa_family == AF_INET);
' return IN4ADDR_ISUNSPECIFIED((CONST SOCKADDR_IN*)a);
' }
'}
'#if (NTDDI_VERSION >= NTDDI_VISTA)
'MSTCPIP_INLINE
'SCOPE_ID
'INETADDR_SCOPE_ID(__in CONST SOCKADDR *a)
'{
' if (a->sa_family == AF_INET6) {
' return ((CONST SOCKADDR_IN6*)a)->sin6_scope_struct;
' } else {
' ASSERT(a->sa_family == AF_INET);
' return IN4ADDR_SCOPE_ID((CONST SOCKADDR_IN*)a);
' }
'}
'#endif
'MSTCPIP_INLINE
'USHORT
'INETADDR_PORT(__in CONST SOCKADDR *a)
'{
' if (a->sa_family == AF_INET6) {
' return ((CONST SOCKADDR_IN6*)a)->sin6_port;
' } else {
' ASSERT(a->sa_family == AF_INET);
' return ((CONST SOCKADDR_IN*)a)->sin_port;
' }
'}
'MSTCPIP_INLINE
'INETADDR_ADDRESS(__in CONST SOCKADDR* a)
'{
' if (a->sa_family == AF_INET6) {
' return (PUCHAR)&((PSOCKADDR_IN6)a)->sin6_addr;
' } else {
' ASSERT(a->sa_family == AF_INET);
' return (PUCHAR)&((PSOCKADDR_IN)a)->sin_addr;
' }
'}
'MSTCPIP_INLINE
'INETADDR_SET_PORT(__inout PSOCKADDR a, __in USHORT Port)
'{
' SS_PORT(a) = Port;
'}
'MSTCPIP_INLINE
'INETADDR_SET_ADDRESS(__inout PSOCKADDR a, __in CONST UCHAR *Address)
'{
' if (a->sa_family == AF_INET6) {
' ((PSOCKADDR_IN6)a)->sin6_addr = *((CONST IN6_ADDR*)Address);
' } else {
' ASSERT(a->sa_family == AF_INET);
' ((PSOCKADDR_IN)a)->sin_addr = *((CONST IN_ADDR*)Address);
' }
'}
'MSTCPIP_INLINE
'INET_UNCANONICALIZE_SCOPE_ID(
' )
'{
' if (AddressFamily == AF_INET6) {
' IN6_UNCANONICALIZE_SCOPE_ID((CONST IN6_ADDR*) Address, ScopeId);
' } else {
' IN4_UNCANONICALIZE_SCOPE_ID((CONST IN_ADDR*) Address, ScopeId);
' }
'}
'#endif // _WS2IPDEF_
'#endif // (NTDDI_VERSION >= NTDDI_WIN2KSP1)
'#ifndef __IP2STRING__
'#define __IP2STRING__
'#if (NTDDI_VERSION >= NTDDI_VISTA)
'//
'// Some simple Rtl routines for IP address <-> string literal conversion
'//
'#ifdef _WS2DEF_
DECLARE FUNCTION RtlIpv4AddressToStringA LIB "ntdll.dll" ALIAS "RtlIpv4AddressToStringA" ( BYREF Addr AS in_addr , BYREF S AS ASCIIZ ) AS QUAD
DECLARE FUNCTION RtlIpv4AddressToStringW LIB "ntdll.dll" ALIAS "RtlIpv4AddressToStringW" ( BYREF Addr AS in_addr
 , BYREF S AS WSTRING
 ) AS DWORD
#IF %DEF(%UNICODE)
 MACRO RtlIpv4AddressToString = RtlIpv4AddressToStringW
#ELSE
 MACRO RtlIpv4AddressToString = RtlIpv4AddressToStringA
#ENDIF
DECLARE FUNCTION RtlIpv4AddressToStringExA LIB "ntdll.dll" ALIAS "RtlIpv4AddressToStringExA" ( BYREF Address AS in_addr , BYVAL Port AS WORD , BYREF AddressString AS ASCIIZ , BYREF AddressStringLength AS QUAD ) AS LONG
DECLARE FUNCTION RtlIpv4AddressToStringExW LIB "ntdll.dll" ALIAS "RtlIpv4AddressToStringExW" ( BYREF Address AS in_addr
 , BYVAL Port AS WORD
 , BYREF AddressString AS WSTRINGZ
 , BYREF AddressStringLength AS DWORD
 ) AS LONG
#IF %DEF(%UNICODE)
 MACRO RtlIpv4AddressToStringEx = RtlIpv4AddressToStringExW
#ELSE
 MACRO RtlIpv4AddressToStringEx = RtlIpv4AddressToStringExA
#ENDIF
DECLARE FUNCTION RtlIpv4StringToAddressA LIB "ntdll.dll" ALIAS "RtlIpv4StringToAddressA" ( BYREF S AS ASCIIZ , BYVAL Strict AS BYTE , BYREF Terminator AS QUAD , BYREF Addr AS in_addr ) AS LONG
DECLARE FUNCTION RtlIpv4StringToAddressW LIB "ntdll.dll" ALIAS "RtlIpv4StringToAddressW" ( BYREF S AS WSTRINGZ
 , BYVAL Strict AS BYTE
 , BYREF Terminator AS DWORD
 , BYREF Addr AS in_addr
 ) AS LONG
#IF %DEF(%UNICODE)
 MACRO RtlIpv4StringToAddress = RtlIpv4StringToAddressW
#ELSE
 MACRO RtlIpv4StringToAddress = RtlIpv4StringToAddressA
#ENDIF
DECLARE FUNCTION RtlIpv4StringToAddressExA LIB "ntdll.dll" ALIAS "RtlIpv4StringToAddressExA" ( BYREF AddressString AS ASCIIZ , BYVAL Strict AS BYTE , BYREF Addr AS in_addr , BYREF Port AS WORD ) AS LONG
DECLARE FUNCTION RtlIpv4StringToAddressExW LIB "ntdll.dll" ALIAS "RtlIpv4StringToAddressExW" ( BYREF AddressString AS WSTRINGZ
 , BYVAL Strict AS BYTE
 , BYREF Addr AS in_addr
 , BYREF Port AS WORD
 ) AS LONG
#IF %DEF(%UNICODE)
 MACRO RtlIpv4StringToAddressEx = RtlIpv4StringToAddressExW
#ELSE
 MACRO RtlIpv4StringToAddressEx = RtlIpv4StringToAddressExA
#ENDIF
'#endif //_WS2DEF_
'#ifdef _WS2IPDEF_
DECLARE FUNCTION RtlIpv6AddressToStringA LIB "ntdll.dll" ALIAS "RtlIpv6AddressToStringA" ( BYREF Addr AS in6_addr , BYREF S AS ASCIIZ ) AS QUAD
DECLARE FUNCTION RtlIpv6AddressToStringW LIB "ntdll.dll" ALIAS "RtlIpv6AddressToStringW" ( BYREF Addr AS in6_addr
 , BYREF S AS WSTRINGZ
 ) AS DWORD
#IF %DEF(%UNICODE)
 MACRO RtlIpv6AddressToString = RtlIpv6AddressToStringW
#ELSE
 MACRO RtlIpv6AddressToString = RtlIpv6AddressToStringA
#ENDIF
DECLARE FUNCTION RtlIpv6AddressToStringExA LIB "ntdll.dll" ALIAS "RtlIpv6AddressToStringExA" ( BYREF Address AS in6_addr , BYVAL ScopeId AS QUAD , BYVAL Port AS WORD , BYREF AddressString AS ASCIIZ , BYREF AddressStringLength AS QUAD ) AS LONG
DECLARE FUNCTION RtlIpv6AddressToStringExW LIB "ntdll.dll" ALIAS "RtlIpv6AddressToStringExW" ( BYREF Address AS in6_addr
 , BYVAL Port AS WORD
 , BYREF AddressString AS WSTRINGZ
 , BYREF AddressStringLength AS DWORD
 ) AS LONG
#IF %DEF(%UNICODE)
 MACRO RtlIpv6AddressToStringEx = RtlIpv6AddressToStringExW
#ELSE
 MACRO RtlIpv6AddressToStringEx = RtlIpv6AddressToStringExA
#ENDIF
DECLARE FUNCTION RtlIpv6StringToAddressA LIB "ntdll.dll" ALIAS "RtlIpv6StringToAddressA" ( BYREF S AS ASCIIZ , BYREF Terminator AS QUAD , BYREF Addr AS in6_addr ) AS LONG
DECLARE FUNCTION RtlIpv6StringToAddressW LIB "ntdll.dll" ALIAS "RtlIpv6StringToAddressW" ( BYREF S AS WSTRINGZ
 , BYREF Terminator AS DWORD
 , BYREF Addr AS in6_addr
 ) AS LONG
#IF %DEF(%UNICODE)
 MACRO RtlIpv6StringToAddress = RtlIpv6StringToAddressW
#ELSE
 MACRO RtlIpv6StringToAddress = RtlIpv6StringToAddressA
#ENDIF
DECLARE FUNCTION RtlIpv6StringToAddressExA LIB "ntdll.dll" ALIAS "RtlIpv6StringToAddressExA" ( BYREF AddressString AS ASCIIZ , BYREF Addr AS in6_addr , BYREF ScopeId AS QUAD , BYREF Port AS WORD ) AS LONG
DECLARE FUNCTION RtlIpv6StringToAddressExW LIB "ntdll.dll" ALIAS "RtlIpv6StringToAddressExW" ( BYREF AddressString AS WSTRINGZ
 , BYREF Addr AS in6_addr
 , BYREF ScopeId AS DWORD
 , BYREF Port AS WORD
 ) AS LONG
#IF %DEF(%UNICODE)
 MACRO RtlIpv6StringToAddressEx = RtlIpv6StringToAddressExW
#ELSE
 MACRO RtlIpv6StringToAddressEx = RtlIpv6StringToAddressExA
#ENDIF
'#endif // __WS2IPDEF__
'//
'// Some simple Rtl routines for Ethernet address <-> string literal conversion
'//
'#ifdef _WS2DEF_
'union _DL_EUI48;
'typedef union _DL_EUI48 DL_EUI48, *PDL_EUI48;
'NTSYSAPI
'NTAPI
'RtlEthernetAddressToStringA (
' );
'NTSYSAPI
'NTAPI
'RtlEthernetAddressToStringW (
' );
'NTSYSAPI
'NTAPI
'RtlEthernetStringToAddressA (
' );
'NTSYSAPI
'NTAPI
'RtlEthernetStringToAddressW (
' );
'#ifdef UNICODE
'#define RtlEthernetAddressToString RtlEthernetAddressToStringW
'#define RtlEthernetStringToAddress RtlEthernetStringToAddressW
'#else
'#define RtlEthernetAddressToString RtlEthernetAddressToStringA
'#define RtlEthernetStringToAddress RtlEthernetStringToAddressA
'#endif // UNICODE
'#endif //_WS2DEF_
'#endif // (NTDDI >= NTDDI_VISTA)
'#endif // __IP2STRING__
#ENDIF
