]> sourceware.org Git - newlib-cygwin.git/blob - winsup/cygwin/fhandler_socket.cc
f780028010725a60bd9148201029f2794982376d
[newlib-cygwin.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, 2006, 2007, 2008,
4 2009, 2010, 2011, 2012 Red Hat, Inc.
5
6 This file is part of Cygwin.
7
8 This software is a copyrighted work licensed under the terms of the
9 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
10 details. */
11
12 /* #define DEBUG_NEST_ON 1 */
13
14 #define __INSIDE_CYGWIN_NET__
15
16 #include "winsup.h"
17 #include <sys/un.h>
18 #include <asm/byteorder.h>
19
20 #include <stdlib.h>
21 #define USE_SYS_TYPES_FD_SET
22 #include <winsock2.h>
23 #include <mswsock.h>
24 #include <iphlpapi.h>
25 #include "cygerrno.h"
26 #include "security.h"
27 #include "cygwin/version.h"
28 #include "perprocess.h"
29 #include "path.h"
30 #include "fhandler.h"
31 #include "dtable.h"
32 #include "cygheap.h"
33 #include "shared_info.h"
34 #include "sigproc.h"
35 #include "wininfo.h"
36 #include <unistd.h>
37 #include <sys/param.h>
38 #include <sys/acl.h>
39 #include "cygtls.h"
40 #include "cygwin/in6.h"
41 #include "ntdll.h"
42 #include "miscfuncs.h"
43
44 #define ASYNC_MASK (FD_READ|FD_WRITE|FD_OOB|FD_ACCEPT|FD_CONNECT)
45 #define EVENT_MASK (FD_READ|FD_WRITE|FD_OOB|FD_ACCEPT|FD_CONNECT|FD_CLOSE)
46
47 extern bool fdsock (cygheap_fdmanip& fd, const device *, SOCKET soc);
48 extern "C" {
49 int sscanf (const char *, const char *, ...);
50 } /* End of "C" section */
51
52 fhandler_dev_random* entropy_source;
53
54 static inline mode_t
55 adjust_socket_file_mode (mode_t mode)
56 {
57 /* Kludge: Don't allow to remove read bit on socket files for
58 user/group/other, if the accompanying write bit is set. It would
59 be nice to have exact permissions on a socket file, but it's
60 necessary that somebody able to access the socket can always read
61 the contents of the socket file to avoid spurious "permission
62 denied" messages. */
63 return mode | ((mode & (S_IWUSR | S_IWGRP | S_IWOTH)) << 1);
64 }
65
66 /* cygwin internal: map sockaddr into internet domain address */
67 int
68 get_inet_addr (const struct sockaddr *in, int inlen,
69 struct sockaddr_storage *out, int *outlen,
70 int *type = NULL, int *secret = NULL)
71 {
72 int secret_buf [4];
73 int* secret_ptr = (secret ? : secret_buf);
74
75 switch (in->sa_family)
76 {
77 case AF_LOCAL:
78 break;
79 case AF_INET:
80 case AF_INET6:
81 memcpy (out, in, inlen);
82 *outlen = inlen;
83 return 0;
84 default:
85 set_errno (EAFNOSUPPORT);
86 return SOCKET_ERROR;
87 }
88 /* AF_LOCAL/AF_UNIX only */
89 path_conv pc (in->sa_data, PC_SYM_FOLLOW);
90 if (pc.error)
91 {
92 set_errno (pc.error);
93 return SOCKET_ERROR;
94 }
95 if (!pc.exists ())
96 {
97 set_errno (ENOENT);
98 return SOCKET_ERROR;
99 }
100 /* Do NOT test for the file being a socket file here. The socket file
101 creation is not an atomic operation, so there is a chance that socket
102 files which are just in the process of being created are recognized
103 as non-socket files. To work around this problem we now create the
104 file with all sharing disabled. If the below NtOpenFile fails
105 with STATUS_SHARING_VIOLATION we know that the file already exists,
106 but the creating process isn't finished yet. So we yield and try
107 again, until we can either open the file successfully, or some error
108 other than STATUS_SHARING_VIOLATION occurs.
109 Since we now don't know if the file is actually a socket file, we
110 perform this check here explicitely. */
111 NTSTATUS status;
112 HANDLE fh;
113 OBJECT_ATTRIBUTES attr;
114 IO_STATUS_BLOCK io;
115
116 pc.get_object_attr (attr, sec_none_nih);
117 do
118 {
119 status = NtOpenFile (&fh, GENERIC_READ | SYNCHRONIZE, &attr, &io,
120 FILE_SHARE_VALID_FLAGS,
121 FILE_SYNCHRONOUS_IO_NONALERT
122 | FILE_OPEN_FOR_BACKUP_INTENT
123 | FILE_NON_DIRECTORY_FILE);
124 if (status == STATUS_SHARING_VIOLATION)
125 {
126 /* While we hope that the sharing violation is only temporary, we
127 also could easily get stuck here, waiting for a file in use by
128 some greedy Win32 application. Therefore we should never wait
129 endlessly without checking for signals and thread cancel event. */
130 pthread_testcancel ();
131 /* Using IsEventSignalled like this is racy since another thread could
132 be waiting for signal_arrived. */
133 if (IsEventSignalled (signal_arrived)
134 && !_my_tls.call_signal_handler ())
135 {
136 set_errno (EINTR);
137 return SOCKET_ERROR;
138 }
139 yield ();
140 }
141 else if (!NT_SUCCESS (status))
142 {
143 __seterrno_from_nt_status (status);
144 return SOCKET_ERROR;
145 }
146 }
147 while (status == STATUS_SHARING_VIOLATION);
148 /* Now test for the SYSTEM bit. */
149 FILE_BASIC_INFORMATION fbi;
150 status = NtQueryInformationFile (fh, &io, &fbi, sizeof fbi,
151 FileBasicInformation);
152 if (!NT_SUCCESS (status))
153 {
154 __seterrno_from_nt_status (status);
155 return SOCKET_ERROR;
156 }
157 if (!(fbi.FileAttributes & FILE_ATTRIBUTE_SYSTEM))
158 {
159 NtClose (fh);
160 set_errno (EBADF);
161 return SOCKET_ERROR;
162 }
163 /* Eventually check the content and fetch the required information. */
164 char buf[128];
165 memset (buf, 0, sizeof buf);
166 status = NtReadFile (fh, NULL, NULL, NULL, &io, buf, 128, NULL, NULL);
167 NtClose (fh);
168 if (NT_SUCCESS (status))
169 {
170 struct sockaddr_in sin;
171 char ctype;
172 sin.sin_family = AF_INET;
173 if (strncmp (buf, SOCKET_COOKIE, strlen (SOCKET_COOKIE)))
174 {
175 set_errno (EBADF);
176 return SOCKET_ERROR;
177 }
178 sscanf (buf + strlen (SOCKET_COOKIE), "%hu %c %08x-%08x-%08x-%08x",
179 &sin.sin_port,
180 &ctype,
181 secret_ptr, secret_ptr + 1, secret_ptr + 2, secret_ptr + 3);
182 sin.sin_port = htons (sin.sin_port);
183 sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
184 memcpy (out, &sin, sizeof sin);
185 *outlen = sizeof sin;
186 if (type)
187 *type = (ctype == 's' ? SOCK_STREAM :
188 ctype == 'd' ? SOCK_DGRAM
189 : 0);
190 return 0;
191 }
192 __seterrno_from_nt_status (status);
193 return SOCKET_ERROR;
194 }
195
196 /**********************************************************************/
197 /* fhandler_socket */
198
199 fhandler_socket::fhandler_socket () :
200 fhandler_base (),
201 wsock_events (NULL),
202 wsock_mtx (NULL),
203 wsock_evt (NULL),
204 prot_info_ptr (NULL),
205 sun_path (NULL),
206 peer_sun_path (NULL),
207 status ()
208 {
209 need_fork_fixup (true);
210 }
211
212 fhandler_socket::~fhandler_socket ()
213 {
214 if (prot_info_ptr)
215 cfree (prot_info_ptr);
216 if (sun_path)
217 cfree (sun_path);
218 if (peer_sun_path)
219 cfree (peer_sun_path);
220 }
221
222 char *
223 fhandler_socket::get_proc_fd_name (char *buf)
224 {
225 __small_sprintf (buf, "socket:[%d]", get_socket ());
226 return buf;
227 }
228
229 int
230 fhandler_socket::open (int flags, mode_t mode)
231 {
232 set_errno (ENXIO);
233 return 0;
234 }
235
236 void
237 fhandler_socket::af_local_set_sockpair_cred ()
238 {
239 sec_pid = sec_peer_pid = getpid ();
240 sec_uid = sec_peer_uid = geteuid32 ();
241 sec_gid = sec_peer_gid = getegid32 ();
242 }
243
244 void
245 fhandler_socket::af_local_setblocking (bool &async, bool &nonblocking)
246 {
247 async = async_io ();
248 nonblocking = is_nonblocking ();
249 if (async)
250 {
251 WSAAsyncSelect (get_socket (), winmsg, 0, 0);
252 WSAEventSelect (get_socket (), wsock_evt, EVENT_MASK);
253 }
254 set_nonblocking (false);
255 async_io (false);
256 }
257
258 void
259 fhandler_socket::af_local_unsetblocking (bool async, bool nonblocking)
260 {
261 if (nonblocking)
262 set_nonblocking (true);
263 if (async)
264 {
265 WSAAsyncSelect (get_socket (), winmsg, WM_ASYNCIO, ASYNC_MASK);
266 async_io (true);
267 }
268 }
269
270 bool
271 fhandler_socket::af_local_recv_secret ()
272 {
273 int out[4] = { 0, 0, 0, 0 };
274 int rest = sizeof out;
275 char *ptr = (char *) out;
276 while (rest > 0)
277 {
278 int ret = recvfrom (ptr, rest, 0, NULL, NULL);
279 if (ret <= 0)
280 break;
281 rest -= ret;
282 ptr += ret;
283 }
284 if (rest == 0)
285 {
286 debug_printf ("Received af_local secret: %08x-%08x-%08x-%08x",
287 out[0], out[1], out[2], out[3]);
288 if (out[0] != connect_secret[0] || out[1] != connect_secret[1]
289 || out[2] != connect_secret[2] || out[3] != connect_secret[3])
290 {
291 debug_printf ("Receiving af_local secret mismatch");
292 return false;
293 }
294 }
295 else
296 debug_printf ("Receiving af_local secret failed");
297 return rest == 0;
298 }
299
300 bool
301 fhandler_socket::af_local_send_secret ()
302 {
303 int rest = sizeof connect_secret;
304 char *ptr = (char *) connect_secret;
305 while (rest > 0)
306 {
307 int ret = sendto (ptr, rest, 0, NULL, 0);
308 if (ret <= 0)
309 break;
310 rest -= ret;
311 ptr += ret;
312 }
313 debug_printf ("Sending af_local secret %s", rest == 0 ? "succeeded"
314 : "failed");
315 return rest == 0;
316 }
317
318 bool
319 fhandler_socket::af_local_recv_cred ()
320 {
321 struct ucred out = { (pid_t) 0, (__uid32_t) -1, (__gid32_t) -1 };
322 int rest = sizeof out;
323 char *ptr = (char *) &out;
324 while (rest > 0)
325 {
326 int ret = recvfrom (ptr, rest, 0, NULL, NULL);
327 if (ret <= 0)
328 break;
329 rest -= ret;
330 ptr += ret;
331 }
332 if (rest == 0)
333 {
334 debug_printf ("Received eid credentials: pid: %d, uid: %d, gid: %d",
335 out.pid, out.uid, out.gid);
336 sec_peer_pid = out.pid;
337 sec_peer_uid = out.uid;
338 sec_peer_gid = out.gid;
339 }
340 else
341 debug_printf ("Receiving eid credentials failed");
342 return rest == 0;
343 }
344
345 bool
346 fhandler_socket::af_local_send_cred ()
347 {
348 struct ucred in = { sec_pid, sec_uid, sec_gid };
349 int rest = sizeof in;
350 char *ptr = (char *) &in;
351 while (rest > 0)
352 {
353 int ret = sendto (ptr, rest, 0, NULL, 0);
354 if (ret <= 0)
355 break;
356 rest -= ret;
357 ptr += ret;
358 }
359 if (rest == 0)
360 debug_printf ("Sending eid credentials succeeded");
361 else
362 debug_printf ("Sending eid credentials failed");
363 return rest == 0;
364 }
365
366 int
367 fhandler_socket::af_local_connect ()
368 {
369 /* This keeps the test out of select. */
370 if (get_addr_family () != AF_LOCAL || get_socket_type () != SOCK_STREAM)
371 return 0;
372
373 debug_printf ("af_local_connect called");
374 bool orig_async_io, orig_is_nonblocking;
375 af_local_setblocking (orig_async_io, orig_is_nonblocking);
376 if (!af_local_send_secret () || !af_local_recv_secret ()
377 || !af_local_send_cred () || !af_local_recv_cred ())
378 {
379 debug_printf ("accept from unauthorized server");
380 ::shutdown (get_socket (), SD_BOTH);
381 WSASetLastError (WSAECONNREFUSED);
382 return -1;
383 }
384 af_local_unsetblocking (orig_async_io, orig_is_nonblocking);
385 return 0;
386 }
387
388 int
389 fhandler_socket::af_local_accept ()
390 {
391 debug_printf ("af_local_accept called");
392 bool orig_async_io, orig_is_nonblocking;
393 af_local_setblocking (orig_async_io, orig_is_nonblocking);
394 if (!af_local_recv_secret () || !af_local_send_secret ()
395 || !af_local_recv_cred () || !af_local_send_cred ())
396 {
397 debug_printf ("connect from unauthorized client");
398 ::shutdown (get_socket (), SD_BOTH);
399 ::closesocket (get_socket ());
400 WSASetLastError (WSAECONNABORTED);
401 return -1;
402 }
403 af_local_unsetblocking (orig_async_io, orig_is_nonblocking);
404 return 0;
405 }
406
407 void
408 fhandler_socket::af_local_set_cred ()
409 {
410 sec_pid = getpid ();
411 sec_uid = geteuid32 ();
412 sec_gid = getegid32 ();
413 sec_peer_pid = (pid_t) 0;
414 sec_peer_uid = (__uid32_t) -1;
415 sec_peer_gid = (__gid32_t) -1;
416 }
417
418 void
419 fhandler_socket::af_local_copy (fhandler_socket *sock)
420 {
421 sock->connect_secret[0] = connect_secret[0];
422 sock->connect_secret[1] = connect_secret[1];
423 sock->connect_secret[2] = connect_secret[2];
424 sock->connect_secret[3] = connect_secret[3];
425 sock->sec_pid = sec_pid;
426 sock->sec_uid = sec_uid;
427 sock->sec_gid = sec_gid;
428 sock->sec_peer_pid = sec_peer_pid;
429 sock->sec_peer_uid = sec_peer_uid;
430 sock->sec_peer_gid = sec_peer_gid;
431 }
432
433 void
434 fhandler_socket::af_local_set_secret (char *buf)
435 {
436 if (!entropy_source)
437 {
438 void *buf = malloc (sizeof (fhandler_dev_random));
439 entropy_source = new (buf) fhandler_dev_random ();
440 entropy_source->dev () = *urandom_dev;
441 }
442 if (entropy_source &&
443 !entropy_source->open (O_RDONLY))
444 {
445 delete entropy_source;
446 entropy_source = NULL;
447 }
448 if (entropy_source)
449 {
450 size_t len = sizeof (connect_secret);
451 entropy_source->read (connect_secret, len);
452 if (len != sizeof (connect_secret))
453 bzero ((char*) connect_secret, sizeof (connect_secret));
454 }
455 __small_sprintf (buf, "%08x-%08x-%08x-%08x",
456 connect_secret [0], connect_secret [1],
457 connect_secret [2], connect_secret [3]);
458 }
459
460 /* Maximum number of concurrently opened sockets from all Cygwin processes
461 per session. Note that shared sockets (through dup/fork/exec) are
462 counted as one socket. */
463 #define NUM_SOCKS (32768 / sizeof (wsa_event))
464
465 #define LOCK_EVENTS WaitForSingleObject (wsock_mtx, INFINITE)
466 #define UNLOCK_EVENTS ReleaseMutex (wsock_mtx)
467
468 static wsa_event wsa_events[NUM_SOCKS] __attribute__((section (".cygwin_dll_common"), shared));
469
470 static LONG socket_serial_number __attribute__((section (".cygwin_dll_common"), shared));
471
472 static HANDLE wsa_slot_mtx;
473
474 static PWCHAR
475 sock_shared_name (PWCHAR buf, LONG num)
476 {
477 __small_swprintf (buf, L"socket.%d", num);
478 return buf;
479 }
480
481 static wsa_event *
482 search_wsa_event_slot (LONG new_serial_number)
483 {
484 WCHAR name[32], searchname[32];
485 UNICODE_STRING uname;
486 OBJECT_ATTRIBUTES attr;
487 NTSTATUS status;
488
489 if (!wsa_slot_mtx)
490 {
491 RtlInitUnicodeString (&uname, sock_shared_name (name, 0));
492 InitializeObjectAttributes (&attr, &uname, OBJ_INHERIT | OBJ_OPENIF,
493 get_session_parent_dir (),
494 everyone_sd (CYG_MUTANT_ACCESS));
495 status = NtCreateMutant (&wsa_slot_mtx, CYG_MUTANT_ACCESS, &attr, FALSE);
496 if (!NT_SUCCESS (status))
497 api_fatal ("Couldn't create/open shared socket mutex %S, %p",
498 &uname, status);
499 }
500 switch (WaitForSingleObject (wsa_slot_mtx, INFINITE))
501 {
502 case WAIT_OBJECT_0:
503 case WAIT_ABANDONED:
504 break;
505 default:
506 api_fatal ("WFSO failed for shared socket mutex, %E");
507 break;
508 }
509 unsigned int slot = new_serial_number % NUM_SOCKS;
510 while (wsa_events[slot].serial_number)
511 {
512 HANDLE searchmtx;
513 RtlInitUnicodeString (&uname, sock_shared_name (searchname,
514 wsa_events[slot].serial_number));
515 InitializeObjectAttributes (&attr, &uname, 0, get_session_parent_dir (),
516 NULL);
517 status = NtOpenMutant (&searchmtx, READ_CONTROL, &attr);
518 if (!NT_SUCCESS (status))
519 break;
520 /* Mutex still exists, attached socket is active, try next slot. */
521 NtClose (searchmtx);
522 slot = (slot + 1) % NUM_SOCKS;
523 if (slot == (new_serial_number % NUM_SOCKS))
524 {
525 /* Did the whole array once. Too bad. */
526 debug_printf ("No free socket slot");
527 ReleaseMutex (wsa_slot_mtx);
528 return NULL;
529 }
530 }
531 memset (&wsa_events[slot], 0, sizeof (wsa_event));
532 wsa_events[slot].serial_number = new_serial_number;
533 ReleaseMutex (wsa_slot_mtx);
534 return wsa_events + slot;
535 }
536
537 bool
538 fhandler_socket::init_events ()
539 {
540 LONG new_serial_number;
541 WCHAR name[32];
542 UNICODE_STRING uname;
543 OBJECT_ATTRIBUTES attr;
544 NTSTATUS status;
545
546 do
547 {
548 new_serial_number =
549 InterlockedIncrement (&socket_serial_number);
550 if (!new_serial_number) /* 0 is reserved for global mutex */
551 InterlockedIncrement (&socket_serial_number);
552 RtlInitUnicodeString (&uname, sock_shared_name (name, new_serial_number));
553 InitializeObjectAttributes (&attr, &uname, OBJ_INHERIT | OBJ_OPENIF,
554 get_session_parent_dir (),
555 everyone_sd (CYG_MUTANT_ACCESS));
556 status = NtCreateMutant (&wsock_mtx, CYG_MUTANT_ACCESS, &attr, FALSE);
557 if (!NT_SUCCESS (status))
558 {
559 debug_printf ("NtCreateMutant(%S), %p", &uname, status);
560 set_errno (ENOBUFS);
561 return false;
562 }
563 if (status == STATUS_OBJECT_NAME_EXISTS)
564 NtClose (wsock_mtx);
565 }
566 while (status == STATUS_OBJECT_NAME_EXISTS);
567 if ((wsock_evt = CreateEvent (&sec_all, TRUE, FALSE, NULL))
568 == WSA_INVALID_EVENT)
569 {
570 debug_printf ("CreateEvent, %E");
571 set_errno (ENOBUFS);
572 NtClose (wsock_mtx);
573 return false;
574 }
575 if (WSAEventSelect (get_socket (), wsock_evt, EVENT_MASK) == SOCKET_ERROR)
576 {
577 debug_printf ("WSAEventSelect, %E");
578 set_winsock_errno ();
579 NtClose (wsock_evt);
580 NtClose (wsock_mtx);
581 return false;
582 }
583 wsock_events = search_wsa_event_slot (new_serial_number);
584 /* sock type not yet set here. */
585 if (pc.dev == FH_UDP || pc.dev == FH_DGRAM)
586 wsock_events->events = FD_WRITE;
587 return true;
588 }
589
590 int
591 fhandler_socket::evaluate_events (const long event_mask, long &events,
592 const bool erase)
593 {
594 int ret = 0;
595 long events_now = 0;
596
597 WSANETWORKEVENTS evts = { 0 };
598 if (!(WSAEnumNetworkEvents (get_socket (), wsock_evt, &evts)))
599 {
600 if (evts.lNetworkEvents)
601 {
602 LOCK_EVENTS;
603 wsock_events->events |= evts.lNetworkEvents;
604 events_now = (wsock_events->events & event_mask);
605 if (evts.lNetworkEvents & FD_CONNECT)
606 wsock_events->connect_errorcode = evts.iErrorCode[FD_CONNECT_BIT];
607 UNLOCK_EVENTS;
608 if ((evts.lNetworkEvents & FD_OOB) && wsock_events->owner)
609 kill (wsock_events->owner, SIGURG);
610 }
611 }
612
613 LOCK_EVENTS;
614 if ((events = events_now) != 0
615 || (events = (wsock_events->events & event_mask)) != 0)
616 {
617 if (events & FD_CONNECT)
618 {
619 int wsa_err = 0;
620 if ((wsa_err = wsock_events->connect_errorcode) != 0)
621 {
622 WSASetLastError (wsa_err);
623 ret = SOCKET_ERROR;
624 }
625 else
626 wsock_events->events |= FD_WRITE;
627 wsock_events->events &= ~FD_CONNECT;
628 wsock_events->connect_errorcode = 0;
629 }
630 /* This test makes the accept function behave as on Linux when
631 accept is called on a socket for which shutdown for the read side
632 has been called. The second half of this code is in the shutdown
633 method. See there for more info. */
634 if ((event_mask & FD_ACCEPT) && (events & FD_CLOSE))
635 {
636 WSASetLastError (WSAEINVAL);
637 ret = SOCKET_ERROR;
638 }
639 if (erase)
640 wsock_events->events &= ~(events & ~(FD_WRITE | FD_CLOSE));
641 }
642 UNLOCK_EVENTS;
643
644 return ret;
645 }
646
647 int
648 fhandler_socket::wait_for_events (const long event_mask, const DWORD flags)
649 {
650 if (async_io ())
651 return 0;
652
653 int ret;
654 long events;
655
656 while (!(ret = evaluate_events (event_mask, events, !(flags & MSG_PEEK)))
657 && !events)
658 {
659 if (is_nonblocking () || (flags & MSG_DONTWAIT))
660 {
661 WSASetLastError (WSAEWOULDBLOCK);
662 return SOCKET_ERROR;
663 }
664
665 WSAEVENT ev[2] = { wsock_evt, signal_arrived };
666 switch (WSAWaitForMultipleEvents (2, ev, FALSE, 50, FALSE))
667 {
668 case WSA_WAIT_TIMEOUT:
669 pthread_testcancel ();
670 /*FALLTHRU*/
671 case WSA_WAIT_EVENT_0:
672 break;
673
674 case WSA_WAIT_EVENT_0 + 1:
675 if (_my_tls.call_signal_handler ())
676 break;
677 WSASetLastError (WSAEINTR);
678 return SOCKET_ERROR;
679
680 default:
681 WSASetLastError (WSAEFAULT);
682 return SOCKET_ERROR;
683 }
684 }
685
686 return ret;
687 }
688
689 void
690 fhandler_socket::release_events ()
691 {
692 NtClose (wsock_evt);
693 NtClose (wsock_mtx);
694 }
695
696 /* Called from net.cc:fdsock() if a freshly created socket is not
697 inheritable. In that case we use fixup_before_fork_exec. See
698 the comment in fdsock() for a description of the problem. */
699 void
700 fhandler_socket::init_fixup_before ()
701 {
702 prot_info_ptr = (LPWSAPROTOCOL_INFOW)
703 cmalloc_abort (HEAP_BUF, sizeof (WSAPROTOCOL_INFOW));
704 cygheap->fdtab.inc_need_fixup_before ();
705 }
706
707 int
708 fhandler_socket::fixup_before_fork_exec (DWORD win_pid)
709 {
710 SOCKET ret = WSADuplicateSocketW (get_socket (), win_pid, prot_info_ptr);
711 if (ret)
712 set_winsock_errno ();
713 else
714 debug_printf ("WSADuplicateSocket succeeded (%lx)", prot_info_ptr->dwProviderReserved);
715 return (int) ret;
716 }
717
718 void
719 fhandler_socket::fixup_after_fork (HANDLE parent)
720 {
721 fork_fixup (parent, wsock_mtx, "wsock_mtx");
722 fork_fixup (parent, wsock_evt, "wsock_evt");
723
724 if (!need_fixup_before ())
725 {
726 fhandler_base::fixup_after_fork (parent);
727 return;
728 }
729
730 SOCKET new_sock = WSASocketW (FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO,
731 FROM_PROTOCOL_INFO, prot_info_ptr, 0,
732 WSA_FLAG_OVERLAPPED);
733 if (new_sock == INVALID_SOCKET)
734 {
735 set_winsock_errno ();
736 set_io_handle ((HANDLE) INVALID_SOCKET);
737 }
738 else
739 {
740 /* Even though the original socket was not inheritable, the duplicated
741 socket is potentially inheritable again. */
742 SetHandleInformation ((HANDLE) new_sock, HANDLE_FLAG_INHERIT, 0);
743 set_io_handle ((HANDLE) new_sock);
744 debug_printf ("WSASocket succeeded (%lx)", new_sock);
745 }
746 }
747
748 void
749 fhandler_socket::fixup_after_exec ()
750 {
751 if (need_fixup_before () && !close_on_exec ())
752 fixup_after_fork (NULL);
753 }
754
755 int
756 fhandler_socket::dup (fhandler_base *child, int flags)
757 {
758 debug_printf ("here");
759 fhandler_socket *fhs = (fhandler_socket *) child;
760
761 if (!DuplicateHandle (GetCurrentProcess (), wsock_mtx,
762 GetCurrentProcess (), &fhs->wsock_mtx,
763 0, TRUE, DUPLICATE_SAME_ACCESS))
764 {
765 __seterrno ();
766 return -1;
767 }
768 if (!DuplicateHandle (GetCurrentProcess (), wsock_evt,
769 GetCurrentProcess (), &fhs->wsock_evt,
770 0, TRUE, DUPLICATE_SAME_ACCESS))
771 {
772 __seterrno ();
773 NtClose (fhs->wsock_mtx);
774 return -1;
775 }
776 if (get_addr_family () == AF_LOCAL)
777 {
778 fhs->set_sun_path (get_sun_path ());
779 fhs->set_peer_sun_path (get_peer_sun_path ());
780 }
781 if (!need_fixup_before ())
782 {
783 int ret = fhandler_base::dup (child, flags);
784 if (ret)
785 {
786 NtClose (fhs->wsock_evt);
787 NtClose (fhs->wsock_mtx);
788 }
789 return ret;
790 }
791
792 cygheap->user.deimpersonate ();
793 fhs->init_fixup_before ();
794 fhs->set_io_handle (get_io_handle ());
795 int ret = fhs->fixup_before_fork_exec (GetCurrentProcessId ());
796 cygheap->user.reimpersonate ();
797 if (!ret)
798 {
799 fhs->fixup_after_fork (GetCurrentProcess ());
800 if (fhs->get_io_handle() != (HANDLE) INVALID_SOCKET)
801 return 0;
802 }
803 cygheap->fdtab.dec_need_fixup_before ();
804 NtClose (fhs->wsock_evt);
805 NtClose (fhs->wsock_mtx);
806 return -1;
807 }
808
809 int __stdcall
810 fhandler_socket::fstat (struct __stat64 *buf)
811 {
812 int res;
813 if (get_device () == FH_UNIX)
814 {
815 res = fhandler_base::fstat_fs (buf);
816 if (!res)
817 {
818 buf->st_mode = (buf->st_mode & ~S_IFMT) | S_IFSOCK;
819 buf->st_size = 0;
820 }
821 }
822 else
823 {
824 res = fhandler_base::fstat (buf);
825 if (!res)
826 {
827 buf->st_dev = 0;
828 buf->st_ino = (__ino64_t) ((DWORD) get_handle ());
829 buf->st_mode = S_IFSOCK | S_IRWXU | S_IRWXG | S_IRWXO;
830 buf->st_size = 0;
831 }
832 }
833 return res;
834 }
835
836 int __stdcall
837 fhandler_socket::fstatvfs (struct statvfs *sfs)
838 {
839 if (get_device () == FH_UNIX)
840 {
841 fhandler_disk_file fh (pc);
842 fh.get_device () = FH_FS;
843 return fh.fstatvfs (sfs);
844 }
845 set_errno (EBADF);
846 return -1;
847 }
848
849 int
850 fhandler_socket::fchmod (mode_t mode)
851 {
852 if (get_device () == FH_UNIX)
853 {
854 fhandler_disk_file fh (pc);
855 fh.get_device () = FH_FS;
856 int ret = fh.fchmod (S_IFSOCK | adjust_socket_file_mode (mode));
857 return ret;
858 }
859 set_errno (EBADF);
860 return -1;
861 }
862
863 int
864 fhandler_socket::fchown (__uid32_t uid, __gid32_t gid)
865 {
866 if (get_device () == FH_UNIX)
867 {
868 fhandler_disk_file fh (pc);
869 return fh.fchown (uid, gid);
870 }
871 set_errno (EBADF);
872 return -1;
873 }
874
875 int
876 fhandler_socket::facl (int cmd, int nentries, __aclent32_t *aclbufp)
877 {
878 if (get_device () == FH_UNIX)
879 {
880 fhandler_disk_file fh (pc);
881 return fh.facl (cmd, nentries, aclbufp);
882 }
883 set_errno (EBADF);
884 return -1;
885 }
886
887 int
888 fhandler_socket::link (const char *newpath)
889 {
890 if (get_device () == FH_UNIX)
891 {
892 fhandler_disk_file fh (pc);
893 return fh.link (newpath);
894 }
895 return fhandler_base::link (newpath);
896 }
897
898 int
899 fhandler_socket::bind (const struct sockaddr *name, int namelen)
900 {
901 int res = -1;
902
903 if (name->sa_family == AF_LOCAL)
904 {
905 #define un_addr ((struct sockaddr_un *) name)
906 struct sockaddr_in sin;
907 int len = sizeof sin;
908
909 if (strlen (un_addr->sun_path) >= UNIX_PATH_LEN)
910 {
911 set_errno (ENAMETOOLONG);
912 goto out;
913 }
914 sin.sin_family = AF_INET;
915 sin.sin_port = 0;
916 sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
917 if (::bind (get_socket (), (sockaddr *) &sin, len))
918 {
919 syscall_printf ("AF_LOCAL: bind failed");
920 set_winsock_errno ();
921 goto out;
922 }
923 if (::getsockname (get_socket (), (sockaddr *) &sin, &len))
924 {
925 syscall_printf ("AF_LOCAL: getsockname failed");
926 set_winsock_errno ();
927 goto out;
928 }
929
930 sin.sin_port = ntohs (sin.sin_port);
931 debug_printf ("AF_LOCAL: socket bound to port %u", sin.sin_port);
932
933 path_conv pc (un_addr->sun_path, PC_SYM_FOLLOW);
934 if (pc.error)
935 {
936 set_errno (pc.error);
937 goto out;
938 }
939 if (pc.exists ())
940 {
941 set_errno (EADDRINUSE);
942 goto out;
943 }
944 mode_t mode = adjust_socket_file_mode ((S_IRWXU | S_IRWXG | S_IRWXO)
945 & ~cygheap->umask);
946 DWORD fattr = FILE_ATTRIBUTE_SYSTEM;
947 if (!(mode & (S_IWUSR | S_IWGRP | S_IWOTH)) && !pc.has_acls ())
948 fattr |= FILE_ATTRIBUTE_READONLY;
949 SECURITY_ATTRIBUTES sa = sec_none_nih;
950 NTSTATUS status;
951 HANDLE fh;
952 OBJECT_ATTRIBUTES attr;
953 IO_STATUS_BLOCK io;
954 ULONG access = DELETE | FILE_GENERIC_WRITE;
955
956 /* If the filesystem supports ACLs, we will overwrite the DACL after the
957 call to NtCreateFile. This requires a handle with READ_CONTROL and
958 WRITE_DAC access, otherwise get_file_sd and set_file_sd both have to
959 open the file again.
960 FIXME: On remote NTFS shares open sometimes fails because even the
961 creator of the file doesn't have the right to change the DACL.
962 I don't know what setting that is or how to recognize such a share,
963 so for now we don't request WRITE_DAC on remote drives. */
964 if (pc.has_acls () && !pc.isremote ())
965 access |= READ_CONTROL | WRITE_DAC;
966
967 status = NtCreateFile (&fh, access, pc.get_object_attr (attr, sa), &io,
968 NULL, fattr, 0, FILE_CREATE,
969 FILE_NON_DIRECTORY_FILE
970 | FILE_SYNCHRONOUS_IO_NONALERT
971 | FILE_OPEN_FOR_BACKUP_INTENT,
972 NULL, 0);
973 if (!NT_SUCCESS (status))
974 {
975 if (io.Information == FILE_EXISTS)
976 set_errno (EADDRINUSE);
977 else
978 __seterrno_from_nt_status (status);
979 }
980 else
981 {
982 if (pc.has_acls ())
983 set_file_attribute (fh, pc, ILLEGAL_UID, ILLEGAL_GID,
984 S_JUSTCREATED | mode);
985 char buf[sizeof (SOCKET_COOKIE) + 80];
986 __small_sprintf (buf, "%s%u %c ", SOCKET_COOKIE, sin.sin_port,
987 get_socket_type () == SOCK_STREAM ? 's'
988 : get_socket_type () == SOCK_DGRAM ? 'd' : '-');
989 af_local_set_secret (strchr (buf, '\0'));
990 DWORD blen = strlen (buf) + 1;
991 status = NtWriteFile (fh, NULL, NULL, NULL, &io, buf, blen, NULL, 0);
992 if (!NT_SUCCESS (status))
993 {
994 __seterrno_from_nt_status (status);
995 FILE_DISPOSITION_INFORMATION fdi = { TRUE };
996 status = NtSetInformationFile (fh, &io, &fdi, sizeof fdi,
997 FileDispositionInformation);
998 if (!NT_SUCCESS (status))
999 debug_printf ("Setting delete dispostion failed, status = %p",
1000 status);
1001 }
1002 else
1003 {
1004 set_sun_path (un_addr->sun_path);
1005 res = 0;
1006 }
1007 NtClose (fh);
1008 }
1009 #undef un_addr
1010 }
1011 else
1012 {
1013 if (!saw_reuseaddr ())
1014 {
1015 /* If the application didn't explicitely request SO_REUSEADDR,
1016 enforce POSIX standard socket binding behaviour by setting the
1017 SO_EXCLUSIVEADDRUSE socket option. See cygwin_setsockopt()
1018 for a more detailed description.
1019
1020 KB 870562: Note that a bug in Win2K SP1-3 and XP up to SP1 only
1021 enables this option for users in the local administrators group. */
1022 int on = 1;
1023 int ret = ::setsockopt (get_socket (), SOL_SOCKET,
1024 ~(SO_REUSEADDR),
1025 (const char *) &on, sizeof on);
1026 debug_printf ("%d = setsockopt(SO_EXCLUSIVEADDRUSE), %E", ret);
1027 }
1028 if (::bind (get_socket (), name, namelen))
1029 set_winsock_errno ();
1030 else
1031 res = 0;
1032 }
1033
1034 out:
1035 return res;
1036 }
1037
1038 int
1039 fhandler_socket::connect (const struct sockaddr *name, int namelen)
1040 {
1041 bool in_progress = false;
1042 struct sockaddr_storage sst;
1043 DWORD err;
1044 int type;
1045
1046 pthread_testcancel ();
1047
1048 if (get_inet_addr (name, namelen, &sst, &namelen, &type, connect_secret)
1049 == SOCKET_ERROR)
1050 return SOCKET_ERROR;
1051
1052 if (get_addr_family () == AF_LOCAL && get_socket_type () != type)
1053 {
1054 WSASetLastError (WSAEPROTOTYPE);
1055 set_winsock_errno ();
1056 return SOCKET_ERROR;
1057 }
1058
1059 int res = ::connect (get_socket (), (struct sockaddr *) &sst, namelen);
1060 if (!is_nonblocking ()
1061 && res == SOCKET_ERROR
1062 && WSAGetLastError () == WSAEWOULDBLOCK)
1063 res = wait_for_events (FD_CONNECT | FD_CLOSE, 0);
1064
1065 if (!res)
1066 err = 0;
1067 else
1068 {
1069 err = WSAGetLastError ();
1070 /* Special handling for connect to return the correct error code
1071 when called on a non-blocking socket. */
1072 if (is_nonblocking ())
1073 {
1074 if (err == WSAEWOULDBLOCK || err == WSAEALREADY)
1075 in_progress = true;
1076
1077 if (err == WSAEWOULDBLOCK)
1078 WSASetLastError (err = WSAEINPROGRESS);
1079 }
1080 if (err == WSAEINVAL)
1081 WSASetLastError (err = WSAEISCONN);
1082 set_winsock_errno ();
1083 }
1084
1085 if (get_addr_family () == AF_LOCAL && (!res || in_progress))
1086 set_peer_sun_path (name->sa_data);
1087
1088 if (get_addr_family () == AF_LOCAL && get_socket_type () == SOCK_STREAM)
1089 {
1090 af_local_set_cred (); /* Don't move into af_local_connect since
1091 af_local_connect is called from select,
1092 possibly running under another identity. */
1093 if (!res && af_local_connect ())
1094 {
1095 set_winsock_errno ();
1096 return SOCKET_ERROR;
1097 }
1098 }
1099
1100 if (err == WSAEINPROGRESS || err == WSAEALREADY)
1101 connect_state (connect_pending);
1102 else if (err)
1103 connect_state (connect_failed);
1104 else
1105 connect_state (connected);
1106
1107 return res;
1108 }
1109
1110 int
1111 fhandler_socket::listen (int backlog)
1112 {
1113 int res = ::listen (get_socket (), backlog);
1114 if (res && WSAGetLastError () == WSAEINVAL)
1115 {
1116 /* It's perfectly valid to call listen on an unbound INET socket.
1117 In this case the socket is automatically bound to an unused
1118 port number, listening on all interfaces. On WinSock, listen
1119 fails with WSAEINVAL when it's called on an unbound socket.
1120 So we have to bind manually here to have POSIX semantics. */
1121 if (get_addr_family () == AF_INET)
1122 {
1123 struct sockaddr_in sin;
1124 sin.sin_family = AF_INET;
1125 sin.sin_port = 0;
1126 sin.sin_addr.s_addr = INADDR_ANY;
1127 if (!::bind (get_socket (), (struct sockaddr *) &sin, sizeof sin))
1128 res = ::listen (get_socket (), backlog);
1129 }
1130 else if (get_addr_family () == AF_INET6)
1131 {
1132 struct sockaddr_in6 sin6 =
1133 {
1134 sin6_family: AF_INET6,
1135 sin6_port: 0,
1136 sin6_flowinfo: 0,
1137 sin6_addr: {{IN6ADDR_ANY_INIT}},
1138 sin6_scope_id: 0
1139 };
1140 if (!::bind (get_socket (), (struct sockaddr *) &sin6, sizeof sin6))
1141 res = ::listen (get_socket (), backlog);
1142 }
1143 }
1144 if (!res)
1145 {
1146 if (get_addr_family () == AF_LOCAL && get_socket_type () == SOCK_STREAM)
1147 af_local_set_cred ();
1148 connect_state (connected);
1149 listener (true);
1150 }
1151 else
1152 set_winsock_errno ();
1153 return res;
1154 }
1155
1156 int
1157 fhandler_socket::accept4 (struct sockaddr *peer, int *len, int flags)
1158 {
1159 /* Allows NULL peer and len parameters. */
1160 struct sockaddr_storage lpeer;
1161 int llen = sizeof (struct sockaddr_storage);
1162
1163 pthread_testcancel ();
1164
1165 int res = 0;
1166 while (!(res = wait_for_events (FD_ACCEPT | FD_CLOSE, 0))
1167 && (res = ::accept (get_socket (), (struct sockaddr *) &lpeer, &llen))
1168 == SOCKET_ERROR
1169 && WSAGetLastError () == WSAEWOULDBLOCK)
1170 ;
1171 if (res == (int) INVALID_SOCKET)
1172 set_winsock_errno ();
1173 else
1174 {
1175 cygheap_fdnew res_fd;
1176 if (res_fd >= 0 && fdsock (res_fd, &dev (), res))
1177 {
1178 fhandler_socket *sock = (fhandler_socket *) res_fd;
1179 sock->set_addr_family (get_addr_family ());
1180 sock->set_socket_type (get_socket_type ());
1181 sock->async_io (false); /* fdsock switches async mode off. */
1182 if (get_addr_family () == AF_LOCAL)
1183 {
1184 sock->set_sun_path (get_sun_path ());
1185 sock->set_peer_sun_path (get_peer_sun_path ());
1186 if (get_socket_type () == SOCK_STREAM)
1187 {
1188 /* Don't forget to copy credentials from accepting
1189 socket to accepted socket and start transaction
1190 on accepted socket! */
1191 af_local_copy (sock);
1192 res = sock->af_local_accept ();
1193 if (res == -1)
1194 {
1195 res_fd.release ();
1196 set_winsock_errno ();
1197 goto out;
1198 }
1199 }
1200 }
1201 sock->set_nonblocking (flags & SOCK_NONBLOCK);
1202 if (flags & SOCK_CLOEXEC)
1203 sock->set_close_on_exec (true);
1204 /* No locking necessary at this point. */
1205 sock->wsock_events->events = wsock_events->events | FD_WRITE;
1206 sock->wsock_events->owner = wsock_events->owner;
1207 sock->connect_state (connected);
1208 res = res_fd;
1209 if (peer)
1210 {
1211 if (get_addr_family () == AF_LOCAL)
1212 {
1213 /* FIXME: Right now we have no way to determine the
1214 bound socket name of the peer's socket. For now
1215 we just fake an unbound socket on the other side. */
1216 static struct sockaddr_un un = { AF_LOCAL, "" };
1217 memcpy (peer, &un, MIN (*len, (int) sizeof (un.sun_family)));
1218 *len = (int) sizeof (un.sun_family);
1219 }
1220 else
1221 {
1222 memcpy (peer, &lpeer, MIN (*len, llen));
1223 *len = llen;
1224 }
1225 }
1226 }
1227 else
1228 {
1229 closesocket (res);
1230 res = -1;
1231 }
1232 }
1233
1234 out:
1235 debug_printf ("res %d", res);
1236 return res;
1237 }
1238
1239 int
1240 fhandler_socket::getsockname (struct sockaddr *name, int *namelen)
1241 {
1242 int res = -1;
1243
1244 if (get_addr_family () == AF_LOCAL)
1245 {
1246 struct sockaddr_un sun;
1247 sun.sun_family = AF_LOCAL;
1248 sun.sun_path[0] = '\0';
1249 if (get_sun_path ())
1250 strncat (sun.sun_path, get_sun_path (), UNIX_PATH_LEN - 1);
1251 memcpy (name, &sun, MIN (*namelen, (int) SUN_LEN (&sun) + 1));
1252 *namelen = (int) SUN_LEN (&sun) + (get_sun_path () ? 1 : 0);
1253 res = 0;
1254 }
1255 else
1256 {
1257 /* Always use a local big enough buffer and truncate later as necessary
1258 per POSIX. WinSock unfortunaltey only returns WSAEFAULT if the buffer
1259 is too small. */
1260 struct sockaddr_storage sock;
1261 int len = sizeof sock;
1262 res = ::getsockname (get_socket (), (struct sockaddr *) &sock, &len);
1263 if (!res)
1264 {
1265 memcpy (name, &sock, MIN (*namelen, len));
1266 *namelen = len;
1267 }
1268 else
1269 {
1270 if (WSAGetLastError () == WSAEINVAL)
1271 {
1272 /* WinSock returns WSAEINVAL if the socket is locally
1273 unbound. Per SUSv3 this is not an error condition.
1274 We're faking a valid return value here by creating the
1275 same content in the sockaddr structure as on Linux. */
1276 memset (&sock, 0, sizeof sock);
1277 sock.ss_family = get_addr_family ();
1278 switch (get_addr_family ())
1279 {
1280 case AF_INET:
1281 res = 0;
1282 len = (int) sizeof (struct sockaddr_in);
1283 break;
1284 case AF_INET6:
1285 res = 0;
1286 len = (int) sizeof (struct sockaddr_in6);
1287 break;
1288 default:
1289 WSASetLastError (WSAEOPNOTSUPP);
1290 break;
1291 }
1292 if (!res)
1293 {
1294 memcpy (name, &sock, MIN (*namelen, len));
1295 *namelen = len;
1296 }
1297 }
1298 if (res)
1299 set_winsock_errno ();
1300 }
1301 }
1302
1303 return res;
1304 }
1305
1306 int
1307 fhandler_socket::getpeername (struct sockaddr *name, int *namelen)
1308 {
1309 /* Always use a local big enough buffer and truncate later as necessary
1310 per POSIX. WinSock unfortunately only returns WSAEFAULT if the buffer
1311 is too small. */
1312 struct sockaddr_storage sock;
1313 int len = sizeof sock;
1314 int res = ::getpeername (get_socket (), (struct sockaddr *) &sock, &len);
1315 if (res)
1316 set_winsock_errno ();
1317 else if (get_addr_family () == AF_LOCAL)
1318 {
1319 struct sockaddr_un sun;
1320 memset (&sun, 0, sizeof sun);
1321 sun.sun_family = AF_LOCAL;
1322 sun.sun_path[0] = '\0';
1323 if (get_peer_sun_path ())
1324 strncat (sun.sun_path, get_peer_sun_path (), UNIX_PATH_LEN - 1);
1325 memcpy (name, &sun, MIN (*namelen, (int) SUN_LEN (&sun) + 1));
1326 *namelen = (int) SUN_LEN (&sun) + (get_peer_sun_path () ? 1 : 0);
1327 }
1328 else
1329 {
1330 memcpy (name, &sock, MIN (*namelen, len));
1331 *namelen = len;
1332 }
1333
1334 return res;
1335 }
1336
1337 void __stdcall
1338 fhandler_socket::read (void *in_ptr, size_t& len)
1339 {
1340 WSABUF wsabuf = { len, (char *) in_ptr };
1341 WSAMSG wsamsg = { NULL, 0, &wsabuf, 1, { 0, NULL }, 0 };
1342 len = recv_internal (&wsamsg);
1343 }
1344
1345 int
1346 fhandler_socket::readv (const struct iovec *const iov, const int iovcnt,
1347 ssize_t tot)
1348 {
1349 WSABUF wsabuf[iovcnt];
1350 WSABUF *wsaptr = wsabuf + iovcnt;
1351 const struct iovec *iovptr = iov + iovcnt;
1352 while (--wsaptr >= wsabuf)
1353 {
1354 wsaptr->len = (--iovptr)->iov_len;
1355 wsaptr->buf = (char *) iovptr->iov_base;
1356 }
1357 WSAMSG wsamsg = { NULL, 0, wsabuf, iovcnt, { 0, NULL}, 0 };
1358 return recv_internal (&wsamsg);
1359 }
1360
1361 extern "C" {
1362 #define WSAID_WSARECVMSG \
1363 {0xf689d7c8,0x6f1f,0x436b,{0x8a,0x53,0xe5,0x4f,0xe3,0x51,0xc3,0x22}};
1364 typedef int (WSAAPI *LPFN_WSARECVMSG)(SOCKET,LPWSAMSG,LPDWORD,LPWSAOVERLAPPED,
1365 LPWSAOVERLAPPED_COMPLETION_ROUTINE);
1366 int WSAAPI WSASendMsg(SOCKET,LPWSAMSG,DWORD,LPDWORD, LPWSAOVERLAPPED,
1367 LPWSAOVERLAPPED_COMPLETION_ROUTINE);
1368 };
1369
1370 /* There's no DLL which exports the symbol WSARecvMsg. One has to call
1371 WSAIoctl as below to fetch the function pointer. Why on earth did the
1372 MS developers decide not to export a normal symbol for these extension
1373 functions? */
1374 inline int
1375 get_ext_funcptr (SOCKET sock, void *funcptr)
1376 {
1377 DWORD bret;
1378 const GUID guid = WSAID_WSARECVMSG;
1379 return WSAIoctl (sock, SIO_GET_EXTENSION_FUNCTION_POINTER,
1380 (void *) &guid, sizeof (GUID), funcptr, sizeof (void *),
1381 &bret, NULL, NULL);
1382 }
1383
1384 inline ssize_t
1385 fhandler_socket::recv_internal (LPWSAMSG wsamsg)
1386 {
1387 ssize_t res = 0;
1388 DWORD ret = 0, wret;
1389 int evt_mask = FD_READ | ((wsamsg->dwFlags & MSG_OOB) ? FD_OOB : 0);
1390 LPWSABUF &wsabuf = wsamsg->lpBuffers;
1391 ULONG &wsacnt = wsamsg->dwBufferCount;
1392 bool use_recvmsg = false;
1393 static NO_COPY LPFN_WSARECVMSG WSARecvMsg;
1394
1395 DWORD wait_flags = wsamsg->dwFlags;
1396 bool waitall = !!(wait_flags & MSG_WAITALL);
1397 wsamsg->dwFlags &= (MSG_OOB | MSG_PEEK | MSG_DONTROUTE);
1398 if (wsamsg->Control.len > 0)
1399 {
1400 if (!WSARecvMsg
1401 && get_ext_funcptr (get_socket (), &WSARecvMsg) == SOCKET_ERROR)
1402 {
1403 set_winsock_errno ();
1404 return SOCKET_ERROR;
1405 }
1406 use_recvmsg = true;
1407 }
1408 if (waitall)
1409 {
1410 if (get_socket_type () != SOCK_STREAM)
1411 {
1412 WSASetLastError (WSAEOPNOTSUPP);
1413 set_winsock_errno ();
1414 return SOCKET_ERROR;
1415 }
1416 if (is_nonblocking () || (wsamsg->dwFlags & (MSG_OOB | MSG_PEEK)))
1417 waitall = false;
1418 }
1419
1420 /* Note: Don't call WSARecvFrom(MSG_PEEK) without actually having data
1421 waiting in the buffers, otherwise the event handling gets messed up
1422 for some reason. */
1423 while (!(res = wait_for_events (evt_mask | FD_CLOSE, wait_flags))
1424 || saw_shutdown_read ())
1425 {
1426 if (use_recvmsg)
1427 res = WSARecvMsg (get_socket (), wsamsg, &wret, NULL, NULL);
1428 /* This is working around a really weird problem in WinSock.
1429
1430 Assume you create a socket, fork the process (thus duplicating
1431 the socket), connect the socket in the child, then call recv
1432 on the original socket handle in the parent process.
1433 In this scenario, calls to WinSock's recvfrom and WSARecvFrom
1434 in the parent will fail with WSAEINVAL, regardless whether both
1435 address parameters, name and namelen, are NULL or point to valid
1436 storage. However, calls to recv and WSARecv succeed as expected.
1437 Per MSDN, WSAEINVAL in the context of recv means "The socket has not
1438 been bound". It is as if the recvfrom functions test if the socket
1439 is bound locally, but in the parent process, WinSock doesn't know
1440 about that and fails, while the same test is omitted in the recv
1441 functions.
1442
1443 This also covers another weird case: WinSock returns WSAEFAULT if
1444 namelen is a valid pointer while name is NULL. Both parameters are
1445 ignored for TCP sockets, so this only occurs when using UDP socket. */
1446 else if (!wsamsg->name || get_socket_type () == SOCK_STREAM)
1447 res = WSARecv (get_socket (), wsabuf, wsacnt, &wret, &wsamsg->dwFlags,
1448 NULL, NULL);
1449 else
1450 res = WSARecvFrom (get_socket (), wsabuf, wsacnt, &wret,
1451 &wsamsg->dwFlags, wsamsg->name, &wsamsg->namelen,
1452 NULL, NULL);
1453 if (!res)
1454 {
1455 ret += wret;
1456 if (!waitall)
1457 break;
1458 while (wret && wsacnt)
1459 {
1460 if (wsabuf->len > wret)
1461 {
1462 wsabuf->len -= wret;
1463 wsabuf->buf += wret;
1464 wret = 0;
1465 }
1466 else
1467 {
1468 wret -= wsabuf->len;
1469 ++wsabuf;
1470 --wsacnt;
1471 }
1472 }
1473 if (!wret)
1474 break;
1475 }
1476 else if (WSAGetLastError () != WSAEWOULDBLOCK)
1477 break;
1478 }
1479
1480 if (res)
1481 {
1482 /* According to SUSv3, errno isn't set in that case and no error
1483 condition is returned. */
1484 if (WSAGetLastError () == WSAEMSGSIZE)
1485 return ret + wret;
1486
1487 if (!ret)
1488 {
1489 /* ESHUTDOWN isn't defined for recv in SUSv3. Simply EOF is returned
1490 in this case. */
1491 if (WSAGetLastError () == WSAESHUTDOWN)
1492 return 0;
1493
1494 set_winsock_errno ();
1495 return SOCKET_ERROR;
1496 }
1497 }
1498
1499 return ret;
1500 }
1501
1502 ssize_t
1503 fhandler_socket::recvfrom (void *ptr, size_t len, int flags,
1504 struct sockaddr *from, int *fromlen)
1505 {
1506 pthread_testcancel ();
1507
1508 WSABUF wsabuf = { len, (char *) ptr };
1509 WSAMSG wsamsg = { from, from && fromlen ? *fromlen : 0,
1510 &wsabuf, 1,
1511 { 0, NULL},
1512 flags };
1513 ssize_t ret = recv_internal (&wsamsg);
1514 if (fromlen)
1515 *fromlen = wsamsg.namelen;
1516 return ret;
1517 }
1518
1519 ssize_t
1520 fhandler_socket::recvmsg (struct msghdr *msg, int flags)
1521 {
1522 pthread_testcancel ();
1523
1524 /* TODO: Descriptor passing on AF_LOCAL sockets. */
1525
1526 /* Disappointing but true: Even if WSARecvMsg is supported, it's only
1527 supported for datagram and raw sockets. */
1528 if (!wincap.has_recvmsg () || get_socket_type () == SOCK_STREAM
1529 || get_addr_family () == AF_LOCAL)
1530 {
1531 msg->msg_controllen = 0;
1532 if (!CYGWIN_VERSION_CHECK_FOR_USING_ANCIENT_MSGHDR)
1533 msg->msg_flags = 0;
1534 }
1535
1536 WSABUF wsabuf[msg->msg_iovlen];
1537 WSABUF *wsaptr = wsabuf + msg->msg_iovlen;
1538 const struct iovec *iovptr = msg->msg_iov + msg->msg_iovlen;
1539 while (--wsaptr >= wsabuf)
1540 {
1541 wsaptr->len = (--iovptr)->iov_len;
1542 wsaptr->buf = (char *) iovptr->iov_base;
1543 }
1544 WSAMSG wsamsg = { (struct sockaddr *) msg->msg_name, msg->msg_namelen,
1545 wsabuf, msg->msg_iovlen,
1546 { msg->msg_controllen, (char *) msg->msg_control },
1547 flags };
1548 ssize_t ret = recv_internal (&wsamsg);
1549 if (ret >= 0)
1550 {
1551 msg->msg_namelen = wsamsg.namelen;
1552 msg->msg_controllen = wsamsg.Control.len;
1553 if (!CYGWIN_VERSION_CHECK_FOR_USING_ANCIENT_MSGHDR)
1554 msg->msg_flags = wsamsg.dwFlags;
1555 }
1556 return ret;
1557 }
1558
1559 int
1560 fhandler_socket::write (const void *ptr, size_t len)
1561 {
1562 WSABUF wsabuf = { len, (char *) ptr };
1563 WSAMSG wsamsg = { NULL, 0, &wsabuf, 1, { 0, NULL }, 0 };
1564 return send_internal (&wsamsg, 0);
1565 }
1566
1567 int
1568 fhandler_socket::writev (const struct iovec *const iov, const int iovcnt,
1569 ssize_t tot)
1570 {
1571 WSABUF wsabuf[iovcnt];
1572 WSABUF *wsaptr = wsabuf;
1573 const struct iovec *iovptr = iov;
1574 for (int i = 0; i < iovcnt; ++i)
1575 {
1576 wsaptr->len = iovptr->iov_len;
1577 (wsaptr++)->buf = (char *) (iovptr++)->iov_base;
1578 }
1579 WSAMSG wsamsg = { NULL, 0, wsabuf, iovcnt, { 0, NULL}, 0 };
1580 return send_internal (&wsamsg, 0);
1581 }
1582
1583 inline ssize_t
1584 fhandler_socket::send_internal (struct _WSAMSG *wsamsg, int flags)
1585 {
1586 int res = 0;
1587 DWORD ret = 0, err = 0, sum = 0, off = 0;
1588 WSABUF buf;
1589 bool use_sendmsg = false;
1590 DWORD wait_flags = flags & MSG_DONTWAIT;
1591 bool nosignal = !!(flags & MSG_NOSIGNAL);
1592
1593 flags &= (MSG_OOB | MSG_DONTROUTE);
1594 if (wsamsg->Control.len > 0)
1595 use_sendmsg = true;
1596 for (DWORD i = 0; i < wsamsg->dwBufferCount;
1597 off >= wsamsg->lpBuffers[i].len && (++i, off = 0))
1598 {
1599 /* CV 2009-12-02: Don't split datagram messages. */
1600 /* FIXME: Look for a way to split a message into the least number of
1601 pieces to minimize the number of WsaSendTo calls. */
1602 if (get_socket_type () == SOCK_STREAM)
1603 {
1604 buf.buf = wsamsg->lpBuffers[i].buf + off;
1605 buf.len = wsamsg->lpBuffers[i].len - off;
1606 /* See net.cc:fdsock() and MSDN KB 823764 */
1607 if (buf.len >= (unsigned) wmem ())
1608 buf.len = (unsigned) wmem ();
1609 }
1610
1611 do
1612 {
1613 if (use_sendmsg)
1614 res = WSASendMsg (get_socket (), wsamsg, flags, &ret, NULL, NULL);
1615 else if (get_socket_type () == SOCK_STREAM)
1616 res = WSASendTo (get_socket (), &buf, 1, &ret, flags,
1617 wsamsg->name, wsamsg->namelen, NULL, NULL);
1618 else
1619 res = WSASendTo (get_socket (), wsamsg->lpBuffers,
1620 wsamsg->dwBufferCount, &ret, flags,
1621 wsamsg->name, wsamsg->namelen, NULL, NULL);
1622 if (res && (err = WSAGetLastError ()) == WSAEWOULDBLOCK)
1623 {
1624 LOCK_EVENTS;
1625 wsock_events->events &= ~FD_WRITE;
1626 UNLOCK_EVENTS;
1627 }
1628 }
1629 while (res && err == WSAEWOULDBLOCK
1630 && !(res = wait_for_events (FD_WRITE | FD_CLOSE, wait_flags)));
1631
1632 if (!res)
1633 {
1634 off += ret;
1635 sum += ret;
1636 if (get_socket_type () != SOCK_STREAM)
1637 break;
1638 }
1639 else if (is_nonblocking () || err != WSAEWOULDBLOCK)
1640 break;
1641 }
1642
1643 if (sum)
1644 res = sum;
1645 else if (res == SOCKET_ERROR)
1646 {
1647 set_winsock_errno ();
1648
1649 /* Special handling for EPIPE and SIGPIPE.
1650
1651 EPIPE is generated if the local end has been shut down on a connection
1652 oriented socket. In this case the process will also receive a SIGPIPE
1653 unless MSG_NOSIGNAL is set. */
1654 if ((get_errno () == ECONNABORTED || get_errno () == ESHUTDOWN)
1655 && get_socket_type () == SOCK_STREAM)
1656 {
1657 set_errno (EPIPE);
1658 if (!nosignal)
1659 raise (SIGPIPE);
1660 }
1661 }
1662
1663 return res;
1664 }
1665
1666 ssize_t
1667 fhandler_socket::sendto (const void *ptr, size_t len, int flags,
1668 const struct sockaddr *to, int tolen)
1669 {
1670 struct sockaddr_storage sst;
1671
1672 pthread_testcancel ();
1673
1674 if (to && get_inet_addr (to, tolen, &sst, &tolen) == SOCKET_ERROR)
1675 return SOCKET_ERROR;
1676
1677 WSABUF wsabuf = { len, (char *) ptr };
1678 WSAMSG wsamsg = { to ? (struct sockaddr *) &sst : NULL, tolen,
1679 &wsabuf, 1,
1680 { 0, NULL},
1681 0 };
1682 return send_internal (&wsamsg, flags);
1683 }
1684
1685 int
1686 fhandler_socket::sendmsg (const struct msghdr *msg, int flags)
1687 {
1688 /* TODO: Descriptor passing on AF_LOCAL sockets. */
1689
1690 struct sockaddr_storage sst;
1691 int len = 0;
1692
1693 pthread_testcancel ();
1694
1695 if (msg->msg_name
1696 && get_inet_addr ((struct sockaddr *) msg->msg_name, msg->msg_namelen,
1697 &sst, &len) == SOCKET_ERROR)
1698 return SOCKET_ERROR;
1699
1700 WSABUF wsabuf[msg->msg_iovlen];
1701 WSABUF *wsaptr = wsabuf;
1702 const struct iovec *iovptr = msg->msg_iov;
1703 for (int i = 0; i < msg->msg_iovlen; ++i)
1704 {
1705 wsaptr->len = iovptr->iov_len;
1706 (wsaptr++)->buf = (char *) (iovptr++)->iov_base;
1707 }
1708 WSAMSG wsamsg = { msg->msg_name ? (struct sockaddr *) &sst : NULL, len,
1709 wsabuf, msg->msg_iovlen,
1710 /* Disappointing but true: Even if WSASendMsg is
1711 supported, it's only supported for datagram and
1712 raw sockets. */
1713 { !wincap.has_sendmsg ()
1714 || get_socket_type () == SOCK_STREAM
1715 || get_addr_family () == AF_LOCAL
1716 ? 0 : msg->msg_controllen, (char *) msg->msg_control },
1717 0 };
1718 return send_internal (&wsamsg, flags);
1719 }
1720
1721 int
1722 fhandler_socket::shutdown (int how)
1723 {
1724 int res = ::shutdown (get_socket (), how);
1725
1726 /* Linux allows to call shutdown for any socket, even if it's not connected.
1727 This also disables to call accept on this socket, if shutdown has been
1728 called with the SHUT_RD or SHUT_RDWR parameter. In contrast, WinSock
1729 only allows to call shutdown on a connected socket. The accept function
1730 is in no way affected. So, what we do here is to fake success, and to
1731 change the event settings so that an FD_CLOSE event is triggered for the
1732 calling Cygwin function. The evaluate_events method handles the call
1733 from accept specially to generate a Linux-compatible behaviour. */
1734 if (res && WSAGetLastError () != WSAENOTCONN)
1735 set_winsock_errno ();
1736 else
1737 {
1738 res = 0;
1739 switch (how)
1740 {
1741 case SHUT_RD:
1742 saw_shutdown_read (true);
1743 wsock_events->events |= FD_CLOSE;
1744 SetEvent (wsock_evt);
1745 break;
1746 case SHUT_WR:
1747 saw_shutdown_write (true);
1748 break;
1749 case SHUT_RDWR:
1750 saw_shutdown_read (true);
1751 saw_shutdown_write (true);
1752 wsock_events->events |= FD_CLOSE;
1753 SetEvent (wsock_evt);
1754 break;
1755 }
1756 }
1757 return res;
1758 }
1759
1760 int
1761 fhandler_socket::close ()
1762 {
1763 int res = 0;
1764 /* TODO: CV - 2008-04-16. Lingering disabled. The original problem
1765 could be no longer reproduced on NT4, XP, 2K8. Any return of a
1766 spurious "Connection reset by peer" *could* be caused by disabling
1767 the linger code here... */
1768 #if 0
1769 /* HACK to allow a graceful shutdown even if shutdown() hasn't been
1770 called by the application. Note that this isn't the ultimate
1771 solution but it helps in many cases. */
1772 struct linger linger;
1773 linger.l_onoff = 1;
1774 linger.l_linger = 240; /* secs. default 2MSL value according to MSDN. */
1775 setsockopt (get_socket (), SOL_SOCKET, SO_LINGER,
1776 (const char *)&linger, sizeof linger);
1777 #endif
1778 release_events ();
1779 while ((res = closesocket (get_socket ())) != 0)
1780 {
1781 if (WSAGetLastError () != WSAEWOULDBLOCK)
1782 {
1783 set_winsock_errno ();
1784 res = -1;
1785 break;
1786 }
1787 if (WaitForSingleObject (signal_arrived, 10) == WAIT_OBJECT_0)
1788 {
1789 set_errno (EINTR);
1790 res = -1;
1791 break;
1792 }
1793 WSASetLastError (0);
1794 }
1795
1796 debug_printf ("%d = fhandler_socket::close()", res);
1797 return res;
1798 }
1799
1800 /* Definitions of old ifreq stuff used prior to Cygwin 1.7.0. */
1801 #define OLD_SIOCGIFFLAGS _IOW('s', 101, struct __old_ifreq)
1802 #define OLD_SIOCGIFADDR _IOW('s', 102, struct __old_ifreq)
1803 #define OLD_SIOCGIFBRDADDR _IOW('s', 103, struct __old_ifreq)
1804 #define OLD_SIOCGIFNETMASK _IOW('s', 104, struct __old_ifreq)
1805 #define OLD_SIOCGIFHWADDR _IOW('s', 105, struct __old_ifreq)
1806 #define OLD_SIOCGIFMETRIC _IOW('s', 106, struct __old_ifreq)
1807 #define OLD_SIOCGIFMTU _IOW('s', 107, struct __old_ifreq)
1808 #define OLD_SIOCGIFINDEX _IOW('s', 108, struct __old_ifreq)
1809
1810 #define CONV_OLD_TO_NEW_SIO(old) (((old)&0xff00ffff)|(((long)sizeof(struct ifreq)&IOCPARM_MASK)<<16))
1811
1812 struct __old_ifreq {
1813 #define __OLD_IFNAMSIZ 16
1814 union {
1815 char ifrn_name[__OLD_IFNAMSIZ]; /* if name, e.g. "en0" */
1816 } ifr_ifrn;
1817
1818 union {
1819 struct sockaddr ifru_addr;
1820 struct sockaddr ifru_broadaddr;
1821 struct sockaddr ifru_netmask;
1822 struct sockaddr ifru_hwaddr;
1823 short ifru_flags;
1824 int ifru_metric;
1825 int ifru_mtu;
1826 int ifru_ifindex;
1827 } ifr_ifru;
1828 };
1829
1830 int
1831 fhandler_socket::ioctl (unsigned int cmd, void *p)
1832 {
1833 extern int get_ifconf (struct ifconf *ifc, int what); /* net.cc */
1834 int res;
1835 struct ifconf ifc, *ifcp;
1836 struct ifreq *ifrp;
1837
1838 switch (cmd)
1839 {
1840 case SIOCGIFCONF:
1841 ifcp = (struct ifconf *) p;
1842 if (!ifcp)
1843 {
1844 set_errno (EINVAL);
1845 return -1;
1846 }
1847 if (CYGWIN_VERSION_CHECK_FOR_OLD_IFREQ)
1848 {
1849 ifc.ifc_len = ifcp->ifc_len / sizeof (struct __old_ifreq)
1850 * sizeof (struct ifreq);
1851 ifc.ifc_buf = (caddr_t) alloca (ifc.ifc_len);
1852 }
1853 else
1854 {
1855 ifc.ifc_len = ifcp->ifc_len;
1856 ifc.ifc_buf = ifcp->ifc_buf;
1857 }
1858 res = get_ifconf (&ifc, cmd);
1859 if (res)
1860 debug_printf ("error in get_ifconf");
1861 if (CYGWIN_VERSION_CHECK_FOR_OLD_IFREQ)
1862 {
1863 struct __old_ifreq *ifr = (struct __old_ifreq *) ifcp->ifc_buf;
1864 for (ifrp = ifc.ifc_req;
1865 (caddr_t) ifrp < ifc.ifc_buf + ifc.ifc_len;
1866 ++ifrp, ++ifr)
1867 {
1868 memcpy (&ifr->ifr_ifrn, &ifrp->ifr_ifrn, sizeof ifr->ifr_ifrn);
1869 ifr->ifr_name[__OLD_IFNAMSIZ - 1] = '\0';
1870 memcpy (&ifr->ifr_ifru, &ifrp->ifr_ifru, sizeof ifr->ifr_ifru);
1871 }
1872 ifcp->ifc_len = ifc.ifc_len / sizeof (struct ifreq)
1873 * sizeof (struct __old_ifreq);
1874 }
1875 else
1876 ifcp->ifc_len = ifc.ifc_len;
1877 break;
1878 case OLD_SIOCGIFFLAGS:
1879 case OLD_SIOCGIFADDR:
1880 case OLD_SIOCGIFBRDADDR:
1881 case OLD_SIOCGIFNETMASK:
1882 case OLD_SIOCGIFHWADDR:
1883 case OLD_SIOCGIFMETRIC:
1884 case OLD_SIOCGIFMTU:
1885 case OLD_SIOCGIFINDEX:
1886 cmd = CONV_OLD_TO_NEW_SIO (cmd);
1887 /*FALLTHRU*/
1888 case SIOCGIFFLAGS:
1889 case SIOCGIFBRDADDR:
1890 case SIOCGIFNETMASK:
1891 case SIOCGIFADDR:
1892 case SIOCGIFHWADDR:
1893 case SIOCGIFMETRIC:
1894 case SIOCGIFMTU:
1895 case SIOCGIFINDEX:
1896 case SIOCGIFFRNDLYNAM:
1897 case SIOCGIFDSTADDR:
1898 {
1899 if (!p)
1900 {
1901 debug_printf ("ifr == NULL");
1902 set_errno (EINVAL);
1903 return -1;
1904 }
1905
1906 if (cmd > SIOCGIFINDEX && CYGWIN_VERSION_CHECK_FOR_OLD_IFREQ)
1907 {
1908 debug_printf ("cmd not supported on this platform");
1909 set_errno (EINVAL);
1910 return -1;
1911 }
1912 ifc.ifc_len = 64 * sizeof (struct ifreq);
1913 ifc.ifc_buf = (caddr_t) alloca (ifc.ifc_len);
1914 if (cmd == SIOCGIFFRNDLYNAM)
1915 {
1916 struct ifreq_frndlyname *iff = (struct ifreq_frndlyname *)
1917 alloca (64 * sizeof (struct ifreq_frndlyname));
1918 for (int i = 0; i < 64; ++i)
1919 ifc.ifc_req[i].ifr_frndlyname = &iff[i];
1920 }
1921
1922 res = get_ifconf (&ifc, cmd);
1923 if (res)
1924 {
1925 debug_printf ("error in get_ifconf");
1926 break;
1927 }
1928
1929 if (CYGWIN_VERSION_CHECK_FOR_OLD_IFREQ)
1930 {
1931 struct __old_ifreq *ifr = (struct __old_ifreq *) p;
1932 debug_printf (" name: %s", ifr->ifr_name);
1933 for (ifrp = ifc.ifc_req;
1934 (caddr_t) ifrp < ifc.ifc_buf + ifc.ifc_len;
1935 ++ifrp)
1936 {
1937 debug_printf ("testname: %s", ifrp->ifr_name);
1938 if (! strcmp (ifrp->ifr_name, ifr->ifr_name))
1939 {
1940 memcpy (&ifr->ifr_ifru, &ifrp->ifr_ifru,
1941 sizeof ifr->ifr_ifru);
1942 break;
1943 }
1944 }
1945 }
1946 else
1947 {
1948 struct ifreq *ifr = (struct ifreq *) p;
1949 debug_printf (" name: %s", ifr->ifr_name);
1950 for (ifrp = ifc.ifc_req;
1951 (caddr_t) ifrp < ifc.ifc_buf + ifc.ifc_len;
1952 ++ifrp)
1953 {
1954 debug_printf ("testname: %s", ifrp->ifr_name);
1955 if (! strcmp (ifrp->ifr_name, ifr->ifr_name))
1956 {
1957 if (cmd == SIOCGIFFRNDLYNAM)
1958 /* The application has to care for the space. */
1959 memcpy (ifr->ifr_frndlyname, ifrp->ifr_frndlyname,
1960 sizeof (struct ifreq_frndlyname));
1961 else
1962 memcpy (&ifr->ifr_ifru, &ifrp->ifr_ifru,
1963 sizeof ifr->ifr_ifru);
1964 break;
1965 }
1966 }
1967 }
1968 if ((caddr_t) ifrp >= ifc.ifc_buf + ifc.ifc_len)
1969 {
1970 set_errno (EINVAL);
1971 return -1;
1972 }
1973 break;
1974 }
1975 case FIOASYNC:
1976 res = WSAAsyncSelect (get_socket (), winmsg, WM_ASYNCIO,
1977 *(int *) p ? ASYNC_MASK : 0);
1978 syscall_printf ("Async I/O on socket %s",
1979 *(int *) p ? "started" : "cancelled");
1980 async_io (*(int *) p != 0);
1981 /* If async_io is switched off, revert the event handling. */
1982 if (*(int *) p == 0)
1983 WSAEventSelect (get_socket (), wsock_evt, EVENT_MASK);
1984 break;
1985 case FIONREAD:
1986 res = ioctlsocket (get_socket (), FIONREAD, (unsigned long *) p);
1987 if (res == SOCKET_ERROR)
1988 set_winsock_errno ();
1989 break;
1990 default:
1991 /* Sockets are always non-blocking internally. So we just note the
1992 state here. */
1993 if (cmd == FIONBIO)
1994 {
1995 syscall_printf ("socket is now %sblocking",
1996 *(int *) p ? "non" : "");
1997 set_nonblocking (*(int *) p);
1998 res = 0;
1999 }
2000 else
2001 res = ioctlsocket (get_socket (), cmd, (unsigned long *) p);
2002 break;
2003 }
2004 syscall_printf ("%d = ioctl_socket(%x, %x)", res, cmd, p);
2005 return res;
2006 }
2007
2008 int
2009 fhandler_socket::fcntl (int cmd, void *arg)
2010 {
2011 int res = 0;
2012 int request, current;
2013
2014 switch (cmd)
2015 {
2016 case F_SETOWN:
2017 {
2018 pid_t pid = (pid_t) arg;
2019 LOCK_EVENTS;
2020 wsock_events->owner = pid;
2021 UNLOCK_EVENTS;
2022 debug_printf ("owner set to %d", pid);
2023 }
2024 break;
2025 case F_GETOWN:
2026 res = wsock_events->owner;
2027 break;
2028 case F_SETFL:
2029 {
2030 /* Carefully test for the O_NONBLOCK or deprecated OLD_O_NDELAY flag.
2031 Set only the flag that has been passed in. If both are set, just
2032 record O_NONBLOCK. */
2033 int new_flags = (int) arg & O_NONBLOCK_MASK;
2034 if ((new_flags & OLD_O_NDELAY) && (new_flags & O_NONBLOCK))
2035 new_flags = O_NONBLOCK;
2036 current = get_flags () & O_NONBLOCK_MASK;
2037 request = new_flags ? 1 : 0;
2038 if (!!current != !!new_flags && (res = ioctl (FIONBIO, &request)))
2039 break;
2040 set_flags ((get_flags () & ~O_NONBLOCK_MASK) | new_flags);
2041 break;
2042 }
2043 default:
2044 res = fhandler_base::fcntl (cmd, arg);
2045 break;
2046 }
2047 return res;
2048 }
2049
2050 void
2051 fhandler_socket::set_close_on_exec (bool val)
2052 {
2053 set_no_inheritance (wsock_mtx, val);
2054 set_no_inheritance (wsock_evt, val);
2055 if (need_fixup_before ())
2056 {
2057 close_on_exec (val);
2058 debug_printf ("set close_on_exec for %s to %d", get_name (), val);
2059 }
2060 else
2061 fhandler_base::set_close_on_exec (val);
2062 }
2063
2064 void
2065 fhandler_socket::set_sun_path (const char *path)
2066 {
2067 sun_path = path ? cstrdup (path) : NULL;
2068 }
2069
2070 void
2071 fhandler_socket::set_peer_sun_path (const char *path)
2072 {
2073 peer_sun_path = path ? cstrdup (path) : NULL;
2074 }
2075
2076 int
2077 fhandler_socket::getpeereid (pid_t *pid, __uid32_t *euid, __gid32_t *egid)
2078 {
2079 if (get_addr_family () != AF_LOCAL || get_socket_type () != SOCK_STREAM)
2080 {
2081 set_errno (EINVAL);
2082 return -1;
2083 }
2084 if (connect_state () != connected)
2085 {
2086 set_errno (ENOTCONN);
2087 return -1;
2088 }
2089 if (sec_peer_pid == (pid_t) 0)
2090 {
2091 set_errno (ENOTCONN); /* Usually when calling getpeereid on
2092 accepting (instead of accepted) socket. */
2093 return -1;
2094 }
2095
2096 myfault efault;
2097 if (efault.faulted (EFAULT))
2098 return -1;
2099 if (pid)
2100 *pid = sec_peer_pid;
2101 if (euid)
2102 *euid = sec_peer_uid;
2103 if (egid)
2104 *egid = sec_peer_gid;
2105 return 0;
2106 }
This page took 0.12608 seconds and 4 git commands to generate.