• R/O
  • HTTP
  • SSH
  • HTTPS

mingw-org-wsl: コミット

The MinGW.org Windows System Libraries


コミットメタ情報

リビジョンa45cb9690d6298067a8cf9e5d69b9f006833034d (tree)
日時2020-01-21 03:03:57
作者Keith Marshall <keith@user...>
コミッターKeith Marshall

ログメッセージ

Implement <wspiapi.h> sockets fall-back API.

変更サマリ

差分

--- a/w32api/ChangeLog
+++ b/w32api/ChangeLog
@@ -1,3 +1,23 @@
1+2020-01-20 Keith Marshall <keith@users.osdn.me>
2+
3+ Implement <wspiapi.h> sockets fall-back API.
4+
5+ * tests/headers.at: Add...
6+ * include/wspiapi.h: ...this new file; it implements...
7+ (WspiapiGetAddrInfo, WspiapiGetNameInfo, WspiapiFreeAddrInfo):
8+ ...these inline fall-back replacement implementations for...
9+ (getaddrinfo, getnameinfo, freeaddrinfo): ...these IETF RFC 3493
10+ functions, respectively, per hints in Microsoft online docs.
11+
12+ * include/ws2tcpip.h: Tidy layout; assert copyright.
13+ (pragma GCC system_header): Remove redundant GCC version guard.
14+ (EAI_SYSTEM, EAI_OVERFLOW): New symbolic error codes; define them.
15+ (socklen_t): Correct typedef; was signed but negative is meaningless.
16+ (getnameinfo): Adjust prototype declaration to conform to RFC 3493.
17+ (__AW_SUFFIXED__): Use it to selectively map definitions for...
18+ [UNICODE vs. ! UNICODE] (gai_strerror): ...this function.
19+ (_BEGIN_C_DECLS, _END_C_DECLS): Use them.
20+
121 2020-01-17 Keith Marshall <keith@users.osdn.me>
222
323 Preserve order of tests for integrity of header files.
--- a/w32api/include/ws2tcpip.h
+++ b/w32api/include/ws2tcpip.h
@@ -1,379 +1,515 @@
11 /*
2- * ws2tcpip.h : TCP/IP specific extensions in Windows Sockets 2
2+ * ws2tcpip.h
3+ *
4+ * TCP/IP specific extensions to the Windows Sockets API v2
5+ *
6+ *
7+ * $Id$
8+ *
9+ * Contributed by Danny Smith <dannysmith@users.sourceforge.net>
10+ * Copyright (C) 2001-2003, 2005-2008, 2020, MinGW.org Project
311 *
412 * Portions Copyright (c) 1980, 1983, 1988, 1993
513 * The Regents of the University of California. All rights reserved.
614 *
15+ * Redistribution and use in source and binary forms, with or without
16+ * modification, are permitted provided that the following conditions
17+ * are met:
18+ *
19+ * 1. Redistributions of source code must retain the above copyright
20+ * notice, this list of conditions and the following disclaimer.
21+ *
22+ * 2. Redistributions in binary form must reproduce the above copyright
23+ * notice, this list of conditions and the following disclaimer in the
24+ * documentation and/or other materials provided with the distribution.
25+ *
26+ * 3. Neither the name of the University nor the names of its contributors
27+ * may be used to endorse or promote products derived from this software
28+ * without specific prior written permission.
29+ *
30+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
31+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
34+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
36+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
37+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40+ * SUCH DAMAGE.
41+ *
742 */
8-
943 #ifndef _WS2TCPIP_H
10-#define _WS2TCPIP_H
11-#if __GNUC__ >=3
1244 #pragma GCC system_header
13-#endif
45+#define _WS2TCPIP_H
1446
15-#if (defined _WINSOCK_H && !defined _WINSOCK2_H)
16-#error "ws2tcpip.h is not compatible with winsock.h. Include winsock2.h instead."
47+#if defined _WINSOCK_H && ! defined _WINSOCK2_H
48+#error "ws2tcpip.h is not compatible with winsock.h; include winsock2.h instead."
1749 #endif
1850
1951 #include <winsock2.h>
20-#ifdef __cplusplus
21-extern "C" {
22-#endif
2352
24-/*
25- * The IP_* macros are also defined in winsock.h, but some values are different there.
26- * The values defined in winsock.h for 1.1 and used in wsock32.dll are consistent
27- * with the original values Steve Deering defined in his document "IP Multicast Extensions
28- * for 4.3BSD UNIX related systems (MULTICAST 1.2 Release)." However, these conflicted with
29- * the definitions for some IPPROTO_IP level socket options already assigned by BSD,
30- * so Berkeley changed all the values by adding 7. WinSock2 (ws2_32.dll) uses
53+_BEGIN_C_DECLS
54+
55+/* The IP_* macros are also defined in winsock.h, but some values are different there.
56+ * The values defined in winsock.h for 1.1 and used in wsock32.dll are consistent with
57+ * the original values Steve Deering defined in his document, "IP Multicast Extensions
58+ * for 4.3BSD UNIX related systems (MULTICAST 1.2 Release)". However, these conflict
59+ * with the definitions for some IPPROTO_IP level socket options already assigned by
60+ * BSD, so Berkeley changed all the values by adding 7. WinSock2 (ws2_32.dll) uses
3161 * the BSD 4.4 compatible values defined here.
3262 *
3363 * See also: msdn kb article Q257460
3464 * http://support.microsoft.com/support/kb/articles/Q257/4/60.asp
3565 */
36-
37-/* This is also defined in winsock.h; value hasn't changed */
38-#define IP_OPTIONS 1
39-
40-#define IP_HDRINCL 2
41-/*
42- * These are also be defined in winsock.h,
43- * but values have changed for WinSock2 interface
44- */
45-#define IP_TOS 3 /* old (winsock 1.1) value 8 */
46-#define IP_TTL 4 /* old value 7 */
47-#define IP_MULTICAST_IF 9 /* old value 2 */
48-#define IP_MULTICAST_TTL 10 /* old value 3 */
49-#define IP_MULTICAST_LOOP 11 /* old value 4 */
50-#define IP_ADD_MEMBERSHIP 12 /* old value 5 */
51-#define IP_DROP_MEMBERSHIP 13 /* old value 6 */
52-#define IP_DONTFRAGMENT 14 /* old value 9 */
53-#define IP_ADD_SOURCE_MEMBERSHIP 15
54-#define IP_DROP_SOURCE_MEMBERSHIP 16
55-#define IP_BLOCK_SOURCE 17
56-#define IP_UNBLOCK_SOURCE 18
57-#define IP_PKTINFO 19
58-
59-/*
60- * As with BSD implementation, IPPROTO_IPV6 level socket options have
61- * same values as IPv4 counterparts.
66+#define IP_OPTIONS 1 /* unchanged from WinSock v1.1 */
67+#define IP_HDRINCL 2 /* unchanged from WinSock v1.1 */
68+#define IP_TOS 3 /* had value 8 in WinSock v1.1 */
69+#define IP_TTL 4 /* had value 7 in WinSock v1.1 */
70+#define IP_MULTICAST_IF 9 /* had value 2 in WinSock v1.1 */
71+#define IP_MULTICAST_TTL 10 /* had value 3 in WinSock v1.1 */
72+#define IP_MULTICAST_LOOP 11 /* had value 4 in WinSock v1.1 */
73+#define IP_ADD_MEMBERSHIP 12 /* had value 5 in WinSock v1.1 */
74+#define IP_DROP_MEMBERSHIP 13 /* had value 6 in WinSock v1.1 */
75+#define IP_DONTFRAGMENT 14 /* had value 9 in WinSock v1.1 */
76+#define IP_ADD_SOURCE_MEMBERSHIP 15 /* undefined in WinSock v1.1 */
77+#define IP_DROP_SOURCE_MEMBERSHIP 16 /* undefined in WinSock v1.1 */
78+#define IP_BLOCK_SOURCE 17 /* undefined in WinSock v1.1 */
79+#define IP_UNBLOCK_SOURCE 18 /* undefined in WinSock v1.1 */
80+#define IP_PKTINFO 19 /* undefined in WinSock v1.1 */
81+
82+/* As with BSD implementation, IPPROTO_IPV6 level socket options have
83+ * the same values as their IPv4 counterparts.
6284 */
63-#define IPV6_UNICAST_HOPS 4
64-#define IPV6_MULTICAST_IF 9
65-#define IPV6_MULTICAST_HOPS 10
66-#define IPV6_MULTICAST_LOOP 11
67-#define IPV6_ADD_MEMBERSHIP 12
68-#define IPV6_DROP_MEMBERSHIP 13
69-#define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP
70-#define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP
71-#define IPV6_PKTINFO 19
85+#define IPV6_UNICAST_HOPS 4
86+#define IPV6_MULTICAST_IF 9
87+#define IPV6_MULTICAST_HOPS 10
88+#define IPV6_MULTICAST_LOOP 11
89+#define IPV6_ADD_MEMBERSHIP 12
90+#define IPV6_DROP_MEMBERSHIP 13
91+#define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP
92+#define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP
93+#define IPV6_PKTINFO 19
7294
73-#define IP_DEFAULT_MULTICAST_TTL 1
74-#define IP_DEFAULT_MULTICAST_LOOP 1
75-#define IP_MAX_MEMBERSHIPS 20
95+#define IP_DEFAULT_MULTICAST_TTL 1
96+#define IP_DEFAULT_MULTICAST_LOOP 1
97+#define IP_MAX_MEMBERSHIPS 20
7698
77-#define TCP_EXPEDITED_1122 2
99+#define TCP_EXPEDITED_1122 2
78100
79-#define UDP_NOCHECKSUM 1
101+#define UDP_NOCHECKSUM 1
80102
81-/* INTERFACE_INFO iiFlags */
82-#define IFF_UP 1
83-#define IFF_BROADCAST 2
84-#define IFF_LOOPBACK 4
85-#define IFF_POINTTOPOINT 8
86-#define IFF_MULTICAST 16
103+/* INTERFACE_INFO iiFlags
104+ */
105+#define IFF_UP 1
106+#define IFF_BROADCAST 2
107+#define IFF_LOOPBACK 4
108+#define IFF_POINTTOPOINT 8
109+#define IFF_MULTICAST 16
87110
88-#define SIO_GET_INTERFACE_LIST _IOR('t', 127, u_long)
111+#define SIO_GET_INTERFACE_LIST _IOR('t', 127, u_long)
89112
90-#define INET_ADDRSTRLEN 16
91-#define INET6_ADDRSTRLEN 46
113+/* Minimum buffer sizes required, to store any arbitrary IPv4,
114+ * or IPv6 address, respectively, in string format.
115+ */
116+#define INET_ADDRSTRLEN 16
117+#define INET6_ADDRSTRLEN 46
92118
93-/* getnameinfo constants */
94-#define NI_MAXHOST 1025
95-#define NI_MAXSERV 32
119+/* Constants for use when calling the getnameinfo() function;
120+ * first, the recommended lengths for host-name and service-name
121+ * return data buffers...
122+ */
123+#define NI_MAXHOST 1025
124+#define NI_MAXSERV 32
96125
126+/* ...and also, symbolic names for the flags argument bits.
127+ */
97128 #define NI_NOFQDN 0x01
98129 #define NI_NUMERICHOST 0x02
99130 #define NI_NAMEREQD 0x04
100131 #define NI_NUMERICSERV 0x08
101132 #define NI_DGRAM 0x10
102133
103-/* getaddrinfo constants */
104-#define AI_PASSIVE 1
105-#define AI_CANONNAME 2
106-#define AI_NUMERICHOST 4
107-
108-/* getaddrinfo error codes */
109-#define EAI_AGAIN WSATRY_AGAIN
110-#define EAI_BADFLAGS WSAEINVAL
111-#define EAI_FAIL WSANO_RECOVERY
112-#define EAI_FAMILY WSAEAFNOSUPPORT
113-#define EAI_MEMORY WSA_NOT_ENOUGH_MEMORY
114-#define EAI_NODATA WSANO_DATA
115-#define EAI_NONAME WSAHOST_NOT_FOUND
116-#define EAI_SERVICE WSATYPE_NOT_FOUND
117-#define EAI_SOCKTYPE WSAESOCKTNOSUPPORT
118-
119-/*
120- * ip_mreq also in winsock.h for WinSock1.1,
121- * but online msdn docs say it is defined here for WinSock2.
134+/* Options which may be passed, as inclusive-or bit flags, in
135+ * the hints->ai_flags argument, to getaddrinfo()
122136 */
123-
124-struct ip_mreq {
125- struct in_addr imr_multiaddr;
126- struct in_addr imr_interface;
137+#define AI_PASSIVE 1
138+#define AI_CANONNAME 2
139+#define AI_NUMERICHOST 4
140+
141+/* Error codes which may be returned by the getaddrinfo() and
142+ * getnameinfo() functions. These are the symbolic names which
143+ * conform to IETF convention; each represents, and is mapped
144+ * to, a corresponding WinSock error condition.
145+ */
146+#define EAI_AGAIN WSATRY_AGAIN
147+#define EAI_BADFLAGS WSAEINVAL
148+#define EAI_FAIL WSANO_RECOVERY
149+#define EAI_FAMILY WSAEAFNOSUPPORT
150+#define EAI_MEMORY WSA_NOT_ENOUGH_MEMORY
151+#define EAI_NODATA WSANO_DATA
152+#define EAI_NONAME WSAHOST_NOT_FOUND
153+#define EAI_OVERFLOW WSAENAMETOOLONG
154+#define EAI_SERVICE WSATYPE_NOT_FOUND
155+#define EAI_SOCKTYPE WSAESOCKTNOSUPPORT
156+#define EAI_SYSTEM WSASYSCALLFAILURE
157+
158+/* The ip_mreq structure is also required by WinSock v1.1, for
159+ * which case it is declared in <winsock.h>, since the definition
160+ * here is visible only to WinSock v2 applications which include
161+ * this <ws2tcpip.h> header file.
162+ */
163+struct ip_mreq
164+{ struct in_addr imr_multiaddr;
165+ struct in_addr imr_interface;
127166 };
128167
129-struct ip_mreq_source {
130- struct in_addr imr_multiaddr;
131- struct in_addr imr_sourceaddr;
132- struct in_addr imr_interface;
168+struct ip_mreq_source
169+{ struct in_addr imr_multiaddr;
170+ struct in_addr imr_sourceaddr;
171+ struct in_addr imr_interface;
133172 };
134173
135-struct ip_msfilter {
136- struct in_addr imsf_multiaddr;
137- struct in_addr imsf_interface;
138- u_long imsf_fmode;
139- u_long imsf_numsrc;
140- struct in_addr imsf_slist[1];
174+struct ip_msfilter
175+{ struct in_addr imsf_multiaddr;
176+ struct in_addr imsf_interface;
177+ u_long imsf_fmode;
178+ u_long imsf_numsrc;
179+ struct in_addr imsf_slist[1];
141180 };
142181
143-#define IP_MSFILTER_SIZE(numsrc) \
144- (sizeof(struct ip_msfilter) - sizeof(struct in_addr) \
145- + (numsrc) * sizeof(struct in_addr))
146-
147-struct in_pktinfo {
148- IN_ADDR ipi_addr;
149- UINT ipi_ifindex;
150-};
151-typedef struct in_pktinfo IN_PKTINFO;
182+#define IP_MSFILTER_SIZE(numsrc) \
183+ ( sizeof( struct ip_msfilter ) - sizeof( struct in_addr ) \
184+ + (numsrc) * sizeof( struct in_addr ) \
185+ )
152186
187+typedef
188+struct in_pktinfo
189+{ IN_ADDR ipi_addr;
190+ UINT ipi_ifindex;
191+} IN_PKTINFO;
153192
154-/* ipv6 */
155-/* These require XP or .NET Server or use of add-on IPv6 stacks on NT 4
156- or higher */
157-
158-/* This is based on the example given in RFC 2553 with stdint types
159- changed to BSD types. For now, use these field names until there
160- is some consistency in MS docs. In this file, we only use the
161- in6_addr structure start address, with casts to get the right offsets
162- when testing addresses */
163-
164-struct in6_addr {
165- union {
166- u_char _S6_u8[16];
167- u_short _S6_u16[8];
168- u_long _S6_u32[4];
169- } _S6_un;
193+/* IPv6
194+ *
195+ * This implementation requires WinXP or .NET Server or use of add-on
196+ * IPv6 stacks on WinNT4 and Win2K legacy platforms.
197+ *
198+ * The following in6_addr definition is based on the example given in
199+ * RFC 3493, with stdint types replaced by BSD types. For now, we use
200+ * these field names until there is some consistency in MS docs; Within
201+ * this file, we only use the in6_addr structure start address, with
202+ * casts to get the right offsets when testing addresses.
203+ */
204+struct in6_addr
205+{ union
206+ { u_char _S6_u8[16];
207+ u_short _S6_u16[8];
208+ u_long _S6_u32[4];
209+ } _S6_un;
210+# define s6_addr _S6_un._S6_u8 /* RFC 3493 standard name */
170211 };
171-/* s6_addr is the standard name */
172-#define s6_addr _S6_un._S6_u8
173212
174-/* These are GLIBC names */
213+/* The following are GLIBC specific field names...
214+ */
175215 #define s6_addr16 _S6_un._S6_u16
176216 #define s6_addr32 _S6_un._S6_u32
177217
178-/* These are used in some MS code */
179-#define in_addr6 in6_addr
218+/* ...while these may be found in some Microsoft code.
219+ */
220+#define in_addr6 in6_addr
180221 #define _s6_bytes _S6_un._S6_u8
181222 #define _s6_words _S6_un._S6_u16
182223
183224 typedef struct in6_addr IN6_ADDR, *PIN6_ADDR, *LPIN6_ADDR;
184225
185-struct sockaddr_in6 {
186- short sin6_family; /* AF_INET6 */
187- u_short sin6_port; /* transport layer port # */
188- u_long sin6_flowinfo; /* IPv6 traffic class & flow info */
189- struct in6_addr sin6_addr; /* IPv6 address */
190- u_long sin6_scope_id; /* set of interfaces for a scope */
191-};
192-typedef struct sockaddr_in6 SOCKADDR_IN6, *PSOCKADDR_IN6, *LPSOCKADDR_IN6;
226+typedef
227+struct sockaddr_in6
228+{ short sin6_family; /* AF_INET6 */
229+ u_short sin6_port; /* transport layer port # */
230+ u_long sin6_flowinfo; /* IPv6 traffic class & flow info */
231+ struct in6_addr sin6_addr; /* IPv6 address */
232+ u_long sin6_scope_id; /* set of interfaces for a scope */
233+} SOCKADDR_IN6, *PSOCKADDR_IN6, *LPSOCKADDR_IN6;
193234
194235 extern const struct in6_addr in6addr_any;
195236 extern const struct in6_addr in6addr_loopback;
196-/* the above can get initialised using: */
237+
197238 #define IN6ADDR_ANY_INIT { 0 }
198239 #define IN6ADDR_LOOPBACK_INIT { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 }
199240
200-/* Described in RFC 2292, but not in 2553 */
201-/* int IN6_ARE_ADDR_EQUAL(const struct in6_addr * a, const struct in6_addr * b) */
202-#define IN6_ARE_ADDR_EQUAL(a, b) \
203- (memcmp ((void*)(a), (void*)(b), sizeof (struct in6_addr)) == 0)
204-
205241
206-/* Address Testing Macros
207-
208- These macro functions all take const struct in6_addr* as arg.
209- Static inlines would allow type checking, but RFC 2553 says they
210- macros.
211- NB: These are written specifically for little endian host */
212-
213-#define IN6_IS_ADDR_UNSPECIFIED(_addr) \
214- ( (((const u_long *)(_addr))[0] == 0) \
215- && (((const u_long *)(_addr))[1] == 0) \
216- && (((const u_long *)(_addr))[2] == 0) \
217- && (((const u_long *)(_addr))[3] == 0))
218-
219-#define IN6_IS_ADDR_LOOPBACK(_addr) \
220- ( (((const u_long *)(_addr))[0] == 0) \
221- && (((const u_long *)(_addr))[1] == 0) \
222- && (((const u_long *)(_addr))[2] == 0) \
223- && (((const u_long *)(_addr))[3] == 0x01000000)) /* Note byte order reversed */
224-/* (((const u_long *)(_addr))[3] == ntohl(1)) */
225-
226-#define IN6_IS_ADDR_MULTICAST(_addr) (((const u_char *) (_addr))[0] == 0xff)
227-
228-#define IN6_IS_ADDR_LINKLOCAL(_addr) \
229- ( (((const u_char *)(_addr))[0] == 0xfe) \
230- && ((((const u_char *)(_addr))[1] & 0xc0) == 0x80))
231-
232-#define IN6_IS_ADDR_SITELOCAL(_addr) \
233- ( (((const u_char *)(_addr))[0] == 0xfe) \
234- && ((((const u_char *)(_addr))[1] & 0xc0) == 0xc0))
235-
236-#define IN6_IS_ADDR_V4MAPPED(_addr) \
237- ( (((const u_long *)(_addr))[0] == 0) \
238- && (((const u_long *)(_addr))[1] == 0) \
239- && (((const u_long *)(_addr))[2] == 0xffff0000)) /* Note byte order reversed */
240-/* (((const u_long *)(_addr))[2] == ntohl(0x0000ffff))) */
241-
242-#define IN6_IS_ADDR_V4COMPAT(_addr) \
243- ( (((const u_long *)(_addr))[0] == 0) \
244- && (((const u_long *)(_addr))[1] == 0) \
245- && (((const u_long *)(_addr))[2] == 0) \
246- && (((const u_long *)(_addr))[3] != 0) \
247- && (((const u_long *)(_addr))[3] != 0x01000000)) /* Note byte order reversed */
248-/* (ntohl (((const u_long *)(_addr))[3]) > 1 ) */
249-
250-
251-#define IN6_IS_ADDR_MC_NODELOCAL(_addr) \
252- ( IN6_IS_ADDR_MULTICAST(_addr) \
253- && ((((const u_char *)(_addr))[1] & 0xf) == 0x1))
254-
255-#define IN6_IS_ADDR_MC_LINKLOCAL(_addr) \
256- ( IN6_IS_ADDR_MULTICAST (_addr) \
257- && ((((const u_char *)(_addr))[1] & 0xf) == 0x2))
258-
259-#define IN6_IS_ADDR_MC_SITELOCAL(_addr) \
260- ( IN6_IS_ADDR_MULTICAST(_addr) \
261- && ((((const u_char *)(_addr))[1] & 0xf) == 0x5))
262-
263-#define IN6_IS_ADDR_MC_ORGLOCAL(_addr) \
264- ( IN6_IS_ADDR_MULTICAST(_addr) \
265- && ((((const u_char *)(_addr))[1] & 0xf) == 0x8))
266-
267-#define IN6_IS_ADDR_MC_GLOBAL(_addr) \
268- ( IN6_IS_ADDR_MULTICAST(_addr) \
269- && ((((const u_char *)(_addr))[1] & 0xf) == 0xe))
270-
271-
272-typedef int socklen_t;
273-
274-struct ipv6_mreq {
275- struct in6_addr ipv6mr_multiaddr;
276- unsigned int ipv6mr_interface;
242+/* IPv6 Address Testing Macros
243+ *
244+ * Each of these macros, as specified in RFC 3493, exhibits semantics
245+ * of a function taking a "const struct in6_addr *" argument; (static
246+ * inline functions would allow type checking, but RFC 3493 stipulates
247+ * that they are macros, so we implement them as such).
248+ *
249+ * Note that IPv6 addresses are expressed in big-endian byte order.
250+ * Host-native addressing is little-endian; thus, we implement each of
251+ * these macros to interpret its argument as a byte array, stored in
252+ * big-endian order, (reversing byte order throughout the quad-byte
253+ * representation of the array).
254+ *
255+ * Further note that, while each of the following macros is named as
256+ * specified in RFC 3493, the bit patterns, on which classification of
257+ * the addresses is based, are specified in RFC 4291.
258+ */
259+#define IN6_IS_ADDR_UNSPECIFIED(_addr) \
260+/* All 16 bytes of the IPv6 unspecified (i.e. the wildcard) \
261+ * address MUST be zero. \
262+ */ \
263+ ( (((const u_long *)(_addr))[0] == 0) \
264+ && (((const u_long *)(_addr))[1] == 0) \
265+ && (((const u_long *)(_addr))[2] == 0) \
266+ && (((const u_long *)(_addr))[3] == 0) \
267+ )
268+
269+#define IN6_IS_ADDR_LOOPBACK(_addr) \
270+/* Loopback address is ::1; for big-endian storage, the least \
271+ * significant byte, with value one, must be moved to the most \
272+ * significant byte of the most significant quad-byte, giving \
273+ * it an effective value of 0x01000000 \
274+ */ \
275+ ( (((const u_long *)(_addr))[0] == 0) \
276+ && (((const u_long *)(_addr))[1] == 0) \
277+ && (((const u_long *)(_addr))[2] == 0) \
278+ && (((const u_long *)(_addr))[3] == 0x01000000) \
279+ )
280+
281+#define IN6_IS_ADDR_LINKLOCAL(_addr) \
282+/* IPv6 link-local addresses are identified by having their \
283+ * ten most significant bits equal to 1111111010b \
284+ */ \
285+ ( (((const u_char *)(_addr))[0] == 0xfe) \
286+ && ((((const u_char *)(_addr))[1] & 0xc0) == 0x80) \
287+ )
288+
289+#define IN6_IS_ADDR_SITELOCAL(_addr) \
290+/* RFC 4291 says that IPv6 site-local addresses are obsolete, \
291+ * and forbids their use in new applications; nonetheless they \
292+ * are still permitted in pre-existing applications, in which \
293+ * they may be indentified by having their most significant \
294+ * ten bits equal to 1111111011b \
295+ */ \
296+ ( (((const u_char *)(_addr))[0] == 0xfe) \
297+ && ((((const u_char *)(_addr))[1] & 0xc0) == 0xc0) \
298+ )
299+
300+#define IN6_IS_ADDR_V4MAPPED(_addr) \
301+/* An IPv4 mapped address reserves the least significant four \
302+ * bytes, (most significant in big-endian equivalent storage), \
303+ * for the IPv4 address; the immediately adjacent two bytes \
304+ * MUST be 0xffff, with the remaining ten bytes all zero. \
305+ */ \
306+ ( (((const u_long *)(_addr))[0] == 0) \
307+ && (((const u_long *)(_addr))[1] == 0) \
308+ && (((const u_long *)(_addr))[2] == 0xffff0000) \
309+ )
310+
311+#define IN6_IS_ADDR_V4COMPAT(_addr) \
312+/* IPv4 compatible address format is effectively obsolete; \
313+ * nonetheless, it may be recognized as being the same as the \
314+ * IPv4 mapped format, but with 0x0000 in place of the 0xffff \
315+ * byte pair, and the IPv4 address represented being neither \
316+ * 0.0.0.0, nor 0.0.0.1, (again noting the byte reversal for \
317+ * big-endian storage order). \
318+ */ \
319+ ( (((const u_long *)(_addr))[0] == 0) \
320+ && (((const u_long *)(_addr))[1] == 0) \
321+ && (((const u_long *)(_addr))[2] == 0) \
322+ && (((const u_long *)(_addr))[3] != 0) \
323+ && (((const u_long *)(_addr))[3] != 0x01000000) \
324+ )
325+
326+#define IN6_IS_ADDR_MULTICAST(_addr) \
327+/* Any IPv6 address in which the most significant byte, (least \
328+ * significant in host storage order), has a value of 0xff, is \
329+ * a multicast address. \
330+ */ \
331+ (((const u_char *)(_addr))[0] == 0xff)
332+
333+/* IPv6 multicast addresses may be further classified into
334+ * "scope" groups, based on the value of the low order four
335+ * bits of the second most significant byte; as above, the
336+ * following macro names are specified in RFC 3493, but the
337+ * scope indices are specified in RFC 4291.
338+ */
339+#define IN6_IS_ADDR_MC_NODELOCAL(_addr) \
340+/* IPv6 multicast addresses with a scope index of one refer \
341+ * only to interfaces of the originating host node; (this is \
342+ * a multicast equivalent to the loopback address). \
343+ */ \
344+ ( IN6_IS_ADDR_MULTICAST(_addr) \
345+ && ((((const u_char *)(_addr))[1] & 0xf) == 0x1) \
346+ )
347+
348+#define IN6_IS_ADDR_MC_LINKLOCAL(_addr) \
349+/* IPv6 multicast addresses with a scope index of two refer \
350+ * to interfaces on the same subnet as the originating host. \
351+ */ \
352+ ( IN6_IS_ADDR_MULTICAST(_addr) \
353+ && ((((const u_char *)(_addr))[1] & 0xf) == 0x2) \
354+ )
355+
356+#define IN6_IS_ADDR_MC_SITELOCAL(_addr) \
357+/* IPv6 multicast addresses with a scope index of five refer \
358+ * to interfaces, possibly spanning multiple subnets, but all \
359+ * within the confines of a single geographical location. \
360+ */ \
361+ ( IN6_IS_ADDR_MULTICAST(_addr) \
362+ && ((((const u_char *)(_addr))[1] & 0xf) == 0x5) \
363+ )
364+
365+#define IN6_IS_ADDR_MC_ORGLOCAL(_addr) \
366+/* IPv6 multicast addresses with a scope index of eight refer \
367+ * to interfaces which are geographically distributed across \
368+ * multiple sites, all belonging to a single organization. \
369+ */ \
370+ ( IN6_IS_ADDR_MULTICAST(_addr) \
371+ && ((((const u_char *)(_addr))[1] & 0xf) == 0x8) \
372+ )
373+
374+#define IN6_IS_ADDR_MC_GLOBAL(_addr) \
375+/* IPv6 multicast addresses with a scope index of fourteen \
376+ * refer to interfaces which may be globally distributed over \
377+ * the public internet. \
378+ */ \
379+ ( IN6_IS_ADDR_MULTICAST(_addr) \
380+ && ((((const u_char *)(_addr))[1] & 0xf) == 0xe) \
381+ )
382+
383+/* RFC 3542 augments the preceding set of address testing macros, by the
384+ * addition of one more, intended for use in "advanced" applications; it
385+ * is semantically equivalent to a function with prototype:
386+ *
387+ * int IN6_ARE_ADDR_EQUAL
388+ * ( const struct in6_addr *, const struct in6_addr * )
389+ *
390+ * and returns non-zero if its two IPv6 address arguments are the same,
391+ * or zero, if they differ.
392+ */
393+#define IN6_ARE_ADDR_EQUAL(_addr1, _addr2) \
394+ ( memcmp( (void *)(_addr1), (void *)(_addr2), \
395+ sizeof( struct in6_addr ) \
396+ ) == 0 \
397+ )
398+
399+typedef unsigned int socklen_t;
400+
401+typedef
402+struct ipv6_mreq
403+{ struct in6_addr ipv6mr_multiaddr;
404+ unsigned int ipv6mr_interface;
405+} IPV6_MREQ;
406+
407+typedef
408+struct in6_pktinfo
409+{ IN6_ADDR ipi6_addr;
410+ UINT ipi6_ifindex;
411+} IN6_PKTINFO;
412+
413+struct addrinfo
414+{ int ai_flags;
415+ int ai_family;
416+ int ai_socktype;
417+ int ai_protocol;
418+ size_t ai_addrlen;
419+ char *ai_canonname;
420+ struct sockaddr *ai_addr;
421+ struct addrinfo *ai_next;
277422 };
278-typedef struct ipv6_mreq IPV6_MREQ;
279423
280-struct in6_pktinfo {
281- IN6_ADDR ipi6_addr;
282- UINT ipi6_ifindex;
283-};
284-typedef struct in6_pktinfo IN6_PKTINFO;
285-
286-struct addrinfo {
287- int ai_flags;
288- int ai_family;
289- int ai_socktype;
290- int ai_protocol;
291- size_t ai_addrlen;
292- char *ai_canonname;
293- struct sockaddr *ai_addr;
294- struct addrinfo *ai_next;
295-};
424+#if _WIN32_WINNT >= _WIN32_WINNT_WINXP && ! defined _WSPIAPI_H
425+/* The following three functions are required by RFC 3493, (formerly
426+ * RFC 2553), but MS-Windows did not support them natively, prior to
427+ * Win-XP. On earlier Windows versions, they may be supported, (but
428+ * without IPv6 support), by including <wspiapi.h>; (on Win-2K, IPv6
429+ * support may be attainable, if the IPv6 Technology Preview kit has
430+ * been installed, and the application is linked with WSHIP6.DLL).
431+ *
432+ * We expose these declarations only if we are compiling for Win-XP
433+ * or later, and then only if <wspiapi.h> has not been included.
434+ */
435+WSAAPI int getaddrinfo
436+(const char *, const char *, const struct addrinfo *, struct addrinfo **);
437+
438+WSAAPI int getnameinfo
439+(const struct sockaddr *, socklen_t, char *, socklen_t, char *, socklen_t, int);
296440
297-#if (_WIN32_WINNT >= 0x0501)
298-void WSAAPI freeaddrinfo (struct addrinfo*);
299-int WSAAPI getaddrinfo (const char*,const char*,const struct addrinfo*,
300- struct addrinfo**);
301-int WSAAPI getnameinfo(const struct sockaddr*,socklen_t,char*,DWORD,
302- char*,DWORD,int);
303-#else
304-/* FIXME: Need WS protocol-independent API helpers. */
441+WSAAPI void freeaddrinfo (struct addrinfo *);
305442 #endif
306443
307-static __inline char*
308-gai_strerrorA(int ecode)
444+#define gai_strerror __AW_SUFFIXED__( gai_strerror )
445+
446+static __inline__
447+char *gai_strerrorA (int ecode)
309448 {
310- static char message[1024+1];
311- DWORD dwFlags = FORMAT_MESSAGE_FROM_SYSTEM
312- | FORMAT_MESSAGE_IGNORE_INSERTS
313- | FORMAT_MESSAGE_MAX_WIDTH_MASK;
314- DWORD dwLanguageId = MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT);
315- FormatMessageA(dwFlags, NULL, ecode, dwLanguageId, (LPSTR)message, 1024, NULL);
316- return message;
449+ static char message[1024+1];
450+ DWORD Flags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS
451+ | FORMAT_MESSAGE_MAX_WIDTH_MASK;
452+ DWORD LanguageId = MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT);
453+ FormatMessageA (Flags, NULL, ecode, LanguageId, message, 1024, NULL);
454+ return message;
317455 }
318-static __inline WCHAR*
319-gai_strerrorW(int ecode)
456+
457+static __inline__
458+WCHAR *gai_strerrorW (int ecode)
320459 {
321- static WCHAR message[1024+1];
322- DWORD dwFlags = FORMAT_MESSAGE_FROM_SYSTEM
323- | FORMAT_MESSAGE_IGNORE_INSERTS
324- | FORMAT_MESSAGE_MAX_WIDTH_MASK;
325- DWORD dwLanguageId = MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT);
326- FormatMessageW(dwFlags, NULL, ecode, dwLanguageId, (LPWSTR)message, 1024, NULL);
327- return message;
460+ static WCHAR message[1024+1];
461+ DWORD Flags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS
462+ | FORMAT_MESSAGE_MAX_WIDTH_MASK;
463+ DWORD LanguageId = MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT);
464+ FormatMessageW (Flags, NULL, ecode, LanguageId, message, 1024, NULL);
465+ return message;
328466 }
329-#ifdef UNICODE
330-#define gai_strerror gai_strerrorW
331-#else
332-#define gai_strerror gai_strerrorA
333-#endif
334467
335468 /* Some older IPv4/IPv6 compatibility stuff */
336469
337470 /* This struct lacks sin6_scope_id; retained for use in sockaddr_gen */
338-struct sockaddr_in6_old {
339- short sin6_family;
340- u_short sin6_port;
341- u_long sin6_flowinfo;
342- struct in6_addr sin6_addr;
471+struct sockaddr_in6_old
472+{ short sin6_family;
473+ u_short sin6_port;
474+ u_long sin6_flowinfo;
475+ struct in6_addr sin6_addr;
343476 };
344477
345-typedef union sockaddr_gen{
346- struct sockaddr Address;
347- struct sockaddr_in AddressIn;
348- struct sockaddr_in6_old AddressIn6;
478+typedef
479+union sockaddr_gen
480+{ struct sockaddr Address;
481+ struct sockaddr_in AddressIn;
482+ struct sockaddr_in6_old AddressIn6;
349483 } sockaddr_gen;
350484
351-
352-typedef struct _INTERFACE_INFO {
353- u_long iiFlags;
354- sockaddr_gen iiAddress;
355- sockaddr_gen iiBroadcastAddress;
356- sockaddr_gen iiNetmask;
485+typedef
486+struct _INTERFACE_INFO
487+{ u_long iiFlags;
488+ sockaddr_gen iiAddress;
489+ sockaddr_gen iiBroadcastAddress;
490+ sockaddr_gen iiNetmask;
357491 } INTERFACE_INFO, *LPINTERFACE_INFO;
358492
359-/*
360- The definition above can cause problems on NT4,prior to sp4.
361- To workaround, include the following struct and typedef and
362- #define INTERFACE_INFO OLD_INTERFACE_INFO
363- See: FIX: WSAIoctl SIO_GET_INTERFACE_LIST Option Problem
364- (Q181520) in MSDN KB.
365-
366- The old definition causes problems on newer NT and on XP.
367-
368-typedef struct _OLD_INTERFACE_INFO {
369- u_long iiFlags;
370- struct sockaddr iiAddress;
371- struct sockaddr iiBroadcastAddress;
372- struct sockaddr iiNetmask;
493+#if 0
494+/* The definition above may cause problems on WinNT4, prior to
495+ * service pack 4. To work around this, if necessary, include
496+ * the following typedef and struct definition, and
497+ *
498+ * #define INTERFACE_INFO OLD_INTERFACE_INFO
499+ *
500+ * See FIX: WSAIoctl SIO_GET_INTERFACE_LIST Option Problem
501+ * (Q181520) in MSDN KB. Do note, however, that exposure of
502+ * the old definition may cause problems on newer variants of
503+ * WinNT, and on WinXP and later.
504+ */
505+typedef struct _OLD_INTERFACE_INFO
506+{ u_long iiFlags;
507+ struct sockaddr iiAddress;
508+ struct sockaddr iiBroadcastAddress;
509+ struct sockaddr iiNetmask;
373510 } OLD_INTERFACE_INFO;
374-*/
375-
376-#ifdef __cplusplus
377-}
378-#endif
379511 #endif
512+
513+_END_C_DECLS
514+
515+#endif /* !_WS2TCPIP_H: $RCSfile$: end of file */
--- /dev/null
+++ b/w32api/include/wspiapi.h
@@ -0,0 +1,980 @@
1+/*
2+ * wspiapi.h
3+ *
4+ * Implementation for pre-WinXP getaddrinfo() and getnameinfo() APIs.
5+ *
6+ *
7+ * $Id$
8+ *
9+ * Written by Keith Marshall <keith@users.osdn.me>
10+ * Copyright (C) 2020, MinGW.org Project
11+ *
12+ *
13+ * Permission is hereby granted, free of charge, to any person obtaining a
14+ * copy of this software and associated documentation files (the "Software"),
15+ * to deal in the Software without restriction, including without limitation
16+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
17+ * and/or sell copies of the Software, and to permit persons to whom the
18+ * Software is furnished to do so, subject to the following conditions:
19+ *
20+ * The above copyright notice and this permission notice (including the next
21+ * paragraph) shall be included in all copies or substantial portions of the
22+ * Software.
23+ *
24+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30+ * DEALINGS IN THE SOFTWARE.
31+ *
32+ *
33+ * Author's Note:
34+ * I have written this implementation of <wspiapi.h> from scratch, based
35+ * entirely on hints from publicly visible Microsoft documentation, my own
36+ * interpretation of IETF's RFC 3493, the corresponding POSIX.1 specification,
37+ * and observation of the behaviour of example code from Microsoft's publicly
38+ * visible documentation, which I have adapted to run on my GNU/Linux host.
39+ * I have never seen code for Microsoft's <wspiapi.h> implementation; nor
40+ * have I copied code from any other implementation, however licensed.
41+ *
42+ * This implementation servs as a fall-back for use on those legacy versions
43+ * of Windows which do not support the getaddrinfo() and getnameinfo() APIs,
44+ * through WS2_32.DLL on WinXP and later, or through WSHIP6.DLL on Win2K
45+ * (with the IPv6 Preview Kit). Since such legacy Windows versions do not
46+ * otherwise support IPv6, there is no attempt to support the AF_INET6
47+ * address family; AF_INET is supported, as is AF_UNSPEC, but only to
48+ * the extent that it is interpreted as AF_INET alone.
49+ *
50+ * It should be noted that, as described in Microsoft's documentation, the
51+ * fall-back code is implemented in the form of in-line functions. This
52+ * has a potentially disadvantageous side effect, in that every translation
53+ * unit which calls any of the fall-back functions will incur a substantial
54+ * overhead of potentially duplicated fall-back code. To mitigate this, it
55+ * is recommended that all such calls be encapsulated within one translation
56+ * unit, and exposed globally through public wrapper functions; an example
57+ * of this technique may be found in the gcc/ada/socket.c implementation
58+ * within recent GCC sources, wherein the public API is exposed via the
59+ * __gnat_getaddrinfo(), __gnat_freeaddrinfo(), and __gnat_getnameinfo()
60+ * function wrappers.
61+ *
62+ */
63+#ifndef _WSPIAPI_H
64+#pragma GCC system_header
65+#define _WSPIAPI_H
66+
67+#include <stdio.h>
68+#include <ws2tcpip.h>
69+
70+/* Symbolic constants are useful as wild-card identifiers for socket types
71+ * and protocols, but these are non-standard; we don't want to pollute the
72+ * public namespace, so we add the reserved __WSPIAPI_ prefix for these.
73+ */
74+#define __WSPIAPI_SOCK_ANY 0
75+#define __WSPIAPI_IPPROTO_ANY 0
76+
77+_BEGIN_C_DECLS
78+
79+/* __wspiapi_errout(): a helper to assign a WSA error code, via the
80+ * WSASetLastError() function, and also return it for immediate use
81+ * as the exit status for any wspiapi function.
82+ */
83+static __inline__ __attribute__((__always_inline__))
84+int __wspiapi_errout( int status ){ WSASetLastError( status ); return status; }
85+
86+/* __wspiapi_syserrout(): variation on __wspiapi_errout(), returning
87+ * EAI_SYSTEM, after assigning a specific system errno value.
88+ */
89+static __inline__
90+__attribute__((__always_inline__))
91+int __wspiapi_syserrout( int errcode )
92+{ errno = errcode; return __wspiapi_errout( EAI_SYSTEM ); }
93+
94+/* enum __wspiapi: generate symbolic names for the entry point indices
95+ * within the wspapi function reference dictionary.
96+ */
97+enum __wspiapi
98+{ __WSPIAPI_FREEADDRINFO__,
99+ __WSPIAPI_GETADDRINFO__,
100+ __WSPIAPI_GETNAMEINFO__
101+};
102+
103+/* __wspiapi_t: a private use data type, describing the structure of
104+ * each individual function reference within the dictionary.
105+ */
106+typedef struct
107+{ const char *name;
108+ void *entry;
109+} __wspiapi_t;
110+
111+/* __wspiapi_reference(): a helper function to retrieve a function
112+ * entry point address, by indexed function name look-up within the
113+ * reference dictionary.
114+ */
115+static __inline__ __attribute__((__always_inline__))
116+__wspiapi_t *__wspiapi_reference( enum __wspiapi index )
117+{
118+ /* The dictionary, itself, is statically encapsulated within this
119+ * helper function, (and thus, is not publicly visible). Note that,
120+ * initially, all entry point vectors are specified as (void *)(-1),
121+ * and will be fixed-up on first call to any related function.
122+ */
123+ static __wspiapi_t dictionary[] =
124+ { { "freeaddrinfo", (void *)(-1) },
125+ { "getaddrinfo", (void *)(-1) },
126+ { "getnameinfo", (void *)(-1) }
127+ };
128+
129+ /* The return value is simply a pointer to the dictionary entry
130+ * corresponding to the specified index.
131+ */
132+ return dictionary + index;
133+}
134+
135+/* __wspiapi_set_entry(): helper function to perform the dictionary
136+ * fix-up, for a single function entry point reference, as described
137+ * for the __wspiapi_reference() function above. Note that this is
138+ * called, only after a candidate DLL, which may be expected to
139+ * provide the associated function, has been identified.
140+ */
141+static __inline__ __attribute__((__always_inline__))
142+void __wspiapi_set_entry( HMODULE dll, __wspiapi_t *api )
143+{ api->entry = (void *)(GetProcAddress( dll, api->name )); }
144+
145+/* __wspiapi_module_handle(): helper to obtain a module handle for
146+ * a candidate DLL, which is expected to provide all of the wspiapi
147+ * functions, based on it satisfying one dictionary reference.
148+ */
149+static __inline__
150+HMODULE __wspiapi_module_handle
151+( char *path, char *subst, const char *name, __wspiapi_t *api )
152+{
153+ HMODULE ref;
154+
155+ /* "subst" points to the offset, within the "path" buffer, at which
156+ * the system directory path name ends, and the DLL file name should
157+ * be inserted; append the specified DLL file "name", and attempt to
158+ * load a system DLL of that name.
159+ */
160+ strcpy( subst, name );
161+ if( (ref = LoadLibraryA( path )) != NULL )
162+ {
163+ /* We successfully obtained a reference handle for the named DLL;
164+ * check that we can also obtain an entry point reference, within
165+ * this DLL, for the specified wspiapi function, recording the
166+ * result in the wspiapi reference dictionary...
167+ */
168+ if( (api->entry = (void *)(GetProcAddress( ref, api->name ))) == NULL )
169+ {
170+ /* ...and declaring no further wspiapi interest in this DLL, if
171+ * the requisite entry point is unavailable.
172+ */
173+ FreeLibrary( ref );
174+ return NULL;
175+ }
176+ }
177+ /* If we get to here, then we either have a valid handle for a DLL
178+ * which does provide the requisite wspiapi witness function, in
179+ * which case we return that handle, otherwise we return the NULL
180+ * resulting from a failed DLL load request.
181+ */
182+ return ref;
183+}
184+
185+/* __wspiapi_lib(): a thin wrapper, through which all calls to
186+ * __wspiapi_module_handle() are directed; it passes a system DLL
187+ * search path, wherein the specified DLL name is substituted, (at
188+ * the substring offset specified by "subst"), requiring that the
189+ * designated system DLL should provide freeaddrinfo() as witness
190+ * that it may be a suitable candidate provider for all of those
191+ * functions which must otherwise be replaced by <wspiapi.h>
192+ * fall-back implementations.
193+ */
194+static __inline__ __attribute__((__always_inline__))
195+HMODULE __wspiapi_lib( char *path, char *subst, const char *name )
196+{
197+ /* This requires nothing more than appending the wspiapi dictionary
198+ * reference for the freeaddrinfo() function, to the arguments which
199+ * have already been specified, and forwarding the request onward,
200+ * to __wspiapi_module_handle().
201+ */
202+ return __wspiapi_module_handle(
203+ path, subst, name, __wspiapi_reference(__WSPIAPI_FREEADDRINFO__)
204+ );
205+}
206+
207+/* __wspiapi_entry(): helper to retrieve the entry point address for
208+ * a specified wspiapi function, by indexed look-up within the wspiapi
209+ * reference dictionary; invokes __wspiapi_lib(), as may be required,
210+ * to initialize the reference dictionary entries.
211+ */
212+static __inline__
213+void *__wspiapi_entry( enum __wspiapi index )
214+# define __wspiapi_call( index ) (call)(__wspiapi_entry( index ))
215+{
216+ /* First, check that the reference dictionary has been initialized,
217+ * using the freeaddrinfo() entry point reference as witness.
218+ */
219+ if( __wspiapi_reference(__WSPIAPI_FREEADDRINFO__)->entry == (void *)(-1) )
220+ {
221+ /* The dictionary appears to be uninitialized; set up to perform
222+ * entry point searches within DLLs in the system directory...
223+ */
224+ HMODULE dll;
225+ char sys_path[MAX_PATH], *dllname;
226+ dllname = sys_path + GetSystemDirectory( sys_path, MAX_PATH - 11 );
227+ if( dllname > sys_path )
228+ { /* ...then, preferring WS2_32.DLL, but accepting WSHIP6.DLL as
229+ * a second choice alternative, initialize the dictionary entry
230+ * for the freeaddrinfo() witness function...
231+ */
232+ if( ((dll = __wspiapi_lib( sys_path, dllname, "\\ws2_32" )) != NULL)
233+ || ((dll = __wspiapi_lib( sys_path, dllname, "\\wship6" )) != NULL) )
234+ {
235+ /* ...and, when that resolves to a valid entry point address,
236+ * also initialize the entry point references, using the same
237+ * DLL, for the getaddrinfo() and getnameinfo() functions...
238+ */
239+ __wspiapi_set_entry( dll, __wspiapi_reference(__WSPIAPI_GETADDRINFO__) );
240+ __wspiapi_set_entry( dll, __wspiapi_reference(__WSPIAPI_GETNAMEINFO__) );
241+ FreeLibrary( dll );
242+ }
243+ else
244+ { /* ...otherwise, initialize these remaining references, such
245+ * that all three functions are marked as unsupported by any
246+ * system DLL, and thus must be emulated, on demand, by use
247+ * of <wspiapi.h> in-line code.
248+ */
249+ __wspiapi_reference(__WSPIAPI_GETADDRINFO__)->entry = NULL;
250+ __wspiapi_reference(__WSPIAPI_GETNAMEINFO__)->entry = NULL;
251+ }
252+ }
253+ }
254+ /* Irrespective of whether initialization was performed on this
255+ * occasion, or had been performed previously, we return the entry
256+ * point address for the requested function, as it is now recorded
257+ * in the wspiapi reference dictionary.
258+ */
259+ return __wspiapi_reference( index )->entry;
260+}
261+
262+/* __wspiapi_freeaddrinfo(): fall-back implementation for freeaddrinfo(),
263+ * invoked by WspiapiFreeAddrInfo(), if (and only if), there is no native
264+ * implementation provided in WS2_32.DLL, or by way of WSHIP6.DLL, from
265+ * the Win2K IPv6 Technology Preview.
266+ */
267+static __inline__
268+WSAAPI void __wspiapi_freeaddrinfo( struct addrinfo *ai_chain )
269+{
270+ /* This must free all addrinfo records on a single chain, which has been
271+ * allocated by a prior call of __wspiapi_getaddrinfo(); note that it is
272+ * necessary to free any associated ai_canonname records, which have been
273+ * independently allocated, but not any ai_addr records, as these are all
274+ * allocated as integral elements of the owner addrinfo record itself.
275+ */
276+ while( ai_chain != NULL )
277+ { struct addrinfo *next = ai_chain->ai_next;
278+ free( ai_chain->ai_canonname ); free( ai_chain );
279+ ai_chain = next;
280+ }
281+}
282+
283+/* __wspiapi_addrinfo_cleanup(): a local helper function, called only by
284+ * __wspiapi_getaddrinfo(), to clean up any partially allocated addrinfo
285+ * record chain, in the event of __wspiapi_getaddrinfo() failure.
286+ */
287+static __inline__ __attribute__((__always_inline__))
288+struct addrinfo *__wspiapi_addrinfo_cleanup( struct addrinfo *ai_chain )
289+{ __wspiapi_freeaddrinfo( ai_chain ); return NULL; }
290+
291+/* __wspiapi_getaddrinfo_internal(): core implementation for, and called
292+ * exclusively by, __wspiapi_getaddrinfo(); returns zero on success, or
293+ * an EAI error code, (but without updating WSAGetLastError() status),
294+ * on failure.
295+ */
296+static __inline__
297+__attribute__((__always_inline__))
298+int __wspiapi_getaddrinfo_internal
299+( const char *__restrict__ nodename, const char *__restrict__ servname,
300+ const struct addrinfo *__restrict__ hints, struct addrinfo **__restrict__ res
301+)
302+{ /* Either nodename, or servname, but not both, may be NULL; initially
303+ * assign status to reflect the invalid condition of both being NULL.
304+ */
305+ int status = EAI_NONAME;
306+
307+ /* Initialize a local template, from which each allocated resultant
308+ * addrinfo record may be derived.
309+ */
310+ struct ai { struct addrinfo ai; struct sockaddr_in sa; } ai_data;
311+ memset( &ai_data, 0, sizeof( struct ai ) );
312+
313+ /* Ensure that the state of the resultant addrinfo record chain will
314+ * be sane, in the event of early failure.
315+ */
316+ *res = NULL;
317+
318+ /* The hints may be NULL, (in which case the initial template state
319+ * will prevail), but if specified...
320+ */
321+ if( hints != NULL )
322+ { /* ...then its ai_addr, ai_canonname, and ai_next fields MUST all
323+ * be NULL, and ai_addrlen MUST be zero.
324+ */
325+ if( (hints->ai_addr != NULL) || (hints->ai_addrlen != 0)
326+ || (hints->ai_next != NULL) || (hints->ai_canonname != NULL) )
327+ return EAI_FAIL;
328+
329+ /* Only the IPv4 AF_INET ai_family is supported, (but we tolerate
330+ * AF_UNSPEC as implying AF_INET).
331+ */
332+ switch( ai_data.ai.ai_family = hints->ai_family )
333+ { case AF_UNSPEC: case AF_INET: break; default: return EAI_FAMILY; }
334+
335+ /* Protocol and socket type may each be specified explicitly, or
336+ * implicitly, (by default, or by wild-card assignment; supported
337+ * protocols are TCP and UDP...
338+ */
339+ switch( ai_data.ai.ai_protocol = hints->ai_protocol )
340+ {
341+ case IPPROTO_TCP:
342+ /* ...where an explicit choice of TCP must be associated with
343+ * a stream type socket...
344+ */
345+ switch( hints->ai_socktype )
346+ { /* ...which again, may be either explicitly assigned, or
347+ * implicitly deduced.
348+ */
349+ case SOCK_STREAM: case __WSPIAPI_SOCK_ANY:
350+ ai_data.ai.ai_socktype = SOCK_STREAM;
351+ break;
352+
353+ /* Any other explicit pairing results in failure.
354+ */
355+ default: return EAI_SOCKTYPE;
356+ }
357+ break;
358+
359+ case IPPROTO_UDP:
360+ /* Similarly, an explicit protocol choice must be paired,
361+ * explicitly or implicitly, with a datagram socket.
362+ */
363+ switch( hints->ai_socktype )
364+ { case SOCK_DGRAM: case __WSPIAPI_SOCK_ANY:
365+ ai_data.ai.ai_socktype = SOCK_DGRAM;
366+ break;
367+
368+ /* Once again, any other explicit pairing is invalid.
369+ */
370+ default: return EAI_SOCKTYPE;
371+ }
372+ break;
373+
374+ case __WSPIAPI_IPPROTO_ANY:
375+ /* Without an explicit protocol specification, we may need
376+ * to infer a match for the socket type...
377+ */
378+ switch( ai_data.ai.ai_socktype = hints->ai_socktype )
379+ {
380+ /* ...pairing TCP with an explicit stream socket...
381+ */
382+ case SOCK_STREAM:
383+ ai_data.ai.ai_protocol = IPPROTO_TCP;
384+ break;
385+
386+ /* ...UDP with a datagram socket...
387+ */
388+ case SOCK_DGRAM:
389+ ai_data.ai.ai_protocol = IPPROTO_UDP;
390+
391+ /* ...or fall through, to enable generation of an addrinfo
392+ * list, with all supported valid pairings.
393+ */
394+ case __WSPIAPI_SOCK_ANY: break;
395+
396+ /* Bail out, if any unsupported socket type is explicitly
397+ * specified...
398+ */
399+ default: return EAI_SOCKTYPE;
400+ }
401+ break;
402+
403+ /* ...and likewise, for any unsupported protocol.
404+ */
405+ default: return EAI_SOCKTYPE;
406+ }
407+
408+ /* Simply propagate whatever flags may have been specified, but
409+ * defer any validation of them, until later.
410+ */
411+ ai_data.ai.ai_flags = hints->ai_flags;
412+ }
413+
414+ /* Only the IPv4 address family is supported; whether confirmed in
415+ * the hints, or left unspecified, we may stipulate that now.
416+ */
417+ ai_data.ai.ai_family = ai_data.sa.sin_family = AF_INET;
418+
419+ /* The servname argument may be NULL, but when it is specified, and
420+ * it is a non-empty string...
421+ */
422+ if( (servname != NULL) && (*servname != '\0') )
423+ { /* ...first try to interpret it as a textual representation of a
424+ * service port number...
425+ */
426+ struct servent *pi; char *brk;
427+ ai_data.sa.sin_port = strtoul( servname, &brk, 0 );
428+ if( *brk == '\0' ) pi = getservbyport( htons( ai_data.sa.sin_port ), NULL );
429+
430+ /* ...or, failing that, a well known service name, which may be
431+ * mapped to such a port number, or else bail out.
432+ */
433+ else pi = getservbyname( servname, NULL );
434+ if( pi == NULL ) return EAI_SERVICE;
435+
436+ /* When the servname argument has been successfully interpreted,
437+ * store the port number within the addrinfo template, and reset
438+ * the return status, to indicate that the minimal requirement
439+ * for at least one of servname and nodename is non-NULL.
440+ */
441+ ai_data.sa.sin_port = pi->s_port;
442+ status = 0;
443+ }
444+
445+ /* Similarly, the nodename argument may be NULL, but when it is
446+ * specified, and is non-empty...
447+ */
448+ if( (nodename != NULL) && (*nodename != '\0') )
449+ { /* ...then we first attempt to interpret it as a representation,
450+ * in textual format, of an IPv4 address.
451+ */
452+ unsigned long *addr = (unsigned long *)(&(ai_data.sa.sin_addr));
453+ if( (*addr = inet_addr( nodename )) != INADDR_NONE )
454+ {
455+ /* We've interpreted, and stored, a valid IPv4 address; this
456+ * isn't, strictly, a node name; it is valid, in this context,
457+ * but association with a canonical name is disallowed.
458+ */
459+ if( (ai_data.ai.ai_flags & AI_CANONNAME) == AI_CANONNAME )
460+ return EAI_BADFLAGS;
461+
462+ /* When the IPv4 address form is accepted, we may immediately
463+ * reset the return status, since the requirement for at least
464+ * one nodename, or servname, to be non-NULL is satisfied.
465+ */
466+ status = 0;
467+ }
468+ else if( (ai_data.ai.ai_flags & AI_NUMERICHOST) == AI_NUMERICHOST )
469+ {
470+ /* No numeric IPv4 address was specified, but with this flag
471+ * one becomes a mandatory requirement; bail out.
472+ */
473+ return EAI_NONAME;
474+ }
475+ else
476+ { /* The specified nodename could not be interpreted as an IPv4
477+ * address, (but was not required to be); resolve it as a host
478+ * name, to obtain the corresponding IPv4 address.
479+ */
480+ struct hostent *hi = gethostbyname( nodename );
481+ if( hi != NULL )
482+ {
483+ /* Name resolution was successful; update the template data
484+ * to reflect the size of an IPv4 socket data structure, and
485+ * store the resolved IPv4 address.
486+ *
487+ * FIXME: is it necessary to adapt this, to process a list
488+ * comprising more than one resolved IPv4 address?
489+ */
490+ ai_data.ai.ai_addrlen = sizeof( struct sockaddr );
491+ ai_data.sa.sin_addr = **(struct in_addr **)(hi->h_addr_list);
492+
493+ /* Also, if requested, capture the resolved canonical host
494+ * name, but fail if there is insufficient memory.
495+ */
496+ if( ((ai_data.ai.ai_flags & AI_CANONNAME) == AI_CANONNAME)
497+ && ((ai_data.ai.ai_canonname = strdup( hi->h_name )) == NULL) )
498+ return EAI_MEMORY;
499+
500+ /* On successfully updating the template, to reflect all
501+ * data associated with the resolved nodename, reset the
502+ * exit status to indicate success.
503+ */
504+ status = 0;
505+ }
506+ }
507+ }
508+ else if( status == 0 )
509+ { /* The nodename argument was effectively NULL, but we are able
510+ * to proceed due to prior interpretation of a non-NULL servname
511+ * argument; assign default addresses...
512+ */
513+ if( ((ai_data.ai.ai_flags & AI_PASSIVE) == AI_PASSIVE) )
514+ { /* ...corresponding to the wild-card address for any passive
515+ * connection...
516+ */
517+ ai_data.sa.sin_addr.s_addr = INADDR_ANY;
518+ }
519+ else
520+ { /* ...or the loopback address, for non-passive connections.
521+ */
522+ ai_data.sa.sin_addr.s_addr = INADDR_LOOPBACK;
523+ }
524+ }
525+
526+ /* Provided the return status code has been reset to zero, from
527+ * its initial EAI_NONAME value...
528+ */
529+ if( status == 0 )
530+ { /* ...we should now have a suitably initialized template, from
531+ * which we may construct the linked list of matching addrinfo
532+ * structures to be returned. Each list entry is separately
533+ * allocated, using the local pai pointer to track insertion
534+ * point, selecting protocol and socket type pairings from the
535+ * indexed list, working from TCP (at index two), back towards
536+ * the wild-card protocol match (at index zero), and passing
537+ * through UDP (at index one), until we reach the protocol as
538+ * specified in the template; note that this will generate a
539+ * single entry of TCP, or UDP, when either is specified as an
540+ * explicit match requirement, but will generate three entries,
541+ * matching each of TCP, UDP, and ANY, when a wild-card match
542+ * is specified.
543+ */
544+ struct ai *pai = NULL;
545+ int ref = (ai_data.ai.ai_protocol == IPPROTO_UDP) ? 1 : 2;
546+ struct { int protocol; int socktype; } map[] =
547+ { { __WSPIAPI_IPPROTO_ANY, __WSPIAPI_SOCK_ANY },
548+ { IPPROTO_UDP, SOCK_DGRAM }, { IPPROTO_TCP, SOCK_STREAM }
549+ };
550+ do { if( pai == NULL )
551+ { /* When pai is in its initial NULL state, the entry to
552+ * be generated may be assigned directly to the head of
553+ * the return list...
554+ */
555+ pai = ((struct ai *)(malloc( sizeof ai_data )));
556+ *res = (struct addrinfo *)(pai);
557+ }
558+ /* ...otherwise we link it as ai_next successor to the
559+ * previously allocated entry.
560+ */
561+ else
562+ { pai->ai.ai_next = (struct addrinfo *)(malloc( sizeof ai_data ));
563+ pai = (struct ai *)(pai->ai.ai_next);
564+ }
565+ if( pai == NULL )
566+ { /* When pai remains in, or reverts to, the NULL state,
567+ * then allocation of memory for the list entry failed;
568+ * clean up any partially allocated return data, before
569+ * bailing out.
570+ */
571+ *res = __wspiapi_addrinfo_cleanup( *res );
572+ return EAI_MEMORY;
573+ }
574+ /* We got a successfully allocated block of memory for a
575+ * list entry; populate it by copying the template...
576+ */
577+ *pai = ai_data;
578+
579+ /* ...then fix up the embedded sockaddr data reference,
580+ * its protocol, and the socket type indicators.
581+ */
582+ pai->ai.ai_addr = (struct sockaddr *)(&(pai->sa.sin_family));
583+ pai->ai.ai_protocol = map[ref].protocol;
584+ pai->ai.ai_socktype = map[ref].socktype;
585+
586+ /* The template may initially include a canonical name
587+ * reference; this is propagated to the first list entry
588+ * only, so clear it prior to generating any more.
589+ */
590+ ai_data.ai.ai_canonname = NULL;
591+
592+ /* Go round again, until the addrinfo list has become
593+ * fully populated.
594+ */
595+ } while( map[ref--].protocol != ai_data.ai.ai_protocol );
596+ }
597+ /* Ultimately, return either the initially assumed EAI_NONAME
598+ * failure status, or success.
599+ */
600+ return status;
601+}
602+
603+/* __wspiapi_getaddrinfo(): a thin wrapper around the preceding
604+ * in-line implementation; invoked by WspiapiGetAddrInfo() if, and
605+ * only if, no getaddrinfo() implementation is identifiable within
606+ * the host system's WS2_32.DLL, or WSHIP6.DLL
607+ */
608+WSAAPI int __wspiapi_getaddrinfo (
609+ const char *__restrict__ nodenam, const char *__restrict__ servnam,
610+ const struct addrinfo *__restrict__ hints, struct addrinfo **__restrict__ res
611+)
612+{ /* First ensure that a non-NULL reference pointer is provided, to
613+ * pass the addrinfo result back to the caller, then delegate the
614+ * call to the in-line handler, capturing its exit status, which
615+ * is then propagated through the WSAGetLastError() API.
616+ */
617+ if( res == NULL ) return __wspiapi_syserrout( EINVAL );
618+ { int status = __wspiapi_getaddrinfo_internal( nodenam, servnam, hints, res );
619+ return (status == 0) ? 0 : __wspiapi_errout( status );
620+ }
621+}
622+
623+/* WspiapiGetAddrInfo(): getaddrinfo() function redirector, as
624+ * prescribed by Microsoft's on-line documentation.
625+ */
626+static __inline__
627+WSAAPI int WspiapiGetAddrInfo
628+( const char *node, const char *service, const struct addrinfo *hints,
629+ struct addrinfo **response_list
630+)
631+{ /* Initialized to NULL, the redirector hook will be updated on
632+ * first call, within the containing translation unit. This call
633+ * will determine if it can be directed to an actual getaddrinfo()
634+ * function implementation, provided by the system's WS2_32.DLL or
635+ * WSHIP6.DLL libraries, initializing redirection for this first,
636+ * and any subsequent call, to delegate to any such existing
637+ * implementation, if available...
638+ */
639+ typedef WSAAPI int (*call)
640+ ( const char *, const char *, const struct addrinfo *, struct addrinfo **
641+ );
642+ static call redirector_hook = NULL;
643+ if( (redirector_hook == NULL)
644+ && ((redirector_hook = __wspiapi_call(__WSPIAPI_GETADDRINFO__)) == NULL) )
645+
646+ /* ...or otherwise, to substitute the above fallback.
647+ */
648+ redirector_hook = __wspiapi_getaddrinfo;
649+
650+ /* Ultimately, every call is redirected to whichever handler has
651+ * been selected by the preceding initialization.
652+ */
653+ return redirector_hook( node, service, hints, response_list );
654+}
655+
656+/* getaddrinfo(): a static inline override for any external
657+ * implementation of getaddrinfo(); ensures that corresponding
658+ * function calls, within the translation unit file scope, are
659+ * delegated to the fallback WspiapiGetAddrInfo() redirector.
660+ */
661+static __inline__ __attribute__((__always_inline__))
662+WSAAPI int getaddrinfo( const char *node, const char *service,
663+ const struct addrinfo *hints, struct addrinfo **response_list )
664+{ return WspiapiGetAddrInfo( node, service, hints, response_list ); }
665+
666+/* WspiapiFreeAddrInfo(): freeaddrinfo() function redirector, as
667+ * prescribed by Microsoft's on-line documentation.
668+ */
669+static __inline__
670+WSAAPI void WspiapiFreeAddrInfo( struct addrinfo *ai_chain )
671+{
672+ /* Initialized to NULL, the redirector hook will be updated on
673+ * first call, within the containing translation unit. This call
674+ * will determine if it can be directed to an actual freeaddrinfo()
675+ * function implementation, provided by the system's WS2_32.DLL or
676+ * WSHIP6.DLL libraries, initializing redirection for this first,
677+ * and any subsequent call, to delegate to any such existing
678+ * implementation, if available...
679+ */
680+ typedef WSAAPI void (*call)(struct addrinfo *);
681+ static call redirector_hook = NULL;
682+ if( (redirector_hook == NULL)
683+ && ((redirector_hook = __wspiapi_call(__WSPIAPI_FREEADDRINFO__)) == NULL) )
684+
685+ /* ...or otherwise, to substitute the above fallback.
686+ */
687+ redirector_hook = __wspiapi_freeaddrinfo;
688+
689+ /* Ultimately, every call is redirected to whichever handler has
690+ * been selected by the preceding initialization.
691+ */
692+ redirector_hook( ai_chain );
693+}
694+
695+/* freeaddrinfo(): a static inline override for any external
696+ * implementation of freeaddrinfo(); ensures that corresponding
697+ * function calls, within the translation unit file scope, are
698+ * delegated to the fallback WspiapiFreeAddrInfo() redirector.
699+ */
700+static __inline__ __attribute__((__always_inline__))
701+WSAAPI void freeaddrinfo (struct addrinfo *ai_chain)
702+{ WspiapiFreeAddrInfo (ai_chain); }
703+
704+/* __wspiapi_getservname(): helper to retrieve the standard name,
705+ * if any, for the service nominally associated with any port which
706+ * is specified by its number in network byte order.
707+ */
708+static __inline__ __attribute__((__always_inline__))
709+char *__wspiapi_getservname( u_short port, int flags, char *service,
710+ socklen_t servlen, socklen_t *retlen
711+)
712+{ /* This look-up is suppressed, if NI_NUMERICSERV is included
713+ * within the specified flags...
714+ */
715+ if( (flags & NI_NUMERICSERV) == 0 )
716+ {
717+ /* ...but, when allowed to proceed, we use the legacy windows
718+ * getservbyport() function to perform the look-up...
719+ */
720+ struct servent *service_info;
721+ service_info = getservbyport( port, (flags & NI_DGRAM) ? "udp" : NULL );
722+
723+ /* ...and then, provided a valid service name has been found,
724+ * we transcribe it into the supplied buffer, for return.
725+ */
726+ if( (service_info != NULL) && (service_info->s_name != NULL) )
727+ { *retlen = snprintf( service, servlen, "%s", service_info->s_name );
728+ return service;
729+ }
730+ }
731+ /* If, for whatever reason, no service name is to be returned,
732+ * returning NULL will signal this.
733+ */
734+ return NULL;
735+}
736+
737+/* __wspiapi_getnodename(): helper to perform a reverse DNS look-up,
738+ * to retrieve, and nominally return, the fully qualified domain name
739+ * which is associated with a specified IPv4 address.
740+ */
741+static __inline__ __attribute__((__always_inline__))
742+char *__wspiapi_getnodename( struct in_addr *addr, int flags,
743+ char *nodename, socklen_t nodelen, socklen_t *retlen
744+)
745+{ /* This look-up is suppressed, when NI_NUMERICHOST is included
746+ * within the specified flags...
747+ */
748+ if( (flags & NI_NUMERICHOST) == 0 )
749+ {
750+ /* ...but, when allowed to proceed, we use the legacy windows
751+ * gethostbyaddr() function to perform the look-up...
752+ */
753+ struct hostent *node_info = gethostbyaddr(
754+ (const char *)(addr), sizeof( struct in_addr ), AF_INET
755+ );
756+
757+ /* ...and then, provided a valid host name has been found,
758+ * we transcribe it into the supplied buffer, for return.
759+ */
760+ if( (node_info != NULL) && (node_info->h_name != NULL) )
761+ { *retlen = snprintf( nodename, nodelen, "%s", node_info->h_name );
762+
763+ /* A special case arises, when NI_NOFQDN is included
764+ * within the specified flags.
765+ */
766+ if( (flags & NI_NOFQDN) != 0 )
767+ {
768+ /* In this case, we must check for any period, as
769+ * punctuation separating the host name itself from
770+ * its domain name...
771+ */
772+ char *brk = strchr( nodename, '.' );
773+ if( brk != NULL )
774+ {
775+ /* ...and, when such punctuation is present, we
776+ * truncate the return string at the first period,
777+ * so leaving only the bare host name for return.
778+ */
779+ *brk = '\0';
780+ *retlen = brk - nodename;
781+ }
782+ }
783+ /* Truncated, or otherwise, we may now return the host
784+ * name, as retrieved.
785+ */
786+ return nodename;
787+ }
788+ }
789+ /* If, for whatever reason, no host name is to be returned,
790+ * returning NULL will signal this.
791+ */
792+ return NULL;
793+}
794+
795+/* __wspiapi_getnameinfo_internal(): core implementation for, and called
796+ * exclusively by, __wspiapi_getnameinfo(); returns zero on success, or
797+ * an EAI error code, (but without updating WSAGetLastError() status),
798+ * on failure.
799+ */
800+static __inline__
801+__attribute__((__always_inline__))
802+int __wspiapi_getnameinfo_internal
803+( const struct sockaddr *__restrict__ sa, socklen_t len,
804+ char *__restrict__ node, socklen_t nodelen, char *__restrict__ service,
805+ socklen_t servlen, int flags
806+)
807+{ /* Either the service name, or the node name look-up may be omitted,
808+ * but at least one MUST be performed; if neither is performed, as we
809+ * may establish later, then we should fail with status EAI_NONAME.
810+ */
811+ int status = EAI_NONAME;
812+
813+ /* If support for IPv6 is available, then the system DLL will provide
814+ * its own getnameinfo() implementation, and this fallback handler is
815+ * not invoked; thus, we need only support the IPv4 address family.
816+ */
817+ if( sa->sa_family != AF_INET ) return EAI_FAMILY;
818+
819+ /* The "service" argument may be NULL, or its associated "servlen"
820+ * may be zero; a service name look-up is performed, only if neither
821+ * of these excluding conditions is satisfied.
822+ */
823+ if( (service != NULL) && (servlen > 0) )
824+ {
825+ /* When look-up is NOT excluded, we delegate it to our internal
826+ * __wspiapi_getservname() helper, capturing the result into an
827+ * intermediate buffer of the same length as has been declared
828+ * for the returned result...
829+ */
830+ char servname[servlen];
831+ u_short port = ((const struct sockaddr_in *)(sa))->sin_port;
832+ if( __wspiapi_getservname( port, flags, servname, servlen, &len ) == NULL )
833+
834+ /* ...while noting that, if the look-up was unsuccessful, (or it
835+ * was suppressed, because NI_NUMERICSERV was included within the
836+ * specified flags), we substitute a string representation of the
837+ * service port number.
838+ */
839+ len = snprintf( servname, servlen, "%u", ntohs( port ) );
840+
841+ /* Provided the declared buffer length is sufficient to accommodate
842+ * the result of the look-up, we copy that result from intermediate
843+ * storage to the designated return buffer...
844+ */
845+ if( servlen > len ) strcpy( service, servname );
846+
847+ /* ...but if it doesn't fit, we bail out, reporting overflow.
848+ */
849+ else return EAI_OVERFLOW;
850+
851+ /* We HAVE now performed a successful service name look-up, so we
852+ * may clear our initial EAI_NONAME presumption.
853+ */
854+ status = 0;
855+ }
856+
857+ /* The "node" argument may be NULL, or its associated "nodelen" may
858+ * be zero; a node name look-up is performed, only if neither of
859+ * these excluding conditions is satisfied.
860+ */
861+ if( (node != NULL) && (nodelen > 0) )
862+ {
863+ /* Perform the node name look-up, based on the IPv4 address as
864+ * specified in the "sa" structure argument...
865+ */
866+ char nodename[nodelen];
867+ struct in_addr addr = ((const struct sockaddr_in *)(sa))->sin_addr;
868+ if( __wspiapi_getnodename( &addr, flags, nodename, nodelen, &len ) == NULL )
869+ {
870+ /* ...but on look-up failure, and if not required to succeed,
871+ * (by specification of the NI_NAMEREQD flag)...
872+ */
873+ if( (flags & NI_NAMEREQD) != 0 ) return EAI_NONAME;
874+
875+ /* ...substitute the textual representation of the address.
876+ */
877+ len = snprintf( nodename, nodelen, "%s", inet_ntoa( addr ) );
878+ }
879+ /* Whether the name look-up was successful, or the address was
880+ * substituted, if the return "node" buffer size is sufficient,
881+ * copy the look-up result into place...
882+ */
883+ if( nodelen > len ) strcpy( node, nodename );
884+
885+ /* ...otherwise, bail out.
886+ */
887+ else return EAI_OVERFLOW;
888+
889+ /* If we get this far, the function has completed successfully.
890+ */
891+ return 0;
892+ }
893+ /* If we didn't perform "node" name look-up, then the return state
894+ * must be either the result of successful "service" resolution, or
895+ * the initially assumed failure state.
896+ */
897+ return status;
898+}
899+
900+/* __wspiapi_getnameinfo(): a thin wrapper around the preceding
901+ * in-line implementation; invoked by WspiapiGetNameInfo() if, and
902+ * only if, no getnameinfo() implementation is identifiable within
903+ * the host system's WS2_32.DLL, or WSHIP6.DLL
904+ */
905+static __inline__
906+WSAAPI int __wspiapi_getnameinfo
907+( const struct sockaddr *__restrict__ sa, socklen_t len,
908+ char *__restrict__ node, socklen_t nodelen, char *__restrict__ service,
909+ socklen_t servlen, int flags
910+)
911+{ /* The "sa" argument MUST NOT be NULL, and its declared length MUST
912+ * match that of struct sockaddr. RFC 3493 doesn't prescribe how we
913+ * should handle this case, but we choose to emulate the behaviour of
914+ * Microsoft's invalid parameter handler, while reporting it as an
915+ * EAI_SYSTEM exception.
916+ */
917+ if( (sa == NULL) || (len < sizeof( struct sockaddr )) )
918+ return __wspiapi_syserrout( EINVAL );
919+
920+ { /* When the "sa" argument is valid, we delegate the call to the
921+ * preceding in-line handler, simply capturing its return status,
922+ * and propagating it through the WSAGetLastError() API, as may
923+ * be appropriate.
924+ */
925+ int status = __wspiapi_getnameinfo_internal
926+ ( sa, len, node, nodelen, service, servlen, flags );
927+ return (status == 0) ? 0 : __wspiapi_errout( status );
928+ }
929+}
930+
931+/* WspiapiGetNameInfo(): getnameinfo() function redirector, as
932+ * prescribed by Microsoft's on-line documentation.
933+ */
934+static __inline__
935+WSAAPI int WspiapiGetNameInfo
936+( const struct sockaddr *__restrict__ addr, socklen_t len,
937+ char *__restrict__ node, socklen_t nodelen, char *__restrict__ service,
938+ socklen_t servlen, int flags
939+)
940+{ /* Initialized to NULL, the redirector hook will be updated on
941+ * first call, within the containing translation unit. This call
942+ * will determine if it can be directed to an actual getnameinfo()
943+ * function implementation, provided by the system's WS2_32.DLL or
944+ * WSHIP6.DLL libraries, initializing redirection for this first,
945+ * and any subsequent call, to delegate to any such existing
946+ * implementation, if available...
947+ */
948+ typedef WSAAPI int (*call)
949+ (const SOCKADDR *, socklen_t, char *, socklen_t, char *, socklen_t, int
950+ );
951+ static call redirector_hook = NULL;
952+ if( (redirector_hook == NULL)
953+ && ((redirector_hook = __wspiapi_call(__WSPIAPI_GETNAMEINFO__)) == NULL) )
954+
955+ /* ...or otherwise, to substitute the above fallback.
956+ */
957+ redirector_hook = __wspiapi_getnameinfo;
958+
959+ /* Ultimately, every call is redirected to whichever handler has
960+ * been selected by the preceding initialization.
961+ */
962+ return redirector_hook( addr, len, node, nodelen, service, servlen, flags );
963+}
964+
965+/* getnameinfo(): a static inline override for any external
966+ * implementation of getnameinfo(); ensures that corresponding
967+ * function calls, within the translation unit file scope, are
968+ * delegated to the fallback WspiapiGetNameInfo() redirector.
969+ */
970+static __inline__ __attribute__((__always_inline__))
971+WSAAPI int getnameinfo( const SOCKADDR *addr, socklen_t addrlen,
972+ char *node, socklen_t nb_size, char *service, socklen_t sb_size, int flags
973+)
974+{ return WspiapiGetNameInfo
975+ (addr, addrlen, node, nb_size, service, sb_size, flags);
976+}
977+
978+_END_C_DECLS
979+
980+#endif /* !_WSPIAPI_H: $RCSfile$: end of file */
--- a/w32api/tests/headers.at
+++ b/w32api/tests/headers.at
@@ -265,6 +265,7 @@ ws2tcpip.h dnl
265265 wsahelp.h dnl
266266 wsipx.h dnl
267267 wsnetbs.h dnl
268+wspiapi.h dnl
268269 wtsapi32.h dnl
269270 wtypes.h dnl
270271 xprtdefs.h dnl
旧リポジトリブラウザで表示