1#define _GNU_SOURCE 2 3#include <sys/socket.h> 4#include <netdb.h> 5#include <string.h> 6#include <netinet/in.h> 7#include <errno.h> 8#include <stdint.h> 9#include "lookup.h" 10 11int gethostbyname2_r(const char *name, int af, 12 struct hostent *h, char *buf, size_t buflen, 13 struct hostent **res, int *err) 14{ 15 struct address addrs[MAXADDRS]; 16 char canon[256]; 17 int i, cnt; 18 size_t align, need; 19 20 *res = 0; 21 cnt = __lookup_name(addrs, canon, name, af, AI_CANONNAME); 22 if (cnt<0) switch (cnt) { 23 case EAI_NONAME: 24 *err = HOST_NOT_FOUND; 25 return ENOENT; 26 case EAI_AGAIN: 27 *err = TRY_AGAIN; 28 return EAGAIN; 29 default: 30 case EAI_FAIL: 31 *err = NO_RECOVERY; 32 return EBADMSG; 33 case EAI_MEMORY: 34 case EAI_SYSTEM: 35 *err = NO_RECOVERY; 36 return errno; 37 } 38 39 h->h_addrtype = af; 40 h->h_length = af==AF_INET6 ? 16 : 4; 41 42 /* Align buffer */ 43 align = -(uintptr_t)buf & sizeof(char *)-1; 44 45 need = 4*sizeof(char *); 46 need += (cnt + 1) * (sizeof(char *) + h->h_length); 47 need += strlen(name)+1; 48 need += strlen(canon)+1; 49 need += align; 50 51 if (need > buflen) return ERANGE; 52 53 buf += align; 54 h->h_aliases = (void *)buf; 55 buf += 3*sizeof(char *); 56 h->h_addr_list = (void *)buf; 57 buf += (cnt+1)*sizeof(char *); 58 59 for (i=0; i<cnt; i++) { 60 h->h_addr_list[i] = (void *)buf; 61 buf += h->h_length; 62 memcpy(h->h_addr_list[i], addrs[i].addr, h->h_length); 63 } 64 h->h_addr_list[i] = 0; 65 66 h->h_name = h->h_aliases[0] = buf; 67 strcpy(h->h_name, canon); 68 buf += strlen(h->h_name)+1; 69 70 if (strcmp(h->h_name, name)) { 71 h->h_aliases[1] = buf; 72 strcpy(h->h_aliases[1], name); 73 buf += strlen(h->h_aliases[1])+1; 74 } else h->h_aliases[1] = 0; 75 76 h->h_aliases[2] = 0; 77 78 *res = h; 79 return 0; 80} 81