OSDN Git Service

2002-03-01 David O'Brien <obrien@FreeBSD.org>
[pf3gnuchains/pf3gnuchains3x.git] / winsup / cygwin / net.cc
1 /* net.cc: network-related routines.
2
3    Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
4
5 This file is part of Cygwin.
6
7 This software is a copyrighted work licensed under the terms of the
8 Cygwin license.  Please consult the file "CYGWIN_LICENSE" for
9 details. */
10
11 /* #define DEBUG_NEST_ON 1 */
12
13 #define  __INSIDE_CYGWIN_NET__
14
15 #include "winsup.h"
16 #include <errno.h>
17 #include <sys/socket.h>
18 #include <sys/un.h>
19 #include <iphlpapi.h>
20
21 #include <stdlib.h>
22 #include <unistd.h>
23 #include <netdb.h>
24 #include <fcntl.h>
25 #define USE_SYS_TYPES_FD_SET
26 #include <winsock2.h>
27 #include "cygerrno.h"
28 #include "security.h"
29 #include "fhandler.h"
30 #include "path.h"
31 #include "dtable.h"
32 #include "cygheap.h"
33 #include "sync.h"
34 #include "sigproc.h"
35 #include "pinfo.h"
36 #include "registry.h"
37 #include "wsock_event.h"
38 #include <sys/uio.h>
39
40 extern "C" {
41 int h_errno;
42
43 int __stdcall rcmd (char **ahost, unsigned short inport, char *locuser,
44                     char *remuser, char *cmd, SOCKET *fd2p);
45 int __stdcall rexec (char **ahost, unsigned short inport, char *locuser,
46                      char *password, char *cmd, SOCKET *fd2p);
47 int __stdcall rresvport (int *);
48 int sscanf (const char *, const char *, ...);
49 } /* End of "C" section */
50
51 LPWSAOVERLAPPED
52 wsock_event::prepare ()
53 {
54   LPWSAOVERLAPPED ret = NULL;
55
56   SetLastError (0);
57   if ((event = WSACreateEvent ()) != WSA_INVALID_EVENT)
58     {
59       memset (&ovr, 0, sizeof ovr);
60       ovr.hEvent = event;
61       ret = &ovr;
62     }
63   else if (GetLastError () == ERROR_PROC_NOT_FOUND) /* winsock2 not available */
64     WSASetLastError (0);
65
66   debug_printf ("%d = wsock_event::prepare ()", ret);
67   return ret;
68 }
69
70 int
71 wsock_event::wait (int socket, LPDWORD flags)
72 {
73   int ret = -1;
74   WSAEVENT ev[2] = { event, signal_arrived };
75
76   switch (WSAWaitForMultipleEvents(2, ev, FALSE, WSA_INFINITE, FALSE))
77     {
78     case WSA_WAIT_EVENT_0:
79       DWORD len;
80       if (WSAGetOverlappedResult(socket, &ovr, &len, FALSE, flags))
81         ret = (int) len;
82       break;
83     case WSA_WAIT_EVENT_0 + 1:
84       if (!CancelIo ((HANDLE)socket))
85         {
86           debug_printf ("CancelIo() %E, fallback to blocking io");
87           WSAGetOverlappedResult(socket, &ovr, &len, TRUE, flags);
88         }
89       else
90         WSASetLastError (WSAEINTR);
91       break;
92     case WSA_WAIT_FAILED:
93       break;
94     default: /* Should be impossible. *LOL* */
95       WSASetLastError (WSAEFAULT);
96       break;
97     }
98   WSACloseEvent (event);
99   event = NULL;
100   return ret;
101 }
102
103 WSADATA wsadata;
104
105 /* Cygwin internal */
106 static fhandler_socket *
107 get (int fd)
108 {
109   cygheap_fdget cfd (fd);
110   if (cfd < 0)
111     return 0;
112
113   return cfd->is_socket ();
114 }
115
116 /* Cygwin internal */
117 static SOCKET __stdcall
118 set_socket_inheritance (SOCKET sock)
119 {
120   SOCKET osock = sock;
121   if (!DuplicateHandle (hMainProc, (HANDLE) sock, hMainProc, (HANDLE *) &sock,
122                         0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
123     system_printf ("DuplicateHandle failed %E");
124   else
125     debug_printf ("DuplicateHandle succeeded osock %p, sock %p", osock, sock);
126   return sock;
127 }
128
129 /* htonl: standards? */
130 extern "C" unsigned long int
131 htonl (unsigned long int x)
132 {
133   return ((((x & 0x000000ffU) << 24) |
134            ((x & 0x0000ff00U) <<  8) |
135            ((x & 0x00ff0000U) >>  8) |
136            ((x & 0xff000000U) >> 24)));
137 }
138
139 /* ntohl: standards? */
140 extern "C" unsigned long int
141 ntohl (unsigned long int x)
142 {
143   return htonl (x);
144 }
145
146 /* htons: standards? */
147 extern "C" unsigned short
148 htons (unsigned short x)
149 {
150   return ((((x & 0x000000ffU) << 8) |
151            ((x & 0x0000ff00U) >> 8)));
152 }
153
154 /* ntohs: standards? */
155 extern "C" unsigned short
156 ntohs (unsigned short x)
157 {
158   return htons (x);
159 }
160
161 /* Cygwin internal */
162 static void
163 dump_protoent (struct protoent *p)
164 {
165   if (p)
166     debug_printf ("protoent %s %x %x", p->p_name, p->p_aliases, p->p_proto);
167 }
168
169 /* exported as inet_ntoa: BSD 4.3 */
170 extern "C" char *
171 cygwin_inet_ntoa (struct in_addr in)
172 {
173 #ifdef _MT_SAFE
174 #define ntoa_buf  _reent_winsup ()->_ntoa_buf
175 #else
176   static char *ntoa_buf = NULL;
177 #endif
178
179   char *res = inet_ntoa (in);
180   if (ntoa_buf)
181     {
182       free (ntoa_buf);
183       ntoa_buf = NULL;
184     }
185   if (res)
186     ntoa_buf = strdup (res);
187   return ntoa_buf;
188 }
189
190 /* exported as inet_addr: BSD 4.3 */
191 extern "C" unsigned long
192 cygwin_inet_addr (const char *cp)
193 {
194   if (check_null_str_errno (cp))
195     return INADDR_NONE;
196   unsigned long res = inet_addr (cp);
197   return res;
198 }
199
200 /* exported as inet_aton: BSD 4.3
201    inet_aton is not exported by wsock32 and ws2_32,
202    so it has to be implemented here. */
203 extern "C" int
204 cygwin_inet_aton (const char *cp, struct in_addr *inp)
205 {
206   if (check_null_str_errno (cp) || check_null_invalid_struct_errno (inp))
207     return 0;
208
209   unsigned long res = inet_addr (cp);
210   if (res == INADDR_NONE && strcmp (cp, "255.255.255.255"))
211     return 0;
212   if (inp)
213     inp->s_addr = res;
214   return 1;
215 }
216
217 /* undocumented in wsock32.dll */
218 extern "C" unsigned int WINAPI inet_network (const char *);
219
220 extern "C" unsigned int
221 cygwin_inet_network (const char *cp)
222 {
223   if (check_null_str_errno (cp))
224     return INADDR_NONE;
225   unsigned int res = inet_network (cp);
226   return res;
227 }
228
229 /* inet_netof is in the standard BSD sockets library.  It is useless
230    for modern networks, since it assumes network values which are no
231    longer meaningful, but some existing code calls it.  */
232
233 extern "C" unsigned long
234 inet_netof (struct in_addr in)
235 {
236   unsigned long i, res;
237
238   i = ntohl (in.s_addr);
239   if (IN_CLASSA (i))
240     res = (i & IN_CLASSA_NET) >> IN_CLASSA_NSHIFT;
241   else if (IN_CLASSB (i))
242     res = (i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT;
243   else
244     res = (i & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT;
245
246
247   return res;
248 }
249
250 /* inet_makeaddr is in the standard BSD sockets library.  It is
251    useless for modern networks, since it assumes network values which
252    are no longer meaningful, but some existing code calls it.  */
253
254 extern "C" struct in_addr
255 inet_makeaddr (int net, int lna)
256 {
257   unsigned long i;
258   struct in_addr in;
259
260   if (net < IN_CLASSA_MAX)
261     i = (net << IN_CLASSA_NSHIFT) | (lna & IN_CLASSA_HOST);
262   else if (net < IN_CLASSB_MAX)
263     i = (net << IN_CLASSB_NSHIFT) | (lna & IN_CLASSB_HOST);
264   else if (net < 0x1000000)
265     i = (net << IN_CLASSC_NSHIFT) | (lna & IN_CLASSC_HOST);
266   else
267     i = net | lna;
268
269   in.s_addr = htonl (i);
270
271
272   return in;
273 }
274
275 struct tl
276 {
277   int w;
278   const char *s;
279   int e;
280 };
281
282 static NO_COPY struct tl errmap[] =
283 {
284  {WSAEINTR, "WSAEINTR", EINTR},
285  {WSAEWOULDBLOCK, "WSAEWOULDBLOCK", EWOULDBLOCK},
286  {WSAEINPROGRESS, "WSAEINPROGRESS", EINPROGRESS},
287  {WSAEALREADY, "WSAEALREADY", EALREADY},
288  {WSAENOTSOCK, "WSAENOTSOCK", ENOTSOCK},
289  {WSAEDESTADDRREQ, "WSAEDESTADDRREQ", EDESTADDRREQ},
290  {WSAEMSGSIZE, "WSAEMSGSIZE", EMSGSIZE},
291  {WSAEPROTOTYPE, "WSAEPROTOTYPE", EPROTOTYPE},
292  {WSAENOPROTOOPT, "WSAENOPROTOOPT", ENOPROTOOPT},
293  {WSAEPROTONOSUPPORT, "WSAEPROTONOSUPPORT", EPROTONOSUPPORT},
294  {WSAESOCKTNOSUPPORT, "WSAESOCKTNOSUPPORT", ESOCKTNOSUPPORT},
295  {WSAEOPNOTSUPP, "WSAEOPNOTSUPP", EOPNOTSUPP},
296  {WSAEPFNOSUPPORT, "WSAEPFNOSUPPORT", EPFNOSUPPORT},
297  {WSAEAFNOSUPPORT, "WSAEAFNOSUPPORT", EAFNOSUPPORT},
298  {WSAEADDRINUSE, "WSAEADDRINUSE", EADDRINUSE},
299  {WSAEADDRNOTAVAIL, "WSAEADDRNOTAVAIL", EADDRNOTAVAIL},
300  {WSAENETDOWN, "WSAENETDOWN", ENETDOWN},
301  {WSAENETUNREACH, "WSAENETUNREACH", ENETUNREACH},
302  {WSAENETRESET, "WSAENETRESET", ENETRESET},
303  {WSAECONNABORTED, "WSAECONNABORTED", ECONNABORTED},
304  {WSAECONNRESET, "WSAECONNRESET", ECONNRESET},
305  {WSAENOBUFS, "WSAENOBUFS", ENOBUFS},
306  {WSAEISCONN, "WSAEISCONN", EISCONN},
307  {WSAENOTCONN, "WSAENOTCONN", ENOTCONN},
308  {WSAESHUTDOWN, "WSAESHUTDOWN", ESHUTDOWN},
309  {WSAETOOMANYREFS, "WSAETOOMANYREFS", ETOOMANYREFS},
310  {WSAETIMEDOUT, "WSAETIMEDOUT", ETIMEDOUT},
311  {WSAECONNREFUSED, "WSAECONNREFUSED", ECONNREFUSED},
312  {WSAELOOP, "WSAELOOP", ELOOP},
313  {WSAENAMETOOLONG, "WSAENAMETOOLONG", ENAMETOOLONG},
314  {WSAEHOSTDOWN, "WSAEHOSTDOWN", EHOSTDOWN},
315  {WSAEHOSTUNREACH, "WSAEHOSTUNREACH", EHOSTUNREACH},
316  {WSAENOTEMPTY, "WSAENOTEMPTY", ENOTEMPTY},
317  {WSAEPROCLIM, "WSAEPROCLIM", EPROCLIM},
318  {WSAEUSERS, "WSAEUSERS", EUSERS},
319  {WSAEDQUOT, "WSAEDQUOT", EDQUOT},
320  {WSAESTALE, "WSAESTALE", ESTALE},
321  {WSAEREMOTE, "WSAEREMOTE", EREMOTE},
322  {WSAEINVAL, "WSAEINVAL", EINVAL},
323  {WSAEFAULT, "WSAEFAULT", EFAULT},
324  {0, "NOERROR", 0},
325  {0, NULL, 0}
326 };
327
328 static int
329 find_winsock_errno (int why)
330 {
331   for (int i = 0; errmap[i].s != NULL; ++i)
332     if (why == errmap[i].w)
333       return errmap[i].e;
334
335   return EPERM;
336 }
337
338 /* Cygwin internal */
339 void
340 __set_winsock_errno (const char *fn, int ln)
341 {
342   DWORD werr = WSAGetLastError ();
343   int err = find_winsock_errno (werr);
344   set_errno (err);
345   syscall_printf ("%s:%d - winsock error %d -> errno %d", fn, ln, werr, err);
346 }
347
348 /*
349  * Since the member `s' isn't used for debug output we can use it
350  * for the error text returned by herror and hstrerror.
351  */
352 static NO_COPY struct tl host_errmap[] =
353 {
354   {WSAHOST_NOT_FOUND, "Unknown host", HOST_NOT_FOUND},
355   {WSATRY_AGAIN, "Host name lookup failure", TRY_AGAIN},
356   {WSANO_RECOVERY, "Unknown server error", NO_RECOVERY},
357   {WSANO_DATA, "No address associated with name", NO_DATA},
358   {0, NULL, 0}
359 };
360
361 /* Cygwin internal */
362 static void
363 set_host_errno ()
364 {
365   int i;
366
367   int why = WSAGetLastError ();
368   for (i = 0; host_errmap[i].w != 0; ++i)
369     if (why == host_errmap[i].w)
370       break;
371
372   if (host_errmap[i].w != 0)
373     h_errno = host_errmap[i].e;
374   else
375     h_errno = NETDB_INTERNAL;
376 }
377
378 static void
379 free_char_list (char **clist)
380 {
381   if (clist)
382     {
383       for (char **cl = clist; *cl; ++cl)
384         free (*cl);
385       free (clist);
386     }
387 }
388
389 static char **
390 dup_char_list (char **src)
391 {
392   char **dst;
393   int cnt = 0;
394
395   for (char **cl = src; *cl; ++cl)
396     ++cnt;
397   if (!(dst = (char **) calloc (cnt + 1, sizeof *dst)))
398     return NULL;
399   while (cnt-- > 0)
400     if (!(dst[cnt] = strdup (src[cnt])))
401       return NULL;
402   return dst;
403 }
404
405 #define free_addr_list(addr_list)       free_char_list (addr_list)
406
407 static char **
408 dup_addr_list (char **src, unsigned int size)
409 {
410   char **dst;
411   int cnt = 0;
412
413   for (char **cl = src; *cl; ++cl)
414     ++cnt;
415   if (!(dst = (char **) calloc (cnt + 1, sizeof *dst)))
416     return NULL;
417   while (cnt-- > 0)
418     {
419       if (!(dst[cnt] = (char *) malloc(size)))
420         return NULL;
421       memcpy(dst[cnt], src[cnt], size);
422     }
423   return dst;
424 }
425
426 static void
427 free_protoent_ptr (struct protoent *&p)
428 {
429   if (p)
430     {
431       debug_printf ("protoent: %s", p->p_name);
432
433       if (p->p_name)
434         free (p->p_name);
435       free_char_list (p->p_aliases);
436       p = NULL;
437     }
438 }
439
440 static struct protoent *
441 dup_protoent_ptr (struct protoent *src)
442 {
443   if (!src)
444     return NULL;
445
446   struct protoent *dst = (struct protoent *) calloc (1, sizeof *dst);
447   if (!dst)
448     return NULL;
449
450   debug_printf ("protoent: %s", src->p_name);
451
452   dst->p_proto = src->p_proto;
453   if (src->p_name && !(dst->p_name = strdup (src->p_name)))
454     goto out;
455   if (src->p_aliases && !(dst->p_aliases = dup_char_list (src->p_aliases)))
456     goto out;
457
458   debug_printf ("protoent: copied %s", dst->p_name);
459
460   return dst;
461
462 out:
463   free_protoent_ptr (dst);
464   return NULL;
465 }
466
467 #ifdef _MT_SAFE
468 #define protoent_buf  _reent_winsup ()->_protoent_buf
469 #else
470   static struct protoent *protoent_buf = NULL;
471 #endif
472
473 /* exported as getprotobyname: standards? */
474 extern "C" struct protoent *
475 cygwin_getprotobyname (const char *p)
476 {
477   if (check_null_str_errno (p))
478     return NULL;
479   free_protoent_ptr (protoent_buf);
480   protoent_buf = dup_protoent_ptr (getprotobyname (p));
481   if (!protoent_buf)
482     set_winsock_errno ();
483
484   dump_protoent (protoent_buf);
485   return protoent_buf;
486 }
487
488 /* exported as getprotobynumber: standards? */
489 extern "C" struct protoent *
490 cygwin_getprotobynumber (int number)
491 {
492   free_protoent_ptr (protoent_buf);
493   protoent_buf = dup_protoent_ptr (getprotobynumber (number));
494   if (!protoent_buf)
495     set_winsock_errno ();
496
497   dump_protoent (protoent_buf);
498   return protoent_buf;
499 }
500
501 fhandler_socket *
502 fdsock (int& fd, const char *name, SOCKET soc)
503 {
504   if (!winsock2_active)
505     soc = set_socket_inheritance (soc);
506   else
507     debug_printf ("not setting socket inheritance since winsock2_active %d", winsock2_active);
508   fhandler_socket *fh = (fhandler_socket *) cygheap->fdtab.build_fhandler (fd, FH_SOCKET, name);
509   fh->set_io_handle ((HANDLE) soc);
510   fh->set_flags (O_RDWR);
511   debug_printf ("fd %d, name '%s', soc %p", fd, name, soc);
512   return fh;
513 }
514
515 /* exported as socket: standards? */
516 extern "C" int
517 cygwin_socket (int af, int type, int protocol)
518 {
519   int res = -1;
520   SOCKET soc = 0;
521
522   cygheap_fdnew fd;
523
524   if (fd >= 0)
525     {
526       debug_printf ("socket (%d, %d, %d)", af, type, protocol);
527
528       soc = socket (AF_INET, type, af == AF_LOCAL ? 0 : protocol);
529
530       if (soc == INVALID_SOCKET)
531         {
532           set_winsock_errno ();
533           goto done;
534         }
535
536       const char *name;
537       if (af == AF_INET)
538         name = (type == SOCK_STREAM ? "/dev/tcp" : "/dev/udp");
539       else
540         name = (type == SOCK_STREAM ? "/dev/streamsocket" : "/dev/dgsocket");
541
542       fdsock (fd, name, soc)->set_addr_family (af);
543       res = fd;
544     }
545
546 done:
547   syscall_printf ("%d = socket (%d, %d, %d)", res, af, type, protocol);
548   return res;
549 }
550
551 /* cygwin internal: map sockaddr into internet domain address */
552
553 static int get_inet_addr (const struct sockaddr *in, int inlen,
554                            struct sockaddr_in *out, int *outlen, int* secret = 0)
555 {
556   int secret_buf [4];
557   int* secret_ptr = (secret ? : secret_buf);
558
559   if (in->sa_family == AF_INET)
560     {
561       *out = * (sockaddr_in *)in;
562       *outlen = inlen;
563       return 1;
564     }
565   else if (in->sa_family == AF_LOCAL)
566     {
567       int fd = _open (in->sa_data, O_RDONLY);
568       if (fd == -1)
569         return 0;
570
571       int ret = 0;
572       char buf[128];
573       memset (buf, 0, sizeof buf);
574       if (read (fd, buf, sizeof buf) != -1)
575         {
576           sockaddr_in sin;
577           sin.sin_family = AF_INET;
578           sscanf (buf + strlen (SOCKET_COOKIE), "%hu %08x-%08x-%08x-%08x",
579                   &sin.sin_port,
580                   secret_ptr, secret_ptr + 1, secret_ptr + 2, secret_ptr + 3);
581           sin.sin_port = htons (sin.sin_port);
582           sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
583           *out = sin;
584           *outlen = sizeof sin;
585           ret = 1;
586         }
587       _close (fd);
588       return ret;
589     }
590   else
591     {
592       set_errno (EAFNOSUPPORT);
593       return 0;
594     }
595 }
596
597 /* exported as sendto: standards? */
598 extern "C" int
599 cygwin_sendto (int fd,
600                const void *buf,
601                int len,
602                unsigned int flags,
603                const struct sockaddr *to,
604                int tolen)
605 {
606   int res;
607   wsock_event wsock_evt;
608   LPWSAOVERLAPPED ovr;
609   fhandler_socket *h = get (fd);
610
611   if ((len && __check_invalid_read_ptr_errno (buf, (unsigned) len))
612       || __check_null_invalid_struct_errno (to, tolen)
613       || !h)
614     res = -1;
615   else
616     {
617       sockaddr_in sin;
618       sigframe thisframe (mainthread);
619
620       if (get_inet_addr (to, tolen, &sin, &tolen) == 0)
621         return -1;
622
623       if (h->is_nonblocking () || !(ovr = wsock_evt.prepare ()))
624         {
625           debug_printf ("Fallback to winsock 1 sendto call");
626           if ((res = sendto (h->get_socket (), (const char *) buf, len, flags,
627                              (sockaddr *) &sin, tolen)) == SOCKET_ERROR)
628             {
629               set_winsock_errno ();
630               res = -1;
631             }
632         }
633       else
634         {
635           WSABUF wsabuf = { len, (char *) buf };
636           DWORD ret = 0;
637           if (WSASendTo (h->get_socket (), &wsabuf, 1, &ret, (DWORD)flags,
638                          (sockaddr *) &sin, tolen, ovr, NULL) != SOCKET_ERROR)
639             res = ret;
640           else if ((res = WSAGetLastError ()) != WSA_IO_PENDING)
641             {
642               set_winsock_errno ();
643               res = -1;
644             }
645           else if ((res = wsock_evt.wait (h->get_socket (), (DWORD *)&flags)) == -1)
646             set_winsock_errno ();
647         }
648     }
649
650   syscall_printf ("%d = sendto (%d, %x, %x, %x)", res, fd, buf, len, flags);
651
652   return res;
653 }
654
655 /* exported as recvfrom: standards? */
656 extern "C" int
657 cygwin_recvfrom (int fd,
658                    char *buf,
659                    int len,
660                    int flags,
661                    struct sockaddr *from,
662                    int *fromlen)
663 {
664   int res;
665   wsock_event wsock_evt;
666   LPWSAOVERLAPPED ovr;
667   fhandler_socket *h = get (fd);
668
669   if (__check_null_invalid_struct_errno (buf, (unsigned) len)
670       || check_null_invalid_struct_errno (fromlen)
671       || (from && __check_null_invalid_struct_errno (from, (unsigned) *fromlen))
672       || !h)
673     res = -1;
674   else
675     {
676       sigframe thisframe (mainthread);
677
678       if (h->is_nonblocking () ||!(ovr = wsock_evt.prepare ()))
679         {
680           debug_printf ("Fallback to winsock 1 recvfrom call");
681           if ((res = recvfrom (h->get_socket (), buf, len, flags, from, fromlen))
682               == SOCKET_ERROR)
683             {
684               set_winsock_errno ();
685               res = -1;
686             }
687         }
688       else
689         {
690           WSABUF wsabuf = { len, (char *) buf };
691           DWORD ret = 0;
692           if (WSARecvFrom (h->get_socket (), &wsabuf, 1, &ret, (DWORD *)&flags,
693                            from, fromlen, ovr, NULL) != SOCKET_ERROR)
694             res = ret;
695           else if ((res = WSAGetLastError ()) != WSA_IO_PENDING)
696             {
697               set_winsock_errno ();
698               res = -1;
699             }
700           else if ((res = wsock_evt.wait (h->get_socket (), (DWORD *)&flags)) == -1)
701             set_winsock_errno ();
702         }
703     }
704
705   syscall_printf ("%d = recvfrom (%d, %x, %x, %x)", res, fd, buf, len, flags);
706
707   return res;
708 }
709
710 /* exported as setsockopt: standards? */
711 extern "C" int
712 cygwin_setsockopt (int fd,
713                      int level,
714                      int optname,
715                      const void *optval,
716                      int optlen)
717 {
718   fhandler_socket *h = get (fd);
719   int res = -1;
720   const char *name = "error";
721
722   if ((!optval || !__check_invalid_read_ptr_errno (optval, optlen)) && h)
723     {
724       /* For the following debug_printf */
725       switch (optname)
726         {
727         case SO_DEBUG:
728           name="SO_DEBUG";
729           break;
730         case SO_ACCEPTCONN:
731           name="SO_ACCEPTCONN";
732           break;
733         case SO_REUSEADDR:
734           name="SO_REUSEADDR";
735           break;
736         case SO_KEEPALIVE:
737           name="SO_KEEPALIVE";
738           break;
739         case SO_DONTROUTE:
740           name="SO_DONTROUTE";
741           break;
742         case SO_BROADCAST:
743           name="SO_BROADCAST";
744           break;
745         case SO_USELOOPBACK:
746           name="SO_USELOOPBACK";
747           break;
748         case SO_LINGER:
749           name="SO_LINGER";
750           break;
751         case SO_OOBINLINE:
752           name="SO_OOBINLINE";
753           break;
754         case SO_ERROR:
755           name="SO_ERROR";
756           break;
757         }
758
759       res = setsockopt (h->get_socket (), level, optname,
760                                      (const char *) optval, optlen);
761
762       if (optlen == 4)
763         syscall_printf ("setsockopt optval=%x", *(long *) optval);
764
765       if (res)
766         set_winsock_errno ();
767     }
768
769   syscall_printf ("%d = setsockopt (%d, %d, %x (%s), %x, %d)",
770                   res, fd, level, optname, name, optval, optlen);
771   return res;
772 }
773
774 /* exported as getsockopt: standards? */
775 extern "C" int
776 cygwin_getsockopt (int fd,
777                      int level,
778                      int optname,
779                      void *optval,
780                      int *optlen)
781 {
782   fhandler_socket *h = get (fd);
783   int res = -1;
784   const char *name = "error";
785   if (!check_null_invalid_struct_errno (optlen)
786       && (!optval || !__check_null_invalid_struct_errno (optval, (unsigned) *optlen))
787       && h)
788     {
789       /* For the following debug_printf */
790       switch (optname)
791         {
792         case SO_DEBUG:
793           name="SO_DEBUG";
794           break;
795         case SO_ACCEPTCONN:
796           name="SO_ACCEPTCONN";
797           break;
798         case SO_REUSEADDR:
799           name="SO_REUSEADDR";
800           break;
801         case SO_KEEPALIVE:
802           name="SO_KEEPALIVE";
803           break;
804         case SO_DONTROUTE:
805           name="SO_DONTROUTE";
806           break;
807         case SO_BROADCAST:
808           name="SO_BROADCAST";
809           break;
810         case SO_USELOOPBACK:
811           name="SO_USELOOPBACK";
812           break;
813         case SO_LINGER:
814           name="SO_LINGER";
815           break;
816         case SO_OOBINLINE:
817           name="SO_OOBINLINE";
818           break;
819         case SO_ERROR:
820           name="SO_ERROR";
821           break;
822         }
823
824       res = getsockopt (h->get_socket (), level, optname,
825                                        (char *) optval, (int *) optlen);
826
827       if (optname == SO_ERROR)
828         {
829           int *e = (int *) optval;
830           *e = find_winsock_errno (*e);
831         }
832
833       if (res)
834         set_winsock_errno ();
835     }
836
837   syscall_printf ("%d = getsockopt (%d, %d, %x (%s), %x, %d)",
838                   res, fd, level, optname, name, optval, optlen);
839   return res;
840 }
841
842 /* exported as connect: standards? */
843 extern "C" int
844 cygwin_connect (int fd,
845                   const struct sockaddr *name,
846                   int namelen)
847 {
848   int res;
849   BOOL secret_check_failed = FALSE;
850   BOOL in_progress = FALSE;
851   fhandler_socket *sock = get (fd);
852   sockaddr_in sin;
853   int secret [4];
854   sigframe thisframe (mainthread);
855
856   if (__check_invalid_read_ptr_errno (name, namelen))
857     return -1;
858
859   if (get_inet_addr (name, namelen, &sin, &namelen, secret) == 0)
860     return -1;
861
862   if (!sock)
863     res = -1;
864   else
865     {
866       res = connect (sock->get_socket (), (sockaddr *) &sin, namelen);
867       if (res)
868         {
869           /* Special handling for connect to return the correct error code
870              when called on a non-blocking socket. */
871           if (sock->is_nonblocking ())
872             {
873               DWORD err = WSAGetLastError ();
874               if (err == WSAEWOULDBLOCK || err == WSAEALREADY)
875                 {
876                   WSASetLastError (WSAEINPROGRESS);
877                   in_progress = TRUE;
878                 }
879               else if (err == WSAEINVAL)
880                 WSASetLastError (WSAEISCONN);
881             }
882           set_winsock_errno ();
883         }
884       if (sock->get_addr_family () == AF_LOCAL)
885         {
886           if (!res || in_progress)
887             {
888               if (!sock->create_secret_event (secret))
889                 {
890                   secret_check_failed = TRUE;
891                 }
892               else if (in_progress)
893                 sock->signal_secret_event ();
894             }
895
896           if (!secret_check_failed && !res)
897             {
898               if (!sock->check_peer_secret_event (&sin, secret))
899                 {
900                   debug_printf ( "accept from unauthorized server" );
901                   secret_check_failed = TRUE;
902                 }
903            }
904
905           if (secret_check_failed)
906             {
907               sock->close_secret_event ();
908               if (res)
909                 closesocket (res);
910               set_errno (ECONNREFUSED);
911               res = -1;
912             }
913         }
914     }
915   return res;
916 }
917
918 static void
919 free_servent_ptr (struct servent *&p)
920 {
921   if (p)
922     {
923       debug_printf ("servent: %s", p->s_name);
924
925       if (p->s_name)
926         free (p->s_name);
927       if (p->s_proto)
928         free (p->s_proto);
929       free_char_list (p->s_aliases);
930       p = NULL;
931     }
932 }
933
934 #pragma pack(push,2)
935 struct pservent
936 {
937   char *s_name;
938   char **s_aliases;
939   short s_port;
940   char *s_proto;
941 };
942 #pragma pack(pop)
943 static struct servent *
944 dup_servent_ptr (struct servent *src)
945 {
946   if (!src)
947     return NULL;
948
949   struct servent *dst = (struct servent *) calloc (1, sizeof *dst);
950   if (!dst)
951     return NULL;
952
953   debug_printf ("servent: %s", src->s_name);
954
955   dst->s_port = src->s_port;
956   if (src->s_name && !(dst->s_name = strdup (src->s_name)))
957     goto out;
958   if (src->s_aliases && !(dst->s_aliases = dup_char_list (src->s_aliases)))
959     goto out;
960   char *s_proto;
961   if (IsBadReadPtr (src->s_proto, sizeof (src->s_proto))
962       && !IsBadReadPtr (((pservent *) src)->s_proto, sizeof (src->s_proto)))
963     s_proto = ((pservent *)src)->s_proto;
964   else
965     s_proto = src->s_proto;
966
967   if (s_proto && !(dst->s_proto = strdup (s_proto)))
968     goto out;
969
970   debug_printf ("servent: copied %s", dst->s_name);
971
972   return dst;
973
974 out:
975   free_servent_ptr (dst);
976   return NULL;
977 }
978
979 #ifdef _MT_SAFE
980 #define servent_buf  _reent_winsup ()->_servent_buf
981 #else
982   static struct servent *servent_buf = NULL;
983 #endif
984
985 /* exported as getservbyname: standards? */
986 extern "C" struct servent *
987 cygwin_getservbyname (const char *name, const char *proto)
988 {
989   if (check_null_str_errno (name)
990       || (proto != NULL && check_null_str_errno (proto)))
991     return NULL;
992
993   free_servent_ptr (servent_buf);
994   servent_buf = dup_servent_ptr (getservbyname (name, proto));
995   if (!servent_buf)
996     set_winsock_errno ();
997
998   syscall_printf ("%x = getservbyname (%s, %s)", servent_buf, name, proto);
999   return servent_buf;
1000 }
1001
1002 /* exported as getservbyport: standards? */
1003 extern "C" struct servent *
1004 cygwin_getservbyport (int port, const char *proto)
1005 {
1006   if (proto != NULL && check_null_str_errno (proto))
1007     return NULL;
1008
1009   free_servent_ptr (servent_buf);
1010   servent_buf = dup_servent_ptr (getservbyport (port, proto));
1011   if (!servent_buf)
1012     set_winsock_errno ();
1013
1014   syscall_printf ("%x = getservbyport (%d, %s)", servent_buf, port, proto);
1015   return servent_buf;
1016 }
1017
1018 extern "C" int
1019 cygwin_gethostname (char *name, size_t len)
1020 {
1021   int PASCAL win32_gethostname (char*, int);
1022
1023   if (__check_null_invalid_struct_errno (name, len))
1024     return -1;
1025
1026   if (wsock32_handle == NULL ||
1027       win32_gethostname (name, len) == SOCKET_ERROR)
1028     {
1029       DWORD local_len = len;
1030
1031       if (!GetComputerNameA (name, &local_len))
1032         {
1033           set_winsock_errno ();
1034           return -1;
1035         }
1036     }
1037   debug_printf ("name %s\n", name);
1038   h_errno = 0;
1039   return 0;
1040 }
1041
1042 static void
1043 free_hostent_ptr (struct hostent *&p)
1044 {
1045   if (p)
1046     {
1047       debug_printf ("hostent: %s", p->h_name);
1048
1049       if (p->h_name)
1050         free ((void *)p->h_name);
1051       free_char_list (p->h_aliases);
1052       free_addr_list (p->h_addr_list);
1053       p = NULL;
1054     }
1055 }
1056
1057 static struct hostent *
1058 dup_hostent_ptr (struct hostent *src)
1059 {
1060   if (!src)
1061     return NULL;
1062
1063   struct hostent *dst = (struct hostent *) calloc (1, sizeof *dst);
1064   if (!dst)
1065     return NULL;
1066
1067   debug_printf ("hostent: %s", src->h_name);
1068
1069   dst->h_addrtype = src->h_addrtype;
1070   dst->h_length = src->h_length;
1071   if (src->h_name && !(dst->h_name = strdup (src->h_name)))
1072     goto out;
1073   if (src->h_aliases && !(dst->h_aliases = dup_char_list (src->h_aliases)))
1074     goto out;
1075   if (src->h_addr_list
1076       && !(dst->h_addr_list = dup_addr_list(src->h_addr_list, src->h_length)))
1077     goto out;
1078
1079   debug_printf ("hostent: copied %s", dst->h_name);
1080
1081   return dst;
1082
1083 out:
1084   free_hostent_ptr (dst);
1085   return NULL;
1086 }
1087
1088 #ifdef _MT_SAFE
1089 #define hostent_buf  _reent_winsup ()->_hostent_buf
1090 #else
1091   static struct hostent *hostent_buf = NULL;
1092 #endif
1093
1094 /* exported as gethostbyname: standards? */
1095 extern "C" struct hostent *
1096 cygwin_gethostbyname (const char *name)
1097 {
1098   static unsigned char tmp_addr[4];
1099   static struct hostent tmp;
1100   static char *tmp_aliases[1];
1101   static char *tmp_addr_list[2];
1102   static int a, b, c, d;
1103
1104   if (check_null_str_errno (name))
1105     return NULL;
1106
1107   if (sscanf (name, "%d.%d.%d.%d", &a, &b, &c, &d) == 4)
1108     {
1109       /* In case you don't have DNS, at least x.x.x.x still works */
1110       memset (&tmp, 0, sizeof (tmp));
1111       tmp_addr[0] = a;
1112       tmp_addr[1] = b;
1113       tmp_addr[2] = c;
1114       tmp_addr[3] = d;
1115       tmp_addr_list[0] = (char *)tmp_addr;
1116       tmp.h_name = name;
1117       tmp.h_aliases = tmp_aliases;
1118       tmp.h_addrtype = 2;
1119       tmp.h_length = 4;
1120       tmp.h_addr_list = tmp_addr_list;
1121       return &tmp;
1122     }
1123
1124   free_hostent_ptr (hostent_buf);
1125   hostent_buf = dup_hostent_ptr (gethostbyname (name));
1126   if (!hostent_buf)
1127     {
1128       set_winsock_errno ();
1129       set_host_errno ();
1130     }
1131   else
1132     {
1133       debug_printf ("h_name %s", hostent_buf->h_name);
1134       h_errno = 0;
1135     }
1136   return hostent_buf;
1137 }
1138
1139 /* exported as gethostbyaddr: standards? */
1140 extern "C" struct hostent *
1141 cygwin_gethostbyaddr (const char *addr, int len, int type)
1142 {
1143   if (__check_null_invalid_struct_errno (addr, len))
1144     return NULL;
1145
1146   free_hostent_ptr (hostent_buf);
1147   hostent_buf = dup_hostent_ptr (gethostbyaddr (addr, len, type));
1148   if (!hostent_buf)
1149     {
1150       set_winsock_errno ();
1151       set_host_errno ();
1152     }
1153   else
1154     {
1155       debug_printf ("h_name %s", hostent_buf->h_name);
1156       h_errno = 0;
1157     }
1158   return hostent_buf;
1159 }
1160
1161 /* exported as accept: standards? */
1162 extern "C" int
1163 cygwin_accept (int fd, struct sockaddr *peer, int *len)
1164 {
1165   if (peer != NULL
1166       && (check_null_invalid_struct_errno (len)
1167           || __check_null_invalid_struct_errno (peer, (unsigned) *len)))
1168     return -1;
1169
1170   int res = -1;
1171   BOOL secret_check_failed = FALSE;
1172   BOOL in_progress = FALSE;
1173   sigframe thisframe (mainthread);
1174
1175   fhandler_socket *sock = get (fd);
1176   if (sock)
1177     {
1178       /* Allows NULL peer and len parameters. */
1179       struct sockaddr_in peer_dummy;
1180       int len_dummy;
1181       if (!peer)
1182         peer = (struct sockaddr *) &peer_dummy;
1183       if (!len)
1184         {
1185           len_dummy = sizeof (struct sockaddr_in);
1186           len = &len_dummy;
1187         }
1188
1189       /* accept on NT fails if len < sizeof (sockaddr_in)
1190        * some programs set len to
1191        * sizeof (name.sun_family) + strlen (name.sun_path) for UNIX domain
1192        */
1193       if (len && ((unsigned) *len < sizeof (struct sockaddr_in)))
1194         *len = sizeof (struct sockaddr_in);
1195
1196       res = accept (sock->get_socket (), peer, len);  // can't use a blocking call inside a lock
1197
1198       if ((SOCKET) res == (SOCKET) INVALID_SOCKET &&
1199           WSAGetLastError () == WSAEWOULDBLOCK)
1200         in_progress = TRUE;
1201
1202       if (sock->get_addr_family () == AF_LOCAL)
1203         {
1204           if ((SOCKET) res != (SOCKET) INVALID_SOCKET || in_progress)
1205             {
1206               if (!sock->create_secret_event ())
1207                 secret_check_failed = TRUE;
1208               else if (in_progress)
1209                 sock->signal_secret_event ();
1210             }
1211
1212           if (!secret_check_failed &&
1213               (SOCKET) res != (SOCKET) INVALID_SOCKET)
1214             {
1215               if (!sock->check_peer_secret_event ((struct sockaddr_in*) peer))
1216                 {
1217                   debug_printf ("connect from unauthorized client");
1218                   secret_check_failed = TRUE;
1219                 }
1220             }
1221
1222           if (secret_check_failed)
1223             {
1224               sock->close_secret_event ();
1225               if ((SOCKET) res != (SOCKET) INVALID_SOCKET)
1226                 closesocket (res);
1227               set_errno (ECONNABORTED);
1228               res = -1;
1229               goto done;
1230             }
1231         }
1232
1233
1234       cygheap_fdnew res_fd;
1235       if (res_fd < 0)
1236         /* FIXME: what is correct errno? */;
1237       else if ((SOCKET) res == (SOCKET) INVALID_SOCKET)
1238         set_winsock_errno ();
1239       else
1240         {
1241           fhandler_socket* res_fh = fdsock (res_fd, sock->get_name (), res);
1242           if (sock->get_addr_family () == AF_LOCAL)
1243             res_fh->set_sun_path (sock->get_sun_path ());
1244           res_fh->set_addr_family (sock->get_addr_family ());
1245           res = res_fd;
1246         }
1247     }
1248  done:
1249   syscall_printf ("%d = accept (%d, %x, %x)", res, fd, peer, len);
1250   return res;
1251 }
1252
1253 /* exported as bind: standards? */
1254 extern "C" int
1255 cygwin_bind (int fd, const struct sockaddr *my_addr, int addrlen)
1256 {
1257   if (__check_null_invalid_struct_errno (my_addr, addrlen))
1258     return -1;
1259
1260   int res = -1;
1261
1262   fhandler_socket *sock = get (fd);
1263   if (sock)
1264     {
1265       if (my_addr->sa_family == AF_LOCAL)
1266         {
1267 #define un_addr ((struct sockaddr_un *) my_addr)
1268           struct sockaddr_in sin;
1269           int len = sizeof sin;
1270           int fd;
1271
1272           if (strlen (un_addr->sun_path) >= UNIX_PATH_LEN)
1273             {
1274               set_errno (ENAMETOOLONG);
1275               goto out;
1276             }
1277           sin.sin_family = AF_INET;
1278           sin.sin_port = 0;
1279           sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
1280           if (bind (sock->get_socket (), (sockaddr *) &sin, len))
1281             {
1282               syscall_printf ("AF_LOCAL: bind failed %d", get_errno ());
1283               set_winsock_errno ();
1284               goto out;
1285             }
1286           if (getsockname (sock->get_socket (), (sockaddr *) &sin, &len))
1287             {
1288               syscall_printf ("AF_LOCAL: getsockname failed %d", get_errno ());
1289               set_winsock_errno ();
1290               goto out;
1291             }
1292
1293           sin.sin_port = ntohs (sin.sin_port);
1294           debug_printf ("AF_LOCAL: socket bound to port %u", sin.sin_port);
1295
1296           /* bind must fail if file system socket object already exists
1297              so _open () is called with O_EXCL flag. */
1298           fd = _open (un_addr->sun_path,
1299                       O_WRONLY | O_CREAT | O_EXCL | O_BINARY,
1300                       0);
1301           if (fd < 0)
1302             {
1303               if (get_errno () == EEXIST)
1304                 set_errno (EADDRINUSE);
1305               goto out;
1306             }
1307
1308           sock->set_connect_secret ();
1309
1310           char buf[sizeof (SOCKET_COOKIE) + 80];
1311           __small_sprintf (buf, "%s%u ", SOCKET_COOKIE, sin.sin_port);
1312           sock->get_connect_secret (strchr (buf, '\0'));
1313           len = strlen (buf) + 1;
1314
1315           /* Note that the terminating nul is written.  */
1316           if (_write (fd, buf, len) != len)
1317             {
1318               save_errno here;
1319               _close (fd);
1320               _unlink (un_addr->sun_path);
1321             }
1322           else
1323             {
1324               _close (fd);
1325               chmod (un_addr->sun_path,
1326                 (S_IFSOCK | S_IRWXU | S_IRWXG | S_IRWXO) & ~cygheap->umask);
1327               sock->set_sun_path (un_addr->sun_path);
1328               res = 0;
1329             }
1330 #undef un_addr
1331         }
1332       else if (bind (sock->get_socket (), my_addr, addrlen))
1333         set_winsock_errno ();
1334       else
1335         res = 0;
1336     }
1337
1338 out:
1339   syscall_printf ("%d = bind (%d, %x, %d)", res, fd, my_addr, addrlen);
1340   return res;
1341 }
1342
1343 /* exported as getsockname: standards? */
1344 extern "C" int
1345 cygwin_getsockname (int fd, struct sockaddr *addr, int *namelen)
1346 {
1347   if (check_null_invalid_struct_errno (namelen)
1348       || __check_null_invalid_struct_errno (addr, (unsigned) *namelen))
1349     return -1;
1350
1351   int res = -1;
1352
1353   fhandler_socket *sock = get (fd);
1354   if (sock)
1355     {
1356       if (sock->get_addr_family () == AF_LOCAL)
1357         {
1358           struct sockaddr_un *sun = (struct sockaddr_un *) addr;
1359           memset (sun, 0, *namelen);
1360           sun->sun_family = AF_LOCAL;
1361
1362           if (!sock->get_sun_path ())
1363             sun->sun_path[0] = '\0';
1364           else
1365             /* According to SUSv2 "If the actual length of the address is
1366                greater than the length of the supplied sockaddr structure, the
1367                stored address will be truncated."  We play it save here so
1368                that the path always has a trailing 0 even if it's truncated. */
1369             strncpy (sun->sun_path, sock->get_sun_path (),
1370                      *namelen - sizeof *sun + sizeof sun->sun_path - 1);
1371
1372           *namelen = sizeof *sun - sizeof sun->sun_path
1373                      + strlen (sun->sun_path) + 1;
1374           res = 0;
1375         }
1376       else
1377         {
1378           res = getsockname (sock->get_socket (), addr, namelen);
1379           if (res)
1380             set_winsock_errno ();
1381         }
1382     }
1383   syscall_printf ("%d = getsockname (%d, %x, %d)", res, fd, addr, namelen);
1384   return res;
1385 }
1386
1387 /* exported as listen: standards? */
1388 extern "C" int
1389 cygwin_listen (int fd, int backlog)
1390 {
1391   int res = -1;
1392
1393
1394   fhandler_socket *sock = get (fd);
1395   if (sock)
1396     {
1397       res = listen (sock->get_socket (), backlog);
1398       if (res)
1399         set_winsock_errno ();
1400     }
1401   syscall_printf ("%d = listen (%d, %d)", res, fd, backlog);
1402   return res;
1403 }
1404
1405 /* exported as shutdown: standards? */
1406 extern "C" int
1407 cygwin_shutdown (int fd, int how)
1408 {
1409   int res = -1;
1410   sigframe thisframe (mainthread);
1411
1412   fhandler_socket *sock = get (fd);
1413   if (sock)
1414     {
1415       res = shutdown (sock->get_socket (), how);
1416       if (res)
1417         set_winsock_errno ();
1418       else
1419         switch (how)
1420           {
1421           case SHUT_RD:
1422             sock->set_shutdown_read ();
1423             break;
1424           case SHUT_WR:
1425             sock->set_shutdown_write ();
1426             break;
1427           case SHUT_RDWR:
1428             sock->set_shutdown_read ();
1429             sock->set_shutdown_write ();
1430             break;
1431           }
1432     }
1433   syscall_printf ("%d = shutdown (%d, %d)", res, fd, how);
1434   return res;
1435 }
1436
1437 /* exported as hstrerror: BSD 4.3  */
1438 extern "C" const char *
1439 cygwin_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  */
1451 extern "C" void
1452 cygwin_herror (const char *s)
1453 {
1454   if (s && check_null_str (s))
1455     return;
1456   if (cygheap->fdtab.not_open (2))
1457     return;
1458
1459   if (s)
1460     {
1461       write (2, s, strlen (s));
1462       write (2, ": ", 2);
1463     }
1464
1465   const char *h_errstr = cygwin_hstrerror (h_errno);
1466
1467   if (!h_errstr)
1468     switch (h_errno)
1469       {
1470       case NETDB_INTERNAL:
1471         h_errstr = "Resolver internal error";
1472         break;
1473       case NETDB_SUCCESS:
1474         h_errstr = "Resolver error 0 (no error)";
1475         break;
1476       default:
1477         h_errstr = "Unknown resolver error";
1478         break;
1479       }
1480   write (2, h_errstr, strlen (h_errstr));
1481   write (2, "\n", 1);
1482 }
1483
1484 /* exported as getpeername: standards? */
1485 extern "C" int
1486 cygwin_getpeername (int fd, struct sockaddr *name, int *len)
1487 {
1488   int res;
1489   if (check_null_invalid_struct_errno (len)
1490       || __check_null_invalid_struct_errno (name, (unsigned) *len))
1491     return -1;
1492
1493   fhandler_socket *h = get (fd);
1494
1495   if (!h)
1496     res = -1;
1497   else
1498     {
1499       res = getpeername (h->get_socket (), name, len);
1500       if (res)
1501         set_winsock_errno ();
1502     }
1503
1504   debug_printf ("%d = getpeername %d", res, h->get_socket ());
1505   return res;
1506 }
1507
1508 /* exported as recv: standards? */
1509 extern "C" int
1510 cygwin_recv (int fd, void *buf, int len, unsigned int flags)
1511 {
1512   int res;
1513   fhandler_socket *fh = get (fd);
1514
1515   if (__check_null_invalid_struct_errno (buf, len) || !fh)
1516     res = -1;
1517   else
1518     res = fh->recv (buf, len, flags);
1519
1520   syscall_printf ("%d = recv (%d, %x, %x, %x)", res, fd, buf, len, flags);
1521
1522   return res;
1523 }
1524
1525 /* exported as send: standards? */
1526 extern "C" int
1527 cygwin_send (int fd, const void *buf, int len, unsigned int flags)
1528 {
1529   int res;
1530   fhandler_socket *fh = get (fd);
1531
1532   if (__check_invalid_read_ptr_errno (buf, len) || !fh)
1533     res = -1;
1534   else
1535     res = fh->send (buf, len, flags);
1536
1537   syscall_printf ("%d = send (%d, %x, %d, %x)", res, fd, buf, len, flags);
1538
1539   return res;
1540 }
1541
1542 /* getdomainname: standards? */
1543 extern "C" int
1544 getdomainname (char *domain, int len)
1545 {
1546   /*
1547    * This works for Win95 only if the machine is configured to use MS-TCP.
1548    * If a third-party TCP is being used this will fail.
1549    * FIXME: On Win95, is there a way to portably check the TCP stack
1550    * in use and include paths for the Domain name in each ?
1551    * Punt for now and assume MS-TCP on Win95.
1552    */
1553   if (__check_null_invalid_struct_errno (domain, len))
1554     return -1;
1555
1556   reg_key r (HKEY_LOCAL_MACHINE, KEY_READ,
1557              (!wincap.is_winnt ()) ? "System" : "SYSTEM",
1558              "CurrentControlSet", "Services",
1559              (!wincap.is_winnt ()) ? "VxD" : "Tcpip",
1560              (!wincap.is_winnt ()) ? "MSTCP" : "Parameters",
1561              NULL);
1562
1563   /* FIXME: Are registry keys case sensitive? */
1564   if (r.error () || r.get_string ("Domain", domain, len, "") != ERROR_SUCCESS)
1565     {
1566       __seterrno ();
1567       return -1;
1568     }
1569
1570   return 0;
1571 }
1572
1573 /* Cygwin internal */
1574 /* Fill out an ifconf struct. */
1575
1576 /*
1577  * IFCONF 98/ME, NTSP4, W2K:
1578  * Use IP Helper Library
1579  */
1580 static void
1581 get_2k_ifconf (struct ifconf *ifc, int what)
1582 {
1583   int cnt = 0;
1584   char eth[2] = "/", ppp[2] = "/", slp[2] = "/", sub[2] = "0", tok[2] = "/";
1585
1586   /* Union maps buffer to correct struct */
1587   struct ifreq *ifr = ifc->ifc_req;
1588
1589   DWORD if_cnt, ip_cnt, lip, lnp;
1590   DWORD siz_if_table = 0;
1591   DWORD siz_ip_table = 0;
1592   PMIB_IFTABLE ift;
1593   PMIB_IPADDRTABLE ipt;
1594   struct sockaddr_in *sa = NULL;
1595   struct sockaddr *so = NULL;
1596
1597   if (GetIfTable(NULL, &siz_if_table, TRUE) == ERROR_INSUFFICIENT_BUFFER &&
1598       GetIpAddrTable(NULL, &siz_ip_table, TRUE) == ERROR_INSUFFICIENT_BUFFER &&
1599       (ift = (PMIB_IFTABLE) alloca (siz_if_table)) &&
1600       (ipt = (PMIB_IPADDRTABLE) alloca (siz_ip_table)) &&
1601       !GetIfTable(ift, &siz_if_table, TRUE) &&
1602       !GetIpAddrTable(ipt, &siz_ip_table, TRUE))
1603     {
1604       /* Iterate over all known interfaces */
1605       for (if_cnt = 0; if_cnt < ift->dwNumEntries; ++if_cnt)
1606         {
1607           *sub = '0';
1608           /* Iterate over all configured IP-addresses */
1609           for (ip_cnt = 0; ip_cnt < ipt->dwNumEntries; ++ip_cnt)
1610             {
1611               /* Does the IP address belong to the interface? */
1612               if (ipt->table[ip_cnt].dwIndex == ift->table[if_cnt].dwIndex)
1613                 {
1614                   /* Setup the interface name */
1615                   switch (ift->table[if_cnt].dwType)
1616                     {
1617                       case MIB_IF_TYPE_TOKENRING:
1618                         ++*tok;
1619                         strcpy (ifr->ifr_name, "tok");
1620                         strcat (ifr->ifr_name, tok);
1621                         break;
1622                       case MIB_IF_TYPE_ETHERNET:
1623                         if (*sub == '0')
1624                           ++*eth;
1625                         strcpy (ifr->ifr_name, "eth");
1626                         strcat (ifr->ifr_name, eth);
1627                         break;
1628                       case MIB_IF_TYPE_PPP:
1629                         ++*ppp;
1630                         strcpy (ifr->ifr_name, "ppp");
1631                         strcat (ifr->ifr_name, ppp);
1632                         break;
1633                       case MIB_IF_TYPE_SLIP:
1634                         ++*slp;
1635                         strcpy (ifr->ifr_name, "slp");
1636                         strcat (ifr->ifr_name, slp);
1637                         break;
1638                       case MIB_IF_TYPE_LOOPBACK:
1639                         strcpy (ifr->ifr_name, "lo");
1640                         break;
1641                       default:
1642                         continue;
1643                     }
1644                   if (*sub > '0')
1645                     {
1646                       strcat (ifr->ifr_name, ":");
1647                       strcat (ifr->ifr_name, sub);
1648                     }
1649                   ++*sub;
1650                   /* setup sockaddr struct */
1651                   switch (what)
1652                     {
1653                       case SIOCGIFCONF:
1654                       case SIOCGIFADDR:
1655                         sa = (struct sockaddr_in *) &ifr->ifr_addr;
1656                         sa->sin_addr.s_addr = ipt->table[ip_cnt].dwAddr;
1657                         sa->sin_family = AF_INET;
1658                         sa->sin_port = 0;
1659                         break;
1660                       case SIOCGIFBRDADDR:
1661                         sa = (struct sockaddr_in *) &ifr->ifr_broadaddr;
1662 #if 0
1663                         /* Unfortunately, the field returns only crap. */
1664                         sa->sin_addr.s_addr = ipt->table[ip_cnt].dwBCastAddr;
1665 #else
1666                         lip = ipt->table[ip_cnt].dwAddr;
1667                         lnp = ipt->table[ip_cnt].dwMask;
1668                         sa->sin_addr.s_addr = lip & lnp | ~lnp;
1669                         sa->sin_family = AF_INET;
1670                         sa->sin_port = 0;
1671 #endif
1672                         break;
1673                       case SIOCGIFNETMASK:
1674                         sa = (struct sockaddr_in *) &ifr->ifr_netmask;
1675                         sa->sin_addr.s_addr = ipt->table[ip_cnt].dwMask;
1676                         sa->sin_family = AF_INET;
1677                         sa->sin_port = 0;
1678                         break;
1679                       case SIOCGIFHWADDR:
1680                         so = &ifr->ifr_hwaddr;
1681                         for (UINT i = 0; i < IFHWADDRLEN; ++i)
1682                           if (i >= ift->table[if_cnt].dwPhysAddrLen)
1683                             so->sa_data[i] = '\0';
1684                           else
1685                             so->sa_data[i] = ift->table[if_cnt].bPhysAddr[i];
1686                         so->sa_family = AF_INET;
1687                         break;
1688                       case SIOCGIFMETRIC:
1689                         ifr->ifr_metric = 1;
1690                         break;
1691                       case SIOCGIFMTU:
1692                         ifr->ifr_mtu = ift->table[if_cnt].dwMtu;
1693                         break;
1694                     }
1695                   ++cnt;
1696                   if ((caddr_t) ++ifr >
1697                       ifc->ifc_buf + ifc->ifc_len - sizeof (struct ifreq))
1698                     goto done;
1699                 }
1700             }
1701         }
1702     }
1703 done:
1704   /* Set the correct length */
1705   ifc->ifc_len = cnt * sizeof (struct ifreq);
1706 }
1707
1708 /*
1709  * IFCONF Windows NT < SP4:
1710  * Look at the Bind value in
1711  * HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Linkage\
1712  * This is a REG_MULTI_SZ with strings of the form:
1713  * \Device\<Netcard>, where netcard is the name of the net device.
1714  * Then look under:
1715  * HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\<NetCard>\
1716  *                                                      Parameters\Tcpip
1717  * at the IPAddress, Subnetmask and DefaultGateway values for the
1718  * required values.
1719  */
1720 static void
1721 get_nt_ifconf (struct ifconf *ifc, int what)
1722 {
1723   HKEY key;
1724   unsigned long lip, lnp;
1725   struct sockaddr_in *sa = NULL;
1726   struct sockaddr *so = NULL;
1727   DWORD size;
1728   int cnt = 1;
1729   char *binding = (char *) 0;
1730
1731   /* Union maps buffer to correct struct */
1732   struct ifreq *ifr = ifc->ifc_req;
1733
1734   if (RegOpenKeyEx (HKEY_LOCAL_MACHINE,
1735                     "SYSTEM\\"
1736                     "CurrentControlSet\\"
1737                     "Services\\"
1738                     "Tcpip\\"
1739                     "Linkage",
1740                     0, KEY_READ, &key) == ERROR_SUCCESS)
1741     {
1742       if (RegQueryValueEx (key, "Bind",
1743                            NULL, NULL,
1744                            NULL, &size) == ERROR_SUCCESS)
1745         {
1746           binding = (char *) alloca (size);
1747           if (RegQueryValueEx (key, "Bind",
1748                                NULL, NULL,
1749                                (unsigned char *) binding,
1750                                &size) != ERROR_SUCCESS)
1751             {
1752               binding = NULL;
1753             }
1754         }
1755       RegCloseKey (key);
1756     }
1757
1758   if (binding)
1759     {
1760       char *bp, eth[2] = "/";
1761       char cardkey[256], ipaddress[256], netmask[256];
1762
1763       for (bp = binding; *bp; bp += strlen (bp) + 1)
1764         {
1765           bp += strlen ("\\Device\\");
1766           strcpy (cardkey, "SYSTEM\\CurrentControlSet\\Services\\");
1767           strcat (cardkey, bp);
1768           strcat (cardkey, "\\Parameters\\Tcpip");
1769
1770           if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, cardkey,
1771                             0, KEY_READ, &key) != ERROR_SUCCESS)
1772             continue;
1773
1774           if (RegQueryValueEx (key, "IPAddress",
1775                                NULL, NULL,
1776                                (unsigned char *) ipaddress,
1777                                (size = 256, &size)) == ERROR_SUCCESS
1778               && RegQueryValueEx (key, "SubnetMask",
1779                                   NULL, NULL,
1780                                   (unsigned char *) netmask,
1781                                   (size = 256, &size)) == ERROR_SUCCESS)
1782             {
1783               char *ip, *np;
1784               char dhcpaddress[256], dhcpnetmask[256];
1785
1786               for (ip = ipaddress, np = netmask;
1787                    *ip && *np;
1788                    ip += strlen (ip) + 1, np += strlen (np) + 1)
1789                 {
1790                   if ((caddr_t) ++ifr > ifc->ifc_buf
1791                       + ifc->ifc_len
1792                       - sizeof (struct ifreq))
1793                     break;
1794
1795                   if (! strncmp (bp, "NdisWan", 7))
1796                     {
1797                       strcpy (ifr->ifr_name, "ppp");
1798                       strcat (ifr->ifr_name, bp + 7);
1799                     }
1800                   else
1801                     {
1802                       ++*eth;
1803                       strcpy (ifr->ifr_name, "eth");
1804                       strcat (ifr->ifr_name, eth);
1805                     }
1806                   memset (&ifr->ifr_addr, '\0', sizeof ifr->ifr_addr);
1807                   if (cygwin_inet_addr (ip) == 0L
1808                       && RegQueryValueEx (key, "DhcpIPAddress",
1809                                           NULL, NULL,
1810                                           (unsigned char *) dhcpaddress,
1811                                           (size = 256, &size))
1812                       == ERROR_SUCCESS
1813                       && RegQueryValueEx (key, "DhcpSubnetMask",
1814                                           NULL, NULL,
1815                                           (unsigned char *) dhcpnetmask,
1816                                           (size = 256, &size))
1817                       == ERROR_SUCCESS)
1818                     {
1819                       switch (what)
1820                         {
1821                         case SIOCGIFCONF:
1822                         case SIOCGIFADDR:
1823                           sa = (struct sockaddr_in *) &ifr->ifr_addr;
1824                           sa->sin_addr.s_addr = cygwin_inet_addr (dhcpaddress);
1825                           sa->sin_family = AF_INET;
1826                           sa->sin_port = 0;
1827                           break;
1828                         case SIOCGIFBRDADDR:
1829                           lip = cygwin_inet_addr (dhcpaddress);
1830                           lnp = cygwin_inet_addr (dhcpnetmask);
1831                           sa = (struct sockaddr_in *) &ifr->ifr_broadaddr;
1832                           sa->sin_addr.s_addr = lip & lnp | ~lnp;
1833                           sa->sin_family = AF_INET;
1834                           sa->sin_port = 0;
1835                           break;
1836                         case SIOCGIFNETMASK:
1837                           sa = (struct sockaddr_in *) &ifr->ifr_netmask;
1838                           sa->sin_addr.s_addr =
1839                             cygwin_inet_addr (dhcpnetmask);
1840                           sa->sin_family = AF_INET;
1841                           sa->sin_port = 0;
1842                           break;
1843                         case SIOCGIFHWADDR:
1844                           so = &ifr->ifr_hwaddr;
1845                           memset (so->sa_data, 0, IFHWADDRLEN);
1846                           so->sa_family = AF_INET;
1847                           break;
1848                         case SIOCGIFMETRIC:
1849                           ifr->ifr_metric = 1;
1850                           break;
1851                         case SIOCGIFMTU:
1852                           ifr->ifr_mtu = 1500;
1853                           break;
1854                         }
1855                     }
1856                   else
1857                     {
1858                       switch (what)
1859                         {
1860                         case SIOCGIFCONF:
1861                         case SIOCGIFADDR:
1862                           sa = (struct sockaddr_in *) &ifr->ifr_addr;
1863                           sa->sin_addr.s_addr = cygwin_inet_addr (ip);
1864                           sa->sin_family = AF_INET;
1865                           sa->sin_port = 0;
1866                           break;
1867                         case SIOCGIFBRDADDR:
1868                           lip = cygwin_inet_addr (ip);
1869                           lnp = cygwin_inet_addr (np);
1870                           sa = (struct sockaddr_in *) &ifr->ifr_broadaddr;
1871                           sa->sin_addr.s_addr = lip & lnp | ~lnp;
1872                           sa->sin_family = AF_INET;
1873                           sa->sin_port = 0;
1874                           break;
1875                         case SIOCGIFNETMASK:
1876                           sa = (struct sockaddr_in *) &ifr->ifr_netmask;
1877                           sa->sin_addr.s_addr = cygwin_inet_addr (np);
1878                           sa->sin_family = AF_INET;
1879                           sa->sin_port = 0;
1880                           break;
1881                         case SIOCGIFHWADDR:
1882                           so = &ifr->ifr_hwaddr;
1883                           memset (so->sa_data, 0, IFHWADDRLEN);
1884                           so->sa_family = AF_INET;
1885                           break;
1886                         case SIOCGIFMETRIC:
1887                           ifr->ifr_metric = 1;
1888                           break;
1889                         case SIOCGIFMTU:
1890                           ifr->ifr_mtu = 1500;
1891                           break;
1892                         }
1893                     }
1894                   ++cnt;
1895                 }
1896             }
1897           RegCloseKey (key);
1898         }
1899     }
1900
1901   /* Set the correct length */
1902   ifc->ifc_len = cnt * sizeof (struct ifreq);
1903 }
1904
1905 /*
1906  * IFCONF Windows 95:
1907  * HKLM/Enum/Network/MSTCP/"*"
1908  *        -> Value "Driver" enthält Subkey relativ zu
1909  *          HKLM/System/CurrentControlSet/Class/
1910  *        -> In Subkey "Bindings" die Values aufzählen
1911  *          -> Enthält Subkeys der Form "VREDIR\*"
1912  *             Das * ist ein Subkey relativ zu
1913  *             HKLM/System/CurrentControlSet/Class/Net/
1914  * HKLM/System/CurrentControlSet/Class/"Driver"
1915  *        -> Value "IPAddress"
1916  *        -> Value "IPMask"
1917  * HKLM/System/CurrentControlSet/Class/Net/"*"(aus "VREDIR\*")
1918  *        -> Wenn Value "AdapterName" == "MS$PPP" -> ppp interface
1919  *        -> Value "DriverDesc" enthält den Namen
1920  *
1921  */
1922 static void
1923 get_95_ifconf (struct ifconf *ifc, int what)
1924 {
1925   HKEY key;
1926   unsigned long lip, lnp;
1927   struct sockaddr_in *sa = NULL;
1928   struct sockaddr *so = NULL;
1929   FILETIME update;
1930   LONG res;
1931   DWORD size;
1932   int cnt = 1;
1933   char ifname[256];
1934   char eth[2] = "/";
1935   char ppp[2] = "/";
1936
1937   /* Union maps buffer to correct struct */
1938   struct ifreq *ifr = ifc->ifc_req;
1939
1940   if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, "Enum\\Network\\MSTCP",
1941                     0, KEY_READ, &key) != ERROR_SUCCESS)
1942     {
1943       /* Set the correct length */
1944       ifc->ifc_len = cnt * sizeof (struct ifreq);
1945       return;
1946     }
1947
1948   for (int i = 0;
1949        (res = RegEnumKeyEx (key, i, ifname,
1950                             (size = sizeof ifname, &size),
1951                             0, 0, 0, &update)) != ERROR_NO_MORE_ITEMS;
1952        ++i)
1953     {
1954       HKEY ifkey, subkey;
1955       char driver[256], classname[256], netname[256];
1956       char adapter[256], ip[256], np[256];
1957
1958       if (res != ERROR_SUCCESS
1959           || RegOpenKeyEx (key, ifname, 0,
1960                            KEY_READ, &ifkey) != ERROR_SUCCESS)
1961         continue;
1962
1963       if (RegQueryValueEx (ifkey, "Driver", 0,
1964                            NULL, (unsigned char *) driver,
1965                            (size = sizeof driver, &size)) != ERROR_SUCCESS)
1966         {
1967           RegCloseKey (ifkey);
1968           continue;
1969         }
1970
1971       strcpy (classname, "System\\CurrentControlSet\\Services\\Class\\");
1972       strcat (classname, driver);
1973       if ((res = RegOpenKeyEx (HKEY_LOCAL_MACHINE, classname,
1974                                0, KEY_READ, &subkey)) != ERROR_SUCCESS)
1975         {
1976           RegCloseKey (ifkey);
1977           continue;
1978         }
1979
1980       if (RegQueryValueEx (subkey, "IPAddress", 0,
1981                            NULL, (unsigned char *) ip,
1982                            (size = sizeof ip, &size)) == ERROR_SUCCESS
1983           && RegQueryValueEx (subkey, "IPMask", 0,
1984                               NULL, (unsigned char *) np,
1985                               (size = sizeof np, &size)) == ERROR_SUCCESS)
1986         {
1987           if ((caddr_t)++ifr > ifc->ifc_buf
1988               + ifc->ifc_len
1989               - sizeof (struct ifreq))
1990             goto out;
1991
1992           switch (what)
1993             {
1994             case SIOCGIFCONF:
1995             case SIOCGIFADDR:
1996               sa = (struct sockaddr_in *) &ifr->ifr_addr;
1997               sa->sin_addr.s_addr = cygwin_inet_addr (ip);
1998               sa->sin_family = AF_INET;
1999               sa->sin_port = 0;
2000               break;
2001             case SIOCGIFBRDADDR:
2002               lip = cygwin_inet_addr (ip);
2003               lnp = cygwin_inet_addr (np);
2004               sa = (struct sockaddr_in *) &ifr->ifr_broadaddr;
2005               sa->sin_addr.s_addr = lip & lnp | ~lnp;
2006               sa->sin_family = AF_INET;
2007               sa->sin_port = 0;
2008               break;
2009             case SIOCGIFNETMASK:
2010               sa = (struct sockaddr_in *) &ifr->ifr_netmask;
2011               sa->sin_addr.s_addr = cygwin_inet_addr (np);
2012               sa->sin_family = AF_INET;
2013               sa->sin_port = 0;
2014               break;
2015             case SIOCGIFHWADDR:
2016               so = &ifr->ifr_hwaddr;
2017               memset (so->sa_data, 0, IFHWADDRLEN);
2018               so->sa_family = AF_INET;
2019               break;
2020             case SIOCGIFMETRIC:
2021               ifr->ifr_metric = 1;
2022               break;
2023             case SIOCGIFMTU:
2024               ifr->ifr_mtu = 1500;
2025               break;
2026             }
2027         }
2028
2029       RegCloseKey (subkey);
2030
2031       strcpy (netname, "System\\CurrentControlSet\\Services\\Class\\Net\\");
2032       strcat (netname, ifname);
2033
2034       if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, netname,
2035                   0, KEY_READ, &subkey) != ERROR_SUCCESS)
2036       {
2037           RegCloseKey (ifkey);
2038           --ifr;
2039           continue;
2040       }
2041
2042       if (RegQueryValueEx (subkey, "AdapterName", 0,
2043                   NULL, (unsigned char *) adapter,
2044                   (size = sizeof adapter, &size)) == ERROR_SUCCESS
2045               && strcasematch (adapter, "MS$PPP"))
2046       {
2047           ++*ppp;
2048           strcpy (ifr->ifr_name, "ppp");
2049           strcat (ifr->ifr_name, ppp);
2050       }
2051       else
2052       {
2053           ++*eth;
2054           strcpy (ifr->ifr_name, "eth");
2055           strcat (ifr->ifr_name, eth);
2056       }
2057
2058       RegCloseKey (subkey);
2059       RegCloseKey (ifkey);
2060
2061       ++cnt;
2062     }
2063
2064 out:
2065
2066   RegCloseKey (key);
2067
2068   /* Set the correct length */
2069   ifc->ifc_len = cnt * sizeof (struct ifreq);
2070 }
2071
2072 int
2073 get_ifconf (struct ifconf *ifc, int what)
2074 {
2075   unsigned long lip, lnp;
2076   struct sockaddr_in *sa;
2077
2078   if (check_null_invalid_struct_errno (ifc))
2079     return -1;
2080
2081   /* Union maps buffer to correct struct */
2082   struct ifreq *ifr = ifc->ifc_req;
2083
2084   /* Ensure we have space for two struct ifreqs, fail if not. */
2085   if (ifc->ifc_len < (int) (2 * sizeof (struct ifreq)))
2086     {
2087       set_errno (EFAULT);
2088       return -1;
2089     }
2090
2091   /* Set up interface lo0 first */
2092   strcpy (ifr->ifr_name, "lo");
2093   memset (&ifr->ifr_addr, '\0', sizeof (ifr->ifr_addr));
2094   switch (what)
2095     {
2096     case SIOCGIFCONF:
2097     case SIOCGIFADDR:
2098       sa = (struct sockaddr_in *) &ifr->ifr_addr;
2099       sa->sin_addr.s_addr = htonl (INADDR_LOOPBACK);
2100       sa->sin_family = AF_INET;
2101       sa->sin_port = 0;
2102       break;
2103     case SIOCGIFBRDADDR:
2104       lip = htonl (INADDR_LOOPBACK);
2105       lnp = cygwin_inet_addr ("255.0.0.0");
2106       sa = (struct sockaddr_in *) &ifr->ifr_broadaddr;
2107       sa->sin_addr.s_addr = lip & lnp | ~lnp;
2108       sa->sin_family = AF_INET;
2109       sa->sin_port = 0;
2110       break;
2111     case SIOCGIFNETMASK:
2112       sa = (struct sockaddr_in *) &ifr->ifr_netmask;
2113       sa->sin_addr.s_addr = cygwin_inet_addr ("255.0.0.0");
2114       sa->sin_family = AF_INET;
2115       sa->sin_port = 0;
2116       break;
2117     case SIOCGIFHWADDR:
2118       ifr->ifr_hwaddr.sa_family = AF_INET;
2119       memset (ifr->ifr_hwaddr.sa_data, 0, IFHWADDRLEN);
2120       break;
2121     case SIOCGIFMETRIC:
2122       ifr->ifr_metric = 1;
2123       break;
2124     case SIOCGIFMTU:
2125       /* This funny value is returned by `ifconfig lo' on Linux 2.2 kernel. */
2126       ifr->ifr_mtu = 3924;
2127       break;
2128     default:
2129       set_errno (EINVAL);
2130       return -1;
2131     }
2132
2133   OSVERSIONINFO os_version_info;
2134   memset (&os_version_info, 0, sizeof os_version_info);
2135   os_version_info.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
2136   GetVersionEx (&os_version_info);
2137   if (wincap.has_ip_helper_lib ())
2138     get_2k_ifconf (ifc, what);
2139   else if (wincap.is_winnt ())
2140     get_nt_ifconf (ifc, what);
2141   else
2142     get_95_ifconf (ifc, what);
2143   return 0;
2144 }
2145
2146 /* exported as rcmd: standards? */
2147 extern "C" int
2148 cygwin_rcmd (char **ahost, unsigned short inport, char *locuser,
2149                char *remuser, char *cmd, int *fd2p)
2150 {
2151   int res = -1;
2152   SOCKET fd2s;
2153   sigframe thisframe (mainthread);
2154
2155   if (check_null_invalid_struct_errno (ahost) ||
2156       check_null_empty_str_errno (*ahost) ||
2157       (locuser && check_null_empty_str_errno (locuser)) ||
2158       (remuser && check_null_str_errno (remuser)))
2159     return (int) INVALID_SOCKET;
2160
2161   cygheap_fdnew res_fd;
2162   if (res_fd < 0)
2163     goto done;
2164
2165   if (fd2p)
2166     {
2167       cygheap_fdnew newfd (res_fd, false);
2168       if (*fd2p < 0)
2169         goto done;
2170       *fd2p = newfd;
2171     }
2172
2173   res = rcmd (ahost, inport, locuser, remuser, cmd, fd2p ? &fd2s : NULL);
2174   if (res == (int) INVALID_SOCKET)
2175     goto done;
2176   else
2177     {
2178       fdsock (res_fd, "/dev/tcp", res);
2179       res = res_fd;
2180     }
2181
2182   if (fd2p)
2183     fdsock (*fd2p, "/dev/tcp", fd2s);
2184
2185 done:
2186   syscall_printf ("%d = rcmd (...)", res);
2187   return res;
2188 }
2189
2190 /* exported as rresvport: standards? */
2191 extern "C" int
2192 cygwin_rresvport (int *port)
2193 {
2194   int res;
2195   sigframe thisframe (mainthread);
2196
2197   if (check_null_invalid_struct_errno (port))
2198     return -1;
2199
2200   cygheap_fdnew res_fd;
2201   if (res_fd < 0)
2202     res = -1;
2203   else
2204     {
2205       res = rresvport (port);
2206
2207       if (res != (int) INVALID_SOCKET)
2208         {
2209           fdsock (res_fd, "/dev/tcp", res);
2210           res = res_fd;
2211         }
2212     }
2213
2214   syscall_printf ("%d = rresvport (%d)", res, port ? *port : 0);
2215   return res;
2216 }
2217
2218 /* exported as rexec: standards? */
2219 extern "C" int
2220 cygwin_rexec (char **ahost, unsigned short inport, char *locuser,
2221                char *password, char *cmd, int *fd2p)
2222 {
2223   int res = -1;
2224   SOCKET fd2s;
2225   sigframe thisframe (mainthread);
2226
2227   if (check_null_invalid_struct_errno (ahost) ||
2228       check_null_empty_str_errno (*ahost) ||
2229       (locuser && check_null_empty_str_errno (locuser)) ||
2230       (password && check_null_str_errno (password)))
2231     return (int) INVALID_SOCKET;
2232
2233   cygheap_fdnew res_fd;
2234   if (res_fd < 0)
2235     goto done;
2236   if (fd2p)
2237     {
2238       cygheap_fdnew newfd (res_fd);
2239       if (newfd < 0)
2240         goto done;
2241       *fd2p = newfd;
2242     }
2243   res = rexec (ahost, inport, locuser, password, cmd, fd2p ? &fd2s : NULL);
2244   if (res == (int) INVALID_SOCKET)
2245     goto done;
2246   else
2247     {
2248       fdsock (res_fd, "/dev/tcp", res);
2249       res = res_fd;
2250     }
2251   if (fd2p)
2252     fdsock (*fd2p, "/dev/tcp", fd2s);
2253
2254 done:
2255   syscall_printf ("%d = rexec (...)", res);
2256   return res;
2257 }
2258
2259 /* socketpair: standards? */
2260 /* Win32 supports AF_INET only, so ignore domain and protocol arguments */
2261 extern "C" int
2262 socketpair (int family, int type, int protocol, int *sb)
2263 {
2264   int res = -1;
2265   SOCKET insock, outsock, newsock;
2266   struct sockaddr_in sock_in, sock_out;
2267   int len;
2268   cygheap_fdnew sb0;
2269
2270   if (__check_null_invalid_struct_errno (sb, 2 * sizeof(int)))
2271     return -1;
2272
2273   if (family != AF_LOCAL && family != AF_INET)
2274     {
2275       set_errno (EAFNOSUPPORT);
2276       goto done;
2277     }
2278   if (type != SOCK_STREAM && type != SOCK_DGRAM)
2279     {
2280       set_errno (EPROTOTYPE);
2281       goto done;
2282     }
2283   if ((family == AF_LOCAL && protocol != PF_UNSPEC && protocol != PF_LOCAL)
2284       || (family == AF_INET && protocol != PF_UNSPEC && protocol != PF_INET))
2285     {
2286       set_errno (EPROTONOSUPPORT);
2287       goto done;
2288     }
2289
2290   if (sb0 < 0)
2291     goto done;
2292   else
2293     {
2294       sb[0] = sb0;
2295       cygheap_fdnew sb1 (sb0, false);
2296       if (sb1 < 0)
2297         goto done;
2298
2299       sb[1] = sb1;
2300     }
2301
2302   /* create the first socket */
2303   newsock = socket (AF_INET, type, 0);
2304   if (newsock == INVALID_SOCKET)
2305     {
2306       debug_printf ("first socket call failed");
2307       set_winsock_errno ();
2308       goto done;
2309     }
2310
2311   /* bind the socket to any unused port */
2312   sock_in.sin_family = AF_INET;
2313   sock_in.sin_port = 0;
2314   sock_in.sin_addr.s_addr = INADDR_ANY;
2315   if (bind (newsock, (struct sockaddr *) &sock_in, sizeof (sock_in)) < 0)
2316     {
2317       debug_printf ("bind failed");
2318       set_winsock_errno ();
2319       closesocket (newsock);
2320       goto done;
2321     }
2322   len = sizeof (sock_in);
2323   if (getsockname (newsock, (struct sockaddr *) &sock_in, &len) < 0)
2324     {
2325       debug_printf ("getsockname error");
2326       set_winsock_errno ();
2327       closesocket (newsock);
2328       goto done;
2329     }
2330
2331   /* For stream sockets, create a listener */
2332   if (type == SOCK_STREAM)
2333     listen (newsock, 2);
2334
2335   /* create a connecting socket */
2336   outsock = socket (AF_INET, type, 0);
2337   if (outsock == INVALID_SOCKET)
2338     {
2339       debug_printf ("second socket call failed");
2340       set_winsock_errno ();
2341       closesocket (newsock);
2342       goto done;
2343     }
2344
2345   /* For datagram sockets, bind the 2nd socket to an unused address, too */
2346   if (type == SOCK_DGRAM)
2347     {
2348       sock_out.sin_family = AF_INET;
2349       sock_out.sin_port = 0;
2350       sock_out.sin_addr.s_addr = INADDR_ANY;
2351       if (bind (outsock, (struct sockaddr *) &sock_out, sizeof (sock_out)) < 0)
2352         {
2353           debug_printf ("bind failed");
2354           set_winsock_errno ();
2355           closesocket (newsock);
2356           closesocket (outsock);
2357           goto done;
2358         }
2359       len = sizeof (sock_out);
2360       if (getsockname (outsock, (struct sockaddr *) &sock_out, &len) < 0)
2361         {
2362           debug_printf ("getsockname error");
2363           set_winsock_errno ();
2364           closesocket (newsock);
2365           closesocket (outsock);
2366           goto done;
2367         }
2368     }
2369
2370   /* Force IP address to loopback */
2371   sock_in.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
2372   if (type == SOCK_DGRAM)
2373     sock_out.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
2374
2375   /* Do a connect */
2376   if (connect (outsock, (struct sockaddr *) &sock_in,
2377                                            sizeof (sock_in)) < 0)
2378     {
2379       debug_printf ("connect error");
2380       set_winsock_errno ();
2381       closesocket (newsock);
2382       closesocket (outsock);
2383       goto done;
2384     }
2385
2386   if (type == SOCK_STREAM)
2387     {
2388       /* For stream sockets, accept the connection and close the listener */
2389       len = sizeof (sock_in);
2390       insock = accept (newsock, (struct sockaddr *) &sock_in, &len);
2391       if (insock == INVALID_SOCKET)
2392         {
2393           debug_printf ("accept error");
2394           set_winsock_errno ();
2395           closesocket (newsock);
2396           closesocket (outsock);
2397           goto done;
2398         }
2399       closesocket (newsock);
2400     }
2401   else
2402     {
2403       /* For datagram sockets, connect the 2nd socket */
2404       if (connect (newsock, (struct sockaddr *) &sock_out,
2405                                                sizeof (sock_out)) < 0)
2406         {
2407           debug_printf ("connect error");
2408           set_winsock_errno ();
2409           closesocket (newsock);
2410           closesocket (outsock);
2411           goto done;
2412         }
2413       insock = newsock;
2414     }
2415
2416   res = 0;
2417
2418   if (family == AF_LOCAL)
2419     {
2420       fhandler_socket *fh;
2421
2422       fh = fdsock (sb[0],
2423                    type == SOCK_STREAM ? "/dev/streamsocket" : "/dev/dgsocket",
2424                    insock);
2425       fh->set_sun_path ("");
2426       fh->set_addr_family (AF_LOCAL);
2427       fh = fdsock (sb[1],
2428                    type == SOCK_STREAM ? "/dev/streamsocket" : "/dev/dgsocket",
2429                    outsock);
2430       fh->set_sun_path ("");
2431       fh->set_addr_family (AF_LOCAL);
2432     }
2433   else
2434     {
2435       fdsock (sb[0], type == SOCK_STREAM ? "/dev/tcp" : "/dev/udp",
2436               insock)->set_addr_family (AF_INET);
2437       fdsock (sb[1], type == SOCK_STREAM ? "/dev/tcp" : "/dev/udp",
2438               outsock)->set_addr_family (AF_INET);
2439     }
2440
2441 done:
2442   syscall_printf ("%d = socketpair (...)", res);
2443   return res;
2444 }
2445
2446 /* sethostent: standards? */
2447 extern "C" void
2448 sethostent (int)
2449 {
2450 }
2451
2452 /* endhostent: standards? */
2453 extern "C" void
2454 endhostent (void)
2455 {
2456 }
2457
2458 /* exported as recvmsg: standards? */
2459 extern "C" int 
2460 cygwin_recvmsg(int s, struct msghdr *msg, int flags)
2461 {
2462     int ret, nb;
2463     size_t tot = 0;
2464     int i;
2465     char *buf, *p;
2466     struct iovec *iov = msg->msg_iov;
2467
2468     for(i = 0; i < msg->msg_iovlen; ++i)
2469         tot += iov[i].iov_len;
2470     buf = (char *) malloc(tot);
2471     if (tot != 0 && buf == NULL) {
2472         errno = ENOMEM;
2473         return -1;
2474     }
2475     nb = ret = cygwin_recvfrom (s, buf, tot, flags, 
2476       (struct sockaddr *) msg->msg_name, (int *) &msg->msg_namelen);
2477     p = buf;
2478     while (nb > 0) {
2479         ssize_t cnt = min(nb, iov->iov_len);
2480
2481         memcpy (iov->iov_base, p, cnt);
2482         p += cnt;
2483         nb -= cnt;
2484         ++iov;
2485     }
2486     free(buf);
2487     return ret;
2488 }
2489
2490 /* exported as sendmsg: standards? */
2491 extern "C" int
2492 cygwin_sendmsg(int s, const struct msghdr *msg, int flags)
2493 {
2494     int ret;
2495     size_t tot = 0;
2496     int i;
2497     char *buf, *p;
2498     struct iovec *iov = msg->msg_iov;
2499
2500     for(i = 0; i < msg->msg_iovlen; ++i)
2501         tot += iov[i].iov_len;
2502     buf = (char *) malloc(tot);
2503     if (tot != 0 && buf == NULL) {
2504         errno = ENOMEM;
2505         return -1;
2506     }
2507     p = buf;
2508     for (i = 0; i < msg->msg_iovlen; ++i) {
2509         memcpy (p, iov[i].iov_base, iov[i].iov_len);
2510         p += iov[i].iov_len;
2511     }
2512     ret = cygwin_sendto (s, buf, tot, flags, 
2513       (struct sockaddr *) msg->msg_name, msg->msg_namelen);
2514     free (buf);
2515     return ret;
2516 }