Line data Source code
1 : #include <stdlib.h> 2 : #include <sys/socket.h> 3 : #include <netinet/in.h> 4 : #include "fd_netdb.h" 5 : #include <string.h> 6 : #include <pthread.h> 7 : #include <unistd.h> 8 : #include <endian.h> 9 : #include "fd_lookup.h" 10 : #include "../../util/io/fd_io.h" 11 : 12 : int 13 : fd_getaddrinfo( char const * restrict host, 14 : fd_addrinfo_t const * restrict hint, 15 : fd_addrinfo_t ** restrict res, 16 : void ** pout, 17 0 : ulong out_max ) { 18 0 : int family = AF_UNSPEC; 19 0 : int flags = 0; 20 : 21 0 : if( !host ) return FD_EAI_NONAME; 22 : 23 0 : if( hint ) { 24 0 : family = hint->ai_family; 25 0 : flags = hint->ai_flags; 26 : 27 0 : int const mask = FD_AI_PASSIVE | FD_AI_NUMERICHOST | FD_AI_V4MAPPED | FD_AI_ALL; 28 0 : if( (flags & mask)!=flags ) 29 0 : return FD_EAI_BADFLAGS; 30 : 31 0 : switch( family ) { 32 0 : case AF_INET: 33 0 : case AF_INET6: 34 0 : case AF_UNSPEC: 35 0 : break; 36 0 : default: 37 0 : return FD_EAI_FAMILY; 38 0 : } 39 0 : } 40 : 41 0 : struct address addrs[ MAXADDRS ]; 42 0 : char canon[ 256 ]; 43 0 : int const naddrs = fd_lookup_name( addrs, canon, host, family, flags ); 44 0 : if( naddrs < 0 ) return naddrs; 45 : 46 0 : int const nais = naddrs; 47 0 : int const canon_len = (int)strlen( canon ); 48 : 49 0 : ulong alloc_sz = (ulong)nais * sizeof(struct aibuf) + (ulong)canon_len + 1; 50 0 : if( FD_UNLIKELY( !pout ) ) return FD_EAI_MEMORY; 51 0 : if( FD_UNLIKELY( out_max<alloc_sz ) ) return FD_EAI_MEMORY; 52 0 : struct aibuf * out = *pout; 53 0 : *pout = (void *)( (ulong)out + alloc_sz ); 54 : 55 0 : char * outcanon; 56 0 : if( canon_len ) { 57 0 : outcanon = (void *)&out[nais]; 58 0 : memcpy( outcanon, canon, (ulong)canon_len+1 ); 59 0 : } else { 60 0 : outcanon = 0; 61 0 : } 62 : 63 0 : int i, k; 64 0 : for( k=i=0; i<naddrs; i++ ) for ( int j=0; j<1; j++, k++ ) { 65 0 : out[k].slot = (short)k; 66 0 : out[k].ai = (fd_addrinfo_t) { 67 0 : .ai_family = addrs[i].family, 68 0 : .ai_addrlen = addrs[i].family == AF_INET 69 0 : ? sizeof(struct sockaddr_in) 70 0 : : sizeof(struct sockaddr_in6), 71 0 : .ai_addr = (void *)&out[k].sa, 72 0 : .ai_canonname = outcanon 73 0 : }; 74 0 : if( k ) out[k-1].ai.ai_next = &out[k].ai; 75 0 : switch( addrs[i].family ) { 76 0 : case AF_INET: 77 0 : out[k].sa.sin.sin_family = AF_INET; 78 0 : memcpy( &out[k].sa.sin.sin_addr, &addrs[i].addr, 4 ); 79 0 : break; 80 0 : case AF_INET6: 81 0 : out[k].sa.sin6.sin6_family = AF_INET6; 82 0 : out[k].sa.sin6.sin6_scope_id = addrs[i].scopeid; 83 0 : memcpy( &out[k].sa.sin6.sin6_addr, &addrs[i].addr, 16 ); 84 0 : break; 85 0 : } 86 0 : } 87 0 : out[0].ref = (short)nais; 88 0 : *res = &out->ai; 89 0 : return 0; 90 0 : } 91 : 92 : char const * 93 0 : fd_gai_strerror( int gai ) { 94 0 : if( gai<=FD_EAI_SYSTEM ) { 95 0 : int err = gai-FD_EAI_SYSTEM; 96 0 : return fd_io_strerror( err ); 97 0 : } 98 0 : switch( gai ) { 99 0 : case FD_EAI_BADFLAGS: return "bad flags"; 100 0 : case FD_EAI_NONAME: return "not found"; 101 0 : case FD_EAI_AGAIN: return "temporary failure"; 102 0 : case FD_EAI_FAIL: return "permanent failure"; 103 0 : case FD_EAI_NODATA: return "no data"; 104 0 : case FD_EAI_FAMILY: return "unsupported address family"; 105 0 : case FD_EAI_MEMORY: return "out of memory"; 106 0 : default: return "unknown error"; 107 0 : } 108 0 : }