1 /* $NetBSD: dllfunc.c,v 1.3 2014/12/10 04:37:56 christos Exp $ */
2
3 /*
4 * dllfunc.c - wrapper functions
5 */
6
7 /*
8 * Copyright (c) 2000,2002 Japan Network Information Center.
9 * All rights reserved.
10 *
11 * By using this file, you agree to the terms and conditions set forth bellow.
12 *
13 * LICENSE TERMS AND CONDITIONS
14 *
15 * The following License Terms and Conditions apply, unless a different
16 * license is obtained from Japan Network Information Center ("JPNIC"),
17 * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
18 * Chiyoda-ku, Tokyo 101-0047, Japan.
19 *
20 * 1. Use, Modification and Redistribution (including distribution of any
21 * modified or derived work) in source and/or binary forms is permitted
22 * under this License Terms and Conditions.
23 *
24 * 2. Redistribution of source code must retain the copyright notices as they
25 * appear in each source code file, this License Terms and Conditions.
26 *
27 * 3. Redistribution in binary form must reproduce the Copyright Notice,
28 * this License Terms and Conditions, in the documentation and/or other
29 * materials provided with the distribution. For the purposes of binary
30 * distribution the "Copyright Notice" refers to the following language:
31 * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
32 *
33 * 4. The name of JPNIC may not be used to endorse or promote products
34 * derived from this Software without specific prior written approval of
35 * JPNIC.
36 *
37 * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
38 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
39 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
40 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
41 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
43 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
44 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
45 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
46 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
47 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
48 */
49
50 #include <windows.h>
51 #include <svcguid.h>
52 #include <stdio.h>
53 #include <stdlib.h>
54 #include <string.h>
55 #include <process.h>
56
57 #include "dlldef.h"
58
59 #ifndef EAI_MEMORY
60 #define EAI_MEMORY WSA_NOT_ENOUGH_MEMORY
61 #endif
62 #ifndef EAI_FAIL
63 #define EAI_FAIL WSANO_RECOVERY
64 #endif
65
66 static GUID guid_habn = SVCID_INET_HOSTADDRBYNAME;
67 static GUID guid_habis = SVCID_INET_HOSTADDRBYINETSTRING;
68
69 #define SVCID_IS_HABN(p) (memcmp(p, &guid_habn, sizeof(GUID)) == 0)
70 #define SVCID_IS_HABIS(p) (memcmp(p, &guid_habis, sizeof(GUID)) == 0)
71
72 /*
73 * Rename addrinfo to my_addrinfo for avoiding possible name conflict.
74 */
75 struct my_addrinfo {
76 int ai_flags;
77 int ai_family;
78 int ai_socktype;
79 int ai_protocol;
80 size_t ai_addrlen;
81 char *ai_canonname;
82 struct sockaddr *ai_addr;
83 struct my_addrinfo *ai_next;
84 };
85
86 typedef struct obj_lock {
87 void *key;
88 struct obj_lock *next;
89 } obj_lock_t;
90
91 #define OBJLOCKHASH_SIZE 127
92 static obj_lock_t *obj_lock_hash[OBJLOCKHASH_SIZE];
93
94 static int obj_hash(void *key);
95 static int obj_islocked(void *key);
96 static void obj_lock(void *key);
97 static void obj_unlock(void *key);
98 static char *decode_name_dynamic(const char *name, idn_resconf_t idnctx);
99 static struct my_addrinfo
100 *copy_decode_addrinfo_dynamic(struct my_addrinfo *aip,
101 idn_resconf_t idnctx);
102 static void free_copied_addrinfo(struct my_addrinfo *aip);
103
104 WRAPPER_EXPORT int WSAAPI
gethostname(char FAR * name,int namelen)105 gethostname(char FAR * name, int namelen) {
106 int ret;
107
108 TRACE("ENTER gethostname\n");
109 ret = _org_gethostname(name, namelen);
110 TRACE("LEAVE gethostname %d <%-.100s>\n", ret, name);
111
112 return (ret);
113 }
114
115 WRAPPER_EXPORT struct hostent FAR * WSAAPI
gethostbyname(const char FAR * name)116 gethostbyname(const char FAR * name) {
117 struct hostent FAR *ret;
118 char nbuff[256];
119 char hbuff[256];
120 BOOL stat;
121 idn_resconf_t encodeCtx;
122
123 TRACE("ENTER gethostbyname <%-.100s>\n",
124 (name != NULL ? name : "NULL"));
125
126 encodeCtx = idnGetContext();
127
128 if (encodeCtx == NULL || name == NULL) {
129 ret = _org_gethostbyname(name);
130 } else {
131 stat = idnConvReq(encodeCtx, name, nbuff, sizeof(nbuff));
132 if (stat == FALSE) {
133 TRACE("idnConvReq failed\n");
134 ret = NULL;
135 } else {
136 TRACE("Converted Name <%s>\n",
137 dumpName(nbuff, hbuff, sizeof(hbuff)));
138 ret = _org_gethostbyname(nbuff);
139 }
140 }
141
142 if (ret != NULL && encodeCtx != NULL) {
143 TRACE("Resulting Name <%s>\n",
144 dumpName(ret->h_name, hbuff, sizeof(hbuff)));
145 stat = idnConvRsp(encodeCtx, ret->h_name,
146 nbuff, sizeof(nbuff));
147 if (stat == FALSE) {
148 TRACE("Decoding failed - return the name verbatim\n");
149 } else {
150 TRACE("Converted Back <%s>\n",
151 dumpName(nbuff, hbuff, sizeof(hbuff)));
152 strcpy(ret->h_name, nbuff);
153 }
154 }
155
156 if (ret == NULL) {
157 TRACE("LEAVE gethostbyname NULL\n");
158 } else {
159 TRACE("LEAVE gethostbyname <%s>\n",
160 dumpHost(ret, hbuff, sizeof(hbuff)));
161 }
162 return (ret);
163 }
164
165 WRAPPER_EXPORT struct hostent FAR * WSAAPI
gethostbyaddr(const char FAR * addr,int len,int type)166 gethostbyaddr(const char FAR * addr, int len, int type) {
167 struct hostent FAR *ret;
168 char nbuff[256];
169 char abuff[256];
170 char hbuff[256];
171 BOOL stat;
172 idn_resconf_t encodeCtx;
173
174 TRACE("ENTER gethostbyaddr <%s>\n",
175 dumpAddr(addr, len, abuff, sizeof(abuff)));
176
177 encodeCtx = idnGetContext();
178
179 ret = _org_gethostbyaddr(addr, len, type);
180
181 if (ret != NULL && encodeCtx != NULL) {
182 TRACE("Resulting Name <%s>\n",
183 dumpName(ret->h_name, hbuff, sizeof(hbuff)));
184 stat = idnConvRsp(encodeCtx, ret->h_name,
185 nbuff, sizeof(nbuff));
186 if (stat == FALSE) {
187 TRACE("Decoding failed - return the name verbatim\n");
188 } else {
189 TRACE("Converted Back <%s>\n",
190 dumpName(nbuff, hbuff, sizeof(hbuff)));
191 strcpy(ret->h_name, nbuff);
192 }
193 }
194
195 if (ret == NULL) {
196 TRACE("LEAVE gethostbyaddr NULL\n");
197 } else {
198 TRACE("LEAVE gethostbyaddr <%s>\n",
199 dumpHost(ret, hbuff, sizeof(hbuff)));
200 }
201 return (ret);
202 }
203
204 WRAPPER_EXPORT HANDLE WSAAPI
WSAAsyncGetHostByName(HWND hWnd,u_int wMsg,const char FAR * name,char FAR * buf,int buflen)205 WSAAsyncGetHostByName(HWND hWnd, u_int wMsg,
206 const char FAR * name, char FAR * buf, int buflen)
207 {
208 HANDLE ret;
209 char nbuff[256];
210 char hbuff[256];
211 idn_resconf_t encodeCtx;
212
213 TRACE("ENTER WSAAsyncGetHostByName <%-.100s>\n", name);
214
215 encodeCtx = idnGetContext();
216
217 if (encodeCtx == NULL || name == NULL) {
218 ret = _org_WSAAsyncGetHostByName(hWnd, wMsg,
219 name, buf, buflen);
220 } else {
221 idnHook(hWnd, wMsg, buf, encodeCtx);
222 idnConvReq(encodeCtx, name, nbuff, sizeof(nbuff));
223 TRACE("Converted Name <%s>\n",
224 dumpName(nbuff, hbuff, sizeof(hbuff)));
225 ret = _org_WSAAsyncGetHostByName(hWnd, wMsg, nbuff,
226 buf, buflen);
227 }
228
229 TRACE("LEAVE WSAAsyncGetHostByName HANDLE %08x\n", ret);
230
231 return (ret);
232 }
233
234 WRAPPER_EXPORT HANDLE WSAAPI
WSAAsyncGetHostByAddr(HWND hWnd,u_int wMsg,const char FAR * addr,int len,int type,char FAR * buf,int buflen)235 WSAAsyncGetHostByAddr(HWND hWnd, u_int wMsg, const char FAR * addr,
236 int len, int type, char FAR * buf, int buflen)
237 {
238 HANDLE ret;
239 char abuff[256];
240 idn_resconf_t encodeCtx;
241
242 encodeCtx = idnGetContext();
243
244 if (encodeCtx != NULL) {
245 idnHook(hWnd, wMsg, buf, encodeCtx);
246 }
247
248 TRACE("ENTER WSAAsyncGetHostByAddr <%s>\n",
249 dumpAddr(addr, len, abuff, sizeof(abuff)));
250 ret = _org_WSAAsyncGetHostByAddr(hWnd, wMsg, addr, len, type,
251 buf, buflen);
252 TRACE("LEAVE WSAAsyncGetHostByAddr HANDLE %08x\n", ret);
253
254 return (ret);
255 }
256
257 WRAPPER_EXPORT INT WSAAPI
WSALookupServiceBeginA(LPWSAQUERYSETA lpqsRestrictions,DWORD dwControlFlags,LPHANDLE lphLookup)258 WSALookupServiceBeginA(LPWSAQUERYSETA lpqsRestrictions,
259 DWORD dwControlFlags, LPHANDLE lphLookup)
260 {
261 INT ret;
262 char nbuff[256];
263 char hbuff[256];
264 LPSTR name = lpqsRestrictions->lpszServiceInstanceName;
265 LPGUID class = lpqsRestrictions->lpServiceClassId;
266 idn_resconf_t encodeCtx;
267
268 TRACE("ENTER WSALookupServiceBeginA <%-.100s>\n",
269 name == NULL ? "<NULL>" : name);
270
271 encodeCtx = idnGetContext();
272
273 if (name != NULL && encodeCtx != NULL && SVCID_IS_HABN(class) == 0) {
274 idnConvReq(encodeCtx, name, nbuff, sizeof(nbuff));
275 TRACE("Converted Name <%s>\n",
276 dumpName(nbuff, hbuff, sizeof(hbuff)));
277 /* strcpy(lpqsRestrictions->lpszQueryString, nbuff); */
278 lpqsRestrictions->lpszServiceInstanceName = nbuff;
279 }
280 ret = _org_WSALookupServiceBeginA(lpqsRestrictions,
281 dwControlFlags, lphLookup);
282 TRACE("LEAVE WSALookupServiceBeginA %d\n", ret);
283
284 return (ret);
285 }
286
287 WRAPPER_EXPORT INT WSAAPI
WSALookupServiceNextA(HANDLE hLookup,DWORD dwControlFlags,LPDWORD lpdwBufferLength,LPWSAQUERYSETA lpqsResults)288 WSALookupServiceNextA(HANDLE hLookup, DWORD dwControlFlags,
289 LPDWORD lpdwBufferLength, LPWSAQUERYSETA lpqsResults)
290 {
291 INT ret;
292 char nbuff[256];
293 char hbuff[256];
294 LPGUID class;
295 idn_resconf_t encodeCtx;
296
297 TRACE("ENTER WSALookupServiceNextA\n");
298
299 encodeCtx = idnGetContext();
300
301 ret = _org_WSALookupServiceNextA(hLookup, dwControlFlags,
302 lpdwBufferLength, lpqsResults);
303 class = lpqsResults->lpServiceClassId;
304
305 if (ret == 0 &&
306 encodeCtx != NULL &&
307 (dwControlFlags & LUP_RETURN_NAME) &&
308 (SVCID_IS_HABN(class) || SVCID_IS_HABIS(class))) {
309 TRACE("Resulting Name <%s>\n",
310 dumpName(lpqsResults->lpszServiceInstanceName,
311 hbuff, sizeof(hbuff)));
312 if (idnConvRsp(encodeCtx,
313 lpqsResults->lpszServiceInstanceName,
314 nbuff, sizeof(nbuff)) == FALSE) {
315 TRACE("Decoding failed - return the name verbatim\n");
316 } else {
317 TRACE("Converted Back <%s>\n",
318 dumpName(nbuff, hbuff, sizeof(hbuff)));
319 strcpy(lpqsResults->lpszServiceInstanceName, nbuff);
320 }
321 }
322 TRACE("LEAVE WSALookupServiceNextA %d <%s>\n", ret, nbuff);
323
324 return (ret);
325 }
326
327 WRAPPER_EXPORT INT WSAAPI
WSALookupServiceBeginW(LPWSAQUERYSETW lpqsRestrictions,DWORD dwControlFlags,LPHANDLE lphLookup)328 WSALookupServiceBeginW(LPWSAQUERYSETW lpqsRestrictions,
329 DWORD dwControlFlags, LPHANDLE lphLookup)
330 {
331 INT ret;
332
333 TRACE("ENTER WSALookupServiceBeginW\n");
334 ret = _org_WSALookupServiceBeginW(lpqsRestrictions,
335 dwControlFlags,lphLookup);
336 TRACE("LEAVE WSALookupServiceBeginW %d\n", ret);
337
338 return (ret);
339 }
340
341 WRAPPER_EXPORT INT WSAAPI
WSALookupServiceNextW(HANDLE hLookup,DWORD dwControlFlags,LPDWORD lpdwBufferLength,LPWSAQUERYSETW lpqsResults)342 WSALookupServiceNextW(HANDLE hLookup, DWORD dwControlFlags,
343 LPDWORD lpdwBufferLength, LPWSAQUERYSETW lpqsResults)
344 {
345 INT ret;
346
347 TRACE("ENTER WSALookupServiceNextW\n");
348 ret = _org_WSALookupServiceNextW(hLookup, dwControlFlags,
349 lpdwBufferLength, lpqsResults);
350 TRACE("LEAVE WSALookupServiceNextW %d\n", ret);
351
352 return (ret);
353 }
354
355 WRAPPER_EXPORT INT WSAAPI
WSALookupServiceEnd(HANDLE hLookup)356 WSALookupServiceEnd(HANDLE hLookup) {
357 INT ret;
358
359 TRACE("ENTER WSALookupServiceEnd\n");
360 ret = _org_WSALookupServiceEnd(hLookup);
361 TRACE("LEAVE WSALookupServiceEnd %d\n", ret);
362
363 return (ret);
364 }
365
366 static int
obj_hash(void * key)367 obj_hash(void *key) {
368 /*
369 * Hash function for obj_*.
370 * 'key' is supposed to be an address.
371 */
372 unsigned long v = (unsigned long)key;
373
374 return ((v >> 3) % OBJLOCKHASH_SIZE);
375 }
376
377 static int
obj_islocked(void * key)378 obj_islocked(void *key)
379 {
380 /*
381 * Check if the object specified by 'key' is locked.
382 * Return 1 if so, 0 otherwise.
383 */
384 int h = obj_hash(key);
385 obj_lock_t *olp = obj_lock_hash[h];
386
387 while (olp != NULL) {
388 if (olp->key == key)
389 return (1);
390 olp = olp->next;
391 }
392 return (0);
393 }
394
395 static void
obj_lock(void * key)396 obj_lock(void *key)
397 {
398 /*
399 * Lock an object specified by 'key'.
400 */
401 int h = obj_hash(key);
402 obj_lock_t *olp;
403
404 olp = malloc(sizeof(obj_lock_t));
405 if (olp != NULL) {
406 olp->key = key;
407 olp->next = obj_lock_hash[h];
408 obj_lock_hash[h] = olp;
409 }
410 }
411
412 static void
obj_unlock(void * key)413 obj_unlock(void *key)
414 {
415 /*
416 * Unlock an object specified by 'key'.
417 */
418 int h = obj_hash(key);
419 obj_lock_t *olp, *olp0;
420
421 olp = obj_lock_hash[h];
422 olp0 = NULL;
423 while (olp != NULL) {
424 if (olp->key == key) {
425 if (olp0 == NULL)
426 obj_lock_hash[h] = olp->next;
427 else
428 olp0->next = olp->next;
429 free(olp);
430 return;
431 }
432 olp0 = olp;
433 olp = olp->next;
434 }
435 }
436
437 static char *
decode_name_dynamic(const char * name,idn_resconf_t idnctx)438 decode_name_dynamic(const char *name, idn_resconf_t idnctx) {
439 BOOL stat;
440 char buf[256], tmp[256];
441 char *s;
442
443 if (idnConvRsp(idnctx, name, buf, sizeof(buf)) == TRUE) {
444 TRACE("Converted Back <%s>\n",
445 dumpName(buf, tmp, sizeof(tmp)));
446 name = buf;
447 } else {
448 TRACE("Decoding failed - return the name verbatim\n");
449 }
450 s = malloc(strlen(name) + 1);
451 if (s == NULL)
452 return (NULL);
453 else
454 return (strcpy(s, name));
455 }
456
457 static struct my_addrinfo *
copy_decode_addrinfo_dynamic(struct my_addrinfo * aip,idn_resconf_t idnctx)458 copy_decode_addrinfo_dynamic(struct my_addrinfo *aip, idn_resconf_t idnctx)
459 {
460 struct my_addrinfo *newaip;
461
462 if (aip == NULL)
463 return (NULL);
464
465 newaip = malloc(sizeof(struct my_addrinfo) + aip->ai_addrlen);
466 if (newaip == NULL)
467 return (NULL);
468
469 *newaip = *aip;
470 newaip->ai_addr = (struct sockaddr *)(newaip + 1);
471 memcpy(newaip->ai_addr, aip->ai_addr, aip->ai_addrlen);
472
473 if (newaip->ai_canonname != NULL)
474 newaip->ai_canonname = decode_name_dynamic(aip->ai_canonname,
475 idnctx);
476
477 newaip->ai_next = copy_decode_addrinfo_dynamic(aip->ai_next, idnctx);
478 return (newaip);
479 }
480
481 static void
free_copied_addrinfo(struct my_addrinfo * aip)482 free_copied_addrinfo(struct my_addrinfo *aip) {
483 while (aip != NULL) {
484 struct my_addrinfo *next = aip->ai_next;
485
486 if (aip->ai_canonname != NULL)
487 free(aip->ai_canonname);
488 free(aip);
489 aip = next;
490 }
491 }
492
493 WRAPPER_EXPORT int WSAAPI
getaddrinfo(const char * nodename,const char * servname,const struct my_addrinfo * hints,struct my_addrinfo ** res)494 getaddrinfo(const char *nodename, const char *servname,
495 const struct my_addrinfo *hints, struct my_addrinfo **res)
496 {
497 char namebuf[256];
498 BOOL stat;
499 struct my_addrinfo *aip;
500 int err;
501 idn_resconf_t encodeCtx;
502
503 TRACE("ENTER getaddrinfo <%-.100s>\n", nodename ? nodename : "NULL");
504
505 encodeCtx = idnGetContext();
506
507 if (nodename == NULL || encodeCtx == NULL) {
508 TRACE("conversion unnecessary\n");
509 err = _org_getaddrinfo(nodename, servname, hints, res);
510 } else {
511 stat = idnConvReq(encodeCtx, nodename,
512 namebuf, sizeof(namebuf));
513 if (stat == TRUE) {
514 nodename = namebuf;
515 TRACE("Converted Name <%-.100s>\n", namebuf);
516 }
517
518 err = _org_getaddrinfo(nodename, servname, hints, &aip);
519 if (err == 0 && aip != NULL) {
520 *res = copy_decode_addrinfo_dynamic(aip, encodeCtx);
521 if (*res == NULL)
522 err = EAI_FAIL;
523 else
524 obj_lock(*res);
525 if (aip != NULL)
526 _org_freeaddrinfo(aip);
527 }
528 }
529
530 TRACE("LEAVE getaddrinfo %d\n", err);
531 return (err);
532 }
533
534 WRAPPER_EXPORT void WSAAPI
freeaddrinfo(struct my_addrinfo * aip)535 freeaddrinfo(struct my_addrinfo *aip) {
536 TRACE("ENTER freeaddrinfo aip=%p\n", (void *)aip);
537
538 if (obj_islocked(aip)) {
539 /*
540 * We allocated the data.
541 */
542 obj_unlock(aip);
543 free_copied_addrinfo(aip);
544 } else {
545 /*
546 * It was allocated the original getaddrinfo().
547 */
548 TRACE("Not allocated by the wrapper\n");
549 _org_freeaddrinfo(aip);
550 }
551 TRACE("LEAVE freeaddrinfo\n");
552 }
553
554 WRAPPER_EXPORT int WSAAPI
getnameinfo(const struct sockaddr * sa,DWORD salen,char * host,DWORD hostlen,char * serv,DWORD servlen,int flags)555 getnameinfo(const struct sockaddr *sa, DWORD salen,
556 char *host, DWORD hostlen, char *serv,
557 DWORD servlen, int flags)
558 {
559 char name[256];
560 size_t namelen = sizeof(name);
561 int code;
562 BOOL stat;
563 idn_resconf_t encodeCtx;
564
565 TRACE("ENTER getnameinfo\n");
566
567 encodeCtx = idnGetContext();
568
569 if (host == NULL || hostlen == 0 || encodeCtx == NULL) {
570 TRACE("conversion unnecessary\n");
571 code = _org_getnameinfo(sa, salen, host, hostlen,
572 serv, servlen, flags);
573 } else {
574 code = _org_getnameinfo(sa, salen, name, namelen,
575 serv, servlen, flags);
576 if (code == 0 && name[0] != '\0') {
577 stat = idnConvRsp(encodeCtx, name, host, hostlen);
578 if (stat == FALSE) {
579 TRACE("Decoding failed - return the name verbatim\n");
580 if (strlen(name) >= hostlen) {
581 code = EAI_FAIL;
582 } else {
583 strcpy(host, name);
584 }
585 } else {
586 TRACE("Converted Back <%s>\n",
587 dumpName(host, name, sizeof(name)));
588 }
589 }
590 }
591
592 TRACE("LEAVE getnameinfo %d\n", code);
593 return (code);
594 }
595