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 *
shared_obj_open(const char * path)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 *
shared_obj_findsym(void * handle,const char * name)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 *
shared_obj_findsymx(void * handle,const char * name)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 *
get_func_addr(const char * name)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 *
idn_stub_gethostbyname(const char * name)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 *
idn_stub_gethostbyname2(const char * name,int af)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 *
idn_stub_gethostbyaddr(GHBA_ADDR_T addr,GHBA_ADDRLEN_T len,int type)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
idn_stub_gethostbyname_r(const char * name,struct hostent * result,char * buffer,size_t buflen,struct hostent ** rp,int * errp)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
idn_stub_gethostbyname2_r(const char * name,int af,struct hostent * result,char * buffer,size_t buflen,struct hostent ** rp,int * errp)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
idn_stub_gethostbyaddr_r(GHBA_ADDR_T addr,GHBA_ADDRLEN_T len,int type,struct hostent * result,char * buffer,size_t buflen,struct hostent ** rp,int * errp)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 *
idn_stub_gethostbyname_r(const char * name,struct hostent * result,char * buffer,int buflen,int * errp)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 *
idn_stub_gethostbyaddr_r(GHBA_ADDR_T addr,int len,int type,struct hostent * result,char * buffer,int buflen,int * errp)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 *
idn_stub_getipnodebyname(const char * name,int af,int flags,int * errp)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 *
idn_stub_getipnodebyaddr(const void * src,size_t len,int af,int * errp)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
idn_stub_freehostent(struct hostent * hp)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
idn_stub_getaddrinfo(const char * nodename,const char * servname,const struct addrinfo * hints,struct addrinfo ** res)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
idn_stub_freeaddrinfo(struct addrinfo * aip)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
idn_stub_getnameinfo(const struct sockaddr * sa,GNI_SALEN_T salen,char * host,GNI_HOSTLEN_T hostlen,char * serv,GNI_SERVLEN_T servlen,GNI_FLAGS_T flags)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