]> sourceware.org Git - newlib-cygwin.git/blame - winsup/cygwin/net.cc
* fhandler.cc (fhandler_base::fcntl): Use new O_NONBLOCK_MASK define.
[newlib-cygwin.git] / winsup / cygwin / net.cc
CommitLineData
1fd5e000
CF
1/* net.cc: network-related routines.
2
55ae1dff 3 Copyright 1996, 1997, 1998, 1999, 2000, 2001 Cygnus Solutions.
1fd5e000
CF
4
5This file is part of Cygwin.
6
7This software is a copyrighted work licensed under the terms of the
8Cygwin license. Please consult the file "CYGWIN_LICENSE" for
9details. */
10
11/* #define DEBUG_NEST_ON 1 */
12
13#define __INSIDE_CYGWIN_NET__
14
4c8d72de 15#include "winsup.h"
1fd5e000
CF
16#include <errno.h>
17#include <sys/socket.h>
18#include <sys/un.h>
9182099c 19#include <iphlpapi.h>
1fd5e000 20
619f7fa0 21#include <stdlib.h>
84c7d409 22#include <unistd.h>
1fd5e000
CF
23#include <netdb.h>
24#include <fcntl.h>
a1299ba5 25#define USE_SYS_TYPES_FD_SET
dd4f0b23 26#include <winsock2.h>
bccd5e0d 27#include "cygerrno.h"
95a8465b 28#include "perprocess.h"
6b91b8d5 29#include "security.h"
bccd5e0d
CF
30#include "fhandler.h"
31#include "path.h"
e2ebe117 32#include "dtable.h"
0381fec6 33#include "cygheap.h"
bccd5e0d
CF
34#include "sync.h"
35#include "sigproc.h"
e2ebe117 36#include "pinfo.h"
f0338f54 37#include "registry.h"
1fd5e000 38
4e6a4ea8 39extern "C" {
1fd5e000
CF
40int h_errno;
41
42int __stdcall rcmd (char **ahost, unsigned short inport, char *locuser,
43 char *remuser, char *cmd, SOCKET *fd2p);
44int __stdcall rexec (char **ahost, unsigned short inport, char *locuser,
45 char *password, char *cmd, SOCKET *fd2p);
46int __stdcall rresvport (int *);
47int sscanf (const char *, const char *, ...);
48} /* End of "C" section */
49
a2cdb048
CV
50class wsock_event
51{
52 WSAEVENT event;
53 WSAOVERLAPPED ovr;
54public:
55 wsock_event () : event (NULL) {};
9f13167f
CV
56 ~wsock_event ()
57 {
58 if (event)
462f4eff 59 WSACloseEvent (event);
9f13167f
CV
60 event = NULL;
61 };
a2cdb048
CV
62
63 LPWSAOVERLAPPED prepare ();
64 int wait (int socket, LPDWORD flags);
65};
66
67LPWSAOVERLAPPED
68wsock_event::prepare ()
69{
70 LPWSAOVERLAPPED ret = NULL;
71
72 SetLastError (0);
6a574f1a 73 if ((event = WSACreateEvent ()) != WSA_INVALID_EVENT)
a2cdb048
CV
74 {
75 memset (&ovr, 0, sizeof ovr);
76 ovr.hEvent = event;
77 ret = &ovr;
78 }
79 else if (GetLastError () == ERROR_PROC_NOT_FOUND) /* winsock2 not available */
80 WSASetLastError (0);
462f4eff 81
a2cdb048
CV
82 debug_printf ("%d = wsock_event::prepare ()", ret);
83 return ret;
84}
85
86int
87wsock_event::wait (int socket, LPDWORD flags)
88{
89 int ret = -1;
90 WSAEVENT ev[2] = { event, signal_arrived };
91
92 switch (WSAWaitForMultipleEvents(2, ev, FALSE, WSA_INFINITE, FALSE))
93 {
94 case WSA_WAIT_EVENT_0:
95 DWORD len;
96 if (WSAGetOverlappedResult(socket, &ovr, &len, FALSE, flags))
97 ret = (int) len;
98 break;
99 case WSA_WAIT_EVENT_0 + 1:
0260054a
CV
100 if (!CancelIo ((HANDLE)socket))
101 {
102 debug_printf ("CancelIo() %E, fallback to blocking io");
103 WSAGetOverlappedResult(socket, &ovr, &len, TRUE, flags);
462f4eff 104 }
0260054a 105 else
462f4eff 106 WSASetLastError (WSAEINTR);
a2cdb048
CV
107 break;
108 case WSA_WAIT_FAILED:
109 break;
110 default: /* Should be impossible. *LOL* */
111 WSASetLastError (WSAEFAULT);
112 break;
113 }
114 WSACloseEvent (event);
115 event = NULL;
116 return ret;
117}
118
d61b1993 119WSADATA wsadata;
dd4f0b23 120
1fd5e000 121/* Cygwin internal */
829425c9
CF
122static SOCKET __stdcall
123set_socket_inheritance (SOCKET sock)
1fd5e000 124{
e5ba4c06 125 if (iswinnt)
829425c9
CF
126 (void) SetHandleInformation ((HANDLE) sock, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT);
127 else
1fd5e000 128 {
829425c9
CF
129 SOCKET newsock;
130 if (!DuplicateHandle (hMainProc, (HANDLE) sock, hMainProc, (HANDLE *) &newsock,
131 0, TRUE, DUPLICATE_SAME_ACCESS))
132 small_printf ("DuplicateHandle failed %E");
133 else
134 {
135 closesocket (sock);
136 sock = newsock;
137 }
1fd5e000 138 }
1fd5e000
CF
139 return sock;
140}
141
142/* htonl: standards? */
4e6a4ea8 143extern "C" unsigned long int
1fd5e000
CF
144htonl (unsigned long int x)
145{
1fd5e000
CF
146 return ((((x & 0x000000ffU) << 24) |
147 ((x & 0x0000ff00U) << 8) |
148 ((x & 0x00ff0000U) >> 8) |
149 ((x & 0xff000000U) >> 24)));
150}
151
152/* ntohl: standards? */
4e6a4ea8 153extern "C" unsigned long int
1fd5e000
CF
154ntohl (unsigned long int x)
155{
156 return htonl (x);
157}
158
159/* htons: standards? */
4e6a4ea8 160extern "C" unsigned short
1fd5e000
CF
161htons (unsigned short x)
162{
1fd5e000
CF
163 return ((((x & 0x000000ffU) << 8) |
164 ((x & 0x0000ff00U) >> 8)));
165}
166
167/* ntohs: standards? */
4e6a4ea8 168extern "C" unsigned short
1fd5e000
CF
169ntohs (unsigned short x)
170{
171 return htons (x);
172}
173
174/* Cygwin internal */
175static void
176dump_protoent (struct protoent *p)
177{
178 if (p)
179 debug_printf ("protoent %s %x %x", p->p_name, p->p_aliases, p->p_proto);
180}
181
0bec0119 182/* exported as inet_ntoa: BSD 4.3 */
4e6a4ea8 183extern "C" char *
1fd5e000
CF
184cygwin_inet_ntoa (struct in_addr in)
185{
186 char *res = inet_ntoa (in);
187 return res;
188}
189
0bec0119 190/* exported as inet_addr: BSD 4.3 */
4e6a4ea8 191extern "C" unsigned long
1fd5e000
CF
192cygwin_inet_addr (const char *cp)
193{
194 unsigned long res = inet_addr (cp);
195 return res;
196}
197
0bec0119
CV
198/* exported as inet_aton: BSD 4.3
199 inet_aton is not exported by wsock32 and ws2_32,
200 so it has to be implemented here. */
201extern "C" int
202cygwin_inet_aton (const char *cp, struct in_addr *inp)
203{
204 unsigned long res = inet_addr (cp);
205 if (res == INADDR_NONE && strcmp (cp, "255.255.255.255"))
38c5dd44 206 return 0;
0bec0119
CV
207 if (inp)
208 inp->s_addr = res;
38c5dd44 209 return 1;
0bec0119
CV
210}
211
046069e4 212/* undocumented in wsock32.dll */
e77d29a9 213extern "C" unsigned int WINAPI inet_network (const char *);
046069e4 214
75a57bf0 215extern "C" unsigned int
046069e4
DD
216cygwin_inet_network (const char *cp)
217{
218 unsigned int res = inet_network (cp);
219 return res;
220}
221
1fd5e000
CF
222/* inet_netof is in the standard BSD sockets library. It is useless
223 for modern networks, since it assumes network values which are no
224 longer meaningful, but some existing code calls it. */
225
4e6a4ea8 226extern "C" unsigned long
1fd5e000
CF
227inet_netof (struct in_addr in)
228{
229 unsigned long i, res;
230
231
232 i = ntohl (in.s_addr);
233 if (IN_CLASSA (i))
234 res = (i & IN_CLASSA_NET) >> IN_CLASSA_NSHIFT;
235 else if (IN_CLASSB (i))
236 res = (i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT;
237 else
238 res = (i & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT;
239
240
241 return res;
242}
243
244/* inet_makeaddr is in the standard BSD sockets library. It is
245 useless for modern networks, since it assumes network values which
246 are no longer meaningful, but some existing code calls it. */
247
4e6a4ea8 248extern "C" struct in_addr
1fd5e000
CF
249inet_makeaddr (int net, int lna)
250{
251 unsigned long i;
252 struct in_addr in;
253
254
255 if (net < IN_CLASSA_MAX)
256 i = (net << IN_CLASSA_NSHIFT) | (lna & IN_CLASSA_HOST);
257 else if (net < IN_CLASSB_MAX)
258 i = (net << IN_CLASSB_NSHIFT) | (lna & IN_CLASSB_HOST);
259 else if (net < 0x1000000)
260 i = (net << IN_CLASSC_NSHIFT) | (lna & IN_CLASSC_HOST);
261 else
262 i = net | lna;
263
264 in.s_addr = htonl (i);
265
266
267 return in;
268}
269
270struct tl
271{
272 int w;
273 const char *s;
274 int e;
275};
276
277static struct tl errmap[] =
278{
3065afdb 279 {WSAEINTR, "WSAEINTR", EINTR},
1fd5e000
CF
280 {WSAEWOULDBLOCK, "WSAEWOULDBLOCK", EWOULDBLOCK},
281 {WSAEINPROGRESS, "WSAEINPROGRESS", EINPROGRESS},
282 {WSAEALREADY, "WSAEALREADY", EALREADY},
283 {WSAENOTSOCK, "WSAENOTSOCK", ENOTSOCK},
284 {WSAEDESTADDRREQ, "WSAEDESTADDRREQ", EDESTADDRREQ},
285 {WSAEMSGSIZE, "WSAEMSGSIZE", EMSGSIZE},
286 {WSAEPROTOTYPE, "WSAEPROTOTYPE", EPROTOTYPE},
287 {WSAENOPROTOOPT, "WSAENOPROTOOPT", ENOPROTOOPT},
288 {WSAEPROTONOSUPPORT, "WSAEPROTONOSUPPORT", EPROTONOSUPPORT},
289 {WSAESOCKTNOSUPPORT, "WSAESOCKTNOSUPPORT", ESOCKTNOSUPPORT},
290 {WSAEOPNOTSUPP, "WSAEOPNOTSUPP", EOPNOTSUPP},
291 {WSAEPFNOSUPPORT, "WSAEPFNOSUPPORT", EPFNOSUPPORT},
292 {WSAEAFNOSUPPORT, "WSAEAFNOSUPPORT", EAFNOSUPPORT},
293 {WSAEADDRINUSE, "WSAEADDRINUSE", EADDRINUSE},
294 {WSAEADDRNOTAVAIL, "WSAEADDRNOTAVAIL", EADDRNOTAVAIL},
295 {WSAENETDOWN, "WSAENETDOWN", ENETDOWN},
296 {WSAENETUNREACH, "WSAENETUNREACH", ENETUNREACH},
297 {WSAENETRESET, "WSAENETRESET", ENETRESET},
298 {WSAECONNABORTED, "WSAECONNABORTED", ECONNABORTED},
299 {WSAECONNRESET, "WSAECONNRESET", ECONNRESET},
300 {WSAENOBUFS, "WSAENOBUFS", ENOBUFS},
301 {WSAEISCONN, "WSAEISCONN", EISCONN},
302 {WSAENOTCONN, "WSAENOTCONN", ENOTCONN},
303 {WSAESHUTDOWN, "WSAESHUTDOWN", ESHUTDOWN},
304 {WSAETOOMANYREFS, "WSAETOOMANYREFS", ETOOMANYREFS},
305 {WSAETIMEDOUT, "WSAETIMEDOUT", ETIMEDOUT},
306 {WSAECONNREFUSED, "WSAECONNREFUSED", ECONNREFUSED},
307 {WSAELOOP, "WSAELOOP", ELOOP},
308 {WSAENAMETOOLONG, "WSAENAMETOOLONG", ENAMETOOLONG},
309 {WSAEHOSTDOWN, "WSAEHOSTDOWN", EHOSTDOWN},
310 {WSAEHOSTUNREACH, "WSAEHOSTUNREACH", EHOSTUNREACH},
311 {WSAENOTEMPTY, "WSAENOTEMPTY", ENOTEMPTY},
312 {WSAEPROCLIM, "WSAEPROCLIM", EPROCLIM},
313 {WSAEUSERS, "WSAEUSERS", EUSERS},
314 {WSAEDQUOT, "WSAEDQUOT", EDQUOT},
315 {WSAESTALE, "WSAESTALE", ESTALE},
316 {WSAEREMOTE, "WSAEREMOTE", EREMOTE},
317 {WSAEINVAL, "WSAEINVAL", EINVAL},
318 {WSAEFAULT, "WSAEFAULT", EFAULT},
f940c5b1 319 {0, "NOERROR", 0},
01cf5d0f 320 {0, NULL, 0}
1fd5e000
CF
321};
322
c90e420d
CF
323static int
324find_winsock_errno (int why)
325{
f940c5b1 326 for (int i = 0; errmap[i].s != NULL; ++i)
c90e420d
CF
327 if (why == errmap[i].w)
328 return errmap[i].e;
329
330 return EPERM;
331}
332
1fd5e000
CF
333/* Cygwin internal */
334void
829425c9 335__set_winsock_errno (const char *fn, int ln)
1fd5e000 336{
c90e420d
CF
337 DWORD werr = WSAGetLastError ();
338 int err = find_winsock_errno (werr);
339 set_errno (err);
340 syscall_printf ("%s:%d - winsock error %d -> errno %d", fn, ln, werr, err);
1fd5e000
CF
341}
342
7d9688b7
CV
343/*
344 * Since the member `s' isn't used for debug output we can use it
345 * for the error text returned by herror and hstrerror.
346 */
1fd5e000
CF
347static struct tl host_errmap[] =
348{
7d9688b7
CV
349 {WSAHOST_NOT_FOUND, "Unknown host", HOST_NOT_FOUND},
350 {WSATRY_AGAIN, "Host name lookup failure", TRY_AGAIN},
351 {WSANO_RECOVERY, "Unknown server error", NO_RECOVERY},
352 {WSANO_DATA, "No address associated with name", NO_DATA},
01cf5d0f 353 {0, NULL, 0}
1fd5e000
CF
354};
355
356/* Cygwin internal */
357static void
358set_host_errno ()
359{
360 int i;
361
362 int why = WSAGetLastError ();
7d9688b7 363 for (i = 0; host_errmap[i].w != 0; ++i)
1fd5e000
CF
364 if (why == host_errmap[i].w)
365 break;
366
367 if (host_errmap[i].w != 0)
368 h_errno = host_errmap[i].e;
369 else
370 h_errno = NETDB_INTERNAL;
371}
372
373/* exported as getprotobyname: standards? */
4e6a4ea8 374extern "C" struct protoent *
1fd5e000
CF
375cygwin_getprotobyname (const char *p)
376{
1fd5e000
CF
377 struct protoent *res = getprotobyname (p);
378 if (!res)
379 set_winsock_errno ();
380
381 dump_protoent (res);
382 return res;
383}
384
385/* exported as getprotobynumber: standards? */
4e6a4ea8 386extern "C" struct protoent *
1fd5e000
CF
387cygwin_getprotobynumber (int number)
388{
1fd5e000
CF
389 struct protoent *res = getprotobynumber (number);
390 if (!res)
391 set_winsock_errno ();
392
393 dump_protoent (res);
394 return res;
395}
396
4e6a4ea8 397fhandler_socket *
1fd5e000
CF
398fdsock (int fd, const char *name, SOCKET soc)
399{
dd4f0b23
CV
400 if (wsadata.wVersion < 512) /* < Winsock 2.0 */
401 soc = set_socket_inheritance (soc);
0381fec6 402 fhandler_socket *fh = (fhandler_socket *) cygheap->fdtab.build_fhandler (fd, FH_SOCKET, name);
1fd5e000
CF
403 fh->set_io_handle ((HANDLE) soc);
404 fh->set_flags (O_RDWR);
0381fec6 405 cygheap->fdtab.inc_need_fixup_before ();
4e6a4ea8 406 return fh;
1fd5e000
CF
407}
408
409/* exported as socket: standards? */
4e6a4ea8 410extern "C" int
1fd5e000
CF
411cygwin_socket (int af, int type, int protocol)
412{
413 int res = -1;
4e6a4ea8 414 SetResourceLock (LOCK_FD_LIST, WRITE_LOCK|READ_LOCK, "socket");
1fd5e000
CF
415
416 SOCKET soc;
417
0381fec6 418 int fd = cygheap->fdtab.find_unused_handle ();
1fd5e000
CF
419
420 if (fd < 0)
4e6a4ea8 421 set_errno (EMFILE);
1fd5e000
CF
422 else
423 {
424 debug_printf ("socket (%d, %d, %d)", af, type, protocol);
425
298fad46 426 soc = socket (AF_INET, type, af == AF_UNIX ? 0 : protocol);
1fd5e000
CF
427
428 if (soc == INVALID_SOCKET)
b0e82b74
CF
429 {
430 set_winsock_errno ();
431 goto done;
432 }
1fd5e000 433
1fd5e000
CF
434 const char *name;
435 if (af == AF_INET)
b0e82b74 436 name = (type == SOCK_STREAM ? "/dev/tcp" : "/dev/udp");
1fd5e000 437 else
0381fec6 438 name = (type == SOCK_STREAM ? "/dev/streamsocket" : "/dev/dgsocket");
1fd5e000 439
4e6a4ea8 440 fdsock (fd, name, soc)->set_addr_family (af);
1fd5e000 441 res = fd;
1fd5e000
CF
442 }
443
444done:
445 syscall_printf ("%d = socket (%d, %d, %d)", res, af, type, protocol);
4e6a4ea8 446 ReleaseResourceLock (LOCK_FD_LIST, WRITE_LOCK|READ_LOCK, "socket");
1fd5e000
CF
447 return res;
448}
449
450/* cygwin internal: map sockaddr into internet domain address */
451
452static int get_inet_addr (const struct sockaddr *in, int inlen,
619f7fa0 453 struct sockaddr_in *out, int *outlen, int* secret = 0)
1fd5e000 454{
619f7fa0
ED
455 int secret_buf [4];
456 int* secret_ptr = (secret ? : secret_buf);
457
1fd5e000
CF
458 if (in->sa_family == AF_INET)
459 {
460 *out = * (sockaddr_in *)in;
461 *outlen = inlen;
462 return 1;
463 }
464 else if (in->sa_family == AF_UNIX)
465 {
6b6a8cef 466 int fd = _open (in->sa_data, O_RDONLY);
1fd5e000
CF
467 if (fd == -1)
468 return 0;
6b6a8cef
CV
469
470 int ret = 0;
619f7fa0 471 char buf[128];
6b6a8cef
CV
472 memset (buf, 0, sizeof buf);
473 if (read (fd, buf, sizeof buf) != -1)
462f4eff 474 {
6b6a8cef
CV
475 sockaddr_in sin;
476 sin.sin_family = AF_INET;
619f7fa0
ED
477 sscanf (buf + strlen (SOCKET_COOKIE), "%hu %08x-%08x-%08x-%08x",
478 &sin.sin_port,
479 secret_ptr, secret_ptr + 1, secret_ptr + 2, secret_ptr + 3);
6b6a8cef
CV
480 sin.sin_port = htons (sin.sin_port);
481 sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
482 *out = sin;
483 *outlen = sizeof sin;
484 ret = 1;
462f4eff 485 }
6b6a8cef
CV
486 _close (fd);
487 return ret;
1fd5e000
CF
488 }
489 else
490 {
491 set_errno (EAFNOSUPPORT);
492 return 0;
493 }
494}
495
496/* exported as sendto: standards? */
4e6a4ea8 497extern "C" int
1fd5e000
CF
498cygwin_sendto (int fd,
499 const void *buf,
500 int len,
501 unsigned int flags,
502 const struct sockaddr *to,
503 int tolen)
504{
a2cdb048
CV
505 int res;
506 wsock_event wsock_evt;
507 LPWSAOVERLAPPED ovr;
0381fec6 508 fhandler_socket *h = (fhandler_socket *) cygheap->fdtab[fd];
1fd5e000 509 sockaddr_in sin;
3b0d65ea 510 sigframe thisframe (mainthread);
1fd5e000
CF
511
512 if (get_inet_addr (to, tolen, &sin, &tolen) == 0)
513 return -1;
514
a2cdb048 515 if (!(ovr = wsock_evt.prepare ()))
1fd5e000 516 {
a2cdb048
CV
517 debug_printf ("Fallback to winsock 1 sendto call");
518 if ((res = sendto (h->get_socket (), (const char *) buf, len, flags,
519 to, tolen)) == SOCKET_ERROR)
520 {
521 set_winsock_errno ();
522 res = -1;
523 }
524 }
525 else
526 {
527 WSABUF wsabuf = { len, (char *) buf };
528 DWORD ret = 0;
529 if (WSASendTo (h->get_socket (), &wsabuf, 1, &ret, (DWORD)flags,
462f4eff
CF
530 to, tolen, ovr, NULL) != SOCKET_ERROR)
531 res = ret;
a2cdb048 532 else if ((res = WSAGetLastError ()) != WSA_IO_PENDING)
462f4eff
CF
533 {
534 set_winsock_errno ();
535 res = -1;
536 }
a2cdb048 537 else if ((res = wsock_evt.wait (h->get_socket (), (DWORD *)&flags)) == -1)
462f4eff 538 set_winsock_errno ();
1fd5e000 539 }
a2cdb048
CV
540
541 syscall_printf ("%d = sendto (%d, %x, %x, %x)", res, fd, buf, len, flags);
542
1fd5e000
CF
543 return res;
544}
545
546/* exported as recvfrom: standards? */
4e6a4ea8 547extern "C" int
1fd5e000
CF
548cygwin_recvfrom (int fd,
549 char *buf,
550 int len,
551 int flags,
552 struct sockaddr *from,
553 int *fromlen)
554{
a2cdb048
CV
555 int res;
556 wsock_event wsock_evt;
557 LPWSAOVERLAPPED ovr;
0381fec6 558 fhandler_socket *h = (fhandler_socket *) cygheap->fdtab[fd];
3b0d65ea 559 sigframe thisframe (mainthread);
1fd5e000 560
a2cdb048 561 if (!(ovr = wsock_evt.prepare ()))
1fd5e000 562 {
a2cdb048
CV
563 debug_printf ("Fallback to winsock 1 recvfrom call");
564 if ((res = recvfrom (h->get_socket (), buf, len, flags, from, fromlen))
462f4eff 565 == SOCKET_ERROR)
a2cdb048
CV
566 {
567 set_winsock_errno ();
568 res = -1;
569 }
570 }
571 else
572 {
573 WSABUF wsabuf = { len, (char *) buf };
574 DWORD ret = 0;
575 if (WSARecvFrom (h->get_socket (), &wsabuf, 1, &ret, (DWORD *)&flags,
462f4eff
CF
576 from, fromlen, ovr, NULL) != SOCKET_ERROR)
577 res = ret;
a2cdb048 578 else if ((res = WSAGetLastError ()) != WSA_IO_PENDING)
462f4eff
CF
579 {
580 set_winsock_errno ();
581 res = -1;
582 }
a2cdb048 583 else if ((res = wsock_evt.wait (h->get_socket (), (DWORD *)&flags)) == -1)
462f4eff 584 set_winsock_errno ();
1fd5e000
CF
585 }
586
a2cdb048
CV
587 syscall_printf ("%d = recvfrom (%d, %x, %x, %x)", res, fd, buf, len, flags);
588
1fd5e000
CF
589 return res;
590}
591
592/* Cygwin internal */
593fhandler_socket *
594get (int fd)
595{
0381fec6 596 if (cygheap->fdtab.not_open (fd))
1fd5e000
CF
597 {
598 set_errno (EINVAL);
599 return 0;
600 }
601
0381fec6 602 return cygheap->fdtab[fd]->is_socket ();
1fd5e000
CF
603}
604
605/* exported as setsockopt: standards? */
4e6a4ea8 606extern "C" int
1fd5e000
CF
607cygwin_setsockopt (int fd,
608 int level,
609 int optname,
610 const void *optval,
611 int optlen)
612{
613 fhandler_socket *h = get (fd);
614 int res = -1;
615 const char *name = "error";
616
617 if (h)
618 {
619 /* For the following debug_printf */
620 switch (optname)
621 {
622 case SO_DEBUG:
623 name="SO_DEBUG";
624 break;
625 case SO_ACCEPTCONN:
626 name="SO_ACCEPTCONN";
627 break;
628 case SO_REUSEADDR:
629 name="SO_REUSEADDR";
630 break;
631 case SO_KEEPALIVE:
632 name="SO_KEEPALIVE";
633 break;
634 case SO_DONTROUTE:
635 name="SO_DONTROUTE";
636 break;
637 case SO_BROADCAST:
638 name="SO_BROADCAST";
639 break;
640 case SO_USELOOPBACK:
641 name="SO_USELOOPBACK";
642 break;
643 case SO_LINGER:
644 name="SO_LINGER";
645 break;
646 case SO_OOBINLINE:
647 name="SO_OOBINLINE";
648 break;
c90e420d
CF
649 case SO_ERROR:
650 name="SO_ERROR";
651 break;
1fd5e000
CF
652 }
653
654 res = setsockopt (h->get_socket (), level, optname,
655 (const char *) optval, optlen);
656
657 if (optlen == 4)
658 syscall_printf ("setsockopt optval=%x", *(long *) optval);
659
660 if (res)
661 set_winsock_errno ();
662 }
663
664 syscall_printf ("%d = setsockopt (%d, %d, %x (%s), %x, %d)",
665 res, fd, level, optname, name, optval, optlen);
666 return res;
667}
668
669/* exported as getsockopt: standards? */
4e6a4ea8 670extern "C" int
1fd5e000
CF
671cygwin_getsockopt (int fd,
672 int level,
673 int optname,
674 void *optval,
675 int *optlen)
676{
677 fhandler_socket *h = get (fd);
678 int res = -1;
679 const char *name = "error";
680 if (h)
681 {
682 /* For the following debug_printf */
683 switch (optname)
684 {
685 case SO_DEBUG:
686 name="SO_DEBUG";
687 break;
688 case SO_ACCEPTCONN:
689 name="SO_ACCEPTCONN";
690 break;
691 case SO_REUSEADDR:
692 name="SO_REUSEADDR";
693 break;
694 case SO_KEEPALIVE:
695 name="SO_KEEPALIVE";
696 break;
697 case SO_DONTROUTE:
698 name="SO_DONTROUTE";
699 break;
700 case SO_BROADCAST:
701 name="SO_BROADCAST";
702 break;
703 case SO_USELOOPBACK:
704 name="SO_USELOOPBACK";
705 break;
706 case SO_LINGER:
707 name="SO_LINGER";
708 break;
709 case SO_OOBINLINE:
710 name="SO_OOBINLINE";
711 break;
c90e420d
CF
712 case SO_ERROR:
713 name="SO_ERROR";
714 break;
1fd5e000
CF
715 }
716
717 res = getsockopt (h->get_socket (), level, optname,
718 (char *) optval, (int *) optlen);
719
c90e420d
CF
720 if (optname == SO_ERROR)
721 {
722 int *e = (int *) optval;
723 *e = find_winsock_errno (*e);
724 }
725
1fd5e000
CF
726 if (res)
727 set_winsock_errno ();
728 }
729
730 syscall_printf ("%d = getsockopt (%d, %d, %x (%s), %x, %d)",
731 res, fd, level, optname, name, optval, optlen);
732 return res;
733}
734
735/* exported as connect: standards? */
4e6a4ea8 736extern "C" int
1fd5e000
CF
737cygwin_connect (int fd,
738 const struct sockaddr *name,
739 int namelen)
740{
741 int res;
619f7fa0 742 BOOL secret_check_failed = FALSE;
ae036f47 743 BOOL in_progress = FALSE;
1fd5e000
CF
744 fhandler_socket *sock = get (fd);
745 sockaddr_in sin;
619f7fa0 746 int secret [4];
3b0d65ea 747 sigframe thisframe (mainthread);
1fd5e000 748
619f7fa0 749 if (get_inet_addr (name, namelen, &sin, &namelen, secret) == 0)
1fd5e000
CF
750 return -1;
751
752 if (!sock)
753 {
754 res = -1;
755 }
756 else
757 {
758 res = connect (sock->get_socket (), (sockaddr *) &sin, namelen);
759 if (res)
462f4eff 760 {
4c25744f
CV
761 /* Special handling for connect to return the correct error code
762 when called to early on a non-blocking socket. */
763 if (WSAGetLastError () == WSAEWOULDBLOCK)
ae036f47
ED
764 {
765 WSASetLastError (WSAEINPROGRESS);
766 in_progress = TRUE;
767 }
4c25744f
CV
768
769 set_winsock_errno ();
462f4eff 770 }
619f7fa0 771 if (sock->get_addr_family () == AF_UNIX)
462f4eff
CF
772 {
773 if (!res || in_progress)
774 {
775 if (!sock->create_secret_event (secret))
776 {
619f7fa0
ED
777 secret_check_failed = TRUE;
778 }
ae036f47
ED
779 else if (in_progress)
780 sock->signal_secret_event ();
462f4eff 781 }
619f7fa0 782
462f4eff
CF
783 if (!secret_check_failed && !res)
784 {
619f7fa0
ED
785 if (!sock->check_peer_secret_event (&sin, secret))
786 {
787 debug_printf ( "accept from unauthorized server" );
788 secret_check_failed = TRUE;
789 }
462f4eff 790 }
619f7fa0 791
462f4eff
CF
792 if (secret_check_failed)
793 {
619f7fa0 794 sock->close_secret_event ();
462f4eff
CF
795 if (res)
796 closesocket (res);
619f7fa0
ED
797 set_errno (ECONNREFUSED);
798 res = -1;
462f4eff
CF
799 }
800 }
1fd5e000
CF
801 }
802 return res;
803}
804
805/* exported as getservbyname: standards? */
4e6a4ea8 806extern "C" struct servent *
1fd5e000
CF
807cygwin_getservbyname (const char *name, const char *proto)
808{
809 struct servent *p = getservbyname (name, proto);
810 if (!p)
811 set_winsock_errno ();
812
813 syscall_printf ("%x = getservbyname (%s, %s)", p, name, proto);
814 return p;
815}
816
817/* exported as getservbyport: standards? */
4e6a4ea8 818extern "C" struct servent *
1fd5e000
CF
819cygwin_getservbyport (int port, const char *proto)
820{
821 struct servent *p = getservbyport (port, proto);
822 if (!p)
823 set_winsock_errno ();
824
825 syscall_printf ("%x = getservbyport (%d, %s)", p, port, proto);
826 return p;
827}
828
4e6a4ea8 829extern "C" int
1fd5e000
CF
830cygwin_gethostname (char *name, size_t len)
831{
4e6a4ea8 832 int PASCAL win32_gethostname (char*, int);
1fd5e000
CF
833
834 if (wsock32_handle == NULL ||
835 win32_gethostname (name, len) == SOCKET_ERROR)
836 {
837 DWORD local_len = len;
838
839 if (!GetComputerNameA (name, &local_len))
840 {
841 set_winsock_errno ();
842 return -1;
843 }
844 }
845 debug_printf ("name %s\n", name);
846 h_errno = 0;
847 return 0;
848}
849
850/* exported as gethostbyname: standards? */
4e6a4ea8 851extern "C" struct hostent *
1fd5e000
CF
852cygwin_gethostbyname (const char *name)
853{
854 static unsigned char tmp_addr[4];
855 static struct hostent tmp;
856 static char *tmp_aliases[1] = {0};
4e6a4ea8 857 static char *tmp_addr_list[2] = {0, 0};
1fd5e000 858 static int a, b, c, d;
4e6a4ea8
CF
859
860 if (sscanf (name, "%d.%d.%d.%d", &a, &b, &c, &d) == 4)
1fd5e000
CF
861 {
862 /* In case you don't have DNS, at least x.x.x.x still works */
4e6a4ea8 863 memset (&tmp, 0, sizeof (tmp));
1fd5e000
CF
864 tmp_addr[0] = a;
865 tmp_addr[1] = b;
866 tmp_addr[2] = c;
867 tmp_addr[3] = d;
868 tmp_addr_list[0] = (char *)tmp_addr;
869 tmp.h_name = name;
870 tmp.h_aliases = tmp_aliases;
871 tmp.h_addrtype = 2;
872 tmp.h_length = 4;
873 tmp.h_addr_list = tmp_addr_list;
874 return &tmp;
875 }
876
877 struct hostent *ptr = gethostbyname (name);
878 if (!ptr)
879 {
880 set_winsock_errno ();
881 set_host_errno ();
882 }
883 else
884 {
885 debug_printf ("h_name %s", ptr->h_name);
886 h_errno = 0;
887 }
888 return ptr;
889}
890
891/* exported as accept: standards? */
4e6a4ea8 892extern "C" int
1fd5e000
CF
893cygwin_accept (int fd, struct sockaddr *peer, int *len)
894{
895 int res = -1;
619f7fa0 896 BOOL secret_check_failed = FALSE;
ae036f47 897 BOOL in_progress = FALSE;
3b0d65ea 898 sigframe thisframe (mainthread);
1fd5e000
CF
899
900 fhandler_socket *sock = get (fd);
901 if (sock)
902 {
7eb971a5
CV
903 /* Allows NULL peer and len parameters. */
904 struct sockaddr_in peer_dummy;
905 int len_dummy;
906 if (!peer)
96a3f4ae 907 peer = (struct sockaddr *) &peer_dummy;
7eb971a5 908 if (!len)
96a3f4ae 909 {
7eb971a5
CV
910 len_dummy = sizeof (struct sockaddr_in);
911 len = &len_dummy;
912 }
913
1fd5e000
CF
914 /* accept on NT fails if len < sizeof (sockaddr_in)
915 * some programs set len to
4e6a4ea8 916 * sizeof (name.sun_family) + strlen (name.sun_path) for UNIX domain
1fd5e000
CF
917 */
918 if (len && ((unsigned) *len < sizeof (struct sockaddr_in)))
919 *len = sizeof (struct sockaddr_in);
920
921 res = accept (sock->get_socket (), peer, len); // can't use a blocking call inside a lock
922
ae036f47
ED
923 if ((SOCKET) res == (SOCKET) INVALID_SOCKET &&
924 WSAGetLastError () == WSAEWOULDBLOCK)
925 in_progress = TRUE;
926
619f7fa0 927 if (sock->get_addr_family () == AF_UNIX)
462f4eff 928 {
ae036f47
ED
929 if ((SOCKET) res != (SOCKET) INVALID_SOCKET || in_progress)
930 {
931 if (!sock->create_secret_event ())
932 secret_check_failed = TRUE;
933 else if (in_progress)
934 sock->signal_secret_event ();
935 }
936
937 if (!secret_check_failed &&
462f4eff
CF
938 (SOCKET) res != (SOCKET) INVALID_SOCKET)
939 {
619f7fa0
ED
940 if (!sock->check_peer_secret_event ((struct sockaddr_in*) peer))
941 {
942 debug_printf ("connect from unauthorized client");
943 secret_check_failed = TRUE;
462f4eff
CF
944 }
945 }
946
947 if (secret_check_failed)
948 {
949 sock->close_secret_event ();
950 if ((SOCKET) res != (SOCKET) INVALID_SOCKET)
951 closesocket (res);
619f7fa0 952 set_errno (ECONNABORTED);
462f4eff
CF
953 res = -1;
954 goto done;
955 }
956 }
619f7fa0 957
4e6a4ea8 958 SetResourceLock (LOCK_FD_LIST, WRITE_LOCK|READ_LOCK, "accept");
1fd5e000 959
0381fec6 960 int res_fd = cygheap->fdtab.find_unused_handle ();
1fd5e000
CF
961 if (res_fd == -1)
962 {
963 /* FIXME: what is correct errno? */
964 set_errno (EMFILE);
619f7fa0 965 goto lock_done;
1fd5e000
CF
966 }
967 if ((SOCKET) res == (SOCKET) INVALID_SOCKET)
968 set_winsock_errno ();
969 else
970 {
619f7fa0
ED
971 fhandler_socket* res_fh = fdsock (res_fd, sock->get_name (), res);
972 res_fh->set_addr_family (sock->get_addr_family ());
1fd5e000
CF
973 res = res_fd;
974 }
975 }
619f7fa0
ED
976lock_done:
977 ReleaseResourceLock (LOCK_FD_LIST, WRITE_LOCK|READ_LOCK, "accept");
1fd5e000
CF
978done:
979 syscall_printf ("%d = accept (%d, %x, %x)", res, fd, peer, len);
1fd5e000
CF
980 return res;
981}
982
983/* exported as bind: standards? */
4e6a4ea8 984extern "C" int
55ae1dff 985cygwin_bind (int fd, const struct sockaddr *my_addr, int addrlen)
1fd5e000
CF
986{
987 int res = -1;
988
989 fhandler_socket *sock = get (fd);
990 if (sock)
991 {
992 if (my_addr->sa_family == AF_UNIX)
993 {
994#define un_addr ((struct sockaddr_un *) my_addr)
995 struct sockaddr_in sin;
996 int len = sizeof sin;
997 int fd;
998
b0e82b74
CF
999 if (strlen (un_addr->sun_path) >= UNIX_PATH_LEN)
1000 {
1001 set_errno (ENAMETOOLONG);
1002 goto out;
1003 }
1fd5e000
CF
1004 sin.sin_family = AF_INET;
1005 sin.sin_port = 0;
1006 sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
1007 if (bind (sock->get_socket (), (sockaddr *) &sin, len))
1008 {
1009 syscall_printf ("AF_UNIX: bind failed %d", get_errno ());
1010 set_winsock_errno ();
1011 goto out;
1012 }
1013 if (getsockname (sock->get_socket (), (sockaddr *) &sin, &len))
1014 {
1015 syscall_printf ("AF_UNIX: getsockname failed %d", get_errno ());
1016 set_winsock_errno ();
1017 goto out;
1018 }
1019
1020 sin.sin_port = ntohs (sin.sin_port);
1021 debug_printf ("AF_UNIX: socket bound to port %u", sin.sin_port);
1022
b0e82b74 1023 /* bind must fail if file system socket object already exists
4e6a4ea8 1024 so _open () is called with O_EXCL flag. */
1fd5e000 1025 fd = _open (un_addr->sun_path,
b0e82b74
CF
1026 O_WRONLY | O_CREAT | O_EXCL | O_BINARY,
1027 0);
1fd5e000 1028 if (fd < 0)
b0e82b74
CF
1029 {
1030 if (get_errno () == EEXIST)
1031 set_errno (EADDRINUSE);
1fd5e000 1032 goto out;
b0e82b74 1033 }
1fd5e000 1034
462f4eff 1035 sock->set_connect_secret ();
619f7fa0
ED
1036
1037 char buf[sizeof (SOCKET_COOKIE) + 80];
1038 __small_sprintf (buf, "%s%u ", SOCKET_COOKIE, sin.sin_port);
462f4eff 1039 sock->get_connect_secret (strchr (buf, '\0'));
b0e82b74 1040 len = strlen (buf) + 1;
1fd5e000 1041
b0e82b74
CF
1042 /* Note that the terminating nul is written. */
1043 if (_write (fd, buf, len) != len)
1044 {
1fd5e000 1045 save_errno here;
b0e82b74
CF
1046 _close (fd);
1047 _unlink (un_addr->sun_path);
1048 }
1049 else
1050 {
1051 _close (fd);
1052 chmod (un_addr->sun_path,
a4785603 1053 (S_IFSOCK | S_IRWXU | S_IRWXG | S_IRWXO) & ~cygheap->umask);
1fd5e000 1054 res = 0;
b0e82b74 1055 }
1fd5e000
CF
1056#undef un_addr
1057 }
1058 else if (bind (sock->get_socket (), my_addr, addrlen))
1059 set_winsock_errno ();
1060 else
1061 res = 0;
1062 }
1063
1064out:
1065 syscall_printf ("%d = bind (%d, %x, %d)", res, fd, my_addr, addrlen);
1066 return res;
1067}
1068
1069/* exported as getsockname: standards? */
4e6a4ea8 1070extern "C" int
1fd5e000
CF
1071cygwin_getsockname (int fd, struct sockaddr *addr, int *namelen)
1072{
1073 int res = -1;
1074
1075 fhandler_socket *sock = get (fd);
1076 if (sock)
1077 {
1078 res = getsockname (sock->get_socket (), addr, namelen);
1079 if (res)
1080 set_winsock_errno ();
1081
1082 }
1083 syscall_printf ("%d = getsockname (%d, %x, %d)", res, fd, addr, namelen);
1084 return res;
1085}
1086
1087/* exported as gethostbyaddr: standards? */
4e6a4ea8 1088extern "C" struct hostent *
1fd5e000
CF
1089cygwin_gethostbyaddr (const char *addr, int len, int type)
1090{
1091 struct hostent *ptr = gethostbyaddr (addr, len, type);
1092 if (!ptr)
1093 {
1094 set_winsock_errno ();
1095 set_host_errno ();
1096 }
1097 else
1098 {
1099 debug_printf ("h_name %s", ptr->h_name);
1100 h_errno = 0;
1101 }
1102 return ptr;
1103}
1104
1105/* exported as listen: standards? */
4e6a4ea8 1106extern "C" int
1fd5e000
CF
1107cygwin_listen (int fd, int backlog)
1108{
1109 int res = -1;
1110
1111
1112 fhandler_socket *sock = get (fd);
1113 if (sock)
1114 {
1115 res = listen (sock->get_socket (), backlog);
1116 if (res)
1117 set_winsock_errno ();
1118 }
1119 syscall_printf ("%d = listen (%d, %d)", res, fd, backlog);
1120 return res;
1121}
1122
1123/* exported as shutdown: standards? */
4e6a4ea8 1124extern "C" int
1fd5e000
CF
1125cygwin_shutdown (int fd, int how)
1126{
1127 int res = -1;
3b0d65ea 1128 sigframe thisframe (mainthread);
1fd5e000
CF
1129
1130 fhandler_socket *sock = get (fd);
1131 if (sock)
1132 {
1133 res = shutdown (sock->get_socket (), how);
1134 if (res)
1135 set_winsock_errno ();
1136 }
1137 syscall_printf ("%d = shutdown (%d, %d)", res, fd, how);
1138 return res;
1139}
1140
7d9688b7
CV
1141/* exported as hstrerror: BSD 4.3 */
1142extern "C" const char *
1143cygwin_hstrerror (int err)
1144{
1145 int i;
1146
1147 for (i = 0; host_errmap[i].e != 0; ++i)
1148 if (err == host_errmap[i].e)
1149 break;
1150
1151 return host_errmap[i].s;
1152}
1153
1154/* exported as herror: BSD 4.3 */
4e6a4ea8 1155extern "C" void
7d9688b7 1156cygwin_herror (const char *s)
1fd5e000 1157{
0381fec6 1158 if (cygheap->fdtab.not_open (2))
7d9688b7
CV
1159 return;
1160
1161 if (s)
1162 {
1163 write (2, s, strlen (s));
1164 write (2, ": ", 2);
1165 }
1166
1167 const char *h_errstr = cygwin_hstrerror (h_errno);
1168
1169 if (!h_errstr)
1170 switch (h_errno)
1171 {
1172 case NETDB_INTERNAL:
462f4eff
CF
1173 h_errstr = "Resolver internal error";
1174 break;
7d9688b7 1175 case NETDB_SUCCESS:
462f4eff
CF
1176 h_errstr = "Resolver error 0 (no error)";
1177 break;
7d9688b7 1178 default:
462f4eff
CF
1179 h_errstr = "Unknown resolver error";
1180 break;
7d9688b7
CV
1181 }
1182 write (2, h_errstr, strlen (h_errstr));
1183 write (2, "\n", 1);
1fd5e000
CF
1184}
1185
1186/* exported as getpeername: standards? */
4e6a4ea8 1187extern "C" int
1fd5e000
CF
1188cygwin_getpeername (int fd, struct sockaddr *name, int *len)
1189{
0381fec6 1190 fhandler_socket *h = (fhandler_socket *) cygheap->fdtab[fd];
1fd5e000
CF
1191
1192 debug_printf ("getpeername %d", h->get_socket ());
1193 int res = getpeername (h->get_socket (), name, len);
1194 if (res)
1195 set_winsock_errno ();
1196
1197 debug_printf ("%d = getpeername %d", res, h->get_socket ());
1198 return res;
1199}
1200
1201/* exported as recv: standards? */
4e6a4ea8 1202extern "C" int
1fd5e000
CF
1203cygwin_recv (int fd, void *buf, int len, unsigned int flags)
1204{
a2cdb048
CV
1205 int res;
1206 wsock_event wsock_evt;
1207 LPWSAOVERLAPPED ovr;
0381fec6 1208 fhandler_socket *h = (fhandler_socket *) cygheap->fdtab[fd];
3b0d65ea 1209 sigframe thisframe (mainthread);
1fd5e000 1210
a2cdb048 1211 if (!(ovr = wsock_evt.prepare ()))
1fd5e000 1212 {
a2cdb048
CV
1213 debug_printf ("Fallback to winsock 1 recv call");
1214 if ((res = recv (h->get_socket (), (char *) buf, len, flags))
462f4eff 1215 == SOCKET_ERROR)
a2cdb048
CV
1216 {
1217 set_winsock_errno ();
1218 res = -1;
1219 }
1220 }
1221 else
1222 {
1223 WSABUF wsabuf = { len, (char *) buf };
1224 DWORD ret = 0;
1225 if (WSARecv (h->get_socket (), &wsabuf, 1, &ret, (DWORD *)&flags,
1226 ovr, NULL) != SOCKET_ERROR)
1227 res = ret;
1228 else if ((res = WSAGetLastError ()) != WSA_IO_PENDING)
1229 {
1230 set_winsock_errno ();
1231 res = -1;
1232 }
1233 else if ((res = wsock_evt.wait (h->get_socket (), (DWORD *)&flags)) == -1)
1234 set_winsock_errno ();
1fd5e000 1235 }
1fd5e000
CF
1236
1237 syscall_printf ("%d = recv (%d, %x, %x, %x)", res, fd, buf, len, flags);
1238
1239 return res;
1240}
1241
1242/* exported as send: standards? */
4e6a4ea8 1243extern "C" int
1fd5e000
CF
1244cygwin_send (int fd, const void *buf, int len, unsigned int flags)
1245{
a2cdb048
CV
1246 int res;
1247 wsock_event wsock_evt;
1248 LPWSAOVERLAPPED ovr;
0381fec6 1249 fhandler_socket *h = (fhandler_socket *) cygheap->fdtab[fd];
3b0d65ea 1250 sigframe thisframe (mainthread);
1fd5e000 1251
a2cdb048 1252 if (!(ovr = wsock_evt.prepare ()))
1fd5e000 1253 {
a2cdb048
CV
1254 debug_printf ("Fallback to winsock 1 send call");
1255 if ((res = send (h->get_socket (), (const char *) buf, len, flags))
1256 == SOCKET_ERROR)
1257 {
1258 set_winsock_errno ();
1259 res = -1;
1260 }
1261 }
1262 else
1263 {
1264 WSABUF wsabuf = { len, (char *) buf };
1265 DWORD ret = 0;
1266 if (WSASend (h->get_socket (), &wsabuf, 1, &ret, (DWORD)flags,
462f4eff
CF
1267 ovr, NULL) != SOCKET_ERROR)
1268 res = ret;
a2cdb048 1269 else if ((res = WSAGetLastError ()) != WSA_IO_PENDING)
462f4eff
CF
1270 {
1271 set_winsock_errno ();
1272 res = -1;
1273 }
a2cdb048 1274 else if ((res = wsock_evt.wait (h->get_socket (), (DWORD *)&flags)) == -1)
462f4eff 1275 set_winsock_errno ();
1fd5e000
CF
1276 }
1277
1278 syscall_printf ("%d = send (%d, %x, %d, %x)", res, fd, buf, len, flags);
1279
1280 return res;
1281}
1282
1283/* getdomainname: standards? */
4e6a4ea8 1284extern "C" int
1fd5e000
CF
1285getdomainname (char *domain, int len)
1286{
1287 /*
1288 * This works for Win95 only if the machine is configured to use MS-TCP.
1289 * If a third-party TCP is being used this will fail.
1290 * FIXME: On Win95, is there a way to portably check the TCP stack
1291 * in use and include paths for the Domain name in each ?
1292 * Punt for now and assume MS-TCP on Win95.
1293 */
1294 reg_key r (HKEY_LOCAL_MACHINE, KEY_READ,
e5ba4c06 1295 (!iswinnt) ? "System" : "SYSTEM",
1fd5e000 1296 "CurrentControlSet", "Services",
e5ba4c06 1297 (!iswinnt) ? "MSTCP" : "Tcpip",
1fd5e000
CF
1298 NULL);
1299
1300 /* FIXME: Are registry keys case sensitive? */
1301 if (r.error () || r.get_string ("Domain", domain, len, "") != ERROR_SUCCESS)
1302 {
1303 __seterrno ();
1304 return -1;
1305 }
1306
1307 return 0;
1308}
1309
1310/* Cygwin internal */
52b5a971
CV
1311/* Fill out an ifconf struct. */
1312
1313/*
9182099c
CV
1314 * IFCONF 98/ME, NTSP4, W2K:
1315 * Use IP Helper Library
1fd5e000 1316 */
7326d4e4 1317static void
52b5a971 1318get_2k_ifconf (struct ifconf *ifc, int what)
1fd5e000 1319{
9182099c
CV
1320 int cnt = 0;
1321 char eth[2] = "/", ppp[2] = "/", slp[2] = "/";
7326d4e4
CV
1322
1323 /* Union maps buffer to correct struct */
1324 struct ifreq *ifr = ifc->ifc_req;
1325
9182099c
CV
1326 DWORD if_cnt, ip_cnt, lip, lnp;
1327 DWORD siz_if_table = 0;
1328 DWORD siz_ip_table = 0;
1329 PMIB_IFTABLE ift;
1330 PMIB_IPADDRTABLE ipt;
1331 struct sockaddr_in *sa = NULL;
1332 struct sockaddr *so = NULL;
1333
1334 if (GetIfTable(NULL, &siz_if_table, TRUE) == ERROR_INSUFFICIENT_BUFFER &&
1335 GetIpAddrTable(NULL, &siz_ip_table, TRUE) == ERROR_INSUFFICIENT_BUFFER &&
1336 (ift = (PMIB_IFTABLE) alloca (siz_if_table)) &&
1337 (ipt = (PMIB_IPADDRTABLE) alloca (siz_ip_table)) &&
1338 !GetIfTable(ift, &siz_if_table, TRUE) &&
1339 !GetIpAddrTable(ipt, &siz_ip_table, TRUE))
1fd5e000 1340 {
9182099c 1341 for (if_cnt = 0; if_cnt < ift->dwNumEntries; ++if_cnt)
462f4eff 1342 {
9182099c
CV
1343 switch (ift->table[if_cnt].dwType)
1344 {
1345 case MIB_IF_TYPE_ETHERNET:
1346 ++*eth;
1347 strcpy (ifr->ifr_name, "eth");
1348 strcat (ifr->ifr_name, eth);
1349 break;
1350 case MIB_IF_TYPE_PPP:
1351 ++*ppp;
1352 strcpy (ifr->ifr_name, "ppp");
1353 strcat (ifr->ifr_name, ppp);
1354 break;
1355 case MIB_IF_TYPE_SLIP:
1356 ++*slp;
1357 strcpy (ifr->ifr_name, "slp");
1358 strcat (ifr->ifr_name, slp);
1359 break;
1360 case MIB_IF_TYPE_LOOPBACK:
1361 strcpy (ifr->ifr_name, "lo");
1362 break;
1363 default:
1364 continue;
1365 }
462f4eff
CF
1366 for (ip_cnt = 0; ip_cnt < ipt->dwNumEntries; ++ip_cnt)
1367 if (ipt->table[ip_cnt].dwIndex == ift->table[if_cnt].dwIndex)
9182099c 1368 {
462f4eff
CF
1369 switch (what)
1370 {
1371 case SIOCGIFCONF:
1372 case SIOCGIFADDR:
1373 sa = (struct sockaddr_in *) &ifr->ifr_addr;
1374 sa->sin_addr.s_addr = ipt->table[ip_cnt].dwAddr;
9182099c
CV
1375 sa->sin_family = AF_INET;
1376 sa->sin_port = 0;
462f4eff
CF
1377 break;
1378 case SIOCGIFBRDADDR:
1379 sa = (struct sockaddr_in *) &ifr->ifr_broadaddr;
9182099c
CV
1380#if 0
1381 /* Unfortunately, the field returns only crap. */
462f4eff 1382 sa->sin_addr.s_addr = ipt->table[ip_cnt].dwBCastAddr;
9182099c 1383#else
462f4eff
CF
1384 lip = ipt->table[ip_cnt].dwAddr;
1385 lnp = ipt->table[ip_cnt].dwMask;
1386 sa->sin_addr.s_addr = lip & lnp | ~lnp;
9182099c
CV
1387 sa->sin_family = AF_INET;
1388 sa->sin_port = 0;
1389#endif
462f4eff
CF
1390 break;
1391 case SIOCGIFNETMASK:
1392 sa = (struct sockaddr_in *) &ifr->ifr_netmask;
1393 sa->sin_addr.s_addr = ipt->table[ip_cnt].dwMask;
9182099c
CV
1394 sa->sin_family = AF_INET;
1395 sa->sin_port = 0;
462f4eff 1396 break;
9182099c 1397 case SIOCGIFHWADDR:
462f4eff 1398 so = &ifr->ifr_hwaddr;
9182099c
CV
1399 for (UINT i = 0; i < IFHWADDRLEN; ++i)
1400 if (i >= ift->table[if_cnt].dwPhysAddrLen)
462f4eff 1401 so->sa_data[i] = '\0';
9182099c 1402 else
462f4eff 1403 so->sa_data[i] = ift->table[if_cnt].bPhysAddr[i];
9182099c
CV
1404 so->sa_family = AF_INET;
1405 break;
1406 case SIOCGIFMETRIC:
1407 ifr->ifr_metric = 1;
1408 break;
1409 case SIOCGIFMTU:
1410 ifr->ifr_mtu = ift->table[if_cnt].dwMtu;
1411 break;
462f4eff
CF
1412 }
1413 ++cnt;
1414 if ((caddr_t) ++ifr >
9182099c
CV
1415 ifc->ifc_buf + ifc->ifc_len - sizeof (struct ifreq))
1416 goto done;
462f4eff
CF
1417 break;
1418 }
9182099c 1419 }
7326d4e4 1420 }
9182099c 1421done:
7326d4e4
CV
1422 /* Set the correct length */
1423 ifc->ifc_len = cnt * sizeof (struct ifreq);
1424}
1fd5e000 1425
52b5a971 1426/*
9182099c 1427 * IFCONF Windows NT < SP4:
52b5a971
CV
1428 * Look at the Bind value in
1429 * HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Linkage\
1430 * This is a REG_MULTI_SZ with strings of the form:
1431 * \Device\<Netcard>, where netcard is the name of the net device.
1432 * Then look under:
1433 * HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\<NetCard>\
1434 * Parameters\Tcpip
1435 * at the IPAddress, Subnetmask and DefaultGateway values for the
1436 * required values.
1437 */
7326d4e4 1438static void
52b5a971 1439get_nt_ifconf (struct ifconf *ifc, int what)
7326d4e4
CV
1440{
1441 HKEY key;
1442 unsigned long lip, lnp;
52b5a971 1443 struct sockaddr_in *sa = NULL;
9182099c 1444 struct sockaddr *so = NULL;
52b5a971 1445 DWORD size;
7326d4e4
CV
1446 int cnt = 1;
1447 char *binding = (char *) 0;
1448
1449 /* Union maps buffer to correct struct */
1450 struct ifreq *ifr = ifc->ifc_req;
1451
1452 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE,
462f4eff
CF
1453 "SYSTEM\\"
1454 "CurrentControlSet\\"
1455 "Services\\"
1456 "Tcpip\\"
1457 "Linkage",
1458 0, KEY_READ, &key) == ERROR_SUCCESS)
7326d4e4
CV
1459 {
1460 if (RegQueryValueEx (key, "Bind",
462f4eff
CF
1461 NULL, NULL,
1462 NULL, &size) == ERROR_SUCCESS)
1463 {
1464 binding = (char *) alloca (size);
1465 if (RegQueryValueEx (key, "Bind",
1466 NULL, NULL,
1467 (unsigned char *) binding,
1468 &size) != ERROR_SUCCESS)
1469 {
1470 binding = NULL;
1471 }
1472 }
7326d4e4
CV
1473 RegCloseKey (key);
1474 }
1fd5e000 1475
7326d4e4
CV
1476 if (binding)
1477 {
1478 char *bp, eth[2] = "/";
1479 char cardkey[256], ipaddress[256], netmask[256];
1480
4e6a4ea8 1481 for (bp = binding; *bp; bp += strlen (bp) + 1)
462f4eff
CF
1482 {
1483 bp += strlen ("\\Device\\");
1484 strcpy (cardkey, "SYSTEM\\CurrentControlSet\\Services\\");
1485 strcat (cardkey, bp);
1486 strcat (cardkey, "\\Parameters\\Tcpip");
1487
1488 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, cardkey,
1489 0, KEY_READ, &key) != ERROR_SUCCESS)
1490 continue;
1491
1492 if (RegQueryValueEx (key, "IPAddress",
1493 NULL, NULL,
1494 (unsigned char *) ipaddress,
1495 (size = 256, &size)) == ERROR_SUCCESS
1496 && RegQueryValueEx (key, "SubnetMask",
1497 NULL, NULL,
1498 (unsigned char *) netmask,
1499 (size = 256, &size)) == ERROR_SUCCESS)
1500 {
1501 char *ip, *np;
1502 char dhcpaddress[256], dhcpnetmask[256];
1503
1504 for (ip = ipaddress, np = netmask;
1505 *ip && *np;
1506 ip += strlen (ip) + 1, np += strlen (np) + 1)
1507 {
1508 if ((caddr_t) ++ifr > ifc->ifc_buf
1509 + ifc->ifc_len
1510 - sizeof (struct ifreq))
1511 break;
1512
1513 if (! strncmp (bp, "NdisWan", 7))
1514 {
1515 strcpy (ifr->ifr_name, "ppp");
1516 strcat (ifr->ifr_name, bp + 7);
1517 }
1518 else
1519 {
1520 ++*eth;
1521 strcpy (ifr->ifr_name, "eth");
1522 strcat (ifr->ifr_name, eth);
1523 }
1524 memset (&ifr->ifr_addr, '\0', sizeof ifr->ifr_addr);
1525 if (cygwin_inet_addr (ip) == 0L
1526 && RegQueryValueEx (key, "DhcpIPAddress",
1527 NULL, NULL,
1528 (unsigned char *) dhcpaddress,
1529 (size = 256, &size))
1530 == ERROR_SUCCESS
1531 && RegQueryValueEx (key, "DhcpSubnetMask",
1532 NULL, NULL,
1533 (unsigned char *) dhcpnetmask,
1534 (size = 256, &size))
1535 == ERROR_SUCCESS)
1536 {
1537 switch (what)
1538 {
1539 case SIOCGIFCONF:
1540 case SIOCGIFADDR:
1541 sa = (struct sockaddr_in *) &ifr->ifr_addr;
1542 sa->sin_addr.s_addr = cygwin_inet_addr (dhcpaddress);
9182099c
CV
1543 sa->sin_family = AF_INET;
1544 sa->sin_port = 0;
462f4eff
CF
1545 break;
1546 case SIOCGIFBRDADDR:
1547 lip = cygwin_inet_addr (dhcpaddress);
1548 lnp = cygwin_inet_addr (dhcpnetmask);
1549 sa = (struct sockaddr_in *) &ifr->ifr_broadaddr;
1550 sa->sin_addr.s_addr = lip & lnp | ~lnp;
9182099c
CV
1551 sa->sin_family = AF_INET;
1552 sa->sin_port = 0;
462f4eff
CF
1553 break;
1554 case SIOCGIFNETMASK:
1555 sa = (struct sockaddr_in *) &ifr->ifr_netmask;
1556 sa->sin_addr.s_addr =
1557 cygwin_inet_addr (dhcpnetmask);
9182099c
CV
1558 sa->sin_family = AF_INET;
1559 sa->sin_port = 0;
462f4eff
CF
1560 break;
1561 case SIOCGIFHWADDR:
9182099c
CV
1562 so = &ifr->ifr_hwaddr;
1563 memset (so->sa_data, 0, IFHWADDRLEN);
1564 so->sa_family = AF_INET;
1565 break;
462f4eff 1566 case SIOCGIFMETRIC:
9182099c
CV
1567 ifr->ifr_metric = 1;
1568 break;
1569 case SIOCGIFMTU:
1570 ifr->ifr_mtu = 1500;
1571 break;
462f4eff
CF
1572 }
1573 }
1574 else
1575 {
1576 switch (what)
1577 {
1578 case SIOCGIFCONF:
1579 case SIOCGIFADDR:
1580 sa = (struct sockaddr_in *) &ifr->ifr_addr;
1581 sa->sin_addr.s_addr = cygwin_inet_addr (ip);
9182099c
CV
1582 sa->sin_family = AF_INET;
1583 sa->sin_port = 0;
462f4eff
CF
1584 break;
1585 case SIOCGIFBRDADDR:
1586 lip = cygwin_inet_addr (ip);
1587 lnp = cygwin_inet_addr (np);
1588 sa = (struct sockaddr_in *) &ifr->ifr_broadaddr;
1589 sa->sin_addr.s_addr = lip & lnp | ~lnp;
9182099c
CV
1590 sa->sin_family = AF_INET;
1591 sa->sin_port = 0;
462f4eff
CF
1592 break;
1593 case SIOCGIFNETMASK:
1594 sa = (struct sockaddr_in *) &ifr->ifr_netmask;
1595 sa->sin_addr.s_addr = cygwin_inet_addr (np);
9182099c
CV
1596 sa->sin_family = AF_INET;
1597 sa->sin_port = 0;
462f4eff
CF
1598 break;
1599 case SIOCGIFHWADDR:
9182099c
CV
1600 so = &ifr->ifr_hwaddr;
1601 memset (so->sa_data, 0, IFHWADDRLEN);
1602 so->sa_family = AF_INET;
1603 break;
462f4eff 1604 case SIOCGIFMETRIC:
9182099c
CV
1605 ifr->ifr_metric = 1;
1606 break;
1607 case SIOCGIFMTU:
1608 ifr->ifr_mtu = 1500;
1609 break;
462f4eff
CF
1610 }
1611 }
1612 ++cnt;
1613 }
1614 }
1615 RegCloseKey (key);
1616 }
7326d4e4 1617 }
1fd5e000 1618
7326d4e4
CV
1619 /* Set the correct length */
1620 ifc->ifc_len = cnt * sizeof (struct ifreq);
1621}
1fd5e000 1622
52b5a971 1623/*
9182099c 1624 * IFCONF Windows 95:
52b5a971
CV
1625 * HKLM/Enum/Network/MSTCP/"*"
1626