| OLD | NEW |
| 1 #include <stdlib.h> | 1 #include <stdlib.h> |
| 2 #include <sys/socket.h> | 2 #include <sys/socket.h> |
| 3 #include <netinet/in.h> | 3 #include <netinet/in.h> |
| 4 #include <netdb.h> | 4 #include <netdb.h> |
| 5 #include <string.h> | 5 #include <string.h> |
| 6 #include "lookup.h" | 6 #include "lookup.h" |
| 7 | 7 |
| 8 int getaddrinfo(const char *restrict host, const char *restrict serv, const stru
ct addrinfo *restrict hint, struct addrinfo **restrict res) | 8 int getaddrinfo(const char* restrict host, |
| 9 { | 9 const char* restrict serv, |
| 10 » struct service ports[MAXSERVS]; | 10 const struct addrinfo* restrict hint, |
| 11 » struct address addrs[MAXADDRS]; | 11 struct addrinfo** restrict res) { |
| 12 » char canon[256], *outcanon; | 12 struct service ports[MAXSERVS]; |
| 13 » int nservs, naddrs, nais, canon_len, i, j, k; | 13 struct address addrs[MAXADDRS]; |
| 14 » int family = AF_UNSPEC, flags = 0, proto = 0, socktype = 0; | 14 char canon[256], *outcanon; |
| 15 » struct aibuf { | 15 int nservs, naddrs, nais, canon_len, i, j, k; |
| 16 » » struct addrinfo ai; | 16 int family = AF_UNSPEC, flags = 0, proto = 0, socktype = 0; |
| 17 » » union sa { | 17 struct aibuf { |
| 18 » » » struct sockaddr_in sin; | 18 struct addrinfo ai; |
| 19 » » » struct sockaddr_in6 sin6; | 19 union sa { |
| 20 » » } sa; | 20 struct sockaddr_in sin; |
| 21 » } *out; | 21 struct sockaddr_in6 sin6; |
| 22 } sa; |
| 23 } * out; |
| 22 | 24 |
| 23 » if (!host && !serv) return EAI_NONAME; | 25 if (!host && !serv) |
| 26 return EAI_NONAME; |
| 24 | 27 |
| 25 » if (hint) { | 28 if (hint) { |
| 26 » » family = hint->ai_family; | 29 family = hint->ai_family; |
| 27 » » flags = hint->ai_flags; | 30 flags = hint->ai_flags; |
| 28 » » proto = hint->ai_protocol; | 31 proto = hint->ai_protocol; |
| 29 » » socktype = hint->ai_socktype; | 32 socktype = hint->ai_socktype; |
| 30 | 33 |
| 31 » » const int mask = AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST | | 34 const int mask = AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST | AI_V4MAPPED | |
| 32 » » » AI_V4MAPPED | AI_ALL | AI_ADDRCONFIG | AI_NUMERICSERV; | 35 AI_ALL | AI_ADDRCONFIG | AI_NUMERICSERV; |
| 33 » » if ((flags & mask) != flags) | 36 if ((flags & mask) != flags) |
| 34 » » » return EAI_BADFLAGS; | 37 return EAI_BADFLAGS; |
| 35 | 38 |
| 36 » » switch (family) { | 39 switch (family) { |
| 37 » » case AF_INET: | 40 case AF_INET: |
| 38 » » case AF_INET6: | 41 case AF_INET6: |
| 39 » » case AF_UNSPEC: | 42 case AF_UNSPEC: |
| 40 » » » break; | 43 break; |
| 41 » » default: | 44 default: |
| 42 » » » return EAI_FAMILY; | 45 return EAI_FAMILY; |
| 43 » » } | 46 } |
| 44 » } | 47 } |
| 45 | 48 |
| 46 » nservs = __lookup_serv(ports, serv, proto, socktype, flags); | 49 nservs = __lookup_serv(ports, serv, proto, socktype, flags); |
| 47 » if (nservs < 0) return nservs; | 50 if (nservs < 0) |
| 51 return nservs; |
| 48 | 52 |
| 49 » naddrs = __lookup_name(addrs, canon, host, family, flags); | 53 naddrs = __lookup_name(addrs, canon, host, family, flags); |
| 50 » if (naddrs < 0) return naddrs; | 54 if (naddrs < 0) |
| 55 return naddrs; |
| 51 | 56 |
| 52 » nais = nservs * naddrs; | 57 nais = nservs * naddrs; |
| 53 » canon_len = strlen(canon); | 58 canon_len = strlen(canon); |
| 54 » out = calloc(1, nais * sizeof(*out) + canon_len + 1); | 59 out = calloc(1, nais * sizeof(*out) + canon_len + 1); |
| 55 » if (!out) return EAI_MEMORY; | 60 if (!out) |
| 61 return EAI_MEMORY; |
| 56 | 62 |
| 57 » if (canon_len) { | 63 if (canon_len) { |
| 58 » » outcanon = (void *)&out[nais]; | 64 outcanon = (void*)&out[nais]; |
| 59 » » memcpy(outcanon, canon, canon_len+1); | 65 memcpy(outcanon, canon, canon_len + 1); |
| 60 » } else { | 66 } else { |
| 61 » » outcanon = 0; | 67 outcanon = 0; |
| 62 » } | 68 } |
| 63 | 69 |
| 64 » for (k=i=0; i<naddrs; i++) for (j=0; j<nservs; j++, k++) { | 70 for (k = i = 0; i < naddrs; i++) |
| 65 » » out[k].ai = (struct addrinfo){ | 71 for (j = 0; j < nservs; j++, k++) { |
| 66 » » » .ai_family = addrs[i].family, | 72 out[k].ai = |
| 67 » » » .ai_socktype = ports[j].socktype, | 73 (struct addrinfo){.ai_family = addrs[i].family, |
| 68 » » » .ai_protocol = ports[j].proto, | 74 .ai_socktype = ports[j].socktype, |
| 69 » » » .ai_addrlen = addrs[i].family == AF_INET | 75 .ai_protocol = ports[j].proto, |
| 70 » » » » ? sizeof(struct sockaddr_in) | 76 .ai_addrlen = addrs[i].family == AF_INET |
| 71 » » » » : sizeof(struct sockaddr_in6), | 77 ? sizeof(struct sockaddr_in) |
| 72 » » » .ai_addr = (void *)&out[k].sa, | 78 : sizeof(struct sockaddr_in6), |
| 73 » » » .ai_canonname = outcanon, | 79 .ai_addr = (void*)&out[k].sa, |
| 74 » » » .ai_next = &out[k+1].ai }; | 80 .ai_canonname = outcanon, |
| 75 » » switch (addrs[i].family) { | 81 .ai_next = &out[k + 1].ai}; |
| 76 » » case AF_INET: | 82 switch (addrs[i].family) { |
| 77 » » » out[k].sa.sin.sin_family = AF_INET; | 83 case AF_INET: |
| 78 » » » out[k].sa.sin.sin_port = htons(ports[j].port); | 84 out[k].sa.sin.sin_family = AF_INET; |
| 79 » » » memcpy(&out[k].sa.sin.sin_addr, &addrs[i].addr, 4); | 85 out[k].sa.sin.sin_port = htons(ports[j].port); |
| 80 » » » break; | 86 memcpy(&out[k].sa.sin.sin_addr, &addrs[i].addr, 4); |
| 81 » » case AF_INET6: | 87 break; |
| 82 » » » out[k].sa.sin6.sin6_family = AF_INET6; | 88 case AF_INET6: |
| 83 » » » out[k].sa.sin6.sin6_port = htons(ports[j].port); | 89 out[k].sa.sin6.sin6_family = AF_INET6; |
| 84 » » » out[k].sa.sin6.sin6_scope_id = addrs[i].scopeid; | 90 out[k].sa.sin6.sin6_port = htons(ports[j].port); |
| 85 » » » memcpy(&out[k].sa.sin6.sin6_addr, &addrs[i].addr, 16); | 91 out[k].sa.sin6.sin6_scope_id = addrs[i].scopeid; |
| 86 » » » break;» » » | 92 memcpy(&out[k].sa.sin6.sin6_addr, &addrs[i].addr, 16); |
| 87 » » } | 93 break; |
| 88 » } | 94 } |
| 89 » out[nais-1].ai.ai_next = 0; | 95 } |
| 90 » *res = &out->ai; | 96 out[nais - 1].ai.ai_next = 0; |
| 91 » return 0; | 97 *res = &out->ai; |
| 98 return 0; |
| 92 } | 99 } |
| OLD | NEW |