diff --git a/src/inc/msquic_linux.h b/src/inc/msquic_linux.h index ec71660d2..8e67cb1fe 100644 --- a/src/inc/msquic_linux.h +++ b/src/inc/msquic_linux.h @@ -30,6 +30,7 @@ Environment: #include #include #include +#include #include #include @@ -192,76 +193,257 @@ extern char *QuicOpenSslClientTrustedCert; // IP Address Abstraction Helpers // +inline BOOLEAN QuicAddrFamilyIsValid( - QUIC_ADDRESS_FAMILY Family - ); - + _In_ QUIC_ADDRESS_FAMILY Family + ) +{ + return Family == AF_INET || Family == AF_INET6 || Family == AF_UNSPEC; +} + +inline BOOLEAN QuicAddrIsValid( _In_ const QUIC_ADDR* const Addr - ); + ) +{ + return QuicAddrFamilyIsValid(Addr->si_family); +} +inline BOOLEAN QuicAddrCompareIp( _In_ const QUIC_ADDR* const Addr1, _In_ const QUIC_ADDR* const Addr2 - ); + ) +{ + if (AF_INET == Addr1->si_family) { + return memcmp(&Addr1->Ipv4.sin_addr, &Addr2->Ipv4.sin_addr, sizeof(IN_ADDR)) == 0; + } else { + return memcmp(&Addr1->Ipv6.sin6_addr, &Addr2->Ipv6.sin6_addr, sizeof(IN6_ADDR)) == 0; + } +} +inline BOOLEAN QuicAddrCompare( _In_ const QUIC_ADDR* const Addr1, _In_ const QUIC_ADDR* const Addr2 - ); + ) +{ + if (Addr1->si_family != Addr2->si_family || + Addr1->Ipv4.sin_port != Addr2->Ipv4.sin_port) { + return FALSE; + } + if (AF_INET == Addr1->si_family) { + return memcmp(&Addr1->Ipv4.sin_addr, &Addr2->Ipv4.sin_addr, sizeof(IN_ADDR)) == 0; + } else { + return memcmp(&Addr1->Ipv6.sin6_addr, &Addr2->Ipv6.sin6_addr, sizeof(IN6_ADDR)) == 0; + } +} + +inline uint16_t QuicAddrGetFamily( _In_ const QUIC_ADDR* const Addr - ); + ) +{ + return Addr->si_family; +} +inline void QuicAddrSetFamily( _In_ QUIC_ADDR* Addr, _In_ uint16_t Family - ); + ) +{ + Addr->si_family = Family; +} -uint16_t // Returns in host byte order. +inline +uint16_t QuicAddrGetPort( _In_ const QUIC_ADDR* const Addr - ); + ) +{ + if (AF_INET == Addr->si_family) { + return ntohs(Addr->Ipv4.sin_port); + } else { + return ntohs(Addr->Ipv6.sin6_port); + } +} +inline void QuicAddrSetPort( - _In_ QUIC_ADDR* Addr, - _In_ uint16_t Port // Host byte order - ); + _Out_ QUIC_ADDR* Addr, + _In_ uint16_t Port + ) +{ + if (AF_INET == Addr->si_family) { + Addr->Ipv4.sin_port = htons(Port); + } else { + Addr->Ipv6.sin6_port = htons(Port); + } +} +inline BOOLEAN QuicAddrIsBoundExplicitly( _In_ const QUIC_ADDR* const Addr - ); + ) +{ + // LINUX_TODO: How to handle IPv4? Windows just does the below. + // + // Scope ID of zero indicates we are sending from a connected binding. + // + + return Addr->Ipv6.sin6_scope_id == 0; +} + +inline void QuicAddrSetToLoopback( - _In_ QUIC_ADDR* Addr - ); + _Inout_ QUIC_ADDR* Addr + ) +{ + if (Addr->si_family == AF_INET) { + Addr->Ipv4.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + } else { + Addr->Ipv6.sin6_addr = in6addr_loopback; + } +} +inline uint32_t QuicAddrHash( _In_ const QUIC_ADDR* Addr - ); + ) +{ + uint32_t Hash = 5387; // A random prime number. +#define UPDATE_HASH(byte) Hash = ((Hash << 5) - Hash) + (byte) + if (Addr->si_family == AF_INET) { + UPDATE_HASH(Addr->Ipv4.sin_port & 0xFF); + UPDATE_HASH(Addr->Ipv4.sin_port >> 8); + for (uint8_t i = 0; i < sizeof(Addr->Ipv4.sin_addr); ++i) { + UPDATE_HASH(((uint8_t*)&Addr->Ipv4.sin_addr)[i]); + } + } else { + UPDATE_HASH(Addr->Ipv6.sin6_port & 0xFF); + UPDATE_HASH(Addr->Ipv6.sin6_port >> 8); + for (uint8_t i = 0; i < sizeof(Addr->Ipv6.sin6_addr); ++i) { + UPDATE_HASH(((uint8_t*)&Addr->Ipv6.sin6_addr)[i]); + } + } + return Hash; +} +inline BOOLEAN QuicAddrIsWildCard( _In_ const QUIC_ADDR* const Addr - ); + ) +{ + if (Addr->si_family == AF_UNSPEC) { + return TRUE; + } else if (Addr->si_family == AF_INET) { + const IN_ADDR ZeroAddr = {0}; + return memcmp(&Addr->Ipv4.sin_addr.s_addr, &ZeroAddr, sizeof(IN_ADDR)) == 0; + } else { + const IN6_ADDR ZeroAddr = {0}; + return memcmp(&Addr->Ipv6.sin6_addr, &ZeroAddr, sizeof(IN6_ADDR)) == 0; + } +} +inline +BOOLEAN +QuicAddr4FromString( + _In_z_ const char* AddrStr, + _Out_ QUIC_ADDR* Addr + ) +{ + if (AddrStr[0] == '[') { + return FALSE; + } + + const char* PortStart = strchr(AddrStr, ':'); + if (PortStart != NULL) { + if (strchr(PortStart+1, ':') != NULL) { + return FALSE; + } + + char TmpAddrStr[16]; + size_t AddrLength = PortStart - AddrStr; + if (AddrLength >= sizeof(TmpAddrStr)) { + return FALSE; + } + memcpy(TmpAddrStr, AddrStr, AddrLength); + TmpAddrStr[AddrLength] = '\0'; + + if (inet_pton(AF_INET, TmpAddrStr, &Addr->Ipv4.sin_addr) != 1) { + return FALSE; + } + Addr->Ipv4.sin_port = htons(atoi(PortStart+1)); + } else { + if (inet_pton(AF_INET, AddrStr, &Addr->Ipv4.sin_addr) != 1) { + return FALSE; + } + } + Addr->si_family = AF_INET; + return TRUE; +} + +inline +BOOLEAN +QuicAddr6FromString( + _In_z_ const char* AddrStr, + _Out_ QUIC_ADDR* Addr + ) +{ + if (AddrStr[0] == '[') { + const char* BracketEnd = strchr(AddrStr, ']'); + if (BracketEnd == NULL || *(BracketEnd+1) != ':') { + return FALSE; + } + + char TmpAddrStr[64]; + size_t AddrLength = BracketEnd - AddrStr; + if (AddrLength >= sizeof(TmpAddrStr)) { + return FALSE; + } + memcpy(TmpAddrStr, AddrStr, AddrLength); + TmpAddrStr[AddrLength] = '\0'; + + if (inet_pton(AF_INET6, TmpAddrStr, &Addr->Ipv6.sin6_addr) != 1) { + return FALSE; + } + Addr->Ipv6.sin6_port = htons(atoi(BracketEnd+2)); + } else { + if (inet_pton(AF_INET6, AddrStr, &Addr->Ipv6.sin6_addr) != 1) { + return FALSE; + } + } + Addr->si_family = AF_INET6; + return TRUE; +} + +inline BOOLEAN QuicAddrFromString( _In_z_ const char* AddrStr, _In_ uint16_t Port, // Host byte order _Out_ QUIC_ADDR* Addr - ); + ) +{ + Addr->Ipv4.sin_port = htons(Port); + return + QuicAddr4FromString(AddrStr, Addr) || + QuicAddr6FromString(AddrStr, Addr); +} // // Represents an IP address and (optionally) port number as a string. @@ -270,11 +452,35 @@ typedef struct QUIC_ADDR_STR { char Address[64]; } QUIC_ADDR_STR; +inline BOOLEAN QuicAddrToString( _In_ const QUIC_ADDR* Addr, _Out_ QUIC_ADDR_STR* AddrStr - ); + ) +{ + char* Address = AddrStr->Address; + if (Addr->si_family == AF_INET6 && Addr->Ipv6.sin6_port != 0) { + Address[0] = '['; + Address++; + } + if (inet_ntop( + Addr->si_family, + &Addr->Ipv4.sin_addr, + Address, + sizeof(QUIC_ADDR_STR)) != 0) { + return FALSE; + } + if (Addr->Ipv4.sin_port != 0) { + Address += strlen(Address); + if (Addr->si_family == AF_INET6) { + Address[0] = ']'; + Address++; + } + sprintf(Address, ":%hu", ntohs(Addr->Ipv4.sin_port)); + } + return TRUE; +} #if defined(__cplusplus) } diff --git a/src/platform/inline.c b/src/platform/inline.c index 976312a31..d5c028886 100644 --- a/src/platform/inline.c +++ b/src/platform/inline.c @@ -179,3 +179,92 @@ QuicTlsAlpnFindInList( _In_reads_(FindAlpnLength) const uint8_t* FindAlpn ); + +BOOLEAN +QuicAddrFamilyIsValid( + _In_ QUIC_ADDRESS_FAMILY Family + ); + +BOOLEAN +QuicAddrIsValid( + _In_ const QUIC_ADDR* const Addr + ); + +BOOLEAN +QuicAddrCompareIp( + _In_ const QUIC_ADDR* const Addr1, + _In_ const QUIC_ADDR* const Addr2 + ); + +BOOLEAN +QuicAddrCompare( + _In_ const QUIC_ADDR* const Addr1, + _In_ const QUIC_ADDR* const Addr2 + ); + +uint16_t +QuicAddrGetFamily( + _In_ const QUIC_ADDR* const Addr + ); + +void +QuicAddrSetFamily( + _In_ QUIC_ADDR* Addr, + _In_ uint16_t Family + ); + +uint16_t +QuicAddrGetPort( + _In_ const QUIC_ADDR* const Addr + ); + +void +QuicAddrSetPort( + _Out_ QUIC_ADDR* Addr, + _In_ uint16_t Port + ); + +BOOLEAN +QuicAddrIsBoundExplicitly( + _In_ const QUIC_ADDR* const Addr + ); + +void +QuicAddrSetToLoopback( + _Inout_ QUIC_ADDR* Addr + ); + +uint32_t +QuicAddrHash( + _In_ const QUIC_ADDR* Addr + ); + +BOOLEAN +QuicAddrIsWildCard( + _In_ const QUIC_ADDR* const Addr + ); + +BOOLEAN +QuicAddr4FromString( + _In_z_ const char* AddrStr, + _Out_ QUIC_ADDR* Addr + ); + +BOOLEAN +QuicAddr6FromString( + _In_z_ const char* AddrStr, + _Out_ QUIC_ADDR* Addr + ); + +BOOLEAN +QuicAddrFromString( + _In_z_ const char* AddrStr, + _In_ uint16_t Port, // Host byte order + _Out_ QUIC_ADDR* Addr + ); + +BOOLEAN +QuicAddrToString( + _In_ const QUIC_ADDR* Addr, + _Out_ QUIC_ADDR_STR* AddrStr + ); diff --git a/src/platform/platform_linux.c b/src/platform/platform_linux.c index 5405e87c6..12dd73a2e 100644 --- a/src/platform/platform_linux.c +++ b/src/platform/platform_linux.c @@ -21,7 +21,6 @@ Environment: #include #include #include -#include #include "quic_trace.h" #include "quic_platform_dispatch.h" @@ -610,275 +609,6 @@ QuicConvertFromMappedV6( } } -BOOLEAN -QuicAddrFamilyIsValid( - _In_ QUIC_ADDRESS_FAMILY Family - ) -{ - return Family == AF_INET || Family == AF_INET6 || Family == AF_UNSPEC; -} - -BOOLEAN -QuicAddrIsValid( - _In_ const QUIC_ADDR* const Addr - ) -{ - QUIC_DBG_ASSERT(Addr); - return QuicAddrFamilyIsValid(Addr->si_family); -} - -BOOLEAN -QuicAddrCompareIp( - _In_ const QUIC_ADDR* const Addr1, - _In_ const QUIC_ADDR* const Addr2 - ) -{ - QUIC_DBG_ASSERT(QuicAddrIsValid(Addr1)); - QUIC_DBG_ASSERT(QuicAddrIsValid(Addr2)); - - if (AF_INET == Addr1->si_family) { - return memcmp(&Addr1->Ipv4.sin_addr, &Addr2->Ipv4.sin_addr, sizeof(IN_ADDR)) == 0; - } else { - return memcmp(&Addr1->Ipv6.sin6_addr, &Addr2->Ipv6.sin6_addr, sizeof(IN6_ADDR)) == 0; - } -} - -BOOLEAN -QuicAddrCompare( - _In_ const QUIC_ADDR* const Addr1, - _In_ const QUIC_ADDR* const Addr2 - ) -{ - QUIC_DBG_ASSERT(QuicAddrIsValid(Addr1)); - QUIC_DBG_ASSERT(QuicAddrIsValid(Addr2)); - - if (Addr1->si_family != Addr2->si_family || - Addr1->Ipv4.sin_port != Addr2->Ipv4.sin_port) { - return FALSE; - } - - if (AF_INET == Addr1->si_family) { - return memcmp(&Addr1->Ipv4.sin_addr, &Addr2->Ipv4.sin_addr, sizeof(IN_ADDR)) == 0; - } else { - return memcmp(&Addr1->Ipv6.sin6_addr, &Addr2->Ipv6.sin6_addr, sizeof(IN6_ADDR)) == 0; - } -} - -uint16_t -QuicAddrGetFamily( - _In_ const QUIC_ADDR* const Addr - ) -{ - QUIC_DBG_ASSERT(QuicAddrIsValid(Addr)); - return Addr->si_family; -} - -void -QuicAddrSetFamily( - _In_ QUIC_ADDR* Addr, - _In_ uint16_t Family - ) -{ - QUIC_DBG_ASSERT(Addr); - QUIC_DBG_ASSERT(QuicAddrFamilyIsValid(Family)); - Addr->si_family = Family; -} - -uint16_t -QuicAddrGetPort( - _In_ const QUIC_ADDR* const Addr - ) -{ - QUIC_DBG_ASSERT(QuicAddrIsValid(Addr)); - - if (AF_INET == Addr->si_family) { - return ntohs(Addr->Ipv4.sin_port); - } else { - return ntohs(Addr->Ipv6.sin6_port); - } -} - -void -QuicAddrSetPort( - _Out_ QUIC_ADDR* Addr, - _In_ uint16_t Port - ) -{ - QUIC_DBG_ASSERT(QuicAddrIsValid(Addr)); - - if (AF_INET == Addr->si_family) { - Addr->Ipv4.sin_port = htons(Port); - } else { - Addr->Ipv6.sin6_port = htons(Port); - } -} - -BOOLEAN -QuicAddrIsBoundExplicitly( - _In_ const QUIC_ADDR* const Addr - ) -{ - QUIC_DBG_ASSERT(QuicAddrIsValid(Addr)); - - // LINUX_TODO: How to handle IPv4? Windows just does the below. - - // - // Scope ID of zero indicates we are sending from a connected binding. - // - - return Addr->Ipv6.sin6_scope_id == 0; -} - -void -QuicAddrSetToLoopback( - _Inout_ QUIC_ADDR* Addr - ) -{ - QUIC_DBG_ASSERT(QuicAddrIsValid(Addr)); - - if (Addr->si_family == AF_INET) { - Addr->Ipv4.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - } else { - Addr->Ipv6.sin6_addr = in6addr_loopback; - } -} - -uint32_t -QuicAddrHash( - _In_ const QUIC_ADDR* Addr - ) -{ - uint32_t Hash = 5387; // A random prime number. -#define UPDATE_HASH(byte) Hash = ((Hash << 5) - Hash) + (byte) - if (Addr->si_family == AF_INET) { - UPDATE_HASH(Addr->Ipv4.sin_port & 0xFF); - UPDATE_HASH(Addr->Ipv4.sin_port >> 8); - for (uint8_t i = 0; i < sizeof(Addr->Ipv4.sin_addr); ++i) { - UPDATE_HASH(((uint8_t*)&Addr->Ipv4.sin_addr)[i]); - } - } else { - UPDATE_HASH(Addr->Ipv6.sin6_port & 0xFF); - UPDATE_HASH(Addr->Ipv6.sin6_port >> 8); - for (uint8_t i = 0; i < sizeof(Addr->Ipv6.sin6_addr); ++i) { - UPDATE_HASH(((uint8_t*)&Addr->Ipv6.sin6_addr)[i]); - } - } - return Hash; -} - -BOOLEAN -QuicAddrIsWildCard( - _In_ const QUIC_ADDR* const Addr - ) -{ - if (Addr->si_family == AF_UNSPEC) { - return TRUE; - } else if (Addr->si_family == AF_INET) { - const IN_ADDR ZeroAddr = {0}; - return memcmp(&Addr->Ipv4.sin_addr.s_addr, &ZeroAddr, sizeof(IN_ADDR)) == 0; - } else { - const IN6_ADDR ZeroAddr = {0}; - return memcmp(&Addr->Ipv6.sin6_addr, &ZeroAddr, sizeof(IN6_ADDR)) == 0; - } -} - -BOOLEAN -QuicAddr4FromString( - _In_z_ const char* AddrStr, - _Out_ QUIC_ADDR* Addr - ) -{ - if (AddrStr[0] == '[') { - return FALSE; - } - char* PortStart = strchr(AddrStr, ':'); - if (PortStart != NULL) { - if (strchr(PortStart+1, ':') != NULL) { - return FALSE; - } - *PortStart = '\0'; - if (inet_pton(AF_INET, AddrStr, &Addr->Ipv4.sin_addr) != 1) { - return FALSE; - } - *PortStart = ':'; - Addr->Ipv4.sin_port = htons(atoi(PortStart+1)); - } else { - if (inet_pton(AF_INET, AddrStr, &Addr->Ipv4.sin_addr) != 1) { - return FALSE; - } - } - Addr->si_family = AF_INET; - return TRUE; -} - -BOOLEAN -QuicAddr6FromString( - _In_z_ const char* AddrStr, - _Out_ QUIC_ADDR* Addr - ) -{ - if (AddrStr[0] == '[') { - char* BracketEnd = strchr(AddrStr, ']'); - if (BracketEnd == NULL || *(BracketEnd+1) != ':') { - return FALSE; - } - *BracketEnd = '\0'; - if (inet_pton(AF_INET6, AddrStr+1, &Addr->Ipv6.sin6_addr) != 1) { - return FALSE; - } - *BracketEnd = ']'; - Addr->Ipv6.sin6_port = htons(atoi(BracketEnd+2)); - } else { - if (inet_pton(AF_INET6, AddrStr, &Addr->Ipv6.sin6_addr) != 1) { - return FALSE; - } - } - Addr->si_family = AF_INET6; - return TRUE; -} - -BOOLEAN -QuicAddrFromString( - _In_z_ const char* AddrStr, - _In_ uint16_t Port, // Host byte order - _Out_ QUIC_ADDR* Addr - ) -{ - Addr->Ipv4.sin_port = htons(Port); - return - QuicAddr4FromString(AddrStr, Addr) || - QuicAddr6FromString(AddrStr, Addr); -} - -BOOLEAN -QuicAddrToString( - _In_ const QUIC_ADDR* Addr, - _Out_ QUIC_ADDR_STR* AddrStr - ) -{ - char* Address = AddrStr->Address; - if (Addr->si_family == AF_INET6 && Addr->Ipv6.sin6_port != 0) { - Address[0] = '['; - Address++; - } - if (inet_ntop( - Addr->si_family, - &Addr->Ipv4.sin_addr, - Address, - sizeof(QUIC_ADDR_STR)) != NULL) { - return FALSE; - } - if (Addr->Ipv4.sin_port != 0) { - Address += strlen(Address); - if (Addr->si_family == AF_INET6) { - Address[0] = ']'; - Address++; - } - sprintf(Address, ":%hu", ntohs(Addr->Ipv4.sin_port)); - } - return TRUE; -} - int _strnicmp( _In_ const char * _Str1,