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 |