OLD | NEW |
1 #define _GNU_SOURCE | 1 #define _GNU_SOURCE |
2 | 2 |
3 #include <sys/socket.h> | 3 #include <sys/socket.h> |
4 #include <netdb.h> | 4 #include <netdb.h> |
5 #include <string.h> | 5 #include <string.h> |
6 #include <netinet/in.h> | 6 #include <netinet/in.h> |
7 #include <errno.h> | 7 #include <errno.h> |
8 #include <inttypes.h> | 8 #include <inttypes.h> |
9 | 9 |
10 int gethostbyaddr_r(const void *a, socklen_t l, int af, | 10 int gethostbyaddr_r(const void* a, |
11 » struct hostent *h, char *buf, size_t buflen, | 11 socklen_t l, |
12 » struct hostent **res, int *err) | 12 int af, |
13 { | 13 struct hostent* h, |
14 » union { | 14 char* buf, |
15 » » struct sockaddr_in sin; | 15 size_t buflen, |
16 » » struct sockaddr_in6 sin6; | 16 struct hostent** res, |
17 » } sa = { .sin.sin_family = af }; | 17 int* err) { |
18 » socklen_t sl = af==AF_INET6 ? sizeof sa.sin6 : sizeof sa.sin; | 18 union { |
19 » int i; | 19 struct sockaddr_in sin; |
| 20 struct sockaddr_in6 sin6; |
| 21 } sa = {.sin.sin_family = af}; |
| 22 socklen_t sl = af == AF_INET6 ? sizeof sa.sin6 : sizeof sa.sin; |
| 23 int i; |
20 | 24 |
21 » *res = 0; | 25 *res = 0; |
22 | 26 |
23 » /* Load address argument into sockaddr structure */ | 27 /* Load address argument into sockaddr structure */ |
24 » if (af==AF_INET6 && l==16) memcpy(&sa.sin6.sin6_addr, a, 16); | 28 if (af == AF_INET6 && l == 16) |
25 » else if (af==AF_INET && l==4) memcpy(&sa.sin.sin_addr, a, 4); | 29 memcpy(&sa.sin6.sin6_addr, a, 16); |
26 » else { | 30 else if (af == AF_INET && l == 4) |
27 » » *err = NO_RECOVERY; | 31 memcpy(&sa.sin.sin_addr, a, 4); |
28 » » return EINVAL; | 32 else { |
29 » } | 33 *err = NO_RECOVERY; |
| 34 return EINVAL; |
| 35 } |
30 | 36 |
31 » /* Align buffer and check for space for pointers and ip address */ | 37 /* Align buffer and check for space for pointers and ip address */ |
32 » i = (uintptr_t)buf & sizeof(char *)-1; | 38 i = (uintptr_t)buf & sizeof(char*) - 1; |
33 » if (!i) i = sizeof(char *); | 39 if (!i) |
34 » if (buflen <= 5*sizeof(char *)-i + l) return ERANGE; | 40 i = sizeof(char*); |
35 » buf += sizeof(char *)-i; | 41 if (buflen <= 5 * sizeof(char*) - i + l) |
36 » buflen -= 5*sizeof(char *)-i + l; | 42 return ERANGE; |
| 43 buf += sizeof(char*) - i; |
| 44 buflen -= 5 * sizeof(char*) - i + l; |
37 | 45 |
38 » h->h_addr_list = (void *)buf; | 46 h->h_addr_list = (void*)buf; |
39 » buf += 2*sizeof(char *); | 47 buf += 2 * sizeof(char*); |
40 » h->h_aliases = (void *)buf; | 48 h->h_aliases = (void*)buf; |
41 » buf += 2*sizeof(char *); | 49 buf += 2 * sizeof(char*); |
42 | 50 |
43 » h->h_addr_list[0] = buf; | 51 h->h_addr_list[0] = buf; |
44 » memcpy(h->h_addr_list[0], a, l); | 52 memcpy(h->h_addr_list[0], a, l); |
45 » buf += l; | 53 buf += l; |
46 » h->h_addr_list[1] = 0; | 54 h->h_addr_list[1] = 0; |
47 » h->h_aliases[0] = buf; | 55 h->h_aliases[0] = buf; |
48 » h->h_aliases[1] = 0; | 56 h->h_aliases[1] = 0; |
49 | 57 |
50 » switch (getnameinfo((void *)&sa, sl, buf, buflen, 0, 0, 0)) { | 58 switch (getnameinfo((void*)&sa, sl, buf, buflen, 0, 0, 0)) { |
51 » case EAI_AGAIN: | 59 case EAI_AGAIN: |
52 » » *err = TRY_AGAIN; | 60 *err = TRY_AGAIN; |
53 » » return EAGAIN; | 61 return EAGAIN; |
54 » case EAI_OVERFLOW: | 62 case EAI_OVERFLOW: |
55 » » return ERANGE; | 63 return ERANGE; |
56 » default: | 64 default: |
57 » case EAI_MEMORY: | 65 case EAI_MEMORY: |
58 » case EAI_SYSTEM: | 66 case EAI_SYSTEM: |
59 » case EAI_FAIL: | 67 case EAI_FAIL: |
60 » » *err = NO_RECOVERY; | 68 *err = NO_RECOVERY; |
61 » » return errno; | 69 return errno; |
62 » case 0: | 70 case 0: |
63 » » break; | 71 break; |
64 » } | 72 } |
65 | 73 |
66 » h->h_addrtype = af; | 74 h->h_addrtype = af; |
67 » h->h_name = h->h_aliases[0]; | 75 h->h_name = h->h_aliases[0]; |
68 » *res = h; | 76 *res = h; |
69 » return 0; | 77 return 0; |
70 } | 78 } |
OLD | NEW |