1 /*****************************************************************
2 |
3 |      Neptune - Network :: BSD Implementation
4 |
5 |      (c) 2001-2005 Gilles Boccon-Gibod
6 |      Author: Gilles Boccon-Gibod (bok@bok.net)
7 |
8  ****************************************************************/
9 
10 /*----------------------------------------------------------------------
11 |   includes
12 +---------------------------------------------------------------------*/
13 #if (defined(_WIN32) || defined(_WIN32_WCE) || defined(_XBOX)) && !defined(__SYMBIAN32__)
14 #if !defined(__WINSOCK__)
15 #define __WINSOCK__
16 #endif
17 #endif
18 
19 #if defined(__WINSOCK__) && !defined(_XBOX)
20 #define STRICT
21 #define NPT_WIN32_USE_WINSOCK2
22 #ifdef NPT_WIN32_USE_WINSOCK2
23 /* it is important to include this in this order, because winsock.h and ws2tcpip.h */
24 /* have different definitions for the same preprocessor symbols, such as IP_ADD_MEMBERSHIP */
25 #include <winsock2.h>
26 #include <ws2tcpip.h>
27 #else
28 #include <winsock.h>
29 #endif
30 #include <windows.h>
31 
32 // force a reference to the initializer so that the linker does not optimize it out
33 #include "NptWin32Network.h" // we need this for the static initializer
34 static NPT_WinsockSystem& WinsockInitializer = NPT_WinsockSystem::Initializer;
35 
36 #else
37 
38 #include <sys/types.h>
39 #include <sys/socket.h>
40 #include <netinet/in.h>
41 #include <netdb.h>
42 #include <errno.h>
43 
44 #endif
45 
46 #include "NptConfig.h"
47 #include "NptTypes.h"
48 #include "NptNetwork.h"
49 #include "NptUtils.h"
50 #include "NptConstants.h"
51 #include "NptResults.h"
52 #include "NptSockets.h"
53 
54 #if defined(NPT_CONFIG_HAVE_GETADDRINFO)
55 /*----------------------------------------------------------------------
56 |   constants
57 +---------------------------------------------------------------------*/
58 const unsigned int NPT_BSD_NETWORK_MAX_ADDR_LIST_LENGTH = 1024;
59 
60 /*----------------------------------------------------------------------
61 |   IPv6 support
62 +---------------------------------------------------------------------*/
63 #if defined(NPT_CONFIG_ENABLE_IPV6)
64 #include <arpa/inet.h>
65 #endif
66 
67 /*----------------------------------------------------------------------
68 |   MapGetAddrInfoErrorCode
69 +---------------------------------------------------------------------*/
70 static NPT_Result
MapGetAddrInfoErrorCode(int)71 MapGetAddrInfoErrorCode(int /*error_code*/)
72 {
73     return NPT_ERROR_HOST_UNKNOWN;
74 }
75 
76 /*----------------------------------------------------------------------
77 |   NPT_NetworkNameResolver::Resolve
78 +---------------------------------------------------------------------*/
79 NPT_Result
Resolve(const char * name,NPT_List<NPT_IpAddress> & addresses,NPT_Timeout)80 NPT_NetworkNameResolver::Resolve(const char*              name,
81                                  NPT_List<NPT_IpAddress>& addresses,
82                                  NPT_Timeout              /*timeout*/)
83 {
84     // empty the list first
85     addresses.Clear();
86 
87 
88     // get the addr list
89 
90     //struct addrinfo hints;
91     //NPT_SetMemory(&hints, 0, sizeof(hints));
92     //hints.ai_family   = PF_UNSPEC;
93     //hints.ai_socktype = SOCK_STREAM;
94     //hints.ai_flags    = AI_DEFAULT;
95     struct addrinfo *infos = NULL;
96     int result = getaddrinfo(name,  /* hostname */
97                              NULL,  /* servname */
98                              NULL,  /* hints    */
99                              &infos /* res      */);
100     if (result != 0) {
101         return MapGetAddrInfoErrorCode(result);
102     }
103 
104     for (struct addrinfo* info = infos;
105                           info && addresses.GetItemCount() < NPT_BSD_NETWORK_MAX_ADDR_LIST_LENGTH;
106                           info = info->ai_next) {
107         unsigned int expected_length;
108         if (info->ai_family == AF_INET) {
109             expected_length = sizeof(struct sockaddr_in);
110 #if defined(NPT_CONFIG_ENABLE_IPV6)
111         } else if (info->ai_family == AF_INET6) {
112             expected_length = sizeof(struct sockaddr_in6);
113 #endif
114         } else {
115             continue;
116         }
117         if ((unsigned int)info->ai_addrlen < expected_length) continue;
118         if (info->ai_protocol != 0 && info->ai_protocol != IPPROTO_TCP) continue;
119 
120         if (info->ai_family == AF_INET) {
121             struct sockaddr_in* inet_addr = (struct sockaddr_in*)info->ai_addr;
122             NPT_IpAddress address(ntohl(inet_addr->sin_addr.s_addr));
123             addresses.Add(address);
124         }
125 #if defined(NPT_CONFIG_ENABLE_IPV6)
126         else if (info->ai_family == AF_INET6) {
127             struct sockaddr_in6* inet_addr = (struct sockaddr_in6*)info->ai_addr;
128             NPT_IpAddress address(NPT_IpAddress::IPV6, inet_addr->sin6_addr.s6_addr, 16, inet_addr->sin6_scope_id);
129             addresses.Add(address);
130         }
131 #endif
132     }
133     freeaddrinfo(infos);
134 
135     return NPT_SUCCESS;
136 }
137 #endif
138