1e66f31c5Sopenharmony_ci/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2e66f31c5Sopenharmony_ci *
3e66f31c5Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy
4e66f31c5Sopenharmony_ci * of this software and associated documentation files (the "Software"), to
5e66f31c5Sopenharmony_ci * deal in the Software without restriction, including without limitation the
6e66f31c5Sopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7e66f31c5Sopenharmony_ci * sell copies of the Software, and to permit persons to whom the Software is
8e66f31c5Sopenharmony_ci * furnished to do so, subject to the following conditions:
9e66f31c5Sopenharmony_ci *
10e66f31c5Sopenharmony_ci * The above copyright notice and this permission notice shall be included in
11e66f31c5Sopenharmony_ci * all copies or substantial portions of the Software.
12e66f31c5Sopenharmony_ci *
13e66f31c5Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14e66f31c5Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15e66f31c5Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16e66f31c5Sopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17e66f31c5Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18e66f31c5Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19e66f31c5Sopenharmony_ci * IN THE SOFTWARE.
20e66f31c5Sopenharmony_ci */
21e66f31c5Sopenharmony_ci
22e66f31c5Sopenharmony_ci#include <assert.h>
23e66f31c5Sopenharmony_ci
24e66f31c5Sopenharmony_ci#include "uv.h"
25e66f31c5Sopenharmony_ci#include "internal.h"
26e66f31c5Sopenharmony_ci#include "req-inl.h"
27e66f31c5Sopenharmony_ci#include "idna.h"
28e66f31c5Sopenharmony_ci
29e66f31c5Sopenharmony_ci/* EAI_* constants. */
30e66f31c5Sopenharmony_ci#include <winsock2.h>
31e66f31c5Sopenharmony_ci
32e66f31c5Sopenharmony_ci/* Needed for ConvertInterfaceIndexToLuid and ConvertInterfaceLuidToNameA */
33e66f31c5Sopenharmony_ci#include <iphlpapi.h>
34e66f31c5Sopenharmony_ci
35e66f31c5Sopenharmony_ciint uv__getaddrinfo_translate_error(int sys_err) {
36e66f31c5Sopenharmony_ci  switch (sys_err) {
37e66f31c5Sopenharmony_ci    case 0:                       return 0;
38e66f31c5Sopenharmony_ci    case WSATRY_AGAIN:            return UV_EAI_AGAIN;
39e66f31c5Sopenharmony_ci    case WSAEINVAL:               return UV_EAI_BADFLAGS;
40e66f31c5Sopenharmony_ci    case WSANO_RECOVERY:          return UV_EAI_FAIL;
41e66f31c5Sopenharmony_ci    case WSAEAFNOSUPPORT:         return UV_EAI_FAMILY;
42e66f31c5Sopenharmony_ci    case WSA_NOT_ENOUGH_MEMORY:   return UV_EAI_MEMORY;
43e66f31c5Sopenharmony_ci    case WSAHOST_NOT_FOUND:       return UV_EAI_NONAME;
44e66f31c5Sopenharmony_ci    case WSATYPE_NOT_FOUND:       return UV_EAI_SERVICE;
45e66f31c5Sopenharmony_ci    case WSAESOCKTNOSUPPORT:      return UV_EAI_SOCKTYPE;
46e66f31c5Sopenharmony_ci    default:                      return uv_translate_sys_error(sys_err);
47e66f31c5Sopenharmony_ci  }
48e66f31c5Sopenharmony_ci}
49e66f31c5Sopenharmony_ci
50e66f31c5Sopenharmony_ci
51e66f31c5Sopenharmony_ci/*
52e66f31c5Sopenharmony_ci * MinGW is missing this
53e66f31c5Sopenharmony_ci */
54e66f31c5Sopenharmony_ci#if !defined(_MSC_VER) && !defined(__MINGW64_VERSION_MAJOR)
55e66f31c5Sopenharmony_ci  typedef struct addrinfoW {
56e66f31c5Sopenharmony_ci    int ai_flags;
57e66f31c5Sopenharmony_ci    int ai_family;
58e66f31c5Sopenharmony_ci    int ai_socktype;
59e66f31c5Sopenharmony_ci    int ai_protocol;
60e66f31c5Sopenharmony_ci    size_t ai_addrlen;
61e66f31c5Sopenharmony_ci    WCHAR* ai_canonname;
62e66f31c5Sopenharmony_ci    struct sockaddr* ai_addr;
63e66f31c5Sopenharmony_ci    struct addrinfoW* ai_next;
64e66f31c5Sopenharmony_ci  } ADDRINFOW, *PADDRINFOW;
65e66f31c5Sopenharmony_ci
66e66f31c5Sopenharmony_ci  DECLSPEC_IMPORT int WSAAPI GetAddrInfoW(const WCHAR* node,
67e66f31c5Sopenharmony_ci                                          const WCHAR* service,
68e66f31c5Sopenharmony_ci                                          const ADDRINFOW* hints,
69e66f31c5Sopenharmony_ci                                          PADDRINFOW* result);
70e66f31c5Sopenharmony_ci
71e66f31c5Sopenharmony_ci  DECLSPEC_IMPORT void WSAAPI FreeAddrInfoW(PADDRINFOW pAddrInfo);
72e66f31c5Sopenharmony_ci#endif
73e66f31c5Sopenharmony_ci
74e66f31c5Sopenharmony_ci
75e66f31c5Sopenharmony_ci/* Adjust size value to be multiple of 4. Use to keep pointer aligned.
76e66f31c5Sopenharmony_ci * Do we need different versions of this for different architectures? */
77e66f31c5Sopenharmony_ci#define ALIGNED_SIZE(X)     ((((X) + 3) >> 2) << 2)
78e66f31c5Sopenharmony_ci
79e66f31c5Sopenharmony_ci#ifndef NDIS_IF_MAX_STRING_SIZE
80e66f31c5Sopenharmony_ci#define NDIS_IF_MAX_STRING_SIZE IF_MAX_STRING_SIZE
81e66f31c5Sopenharmony_ci#endif
82e66f31c5Sopenharmony_ci
83e66f31c5Sopenharmony_cistatic void uv__getaddrinfo_work(struct uv__work* w) {
84e66f31c5Sopenharmony_ci  uv_getaddrinfo_t* req;
85e66f31c5Sopenharmony_ci  struct addrinfoW* hints;
86e66f31c5Sopenharmony_ci  int err;
87e66f31c5Sopenharmony_ci
88e66f31c5Sopenharmony_ci  req = container_of(w, uv_getaddrinfo_t, work_req);
89e66f31c5Sopenharmony_ci  hints = req->addrinfow;
90e66f31c5Sopenharmony_ci  req->addrinfow = NULL;
91e66f31c5Sopenharmony_ci  err = GetAddrInfoW(req->node, req->service, hints, &req->addrinfow);
92e66f31c5Sopenharmony_ci  req->retcode = uv__getaddrinfo_translate_error(err);
93e66f31c5Sopenharmony_ci}
94e66f31c5Sopenharmony_ci
95e66f31c5Sopenharmony_ci
96e66f31c5Sopenharmony_ci/*
97e66f31c5Sopenharmony_ci * Called from uv_run when complete. Call user specified callback
98e66f31c5Sopenharmony_ci * then free returned addrinfo
99e66f31c5Sopenharmony_ci * Returned addrinfo strings are converted from UTF-16 to UTF-8.
100e66f31c5Sopenharmony_ci *
101e66f31c5Sopenharmony_ci * To minimize allocation we calculate total size required,
102e66f31c5Sopenharmony_ci * and copy all structs and referenced strings into the one block.
103e66f31c5Sopenharmony_ci * Each size calculation is adjusted to avoid unaligned pointers.
104e66f31c5Sopenharmony_ci */
105e66f31c5Sopenharmony_cistatic void uv__getaddrinfo_done(struct uv__work* w, int status) {
106e66f31c5Sopenharmony_ci  uv_getaddrinfo_t* req;
107e66f31c5Sopenharmony_ci  size_t addrinfo_len = 0;
108e66f31c5Sopenharmony_ci  ssize_t name_len = 0;
109e66f31c5Sopenharmony_ci  size_t addrinfo_struct_len = ALIGNED_SIZE(sizeof(struct addrinfo));
110e66f31c5Sopenharmony_ci  struct addrinfoW* addrinfow_ptr;
111e66f31c5Sopenharmony_ci  struct addrinfo* addrinfo_ptr;
112e66f31c5Sopenharmony_ci  char* alloc_ptr = NULL;
113e66f31c5Sopenharmony_ci  char* cur_ptr = NULL;
114e66f31c5Sopenharmony_ci  int r;
115e66f31c5Sopenharmony_ci
116e66f31c5Sopenharmony_ci  req = container_of(w, uv_getaddrinfo_t, work_req);
117e66f31c5Sopenharmony_ci
118e66f31c5Sopenharmony_ci  /* release input parameter memory */
119e66f31c5Sopenharmony_ci  uv__free(req->alloc);
120e66f31c5Sopenharmony_ci  req->alloc = NULL;
121e66f31c5Sopenharmony_ci
122e66f31c5Sopenharmony_ci  if (status == UV_ECANCELED) {
123e66f31c5Sopenharmony_ci    assert(req->retcode == 0);
124e66f31c5Sopenharmony_ci    req->retcode = UV_EAI_CANCELED;
125e66f31c5Sopenharmony_ci    goto complete;
126e66f31c5Sopenharmony_ci  }
127e66f31c5Sopenharmony_ci
128e66f31c5Sopenharmony_ci  if (req->retcode == 0) {
129e66f31c5Sopenharmony_ci    /* Convert addrinfoW to addrinfo. First calculate required length. */
130e66f31c5Sopenharmony_ci    addrinfow_ptr = req->addrinfow;
131e66f31c5Sopenharmony_ci    while (addrinfow_ptr != NULL) {
132e66f31c5Sopenharmony_ci      addrinfo_len += addrinfo_struct_len +
133e66f31c5Sopenharmony_ci          ALIGNED_SIZE(addrinfow_ptr->ai_addrlen);
134e66f31c5Sopenharmony_ci      if (addrinfow_ptr->ai_canonname != NULL) {
135e66f31c5Sopenharmony_ci        name_len = uv_utf16_length_as_wtf8(addrinfow_ptr->ai_canonname, -1);
136e66f31c5Sopenharmony_ci        if (name_len < 0) {
137e66f31c5Sopenharmony_ci          req->retcode = name_len;
138e66f31c5Sopenharmony_ci          goto complete;
139e66f31c5Sopenharmony_ci        }
140e66f31c5Sopenharmony_ci        addrinfo_len += ALIGNED_SIZE(name_len + 1);
141e66f31c5Sopenharmony_ci      }
142e66f31c5Sopenharmony_ci      addrinfow_ptr = addrinfow_ptr->ai_next;
143e66f31c5Sopenharmony_ci    }
144e66f31c5Sopenharmony_ci
145e66f31c5Sopenharmony_ci    /* allocate memory for addrinfo results */
146e66f31c5Sopenharmony_ci    alloc_ptr = (char*)uv__malloc(addrinfo_len);
147e66f31c5Sopenharmony_ci
148e66f31c5Sopenharmony_ci    /* do conversions */
149e66f31c5Sopenharmony_ci    if (alloc_ptr != NULL) {
150e66f31c5Sopenharmony_ci      cur_ptr = alloc_ptr;
151e66f31c5Sopenharmony_ci      addrinfow_ptr = req->addrinfow;
152e66f31c5Sopenharmony_ci
153e66f31c5Sopenharmony_ci      while (addrinfow_ptr != NULL) {
154e66f31c5Sopenharmony_ci        /* copy addrinfo struct data */
155e66f31c5Sopenharmony_ci        assert(cur_ptr + addrinfo_struct_len <= alloc_ptr + addrinfo_len);
156e66f31c5Sopenharmony_ci        addrinfo_ptr = (struct addrinfo*)cur_ptr;
157e66f31c5Sopenharmony_ci        addrinfo_ptr->ai_family = addrinfow_ptr->ai_family;
158e66f31c5Sopenharmony_ci        addrinfo_ptr->ai_socktype = addrinfow_ptr->ai_socktype;
159e66f31c5Sopenharmony_ci        addrinfo_ptr->ai_protocol = addrinfow_ptr->ai_protocol;
160e66f31c5Sopenharmony_ci        addrinfo_ptr->ai_flags = addrinfow_ptr->ai_flags;
161e66f31c5Sopenharmony_ci        addrinfo_ptr->ai_addrlen = addrinfow_ptr->ai_addrlen;
162e66f31c5Sopenharmony_ci        addrinfo_ptr->ai_canonname = NULL;
163e66f31c5Sopenharmony_ci        addrinfo_ptr->ai_addr = NULL;
164e66f31c5Sopenharmony_ci        addrinfo_ptr->ai_next = NULL;
165e66f31c5Sopenharmony_ci
166e66f31c5Sopenharmony_ci        cur_ptr += addrinfo_struct_len;
167e66f31c5Sopenharmony_ci
168e66f31c5Sopenharmony_ci        /* copy sockaddr */
169e66f31c5Sopenharmony_ci        if (addrinfo_ptr->ai_addrlen > 0) {
170e66f31c5Sopenharmony_ci          assert(cur_ptr + addrinfo_ptr->ai_addrlen <=
171e66f31c5Sopenharmony_ci                 alloc_ptr + addrinfo_len);
172e66f31c5Sopenharmony_ci          memcpy(cur_ptr, addrinfow_ptr->ai_addr, addrinfo_ptr->ai_addrlen);
173e66f31c5Sopenharmony_ci          addrinfo_ptr->ai_addr = (struct sockaddr*)cur_ptr;
174e66f31c5Sopenharmony_ci          cur_ptr += ALIGNED_SIZE(addrinfo_ptr->ai_addrlen);
175e66f31c5Sopenharmony_ci        }
176e66f31c5Sopenharmony_ci
177e66f31c5Sopenharmony_ci        /* convert canonical name to UTF-8 */
178e66f31c5Sopenharmony_ci        if (addrinfow_ptr->ai_canonname != NULL) {
179e66f31c5Sopenharmony_ci          name_len = alloc_ptr + addrinfo_len - cur_ptr;
180e66f31c5Sopenharmony_ci          r = uv__copy_utf16_to_utf8(addrinfow_ptr->ai_canonname,
181e66f31c5Sopenharmony_ci                                     -1,
182e66f31c5Sopenharmony_ci                                     cur_ptr,
183e66f31c5Sopenharmony_ci                                     (size_t*)&name_len);
184e66f31c5Sopenharmony_ci          assert(r == 0);
185e66f31c5Sopenharmony_ci          addrinfo_ptr->ai_canonname = cur_ptr;
186e66f31c5Sopenharmony_ci          cur_ptr += ALIGNED_SIZE(name_len + 1);
187e66f31c5Sopenharmony_ci        }
188e66f31c5Sopenharmony_ci        assert(cur_ptr <= alloc_ptr + addrinfo_len);
189e66f31c5Sopenharmony_ci
190e66f31c5Sopenharmony_ci        /* set next ptr */
191e66f31c5Sopenharmony_ci        addrinfow_ptr = addrinfow_ptr->ai_next;
192e66f31c5Sopenharmony_ci        if (addrinfow_ptr != NULL) {
193e66f31c5Sopenharmony_ci          addrinfo_ptr->ai_next = (struct addrinfo*)cur_ptr;
194e66f31c5Sopenharmony_ci        }
195e66f31c5Sopenharmony_ci      }
196e66f31c5Sopenharmony_ci      req->addrinfo = (struct addrinfo*)alloc_ptr;
197e66f31c5Sopenharmony_ci    } else {
198e66f31c5Sopenharmony_ci      req->retcode = UV_EAI_MEMORY;
199e66f31c5Sopenharmony_ci    }
200e66f31c5Sopenharmony_ci  }
201e66f31c5Sopenharmony_ci
202e66f31c5Sopenharmony_ci  /* return memory to system */
203e66f31c5Sopenharmony_ci  if (req->addrinfow != NULL) {
204e66f31c5Sopenharmony_ci    FreeAddrInfoW(req->addrinfow);
205e66f31c5Sopenharmony_ci    req->addrinfow = NULL;
206e66f31c5Sopenharmony_ci  }
207e66f31c5Sopenharmony_ci
208e66f31c5Sopenharmony_cicomplete:
209e66f31c5Sopenharmony_ci  uv__req_unregister(req->loop, req);
210e66f31c5Sopenharmony_ci
211e66f31c5Sopenharmony_ci  /* finally do callback with converted result */
212e66f31c5Sopenharmony_ci  if (req->getaddrinfo_cb)
213e66f31c5Sopenharmony_ci    req->getaddrinfo_cb(req, req->retcode, req->addrinfo);
214e66f31c5Sopenharmony_ci}
215e66f31c5Sopenharmony_ci
216e66f31c5Sopenharmony_ci
217e66f31c5Sopenharmony_civoid uv_freeaddrinfo(struct addrinfo* ai) {
218e66f31c5Sopenharmony_ci  char* alloc_ptr = (char*)ai;
219e66f31c5Sopenharmony_ci
220e66f31c5Sopenharmony_ci  /* release copied result memory */
221e66f31c5Sopenharmony_ci  uv__free(alloc_ptr);
222e66f31c5Sopenharmony_ci}
223e66f31c5Sopenharmony_ci
224e66f31c5Sopenharmony_ci
225e66f31c5Sopenharmony_ci/*
226e66f31c5Sopenharmony_ci * Entry point for getaddrinfo
227e66f31c5Sopenharmony_ci * we convert the UTF-8 strings to UNICODE
228e66f31c5Sopenharmony_ci * and save the UNICODE string pointers in the req
229e66f31c5Sopenharmony_ci * We also copy hints so that caller does not need to keep memory until the
230e66f31c5Sopenharmony_ci * callback.
231e66f31c5Sopenharmony_ci * return 0 if a callback will be made
232e66f31c5Sopenharmony_ci * return error code if validation fails
233e66f31c5Sopenharmony_ci *
234e66f31c5Sopenharmony_ci * To minimize allocation we calculate total size required,
235e66f31c5Sopenharmony_ci * and copy all structs and referenced strings into the one block.
236e66f31c5Sopenharmony_ci * Each size calculation is adjusted to avoid unaligned pointers.
237e66f31c5Sopenharmony_ci */
238e66f31c5Sopenharmony_ciint uv_getaddrinfo(uv_loop_t* loop,
239e66f31c5Sopenharmony_ci                   uv_getaddrinfo_t* req,
240e66f31c5Sopenharmony_ci                   uv_getaddrinfo_cb getaddrinfo_cb,
241e66f31c5Sopenharmony_ci                   const char* node,
242e66f31c5Sopenharmony_ci                   const char* service,
243e66f31c5Sopenharmony_ci                   const struct addrinfo* hints) {
244e66f31c5Sopenharmony_ci  char hostname_ascii[256];
245e66f31c5Sopenharmony_ci  size_t nodesize = 0;
246e66f31c5Sopenharmony_ci  size_t servicesize = 0;
247e66f31c5Sopenharmony_ci  size_t hintssize = 0;
248e66f31c5Sopenharmony_ci  char* alloc_ptr = NULL;
249e66f31c5Sopenharmony_ci  ssize_t rc;
250e66f31c5Sopenharmony_ci
251e66f31c5Sopenharmony_ci  if (req == NULL || (node == NULL && service == NULL)) {
252e66f31c5Sopenharmony_ci    return UV_EINVAL;
253e66f31c5Sopenharmony_ci  }
254e66f31c5Sopenharmony_ci
255e66f31c5Sopenharmony_ci  UV_REQ_INIT(req, UV_GETADDRINFO);
256e66f31c5Sopenharmony_ci  req->getaddrinfo_cb = getaddrinfo_cb;
257e66f31c5Sopenharmony_ci  req->addrinfo = NULL;
258e66f31c5Sopenharmony_ci  req->loop = loop;
259e66f31c5Sopenharmony_ci  req->retcode = 0;
260e66f31c5Sopenharmony_ci
261e66f31c5Sopenharmony_ci  /* calculate required memory size for all input values */
262e66f31c5Sopenharmony_ci  if (node != NULL) {
263e66f31c5Sopenharmony_ci    rc = uv__idna_toascii(node,
264e66f31c5Sopenharmony_ci                          node + strlen(node),
265e66f31c5Sopenharmony_ci                          hostname_ascii,
266e66f31c5Sopenharmony_ci                          hostname_ascii + sizeof(hostname_ascii));
267e66f31c5Sopenharmony_ci    if (rc < 0)
268e66f31c5Sopenharmony_ci      return rc;
269e66f31c5Sopenharmony_ci    nodesize = strlen(hostname_ascii) + 1;
270e66f31c5Sopenharmony_ci    node = hostname_ascii;
271e66f31c5Sopenharmony_ci  }
272e66f31c5Sopenharmony_ci
273e66f31c5Sopenharmony_ci  if (service != NULL) {
274e66f31c5Sopenharmony_ci    rc = uv_wtf8_length_as_utf16(service);
275e66f31c5Sopenharmony_ci    if (rc < 0)
276e66f31c5Sopenharmony_ci       return rc;
277e66f31c5Sopenharmony_ci    servicesize = rc;
278e66f31c5Sopenharmony_ci  }
279e66f31c5Sopenharmony_ci  if (hints != NULL) {
280e66f31c5Sopenharmony_ci    hintssize = ALIGNED_SIZE(sizeof(struct addrinfoW));
281e66f31c5Sopenharmony_ci  }
282e66f31c5Sopenharmony_ci
283e66f31c5Sopenharmony_ci  /* allocate memory for inputs, and partition it as needed */
284e66f31c5Sopenharmony_ci  alloc_ptr = uv__malloc(ALIGNED_SIZE(nodesize * sizeof(WCHAR)) +
285e66f31c5Sopenharmony_ci                         ALIGNED_SIZE(servicesize * sizeof(WCHAR)) +
286e66f31c5Sopenharmony_ci                         hintssize);
287e66f31c5Sopenharmony_ci  if (!alloc_ptr)
288e66f31c5Sopenharmony_ci    return UV_ENOMEM;
289e66f31c5Sopenharmony_ci
290e66f31c5Sopenharmony_ci  /* save alloc_ptr now so we can free if error */
291e66f31c5Sopenharmony_ci  req->alloc = (void*) alloc_ptr;
292e66f31c5Sopenharmony_ci
293e66f31c5Sopenharmony_ci  /* Convert node string to UTF16 into allocated memory and save pointer in the
294e66f31c5Sopenharmony_ci   * request. The node here has been converted to ascii. */
295e66f31c5Sopenharmony_ci  if (node != NULL) {
296e66f31c5Sopenharmony_ci    req->node = (WCHAR*) alloc_ptr;
297e66f31c5Sopenharmony_ci    uv_wtf8_to_utf16(node, (WCHAR*) alloc_ptr, nodesize);
298e66f31c5Sopenharmony_ci    alloc_ptr += ALIGNED_SIZE(nodesize * sizeof(WCHAR));
299e66f31c5Sopenharmony_ci  } else {
300e66f31c5Sopenharmony_ci    req->node = NULL;
301e66f31c5Sopenharmony_ci  }
302e66f31c5Sopenharmony_ci
303e66f31c5Sopenharmony_ci  /* Convert service string to UTF16 into allocated memory and save pointer in
304e66f31c5Sopenharmony_ci   * the req. */
305e66f31c5Sopenharmony_ci  if (service != NULL) {
306e66f31c5Sopenharmony_ci    req->service = (WCHAR*) alloc_ptr;
307e66f31c5Sopenharmony_ci    uv_wtf8_to_utf16(service, (WCHAR*) alloc_ptr, servicesize);
308e66f31c5Sopenharmony_ci    alloc_ptr += ALIGNED_SIZE(servicesize * sizeof(WCHAR));
309e66f31c5Sopenharmony_ci  } else {
310e66f31c5Sopenharmony_ci    req->service = NULL;
311e66f31c5Sopenharmony_ci  }
312e66f31c5Sopenharmony_ci
313e66f31c5Sopenharmony_ci  /* copy hints to allocated memory and save pointer in req */
314e66f31c5Sopenharmony_ci  if (hints != NULL) {
315e66f31c5Sopenharmony_ci    req->addrinfow = (struct addrinfoW*) alloc_ptr;
316e66f31c5Sopenharmony_ci    req->addrinfow->ai_family = hints->ai_family;
317e66f31c5Sopenharmony_ci    req->addrinfow->ai_socktype = hints->ai_socktype;
318e66f31c5Sopenharmony_ci    req->addrinfow->ai_protocol = hints->ai_protocol;
319e66f31c5Sopenharmony_ci    req->addrinfow->ai_flags = hints->ai_flags;
320e66f31c5Sopenharmony_ci    req->addrinfow->ai_addrlen = 0;
321e66f31c5Sopenharmony_ci    req->addrinfow->ai_canonname = NULL;
322e66f31c5Sopenharmony_ci    req->addrinfow->ai_addr = NULL;
323e66f31c5Sopenharmony_ci    req->addrinfow->ai_next = NULL;
324e66f31c5Sopenharmony_ci  } else {
325e66f31c5Sopenharmony_ci    req->addrinfow = NULL;
326e66f31c5Sopenharmony_ci  }
327e66f31c5Sopenharmony_ci
328e66f31c5Sopenharmony_ci  uv__req_register(loop, req);
329e66f31c5Sopenharmony_ci
330e66f31c5Sopenharmony_ci  if (getaddrinfo_cb) {
331e66f31c5Sopenharmony_ci    uv__work_submit(loop,
332e66f31c5Sopenharmony_ci                    &req->work_req,
333e66f31c5Sopenharmony_ci                    UV__WORK_SLOW_IO,
334e66f31c5Sopenharmony_ci                    uv__getaddrinfo_work,
335e66f31c5Sopenharmony_ci                    uv__getaddrinfo_done);
336e66f31c5Sopenharmony_ci    return 0;
337e66f31c5Sopenharmony_ci  } else {
338e66f31c5Sopenharmony_ci    uv__getaddrinfo_work(&req->work_req);
339e66f31c5Sopenharmony_ci    uv__getaddrinfo_done(&req->work_req, 0);
340e66f31c5Sopenharmony_ci    return req->retcode;
341e66f31c5Sopenharmony_ci  }
342e66f31c5Sopenharmony_ci}
343e66f31c5Sopenharmony_ci
344e66f31c5Sopenharmony_ciint uv_if_indextoname(unsigned int ifindex, char* buffer, size_t* size) {
345e66f31c5Sopenharmony_ci  NET_LUID luid;
346e66f31c5Sopenharmony_ci  wchar_t wname[NDIS_IF_MAX_STRING_SIZE + 1]; /* Add one for the NUL. */
347e66f31c5Sopenharmony_ci  int r;
348e66f31c5Sopenharmony_ci
349e66f31c5Sopenharmony_ci  if (buffer == NULL || size == NULL || *size == 0)
350e66f31c5Sopenharmony_ci    return UV_EINVAL;
351e66f31c5Sopenharmony_ci
352e66f31c5Sopenharmony_ci  r = ConvertInterfaceIndexToLuid(ifindex, &luid);
353e66f31c5Sopenharmony_ci
354e66f31c5Sopenharmony_ci  if (r != 0)
355e66f31c5Sopenharmony_ci    return uv_translate_sys_error(r);
356e66f31c5Sopenharmony_ci
357e66f31c5Sopenharmony_ci  r = ConvertInterfaceLuidToNameW(&luid, wname, ARRAY_SIZE(wname));
358e66f31c5Sopenharmony_ci
359e66f31c5Sopenharmony_ci  if (r != 0)
360e66f31c5Sopenharmony_ci    return uv_translate_sys_error(r);
361e66f31c5Sopenharmony_ci
362e66f31c5Sopenharmony_ci  return uv__copy_utf16_to_utf8(wname, -1, buffer, size);
363e66f31c5Sopenharmony_ci}
364e66f31c5Sopenharmony_ci
365e66f31c5Sopenharmony_ciint uv_if_indextoiid(unsigned int ifindex, char* buffer, size_t* size) {
366e66f31c5Sopenharmony_ci  int r;
367e66f31c5Sopenharmony_ci
368e66f31c5Sopenharmony_ci  if (buffer == NULL || size == NULL || *size == 0)
369e66f31c5Sopenharmony_ci    return UV_EINVAL;
370e66f31c5Sopenharmony_ci
371e66f31c5Sopenharmony_ci  r = snprintf(buffer, *size, "%d", ifindex);
372e66f31c5Sopenharmony_ci
373e66f31c5Sopenharmony_ci  if (r < 0)
374e66f31c5Sopenharmony_ci    return uv_translate_sys_error(r);
375e66f31c5Sopenharmony_ci
376e66f31c5Sopenharmony_ci  if (r >= (int) *size) {
377e66f31c5Sopenharmony_ci    *size = r + 1;
378e66f31c5Sopenharmony_ci    return UV_ENOBUFS;
379e66f31c5Sopenharmony_ci  }
380e66f31c5Sopenharmony_ci
381e66f31c5Sopenharmony_ci  *size = r;
382e66f31c5Sopenharmony_ci  return 0;
383e66f31c5Sopenharmony_ci}
384