Rizin
unix-like reverse engineering framework and cli tools
getaddrinfo.c File Reference
#include <assert.h>
#include "uv.h"
#include "internal.h"
#include "req-inl.h"
#include "idna.h"
#include <winsock2.h>
#include <iphlpapi.h>

Go to the source code of this file.

Classes

struct  addrinfoW
 

Macros

#define ALIGNED_SIZE(X)   ((((X) + 3) >> 2) << 2)
 
#define NDIS_IF_MAX_STRING_SIZE   IF_MAX_STRING_SIZE
 

Typedefs

typedef struct addrinfoW ADDRINFOW
 
typedef struct addrinfoWPADDRINFOW
 

Functions

int uv__getaddrinfo_translate_error (int sys_err)
 
DECLSPEC_IMPORT int WSAAPI GetAddrInfoW (const WCHAR *node, const WCHAR *service, const ADDRINFOW *hints, PADDRINFOW *result)
 
DECLSPEC_IMPORT void WSAAPI FreeAddrInfoW (PADDRINFOW pAddrInfo)
 
static void uv__getaddrinfo_work (struct uv__work *w)
 
static void uv__getaddrinfo_done (struct uv__work *w, int status)
 
void uv_freeaddrinfo (struct addrinfo *ai)
 
int uv_getaddrinfo (uv_loop_t *loop, uv_getaddrinfo_t *req, uv_getaddrinfo_cb getaddrinfo_cb, const char *node, const char *service, const struct addrinfo *hints)
 
int uv_if_indextoname (unsigned int ifindex, char *buffer, size_t *size)
 
int uv_if_indextoiid (unsigned int ifindex, char *buffer, size_t *size)
 

Macro Definition Documentation

◆ ALIGNED_SIZE

#define ALIGNED_SIZE (   X)    ((((X) + 3) >> 2) << 2)

Definition at line 77 of file getaddrinfo.c.

◆ NDIS_IF_MAX_STRING_SIZE

#define NDIS_IF_MAX_STRING_SIZE   IF_MAX_STRING_SIZE

Definition at line 80 of file getaddrinfo.c.

Typedef Documentation

◆ ADDRINFOW

typedef struct addrinfoW ADDRINFOW

◆ PADDRINFOW

typedef struct addrinfoW * PADDRINFOW

Function Documentation

◆ FreeAddrInfoW()

DECLSPEC_IMPORT void WSAAPI FreeAddrInfoW ( PADDRINFOW  pAddrInfo)

Referenced by uv__getaddrinfo_done().

◆ GetAddrInfoW()

DECLSPEC_IMPORT int WSAAPI GetAddrInfoW ( const WCHAR *  node,
const WCHAR *  service,
const ADDRINFOW hints,
PADDRINFOW result 
)

Referenced by uv__getaddrinfo_work().

◆ uv__getaddrinfo_done()

static void uv__getaddrinfo_done ( struct uv__work w,
int  status 
)
static

Definition at line 105 of file getaddrinfo.c.

