]> sourceware.org Git - newlib-cygwin.git/blob - winsup/cygwin/net.cc
737e494f8f4a5021d3ce2bfb20de06491e178866
[newlib-cygwin.git] / winsup / cygwin / net.cc
1 /* net.cc: network-related routines.
2
3 This file is part of Cygwin.
4
5 This software is a copyrighted work licensed under the terms of the
6 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
7 details. */
8
9 /* #define DEBUG_NEST_ON 1 */
10
11 #define __INSIDE_CYGWIN_NET__
12 #define USE_SYS_TYPES_FD_SET
13 #define __WSA_ERR_MACROS_DEFINED
14 #include "winsup.h"
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
17 definition and size of sockaddr_in6 when building with winsock headers. */
18 #undef u_long
19 #define u_long __ms_u_long
20 #include <w32api/ws2tcpip.h>
21 #include <w32api/mswsock.h>
22 #include <w32api/iphlpapi.h>
23 #define gethostname cygwin_gethostname
24 #include <unistd.h>
25 #undef gethostname
26 #include <ifaddrs.h>
27 #include <netdb.h>
28 #include <asm/byteorder.h>
29 #include "shared_info.h"
30 #include "path.h"
31 #include "fhandler.h"
32 #include "dtable.h"
33 #include "cygheap.h"
34 #include "tls_pbuf.h"
35
36 /* Unfortunately defined in Windows header files and arpa/nameser_compat.h. */
37 #undef NOERROR
38 #undef DELETE
39 #define _CYGWIN_IN_H
40 #include <resolv.h>
41
42 extern "C"
43 {
44 int h_errno;
45
46 int sscanf (const char *, const char *, ...);
47 int cygwin_inet_pton(int, const char *, void *);
48 const char *cygwin_inet_ntop (int, const void *, char *, socklen_t);
49 int dn_length1(const unsigned char *, const unsigned char *,
50 const unsigned char *);
51 } /* End of "C" section */
52
53 const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
54 const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
55
56 static fhandler_socket *
57 get (const int fd)
58 {
59 cygheap_fdget cfd (fd);
60
61 if (cfd < 0)
62 return NULL;
63
64 fhandler_socket *const fh = cfd->is_socket ();
65
66 if (!fh || (fh->get_flags () & O_PATH))
67 {
68 set_errno (ENOTSOCK);
69 return NULL;
70 }
71
72 return fh;
73 }
74
75 /* exported as inet_ntoa: BSD 4.3 */
76 extern "C" char *
77 cygwin_inet_ntoa (struct in_addr in)
78 {
79 char buf[20];
80 const char *res = cygwin_inet_ntop (AF_INET, &in, buf, sizeof buf);
81
82 if (_my_tls.locals.ntoa_buf)
83 {
84 free (_my_tls.locals.ntoa_buf);
85 _my_tls.locals.ntoa_buf = NULL;
86 }
87 if (res)
88 _my_tls.locals.ntoa_buf = strdup (res);
89 return _my_tls.locals.ntoa_buf;
90 }
91
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
96 extern "C" unsigned long
97 inet_netof (struct in_addr in)
98 {
99 unsigned long i, res;
100
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
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
116 extern "C" struct in_addr
117 inet_makeaddr (int net, int lna)
118 {
119 unsigned long i;
120 struct in_addr in;
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
137 static 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 */
211 };
212
213 int
214 find_winsock_errno (DWORD why)
215 {
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];
224
225 return EACCES;
226 }
227
228 void
229 __set_winsock_errno (const char *fn, int ln)
230 {
231 DWORD werr = WSAGetLastError ();
232 int err = find_winsock_errno (werr);
233
234 set_errno (err);
235 syscall_printf ("%s:%d - winsock error %u -> errno %d", fn, ln, werr, err);
236 }
237
238 static 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[] = {
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},
248 {0, NULL, 0}
249 };
250
251 static void
252 set_host_errno ()
253 {
254 int i;
255
256 DWORD why = WSAGetLastError ();
257
258 for (i = 0; host_errmap[i].w != 0; ++i)
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
268 inline int
269 DWORD_round (int n)
270 {
271 return sizeof (DWORD) * (((n + sizeof (DWORD) - 1)) / sizeof (DWORD));
272 }
273
274 inline int
275 strlen_round (const char *s)
276 {
277 if (!s)
278 return 0;
279 return DWORD_round (strlen (s) + 1);
280 }
281
282 #pragma pack(push,2)
283 struct pservent
284 {
285 char *s_name;
286 char **s_aliases;
287 short s_port;
288 char *s_proto;
289 };
290 #pragma pack(pop)
291
292 static const char *entnames[] = {"host", "proto", "serv"};
293
294 static unionent *
295 realloc_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
307 static inline hostent *
308 realloc_ent (int sz, hostent *)
309 {
310 return (hostent *) realloc_ent (_my_tls.locals.hostent_buf, sz);
311 }
312
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
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. */
325 struct 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))
333
334 #ifdef DEBUGGING
335 static void *
336 #else
337 static inline void *
338 #endif
339 dup_ent (unionent *&dst, unionent *src, unionent::struct_type type)
340 {
341 if (dst)
342 debug_printf ("old %sent structure \"%s\" %p\n", entnames[type],
343 dst->name, dst);
344
345 if (!src)
346 {
347 set_winsock_errno ();
348 return NULL;
349 }
350
351 debug_printf ("duping %sent \"%s\", %p", entnames[type], src->name, src);
352
353 /* Find the size of the raw structure minus any character strings, etc. */
354 int sz, struct_sz;
355 switch (type)
356 {
357 case unionent::t_protoent:
358 struct_sz = sizeof (protoent);
359 break;
360 case unionent::t_servent:
361 struct_sz = sizeof (servent);
362 break;
363 case unionent::t_hostent:
364 struct_sz = sizeof (hostent);
365 break;
366 default:
367 api_fatal ("called with invalid value %d", type);
368 break;
369 }
370
371 /* Every *ent begins with a name. Calculate its length. */
372 int namelen = strlen_round (src->name);
373 sz = struct_sz + namelen;
374
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 }
385
386 /* NULL terminate if there actually was a list */
387 if (av)
388 {
389 sz += sizeof (char **);
390 list_len++;
391 }
392
393 /* Do servent/hostent specific processing */
394 int protolen = 0;
395 int addr_list_len = 0;
396 if (type == unionent::t_servent)
397 {
398 if (WIN_SERVENT (src)->s_proto)
399 sz += (protolen = strlen_round (WIN_SERVENT (src)->s_proto));
400 }
401 else if (type == unionent::t_hostent)
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 }
415
416 /* Allocate the storage needed. */
417 if (realloc_ent (dst, sz))
418 {
419 memset (dst, 0, sz);
420 /* This field is common to all *ent structures but named differently
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;
427
428 char *dp = ((char *) dst) + struct_sz;
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 }
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 }
450
451 /* Do servent/protoent/hostent specific processing. */
452 if (type == unionent::t_protoent)
453 debug_printf ("protoent %s %p %y", dst->name, dst->list, dst->port_proto_addrtype);
454 else if (type == unionent::t_servent)
455 {
456 if (WIN_SERVENT (src)->s_proto)
457 {
458 strcpy (dst->s_proto = dp, WIN_SERVENT (src)->s_proto);
459 dp += protolen;
460 }
461 }
462 else if (type == unionent::t_hostent)
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 }
475 }
476 debug_printf ("duped %sent \"%s\", %p", entnames[type], dst ? dst->name : "<null!>", dst);
477 return dst;
478 }
479
480 static inline hostent *
481 dup_ent (hostent *src)
482 {
483 return (hostent *) dup_ent (_my_tls.locals.hostent_buf, (unionent *) src, unionent::t_hostent);
484 }
485
486 static inline protoent *
487 dup_ent (protoent *src)
488 {
489 return (protoent *) dup_ent (_my_tls.locals.protoent_buf, (unionent *) src, unionent::t_protoent);
490 }
491
492 static inline servent *
493 dup_ent (servent *src)
494 {
495 return (servent *) dup_ent (_my_tls.locals.servent_buf, (unionent *) src, unionent::t_servent);
496 }
497
498 /* exported as getprotobyname: POSIX.1-2001, POSIX.1-2008, 4.3BSD */
499 extern "C" struct protoent *
500 cygwin_getprotobyname (const char *p)
501 {
502 __try
503 {
504 return dup_ent (getprotobyname (p));
505 }
506 __except (EFAULT) {}
507 __endtry
508 return NULL;
509 }
510
511 /* exported as getprotobynumber: POSIX.1-2001, POSIX.1-2008, 4.3BSD */
512 extern "C" struct protoent *
513 cygwin_getprotobynumber (int number)
514 {
515 return dup_ent (getprotobynumber (number));
516 }
517
518 /* exported as socket: POSIX.1-2001, POSIX.1-2008, 4.4BSD */
519 extern "C" int
520 cygwin_socket (int af, int type, int protocol)
521 {
522 int res = -1;
523 const device *dev;
524 fhandler_socket *fh;
525
526 int flags = type & _SOCK_FLAG_MASK;
527 type &= ~_SOCK_FLAG_MASK;
528
529 debug_printf ("socket (%d, %d (flags %y), %d)", af, type, flags, protocol);
530
531 switch (af)
532 {
533 case AF_LOCAL:
534 #ifndef __WITH_AF_UNIX
535 dev = af_local_dev;
536 #else
537 case AF_UNIX:
538 dev = (af == AF_LOCAL) ? af_local_dev : af_unix_dev;
539 #endif /* __WITH_AF_UNIX */
540 break;
541 case AF_INET:
542 case AF_INET6:
543 dev = af_inet_dev;
544 break;
545 default:
546 set_errno (EAFNOSUPPORT);
547 goto done;
548 }
549
550 if ((flags & ~(SOCK_NONBLOCK | SOCK_CLOEXEC)) != 0)
551 {
552 set_errno (EINVAL);
553 goto done;
554 }
555
556 {
557 cygheap_fdnew fd;
558
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
570 delete fh;
571 }
572
573 done:
574 syscall_printf ("%R = socket(%d, %d (flags %y), %d)",
575 res, af, type, flags, protocol);
576 return res;
577 }
578
579 /* exported as sendto: 4.4BSD, SVr4, POSIX.1-2001 */
580 extern "C" ssize_t
581 cygwin_sendto (int fd, const void *buf, size_t len, int flags,
582 const struct sockaddr *to, socklen_t tolen)
583 {
584 ssize_t res = -1;
585
586 pthread_testcancel ();
587
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
596 syscall_printf ("%lR = sendto(%d, %p, %ld, %y, %p, %d)",
597 res, fd, buf, len, flags, to, tolen);
598 return res;
599 }
600
601 /* exported as recvfrom: 4.4BSD, SVr4, POSIX.1-2001 */
602 extern "C" ssize_t
603 cygwin_recvfrom (int fd, void *buf, size_t len, int flags,
604 struct sockaddr *from, socklen_t *fromlen)
605 {
606 ssize_t res = -1;
607
608 pthread_testcancel ();
609
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
622 syscall_printf ("%lR = recvfrom(%d, %p, %ld, %y, %p, %p)",
623 res, fd, buf, len, flags, from, fromlen);
624 return res;
625 }
626
627 /* exported as setsockopt: POSIX.1-2001, POSIX.1-2008, SVr4, 4.4BSD */
628 extern "C" int
629 cygwin_setsockopt (int fd, int level, int optname, const void *optval,
630 socklen_t optlen)
631 {
632 int ret = -1;
633
634 __try
635 {
636 fhandler_socket *fh = get (fd);
637 if (fh)
638 ret = fh->setsockopt (level, optname, optval, optlen);
639 }
640 __except (EFAULT) {}
641 __endtry
642 syscall_printf ("%R = setsockopt(%d, %d, %y, %p, %d)",
643 ret, fd, level, optname, optval, optlen);
644 return ret;
645 }
646
647 /* exported as getsockopt: POSIX.1-2001, POSIX.1-2008, SVr4, 4.4BSD */
648 extern "C" int
649 cygwin_getsockopt (int fd, int level, int optname, void *optval,
650 socklen_t *optlen)
651 {
652 int ret = -1;
653
654 __try
655 {
656 fhandler_socket *fh = get (fd);
657 if (fh)
658 ret = fh->getsockopt (level, optname, optval, optlen);
659 }
660 __except (EFAULT) {}
661 __endtry
662 syscall_printf ("%R = getsockopt(%d, %d, %y, %p, %p)",
663 ret, fd, level, optname, optval, optlen);
664 return ret;
665 }
666
667 /* POSIX.1-2001 */
668 extern "C" int
669 sockatmark (int fd)
670 {
671 int ret;
672 cygheap_fdget cfd (fd);
673
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)
683 return ret;
684 return -1;
685 }
686
687 /* BSD */
688 extern "C" int
689 getpeereid (int fd, uid_t *euid, gid_t *egid)
690 {
691 fhandler_socket *fh = get (fd);
692 if (fh)
693 return fh->getpeereid (NULL, euid, egid);
694 return -1;
695 }
696
697 /* exported as connect: POSIX.1-2001, POSIX.1-2008, SVr4, 4.4BSD */
698 extern "C" int
699 cygwin_connect (int fd, const struct sockaddr *name, socklen_t namelen)
700 {
701 int res = -1;
702
703 pthread_testcancel ();
704
705 __try
706 {
707 fhandler_socket *fh = get (fd);
708 if (fh)
709 res = fh->connect (name, namelen);
710 }
711 __except (EFAULT) {}
712 __endtry
713 syscall_printf ("%R = connect(%d, %p, %d)", res, fd, name, namelen);
714 return res;
715 }
716
717 /* exported as getservbyname: POSIX.1-2001, POSIX.1-2008, 4.3BSD */
718 extern "C" struct servent *
719 cygwin_getservbyname (const char *name, const char *proto)
720 {
721 servent *res = NULL;
722
723 __try
724 {
725 res = dup_ent (getservbyname (name, proto));
726 }
727 __except (EFAULT) {}
728 __endtry
729 syscall_printf ("%p = getservbyname (%s, %s)", res, name, proto);
730 return res;
731 }
732
733 /* exported as getservbyport: POSIX.1-2001, POSIX.1-2008, 4.3BSD */
734 extern "C" struct servent *
735 cygwin_getservbyport (int port, const char *proto)
736 {
737 servent *res = NULL;
738
739 __try
740 {
741 res = dup_ent (getservbyport (port, proto));
742 }
743 __except (EFAULT) {}
744 __endtry
745 syscall_printf ("%p = getservbyport (%d, %s)", res, port, proto);
746 return res;
747 }
748
749 extern "C" int
750 cygwin_gethostname (char *name, size_t len)
751 {
752 __try
753 {
754 PFIXED_INFO info = NULL;
755 ULONG size = 0;
756
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;
764 }
765 __seterrno ();
766 }
767 __except (EFAULT)
768 __endtry
769 return -1;
770 }
771
772 extern "C" int
773 sethostname (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
786 /* getdomainname: 4.4BSD */
787 extern "C" int
788 getdomainname (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);
800 debug_printf ("getdomainname %s", domain);
801 return 0;
802 }
803 __seterrno ();
804 }
805 __except (EFAULT)
806 __endtry
807 return -1;
808 }
809
810 /* exported as gethostbyname: POSIX.1-2001 */
811 extern "C" struct hostent *
812 cygwin_gethostbyname (const char *name)
813 {
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;
820 hostent *res = NULL;
821
822 __try
823 {
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)
854 {
855 res = NULL;
856 }
857 __endtry
858 return res;
859 }
860
861 /* exported as gethostbyaddr: POSIX.1-2001 */
862 extern "C" struct hostent *
863 cygwin_gethostbyaddr (const void *addr, socklen_t len, int type)
864 {
865 hostent *res = NULL;
866
867 __try
868 {
869 res = dup_ent (gethostbyaddr ((const char *) addr, len, type));
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
880 return res;
881 }
882
883 static void
884 memcpy4to6 (char *dst, const u_int8_t *src)
885 {
886 const unsigned int h[] = {0, 0, htonl (0xFFFF)};
887 memcpy (dst, h, 12);
888 memcpy (dst + 12, src, NS_INADDRSZ);
889 }
890
891 /* gethostby_specials: RFC 6761
892 Handles numerical addresses and special names for gethostbyname2 */
893 static hostent *
894 gethostby_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 '.' */
899 if ((namelen == 0) || ((namelen -= (name[namelen - 1] == '.')) == 0))
900 {
901 set_errno (EINVAL);
902 h_errno = NETDB_INTERNAL;
903 return NULL;
904 }
905
906 int res;
907 u_int8_t address[NS_IN6ADDRSZ];
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)
947 return NULL;
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
989 static hostent *
990 gethostby_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;
996 unsigned char *ptr, *msg = NULL;
997 int sz;
998 hostent *ret;
999 char *string_ptr;
1000
1001 while ((anlen > msgsize) && (ancount++ < maxcount))
1002 {
1003 msgsize = anlen;
1004 ptr = (unsigned char *) realloc (msg, msgsize);
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);
1015 }
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);
1028 return NULL;
1029 }
1030 unsigned char *eomsg = msg + anlen - 1;
1031
1032 /* We scan the answer records to determine the required memory size.
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
1039 - the first 16 bits of the "ttl" store the expanded name size + 1
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. */
1042
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
1050 unsigned char data[]; // data
1051 record * next () { return (record *) (((char *) this) + next_o); }
1052 void set_next ( record * nxt) { next_o = ((char *) nxt) - ((char *) this); }
1053 unsigned char *name () { return (unsigned char *)
1054 (((char *) this) - complen); }
1055 };
1056
1057 record * anptr = NULL, * prevptr = NULL, * curptr;
1058 int i, alias_count = 0, string_size = 0, address_count = 0;
1059 int namelen1 = 0, address_len = 0, antype, anclass, ansize;
1060 unsigned complen;
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)
1068 goto corrupted;
1069 /* Point to the beginning of the answer section */
1070 ptr += complen + NS_QFIXEDSZ;
1071
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
1090 if (antype == ns_t_cname)
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 }
1128
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);
1136 if (! ret)
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);
1150
1151 /* Rescan the answers */
1152 alias_count = address_count = 0;
1153 prevptr->set_next (prevptr + 1);
1154
1155 for (curptr = anptr; curptr <= prevptr; curptr = curptr->next ())
1156 {
1157 antype = curptr->type;
1158 if (antype == ns_t_cname)
1159 {
1160 dn_expand (msg, eomsg, curptr->name (), string_ptr, curptr->namelen1);
1161 ret->h_aliases[alias_count++] = string_ptr;
1162 string_ptr += curptr->namelen1;
1163 }
1164 else
1165 {
1166 if (address_count == 0)
1167 {
1168 dn_expand (msg, eomsg, curptr->name (), string_ptr,
1169 curptr->namelen1);
1170 ret->h_name = string_ptr;
1171 string_ptr += curptr->namelen1;
1172 }
1173 ret->h_addr_list[address_count++] = string_ptr;
1174 if (addrsize_in != addrsize_out)
1175 {
1176 memcpy4to6 (string_ptr, curptr->data);
1177 ret->h_addrtype = AF_INET6;
1178 }
1179 else
1180 memcpy (string_ptr, curptr->data, addrsize_in);
1181 string_ptr += addrsize_out;
1182 }
1183 }
1184
1185 free (msg);
1186
1187 ret->h_aliases[alias_count] = NULL;
1188 ret->h_addr_list[address_count] = NULL;
1189
1190 return ret;
1191
1192 corrupted:
1193 free (msg);
1194 /* Hopefully message corruption errors are temporary.
1195 Should it be NO_RECOVERY ? */
1196 h_errno = TRY_AGAIN;
1197 return NULL;
1198 }
1199
1200 /* gethostbyname2: GNU extension */
1201 extern "C" struct hostent *
1202 gethostbyname2 (const char *name, int af)
1203 {
1204 hostent *res = NULL;
1205
1206 __try
1207 {
1208 if (!(_res.options & RES_INIT))
1209 res_init();
1210
1211 bool v4to6 = _res.options & RES_USE_INET6;
1212 int type, addrsize_in, addrsize_out;
1213
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 }
1230
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);
1235 }
1236 __except (EFAULT) {}
1237 __endtry
1238 return res;
1239 }
1240
1241 /* exported as accept: POSIX.1-2001, POSIX.1-2008, SVr4, 4.4BSD */
1242 extern "C" int
1243 cygwin_accept (int fd, struct sockaddr *peer, socklen_t *len)
1244 {
1245 int res = -1;
1246
1247 pthread_testcancel ();
1248
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
1258 syscall_printf ("%R = accept(%d, %p, %p)", res, fd, peer, len);
1259 return res;
1260 }
1261
1262 /* accept4: GNU extension */
1263 extern "C" int
1264 accept4 (int fd, struct sockaddr *peer, socklen_t *len, int flags)
1265 {
1266 int res = -1;
1267
1268 pthread_testcancel ();
1269
1270 __try
1271 {
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);
1279 }
1280 __except (EFAULT) {}
1281 __endtry
1282 syscall_printf ("%R = accept4(%d, %p, %p, %y)", res, fd, peer, len, flags);
1283 return res;
1284 }
1285
1286 /* exported as bind: POSIX.1-2001, POSIX.1-2008, SVr4, 4.4BSD */
1287 extern "C" int
1288 cygwin_bind (int fd, const struct sockaddr *my_addr, socklen_t addrlen)
1289 {
1290 int res = -1;
1291
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
1300 syscall_printf ("%R = bind(%d, %p, %d)", res, fd, my_addr, addrlen);
1301 return res;
1302 }
1303
1304 /* exported as getsockname: POSIX.1-2001, POSIX.1-2008, SVr4, 4.4BSD */
1305 extern "C" int
1306 cygwin_getsockname (int fd, struct sockaddr *addr, socklen_t *namelen)
1307 {
1308 int res = -1;
1309
1310 __try
1311 {
1312 fhandler_socket *fh = get (fd);
1313 if (fh)
1314 res = fh->getsockname (addr, namelen);
1315 }
1316 __except (EFAULT) {}
1317 __endtry
1318 syscall_printf ("%R =getsockname (%d, %p, %p)", res, fd, addr, namelen);
1319 return res;
1320 }
1321
1322 /* exported as listen: POSIX.1-2001, POSIX.1-2008, SVr4, 4.4BSD */
1323 extern "C" int
1324 cygwin_listen (int fd, int backlog)
1325 {
1326 int res = -1;
1327
1328 __try
1329 {
1330 fhandler_socket *fh = get (fd);
1331 if (fh)
1332 res = fh->listen (backlog);
1333 }
1334 __except (EFAULT) {}
1335 __endtry
1336 syscall_printf ("%R = listen(%d, %d)", res, fd, backlog);
1337 return res;
1338 }
1339
1340 /* exported as shutdown: POSIX.1-2001, POSIX.1-2008, SVr4, 4.4BSD */
1341 extern "C" int
1342 cygwin_shutdown (int fd, int how)
1343 {
1344 int res = -1;
1345
1346 fhandler_socket *fh = get (fd);
1347 if (fh)
1348 res = fh->shutdown (how);
1349 syscall_printf ("%R = shutdown(%d, %d)", res, fd, how);
1350 return res;
1351 }
1352
1353 /* exported as hstrerror: BSD 4.3 */
1354 extern "C" const char *
1355 cygwin_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 */
1367 extern "C" void
1368 cygwin_herror (const char *s)
1369 {
1370 __try
1371 {
1372 if (cygheap->fdtab.not_open (2))
1373 return;
1374
1375 if (s)
1376 {
1377 write (2, s, strlen (s));
1378 write (2, ": ", 2);
1379 }
1380
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
1401 }
1402
1403 /* exported as getpeername: POSIX.1-2001, POSIX.1-2008, SVr4, 4.4BSD */
1404 extern "C" int
1405 cygwin_getpeername (int fd, struct sockaddr *name, socklen_t *len)
1406 {
1407 int res = -1;
1408 fhandler_socket *fh = NULL;
1409
1410 __try
1411 {
1412 fh = get (fd);
1413 if (fh)
1414 res = fh->getpeername (name, len);
1415 }
1416 __except (EFAULT) {}
1417 __endtry
1418 syscall_printf ("%R = getpeername(%d)", res, fd);
1419 return res;
1420 }
1421
1422 /* exported as recv: POSIX.1-2001, POSIX.1-2008, SVr4, 4.4BSD */
1423 extern "C" ssize_t
1424 cygwin_recv (int fd, void *buf, size_t len, int flags)
1425 {
1426 ssize_t res = -1;
1427
1428 pthread_testcancel ();
1429
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
1442 syscall_printf ("%lR = recv(%d, %p, %ld, %y)", res, fd, buf, len, flags);
1443 return res;
1444 }
1445
1446 /* exported as send: POSIX.1-2001, POSIX.1-2008, SVr4, 4.4BSD */
1447 extern "C" ssize_t
1448 cygwin_send (int fd, const void *buf, size_t len, int flags)
1449 {
1450 ssize_t res = -1;
1451
1452 pthread_testcancel ();
1453
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
1462 syscall_printf ("%lR = send(%d, %p, %ld, %y)", res, fd, buf, len, flags);
1463 return res;
1464 }
1465
1466 /* Fill out an ifconf struct. */
1467
1468 bool
1469 get_adapters_addresses (PIP_ADAPTER_ADDRESSES *pa_ret, ULONG family)
1470 {
1471 DWORD ret, size = 0;
1472 PIP_ADAPTER_ADDRESSES pa0 = NULL;
1473
1474 if (!pa_ret)
1475 return GetAdaptersAddresses (family, GAA_FLAG_INCLUDE_PREFIX
1476 | GAA_FLAG_INCLUDE_ALL_INTERFACES,
1477 NULL, NULL, &size);
1478 do
1479 {
1480 ret = GetAdaptersAddresses (family, GAA_FLAG_INCLUDE_PREFIX
1481 | GAA_FLAG_INCLUDE_ALL_INTERFACES,
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);
1488 if (pa0)
1489 {
1490 if (ret != ERROR_SUCCESS)
1491 {
1492 free (pa0);
1493 *pa_ret = NULL;
1494 }
1495 else
1496 *pa_ret = pa0;
1497 }
1498 return ret == ERROR_SUCCESS || (!pa_ret && ret == ERROR_BUFFER_OVERFLOW);
1499 }
1500
1501 static in_addr_t
1502 get_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 {
1511 if (pift->table[i].dwForwardIfIndex == if_index
1512 && pift->table[i].dwForwardMask == INADDR_BROADCAST)
1513 return pift->table[i].dwForwardDest;
1514 }
1515 return INADDR_ANY;
1516 }
1517
1518 struct 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;
1524 struct ifaddrs_hwdata ifa_hwdata;
1525 };
1526
1527 static unsigned int
1528 get_flags (PIP_ADAPTER_ADDRESSES pap)
1529 {
1530 unsigned int flags = IFF_UP;
1531 if (pap->IfType == IF_TYPE_SOFTWARE_LOOPBACK)
1532 flags |= IFF_LOOPBACK;
1533 else if (pap->IfType == IF_TYPE_PPP
1534 || pap->IfType == IF_TYPE_SLIP)
1535 flags |= IFF_POINTOPOINT | IFF_NOARP;
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
1548 static ULONG
1549 get_ipv4fromreg_ipcnt (const char *name)
1550 {
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
1558 ULONG ifs = 1;
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 };
1568
1569 /* If DHCP is used, we have only one address. */
1570 if (NT_SUCCESS (RtlQueryRegistryValues (RTL_REGISTRY_SERVICES, regkey, tab,
1571 NULL, NULL))
1572 && uipa.Buffer)
1573 {
1574 if (dhcp == 0)
1575 for (ifs = 0, c = uipa.Buffer; *c; c += wcslen (c) + 1)
1576 ifs++;
1577 RtlFreeUnicodeString (&uipa);
1578 }
1579 return ifs;
1580 }
1581
1582 static void
1583 get_ipv4fromreg (struct ifall *ifp, const char *name, DWORD idx)
1584 {
1585 WCHAR regkey[256], *c;
1586 bool got_addr = false, got_mask = false;
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)))
1615 {
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)); \
1623 cygwin_inet_pton (AF_INET, t, (a)); \
1624 }
1625 /* If DHCP is used, we have only one address. */
1626 if (dhcp)
1627 {
1628 if (udipa.Buffer)
1629 {
1630 inet_uton (udipa.Buffer, &addr->sin_addr);
1631 got_addr = true;
1632 }
1633 if (udsub.Buffer)
1634 {
1635 inet_uton (udsub.Buffer, &mask->sin_addr);
1636 got_mask = true;
1637 }
1638 }
1639 else
1640 {
1641 if (uipa.Buffer)
1642 {
1643 for (ifs = 0, c = uipa.Buffer; *c && ifs < idx;
1644 c += wcslen (c) + 1)
1645 ifs++;
1646 if (*c)
1647 {
1648 inet_uton (c, &addr->sin_addr);
1649 got_addr = true;
1650 }
1651 }
1652 if (usub.Buffer)
1653 {
1654 for (ifs = 0, c = usub.Buffer; *c && ifs < idx;
1655 c += wcslen (c) + 1)
1656 ifs++;
1657 if (*c)
1658 {
1659 inet_uton (c, &mask->sin_addr);
1660 got_mask = true;
1661 }
1662 }
1663 }
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;
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
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);
1684 }
1685 }
1686
1687 static void
1688 get_friendlyname (struct ifall *ifp, PIP_ADAPTER_ADDRESSES pap)
1689 {
1690 struct ifreq_frndlyname *iff = (struct ifreq_frndlyname *)
1691 &ifp->ifa_hwdata.ifa_frndlyname;
1692 iff->ifrf_len = sys_wcstombs (iff->ifrf_friendlyname,
1693 IFRF_FRIENDLYNAMESIZ,
1694 pap->FriendlyName) + 1;
1695 }
1696
1697 static void
1698 get_hwaddr (struct ifall *ifp, PIP_ADAPTER_ADDRESSES pap)
1699 {
1700 for (UINT i = 0; i < IFHWADDRLEN; ++i)
1701 if (i >= pap->PhysicalAddressLength)
1702 ifp->ifa_hwdata.ifa_hwaddr.sa_data[i] = '\0';
1703 else
1704 ifp->ifa_hwdata.ifa_hwaddr.sa_data[i] = pap->PhysicalAddress[i];
1705 }
1706
1707 /*
1708 * Get network interfaces. Use IP Helper function GetAdaptersAddresses.
1709 */
1710 static struct ifall *
1711 get_ifs (ULONG family)
1712 {
1713 PIP_ADAPTER_ADDRESSES pa0 = NULL, pap;
1714 PIP_ADAPTER_UNICAST_ADDRESS pua;
1715 int cnt = 0;
1716 struct ifall *ifret = NULL, *ifp;
1717 struct sockaddr_in *if_sin;
1718 struct sockaddr_in6 *if_sin6;
1719
1720 if (!get_adapters_addresses (&pa0, family))
1721 goto done;
1722
1723 for (pap = pa0; pap; pap = pap->Next)
1724 if (!pap->FirstUnicastAddress)
1725 {
1726 /* FirstUnicastAddress is NULL for interfaces which are disconnected.
1727 Fetch number of configured IPv4 addresses from registry and
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)
1733 ++cnt;
1734
1735 if (!(ifret = (struct ifall *) calloc (cnt, sizeof (struct ifall))))
1736 goto done;
1737 ifp = ifret;
1738
1739 for (pap = pa0; pap; pap = pap->Next)
1740 {
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 */
1748
1749 if (idx)
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);
1756 if (pap->IfType != IF_TYPE_PPP
1757 && pap->IfType != IF_TYPE_SOFTWARE_LOOPBACK)
1758 ifp->ifa_ifa.ifa_flags |= IFF_BROADCAST;
1759 /* Address */
1760 ifp->ifa_addr.ss_family = AF_INET;
1761 ifp->ifa_ifa.ifa_addr = NULL;
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;
1767 ifp->ifa_ifa.ifa_netmask = NULL;
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 */
1773 ifp->ifa_hwdata.ifa_metric = 1;
1774 /* MTU */
1775 ifp->ifa_hwdata.ifa_mtu = pap->Mtu;
1776 /* Interface index */
1777 ifp->ifa_hwdata.ifa_ifindex = pap->IfIndex;
1778 /* Friendly name */
1779 get_friendlyname (ifp, pap);
1780 /* Let ifa_data member point to "ifaddrs_hwdata" data. */
1781 ifp->ifa_ifa.ifa_data = &ifp->ifa_hwdata;
1782 ++ifp;
1783 }
1784 else
1785 for (idx = 0, pua = pap->FirstUnicastAddress; pua; pua = pua->Next)
1786 {
1787 struct sockaddr *sa = (struct sockaddr *) pua->Address.lpSockaddr;
1788 # define sin ((struct sockaddr_in *) sa)
1789 # define sin6 ((struct sockaddr_in6 *) sa)
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 */
1795 if (sa->sa_family == AF_INET && idx)
1796 __small_sprintf (ifp->ifa_name, "%s:%u", pap->AdapterName, idx);
1797 else
1798 strcpy (ifp->ifa_name, pap->AdapterName);
1799 if (sa->sa_family == AF_INET)
1800 ++idx;
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;
1808 /* Address */
1809 memcpy (&ifp->ifa_addr, sa, sa_size);
1810 ifp->ifa_ifa.ifa_addr = (struct sockaddr *) &ifp->ifa_addr;
1811 /* Netmask */
1812 int prefix = pua->OnLinkPrefixLength;
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;
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 }
1828 if_sin6->sin6_family = AF_INET6;
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 */
1867 ifp->ifa_hwdata.ifa_metric = (sa->sa_family == AF_INET
1868 ? pap->Ipv4Metric : pap->Ipv6Metric);
1869 /* MTU */
1870 ifp->ifa_hwdata.ifa_mtu = pap->Mtu;
1871 /* Interface index */
1872 ifp->ifa_hwdata.ifa_ifindex = pap->IfIndex;
1873 /* Friendly name */
1874 get_friendlyname (ifp, pap);
1875 /* Let ifa_data member point to "ifaddrs_hwdata" data. */
1876 ifp->ifa_ifa.ifa_data = &ifp->ifa_hwdata;
1877 ++ifp;
1878 # undef sin
1879 # undef sin6
1880 }
1881 }
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;
1886
1887 done:
1888 if (pa0)
1889 free (pa0);
1890 return ifret;
1891 }
1892
1893 extern "C" int
1894 getifaddrs (struct ifaddrs **ifap)
1895 {
1896 if (!ifap)
1897 {
1898 set_errno (EINVAL);
1899 return -1;
1900 }
1901 struct ifall *ifp;
1902 ifp = get_ifs (AF_UNSPEC);
1903 *ifap = &ifp->ifa_ifa;
1904 return ifp ? 0 : -1;
1905 }
1906
1907 extern "C" void
1908 freeifaddrs (struct ifaddrs *ifp)
1909 {
1910 if (ifp)
1911 free (ifp);
1912 }
1913
1914 int
1915 get_ifconf (struct ifconf *ifc, unsigned int what)
1916 {
1917 __try
1918 {
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 }
1925
1926 struct ifall *ifret, *ifp;
1927 ifret = get_ifs (AF_INET);
1928 if (!ifret)
1929 __leave;
1930
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)
1935 {
1936 ++cnt;
1937 strcpy (ifr->ifr_name, ifp->ifa_name);
1938 switch (what)
1939 {
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:
1971 memcpy (&ifr->ifr_hwaddr, &ifp->ifa_hwdata.ifa_hwaddr,
1972 sizeof ifr->ifr_hwaddr);
1973 break;
1974 case SIOCGIFMETRIC:
1975 ifr->ifr_metric = ifp->ifa_hwdata.ifa_metric;
1976 break;
1977 case SIOCGIFMTU:
1978 ifr->ifr_mtu = ifp->ifa_hwdata.ifa_mtu;
1979 break;
1980 case SIOCGIFINDEX:
1981 ifr->ifr_ifindex = ifp->ifa_hwdata.ifa_ifindex;
1982 break;
1983 case SIOCGIFFRNDLYNAM:
1984 memcpy (ifr->ifr_frndlyname, &ifp->ifa_hwdata.ifa_frndlyname,
1985 sizeof (struct ifreq_frndlyname));
1986 }
1987 if ((caddr_t) ++ifr >
1988 ifc->ifc_buf + ifc->ifc_len - sizeof (struct ifreq))
1989 break;
1990 }
1991 /* Set the correct length */
1992 ifc->ifc_len = cnt * sizeof (struct ifreq);
1993 free (ifret);
1994 return 0;
1995 }
1996 __except (EFAULT) {}
1997 __endtry
1998 return -1;
1999 }
2000
2001 extern "C" unsigned
2002 cygwin_if_nametoindex (const char *name)
2003 {
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;
2015 }
2016
2017 extern "C" char *
2018 cygwin_if_indextoname (unsigned ifindex, char *ifname)
2019 {
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;
2038 }
2039
2040 extern "C" struct if_nameindex *
2041 if_nameindex (void)
2042 {
2043 PIP_ADAPTER_ADDRESSES pa0 = NULL, pap;
2044 struct if_nameindex *iflist = NULL;
2045 char (*ifnamelist)[IF_NAMESIZE];
2046
2047 __try
2048 {
2049 if (get_adapters_addresses (&pa0, AF_UNSPEC))
2050 {
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
2060 {
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;
2087 }
2088 free (pa0);
2089 }
2090 else
2091 set_errno (ENXIO);
2092 }
2093 __except (EFAULT) {}
2094 __endtry
2095 return iflist;
2096 }
2097
2098 extern "C" void
2099 if_freenameindex (struct if_nameindex *ptr)
2100 {
2101 free (ptr);
2102 }
2103
2104 #define PORT_LOW (IPPORT_EFSSERVER + 1)
2105 #define PORT_HIGH (IPPORT_RESERVED - 1)
2106 #define NUM_PORTS (PORT_HIGH - PORT_LOW + 1)
2107
2108 /* port is in host byte order */
2109 static in_port_t
2110 next_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
2168 extern "C" int
2169 cygwin_bindresvport_sa (int fd, struct sockaddr *sa)
2170 {
2171 struct sockaddr_storage sst;
2172 struct sockaddr_in *sin = NULL;
2173 struct sockaddr_in6 *sin6 = NULL;
2174 socklen_t salen;
2175 int ret = -1;
2176 LONG port, next_port;
2177
2178 __try
2179 {
2180 fhandler_socket *fh = get (fd);
2181 if (!fh)
2182 __leave;
2183
2184 if (!sa)
2185 {
2186 sa = (struct sockaddr *) &sst;
2187 memset (&sst, 0, sizeof sst);
2188 sa->sa_family = fh->get_addr_family ();
2189 }
2190 else if (sa->sa_family != fh->get_addr_family ())
2191 {
2192 set_errno (EPFNOSUPPORT);
2193 __leave;
2194 }
2195
2196 switch (sa->sa_family)
2197 {
2198 case AF_INET:
2199 salen = sizeof (struct sockaddr_in);
2200 sin = (struct sockaddr_in *) sa;
2201 break;
2202 case AF_INET6:
2203 salen = sizeof (struct sockaddr_in6);
2204 sin6 = (struct sockaddr_in6 *) sa;
2205 break;
2206 default:
2207 set_errno (EPFNOSUPPORT);
2208 __leave;
2209 }
2210
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. */
2215
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. */
2221 for (int i = 0; i < NUM_PORTS; i++)
2222 {
2223 while ((port = InterlockedExchange (
2224 &cygwin_shared->last_used_bindresvport, -1)) == -1)
2225 yield ();
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 }
2239 if (sa->sa_family == AF_INET6)
2240 sin6->sin6_port = htons (port);
2241 else
2242 sin->sin_port = htons (port);
2243 if (!(ret = fh->bind (sa, salen)))
2244 break;
2245 if (get_errno () != EADDRINUSE && get_errno () != EINVAL)
2246 break;
2247 }
2248
2249 }
2250 __except (EFAULT) {}
2251 __endtry
2252 return ret;
2253 }
2254
2255 extern "C" int
2256 cygwin_bindresvport (int fd, struct sockaddr_in *sin)
2257 {
2258 if (sin && sin->sin_family != AF_INET)
2259 {
2260 set_errno (EAFNOSUPPORT);
2261 return -1;
2262 }
2263 return cygwin_bindresvport_sa (fd, (struct sockaddr *) sin);
2264 }
2265
2266 /* socketpair: POSIX.1-2001, POSIX.1-2008, 4.4BSD. */
2267 extern "C" int
2268 socketpair (int af, int type, int protocol, int sv[2])
2269 {
2270 int res = -1;
2271 const device *dev;
2272 fhandler_socket *fh_in, *fh_out;
2273
2274 int flags = type & _SOCK_FLAG_MASK;
2275 type &= ~_SOCK_FLAG_MASK;
2276
2277 debug_printf ("socket (%d, %d (flags %y), %d)", af, type, flags, protocol);
2278
2279 switch (af)
2280 {
2281 case AF_LOCAL:
2282 #ifndef __WITH_AF_UNIX
2283 dev = af_local_dev;
2284 #else
2285 case AF_UNIX:
2286 dev = (af == AF_LOCAL) ? af_local_dev : af_unix_dev;
2287 #endif /* __WITH_AF_UNIX */
2288 break;
2289 default:
2290 set_errno (EAFNOSUPPORT);
2291 goto done;
2292 }
2293
2294 if ((flags & ~(SOCK_NONBLOCK | SOCK_CLOEXEC)) != 0)
2295 {
2296 set_errno (EINVAL);
2297 goto done;
2298 }
2299
2300 {
2301 cygheap_fdnew fd_in;
2302 if (fd_in < 0)
2303 goto done;
2304
2305 cygheap_fdnew fd_out (fd_in, false);
2306 if (fd_out < 0)
2307 goto done;
2308
2309 fh_in = reinterpret_cast<fhandler_socket *> (build_fh_dev (*dev));
2310 fh_out = reinterpret_cast<fhandler_socket *> (build_fh_dev (*dev));
2311 if (fh_in && fh_out
2312 && fh_in->socketpair (af, type, protocol, flags, fh_out) == 0)
2313 {
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
2321 {
2322 sv[0] = fd_in;
2323 sv[1] = fd_out;
2324 res = 0;
2325 }
2326 __except (EFAULT) {}
2327 __endtry
2328 }
2329 else
2330 {
2331 delete fh_in;
2332 delete fh_out;
2333 }
2334 }
2335
2336 done:
2337 syscall_printf ("%R = socketpair(...)", res);
2338 return res;
2339 }
2340
2341 /* sethostent: POSIX.1-2001 */
2342 extern "C" void
2343 sethostent (int)
2344 {
2345 }
2346
2347 /* endhostent: POSIX.1-2001 */
2348 extern "C" void
2349 endhostent (void)
2350 {
2351 }
2352
2353 /* exported as recvmsg: POSIX.1-2001, POSIX.1-2008, 4.4BSD */
2354 extern "C" ssize_t
2355 cygwin_recvmsg (int fd, struct msghdr *msg, int flags)
2356 {
2357 ssize_t res = -1;
2358
2359 pthread_testcancel ();
2360
2361 __try
2362 {
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 }
2374 }
2375 __except (EFAULT)
2376 {
2377 res = -1;
2378 }
2379 __endtry
2380 syscall_printf ("%lR = recvmsg(%d, %p, %y)", res, fd, msg, flags);
2381 return res;
2382 }
2383
2384 /* exported as sendmsg: POSIX.1-2001, POSIX.1-2008, 4.4BSD */
2385 extern "C" ssize_t
2386 cygwin_sendmsg (int fd, const struct msghdr *msg, int flags)
2387 {
2388 ssize_t res = -1;
2389
2390 pthread_testcancel ();
2391
2392 __try
2393 {
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 }
2401 }
2402 __except (EFAULT)
2403 {
2404 res = -1;
2405 }
2406 __endtry
2407 syscall_printf ("%lR = sendmsg(%d, %p, %y)", res, fd, msg, flags);
2408 return res;
2409 }
2410
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
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 */
2439 static int
2440 inet_pton4 (const char *src, u_int8_t *dst)
2441 {
2442 static const char digits[] = "0123456789";
2443 int saw_digit, octets, ch;
2444 u_int8_t tmp[INADDRSZ], *tp;
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)
2454 {
2455 u_int32_t ret = *tp * 10 + (pch - digits);
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)
2468 {
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 */
2497 static int
2498 inet_pton6 (const char *src, u_int8_t *dst)
2499 {
2500 static const char xdigits_l[] = "0123456789abcdef",
2501 xdigits_u[] = "0123456789ABCDEF";
2502 u_int8_t tmp[IN6ADDRSZ], *tp, *endp, *colonp;
2503 const char *xdigits, *curtok;
2504 int ch, saw_xdigit;
2505 u_int32_t val;
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)
2524 {
2525 val <<= 4;
2526 val |= (pch - xdigits);
2527 if (val > 0xffff)
2528 return (0);
2529 saw_xdigit = 1;
2530 continue;
2531 }
2532 if (ch == ':')
2533 {
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);
2544 *tp++ = (u_int8_t) (val >> 8) & 0xff;
2545 *tp++ = (u_int8_t) val & 0xff;
2546 saw_xdigit = 0;
2547 val = 0;
2548 continue;
2549 }
2550 if (ch == '.' && ((tp + INADDRSZ) <= endp) && inet_pton4(curtok, tp) > 0)
2551 {
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);
2562 *tp++ = (u_int8_t) (val >> 8) & 0xff;
2563 *tp++ = (u_int8_t) val & 0xff;
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++)
2575 {
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 */
2599 extern "C" int
2600 cygwin_inet_pton (int af, const char *src, void *dst)
2601 {
2602 switch (af)
2603 {
2604 case AF_INET:
2605 return (inet_pton4(src, (u_int8_t *) dst));
2606 case AF_INET6:
2607 return (inet_pton6(src, (u_int8_t *) dst));
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
2622 * (2) takes a u_int8_t* not an in_addr as input
2623 * author:
2624 * Paul Vixie, 1996.
2625 */
2626 static const char *
2627 inet_ntop4 (const u_int8_t *src, char *dst, size_t size)
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 */
2648 static const char *
2649 inet_ntop6 (const u_int8_t *src, char *dst, size_t size)
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;
2660 u_int32_t words[IN6ADDRSZ / INT16SZ];
2661 int i;
2662
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;
2673 best.len = 0;
2674 cur.len = 0;
2675 for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++)
2676 {
2677 if (words[i] == 0)
2678 {
2679 if (cur.base == -1)
2680 cur.base = i, cur.len = 1;
2681 else
2682 cur.len++;
2683 }
2684 else
2685 {
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))
2710 {
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)))
2721 {
2722 if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp)))
2723 return (NULL);
2724 tp += strlen(tp);
2725 break;
2726 }
2727 __small_sprintf(tp, "%x", words[i]);
2728 while (*tp)
2729 {
2730 if (isupper (*tp))
2731 *tp = _tolower (*tp);
2732 ++tp;
2733 }
2734 }
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);
2750 }
2751
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 */
2760 extern "C" const char *
2761 cygwin_inet_ntop (int af, const void *src, char *dst, socklen_t size)
2762 {
2763 switch (af)
2764 {
2765 case AF_INET:
2766 return (inet_ntop4((const u_int8_t *) src, dst, size));
2767 case AF_INET6:
2768 return (inet_ntop6((const u_int8_t *) src, dst, size));
2769 default:
2770 errno = EAFNOSUPPORT;
2771 return (NULL);
2772 }
2773 /* NOTREACHED */
2774 }
2775
2776 /* Exported as freeaddrinfo: POSIX.1-2001, POSIX.1-2008, RFC 2553 */
2777 extern "C" void
2778 cygwin_freeaddrinfo (struct addrinfo *addr)
2779 {
2780 struct addrinfo *ai, *ainext;
2781
2782 for (ai = addr; ai != NULL; ai = ainext)
2783 {
2784 if (ai->ai_addr != NULL)
2785 free (ai->ai_addr); /* socket address structure */
2786
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 */
2792 }
2793 }
2794
2795 static struct addrinfo *
2796 ga_dup (struct addrinfoW *ai, bool v4mapped, int idn_flags, int &err)
2797 {
2798 struct addrinfo *nai;
2799
2800 if ((nai = (struct addrinfo *) calloc (1, sizeof (struct addrinfo))) == NULL)
2801 {
2802 err = EAI_MEMORY;
2803 return NULL;
2804 }
2805
2806 nai->ai_family = v4mapped ? AF_INET6 : ai->ai_family;
2807 nai->ai_socktype = ai->ai_socktype;
2808 nai->ai_protocol = ai->ai_protocol;
2809 if (ai->ai_canonname)
2810 {
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);
2843 }
2844
2845 nai->ai_addrlen = v4mapped ? sizeof (struct sockaddr_in6) : ai->ai_addrlen;
2846 if ((nai->ai_addr = (struct sockaddr *) malloc (v4mapped
2847 ? sizeof (struct sockaddr_in6)
2848 : ai->ai_addrlen)) == NULL)
2849 {
2850 if (nai->ai_canonname)
2851 free (nai->ai_canonname);
2852 free (nai);
2853 err = EAI_MEMORY;
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
2874 static struct addrinfo *
2875 ga_duplist (struct addrinfoW *ai, bool v4mapped, int idn_flags, int &err)
2876 {
2877 struct addrinfo *tmp, *nai = NULL, *nai0 = NULL;
2878
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 }
2928 if (!(tmp = ga_dup (ai, v4mapped, idn_flags, err)))
2929 goto bad;
2930 if (!nai0)
2931 nai0 = tmp;
2932 if (nai)
2933 nai->ai_next = tmp;
2934 nai = tmp;
2935 }
2936 return nai0;
2937
2938 bad:
2939 cygwin_freeaddrinfo (nai0);
2940 return NULL;
2941 }
2942
2943 /* Cygwin specific wrappers around the gai functions. */
2944 static const struct gai_errmap_t
2945 {
2946 int w32_errval;
2947 const char *errtxt;
2948 } gai_errmap[] =
2949 {
2950 {0, "Success"},
2951 /* EAI_ADDRFAMILY */
2952 {0, "Address family for hostname not supported"},
2953 /* EAI_AGAIN */
2954 {WSATRY_AGAIN, "Temporary failure in name resolution"},
2955 /* EAI_BADFLAGS */
2956 {WSAEINVAL, "Bad value for ai_flags"},
2957 /* EAI_FAIL */
2958 {WSANO_RECOVERY, "Non-recoverable failure in name resolution"},
2959 /* EAI_FAMILY */
2960 {WSAEAFNOSUPPORT, "ai_family not supported"},
2961 /* EAI_MEMORY */
2962 {WSA_NOT_ENOUGH_MEMORY, "Memory allocation failure"},
2963 /* EAI_NODATA */
2964 {WSANO_DATA, "No address associated with hostname"},
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 */
2970 {WSAESOCKTNOSUPPORT, "ai_socktype not supported"},
2971 /* EAI_SYSTEM */
2972 {0, "System error"},
2973 /* EAI_BADHINTS */
2974 {0, "Invalid value for hints"},
2975 /* EAI_PROTOCOL */
2976 {0, "Resolved protocol is unknown"},
2977 /* EAI_OVERFLOW */
2978 {WSAEFAULT, "An argument buffer overflowed"},
2979 /* EAI_IDN_ENCODE */
2980 {0, "Parameter string not correctly encoded"}
2981 };
2982
2983 /* Exported as gai_strerror: POSIX.1-2001, POSIX.1-2008 */
2984 extern "C" const char *
2985 cygwin_gai_strerror (int err)
2986 {
2987 if (err >= 0 && err < (int) (sizeof gai_errmap / sizeof *gai_errmap))
2988 return gai_errmap[err].errtxt;
2989 return "Unknown error";
2990 }
2991
2992 static int
2993 w32_to_gai_err (int w32_err)
2994 {
2995 if (w32_err >= WSABASEERR)
2996 for (unsigned i = 0; i < sizeof gai_errmap / sizeof *gai_errmap; ++i)
2997 if (gai_errmap[i].w32_errval == w32_err)
2998 return i;
2999 return w32_err;
3000 }
3001
3002 /* Exported as getaddrinfo: POSIX.1-2001, POSIX.1-2008, RFC 2553 */
3003 extern "C" int
3004 cygwin_getaddrinfo (const char *hostname, const char *servname,
3005 const struct addrinfo *hints, struct addrinfo **res)
3006 {
3007 int ret = 0;
3008
3009 /* Windows' getaddrinfo implementations lets all possible values
3010 in ai_flags slip through and just ignores unknown values. So we
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
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;
3026 /* AI_NUMERICSERV is not supported "by Microsoft providers". We just
3027 check the servname parameter by ourselves here. */
3028 if (hints && (hints->ai_flags & AI_NUMERICSERV))
3029 {
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)
3048 return EAI_IDN_ENCODE;
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;
3070 }
3071
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;
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;
3087 /* On Windows, the default behaviour is as if AI_ADDRCONFIG is set,
3088 apparently for performance reasons. To get the POSIX default
3089 behaviour, the AI_ALL flag has to be set. */
3090 if (whints.ai_family == PF_UNSPEC
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;
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);
3106 /* Always copy over to self-allocated memory. */
3107 if (!ret)
3108 {
3109 *res = ga_duplist (wres, false, idn_flags, ret);
3110 FreeAddrInfoW (wres);
3111 if (!*res)
3112 __leave;
3113 }
3114 }
3115 __except (EFAULT)
3116 {
3117 ret = EAI_SYSTEM;
3118 }
3119 __endtry
3120 return ret;
3121 }
3122
3123 /* Exported as getnameinfo: POSIX.1-2001, POSIX.1-2008, RFC 2553 */
3124 extern "C" int
3125 cygwin_getnameinfo (const struct sockaddr *sa, socklen_t salen,
3126 char *host, size_t hostlen, char *serv,
3127 size_t servlen, int flags)
3128 {
3129 int ret = 0;
3130
3131 __try
3132 {
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. */
3135 #define NI_IDN_MASK (NI_IDN | \
3136 NI_IDN_ALLOW_UNASSIGNED | \
3137 NI_IDN_USE_STD3_ASCII_RULES)
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;
3143
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 }
3154
3155 ret = w32_to_gai_err (GetNameInfoW (sa, salen, whost, whlen,
3156 wserv, wslen, flags));
3157 if (!ret)
3158 {
3159 const wchar_t *src;
3160
3161 if (whost)
3162 {
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)
3175 return EAI_IDN_ENCODE;
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;
3186 }
3187 }
3188 else if (ret == EAI_SYSTEM)
3189 set_winsock_errno ();
3190 }
3191 __except (EFAULT)
3192 {
3193 ret = EAI_SYSTEM;
3194 }
3195 __endtry
3196 return ret;
3197 }
3198
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
3207 /* htonl: POSIX.1-2001, POSIX.1-2008 */
3208 extern "C" uint32_t
3209 htonl (uint32_t x)
3210 {
3211 return __htonl (x);
3212 }
3213
3214 /* ntohl: POSIX.1-2001, POSIX.1-2008 */
3215 extern "C" uint32_t
3216 ntohl (uint32_t x)
3217 {
3218 return __ntohl (x);
3219 }
3220
3221 /* htons: POSIX.1-2001, POSIX.1-2008 */
3222 extern "C" uint16_t
3223 htons (uint16_t x)
3224 {
3225 return __htons (x);
3226 }
3227
3228 /* ntohs: POSIX.1-2001, POSIX.1-2008 */
3229 extern "C" uint16_t
3230 ntohs (uint16_t x)
3231 {
3232 return __ntohs (x);
3233 }
This page took 0.174372 seconds and 6 git commands to generate.