]> sourceware.org Git - newlib-cygwin.git/blame - winsup/cygwin/net.cc
newlib: Add more FreeBSD files for non LDBL_EQ_DBL support
[newlib-cygwin.git] / winsup / cygwin / net.cc
CommitLineData
1fd5e000
CF
1/* net.cc: network-related routines.
2
1fd5e000
CF
3This file is part of Cygwin.
4
5This software is a copyrighted work licensed under the terms of the
6Cygwin license. Please consult the file "CYGWIN_LICENSE" for
7details. */
8
9/* #define DEBUG_NEST_ON 1 */
10
11#define __INSIDE_CYGWIN_NET__
acddda4b
CV
12#define USE_SYS_TYPES_FD_SET
13#define __WSA_ERR_MACROS_DEFINED
4c8d72de 14#include "winsup.h"
8e220283
CV
15/* 2014-04-24: Current Mingw headers define sockaddr_in6 using u_long (8 byte)
16 because a redefinition for LP64 systems is missing. This leads to a wrong
acc5f02c 17 definition and size of sockaddr_in6 when building with winsock headers. */
8e220283
CV
18#undef u_long
19#define u_long __ms_u_long
25ea6af1
CV
20#include <w32api/ws2tcpip.h>
21#include <w32api/mswsock.h>
22#include <w32api/iphlpapi.h>
68115c74 23#define gethostname cygwin_gethostname
84c7d409 24#include <unistd.h>
68115c74 25#undef gethostname
25ea6af1 26#include <ifaddrs.h>
1fd5e000 27#include <netdb.h>
2895b8b5 28#include <asm/byteorder.h>
db5ae618 29#include "shared_info.h"
bccd5e0d 30#include "path.h"
7ac61736 31#include "fhandler.h"
e2ebe117 32#include "dtable.h"
0381fec6 33#include "cygheap.h"
ba047ace 34#include "tls_pbuf.h"
acddda4b
CV
35
36/* Unfortunately defined in Windows header files and arpa/nameser_compat.h. */
37#undef NOERROR
38#undef DELETE
0a20e5a0 39#define _CYGWIN_IN_H
6f57cb4a 40#include <resolv.h>
1fd5e000 41
79224853
CV
42extern "C"
43{
44 int h_errno;
1fd5e000 45
79224853 46 int sscanf (const char *, const char *, ...);
64f8b4ca 47 int cygwin_inet_pton(int, const char *, void *);
72203114 48 const char *cygwin_inet_ntop (int, const void *, char *, socklen_t);
6f57cb4a
CV
49 int dn_length1(const unsigned char *, const unsigned char *,
50 const unsigned char *);
79224853 51} /* End of "C" section */
1fd5e000 52
aaa7d1f1
AP
53const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
54const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
70e476d2 55
5a64d869 56static fhandler_socket *
b4f06520 57get (const int fd)
5a64d869
CF
58{
59 cygheap_fdget cfd (fd);
79224853 60
5a64d869 61 if (cfd < 0)
7f601990 62 return NULL;
5a64d869 63
b4f06520 64 fhandler_socket *const fh = cfd->is_socket ();
79224853 65
141437d3
KB
66 if (!fh || (fh->get_flags () & O_PATH))
67 {
68 set_errno (ENOTSOCK);
69 return NULL;
70 }
b4f06520
CS
71
72 return fh;
5a64d869
CF
73}
74
0bec0119 75/* exported as inet_ntoa: BSD 4.3 */
4e6a4ea8 76extern "C" char *
1fd5e000
CF
77cygwin_inet_ntoa (struct in_addr in)
78{
72203114
CV
79 char buf[20];
80 const char *res = cygwin_inet_ntop (AF_INET, &in, buf, sizeof buf);
79224853 81
29d52c8a 82 if (_my_tls.locals.ntoa_buf)
1fdc8df9 83 {
29d52c8a
CF
84 free (_my_tls.locals.ntoa_buf);
85 _my_tls.locals.ntoa_buf = NULL;
1fdc8df9
CV
86 }
87 if (res)
29d52c8a
CF
88 _my_tls.locals.ntoa_buf = strdup (res);
89 return _my_tls.locals.ntoa_buf;
1fd5e000
CF
90}
91
1fd5e000
CF
92/* inet_netof is in the standard BSD sockets library. It is useless
93 for modern networks, since it assumes network values which are no
94 longer meaningful, but some existing code calls it. */
95
4e6a4ea8 96extern "C" unsigned long
1fd5e000
CF
97inet_netof (struct in_addr in)
98{
99 unsigned long i, res;
100
1fd5e000
CF
101 i = ntohl (in.s_addr);
102 if (IN_CLASSA (i))
103 res = (i & IN_CLASSA_NET) >> IN_CLASSA_NSHIFT;
104 else if (IN_CLASSB (i))
105 res = (i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT;
106 else
107 res = (i & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT;
108
1fd5e000
CF
109 return res;
110}
111
112/* inet_makeaddr is in the standard BSD sockets library. It is
113 useless for modern networks, since it assumes network values which
114 are no longer meaningful, but some existing code calls it. */
115
4e6a4ea8 116extern "C" struct in_addr
1fd5e000
CF
117inet_makeaddr (int net, int lna)
118{
119 unsigned long i;
53a12585 120 struct in_addr in;
1fd5e000
CF
121
122 if (net < IN_CLASSA_MAX)
123 i = (net << IN_CLASSA_NSHIFT) | (lna & IN_CLASSA_HOST);
124 else if (net < IN_CLASSB_MAX)
125 i = (net << IN_CLASSB_NSHIFT) | (lna & IN_CLASSB_HOST);
126 else if (net < 0x1000000)
127 i = (net << IN_CLASSC_NSHIFT) | (lna & IN_CLASSC_HOST);
128 else
129 i = net | lna;
130
131 in.s_addr = htonl (i);
132
133
134 return in;
135}
136
70c7e8c1
CV
137static const int wsock_errmap[] =
138{
139 0, /* WSABASEERR (10000) */
140 0, /* 10001 */
141 0, /* 10002 */
142 0, /* 10003 */
143 EINTR, /* WSAEINTR */
144 0, /* 10005 */
145 0, /* 10006 */
146 0, /* 10007 */
147 0, /* 10008 */
148 EBADF, /* WSAEBADF */
149 0, /* 10010 */
150 0, /* 10011 */
151 0, /* 10012 */
152 EACCES, /* WSAEACCES */
153 EFAULT, /* WSAEFAULT */
154 0, /* 10015 */
155 0, /* 10016 */
156 0, /* 10017 */
157 0, /* 10018 */
158 0, /* 10019 */
159 0, /* 10020 */
160 0, /* 10021 */
161 EINVAL, /* WSAEINVAL */
162 0, /* 10023 */
163 EMFILE, /* WSAEMFILE */
164 0, /* 10025 */
165 0, /* 10026 */
166 0, /* 10027 */
167 0, /* 10028 */
168 0, /* 10029 */
169 0, /* 10030 */
170 0, /* 10031 */
171 0, /* 10032 */
172 0, /* 10033 */
173 0, /* 10034 */
174 EWOULDBLOCK, /* WSAEWOULDBLOCK */
175 EINPROGRESS, /* WSAEINPROGRESS */
176 EALREADY, /* WSAEALREADY */
177 ENOTSOCK, /* WSAENOTSOCK */
178 EDESTADDRREQ, /* WSAEDESTADDRREQ */
179 EMSGSIZE, /* WSAEMSGSIZE */
180 EPROTOTYPE, /* WSAEPROTOTYPE */
181 ENOPROTOOPT, /* WSAENOPROTOOPT */
182 EPROTONOSUPPORT, /* WSAEPROTONOSUPPORT */
183 ESOCKTNOSUPPORT, /* WSAESOCKTNOSUPPORT */
184 EOPNOTSUPP, /* WSAEOPNOTSUPP */
185 EPFNOSUPPORT, /* WSAEPFNOSUPPORT */
186 EAFNOSUPPORT, /* WSAEAFNOSUPPORT */
187 EADDRINUSE, /* WSAEADDRINUSE */
188 EADDRNOTAVAIL, /* WSAEADDRNOTAVAIL */
189 ENETDOWN, /* WSAENETDOWN */
190 ENETUNREACH, /* WSAENETUNREACH */
191 ENETRESET, /* WSAENETRESET */
192 ECONNABORTED, /* WSAECONNABORTED */
193 ECONNRESET, /* WSAECONNRESET */
194 ENOBUFS, /* WSAENOBUFS */
195 EISCONN, /* WSAEISCONN */
196 ENOTCONN, /* WSAENOTCONN */
197 ESHUTDOWN, /* WSAESHUTDOWN */
198 ETOOMANYREFS, /* WSAETOOMANYREFS */
199 ETIMEDOUT, /* WSAETIMEDOUT */
200 ECONNREFUSED, /* WSAECONNREFUSED */
201 ELOOP, /* WSAELOOP */
202 ENAMETOOLONG, /* WSAENAMETOOLONG */
203 EHOSTDOWN, /* WSAEHOSTDOWN */
204 EHOSTUNREACH, /* WSAEHOSTUNREACH */
205 ENOTEMPTY, /* WSAENOTEMPTY */
206 EPROCLIM, /* WSAEPROCLIM */
207 EUSERS, /* WSAEUSERS */
208 EDQUOT, /* WSAEDQUOT */
209 ESTALE, /* WSAESTALE */
210 EREMOTE, /* WSAEREMOTE */
1fd5e000
CF
211};
212
ea1e5318 213int
044ab77d 214find_winsock_errno (DWORD why)
c90e420d 215{
70c7e8c1
CV
216 if (!why)
217 return 0;
218 if (why < WSABASEERR)
219 geterrno_from_win_error (why, EACCES);
220
221 why -= WSABASEERR;
222 if (why < sizeof wsock_errmap / sizeof wsock_errmap[0])
223 return wsock_errmap[why];
c90e420d 224
489e7e20 225 return EACCES;
c90e420d
CF
226}
227
1fd5e000 228void
829425c9 229__set_winsock_errno (const char *fn, int ln)
1fd5e000 230{
c90e420d
CF
231 DWORD werr = WSAGetLastError ();
232 int err = find_winsock_errno (werr);
79224853 233
c90e420d 234 set_errno (err);
61522196 235 syscall_printf ("%s:%d - winsock error %u -> errno %d", fn, ln, werr, err);
1fd5e000
CF
236}
237
a8c1dd2c
CV
238static const struct host_errmap_t
239{
240 DWORD w; /* windows version of error */
241 const char *s; /* error text returned by herror and hstrerror */
242 int e; /* errno version of error */
243} host_errmap[] = {
7d9688b7
CV
244 {WSAHOST_NOT_FOUND, "Unknown host", HOST_NOT_FOUND},
245 {WSATRY_AGAIN, "Host name lookup failure", TRY_AGAIN},
246 {WSANO_RECOVERY, "Unknown server error", NO_RECOVERY},
247 {WSANO_DATA, "No address associated with name", NO_DATA},
01cf5d0f 248 {0, NULL, 0}
1fd5e000
CF
249};
250
1fd5e000
CF
251static void
252set_host_errno ()
253{
254 int i;
255
044ab77d 256 DWORD why = WSAGetLastError ();
79224853 257
7d9688b7 258 for (i = 0; host_errmap[i].w != 0; ++i)
1fd5e000
CF
259 if (why == host_errmap[i].w)
260 break;
261
262 if (host_errmap[i].w != 0)
263 h_errno = host_errmap[i].e;
264 else
265 h_errno = NETDB_INTERNAL;
266}
267
edf16a29
CF
268inline int
269DWORD_round (int n)
1fdc8df9 270{
edf16a29 271 return sizeof (DWORD) * (((n + sizeof (DWORD) - 1)) / sizeof (DWORD));
1fdc8df9
CV
272}
273
edf16a29
CF
274inline int
275strlen_round (const char *s)
1fdc8df9 276{
edf16a29
CF
277 if (!s)
278 return 0;
279 return DWORD_round (strlen (s) + 1);
1fdc8df9
CV
280}
281
edf16a29
CF
282#pragma pack(push,2)
283struct pservent
5d0fe635 284{
edf16a29
CF
285 char *s_name;
286 char **s_aliases;
287 short s_port;
288 char *s_proto;
289};
290#pragma pack(pop)
1ff9f4b9 291
a3de4e19
CF
292static const char *entnames[] = {"host", "proto", "serv"};
293
6f57cb4a
CV
294static unionent *
295realloc_ent (unionent *&dst, int sz)
296{
297 /* Allocate the storage needed. Allocate a rounded size to attempt to force
298 reuse of this buffer so that a poorly-written caller will not be using
299 a freed buffer. */
300 unsigned rsz = 256 * ((sz + 255) / 256);
301 unionent * ptr;
302 if ((ptr = (unionent *) realloc (dst, rsz)))
303 dst = ptr;
304 return ptr;
305}
306
307static inline hostent *
308realloc_ent (int sz, hostent *)
309{
310 return (hostent *) realloc_ent (_my_tls.locals.hostent_buf, sz);
311}
312
edf16a29
CF
313/* Generic "dup a {host,proto,serv}ent structure" function.
314 This is complicated because we need to be able to free the
315 structure at any point and we can't rely on the pointer contents
316 being untouched by callers. So, we allocate a chunk of memory
317 large enough to hold the structure and all of the stuff it points
318 to then we copy the source into this new block of memory.
319 The 'unionent' struct is a union of all of the currently used
320 *ent structure. */
321
61522196
CV
322/* For some baffling reason, somebody at Microsoft decided that it would be
323 a good idea to exchange the s_port and s_proto members in the servent
324 structure. */
325struct win64_servent
326{
327 char *s_name;
328 char **s_aliases;
329 char *s_proto;
330 short s_port;
331};
332#define WIN_SERVENT(x) ((win64_servent *)(x))
61522196 333
edf16a29
CF
334#ifdef DEBUGGING
335static void *
336#else
337static inline void *
338#endif
f2c11dad 339dup_ent (unionent *&dst, unionent *src, unionent::struct_type type)
1fdc8df9 340{
fe836470
CF
341 if (dst)
342 debug_printf ("old %sent structure \"%s\" %p\n", entnames[type],
f2c11dad 343 dst->name, dst);
fe836470
CF
344
345 if (!src)
a3de4e19 346 {
fe836470
CF
347 set_winsock_errno ();
348 return NULL;
a3de4e19
CF
349 }
350
8b59143f 351 debug_printf ("duping %sent \"%s\", %p", entnames[type], src->name, src);
1fdc8df9 352
edf16a29
CF
353 /* Find the size of the raw structure minus any character strings, etc. */
354 int sz, struct_sz;
355 switch (type)
356 {
f2c11dad 357 case unionent::t_protoent:
edf16a29
CF
358 struct_sz = sizeof (protoent);
359 break;
f2c11dad 360 case unionent::t_servent:
edf16a29
CF
361 struct_sz = sizeof (servent);
362 break;
f2c11dad 363 case unionent::t_hostent:
edf16a29
CF
364 struct_sz = sizeof (hostent);
365 break;
366 default:
367 api_fatal ("called with invalid value %d", type);
368 break;
1fdc8df9 369 }
1fdc8df9 370
6f57cb4a 371 /* Every *ent begins with a name. Calculate its length. */
edf16a29
CF
372 int namelen = strlen_round (src->name);
373 sz = struct_sz + namelen;
1fdc8df9 374
edf16a29
CF
375 char **av;
376 /* The next field in every *ent is an argv list of "something".
377 Calculate the number of components and how much space the
378 character strings will take. */
379 int list_len = 0;
380 for (av = src->list; av && *av; av++)
381 {
382 list_len++;
383 sz += sizeof (char **) + strlen_round (*av);
384 }
79224853 385
edf16a29
CF
386 /* NULL terminate if there actually was a list */
387 if (av)
388 {
389 sz += sizeof (char **);
390 list_len++;
391 }
1fdc8df9 392
edf16a29
CF
393 /* Do servent/hostent specific processing */
394 int protolen = 0;
395 int addr_list_len = 0;
f2c11dad 396 if (type == unionent::t_servent)
dff017b2 397 {
61522196
CV
398 if (WIN_SERVENT (src)->s_proto)
399 sz += (protolen = strlen_round (WIN_SERVENT (src)->s_proto));
dff017b2 400 }
f2c11dad 401 else if (type == unionent::t_hostent)
edf16a29
CF
402 {
403 /* Calculate the length and storage used for h_addr_list */
404 for (av = src->h_addr_list; av && *av; av++)
405 {
406 addr_list_len++;
407 sz += sizeof (char **) + DWORD_round (src->h_len);
408 }
409 if (av)
410 {
411 sz += sizeof (char **);
412 addr_list_len++;
413 }
414 }
1fdc8df9 415
6f57cb4a
CV
416 /* Allocate the storage needed. */
417 if (realloc_ent (dst, sz))
edf16a29 418 {
fe836470 419 memset (dst, 0, sz);
edf16a29 420 /* This field is common to all *ent structures but named differently
61522196
CV
421 in each, of course. Also, take 64 bit Windows servent weirdness
422 into account. */
423 if (type == unionent::t_servent)
424 dst->port_proto_addrtype = WIN_SERVENT (src)->s_port;
425 else
426 dst->port_proto_addrtype = src->port_proto_addrtype;
edf16a29 427
edf16a29 428 char *dp = ((char *) dst) + struct_sz;
8b59143f
CF
429 if (namelen)
430 {
431 /* Copy the name field to dst, using space just beyond the end of
432 the dst structure. */
433 strcpy (dst->name = dp, src->name);
434 dp += namelen;
435 }
edf16a29
CF
436
437 /* Copy the 'list' type to dst, using space beyond end of structure
438 + storage for name. */
439 if (src->list)
440 {
441 char **dav = dst->list = (char **) dp;
442 dp += sizeof (char **) * list_len;
443 for (av = src->list; av && *av; av++)
444 {
445 int len = strlen (*av) + 1;
446 memcpy (*dav++ = dp, *av, len);
447 dp += DWORD_round (len);
448 }
449 }
1fdc8df9 450
fe836470 451 /* Do servent/protoent/hostent specific processing. */
f2c11dad 452 if (type == unionent::t_protoent)
61522196 453 debug_printf ("protoent %s %p %y", dst->name, dst->list, dst->port_proto_addrtype);
f2c11dad 454 else if (type == unionent::t_servent)
edf16a29 455 {
61522196 456 if (WIN_SERVENT (src)->s_proto)
edf16a29 457 {
61522196 458 strcpy (dst->s_proto = dp, WIN_SERVENT (src)->s_proto);
edf16a29
CF
459 dp += protolen;
460 }
461 }
f2c11dad 462 else if (type == unionent::t_hostent)
edf16a29
CF
463 {
464 /* Transfer h_len and duplicate contents of h_addr_list, using
465 memory after 'list' allocation. */
466 dst->h_len = src->h_len;
467 char **dav = dst->h_addr_list = (char **) dp;
468 dp += sizeof (char **) * addr_list_len;
469 for (av = src->h_addr_list; av && *av; av++)
470 {
471 memcpy (*dav++ = dp, *av, src->h_len);
472 dp += DWORD_round (src->h_len);
473 }
474 }
edf16a29 475 }
a3de4e19 476 debug_printf ("duped %sent \"%s\", %p", entnames[type], dst ? dst->name : "<null!>", dst);
1fdc8df9 477 return dst;
1fdc8df9
CV
478}
479
f2c11dad
CF
480static inline hostent *
481dup_ent (hostent *src)
482{
483 return (hostent *) dup_ent (_my_tls.locals.hostent_buf, (unionent *) src, unionent::t_hostent);
484}
485
486static inline protoent *
487dup_ent (protoent *src)
488{
489 return (protoent *) dup_ent (_my_tls.locals.protoent_buf, (unionent *) src, unionent::t_protoent);
490}
491
492static inline servent *
493dup_ent (servent *src)
494{
495 return (servent *) dup_ent (_my_tls.locals.servent_buf, (unionent *) src, unionent::t_servent);
496}
497
f881942d 498/* exported as getprotobyname: POSIX.1-2001, POSIX.1-2008, 4.3BSD */
4e6a4ea8 499extern "C" struct protoent *
1fd5e000
CF
500cygwin_getprotobyname (const char *p)
501{
3f3bd101
CV
502 __try
503 {
504 return dup_ent (getprotobyname (p));
505 }
506 __except (EFAULT) {}
507 __endtry
508 return NULL;
1fd5e000
CF
509}
510
f881942d 511/* exported as getprotobynumber: POSIX.1-2001, POSIX.1-2008, 4.3BSD */
4e6a4ea8 512extern "C" struct protoent *
1fd5e000
CF
513cygwin_getprotobynumber (int number)
514{
f2c11dad 515 return dup_ent (getprotobynumber (number));
1fd5e000
CF
516}
517
f881942d 518/* exported as socket: POSIX.1-2001, POSIX.1-2008, 4.4BSD */
4e6a4ea8 519extern "C" int
1fd5e000
CF
520cygwin_socket (int af, int type, int protocol)
521{
522 int res = -1;
913c6ca2
CV
523 const device *dev;
524 fhandler_socket *fh;
1fd5e000 525
0d653155
CV
526 int flags = type & _SOCK_FLAG_MASK;
527 type &= ~_SOCK_FLAG_MASK;
528
61522196 529 debug_printf ("socket (%d, %d (flags %y), %d)", af, type, flags, protocol);
0d653155 530
913c6ca2 531 switch (af)
0d653155 532 {
913c6ca2 533 case AF_LOCAL:
6c55be9d
CV
534#ifndef __WITH_AF_UNIX
535 dev = af_local_dev;
536#else
7f7532fa 537 case AF_UNIX:
7f7532fa 538 dev = (af == AF_LOCAL) ? af_local_dev : af_unix_dev;
6c55be9d 539#endif /* __WITH_AF_UNIX */
913c6ca2
CV
540 break;
541 case AF_INET:
542 case AF_INET6:
03f380c2 543 dev = af_inet_dev;
913c6ca2
CV
544 break;
545 default:
546 set_errno (EAFNOSUPPORT);
0d653155
CV
547 goto done;
548 }
1fd5e000 549
913c6ca2 550 if ((flags & ~(SOCK_NONBLOCK | SOCK_CLOEXEC)) != 0)
518f5d49 551 {
913c6ca2 552 set_errno (EINVAL);
518f5d49
CV
553 goto done;
554 }
1fd5e000 555
913c6ca2
CV
556 {
557 cygheap_fdnew fd;
79224853 558
913c6ca2
CV
559 if (fd < 0)
560 goto done;
561 fh = (fhandler_socket *) build_fh_dev (*dev);
562 if (fh && fh->socket (af, type, protocol, flags) == 0)
563 {
564 fd = fh;
565 if (fd <= 2)
566 set_std_handle (fd);
567 res = fd;
568 }
569 else
2bbe8697 570 delete fh;
913c6ca2 571 }
1fd5e000
CF
572
573done:
61522196 574 syscall_printf ("%R = socket(%d, %d (flags %y), %d)",
0d653155 575 res, af, type, flags, protocol);
1fd5e000
CF
576 return res;
577}
578
f881942d 579/* exported as sendto: 4.4BSD, SVr4, POSIX.1-2001 */
61522196 580extern "C" ssize_t
78db7dff
CV
581cygwin_sendto (int fd, const void *buf, size_t len, int flags,
582 const struct sockaddr *to, socklen_t tolen)
1fd5e000 583{
3f3bd101 584 ssize_t res = -1;
61522196
CV
585
586 pthread_testcancel ();
0a642325 587
3f3bd101
CV
588 __try
589 {
590 fhandler_socket *fh = get (fd);
591 if (fh)
592 res = fh->sendto (buf, len, flags, to, tolen);
593 }
594 __except (EFAULT) {}
595 __endtry
61522196 596 syscall_printf ("%lR = sendto(%d, %p, %ld, %y, %p, %d)",
c250f914 597 res, fd, buf, len, flags, to, tolen);
1fd5e000
CF
598 return res;
599}
600
f881942d 601/* exported as recvfrom: 4.4BSD, SVr4, POSIX.1-2001 */
61522196 602extern "C" ssize_t
78db7dff
CV
603cygwin_recvfrom (int fd, void *buf, size_t len, int flags,
604 struct sockaddr *from, socklen_t *fromlen)
1fd5e000 605{
3f3bd101 606 ssize_t res = -1;
61522196
CV
607
608 pthread_testcancel ();
0a642325 609
3f3bd101
CV
610 __try
611 {
612 fhandler_socket *fh = get (fd);
613 if (fh)
614 /* Originally we shortcircuited here if res == 0.
615 Allow 0 bytes buffer. This is valid in POSIX and handled in
616 fhandler_socket::recv_internal. If we shortcircuit, we fail
617 to deliver valid error conditions and peer address. */
618 res = fh->recvfrom (buf, len, flags, from, fromlen);
619 }
620 __except (EFAULT) {}
621 __endtry
61522196 622 syscall_printf ("%lR = recvfrom(%d, %p, %ld, %y, %p, %p)",
c250f914 623 res, fd, buf, len, flags, from, fromlen);
1fd5e000
CF
624 return res;
625}
626
f881942d 627/* exported as setsockopt: POSIX.1-2001, POSIX.1-2008, SVr4, 4.4BSD */
4e6a4ea8 628extern "C" int
be5007aa 629cygwin_setsockopt (int fd, int level, int optname, const void *optval,
78db7dff 630 socklen_t optlen)
1fd5e000 631{
ea1e5318 632 int ret = -1;
1fd5e000 633
3f3bd101 634 __try
b4f06520 635 {
3f3bd101 636 fhandler_socket *fh = get (fd);
ea1e5318
CV
637 if (fh)
638 ret = fh->setsockopt (level, optname, optval, optlen);
3f3bd101 639 }
ea1e5318 640 __except (EFAULT) {}
3f3bd101 641 __endtry
61522196 642 syscall_printf ("%R = setsockopt(%d, %d, %y, %p, %d)",
ea1e5318
CV
643 ret, fd, level, optname, optval, optlen);
644 return ret;
1fd5e000
CF
645}
646
f881942d 647/* exported as getsockopt: POSIX.1-2001, POSIX.1-2008, SVr4, 4.4BSD */
4e6a4ea8 648extern "C" int
78db7dff
CV
649cygwin_getsockopt (int fd, int level, int optname, void *optval,
650 socklen_t *optlen)
1fd5e000 651{
ea1e5318 652 int ret = -1;
1fd5e000 653
3f3bd101 654 __try
b4f06520 655 {
3f3bd101 656 fhandler_socket *fh = get (fd);
ea1e5318
CV
657 if (fh)
658 ret = fh->getsockopt (level, optname, optval, optlen);
3f3bd101 659 }
ea1e5318 660 __except (EFAULT) {}
3f3bd101 661 __endtry
61522196 662 syscall_printf ("%R = getsockopt(%d, %d, %y, %p, %p)",
ea1e5318
CV
663 ret, fd, level, optname, optval, optlen);
664 return ret;
1fd5e000
CF
665}
666
d2264bce
CV
667/* POSIX.1-2001 */
668extern "C" int
669sockatmark (int fd)
670{
671 int ret;
141437d3 672 cygheap_fdget cfd (fd);
d2264bce 673
141437d3
KB
674 if (cfd < 0)
675 return -1;
676
677 fhandler_socket *const fh = cfd->is_socket ();
678 if (!fh)
679 set_errno (ENOTSOCK);
680 else if (fh->get_flags () & O_PATH)
681 set_errno (EBADF);
682 else if (fh->ioctl (SIOCATMARK, &ret) != -1)
d2264bce
CV
683 return ret;
684 return -1;
685}
686
687/* BSD */
c8b404bf 688extern "C" int
61522196 689getpeereid (int fd, uid_t *euid, gid_t *egid)
c8b404bf 690{
c8b404bf
CV
691 fhandler_socket *fh = get (fd);
692 if (fh)
693 return fh->getpeereid (NULL, euid, egid);
694 return -1;
695}
696
f881942d 697/* exported as connect: POSIX.1-2001, POSIX.1-2008, SVr4, 4.4BSD */
4e6a4ea8 698extern "C" int
78db7dff 699cygwin_connect (int fd, const struct sockaddr *name, socklen_t namelen)
1fd5e000 700{
3f3bd101 701 int res = -1;
0a642325 702
61522196
CV
703 pthread_testcancel ();
704
3f3bd101
CV
705 __try
706 {
707 fhandler_socket *fh = get (fd);
708 if (fh)
709 res = fh->connect (name, namelen);
710 }
711 __except (EFAULT) {}
712 __endtry
b9aa8149 713 syscall_printf ("%R = connect(%d, %p, %d)", res, fd, name, namelen);
1fd5e000
CF
714 return res;
715}
716
f881942d 717/* exported as getservbyname: POSIX.1-2001, POSIX.1-2008, 4.3BSD */
4e6a4ea8 718extern "C" struct servent *
1fd5e000
CF
719cygwin_getservbyname (const char *name, const char *proto)
720{
3f3bd101 721 servent *res = NULL;
5a64d869 722
3f3bd101
CV
723 __try
724 {
725 res = dup_ent (getservbyname (name, proto));
726 }
727 __except (EFAULT) {}
728 __endtry
4ef6a27a
CF
729 syscall_printf ("%p = getservbyname (%s, %s)", res, name, proto);
730 return res;
1fd5e000
CF
731}
732
f881942d 733/* exported as getservbyport: POSIX.1-2001, POSIX.1-2008, 4.3BSD */
4e6a4ea8 734extern "C" struct servent *
1fd5e000
CF
735cygwin_getservbyport (int port, const char *proto)
736{
3f3bd101 737 servent *res = NULL;
5a64d869 738
3f3bd101
CV
739 __try
740 {
741 res = dup_ent (getservbyport (port, proto));
742 }
743 __except (EFAULT) {}
744 __endtry
f2c11dad 745 syscall_printf ("%p = getservbyport (%d, %s)", res, port, proto);
4ef6a27a 746 return res;
1fd5e000
CF
747}
748
4e6a4ea8 749extern "C" int
1fd5e000
CF
750cygwin_gethostname (char *name, size_t len)
751{
3f3bd101 752 __try
1fd5e000 753 {
2166f7dc
CV
754 PFIXED_INFO info = NULL;
755 ULONG size = 0;
3f3bd101 756
2166f7dc
CV
757 if (GetNetworkParams(info, &size) == ERROR_BUFFER_OVERFLOW
758 && (info = (PFIXED_INFO) alloca(size))
759 && GetNetworkParams(info, &size) == ERROR_SUCCESS)
760 {
761 strncpy(name, info->HostName, len);
762 debug_printf ("gethostname %s", name);
763 return 0;
1fd5e000 764 }
2166f7dc 765 __seterrno ();
1fd5e000 766 }
2166f7dc 767 __except (EFAULT)
3f3bd101 768 __endtry
2166f7dc 769 return -1;
1fd5e000
CF
770}
771
50b00d2b
CV
772extern "C" int
773sethostname (const char *name, size_t len)
774{
775 WCHAR wname[MAX_COMPUTERNAME_LENGTH + 1];
776
777 sys_mbstowcs (wname, MAX_COMPUTERNAME_LENGTH + 1, name, len);
778 if (!SetComputerNameExW (ComputerNamePhysicalDnsHostname, wname))
779 {
780 __seterrno ();
781 return -1;
782 }
783 return 0;
784}
785
2166f7dc
CV
786/* getdomainname: 4.4BSD */
787extern "C" int
788getdomainname (char *domain, size_t len)
789{
790 __try
791 {
792 PFIXED_INFO info = NULL;
793 ULONG size = 0;
794
795 if (GetNetworkParams(info, &size) == ERROR_BUFFER_OVERFLOW
796 && (info = (PFIXED_INFO) alloca(size))
797 && GetNetworkParams(info, &size) == ERROR_SUCCESS)
798 {
799 strncpy(domain, info->DomainName, len);
6c9c37d0 800 debug_printf ("getdomainname %s", domain);
2166f7dc
CV
801 return 0;
802 }
803 __seterrno ();
804 }
805 __except (EFAULT)
806 __endtry
807 return -1;
808}
809
f881942d 810/* exported as gethostbyname: POSIX.1-2001 */
4e6a4ea8 811extern "C" struct hostent *
1fd5e000
CF
812cygwin_gethostbyname (const char *name)
813{
a694f079
CF
814 unsigned char tmp_addr[4];
815 struct hostent tmp, *h;
816 char *tmp_aliases[1] = {0};
817 char *tmp_addr_list[2] = {0,0};
818 unsigned int a, b, c, d;
819 char dummy;
3f3bd101 820 hostent *res = NULL;
4e6a4ea8 821
3f3bd101 822 __try
1fd5e000 823 {
3f3bd101
CV
824 if (sscanf (name, "%u.%u.%u.%u%c", &a, &b, &c, &d, &dummy) != 4
825 || a >= 256 || b >= 256 || c >= 256 || d >= 256)
826 h = gethostbyname (name);
827 else
828 {
829 /* In case you don't have DNS, at least x.x.x.x still works */
830 memset (&tmp, 0, sizeof (tmp));
831 tmp_addr[0] = a;
832 tmp_addr[1] = b;
833 tmp_addr[2] = c;
834 tmp_addr[3] = d;
835 tmp_addr_list[0] = (char *) tmp_addr;
836 tmp.h_name = name;
837 tmp.h_aliases = tmp_aliases;
838 tmp.h_addrtype = 2;
839 tmp.h_length = 4;
840 tmp.h_addr_list = tmp_addr_list;
841 h = &tmp;
842 }
843
844 res = dup_ent (h);
845 if (res)
846 debug_printf ("h_name %s", res->h_name);
847 else
848 {
849 debug_printf ("dup_ent returned NULL for name %s, h %p", name, h);
850 set_host_errno ();
851 }
852 }
853 __except (EFAULT)
1fd5e000 854 {
3f3bd101 855 res = NULL;
1fd5e000 856 }
3f3bd101 857 __endtry
4ef6a27a 858 return res;
cb19ccf4
CV
859}
860
f881942d 861/* exported as gethostbyaddr: POSIX.1-2001 */
cb19ccf4 862extern "C" struct hostent *
747f3185 863cygwin_gethostbyaddr (const void *addr, socklen_t len, int type)
cb19ccf4 864{
3f3bd101 865 hostent *res = NULL;
5a64d869 866
3f3bd101
CV
867 __try
868 {
747f3185 869 res = dup_ent (gethostbyaddr ((const char *) addr, len, type));
3f3bd101
CV
870 if (res)
871 debug_printf ("h_name %s", res->h_name);
872 else
873 set_host_errno ();
874 }
875 __except (EFAULT)
876 {
877 res = NULL;
878 }
879 __endtry
4ef6a27a 880 return res;
1fd5e000
CF
881}
882
0a20e5a0 883static void
acc5f02c 884memcpy4to6 (char *dst, const u_int8_t *src)
6f57cb4a
CV
885{
886 const unsigned int h[] = {0, 0, htonl (0xFFFF)};
887 memcpy (dst, h, 12);
888 memcpy (dst + 12, src, NS_INADDRSZ);
889}
890
b74bc883
CV
891/* gethostby_specials: RFC 6761
892 Handles numerical addresses and special names for gethostbyname2 */
64f8b4ca
CV
893static hostent *
894gethostby_specials (const char *name, const int af,
895 const int addrsize_in, const int addrsize_out)
896{
897 int namelen = strlen (name);
898 /* Ignore a final '.' */
b74bc883 899 if ((namelen == 0) || ((namelen -= (name[namelen - 1] == '.')) == 0))
64f8b4ca
CV
900 {
901 set_errno (EINVAL);
902 h_errno = NETDB_INTERNAL;
903 return NULL;
904 }
905
906 int res;
acc5f02c 907 u_int8_t address[NS_IN6ADDRSZ];
64f8b4ca
CV
908 /* Test for numerical addresses */
909 res = cygwin_inet_pton(af, name, address);
910 /* Test for special domain names */
911 if (res != 1)
912 {
913 {
914 char const match[] = "invalid";
915 int const matchlen = sizeof(match) - 1;
916 int start = namelen - matchlen;
917 if ((start >= 0) && ((start == 0) || (name[start-1] == '.'))
918 && (strncasecmp (&name[start], match , matchlen) == 0))
919 {
920 h_errno = HOST_NOT_FOUND;
921 return NULL;
922 }
923 }
924 {
925 char const match[] = "localhost";
926 int const matchlen = sizeof(match) - 1;
927 int start = namelen - matchlen;
928 if ((start >= 0) && ((start == 0) || (name[start-1] == '.'))
929 && (strncasecmp (&name[start], match , matchlen) == 0))
930 {
931 res = 1;
932 if (af == AF_INET)
933 {
934 address[0] = 127;
935 address[1] = address[2] = 0;
936 address[3] = 1;
937 }
938 else
939 {
940 memset (address, 0, NS_IN6ADDRSZ);
941 address[NS_IN6ADDRSZ-1] = 1;
942 }
943 }
944 }
945 }
946 if (res != 1)
b74bc883 947 return NULL;
64f8b4ca
CV
948
949 int const alias_count = 0, address_count = 1;
950 char * string_ptr;
951 int sz = DWORD_round (sizeof(hostent))
952 + sizeof (char *) * (alias_count + address_count + 2)
953 + namelen + 1
954 + address_count * addrsize_out;
955 hostent *ret = realloc_ent (sz, (hostent *) NULL);
956 if (!ret)
957 {
958 /* errno is already set */
959 h_errno = NETDB_INTERNAL;
960 return NULL;
961 }
962
963 ret->h_addrtype = af;
964 ret->h_length = addrsize_out;
965 ret->h_aliases = (char **) (((char *) ret) + DWORD_round (sizeof(hostent)));
966 ret->h_addr_list = ret->h_aliases + alias_count + 1;
967 string_ptr = (char *) (ret->h_addr_list + address_count + 1);
968 ret->h_name = string_ptr;
969
970 memcpy (string_ptr, name, namelen);
971 string_ptr[namelen] = 0;
972 string_ptr += namelen + 1;
973
974 ret->h_addr_list[0] = string_ptr;
975 if (addrsize_in != addrsize_out)
976 {
977 memcpy4to6 (string_ptr, address);
978 ret->h_addrtype = AF_INET6;
979 }
980 else
981 memcpy (string_ptr, address, addrsize_out);
982
983 ret->h_aliases[alias_count] = NULL;
984 ret->h_addr_list[address_count] = NULL;
985
986 return ret;
987}
988
0a20e5a0 989static hostent *
6f57cb4a
CV
990gethostby_helper (const char *name, const int af, const int type,
991 const int addrsize_in, const int addrsize_out)
992{
993 /* Get the data from the name server */
994 const int maxcount = 3;
995 int old_errno, ancount = 0, anlen = 1024, msgsize = 0;
acc5f02c 996 unsigned char *ptr, *msg = NULL;
6f57cb4a
CV
997 int sz;
998 hostent *ret;
999 char *string_ptr;
1000
1001 while ((anlen > msgsize) && (ancount++ < maxcount))
1002 {
1003 msgsize = anlen;
acc5f02c 1004 ptr = (unsigned char *) realloc (msg, msgsize);
6f57cb4a
CV
1005 if (ptr == NULL )
1006 {
1007 old_errno = errno;
1008 free (msg);
1009 set_errno (old_errno);
1010 h_errno = NETDB_INTERNAL;
1011 return NULL;
1012 }
1013 msg = ptr;
1014 anlen = res_search (name, ns_c_in, type, msg, msgsize);
0a20e5a0 1015 }
6f57cb4a
CV
1016
1017 if (ancount >= maxcount)
1018 {
1019 free (msg);
1020 h_errno = NO_RECOVERY;
1021 return NULL;
1022 }
1023 if (anlen < 0) /* errno and h_errno are set */
1024 {
1025 old_errno = errno;
1026 free (msg);
1027 set_errno (old_errno);
0a20e5a0 1028 return NULL;
6f57cb4a 1029 }
acc5f02c 1030 unsigned char *eomsg = msg + anlen - 1;
6f57cb4a 1031
0a20e5a0 1032 /* We scan the answer records to determine the required memory size.
6f57cb4a
CV
1033 They can be corrupted and we don't fully trust that the message
1034 follows the standard exactly. glibc applies some checks that
1035 we emulate.
1036 The answers are copied in the hostent structure in a second scan.
1037 To simplify the second scan we store information as follows:
1038 - "class" is replaced by the compressed name size
0a20e5a0 1039 - the first 16 bits of the "ttl" store the expanded name size + 1
6f57cb4a
CV
1040 - the last 16 bits of the "ttl" store the offset to the next valid record.
1041 Note that "type" is rewritten in host byte order. */
0a20e5a0 1042
6f57cb4a
CV
1043 class record {
1044 public:
1045 unsigned type: 16; // type
1046 unsigned complen: 16; // class or compressed length
1047 unsigned namelen1: 16; // expanded length (with final 0)
1048 unsigned next_o: 16; // offset to next valid
1049 unsigned size: 16; // data size
acc5f02c 1050 unsigned char data[]; // data
6f57cb4a
CV
1051 record * next () { return (record *) (((char *) this) + next_o); }
1052 void set_next ( record * nxt) { next_o = ((char *) nxt) - ((char *) this); }
acc5f02c
CV
1053 unsigned char *name () { return (unsigned char *)
1054 (((char *) this) - complen); }
6f57cb4a
CV
1055 };
1056
1057 record * anptr = NULL, * prevptr = NULL, * curptr;
1058 int i, alias_count = 0, string_size = 0, address_count = 0;
0a20e5a0
CF
1059 int namelen1 = 0, address_len = 0, antype, anclass, ansize;
1060 unsigned complen;
6f57cb4a
CV
1061
1062 /* Get the count of answers */
1063 ancount = ntohs (((HEADER *) msg)->ancount);
1064
1065 /* Skip the question, it was verified by res_send */
1066 ptr = msg + sizeof (HEADER);
1067 if ((complen = dn_skipname (ptr, eomsg)) < 0)
0a20e5a0 1068 goto corrupted;
6f57cb4a
CV
1069 /* Point to the beginning of the answer section */
1070 ptr += complen + NS_QFIXEDSZ;
0a20e5a0 1071
6f57cb4a
CV
1072 /* Scan the answer records to determine the sizes */
1073 for (i = 0; i < ancount; i++, ptr = curptr->data + ansize)
1074 {
1075 if ((complen = dn_skipname (ptr, eomsg)) < 0)
1076 goto corrupted;
1077
1078 curptr = (record *) (ptr + complen);
1079 antype = ntohs (curptr->type);
1080 anclass = ntohs (curptr->complen);
1081 ansize = ntohs (curptr->size);
1082 /* Class must be internet */
1083 if (anclass != ns_c_in)
1084 continue;
1085
1086 curptr->complen = complen;
1087 if ((namelen1 = dn_length1 (msg, eomsg, curptr-> name())) <= 0)
1088 goto corrupted;
1089
0a20e5a0 1090 if (antype == ns_t_cname)
6f57cb4a
CV
1091 {
1092 alias_count++;
1093 string_size += namelen1;
1094 }
1095 else if (antype == type)
1096 {
1097 ansize = ntohs (curptr->size);
1098 if (ansize != addrsize_in)
1099 continue;
1100 if (address_count == 0)
1101 {
1102 address_len = namelen1;
1103 string_size += namelen1;
1104 }
1105 else if (address_len != namelen1)
1106 continue;
1107 address_count++;
1108 }
1109 /* Update the records */
1110 curptr->type = antype; /* Host byte order */
1111 curptr->namelen1 = namelen1;
1112 if (! anptr)
1113 anptr = prevptr = curptr;
1114 else
1115 {
1116 prevptr->set_next (curptr);
1117 prevptr = curptr;
1118 }
1119 }
1120
1121 /* If there is no address, quit */
1122 if (address_count == 0)
1123 {
1124 free (msg);
1125 h_errno = NO_DATA;
1126 return NULL;
1127 }
0a20e5a0 1128
6f57cb4a
CV
1129 /* Determine the total size */
1130 sz = DWORD_round (sizeof(hostent))
1131 + sizeof (char *) * (alias_count + address_count + 2)
1132 + string_size
1133 + address_count * addrsize_out;
1134
1135 ret = realloc_ent (sz, (hostent *) NULL);
0a20e5a0 1136 if (! ret)
6f57cb4a
CV
1137 {
1138 old_errno = errno;
1139 free (msg);
1140 set_errno (old_errno);
1141 h_errno = NETDB_INTERNAL;
1142 return NULL;
1143 }
1144
1145 ret->h_addrtype = af;
1146 ret->h_length = addrsize_out;
1147 ret->h_aliases = (char **) (((char *) ret) + DWORD_round (sizeof(hostent)));
1148 ret->h_addr_list = ret->h_aliases + alias_count + 1;
1149 string_ptr = (char *) (ret->h_addr_list + address_count + 1);
0a20e5a0 1150
6f57cb4a 1151 /* Rescan the answers */
6f57cb4a 1152 alias_count = address_count = 0;
927761a4 1153 prevptr->set_next (prevptr + 1);
6f57cb4a 1154
927761a4 1155 for (curptr = anptr; curptr <= prevptr; curptr = curptr->next ())
6f57cb4a
CV
1156 {
1157 antype = curptr->type;
0a20e5a0 1158 if (antype == ns_t_cname)
6f57cb4a 1159 {
927761a4 1160 dn_expand (msg, eomsg, curptr->name (), string_ptr, curptr->namelen1);
6f57cb4a 1161 ret->h_aliases[alias_count++] = string_ptr;
927761a4 1162 string_ptr += curptr->namelen1;
6f57cb4a 1163 }
927761a4
PH
1164 else
1165 {
1166 if (address_count == 0)
6f57cb4a 1167 {
64f8b4ca
CV
1168 dn_expand (msg, eomsg, curptr->name (), string_ptr,
1169 curptr->namelen1);
927761a4
PH
1170 ret->h_name = string_ptr;
1171 string_ptr += curptr->namelen1;
6f57cb4a 1172 }
927761a4
PH
1173 ret->h_addr_list[address_count++] = string_ptr;
1174 if (addrsize_in != addrsize_out)
64f8b4ca
CV
1175 {
1176 memcpy4to6 (string_ptr, curptr->data);
1177 ret->h_addrtype = AF_INET6;
1178 }
927761a4
PH
1179 else
1180 memcpy (string_ptr, curptr->data, addrsize_in);
1181 string_ptr += addrsize_out;
1182 }
6f57cb4a 1183 }
0a20e5a0 1184
6f57cb4a
CV
1185 free (msg);
1186
1187 ret->h_aliases[alias_count] = NULL;
1188 ret->h_addr_list[address_count] = NULL;
0a20e5a0 1189
6f57cb4a
CV
1190 return ret;
1191
64f8b4ca 1192corrupted:
6f57cb4a
CV
1193 free (msg);
1194 /* Hopefully message corruption errors are temporary.
1195 Should it be NO_RECOVERY ? */
1196 h_errno = TRY_AGAIN;
1197 return NULL;
6f57cb4a
CV
1198}
1199
f881942d 1200/* gethostbyname2: GNU extension */
6f57cb4a
CV
1201extern "C" struct hostent *
1202gethostbyname2 (const char *name, int af)
1203{
3f3bd101 1204 hostent *res = NULL;
6f57cb4a 1205
3f3bd101 1206 __try
6f57cb4a 1207 {
3f3bd101 1208 if (!(_res.options & RES_INIT))
64f8b4ca 1209 res_init();
3f3bd101 1210
64f8b4ca 1211 bool v4to6 = _res.options & RES_USE_INET6;
3f3bd101 1212 int type, addrsize_in, addrsize_out;
64f8b4ca 1213
3f3bd101
CV
1214 switch (af)
1215 {
1216 case AF_INET:
1217 addrsize_in = NS_INADDRSZ;
1218 addrsize_out = (v4to6) ? NS_IN6ADDRSZ : NS_INADDRSZ;
1219 type = ns_t_a;
1220 break;
1221 case AF_INET6:
1222 addrsize_in = addrsize_out = NS_IN6ADDRSZ;
1223 type = ns_t_aaaa;
1224 break;
1225 default:
1226 set_errno (EAFNOSUPPORT);
1227 h_errno = NETDB_INTERNAL;
1228 __leave;
1229 }
0a20e5a0 1230
64f8b4ca
CV
1231 h_errno = NETDB_SUCCESS;
1232 res = gethostby_specials (name, af, addrsize_in, addrsize_out);
1233 if ((res == NULL) && (h_errno == NETDB_SUCCESS))
1234 res = gethostby_helper (name, af, type, addrsize_in, addrsize_out);
3f3bd101
CV
1235 }
1236 __except (EFAULT) {}
1237 __endtry
1238 return res;
6f57cb4a
CV
1239}
1240
f881942d 1241/* exported as accept: POSIX.1-2001, POSIX.1-2008, SVr4, 4.4BSD */
4e6a4ea8 1242extern "C" int
78db7dff 1243cygwin_accept (int fd, struct sockaddr *peer, socklen_t *len)
1fd5e000 1244{
3f3bd101 1245 int res = -1;
0a642325 1246
61522196
CV
1247 pthread_testcancel ();
1248
3f3bd101
CV
1249 __try
1250 {
1251 fhandler_socket *fh = get (fd);
1252 if (fh)
1253 res = fh->accept4 (peer, len,
1254 fh->is_nonblocking () ? SOCK_NONBLOCK : 0);
1255 }
1256 __except (EFAULT) {}
1257 __endtry
b9aa8149 1258 syscall_printf ("%R = accept(%d, %p, %p)", res, fd, peer, len);
1fd5e000
CF
1259 return res;
1260}
1261
f881942d 1262/* accept4: GNU extension */
0d653155
CV
1263extern "C" int
1264accept4 (int fd, struct sockaddr *peer, socklen_t *len, int flags)
1265{
3f3bd101 1266 int res = -1;
0d653155 1267
61522196
CV
1268 pthread_testcancel ();
1269
3f3bd101 1270 __try
0d653155 1271 {
3f3bd101
CV
1272 fhandler_socket *fh = get (fd);
1273 if (!fh)
1274 __leave;
1275 if ((flags & ~(SOCK_NONBLOCK | SOCK_CLOEXEC)) != 0)
1276 set_errno (EINVAL);
1277 else
1278 res = fh->accept4 (peer, len, flags);
0d653155 1279 }
3f3bd101
CV
1280 __except (EFAULT) {}
1281 __endtry
61522196 1282 syscall_printf ("%R = accept4(%d, %p, %p, %y)", res, fd, peer, len, flags);
0d653155
CV
1283 return res;
1284}
1285
f881942d 1286/* exported as bind: POSIX.1-2001, POSIX.1-2008, SVr4, 4.4BSD */
4e6a4ea8 1287extern "C" int
78db7dff 1288cygwin_bind (int fd, const struct sockaddr *my_addr, socklen_t addrlen)
1fd5e000 1289{
3f3bd101 1290 int res = -1;
1fd5e000 1291
3f3bd101
CV
1292 __try
1293 {
1294 fhandler_socket *fh = get (fd);
1295 if (fh)
1296 res = fh->bind (my_addr, addrlen);
1297 }
1298 __except (EFAULT) {}
1299 __endtry
b9aa8149 1300 syscall_printf ("%R = bind(%d, %p, %d)", res, fd, my_addr, addrlen);
1fd5e000
CF
1301 return res;
1302}
1303
f881942d 1304/* exported as getsockname: POSIX.1-2001, POSIX.1-2008, SVr4, 4.4BSD */
4e6a4ea8 1305extern "C" int
78db7dff 1306cygwin_getsockname (int fd, struct sockaddr *addr, socklen_t *namelen)
1fd5e000 1307{
3f3bd101 1308 int res = -1;
be5007aa 1309
3f3bd101
CV
1310 __try
1311 {
1312 fhandler_socket *fh = get (fd);
1313 if (fh)
1314 res = fh->getsockname (addr, namelen);
1315 }
1316 __except (EFAULT) {}
1317 __endtry
b9aa8149 1318 syscall_printf ("%R =getsockname (%d, %p, %p)", res, fd, addr, namelen);
1fd5e000
CF
1319 return res;
1320}
1321
f881942d 1322/* exported as listen: POSIX.1-2001, POSIX.1-2008, SVr4, 4.4BSD */
4e6a4ea8 1323extern "C" int
1fd5e000
CF
1324cygwin_listen (int fd, int backlog)
1325{
3f3bd101 1326 int res = -1;
1fd5e000 1327
3f3bd101
CV
1328 __try
1329 {
1330 fhandler_socket *fh = get (fd);
1331 if (fh)
1332 res = fh->listen (backlog);
1333 }
1334 __except (EFAULT) {}
1335 __endtry
b9aa8149 1336 syscall_printf ("%R = listen(%d, %d)", res, fd, backlog);
1fd5e000
CF
1337 return res;
1338}
1339
f881942d 1340/* exported as shutdown: POSIX.1-2001, POSIX.1-2008, SVr4, 4.4BSD */
4e6a4ea8 1341extern "C" int
1fd5e000
CF
1342cygwin_shutdown (int fd, int how)
1343{
3f3bd101 1344 int res = -1;
0a642325 1345
be5007aa 1346 fhandler_socket *fh = get (fd);
3f3bd101 1347 if (fh)
be5007aa 1348 res = fh->shutdown (how);
b9aa8149 1349 syscall_printf ("%R = shutdown(%d, %d)", res, fd, how);
1fd5e000
CF
1350 return res;
1351}
1352
7d9688b7
CV
1353/* exported as hstrerror: BSD 4.3 */
1354extern "C" const char *
1355cygwin_hstrerror (int err)
1356{
1357 int i;
1358
1359 for (i = 0; host_errmap[i].e != 0; ++i)
1360 if (err == host_errmap[i].e)
1361 break;
1362
1363 return host_errmap[i].s;
1364}
1365
1366/* exported as herror: BSD 4.3 */
4e6a4ea8 1367extern "C" void
7d9688b7 1368cygwin_herror (const char *s)
1fd5e000 1369{
3f3bd101 1370 __try
7d9688b7 1371 {
3f3bd101
CV
1372 if (cygheap->fdtab.not_open (2))
1373 return;
7d9688b7 1374
3f3bd101
CV
1375 if (s)
1376 {
1377 write (2, s, strlen (s));
1378 write (2, ": ", 2);
1379 }
7d9688b7 1380
3f3bd101
CV
1381 const char *h_errstr = cygwin_hstrerror (h_errno);
1382
1383 if (!h_errstr)
1384 switch (h_errno)
1385 {
1386 case NETDB_INTERNAL:
1387 h_errstr = "Resolver internal error";
1388 break;
1389 case NETDB_SUCCESS:
1390 h_errstr = "Resolver error 0 (no error)";
1391 break;
1392 default:
1393 h_errstr = "Unknown resolver error";
1394 break;
1395 }
1396 write (2, h_errstr, strlen (h_errstr));
1397 write (2, "\n", 1);
1398 }
1399 __except (NO_ERROR) {}
1400 __endtry
1fd5e000
CF
1401}
1402
f881942d 1403/* exported as getpeername: POSIX.1-2001, POSIX.1-2008, SVr4, 4.4BSD */
4e6a4ea8 1404extern "C" int
78db7dff 1405cygwin_getpeername (int fd, struct sockaddr *name, socklen_t *len)
1fd5e000 1406{
3f3bd101
CV
1407 int res = -1;
1408 fhandler_socket *fh = NULL;
5a64d869 1409
3f3bd101
CV
1410 __try
1411 {
1412 fh = get (fd);
1413 if (fh)
1414 res = fh->getpeername (name, len);
1415 }
1416 __except (EFAULT) {}
1417 __endtry
b79018ee 1418 syscall_printf ("%R = getpeername(%d)", res, fd);
1fd5e000
CF
1419 return res;
1420}
1421
f881942d 1422/* exported as recv: POSIX.1-2001, POSIX.1-2008, SVr4, 4.4BSD */
61522196 1423extern "C" ssize_t
78db7dff 1424cygwin_recv (int fd, void *buf, size_t len, int flags)
1fd5e000 1425{
3f3bd101 1426 ssize_t res = -1;
61522196
CV
1427
1428 pthread_testcancel ();
291698e5 1429
3f3bd101
CV
1430 __try
1431 {
1432 fhandler_socket *fh = get (fd);
1433 if (fh)
1434 /* Originally we shortcircuited here if res == 0.
1435 Allow 0 bytes buffer. This is valid in POSIX and handled in
1436 fhandler_socket::recv_internal. If we shortcircuit, we fail
1437 to deliver valid error conditions. */
1438 res = fh->recvfrom (buf, len, flags, NULL, NULL);
1439 }
1440 __except (EFAULT) {}
1441 __endtry
61522196 1442 syscall_printf ("%lR = recv(%d, %p, %ld, %y)", res, fd, buf, len, flags);
291698e5 1443 return res;
1fd5e000
CF
1444}
1445
f881942d 1446/* exported as send: POSIX.1-2001, POSIX.1-2008, SVr4, 4.4BSD */
61522196 1447extern "C" ssize_t
78db7dff 1448cygwin_send (int fd, const void *buf, size_t len, int flags)
1fd5e000 1449{
3f3bd101 1450 ssize_t res = -1;
61522196
CV
1451
1452 pthread_testcancel ();
291698e5 1453
3f3bd101
CV
1454 __try
1455 {
1456 fhandler_socket *fh = get (fd);
1457 if (fh)
1458 res = fh->sendto (buf, len, flags, NULL, 0);
1459 }
1460 __except (EFAULT)
1461 __endtry
61522196 1462 syscall_printf ("%lR = send(%d, %p, %ld, %y)", res, fd, buf, len, flags);
291698e5 1463 return res;
1fd5e000
CF
1464}
1465
52b5a971
CV
1466/* Fill out an ifconf struct. */
1467
974163bc
CV
1468bool
1469get_adapters_addresses (PIP_ADAPTER_ADDRESSES *pa_ret, ULONG family)
bff43891
CV
1470{
1471 DWORD ret, size = 0;
1472 PIP_ADAPTER_ADDRESSES pa0 = NULL;
1473
974163bc
CV
1474 if (!pa_ret)
1475 return GetAdaptersAddresses (family, GAA_FLAG_INCLUDE_PREFIX
1476 | GAA_FLAG_INCLUDE_ALL_INTERFACES,
3e25449a 1477 NULL, NULL, &size);
bff43891
CV
1478 do
1479 {
974163bc
CV
1480 ret = GetAdaptersAddresses (family, GAA_FLAG_INCLUDE_PREFIX
1481 | GAA_FLAG_INCLUDE_ALL_INTERFACES,
bff43891
CV
1482 NULL, pa0, &size);
1483 if (ret == ERROR_BUFFER_OVERFLOW
1484 && !(pa0 = (PIP_ADAPTER_ADDRESSES) realloc (pa0, size)))
1485 break;
1486 }
1487 while (ret == ERROR_BUFFER_OVERFLOW);
3e25449a 1488 if (pa0)
bff43891 1489 {
3e25449a
CV
1490 if (ret != ERROR_SUCCESS)
1491 {
1492 free (pa0);
974163bc 1493 *pa_ret = NULL;
3e25449a
CV
1494 }
1495 else
974163bc 1496 *pa_ret = pa0;
3e25449a 1497 }
3e25449a 1498 return ret == ERROR_SUCCESS || (!pa_ret && ret == ERROR_BUFFER_OVERFLOW);
bff43891
CV
1499}
1500
34adefae 1501static in_addr_t
8e4a60b3
CV
1502get_routedst (DWORD if_index)
1503{
1504 PMIB_IPFORWARDTABLE pift;
1505 ULONG size = 0;
1506 if (GetIpForwardTable (NULL, &size, FALSE) == ERROR_INSUFFICIENT_BUFFER
1507 && (pift = (PMIB_IPFORWARDTABLE) alloca (size))
1508 && GetIpForwardTable (pift, &size, FALSE) == NO_ERROR)
1509 for (DWORD i = 0; i < pift->dwNumEntries; ++i)
1510 {
7b44665a 1511 if (pift->table[i].dwForwardIfIndex == if_index
8e4a60b3
CV
1512 && pift->table[i].dwForwardMask == INADDR_BROADCAST)
1513 return pift->table[i].dwForwardDest;
1514 }
1515 return INADDR_ANY;
1516}
1517
a71ecb55
CV
1518struct ifall {
1519 struct ifaddrs ifa_ifa;
1520 char ifa_name[IFNAMSIZ];
1521 struct sockaddr_storage ifa_addr;
1522 struct sockaddr_storage ifa_brddstaddr;
1523 struct sockaddr_storage ifa_netmask;
65231f41 1524 struct ifaddrs_hwdata ifa_hwdata;
a71ecb55
CV
1525};
1526
ea392307
CV
1527static unsigned int
1528get_flags (PIP_ADAPTER_ADDRESSES pap)
1529{
1530 unsigned int flags = IFF_UP;
1531 if (pap->IfType == IF_TYPE_SOFTWARE_LOOPBACK)
1532 flags |= IFF_LOOPBACK;
943c59e3
CV
1533 else if (pap->IfType == IF_TYPE_PPP
1534 || pap->IfType == IF_TYPE_SLIP)
1535 flags |= IFF_POINTOPOINT | IFF_NOARP;
ea392307
CV
1536 if (!(pap->Flags & IP_ADAPTER_NO_MULTICAST))
1537 flags |= IFF_MULTICAST;
1538 if (pap->OperStatus == IfOperStatusUp
1539 || pap->OperStatus == IfOperStatusUnknown)
1540 flags |= IFF_RUNNING;
1541 if (pap->OperStatus != IfOperStatusLowerLayerDown)
1542 flags |= IFF_LOWER_UP;
1543 if (pap->OperStatus == IfOperStatusDormant)
1544 flags |= IFF_DORMANT;
1545 return flags;
1546}
1547
1548static ULONG
1549get_ipv4fromreg_ipcnt (const char *name)
1550{
cbc26145
CV
1551 WCHAR regkey[256], *c;
1552
1553 c = wcpcpy (regkey, L"Tcpip\\Parameters\\Interfaces\\");
1554 sys_mbstowcs (c, 220, name);
1555 if (!NT_SUCCESS (RtlCheckRegistryKey (RTL_REGISTRY_SERVICES, regkey)))
1556 return 0;
1557
ea392307 1558 ULONG ifs = 1;
cbc26145
CV
1559 DWORD dhcp = 0;
1560 UNICODE_STRING uipa = { 0, 0, NULL };
1561 RTL_QUERY_REGISTRY_TABLE tab[3] = {
1562 { NULL, RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_NOSTRING,
1563 L"EnableDHCP", &dhcp, REG_NONE, NULL, 0 },
1564 { NULL, RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_NOEXPAND,
1565 L"IPAddress", &uipa, REG_NONE, NULL, 0 },
1566 { NULL, 0, NULL, NULL, 0, NULL, 0 }
1567 };
ea392307 1568
ea392307 1569 /* If DHCP is used, we have only one address. */
cbc26145
CV
1570 if (NT_SUCCESS (RtlQueryRegistryValues (RTL_REGISTRY_SERVICES, regkey, tab,
1571 NULL, NULL))
1572 && uipa.Buffer)
ea392307 1573 {
cbc26145
CV
1574 if (dhcp == 0)
1575 for (ifs = 0, c = uipa.Buffer; *c; c += wcslen (c) + 1)
ea392307 1576 ifs++;
cbc26145 1577 RtlFreeUnicodeString (&uipa);
ea392307 1578 }
ea392307
CV
1579 return ifs;
1580}
1581
1582static void
1583get_ipv4fromreg (struct ifall *ifp, const char *name, DWORD idx)
1584{
cbc26145 1585 WCHAR regkey[256], *c;
b88d686a 1586 bool got_addr = false, got_mask = false;
cbc26145
CV
1587
1588 c = wcpcpy (regkey, L"Tcpip\\Parameters\\Interfaces\\");
1589 sys_mbstowcs (c, 220, name);
1590 if (!NT_SUCCESS (RtlCheckRegistryKey (RTL_REGISTRY_SERVICES, regkey)))
1591 return;
1592
1593 ULONG ifs;
1594 DWORD dhcp = 0;
1595 UNICODE_STRING udipa = { 0, 0, NULL };
1596 UNICODE_STRING udsub = { 0, 0, NULL };
1597 UNICODE_STRING uipa = { 0, 0, NULL };
1598 UNICODE_STRING usub = { 0, 0, NULL };
1599 RTL_QUERY_REGISTRY_TABLE tab[6] = {
1600 { NULL, RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_NOSTRING,
1601 L"EnableDHCP", &dhcp, REG_NONE, NULL, 0 },
1602 { NULL, RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_NOEXPAND,
1603 L"DhcpIPAddress", &udipa, REG_NONE, NULL, 0 },
1604 { NULL, RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_NOEXPAND,
1605 L"DhcpSubnetMask", &udsub, REG_NONE, NULL, 0 },
1606 { NULL, RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_NOEXPAND,
1607 L"IPAddress", &uipa, REG_NONE, NULL, 0 },
1608 { NULL, RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_NOEXPAND,
1609 L"SubnetMask", &usub, REG_NONE, NULL, 0 },
1610 { NULL, 0, NULL, NULL, 0, NULL, 0 }
1611 };
1612
1613 if (NT_SUCCESS (RtlQueryRegistryValues (RTL_REGISTRY_SERVICES, regkey, tab,
1614 NULL, NULL)))
ea392307 1615 {
cbc26145
CV
1616# define addr ((struct sockaddr_in *) &ifp->ifa_addr)
1617# define mask ((struct sockaddr_in *) &ifp->ifa_netmask)
1618# define brdc ((struct sockaddr_in *) &ifp->ifa_brddstaddr)
1619# define inet_uton(u, a) \
1620 { \
1621 char t[64]; \
1622 sys_wcstombs (t, 64, (u)); \
dff3bc9a 1623 cygwin_inet_pton (AF_INET, t, (a)); \
cbc26145
CV
1624 }
1625 /* If DHCP is used, we have only one address. */
ea392307
CV
1626 if (dhcp)
1627 {
cbc26145 1628 if (udipa.Buffer)
b88d686a
KB
1629 {
1630 inet_uton (udipa.Buffer, &addr->sin_addr);
1631 got_addr = true;
1632 }
cbc26145 1633 if (udsub.Buffer)
b88d686a
KB
1634 {
1635 inet_uton (udsub.Buffer, &mask->sin_addr);
1636 got_mask = true;
1637 }
ea392307
CV
1638 }
1639 else
1640 {
cbc26145 1641 if (uipa.Buffer)
ea392307 1642 {
cbc26145
CV
1643 for (ifs = 0, c = uipa.Buffer; *c && ifs < idx;
1644 c += wcslen (c) + 1)
ea392307
CV
1645 ifs++;
1646 if (*c)
b88d686a
KB
1647 {
1648 inet_uton (c, &addr->sin_addr);
1649 got_addr = true;
1650 }
ea392307 1651 }
cbc26145 1652 if (usub.Buffer)
ea392307 1653 {
cbc26145
CV
1654 for (ifs = 0, c = usub.Buffer; *c && ifs < idx;
1655 c += wcslen (c) + 1)
ea392307
CV
1656 ifs++;
1657 if (*c)
b88d686a
KB
1658 {
1659 inet_uton (c, &mask->sin_addr);
1660 got_mask = true;
1661 }
ea392307
CV
1662 }
1663 }
b88d686a
KB
1664 if (got_addr)
1665 ifp->ifa_ifa.ifa_addr = (struct sockaddr *) addr;
1666 if (got_mask)
1667 ifp->ifa_ifa.ifa_netmask = (struct sockaddr *) mask;
ea392307
CV
1668 if (ifp->ifa_ifa.ifa_flags & IFF_BROADCAST)
1669 brdc->sin_addr.s_addr = (addr->sin_addr.s_addr
1670 & mask->sin_addr.s_addr)
1671 | ~mask->sin_addr.s_addr;
1672#undef addr
1673#undef mask
1674#undef brdc
cbc26145
CV
1675#undef inet_uton
1676 if (udipa.Buffer)
1677 RtlFreeUnicodeString (&udipa);
1678 if (udsub.Buffer)
1679 RtlFreeUnicodeString (&udsub);
1680 if (uipa.Buffer)
1681 RtlFreeUnicodeString (&uipa);
1682 if (usub.Buffer)
1683 RtlFreeUnicodeString (&usub);
ea392307 1684 }
ea392307
CV
1685}
1686
1687static void
1688get_friendlyname (struct ifall *ifp, PIP_ADAPTER_ADDRESSES pap)
1689{
1690 struct ifreq_frndlyname *iff = (struct ifreq_frndlyname *)
65231f41 1691 &ifp->ifa_hwdata.ifa_frndlyname;
ea392307
CV
1692 iff->ifrf_len = sys_wcstombs (iff->ifrf_friendlyname,
1693 IFRF_FRIENDLYNAMESIZ,
ef750173 1694 pap->FriendlyName) + 1;
ea392307
CV
1695}
1696
1697static void
1698get_hwaddr (struct ifall *ifp, PIP_ADAPTER_ADDRESSES pap)
1699{
1700 for (UINT i = 0; i < IFHWADDRLEN; ++i)
1701 if (i >= pap->PhysicalAddressLength)
65231f41 1702 ifp->ifa_hwdata.ifa_hwaddr.sa_data[i] = '\0';
ea392307 1703 else
65231f41 1704 ifp->ifa_hwdata.ifa_hwaddr.sa_data[i] = pap->PhysicalAddress[i];
ea392307 1705}
61522196 1706
bff43891 1707/*
61522196 1708 * Get network interfaces. Use IP Helper function GetAdaptersAddresses.
bff43891 1709 */
a71ecb55 1710static struct ifall *
61522196 1711get_ifs (ULONG family)
bff43891
CV
1712{
1713 PIP_ADAPTER_ADDRESSES pa0 = NULL, pap;
1714 PIP_ADAPTER_UNICAST_ADDRESS pua;
bff43891 1715 int cnt = 0;
a71ecb55
CV
1716 struct ifall *ifret = NULL, *ifp;
1717 struct sockaddr_in *if_sin;
1718 struct sockaddr_in6 *if_sin6;
bff43891 1719
a71ecb55 1720 if (!get_adapters_addresses (&pa0, family))
bff43891 1721 goto done;
510a85cb 1722
bff43891 1723 for (pap = pa0; pap; pap = pap->Next)
ea392307
CV
1724 if (!pap->FirstUnicastAddress)
1725 {
1726 /* FirstUnicastAddress is NULL for interfaces which are disconnected.
d3920e10 1727 Fetch number of configured IPv4 addresses from registry and
ea392307
CV
1728 store in an unused member of the adapter addresses structure. */
1729 pap->Ipv6IfIndex = get_ipv4fromreg_ipcnt (pap->AdapterName);
1730 cnt += pap->Ipv6IfIndex;
1731 }
1732 else for (pua = pap->FirstUnicastAddress; pua; pua = pua->Next)
bff43891 1733 ++cnt;
510a85cb 1734
a71ecb55
CV
1735 if (!(ifret = (struct ifall *) calloc (cnt, sizeof (struct ifall))))
1736 goto done;
1737 ifp = ifret;
1738
bff43891
CV
1739 for (pap = pa0; pap; pap = pap->Next)
1740 {
ea392307
CV
1741 DWORD idx = 0;
1742 if (!pap->FirstUnicastAddress)
1743 for (idx = 0; idx < pap->Ipv6IfIndex; ++idx)
1744 {
1745 /* Next in chain */
1746 ifp->ifa_ifa.ifa_next = (struct ifaddrs *) &ifp[1].ifa_ifa;
1747 /* Interface name */
ba763af5 1748
fee7b24b 1749 if (idx)
ea392307
CV
1750 __small_sprintf (ifp->ifa_name, "%s:%u", pap->AdapterName, idx);
1751 else
1752 strcpy (ifp->ifa_name, pap->AdapterName);
1753 ifp->ifa_ifa.ifa_name = ifp->ifa_name;
1754 /* Flags */
1755 ifp->ifa_ifa.ifa_flags = get_flags (pap);
943c59e3
CV
1756 if (pap->IfType != IF_TYPE_PPP
1757 && pap->IfType != IF_TYPE_SOFTWARE_LOOPBACK)
ea392307
CV
1758 ifp->ifa_ifa.ifa_flags |= IFF_BROADCAST;
1759 /* Address */
1760 ifp->ifa_addr.ss_family = AF_INET;
b88d686a 1761 ifp->ifa_ifa.ifa_addr = NULL;
ea392307
CV
1762 /* Broadcast/Destination address */
1763 ifp->ifa_brddstaddr.ss_family = AF_INET;
1764 ifp->ifa_ifa.ifa_dstaddr = NULL;
1765 /* Netmask */
1766 ifp->ifa_netmask.ss_family = AF_INET;
b88d686a 1767 ifp->ifa_ifa.ifa_netmask = NULL;
ea392307
CV
1768 /* Try to fetch real IPv4 address information from registry. */
1769 get_ipv4fromreg (ifp, pap->AdapterName, idx);
1770 /* Hardware address */
1771 get_hwaddr (ifp, pap);
1772 /* Metric */
65231f41 1773 ifp->ifa_hwdata.ifa_metric = 1;
ea392307 1774 /* MTU */
65231f41 1775 ifp->ifa_hwdata.ifa_mtu = pap->Mtu;
ea392307 1776 /* Interface index */
65231f41 1777 ifp->ifa_hwdata.ifa_ifindex = pap->IfIndex;
ea392307
CV
1778 /* Friendly name */
1779 get_friendlyname (ifp, pap);
65231f41
CV
1780 /* Let ifa_data member point to "ifaddrs_hwdata" data. */
1781 ifp->ifa_ifa.ifa_data = &ifp->ifa_hwdata;
ea392307
CV
1782 ++ifp;
1783 }
1784 else
bdcc0b84 1785 for (idx = 0, pua = pap->FirstUnicastAddress; pua; pua = pua->Next)
ea392307
CV
1786 {
1787 struct sockaddr *sa = (struct sockaddr *) pua->Address.lpSockaddr;
a71ecb55
CV
1788# define sin ((struct sockaddr_in *) sa)
1789# define sin6 ((struct sockaddr_in6 *) sa)
ea392307
CV
1790 size_t sa_size = (sa->sa_family == AF_INET6
1791 ? sizeof *sin6 : sizeof *sin);
1792 /* Next in chain */
1793 ifp->ifa_ifa.ifa_next = (struct ifaddrs *) &ifp[1].ifa_ifa;
1794 /* Interface name */
fee7b24b 1795 if (sa->sa_family == AF_INET && idx)
ea392307 1796 __small_sprintf (ifp->ifa_name, "%s:%u", pap->AdapterName, idx);
a71ecb55 1797 else
ea392307 1798 strcpy (ifp->ifa_name, pap->AdapterName);
bdcc0b84
CV
1799 if (sa->sa_family == AF_INET)
1800 ++idx;
ea392307
CV
1801 ifp->ifa_ifa.ifa_name = ifp->ifa_name;
1802 /* Flags */
1803 ifp->ifa_ifa.ifa_flags = get_flags (pap);
1804 if (sa->sa_family == AF_INET
1805 && pap->IfType != IF_TYPE_SOFTWARE_LOOPBACK
1806 && pap->IfType != IF_TYPE_PPP)
1807 ifp->ifa_ifa.ifa_flags |= IFF_BROADCAST;
ea392307
CV
1808 /* Address */
1809 memcpy (&ifp->ifa_addr, sa, sa_size);
1810 ifp->ifa_ifa.ifa_addr = (struct sockaddr *) &ifp->ifa_addr;
1811 /* Netmask */
a7595584 1812 int prefix = pua->OnLinkPrefixLength;
ea392307
CV
1813 switch (sa->sa_family)
1814 {
1815 case AF_INET:
1816 if_sin = (struct sockaddr_in *) &ifp->ifa_netmask;
1817 if_sin->sin_addr.s_addr = htonl (UINT32_MAX << (32 - prefix));
1818 if_sin->sin_family = AF_INET;
1819 break;
1820 case AF_INET6:
1821 if_sin6 = (struct sockaddr_in6 *) &ifp->ifa_netmask;
e0f53cfe
CV
1822 for (cnt = 0; cnt < 4 && prefix > 0; ++cnt, prefix -= 32)
1823 {
1824 if_sin6->sin6_addr.s6_addr32[cnt] = UINT32_MAX;
1825 if (prefix < 32)
1826 if_sin6->sin6_addr.s6_addr32[cnt] <<= 32 - prefix;
1827 }
c08ee10d 1828 if_sin6->sin6_family = AF_INET6;
ea392307
CV
1829 break;
1830 }
1831 ifp->ifa_ifa.ifa_netmask = (struct sockaddr *) &ifp->ifa_netmask;
1832 if (pap->IfType == IF_TYPE_PPP)
1833 {
1834 /* Destination address */
1835 if (sa->sa_family == AF_INET)
1836 {
1837 if_sin = (struct sockaddr_in *) &ifp->ifa_brddstaddr;
1838 if_sin->sin_addr.s_addr = get_routedst (pap->IfIndex);
1839 if_sin->sin_family = AF_INET;
1840 }
1841 else
1842 /* FIXME: No official way to get the dstaddr for ipv6? */
1843 memcpy (&ifp->ifa_addr, sa, sa_size);
1844 ifp->ifa_ifa.ifa_dstaddr = (struct sockaddr *)
1845 &ifp->ifa_brddstaddr;
1846 }
1847 else
1848 {
1849 /* Broadcast address */
1850 if (sa->sa_family == AF_INET)
1851 {
1852 if_sin = (struct sockaddr_in *) &ifp->ifa_brddstaddr;
1853 uint32_t mask =
1854 ((struct sockaddr_in *) &ifp->ifa_netmask)->sin_addr.s_addr;
1855 if_sin->sin_addr.s_addr = (sin->sin_addr.s_addr & mask)
1856 | ~mask;
1857 if_sin->sin_family = AF_INET;
1858 ifp->ifa_ifa.ifa_broadaddr = (struct sockaddr *)
1859 &ifp->ifa_brddstaddr;
1860 }
1861 else /* No IPv6 broadcast */
1862 ifp->ifa_ifa.ifa_broadaddr = NULL;
1863 }
1864 /* Hardware address */
1865 get_hwaddr (ifp, pap);
1866 /* Metric */
a7595584
CV
1867 ifp->ifa_hwdata.ifa_metric = (sa->sa_family == AF_INET
1868 ? pap->Ipv4Metric : pap->Ipv6Metric);
ea392307 1869 /* MTU */
65231f41 1870 ifp->ifa_hwdata.ifa_mtu = pap->Mtu;
ea392307 1871 /* Interface index */
65231f41 1872 ifp->ifa_hwdata.ifa_ifindex = pap->IfIndex;
ea392307
CV
1873 /* Friendly name */
1874 get_friendlyname (ifp, pap);
65231f41
CV
1875 /* Let ifa_data member point to "ifaddrs_hwdata" data. */
1876 ifp->ifa_ifa.ifa_data = &ifp->ifa_hwdata;
ea392307 1877 ++ifp;
a71ecb55
CV
1878# undef sin
1879# undef sin6
ea392307 1880 }
bff43891 1881 }
a71ecb55
CV
1882 /* Since every entry is set to the next entry, the last entry points to an
1883 invalid next entry now. Fix it retroactively. */
1884 if (ifp > ifret)
1885 ifp[-1].ifa_ifa.ifa_next = NULL;
bff43891
CV
1886
1887done:
1888 if (pa0)
1889 free (pa0);
a71ecb55 1890 return ifret;
bff43891
CV
1891}
1892
a71ecb55
CV
1893extern "C" int
1894getifaddrs (struct ifaddrs **ifap)
1895{
1896 if (!ifap)
1897 {
1898 set_errno (EINVAL);
1899 return -1;
1900 }
1901 struct ifall *ifp;
61522196 1902 ifp = get_ifs (AF_UNSPEC);
a71ecb55
CV
1903 *ifap = &ifp->ifa_ifa;
1904 return ifp ? 0 : -1;
7326d4e4 1905}
1fd5e000 1906
a71ecb55
CV
1907extern "C" void
1908freeifaddrs (struct ifaddrs *ifp)
7326d4e4 1909{
a71ecb55
CV
1910 if (ifp)
1911 free (ifp);
1912}
1fd5e000 1913
a71ecb55
CV
1914int
1915get_ifconf (struct ifconf *ifc, int what)
1916{
3f3bd101 1917 __try
7326d4e4 1918 {
3f3bd101
CV
1919 /* Ensure we have space for at least one struct ifreqs, fail if not. */
1920 if (ifc->ifc_len < (int) sizeof (struct ifreq))
1921 {
1922 set_errno (EINVAL);
1923 __leave;
1924 }
1fd5e000 1925
3f3bd101
CV
1926 struct ifall *ifret, *ifp;
1927 ifret = get_ifs (AF_INET);
1928 if (!ifret)
1929 __leave;
a71ecb55 1930
3f3bd101
CV
1931 struct sockaddr_in *sin;
1932 struct ifreq *ifr = ifc->ifc_req;
1933 int cnt = 0;
1934 for (ifp = ifret; ifp; ifp = (struct ifall *) ifp->ifa_ifa.ifa_next)
7b44665a 1935 {
3f3bd101
CV
1936 ++cnt;
1937 strcpy (ifr->ifr_name, ifp->ifa_name);
1938 switch (what)
a71ecb55 1939 {
3f3bd101
CV
1940 case SIOCGIFFLAGS:
1941 ifr->ifr_flags = ifp->ifa_ifa.ifa_flags;
1942 break;
1943 case SIOCGIFCONF:
1944 case SIOCGIFADDR:
1945 sin = (struct sockaddr_in *) &ifr->ifr_addr;
1946 memcpy (sin, &ifp->ifa_addr, sizeof *sin);
1947 break;
1948 case SIOCGIFNETMASK:
1949 sin = (struct sockaddr_in *) &ifr->ifr_netmask;
1950 memcpy (sin, &ifp->ifa_netmask, sizeof *sin);
1951 break;
1952 case SIOCGIFDSTADDR:
1953 sin = (struct sockaddr_in *) &ifr->ifr_dstaddr;
1954 if (ifp->ifa_ifa.ifa_flags & IFF_POINTOPOINT)
1955 memcpy (sin, &ifp->ifa_brddstaddr, sizeof *sin);
1956 else /* Return addr as on Linux. */
1957 memcpy (sin, &ifp->ifa_addr, sizeof *sin);
1958 break;
1959 case SIOCGIFBRDADDR:
1960 sin = (struct sockaddr_in *) &ifr->ifr_broadaddr;
1961 if (!(ifp->ifa_ifa.ifa_flags & IFF_POINTOPOINT))
1962 memcpy (sin, &ifp->ifa_brddstaddr, sizeof *sin);
1963 else
1964 {
1965 sin->sin_addr.s_addr = INADDR_ANY;
1966 sin->sin_family = AF_INET;
1967 sin->sin_port = 0;
1968 }
1969 break;
1970 case SIOCGIFHWADDR:
65231f41 1971 memcpy (&ifr->ifr_hwaddr, &ifp->ifa_hwdata.ifa_hwaddr,
3f3bd101
CV
1972 sizeof ifr->ifr_hwaddr);
1973 break;
1974 case SIOCGIFMETRIC:
65231f41 1975 ifr->ifr_metric = ifp->ifa_hwdata.ifa_metric;
3f3bd101
CV
1976 break;
1977 case SIOCGIFMTU:
65231f41 1978 ifr->ifr_mtu = ifp->ifa_hwdata.ifa_mtu;
3f3bd101
CV
1979 break;
1980 case SIOCGIFINDEX:
65231f41 1981 ifr->ifr_ifindex = ifp->ifa_hwdata.ifa_ifindex;
3f3bd101
CV
1982 break;
1983 case SIOCGIFFRNDLYNAM:
65231f41 1984 memcpy (ifr->ifr_frndlyname, &ifp->ifa_hwdata.ifa_frndlyname,
3f3bd101 1985 sizeof (struct ifreq_frndlyname));
a71ecb55 1986 }
3f3bd101
CV
1987 if ((caddr_t) ++ifr >
1988 ifc->ifc_buf + ifc->ifc_len - sizeof (struct ifreq))
1989 break;
bcdf7421 1990 }
3f3bd101
CV
1991 /* Set the correct length */
1992 ifc->ifc_len = cnt * sizeof (struct ifreq);
1993 free (ifret);
1994 return 0;
1fd5e000 1995 }
3f3bd101
CV
1996 __except (EFAULT) {}
1997 __endtry
1998 return -1;
1fd5e000
CF
1999}
2000
bff43891 2001extern "C" unsigned
c356901f 2002cygwin_if_nametoindex (const char *name)
bff43891 2003{
b91d38db
TY
2004 PIP_ADAPTER_ADDRESSES pa0 = NULL, pap;
2005 if (get_adapters_addresses (&pa0, AF_UNSPEC))
2006 for (pap = pa0; pap; pap = pap->Next)
2007 if (strcmp (name, pap->AdapterName) == 0)
2008 {
2009 free (pa0);
2010 return pap->IfIndex;
2011 }
2012 if (pa0)
2013 free (pa0);
2014 return 0;
bff43891
CV
2015}
2016
2017extern "C" char *
c356901f 2018cygwin_if_indextoname (unsigned ifindex, char *ifname)
bff43891 2019{
b91d38db
TY
2020 if (ifindex == 0 || ifname == NULL)
2021 {
2022 set_errno (ENXIO);
2023 return NULL;
2024 }
2025 PIP_ADAPTER_ADDRESSES pa0 = NULL, pap;
2026 if (get_adapters_addresses (&pa0, AF_UNSPEC))
2027 for (pap = pa0; pap; pap = pap->Next)
2028 if (ifindex == pap->IfIndex)
2029 {
2030 strcpy (ifname, pap->AdapterName);
2031 free (pa0);
2032 return ifname;
2033 }
2034 if (pa0)
2035 free (pa0);
2036 set_errno (ENXIO);
2037 return NULL;
bff43891
CV
2038}
2039
2040extern "C" struct if_nameindex *
2041if_nameindex (void)
2042{
2043 PIP_ADAPTER_ADDRESSES pa0 = NULL, pap;
2044 struct if_nameindex *iflist = NULL;
2045 char (*ifnamelist)[IF_NAMESIZE];
2046
3f3bd101 2047 __try
bff43891 2048 {
3f3bd101 2049 if (get_adapters_addresses (&pa0, AF_UNSPEC))
510a85cb 2050 {
3f3bd101
CV
2051 int cnt = 0;
2052 for (pap = pa0; pap; pap = pap->Next)
2053 ++cnt;
2054 iflist = (struct if_nameindex *)
2055 malloc ((cnt + 1) * sizeof (struct if_nameindex)
2056 + cnt * IF_NAMESIZE);
2057 if (!iflist)
2058 set_errno (ENOBUFS);
2059 else
4b13fd15 2060 {
3f3bd101
CV
2061 ifnamelist = (char (*)[IF_NAMESIZE]) (iflist + cnt + 1);
2062 for (pap = pa0, cnt = 0; pap; pap = pap->Next)
2063 {
2064 for (int i = 0; i < cnt; ++i)
2065 if (iflist[i].if_index
2066 == (pap->Ipv6IfIndex ?: pap->IfIndex))
2067 goto outer_loop;
2068 iflist[cnt].if_index = pap->Ipv6IfIndex ?: pap->IfIndex;
2069 strcpy (iflist[cnt].if_name = ifnamelist[cnt],
2070 pap->AdapterName);
2071 /* See comment in if_indextoname. */
2072 if (pap->IfIndex == 1 && pap->Ipv6IfIndex == 0)
2073 for (PIP_ADAPTER_ADDRESSES pap2 = pa0;
2074 pap2;
2075 pap2 = pap2->Next)
2076 if (pap2->Ipv6IfIndex == 1)
2077 {
2078 strcpy (ifnamelist[cnt], pap2->AdapterName);
2079 break;
2080 }
2081 ++cnt;
2082 outer_loop:
2083 ;
2084 }
2085 iflist[cnt].if_index = 0;
2086 iflist[cnt].if_name = NULL;
4b13fd15 2087 }
3f3bd101 2088 free (pa0);
bff43891 2089 }
3f3bd101
CV
2090 else
2091 set_errno (ENXIO);
bff43891 2092 }
3f3bd101
CV
2093 __except (EFAULT) {}
2094 __endtry
4b13fd15 2095 return iflist;
bff43891
CV
2096}
2097
2098extern "C" void
2099if_freenameindex (struct if_nameindex *ptr)
2100{
bff43891
CV
2101 free (ptr);
2102}
2103
06a5dd43
CV
2104#define PORT_LOW (IPPORT_EFSSERVER + 1)
2105#define PORT_HIGH (IPPORT_RESERVED - 1)
2106#define NUM_PORTS (PORT_HIGH - PORT_LOW + 1)
2107
e9ff2d69
CV
2108/* port is in host byte order */
2109static in_port_t
2110next_free_port (sa_family_t family, in_port_t in_port)
2111{
2112 DWORD ret;
2113 ULONG size = 0;
2114 char *tab = NULL;
2115 PMIB_TCPTABLE tab4 = NULL;
2116 PMIB_TCP6TABLE tab6 = NULL;
2117
2118 /* Start testing with incoming port number. */
2119 in_port_t tst_port = in_port;
2120 in_port_t res_port = 0;
2121 in_port_t tab_port;
2122
2123 do
2124 {
2125 if (family == AF_INET)
2126 ret = GetTcpTable ((PMIB_TCPTABLE) tab, &size, TRUE);
2127 else
2128 ret = GetTcp6Table ((PMIB_TCP6TABLE) tab, &size, TRUE);
2129
2130 if (ret == ERROR_INSUFFICIENT_BUFFER)
2131 tab = (char *) realloc (tab, size);
2132 }
2133 while (ret == ERROR_INSUFFICIENT_BUFFER);
2134
2135 tab4 = (PMIB_TCPTABLE) tab;
2136 tab6 = (PMIB_TCP6TABLE) tab;
2137
2138 /* dwNumEntries has offset 0 in both structs. */
2139 for (int idx = tab4->dwNumEntries - 1; idx >= 0; --idx)
2140 {
2141 if (family == AF_INET)
2142 tab_port = ntohs (tab4->table[idx].dwLocalPort);
2143 else
2144 tab_port = ntohs (tab6->table[idx].dwLocalPort);
2145 /* Skip table entries with too high port number. */
2146 if (tab_port > tst_port)
2147 continue;
2148 /* Is the current port number free? */
2149 if (tab_port < tst_port)
2150 {
2151 res_port = tst_port;
2152 break;
2153 }
2154 /* Decrement port and handle underflow of the reserved area. */
2155 if (--tst_port < PORT_LOW)
2156 {
2157 tst_port = PORT_HIGH;
2158 idx = tab4->dwNumEntries;
2159 }
2160 /* Check if we're round to the incoming port. */
2161 if (tst_port == in_port)
2162 break;
2163 }
2164 free (tab);
2165 return res_port;
2166}
2167
4e6a4ea8 2168extern "C" int
70e476d2 2169cygwin_bindresvport_sa (int fd, struct sockaddr *sa)
1fd5e000 2170{
70e476d2
CV
2171 struct sockaddr_storage sst;
2172 struct sockaddr_in *sin = NULL;
2173 struct sockaddr_in6 *sin6 = NULL;
70e476d2 2174 socklen_t salen;
3f3bd101 2175 int ret = -1;
e9ff2d69 2176 LONG port, next_port;
70e476d2 2177
3f3bd101 2178 __try
06a5dd43 2179 {
3f3bd101
CV
2180 fhandler_socket *fh = get (fd);
2181 if (!fh)
2182 __leave;
06a5dd43 2183
3f3bd101
CV
2184 if (!sa)
2185 {
2186 sa = (struct sockaddr *) &sst;
2187 memset (&sst, 0, sizeof sst);
2188 sa->sa_family = fh->get_addr_family ();
2189 }
2f61f656
CV
2190 else if (sa->sa_family != fh->get_addr_family ())
2191 {
2192 set_errno (EPFNOSUPPORT);
2193 __leave;
2194 }
79224853 2195
3f3bd101
CV
2196 switch (sa->sa_family)
2197 {
2198 case AF_INET:
2199 salen = sizeof (struct sockaddr_in);
2200 sin = (struct sockaddr_in *) sa;
3f3bd101
CV
2201 break;
2202 case AF_INET6:
2203 salen = sizeof (struct sockaddr_in6);
2204 sin6 = (struct sockaddr_in6 *) sa;
3f3bd101
CV
2205 break;
2206 default:
2207 set_errno (EPFNOSUPPORT);
2208 __leave;
2209 }
df63bd49 2210
34f03198
CV
2211 /* Originally we tried to use the incoming port number first here,
2212 but that may lead to EADDRINUSE scenarios when calling bindresvport
2213 on the client side. So we ignore any port value that the caller
2214 supplies, just like glibc. */
70e476d2 2215
e9ff2d69
CV
2216 /* Note that repeating this loop NUM_PORTS times is arbitrary. The
2217 job is mainly done by next_free_port() but it doesn't cover bound
2218 sockets. And calling and checking GetTcpTable and subsequently
2219 calling bind is inevitably racy. We have to continue if bind fails
2220 with EADDRINUSE. */
3f3bd101
CV
2221 for (int i = 0; i < NUM_PORTS; i++)
2222 {
e9ff2d69 2223 while ((port = InterlockedExchange (
3f3bd101
CV
2224 &cygwin_shared->last_used_bindresvport, -1)) == -1)
2225 yield ();
e9ff2d69
CV
2226 next_port = port;
2227 if (next_port == 0 || --next_port < PORT_LOW)
2228 next_port = PORT_HIGH;
2229 /* Returns 0 if no reserved port is free. */
2230 next_port = next_free_port (sa->sa_family, next_port);
2231 if (next_port)
2232 port = next_port;
2233 InterlockedExchange (&cygwin_shared->last_used_bindresvport, port);
2234 if (next_port == 0)
2235 {
2236 set_errno (EADDRINUSE);
2237 break;
2238 }
3f3bd101 2239 if (sa->sa_family == AF_INET6)
e9ff2d69 2240 sin6->sin6_port = htons (port);
3f3bd101 2241 else
e9ff2d69 2242 sin->sin_port = htons (port);
3f3bd101
CV
2243 if (!(ret = fh->bind (sa, salen)))
2244 break;
2245 if (get_errno () != EADDRINUSE && get_errno () != EINVAL)
2246 break;
2247 }
df63bd49 2248
3f3bd101
CV
2249 }
2250 __except (EFAULT) {}
2251 __endtry
70e476d2
CV
2252 return ret;
2253}
2254
2255extern "C" int
2256cygwin_bindresvport (int fd, struct sockaddr_in *sin)
2257{
2f61f656
CV
2258 if (sin && sin->sin_family != AF_INET)
2259 {
2260 set_errno (EAFNOSUPPORT);
2261 return -1;
2262 }
70e476d2 2263 return cygwin_bindresvport_sa (fd, (struct sockaddr *) sin);
1fd5e000
CF
2264}
2265
4e04751f 2266/* socketpair: POSIX.1-2001, POSIX.1-2008, 4.4BSD. */
4e6a4ea8 2267extern "C" int
f4a1a186 2268socketpair (int af, int type, int protocol, int sv[2])
1fd5e000
CF
2269{
2270 int res = -1;
4e04751f 2271 const device *dev;
1e5e44a9 2272 fhandler_socket *fh_in, *fh_out;
1fd5e000 2273
4e04751f
CV
2274 int flags = type & _SOCK_FLAG_MASK;
2275 type &= ~_SOCK_FLAG_MASK;
dc63cea5 2276
4e04751f 2277 debug_printf ("socket (%d, %d (flags %y), %d)", af, type, flags, protocol);
1fd5e000 2278
4e04751f
CV
2279 switch (af)
2280 {
2281 case AF_LOCAL:
6c55be9d
CV
2282#ifndef __WITH_AF_UNIX
2283 dev = af_local_dev;
2284#else
7f7532fa 2285 case AF_UNIX:
7f7532fa 2286 dev = (af == AF_LOCAL) ? af_local_dev : af_unix_dev;
6c55be9d 2287#endif /* __WITH_AF_UNIX */
4e04751f 2288 break;
4e04751f
CV
2289 default:
2290 set_errno (EAFNOSUPPORT);
2291 goto done;
2292 }
3f3bd101 2293
4e04751f
CV
2294 if ((flags & ~(SOCK_NONBLOCK | SOCK_CLOEXEC)) != 0)
2295 {
2296 set_errno (EINVAL);
2297 goto done;
2298 }
1fd5e000 2299
4e04751f
CV
2300 {
2301 cygheap_fdnew fd_in;
2302 if (fd_in < 0)
2303 goto done;
518f5d49 2304
4e04751f
CV
2305 cygheap_fdnew fd_out (fd_in, false);
2306 if (fd_out < 0)
2bbe8697 2307 goto done;
518f5d49 2308
1e5e44a9
CV
2309 fh_in = reinterpret_cast<fhandler_socket *> (build_fh_dev (*dev));
2310 fh_out = reinterpret_cast<fhandler_socket *> (build_fh_dev (*dev));
4e04751f
CV
2311 if (fh_in && fh_out
2312 && fh_in->socketpair (af, type, protocol, flags, fh_out) == 0)
3f3bd101 2313 {
4e04751f
CV
2314 fd_in = fh_in;
2315 fd_out = fh_out;
2316 if (fd_in <= 2)
2317 set_std_handle (fd_in);
2318 if (fd_out <= 2)
2319 set_std_handle (fd_out);
2320 __try
3f3bd101 2321 {
f4a1a186
CV
2322 sv[0] = fd_in;
2323 sv[1] = fd_out;
4e04751f 2324 res = 0;
3f3bd101 2325 }
4e04751f
CV
2326 __except (EFAULT) {}
2327 __endtry
3f3bd101 2328 }
3f3bd101 2329 else
3f3bd101 2330 {
b995936a
CV
2331 delete fh_in;
2332 delete fh_out;
3f3bd101
CV
2333 }
2334 }
4e04751f
CV
2335
2336done:
3f3bd101 2337 syscall_printf ("%R = socketpair(...)", res);
1fd5e000
CF
2338 return res;
2339}
2340
f881942d 2341/* sethostent: POSIX.1-2001 */
dd4f0b23
CV
2342extern "C" void
2343sethostent (int)
2344{
2345}
2346
f881942d 2347/* endhostent: POSIX.1-2001 */
dd4f0b23
CV
2348extern "C" void
2349endhostent (void)
2350{
2351}
7d6be0d6 2352
f881942d 2353/* exported as recvmsg: POSIX.1-2001, POSIX.1-2008, 4.4BSD */
61522196 2354extern "C" ssize_t
b4f06520 2355cygwin_recvmsg (int fd, struct msghdr *msg, int flags)
be5007aa 2356{
3f3bd101 2357 ssize_t res = -1;
61522196
CV
2358
2359 pthread_testcancel ();
0a642325 2360
3f3bd101 2361 __try
4d147a03 2362 {
3f3bd101
CV
2363 fhandler_socket *fh = get (fd);
2364 if (fh)
2365 {
2366 res = check_iovec_for_read (msg->msg_iov, msg->msg_iovlen);
2367 /* Originally we shortcircuited here if res == 0.
2368 Allow 0 bytes buffer. This is valid in POSIX and handled in
2369 fhandler_socket::recv_internal. If we shortcircuit, we fail
2370 to deliver valid error conditions and peer address. */
2371 if (res >= 0)
2372 res = fh->recvmsg (msg, flags);
2373 }
4d147a03 2374 }
3f3bd101
CV
2375 __except (EFAULT)
2376 {
2377 res = -1;
2378 }
2379 __endtry
61522196 2380 syscall_printf ("%lR = recvmsg(%d, %p, %y)", res, fd, msg, flags);
b4f06520 2381 return res;
7d6be0d6
CV
2382}
2383
f881942d 2384/* exported as sendmsg: POSIX.1-2001, POSIX.1-2008, 4.4BSD */
61522196 2385extern "C" ssize_t
b4f06520 2386cygwin_sendmsg (int fd, const struct msghdr *msg, int flags)
be5007aa 2387{
3f3bd101 2388 ssize_t res = -1;
61522196
CV
2389
2390 pthread_testcancel ();
4d147a03 2391
3f3bd101 2392 __try
4d147a03 2393 {
3f3bd101
CV
2394 fhandler_socket *fh = get (fd);
2395 if (fh)
2396 {
2397 res = check_iovec_for_write (msg->msg_iov, msg->msg_iovlen);
2398 if (res >= 0)
2399 res = fh->sendmsg (msg, flags);
2400 }
4d147a03 2401 }
3f3bd101
CV
2402 __except (EFAULT)
2403 {
2404 res = -1;
2405 }
2406 __endtry
61522196 2407 syscall_printf ("%lR = sendmsg(%d, %p, %y)", res, fd, msg, flags);
b4f06520 2408 return res;
1c657740 2409}
b3ba5059 2410
70e476d2
CV
2411/* This is from the BIND 4.9.4 release, modified to compile by itself */
2412
2413/* Copyright (c) 1996 by Internet Software Consortium.
2414 *
2415 * Permission to use, copy, modify, and distribute this software for any
2416 * purpose with or without fee is hereby granted, provided that the above
2417 * copyright notice and this permission notice appear in all copies.
2418 *
2419 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
2420 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
2421 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
2422 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
2423 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
2424 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
2425 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
2426 * SOFTWARE.
2427 */
2428
70e476d2
CV
2429/* int
2430 * inet_pton4(src, dst)
2431 * like inet_aton() but without all the hexadecimal and shorthand.
2432 * return:
2433 * 1 if `src' is a valid dotted quad, else 0.
2434 * notice:
2435 * does not touch `dst' unless it's returning 1.
2436 * author:
2437 * Paul Vixie, 1996.
2438 */
2439static int
acc5f02c 2440inet_pton4 (const char *src, u_int8_t *dst)
70e476d2
CV
2441{
2442 static const char digits[] = "0123456789";
2443 int saw_digit, octets, ch;
acc5f02c 2444 u_int8_t tmp[INADDRSZ], *tp;
70e476d2
CV
2445
2446 saw_digit = 0;
2447 octets = 0;
2448 *(tp = tmp) = 0;
2449 while ((ch = *src++) != '\0')
2450 {
2451 const char *pch;
2452
2453 if ((pch = strchr(digits, ch)) != NULL)
510a85cb 2454 {
acc5f02c 2455 u_int32_t ret = *tp * 10 + (pch - digits);
70e476d2
CV
2456
2457 if (ret > 255)
2458 return (0);
2459 *tp = ret;
2460 if (! saw_digit)
2461 {
2462 if (++octets > 4)
2463 return (0);
2464 saw_digit = 1;
2465 }
2466 }
2467 else if (ch == '.' && saw_digit)
510a85cb 2468 {
70e476d2
CV
2469 if (octets == 4)
2470 return (0);
2471 *++tp = 0;
2472 saw_digit = 0;
2473 }
2474 else
2475 return (0);
2476 }
2477 if (octets < 4)
2478 return (0);
2479
2480 memcpy(dst, tmp, INADDRSZ);
2481 return (1);
2482}
2483
2484/* int
2485 * inet_pton6(src, dst)
2486 * convert presentation level address to network order binary form.
2487 * return:
2488 * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
2489 * notice:
2490 * (1) does not touch `dst' unless it's returning 1.
2491 * (2) :: in a full address is silently ignored.
2492 * credit:
2493 * inspired by Mark Andrews.
2494 * author:
2495 * Paul Vixie, 1996.
2496 */
2497static int
acc5f02c 2498inet_pton6 (const char *src, u_int8_t *dst)
70e476d2
CV
2499{
2500 static const char xdigits_l[] = "0123456789abcdef",
2501 xdigits_u[] = "0123456789ABCDEF";
acc5f02c 2502 u_int8_t tmp[IN6ADDRSZ], *tp, *endp, *colonp;
70e476d2
CV
2503 const char *xdigits, *curtok;
2504 int ch, saw_xdigit;
acc5f02c 2505 u_int32_t val;
70e476d2
CV
2506
2507 memset((tp = tmp), 0, IN6ADDRSZ);
2508 endp = tp + IN6ADDRSZ;
2509 colonp = NULL;
2510 /* Leading :: requires some special handling. */
2511 if (*src == ':')
2512 if (*++src != ':')
2513 return (0);
2514 curtok = src;
2515 saw_xdigit = 0;
2516 val = 0;
2517 while ((ch = *src++) != '\0')
2518 {
2519 const char *pch;
2520
2521 if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
2522 pch = strchr((xdigits = xdigits_u), ch);
2523 if (pch != NULL)
510a85cb 2524 {
70e476d2
CV
2525 val <<= 4;
2526 val |= (pch - xdigits);
2527 if (val > 0xffff)
2528 return (0);
2529 saw_xdigit = 1;
2530 continue;
2531 }
2532 if (ch == ':')
510a85cb 2533 {
70e476d2
CV
2534 curtok = src;
2535 if (!saw_xdigit)
2536 {
2537 if (colonp)
2538 return (0);
2539 colonp = tp;
2540 continue;
2541 }
2542 if (tp + INT16SZ > endp)
2543 return (0);
acc5f02c
CV
2544 *tp++ = (u_int8_t) (val >> 8) & 0xff;
2545 *tp++ = (u_int8_t) val & 0xff;
70e476d2
CV
2546 saw_xdigit = 0;
2547 val = 0;
2548 continue;
2549 }
2550 if (ch == '.' && ((tp + INADDRSZ) <= endp) && inet_pton4(curtok, tp) > 0)
510a85cb 2551 {
70e476d2
CV
2552 tp += INADDRSZ;
2553 saw_xdigit = 0;
2554 break; /* '\0' was seen by inet_pton4(). */
2555 }
2556 return (0);
2557 }
2558 if (saw_xdigit)
2559 {
2560 if (tp + INT16SZ > endp)
2561 return (0);
acc5f02c
CV
2562 *tp++ = (u_int8_t) (val >> 8) & 0xff;
2563 *tp++ = (u_int8_t) val & 0xff;
70e476d2
CV
2564 }
2565 if (colonp != NULL)
2566 {
2567 /*
2568 * Since some memmove()'s erroneously fail to handle
2569 * overlapping regions, we'll do the shift by hand.
2570 */
2571 const int n = tp - colonp;
2572 int i;
2573
2574 for (i = 1; i <= n; i++)
510a85cb 2575 {
70e476d2
CV
2576 endp[- i] = colonp[n - i];
2577 colonp[n - i] = 0;
2578 }
2579 tp = endp;
2580 }
2581 if (tp != endp)
2582 return (0);
2583
2584 memcpy(dst, tmp, IN6ADDRSZ);
2585 return (1);
2586}
2587
2588/* int
2589 * inet_pton(af, src, dst)
2590 * convert from presentation format (which usually means ASCII printable)
2591 * to network format (which is usually some kind of binary format).
2592 * return:
2593 * 1 if the address was valid for the specified address family
2594 * 0 if the address wasn't valid (`dst' is untouched in this case)
2595 * -1 if some other error occurred (`dst' is untouched in this case, too)
2596 * author:
2597 * Paul Vixie, 1996.
2598 */
b3ba5059 2599extern "C" int
70e476d2 2600cygwin_inet_pton (int af, const char *src, void *dst)
b3ba5059 2601{
70e476d2 2602 switch (af)
b3ba5059 2603 {
70e476d2 2604 case AF_INET:
acc5f02c 2605 return (inet_pton4(src, (u_int8_t *) dst));
70e476d2 2606 case AF_INET6:
acc5f02c 2607 return (inet_pton6(src, (u_int8_t *) dst));
70e476d2
CV
2608 default:
2609 errno = EAFNOSUPPORT;
2610 return (-1);
2611 }
2612 /* NOTREACHED */
2613}
2614
2615/* const char *
2616 * inet_ntop4(src, dst, size)
2617 * format an IPv4 address, more or less like inet_ntoa()
2618 * return:
2619 * `dst' (as a const)
2620 * notes:
2621 * (1) uses no statics
acc5f02c 2622 * (2) takes a u_int8_t* not an in_addr as input
70e476d2
CV
2623 * author:
2624 * Paul Vixie, 1996.
2625 */
2626static const char *
acc5f02c 2627inet_ntop4 (const u_int8_t *src, char *dst, size_t size)
70e476d2
CV
2628{
2629 static const char fmt[] = "%u.%u.%u.%u";
2630 char tmp[sizeof "255.255.255.255"];
2631
2632 __small_sprintf(tmp, fmt, src[0], src[1], src[2], src[3]);
2633 if (strlen(tmp) > size)
2634 {
2635 errno = ENOSPC;
2636 return (NULL);
2637 }
2638 strcpy(dst, tmp);
2639 return (dst);
2640}
2641
2642/* const char *
2643 * inet_ntop6(src, dst, size)
2644 * convert IPv6 binary address into presentation (printable) format
2645 * author:
2646 * Paul Vixie, 1996.
2647 */
2648static const char *
acc5f02c 2649inet_ntop6 (const u_int8_t *src, char *dst, size_t size)
70e476d2
CV
2650{
2651 /*
2652 * Note that int32_t and int16_t need only be "at least" large enough
2653 * to contain a value of the specified size. On some systems, like
2654 * Crays, there is no such thing as an integer variable with 16 bits.
2655 * Keep this in mind if you think this function should have been coded
2656 * to use pointer overlays. All the world's not a VAX.
2657 */
2658 char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
2659 struct { int base, len; } best, cur;
acc5f02c 2660 u_int32_t words[IN6ADDRSZ / INT16SZ];
70e476d2 2661 int i;
b3ba5059 2662
70e476d2
CV
2663 /*
2664 * Preprocess:
2665 * Copy the input (bytewise) array into a wordwise array.
2666 * Find the longest run of 0x00's in src[] for :: shorthanding.
2667 */
2668 memset(words, 0, sizeof words);
2669 for (i = 0; i < IN6ADDRSZ; i++)
2670 words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
2671 best.base = -1;
2672 cur.base = -1;
1809b65e
CF
2673 best.len = 0;
2674 cur.len = 0;
70e476d2
CV
2675 for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++)
2676 {
2677 if (words[i] == 0)
510a85cb 2678 {
70e476d2
CV
2679 if (cur.base == -1)
2680 cur.base = i, cur.len = 1;
2681 else
2682 cur.len++;
2683 }
2684 else
510a85cb 2685 {
70e476d2
CV
2686 if (cur.base != -1)
2687 {
2688 if (best.base == -1 || cur.len > best.len)
2689 best = cur;
2690 cur.base = -1;
2691 }
2692 }
2693 }
2694 if (cur.base != -1)
2695 {
2696 if (best.base == -1 || cur.len > best.len)
2697 best = cur;
2698 }
2699 if (best.base != -1 && best.len < 2)
2700 best.base = -1;
2701
2702 /*
2703 * Format the result.
2704 */
2705 tp = tmp;
2706 for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++)
2707 {
2708 /* Are we inside the best run of 0x00's? */
2709 if (best.base != -1 && i >= best.base && i < (best.base + best.len))
510a85cb 2710 {
70e476d2
CV
2711 if (i == best.base)
2712 *tp++ = ':';
2713 continue;
2714 }
2715 /* Are we following an initial run of 0x00s or any real hex? */
2716 if (i != 0)
2717 *tp++ = ':';
2718 /* Is this address an encapsulated IPv4? */
2719 if (i == 6 && best.base == 0 &&
2720 (best.len == 6 || (best.len == 5 && words[5] == 0xffff)))
1cd06583 2721 {
70e476d2
CV
2722 if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp)))
2723 return (NULL);
2724 tp += strlen(tp);
2725 break;
b3ba5059 2726 }
70e476d2 2727 __small_sprintf(tp, "%x", words[i]);
6f0c3cc8
CV
2728 while (*tp)
2729 {
2730 if (isupper (*tp))
2731 *tp = _tolower (*tp);
2732 ++tp;
2733 }
b3ba5059 2734 }
70e476d2
CV
2735 /* Was it a trailing run of 0x00's? */
2736 if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ))
2737 *tp++ = ':';
2738 *tp++ = '\0';
2739
2740 /*
2741 * Check for overflow, copy, and we're done.
2742 */
2743 if ((size_t) (tp - tmp) > size)
2744 {
2745 errno = ENOSPC;
2746 return (NULL);
2747 }
2748 strcpy(dst, tmp);
2749 return (dst);
b3ba5059
CV
2750}
2751
70e476d2
CV
2752/* char *
2753 * inet_ntop(af, src, dst, size)
2754 * convert a network format address to presentation format.
2755 * return:
2756 * pointer to presentation format address (`dst'), or NULL (see errno).
2757 * author:
2758 * Paul Vixie, 1996.
2759 */
b3ba5059 2760extern "C" const char *
70e476d2 2761cygwin_inet_ntop (int af, const void *src, char *dst, socklen_t size)
b3ba5059 2762{
70e476d2
CV
2763 switch (af)
2764 {
2765 case AF_INET:
acc5f02c 2766 return (inet_ntop4((const u_int8_t *) src, dst, size));
70e476d2 2767 case AF_INET6:
acc5f02c 2768 return (inet_ntop6((const u_int8_t *) src, dst, size));
70e476d2
CV
2769 default:
2770 errno = EAFNOSUPPORT;
2771 return (NULL);
2772 }
2773 /* NOTREACHED */
2774}
b3ba5059 2775
f881942d 2776/* Exported as freeaddrinfo: POSIX.1-2001, POSIX.1-2008, RFC 2553 */
5b56e9b0
CV
2777extern "C" void
2778cygwin_freeaddrinfo (struct addrinfo *addr)
70e476d2 2779{
5b56e9b0 2780 struct addrinfo *ai, *ainext;
70e476d2 2781
5b56e9b0 2782 for (ai = addr; ai != NULL; ai = ainext)
70e476d2 2783 {
5b56e9b0
CV
2784 if (ai->ai_addr != NULL)
2785 free (ai->ai_addr); /* socket address structure */
70e476d2 2786
5b56e9b0
CV
2787 if (ai->ai_canonname != NULL)
2788 free (ai->ai_canonname);
2789
2790 ainext = ai->ai_next; /* can't fetch ai_next after free() */
2791 free (ai); /* the addrinfo{} itself */
70e476d2 2792 }
70e476d2
CV
2793}
2794
70e476d2 2795static struct addrinfo *
5b56e9b0 2796ga_dup (struct addrinfoW *ai, bool v4mapped, int idn_flags, int &err)
70e476d2
CV
2797{
2798 struct addrinfo *nai;
2799
2800 if ((nai = (struct addrinfo *) calloc (1, sizeof (struct addrinfo))) == NULL)
5b56e9b0
CV
2801 {
2802 err = EAI_MEMORY;
2803 return NULL;
2804 }
70e476d2 2805
4815dd49 2806 nai->ai_family = v4mapped ? AF_INET6 : ai->ai_family;
70e476d2
CV
2807 nai->ai_socktype = ai->ai_socktype;
2808 nai->ai_protocol = ai->ai_protocol;
5b56e9b0 2809 if (ai->ai_canonname)
4815dd49 2810 {
5b56e9b0
CV
2811 tmp_pathbuf tp;
2812 wchar_t *canonname = ai->ai_canonname;
2813
2814 if (idn_flags & AI_CANONIDN)
2815 {
2816 /* Map flags to equivalent IDN_* flags. */
2817 wchar_t *canonbuf = tp.w_get ();
2818 if (IdnToUnicode (idn_flags >> 16, canonname, -1,
2819 canonbuf, NT_MAX_PATH))
2820 canonname = canonbuf;
2821 else if (GetLastError () != ERROR_PROC_NOT_FOUND)
2822 {
2823 free (nai);
2824 err = EAI_IDN_ENCODE;
2825 return NULL;
2826 }
2827 }
2828 size_t len = wcstombs (NULL, canonname, 0);
2829 if (len == (size_t) -1)
2830 {
2831 free (nai);
2832 err = EAI_IDN_ENCODE;
2833 return NULL;
2834 }
2835 nai->ai_canonname = (char *) malloc (len + 1);
2836 if (!nai->ai_canonname)
2837 {
2838 free (nai);
2839 err = EAI_MEMORY;
2840 return NULL;
2841 }
2842 wcstombs (nai->ai_canonname, canonname, len + 1);
4815dd49 2843 }
3bb346d5 2844
4815dd49
CV
2845 nai->ai_addrlen = v4mapped ? sizeof (struct sockaddr_in6) : ai->ai_addrlen;
2846 if ((nai->ai_addr = (struct sockaddr *) malloc (v4mapped
510a85cb 2847 ? sizeof (struct sockaddr_in6)
4815dd49
CV
2848 : ai->ai_addrlen)) == NULL)
2849 {
2850 if (nai->ai_canonname)
510a85cb 2851 free (nai->ai_canonname);
4815dd49 2852 free (nai);
5b56e9b0 2853 err = EAI_MEMORY;
4815dd49
CV
2854 return NULL;
2855 }
2856 if (v4mapped)
2857 {
2858 struct sockaddr_in6 *in = (struct sockaddr_in6 *) nai->ai_addr;
2859 in->sin6_family = AF_INET6;
2860 in->sin6_port = ((struct sockaddr_in *) ai->ai_addr)->sin_port;
2861 in->sin6_flowinfo = 0;
2862 in->sin6_addr.s6_addr32[0] = 0;
2863 in->sin6_addr.s6_addr32[1] = 0;
2864 in->sin6_addr.s6_addr32[2] = htonl (0xffff);
2865 in->sin6_addr.s6_addr32[3] = ((struct sockaddr_in *) ai->ai_addr)->sin_addr.s_addr;
2866 in->sin6_scope_id = 0;
2867 }
2868 else
2869 memcpy (nai->ai_addr, ai->ai_addr, ai->ai_addrlen);
2870
2871 return nai;
2872}
2873
2874static struct addrinfo *
5b56e9b0 2875ga_duplist (struct addrinfoW *ai, bool v4mapped, int idn_flags, int &err)
4815dd49 2876{
4815dd49
CV
2877 struct addrinfo *tmp, *nai = NULL, *nai0 = NULL;
2878
582c7f96
CV
2879 for (; ai; ai = ai->ai_next)
2880 {
2881 /* Workaround for a Windows weirdness. If a service is supported as
2882 TCP and UDP service, GetAddrInfo does not return two entries, one
2883 for TCP, one for UDP, as on Linux. Rather, it just returns a single
2884 entry with ai_socktype and ai_protocol set to 0, kind of like a
2885 placeholder. If the service only exists as TCP or UDP service, then
2886 ai->ai_socktype is set, but ai_protocol isn't. Fix up the fields,
2887 and in case ai_socktype and ai_protocol are 0 duplicate the entry
2888 with valid values for ai_socktype and ai_protocol. */
2889 switch (ai->ai_socktype)
2890 {
2891 case SOCK_STREAM:
2892 if (ai->ai_protocol == 0)
2893 ai->ai_protocol = IPPROTO_TCP;
2894 break;
2895 case SOCK_DGRAM:
2896 if (ai->ai_protocol == 0)
2897 ai->ai_protocol = IPPROTO_UDP;
2898 break;
2899 case 0:
2900 switch (ai->ai_protocol)
2901 {
2902 case IPPROTO_TCP:
2903 ai->ai_socktype = SOCK_STREAM;
2904 break;
2905 case IPPROTO_UDP:
2906 ai->ai_socktype = SOCK_DGRAM;
2907 break;
2908 case 0:
2909 ai->ai_socktype = SOCK_STREAM;
2910 ai->ai_protocol = IPPROTO_TCP;
2911 if (!(tmp = ga_dup (ai, v4mapped, idn_flags, err)))
2912 goto bad;
2913 if (!nai0)
2914 nai0 = tmp;
2915 if (nai)
2916 nai->ai_next = tmp;
2917 nai = tmp;
2918 ai->ai_socktype = SOCK_DGRAM;
2919 ai->ai_protocol = IPPROTO_UDP;
2920 break;
2921 default:
2922 break;
2923 }
2924 break;
2925 default:
2926 break;
2927 }
5b56e9b0 2928 if (!(tmp = ga_dup (ai, v4mapped, idn_flags, err)))
510a85cb 2929 goto bad;
4815dd49 2930 if (!nai0)
510a85cb 2931 nai0 = tmp;
4815dd49 2932 if (nai)
510a85cb 2933 nai->ai_next = tmp;
582c7f96 2934 nai = tmp;
4815dd49
CV
2935 }
2936 return nai0;
2937
2938bad:
5b56e9b0 2939 cygwin_freeaddrinfo (nai0);
4815dd49 2940 return NULL;
70e476d2
CV
2941}
2942
5b56e9b0 2943/* Cygwin specific wrappers around the gai functions. */
8053ccd4 2944static const struct gai_errmap_t
70e476d2
CV
2945{
2946 int w32_errval;
2947 const char *errtxt;
5b56e9b0 2948} gai_errmap[] =
70e476d2 2949{
f28f68cc 2950 {0, "Success"},
5b56e9b0 2951 /* EAI_ADDRFAMILY */
f28f68cc 2952 {0, "Address family for hostname not supported"},
5b56e9b0 2953 /* EAI_AGAIN */
f28f68cc 2954 {WSATRY_AGAIN, "Temporary failure in name resolution"},
5b56e9b0
CV
2955 /* EAI_BADFLAGS */
2956 {WSAEINVAL, "Bad value for ai_flags"},
2957 /* EAI_FAIL */
f28f68cc 2958 {WSANO_RECOVERY, "Non-recoverable failure in name resolution"},
5b56e9b0 2959 /* EAI_FAMILY */
f28f68cc 2960 {WSAEAFNOSUPPORT, "ai_family not supported"},
5b56e9b0 2961 /* EAI_MEMORY */
70e476d2 2962 {WSA_NOT_ENOUGH_MEMORY, "Memory allocation failure"},
5b56e9b0 2963 /* EAI_NODATA */
f28f68cc 2964 {WSANO_DATA, "No address associated with hostname"},
5b56e9b0
CV
2965 /* EAI_NONAME */
2966 {WSAHOST_NOT_FOUND, "Name or service not known"},
2967 /* EAI_SERVICE */
2968 {WSATYPE_NOT_FOUND, "Servname not supported for ai_socktype"},
2969 /* EAI_SOCKTYPE */
f28f68cc 2970 {WSAESOCKTNOSUPPORT, "ai_socktype not supported"},
5b56e9b0
CV
2971 /* EAI_SYSTEM */
2972 {0, "System error"},
2973 /* EAI_BADHINTS */
2974 {0, "Invalid value for hints"},
2975 /* EAI_PROTOCOL */
f28f68cc 2976 {0, "Resolved protocol is unknown"},
5b56e9b0
CV
2977 /* EAI_OVERFLOW */
2978 {WSAEFAULT, "An argument buffer overflowed"},
2979 /* EAI_IDN_ENCODE */
2980 {0, "Parameter string not correctly encoded"}
70e476d2
CV
2981};
2982
f881942d 2983/* Exported as gai_strerror: POSIX.1-2001, POSIX.1-2008 */
70e476d2
CV
2984extern "C" const char *
2985cygwin_gai_strerror (int err)
2986{
f28f68cc 2987 if (err >= 0 && err < (int) (sizeof gai_errmap / sizeof *gai_errmap))
70e476d2
CV
2988 return gai_errmap[err].errtxt;
2989 return "Unknown error";
2990}
2991
2992static int
2993w32_to_gai_err (int w32_err)
2994{
2995 if (w32_err >= WSABASEERR)
f28f68cc 2996 for (unsigned i = 0; i < sizeof gai_errmap / sizeof *gai_errmap; ++i)
70e476d2
CV
2997 if (gai_errmap[i].w32_errval == w32_err)
2998 return i;
2999 return w32_err;
3000}
3001
f881942d 3002/* Exported as getaddrinfo: POSIX.1-2001, POSIX.1-2008, RFC 2553 */
70e476d2
CV
3003extern "C" int
3004cygwin_getaddrinfo (const char *hostname, const char *servname,
3005 const struct addrinfo *hints, struct addrinfo **res)
3006{
3f3bd101
CV
3007 int ret = 0;
3008
5b56e9b0 3009 /* Windows' getaddrinfo implementations lets all possible values
b74bc883 3010 in ai_flags slip through and just ignores unknown values. So we
5b56e9b0
CV
3011 check manually here. */
3012#define AI_IDN_MASK (AI_IDN | \
3013 AI_CANONIDN | \
3014 AI_IDN_ALLOW_UNASSIGNED | \
3015 AI_IDN_USE_STD3_ASCII_RULES)
3016#ifndef AI_DISABLE_IDN_ENCODING
3017#define AI_DISABLE_IDN_ENCODING 0x80000
3018#endif
3f3bd101
CV
3019 __try
3020 {
3021 if (hints && (hints->ai_flags
3022 & ~(AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST | AI_ALL
3023 | AI_NUMERICSERV | AI_ADDRCONFIG | AI_V4MAPPED
3024 | AI_IDN_MASK)))
3025 return EAI_BADFLAGS;
00e9bf2b
CV
3026 /* AI_NUMERICSERV is not supported "by Microsoft providers". We just
3027 check the servname parameter by ourselves here. */
3f3bd101 3028 if (hints && (hints->ai_flags & AI_NUMERICSERV))
5b56e9b0 3029 {
3f3bd101
CV
3030 char *p;
3031 if (servname && *servname && (strtoul (servname, &p, 10), *p))
3032 return EAI_NONAME;
3033 }
3034
3035 int idn_flags = hints ? (hints->ai_flags & AI_IDN_MASK) : 0;
3036 const char *src;
3037 mbstate_t ps;
3038 tmp_pathbuf tp;
3039 wchar_t *whost = NULL, *wserv = NULL;
3040 struct addrinfoW whints, *wres;
3041
3042 if (hostname)
3043 {
3044 memset (&ps, 0, sizeof ps);
3045 src = hostname;
3046 whost = tp.w_get ();
3047 if (mbsrtowcs (whost, &src, NT_MAX_PATH, &ps) == (size_t) -1)
5b56e9b0 3048 return EAI_IDN_ENCODE;
3f3bd101
CV
3049 if (src)
3050 return EAI_MEMORY;
3051 if (idn_flags & AI_IDN)
3052 {
3053 /* Map flags to equivalent IDN_* flags. */
3054 wchar_t *ascbuf = tp.w_get ();
3055 if (IdnToAscii (idn_flags >> 16, whost, -1, ascbuf, NT_MAX_PATH))
3056 whost = ascbuf;
3057 else if (GetLastError () != ERROR_PROC_NOT_FOUND)
3058 return EAI_IDN_ENCODE;
3059 }
3060 }
3061 if (servname)
3062 {
3063 memset (&ps, 0, sizeof ps);
3064 src = servname;
3065 wserv = tp.w_get ();
3066 if (mbsrtowcs (wserv, &src, NT_MAX_PATH, &ps) == (size_t) -1)
3067 return EAI_IDN_ENCODE;
3068 if (src)
3069 return EAI_MEMORY;
5b56e9b0 3070 }
5b56e9b0 3071
3f3bd101
CV
3072 if (!hints)
3073 {
3074 /* Default settings per glibc man page. */
3075 memset (&whints, 0, sizeof whints);
3076 whints.ai_family = PF_UNSPEC;
3077 whints.ai_flags = AI_V4MAPPED | AI_ADDRCONFIG;
3078 }
3079 else
3080 {
3081 /* sizeof addrinfo == sizeof addrinfoW */
3082 memcpy (&whints, hints, sizeof whints);
3083 whints.ai_flags &= ~AI_IDN_MASK;
3f3bd101
CV
3084 /* ai_addrlen is socklen_t (4 bytes) in POSIX but size_t (8 bytes) in
3085 Winsock. Sert upper 4 bytes explicitely to 0 to avoid EAI_FAIL. */
3086 whints.ai_addrlen &= UINT32_MAX;
6f560555 3087 /* On Windows, the default behaviour is as if AI_ADDRCONFIG is set,
3f3bd101
CV
3088 apparently for performance reasons. To get the POSIX default
3089 behaviour, the AI_ALL flag has to be set. */
6f560555 3090 if (whints.ai_family == PF_UNSPEC
3f3bd101
CV
3091 && !(whints.ai_flags & AI_ADDRCONFIG))
3092 whints.ai_flags |= AI_ALL;
3093 }
3094 /* Disable automatic IDN conversion on W8 and later. */
3095 whints.ai_flags |= AI_DISABLE_IDN_ENCODING;
7176a85c
CV
3096 ret = GetAddrInfoW (whost, wserv, &whints, &wres);
3097 /* Try to workaround an apparent shortcoming in Winsock's getaddrinfo
3098 implementation. See this link for details:
3099 https://communities.vmware.com/message/2577858#2577858 */
3100 if (ret == WSANO_RECOVERY && (whints.ai_flags & AI_ALL))
3101 {
3102 whints.ai_flags &= ~AI_ALL;
3103 ret = GetAddrInfoW (whost, wserv, &whints, &wres);
3104 }
3105 ret = w32_to_gai_err (ret);
3f3bd101
CV
3106 /* Always copy over to self-allocated memory. */
3107 if (!ret)
510a85cb 3108 {
3f3bd101 3109 *res = ga_duplist (wres, false, idn_flags, ret);
5b56e9b0 3110 FreeAddrInfoW (wres);
3f3bd101
CV
3111 if (!*res)
3112 __leave;
3113 }
c2decfdc 3114 }
3f3bd101
CV
3115 __except (EFAULT)
3116 {
3117 ret = EAI_SYSTEM;
3118 }
3119 __endtry
6eedb2be 3120 return ret;
70e476d2
CV
3121}
3122
f881942d 3123/* Exported as getnameinfo: POSIX.1-2001, POSIX.1-2008, RFC 2553 */
70e476d2
CV
3124extern "C" int
3125cygwin_getnameinfo (const struct sockaddr *sa, socklen_t salen,
3126 char *host, size_t hostlen, char *serv,
3127 size_t servlen, int flags)
3128{
3f3bd101 3129 int ret = 0;
6eedb2be 3130
3f3bd101 3131 __try
70e476d2 3132 {
3f3bd101
CV
3133 /* We call GetNameInfoW with local buffers and convert to locale
3134 charset to allow RFC 3490 IDNs like glibc 2.3.4 and later. */
5b56e9b0
CV
3135#define NI_IDN_MASK (NI_IDN | \
3136 NI_IDN_ALLOW_UNASSIGNED | \
3137 NI_IDN_USE_STD3_ASCII_RULES)
3f3bd101
CV
3138 int idn_flags = flags & NI_IDN_MASK;
3139 flags &= ~NI_IDN_MASK;
3140 tmp_pathbuf tp;
3141 wchar_t *whost = NULL, *wserv = NULL;
3142 DWORD whlen = 0, wslen = 0;
5b56e9b0 3143
3f3bd101
CV
3144 if (host && hostlen)
3145 {
3146 whost = tp.w_get ();
3147 whlen = NT_MAX_PATH;
3148 }
3149 if (serv && servlen)
3150 {
3151 wserv = tp.w_get ();
3152 wslen = NT_MAX_PATH;
3153 }
5b56e9b0 3154
3f3bd101 3155 ret = w32_to_gai_err (GetNameInfoW (sa, salen, whost, whlen,
5b56e9b0 3156 wserv, wslen, flags));
3f3bd101 3157 if (!ret)
5b56e9b0 3158 {
3f3bd101
CV
3159 const wchar_t *src;
3160
3161 if (whost)
5b56e9b0 3162 {
3f3bd101
CV
3163 if (idn_flags & NI_IDN)
3164 {
3165 /* Map flags to equivalent IDN_* flags. */
3166 wchar_t *idnbuf = tp.w_get ();
3167 if (IdnToUnicode (idn_flags >> 16, whost, -1,
3168 idnbuf, NT_MAX_PATH))
3169 whost = idnbuf;
3170 else if (GetLastError () != ERROR_PROC_NOT_FOUND)
3171 return EAI_IDN_ENCODE;
3172 }
3173 src = whost;
3174 if (wcsrtombs (host, &src, hostlen, NULL) == (size_t) -1)
5b56e9b0 3175 return EAI_IDN_ENCODE;
3f3bd101
CV
3176 if (src)
3177 return EAI_OVERFLOW;
3178 }
3179 if (wserv)
3180 {
3181 src = wserv;
3182 if (wcsrtombs (serv, &src, servlen, NULL) == (size_t) -1)
3183 return EAI_IDN_ENCODE;
3184 if (src)
3185 return EAI_OVERFLOW;
5b56e9b0 3186 }
5b56e9b0 3187 }
3f3bd101
CV
3188 else if (ret == EAI_SYSTEM)
3189 set_winsock_errno ();
3190 }
3191 __except (EFAULT)
3192 {
3193 ret = EAI_SYSTEM;
5b56e9b0 3194 }
3f3bd101 3195 __endtry
6eedb2be 3196 return ret;
70e476d2
CV
3197}
3198
2895b8b5
CV
3199/* These functions are stick to the end of this file so that the
3200 optimization in asm/byteorder.h can be used even here in net.cc. */
3201
3202#undef htonl
3203#undef ntohl
3204#undef htons
3205#undef ntohs
3206
f881942d 3207/* htonl: POSIX.1-2001, POSIX.1-2008 */
2895b8b5
CV
3208extern "C" uint32_t
3209htonl (uint32_t x)
3210{
3211 return __htonl (x);
3212}
3213
f881942d 3214/* ntohl: POSIX.1-2001, POSIX.1-2008 */
2895b8b5
CV
3215extern "C" uint32_t
3216ntohl (uint32_t x)
3217{
3218 return __ntohl (x);
3219}
3220
f881942d 3221/* htons: POSIX.1-2001, POSIX.1-2008 */
2895b8b5
CV
3222extern "C" uint16_t
3223htons (uint16_t x)
3224{
3225 return __htons (x);
3226}
3227
f881942d 3228/* ntohs: POSIX.1-2001, POSIX.1-2008 */
2895b8b5
CV
3229extern "C" uint16_t
3230ntohs (uint16_t x)
3231{
3232 return __ntohs (x);
3233}
This page took 1.190597 seconds and 6 git commands to generate.