OSDN Git Service

white space and minor comment cleanup.
[pf3gnuchains/sourceware.git] / winsup / cygwin / fhandler_socket.cc
1 /* fhandler_socket.cc. See fhandler.h for a description of the fhandler classes.
2
3    Copyright 2000, 2001, 2002, 2003, 2004, 2005 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 <sys/socket.h>
17 #include <sys/un.h>
18 #include <sys/uio.h>
19 #include <asm/byteorder.h>
20
21 #include <stdlib.h>
22 #define USE_SYS_TYPES_FD_SET
23 #include <winsock2.h>
24 #include "cygerrno.h"
25 #include "security.h"
26 #include "cygwin/version.h"
27 #include "perprocess.h"
28 #include "path.h"
29 #include "fhandler.h"
30 #include "dtable.h"
31 #include "cygheap.h"
32 #include "sigproc.h"
33 #include "cygthread.h"
34 #include "select.h"
35 #include "wininfo.h"
36 #include <unistd.h>
37 #include <sys/acl.h>
38
39 #define ASYNC_MASK (FD_READ|FD_WRITE|FD_OOB|FD_ACCEPT|FD_CONNECT)
40
41 extern bool fdsock (cygheap_fdmanip& fd, const device *, SOCKET soc);
42 extern "C" {
43 int sscanf (const char *, const char *, ...);
44 } /* End of "C" section */
45
46 fhandler_dev_random* entropy_source;
47
48 /* cygwin internal: map sockaddr into internet domain address */
49 static int
50 get_inet_addr (const struct sockaddr *in, int inlen,
51                struct sockaddr_in *out, int *outlen,
52                int *type = NULL, int *secret = NULL)
53 {
54   int secret_buf [4];
55   int* secret_ptr = (secret ? : secret_buf);
56
57   if (in->sa_family == AF_INET)
58     {
59       *out = * (struct sockaddr_in *)in;
60       *outlen = inlen;
61       return 1;
62     }
63   else if (in->sa_family == AF_LOCAL)
64     {
65       path_conv pc (in->sa_data, PC_SYM_FOLLOW);
66       if (pc.error)
67         {
68           set_errno (pc.error);
69           return 0;
70         }
71       if (!pc.exists ())
72         {
73           set_errno (ENOENT);
74           return 0;
75         }
76       if (!pc.issocket ())
77         {
78           set_errno (EBADF);
79           return 0;
80         }
81       HANDLE fh = CreateFile (pc, GENERIC_READ, wincap.shared (), &sec_none,
82                               OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
83       if (fh == INVALID_HANDLE_VALUE)
84         {
85           __seterrno ();
86           return 0;
87         }
88       int ret = 0;
89       DWORD len = 0;
90       char buf[128];
91       memset (buf, 0, sizeof buf);
92       if (ReadFile (fh, buf, 128, &len, 0))
93         {
94           struct sockaddr_in sin;
95           char ctype;
96           sin.sin_family = AF_INET;
97           sscanf (buf + strlen (SOCKET_COOKIE), "%hu %c %08x-%08x-%08x-%08x",
98                   &sin.sin_port,
99                   &ctype,
100                   secret_ptr, secret_ptr + 1, secret_ptr + 2, secret_ptr + 3);
101           sin.sin_port = htons (sin.sin_port);
102           sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
103           *out = sin;
104           *outlen = sizeof sin;
105           if (type)
106             *type = (ctype == 's' ? SOCK_STREAM :
107                      ctype == 'd' ? SOCK_DGRAM
108                                   : 0);
109           ret = 1;
110         }
111       CloseHandle (fh);
112       return ret;
113     }
114   else
115     {
116       set_errno (EAFNOSUPPORT);
117       return 0;
118     }
119 }
120
121 /**********************************************************************/
122 /* fhandler_socket */
123
124 fhandler_socket::fhandler_socket () :
125   fhandler_base (),
126   sun_path (NULL),
127   status ()
128 {
129   need_fork_fixup (true);
130   prot_info_ptr = (LPWSAPROTOCOL_INFOA) cmalloc (HEAP_BUF,
131                                                  sizeof (WSAPROTOCOL_INFOA));
132 #if 0
133   if (pc.is_fs_special ())
134     {
135       fhandler_socket * fhs = (fhandler_socket *) fh;
136       fhs->set_addr_family (AF_LOCAL);
137       fhs->set_sun_path (posix_path);
138     }
139 #endif
140 }
141
142 fhandler_socket::~fhandler_socket ()
143 {
144   if (prot_info_ptr)
145     cfree (prot_info_ptr);
146   if (sun_path)
147     cfree (sun_path);
148 }
149
150 char *
151 fhandler_socket::get_proc_fd_name (char *buf)
152 {
153   __small_sprintf (buf, "socket:[%d]", get_socket ());
154   return buf;
155 }
156
157 int
158 fhandler_socket::open (int flags, mode_t mode)
159 {
160   set_errno (ENXIO);
161   return 0;
162 }
163
164 void
165 fhandler_socket::af_local_set_sockpair_cred (void)
166 {
167   sec_pid = sec_peer_pid = getpid ();
168   sec_uid = sec_peer_uid = geteuid32 ();
169   sec_gid = sec_peer_gid = getegid32 ();
170 }
171
172 void
173 fhandler_socket::af_local_setblocking (bool &async, bool &nonblocking)
174 {
175   async = async_io ();
176   nonblocking = is_nonblocking ();
177   if (async || nonblocking)
178   WSAAsyncSelect (get_socket (), winmsg, 0, 0);
179   unsigned long p = 0;
180   ioctlsocket (get_socket (), FIONBIO, &p);
181   set_nonblocking (false);
182   async_io (false);
183 }
184
185 void
186 fhandler_socket::af_local_unsetblocking (bool async, bool nonblocking)
187 {
188   if (nonblocking)
189     {
190       unsigned long p = 1;
191       ioctlsocket (get_socket (), FIONBIO, &p);
192       set_nonblocking (true);
193     }
194   if (async)
195     {
196       WSAAsyncSelect (get_socket (), winmsg, WM_ASYNCIO, ASYNC_MASK);
197       async_io (true);
198     }
199 }
200
201 bool
202 fhandler_socket::af_local_recv_secret (void)
203 {
204   int out[4] = { 0, 0, 0, 0 };
205   int rest = sizeof out;
206   char *ptr = (char *) out;
207   while (rest > 0)
208     {
209       int ret = recvfrom (ptr, rest, 0, NULL, NULL);
210       if (ret <= 0)
211         break;
212       rest -= ret;
213       ptr += ret;
214     }
215   if (rest == 0)
216     {
217       debug_printf ("Received af_local secret: %08x-%08x-%08x-%08x",
218                     out[0], out[1], out[2], out[3]);
219       if (out[0] != connect_secret[0] || out[1] != connect_secret[1]
220           || out[2] != connect_secret[2] || out[3] != connect_secret[3])
221         {
222           debug_printf ("Receiving af_local secret mismatch");
223           return false;
224         }
225     }
226   else
227     debug_printf ("Receiving af_local secret failed");
228   return rest == 0;
229 }
230
231 bool
232 fhandler_socket::af_local_send_secret (void)
233 {
234   int rest = sizeof connect_secret;
235   char *ptr = (char *) connect_secret;
236   while (rest > 0)
237     {
238       int ret = sendto (ptr, rest, 0, NULL, 0);
239       if (ret <= 0)
240         break;
241       rest -= ret;
242       ptr += ret;
243     }
244   debug_printf ("Sending af_local secret %s", rest == 0 ? "succeeded"
245                                                         : "failed");
246   return rest == 0;
247 }
248
249 bool
250 fhandler_socket::af_local_recv_cred (void)
251 {
252   struct ucred out = { (pid_t) 0, (__uid32_t) -1, (__gid32_t) -1 };
253   int rest = sizeof out;
254   char *ptr = (char *) &out;
255   while (rest > 0)
256     {
257       int ret = recvfrom (ptr, rest, 0, NULL, NULL);
258       if (ret <= 0)
259         break;
260       rest -= ret;
261       ptr += ret;
262     }
263   if (rest == 0)
264     {
265       debug_printf ("Received eid credentials: pid: %d, uid: %d, gid: %d",
266                     out.pid, out.uid, out.gid);
267       sec_peer_pid = out.pid;
268       sec_peer_uid = out.uid;
269       sec_peer_gid = out.gid;
270     }
271   else
272     debug_printf ("Receiving eid credentials failed");
273   return rest == 0;
274 }
275
276 bool
277 fhandler_socket::af_local_send_cred (void)
278 {
279   struct ucred in = { sec_pid, sec_uid, sec_gid };
280   int rest = sizeof in;
281   char *ptr = (char *) &in;
282   while (rest > 0)
283     {
284       int ret = sendto (ptr, rest, 0, NULL, 0);
285       if (ret <= 0)
286         break;
287       rest -= ret;
288       ptr += ret;
289     }
290   if (rest == 0)
291     debug_printf ("Sending eid credentials succeeded");
292   else
293     debug_printf ("Sending eid credentials failed");
294   return rest == 0;
295 }
296
297 int
298 fhandler_socket::af_local_connect (void)
299 {
300   /* This keeps the test out of select. */
301   if (get_addr_family () != AF_LOCAL || get_socket_type () != SOCK_STREAM)
302     return 0;
303
304   debug_printf ("af_local_connect called");
305   bool orig_async_io, orig_is_nonblocking;
306   af_local_setblocking (orig_async_io, orig_is_nonblocking);
307   if (!af_local_send_secret () || !af_local_recv_secret ()
308       || !af_local_send_cred () || !af_local_recv_cred ())
309     {
310       debug_printf ("accept from unauthorized server");
311       ::shutdown (get_socket (), SD_BOTH);
312       WSASetLastError (WSAECONNREFUSED);
313       return -1;
314     }
315   af_local_unsetblocking (orig_async_io, orig_is_nonblocking);
316   return 0;
317 }
318
319 int
320 fhandler_socket::af_local_accept (void)
321 {
322   debug_printf ("af_local_accept called");
323   bool orig_async_io, orig_is_nonblocking;
324   af_local_setblocking (orig_async_io, orig_is_nonblocking);
325   if (!af_local_recv_secret () || !af_local_send_secret ()
326       || !af_local_recv_cred () || !af_local_send_cred ())
327     {
328       debug_printf ("connect from unauthorized client");
329       ::shutdown (get_socket (), SD_BOTH);
330       ::closesocket (get_socket ());
331       WSASetLastError (WSAECONNABORTED);
332       return -1;
333     }
334   af_local_unsetblocking (orig_async_io, orig_is_nonblocking);
335   return 0;
336 }
337
338 void
339 fhandler_socket::af_local_set_cred (void)
340 {
341   sec_pid = getpid ();
342   sec_uid = geteuid32 ();
343   sec_gid = getegid32 ();
344   sec_peer_pid = (pid_t) 0;
345   sec_peer_uid = (__uid32_t) -1;
346   sec_peer_gid = (__gid32_t) -1;
347 }
348
349 void
350 fhandler_socket::af_local_copy (fhandler_socket *sock)
351 {
352   sock->connect_secret[0] = connect_secret[0];
353   sock->connect_secret[1] = connect_secret[1];
354   sock->connect_secret[2] = connect_secret[2];
355   sock->connect_secret[3] = connect_secret[3];
356   sock->sec_pid = sec_pid;
357   sock->sec_uid = sec_uid;
358   sock->sec_gid = sec_gid;
359   sock->sec_peer_pid = sec_peer_pid;
360   sock->sec_peer_uid = sec_peer_uid;
361   sock->sec_peer_gid = sec_peer_gid;
362 }
363
364 void
365 fhandler_socket::af_local_set_secret (char *buf)
366 {
367   if (!entropy_source)
368     {
369       void *buf = malloc (sizeof (fhandler_dev_random));
370       entropy_source = new (buf) fhandler_dev_random ();
371       entropy_source->dev () = *urandom_dev;
372     }
373   if (entropy_source &&
374       !entropy_source->open (O_RDONLY))
375     {
376       delete entropy_source;
377       entropy_source = NULL;
378     }
379   if (entropy_source)
380     {
381       size_t len = sizeof (connect_secret);
382       entropy_source->read (connect_secret, len);
383       if (len != sizeof (connect_secret))
384         bzero ((char*) connect_secret, sizeof (connect_secret));
385     }
386   __small_sprintf (buf, "%08x-%08x-%08x-%08x",
387                    connect_secret [0], connect_secret [1],
388                    connect_secret [2], connect_secret [3]);
389 }
390
391 void
392 fhandler_socket::fixup_before_fork_exec (DWORD win_proc_id)
393 {
394   if (!winsock2_active)
395     {
396       fhandler_base::fixup_before_fork_exec (win_proc_id);
397       debug_printf ("Without Winsock 2.0");
398     }
399   else if (!WSADuplicateSocketA (get_socket (), win_proc_id, prot_info_ptr))
400     debug_printf ("WSADuplicateSocket went fine, sock %p, win_proc_id %d, prot_info_ptr %p",
401                   get_socket (), win_proc_id, prot_info_ptr);
402   else
403     {
404       debug_printf ("WSADuplicateSocket error, sock %p, win_proc_id %d, prot_info_ptr %p",
405                     get_socket (), win_proc_id, prot_info_ptr);
406       set_winsock_errno ();
407     }
408 }
409
410 extern "C" void __stdcall load_wsock32 ();
411 void
412 fhandler_socket::fixup_after_fork (HANDLE parent)
413 {
414   SOCKET new_sock;
415
416   debug_printf ("WSASocket begin, dwServiceFlags1=%d",
417                 prot_info_ptr->dwServiceFlags1);
418
419   if ((new_sock = WSASocketA (FROM_PROTOCOL_INFO,
420                                    FROM_PROTOCOL_INFO,
421                                    FROM_PROTOCOL_INFO,
422                                    prot_info_ptr, 0, 0)) == INVALID_SOCKET)
423     {
424       debug_printf ("WSASocket error");
425       set_io_handle ((HANDLE)INVALID_SOCKET);
426       set_winsock_errno ();
427     }
428   else if (!new_sock && !winsock2_active)
429     {
430       load_wsock32 ();
431       fhandler_base::fixup_after_fork (parent);
432       debug_printf ("Without Winsock 2.0");
433     }
434   else
435     {
436       debug_printf ("WSASocket went fine new_sock %p, old_sock %p", new_sock, get_io_handle ());
437       set_io_handle ((HANDLE) new_sock);
438     }
439 }
440
441 void
442 fhandler_socket::fixup_after_exec ()
443 {
444   debug_printf ("here");
445   if (!close_on_exec ())
446     fixup_after_fork (NULL);
447 #if 0
448   else if (!winsock2_active)
449     closesocket (get_socket ());
450 #endif
451 }
452
453 int
454 fhandler_socket::dup (fhandler_base *child)
455 {
456   HANDLE nh;
457
458   debug_printf ("here");
459   fhandler_socket *fhs = (fhandler_socket *) child;
460   fhs->addr_family = addr_family;
461   fhs->set_socket_type (get_socket_type ());
462   if (get_addr_family () == AF_LOCAL)
463     {
464       fhs->set_sun_path (get_sun_path ());
465       if (get_socket_type () == SOCK_STREAM)
466         {
467           fhs->sec_pid = sec_pid;
468           fhs->sec_uid = sec_uid;
469           fhs->sec_gid = sec_gid;
470           fhs->sec_peer_pid = sec_peer_pid;
471           fhs->sec_peer_uid = sec_peer_uid;
472           fhs->sec_peer_gid = sec_peer_gid;
473         }
474     }
475   fhs->connect_state (connect_state ());
476
477   if (winsock2_active)
478     {
479       /* Since WSADuplicateSocket() fails on NT systems when the process
480          is currently impersonating a non-privileged account, we revert
481          to the original account before calling WSADuplicateSocket() and
482          switch back afterwards as it's also in fork().
483          If WSADuplicateSocket() still fails for some reason, we fall back
484          to DuplicateHandle(). */
485       WSASetLastError (0);
486       cygheap->user.deimpersonate ();
487       fhs->set_io_handle (get_io_handle ());
488       fhs->fixup_before_fork_exec (GetCurrentProcessId ());
489       cygheap->user.reimpersonate ();
490       if (!WSAGetLastError ())
491         {
492           fhs->fixup_after_fork (hMainProc);
493           if (fhs->get_io_handle() != (HANDLE) INVALID_SOCKET)
494             {
495               cygheap->fdtab.inc_need_fixup_before ();
496               return 0;
497             }
498         }
499       debug_printf ("WSADuplicateSocket failed, trying DuplicateHandle");
500     }
501
502   /* We don't call fhandler_base::dup here since that requires
503      having winsock called from fhandler_base and it creates only
504      inheritable sockets which is wrong for winsock2. */
505
506   if (!DuplicateHandle (hMainProc, get_io_handle (), hMainProc, &nh, 0,
507                         !winsock2_active, DUPLICATE_SAME_ACCESS))
508     {
509       system_printf ("!DuplicateHandle(%x) failed, %E", get_io_handle ());
510       __seterrno ();
511       return -1;
512     }
513   VerifyHandle (nh);
514   fhs->set_io_handle (nh);
515   cygheap->fdtab.inc_need_fixup_before ();
516   return 0;
517 }
518
519 int __stdcall
520 fhandler_socket::fstat (struct __stat64 *buf)
521 {
522   int res;
523   if (get_device () == FH_UNIX)
524     {
525       res = fhandler_base::fstat_fs (buf);
526       if (!res)
527         {
528           buf->st_mode = (buf->st_mode & ~S_IFMT) | S_IFSOCK;
529         }
530     }
531   else
532     {
533       res = fhandler_base::fstat (buf);
534       if (!res)
535         {
536           buf->st_dev = 0;
537           buf->st_ino = (__ino64_t) ((DWORD) get_handle ());
538           buf->st_mode = S_IFSOCK | S_IRWXU | S_IRWXG | S_IRWXO;
539         }
540     }
541   return res;
542 }
543
544 int
545 fhandler_socket::fchmod (mode_t mode)
546 {
547   if (get_device () == FH_UNIX)
548     {
549       fhandler_disk_file fh (pc);
550       fh.get_device () = FH_FS;
551       int ret = fh.fchmod (mode);
552       SetFileAttributes (pc, GetFileAttributes (pc) | FILE_ATTRIBUTE_SYSTEM);
553       return ret;
554     }
555   return 0;
556 }
557
558 int
559 fhandler_socket::fchown (__uid32_t uid, __gid32_t gid)
560 {
561   if (get_device () == FH_UNIX)
562     {
563       fhandler_disk_file fh (pc);
564       return fh.fchown (uid, gid);
565     }
566   return 0;
567 }
568
569 int
570 fhandler_socket::facl (int cmd, int nentries, __aclent32_t *aclbufp)
571 {
572   if (get_device () == FH_UNIX)
573     {
574       fhandler_disk_file fh (pc);
575       return fh.facl (cmd, nentries, aclbufp);
576     }
577   return fhandler_base::facl (cmd, nentries, aclbufp);
578 }
579
580 int
581 fhandler_socket::link (const char *newpath)
582 {
583   if (get_device () == FH_UNIX)
584     {
585       fhandler_disk_file fh (pc);
586       return fh.link (newpath);
587     }
588   return fhandler_base::link (newpath);
589 }
590
591 int
592 fhandler_socket::bind (const struct sockaddr *name, int namelen)
593 {
594   int res = -1;
595
596   if (name->sa_family == AF_LOCAL)
597     {
598 #define un_addr ((struct sockaddr_un *) name)
599       struct sockaddr_in sin;
600       int len = sizeof sin;
601
602       if (strlen (un_addr->sun_path) >= UNIX_PATH_LEN)
603         {
604           set_errno (ENAMETOOLONG);
605           goto out;
606         }
607       sin.sin_family = AF_INET;
608       sin.sin_port = 0;
609       sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
610       if (::bind (get_socket (), (sockaddr *) &sin, len))
611         {
612           syscall_printf ("AF_LOCAL: bind failed %d", get_errno ());
613           set_winsock_errno ();
614           goto out;
615         }
616       if (::getsockname (get_socket (), (sockaddr *) &sin, &len))
617         {
618           syscall_printf ("AF_LOCAL: getsockname failed %d", get_errno ());
619           set_winsock_errno ();
620           goto out;
621         }
622
623       sin.sin_port = ntohs (sin.sin_port);
624       debug_printf ("AF_LOCAL: socket bound to port %u", sin.sin_port);
625
626       path_conv pc (un_addr->sun_path, PC_SYM_FOLLOW);
627       if (pc.error)
628         {
629           set_errno (pc.error);
630           goto out;
631         }
632       if (pc.exists ())
633         {
634           set_errno (EADDRINUSE);
635           goto out;
636         }
637       mode_t mode = (S_IRWXU | S_IRWXG | S_IRWXO) & ~cygheap->umask;
638       DWORD attr = FILE_ATTRIBUTE_SYSTEM;
639       if (!(mode & (S_IWUSR | S_IWGRP | S_IWOTH)))
640         attr |= FILE_ATTRIBUTE_READONLY;
641       SECURITY_ATTRIBUTES sa = sec_none;
642       security_descriptor sd;
643       if (allow_ntsec && pc.has_acls ())
644         set_security_attribute (mode, &sa, sd);
645       HANDLE fh = CreateFile (pc, GENERIC_WRITE, 0, &sa, CREATE_NEW, attr, 0);
646       if (fh == INVALID_HANDLE_VALUE)
647         {
648           if (GetLastError () == ERROR_ALREADY_EXISTS)
649             set_errno (EADDRINUSE);
650           else
651             __seterrno ();
652         }
653
654       char buf[sizeof (SOCKET_COOKIE) + 80];
655       __small_sprintf (buf, "%s%u %c ", SOCKET_COOKIE, sin.sin_port, get_socket_type () == SOCK_STREAM ? 's' : get_socket_type () == SOCK_DGRAM ? 'd' : '-');
656       af_local_set_secret (strchr (buf, '\0'));
657       DWORD blen = strlen (buf) + 1;
658       if (!WriteFile (fh, buf, blen, &blen, 0))
659         {
660           __seterrno ();
661           CloseHandle (fh);
662           DeleteFile (pc);
663         }
664       else
665         {
666           CloseHandle (fh);
667           set_sun_path (un_addr->sun_path);
668           res = 0;
669         }
670 #undef un_addr
671     }
672   else if (::bind (get_socket (), name, namelen))
673     set_winsock_errno ();
674   else
675     res = 0;
676
677 out:
678   return res;
679 }
680
681 int
682 fhandler_socket::connect (const struct sockaddr *name, int namelen)
683 {
684   int res = -1;
685   bool in_progress = false;
686   struct sockaddr_in sin;
687   DWORD err;
688   int type;
689
690   if (!get_inet_addr (name, namelen, &sin, &namelen, &type, connect_secret))
691     return -1;
692
693   if (get_addr_family () == AF_LOCAL && get_socket_type () != type)
694     {
695       WSASetLastError (WSAEPROTOTYPE);
696       set_winsock_errno ();
697       return -1;
698     }
699
700   res = ::connect (get_socket (), (struct sockaddr *) &sin, namelen);
701
702   if (!res)
703     err = 0;
704   else
705     {
706       err = WSAGetLastError ();
707       /* Special handling for connect to return the correct error code
708          when called on a non-blocking socket. */
709       if (is_nonblocking ())
710         {
711           if (err == WSAEWOULDBLOCK || err == WSAEALREADY)
712             in_progress = true;
713
714           if (err == WSAEWOULDBLOCK)
715             WSASetLastError (err = WSAEINPROGRESS);
716           else if (err == WSAEINVAL)
717             WSASetLastError (err = WSAEISCONN);
718         }
719       set_winsock_errno ();
720     }
721
722   if (get_addr_family () == AF_LOCAL && (!res || in_progress))
723     set_sun_path (name->sa_data);
724
725   if (get_addr_family () == AF_LOCAL && get_socket_type () == SOCK_STREAM)
726     {
727       af_local_set_cred (); /* Don't move into af_local_connect since
728                                af_local_connect is called from select,
729                                possibly running under another identity. */
730       if (!res && af_local_connect ())
731         {
732           set_winsock_errno ();
733           return -1;
734         }
735     }
736
737   if (err == WSAEINPROGRESS || err == WSAEALREADY)
738     connect_state (connect_pending);
739   else if (err)
740     connect_state (connect_failed);
741   else
742     connect_state (connected);
743
744   return res;
745 }
746
747 int
748 fhandler_socket::listen (int backlog)
749 {
750   int res = ::listen (get_socket (), backlog);
751   if (res)
752     set_winsock_errno ();
753   else
754     {
755       if (get_addr_family () == AF_LOCAL && get_socket_type () == SOCK_STREAM)
756         af_local_set_cred ();
757       connect_state (connected);
758     }
759   return res;
760 }
761
762 int
763 fhandler_socket::accept (struct sockaddr *peer, int *len)
764 {
765   int res = -1;
766
767   /* Allows NULL peer and len parameters. */
768   struct sockaddr_in peer_dummy;
769   int len_dummy;
770   if (!peer)
771     peer = (struct sockaddr *) &peer_dummy;
772   if (!len)
773     {
774       len_dummy = sizeof (struct sockaddr_in);
775       len = &len_dummy;
776     }
777
778   /* accept on NT fails if len < sizeof (sockaddr_in)
779    * some programs set len to
780    * sizeof (name.sun_family) + strlen (name.sun_path) for UNIX domain
781    */
782   if (len && ((unsigned) *len < sizeof (struct sockaddr_in)))
783     *len = sizeof (struct sockaddr_in);
784
785   res = ::accept (get_socket (), peer, len);
786
787   if (res == (int) INVALID_SOCKET)
788     set_winsock_errno ();
789   else
790     {
791       cygheap_fdnew res_fd;
792       if (res_fd >= 0 && fdsock (res_fd, &dev (), res))
793         {
794           fhandler_socket *sock = (fhandler_socket *) res_fd;
795           sock->set_addr_family (get_addr_family ());
796           sock->set_socket_type (get_socket_type ());
797           sock->async_io (async_io ());
798           sock->set_nonblocking (is_nonblocking ());
799           if (get_addr_family () == AF_LOCAL)
800             {
801               sock->set_sun_path (get_sun_path ());
802               if (get_socket_type () == SOCK_STREAM)
803                 {
804                   /* Don't forget to copy credentials from accepting
805                      socket to accepted socket and start transaction
806                      on accepted socket! */
807                   af_local_copy (sock);
808                   res = sock->af_local_accept ();
809                   if (res == -1)
810                     {
811                       res_fd.release ();
812                       set_winsock_errno ();
813                       goto out;
814                     }
815                 }
816             }
817           sock->connect_state (connected);
818           res = res_fd;
819         }
820       else
821         {
822           closesocket (res);
823           res = -1;
824         }
825     }
826
827 out:
828   debug_printf ("res %d", res);
829   return res;
830 }
831
832 int
833 fhandler_socket::getsockname (struct sockaddr *name, int *namelen)
834 {
835   int res = -1;
836
837   if (get_addr_family () == AF_LOCAL)
838     {
839       struct sockaddr_un *sun = (struct sockaddr_un *) name;
840       memset (sun, 0, *namelen);
841       sun->sun_family = AF_LOCAL;
842
843       if (!get_sun_path ())
844         sun->sun_path[0] = '\0';
845       else
846         /* According to SUSv2 "If the actual length of the address is
847            greater than the length of the supplied sockaddr structure, the
848            stored address will be truncated."  We play it save here so
849            that the path always has a trailing 0 even if it's truncated. */
850         strncpy (sun->sun_path, get_sun_path (),
851                  *namelen - sizeof *sun + sizeof sun->sun_path - 1);
852
853       *namelen = sizeof *sun - sizeof sun->sun_path
854                  + strlen (sun->sun_path) + 1;
855       res = 0;
856     }
857   else
858     {
859       res = ::getsockname (get_socket (), name, namelen);
860       if (res)
861         set_winsock_errno ();
862     }
863
864   return res;
865 }
866
867 int
868 fhandler_socket::getpeername (struct sockaddr *name, int *namelen)
869 {
870   int res = ::getpeername (get_socket (), name, namelen);
871   if (res)
872     set_winsock_errno ();
873
874   return res;
875 }
876
877 bool
878 fhandler_socket::prepare (HANDLE &event, long event_mask)
879 {
880   WSASetLastError (0);
881   closed (false);
882   if ((event = WSACreateEvent ()) == WSA_INVALID_EVENT)
883     {
884       debug_printf ("WSACreateEvent, %E");
885       return false;
886     }
887   if (WSAEventSelect (get_socket (), event, event_mask) == SOCKET_ERROR)
888     {
889       debug_printf ("WSAEventSelect, %E");
890       return false;
891     }
892   return true;
893 }
894
895 int
896 fhandler_socket::wait (HANDLE event, int flags)
897 {
898   int ret = SOCKET_ERROR;
899   int wsa_err = 0;
900   WSAEVENT ev[2] = { event, signal_arrived };
901   WSANETWORKEVENTS evts;
902
903   switch (WSAWaitForMultipleEvents (2, ev, FALSE, 10, FALSE))
904     {
905       case WSA_WAIT_TIMEOUT:
906         ret = 0;
907         break;
908       case WSA_WAIT_EVENT_0:
909         if (!WSAEnumNetworkEvents (get_socket (), event, &evts))
910           {
911             if (!evts.lNetworkEvents)
912               {
913                 ret = 0;
914                 break;
915               }
916             if (evts.lNetworkEvents & FD_OOB)
917               {
918                 if (evts.iErrorCode[FD_OOB_BIT])
919                   wsa_err = evts.iErrorCode[FD_OOB_BIT];
920                 else if (flags & MSG_OOB)
921                   ret = 0;
922                 else
923                   {
924                     raise (SIGURG);
925                     WSASetLastError (WSAEINTR);
926                     break;
927                   }
928               }
929             if (evts.lNetworkEvents & FD_READ)
930               {
931                 if (evts.iErrorCode[FD_READ_BIT])
932                   wsa_err = evts.iErrorCode[FD_READ_BIT];
933                 else
934                   ret = 0;
935               }
936             else if (evts.lNetworkEvents & FD_WRITE)
937               {
938                 if (evts.iErrorCode[FD_WRITE_BIT])
939                   wsa_err = evts.iErrorCode[FD_WRITE_BIT];
940                 else
941                   ret = 0;
942               }
943             if (evts.lNetworkEvents & FD_CLOSE)
944               {
945                 closed (true);
946                 if (!wsa_err)
947                   {
948                     if (evts.iErrorCode[FD_CLOSE_BIT])
949                       wsa_err = evts.iErrorCode[FD_CLOSE_BIT];
950                     else
951                       ret = 0;
952                   }
953               }
954             if (wsa_err)
955               WSASetLastError (wsa_err);
956           }
957         break;
958       case WSA_WAIT_EVENT_0 + 1:
959         WSASetLastError (WSAEINTR);
960         break;
961       default:
962         WSASetLastError (WSAEFAULT);
963         break;
964     }
965   return ret;
966 }
967
968 void
969 fhandler_socket::release (HANDLE event)
970 {
971   int last_err = WSAGetLastError ();
972   /* KB 168349: NT4 fails if the event parameter is not NULL. */
973   WSAEventSelect (get_socket (), NULL, 0);
974   WSACloseEvent (event);
975   unsigned long non_block = 0;
976   if (ioctlsocket (get_socket (), FIONBIO, &non_block))
977     debug_printf ("return to blocking failed: %d", WSAGetLastError ());
978   else
979     WSASetLastError (last_err);
980 }
981
982 int
983 fhandler_socket::readv (const struct iovec *const iov, const int iovcnt,
984                         ssize_t tot)
985 {
986   struct msghdr msg =
987     {
988       msg_name:         NULL,
989       msg_namelen:      0,
990       msg_iov:          (struct iovec *) iov, // const_cast
991       msg_iovlen:       iovcnt,
992       msg_accrights:    NULL,
993       msg_accrightslen: 0
994     };
995
996   return recvmsg (&msg, 0, tot);
997 }
998
999 int
1000 fhandler_socket::recvfrom (void *ptr, size_t len, int flags,
1001                            struct sockaddr *from, int *fromlen)
1002 {
1003   int res = SOCKET_ERROR;
1004   DWORD ret;
1005
1006   flags &= MSG_WINMASK;
1007   if (!winsock2_active)
1008     ret = res = ::recvfrom (get_socket (),
1009                             (char *) ptr, len, flags,
1010                             from, fromlen);
1011   else
1012     {
1013       WSABUF wsabuf = { len, (char *) ptr };
1014
1015       if (is_nonblocking () || closed () || async_io ())
1016         res = WSARecvFrom (get_socket (), &wsabuf, 1, (ret = 0, &ret),
1017                            (DWORD *) &flags, from, fromlen, NULL, NULL);
1018       else
1019         {
1020           HANDLE evt;
1021           if (prepare (evt, FD_CLOSE | FD_READ | (owner () ? FD_OOB : 0)))
1022             {
1023               do
1024                 {
1025                   DWORD lflags = (DWORD) flags;
1026                   res = WSARecvFrom (get_socket (), &wsabuf, 1, &ret, &lflags,
1027                                      from, fromlen, NULL, NULL);
1028                 }
1029               while (res == SOCKET_ERROR
1030                      && WSAGetLastError () == WSAEWOULDBLOCK
1031                      && !closed ()
1032                      && !(res = wait (evt, flags)));
1033               release (evt);
1034             }
1035         }
1036     }
1037
1038   if (res == SOCKET_ERROR)
1039     {
1040       /* According to SUSv3, errno isn't set in that case and no error
1041          condition is returned. */
1042       if (WSAGetLastError () == WSAEMSGSIZE)
1043         return len;
1044
1045       set_winsock_errno ();
1046     }
1047   else
1048     res = ret;
1049
1050   return res;
1051 }
1052
1053 int
1054 fhandler_socket::recvmsg (struct msghdr *msg, int flags, ssize_t tot)
1055 {
1056   if (get_addr_family () == AF_LOCAL)
1057     {
1058       /* On AF_LOCAL sockets the (fixed-size) name of the shared memory
1059          area used for descriptor passing is transmitted first.
1060          If this string is empty, no descriptors are passed and we can
1061          go ahead recv'ing the normal data blocks.  Otherwise start
1062          special handling for descriptor passing. */
1063       /*TODO*/
1064     }
1065
1066   struct iovec *const iov = msg->msg_iov;
1067   const int iovcnt = msg->msg_iovlen;
1068
1069   struct sockaddr *from = (struct sockaddr *) msg->msg_name;
1070   int *fromlen = from ? &msg->msg_namelen : NULL;
1071
1072   int res = SOCKET_ERROR;
1073
1074   if (!winsock2_active)
1075     {
1076       if (iovcnt == 1)
1077         res = recvfrom (iov->iov_base, iov->iov_len, flags, from, fromlen);
1078       else
1079         {
1080           if (tot == -1)        // i.e. if not pre-calculated by the caller.
1081             {
1082               tot = 0;
1083               const struct iovec *iovptr = iov + iovcnt;
1084               do
1085                 {
1086                   iovptr -= 1;
1087                   tot += iovptr->iov_len;
1088                 }
1089               while (iovptr != iov);
1090             }
1091
1092           char *buf = (char *) alloca (tot);
1093
1094           if (!buf)
1095             {
1096               set_errno (ENOMEM);
1097               res = SOCKET_ERROR;
1098             }
1099           else
1100             {
1101               res = recvfrom (buf, tot, flags, from, fromlen);
1102
1103               const struct iovec *iovptr = iov;
1104               int nbytes = res;
1105
1106               while (nbytes > 0)
1107                 {
1108                   const int frag = min (nbytes, (ssize_t) iovptr->iov_len);
1109                   memcpy (iovptr->iov_base, buf, frag);
1110                   buf += frag;
1111                   iovptr += 1;
1112                   nbytes -= frag;
1113                 }
1114             }
1115         }
1116     }
1117   else
1118     {
1119       WSABUF wsabuf[iovcnt];
1120       unsigned long len = 0L;
1121
1122       {
1123         const struct iovec *iovptr = iov + iovcnt;
1124         WSABUF *wsaptr = wsabuf + iovcnt;
1125         do
1126           {
1127             iovptr -= 1;
1128             wsaptr -= 1;
1129             len += wsaptr->len = iovptr->iov_len;
1130             wsaptr->buf = (char *) iovptr->iov_base;
1131           }
1132         while (wsaptr != wsabuf);
1133       }
1134
1135       DWORD ret;
1136
1137       if (is_nonblocking () || closed () || async_io ())
1138         res = WSARecvFrom (get_socket (), wsabuf, iovcnt, (ret = 0, &ret),
1139                            (DWORD *) &flags, from, fromlen, NULL, NULL);
1140       else
1141         {
1142           HANDLE evt;
1143           if (prepare (evt, FD_CLOSE | FD_READ | (owner () ? FD_OOB : 0)))
1144             {
1145               do
1146                 {
1147                   DWORD lflags = (DWORD) flags;
1148                   res = WSARecvFrom (get_socket (), wsabuf, iovcnt, &ret,
1149                                      &lflags, from, fromlen, NULL, NULL);
1150                 }
1151               while (res == SOCKET_ERROR
1152                      && WSAGetLastError () == WSAEWOULDBLOCK
1153                      && !closed ()
1154                      && !(res = wait (evt, flags)));
1155               release (evt);
1156             }
1157         }
1158
1159       if (res == SOCKET_ERROR)
1160         {
1161           /* According to SUSv3, errno isn't set in that case and no error
1162              condition is returned. */
1163           if (WSAGetLastError () == WSAEMSGSIZE)
1164             return len;
1165
1166           set_winsock_errno ();
1167         }
1168       else
1169         res = ret;
1170     }
1171
1172   return res;
1173 }
1174
1175 int
1176 fhandler_socket::writev (const struct iovec *const iov, const int iovcnt,
1177                          ssize_t tot)
1178 {
1179   struct msghdr msg =
1180     {
1181       msg_name:         NULL,
1182       msg_namelen:      0,
1183       msg_iov:          (struct iovec *) iov, // const_cast
1184       msg_iovlen:       iovcnt,
1185       msg_accrights:    NULL,
1186       msg_accrightslen: 0
1187     };
1188
1189   return sendmsg (&msg, 0, tot);
1190 }
1191
1192 int
1193 fhandler_socket::sendto (const void *ptr, size_t len, int flags,
1194                          const struct sockaddr *to, int tolen)
1195 {
1196   struct sockaddr_in sin;
1197
1198   if (to && !get_inet_addr (to, tolen, &sin, &tolen))
1199     return SOCKET_ERROR;
1200
1201   int res = SOCKET_ERROR;
1202   DWORD ret;
1203
1204   if (!winsock2_active)
1205     ret = res = ::sendto (get_socket (), (const char *) ptr, len,
1206                           flags & MSG_WINMASK,
1207                           (to ? (const struct sockaddr *) &sin : NULL), tolen);
1208   else
1209     {
1210       WSABUF wsabuf = { len, (char *) ptr };
1211
1212       if (is_nonblocking () || closed () || async_io ())
1213         res = WSASendTo (get_socket (), &wsabuf, 1, (ret = 0, &ret),
1214                          flags & MSG_WINMASK,
1215                          (to ? (const struct sockaddr *) &sin : NULL), tolen,
1216                          NULL, NULL);
1217       else
1218         {
1219           HANDLE evt;
1220           if (prepare (evt, FD_CLOSE | FD_WRITE | (owner () ? FD_OOB : 0)))
1221             {
1222               do
1223                 {
1224                   res = WSASendTo (get_socket (), &wsabuf, 1, &ret,
1225                                    flags & MSG_WINMASK,
1226                                    (to ? (const struct sockaddr *) &sin : NULL),
1227                                    tolen, NULL, NULL);
1228                 }
1229               while (res == SOCKET_ERROR
1230                      && WSAGetLastError () == WSAEWOULDBLOCK
1231                      && !(res = wait (evt, 0))
1232                      && !closed ());
1233               release (evt);
1234             }
1235         }
1236     }
1237
1238   if (res == SOCKET_ERROR)
1239     set_winsock_errno ();
1240   else
1241     res = ret;
1242
1243   /* Special handling for EPIPE and SIGPIPE.
1244
1245      EPIPE is generated if the local end has been shut down on a connection
1246      oriented socket.  In this case the process will also receive a SIGPIPE
1247      unless MSG_NOSIGNAL is set.  */
1248   if (res == SOCKET_ERROR && get_errno () == ESHUTDOWN
1249       && get_socket_type () == SOCK_STREAM)
1250     {
1251       set_errno (EPIPE);
1252       if (! (flags & MSG_NOSIGNAL))
1253         raise (SIGPIPE);
1254     }
1255
1256   return res;
1257 }
1258
1259 int
1260 fhandler_socket::sendmsg (const struct msghdr *msg, int flags, ssize_t tot)
1261 {
1262   if (get_addr_family () == AF_LOCAL)
1263     {
1264       /* For AF_LOCAL/AF_UNIX sockets, if descriptors are given, start
1265          the special handling for descriptor passing.  Otherwise just
1266          transmit an empty string to tell the receiver that no
1267          descriptor passing is done. */
1268       /*TODO*/
1269     }
1270
1271   struct iovec *const iov = msg->msg_iov;
1272   const int iovcnt = msg->msg_iovlen;
1273
1274   int res = SOCKET_ERROR;
1275
1276   if (!winsock2_active)
1277     {
1278       if (iovcnt == 1)
1279         res = sendto (iov->iov_base, iov->iov_len, flags,
1280                       (struct sockaddr *) msg->msg_name,
1281                       msg->msg_namelen);
1282       else
1283         {
1284           if (tot == -1)        // i.e. if not pre-calculated by the caller.
1285             {
1286               tot = 0;
1287               const struct iovec *iovptr = iov + iovcnt;
1288               do
1289                 {
1290                   iovptr -= 1;
1291                   tot += iovptr->iov_len;
1292                 }
1293               while (iovptr != iov);
1294             }
1295
1296           char *const buf = (char *) alloca (tot);
1297
1298           if (!buf)
1299             {
1300               set_errno (ENOMEM);
1301               res = SOCKET_ERROR;
1302             }
1303           else
1304             {
1305               char *bufptr = buf;
1306               const struct iovec *iovptr = iov;
1307               int nbytes = tot;
1308
1309               while (nbytes != 0)
1310                 {
1311                   const int frag = min (nbytes, (ssize_t) iovptr->iov_len);
1312                   memcpy (bufptr, iovptr->iov_base, frag);
1313                   bufptr += frag;
1314                   iovptr += 1;
1315                   nbytes -= frag;
1316                 }
1317
1318               res = sendto (buf, tot, flags,
1319                             (struct sockaddr *) msg->msg_name,
1320                             msg->msg_namelen);
1321             }
1322         }
1323     }
1324   else
1325     {
1326       WSABUF wsabuf[iovcnt];
1327
1328       {
1329         const struct iovec *iovptr = iov + iovcnt;
1330         WSABUF *wsaptr = wsabuf + iovcnt;
1331         do
1332           {
1333             iovptr -= 1;
1334             wsaptr -= 1;
1335             wsaptr->len = iovptr->iov_len;
1336             wsaptr->buf = (char *) iovptr->iov_base;
1337           }
1338         while (wsaptr != wsabuf);
1339       }
1340
1341       DWORD ret;
1342
1343       if (is_nonblocking () || closed () || async_io ())
1344         res = WSASendTo (get_socket (), wsabuf, iovcnt, (ret = 0, &ret),
1345                          flags, (struct sockaddr *) msg->msg_name,
1346                          msg->msg_namelen, NULL, NULL);
1347       else
1348         {
1349           HANDLE evt;
1350           if (prepare (evt, FD_CLOSE | FD_WRITE | (owner () ? FD_OOB : 0)))
1351             {
1352               do
1353                 {
1354                   res = WSASendTo (get_socket (), wsabuf, iovcnt,
1355                                    &ret, flags,
1356                                    (struct sockaddr *) msg->msg_name,
1357                                    msg->msg_namelen, NULL, NULL);
1358                 }
1359               while (res == SOCKET_ERROR
1360                      && WSAGetLastError () == WSAEWOULDBLOCK
1361                      && !(res = wait (evt, 0))
1362                      && !closed ());
1363               release (evt);
1364             }
1365         }
1366
1367       if (res == SOCKET_ERROR)
1368         set_winsock_errno ();
1369       else
1370         res = ret;
1371     }
1372
1373   /* Special handling for EPIPE and SIGPIPE.
1374
1375      EPIPE is generated if the local end has been shut down on a connection
1376      oriented socket.  In this case the process will also receive a SIGPIPE
1377      unless MSG_NOSIGNAL is set.  */
1378   if (res == SOCKET_ERROR && get_errno () == ESHUTDOWN
1379       && get_socket_type () == SOCK_STREAM)
1380     {
1381       set_errno (EPIPE);
1382       if (! (flags & MSG_NOSIGNAL))
1383         raise (SIGPIPE);
1384     }
1385
1386   return res;
1387 }
1388
1389 int
1390 fhandler_socket::shutdown (int how)
1391 {
1392   int res = ::shutdown (get_socket (), how);
1393
1394   if (res)
1395     set_winsock_errno ();
1396   else
1397     switch (how)
1398       {
1399       case SHUT_RD:
1400         saw_shutdown_read (true);
1401         break;
1402       case SHUT_WR:
1403         saw_shutdown_write (true);
1404         break;
1405       case SHUT_RDWR:
1406         saw_shutdown_read (true);
1407         saw_shutdown_write (true);
1408         break;
1409       }
1410   return res;
1411 }
1412
1413 int
1414 fhandler_socket::close ()
1415 {
1416   int res = 0;
1417
1418   /* HACK to allow a graceful shutdown even if shutdown() hasn't been
1419      called by the application. Note that this isn't the ultimate
1420      solution but it helps in many cases. */
1421   struct linger linger;
1422   linger.l_onoff = 1;
1423   linger.l_linger = 240; /* secs. default 2MSL value according to MSDN. */
1424   setsockopt (get_socket (), SOL_SOCKET, SO_LINGER,
1425               (const char *)&linger, sizeof linger);
1426
1427   while ((res = closesocket (get_socket ())) != 0)
1428     {
1429       if (WSAGetLastError () != WSAEWOULDBLOCK)
1430         {
1431           set_winsock_errno ();
1432           res = -1;
1433           break;
1434         }
1435       if (WaitForSingleObject (signal_arrived, 10) == WAIT_OBJECT_0)
1436         {
1437           set_errno (EINTR);
1438           res = -1;
1439           break;
1440         }
1441       WSASetLastError (0);
1442     }
1443
1444   debug_printf ("%d = fhandler_socket::close()", res);
1445   return res;
1446 }
1447
1448 int
1449 fhandler_socket::ioctl (unsigned int cmd, void *p)
1450 {
1451   extern int get_ifconf (struct ifconf *ifc, int what); /* net.cc */
1452   int res;
1453   struct ifconf ifc, *ifcp;
1454   struct ifreq *ifr, *ifrp;
1455
1456   switch (cmd)
1457     {
1458     case SIOCGIFCONF:
1459       ifcp = (struct ifconf *) p;
1460       if (!ifcp)
1461         {
1462           set_errno (EINVAL);
1463           return -1;
1464         }
1465       res = get_ifconf (ifcp, cmd);
1466       if (res)
1467         debug_printf ("error in get_ifconf");
1468       break;
1469     case SIOCGIFFLAGS:
1470       ifr = (struct ifreq *) p;
1471       if (ifr == 0)
1472         {
1473           set_errno (EINVAL);
1474           return -1;
1475         }
1476       ifr->ifr_flags = IFF_NOTRAILERS | IFF_UP | IFF_RUNNING;
1477       if (!strncmp(ifr->ifr_name, "lo", 2)
1478           || ntohl (((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr)
1479           == INADDR_LOOPBACK)
1480         ifr->ifr_flags |= IFF_LOOPBACK;
1481       else
1482         ifr->ifr_flags |= IFF_BROADCAST;
1483       res = 0;
1484       break;
1485     case SIOCGIFBRDADDR:
1486     case SIOCGIFNETMASK:
1487     case SIOCGIFADDR:
1488     case SIOCGIFHWADDR:
1489     case SIOCGIFMETRIC:
1490     case SIOCGIFMTU:
1491       {
1492         ifc.ifc_len = 2048;
1493         ifc.ifc_buf = (char *) alloca (2048);
1494
1495         ifr = (struct ifreq *) p;
1496         if (ifr == 0)
1497           {
1498             debug_printf ("ifr == NULL");
1499             set_errno (EINVAL);
1500             return -1;
1501           }
1502
1503         res = get_ifconf (&ifc, cmd);
1504         if (res)
1505           {
1506             debug_printf ("error in get_ifconf");
1507             break;
1508           }
1509
1510         debug_printf ("    name: %s", ifr->ifr_name);
1511         for (ifrp = ifc.ifc_req;
1512              (caddr_t) ifrp < ifc.ifc_buf + ifc.ifc_len;
1513              ++ifrp)
1514           {
1515             debug_printf ("testname: %s", ifrp->ifr_name);
1516             if (! strcmp (ifrp->ifr_name, ifr->ifr_name))
1517               {
1518                 switch (cmd)
1519                   {
1520                   case SIOCGIFADDR:
1521                     ifr->ifr_addr = ifrp->ifr_addr;
1522                     break;
1523                   case SIOCGIFBRDADDR:
1524                     ifr->ifr_broadaddr = ifrp->ifr_broadaddr;
1525                     break;
1526                   case SIOCGIFNETMASK:
1527                     ifr->ifr_netmask = ifrp->ifr_netmask;
1528                     break;
1529                   case SIOCGIFHWADDR:
1530                     ifr->ifr_hwaddr = ifrp->ifr_hwaddr;
1531                     break;
1532                   case SIOCGIFMETRIC:
1533                     ifr->ifr_metric = ifrp->ifr_metric;
1534                     break;
1535                   case SIOCGIFMTU:
1536                     ifr->ifr_mtu = ifrp->ifr_mtu;
1537                     break;
1538                   }
1539                 break;
1540               }
1541           }
1542         if ((caddr_t) ifrp >= ifc.ifc_buf + ifc.ifc_len)
1543           {
1544             set_errno (EINVAL);
1545             return -1;
1546           }
1547         break;
1548       }
1549     case FIOASYNC:
1550       res = WSAAsyncSelect (get_socket (), winmsg, WM_ASYNCIO,
1551               *(int *) p ? ASYNC_MASK : 0);
1552       syscall_printf ("Async I/O on socket %s",
1553               *(int *) p ? "started" : "cancelled");
1554       async_io (*(int *) p != 0);
1555       break;
1556     case FIONREAD:
1557       res = ioctlsocket (get_socket (), FIONREAD, (unsigned long *) p);
1558       if (res == SOCKET_ERROR)
1559         set_winsock_errno ();
1560       break;
1561     default:
1562       /* We must cancel WSAAsyncSelect (if any) before setting socket to
1563        * blocking mode
1564        */
1565       if (cmd == FIONBIO && async_io () && *(int *) p == 0)
1566         WSAAsyncSelect (get_socket (), winmsg, 0, 0);
1567       res = ioctlsocket (get_socket (), cmd, (unsigned long *) p);
1568       if (res == SOCKET_ERROR)
1569           set_winsock_errno ();
1570       if (cmd == FIONBIO)
1571         {
1572           syscall_printf ("socket is now %sblocking",
1573                             *(int *) p ? "non" : "");
1574           /* Start AsyncSelect if async socket unblocked */
1575           if (*(int *) p && async_io ())
1576             WSAAsyncSelect (get_socket (), winmsg, WM_ASYNCIO, ASYNC_MASK);
1577
1578           set_nonblocking (*(int *) p);
1579         }
1580       break;
1581     }
1582   syscall_printf ("%d = ioctl_socket (%x, %x)", res, cmd, p);
1583   return res;
1584 }
1585
1586 int
1587 fhandler_socket::fcntl (int cmd, void *arg)
1588 {
1589   int res = 0;
1590   int request, current;
1591
1592   switch (cmd)
1593     {
1594     case F_SETOWN:
1595       {
1596         /* Urgh!  Bad hack! */
1597         pid_t pid = (pid_t) arg;
1598         owner (pid == getpid ());
1599         debug_printf ("owner set to %d", owner ());
1600       }
1601       break;
1602     case F_SETFL:
1603       {
1604         /* Carefully test for the O_NONBLOCK or deprecated OLD_O_NDELAY flag.
1605            Set only the flag that has been passed in.  If both are set, just
1606            record O_NONBLOCK.   */
1607         int new_flags = (int) arg & O_NONBLOCK_MASK;
1608         if ((new_flags & OLD_O_NDELAY) && (new_flags & O_NONBLOCK))
1609           new_flags = O_NONBLOCK;
1610         current = get_flags () & O_NONBLOCK_MASK;
1611         request = new_flags ? 1 : 0;
1612         if (!!current != !!new_flags && (res = ioctl (FIONBIO, &request)))
1613           break;
1614         set_flags ((get_flags () & ~O_NONBLOCK_MASK) | new_flags);
1615         break;
1616       }
1617     default:
1618       res = fhandler_base::fcntl (cmd, arg);
1619       break;
1620     }
1621   return res;
1622 }
1623
1624 void
1625 fhandler_socket::set_close_on_exec (bool val)
1626 {
1627   if (!winsock2_active) /* < Winsock 2.0 */
1628     set_no_inheritance (get_handle (), val);
1629   close_on_exec (val);
1630   debug_printf ("set close_on_exec for %s to %d", get_name (), val);
1631 }
1632
1633 void
1634 fhandler_socket::set_sun_path (const char *path)
1635 {
1636   sun_path = path ? cstrdup (path) : NULL;
1637 }
1638
1639 int
1640 fhandler_socket::getpeereid (pid_t *pid, __uid32_t *euid, __gid32_t *egid)
1641 {
1642   if (get_addr_family () != AF_LOCAL || get_socket_type () != SOCK_STREAM)
1643     {
1644       set_errno (EINVAL);
1645       return -1;
1646     }
1647   if (connect_state () != connected)
1648     {
1649       set_errno (ENOTCONN);
1650       return -1;
1651     }
1652   if (sec_peer_pid == (pid_t) 0)
1653     {
1654       set_errno (ENOTCONN);     /* Usually when calling getpeereid on
1655                                    accepting (instead of accepted) socket. */
1656       return -1;
1657     }
1658
1659   if (!check_null_invalid_struct (pid))
1660     *pid = sec_peer_pid;
1661   if (!check_null_invalid_struct (euid))
1662     *euid = sec_peer_uid;
1663   if (!check_null_invalid_struct (egid))
1664     *egid = sec_peer_gid;
1665   return 0;
1666 }