11cb0ef41Sopenharmony_ci/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. 21cb0ef41Sopenharmony_ci * 31cb0ef41Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy 41cb0ef41Sopenharmony_ci * of this software and associated documentation files (the "Software"), to 51cb0ef41Sopenharmony_ci * deal in the Software without restriction, including without limitation the 61cb0ef41Sopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 71cb0ef41Sopenharmony_ci * sell copies of the Software, and to permit persons to whom the Software is 81cb0ef41Sopenharmony_ci * furnished to do so, subject to the following conditions: 91cb0ef41Sopenharmony_ci * 101cb0ef41Sopenharmony_ci * The above copyright notice and this permission notice shall be included in 111cb0ef41Sopenharmony_ci * all copies or substantial portions of the Software. 121cb0ef41Sopenharmony_ci * 131cb0ef41Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 141cb0ef41Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 151cb0ef41Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 161cb0ef41Sopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 171cb0ef41Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 181cb0ef41Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 191cb0ef41Sopenharmony_ci * IN THE SOFTWARE. 201cb0ef41Sopenharmony_ci */ 211cb0ef41Sopenharmony_ci 221cb0ef41Sopenharmony_ci#include <assert.h> 231cb0ef41Sopenharmony_ci 241cb0ef41Sopenharmony_ci#include "uv.h" 251cb0ef41Sopenharmony_ci#include "internal.h" 261cb0ef41Sopenharmony_ci#include "req-inl.h" 271cb0ef41Sopenharmony_ci#include "idna.h" 281cb0ef41Sopenharmony_ci 291cb0ef41Sopenharmony_ci/* EAI_* constants. */ 301cb0ef41Sopenharmony_ci#include <winsock2.h> 311cb0ef41Sopenharmony_ci 321cb0ef41Sopenharmony_ci/* Needed for ConvertInterfaceIndexToLuid and ConvertInterfaceLuidToNameA */ 331cb0ef41Sopenharmony_ci#include <iphlpapi.h> 341cb0ef41Sopenharmony_ci 351cb0ef41Sopenharmony_ciint uv__getaddrinfo_translate_error(int sys_err) { 361cb0ef41Sopenharmony_ci switch (sys_err) { 371cb0ef41Sopenharmony_ci case 0: return 0; 381cb0ef41Sopenharmony_ci case WSATRY_AGAIN: return UV_EAI_AGAIN; 391cb0ef41Sopenharmony_ci case WSAEINVAL: return UV_EAI_BADFLAGS; 401cb0ef41Sopenharmony_ci case WSANO_RECOVERY: return UV_EAI_FAIL; 411cb0ef41Sopenharmony_ci case WSAEAFNOSUPPORT: return UV_EAI_FAMILY; 421cb0ef41Sopenharmony_ci case WSA_NOT_ENOUGH_MEMORY: return UV_EAI_MEMORY; 431cb0ef41Sopenharmony_ci case WSAHOST_NOT_FOUND: return UV_EAI_NONAME; 441cb0ef41Sopenharmony_ci case WSATYPE_NOT_FOUND: return UV_EAI_SERVICE; 451cb0ef41Sopenharmony_ci case WSAESOCKTNOSUPPORT: return UV_EAI_SOCKTYPE; 461cb0ef41Sopenharmony_ci default: return uv_translate_sys_error(sys_err); 471cb0ef41Sopenharmony_ci } 481cb0ef41Sopenharmony_ci} 491cb0ef41Sopenharmony_ci 501cb0ef41Sopenharmony_ci 511cb0ef41Sopenharmony_ci/* 521cb0ef41Sopenharmony_ci * MinGW is missing this 531cb0ef41Sopenharmony_ci */ 541cb0ef41Sopenharmony_ci#if !defined(_MSC_VER) && !defined(__MINGW64_VERSION_MAJOR) 551cb0ef41Sopenharmony_ci typedef struct addrinfoW { 561cb0ef41Sopenharmony_ci int ai_flags; 571cb0ef41Sopenharmony_ci int ai_family; 581cb0ef41Sopenharmony_ci int ai_socktype; 591cb0ef41Sopenharmony_ci int ai_protocol; 601cb0ef41Sopenharmony_ci size_t ai_addrlen; 611cb0ef41Sopenharmony_ci WCHAR* ai_canonname; 621cb0ef41Sopenharmony_ci struct sockaddr* ai_addr; 631cb0ef41Sopenharmony_ci struct addrinfoW* ai_next; 641cb0ef41Sopenharmony_ci } ADDRINFOW, *PADDRINFOW; 651cb0ef41Sopenharmony_ci 661cb0ef41Sopenharmony_ci DECLSPEC_IMPORT int WSAAPI GetAddrInfoW(const WCHAR* node, 671cb0ef41Sopenharmony_ci const WCHAR* service, 681cb0ef41Sopenharmony_ci const ADDRINFOW* hints, 691cb0ef41Sopenharmony_ci PADDRINFOW* result); 701cb0ef41Sopenharmony_ci 711cb0ef41Sopenharmony_ci DECLSPEC_IMPORT void WSAAPI FreeAddrInfoW(PADDRINFOW pAddrInfo); 721cb0ef41Sopenharmony_ci#endif 731cb0ef41Sopenharmony_ci 741cb0ef41Sopenharmony_ci 751cb0ef41Sopenharmony_ci/* Adjust size value to be multiple of 4. Use to keep pointer aligned. 761cb0ef41Sopenharmony_ci * Do we need different versions of this for different architectures? */ 771cb0ef41Sopenharmony_ci#define ALIGNED_SIZE(X) ((((X) + 3) >> 2) << 2) 781cb0ef41Sopenharmony_ci 791cb0ef41Sopenharmony_ci#ifndef NDIS_IF_MAX_STRING_SIZE 801cb0ef41Sopenharmony_ci#define NDIS_IF_MAX_STRING_SIZE IF_MAX_STRING_SIZE 811cb0ef41Sopenharmony_ci#endif 821cb0ef41Sopenharmony_ci 831cb0ef41Sopenharmony_cistatic void uv__getaddrinfo_work(struct uv__work* w) { 841cb0ef41Sopenharmony_ci uv_getaddrinfo_t* req; 851cb0ef41Sopenharmony_ci struct addrinfoW* hints; 861cb0ef41Sopenharmony_ci int err; 871cb0ef41Sopenharmony_ci 881cb0ef41Sopenharmony_ci req = container_of(w, uv_getaddrinfo_t, work_req); 891cb0ef41Sopenharmony_ci hints = req->addrinfow; 901cb0ef41Sopenharmony_ci req->addrinfow = NULL; 911cb0ef41Sopenharmony_ci err = GetAddrInfoW(req->node, req->service, hints, &req->addrinfow); 921cb0ef41Sopenharmony_ci req->retcode = uv__getaddrinfo_translate_error(err); 931cb0ef41Sopenharmony_ci} 941cb0ef41Sopenharmony_ci 951cb0ef41Sopenharmony_ci 961cb0ef41Sopenharmony_ci/* 971cb0ef41Sopenharmony_ci * Called from uv_run when complete. Call user specified callback 981cb0ef41Sopenharmony_ci * then free returned addrinfo 991cb0ef41Sopenharmony_ci * Returned addrinfo strings are converted from UTF-16 to UTF-8. 1001cb0ef41Sopenharmony_ci * 1011cb0ef41Sopenharmony_ci * To minimize allocation we calculate total size required, 1021cb0ef41Sopenharmony_ci * and copy all structs and referenced strings into the one block. 1031cb0ef41Sopenharmony_ci * Each size calculation is adjusted to avoid unaligned pointers. 1041cb0ef41Sopenharmony_ci */ 1051cb0ef41Sopenharmony_cistatic void uv__getaddrinfo_done(struct uv__work* w, int status) { 1061cb0ef41Sopenharmony_ci uv_getaddrinfo_t* req; 1071cb0ef41Sopenharmony_ci int addrinfo_len = 0; 1081cb0ef41Sopenharmony_ci int name_len = 0; 1091cb0ef41Sopenharmony_ci size_t addrinfo_struct_len = ALIGNED_SIZE(sizeof(struct addrinfo)); 1101cb0ef41Sopenharmony_ci struct addrinfoW* addrinfow_ptr; 1111cb0ef41Sopenharmony_ci struct addrinfo* addrinfo_ptr; 1121cb0ef41Sopenharmony_ci char* alloc_ptr = NULL; 1131cb0ef41Sopenharmony_ci char* cur_ptr = NULL; 1141cb0ef41Sopenharmony_ci 1151cb0ef41Sopenharmony_ci req = container_of(w, uv_getaddrinfo_t, work_req); 1161cb0ef41Sopenharmony_ci 1171cb0ef41Sopenharmony_ci /* release input parameter memory */ 1181cb0ef41Sopenharmony_ci uv__free(req->alloc); 1191cb0ef41Sopenharmony_ci req->alloc = NULL; 1201cb0ef41Sopenharmony_ci 1211cb0ef41Sopenharmony_ci if (status == UV_ECANCELED) { 1221cb0ef41Sopenharmony_ci assert(req->retcode == 0); 1231cb0ef41Sopenharmony_ci req->retcode = UV_EAI_CANCELED; 1241cb0ef41Sopenharmony_ci goto complete; 1251cb0ef41Sopenharmony_ci } 1261cb0ef41Sopenharmony_ci 1271cb0ef41Sopenharmony_ci if (req->retcode == 0) { 1281cb0ef41Sopenharmony_ci /* Convert addrinfoW to addrinfo. First calculate required length. */ 1291cb0ef41Sopenharmony_ci addrinfow_ptr = req->addrinfow; 1301cb0ef41Sopenharmony_ci while (addrinfow_ptr != NULL) { 1311cb0ef41Sopenharmony_ci addrinfo_len += addrinfo_struct_len + 1321cb0ef41Sopenharmony_ci ALIGNED_SIZE(addrinfow_ptr->ai_addrlen); 1331cb0ef41Sopenharmony_ci if (addrinfow_ptr->ai_canonname != NULL) { 1341cb0ef41Sopenharmony_ci name_len = WideCharToMultiByte(CP_UTF8, 1351cb0ef41Sopenharmony_ci 0, 1361cb0ef41Sopenharmony_ci addrinfow_ptr->ai_canonname, 1371cb0ef41Sopenharmony_ci -1, 1381cb0ef41Sopenharmony_ci NULL, 1391cb0ef41Sopenharmony_ci 0, 1401cb0ef41Sopenharmony_ci NULL, 1411cb0ef41Sopenharmony_ci NULL); 1421cb0ef41Sopenharmony_ci if (name_len == 0) { 1431cb0ef41Sopenharmony_ci req->retcode = uv_translate_sys_error(GetLastError()); 1441cb0ef41Sopenharmony_ci goto complete; 1451cb0ef41Sopenharmony_ci } 1461cb0ef41Sopenharmony_ci addrinfo_len += ALIGNED_SIZE(name_len); 1471cb0ef41Sopenharmony_ci } 1481cb0ef41Sopenharmony_ci addrinfow_ptr = addrinfow_ptr->ai_next; 1491cb0ef41Sopenharmony_ci } 1501cb0ef41Sopenharmony_ci 1511cb0ef41Sopenharmony_ci /* allocate memory for addrinfo results */ 1521cb0ef41Sopenharmony_ci alloc_ptr = (char*)uv__malloc(addrinfo_len); 1531cb0ef41Sopenharmony_ci 1541cb0ef41Sopenharmony_ci /* do conversions */ 1551cb0ef41Sopenharmony_ci if (alloc_ptr != NULL) { 1561cb0ef41Sopenharmony_ci cur_ptr = alloc_ptr; 1571cb0ef41Sopenharmony_ci addrinfow_ptr = req->addrinfow; 1581cb0ef41Sopenharmony_ci 1591cb0ef41Sopenharmony_ci while (addrinfow_ptr != NULL) { 1601cb0ef41Sopenharmony_ci /* copy addrinfo struct data */ 1611cb0ef41Sopenharmony_ci assert(cur_ptr + addrinfo_struct_len <= alloc_ptr + addrinfo_len); 1621cb0ef41Sopenharmony_ci addrinfo_ptr = (struct addrinfo*)cur_ptr; 1631cb0ef41Sopenharmony_ci addrinfo_ptr->ai_family = addrinfow_ptr->ai_family; 1641cb0ef41Sopenharmony_ci addrinfo_ptr->ai_socktype = addrinfow_ptr->ai_socktype; 1651cb0ef41Sopenharmony_ci addrinfo_ptr->ai_protocol = addrinfow_ptr->ai_protocol; 1661cb0ef41Sopenharmony_ci addrinfo_ptr->ai_flags = addrinfow_ptr->ai_flags; 1671cb0ef41Sopenharmony_ci addrinfo_ptr->ai_addrlen = addrinfow_ptr->ai_addrlen; 1681cb0ef41Sopenharmony_ci addrinfo_ptr->ai_canonname = NULL; 1691cb0ef41Sopenharmony_ci addrinfo_ptr->ai_addr = NULL; 1701cb0ef41Sopenharmony_ci addrinfo_ptr->ai_next = NULL; 1711cb0ef41Sopenharmony_ci 1721cb0ef41Sopenharmony_ci cur_ptr += addrinfo_struct_len; 1731cb0ef41Sopenharmony_ci 1741cb0ef41Sopenharmony_ci /* copy sockaddr */ 1751cb0ef41Sopenharmony_ci if (addrinfo_ptr->ai_addrlen > 0) { 1761cb0ef41Sopenharmony_ci assert(cur_ptr + addrinfo_ptr->ai_addrlen <= 1771cb0ef41Sopenharmony_ci alloc_ptr + addrinfo_len); 1781cb0ef41Sopenharmony_ci memcpy(cur_ptr, addrinfow_ptr->ai_addr, addrinfo_ptr->ai_addrlen); 1791cb0ef41Sopenharmony_ci addrinfo_ptr->ai_addr = (struct sockaddr*)cur_ptr; 1801cb0ef41Sopenharmony_ci cur_ptr += ALIGNED_SIZE(addrinfo_ptr->ai_addrlen); 1811cb0ef41Sopenharmony_ci } 1821cb0ef41Sopenharmony_ci 1831cb0ef41Sopenharmony_ci /* convert canonical name to UTF-8 */ 1841cb0ef41Sopenharmony_ci if (addrinfow_ptr->ai_canonname != NULL) { 1851cb0ef41Sopenharmony_ci name_len = WideCharToMultiByte(CP_UTF8, 1861cb0ef41Sopenharmony_ci 0, 1871cb0ef41Sopenharmony_ci addrinfow_ptr->ai_canonname, 1881cb0ef41Sopenharmony_ci -1, 1891cb0ef41Sopenharmony_ci NULL, 1901cb0ef41Sopenharmony_ci 0, 1911cb0ef41Sopenharmony_ci NULL, 1921cb0ef41Sopenharmony_ci NULL); 1931cb0ef41Sopenharmony_ci assert(name_len > 0); 1941cb0ef41Sopenharmony_ci assert(cur_ptr + name_len <= alloc_ptr + addrinfo_len); 1951cb0ef41Sopenharmony_ci name_len = WideCharToMultiByte(CP_UTF8, 1961cb0ef41Sopenharmony_ci 0, 1971cb0ef41Sopenharmony_ci addrinfow_ptr->ai_canonname, 1981cb0ef41Sopenharmony_ci -1, 1991cb0ef41Sopenharmony_ci cur_ptr, 2001cb0ef41Sopenharmony_ci name_len, 2011cb0ef41Sopenharmony_ci NULL, 2021cb0ef41Sopenharmony_ci NULL); 2031cb0ef41Sopenharmony_ci assert(name_len > 0); 2041cb0ef41Sopenharmony_ci addrinfo_ptr->ai_canonname = cur_ptr; 2051cb0ef41Sopenharmony_ci cur_ptr += ALIGNED_SIZE(name_len); 2061cb0ef41Sopenharmony_ci } 2071cb0ef41Sopenharmony_ci assert(cur_ptr <= alloc_ptr + addrinfo_len); 2081cb0ef41Sopenharmony_ci 2091cb0ef41Sopenharmony_ci /* set next ptr */ 2101cb0ef41Sopenharmony_ci addrinfow_ptr = addrinfow_ptr->ai_next; 2111cb0ef41Sopenharmony_ci if (addrinfow_ptr != NULL) { 2121cb0ef41Sopenharmony_ci addrinfo_ptr->ai_next = (struct addrinfo*)cur_ptr; 2131cb0ef41Sopenharmony_ci } 2141cb0ef41Sopenharmony_ci } 2151cb0ef41Sopenharmony_ci req->addrinfo = (struct addrinfo*)alloc_ptr; 2161cb0ef41Sopenharmony_ci } else { 2171cb0ef41Sopenharmony_ci req->retcode = UV_EAI_MEMORY; 2181cb0ef41Sopenharmony_ci } 2191cb0ef41Sopenharmony_ci } 2201cb0ef41Sopenharmony_ci 2211cb0ef41Sopenharmony_ci /* return memory to system */ 2221cb0ef41Sopenharmony_ci if (req->addrinfow != NULL) { 2231cb0ef41Sopenharmony_ci FreeAddrInfoW(req->addrinfow); 2241cb0ef41Sopenharmony_ci req->addrinfow = NULL; 2251cb0ef41Sopenharmony_ci } 2261cb0ef41Sopenharmony_ci 2271cb0ef41Sopenharmony_cicomplete: 2281cb0ef41Sopenharmony_ci uv__req_unregister(req->loop, req); 2291cb0ef41Sopenharmony_ci 2301cb0ef41Sopenharmony_ci /* finally do callback with converted result */ 2311cb0ef41Sopenharmony_ci if (req->getaddrinfo_cb) 2321cb0ef41Sopenharmony_ci req->getaddrinfo_cb(req, req->retcode, req->addrinfo); 2331cb0ef41Sopenharmony_ci} 2341cb0ef41Sopenharmony_ci 2351cb0ef41Sopenharmony_ci 2361cb0ef41Sopenharmony_civoid uv_freeaddrinfo(struct addrinfo* ai) { 2371cb0ef41Sopenharmony_ci char* alloc_ptr = (char*)ai; 2381cb0ef41Sopenharmony_ci 2391cb0ef41Sopenharmony_ci /* release copied result memory */ 2401cb0ef41Sopenharmony_ci uv__free(alloc_ptr); 2411cb0ef41Sopenharmony_ci} 2421cb0ef41Sopenharmony_ci 2431cb0ef41Sopenharmony_ci 2441cb0ef41Sopenharmony_ci/* 2451cb0ef41Sopenharmony_ci * Entry point for getaddrinfo 2461cb0ef41Sopenharmony_ci * we convert the UTF-8 strings to UNICODE 2471cb0ef41Sopenharmony_ci * and save the UNICODE string pointers in the req 2481cb0ef41Sopenharmony_ci * We also copy hints so that caller does not need to keep memory until the 2491cb0ef41Sopenharmony_ci * callback. 2501cb0ef41Sopenharmony_ci * return 0 if a callback will be made 2511cb0ef41Sopenharmony_ci * return error code if validation fails 2521cb0ef41Sopenharmony_ci * 2531cb0ef41Sopenharmony_ci * To minimize allocation we calculate total size required, 2541cb0ef41Sopenharmony_ci * and copy all structs and referenced strings into the one block. 2551cb0ef41Sopenharmony_ci * Each size calculation is adjusted to avoid unaligned pointers. 2561cb0ef41Sopenharmony_ci */ 2571cb0ef41Sopenharmony_ciint uv_getaddrinfo(uv_loop_t* loop, 2581cb0ef41Sopenharmony_ci uv_getaddrinfo_t* req, 2591cb0ef41Sopenharmony_ci uv_getaddrinfo_cb getaddrinfo_cb, 2601cb0ef41Sopenharmony_ci const char* node, 2611cb0ef41Sopenharmony_ci const char* service, 2621cb0ef41Sopenharmony_ci const struct addrinfo* hints) { 2631cb0ef41Sopenharmony_ci char hostname_ascii[256]; 2641cb0ef41Sopenharmony_ci int nodesize = 0; 2651cb0ef41Sopenharmony_ci int servicesize = 0; 2661cb0ef41Sopenharmony_ci int hintssize = 0; 2671cb0ef41Sopenharmony_ci char* alloc_ptr = NULL; 2681cb0ef41Sopenharmony_ci int err; 2691cb0ef41Sopenharmony_ci long rc; 2701cb0ef41Sopenharmony_ci 2711cb0ef41Sopenharmony_ci if (req == NULL || (node == NULL && service == NULL)) { 2721cb0ef41Sopenharmony_ci return UV_EINVAL; 2731cb0ef41Sopenharmony_ci } 2741cb0ef41Sopenharmony_ci 2751cb0ef41Sopenharmony_ci UV_REQ_INIT(req, UV_GETADDRINFO); 2761cb0ef41Sopenharmony_ci req->getaddrinfo_cb = getaddrinfo_cb; 2771cb0ef41Sopenharmony_ci req->addrinfo = NULL; 2781cb0ef41Sopenharmony_ci req->loop = loop; 2791cb0ef41Sopenharmony_ci req->retcode = 0; 2801cb0ef41Sopenharmony_ci 2811cb0ef41Sopenharmony_ci /* calculate required memory size for all input values */ 2821cb0ef41Sopenharmony_ci if (node != NULL) { 2831cb0ef41Sopenharmony_ci rc = uv__idna_toascii(node, 2841cb0ef41Sopenharmony_ci node + strlen(node), 2851cb0ef41Sopenharmony_ci hostname_ascii, 2861cb0ef41Sopenharmony_ci hostname_ascii + sizeof(hostname_ascii)); 2871cb0ef41Sopenharmony_ci if (rc < 0) 2881cb0ef41Sopenharmony_ci return rc; 2891cb0ef41Sopenharmony_ci nodesize = ALIGNED_SIZE(MultiByteToWideChar(CP_UTF8, 0, hostname_ascii, 2901cb0ef41Sopenharmony_ci -1, NULL, 0) * sizeof(WCHAR)); 2911cb0ef41Sopenharmony_ci if (nodesize == 0) { 2921cb0ef41Sopenharmony_ci err = GetLastError(); 2931cb0ef41Sopenharmony_ci goto error; 2941cb0ef41Sopenharmony_ci } 2951cb0ef41Sopenharmony_ci node = hostname_ascii; 2961cb0ef41Sopenharmony_ci } 2971cb0ef41Sopenharmony_ci 2981cb0ef41Sopenharmony_ci if (service != NULL) { 2991cb0ef41Sopenharmony_ci servicesize = ALIGNED_SIZE(MultiByteToWideChar(CP_UTF8, 3001cb0ef41Sopenharmony_ci 0, 3011cb0ef41Sopenharmony_ci service, 3021cb0ef41Sopenharmony_ci -1, 3031cb0ef41Sopenharmony_ci NULL, 3041cb0ef41Sopenharmony_ci 0) * 3051cb0ef41Sopenharmony_ci sizeof(WCHAR)); 3061cb0ef41Sopenharmony_ci if (servicesize == 0) { 3071cb0ef41Sopenharmony_ci err = GetLastError(); 3081cb0ef41Sopenharmony_ci goto error; 3091cb0ef41Sopenharmony_ci } 3101cb0ef41Sopenharmony_ci } 3111cb0ef41Sopenharmony_ci if (hints != NULL) { 3121cb0ef41Sopenharmony_ci hintssize = ALIGNED_SIZE(sizeof(struct addrinfoW)); 3131cb0ef41Sopenharmony_ci } 3141cb0ef41Sopenharmony_ci 3151cb0ef41Sopenharmony_ci /* allocate memory for inputs, and partition it as needed */ 3161cb0ef41Sopenharmony_ci alloc_ptr = (char*)uv__malloc(nodesize + servicesize + hintssize); 3171cb0ef41Sopenharmony_ci if (!alloc_ptr) { 3181cb0ef41Sopenharmony_ci err = WSAENOBUFS; 3191cb0ef41Sopenharmony_ci goto error; 3201cb0ef41Sopenharmony_ci } 3211cb0ef41Sopenharmony_ci 3221cb0ef41Sopenharmony_ci /* save alloc_ptr now so we can free if error */ 3231cb0ef41Sopenharmony_ci req->alloc = (void*)alloc_ptr; 3241cb0ef41Sopenharmony_ci 3251cb0ef41Sopenharmony_ci /* Convert node string to UTF16 into allocated memory and save pointer in the 3261cb0ef41Sopenharmony_ci * request. */ 3271cb0ef41Sopenharmony_ci if (node != NULL) { 3281cb0ef41Sopenharmony_ci req->node = (WCHAR*)alloc_ptr; 3291cb0ef41Sopenharmony_ci if (MultiByteToWideChar(CP_UTF8, 3301cb0ef41Sopenharmony_ci 0, 3311cb0ef41Sopenharmony_ci node, 3321cb0ef41Sopenharmony_ci -1, 3331cb0ef41Sopenharmony_ci (WCHAR*) alloc_ptr, 3341cb0ef41Sopenharmony_ci nodesize / sizeof(WCHAR)) == 0) { 3351cb0ef41Sopenharmony_ci err = GetLastError(); 3361cb0ef41Sopenharmony_ci goto error; 3371cb0ef41Sopenharmony_ci } 3381cb0ef41Sopenharmony_ci alloc_ptr += nodesize; 3391cb0ef41Sopenharmony_ci } else { 3401cb0ef41Sopenharmony_ci req->node = NULL; 3411cb0ef41Sopenharmony_ci } 3421cb0ef41Sopenharmony_ci 3431cb0ef41Sopenharmony_ci /* Convert service string to UTF16 into allocated memory and save pointer in 3441cb0ef41Sopenharmony_ci * the req. */ 3451cb0ef41Sopenharmony_ci if (service != NULL) { 3461cb0ef41Sopenharmony_ci req->service = (WCHAR*)alloc_ptr; 3471cb0ef41Sopenharmony_ci if (MultiByteToWideChar(CP_UTF8, 3481cb0ef41Sopenharmony_ci 0, 3491cb0ef41Sopenharmony_ci service, 3501cb0ef41Sopenharmony_ci -1, 3511cb0ef41Sopenharmony_ci (WCHAR*) alloc_ptr, 3521cb0ef41Sopenharmony_ci servicesize / sizeof(WCHAR)) == 0) { 3531cb0ef41Sopenharmony_ci err = GetLastError(); 3541cb0ef41Sopenharmony_ci goto error; 3551cb0ef41Sopenharmony_ci } 3561cb0ef41Sopenharmony_ci alloc_ptr += servicesize; 3571cb0ef41Sopenharmony_ci } else { 3581cb0ef41Sopenharmony_ci req->service = NULL; 3591cb0ef41Sopenharmony_ci } 3601cb0ef41Sopenharmony_ci 3611cb0ef41Sopenharmony_ci /* copy hints to allocated memory and save pointer in req */ 3621cb0ef41Sopenharmony_ci if (hints != NULL) { 3631cb0ef41Sopenharmony_ci req->addrinfow = (struct addrinfoW*)alloc_ptr; 3641cb0ef41Sopenharmony_ci req->addrinfow->ai_family = hints->ai_family; 3651cb0ef41Sopenharmony_ci req->addrinfow->ai_socktype = hints->ai_socktype; 3661cb0ef41Sopenharmony_ci req->addrinfow->ai_protocol = hints->ai_protocol; 3671cb0ef41Sopenharmony_ci req->addrinfow->ai_flags = hints->ai_flags; 3681cb0ef41Sopenharmony_ci req->addrinfow->ai_addrlen = 0; 3691cb0ef41Sopenharmony_ci req->addrinfow->ai_canonname = NULL; 3701cb0ef41Sopenharmony_ci req->addrinfow->ai_addr = NULL; 3711cb0ef41Sopenharmony_ci req->addrinfow->ai_next = NULL; 3721cb0ef41Sopenharmony_ci } else { 3731cb0ef41Sopenharmony_ci req->addrinfow = NULL; 3741cb0ef41Sopenharmony_ci } 3751cb0ef41Sopenharmony_ci 3761cb0ef41Sopenharmony_ci uv__req_register(loop, req); 3771cb0ef41Sopenharmony_ci 3781cb0ef41Sopenharmony_ci if (getaddrinfo_cb) { 3791cb0ef41Sopenharmony_ci uv__work_submit(loop, 3801cb0ef41Sopenharmony_ci &req->work_req, 3811cb0ef41Sopenharmony_ci UV__WORK_SLOW_IO, 3821cb0ef41Sopenharmony_ci uv__getaddrinfo_work, 3831cb0ef41Sopenharmony_ci uv__getaddrinfo_done); 3841cb0ef41Sopenharmony_ci return 0; 3851cb0ef41Sopenharmony_ci } else { 3861cb0ef41Sopenharmony_ci uv__getaddrinfo_work(&req->work_req); 3871cb0ef41Sopenharmony_ci uv__getaddrinfo_done(&req->work_req, 0); 3881cb0ef41Sopenharmony_ci return req->retcode; 3891cb0ef41Sopenharmony_ci } 3901cb0ef41Sopenharmony_ci 3911cb0ef41Sopenharmony_cierror: 3921cb0ef41Sopenharmony_ci if (req != NULL) { 3931cb0ef41Sopenharmony_ci uv__free(req->alloc); 3941cb0ef41Sopenharmony_ci req->alloc = NULL; 3951cb0ef41Sopenharmony_ci } 3961cb0ef41Sopenharmony_ci return uv_translate_sys_error(err); 3971cb0ef41Sopenharmony_ci} 3981cb0ef41Sopenharmony_ci 3991cb0ef41Sopenharmony_ciint uv_if_indextoname(unsigned int ifindex, char* buffer, size_t* size) { 4001cb0ef41Sopenharmony_ci NET_LUID luid; 4011cb0ef41Sopenharmony_ci wchar_t wname[NDIS_IF_MAX_STRING_SIZE + 1]; /* Add one for the NUL. */ 4021cb0ef41Sopenharmony_ci DWORD bufsize; 4031cb0ef41Sopenharmony_ci int r; 4041cb0ef41Sopenharmony_ci 4051cb0ef41Sopenharmony_ci if (buffer == NULL || size == NULL || *size == 0) 4061cb0ef41Sopenharmony_ci return UV_EINVAL; 4071cb0ef41Sopenharmony_ci 4081cb0ef41Sopenharmony_ci r = ConvertInterfaceIndexToLuid(ifindex, &luid); 4091cb0ef41Sopenharmony_ci 4101cb0ef41Sopenharmony_ci if (r != 0) 4111cb0ef41Sopenharmony_ci return uv_translate_sys_error(r); 4121cb0ef41Sopenharmony_ci 4131cb0ef41Sopenharmony_ci r = ConvertInterfaceLuidToNameW(&luid, wname, ARRAY_SIZE(wname)); 4141cb0ef41Sopenharmony_ci 4151cb0ef41Sopenharmony_ci if (r != 0) 4161cb0ef41Sopenharmony_ci return uv_translate_sys_error(r); 4171cb0ef41Sopenharmony_ci 4181cb0ef41Sopenharmony_ci /* Check how much space we need */ 4191cb0ef41Sopenharmony_ci bufsize = WideCharToMultiByte(CP_UTF8, 0, wname, -1, NULL, 0, NULL, NULL); 4201cb0ef41Sopenharmony_ci 4211cb0ef41Sopenharmony_ci if (bufsize == 0) { 4221cb0ef41Sopenharmony_ci return uv_translate_sys_error(GetLastError()); 4231cb0ef41Sopenharmony_ci } else if (bufsize > *size) { 4241cb0ef41Sopenharmony_ci *size = bufsize; 4251cb0ef41Sopenharmony_ci return UV_ENOBUFS; 4261cb0ef41Sopenharmony_ci } 4271cb0ef41Sopenharmony_ci 4281cb0ef41Sopenharmony_ci /* Convert to UTF-8 */ 4291cb0ef41Sopenharmony_ci bufsize = WideCharToMultiByte(CP_UTF8, 4301cb0ef41Sopenharmony_ci 0, 4311cb0ef41Sopenharmony_ci wname, 4321cb0ef41Sopenharmony_ci -1, 4331cb0ef41Sopenharmony_ci buffer, 4341cb0ef41Sopenharmony_ci *size, 4351cb0ef41Sopenharmony_ci NULL, 4361cb0ef41Sopenharmony_ci NULL); 4371cb0ef41Sopenharmony_ci 4381cb0ef41Sopenharmony_ci if (bufsize == 0) 4391cb0ef41Sopenharmony_ci return uv_translate_sys_error(GetLastError()); 4401cb0ef41Sopenharmony_ci 4411cb0ef41Sopenharmony_ci *size = bufsize - 1; 4421cb0ef41Sopenharmony_ci return 0; 4431cb0ef41Sopenharmony_ci} 4441cb0ef41Sopenharmony_ci 4451cb0ef41Sopenharmony_ciint uv_if_indextoiid(unsigned int ifindex, char* buffer, size_t* size) { 4461cb0ef41Sopenharmony_ci int r; 4471cb0ef41Sopenharmony_ci 4481cb0ef41Sopenharmony_ci if (buffer == NULL || size == NULL || *size == 0) 4491cb0ef41Sopenharmony_ci return UV_EINVAL; 4501cb0ef41Sopenharmony_ci 4511cb0ef41Sopenharmony_ci r = snprintf(buffer, *size, "%d", ifindex); 4521cb0ef41Sopenharmony_ci 4531cb0ef41Sopenharmony_ci if (r < 0) 4541cb0ef41Sopenharmony_ci return uv_translate_sys_error(r); 4551cb0ef41Sopenharmony_ci 4561cb0ef41Sopenharmony_ci if (r >= (int) *size) { 4571cb0ef41Sopenharmony_ci *size = r + 1; 4581cb0ef41Sopenharmony_ci return UV_ENOBUFS; 4591cb0ef41Sopenharmony_ci } 4601cb0ef41Sopenharmony_ci 4611cb0ef41Sopenharmony_ci *size = r; 4621cb0ef41Sopenharmony_ci return 0; 4631cb0ef41Sopenharmony_ci} 464