1 /* $OpenBSD: gethostnamadr.c,v 1.2 2012/11/24 15:12:48 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 <stdlib.h> 24 #include <string.h> 25 26 #include "asr.h" 27 28 static struct hostent *_gethostbyname(const char *, int); 29 static void _fillhostent(const struct hostent *, struct hostent *, char *buf, 30 size_t); 31 32 static struct hostent _hostent; 33 static char _entbuf[4096]; 34 35 static char *_empty[] = { NULL, }; 36 37 static void 38 _fillhostent(const struct hostent *h, struct hostent *r, char *buf, size_t len) 39 { 40 char **ptr, *end, *pos; 41 size_t n, i; 42 int naliases, naddrs; 43 44 end = buf + len; 45 ptr = (char**)buf; /* XXX align */ 46 47 for (naliases = 0; h->h_aliases[naliases]; naliases++) 48 ; 49 for (naddrs = 0; h->h_addr_list[naddrs]; naddrs++) 50 ; 51 52 r->h_name = NULL; 53 r->h_addrtype = h->h_addrtype; 54 r->h_length = h->h_length; 55 r->h_aliases = ptr; 56 r->h_addr_list = ptr + naliases + 1; 57 58 pos = (char*)(ptr + (naliases + 1) + (naddrs + 1)); 59 if (pos > end) { 60 r->h_aliases = _empty; 61 r->h_addr_list = _empty; 62 return; 63 } 64 bzero(ptr, pos - (char*)ptr); 65 66 n = strlcpy(pos, h->h_name, end - pos); 67 if (n >= end - pos) 68 return; 69 r->h_name = pos; 70 pos += n + 1; 71 72 for (i = 0; i < naliases; i++) { 73 n = strlcpy(pos, h->h_aliases[i], end - pos); 74 if (n >= end - pos) 75 return; 76 r->h_aliases[i] = pos; 77 pos += n + 1; 78 } 79 80 for (i = 0; i < naddrs; i++) { 81 if (r->h_length > end - pos) 82 return; 83 memmove(pos, h->h_addr_list[i], r->h_length); 84 r->h_addr_list[i] = pos; 85 pos += r->h_length; 86 } 87 } 88 89 static struct hostent * 90 _gethostbyname(const char *name, int af) 91 { 92 struct async *as; 93 struct async_res ar; 94 95 if (af == -1) 96 as = gethostbyname_async(name, NULL); 97 else 98 as = gethostbyname2_async(name, af, NULL); 99 100 if (as == NULL) { 101 h_errno = NETDB_INTERNAL; 102 return (NULL); 103 } 104 105 async_run_sync(as, &ar); 106 107 errno = ar.ar_errno; 108 h_errno = ar.ar_h_errno; 109 if (ar.ar_hostent == NULL) 110 return (NULL); 111 112 _fillhostent(ar.ar_hostent, &_hostent, _entbuf, sizeof(_entbuf)); 113 free(ar.ar_hostent); 114 115 return (&_hostent); 116 } 117 118 struct hostent * 119 gethostbyname(const char *name) 120 { 121 return _gethostbyname(name, -1); 122 } 123 124 struct hostent * 125 gethostbyname2(const char *name, int af) 126 { 127 return _gethostbyname(name, af); 128 } 129 130 struct hostent * 131 gethostbyaddr(const void *addr, socklen_t len, int af) 132 { 133 struct async *as; 134 struct async_res ar; 135 136 as = gethostbyaddr_async(addr, len, af, NULL); 137 if (as == NULL) { 138 h_errno = NETDB_INTERNAL; 139 return (NULL); 140 } 141 142 async_run_sync(as, &ar); 143 144 errno = ar.ar_errno; 145 h_errno = ar.ar_h_errno; 146 if (ar.ar_hostent == NULL) 147 return (NULL); 148 149 _fillhostent(ar.ar_hostent, &_hostent, _entbuf, sizeof(_entbuf)); 150 free(ar.ar_hostent); 151 152 return (&_hostent); 153 } 154