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