@@ -600,6 +600,18 @@ int enableNoDelay(SOCKET s) {
600
600
return 0 ;
601
601
}
602
602
603
+ static void logWithSockaddr (const char * format , const char * arg , const struct sockaddr * addr , socklen_t len ) {
604
+ char host [NI_MAXHOST ], service [NI_MAXSERV ];
605
+ int res = getnameinfo (addr , len , host , sizeof (host ), service , sizeof (service ),
606
+ NI_NUMERICHOST | NI_NUMERICSERV );
607
+ if (res == 0 ) {
608
+ Limelog (format , arg , host , service );
609
+ }
610
+ else {
611
+ Limelog ("getnameinfo() failed: %s\n" , gai_strerror (res ));
612
+ }
613
+ }
614
+
603
615
int resolveHostName (const char * host , int family , int tcpTestPort , struct sockaddr_storage * addr , SOCKADDR_LEN * addrLen )
604
616
{
605
617
struct addrinfo hints , * res , * currentAddr ;
@@ -621,6 +633,8 @@ int resolveHostName(const char* host, int family, int tcpTestPort, struct sockad
621
633
}
622
634
623
635
for (currentAddr = res ; currentAddr != NULL ; currentAddr = currentAddr -> ai_next ) {
636
+ logWithSockaddr ("Resolved %s to %s %s\n" , host , currentAddr -> ai_addr , sizeof (currentAddr -> ai_addr ));
637
+
624
638
// Use the test port to ensure this address is working if:
625
639
// a) We have multiple addresses
626
640
// b) The caller asked us to test even with a single address
@@ -634,6 +648,7 @@ int resolveHostName(const char* host, int family, int tcpTestPort, struct sockad
634
648
continue ;
635
649
}
636
650
else {
651
+ Limelog ("tcp test on port %d is ok\n" , tcpTestPort );
637
652
closeSocket (testSocket );
638
653
}
639
654
}
@@ -829,6 +844,79 @@ bool isNat64SynthesizedAddress(struct sockaddr_storage* address) {
829
844
return false;
830
845
}
831
846
847
+ static uint32_t ipv4ToHex (const char * ipv4Str ) {
848
+ struct in_addr addr ;
849
+ if (inet_pton (AF_INET , ipv4Str , & addr ) != 1 ) {
850
+ Limelog ("ipv4ToHex: invalid IPv4 address: %s\n" , ipv4ToHex );
851
+ return 0 ;
852
+ }
853
+ return ntohl (addr .s_addr );
854
+ }
855
+
856
+ // Return true if the given IPv6 sockaddr_storage is a synthesized address that
857
+ // encapsulates an IPv4 address for use on an IPv6-only network.
858
+ // See RFC 7050 and 8880 for more details.
859
+ // input: IPv6 address as a struct sockaddr_storage *, and an IPv4 string
860
+ bool is464XLATSynthesizedAddress (struct sockaddr_storage * ipv6Address , const char * ipv4Str ) {
861
+ bool ret = false;
862
+
863
+ #ifdef AF_INET6
864
+ int err ;
865
+ struct addrinfo hints , * res , * currentAddr ;
866
+ memset (& hints , 0 , sizeof (hints ));
867
+
868
+ // perform an AAAA lookup on ipv4only.arpa
869
+ // If this returns one or more responses, the network has a CLAT that is synthesizing IPv6 addresses
870
+ hints .ai_family = AF_INET6 ; // will query AAAA only
871
+ hints .ai_socktype = SOCK_STREAM ;
872
+ hints .ai_flags = AI_CANONNAME ;
873
+ err = getaddrinfo ("ipv4only.arpa" , NULL , & hints , & res );
874
+ if (err != 0 ) {
875
+ Limelog ("is464XLATSynthesizedAddress getaddrinfo(ipv4only.arpa) failed: %d\n" , err );
876
+ return false;
877
+ }
878
+ else if (res == NULL ) {
879
+ return false;
880
+ }
881
+
882
+ char ipv6AddressStr [INET6_ADDRSTRLEN ];
883
+ memset (& ipv6AddressStr , 0 , sizeof (ipv6AddressStr ));
884
+ struct sockaddr_in6 * ipv6Addr = (struct sockaddr_in6 * )ipv6Address ;
885
+ inet_ntop (AF_INET6 , & ipv6Addr -> sin6_addr , ipv6AddressStr , sizeof (ipv6AddressStr ));
886
+
887
+ // Look through all responses, we may see the Well Known Prefix 64:ff9b::/96 as well as
888
+ // Network Specific Prefixes such as T-Mobile's 2607:7700:0:51::*
889
+ char currentAddrStr [INET6_ADDRSTRLEN ];
890
+ for (currentAddr = res ; currentAddr != NULL ; currentAddr = currentAddr -> ai_next ) {
891
+ memset (& currentAddrStr , 0 , sizeof (currentAddrStr ));
892
+ struct sockaddr_in6 * addr = (struct sockaddr_in6 * )currentAddr -> ai_addr ;
893
+ inet_ntop (AF_INET6 , & addr -> sin6_addr , currentAddrStr , sizeof (currentAddrStr ));
894
+
895
+ // Check first 96 bits of IPv6 for matching prefix
896
+ if (memcmp (& ipv6Addr -> sin6_addr , & addr -> sin6_addr , 12 ) == 0 ) {
897
+ // The prefixes match; now compare the IPv4 portion
898
+ uint32_t ipv6Hex ;
899
+ memcpy (& ipv6Hex , ((uint8_t * )& ipv6Addr -> sin6_addr ) + 12 , sizeof (ipv6Hex ));
900
+ ipv6Hex = ntohl (ipv6Hex );
901
+
902
+ if (ipv6Hex == ipv4ToHex (ipv4Str )) {
903
+ ret = true;
904
+ break ;
905
+ }
906
+ }
907
+ }
908
+
909
+ freeaddrinfo (res );
910
+ #endif
911
+
912
+ return ret ;
913
+ }
914
+
915
+ bool isIPv4Address (const char * str ) {
916
+ struct in_addr addr ;
917
+ return inet_pton (AF_INET , str , & addr ) == 1 ;
918
+ }
919
+
832
920
// Enable platform-specific low latency options (best-effort)
833
921
void enterLowLatencyMode (void ) {
834
922
#if defined(LC_WINDOWS_DESKTOP )
@@ -959,3 +1047,36 @@ void cleanupPlatformSockets(void) {
959
1047
#else
960
1048
#endif
961
1049
}
1050
+
1051
+ void logWithSockaddrStorage (struct sockaddr_storage * addr , const char * format ) {
1052
+ void * src = NULL ;
1053
+
1054
+ #ifdef AF_INET6
1055
+ char ip [INET6_ADDRSTRLEN ];
1056
+ #else
1057
+ char ip [INET_ADDRSTRLEN ];
1058
+ #endif
1059
+
1060
+ #ifdef AF_INET6
1061
+ if (addr -> ss_family == AF_INET6 ) {
1062
+ struct sockaddr_in6 * addr_in6 = (struct sockaddr_in6 * )addr ;
1063
+ src = & (addr_in6 -> sin6_addr );
1064
+ }
1065
+ else
1066
+ #endif
1067
+ if (addr -> ss_family == AF_INET ) {
1068
+ struct sockaddr_in * addr_in = (struct sockaddr_in * )addr ;
1069
+ src = & (addr_in -> sin_addr );
1070
+ }
1071
+ else {
1072
+ Limelog ("Unknown address family: %d\n" , addr -> ss_family );
1073
+ return ;
1074
+ }
1075
+
1076
+ if (inet_ntop (addr -> ss_family , src , ip , sizeof (ip )) == NULL ) {
1077
+ Limelog ("invalid struct sockaddr_storage\n" );
1078
+ return ;
1079
+ }
1080
+
1081
+ Limelog (format , ip );
1082
+ }
0 commit comments