105  {
107  int addrinfo_len = 0;
108  int name_len = 0;
109  size_t addrinfo_struct_len = ALIGNED_SIZE(sizeof(struct addrinfo));
110  struct addrinfoW* addrinfow_ptr;
111  struct addrinfo* addrinfo_ptr;
112  char* alloc_ptr = NULL;
113  char* cur_ptr = NULL;
114 
115  req = container_of(w, uv_getaddrinfo_t, work_req);
116 
117  /* release input parameter memory */
118  uv__free(req->alloc);
119  req->alloc = NULL;
120 
121  if (status == UV_ECANCELED) {
122  assert(req->retcode == 0);
123  req->retcode = UV_EAI_CANCELED;
124  goto complete;
125  }
126 
127  if (req->retcode == 0) {
128  /* Convert addrinfoW to addrinfo. First calculate required length. */
129  addrinfow_ptr = req->addrinfow;
130  while (addrinfow_ptr != NULL) {
131  addrinfo_len += addrinfo_struct_len +
132  ALIGNED_SIZE(addrinfow_ptr->ai_addrlen);
133  if (addrinfow_ptr->ai_canonname != NULL) {
134  name_len = WideCharToMultiByte(CP_UTF8,
135  0,
136  addrinfow_ptr->ai_canonname,
137  -1,
138  NULL,
139  0,
140  NULL,
141  NULL);
142  if (name_len == 0) {
143  req->retcode = uv_translate_sys_error(GetLastError());
144  goto complete;
145  }
146  addrinfo_len += ALIGNED_SIZE(name_len);
147  }
148  addrinfow_ptr = addrinfow_ptr->ai_next;
149  }
150 
151  /* allocate memory for addrinfo results */
152  alloc_ptr = (char*)uv__malloc(addrinfo_len);
153 
154  /* do conversions */
155  if (alloc_ptr != NULL) {
156  cur_ptr = alloc_ptr;
157  addrinfow_ptr = req->addrinfow;
158 
159  while (addrinfow_ptr != NULL) {
160  /* copy addrinfo struct data */
161  assert(cur_ptr + addrinfo_struct_len <= alloc_ptr + addrinfo_len);
162  addrinfo_ptr = (struct addrinfo*)cur_ptr;
163  addrinfo_ptr->ai_family = addrinfow_ptr->ai_family;
164  addrinfo_ptr->ai_socktype = addrinfow_ptr->ai_socktype;
165  addrinfo_ptr->ai_protocol = addrinfow_ptr->ai_protocol;
166  addrinfo_ptr->ai_flags = addrinfow_ptr->ai_flags;
167  addrinfo_ptr->ai_addrlen = addrinfow_ptr->ai_addrlen;
168  addrinfo_ptr->ai_canonname = NULL;
169  addrinfo_ptr->ai_addr = NULL;
170  addrinfo_ptr->ai_next = NULL;
171 
172  cur_ptr += addrinfo_struct_len;
173 
174  /* copy sockaddr */
175  if (addrinfo_ptr->ai_addrlen > 0) {
176  assert(cur_ptr + addrinfo_ptr->ai_addrlen <=
177  alloc_ptr + addrinfo_len);
178  memcpy(cur_ptr, addrinfow_ptr->ai_addr, addrinfo_ptr->ai_addrlen);
179  addrinfo_ptr->ai_addr = (struct sockaddr*)cur_ptr;
180  cur_ptr += ALIGNED_SIZE(addrinfo_ptr->ai_addrlen);
181  }
182 
183  /* convert canonical name to UTF-8 */
184  if (addrinfow_ptr->ai_canonname != NULL) {
185  name_len = WideCharToMultiByte(CP_UTF8,
186  0,
187  addrinfow_ptr->ai_canonname,
188  -1,
189  NULL,
190  0,
191  NULL,
192  NULL);
193  assert(name_len > 0);
194  assert(cur_ptr + name_len <= alloc_ptr + addrinfo_len);
195  name_len = WideCharToMultiByte(CP_UTF8,
196  0,
197  addrinfow_ptr->ai_canonname,
198  -1,
199  cur_ptr,
200  name_len,
201  NULL,
202  NULL);
203  assert(name_len > 0);
204  addrinfo_ptr->ai_canonname = cur_ptr;
205  cur_ptr += ALIGNED_SIZE(name_len);
206  }
207  assert(cur_ptr <= alloc_ptr + addrinfo_len);
208 
209  /* set next ptr */
210  addrinfow_ptr = addrinfow_ptr->ai_next;
211  if (addrinfow_ptr != NULL) {
212  addrinfo_ptr->ai_next = (struct addrinfo*)cur_ptr;
213  }
214  }
215  req->addrinfo = (struct addrinfo*)alloc_ptr;
216  } else {
217  req->retcode = UV_EAI_MEMORY;
218  }
219  }
220 
221  /* return memory to system */
222  if (req->addrinfow != NULL) {
223  FreeAddrInfoW(req->addrinfow);
224  req->addrinfow = NULL;
225  }
226 
227 complete:
228  uv__req_unregister(req->loop, req);
229 
230  /* finally do callback with converted result */
231  if (req->getaddrinfo_cb)
232  req->getaddrinfo_cb(req, req->retcode, req->addrinfo);
233 }
#define NULL
Definition: cris-opc.c:27
#define w
Definition: crypto_rc6.c:13
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len static semflg const void static shmflg const struct timespec req
Definition: sflib.h:128
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
static const char struct stat static buf struct stat static buf static vhangup int status
Definition: sflib.h:145
assert(limit<=UINT32_MAX/2)
#define container_of(ptr, type, member)
Definition: rz_types.h:650
WCHAR * ai_canonname
Definition: getaddrinfo.c:61
int ai_protocol
Definition: getaddrinfo.c:59
size_t ai_addrlen
Definition: getaddrinfo.c:60
struct addrinfoW * ai_next
Definition: getaddrinfo.c:63
int ai_flags
Definition: getaddrinfo.c:56
int ai_family
Definition: getaddrinfo.c:57
struct sockaddr * ai_addr
Definition: getaddrinfo.c:62
int ai_socktype
Definition: getaddrinfo.c:58
void * uv__malloc(size_t size)
Definition: uv-common.c:75
void uv__free(void *ptr)
Definition: uv-common.c:81
#define uv__req_unregister(loop, req)
Definition: uv-common.h:230
UV_EXTERN int uv_translate_sys_error(int sys_errno)
Definition: core.c:1249
#define ALIGNED_SIZE(X)
Definition: getaddrinfo.c:77
DECLSPEC_IMPORT void WSAAPI FreeAddrInfoW(PADDRINFOW pAddrInfo)

