github.com/afumu/libc@v0.0.6/musl/src/network/getaddrinfo.c (about) 1 #include <stdlib.h> 2 #include <sys/socket.h> 3 #include <netinet/in.h> 4 #include <netdb.h> 5 #include <string.h> 6 #include <pthread.h> 7 #include <unistd.h> 8 #include <endian.h> 9 #include <errno.h> 10 #include "lookup.h" 11 12 int getaddrinfo(const char *restrict host, const char *restrict serv, const struct addrinfo *restrict hint, struct addrinfo **restrict res) 13 { 14 struct service ports[MAXSERVS]; 15 struct address addrs[MAXADDRS]; 16 char canon[256], *outcanon; 17 int nservs, naddrs, nais, canon_len, i, j, k; 18 int family = AF_UNSPEC, flags = 0, proto = 0, socktype = 0; 19 struct aibuf *out; 20 21 if (!host && !serv) return EAI_NONAME; 22 23 if (hint) { 24 family = hint->ai_family; 25 flags = hint->ai_flags; 26 proto = hint->ai_protocol; 27 socktype = hint->ai_socktype; 28 29 const int mask = AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST | 30 AI_V4MAPPED | AI_ALL | AI_ADDRCONFIG | AI_NUMERICSERV; 31 if ((flags & mask) != flags) 32 return EAI_BADFLAGS; 33 34 switch (family) { 35 case AF_INET: 36 case AF_INET6: 37 case AF_UNSPEC: 38 break; 39 default: 40 return EAI_FAMILY; 41 } 42 } 43 44 if (flags & AI_ADDRCONFIG) { 45 abort(); //TODO- 46 // /* Define the "an address is configured" condition for address 47 // * families via ability to create a socket for the family plus 48 // * routability of the loopback address for the family. */ 49 // static const struct sockaddr_in lo4 = { 50 // .sin_family = AF_INET, .sin_port = 65535, 51 // .sin_addr.s_addr = __BYTE_ORDER == __BIG_ENDIAN 52 // ? 0x7f000001 : 0x0100007f 53 // }; 54 // static const struct sockaddr_in6 lo6 = { 55 // .sin6_family = AF_INET6, .sin6_port = 65535, 56 // .sin6_addr = IN6ADDR_LOOPBACK_INIT 57 // }; 58 // int tf[2] = { AF_INET, AF_INET6 }; 59 // const void *ta[2] = { &lo4, &lo6 }; 60 // socklen_t tl[2] = { sizeof lo4, sizeof lo6 }; 61 // for (i=0; i<2; i++) { 62 // if (family==tf[1-i]) continue; 63 // int s = socket(tf[i], SOCK_CLOEXEC|SOCK_DGRAM, 64 // IPPROTO_UDP); 65 // if (s>=0) { 66 // int cs; 67 // pthread_setcancelstate( 68 // PTHREAD_CANCEL_DISABLE, &cs); 69 // int r = connect(s, ta[i], tl[i]); 70 // pthread_setcancelstate(cs, 0); 71 // close(s); 72 // if (!r) continue; 73 // } 74 // switch (errno) { 75 // case EADDRNOTAVAIL: 76 // case EAFNOSUPPORT: 77 // case EHOSTUNREACH: 78 // case ENETDOWN: 79 // case ENETUNREACH: 80 // break; 81 // default: 82 // return EAI_SYSTEM; 83 // } 84 // if (family == tf[i]) return EAI_NONAME; 85 // family = tf[1-i]; 86 // } 87 } 88 89 nservs = __lookup_serv(ports, serv, proto, socktype, flags); 90 if (nservs < 0) return nservs; 91 92 naddrs = __lookup_name(addrs, canon, host, family, flags); 93 if (naddrs < 0) return naddrs; 94 95 nais = nservs * naddrs; 96 canon_len = strlen(canon); 97 out = calloc(1, nais * sizeof(*out) + canon_len + 1); 98 if (!out) return EAI_MEMORY; 99 100 if (canon_len) { 101 outcanon = (void *)&out[nais]; 102 memcpy(outcanon, canon, canon_len+1); 103 } else { 104 outcanon = 0; 105 } 106 107 for (k=i=0; i<naddrs; i++) for (j=0; j<nservs; j++, k++) { 108 out[k].slot = k; 109 //TODO out[k].ai = (struct addrinfo){ 110 //TODO .ai_family = addrs[i].family, 111 //TODO .ai_socktype = ports[j].socktype, 112 //TODO .ai_protocol = ports[j].proto, 113 //TODO .ai_addrlen = addrs[i].family == AF_INET 114 //TODO ? sizeof(struct sockaddr_in) 115 //TODO : sizeof(struct sockaddr_in6), 116 //TODO .ai_addr = (void *)&out[k].sa, 117 //TODO .ai_canonname = outcanon }; 118 out[k].ai.ai_family = addrs[i].family; 119 out[k].ai.ai_socktype = ports[j].socktype; 120 out[k].ai.ai_protocol = ports[j].proto; 121 out[k].ai.ai_addrlen = addrs[i].family == AF_INET 122 ? sizeof(struct sockaddr_in) 123 : sizeof(struct sockaddr_in6); 124 out[k].ai.ai_addr = (void *)&out[k].sa; 125 out[k].ai.ai_canonname = outcanon; 126 if (k) out[k-1].ai.ai_next = &out[k].ai; 127 switch (addrs[i].family) { 128 case AF_INET: 129 out[k].sa.sin.sin_family = AF_INET; 130 out[k].sa.sin.sin_port = htons(ports[j].port); 131 memcpy(&out[k].sa.sin.sin_addr, &addrs[i].addr, 4); 132 break; 133 case AF_INET6: 134 out[k].sa.sin6.sin6_family = AF_INET6; 135 out[k].sa.sin6.sin6_port = htons(ports[j].port); 136 out[k].sa.sin6.sin6_scope_id = addrs[i].scopeid; 137 memcpy(&out[k].sa.sin6.sin6_addr, &addrs[i].addr, 16); 138 break; 139 } 140 } 141 out[0].ref = nais; 142 *res = &out->ai; 143 return 0; 144 }