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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 * 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 * 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 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 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 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 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