aboutsummaryrefslogtreecommitdiff
path: root/lib/libc/mingw/libsrc/wspiapi/WspiapiLegacyGetAddrInfo.c
blob: b5aa39244ceca488d13e05ba406b62b83d135920 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#undef  __CRT__NO_INLINE
#define __CRT__NO_INLINE
#include <winsock2.h>
#include <wspiapi.h>

int WINAPI
WspiapiLegacyGetAddrInfo(const char *pszNodeName,
			 const char *pszServiceName,
			 const struct addrinfo *ptHints,
			 struct addrinfo **pptResult)
{
  int err = 0, iFlags = 0, iFamily = PF_UNSPEC, iSocketType = 0, iProtocol = 0;
  struct in_addr inAddress;
  struct servent *svc = NULL;
  char *pc = NULL;
  WINBOOL isCloned = FALSE;
  WORD tcpPort = 0, udpPort = 0, port = 0;

  *pptResult = NULL;
  if (!pszNodeName && !pszServiceName)
    return EAI_NONAME;
  if (ptHints)
    {
	if (ptHints->ai_addrlen != 0 || ptHints->ai_canonname != NULL
	    || ptHints->ai_addr!=NULL || ptHints->ai_next != NULL)
	  return EAI_FAIL;
	iFlags = ptHints->ai_flags;
	if ((iFlags & AI_CANONNAME) != 0 && !pszNodeName)
	  return EAI_BADFLAGS;
	iFamily = ptHints->ai_family;
	if (iFamily != PF_UNSPEC && iFamily != PF_INET)
	  return EAI_FAMILY;
	iSocketType = ptHints->ai_socktype;
	if (iSocketType != 0 && iSocketType != SOCK_STREAM && iSocketType != SOCK_DGRAM
	    && iSocketType != SOCK_RAW)
	  return EAI_SOCKTYPE;
	iProtocol = ptHints->ai_protocol;
    }

  if (pszServiceName)
    {
	port = (WORD) strtoul (pszServiceName, &pc, 10);
	if(*pc == 0)
	  {
	    port = tcpPort = udpPort = htons (port);
	    if (iSocketType == 0)
	      {
		isCloned = TRUE;
		iSocketType = SOCK_STREAM;
	      }
	  }
	else
	  {
	    if (iSocketType == 0 || iSocketType == SOCK_DGRAM)
	      {
		svc = getservbyname(pszServiceName, "udp");
		if (svc)
		  port = udpPort = svc->s_port;
	      }
	    if (iSocketType == 0 || iSocketType == SOCK_STREAM)
	      {
		svc = getservbyname(pszServiceName, "tcp");
		if (svc)
		  port = tcpPort = svc->s_port;
	      }
	    if (port == 0)
	      return (iSocketType ? EAI_SERVICE : EAI_NONAME);
	    if (iSocketType==0)
	      {
		iSocketType = (tcpPort) ? SOCK_STREAM : SOCK_DGRAM;
		isCloned = (tcpPort && udpPort);
	      }
	  }
    }
  if (!pszNodeName || WspiapiParseV4Address(pszNodeName,&inAddress.s_addr))
    {
	if (!pszNodeName)
	  {
	    inAddress.s_addr = htonl ((iFlags & AI_PASSIVE) ? INADDR_ANY : INADDR_LOOPBACK);
	  }
      *pptResult = WspiapiNewAddrInfo(iSocketType, iProtocol, port, inAddress.s_addr);
      if (!(*pptResult))
	  err = EAI_MEMORY;
	if (!err && pszNodeName)
	  {
	    (*pptResult)->ai_flags |= AI_NUMERICHOST;
	    if (iFlags & AI_CANONNAME)
	      {
		(*pptResult)->ai_canonname =
		  WspiapiStrdup (inet_ntoa (inAddress));
		if (!(*pptResult)->ai_canonname)
		  err = EAI_MEMORY;
	      }
	  }
    }
  else if (iFlags & AI_NUMERICHOST)
    err = EAI_NONAME;
  else
    err = WspiapiLookupNode (pszNodeName, iSocketType, iProtocol, port,
			       (iFlags & AI_CANONNAME), pptResult);
  if (!err && isCloned)
    err = WspiapiClone(udpPort, *pptResult);
  if (err)
    {
	WspiapiLegacyFreeAddrInfo (*pptResult);
	*pptResult = NULL;
    }
  return err;
}