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