1 /* $OpenBSD: gethostnamadr.c,v 1.3 2013/04/01 07:47:26 eric Exp $ */ 2 /* 3 * Copyright (c) 2012 Eric Faurot <eric@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <sys/types.h> 19 #include <netinet/in.h> 20 21 #include <errno.h> 22 #include <resolv.h> 23 #include <stdint.h> 24 #include <stdlib.h> 25 #include <string.h> 26 27 #include "asr.h" 28 29 #define PALIGN(p, l) \ 30 ((char*)(p) + (((uintptr_t)(p) % (l)) ? \ 31 (l) - (uintptr_t)(p) % (l) : 0)) 32 33 static struct hostent *_gethostbyname(const char *, int); 34 static void _fillhostent(const struct hostent *, struct hostent *, char *buf, 35 size_t); 36 37 static struct hostent _hostent; 38 static char _entbuf[4096]; 39 40 static char *_empty[] = { NULL, }; 41 42 static void 43 _fillhostent(const struct hostent *h, struct hostent *r, char *buf, size_t len) 44 { 45 char **ptr, *end, *pos; 46 size_t n, i; 47 int naliases, naddrs; 48 49 bzero(buf, len); 50 bzero(r, sizeof(*r)); 51 r->h_aliases = _empty; 52 r->h_addr_list = _empty; 53 54 end = buf + len; 55 ptr = (char**)PALIGN(buf, sizeof(char*)); 56 57 if ((char*)ptr >= end) 58 return; 59 60 for (naliases = 0; h->h_aliases[naliases]; naliases++) 61 ; 62 for (naddrs = 0; h->h_addr_list[naddrs]; naddrs++) 63 ; 64 65 pos = (char*)(ptr + (naliases + 1) + (naddrs + 1)); 66 if (pos >= end) 67 return; 68 69 r->h_name = NULL; 70 r->h_addrtype = h->h_addrtype; 71 r->h_length = h->h_length; 72 r->h_aliases = ptr; 73 r->h_addr_list = ptr + naliases + 1; 74 75 n = strlcpy(pos, h->h_name, end - pos); 76 if (n >= end - pos) 77 return; 78 r->h_name = pos; 79 pos += n + 1; 80 81 for (i = 0; i < naliases; i++) { 82 n = strlcpy(pos, h->h_aliases[i], end - pos); 83 if (n >= end - pos) 84 return; 85 r->h_aliases[i] = pos; 86 pos += n + 1; 87 } 88 89 pos = PALIGN(pos, r->h_length); 90 if (pos >= end) 91 return; 92 93 for (i = 0; i < naddrs; i++) { 94 if (r->h_length > end - pos) 95 return; 96 memmove(pos, h->h_addr_list[i], r->h_length); 97 r->h_addr_list[i] = pos; 98 pos += r->h_length; 99 } 100 } 101 102 static struct hostent * 103 _gethostbyname(const char *name, int af) 104 { 105 struct async *as; 106 struct async_res ar; 107 108 if (af == -1) 109 as = gethostbyname_async(name, NULL); 110 else 111 as = gethostbyname2_async(name, af, NULL); 112 113 if (as == NULL) { 114 h_errno = NETDB_INTERNAL; 115 return (NULL); 116 } 117 118 async_run_sync(as, &ar); 119 120 errno = ar.ar_errno; 121 h_errno = ar.ar_h_errno; 122 if (ar.ar_hostent == NULL) 123 return (NULL); 124 125 _fillhostent(ar.ar_hostent, &_hostent, _entbuf, sizeof(_entbuf)); 126 free(ar.ar_hostent); 127 128 return (&_hostent); 129 } 130 131 struct hostent * 132 gethostbyname(const char *name) 133 { 134 return _gethostbyname(name, -1); 135 } 136 137 struct hostent * 138 gethostbyname2(const char *name, int af) 139 { 140 return _gethostbyname(name, af); 141 } 142 143 struct hostent * 144 gethostbyaddr(const void *addr, socklen_t len, int af) 145 { 146 struct async *as; 147 struct async_res ar; 148 149 as = gethostbyaddr_async(addr, len, af, NULL); 150 if (as == NULL) { 151 h_errno = NETDB_INTERNAL; 152 return (NULL); 153 } 154 155 async_run_sync(as, &ar); 156 157 errno = ar.ar_errno; 158 h_errno = ar.ar_h_errno; 159 if (ar.ar_hostent == NULL) 160 return (NULL); 161 162 _fillhostent(ar.ar_hostent, &_hostent, _entbuf, sizeof(_entbuf)); 163 free(ar.ar_hostent); 164 165 return (&_hostent); 166 } 167