gethostbyname2_r.c raw

   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  
  11  int 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