1 /*++
2 Copyright (c) 2000 Microsoft Corporation
3 Module Name:
4     tpipv6.h
5 Abstract:
6     This module contains IPv6-specific extensions, and address family
7     independent extensions to Winsock for the IPv6 Technology Preview.
8 --*/
9 #ifndef _TPIPV6_
10 #define _TPIPV6_
11 #ifdef _MSC_VER
12 #define TPIPV6_INLINE __inline
13 #else
14 #define TPIPV6_INLINE extern inline /* GNU style */
15 #endif
16 #ifdef __cplusplus
17 #define TPIPV6_EXTERN extern "C"
18 #else
19 #define TPIPV6_EXTERN extern
20 #endif
21 #ifdef _WINSOCK2API_
22 /* This section gets included if winsock2.h is included */
23 #ifndef IPPROTO_IPV6
24 #define IPPROTO_IPV6 41
25 typedef unsigned __int64 u_int64;
26 //
27 // Portable socket structure.
28 //
29 //
30 // Desired design of maximum size and alignment.
31 // These are implementation specific.
32 //
33 #define _SS_MAXSIZE 128                  // Maximum size.
34 #define _SS_ALIGNSIZE (sizeof(__int64))  // Desired alignment.
35 //
36 // Definitions used for sockaddr_storage structure paddings design.
37 //
38 #define _SS_PAD1SIZE (_SS_ALIGNSIZE - sizeof (short))
39 #define _SS_PAD2SIZE (_SS_MAXSIZE - (sizeof (short) + _SS_PAD1SIZE \
40                                                     + _SS_ALIGNSIZE))
41 struct sockaddr_storage {
42     short ss_family;               // Address family.
43     char __ss_pad1[_SS_PAD1SIZE];  // 6 byte pad, this is to make
44                                    // implementation specific pad up to
45                                    // alignment field that follows explicit
46                                    // in the data structure.
47     __int64 __ss_align;            // Field to force desired structure.
48     char __ss_pad2[_SS_PAD2SIZE];  // 112 byte pad to achieve desired size;
49                                    // _SS_MAXSIZE value minus size of
50                                    // ss_family, __ss_pad1, and
51                                    // __ss_align fields is 112.
52 };
53 typedef struct sockaddr_storage SOCKADDR_STORAGE;
54 typedef struct sockaddr_storage *PSOCKADDR_STORAGE;
55 typedef struct sockaddr_storage FAR *LPSOCKADDR_STORAGE;
56 #endif /* !IPPROTO_IPV6 */
57 #endif /* _WINSOCK2API_ */
58 #ifdef _WS2TCPIP_H_
59 /* This section gets included if ws2tcpip.h is included */
60 #ifndef IPV6_JOIN_GROUP
61 #define in6_addr in_addr6
62 // Macro that works for both IPv4 and IPv6
63 #define SS_PORT(ssp) (((struct sockaddr_in*)(ssp))->sin_port)
64 #define IN6ADDR_ANY_INIT        { 0 }
65 #define IN6ADDR_LOOPBACK_INIT   { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 }
66 /*TPIPV6_EXTERN*/ const struct in6_addr in6addr_any;
67 /*TPIPV6_EXTERN*/ const struct in6_addr in6addr_loopback;
68 TPIPV6_INLINE int
IN6_ADDR_EQUAL(const struct in6_addr * a,const struct in6_addr * b)69 IN6_ADDR_EQUAL(const struct in6_addr *a, const struct in6_addr *b)
70 {
71     return (memcmp(a, b, sizeof(struct in6_addr)) == 0);
72 }
73 TPIPV6_INLINE int
IN6_IS_ADDR_UNSPECIFIED(const struct in6_addr * a)74 IN6_IS_ADDR_UNSPECIFIED(const struct in6_addr *a)
75 {
76     return IN6_ADDR_EQUAL(a, &in6addr_any);
77 }
78 TPIPV6_INLINE int
IN6_IS_ADDR_LOOPBACK(const struct in6_addr * a)79 IN6_IS_ADDR_LOOPBACK(const struct in6_addr *a)
80 {
81     return IN6_ADDR_EQUAL(a, &in6addr_loopback);
82 }
83 TPIPV6_INLINE int
IN6_IS_ADDR_MULTICAST(const struct in6_addr * a)84 IN6_IS_ADDR_MULTICAST(const struct in6_addr *a)
85 {
86     return (a->s6_addr[0] == 0xff);
87 }
88 TPIPV6_INLINE int
IN6_IS_ADDR_LINKLOCAL(const struct in6_addr * a)89 IN6_IS_ADDR_LINKLOCAL(const struct in6_addr *a)
90 {
91     return ((a->s6_addr[0] == 0xfe) &&
92             ((a->s6_addr[1] & 0xc0) == 0x80));
93 }
94 TPIPV6_INLINE int
IN6_IS_ADDR_SITELOCAL(const struct in6_addr * a)95 IN6_IS_ADDR_SITELOCAL(const struct in6_addr *a)
96 {
97     return ((a->s6_addr[0] == 0xfe) &&
98             ((a->s6_addr[1] & 0xc0) == 0xc0));
99 }
100 TPIPV6_INLINE int
IN6_IS_ADDR_V4MAPPED(const struct in6_addr * a)101 IN6_IS_ADDR_V4MAPPED(const struct in6_addr *a)
102 {
103     return ((a->s6_addr[0] == 0) &&
104             (a->s6_addr[1] == 0) &&
105             (a->s6_addr[2] == 0) &&
106             (a->s6_addr[3] == 0) &&
107             (a->s6_addr[4] == 0) &&
108             (a->s6_addr[5] == 0) &&
109             (a->s6_addr[6] == 0) &&
110             (a->s6_addr[7] == 0) &&
111             (a->s6_addr[8] == 0) &&
112             (a->s6_addr[9] == 0) &&
113             (a->s6_addr[10] == 0xff) &&
114             (a->s6_addr[11] == 0xff));
115 }
116 TPIPV6_INLINE int
IN6_IS_ADDR_V4COMPAT(const struct in6_addr * a)117 IN6_IS_ADDR_V4COMPAT(const struct in6_addr *a)
118 {
119     return ((a->s6_addr[0] == 0) &&
120             (a->s6_addr[1] == 0) &&
121             (a->s6_addr[2] == 0) &&
122             (a->s6_addr[3] == 0) &&
123             (a->s6_addr[4] == 0) &&
124             (a->s6_addr[5] == 0) &&
125             (a->s6_addr[6] == 0) &&
126             (a->s6_addr[7] == 0) &&
127             (a->s6_addr[8] == 0) &&
128             (a->s6_addr[9] == 0) &&
129             (a->s6_addr[10] == 0) &&
130             (a->s6_addr[11] == 0) &&
131             !((a->s6_addr[12] == 0) &&
132               (a->s6_addr[13] == 0) &&
133               (a->s6_addr[14] == 0) &&
134               ((a->s6_addr[15] == 0) ||
135                (a->s6_addr[15] == 1))));
136 }
137 TPIPV6_INLINE int
IN6_IS_ADDR_MC_NODELOCAL(const struct in6_addr * a)138 IN6_IS_ADDR_MC_NODELOCAL(const struct in6_addr *a)
139 {
140     return IN6_IS_ADDR_MULTICAST(a) && ((a->s6_addr[1] & 0xf) == 1);
141 }
142 TPIPV6_INLINE int
IN6_IS_ADDR_MC_LINKLOCAL(const struct in6_addr * a)143 IN6_IS_ADDR_MC_LINKLOCAL(const struct in6_addr *a)
144 {
145     return IN6_IS_ADDR_MULTICAST(a) && ((a->s6_addr[1] & 0xf) == 2);
146 }
147 TPIPV6_INLINE int
IN6_IS_ADDR_MC_SITELOCAL(const struct in6_addr * a)148 IN6_IS_ADDR_MC_SITELOCAL(const struct in6_addr *a)
149 {
150     return IN6_IS_ADDR_MULTICAST(a) && ((a->s6_addr[1] & 0xf) == 5);
151 }
152 TPIPV6_INLINE int
IN6_IS_ADDR_MC_ORGLOCAL(const struct in6_addr * a)153 IN6_IS_ADDR_MC_ORGLOCAL(const struct in6_addr *a)
154 {
155     return IN6_IS_ADDR_MULTICAST(a) && ((a->s6_addr[1] & 0xf) == 8);
156 }
157 TPIPV6_INLINE int
IN6_IS_ADDR_MC_GLOBAL(const struct in6_addr * a)158 IN6_IS_ADDR_MC_GLOBAL(const struct in6_addr *a)
159 {
160     return IN6_IS_ADDR_MULTICAST(a) && ((a->s6_addr[1] & 0xf) == 0xe);
161 }
162 /* Argument structure for IPV6_JOIN_GROUP and IPV6_LEAVE_GROUP */
163 typedef struct ipv6_mreq {
164     struct in6_addr ipv6mr_multiaddr;  // IPv6 multicast address.
165     unsigned int    ipv6mr_interface;  // Interface index.
166 } IPV6_MREQ;
167 //
168 // Socket options at the IPPROTO_IPV6 level.
169 //
170 #define IPV6_UNICAST_HOPS       4  // Set/get IP unicast hop limit.
171 #define IPV6_MULTICAST_IF       9  // Set/get IP multicast interface.
172 #define IPV6_MULTICAST_HOPS     10 // Set/get IP multicast ttl.
173 #define IPV6_MULTICAST_LOOP     11 // Set/get IP multicast loopback.
174 #define IPV6_ADD_MEMBERSHIP     12 // Add an IP group membership.
175 #define IPV6_DROP_MEMBERSHIP    13 // Drop an IP group membership.
176 #define IPV6_JOIN_GROUP         IPV6_ADD_MEMBERSHIP
177 #define IPV6_LEAVE_GROUP        IPV6_DROP_MEMBERSHIP
178 //
179 // Socket options at the IPPROTO_UDP level.
180 //
181 #define UDP_CHECKSUM_COVERAGE   20  // Set/get UDP-Lite checksum coverage.
182 //
183 // Error codes from getaddrinfo().
184 //
185 #define EAI_AGAIN       WSATRY_AGAIN
186 #define EAI_BADFLAGS    WSAEINVAL
187 #define EAI_FAIL        WSANO_RECOVERY
188 #define EAI_FAMILY      WSAEAFNOSUPPORT
189 #define EAI_MEMORY      WSA_NOT_ENOUGH_MEMORY
190 #define EAI_NODATA      WSANO_DATA
191 #define EAI_NONAME      WSAHOST_NOT_FOUND
192 #define EAI_SERVICE     WSATYPE_NOT_FOUND
193 #define EAI_SOCKTYPE    WSAESOCKTNOSUPPORT
194 //
195 // Structure used in getaddrinfo() call.
196 //
197 typedef struct addrinfo {
198     int ai_flags;              // AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST.
199     int ai_family;             // PF_xxx.
200     int ai_socktype;           // SOCK_xxx.
201     int ai_protocol;           // 0 or IPPROTO_xxx for IPv4 and IPv6.
202     size_t ai_addrlen;         // Length of ai_addr.
203     char *ai_canonname;        // Canonical name for nodename.
204     struct sockaddr *ai_addr;  // Binary address.
205     struct addrinfo *ai_next;  // Next structure in linked list.
206 } ADDRINFO, FAR * LPADDRINFO;
207 //
208 // Flags used in "hints" argument to getaddrinfo().
209 //
210 #define AI_PASSIVE     0x1  // Socket address will be used in bind() call.
211 #define AI_CANONNAME   0x2  // Return canonical name in first ai_canonname.
212 #define AI_NUMERICHOST 0x4  // Nodename must be a numeric address string.
213 #ifdef __cplusplus
214 extern "C" {
215 #endif
216 WINSOCK_API_LINKAGE
217 int
218 WSAAPI
219 getaddrinfo(
220     IN const char FAR * nodename,
221     IN const char FAR * servname,
222     IN const struct addrinfo FAR * hints,
223     OUT struct addrinfo FAR * FAR * res
224     );
225 #if INCL_WINSOCK_API_TYPEDEFS
226 typedef
227 int
228 (WSAAPI * LPFN_GETADDRINFO)(
229     IN const char FAR * nodename,
230     IN const char FAR * servname,
231     IN const struct addrinfo FAR * hints,
232     OUT struct addrinfo FAR * FAR * res
233     );
234 #endif
235 WINSOCK_API_LINKAGE
236 void
237 WSAAPI
238 freeaddrinfo(
239     IN struct addrinfo FAR * ai
240     );
241 #if INCL_WINSOCK_API_TYPEDEFS
242 typedef
243 void
244 (WSAAPI * LPFN_FREEADDRINFO)(
245     IN struct addrinfo FAR * ai
246     );
247 #endif
248 #ifdef UNICODE
249 #define gai_strerror   gai_strerrorW
250 #else
251 #define gai_strerror   gai_strerrorA
252 #endif  /* UNICODE */
253 // WARNING: The gai_strerror inline functions below use static buffers,
254 // and hence are not thread-safe.  We'll use buffers long enough to hold
255 // 1k characters.  Any system error messages longer than this will be
256 // returned as empty strings.  However 1k should work for the error codes
257 // used by getaddrinfo().
258 #define GAI_STRERROR_BUFFER_SIZE 1024
259 TPIPV6_INLINE
260 char *
gai_strerrorA(IN int ecode)261 gai_strerrorA(
262     IN int ecode)
263 {
264     DWORD dwMsgLen;
265     static char buff[GAI_STRERROR_BUFFER_SIZE + 1];
266     dwMsgLen = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM
267                              |FORMAT_MESSAGE_IGNORE_INSERTS,
268                               NULL,
269                               ecode,
270                               MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
271                               (LPSTR)buff,
272                               GAI_STRERROR_BUFFER_SIZE,
273                               NULL);
274     return buff;
275 }
276 TPIPV6_INLINE
277 WCHAR *
gai_strerrorW(IN int ecode)278 gai_strerrorW(
279     IN int ecode
280     )
281 {
282     DWORD dwMsgLen;
283     static WCHAR buff[GAI_STRERROR_BUFFER_SIZE + 1];
284     dwMsgLen = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM
285                              |FORMAT_MESSAGE_IGNORE_INSERTS,
286                               NULL,
287                               ecode,
288                               MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
289                               (LPWSTR)buff,
290                               GAI_STRERROR_BUFFER_SIZE,
291                               NULL);
292     return buff;
293 }
294 typedef int socklen_t;
295 WINSOCK_API_LINKAGE
296 int
297 WSAAPI
298 getnameinfo(
299     IN  const struct sockaddr FAR * sa,
300     IN  socklen_t       salen,
301     OUT char FAR *      host,
302     IN  DWORD           hostlen,
303     OUT char FAR *      serv,
304     IN  DWORD           servlen,
305     IN  int             flags
306     );
307 #if INCL_WINSOCK_API_TYPEDEFS
308 typedef
309 int
310 (WSAAPI * LPFN_GETNAMEINFO)(
311     IN  const struct sockaddr FAR * sa,
312     IN  socklen_t       salen,
313     OUT char FAR *      host,
314     IN  DWORD           hostlen,
315     OUT char FAR *      serv,
316     IN  DWORD           servlen,
317     IN  int             flags
318     );
319 #endif
320 #define NI_MAXHOST  1025  // Max size of a fully-qualified domain name.
321 #define NI_MAXSERV    32  // Max size of a service name.
322 //
323 // Flags for getnameinfo().
324 //
325 #define NI_NOFQDN       0x01  // Only return nodename portion for local hosts.
326 #define NI_NUMERICHOST  0x02  // Return numeric form of the host's address.
327 #define NI_NAMEREQD     0x04  // Error if the host's name not in DNS.
328 #define NI_NUMERICSERV  0x08  // Return numeric form of the service (port #).
329 #define NI_DGRAM        0x10  // Service is a datagram service.
330 #ifdef __cplusplus
331 }
332 #endif
333 #endif /* !IPV6_JOIN_GROUP */
334 #endif /* _WS2TCPIP_H_ */
335 //
336 // Unless the build environment is explicitly targeting
337 // platforms that include built-in getaddrinfo() support,
338 // include the backwards-compatibility version of the APIs.
339 //
340 #if !defined(_WIN32_WINNT) || (_WIN32_WINNT <= 0x0500)
341 #include "wspiapi.h"
342 #endif
343 #endif /* _TPIPV6_ */
344