1 /* $NetBSD: stub.c,v 1.4 2014/12/10 04:37:56 christos Exp $ */ 2 3 #ifndef lint 4 static char *rcsid = "Id: stub.c,v 1.1 2003/06/04 00:27:13 marka Exp "; 5 #endif 6 7 /* 8 * Copyright (c) 2001 Japan Network Information Center. All rights reserved. 9 * 10 * By using this file, you agree to the terms and conditions set forth bellow. 11 * 12 * LICENSE TERMS AND CONDITIONS 13 * 14 * The following License Terms and Conditions apply, unless a different 15 * license is obtained from Japan Network Information Center ("JPNIC"), 16 * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda, 17 * Chiyoda-ku, Tokyo 101-0047, Japan. 18 * 19 * 1. Use, Modification and Redistribution (including distribution of any 20 * modified or derived work) in source and/or binary forms is permitted 21 * under this License Terms and Conditions. 22 * 23 * 2. Redistribution of source code must retain the copyright notices as they 24 * appear in each source code file, this License Terms and Conditions. 25 * 26 * 3. Redistribution in binary form must reproduce the Copyright Notice, 27 * this License Terms and Conditions, in the documentation and/or other 28 * materials provided with the distribution. For the purposes of binary 29 * distribution the "Copyright Notice" refers to the following language: 30 * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved." 31 * 32 * 4. The name of JPNIC may not be used to endorse or promote products 33 * derived from this Software without specific prior written approval of 34 * JPNIC. 35 * 36 * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC 37 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 38 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 39 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE 40 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 41 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 42 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 43 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 44 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 45 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 46 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 47 */ 48 49 #include <config.h> 50 51 #include <stdarg.h> 52 #include <stdlib.h> 53 #include <string.h> 54 #include <sys/types.h> 55 #include <sys/socket.h> 56 #include <netdb.h> 57 #include <errno.h> 58 #ifdef HAVE_DLFCN_H 59 #include <dlfcn.h> 60 #endif 61 62 #include <idn/logmacro.h> 63 #include <idn/debug.h> 64 65 #include "stub.h" 66 67 #ifndef RTLD_NEXT 68 typedef struct { 69 const char *name; 70 void *handle; 71 } shared_obj_t; 72 73 static shared_obj_t shobj[] = { 74 #ifdef SOPATH_LIBC 75 { SOPATH_LIBC }, 76 #endif 77 #ifdef SOPATH_LIBNSL 78 { SOPATH_LIBNSL }, 79 #endif 80 { NULL }, 81 }; 82 #endif 83 84 static void *shared_obj_findsym(void *handle, const char *name); 85 static void *shared_obj_findsymx(void *handle, const char *name); 86 static void *get_func_addr(const char *name); 87 88 #ifndef RTLD_NEXT 89 static void * 90 shared_obj_open(const char *path) { 91 #ifdef HAVE_DLOPEN 92 return (dlopen(path, RTLD_LAZY)); 93 #endif 94 FATAL(("stub: no way to load shared object file\n")); 95 return (NULL); 96 } 97 #endif 98 99 static void * 100 shared_obj_findsym(void *handle, const char *name) { 101 char namebuf[100]; 102 void *addr; 103 static int need_leading_underscore = -1; 104 105 /* Prepend underscore. */ 106 namebuf[0] = '_'; 107 (void)strcpy(namebuf + 1, name); 108 name = namebuf; 109 110 if (need_leading_underscore < 0) { 111 /* First try without one. */ 112 if ((addr = shared_obj_findsymx(handle, name + 1)) != NULL) { 113 need_leading_underscore = 0; 114 return (addr); 115 } 116 /* Then try with one. */ 117 if ((addr = shared_obj_findsymx(handle, name)) != NULL) { 118 need_leading_underscore = 1; 119 return (addr); 120 } 121 } else if (need_leading_underscore) { 122 return (shared_obj_findsymx(handle, name)); 123 } else { 124 return (shared_obj_findsymx(handle, name + 1)); 125 } 126 return (NULL); 127 } 128 129 static void * 130 shared_obj_findsymx(void *handle, const char *name) { 131 #ifdef HAVE_DLSYM 132 return (dlsym(handle, name)); 133 #endif 134 /* logging */ 135 FATAL(("stub: no way to get symbol address\n")); 136 return (NULL); 137 } 138 139 static void * 140 get_func_addr(const char *name) { 141 #ifdef RTLD_NEXT 142 void *addr = shared_obj_findsym(RTLD_NEXT, name); 143 144 if (addr != NULL) { 145 TRACE(("stub: %s found in the subsequent objects\n", name)); 146 return (addr); 147 } 148 #else 149 int i; 150 151 for (i = 0; shobj[i].name != NULL; i++) { 152 if (shobj[i].handle == NULL) { 153 TRACE(("stub: loading %s\n", shobj[i].name)); 154 shobj[i].handle = shared_obj_open(shobj[i].name); 155 } 156 if (shobj[i].handle != NULL) { 157 void *addr = shared_obj_findsym(shobj[i].handle, name); 158 if (addr != NULL) { 159 TRACE(("stub: %s found in %s\n", 160 name, shobj[i].name)); 161 return (addr); 162 } 163 } 164 } 165 #endif 166 TRACE(("stub: %s not found\n", name)); 167 return (NULL); 168 } 169 170 #ifdef HAVE_GETHOSTBYNAME 171 struct hostent * 172 idn_stub_gethostbyname(const char *name) { 173 static struct hostent *(*fp)(const char *name); 174 175 if (fp == NULL) 176 fp = get_func_addr("gethostbyname"); 177 if (fp != NULL) 178 return ((*fp)(name)); 179 return (NULL); 180 } 181 #endif 182 183 #ifdef HAVE_GETHOSTBYNAME2 184 struct hostent * 185 idn_stub_gethostbyname2(const char *name, int af) { 186 static struct hostent *(*fp)(const char *name, int af); 187 188 if (fp == NULL) 189 fp = get_func_addr("gethostbyname2"); 190 if (fp != NULL) 191 return ((*fp)(name, af)); 192 return (NULL); 193 } 194 #endif 195 196 #ifdef HAVE_GETHOSTBYADDR 197 struct hostent * 198 idn_stub_gethostbyaddr(GHBA_ADDR_T addr, GHBA_ADDRLEN_T len, int type) { 199 static struct hostent *(*fp)(GHBA_ADDR_T name, 200 GHBA_ADDRLEN_T len, int type); 201 202 if (fp == NULL) 203 fp = get_func_addr("gethostbyaddr"); 204 if (fp != NULL) 205 return ((*fp)(addr, len, type)); 206 return (NULL); 207 } 208 #endif 209 210 #ifdef GETHOST_R_GLIBC_FLAVOR 211 212 #ifdef HAVE_GETHOSTBYNAME_R 213 int 214 idn_stub_gethostbyname_r(const char *name, struct hostent *result, 215 char *buffer, size_t buflen, 216 struct hostent **rp, int *errp) 217 { 218 static int (*fp)(const char *name, struct hostent *result, 219 char *buffer, size_t buflen, 220 struct hostent **rp, int *errp); 221 222 if (fp == NULL) 223 fp = get_func_addr("gethostbyname_r"); 224 if (fp != NULL) 225 return ((*fp)(name, result, buffer, buflen, rp, errp)); 226 return (ENOENT); /* ??? */ 227 } 228 #endif 229 230 #ifdef HAVE_GETHOSTBYNAME2_R 231 int 232 idn_stub_gethostbyname2_r(const char *name, int af, struct hostent *result, 233 char *buffer, size_t buflen, 234 struct hostent **rp, int *errp) 235 { 236 static int (*fp)(const char *name, int af, struct hostent *result, 237 char *buffer, size_t buflen, 238 struct hostent **rp, int *errp); 239 240 if (fp == NULL) 241 fp = get_func_addr("gethostbyname2_r"); 242 if (fp != NULL) 243 return ((*fp)(name, af, result, buffer, buflen, rp, errp)); 244 return (ENOENT); /* ??? */ 245 } 246 #endif 247 248 #ifdef HAVE_GETHOSTBYADDR_R 249 int 250 idn_stub_gethostbyaddr_r(GHBA_ADDR_T addr, GHBA_ADDRLEN_T len, int type, 251 struct hostent *result, char *buffer, 252 size_t buflen, struct hostent **rp, int *errp) 253 { 254 static int (*fp)(GHBA_ADDR_T addr, GHBA_ADDRLEN_T len, int type, 255 struct hostent *result, char *buffer, 256 size_t buflen, struct hostent **rp, int *errp); 257 258 if (fp == NULL) 259 fp = get_func_addr("gethostbyaddr_r"); 260 if (fp != NULL) 261 return ((*fp)(addr, len, type, result, 262 buffer, buflen, rp, errp)); 263 return (ENOENT); /* ??? */ 264 } 265 #endif 266 267 #else /* GETHOST_R_GLIBC_FLAVOR */ 268 269 #ifdef HAVE_GETHOSTBYNAME_R 270 struct hostent * 271 idn_stub_gethostbyname_r(const char *name, struct hostent *result, 272 char *buffer, int buflen, int *errp) 273 { 274 static struct hostent *(*fp)(const char *name, struct hostent *result, 275 char *buffer, int buflen, int *errp); 276 277 if (fp == NULL) 278 fp = get_func_addr("gethostbyname_r"); 279 if (fp != NULL) 280 return ((*fp)(name, result, buffer, buflen, errp)); 281 return (NULL); 282 } 283 #endif 284 285 #ifdef HAVE_GETHOSTBYADDR_R 286 struct hostent * 287 idn_stub_gethostbyaddr_r(GHBA_ADDR_T addr, int len, int type, 288 struct hostent *result, char *buffer, 289 int buflen, int *errp) 290 { 291 static struct hostent *(*fp)(GHBA_ADDR_T addr, int len, int type, 292 struct hostent *result, char *buffer, 293 int buflen, int *errp); 294 295 if (fp == NULL) 296 fp = get_func_addr("gethostbyaddr_r"); 297 if (fp != NULL) 298 return ((*fp)(addr, len, type, result, buffer, buflen, errp)); 299 return (NULL); 300 } 301 #endif 302 303 #endif /* GETHOST_R_GLIBC_FLAVOR */ 304 305 #ifdef HAVE_GETIPNODEBYNAME 306 struct hostent * 307 idn_stub_getipnodebyname(const char *name, int af, int flags, int *errp) { 308 static struct hostent *(*fp)(const char *name, int af, int flags, 309 int *errp); 310 311 if (fp == NULL) 312 fp = get_func_addr("getipnodebyname"); 313 if (fp != NULL) 314 return ((*fp)(name, af, flags, errp)); 315 return (NULL); 316 } 317 #endif 318 319 #ifdef HAVE_GETIPNODEBYADDR 320 struct hostent * 321 idn_stub_getipnodebyaddr(const void *src, size_t len, int af, int *errp) { 322 static struct hostent *(*fp)(const void *src, size_t len, int af, 323 int *errp); 324 325 if (fp == NULL) 326 fp = get_func_addr("getipnodebyaddr"); 327 if (fp != NULL) 328 return ((*fp)(src, len, af, errp)); 329 return (NULL); 330 } 331 #endif 332 333 #ifdef HAVE_FREEHOSTENT 334 void 335 idn_stub_freehostent(struct hostent *hp) { 336 static void (*fp)(struct hostent *hp); 337 338 if (fp == NULL) 339 fp = get_func_addr("freehostent"); 340 if (fp != NULL) 341 (*fp)(hp); 342 } 343 #endif 344 345 #ifdef HAVE_GETADDRINFO 346 int 347 idn_stub_getaddrinfo(const char *nodename, const char *servname, 348 const struct addrinfo *hints, struct addrinfo **res) 349 { 350 static int (*fp)(const char *nodename, const char *servname, 351 const struct addrinfo *hints, struct addrinfo **res); 352 353 if (fp == NULL) 354 fp = get_func_addr("getaddrinfo"); 355 if (fp != NULL) 356 return ((*fp)(nodename, servname, hints, res)); 357 return (EAI_FAIL); 358 } 359 #endif 360 361 #ifdef HAVE_FREEADDRINFO 362 void 363 idn_stub_freeaddrinfo(struct addrinfo *aip) { 364 static void (*fp)(struct addrinfo *aip); 365 366 if (fp == NULL) 367 fp = get_func_addr("freeaddrinfo"); 368 if (fp != NULL) 369 (*fp)(aip); 370 } 371 #endif 372 373 #ifdef HAVE_GETNAMEINFO 374 int 375 idn_stub_getnameinfo(const struct sockaddr *sa, GNI_SALEN_T salen, 376 char *host, GNI_HOSTLEN_T hostlen, 377 char *serv, GNI_SERVLEN_T servlen, GNI_FLAGS_T flags) { 378 static int (*fp)(const struct sockaddr *sa, GNI_SALEN_T salen, 379 char *host, GNI_HOSTLEN_T hostlen, 380 char *serv, GNI_SERVLEN_T servlen, 381 GNI_FLAGS_T flags); 382 383 if (fp == NULL) 384 fp = get_func_addr("getnameinfo"); 385 if (fp != NULL) 386 return ((*fp)(sa, salen, host, hostlen, serv, servlen, flags)); 387 return (EAI_FAIL); 388 } 389 #endif 390