References addrinfoW::ai_addr, addrinfoW::ai_addrlen, addrinfoW::ai_canonname, addrinfoW::ai_family, addrinfoW::ai_flags, addrinfoW::ai_next, addrinfoW::ai_protocol, addrinfoW::ai_socktype, ALIGNED_SIZE, assert(), container_of, FreeAddrInfoW(), memcpy(), NULL, req, status, uv__free(), uv__malloc(), uv__req_unregister, uv_translate_sys_error(), and w.

Referenced by uv_getaddrinfo().

◆ uv__getaddrinfo_translate_error()

int uv__getaddrinfo_translate_error ( int  sys_err)

Definition at line 35 of file getaddrinfo.c.

35  {
36  switch (sys_err) {
37  case 0: return 0;
38  case WSATRY_AGAIN: return UV_EAI_AGAIN;
39  case WSAEINVAL: return UV_EAI_BADFLAGS;
40  case WSANO_RECOVERY: return UV_EAI_FAIL;
41  case WSAEAFNOSUPPORT: return UV_EAI_FAMILY;
42  case WSA_NOT_ENOUGH_MEMORY: return UV_EAI_MEMORY;
43  case WSAHOST_NOT_FOUND: return UV_EAI_NONAME;
44  case WSATYPE_NOT_FOUND: return UV_EAI_SERVICE;
45  case WSAESOCKTNOSUPPORT: return UV_EAI_SOCKTYPE;
46  default: return uv_translate_sys_error(sys_err);
47  }
48 }

References uv_translate_sys_error().

◆ uv__getaddrinfo_work()

static void uv__getaddrinfo_work ( struct uv__work w)
static

Definition at line 83 of file getaddrinfo.c.

83  {
85  struct addrinfoW* hints;
86  int err;
87 
88  req = container_of(w, uv_getaddrinfo_t, work_req);
89  hints = req->addrinfow;
90  req->addrinfow = NULL;
91  err = GetAddrInfoW(req->node, req->service, hints, &req->addrinfow);
93 }
static bool err
Definition: armass.c:435
int uv__getaddrinfo_translate_error(int sys_err)
Definition: getaddrinfo.c:42
DECLSPEC_IMPORT int WSAAPI GetAddrInfoW(const WCHAR *node, const WCHAR *service, const ADDRINFOW *hints, PADDRINFOW *result)

References container_of, err, GetAddrInfoW(), NULL, req, uv__getaddrinfo_translate_error(), and w.

Referenced by uv_getaddrinfo().

◆ uv_freeaddrinfo()

void uv_freeaddrinfo ( struct addrinfo *  ai)

Definition at line 236 of file getaddrinfo.c.

236  {
237  char* alloc_ptr = (char*)ai;
238 
239  /* release copied result memory */
240  uv__free(alloc_ptr);
241 }

References uv__free().

Referenced by on_resolved().

◆ uv_getaddrinfo()

int uv_getaddrinfo ( uv_loop_t loop,
uv_getaddrinfo_t req,
uv_getaddrinfo_cb  getaddrinfo_cb,
const char *  node,
const char *  service,
const struct addrinfo *  hints 
)

