]> sourceware.org Git - newlib-cygwin.git/blame - winsup/cygwin/net.cc
* Merge in cygwin-64bit-branch.
[newlib-cygwin.git] / winsup / cygwin / net.cc
CommitLineData
1fd5e000
CF
1/* net.cc: network-related routines.
2
bc837d22 3 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
61522196 4 2007, 2008, 2009, 2010, 2011, 2012, 2013 Red Hat, Inc.
1fd5e000
CF
5
6This file is part of Cygwin.
7
8This software is a copyrighted work licensed under the terms of the
9Cygwin license. Please consult the file "CYGWIN_LICENSE" for
10details. */
11
12/* #define DEBUG_NEST_ON 1 */
13
14#define __INSIDE_CYGWIN_NET__
acddda4b
CV
15#define USE_SYS_TYPES_FD_SET
16#define __WSA_ERR_MACROS_DEFINED
17/* FIXME: Collision with different declarations of if_nametoindex and
46f5dd59 18 if_indextoname functions in iphlpapi.h since Vista.
acddda4b
CV
19 TODO: Convert if_nametoindex to cygwin_if_nametoindex and call
20 system functions on Vista and later. */
21#define _INC_NETIOAPI
4c8d72de 22#include "winsup.h"
acddda4b
CV
23#include <ws2tcpip.h>
24#include <mswsock.h>
25#include <iphlpapi.h>
ade47a34 26#include "miscfuncs.h"
cf762b08 27#include <ctype.h>
ba047ace 28#include <wchar.h>
619f7fa0 29#include <stdlib.h>
68115c74 30#define gethostname cygwin_gethostname
84c7d409 31#include <unistd.h>
68115c74 32#undef gethostname
1fd5e000 33#include <netdb.h>
acddda4b 34#include <cygwin/in.h>
2895b8b5 35#include <asm/byteorder.h>
edf16a29 36#include <assert.h>
bccd5e0d 37#include "cygerrno.h"
6b91b8d5 38#include "security.h"
8b00a766 39#include "cygwin/version.h"
db5ae618 40#include "shared_info.h"
8b00a766 41#include "perprocess.h"
bccd5e0d 42#include "path.h"
7ac61736 43#include "fhandler.h"
e2ebe117 44#include "dtable.h"
0381fec6 45#include "cygheap.h"
bccd5e0d 46#include "sigproc.h"
f0338f54 47#include "registry.h"
29d52c8a 48#include "cygtls.h"
a71ecb55 49#include "ifaddrs.h"
ba047ace 50#include "tls_pbuf.h"
cbc26145 51#include "ntdll.h"
acddda4b
CV
52
53/* Unfortunately defined in Windows header files and arpa/nameser_compat.h. */
54#undef NOERROR
55#undef DELETE
0a20e5a0 56#define _CYGWIN_IN_H
6f57cb4a 57#include <resolv.h>
1fd5e000 58
79224853
CV
59extern "C"
60{
61 int h_errno;
1fd5e000 62
79224853
CV
63 int __stdcall rcmd (char **ahost, unsigned short inport, char *locuser,
64 char *remuser, char *cmd, SOCKET * fd2p);
79224853 65 int sscanf (const char *, const char *, ...);
72203114
CV
66 int cygwin_inet_aton(const char *, struct in_addr *);
67 const char *cygwin_inet_ntop (int, const void *, char *, socklen_t);
6f57cb4a
CV
68 int dn_length1(const unsigned char *, const unsigned char *,
69 const unsigned char *);
79224853 70} /* End of "C" section */
1fd5e000 71
81ba2b77
CF
72const struct in6_addr in6addr_any = {{IN6ADDR_ANY_INIT}};
73const struct in6_addr in6addr_loopback = {{IN6ADDR_LOOPBACK_INIT}};
70e476d2 74
5a64d869 75static fhandler_socket *
b4f06520 76get (const int fd)
5a64d869
CF
77{
78 cygheap_fdget cfd (fd);
79224853 79
5a64d869
CF
80 if (cfd < 0)
81 return 0;
82
b4f06520 83 fhandler_socket *const fh = cfd->is_socket ();
79224853 84
b4f06520
CS
85 if (!fh)
86 set_errno (ENOTSOCK);
87
88 return fh;
5a64d869
CF
89}
90
0bec0119 91/* exported as inet_ntoa: BSD 4.3 */
4e6a4ea8 92extern "C" char *
1fd5e000
CF
93cygwin_inet_ntoa (struct in_addr in)
94{
72203114
CV
95 char buf[20];
96 const char *res = cygwin_inet_ntop (AF_INET, &in, buf, sizeof buf);
79224853 97
29d52c8a 98 if (_my_tls.locals.ntoa_buf)
1fdc8df9 99 {
29d52c8a
CF
100 free (_my_tls.locals.ntoa_buf);
101 _my_tls.locals.ntoa_buf = NULL;
1fdc8df9
CV
102 }
103 if (res)
29d52c8a
CF
104 _my_tls.locals.ntoa_buf = strdup (res);
105 return _my_tls.locals.ntoa_buf;
1fd5e000
CF
106}
107
1fd5e000
CF
108/* inet_netof is in the standard BSD sockets library. It is useless
109 for modern networks, since it assumes network values which are no
110 longer meaningful, but some existing code calls it. */
111
4e6a4ea8 112extern "C" unsigned long
1fd5e000
CF
113inet_netof (struct in_addr in)
114{
115 unsigned long i, res;
116
1fd5e000
CF
117 i = ntohl (in.s_addr);
118 if (IN_CLASSA (i))
119 res = (i & IN_CLASSA_NET) >> IN_CLASSA_NSHIFT;
120 else if (IN_CLASSB (i))
121 res = (i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT;
122 else
123 res = (i & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT;
124
1fd5e000
CF
125 return res;
126}
127
128/* inet_makeaddr is in the standard BSD sockets library. It is
129 useless for modern networks, since it assumes network values which
130 are no longer meaningful, but some existing code calls it. */
131
4e6a4ea8 132extern "C" struct in_addr
1fd5e000
CF
133inet_makeaddr (int net, int lna)
134{
135 unsigned long i;
53a12585 136 struct in_addr in;
1fd5e000
CF
137
138 if (net < IN_CLASSA_MAX)
139 i = (net << IN_CLASSA_NSHIFT) | (lna & IN_CLASSA_HOST);
140 else if (net < IN_CLASSB_MAX)
141 i = (net << IN_CLASSB_NSHIFT) | (lna & IN_CLASSB_HOST);
142 else if (net < 0x1000000)
143 i = (net << IN_CLASSC_NSHIFT) | (lna & IN_CLASSC_HOST);
144 else
145 i = net | lna;
146
147 in.s_addr = htonl (i);
148
149
150 return in;
151}
152
153struct tl
154{
155 int w;
156 const char *s;
157 int e;
158};
159
61522196 160static const struct tl errmap[] = {
79224853
CV
161 {WSAEINTR, "WSAEINTR", EINTR},
162 {WSAEWOULDBLOCK, "WSAEWOULDBLOCK", EWOULDBLOCK},
163 {WSAEINPROGRESS, "WSAEINPROGRESS", EINPROGRESS},
164 {WSAEALREADY, "WSAEALREADY", EALREADY},
165 {WSAENOTSOCK, "WSAENOTSOCK", ENOTSOCK},
166 {WSAEDESTADDRREQ, "WSAEDESTADDRREQ", EDESTADDRREQ},
167 {WSAEMSGSIZE, "WSAEMSGSIZE", EMSGSIZE},
168 {WSAEPROTOTYPE, "WSAEPROTOTYPE", EPROTOTYPE},
169 {WSAENOPROTOOPT, "WSAENOPROTOOPT", ENOPROTOOPT},
170 {WSAEPROTONOSUPPORT, "WSAEPROTONOSUPPORT", EPROTONOSUPPORT},
171 {WSAESOCKTNOSUPPORT, "WSAESOCKTNOSUPPORT", ESOCKTNOSUPPORT},
172 {WSAEOPNOTSUPP, "WSAEOPNOTSUPP", EOPNOTSUPP},
173 {WSAEPFNOSUPPORT, "WSAEPFNOSUPPORT", EPFNOSUPPORT},
174 {WSAEAFNOSUPPORT, "WSAEAFNOSUPPORT", EAFNOSUPPORT},
175 {WSAEADDRINUSE, "WSAEADDRINUSE", EADDRINUSE},
176 {WSAEADDRNOTAVAIL, "WSAEADDRNOTAVAIL", EADDRNOTAVAIL},
177 {WSAENETDOWN, "WSAENETDOWN", ENETDOWN},
178 {WSAENETUNREACH, "WSAENETUNREACH", ENETUNREACH},
179 {WSAENETRESET, "WSAENETRESET", ENETRESET},
180 {WSAECONNABORTED, "WSAECONNABORTED", ECONNABORTED},
181 {WSAECONNRESET, "WSAECONNRESET", ECONNRESET},
182 {WSAENOBUFS, "WSAENOBUFS", ENOBUFS},
183 {WSAEISCONN, "WSAEISCONN", EISCONN},
184 {WSAENOTCONN, "WSAENOTCONN", ENOTCONN},
185 {WSAESHUTDOWN, "WSAESHUTDOWN", ESHUTDOWN},
186 {WSAETOOMANYREFS, "WSAETOOMANYREFS", ETOOMANYREFS},
187 {WSAETIMEDOUT, "WSAETIMEDOUT", ETIMEDOUT},
188 {WSAECONNREFUSED, "WSAECONNREFUSED", ECONNREFUSED},
189 {WSAELOOP, "WSAELOOP", ELOOP},
190 {WSAENAMETOOLONG, "WSAENAMETOOLONG", ENAMETOOLONG},
191 {WSAEHOSTDOWN, "WSAEHOSTDOWN", EHOSTDOWN},
192 {WSAEHOSTUNREACH, "WSAEHOSTUNREACH", EHOSTUNREACH},
193 {WSAENOTEMPTY, "WSAENOTEMPTY", ENOTEMPTY},
194 {WSAEPROCLIM, "WSAEPROCLIM", EPROCLIM},
195 {WSAEUSERS, "WSAEUSERS", EUSERS},
196 {WSAEDQUOT, "WSAEDQUOT", EDQUOT},
197 {WSAESTALE, "WSAESTALE", ESTALE},
198 {WSAEREMOTE, "WSAEREMOTE", EREMOTE},
199 {WSAEINVAL, "WSAEINVAL", EINVAL},
200 {WSAEFAULT, "WSAEFAULT", EFAULT},
201 {0, "NOERROR", 0},
202 {0, NULL, 0}
1fd5e000
CF
203};
204
c90e420d
CF
205static int
206find_winsock_errno (int why)
207{
f940c5b1 208 for (int i = 0; errmap[i].s != NULL; ++i)
c90e420d
CF
209 if (why == errmap[i].w)
210 return errmap[i].e;
211
212 return EPERM;
213}
214
1fd5e000 215void
829425c9 216__set_winsock_errno (const char *fn, int ln)
1fd5e000 217{
c90e420d
CF
218 DWORD werr = WSAGetLastError ();
219 int err = find_winsock_errno (werr);
79224853 220
c90e420d 221 set_errno (err);
61522196 222 syscall_printf ("%s:%d - winsock error %u -> errno %d", fn, ln, werr, err);
1fd5e000
CF
223}
224
7d9688b7
CV
225/*
226 * Since the member `s' isn't used for debug output we can use it
227 * for the error text returned by herror and hstrerror.
228 */
61522196 229static const struct tl host_errmap[] = {
7d9688b7
CV
230 {WSAHOST_NOT_FOUND, "Unknown host", HOST_NOT_FOUND},
231 {WSATRY_AGAIN, "Host name lookup failure", TRY_AGAIN},
232 {WSANO_RECOVERY, "Unknown server error", NO_RECOVERY},
233 {WSANO_DATA, "No address associated with name", NO_DATA},
01cf5d0f 234 {0, NULL, 0}
1fd5e000
CF
235};
236
1fd5e000
CF
237static void
238set_host_errno ()
239{
240 int i;
241
242 int why = WSAGetLastError ();
79224853 243
7d9688b7 244 for (i = 0; host_errmap[i].w != 0; ++i)
1fd5e000
CF
245 if (why == host_errmap[i].w)
246 break;
247
248 if (host_errmap[i].w != 0)
249 h_errno = host_errmap[i].e;
250 else
251 h_errno = NETDB_INTERNAL;
252}
253
edf16a29
CF
254inline int
255DWORD_round (int n)
1fdc8df9 256{
edf16a29 257 return sizeof (DWORD) * (((n + sizeof (DWORD) - 1)) / sizeof (DWORD));
1fdc8df9
CV
258}
259
edf16a29
CF
260inline int
261strlen_round (const char *s)
1fdc8df9 262{
edf16a29
CF
263 if (!s)
264 return 0;
265 return DWORD_round (strlen (s) + 1);
1fdc8df9
CV
266}
267
edf16a29
CF
268#pragma pack(push,2)
269struct pservent
5d0fe635 270{
edf16a29
CF
271 char *s_name;
272 char **s_aliases;
273 short s_port;
274 char *s_proto;
275};
276#pragma pack(pop)
1ff9f4b9 277
a3de4e19
CF
278static const char *entnames[] = {"host", "proto", "serv"};
279
6f57cb4a
CV
280static unionent *
281realloc_ent (unionent *&dst, int sz)
282{
283 /* Allocate the storage needed. Allocate a rounded size to attempt to force
284 reuse of this buffer so that a poorly-written caller will not be using
285 a freed buffer. */
286 unsigned rsz = 256 * ((sz + 255) / 256);
287 unionent * ptr;
288 if ((ptr = (unionent *) realloc (dst, rsz)))
289 dst = ptr;
290 return ptr;
291}
292
293static inline hostent *
294realloc_ent (int sz, hostent *)
295{
296 return (hostent *) realloc_ent (_my_tls.locals.hostent_buf, sz);
297}
298
edf16a29
CF
299/* Generic "dup a {host,proto,serv}ent structure" function.
300 This is complicated because we need to be able to free the
301 structure at any point and we can't rely on the pointer contents
302 being untouched by callers. So, we allocate a chunk of memory
303 large enough to hold the structure and all of the stuff it points
304 to then we copy the source into this new block of memory.
305 The 'unionent' struct is a union of all of the currently used
306 *ent structure. */
307
61522196
CV
308#ifdef __x86_64__
309/* For some baffling reason, somebody at Microsoft decided that it would be
310 a good idea to exchange the s_port and s_proto members in the servent
311 structure. */
312struct win64_servent
313{
314 char *s_name;
315 char **s_aliases;
316 char *s_proto;
317 short s_port;
318};
319#define WIN_SERVENT(x) ((win64_servent *)(x))
320#else
321#define WIN_SERVENT(x) ((servent *)(x))
322#endif
323
edf16a29
CF
324#ifdef DEBUGGING
325static void *
326#else
327static inline void *
328#endif
f2c11dad 329dup_ent (unionent *&dst, unionent *src, unionent::struct_type type)
1fdc8df9 330{
fe836470
CF
331 if (dst)
332 debug_printf ("old %sent structure \"%s\" %p\n", entnames[type],
f2c11dad 333 dst->name, dst);
fe836470
CF
334
335 if (!src)
a3de4e19 336 {
fe836470
CF
337 set_winsock_errno ();
338 return NULL;
a3de4e19
CF
339 }
340
8b59143f 341 debug_printf ("duping %sent \"%s\", %p", entnames[type], src->name, src);
1fdc8df9 342
edf16a29
CF
343 /* Find the size of the raw structure minus any character strings, etc. */
344 int sz, struct_sz;
345 switch (type)
346 {
f2c11dad 347 case unionent::t_protoent:
edf16a29
CF
348 struct_sz = sizeof (protoent);
349 break;
f2c11dad 350 case unionent::t_servent:
edf16a29
CF
351 struct_sz = sizeof (servent);
352 break;
f2c11dad 353 case unionent::t_hostent:
edf16a29
CF
354 struct_sz = sizeof (hostent);
355 break;
356 default:
357 api_fatal ("called with invalid value %d", type);
358 break;
1fdc8df9 359 }
1fdc8df9 360
6f57cb4a 361 /* Every *ent begins with a name. Calculate its length. */
edf16a29
CF
362 int namelen = strlen_round (src->name);
363 sz = struct_sz + namelen;
1fdc8df9 364
edf16a29
CF
365 char **av;
366 /* The next field in every *ent is an argv list of "something".
367 Calculate the number of components and how much space the
368 character strings will take. */
369 int list_len = 0;
370 for (av = src->list; av && *av; av++)
371 {
372 list_len++;
373 sz += sizeof (char **) + strlen_round (*av);
374 }
79224853 375
edf16a29
CF
376 /* NULL terminate if there actually was a list */
377 if (av)
378 {
379 sz += sizeof (char **);
380 list_len++;
381 }
1fdc8df9 382
edf16a29
CF
383 /* Do servent/hostent specific processing */
384 int protolen = 0;
385 int addr_list_len = 0;
f2c11dad 386 if (type == unionent::t_servent)
dff017b2 387 {
61522196
CV
388 if (WIN_SERVENT (src)->s_proto)
389 sz += (protolen = strlen_round (WIN_SERVENT (src)->s_proto));
dff017b2 390 }
f2c11dad 391 else if (type == unionent::t_hostent)
edf16a29
CF
392 {
393 /* Calculate the length and storage used for h_addr_list */
394 for (av = src->h_addr_list; av && *av; av++)
395 {
396 addr_list_len++;
397 sz += sizeof (char **) + DWORD_round (src->h_len);
398 }
399 if (av)
400 {
401 sz += sizeof (char **);
402 addr_list_len++;
403 }
404 }
1fdc8df9 405
6f57cb4a
CV
406 /* Allocate the storage needed. */
407 if (realloc_ent (dst, sz))
edf16a29 408 {
fe836470 409 memset (dst, 0, sz);
edf16a29 410 /* This field is common to all *ent structures but named differently
61522196
CV
411 in each, of course. Also, take 64 bit Windows servent weirdness
412 into account. */
413 if (type == unionent::t_servent)
414 dst->port_proto_addrtype = WIN_SERVENT (src)->s_port;
415 else
416 dst->port_proto_addrtype = src->port_proto_addrtype;
edf16a29 417
edf16a29 418 char *dp = ((char *) dst) + struct_sz;
8b59143f
CF
419 if (namelen)
420 {
421 /* Copy the name field to dst, using space just beyond the end of
422 the dst structure. */
423 strcpy (dst->name = dp, src->name);
424 dp += namelen;
425 }
edf16a29
CF
426
427 /* Copy the 'list' type to dst, using space beyond end of structure
428 + storage for name. */
429 if (src->list)
430 {
431 char **dav = dst->list = (char **) dp;
432 dp += sizeof (char **) * list_len;
433 for (av = src->list; av && *av; av++)
434 {
435 int len = strlen (*av) + 1;
436 memcpy (*dav++ = dp, *av, len);
437 dp += DWORD_round (len);
438 }
439 }
1fdc8df9 440
fe836470 441 /* Do servent/protoent/hostent specific processing. */
f2c11dad 442 if (type == unionent::t_protoent)
61522196 443 debug_printf ("protoent %s %p %y", dst->name, dst->list, dst->port_proto_addrtype);
f2c11dad 444 else if (type == unionent::t_servent)
edf16a29 445 {
61522196 446 if (WIN_SERVENT (src)->s_proto)
edf16a29 447 {
61522196 448 strcpy (dst->s_proto = dp, WIN_SERVENT (src)->s_proto);
edf16a29
CF
449 dp += protolen;
450 }
451 }
f2c11dad 452 else if (type == unionent::t_hostent)
edf16a29
CF
453 {
454 /* Transfer h_len and duplicate contents of h_addr_list, using
455 memory after 'list' allocation. */
456 dst->h_len = src->h_len;
457 char **dav = dst->h_addr_list = (char **) dp;
458 dp += sizeof (char **) * addr_list_len;
459 for (av = src->h_addr_list; av && *av; av++)
460 {
461 memcpy (*dav++ = dp, *av, src->h_len);
462 dp += DWORD_round (src->h_len);
463 }
464 }
465 /* Sanity check that we did our bookkeeping correctly. */
466 assert ((dp - (char *) dst) == sz);
467 }
a3de4e19 468 debug_printf ("duped %sent \"%s\", %p", entnames[type], dst ? dst->name : "<null!>", dst);
1fdc8df9 469 return dst;
1fdc8df9
CV
470}
471
f2c11dad
CF
472static inline hostent *
473dup_ent (hostent *src)
474{
475 return (hostent *) dup_ent (_my_tls.locals.hostent_buf, (unionent *) src, unionent::t_hostent);
476}
477
478static inline protoent *
479dup_ent (protoent *src)
480{
481 return (protoent *) dup_ent (_my_tls.locals.protoent_buf, (unionent *) src, unionent::t_protoent);
482}
483
484static inline servent *
485dup_ent (servent *src)
486{
487 return (servent *) dup_ent (_my_tls.locals.servent_buf, (unionent *) src, unionent::t_servent);
488}
489
1fd5e000 490/* exported as getprotobyname: standards? */
4e6a4ea8 491extern "C" struct protoent *
1fd5e000
CF
492cygwin_getprotobyname (const char *p)
493{
893ac8e0
CF
494 myfault efault;
495 if (efault.faulted (EFAULT))
5a64d869 496 return NULL;
f2c11dad 497 return dup_ent (getprotobyname (p));
1fd5e000
CF
498}
499
500/* exported as getprotobynumber: standards? */
4e6a4ea8 501extern "C" struct protoent *
1fd5e000
CF
502cygwin_getprotobynumber (int number)
503{
f2c11dad 504 return dup_ent (getprotobynumber (number));
1fd5e000
CF
505}
506
a011f952
CV
507#ifndef SIO_BASE_HANDLE
508#define SIO_BASE_HANDLE _WSAIOR(IOC_WS2,34)
509#endif
510
7ac61736
CF
511bool
512fdsock (cygheap_fdmanip& fd, const device *dev, SOCKET soc)
1fd5e000 513{
ab362395
CV
514 int size;
515
7ac61736
CF
516 fd = build_fh_dev (*dev);
517 if (!fd.isopen ())
518 return false;
8f56da76 519
b14f53a8
CV
520 /* Usually sockets are inheritable IFS objects. Unfortunately some virus
521 scanners or other network-oriented software replace normal sockets
a011f952
CV
522 with their own kind, which is running through a filter driver called
523 "layered service provider" (LSP).
b86f999a 524
a011f952
CV
525 LSP sockets are not kernel objects. They are typically not marked as
526 inheritable, nor are they IFS handles. They are in fact not inheritable
527 to child processes, and it does not help to mark them inheritable via
528 SetHandleInformation. Subsequent socket calls in the child process fail
b86f999a 529 with error 10038, WSAENOTSOCK.
a011f952
CV
530
531 The only way up to Windows Server 2003 to make these sockets usable in
532 child processes is to duplicate them via WSADuplicateSocket/WSASocket
533 calls. This requires to start the child process in SUSPENDED state so
534 we only do this on affected systems. If we recognize a non-inheritable
535 socket we switch to inheritance/dup via WSADuplicateSocket/WSASocket for
536 that socket.
1b23b30b 537
a011f952
CV
538 Starting with Vista there's another neat way to workaround these annoying
539 LSP sockets. WSAIoctl allows to fetch the underlying base socket, which
540 is a normal, inheritable IFS handle. So we fetch the base socket,
541 duplicate it, and close the original socket. Now we have a standard IFS
542 socket which (hopefully) works as expected. */
b14f53a8 543 DWORD flags;
a011f952 544 bool fixup = false;
b14f53a8 545 if (!GetHandleInformation ((HANDLE) soc, &flags)
27bbefde 546 || !(flags & HANDLE_FLAG_INHERIT))
a011f952
CV
547 {
548 int ret;
549 SOCKET base_soc;
550 DWORD bret;
551
552 fixup = true;
553 debug_printf ("LSP handle: %p", soc);
554 ret = WSAIoctl (soc, SIO_BASE_HANDLE, NULL, 0, (void *) &base_soc,
555 sizeof (base_soc), &bret, NULL, NULL);
556 if (ret)
61522196 557 debug_printf ("WSAIoctl: %u", WSAGetLastError ());
07a6b9dd 558 else if (base_soc != soc)
a011f952 559 {
07a6b9dd
CV
560 /* LSPs are often BLODAs as well. So we print an info about
561 detecting an LSP if BLODA detection is desired. */
562 if (detect_bloda)
a011f952 563 {
07a6b9dd
CV
564 WSAPROTOCOL_INFO prot;
565
566 memset (&prot, 0, sizeof prot);
567 ::getsockopt (soc, SOL_SOCKET, SO_PROTOCOL_INFO, (char *) &prot,
568 (size = sizeof prot, &size));
569 small_printf ("\n\nPotential BLODA detected! Layered Socket "
570 "Service Provider:\n %s\n\n", prot.szProtocol);
571 }
572 if (GetHandleInformation ((HANDLE) base_soc, &flags)
573 && (flags & HANDLE_FLAG_INHERIT))
574 {
575 if (!DuplicateHandle (GetCurrentProcess (), (HANDLE) base_soc,
576 GetCurrentProcess (), (PHANDLE) &base_soc,
577 0, TRUE, DUPLICATE_SAME_ACCESS))
578 debug_printf ("DuplicateHandle failed, %E");
579 else
580 {
581 closesocket (soc);
582 soc = base_soc;
583 fixup = false;
584 }
a011f952
CV
585 }
586 }
587 }
588 fd->set_io_handle ((HANDLE) soc);
589 if (!((fhandler_socket *) fd)->init_events ())
590 return false;
591 if (fixup)
b14f53a8 592 ((fhandler_socket *) fd)->init_fixup_before ();
a011f952 593 fd->set_flags (O_RDWR | O_BINARY);
a011f952 594 debug_printf ("fd %d, name '%s', soc %p", (int) fd, dev->name, soc);
b14f53a8 595
4a838033
CV
596 /* Raise default buffer sizes (instead of WinSock default 8K).
597
975a6301
CV
598 64K appear to have the best size/performance ratio for a default
599 value. Tested with ssh/scp on Vista over Gigabit LAN.
600
4a838033 601 NOTE. If the SO_RCVBUF size exceeds 65535(*), and if the socket is
975a6301
CV
602 connected to a remote machine, then calling WSADuplicateSocket on
603 fork/exec fails with WinSock error 10022, WSAEINVAL. Fortunately
604 we don't use WSADuplicateSocket anymore, rather we just utilize
605 handle inheritance. An explanation for this weird behaviour would
606 be nice, though.
8f56da76 607
61522196
CV
608 NOTE 2. Testing on x86_64 (XP, Vista, 2008 R2, W8) indicates that
609 this is no problem on 64 bit. So we set the default buffer size to
610 the default values in current 3.x Linux versions.
611
8f56da76 612 (*) Maximum normal TCP window size. Coincidence? */
61522196
CV
613#ifdef __x86_64__
614 ((fhandler_socket *) fd)->rmem () = 212992;
615 ((fhandler_socket *) fd)->wmem () = 212992;
616#else
63168161
CF
617 ((fhandler_socket *) fd)->rmem () = 65535;
618 ((fhandler_socket *) fd)->wmem () = 65535;
61522196 619#endif
975a6301
CV
620 if (::setsockopt (soc, SOL_SOCKET, SO_RCVBUF,
621 (char *) &((fhandler_socket *) fd)->rmem (), sizeof (int)))
ab362395 622 {
61522196 623 debug_printf ("setsockopt(SO_RCVBUF) failed, %u", WSAGetLastError ());
ab362395
CV
624 if (::getsockopt (soc, SOL_SOCKET, SO_RCVBUF,
625 (char *) &((fhandler_socket *) fd)->rmem (),
626 (size = sizeof (int), &size)))
61522196 627 system_printf ("getsockopt(SO_RCVBUF) failed, %u", WSAGetLastError ());
ab362395 628 }
975a6301
CV
629 if (::setsockopt (soc, SOL_SOCKET, SO_SNDBUF,
630 (char *) &((fhandler_socket *) fd)->wmem (), sizeof (int)))
ab362395 631 {
61522196 632 debug_printf ("setsockopt(SO_SNDBUF) failed, %u", WSAGetLastError ());
ab362395
CV
633 if (::getsockopt (soc, SOL_SOCKET, SO_SNDBUF,
634 (char *) &((fhandler_socket *) fd)->wmem (),
635 (size = sizeof (int), &size)))
61522196 636 system_printf ("getsockopt(SO_SNDBUF) failed, %u", WSAGetLastError ());
ab362395 637 }
4a838033 638
7ac61736 639 return true;
1fd5e000
CF
640}
641
642/* exported as socket: standards? */
4e6a4ea8 643extern "C" int
1fd5e000
CF
644cygwin_socket (int af, int type, int protocol)
645{
646 int res = -1;
611d92e2 647 SOCKET soc = 0;
1fd5e000 648
0d653155
CV
649 int flags = type & _SOCK_FLAG_MASK;
650 type &= ~_SOCK_FLAG_MASK;
651
61522196 652 debug_printf ("socket (%d, %d (flags %y), %d)", af, type, flags, protocol);
0d653155
CV
653
654 if ((flags & ~(SOCK_NONBLOCK | SOCK_CLOEXEC)) != 0)
655 {
656 set_errno (EINVAL);
657 goto done;
658 }
1fd5e000 659
70e476d2 660 soc = socket (af == AF_LOCAL ? AF_INET : af, type,
510a85cb 661 af == AF_LOCAL ? 0 : protocol);
1fd5e000 662
518f5d49
CV
663 if (soc == INVALID_SOCKET)
664 {
665 set_winsock_errno ();
666 goto done;
667 }
1fd5e000 668
7ac61736 669 const device *dev;
79224853 670
70e476d2 671 if (af == AF_LOCAL)
7ac61736 672 dev = type == SOCK_STREAM ? stream_dev : dgram_dev;
70e476d2
CV
673 else
674 dev = type == SOCK_STREAM ? tcp_dev : udp_dev;
1fd5e000 675
518f5d49
CV
676 {
677 cygheap_fdnew fd;
7ac61736
CF
678 if (fd < 0 || !fdsock (fd, dev, soc))
679 closesocket (soc);
680 else
518f5d49 681 {
7ac61736
CF
682 ((fhandler_socket *) fd)->set_addr_family (af);
683 ((fhandler_socket *) fd)->set_socket_type (type);
0d653155
CV
684 if (flags & SOCK_NONBLOCK)
685 ((fhandler_socket *) fd)->set_nonblocking (true);
686 if (flags & SOCK_CLOEXEC)
687 ((fhandler_socket *) fd)->set_close_on_exec (true);
c487f2fe
CV
688 if (type == SOCK_DGRAM)
689 {
690 /* Workaround the problem that a missing listener on a UDP socket
691 in a call to sendto will result in select/WSAEnumNetworkEvents
692 reporting that the socket has pending data and a subsequent call
693 to recvfrom will return -1 with error set to WSAECONNRESET.
694
695 This problem is a regression introduced in Windows 2000.
696 Instead of fixing the problem, a new socket IOCTL code has
697 been added, see http://support.microsoft.com/kb/263823 */
698 BOOL cr = FALSE;
699 DWORD blen;
700 if (WSAIoctl (soc, SIO_UDP_CONNRESET, &cr, sizeof cr, NULL, 0,
701 &blen, NULL, NULL) == SOCKET_ERROR)
61522196 702 debug_printf ("Reset SIO_UDP_CONNRESET: WinSock error %u",
c487f2fe
CV
703 WSAGetLastError ());
704 }
518f5d49
CV
705 res = fd;
706 }
518f5d49 707 }
1fd5e000
CF
708
709done:
61522196 710 syscall_printf ("%R = socket(%d, %d (flags %y), %d)",
0d653155 711 res, af, type, flags, protocol);
1fd5e000
CF
712 return res;
713}
714
1fd5e000 715/* exported as sendto: standards? */
61522196 716extern "C" ssize_t
78db7dff
CV
717cygwin_sendto (int fd, const void *buf, size_t len, int flags,
718 const struct sockaddr *to, socklen_t tolen)
1fd5e000 719{
61522196
CV
720 ssize_t res;
721
722 pthread_testcancel ();
0a642325 723
be5007aa 724 fhandler_socket *fh = get (fd);
1fd5e000 725
893ac8e0
CF
726 myfault efault;
727 if (efault.faulted (EFAULT) || !fh)
5a64d869 728 res = -1;
e0d8706d 729 else
be5007aa 730 res = fh->sendto (buf, len, flags, to, tolen);
a2cdb048 731
61522196 732 syscall_printf ("%lR = sendto(%d, %p, %ld, %y, %p, %d)",
c250f914 733 res, fd, buf, len, flags, to, tolen);
1fd5e000
CF
734 return res;
735}
736
737/* exported as recvfrom: standards? */
61522196 738extern "C" ssize_t
78db7dff
CV
739cygwin_recvfrom (int fd, void *buf, size_t len, int flags,
740 struct sockaddr *from, socklen_t *fromlen)
1fd5e000 741{
61522196
CV
742 ssize_t res;
743
744 pthread_testcancel ();
0a642325 745
be5007aa 746 fhandler_socket *fh = get (fd);
1fd5e000 747
893ac8e0
CF
748 myfault efault;
749 if (efault.faulted (EFAULT) || !fh)
5a64d869 750 res = -1;
6cb222ed
CV
751 else
752 /* Originally we shortcircuited here if res == 0.
753 Allow 0 bytes buffer. This is valid in POSIX and handled in
754 fhandler_socket::recv_internal. If we shortcircuit, we fail
755 to deliver valid error conditions and peer address. */
be5007aa 756 res = fh->recvfrom (buf, len, flags, from, fromlen);
1fd5e000 757
61522196 758 syscall_printf ("%lR = recvfrom(%d, %p, %ld, %y, %p, %p)",
c250f914 759 res, fd, buf, len, flags, from, fromlen);
1fd5e000
CF
760 return res;
761}
762
8b00a766
CV
763static int
764convert_ws1_ip_optname (int optname)
765{
766 static int ws2_optname[] =
767 {
768 0,
769 IP_OPTIONS,
770 IP_MULTICAST_IF,
771 IP_MULTICAST_TTL,
772 IP_MULTICAST_LOOP,
773 IP_ADD_MEMBERSHIP,
774 IP_DROP_MEMBERSHIP,
775 IP_TTL,
776 IP_TOS,
777 IP_DONTFRAGMENT
778 };
779 return (optname < 1 || optname > _WS1_IP_DONTFRAGMENT)
34f5d087 780 ? optname
8b00a766
CV
781 : ws2_optname[optname];
782}
783
1fd5e000 784/* exported as setsockopt: standards? */
4e6a4ea8 785extern "C" int
be5007aa 786cygwin_setsockopt (int fd, int level, int optname, const void *optval,
78db7dff 787 socklen_t optlen)
1fd5e000 788{
b4f06520 789 int res;
be5007aa 790 fhandler_socket *fh = get (fd);
1fd5e000 791
893ac8e0
CF
792 myfault efault;
793 if (efault.faulted (EFAULT) || !fh)
b4f06520
CS
794 res = -1;
795 else
796 {
c487f2fe 797 /* Old applications still use the old WinSock1 IPPROTO_IP values. */
8b00a766 798 if (level == IPPROTO_IP && CYGWIN_VERSION_CHECK_FOR_USING_WINSOCK1_VALUES)
de935f6d 799 optname = convert_ws1_ip_optname (optname);
8b00a766 800
a0145481 801 /* Per POSIX we must not be able to reuse a complete duplicate of a
b86f999a 802 local TCP address (same IP, same port), even if SO_REUSEADDR has been
a0145481
CV
803 set. That's unfortunately possible in WinSock, and this has never
804 been changed to maintain backward compatibility. Instead, the
805 SO_EXCLUSIVEADDRUSE option has been added to allow an application to
806 request POSIX standard behaviour in the non-SO_REUSEADDR case.
807
808 However, the WinSock standard behaviour of stream socket binding
809 is equivalent to the POSIX behaviour as if SO_REUSEADDR has been set.
810 So what we do here is to note that SO_REUSEADDR has been set, but not
811 actually hand over the request to WinSock. This is tested in
812 fhandler_socket::bind(), so that SO_EXCLUSIVEADDRUSE can be set if
813 the application did not set SO_REUSEADDR. This should reflect the
814 POSIX socket binding behaviour as close as possible with WinSock. */
23672785 815 if (level == SOL_SOCKET && optname == SO_REUSEADDR
2f5d8f7b 816 && fh->get_socket_type () == SOCK_STREAM)
23672785
CV
817 res = 0;
818 else
819 res = setsockopt (fh->get_socket (), level, optname,
820 (const char *) optval, optlen);
1fd5e000 821
61522196
CV
822 if (optlen == sizeof (int))
823 syscall_printf ("setsockopt optval=%x", *(int *) optval);
1fd5e000
CF
824
825 if (res)
34f5d087 826 {
494139ff 827 /* KB 248611:
34f5d087 828
494139ff
CV
829 Windows 2000 and above don't support setting the IP_TOS field
830 with setsockopt. Additionally, TOS was always (also under 9x
831 and NT) only implemented for UDP and ICMP, never for TCP.
832
833 The difference is that beginning with Windows 2000 the
834 setsockopt call returns WinSock error 10022, WSAEINVAL when
835 trying to set the IP_TOS field, instead of just ignoring the
836 call. This is *not* explained in KB 248611, but only in KB
837 258978.
838
839 Either case, the official workaround is to add a new registry
840 DWORD value HKLM/System/CurrentControlSet/Services/Tcpip/...
841 ... Parameters/DisableUserTOSSetting, set to 0, and reboot.
842
843 Sidenote: The reasoning for dropping ToS in Win2K is that ToS
844 per RFC 1349 is incompatible with DiffServ per RFC 2474/2475.
845
6fe59500 846 We just ignore the return value of setting IP_TOS entirely. */
494139ff 847 if (level == IPPROTO_IP && optname == IP_TOS
6fe59500 848 && WSAGetLastError () == WSAEINVAL)
494139ff
CV
849 {
850 debug_printf ("Faked IP_TOS success");
851 res = 0;
852 }
853 else
854 set_winsock_errno ();
855 }
975a6301
CV
856 else if (level == SOL_SOCKET)
857 switch (optname)
858 {
859 case SO_REUSEADDR:
860 fh->saw_reuseaddr (*(int *) optval);
861 break;
862 case SO_RCVBUF:
863 fh->rmem (*(int *) optval);
864 break;
865 case SO_SNDBUF:
866 fh->wmem (*(int *) optval);
867 break;
868 default:
869 break;
870 }
1fd5e000
CF
871 }
872
61522196 873 syscall_printf ("%R = setsockopt(%d, %d, %y, %p, %d)",
8b00a766 874 res, fd, level, optname, optval, optlen);
1fd5e000
CF
875 return res;
876}
877
878/* exported as getsockopt: standards? */
4e6a4ea8 879extern "C" int
78db7dff
CV
880cygwin_getsockopt (int fd, int level, int optname, void *optval,
881 socklen_t *optlen)
1fd5e000 882{
b4f06520 883 int res;
be5007aa 884 fhandler_socket *fh = get (fd);
1fd5e000 885
893ac8e0
CF
886 myfault efault;
887 if (efault.faulted (EFAULT) || !fh)
b4f06520 888 res = -1;
7ba0a42f 889 else if (optname == SO_PEERCRED && level == SOL_SOCKET)
c8b404bf
CV
890 {
891 struct ucred *cred = (struct ucred *) optval;
892 res = fh->getpeereid (&cred->pid, &cred->uid, &cred->gid);
893 }
b4f06520
CS
894 else
895 {
c487f2fe 896 /* Old applications still use the old WinSock1 IPPROTO_IP values. */
8b00a766 897 if (level == IPPROTO_IP && CYGWIN_VERSION_CHECK_FOR_USING_WINSOCK1_VALUES)
de935f6d 898 optname = convert_ws1_ip_optname (optname);
be5007aa 899 res = getsockopt (fh->get_socket (), level, optname, (char *) optval,
5bf785a0 900 (int *) optlen);
35e8bb2b
CV
901 if (res == SOCKET_ERROR)
902 set_winsock_errno ();
903 else if (level == SOL_SOCKET)
7ba0a42f
CV
904 {
905 switch (optname)
906 {
907 case SO_ERROR:
908 {
909 int *e = (int *) optval;
910 debug_printf ("WinSock SO_ERROR = %d", *e);
911 *e = find_winsock_errno (*e);
912 }
913 break;
914 case SO_KEEPALIVE:
915 case SO_DONTROUTE:
916 /* Regression in Vista and later: instead of a 4 byte BOOL
b86f999a 917 value, a 1 byte BOOLEAN value is returned, in contrast
7ba0a42f
CV
918 to older systems and the documentation. Since an int
919 type is expected by the calling application, we convert
920 the result here. */
921 if (*optlen == 1)
922 {
923 BOOLEAN *in = (BOOLEAN *) optval;
924 int *out = (int *) optval;
925 *out = *in;
926 *optlen = 4;
927 }
928 break;
929 }
930 }
1fd5e000
CF
931 }
932
61522196 933 syscall_printf ("%R = getsockopt(%d, %d, %y, %p, %p)",
8b00a766 934 res, fd, level, optname, optval, optlen);
1fd5e000
CF
935 return res;
936}
937
c8b404bf 938extern "C" int
61522196 939getpeereid (int fd, uid_t *euid, gid_t *egid)
c8b404bf 940{
c8b404bf
CV
941 fhandler_socket *fh = get (fd);
942 if (fh)
943 return fh->getpeereid (NULL, euid, egid);
944 return -1;
945}
946
1fd5e000 947/* exported as connect: standards? */
4e6a4ea8 948extern "C" int
78db7dff 949cygwin_connect (int fd, const struct sockaddr *name, socklen_t namelen)
1fd5e000
CF
950{
951 int res;
0a642325 952
61522196
CV
953 pthread_testcancel ();
954
be5007aa 955 fhandler_socket *fh = get (fd);
1fd5e000 956
893ac8e0
CF
957 myfault efault;
958 if (efault.faulted (EFAULT) || !fh)
5a64d869 959 res = -1;
1fd5e000 960 else
70e476d2 961 res = fh->connect (name, namelen);
619f7fa0 962
b9aa8149 963 syscall_printf ("%R = connect(%d, %p, %d)", res, fd, name, namelen);
619f7fa0 964
1fd5e000
CF
965 return res;
966}
967
968/* exported as getservbyname: standards? */
4e6a4ea8 969extern "C" struct servent *
1fd5e000
CF
970cygwin_getservbyname (const char *name, const char *proto)
971{
893ac8e0
CF
972 myfault efault;
973 if (efault.faulted (EFAULT))
5a64d869
CF
974 return NULL;
975
f2c11dad 976 servent *res = dup_ent (getservbyname (name, proto));
4ef6a27a
CF
977 syscall_printf ("%p = getservbyname (%s, %s)", res, name, proto);
978 return res;
1fd5e000
CF
979}
980
981/* exported as getservbyport: standards? */
4e6a4ea8 982extern "C" struct servent *
1fd5e000
CF
983cygwin_getservbyport (int port, const char *proto)
984{
893ac8e0
CF
985 myfault efault;
986 if (efault.faulted (EFAULT))
5a64d869
CF
987 return NULL;
988
f2c11dad
CF
989 servent *res = dup_ent (getservbyport (port, proto));
990 syscall_printf ("%p = getservbyport (%d, %s)", res, port, proto);
4ef6a27a 991 return res;
1fd5e000
CF
992}
993
4e6a4ea8 994extern "C" int
1fd5e000
CF
995cygwin_gethostname (char *name, size_t len)
996{
893ac8e0
CF
997 myfault efault;
998 if (efault.faulted (EFAULT))
5a64d869
CF
999 return -1;
1000
dc8d11f5 1001 if (gethostname (name, len))
1fd5e000
CF
1002 {
1003 DWORD local_len = len;
1004
1005 if (!GetComputerNameA (name, &local_len))
1006 {
1007 set_winsock_errno ();
1008 return -1;
1009 }
1010 }
f70389b5 1011 debug_printf ("name %s", name);
1fd5e000
CF
1012 return 0;
1013}
1014
1015/* exported as gethostbyname: standards? */
4e6a4ea8 1016extern "C" struct hostent *
1fd5e000
CF
1017cygwin_gethostbyname (const char *name)
1018{
893ac8e0
CF
1019 myfault efault;
1020 if (efault.faulted (EFAULT))
c9629cef 1021 return NULL;
fe836470 1022
a694f079
CF
1023 unsigned char tmp_addr[4];
1024 struct hostent tmp, *h;
1025 char *tmp_aliases[1] = {0};
1026 char *tmp_addr_list[2] = {0,0};
1027 unsigned int a, b, c, d;
1028 char dummy;
4e6a4ea8 1029
fe836470
CF
1030 if (sscanf (name, "%u.%u.%u.%u%c", &a, &b, &c, &d, &dummy) != 4
1031 || a >= 256 || b >= 256 || c >= 256 || d >= 256)
1032 h = gethostbyname (name);
1033 else
1fd5e000
CF
1034 {
1035 /* In case you don't have DNS, at least x.x.x.x still works */
4e6a4ea8 1036 memset (&tmp, 0, sizeof (tmp));
1fd5e000
CF
1037 tmp_addr[0] = a;
1038 tmp_addr[1] = b;
1039 tmp_addr[2] = c;
1040 tmp_addr[3] = d;
b01cbd5d 1041 tmp_addr_list[0] = (char *) tmp_addr;
1fd5e000
CF
1042 tmp.h_name = name;
1043 tmp.h_aliases = tmp_aliases;
1044 tmp.h_addrtype = 2;
1045 tmp.h_length = 4;
1046 tmp.h_addr_list = tmp_addr_list;
a694f079 1047 h = &tmp;
1fd5e000 1048 }
a694f079 1049
f2c11dad 1050 hostent *res = dup_ent (h);
4ef6a27a 1051 if (res)
c9629cef 1052 debug_printf ("h_name %s", res->h_name);
1fd5e000
CF
1053 else
1054 {
4ef6a27a 1055 debug_printf ("dup_ent returned NULL for name %s, h %p", name, h);
fe836470 1056 set_host_errno ();
1fd5e000 1057 }
4ef6a27a 1058 return res;
cb19ccf4
CV
1059}
1060
1061/* exported as gethostbyaddr: standards? */
1062extern "C" struct hostent *
1063cygwin_gethostbyaddr (const char *addr, int len, int type)
1064{
893ac8e0
CF
1065 myfault efault;
1066 if (efault.faulted (EFAULT))
5a64d869
CF
1067 return NULL;
1068
f2c11dad 1069 hostent *res = dup_ent (gethostbyaddr (addr, len, type));
4ef6a27a 1070 if (res)
f2c11dad 1071 debug_printf ("h_name %s", res->h_name);
cb19ccf4 1072 else
fe836470 1073 set_host_errno ();
4ef6a27a 1074 return res;
1fd5e000
CF
1075}
1076
0a20e5a0 1077static void
6f57cb4a
CV
1078memcpy4to6 (char *dst, const u_char *src)
1079{
1080 const unsigned int h[] = {0, 0, htonl (0xFFFF)};
1081 memcpy (dst, h, 12);
1082 memcpy (dst + 12, src, NS_INADDRSZ);
1083}
1084
0a20e5a0 1085static hostent *
6f57cb4a
CV
1086gethostby_helper (const char *name, const int af, const int type,
1087 const int addrsize_in, const int addrsize_out)
1088{
1089 /* Get the data from the name server */
1090 const int maxcount = 3;
1091 int old_errno, ancount = 0, anlen = 1024, msgsize = 0;
1092 u_char *ptr, *msg = NULL;
1093 int sz;
1094 hostent *ret;
1095 char *string_ptr;
1096
1097 while ((anlen > msgsize) && (ancount++ < maxcount))
1098 {
1099 msgsize = anlen;
1100 ptr = (u_char *) realloc (msg, msgsize);
1101 if (ptr == NULL )
1102 {
1103 old_errno = errno;
1104 free (msg);
1105 set_errno (old_errno);
1106 h_errno = NETDB_INTERNAL;
1107 return NULL;
1108 }
1109 msg = ptr;
1110 anlen = res_search (name, ns_c_in, type, msg, msgsize);
0a20e5a0 1111 }
6f57cb4a
CV
1112
1113 if (ancount >= maxcount)
1114 {
1115 free (msg);
1116 h_errno = NO_RECOVERY;
1117 return NULL;
1118 }
1119 if (anlen < 0) /* errno and h_errno are set */
1120 {
1121 old_errno = errno;
1122 free (msg);
1123 set_errno (old_errno);
0a20e5a0 1124 return NULL;
6f57cb4a
CV
1125 }
1126 u_char *eomsg = msg + anlen - 1;
1127
1128
0a20e5a0 1129 /* We scan the answer records to determine the required memory size.
6f57cb4a
CV
1130 They can be corrupted and we don't fully trust that the message
1131 follows the standard exactly. glibc applies some checks that
1132 we emulate.
1133 The answers are copied in the hostent structure in a second scan.
1134 To simplify the second scan we store information as follows:
1135 - "class" is replaced by the compressed name size
0a20e5a0 1136 - the first 16 bits of the "ttl" store the expanded name size + 1
6f57cb4a
CV
1137 - the last 16 bits of the "ttl" store the offset to the next valid record.
1138 Note that "type" is rewritten in host byte order. */
0a20e5a0 1139
6f57cb4a
CV
1140 class record {
1141 public:
1142 unsigned type: 16; // type
1143 unsigned complen: 16; // class or compressed length
1144 unsigned namelen1: 16; // expanded length (with final 0)
1145 unsigned next_o: 16; // offset to next valid
1146 unsigned size: 16; // data size
1147 u_char data[]; // data
1148 record * next () { return (record *) (((char *) this) + next_o); }
1149 void set_next ( record * nxt) { next_o = ((char *) nxt) - ((char *) this); }
1150 u_char * name () { return (u_char *) (((char *) this) - complen); }
1151 };
1152
1153 record * anptr = NULL, * prevptr = NULL, * curptr;
1154 int i, alias_count = 0, string_size = 0, address_count = 0;
0a20e5a0
CF
1155 int namelen1 = 0, address_len = 0, antype, anclass, ansize;
1156 unsigned complen;
6f57cb4a
CV
1157
1158 /* Get the count of answers */
1159 ancount = ntohs (((HEADER *) msg)->ancount);
1160
1161 /* Skip the question, it was verified by res_send */
1162 ptr = msg + sizeof (HEADER);
1163 if ((complen = dn_skipname (ptr, eomsg)) < 0)
0a20e5a0 1164 goto corrupted;
6f57cb4a
CV
1165 /* Point to the beginning of the answer section */
1166 ptr += complen + NS_QFIXEDSZ;
0a20e5a0 1167
6f57cb4a
CV
1168 /* Scan the answer records to determine the sizes */
1169 for (i = 0; i < ancount; i++, ptr = curptr->data + ansize)
1170 {
1171 if ((complen = dn_skipname (ptr, eomsg)) < 0)
1172 goto corrupted;
1173
1174 curptr = (record *) (ptr + complen);
1175 antype = ntohs (curptr->type);
1176 anclass = ntohs (curptr->complen);
1177 ansize = ntohs (curptr->size);
1178 /* Class must be internet */
1179 if (anclass != ns_c_in)
1180 continue;
1181
1182 curptr->complen = complen;
1183 if ((namelen1 = dn_length1 (msg, eomsg, curptr-> name())) <= 0)
1184 goto corrupted;
1185
0a20e5a0 1186 if (antype == ns_t_cname)
6f57cb4a
CV
1187 {
1188 alias_count++;
1189 string_size += namelen1;
1190 }
1191 else if (antype == type)
1192 {
1193 ansize = ntohs (curptr->size);
1194 if (ansize != addrsize_in)
1195 continue;
1196 if (address_count == 0)
1197 {
1198 address_len = namelen1;
1199 string_size += namelen1;
1200 }
1201 else if (address_len != namelen1)
1202 continue;
1203 address_count++;
1204 }
1205 /* Update the records */
1206 curptr->type = antype; /* Host byte order */
1207 curptr->namelen1 = namelen1;
1208 if (! anptr)
1209 anptr = prevptr = curptr;
1210 else
1211 {
1212 prevptr->set_next (curptr);
1213 prevptr = curptr;
1214 }
1215 }
1216
1217 /* If there is no address, quit */
1218 if (address_count == 0)
1219 {
1220 free (msg);
1221 h_errno = NO_DATA;
1222 return NULL;
1223 }
0a20e5a0 1224
6f57cb4a
CV
1225 /* Determine the total size */
1226 sz = DWORD_round (sizeof(hostent))
1227 + sizeof (char *) * (alias_count + address_count + 2)
1228 + string_size
1229 + address_count * addrsize_out;
1230
1231 ret = realloc_ent (sz, (hostent *) NULL);
0a20e5a0 1232 if (! ret)
6f57cb4a
CV
1233 {
1234 old_errno = errno;
1235 free (msg);
1236 set_errno (old_errno);
1237 h_errno = NETDB_INTERNAL;
1238 return NULL;
1239 }
1240
1241 ret->h_addrtype = af;
1242 ret->h_length = addrsize_out;
1243 ret->h_aliases = (char **) (((char *) ret) + DWORD_round (sizeof(hostent)));
1244 ret->h_addr_list = ret->h_aliases + alias_count + 1;
1245 string_ptr = (char *) (ret->h_addr_list + address_count + 1);
0a20e5a0 1246
6f57cb4a 1247 /* Rescan the answers */
6f57cb4a 1248 alias_count = address_count = 0;
927761a4 1249 prevptr->set_next (prevptr + 1);
6f57cb4a 1250
927761a4 1251 for (curptr = anptr; curptr <= prevptr; curptr = curptr->next ())
6f57cb4a
CV
1252 {
1253 antype = curptr->type;
0a20e5a0 1254 if (antype == ns_t_cname)
6f57cb4a 1255 {
927761a4 1256 dn_expand (msg, eomsg, curptr->name (), string_ptr, curptr->namelen1);
6f57cb4a 1257 ret->h_aliases[alias_count++] = string_ptr;
927761a4 1258 string_ptr += curptr->namelen1;
6f57cb4a 1259 }
927761a4
PH
1260 else
1261 {
1262 if (address_count == 0)
6f57cb4a 1263 {
927761a4
PH
1264 dn_expand (msg, eomsg, curptr->name (), string_ptr, curptr->namelen1);
1265 ret->h_name = string_ptr;
1266 string_ptr += curptr->namelen1;
6f57cb4a 1267 }
927761a4
PH
1268 ret->h_addr_list[address_count++] = string_ptr;
1269 if (addrsize_in != addrsize_out)
1270 memcpy4to6 (string_ptr, curptr->data);
1271 else
1272 memcpy (string_ptr, curptr->data, addrsize_in);
1273 string_ptr += addrsize_out;
1274 }
6f57cb4a 1275 }
0a20e5a0 1276
6f57cb4a
CV
1277 free (msg);
1278
1279 ret->h_aliases[alias_count] = NULL;
1280 ret->h_addr_list[address_count] = NULL;
0a20e5a0 1281
6f57cb4a
CV
1282 return ret;
1283
1284 corrupted:
1285 free (msg);
1286 /* Hopefully message corruption errors are temporary.
1287 Should it be NO_RECOVERY ? */
1288 h_errno = TRY_AGAIN;
1289 return NULL;
6f57cb4a
CV
1290}
1291
1292/* gethostbyname2: standards? */
1293extern "C" struct hostent *
1294gethostbyname2 (const char *name, int af)
1295{
6f57cb4a
CV
1296 myfault efault;
1297 if (efault.faulted (EFAULT))
1298 return NULL;
1299
1300 if (!(_res.options & RES_INIT))
1301 res_init();
1302 bool v4to6 = _res.options & RES_USE_INET6;
1303
1304 int type, addrsize_in, addrsize_out;
0a20e5a0 1305 switch (af)
6f57cb4a
CV
1306 {
1307 case AF_INET:
1308 addrsize_in = NS_INADDRSZ;
1309 addrsize_out = (v4to6) ? NS_IN6ADDRSZ : NS_INADDRSZ;
1310 type = ns_t_a;
1311 break;
1312 case AF_INET6:
1313 addrsize_in = addrsize_out = NS_IN6ADDRSZ;
1314 type = ns_t_aaaa;
1315 break;
1316 default:
1317 set_errno (EAFNOSUPPORT);
1318 h_errno = NETDB_INTERNAL;
1319 return NULL;
1320 }
0a20e5a0 1321
6f57cb4a
CV
1322 return gethostby_helper (name, af, type, addrsize_in, addrsize_out);
1323}
1324
1fd5e000 1325/* exported as accept: standards? */
4e6a4ea8 1326extern "C" int
78db7dff 1327cygwin_accept (int fd, struct sockaddr *peer, socklen_t *len)
1fd5e000 1328{
b4f06520 1329 int res;
0a642325 1330
61522196
CV
1331 pthread_testcancel ();
1332
be5007aa 1333 fhandler_socket *fh = get (fd);
b4f06520 1334
893ac8e0
CF
1335 myfault efault;
1336 if (efault.faulted (EFAULT) || !fh)
b4f06520
CS
1337 res = -1;
1338 else
9d5bf1b1 1339 res = fh->accept4 (peer, len, fh->is_nonblocking () ? SOCK_NONBLOCK : 0);
1fd5e000 1340
b9aa8149 1341 syscall_printf ("%R = accept(%d, %p, %p)", res, fd, peer, len);
1fd5e000
CF
1342 return res;
1343}
1344
0d653155
CV
1345extern "C" int
1346accept4 (int fd, struct sockaddr *peer, socklen_t *len, int flags)
1347{
1348 int res;
0d653155 1349
61522196
CV
1350 pthread_testcancel ();
1351
0d653155
CV
1352 fhandler_socket *fh = get (fd);
1353
1354 myfault efault;
1355 if (efault.faulted (EFAULT) || !fh)
1356 res = -1;
1357 else if ((flags & ~(SOCK_NONBLOCK | SOCK_CLOEXEC)) != 0)
1358 {
1359 set_errno (EINVAL);
1360 res = -1;
1361 }
1362 else
1363 res = fh->accept4 (peer, len, flags);
1364
61522196 1365 syscall_printf ("%R = accept4(%d, %p, %p, %y)", res, fd, peer, len, flags);
0d653155
CV
1366 return res;
1367}
1368
1fd5e000 1369/* exported as bind: standards? */
4e6a4ea8 1370extern "C" int
78db7dff 1371cygwin_bind (int fd, const struct sockaddr *my_addr, socklen_t addrlen)
1fd5e000 1372{
b4f06520 1373 int res;
be5007aa 1374 fhandler_socket *fh = get (fd);
b4f06520 1375
893ac8e0
CF
1376 myfault efault;
1377 if (efault.faulted (EFAULT) || !fh)
b4f06520
CS
1378 res = -1;
1379 else
be5007aa 1380 res = fh->bind (my_addr, addrlen);
1fd5e000 1381
b9aa8149 1382 syscall_printf ("%R = bind(%d, %p, %d)", res, fd, my_addr, addrlen);
1fd5e000
CF
1383 return res;
1384}
1385
1386/* exported as getsockname: standards? */
4e6a4ea8 1387extern "C" int
78db7dff 1388cygwin_getsockname (int fd, struct sockaddr *addr, socklen_t *namelen)
1fd5e000 1389{
b4f06520 1390 int res;
0a642325 1391
be5007aa 1392 fhandler_socket *fh = get (fd);
b4f06520 1393
893ac8e0
CF
1394 myfault efault;
1395 if (efault.faulted (EFAULT) || !fh)
b4f06520
CS
1396 res = -1;
1397 else
be5007aa
CV
1398 res = fh->getsockname (addr, namelen);
1399
b9aa8149 1400 syscall_printf ("%R =getsockname (%d, %p, %p)", res, fd, addr, namelen);
1fd5e000
CF
1401 return res;
1402}
1403
1fd5e000 1404/* exported as listen: standards? */
4e6a4ea8 1405extern "C" int
1fd5e000
CF
1406cygwin_listen (int fd, int backlog)
1407{
b4f06520 1408 int res;
be5007aa 1409 fhandler_socket *fh = get (fd);
b4f06520
CS
1410
1411 if (!fh)
1412 res = -1;
1413 else
be5007aa 1414 res = fh->listen (backlog);
1fd5e000 1415
b9aa8149 1416 syscall_printf ("%R = listen(%d, %d)", res, fd, backlog);
1fd5e000
CF
1417 return res;
1418}
1419
1420/* exported as shutdown: standards? */
4e6a4ea8 1421extern "C" int
1fd5e000
CF
1422cygwin_shutdown (int fd, int how)
1423{
b4f06520 1424 int res;
0a642325 1425
be5007aa 1426 fhandler_socket *fh = get (fd);
b4f06520
CS
1427
1428 if (!fh)
1429 res = -1;
1430 else
be5007aa
CV
1431 res = fh->shutdown (how);
1432
b9aa8149 1433 syscall_printf ("%R = shutdown(%d, %d)", res, fd, how);
1fd5e000
CF
1434 return res;
1435}
1436
7d9688b7
CV
1437/* exported as hstrerror: BSD 4.3 */
1438extern "C" const char *
1439cygwin_hstrerror (int err)
1440{
1441 int i;
1442
1443 for (i = 0; host_errmap[i].e != 0; ++i)
1444 if (err == host_errmap[i].e)
1445 break;
1446
1447 return host_errmap[i].s;
1448}
1449
1450/* exported as herror: BSD 4.3 */
4e6a4ea8 1451extern "C" void
7d9688b7 1452cygwin_herror (const char *s)
1fd5e000 1453{
893ac8e0
CF
1454 myfault efault;
1455 if (efault.faulted ())
b0fa0e6e 1456 return;
0381fec6 1457 if (cygheap->fdtab.not_open (2))
7d9688b7
CV
1458 return;
1459
1460 if (s)
1461 {
1462 write (2, s, strlen (s));
1463 write (2, ": ", 2);
1464 }
1465
1466 const char *h_errstr = cygwin_hstrerror (h_errno);
1467
1468 if (!h_errstr)
1469 switch (h_errno)
1470 {
79224853
CV
1471 case NETDB_INTERNAL:
1472 h_errstr = "Resolver internal error";
1473 break;
1474 case NETDB_SUCCESS:
1475 h_errstr = "Resolver error 0 (no error)";
1476 break;
1477 default:
1478 h_errstr = "Unknown resolver error";
1479 break;
7d9688b7
CV
1480 }
1481 write (2, h_errstr, strlen (h_errstr));
1482 write (2, "\n", 1);
1fd5e000
CF
1483}
1484
1485/* exported as getpeername: standards? */
4e6a4ea8 1486extern "C" int
78db7dff 1487cygwin_getpeername (int fd, struct sockaddr *name, socklen_t *len)
1fd5e000 1488{
b4f06520 1489 int res;
0a642325 1490
b4f06520 1491 fhandler_socket *fh = get (fd);
be5007aa 1492
893ac8e0
CF
1493 myfault efault;
1494 if (efault.faulted (EFAULT) || !fh)
b4f06520
CS
1495 res = -1;
1496 else
be5007aa 1497 res = fh->getpeername (name, len);
5a64d869 1498
61522196
CV
1499 syscall_printf ("%R = getpeername(%d) %p", res, fd,
1500 (fh ? fh->get_socket () : (SOCKET) -1));
1fd5e000
CF
1501 return res;
1502}
1503
1504/* exported as recv: standards? */
61522196 1505extern "C" ssize_t
78db7dff 1506cygwin_recv (int fd, void *buf, size_t len, int flags)
1fd5e000 1507{
61522196
CV
1508 ssize_t res;
1509
1510 pthread_testcancel ();
291698e5
CV
1511
1512 fhandler_socket *fh = get (fd);
1513
1514 myfault efault;
1515 if (efault.faulted (EFAULT) || !fh)
1516 res = -1;
6cb222ed
CV
1517 else
1518 /* Originally we shortcircuited here if res == 0.
1519 Allow 0 bytes buffer. This is valid in POSIX and handled in
1520 fhandler_socket::recv_internal. If we shortcircuit, we fail
1521 to deliver valid error conditions. */
291698e5
CV
1522 res = fh->recvfrom (buf, len, flags, NULL, NULL);
1523
61522196 1524 syscall_printf ("%lR = recv(%d, %p, %ld, %y)", res, fd, buf, len, flags);
291698e5 1525 return res;
1fd5e000
CF
1526}
1527
1528/* exported as send: standards? */
61522196 1529extern "C" ssize_t
78db7dff 1530cygwin_send (int fd, const void *buf, size_t len, int flags)
1fd5e000 1531{
61522196
CV
1532 ssize_t res;
1533
1534 pthread_testcancel ();
291698e5
CV
1535
1536 fhandler_socket *fh = get (fd);
1537
1538 myfault efault;
1539 if (efault.faulted (EFAULT) || !fh)
1540 res = -1;
1541 else
1542 res = fh->sendto (buf, len, flags, NULL, 0);
1543
61522196 1544 syscall_printf ("%lR = send(%d, %p, %ld, %y)", res, fd, buf, len, flags);
291698e5 1545 return res;
1fd5e000
CF
1546}
1547
1548/* getdomainname: standards? */
4e6a4ea8 1549extern "C" int
8761c1dc 1550getdomainname (char *domain, size_t len)
1fd5e000 1551{
893ac8e0
CF
1552 myfault efault;
1553 if (efault.faulted (EFAULT))
5a64d869
CF
1554 return -1;
1555
c9a5cfa0
PH
1556 PFIXED_INFO info = NULL;
1557 ULONG size = 0;
1558
1559 if (GetNetworkParams(info, &size) == ERROR_BUFFER_OVERFLOW
1560 && (info = (PFIXED_INFO) alloca(size))
1561 && GetNetworkParams(info, &size) == ERROR_SUCCESS)
1562 {
1563 strncpy(domain, info->DomainName, len);
1564 return 0;
1565 }
c9a5cfa0
PH
1566 __seterrno ();
1567 return -1;
1fd5e000
CF
1568}
1569
52b5a971
CV
1570/* Fill out an ifconf struct. */
1571
bff43891 1572#ifndef IN_LOOPBACK
0a20e5a0 1573#define IN_LOOPBACK(a) ((((long int) (a)) & 0xff000000) == 0x7f000000)
bff43891
CV
1574#endif
1575
1576static int in6_are_prefix_equal (struct in6_addr *, struct in6_addr *, int);
1577
1578static int in_are_prefix_equal (struct in_addr *p1, struct in_addr *p2, int len)
1579{
1580 if (0 > len || len > 32)
1581 return 0;
1582 uint32_t pfxmask = 0xffffffff << (32 - len);
a71ecb55 1583 return (ntohl (p1->s_addr) & pfxmask) == (ntohl (p2->s_addr) & pfxmask);
bff43891
CV
1584}
1585
1586extern "C" int
1587ip_addr_prefix (PIP_ADAPTER_UNICAST_ADDRESS pua, PIP_ADAPTER_PREFIX pap)
1588{
1589 if (wincap.has_gaa_on_link_prefix ())
1590 return (int) ((PIP_ADAPTER_UNICAST_ADDRESS_LH) pua)->OnLinkPrefixLength;
1591 switch (pua->Address.lpSockaddr->sa_family)
1592 {
1593 case AF_INET:
1594 /* Prior to Vista, the loopback prefix is not available. */
a71ecb55
CV
1595 if (IN_LOOPBACK (ntohl (((struct sockaddr_in *)
1596 pua->Address.lpSockaddr)->sin_addr.s_addr)))
510a85cb 1597 return 8;
bff43891
CV
1598 for ( ; pap; pap = pap->Next)
1599 if (in_are_prefix_equal (
1600 &((struct sockaddr_in *) pua->Address.lpSockaddr)->sin_addr,
1601 &((struct sockaddr_in *) pap->Address.lpSockaddr)->sin_addr,
1602 pap->PrefixLength))
1603 return pap->PrefixLength;
1604 break;
1605 case AF_INET6:
1606 /* Prior to Vista, the loopback prefix is not available. */
1607 if (IN6_IS_ADDR_LOOPBACK (&((struct sockaddr_in6 *)
1608 pua->Address.lpSockaddr)->sin6_addr))
1609 return 128;
1610 for ( ; pap; pap = pap->Next)
1611 if (in6_are_prefix_equal (
1612 &((struct sockaddr_in6 *) pua->Address.lpSockaddr)->sin6_addr,
1613 &((struct sockaddr_in6 *) pap->Address.lpSockaddr)->sin6_addr,
1614 pap->PrefixLength))
1615 return pap->PrefixLength;
1616 break;
1617 default:
1618 break;
1619 }
1620 return 0;
1621}
1622
1623#ifndef GAA_FLAG_INCLUDE_ALL_INTERFACES
1624#define GAA_FLAG_INCLUDE_ALL_INTERFACES 0x0100
1625#endif
1626
3e25449a
CV
1627struct gaa_wa {
1628 ULONG family;
1629 PIP_ADAPTER_ADDRESSES *pa_ret;
1630};
1631
1632DWORD WINAPI
1633call_gaa (LPVOID param)
bff43891
CV
1634{
1635 DWORD ret, size = 0;
3e25449a 1636 gaa_wa *p = (gaa_wa *) param;
bff43891
CV
1637 PIP_ADAPTER_ADDRESSES pa0 = NULL;
1638
3e25449a
CV
1639 if (!p->pa_ret)
1640 return GetAdaptersAddresses (p->family, GAA_FLAG_INCLUDE_PREFIX
bff43891 1641 | GAA_FLAG_INCLUDE_ALL_INTERFACES,
3e25449a 1642 NULL, NULL, &size);
bff43891
CV
1643 do
1644 {
3e25449a
CV
1645 ret = GetAdaptersAddresses (p->family, GAA_FLAG_INCLUDE_PREFIX
1646 | GAA_FLAG_INCLUDE_ALL_INTERFACES,
bff43891
CV
1647 NULL, pa0, &size);
1648 if (ret == ERROR_BUFFER_OVERFLOW
1649 && !(pa0 = (PIP_ADAPTER_ADDRESSES) realloc (pa0, size)))
1650 break;
1651 }
1652 while (ret == ERROR_BUFFER_OVERFLOW);
3e25449a 1653 if (pa0)
bff43891 1654 {
3e25449a
CV
1655 if (ret != ERROR_SUCCESS)
1656 {
1657 free (pa0);
1658 *p->pa_ret = pa0;
1659 }
1660 else
1661 *p->pa_ret = pa0;
bff43891 1662 }
3e25449a
CV
1663 return ret;
1664}
1665
1666bool
1667get_adapters_addresses (PIP_ADAPTER_ADDRESSES *pa_ret, ULONG family)
1668{
1669 DWORD ret;
1670 gaa_wa param = { family, pa_ret ?: NULL };
1671
00a76ece
CV
1672 if ((uintptr_t) &param >= (uintptr_t) 0x80000000L
1673 && wincap.has_gaa_largeaddress_bug ())
3e25449a 1674 {
00a76ece 1675 /* In Windows Vista and Windows 7 under WOW64, GetAdaptersAddresses fails
3e25449a
CV
1676 if it's running in a thread with a stack located in the large address
1677 area. So, if we're running in a pthread with such a stack, we call
00a76ece
CV
1678 GetAdaptersAddresses in a child thread with an OS-allocated stack.
1679 The OS allocates stacks bottom up, so chances are good that the new
0b1545eb 1680 stack will be located in the lower address area. */
3e25449a
CV
1681 HANDLE thr = CreateThread (NULL, 0, call_gaa, &param, 0, NULL);
1682 if (!thr)
1683 {
1684 debug_printf ("CreateThread: %E");
1685 return false;
1686 }
1687 WaitForSingleObject (thr, INFINITE);
1688 GetExitCodeThread (thr, &ret);
1689 CloseHandle (thr);
1690 }
1691 else
1692 ret = call_gaa (&param);
1693 return ret == ERROR_SUCCESS || (!pa_ret && ret == ERROR_BUFFER_OVERFLOW);
bff43891
CV
1694}
1695
1696#define WS_IFF_UP 1
1697#define WS_IFF_BROADCAST 2
1698#define WS_IFF_LOOPBACK 4
1699#define WS_IFF_POINTTOPOINT 8
1700#define WS_IFF_MULTICAST 16
1701
1702static inline short
1703convert_ifr_flags (u_long ws_flags)
1704{
1705 return (ws_flags & (WS_IFF_UP | WS_IFF_BROADCAST))
510a85cb 1706 | ((ws_flags & (WS_IFF_LOOPBACK | WS_IFF_POINTTOPOINT)) << 1)
bff43891
CV
1707 | ((ws_flags & WS_IFF_MULTICAST) << 8);
1708}
1709
8e4a60b3
CV
1710static u_long
1711get_routedst (DWORD if_index)
1712{
1713 PMIB_IPFORWARDTABLE pift;
1714 ULONG size = 0;
1715 if (GetIpForwardTable (NULL, &size, FALSE) == ERROR_INSUFFICIENT_BUFFER
1716 && (pift = (PMIB_IPFORWARDTABLE) alloca (size))
1717 && GetIpForwardTable (pift, &size, FALSE) == NO_ERROR)
1718 for (DWORD i = 0; i < pift->dwNumEntries; ++i)
1719 {
7b44665a 1720 if (pift->table[i].dwForwardIfIndex == if_index
8e4a60b3
CV
1721 && pift->table[i].dwForwardMask == INADDR_BROADCAST)
1722 return pift->table[i].dwForwardDest;
1723 }
1724 return INADDR_ANY;
1725}
1726
a71ecb55
CV
1727struct ifall {
1728 struct ifaddrs ifa_ifa;
1729 char ifa_name[IFNAMSIZ];
1730 struct sockaddr_storage ifa_addr;
1731 struct sockaddr_storage ifa_brddstaddr;
1732 struct sockaddr_storage ifa_netmask;
1733 struct sockaddr ifa_hwaddr;
1734 int ifa_metric;
1735 int ifa_mtu;
1736 int ifa_ifindex;
1737 struct ifreq_frndlyname ifa_frndlyname;
1738};
1739
ea392307
CV
1740static unsigned int
1741get_flags (PIP_ADAPTER_ADDRESSES pap)
1742{
1743 unsigned int flags = IFF_UP;
1744 if (pap->IfType == IF_TYPE_SOFTWARE_LOOPBACK)
1745 flags |= IFF_LOOPBACK;
943c59e3
CV
1746 else if (pap->IfType == IF_TYPE_PPP
1747 || pap->IfType == IF_TYPE_SLIP)
1748 flags |= IFF_POINTOPOINT | IFF_NOARP;
ea392307
CV
1749 if (!(pap->Flags & IP_ADAPTER_NO_MULTICAST))
1750 flags |= IFF_MULTICAST;
1751 if (pap->OperStatus == IfOperStatusUp
1752 || pap->OperStatus == IfOperStatusUnknown)
1753 flags |= IFF_RUNNING;
1754 if (pap->OperStatus != IfOperStatusLowerLayerDown)
1755 flags |= IFF_LOWER_UP;
1756 if (pap->OperStatus == IfOperStatusDormant)
1757 flags |= IFF_DORMANT;
1758 return flags;
1759}
1760
1761static ULONG
1762get_ipv4fromreg_ipcnt (const char *name)
1763{
cbc26145
CV
1764 WCHAR regkey[256], *c;
1765
1766 c = wcpcpy (regkey, L"Tcpip\\Parameters\\Interfaces\\");
1767 sys_mbstowcs (c, 220, name);
1768 if (!NT_SUCCESS (RtlCheckRegistryKey (RTL_REGISTRY_SERVICES, regkey)))
1769 return 0;
1770
ea392307 1771 ULONG ifs = 1;
cbc26145
CV
1772 DWORD dhcp = 0;
1773 UNICODE_STRING uipa = { 0, 0, NULL };
1774 RTL_QUERY_REGISTRY_TABLE tab[3] = {
1775 { NULL, RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_NOSTRING,
1776 L"EnableDHCP", &dhcp, REG_NONE, NULL, 0 },
1777 { NULL, RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_NOEXPAND,
1778 L"IPAddress", &uipa, REG_NONE, NULL, 0 },
1779 { NULL, 0, NULL, NULL, 0, NULL, 0 }
1780 };
ea392307 1781
ea392307 1782 /* If DHCP is used, we have only one address. */
cbc26145
CV
1783 if (NT_SUCCESS (RtlQueryRegistryValues (RTL_REGISTRY_SERVICES, regkey, tab,
1784 NULL, NULL))
1785 && uipa.Buffer)
ea392307 1786 {
cbc26145
CV
1787 if (dhcp == 0)
1788 for (ifs = 0, c = uipa.Buffer; *c; c += wcslen (c) + 1)
ea392307 1789 ifs++;
cbc26145 1790 RtlFreeUnicodeString (&uipa);
ea392307 1791 }
ea392307
CV
1792 return ifs;
1793}
1794
1795static void
1796get_ipv4fromreg (struct ifall *ifp, const char *name, DWORD idx)
1797{
cbc26145
CV
1798 WCHAR regkey[256], *c;
1799
1800 c = wcpcpy (regkey, L"Tcpip\\Parameters\\Interfaces\\");
1801 sys_mbstowcs (c, 220, name);
1802 if (!NT_SUCCESS (RtlCheckRegistryKey (RTL_REGISTRY_SERVICES, regkey)))
1803 return;
1804
1805 ULONG ifs;
1806 DWORD dhcp = 0;
1807 UNICODE_STRING udipa = { 0, 0, NULL };
1808 UNICODE_STRING udsub = { 0, 0, NULL };
1809 UNICODE_STRING uipa = { 0, 0, NULL };
1810 UNICODE_STRING usub = { 0, 0, NULL };
1811 RTL_QUERY_REGISTRY_TABLE tab[6] = {
1812 { NULL, RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_NOSTRING,
1813 L"EnableDHCP", &dhcp, REG_NONE, NULL, 0 },
1814 { NULL, RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_NOEXPAND,
1815 L"DhcpIPAddress", &udipa, REG_NONE, NULL, 0 },
1816 { NULL, RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_NOEXPAND,
1817 L"DhcpSubnetMask", &udsub, REG_NONE, NULL, 0 },
1818 { NULL, RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_NOEXPAND,
1819 L"IPAddress", &uipa, REG_NONE, NULL, 0 },
1820 { NULL, RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_NOEXPAND,
1821 L"SubnetMask", &usub, REG_NONE, NULL, 0 },
1822 { NULL, 0, NULL, NULL, 0, NULL, 0 }
1823 };
1824
1825 if (NT_SUCCESS (RtlQueryRegistryValues (RTL_REGISTRY_SERVICES, regkey, tab,
1826 NULL, NULL)))
ea392307 1827 {
cbc26145
CV
1828# define addr ((struct sockaddr_in *) &ifp->ifa_addr)
1829# define mask ((struct sockaddr_in *) &ifp->ifa_netmask)
1830# define brdc ((struct sockaddr_in *) &ifp->ifa_brddstaddr)
1831# define inet_uton(u, a) \
1832 { \
1833 char t[64]; \
1834 sys_wcstombs (t, 64, (u)); \
1835 cygwin_inet_aton (t, (a)); \
1836 }
1837 /* If DHCP is used, we have only one address. */
ea392307
CV
1838 if (dhcp)
1839 {
cbc26145
CV
1840 if (udipa.Buffer)
1841 inet_uton (udipa.Buffer, &addr->sin_addr);
1842 if (udsub.Buffer)
1843 inet_uton (udsub.Buffer, &mask->sin_addr);
ea392307
CV
1844 }
1845 else
1846 {
cbc26145 1847 if (uipa.Buffer)
ea392307 1848 {
cbc26145
CV
1849 for (ifs = 0, c = uipa.Buffer; *c && ifs < idx;
1850 c += wcslen (c) + 1)
ea392307
CV
1851 ifs++;
1852 if (*c)
cbc26145 1853 inet_uton (c, &addr->sin_addr);
ea392307 1854 }
cbc26145 1855 if (usub.Buffer)
ea392307 1856 {
cbc26145
CV
1857 for (ifs = 0, c = usub.Buffer; *c && ifs < idx;
1858 c += wcslen (c) + 1)
ea392307
CV
1859 ifs++;
1860 if (*c)
cbc26145 1861 inet_uton (c, &mask->sin_addr);
ea392307
CV
1862 }
1863 }
1864 if (ifp->ifa_ifa.ifa_flags & IFF_BROADCAST)
1865 brdc->sin_addr.s_addr = (addr->sin_addr.s_addr
1866 & mask->sin_addr.s_addr)
1867 | ~mask->sin_addr.s_addr;
1868#undef addr
1869#undef mask
1870#undef brdc
cbc26145
CV
1871#undef inet_uton
1872 if (udipa.Buffer)
1873 RtlFreeUnicodeString (&udipa);
1874 if (udsub.Buffer)
1875 RtlFreeUnicodeString (&udsub);
1876 if (uipa.Buffer)
1877 RtlFreeUnicodeString (&uipa);
1878 if (usub.Buffer)
1879 RtlFreeUnicodeString (&usub);
ea392307 1880 }
ea392307
CV
1881}
1882
1883static void
1884get_friendlyname (struct ifall *ifp, PIP_ADAPTER_ADDRESSES pap)
1885{
1886 struct ifreq_frndlyname *iff = (struct ifreq_frndlyname *)
1887 &ifp->ifa_frndlyname;
1888 iff->ifrf_len = sys_wcstombs (iff->ifrf_friendlyname,
1889 IFRF_FRIENDLYNAMESIZ,
1890 pap->FriendlyName);
1891}
1892
1893static void
1894get_hwaddr (struct ifall *ifp, PIP_ADAPTER_ADDRESSES pap)
1895{
1896 for (UINT i = 0; i < IFHWADDRLEN; ++i)
1897 if (i >= pap->PhysicalAddressLength)
1898 ifp->ifa_hwaddr.sa_data[i] = '\0';
1899 else
1900 ifp->ifa_hwaddr.sa_data[i] = pap->PhysicalAddress[i];
1901}
61522196 1902
bff43891 1903/*
61522196 1904 * Get network interfaces. Use IP Helper function GetAdaptersAddresses.
bff43891 1905 */
a71ecb55 1906static struct ifall *
61522196 1907get_ifs (ULONG family)
bff43891
CV
1908{
1909 PIP_ADAPTER_ADDRESSES pa0 = NULL, pap;
1910 PIP_ADAPTER_UNICAST_ADDRESS pua;
bff43891 1911 int cnt = 0;
a71ecb55
CV
1912 struct ifall *ifret = NULL, *ifp;
1913 struct sockaddr_in *if_sin;
1914 struct sockaddr_in6 *if_sin6;
bff43891 1915
a71ecb55 1916 if (!get_adapters_addresses (&pa0, family))
bff43891 1917 goto done;
510a85cb 1918
bff43891 1919 for (pap = pa0; pap; pap = pap->Next)
ea392307
CV
1920 if (!pap->FirstUnicastAddress)
1921 {
1922 /* FirstUnicastAddress is NULL for interfaces which are disconnected.
d3920e10 1923 Fetch number of configured IPv4 addresses from registry and
ea392307
CV
1924 store in an unused member of the adapter addresses structure. */
1925 pap->Ipv6IfIndex = get_ipv4fromreg_ipcnt (pap->AdapterName);
1926 cnt += pap->Ipv6IfIndex;
1927 }
1928 else for (pua = pap->FirstUnicastAddress; pua; pua = pua->Next)
bff43891 1929 ++cnt;
510a85cb 1930
a71ecb55
CV
1931 if (!(ifret = (struct ifall *) calloc (cnt, sizeof (struct ifall))))
1932 goto done;
1933 ifp = ifret;
1934
bff43891
CV
1935 for (pap = pa0; pap; pap = pap->Next)
1936 {
ea392307
CV
1937 DWORD idx = 0;
1938 if (!pap->FirstUnicastAddress)
1939 for (idx = 0; idx < pap->Ipv6IfIndex; ++idx)
1940 {
1941 /* Next in chain */
1942 ifp->ifa_ifa.ifa_next = (struct ifaddrs *) &ifp[1].ifa_ifa;
1943 /* Interface name */
1944 if (idx)
1945 __small_sprintf (ifp->ifa_name, "%s:%u", pap->AdapterName, idx);
1946 else
1947 strcpy (ifp->ifa_name, pap->AdapterName);
1948 ifp->ifa_ifa.ifa_name = ifp->ifa_name;
1949 /* Flags */
1950 ifp->ifa_ifa.ifa_flags = get_flags (pap);
943c59e3
CV
1951 if (pap->IfType != IF_TYPE_PPP
1952 && pap->IfType != IF_TYPE_SOFTWARE_LOOPBACK)
ea392307
CV
1953 ifp->ifa_ifa.ifa_flags |= IFF_BROADCAST;
1954 /* Address */
1955 ifp->ifa_addr.ss_family = AF_INET;
1956 ifp->ifa_ifa.ifa_addr = (struct sockaddr *) &ifp->ifa_addr;
1957 /* Broadcast/Destination address */
1958 ifp->ifa_brddstaddr.ss_family = AF_INET;
1959 ifp->ifa_ifa.ifa_dstaddr = NULL;
1960 /* Netmask */
1961 ifp->ifa_netmask.ss_family = AF_INET;
1962 ifp->ifa_ifa.ifa_netmask = (struct sockaddr *) &ifp->ifa_netmask;
1963 /* Try to fetch real IPv4 address information from registry. */
1964 get_ipv4fromreg (ifp, pap->AdapterName, idx);
1965 /* Hardware address */
1966 get_hwaddr (ifp, pap);
1967 /* Metric */
1968 ifp->ifa_metric = 1;
1969 /* MTU */
1970 ifp->ifa_mtu = pap->Mtu;
1971 /* Interface index */
1972 ifp->ifa_ifindex = pap->IfIndex;
1973 /* Friendly name */
1974 get_friendlyname (ifp, pap);
1975 ++ifp;
1976 }
1977 else
bdcc0b84 1978 for (idx = 0, pua = pap->FirstUnicastAddress; pua; pua = pua->Next)
ea392307
CV
1979 {
1980 struct sockaddr *sa = (struct sockaddr *) pua->Address.lpSockaddr;
a71ecb55
CV
1981# define sin ((struct sockaddr_in *) sa)
1982# define sin6 ((struct sockaddr_in6 *) sa)
ea392307
CV
1983 size_t sa_size = (sa->sa_family == AF_INET6
1984 ? sizeof *sin6 : sizeof *sin);
1985 /* Next in chain */
1986 ifp->ifa_ifa.ifa_next = (struct ifaddrs *) &ifp[1].ifa_ifa;
1987 /* Interface name */
bdcc0b84 1988 if (sa->sa_family == AF_INET && idx)
ea392307 1989 __small_sprintf (ifp->ifa_name, "%s:%u", pap->AdapterName, idx);
a71ecb55 1990 else
ea392307 1991 strcpy (ifp->ifa_name, pap->AdapterName);
bdcc0b84
CV
1992 if (sa->sa_family == AF_INET)
1993 ++idx;
ea392307
CV
1994 ifp->ifa_ifa.ifa_name = ifp->ifa_name;
1995 /* Flags */
1996 ifp->ifa_ifa.ifa_flags = get_flags (pap);
1997 if (sa->sa_family == AF_INET
1998 && pap->IfType != IF_TYPE_SOFTWARE_LOOPBACK
1999 && pap->IfType != IF_TYPE_PPP)
2000 ifp->ifa_ifa.ifa_flags |= IFF_BROADCAST;
ea392307
CV
2001 /* Address */
2002 memcpy (&ifp->ifa_addr, sa, sa_size);
2003 ifp->ifa_ifa.ifa_addr = (struct sockaddr *) &ifp->ifa_addr;
2004 /* Netmask */
2005 int prefix = ip_addr_prefix (pua, pap->FirstPrefix);
2006 switch (sa->sa_family)
2007 {
2008 case AF_INET:
2009 if_sin = (struct sockaddr_in *) &ifp->ifa_netmask;
2010 if_sin->sin_addr.s_addr = htonl (UINT32_MAX << (32 - prefix));
2011 if_sin->sin_family = AF_INET;
2012 break;
2013 case AF_INET6:
2014 if_sin6 = (struct sockaddr_in6 *) &ifp->ifa_netmask;
2015 for (cnt = 0; cnt < 4 && prefix; ++cnt, prefix -= 32)
2016 if_sin6->sin6_addr.s6_addr32[cnt] = UINT32_MAX;
2017 if (prefix < 32)
2018 if_sin6->sin6_addr.s6_addr32[cnt] <<= 32 - prefix;
2019 break;
2020 }
2021 ifp->ifa_ifa.ifa_netmask = (struct sockaddr *) &ifp->ifa_netmask;
2022 if (pap->IfType == IF_TYPE_PPP)
2023 {
2024 /* Destination address */
2025 if (sa->sa_family == AF_INET)
2026 {
2027 if_sin = (struct sockaddr_in *) &ifp->ifa_brddstaddr;
2028 if_sin->sin_addr.s_addr = get_routedst (pap->IfIndex);
2029 if_sin->sin_family = AF_INET;
2030 }
2031 else
2032 /* FIXME: No official way to get the dstaddr for ipv6? */
2033 memcpy (&ifp->ifa_addr, sa, sa_size);
2034 ifp->ifa_ifa.ifa_dstaddr = (struct sockaddr *)
2035 &ifp->ifa_brddstaddr;
2036 }
2037 else
2038 {
2039 /* Broadcast address */
2040 if (sa->sa_family == AF_INET)
2041 {
2042 if_sin = (struct sockaddr_in *) &ifp->ifa_brddstaddr;
2043 uint32_t mask =
2044 ((struct sockaddr_in *) &ifp->ifa_netmask)->sin_addr.s_addr;
2045 if_sin->sin_addr.s_addr = (sin->sin_addr.s_addr & mask)
2046 | ~mask;
2047 if_sin->sin_family = AF_INET;
2048 ifp->ifa_ifa.ifa_broadaddr = (struct sockaddr *)
2049 &ifp->ifa_brddstaddr;
2050 }
2051 else /* No IPv6 broadcast */
2052 ifp->ifa_ifa.ifa_broadaddr = NULL;
2053 }
2054 /* Hardware address */
2055 get_hwaddr (ifp, pap);
2056 /* Metric */
2057 if (wincap.has_gaa_on_link_prefix ())
2058 ifp->ifa_metric = (sa->sa_family == AF_INET
2059 ? ((PIP_ADAPTER_ADDRESSES_LH) pap)->Ipv4Metric
2060 : ((PIP_ADAPTER_ADDRESSES_LH) pap)->Ipv6Metric);
2061 else
2062 ifp->ifa_metric = 1;
2063 /* MTU */
2064 ifp->ifa_mtu = pap->Mtu;
2065 /* Interface index */
2066 ifp->ifa_ifindex = pap->IfIndex;
2067 /* Friendly name */
2068 get_friendlyname (ifp, pap);
2069 ++ifp;
a71ecb55
CV
2070# undef sin
2071# undef sin6
ea392307 2072 }
bff43891 2073 }
a71ecb55
CV
2074 /* Since every entry is set to the next entry, the last entry points to an
2075 invalid next entry now. Fix it retroactively. */
2076 if (ifp > ifret)
2077 ifp[-1].ifa_ifa.ifa_next = NULL;
bff43891
CV
2078
2079done:
2080 if (pa0)
2081 free (pa0);
a71ecb55 2082 return ifret;
bff43891
CV
2083}
2084
a71ecb55
CV
2085extern "C" int
2086getifaddrs (struct ifaddrs **ifap)
2087{
2088 if (!ifap)
2089 {
2090 set_errno (EINVAL);
2091 return -1;
2092 }
2093 struct ifall *ifp;
61522196 2094 ifp = get_ifs (AF_UNSPEC);
a71ecb55
CV
2095 *ifap = &ifp->ifa_ifa;
2096 return ifp ? 0 : -1;
7326d4e4 2097}
1fd5e000 2098
a71ecb55
CV
2099extern "C" void
2100freeifaddrs (struct ifaddrs *ifp)
7326d4e4 2101{
a71ecb55
CV
2102 if (ifp)
2103 free (ifp);
2104}
1fd5e000 2105
a71ecb55
CV
2106int
2107get_ifconf (struct ifconf *ifc, int what)
2108{
893ac8e0
CF
2109 myfault efault;
2110 if (efault.faulted (EFAULT))
5a64d869
CF
2111 return -1;
2112
a71ecb55
CV
2113 /* Ensure we have space for at least one struct ifreqs, fail if not. */
2114 if (ifc->ifc_len < (int) sizeof (struct ifreq))
7326d4e4 2115 {
a71ecb55 2116 set_errno (EINVAL);
7326d4e4
CV
2117 return -1;
2118 }
1fd5e000 2119
a71ecb55 2120 struct ifall *ifret, *ifp;
61522196 2121 ifret = get_ifs (AF_INET);
a71ecb55
CV
2122 if (!ifret)
2123 return -1;
2124
2125 struct sockaddr_in *sin;
2126 struct ifreq *ifr = ifc->ifc_req;
2127 int cnt = 0;
2128 for (ifp = ifret; ifp; ifp = (struct ifall *) ifp->ifa_ifa.ifa_next)
7326d4e4 2129 {
a71ecb55
CV
2130 ++cnt;
2131 strcpy (ifr->ifr_name, ifp->ifa_name);
bcdf7421 2132 switch (what)
7b44665a 2133 {
a71ecb55
CV
2134 case SIOCGIFFLAGS:
2135 ifr->ifr_flags = ifp->ifa_ifa.ifa_flags;
2136 break;
2137 case SIOCGIFCONF:
2138 case SIOCGIFADDR:
2139 sin = (struct sockaddr_in *) &ifr->ifr_addr;
2140 memcpy (sin, &ifp->ifa_addr, sizeof *sin);
2141 break;
2142 case SIOCGIFNETMASK:
2143 sin = (struct sockaddr_in *) &ifr->ifr_netmask;
2144 memcpy (sin, &ifp->ifa_netmask, sizeof *sin);
2145 break;
2146 case SIOCGIFDSTADDR:
2147 sin = (struct sockaddr_in *) &ifr->ifr_dstaddr;
2148 if (ifp->ifa_ifa.ifa_flags & IFF_POINTOPOINT)
2149 memcpy (sin, &ifp->ifa_brddstaddr, sizeof *sin);
2150 else /* Return addr as on Linux. */
2151 memcpy (sin, &ifp->ifa_addr, sizeof *sin);
2152 break;
2153 case SIOCGIFBRDADDR:
2154 sin = (struct sockaddr_in *) &ifr->ifr_broadaddr;
2155 if (!(ifp->ifa_ifa.ifa_flags & IFF_POINTOPOINT))
2156 memcpy (sin, &ifp->ifa_brddstaddr, sizeof *sin);
2157 else
2158 {
2159 sin->sin_addr.s_addr = INADDR_ANY;
2160 sin->sin_family = AF_INET;
2161 sin->sin_port = 0;
2162 }
2163 break;
2164 case SIOCGIFHWADDR:
2165 memcpy (&ifr->ifr_hwaddr, &ifp->ifa_hwaddr, sizeof ifr->ifr_hwaddr);
2166 break;
2167 case SIOCGIFMETRIC:
2168 ifr->ifr_metric = ifp->ifa_metric;
2169 break;
2170 case SIOCGIFMTU:
2171 ifr->ifr_mtu = ifp->ifa_mtu;
2172 break;
2173 case SIOCGIFINDEX:
2174 ifr->ifr_ifindex = ifp->ifa_ifindex;
2175 break;
2176 case SIOCGIFFRNDLYNAM:
2177 memcpy (ifr->ifr_frndlyname, &ifp->ifa_frndlyname,
2178 sizeof (struct ifreq_frndlyname));
bcdf7421 2179 }
a71ecb55
CV
2180 if ((caddr_t) ++ifr >
2181 ifc->ifc_buf + ifc->ifc_len - sizeof (struct ifreq))
2182 break;
1fd5e000 2183 }
a71ecb55
CV
2184 /* Set the correct length */
2185 ifc->ifc_len = cnt * sizeof (struct ifreq);
2186 free (ifret);
1fd5e000
CF
2187 return 0;
2188}
2189
bff43891
CV
2190extern "C" unsigned
2191if_nametoindex (const char *name)
2192{
e7fc9938 2193 PIP_ADAPTER_ADDRESSES pa0 = NULL, pap;
4b13fd15 2194 unsigned index = 0;
bff43891
CV
2195
2196 myfault efault;
2197 if (efault.faulted (EFAULT))
2198 return 0;
2199
61522196 2200 if (get_adapters_addresses (&pa0, AF_UNSPEC))
bff43891
CV
2201 {
2202 char lname[IF_NAMESIZE], *c;
2203
2204 lname[0] = '\0';
2205 strncat (lname, name, IF_NAMESIZE - 1);
2206 if (lname[0] == '{' && (c = strchr (lname, ':')))
2207 *c = '\0';
e7fc9938 2208 for (pap = pa0; pap; pap = pap->Next)
bff43891 2209 if (strcasematch (lname, pap->AdapterName))
4b13fd15 2210 {
7a2c0a0d 2211 index = pap->Ipv6IfIndex ?: pap->IfIndex;
4b13fd15
CV
2212 break;
2213 }
e7fc9938 2214 free (pa0);
bff43891 2215 }
4b13fd15 2216 return index;
bff43891
CV
2217}
2218
2219extern "C" char *
2220if_indextoname (unsigned ifindex, char *ifname)
2221{
e7fc9938 2222 PIP_ADAPTER_ADDRESSES pa0 = NULL, pap;
4b13fd15 2223 char *name = NULL;
bff43891
CV
2224
2225 myfault efault;
2226 if (efault.faulted (EFAULT))
2227 return NULL;
2228
61522196 2229 if (get_adapters_addresses (&pa0, AF_UNSPEC))
bff43891 2230 {
e7fc9938 2231 for (pap = pa0; pap; pap = pap->Next)
7a2c0a0d 2232 if (ifindex == (pap->Ipv6IfIndex ?: pap->IfIndex))
bff43891 2233 {
bbfcc68a
CV
2234 /* Unfortunately the pre-Vista IPv6 stack has a distinct loopback
2235 device with the same Ipv6IfIndex as the IfIndex of the IPv4
2236 loopback device, but with a different adapter name.
2237 For consistency with /proc/net/if_inet6, try to find the
2238 IPv6 loopback device and use that adapter name instead.
2239 We identify the loopback device by its IfIndex of 1. */
2240 if (pap->IfIndex == 1 && pap->Ipv6IfIndex == 0)
2241 for (PIP_ADAPTER_ADDRESSES pap2 = pa0; pap2; pap2 = pap2->Next)
0a20e5a0 2242 if (pap2->Ipv6IfIndex == 1)
bbfcc68a
CV
2243 {
2244 pap = pap2;
2245 break;
2246 }
4b13fd15
CV
2247 name = strcpy (ifname, pap->AdapterName);
2248 break;
bff43891 2249 }
e7fc9938 2250 free (pa0);
bff43891 2251 }
4b13fd15
CV
2252 else
2253 set_errno (ENXIO);
2254 return name;
bff43891
CV
2255}
2256
2257extern "C" struct if_nameindex *
2258if_nameindex (void)
2259{
2260 PIP_ADAPTER_ADDRESSES pa0 = NULL, pap;
2261 struct if_nameindex *iflist = NULL;
2262 char (*ifnamelist)[IF_NAMESIZE];
2263
2264 myfault efault;
2265 if (efault.faulted (EFAULT))
2266 return NULL;
2267
61522196 2268 if (get_adapters_addresses (&pa0, AF_UNSPEC))
bff43891
CV
2269 {
2270 int cnt = 0;
2271 for (pap = pa0; pap; pap = pap->Next)
510a85cb 2272 ++cnt;
bff43891
CV
2273 iflist = (struct if_nameindex *)
2274 malloc ((cnt + 1) * sizeof (struct if_nameindex)
2275 + cnt * IF_NAMESIZE);
2276 if (!iflist)
4b13fd15
CV
2277 set_errno (ENOBUFS);
2278 else
510a85cb 2279 {
4b13fd15
CV
2280 ifnamelist = (char (*)[IF_NAMESIZE]) (iflist + cnt + 1);
2281 for (pap = pa0, cnt = 0; pap; pap = pap->Next)
2282 {
2283 for (int i = 0; i < cnt; ++i)
7a2c0a0d 2284 if (iflist[i].if_index == (pap->Ipv6IfIndex ?: pap->IfIndex))
4b13fd15 2285 goto outer_loop;
7a2c0a0d 2286 iflist[cnt].if_index = pap->Ipv6IfIndex ?: pap->IfIndex;
4b13fd15 2287 strcpy (iflist[cnt].if_name = ifnamelist[cnt], pap->AdapterName);
bbfcc68a
CV
2288 /* See comment in if_indextoname. */
2289 if (pap->IfIndex == 1 && pap->Ipv6IfIndex == 0)
2290 for (PIP_ADAPTER_ADDRESSES pap2 = pa0; pap2; pap2 = pap2->Next)
2291 if (pap2->Ipv6IfIndex == 1)
2292 {
2293 strcpy (ifnamelist[cnt], pap2->AdapterName);
2294 break;
2295 }
4b13fd15
CV
2296 ++cnt;
2297 outer_loop:
2298 ;
2299 }
2300 iflist[cnt].if_index = 0;
2301 iflist[cnt].if_name = NULL;
bff43891 2302 }
4b13fd15 2303 free (pa0);
bff43891 2304 }
4b13fd15
CV
2305 else
2306 set_errno (ENXIO);
2307 return iflist;
bff43891
CV
2308}
2309
2310extern "C" void
2311if_freenameindex (struct if_nameindex *ptr)
2312{
2313 myfault efault;
2314 if (efault.faulted (EFAULT))
2315 return;
2316 free (ptr);
2317}
2318
06a5dd43
CV
2319#define PORT_LOW (IPPORT_EFSSERVER + 1)
2320#define PORT_HIGH (IPPORT_RESERVED - 1)
2321#define NUM_PORTS (PORT_HIGH - PORT_LOW + 1)
2322
4e6a4ea8 2323extern "C" int
70e476d2 2324cygwin_bindresvport_sa (int fd, struct sockaddr *sa)
1fd5e000 2325{
70e476d2
CV
2326 struct sockaddr_storage sst;
2327 struct sockaddr_in *sin = NULL;
2328 struct sockaddr_in6 *sin6 = NULL;
2329 in_port_t port;
2330 socklen_t salen;
2331 int ret;
2332
893ac8e0
CF
2333 myfault efault;
2334 if (efault.faulted (EFAULT))
b0fa0e6e
CV
2335 return -1;
2336
70e476d2
CV
2337 fhandler_socket *fh = get (fd);
2338 if (!fh)
2339 return -1;
2340
2341 if (!sa)
06a5dd43 2342 {
70e476d2
CV
2343 sa = (struct sockaddr *) &sst;
2344 memset (&sst, 0, sizeof sst);
2345 sa->sa_family = fh->get_addr_family ();
2346 }
06a5dd43 2347
70e476d2
CV
2348 switch (sa->sa_family)
2349 {
2350 case AF_INET:
2351 salen = sizeof (struct sockaddr_in);
2352 sin = (struct sockaddr_in *) sa;
2353 port = sin->sin_port;
2354 break;
2355 case AF_INET6:
2356 salen = sizeof (struct sockaddr_in6);
2357 sin6 = (struct sockaddr_in6 *) sa;
2358 port = sin6->sin6_port;
2359 break;
2360 default:
2361 set_errno (EPFNOSUPPORT);
2362 return -1;
06a5dd43 2363 }
79224853 2364
70e476d2
CV
2365 /* If a non-zero port number is given, try this first. If that succeeds,
2366 or if the error message is serious, return. */
2367 if (port)
1fd5e000 2368 {
70e476d2
CV
2369 ret = fh->bind (sa, salen);
2370 if (!ret || (get_errno () != EADDRINUSE && get_errno () != EINVAL))
510a85cb 2371 return ret;
70e476d2 2372 }
df63bd49 2373
70e476d2
CV
2374 LONG myport;
2375
2376 for (int i = 0; i < NUM_PORTS; i++)
2377 {
7b3e3bfd 2378 while ((myport = InterlockedExchange (&cygwin_shared->last_used_bindresvport, -1)) == -1)
084ea510 2379 yield ();
7b3e3bfd 2380 if (myport == 0 || --myport < PORT_LOW)
70e476d2 2381 myport = PORT_HIGH;
db5ae618 2382 InterlockedExchange (&cygwin_shared->last_used_bindresvport, myport);
70e476d2
CV
2383
2384 if (sa->sa_family == AF_INET6)
2385 sin6->sin6_port = htons (myport);
518f5d49 2386 else
70e476d2
CV
2387 sin->sin_port = htons (myport);
2388 if (!(ret = fh->bind (sa, salen)))
2389 break;
2390 if (get_errno () != EADDRINUSE && get_errno () != EINVAL)
2391 break;
1fd5e000 2392 }
df63bd49 2393
70e476d2
CV
2394 return ret;
2395}
2396
2397extern "C" int
2398cygwin_bindresvport (int fd, struct sockaddr_in *sin)
2399{
2400 return cygwin_bindresvport_sa (fd, (struct sockaddr *) sin);
1fd5e000
CF
2401}
2402
1fd5e000
CF
2403/* socketpair: standards? */
2404/* Win32 supports AF_INET only, so ignore domain and protocol arguments */
4e6a4ea8 2405extern "C" int
dc63cea5 2406socketpair (int family, int type, int protocol, int *sb)
1fd5e000
CF
2407{
2408 int res = -1;
2409 SOCKET insock, outsock, newsock;
dc63cea5
CV
2410 struct sockaddr_in sock_in, sock_out;
2411 int len;
1fd5e000 2412
893ac8e0
CF
2413 myfault efault;
2414 if (efault.faulted (EFAULT))
b0fa0e6e
CV
2415 return -1;
2416
0d653155
CV
2417 int flags = type & _SOCK_FLAG_MASK;
2418 type &= ~_SOCK_FLAG_MASK;
2419
dc63cea5
CV
2420 if (family != AF_LOCAL && family != AF_INET)
2421 {
2422 set_errno (EAFNOSUPPORT);
2423 goto done;
2424 }
2425 if (type != SOCK_STREAM && type != SOCK_DGRAM)
2426 {
2427 set_errno (EPROTOTYPE);
2428 goto done;
2429 }
0d653155
CV
2430 if ((flags & ~(SOCK_NONBLOCK | SOCK_CLOEXEC)) != 0)
2431 {
2432 set_errno (EINVAL);
2433 goto done;
2434 }
dc63cea5
CV
2435 if ((family == AF_LOCAL && protocol != PF_UNSPEC && protocol != PF_LOCAL)
2436 || (family == AF_INET && protocol != PF_UNSPEC && protocol != PF_INET))
2437 {
2438 set_errno (EPROTONOSUPPORT);
2439 goto done;
2440 }
2441
dc63cea5 2442 /* create the first socket */
1fd5e000
CF
2443 newsock = socket (AF_INET, type, 0);
2444 if (newsock == INVALID_SOCKET)
2445 {
4e6a4ea8 2446 debug_printf ("first socket call failed");
1fd5e000
CF
2447 set_winsock_errno ();
2448 goto done;
2449 }
2450
2451 /* bind the socket to any unused port */
2452 sock_in.sin_family = AF_INET;
2453 sock_in.sin_port = 0;
a06c3bf3 2454 sock_in.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
1fd5e000
CF
2455 if (bind (newsock, (struct sockaddr *) &sock_in, sizeof (sock_in)) < 0)
2456 {
4e6a4ea8 2457 debug_printf ("bind failed");
1fd5e000
CF
2458 set_winsock_errno ();
2459 closesocket (newsock);
2460 goto done;
2461 }
dc63cea5 2462 len = sizeof (sock_in);
1fd5e000
CF
2463 if (getsockname (newsock, (struct sockaddr *) &sock_in, &len) < 0)
2464 {
2465 debug_printf ("getsockname error");
2466 set_winsock_errno ();
2467 closesocket (newsock);
2468 goto done;
2469 }
2470
dc63cea5
CV
2471 /* For stream sockets, create a listener */
2472 if (type == SOCK_STREAM)
2473 listen (newsock, 2);
1fd5e000
CF
2474
2475 /* create a connecting socket */
2476 outsock = socket (AF_INET, type, 0);
2477 if (outsock == INVALID_SOCKET)
2478 {
4e6a4ea8 2479 debug_printf ("second socket call failed");
1fd5e000
CF
2480 set_winsock_errno ();
2481 closesocket (newsock);
2482 goto done;
2483 }
2484
dc63cea5
CV
2485 /* For datagram sockets, bind the 2nd socket to an unused address, too */
2486 if (type == SOCK_DGRAM)
2487 {
2488 sock_out.sin_family = AF_INET;
2489 sock_out.sin_port = 0;
70e476d2 2490 sock_out.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
dc63cea5
CV
2491 if (bind (outsock, (struct sockaddr *) &sock_out, sizeof (sock_out)) < 0)
2492 {
2493 debug_printf ("bind failed");
2494 set_winsock_errno ();
2495 closesocket (newsock);
2496 closesocket (outsock);
2497 goto done;
2498 }
2499 len = sizeof (sock_out);
2500 if (getsockname (outsock, (struct sockaddr *) &sock_out, &len) < 0)
2501 {
2502 debug_printf ("getsockname error");
2503 set_winsock_errno ();
2504 closesocket (newsock);
2505 closesocket (outsock);
2506 goto done;
2507 }
2508 }
2509
2510 /* Force IP address to loopback */
1fd5e000 2511 sock_in.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
dc63cea5
CV
2512 if (type == SOCK_DGRAM)
2513 sock_out.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
1fd5e000 2514
dc63cea5 2515 /* Do a connect */
79224853 2516 if (connect (outsock, (struct sockaddr *) &sock_in, sizeof (sock_in)) < 0)
1fd5e000
CF
2517 {
2518 debug_printf ("connect error");
2519 set_winsock_errno ();
2520 closesocket (newsock);
2521 closesocket (outsock);
2522 goto done;
2523 }
2524
dc63cea5 2525 if (type == SOCK_STREAM)
1fd5e000 2526 {
dc63cea5
CV
2527 /* For stream sockets, accept the connection and close the listener */
2528 len = sizeof (sock_in);
2529 insock = accept (newsock, (struct sockaddr *) &sock_in, &len);
2530 if (insock == INVALID_SOCKET)
2531 {
2532 debug_printf ("accept error");
2533 set_winsock_errno ();
2534 closesocket (newsock);
2535 closesocket (outsock);
2536 goto done;
2537 }
1fd5e000 2538 closesocket (newsock);
dc63cea5
CV
2539 }
2540 else
2541 {
2542 /* For datagram sockets, connect the 2nd socket */
2543 if (connect (newsock, (struct sockaddr *) &sock_out,
79224853 2544 sizeof (sock_out)) < 0)
dc63cea5
CV
2545 {
2546 debug_printf ("connect error");
2547 set_winsock_errno ();
2548 closesocket (newsock);
2549 closesocket (outsock);
2550 goto done;
2551 }
2552 insock = newsock;
1fd5e000
CF
2553 }
2554
518f5d49 2555 {
518f5d49 2556 cygheap_fdnew sb0;
7ac61736 2557 const device *dev;
518f5d49
CV
2558
2559 if (family == AF_INET)
7ac61736 2560 dev = (type == SOCK_STREAM ? tcp_dev : udp_dev);
518f5d49 2561 else
7ac61736 2562 dev = (type == SOCK_STREAM ? stream_dev : dgram_dev);
518f5d49 2563
7ac61736 2564 if (sb0 >= 0 && fdsock (sb0, dev, insock))
518f5d49 2565 {
7ac61736
CF
2566 ((fhandler_socket *) sb0)->set_addr_family (family);
2567 ((fhandler_socket *) sb0)->set_socket_type (type);
56551a9b 2568 ((fhandler_socket *) sb0)->connect_state (connected);
0d653155
CV
2569 if (flags & SOCK_NONBLOCK)
2570 ((fhandler_socket *) sb0)->set_nonblocking (true);
2571 if (flags & SOCK_CLOEXEC)
2572 ((fhandler_socket *) sb0)->set_close_on_exec (true);
496337c9 2573 if (family == AF_LOCAL && type == SOCK_STREAM)
b832c4cf 2574 ((fhandler_socket *) sb0)->af_local_set_sockpair_cred ();
1fd5e000 2575
518f5d49 2576 cygheap_fdnew sb1 (sb0, false);
dc63cea5 2577
7ac61736 2578 if (sb1 >= 0 && fdsock (sb1, dev, outsock))
518f5d49 2579 {
7ac61736
CF
2580 ((fhandler_socket *) sb1)->set_addr_family (family);
2581 ((fhandler_socket *) sb1)->set_socket_type (type);
56551a9b 2582 ((fhandler_socket *) sb1)->connect_state (connected);
0d653155
CV
2583 if (flags & SOCK_NONBLOCK)
2584 ((fhandler_socket *) sb1)->set_nonblocking (true);
2585 if (flags & SOCK_CLOEXEC)
2586 ((fhandler_socket *) sb1)->set_close_on_exec (true);
496337c9 2587 if (family == AF_LOCAL && type == SOCK_STREAM)
b832c4cf 2588 ((fhandler_socket *) sb1)->af_local_set_sockpair_cred ();
518f5d49
CV
2589
2590 sb[0] = sb0;
2591 sb[1] = sb1;
2592 res = 0;
2593 }
a5408d98
CV
2594 else
2595 sb0.release ();
518f5d49
CV
2596 }
2597
2598 if (res == -1)
2599 {
a113a3c5 2600 closesocket (insock);
518f5d49
CV
2601 closesocket (outsock);
2602 }
2603 }
1fd5e000
CF
2604
2605done:
b9aa8149 2606 syscall_printf ("%R = socketpair(...)", res);
1fd5e000
CF
2607 return res;
2608}
2609
dd4f0b23
CV
2610/* sethostent: standards? */
2611extern "C" void
2612sethostent (int)
2613{
2614}
2615
2616/* endhostent: standards? */
2617extern "C" void
2618endhostent (void)
2619{
2620}
7d6be0d6
CV
2621
2622/* exported as recvmsg: standards? */
61522196 2623extern "C" ssize_t
b4f06520 2624cygwin_recvmsg (int fd, struct msghdr *msg, int flags)
be5007aa 2625{
61522196
CV
2626 ssize_t res;
2627
2628 pthread_testcancel ();
0a642325 2629
b4f06520 2630 fhandler_socket *fh = get (fd);
7d6be0d6 2631
893ac8e0
CF
2632 myfault efault;
2633 if (efault.faulted (EFAULT) || !fh)
b4f06520
CS
2634 res = -1;
2635 else
4d147a03
CV
2636 {
2637 res = check_iovec_for_read (msg->msg_iov, msg->msg_iovlen);
6cb222ed
CV
2638 /* Originally we shortcircuited here if res == 0.
2639 Allow 0 bytes buffer. This is valid in POSIX and handled in
2640 fhandler_socket::recv_internal. If we shortcircuit, we fail
2641 to deliver valid error conditions and peer address. */
2642 if (res >= 0)
88386154 2643 res = fh->recvmsg (msg, flags);
4d147a03 2644 }
b4f06520 2645
61522196 2646 syscall_printf ("%lR = recvmsg(%d, %p, %y)", res, fd, msg, flags);
b4f06520 2647 return res;
7d6be0d6
CV
2648}
2649
2650/* exported as sendmsg: standards? */
61522196 2651extern "C" ssize_t
b4f06520 2652cygwin_sendmsg (int fd, const struct msghdr *msg, int flags)
be5007aa 2653{
61522196
CV
2654 ssize_t res;
2655
2656 pthread_testcancel ();
4d147a03 2657
b4f06520 2658 fhandler_socket *fh = get (fd);
be5007aa 2659
893ac8e0
CF
2660 myfault efault;
2661 if (efault.faulted (EFAULT) || !fh)
b4f06520 2662 res = -1;
5bf785a0 2663 else
4d147a03
CV
2664 {
2665 res = check_iovec_for_write (msg->msg_iov, msg->msg_iovlen);
88386154
CV
2666 if (res >= 0)
2667 res = fh->sendmsg (msg, flags);
4d147a03 2668 }
b4f06520 2669
61522196 2670 syscall_printf ("%lR = sendmsg(%d, %p, %y)", res, fd, msg, flags);
b4f06520 2671 return res;
1c657740 2672}
b3ba5059 2673
70e476d2
CV
2674/* This is from the BIND 4.9.4 release, modified to compile by itself */
2675
2676/* Copyright (c) 1996 by Internet Software Consortium.
2677 *
2678 * Permission to use, copy, modify, and distribute this software for any
2679 * purpose with or without fee is hereby granted, provided that the above
2680 * copyright notice and this permission notice appear in all copies.
2681 *
2682 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
2683 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
2684 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
2685 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
2686 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
2687 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
2688 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
2689 * SOFTWARE.
2690 */
2691
70e476d2
CV
2692/* int
2693 * inet_pton4(src, dst)
2694 * like inet_aton() but without all the hexadecimal and shorthand.
2695 * return:
2696 * 1 if `src' is a valid dotted quad, else 0.
2697 * notice:
2698 * does not touch `dst' unless it's returning 1.
2699 * author:
2700 * Paul Vixie, 1996.
2701 */
2702static int
2703inet_pton4 (const char *src, u_char *dst)
2704{
2705 static const char digits[] = "0123456789";
2706 int saw_digit, octets, ch;
2707 u_char tmp[INADDRSZ], *tp;
2708
2709 saw_digit = 0;
2710 octets = 0;
2711 *(tp = tmp) = 0;
2712 while ((ch = *src++) != '\0')
2713 {
2714 const char *pch;
2715
2716 if ((pch = strchr(digits, ch)) != NULL)
510a85cb 2717 {
70e476d2
CV
2718 u_int ret = *tp * 10 + (pch - digits);
2719
2720 if (ret > 255)
2721 return (0);
2722 *tp = ret;
2723 if (! saw_digit)
2724 {
2725 if (++octets > 4)
2726 return (0);
2727 saw_digit = 1;
2728 }
2729 }
2730 else if (ch == '.' && saw_digit)
510a85cb 2731 {
70e476d2
CV
2732 if (octets == 4)
2733 return (0);
2734 *++tp = 0;
2735 saw_digit = 0;
2736 }
2737 else
2738 return (0);
2739 }
2740 if (octets < 4)
2741 return (0);
2742
2743 memcpy(dst, tmp, INADDRSZ);
2744 return (1);
2745}
2746
2747/* int
2748 * inet_pton6(src, dst)
2749 * convert presentation level address to network order binary form.
2750 * return:
2751 * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
2752 * notice:
2753 * (1) does not touch `dst' unless it's returning 1.
2754 * (2) :: in a full address is silently ignored.
2755 * credit:
2756 * inspired by Mark Andrews.
2757 * author:
2758 * Paul Vixie, 1996.
2759 */
2760static int
2761inet_pton6 (const char *src, u_char *dst)
2762{
2763 static const char xdigits_l[] = "0123456789abcdef",
2764 xdigits_u[] = "0123456789ABCDEF";
2765 u_char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
2766 const char *xdigits, *curtok;
2767 int ch, saw_xdigit;
2768 u_int val;
2769
2770 memset((tp = tmp), 0, IN6ADDRSZ);
2771 endp = tp + IN6ADDRSZ;
2772 colonp = NULL;
2773 /* Leading :: requires some special handling. */
2774 if (*src == ':')
2775 if (*++src != ':')
2776 return (0);
2777 curtok = src;
2778 saw_xdigit = 0;
2779 val = 0;
2780 while ((ch = *src++) != '\0')
2781 {
2782 const char *pch;
2783
2784 if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
2785 pch = strchr((xdigits = xdigits_u), ch);
2786 if (pch != NULL)
510a85cb 2787 {
70e476d2
CV
2788 val <<= 4;
2789 val |= (pch - xdigits);
2790 if (val > 0xffff)
2791 return (0);
2792 saw_xdigit = 1;
2793 continue;
2794 }
2795 if (ch == ':')
510a85cb 2796 {
70e476d2
CV
2797 curtok = src;
2798 if (!saw_xdigit)
2799 {
2800 if (colonp)
2801 return (0);
2802 colonp = tp;
2803 continue;
2804 }
2805 if (tp + INT16SZ > endp)
2806 return (0);
2807 *tp++ = (u_char) (val >> 8) & 0xff;
2808 *tp++ = (u_char) val & 0xff;
2809 saw_xdigit = 0;
2810 val = 0;
2811 continue;
2812 }
2813 if (ch == '.' && ((tp + INADDRSZ) <= endp) && inet_pton4(curtok, tp) > 0)
510a85cb 2814 {
70e476d2
CV
2815 tp += INADDRSZ;
2816 saw_xdigit = 0;
2817 break; /* '\0' was seen by inet_pton4(). */
2818 }
2819 return (0);
2820 }
2821 if (saw_xdigit)
2822 {
2823 if (tp + INT16SZ > endp)
2824 return (0);
2825 *tp++ = (u_char) (val >> 8) & 0xff;
2826 *tp++ = (u_char) val & 0xff;
2827 }
2828 if (colonp != NULL)
2829 {
2830 /*
2831 * Since some memmove()'s erroneously fail to handle
2832 * overlapping regions, we'll do the shift by hand.
2833 */
2834 const int n = tp - colonp;
2835 int i;
2836
2837 for (i = 1; i <= n; i++)
510a85cb 2838 {
70e476d2
CV
2839 endp[- i] = colonp[n - i];
2840 colonp[n - i] = 0;
2841 }
2842 tp = endp;
2843 }
2844 if (tp != endp)
2845 return (0);
2846
2847 memcpy(dst, tmp, IN6ADDRSZ);
2848 return (1);
2849}
2850
2851/* int
2852 * inet_pton(af, src, dst)
2853 * convert from presentation format (which usually means ASCII printable)
2854 * to network format (which is usually some kind of binary format).
2855 * return:
2856 * 1 if the address was valid for the specified address family
2857 * 0 if the address wasn't valid (`dst' is untouched in this case)
2858 * -1 if some other error occurred (`dst' is untouched in this case, too)
2859 * author:
2860 * Paul Vixie, 1996.
2861 */
b3ba5059 2862extern "C" int
70e476d2 2863cygwin_inet_pton (int af, const char *src, void *dst)
b3ba5059 2864{
70e476d2 2865 switch (af)
b3ba5059 2866 {
70e476d2
CV
2867 case AF_INET:
2868 return (inet_pton4(src, (u_char *) dst));
2869 case AF_INET6:
2870 return (inet_pton6(src, (u_char *) dst));
2871 default:
2872 errno = EAFNOSUPPORT;
2873 return (-1);
2874 }
2875 /* NOTREACHED */
2876}
2877
2878/* const char *
2879 * inet_ntop4(src, dst, size)
2880 * format an IPv4 address, more or less like inet_ntoa()
2881 * return:
2882 * `dst' (as a const)
2883 * notes:
2884 * (1) uses no statics
2885 * (2) takes a u_char* not an in_addr as input
2886 * author:
2887 * Paul Vixie, 1996.
2888 */
2889static const char *
2890inet_ntop4 (const u_char *src, char *dst, size_t size)
2891{
2892 static const char fmt[] = "%u.%u.%u.%u";
2893 char tmp[sizeof "255.255.255.255"];
2894
2895 __small_sprintf(tmp, fmt, src[0], src[1], src[2], src[3]);
2896 if (strlen(tmp) > size)
2897 {
2898 errno = ENOSPC;
2899 return (NULL);
2900 }
2901 strcpy(dst, tmp);
2902 return (dst);
2903}
2904
2905/* const char *
2906 * inet_ntop6(src, dst, size)
2907 * convert IPv6 binary address into presentation (printable) format
2908 * author:
2909 * Paul Vixie, 1996.
2910 */
2911static const char *
2912inet_ntop6 (const u_char *src, char *dst, size_t size)
2913{
2914 /*
2915 * Note that int32_t and int16_t need only be "at least" large enough
2916 * to contain a value of the specified size. On some systems, like
2917 * Crays, there is no such thing as an integer variable with 16 bits.
2918 * Keep this in mind if you think this function should have been coded
2919 * to use pointer overlays. All the world's not a VAX.
2920 */
2921 char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
2922 struct { int base, len; } best, cur;
2923 u_int words[IN6ADDRSZ / INT16SZ];
2924 int i;
b3ba5059 2925
70e476d2
CV
2926 /*
2927 * Preprocess:
2928 * Copy the input (bytewise) array into a wordwise array.
2929 * Find the longest run of 0x00's in src[] for :: shorthanding.
2930 */
2931 memset(words, 0, sizeof words);
2932 for (i = 0; i < IN6ADDRSZ; i++)
2933 words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
2934 best.base = -1;
2935 cur.base = -1;
1809b65e
CF
2936 best.len = 0;
2937 cur.len = 0;
70e476d2
CV
2938 for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++)
2939 {
2940 if (words[i] == 0)
510a85cb 2941 {
70e476d2
CV
2942 if (cur.base == -1)
2943 cur.base = i, cur.len = 1;
2944 else
2945 cur.len++;
2946 }
2947 else
510a85cb 2948 {
70e476d2
CV
2949 if (cur.base != -1)
2950 {
2951 if (best.base == -1 || cur.len > best.len)
2952 best = cur;
2953 cur.base = -1;
2954 }
2955 }
2956 }
2957 if (cur.base != -1)
2958 {
2959 if (best.base == -1 || cur.len > best.len)
2960 best = cur;
2961 }
2962 if (best.base != -1 && best.len < 2)
2963 best.base = -1;
2964
2965 /*
2966 * Format the result.
2967 */
2968 tp = tmp;
2969 for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++)
2970 {
2971 /* Are we inside the best run of 0x00's? */
2972 if (best.base != -1 && i >= best.base && i < (best.base + best.len))
510a85cb 2973 {
70e476d2
CV
2974 if (i == best.base)
2975 *tp++ = ':';
2976 continue;
2977 }
2978 /* Are we following an initial run of 0x00s or any real hex? */
2979 if (i != 0)
2980 *tp++ = ':';
2981 /* Is this address an encapsulated IPv4? */
2982 if (i == 6 && best.base == 0 &&
2983 (best.len == 6 || (best.len == 5 && words[5] == 0xffff)))
1cd06583 2984 {
70e476d2
CV
2985 if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp)))
2986 return (NULL);
2987 tp += strlen(tp);
2988 break;
b3ba5059 2989 }
70e476d2 2990 __small_sprintf(tp, "%x", words[i]);
6f0c3cc8
CV
2991 while (*tp)
2992 {
2993 if (isupper (*tp))
2994 *tp = _tolower (*tp);
2995 ++tp;
2996 }
b3ba5059 2997 }
70e476d2
CV
2998 /* Was it a trailing run of 0x00's? */
2999 if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ))
3000 *tp++ = ':';
3001 *tp++ = '\0';
3002
3003 /*
3004 * Check for overflow, copy, and we're done.
3005 */
3006 if ((size_t) (tp - tmp) > size)
3007 {
3008 errno = ENOSPC;
3009 return (NULL);
3010 }
3011 strcpy(dst, tmp);
3012 return (dst);
b3ba5059
CV
3013}
3014
70e476d2
CV
3015/* char *
3016 * inet_ntop(af, src, dst, size)
3017 * convert a network format address to presentation format.
3018 * return:
3019 * pointer to presentation format address (`dst'), or NULL (see errno).
3020 * author:
3021 * Paul Vixie, 1996.
3022 */
b3ba5059 3023extern "C" const char *
70e476d2 3024cygwin_inet_ntop (int af, const void *src, char *dst, socklen_t size)
b3ba5059 3025{
70e476d2
CV
3026 switch (af)
3027 {
3028 case AF_INET:
3029 return (inet_ntop4((const u_char *) src, dst, size));
3030 case AF_INET6:
3031 return (inet_ntop6((const u_char *) src, dst, size));
3032 default:
3033 errno = EAFNOSUPPORT;
3034 return (NULL);
3035 }
3036 /* NOTREACHED */
3037}
b3ba5059 3038
70e476d2
CV
3039/* W. Richard STEVENS libgai implementation, slightly tweaked for inclusion
3040 into Cygwin as pure IPv4 replacement. Please note that the code is
3041 kept intact as much as possible. Especially the IPv6 and AF_UNIX code
3042 is kept in, even though we can support neither of them. Please don't
3043 activate them, they won't work correctly. */
3044
3045#define IPv4
3046#undef IPv6
3047#undef UNIXdomain
3048
3049#undef HAVE_SOCKADDR_SA_LEN
3050#define gethostbyname2(host,family) cygwin_gethostbyname((host))
3051
3052#define AI_CLONE 0x8000 /* Avoid collision with AI_ values in netdb.h */
3053
3054/*
3055 * Create and fill in an addrinfo{}.
3056 */
3057
3058/* include ga_aistruct1 */
3059static int
3060ga_aistruct (struct addrinfo ***paipnext, const struct addrinfo *hintsp,
3061 const void *addr, int family)
3062{
3063 struct addrinfo *ai;
3064
3065 if ((ai = (struct addrinfo *) calloc (1, sizeof (struct addrinfo))) == NULL)
3066 return (EAI_MEMORY);
3067 ai->ai_next = NULL;
3068 ai->ai_canonname = NULL;
3069 **paipnext = ai;
3070 *paipnext = &ai->ai_next;
3071
3072 if ((ai->ai_socktype = hintsp->ai_socktype) == 0)
3073 ai->ai_flags |= AI_CLONE;
3074
3075 ai->ai_protocol = hintsp->ai_protocol;
3076/* end ga_aistruct1 */
3077
3078/* include ga_aistruct2 */
3079 switch ((ai->ai_family = family))
3080 {
3081#ifdef IPv4
3082 case AF_INET:
3083 {
3084 struct sockaddr_in *sinptr;
3085
3086 /* 4allocate sockaddr_in{} and fill in all but port */
3087 if ((sinptr = (struct sockaddr_in *)
3088 calloc (1, sizeof (struct sockaddr_in))) == NULL)
3089 return (EAI_MEMORY);
3090#ifdef HAVE_SOCKADDR_SA_LEN
3091 sinptr->sin_len = sizeof (struct sockaddr_in);
3092#endif
3093 sinptr->sin_family = AF_INET;
3094 memcpy (&sinptr->sin_addr, addr, sizeof (struct in_addr));
3095 ai->ai_addr = (struct sockaddr *) sinptr;
3096 ai->ai_addrlen = sizeof (struct sockaddr_in);
3097 break;
3098 }
3099#endif /* IPV4 */
3100#ifdef IPv6
3101 case AF_INET6:
3102 {
3103 struct sockaddr_in6 *sin6ptr;
3104
3105 /* 4allocate sockaddr_in6{} and fill in all but port */
3106 if ((sin6ptr = calloc (1, sizeof (struct sockaddr_in6))) == NULL)
3107 return (EAI_MEMORY);
3108#ifdef HAVE_SOCKADDR_SA_LEN
3109 sin6ptr->sin6_len = sizeof (struct sockaddr_in6);
3110#endif
3111 sin6ptr->sin6_family = AF_INET6;
3112 memcpy (&sin6ptr->sin6_addr, addr, sizeof (struct in6_addr));
3113 ai->ai_addr = (struct sockaddr *) sin6ptr;
3114 ai->ai_addrlen = sizeof (struct sockaddr_in6);
3115 break;
3116 }
3117#endif /* IPV6 */
3118#ifdef UNIXdomain
3119 case AF_LOCAL:
3120 {
3121 struct sockaddr_un *unp;
3122
3123 /* 4allocate sockaddr_un{} and fill in */
3124/* *INDENT-OFF* */
3125 if (strlen(addr) >= sizeof(unp->sun_path))
3126 return(EAI_SERVICE);
3127 if ( (unp = calloc(1, sizeof(struct sockaddr_un))) == NULL)
3128 return(EAI_MEMORY);
3129/* *INDENT-ON* */
3130 unp->sun_family = AF_LOCAL;
3131 strcpy (unp->sun_path, addr);
3132#ifdef HAVE_SOCKADDR_SA_LEN
3133 unp->sun_len = SUN_LEN (unp);
3134#endif
3135 ai->ai_addr = (struct sockaddr *) unp;
3136 ai->ai_addrlen = sizeof (struct sockaddr_un);
3137 if (hintsp->ai_flags & AI_PASSIVE)
3138 unlink (unp->sun_path); /* OK if this fails */
3139 break;
3140 }
3141#endif /* UNIXDOMAIN */
3142 }
3143 return (0);
3144}
3145
3146/* end ga_aistruct2 */
3147
3148/*
3149 * Clone a new addrinfo structure from an existing one.
3150 */
3151
3152/* include ga_clone */
4815dd49
CV
3153
3154/* Cygwin specific: The ga_clone function is split up to allow an easy
3155 duplication of addrinfo structs. This is used to duplicate the
c487f2fe 3156 structures from WinSock, so that we have the allocation of the structs
4815dd49
CV
3157 returned to the application under control. This is especially helpful
3158 for the AI_V4MAPPED case prior to Vista. */
70e476d2 3159static struct addrinfo *
4815dd49 3160ga_dup (struct addrinfo *ai, bool v4mapped)
70e476d2
CV
3161{
3162 struct addrinfo *nai;
3163
3164 if ((nai = (struct addrinfo *) calloc (1, sizeof (struct addrinfo))) == NULL)
3165 return (NULL);
3166
70e476d2 3167 nai->ai_flags = 0; /* make sure AI_CLONE is off */
4815dd49 3168 nai->ai_family = v4mapped ? AF_INET6 : ai->ai_family;
70e476d2
CV
3169 nai->ai_socktype = ai->ai_socktype;
3170 nai->ai_protocol = ai->ai_protocol;
3171 nai->ai_canonname = NULL;
4815dd49
CV
3172 if (!(ai->ai_flags & AI_CLONE) && ai->ai_canonname
3173 && !(nai->ai_canonname = strdup (ai->ai_canonname)))
3174 {
3175 free (nai);
3176 return NULL;
3177 }
3178 nai->ai_addrlen = v4mapped ? sizeof (struct sockaddr_in6) : ai->ai_addrlen;
3179 if ((nai->ai_addr = (struct sockaddr *) malloc (v4mapped
510a85cb 3180 ? sizeof (struct sockaddr_in6)
4815dd49
CV
3181 : ai->ai_addrlen)) == NULL)
3182 {
3183 if (nai->ai_canonname)
510a85cb 3184 free (nai->ai_canonname);
4815dd49
CV
3185 free (nai);
3186 return NULL;
3187 }
3188 if (v4mapped)
3189 {
3190 struct sockaddr_in6 *in = (struct sockaddr_in6 *) nai->ai_addr;
3191 in->sin6_family = AF_INET6;
3192 in->sin6_port = ((struct sockaddr_in *) ai->ai_addr)->sin_port;
3193 in->sin6_flowinfo = 0;
3194 in->sin6_addr.s6_addr32[0] = 0;
3195 in->sin6_addr.s6_addr32[1] = 0;
3196 in->sin6_addr.s6_addr32[2] = htonl (0xffff);
3197 in->sin6_addr.s6_addr32[3] = ((struct sockaddr_in *) ai->ai_addr)->sin_addr.s_addr;
3198 in->sin6_scope_id = 0;
3199 }
3200 else
3201 memcpy (nai->ai_addr, ai->ai_addr, ai->ai_addrlen);
3202
3203 return nai;
3204}
3205
3206static struct addrinfo *
3207ga_clone (struct addrinfo *ai)
3208{
3209 struct addrinfo *nai;
3210
3211 if ((nai = ga_dup (ai, false)))
3212 {
3213 nai->ai_next = ai->ai_next;
3214 ai->ai_next = nai;
3215 }
3216 return nai;
3217}
70e476d2 3218
4815dd49
CV
3219static struct addrinfo *
3220ga_duplist (struct addrinfo *ai, bool v4mapped)
3221{
3222 void ipv4_freeaddrinfo (struct addrinfo *aihead);
3223 struct addrinfo *tmp, *nai = NULL, *nai0 = NULL;
3224
3225 for (; ai; ai = ai->ai_next, nai = tmp)
3226 {
3227 if (!(tmp = ga_dup (ai, v4mapped)))
510a85cb 3228 goto bad;
4815dd49 3229 if (!nai0)
510a85cb 3230 nai0 = tmp;
4815dd49 3231 if (nai)
510a85cb 3232 nai->ai_next = tmp;
4815dd49
CV
3233 }
3234 return nai0;
3235
3236bad:
3237 ipv4_freeaddrinfo (nai0);
3238 return NULL;
70e476d2
CV
3239}
3240
3241/* end ga_clone */
3242
3243/*
3244 * Basic error checking of flags, family, socket type, and protocol.
3245 */
3246
3247/* include ga_echeck */
3248static int
3249ga_echeck (const char *hostname, const char *servname,
3250 int flags, int family, int socktype, int protocol)
3251{
4815dd49 3252#if 0
70e476d2
CV
3253 if (flags & ~(AI_PASSIVE | AI_CANONNAME))
3254 return (EAI_BADFLAGS); /* unknown flag bits */
4815dd49 3255#endif
70e476d2 3256 if (hostname == NULL || hostname[0] == '\0')
b3ba5059 3257 {
70e476d2
CV
3258 if (servname == NULL || servname[0] == '\0')
3259 return (EAI_NONAME); /* host or service must be specified */
3260 }
b3ba5059 3261
70e476d2
CV
3262 switch (family)
3263 {
3264 case AF_UNSPEC:
3265 break;
3266#ifdef IPv4
3267 case AF_INET:
3268 if (socktype != 0 &&
3269 (socktype != SOCK_STREAM &&
3270 socktype != SOCK_DGRAM && socktype != SOCK_RAW))
3271 return (EAI_SOCKTYPE); /* invalid socket type */
3272 break;
3273#endif
3274#ifdef IPv6
3275 case AF_INET6:
3276 if (socktype != 0 &&
3277 (socktype != SOCK_STREAM &&
3278 socktype != SOCK_DGRAM && socktype != SOCK_RAW))
3279 return (EAI_SOCKTYPE); /* invalid socket type */
3280 break;
3281#endif
3282#ifdef UNIXdomain
3283 case AF_LOCAL:
3284 if (socktype != 0 &&
3285 (socktype != SOCK_STREAM && socktype != SOCK_DGRAM))
3286 return (EAI_SOCKTYPE); /* invalid socket type */
3287 break;
3288#endif
3289 default:
3290 return (EAI_FAMILY); /* unknown protocol family */
b3ba5059 3291 }
70e476d2 3292 return (0);
b3ba5059 3293}
70e476d2
CV
3294
3295/* end ga_echeck */
3296
3297struct search {
3298 const char *host; /* hostname or address string */
3299 int family; /* AF_xxx */
3300};
3301
3302/*
3303 * Set up the search[] array with the hostnames and address families
3304 * that we are to look up.
3305 */
3306
3307/* include ga_nsearch1 */
3308static int
3309ga_nsearch (const char *hostname, const struct addrinfo *hintsp,
3310 struct search *search)
3311{
3312 int nsearch = 0;
3313
3314 if (hostname == NULL || hostname[0] == '\0')
3315 {
3316 if (hintsp->ai_flags & AI_PASSIVE)
3317 {
3318 /* 4no hostname and AI_PASSIVE: implies wildcard bind */
3319 switch (hintsp->ai_family)
3320 {
3321#ifdef IPv4
3322 case AF_INET:
3323 search[nsearch].host = "0.0.0.0";
3324 search[nsearch].family = AF_INET;
3325 nsearch++;
3326 break;
3327#endif
3328#ifdef IPv6
3329 case AF_INET6:
3330 search[nsearch].host = "0::0";
3331 search[nsearch].family = AF_INET6;
3332 nsearch++;
3333 break;
3334#endif
3335 case AF_UNSPEC:
3336#ifdef IPv6
3337 search[nsearch].host = "0::0"; /* IPv6 first, then IPv4 */
3338 search[nsearch].family = AF_INET6;
3339 nsearch++;
3340#endif
3341#ifdef IPv4
3342 search[nsearch].host = "0.0.0.0";
3343 search[nsearch].family = AF_INET;
3344 nsearch++;
3345#endif
3346 break;
3347 }
3348/* end ga_nsearch1 */
3349/* include ga_nsearch2 */
3350 }
3351 else
3352 {
3353 /* 4no host and not AI_PASSIVE: connect to local host */
3354 switch (hintsp->ai_family)
3355 {
3356#ifdef IPv4
3357 case AF_INET:
3358 search[nsearch].host = "localhost"; /* 127.0.0.1 */
3359 search[nsearch].family = AF_INET;
3360 nsearch++;
3361 break;
3362#endif
3363#ifdef IPv6
3364 case AF_INET6:
3365 search[nsearch].host = "0::1";
3366 search[nsearch].family = AF_INET6;
3367 nsearch++;
3368 break;
3369#endif
3370 case AF_UNSPEC:
3371#ifdef IPv6
3372 search[nsearch].host = "0::1"; /* IPv6 first, then IPv4 */
3373 search[nsearch].family = AF_INET6;
3374 nsearch++;
3375#endif
3376#ifdef IPv4
3377 search[nsearch].host = "localhost";
3378 search[nsearch].family = AF_INET;
3379 nsearch++;
3380#endif
3381 break;
3382 }
3383 }
3384/* end ga_nsearch2 */
3385/* include ga_nsearch3 */
3386 }
3387 else
3388 { /* host is specified */
3389 switch (hintsp->ai_family)
3390 {
3391#ifdef IPv4
3392 case AF_INET:
3393 search[nsearch].host = hostname;
3394 search[nsearch].family = AF_INET;
3395 nsearch++;
3396 break;
3397#endif
3398#ifdef IPv6
3399 case AF_INET6:
3400 search[nsearch].host = hostname;
3401 search[nsearch].family = AF_INET6;
3402 nsearch++;
3403 break;
3404#endif
3405 case AF_UNSPEC:
3406#ifdef IPv6
3407 search[nsearch].host = hostname;
3408 search[nsearch].family = AF_INET6; /* IPv6 first */
3409 nsearch++;
3410#endif
3411#ifdef IPv4
3412 search[nsearch].host = hostname;
3413 search[nsearch].family = AF_INET; /* then IPv4 */
3414 nsearch++;
3415#endif
3416 break;
3417 }
3418 }
3419 if (nsearch < 1 || nsearch > 2)
3420 return -1;
3421 return (nsearch);
3422}
3423
3424/* end ga_nsearch3 */
3425
3426/*
3427 * Go through all the addrinfo structures, checking for a match of the
3428 * socket type and filling in the socket type, and then the port number
3429 * in the corresponding socket address structures.
3430 *
3431 * The AI_CLONE flag works as follows. Consider a multihomed host with
3432 * two IP addresses and no socket type specified by the caller. After
3433 * the "host" search there are two addrinfo structures, one per IP address.
3434 * Assuming a service supported by both TCP and UDP (say the daytime
3435 * service) we need to return *four* addrinfo structures:
3436 * IP#1, SOCK_STREAM, TCP port,
3437 * IP#1, SOCK_DGRAM, UDP port,
3438 * IP#2, SOCK_STREAM, TCP port,
3439 * IP#2, SOCK_DGRAM, UDP port.
3440 * To do this, when the "host" loop creates an addrinfo structure, if the
3441 * caller has not specified a socket type (hintsp->ai_socktype == 0), the
3442 * AI_CLONE flag is set. When the following function finds an entry like
3443 * this it is handled as follows: If the entry's ai_socktype is still 0,
3444 * this is the first use of the structure, and the ai_socktype field is set.
3445 * But, if the entry's ai_socktype is nonzero, then we clone a new addrinfo
3446 * structure and set it's ai_socktype to the new value. Although we only
3447 * need two socket types today (SOCK_STREAM and SOCK_DGRAM) this algorithm
3448 * will handle any number. Also notice that Posix.1g requires all socket
3449 * types to be nonzero.
3450 */
3451
3452/* include ga_port */
3453static int
3454ga_port (struct addrinfo *aihead, int port, int socktype)
3455 /* port must be in network byte order */
3456{
3457 int nfound = 0;
3458 struct addrinfo *ai;
3459
3460 for (ai = aihead; ai != NULL; ai = ai->ai_next)
3461 {
3462 if (ai->ai_flags & AI_CLONE)
3463 {
3464 if (ai->ai_socktype != 0)
3465 {
3466 if ((ai = ga_clone (ai)) == NULL)
3467 return (-1); /* memory allocation error */
3468 /* ai points to newly cloned entry, which is what we want */
3469 }
3470 }
3471 else if (ai->ai_socktype != socktype)
3472 continue; /* ignore if mismatch on socket type */
3473
3474 ai->ai_socktype = socktype;
3475
3476 switch (ai->ai_family)
3477 {
3478#ifdef IPv4
3479 case AF_INET:
3480 ((struct sockaddr_in *) ai->ai_addr)->sin_port = port;
3481 nfound++;
3482 break;
3483#endif
3484#ifdef IPv6
3485 case AF_INET6:
3486 ((struct sockaddr_in6 *) ai->ai_addr)->sin6_port = port;
3487 nfound++;
3488 break;
3489#endif
3490 }
3491 }
3492 return (nfound);
3493}
3494
3495/* end ga_port */
3496
3497/*
3498 * This function handles the service string.
3499 */
3500
3501/* include ga_serv */
3502static int
3503ga_serv (struct addrinfo *aihead, const struct addrinfo *hintsp,
3504 const char *serv)
3505{
3506 int port, rc, nfound;
3507 struct servent *sptr;
3508
3509 nfound = 0;
3510 if (isdigit (serv[0]))
3511 { /* check for port number string first */
3512 port = htons (atoi (serv));
3513 if (hintsp->ai_socktype)
3514 {
3515 /* 4caller specifies socket type */
3516 if ((rc = ga_port (aihead, port, hintsp->ai_socktype)) < 0)
3517 return (EAI_MEMORY);
3518 nfound += rc;
3519 }
3520 else
3521 {
3522 /* 4caller does not specify socket type */
3523 if ((rc = ga_port (aihead, port, SOCK_STREAM)) < 0)
3524 return (EAI_MEMORY);
3525 nfound += rc;
3526 if ((rc = ga_port (aihead, port, SOCK_DGRAM)) < 0)
3527 return (EAI_MEMORY);
3528 nfound += rc;
3529 }
3530 }
3531 else
3532 {
3533 /* 4try service name, TCP then UDP */
3534 if (hintsp->ai_socktype == 0 || hintsp->ai_socktype == SOCK_STREAM)
3535 {
3536 if ((sptr = cygwin_getservbyname (serv, "tcp")) != NULL)
3537 {
3538 if ((rc = ga_port (aihead, sptr->s_port, SOCK_STREAM)) < 0)
3539 return (EAI_MEMORY);
3540 nfound += rc;
3541 }
3542 }
3543 if (hintsp->ai_socktype == 0 || hintsp->ai_socktype == SOCK_DGRAM)
3544 {
3545 if ((sptr = cygwin_getservbyname (serv, "udp")) != NULL)
3546 {
3547 if ((rc = ga_port (aihead, sptr->s_port, SOCK_DGRAM)) < 0)
3548 return (EAI_MEMORY);
3549 nfound += rc;
3550 }
3551 }
3552 }
3553
3554 if (nfound == 0)
3555 {
3556 if (hintsp->ai_socktype == 0)
3557 return (EAI_NONAME); /* all calls to getservbyname() failed */
3558 else
3559 return (EAI_SERVICE); /* service not supported for socket type */
3560 }
3561 return (0);
3562}
3563
3564/* end ga_serv */
3565
3566#ifdef UNIXdomain
3567/* include ga_unix */
3568static int
3569ga_unix (const char *path, struct addrinfo *hintsp, struct addrinfo **result)
3570{
3571 int rc;
3572 struct addrinfo *aihead, **aipnext;
3573
3574 aihead = NULL;
3575 aipnext = &aihead;
3576
3577 if (hintsp->ai_family != AF_UNSPEC && hintsp->ai_family != AF_LOCAL)
3578 return (EAI_ADDRFAMILY);
3579
3580 if (hintsp->ai_socktype == 0)
3581 {
3582 /* 4no socket type specified: return stream then dgram */
3583 hintsp->ai_socktype = SOCK_STREAM;
3584 if ((rc = ga_aistruct (&aipnext, hintsp, path, AF_LOCAL)) != 0)
3585 return (rc);
3586 hintsp->ai_socktype = SOCK_DGRAM;
3587 }
3588
3589 if ((rc = ga_aistruct (&aipnext, hintsp, path, AF_LOCAL)) != 0)
3590 return (rc);
3591
3592 if (hintsp->ai_flags & AI_CANONNAME)
3593 {
3594 struct utsname myname;
3595
3596 if (uname (&myname) < 0)
3597 return (EAI_SYSTEM);
3598 if ((aihead->ai_canonname = strdup (myname.nodename)) == NULL)
3599 return (EAI_MEMORY);
3600 }
3601
3602 *result = aihead; /* pointer to first structure in linked list */
3603 return (0);
3604}
3605
3606/* end ga_unix */
3607#endif /* UNIXdomain */
3608
3609/* include gn_ipv46 */
3610static int
3611gn_ipv46 (char *host, size_t hostlen, char *serv, size_t servlen,
3612 void *aptr, size_t alen, int family, int port, int flags)
3613{
3614 char *ptr;
3615 struct hostent *hptr;
3616 struct servent *sptr;
3617
3618 if (host && hostlen > 0)
3619 {
3620 if (flags & NI_NUMERICHOST)
3621 {
3622 if (cygwin_inet_ntop (family, aptr, host, hostlen) == NULL)
3623 return (1);
3624 }
3625 else
3626 {
3627 hptr = cygwin_gethostbyaddr ((const char *) aptr, alen, family);
3628 if (hptr != NULL && hptr->h_name != NULL)
3629 {
3630 if (flags & NI_NOFQDN)
3631 {
3632 if ((ptr = strchr (hptr->h_name, '.')) != NULL)
3633 *ptr = 0; /* overwrite first dot */
3634 }
3635 //snprintf (host, hostlen, "%s", hptr->h_name);
3636 *host = '\0';
3637 strncat (host, hptr->h_name, hostlen - 1);
3638 }
3639 else
3640 {
3641 if (flags & NI_NAMEREQD)
3642 return (1);
3643 if (cygwin_inet_ntop (family, aptr, host, hostlen) == NULL)
3644 return (1);
3645 }
3646 }
3647 }
3648
3649 if (serv && servlen > 0)
3650 {
3651 if (flags & NI_NUMERICSERV)
3652 {
3653 //snprintf (serv, servlen, "%d", ntohs (port));
3654 char buf[32];
3655 __small_sprintf (buf, "%d", ntohs (port));
3656 *serv = '\0';
3657 strncat (serv, buf, servlen - 1);
3658 }
3659 else
3660 {
3661 sptr = cygwin_getservbyport (port, (flags & NI_DGRAM) ? "udp" : NULL);
3662 if (sptr != NULL && sptr->s_name != NULL)
3663 {
3664 //snprintf (serv, servlen, "%s", sptr->s_name);
3665 *serv = '\0';
3666 strncat (serv, sptr->s_name, servlen - 1);
3667 }
3668 else
3669 {
3670 //snprintf (serv, servlen, "%d", ntohs (port));
3671 char buf[32];
3672 __small_sprintf (buf, "%d", ntohs (port));
3673 *serv = '\0';
3674 strncat (serv, buf, servlen - 1);
3675 }
3676 }
3677 }
3678 return (0);
3679}
3680
3681/* end gn_ipv46 */
3682
3683/* include freeaddrinfo */
3684void
3685ipv4_freeaddrinfo (struct addrinfo *aihead)
3686{
3687 struct addrinfo *ai, *ainext;
3688
3689 for (ai = aihead; ai != NULL; ai = ainext)
3690 {
3691 if (ai->ai_addr != NULL)
3692 free (ai->ai_addr); /* socket address structure */
3693
3694 if (ai->ai_canonname != NULL)
3695 free (ai->ai_canonname);
3696
3697 ainext = ai->ai_next; /* can't fetch ai_next after free() */
3698 free (ai); /* the addrinfo{} itself */
3699 }
3700}
3701
3702/* end freeaddrinfo */
3703
3704/* include ga1 */
3705
3706int
3707ipv4_getaddrinfo (const char *hostname, const char *servname,
3708 const struct addrinfo *hintsp, struct addrinfo **result)
3709{
3710 int rc, error, nsearch;
3711 char **ap, *canon;
3712 struct hostent *hptr;
3713 struct search search[3], *sptr;
3714 struct addrinfo hints, *aihead, **aipnext;
3715
3716 /*
3717 * If we encounter an error we want to free() any dynamic memory
3718 * that we've allocated. This is our hack to simplify the code.
3719 */
3720#define error(e) { error = (e); goto bad; }
3721
3722 aihead = NULL; /* initialize automatic variables */
3723 aipnext = &aihead;
3724 canon = NULL;
3725
3726 if (hintsp == NULL)
3727 {
3728 bzero (&hints, sizeof (hints));
3729 hints.ai_family = AF_UNSPEC;
3730 }
3731 else
3732 hints = *hintsp; /* struct copy */
3733
3734 /* 4first some basic error checking */
3735 if ((rc = ga_echeck (hostname, servname, hints.ai_flags, hints.ai_family,
3736 hints.ai_socktype, hints.ai_protocol)) != 0)
3737 error (rc);
3738
3739#ifdef UNIXdomain
3740 /* 4special case Unix domain first */
3741 if (hostname != NULL &&
3742 (strcmp (hostname, "/local") == 0 || strcmp (hostname, "/unix") == 0) &&
3743 (servname != NULL && servname[0] == '/'))
3744 return (ga_unix (servname, &hints, result));
3745#endif
3746/* end ga1 */
3747
3748/* include ga3 */
3749 /* 4remainder of function for IPv4/IPv6 */
3750 nsearch = ga_nsearch (hostname, &hints, &search[0]);
3751 if (nsearch == -1)
3752 error (EAI_FAMILY);
3753 for (sptr = &search[0]; sptr < &search[nsearch]; sptr++)
3754 {
3755#ifdef IPv4
3756 /* 4check for an IPv4 dotted-decimal string */
3757 if (isdigit (sptr->host[0]))
3758 {
3759 struct in_addr inaddr;
3760
3761 if (inet_pton4 (sptr->host, (u_char *) &inaddr) == 1)
3762 {
3763 if (hints.ai_family != AF_UNSPEC && hints.ai_family != AF_INET)
3764 error (EAI_ADDRFAMILY);
3765 if (sptr->family != AF_INET)
3766 continue; /* ignore */
3767 rc = ga_aistruct (&aipnext, &hints, &inaddr, AF_INET);
3768 if (rc != 0)
3769 error (rc);
3770 continue;
3771 }
3772 }
3773#endif
3774
3775#ifdef IPv6
3776 /* 4check for an IPv6 hex string */
3777 if ((isxdigit (sptr->host[0]) || sptr->host[0] == ':') &&
3778 (strchr (sptr->host, ':') != NULL))
3779 {
3780 struct in6_addr in6addr;
3781
3782 if (inet_pton6 (sptr->host, &in6addr) == 1)
3783 {
3784 if (hints.ai_family != AF_UNSPEC && hints.ai_family != AF_INET6)
3785 error (EAI_ADDRFAMILY);
3786 if (sptr->family != AF_INET6)
3787 continue; /* ignore */
3788 rc = ga_aistruct (&aipnext, &hints, &in6addr, AF_INET6);
3789 if (rc != 0)
3790 error (rc);
3791 continue;
3792 }
3793 }
3794#endif
3795/* end ga3 */
3796/* include ga4 */
3797#ifdef IPv6
3798 /* 4remainder of for() to look up hostname */
3799 if ((_res.options & RES_INIT) == 0)
3800 res_init (); /* need this to set _res.options */
3801#endif
3802
3803 if (nsearch == 2)
3804 {
3805#ifdef IPv6
3806 _res.options &= ~RES_USE_INET6;
3807#endif
3808 hptr = gethostbyname2 (sptr->host, sptr->family);
3809 }
3810 else
3811 {
3812#ifdef IPv6
3813 if (sptr->family == AF_INET6)
3814 _res.options |= RES_USE_INET6;
3815 else
3816 _res.options &= ~RES_USE_INET6;
3817#endif
3818 hptr = gethostbyname (sptr->host);
3819 }
3820 if (hptr == NULL)
3821 {
3822 if (nsearch == 2)
3823 continue; /* failure OK if multiple searches */
3824
3825 switch (h_errno)
3826 {
3827 case HOST_NOT_FOUND:
3828 error (EAI_NONAME);
3829 case TRY_AGAIN:
3830 error (EAI_AGAIN);
3831 case NO_RECOVERY:
3832 error (EAI_FAIL);
3833 case NO_DATA:
3834 error (EAI_NODATA);
3835 default:
3836 error (EAI_NONAME);
3837 }
3838 }
3839
3840 /* 4check for address family mismatch if one specified */
3841 if (hints.ai_family != AF_UNSPEC && hints.ai_family != hptr->h_addrtype)
3842 error (EAI_ADDRFAMILY);
3843
3844 /* 4save canonical name first time */
3845 if (hostname != NULL && hostname[0] != '\0' &&
3846 (hints.ai_flags & AI_CANONNAME) && canon == NULL)
3847 {
3848 if ((canon = strdup (hptr->h_name)) == NULL)
3849 error (EAI_MEMORY);
3850 }
3851
3852 /* 4create one addrinfo{} for each returned address */
3853 for (ap = hptr->h_addr_list; *ap != NULL; ap++)
3854 {
3855 rc = ga_aistruct (&aipnext, &hints, *ap, hptr->h_addrtype);
3856 if (rc != 0)
3857 error (rc);
3858 }
3859 }
3860 if (aihead == NULL)
3861 error (EAI_NONAME); /* nothing found */
3862/* end ga4 */
3863
3864/* include ga5 */
3865 /* 4return canonical name */
3866 if (hostname != NULL && hostname[0] != '\0' &&
3867 hints.ai_flags & AI_CANONNAME)
3868 {
3869 if (canon != NULL)
3870 aihead->ai_canonname = canon; /* strdup'ed earlier */
3871 else
3872 {
3873 if ((aihead->ai_canonname = strdup (search[0].host)) == NULL)
3874 error (EAI_MEMORY);
3875 }
3876 }
3877
3878 /* 4now process the service name */
3879 if (servname != NULL && servname[0] != '\0')
3880 {
3881 if ((rc = ga_serv (aihead, &hints, servname)) != 0)
3882 error (rc);
3883 }
3884
3885 *result = aihead; /* pointer to first structure in linked list */
3886 return (0);
3887
3888bad:
3889 ipv4_freeaddrinfo (aihead); /* free any alloc'ed memory */
3890 return (error);
3891}
3892
3893/* end ga5 */
3894
3895/* include getnameinfo */
3896int
3897ipv4_getnameinfo (const struct sockaddr *sa, socklen_t salen,
3898 char *host, size_t hostlen,
3899 char *serv, size_t servlen, int flags)
3900{
3901
3902 switch (sa->sa_family)
3903 {
3904#ifdef IPv4
3905 case AF_INET:
3906 {
3907 struct sockaddr_in *sain = (struct sockaddr_in *) sa;
3908
3909 return (gn_ipv46 (host, hostlen, serv, servlen,
3910 &sain->sin_addr, sizeof (struct in_addr),
3911 AF_INET, sain->sin_port, flags));
3912 }
3913#endif
3914
3915#ifdef IPv6
3916 case AF_INET6:
3917 {
3918 struct sockaddr_in6 *sain = (struct sockaddr_in6 *) sa;
3919
3920 return (gn_ipv46 (host, hostlen, serv, servlen,
3921 &sain->sin6_addr, sizeof (struct in6_addr),
3922 AF_INET6, sain->sin6_port, flags));
3923 }
3924#endif
3925
3926#ifdef UNIXdomain
3927 case AF_LOCAL:
3928 {
3929 struct sockaddr_un *un = (struct sockaddr_un *) sa;
3930
3931 if (hostlen > 0)
3932 snprintf (host, hostlen, "%s", "/local");
3933 if (servlen > 0)
3934 snprintf (serv, servlen, "%s", un->sun_path);
3935 return (0);
3936 }
3937#endif
3938
3939 default:
88d1b6df 3940 return (EAI_FAMILY);
70e476d2
CV
3941 }
3942}
3943
3944/* end getnameinfo */
3945
3946/* Start of cygwin specific wrappers around the gai functions. */
3947
3948struct gai_errmap_t
3949{
3950 int w32_errval;
3951 const char *errtxt;
3952};
3953
3954static gai_errmap_t gai_errmap[] =
3955{
f28f68cc
CV
3956 {0, "Success"},
3957 {0, "Address family for hostname not supported"},
3958 {WSATRY_AGAIN, "Temporary failure in name resolution"},
3959 {WSAEINVAL, "Invalid value for ai_flags"},
3960 {WSANO_RECOVERY, "Non-recoverable failure in name resolution"},
3961 {WSAEAFNOSUPPORT, "ai_family not supported"},
70e476d2 3962 {WSA_NOT_ENOUGH_MEMORY, "Memory allocation failure"},
f28f68cc
CV
3963 {WSANO_DATA, "No address associated with hostname"},
3964 {WSAHOST_NOT_FOUND, "hostname nor servname provided, or not known"},
3965 {WSATYPE_NOT_FOUND, "servname not supported for ai_socktype"},
3966 {WSAESOCKTNOSUPPORT, "ai_socktype not supported"},
3967 {0, "System error returned in errno"},
3968 {0, "Invalid value for hints"},
3969 {0, "Resolved protocol is unknown"},
3970 {WSAEFAULT, "An argument buffer overflowed"}
70e476d2
CV
3971};
3972
3973extern "C" const char *
3974cygwin_gai_strerror (int err)
3975{
f28f68cc 3976 if (err >= 0 && err < (int) (sizeof gai_errmap / sizeof *gai_errmap))
70e476d2
CV
3977 return gai_errmap[err].errtxt;
3978 return "Unknown error";
3979}
3980
3981static int
3982w32_to_gai_err (int w32_err)
3983{
3984 if (w32_err >= WSABASEERR)
f28f68cc 3985 for (unsigned i = 0; i < sizeof gai_errmap / sizeof *gai_errmap; ++i)
70e476d2
CV
3986 if (gai_errmap[i].w32_errval == w32_err)
3987 return i;
3988 return w32_err;
3989}
3990
61522196
CV
3991/* We can't use autoload here because we don't know if the functions
3992 are available (pre-Vista). For those systems we redirect to the
3993 ipv4-only version above. */
70e476d2 3994
acddda4b
CV
3995static void (WINAPI *ws_freeaddrinfo)(const struct addrinfo *);
3996static int (WINAPI *ws_getaddrinfo)(const char *, const char *,
3997 const struct addrinfo *,
3998 struct addrinfo **);
3999static int (WINAPI *ws_getnameinfo)(const struct sockaddr *, socklen_t,
4000 char *, size_t, char *, size_t, int);
70e476d2
CV
4001static bool
4002get_ipv6_funcs (HMODULE lib)
4003{
acddda4b 4004 return ((ws_freeaddrinfo = (void (WINAPI *)(const struct addrinfo *))
23f71001 4005 GetProcAddress (lib, "freeaddrinfo"))
acddda4b
CV
4006 && (ws_getaddrinfo = (int (WINAPI *)(const char *, const char *,
4007 const struct addrinfo *,
4008 struct addrinfo **))
23f71001 4009 GetProcAddress (lib, "getaddrinfo"))
acddda4b
CV
4010 && (ws_getnameinfo = (int (WINAPI *)(const struct sockaddr *,
4011 socklen_t, char *, size_t,
4012 char *, size_t, int))
23f71001 4013 GetProcAddress (lib, "getnameinfo")));
70e476d2
CV
4014}
4015
4016static NO_COPY muto load_ipv6_guard;
b8fbf5d4 4017static NO_COPY bool ipv6_inited = false;
70e476d2
CV
4018#define load_ipv6() if (!ipv6_inited) load_ipv6_funcs ();
4019
4020static void
4021load_ipv6_funcs ()
4022{
ba047ace 4023 tmp_pathbuf tp;
893a8b78
CV
4024 PWCHAR lib_path = tp.w_get ();
4025 PWCHAR lib_name;
70e476d2
CV
4026 HMODULE lib;
4027
4028 load_ipv6_guard.init ("klog_guard")->acquire ();
4029 if (ipv6_inited)
4030 goto out;
4031 WSAGetLastError (); /* Kludge. Enforce WSAStartup call. */
893a8b78
CV
4032 lib_name = wcpcpy (lib_path, windows_system_directory);
4033 wcpcpy (lib_name, L"ws2_32.dll");
893a8b78
CV
4034 if ((lib = LoadLibraryW (lib_path)))
4035 {
4036 if (get_ipv6_funcs (lib))
4037 goto out;
4038 FreeLibrary (lib);
4039 }
acddda4b
CV
4040 ws_freeaddrinfo = NULL;
4041 ws_getaddrinfo = NULL;
4042 ws_getnameinfo = NULL;
893a8b78 4043
70e476d2
CV
4044out:
4045 ipv6_inited = true;
4046 load_ipv6_guard.release ();
4047}
4048
4049extern "C" void
4050cygwin_freeaddrinfo (struct addrinfo *addr)
4051{
4052 myfault efault;
4053 if (efault.faulted (EFAULT))
4054 return;
4815dd49 4055 ipv4_freeaddrinfo (addr);
70e476d2
CV
4056}
4057
4058extern "C" int
4059cygwin_getaddrinfo (const char *hostname, const char *servname,
4060 const struct addrinfo *hints, struct addrinfo **res)
4061{
4062 myfault efault;
4063 if (efault.faulted (EFAULT))
4064 return EAI_SYSTEM;
c2decfdc
CV
4065 /* Both subsequent getaddrinfo implementations let all possible values
4066 in ai_flags slip through and just ignore unknowen values. So we have
4067 to check manually here. */
4068 if (hints && (hints->ai_flags
510a85cb 4069 & ~(AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST | AI_ALL
c2decfdc
CV
4070 | AI_NUMERICSERV | AI_ADDRCONFIG | AI_V4MAPPED)))
4071 return EAI_BADFLAGS;
4072 /* AI_NUMERICSERV is not supported in our replacement getaddrinfo, nor
c487f2fe 4073 is it supported by WinSock prior to Vista. We just check the servname
c2decfdc
CV
4074 parameter by ourselves here. */
4075 if (hints && (hints->ai_flags & AI_NUMERICSERV))
4076 {
4077 char *p;
4078 if (servname && *servname && (strtoul (servname, &p, 10), *p))
4079 return EAI_NONAME;
4080 }
70e476d2 4081 load_ipv6 ();
acddda4b 4082 if (!ws_getaddrinfo)
6eedb2be
CV
4083 return ipv4_getaddrinfo (hostname, servname, hints, res);
4084
4085 struct addrinfo nhints, *dupres;
4086
4087 /* AI_ADDRCONFIG is not supported prior to Vista. Rather it's
4088 the default and only possible setting.
4089 On Vista, the default behaviour is as if AI_ADDRCONFIG is set,
4090 apparently for performance reasons. To get the POSIX default
4091 behaviour, the AI_ALL flag has to be set. */
4092 if (wincap.supports_all_posix_ai_flags ()
4093 && hints && hints->ai_family == PF_UNSPEC)
4094 {
4095 nhints = *hints;
4096 hints = &nhints;
4097 nhints.ai_flags |= AI_ALL;
4098 }
acddda4b 4099 int ret = w32_to_gai_err (ws_getaddrinfo (hostname, servname, hints, res));
6eedb2be
CV
4100 /* Always copy over to self-allocated memory. */
4101 if (!ret)
4102 {
4103 dupres = ga_duplist (*res, false);
acddda4b 4104 ws_freeaddrinfo (*res);
6eedb2be
CV
4105 *res = dupres;
4106 if (!dupres)
4107 return EAI_MEMORY;
4108 }
4109 /* AI_V4MAPPED and AI_ALL are not supported prior to Vista. So, what
4110 we do here is to emulate AI_V4MAPPED. If no IPv6 addresses are
4111 returned, or the AI_ALL flag is set, we try with AF_INET again, and
4112 convert the returned IPv4 addresses into v4-in-v6 entries. This
4113 is done in ga_dup if the v4mapped flag is set. */
4114 if (!wincap.supports_all_posix_ai_flags ()
e5d5e036 4115 && hints
6eedb2be
CV
4116 && hints->ai_family == AF_INET6
4117 && (hints->ai_flags & AI_V4MAPPED)
4118 && (ret == EAI_NODATA || ret == EAI_NONAME
4119 || (hints->ai_flags & AI_ALL)))
4120 {
4121 struct addrinfo *v4res;
4122 nhints = *hints;
4123 nhints.ai_family = AF_INET;
acddda4b
CV
4124 int ret2 = w32_to_gai_err (ws_getaddrinfo (hostname, servname,
4125 &nhints, &v4res));
6eedb2be 4126 if (!ret2)
510a85cb 4127 {
6eedb2be 4128 dupres = ga_duplist (v4res, true);
acddda4b 4129 ws_freeaddrinfo (v4res);
4815dd49 4130 if (!dupres)
4815dd49 4131 {
4815dd49 4132 if (!ret)
6eedb2be
CV
4133 ipv4_freeaddrinfo (*res);
4134 return EAI_MEMORY;
4815dd49 4135 }
6eedb2be
CV
4136 /* If a list of v6 addresses exists, append the v4-in-v6 address
4137 list. Otherwise just return the v4-in-v6 address list. */
4138 if (!ret)
4139 {
4140 struct addrinfo *ptr;
4141 for (ptr = *res; ptr->ai_next; ptr = ptr->ai_next)
4142 ;
4143 ptr->ai_next = dupres;
4144 }
4145 else
4146 *res = dupres;
4147 ret = 0;
4815dd49 4148 }
c2decfdc 4149 }
6eedb2be 4150 return ret;
70e476d2
CV
4151}
4152
4153extern "C" int
4154cygwin_getnameinfo (const struct sockaddr *sa, socklen_t salen,
4155 char *host, size_t hostlen, char *serv,
4156 size_t servlen, int flags)
4157{
4158 myfault efault;
4159 if (efault.faulted (EFAULT))
4160 return EAI_SYSTEM;
4161 load_ipv6 ();
acddda4b 4162 if (!ws_getnameinfo)
6eedb2be
CV
4163 return ipv4_getnameinfo (sa, salen, host, hostlen, serv, servlen, flags);
4164
19753e1d 4165 /* When the incoming port number does not resolve to a well-known service,
c487f2fe 4166 WinSock's getnameinfo up to Windows 2003 returns with error WSANO_DATA
19753e1d
CV
4167 instead of setting `serv' to the numeric port number string, as required
4168 by RFC 3493. This is fixed on Vista and later. To avoid the error on
4169 systems up to Windows 2003, we check if the port number resolves
4170 to a well-known service. If not, we set the NI_NUMERICSERV flag. */
4171 if (!wincap.supports_all_posix_ai_flags ())
70e476d2 4172 {
19753e1d
CV
4173 int port = 0;
4174
4175 switch (sa->sa_family)
4176 {
4177 case AF_INET:
4178 port = ((struct sockaddr_in *) sa)->sin_port;
4179 break;
4180 case AF_INET6:
4181 port = ((struct sockaddr_in6 *) sa)->sin6_port;
4182 break;
4183 }
4184 if (!port || !getservbyport (port, flags & NI_DGRAM ? "udp" : "tcp"))
6eedb2be 4185 flags |= NI_NUMERICSERV;
70e476d2 4186 }
acddda4b
CV
4187 int ret = w32_to_gai_err (ws_getnameinfo (sa, salen, host, hostlen, serv,
4188 servlen, flags));
6eedb2be
CV
4189 if (ret)
4190 set_winsock_errno ();
4191 return ret;
70e476d2
CV
4192}
4193
2895b8b5
CV
4194/* The below function in6_are_prefix_equal has been taken from OpenBSD's
4195 src/sys/netinet6/in6.c. */
bff43891
CV
4196
4197/*
4198 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
4199 * All rights reserved.
4200 *
4201 * Redistribution and use in source and binary forms, with or without
4202 * modification, are permitted provided that the following conditions
4203 * are met:
4204 * 1. Redistributions of source code must retain the above copyright
4205 * notice, this list of conditions and the following disclaimer.
4206 * 2. Redistributions in binary form must reproduce the above copyright
4207 * notice, this list of conditions and the following disclaimer in the
4208 * documentation and/or other materials provided with the distribution.
4209 * 3. Neither the name of the project nor the names of its contributors
4210 * may be used to endorse or promote products derived from this software
4211 * without specific prior written permission.
4212 *
4213 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
4214 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4215 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4216 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
4217 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4218 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4219 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4220 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4221 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
4222 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
4223 * SUCH DAMAGE.
4224 */
4225
4226/*
4227 * Copyright (c) 1982, 1986, 1991, 1993
4228 * The Regents of the University of California. All rights reserved.
4229 *
4230 * Redistribution and use in source and binary forms, with or without
4231 * modification, are permitted provided that the following conditions
4232 * are met:
4233 * 1. Redistributions of source code must retain the above copyright
4234 * notice, this list of conditions and the following disclaimer.
4235 * 2. Redistributions in binary form must reproduce the above copyright
4236 * notice, this list of conditions and the following disclaimer in the
4237 * documentation and/or other materials provided with the distribution.
4238 * 3. Neither the name of the University nor the names of its contributors
4239 * may be used to endorse or promote products derived from this software
4240 * without specific prior written permission.
4241 *
4242 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
4243 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4244 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4245 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
4246 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4247 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4248 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4249 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4250 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
4251 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
4252 * SUCH DAMAGE.
4253 *
4254 * @(#)in.c 8.2 (Berkeley) 11/15/93
4255 */
4256
4257static int
4258in6_are_prefix_equal (struct in6_addr *p1, struct in6_addr *p2, int len)
4259{
4260 int bytelen, bitlen;
4261
4262 /* sanity check */
4263 if (0 > len || len > 128)
4264 return 0;
510a85cb 4265
bff43891
CV
4266 bytelen = len / 8;
4267 bitlen = len % 8;
4268
4269 if (memcmp (&p1->s6_addr, &p2->s6_addr, bytelen))
4270 return 0;
4271 /* len == 128 is ok because bitlen == 0 then */
4272 if (bitlen != 0 &&
4273 p1->s6_addr[bytelen] >> (8 - bitlen) !=
4274 p2->s6_addr[bytelen] >> (8 - bitlen))
4275 return 0;
4276
4277 return 1;
4278}
2895b8b5
CV
4279
4280/* These functions are stick to the end of this file so that the
4281 optimization in asm/byteorder.h can be used even here in net.cc. */
4282
4283#undef htonl
4284#undef ntohl
4285#undef htons
4286#undef ntohs
4287
4288/* htonl: standards? */
4289extern "C" uint32_t
4290htonl (uint32_t x)
4291{
4292 return __htonl (x);
4293}
4294
4295/* ntohl: standards? */
4296extern "C" uint32_t
4297ntohl (uint32_t x)
4298{
4299 return __ntohl (x);
4300}
4301
4302/* htons: standards? */
4303extern "C" uint16_t
4304htons (uint16_t x)
4305{
4306 return __htons (x);
4307}
4308
4309/* ntohs: standards? */
4310extern "C" uint16_t
4311ntohs (uint16_t x)
4312{
4313 return __ntohs (x);
4314}
This page took 0.97715 seconds and 5 git commands to generate.