Definition at line 257 of file getaddrinfo.c.

262  {
263  char hostname_ascii[256];
264  int nodesize = 0;
265  int servicesize = 0;
266  int hintssize = 0;
267  char* alloc_ptr = NULL;
268  int err;
269  long rc;
270 
271  if (req == NULL || (node == NULL && service == NULL)) {
272  return UV_EINVAL;
273  }
274 
275  UV_REQ_INIT(req, UV_GETADDRINFO);
276  req->getaddrinfo_cb = getaddrinfo_cb;
277  req->addrinfo = NULL;
278  req->loop = loop;
279  req->retcode = 0;
280 
281  /* calculate required memory size for all input values */
282  if (node != NULL) {
283  rc = uv__idna_toascii(node,
284  node + strlen(node),
285  hostname_ascii,
286  hostname_ascii + sizeof(hostname_ascii));
287  if (rc < 0)
288  return rc;
289  nodesize = ALIGNED_SIZE(MultiByteToWideChar(CP_UTF8, 0, hostname_ascii,
290  -1, NULL, 0) * sizeof(WCHAR));
291  if (nodesize == 0) {
292  err = GetLastError();
293  goto error;
294  }
295  node = hostname_ascii;
296  }
297 
298  if (service != NULL) {
299  servicesize = ALIGNED_SIZE(MultiByteToWideChar(CP_UTF8,
300  0,
301  service,
302  -1,
303  NULL,
304  0) *
305  sizeof(WCHAR));
306  if (servicesize == 0) {
307  err = GetLastError();
308  goto error;
309  }
310  }
311  if (hints != NULL) {
312  hintssize = ALIGNED_SIZE(sizeof(struct addrinfoW));
313  }
314 
315  /* allocate memory for inputs, and partition it as needed */
316  alloc_ptr = (char*)uv__malloc(nodesize + servicesize + hintssize);
317  if (!alloc_ptr) {
318  err = WSAENOBUFS;
319  goto error;
320  }
321 
322  /* save alloc_ptr now so we can free if error */
323  req->alloc = (void*)alloc_ptr;
324 
325  /* Convert node string to UTF16 into allocated memory and save pointer in the
326  * request. */
327  if (node != NULL) {
328  req->node = (WCHAR*)alloc_ptr;
329  if (MultiByteToWideChar(CP_UTF8,
330  0,
331  node,
332  -1,
333  (WCHAR*) alloc_ptr,
334  nodesize / sizeof(WCHAR)) == 0) {
335  err = GetLastError();
336  goto error;
337  }
338  alloc_ptr += nodesize;
339  } else {
340  req->node = NULL;
341  }
342 
343  /* Convert service string to UTF16 into allocated memory and save pointer in
344  * the req. */
345  if (service != NULL) {
346  req->service = (WCHAR*)alloc_ptr;
347  if (MultiByteToWideChar(CP_UTF8,
348  0,
349  service,
350  -1,
351  (WCHAR*) alloc_ptr,
352  servicesize / sizeof(WCHAR)) == 0) {
353  err = GetLastError();
354  goto error;
355  }
356  alloc_ptr += servicesize;
357  } else {
358  req->service = NULL;
359  }
360 
361  /* copy hints to allocated memory and save pointer in req */
362  if (hints != NULL) {
363  req->addrinfow = (struct addrinfoW*)alloc_ptr;
364  req->addrinfow->ai_family = hints->ai_family;
365  req->addrinfow->ai_socktype = hints->ai_socktype;
366  req->addrinfow->ai_protocol = hints->ai_protocol;
367  req->addrinfow->ai_flags = hints->ai_flags;
368  req->addrinfow->ai_addrlen = 0;
369  req->addrinfow->ai_canonname = NULL;
370  req->addrinfow->ai_addr = NULL;
371  req->addrinfow->ai_next = NULL;
372  } else {
373  req->addrinfow = NULL;
374  }
375 
377 
378  if (getaddrinfo_cb) {
380  &req->work_req,
384  return 0;
385  } else {
386  uv__getaddrinfo_work(&req->work_req);
387  uv__getaddrinfo_done(&req->work_req, 0);
388  return req->retcode;
389  }
390 
391 error:
392  if (req != NULL) {
393  uv__free(req->alloc);
394  req->alloc = NULL;
395  }
396  return uv_translate_sys_error(err);
397 }
long uv__idna_toascii(const char *s, const char *se, char *d, char *de)
Definition: idna.c:250
uv_loop_t * loop
Definition: main.c:7
void uv__work_submit(uv_loop_t *loop, struct uv__work *w, enum uv__work_kind kind, void(*work)(struct uv__work *w), void(*done)(struct uv__work *w, int status))
Definition: threadpool.c:256
void error(const char *msg)
Definition: untgz.c:593
#define UV_REQ_INIT(req, typ)
Definition: uv-common.h:322
@ UV__WORK_SLOW_IO
Definition: uv-common.h:194
#define uv__req_register(loop, req)
Definition: uv-common.h:224
static void uv__getaddrinfo_work(struct uv__work *w)
Definition: getaddrinfo.c:83
static void uv__getaddrinfo_done(struct uv__work *w, int status)
Definition: getaddrinfo.c:105

References ALIGNED_SIZE, cb, err, error(), len, loop, memcpy(), NULL, req, uv__free(), uv__getaddrinfo_done(), uv__getaddrinfo_work(), uv__idna_toascii(), uv__malloc(), uv__req_init, uv__req_register, UV__WORK_SLOW_IO, uv__work_submit(), UV_REQ_INIT, and uv_translate_sys_error().

Referenced by main().

◆ uv_if_indextoiid()

int uv_if_indextoiid ( unsigned int  ifindex,
char *  buffer,
size_t size 
)

Definition at line 445 of file getaddrinfo.c.

445  {
446  int r;
447 
448  if (buffer == NULL || size == NULL || *size == 0)
449  return UV_EINVAL;
450 
451  r = snprintf(buffer, *size, "%d", ifindex);
452 
453  if (r < 0)
454  return uv_translate_sys_error(r);
455 
456  if (r >= (int) *size) {
457  *size = r + 1;
458  return UV_ENOBUFS;
459  }
460 
461  *size = r;
462  return 0;
463 }
#define r
Definition: crypto_rc6.c:12
voidpf void uLong size
Definition: ioapi.h:138
snprintf
Definition: kernel.h:364
Definition: buffer.h:15

References NULL, r, snprintf, uv_if_indextoname(), and uv_translate_sys_error().

◆ uv_if_indextoname()

int uv_if_indextoname ( unsigned int  ifindex,
char *  buffer,
size_t size 
)

Definition at line 399 of file getaddrinfo.c.

399  {
400  NET_LUID luid;
401  wchar_t wname[NDIS_IF_MAX_STRING_SIZE + 1]; /* Add one for the NUL. */
402  DWORD bufsize;
403  int r;
404 
405  if (buffer == NULL || size == NULL || *size == 0)
406  return UV_EINVAL;
407 
408  r = ConvertInterfaceIndexToLuid(ifindex, &luid);
409 
410  if (r != 0)
411  return uv_translate_sys_error(r);
412 
413  r = ConvertInterfaceLuidToNameW(&luid, wname, ARRAY_SIZE(wname));
414 
415  if (r != 0)
416  return uv_translate_sys_error(r);
417 
418  /* Check how much space we need */
419  bufsize = WideCharToMultiByte(CP_UTF8, 0, wname, -1, NULL, 0, NULL, NULL);
420 
421  if (bufsize == 0) {
422  return uv_translate_sys_error(GetLastError());
423  } else if (bufsize > *size) {
424  *size = bufsize;
425  return UV_ENOBUFS;
426  }
427 
428  /* Convert to UTF-8 */
429  bufsize = WideCharToMultiByte(CP_UTF8,
430  0,
431  wname,
432  -1,
433  buffer,
434  *size,
435  NULL,
436  NULL);
437 
438  if (bufsize == 0)
439  return uv_translate_sys_error(GetLastError());
440 
441  *size = bufsize - 1;
442  return 0;
443 }
#define ARRAY_SIZE(a)
#define NDIS_IF_MAX_STRING_SIZE
Definition: getaddrinfo.c:80
DWORD

References ARRAY_SIZE, DWORD, len, memcpy(), NDIS_IF_MAX_STRING_SIZE, NULL, r, strnlen(), UV__ERR, UV_IF_NAMESIZE, and uv_translate_sys_error().