Cygwin: strptime: add release note
[newlib-cygwin.git] / winsup / cygwin / fhandler / socket_local.cc
blobe4a88169b0b2cfdd139f8b7e5dee6df3bba91b7c
1 /* fhandler_socket_local.cc.
3 See fhandler.h for a description of the fhandler classes.
5 This file is part of Cygwin.
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. */
11 #define __INSIDE_CYGWIN_NET__
12 #define USE_SYS_TYPES_FD_SET
14 #include "winsup.h"
15 /* 2014-04-24: Current Mingw headers define sockaddr_in6 using u_long (8 byte)
16 because a redefinition for LP64 systems is missing. This leads to a wrong
17 definition and size of sockaddr_in6 when building with winsock headers.
18 This definition is also required to use the right u_long type in subsequent
19 function calls. */
20 #undef u_long
21 #define u_long __ms_u_long
22 #include "ntsecapi.h"
23 #include <w32api/ws2tcpip.h>
24 #include <w32api/mswsock.h>
25 #include <unistd.h>
26 #include <asm/byteorder.h>
27 #include <sys/socket.h>
28 #include <sys/un.h>
29 #include <sys/param.h>
30 #include <sys/statvfs.h>
31 #include <cygwin/acl.h>
32 #include "cygerrno.h"
33 #include "path.h"
34 #include "fhandler.h"
35 #include "dtable.h"
36 #include "cygheap.h"
37 #include "wininfo.h"
38 #include "ntdll.h"
40 extern "C" {
41 int sscanf (const char *, const char *, ...);
42 } /* End of "C" section */
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)
47 #define LOCK_EVENTS \
48 if (wsock_mtx && \
49 WaitForSingleObject (wsock_mtx, INFINITE) != WAIT_FAILED) \
52 #define UNLOCK_EVENTS \
53 ReleaseMutex (wsock_mtx); \
56 static inline mode_t
57 adjust_socket_file_mode (mode_t mode)
59 /* Kludge: Don't allow to remove read bit on socket files for
60 user/group/other, if the accompanying write bit is set. It would
61 be nice to have exact permissions on a socket file, but it's
62 necessary that somebody able to access the socket can always read
63 the contents of the socket file to avoid spurious "permission
64 denied" messages. */
65 return mode | ((mode & (S_IWUSR | S_IWGRP | S_IWOTH)) << 1);
68 /* cygwin internal: map sockaddr into internet domain address */
69 int
70 get_inet_addr_local (const struct sockaddr *in, int inlen,
71 struct sockaddr_storage *out, int *outlen,
72 int *type = NULL, int *secret = NULL)
74 int secret_buf [4];
75 int* secret_ptr = (secret ? : secret_buf);
77 /* Check for abstract socket. These are generated for AF_LOCAL datagram
78 sockets in recv_internal, to allow a datagram server to use sendto
79 after recvfrom. */
80 if (inlen >= (int) sizeof (in->sa_family) + 7
81 && in->sa_data[0] == '\0' && in->sa_data[1] == 'd'
82 && in->sa_data[6] == '\0')
84 struct sockaddr_in addr;
85 addr.sin_family = AF_INET;
86 sscanf (in->sa_data + 2, "%04hx", &addr.sin_port);
87 addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
88 *outlen = sizeof addr;
89 memcpy (out, &addr, *outlen);
90 return 0;
93 path_conv pc (in->sa_data, PC_SYM_FOLLOW);
94 if (pc.error)
96 set_errno (pc.error);
97 return SOCKET_ERROR;
99 if (!pc.exists ())
101 set_errno (ENOENT);
102 return SOCKET_ERROR;
104 /* Do NOT test for the file being a socket file here. The socket file
105 creation is not an atomic operation, so there is a chance that socket
106 files which are just in the process of being created are recognized
107 as non-socket files. To work around this problem we now create the
108 file with all sharing disabled. If the below NtOpenFile fails
109 with STATUS_SHARING_VIOLATION we know that the file already exists,
110 but the creating process isn't finished yet. So we yield and try
111 again, until we can either open the file successfully, or some error
112 other than STATUS_SHARING_VIOLATION occurs.
113 Since we now don't know if the file is actually a socket file, we
114 perform this check here explicitely. */
115 NTSTATUS status;
116 HANDLE fh;
117 OBJECT_ATTRIBUTES attr;
118 IO_STATUS_BLOCK io;
120 pc.get_object_attr (attr, sec_none_nih);
123 status = NtOpenFile (&fh, GENERIC_READ | SYNCHRONIZE, &attr, &io,
124 FILE_SHARE_VALID_FLAGS,
125 FILE_SYNCHRONOUS_IO_NONALERT
126 | FILE_OPEN_FOR_BACKUP_INTENT
127 | FILE_NON_DIRECTORY_FILE);
128 if (status == STATUS_SHARING_VIOLATION)
130 /* While we hope that the sharing violation is only temporary, we
131 also could easily get stuck here, waiting for a file in use by
132 some greedy Win32 application. Therefore we should never wait
133 endlessly without checking for signals and thread cancel event. */
134 pthread_testcancel ();
135 if (cygwait (NULL, cw_nowait, cw_sig_eintr) == WAIT_SIGNALED
136 && !_my_tls.call_signal_handler ())
138 set_errno (EINTR);
139 return SOCKET_ERROR;
141 yield ();
143 else if (!NT_SUCCESS (status))
145 __seterrno_from_nt_status (status);
146 return SOCKET_ERROR;
149 while (status == STATUS_SHARING_VIOLATION);
150 /* Now test for the SYSTEM bit. */
151 FILE_BASIC_INFORMATION fbi;
152 status = NtQueryInformationFile (fh, &io, &fbi, sizeof fbi,
153 FileBasicInformation);
154 if (!NT_SUCCESS (status))
156 __seterrno_from_nt_status (status);
157 return SOCKET_ERROR;
159 if (!(fbi.FileAttributes & FILE_ATTRIBUTE_SYSTEM))
161 NtClose (fh);
162 set_errno (EBADF);
163 return SOCKET_ERROR;
165 /* Eventually check the content and fetch the required information. */
166 char buf[128];
167 memset (buf, 0, sizeof buf);
168 status = NtReadFile (fh, NULL, NULL, NULL, &io, buf, 128, NULL, NULL);
169 NtClose (fh);
170 if (NT_SUCCESS (status))
172 struct sockaddr_in sin;
173 char ctype;
174 sin.sin_family = AF_INET;
175 if (strncmp (buf, SOCKET_COOKIE, strlen (SOCKET_COOKIE)))
177 set_errno (EBADF);
178 return SOCKET_ERROR;
180 sscanf (buf + strlen (SOCKET_COOKIE), "%hu %c %08x-%08x-%08x-%08x",
181 &sin.sin_port,
182 &ctype,
183 secret_ptr, secret_ptr + 1, secret_ptr + 2, secret_ptr + 3);
184 sin.sin_port = htons (sin.sin_port);
185 sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
186 memcpy (out, &sin, sizeof sin);
187 *outlen = sizeof sin;
188 if (type)
189 *type = (ctype == 's' ? SOCK_STREAM :
190 ctype == 'd' ? SOCK_DGRAM
191 : 0);
192 return 0;
194 __seterrno_from_nt_status (status);
195 return SOCKET_ERROR;
198 /* There's no DLL which exports the symbol WSARecvMsg. One has to call
199 WSAIoctl as below to fetch the function pointer. Why on earth did the
200 MS developers decide not to export a normal symbol for these extension
201 functions? */
202 inline int
203 get_ext_funcptr (SOCKET sock, void *funcptr)
205 DWORD bret;
206 const GUID guid = WSAID_WSARECVMSG;
207 return WSAIoctl (sock, SIO_GET_EXTENSION_FUNCTION_POINTER,
208 (void *) &guid, sizeof (GUID), funcptr, sizeof (void *),
209 &bret, NULL, NULL);
212 fhandler_socket_local::fhandler_socket_local () :
213 fhandler_socket_wsock (),
214 sun_path (NULL),
215 peer_sun_path (NULL),
216 status ()
220 fhandler_socket_local::~fhandler_socket_local ()
222 if (sun_path)
223 cfree (sun_path);
224 if (peer_sun_path)
225 cfree (peer_sun_path);
229 fhandler_socket_local::socket (int af, int type, int protocol, int flags)
231 SOCKET sock;
232 int ret;
234 if (type != SOCK_STREAM && type != SOCK_DGRAM)
236 set_errno (EINVAL);
237 return -1;
239 if (protocol != 0)
241 set_errno (EPROTONOSUPPORT);
242 return -1;
244 sock = ::socket (AF_INET, type, protocol);
245 if (sock == INVALID_SOCKET)
247 set_winsock_errno ();
248 return -1;
250 ret = set_socket_handle (sock, af, type, flags);
251 if (ret < 0)
252 ::closesocket (sock);
253 return ret;
257 fhandler_socket_local::socketpair (int af, int type, int protocol, int flags,
258 fhandler_socket *_fh_out)
260 SOCKET insock = INVALID_SOCKET;
261 SOCKET outsock = INVALID_SOCKET;
262 SOCKET sock = INVALID_SOCKET;
263 struct sockaddr_in sock_in, sock_out;
264 int len;
265 fhandler_socket_local *fh_out = reinterpret_cast<fhandler_socket_local *>
266 (_fh_out);
268 if (type != SOCK_STREAM && type != SOCK_DGRAM)
270 set_errno (EINVAL);
271 return -1;
273 if (protocol != 0)
275 set_errno (EPROTONOSUPPORT);
276 return -1;
278 /* create listening socket */
279 sock = ::socket (AF_INET, type, 0);
280 if (sock == INVALID_SOCKET)
282 set_winsock_errno ();
283 goto err;
285 /* bind to unused port */
286 sock_in.sin_family = AF_INET;
287 sock_in.sin_port = 0;
288 sock_in.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
289 if (::bind (sock, (struct sockaddr *) &sock_in, sizeof (sock_in)) < 0)
291 set_winsock_errno ();
292 goto err;
294 /* fetch socket name */
295 len = sizeof (sock_in);
296 if (::getsockname (sock, (struct sockaddr *) &sock_in, &len) < 0)
298 set_winsock_errno ();
299 goto err;
301 /* on stream sockets, create listener */
302 if (type == SOCK_STREAM && ::listen (sock, 2) < 0)
304 set_winsock_errno ();
305 goto err;
307 /* create connecting socket */
308 outsock = ::socket (AF_INET, type, 0);
309 if (outsock == INVALID_SOCKET)
311 set_winsock_errno ();
312 goto err;
314 /* on datagram sockets, bind connecting socket */
315 if (type == SOCK_DGRAM)
317 sock_out.sin_family = AF_INET;
318 sock_out.sin_port = 0;
319 sock_out.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
320 if (::bind (outsock, (struct sockaddr *) &sock_out,
321 sizeof (sock_out)) < 0)
323 set_winsock_errno ();
324 goto err;
326 /* ...and fetch name */
327 len = sizeof (sock_out);
328 if (::getsockname (outsock, (struct sockaddr *) &sock_out, &len) < 0)
330 set_winsock_errno ();
331 goto err;
334 sock_in.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
335 if (type == SOCK_DGRAM)
336 sock_out.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
337 /* connect */
338 if (::connect (outsock, (struct sockaddr *) &sock_in, sizeof (sock_in)) < 0)
340 set_winsock_errno ();
341 goto err;
343 if (type == SOCK_STREAM)
345 /* on stream sockets, accept connection and close listener */
346 len = sizeof (sock_in);
347 insock = ::accept (sock, (struct sockaddr *) &sock_in, &len);
348 if (insock == INVALID_SOCKET)
350 set_winsock_errno ();
351 goto err;
353 ::closesocket (sock);
355 else
357 /* on datagram sockets, connect vice versa */
358 if (::connect (sock, (struct sockaddr *) &sock_out,
359 sizeof (sock_out)) < 0)
361 set_winsock_errno ();
362 goto err;
364 insock = sock;
366 sock = INVALID_SOCKET;
368 /* postprocessing */
369 connect_state (connected);
370 fh_out->connect_state (connected);
371 if (af == AF_LOCAL && type == SOCK_STREAM)
373 af_local_set_sockpair_cred ();
374 fh_out->af_local_set_sockpair_cred ();
376 if (set_socket_handle (insock, af, type, flags) < 0
377 || fh_out->set_socket_handle (outsock, af, type, flags) < 0)
378 goto err;
380 return 0;
382 err:
383 if (sock != INVALID_SOCKET)
384 ::closesocket (sock);
385 if (insock != INVALID_SOCKET)
386 ::closesocket (insock);
387 if (outsock != INVALID_SOCKET)
388 ::closesocket (outsock);
389 return -1;
392 void
393 fhandler_socket_local::af_local_set_sockpair_cred ()
395 sec_pid = sec_peer_pid = getpid ();
396 sec_uid = sec_peer_uid = geteuid ();
397 sec_gid = sec_peer_gid = getegid ();
400 void
401 fhandler_socket_local::af_local_setblocking (bool &async, bool &nonblocking)
403 async = async_io ();
404 nonblocking = is_nonblocking ();
405 if (async)
407 WSAAsyncSelect (get_socket (), winmsg, 0, 0);
408 WSAEventSelect (get_socket (), wsock_evt, EVENT_MASK);
410 set_nonblocking (false);
411 async_io (false);
414 void
415 fhandler_socket_local::af_local_unsetblocking (bool async, bool nonblocking)
417 if (nonblocking)
418 set_nonblocking (true);
419 if (async)
421 WSAAsyncSelect (get_socket (), winmsg, WM_ASYNCIO, ASYNC_MASK);
422 async_io (true);
426 bool
427 fhandler_socket_local::af_local_recv_secret ()
429 int out[4] = { 0, 0, 0, 0 };
430 int rest = sizeof out;
431 char *ptr = (char *) out;
432 while (rest > 0)
434 int ret = recvfrom (ptr, rest, 0, NULL, NULL);
435 if (ret <= 0)
436 break;
437 rest -= ret;
438 ptr += ret;
440 if (rest == 0)
442 debug_printf ("Received af_local secret: %08x-%08x-%08x-%08x",
443 out[0], out[1], out[2], out[3]);
444 if (out[0] != connect_secret[0] || out[1] != connect_secret[1]
445 || out[2] != connect_secret[2] || out[3] != connect_secret[3])
447 debug_printf ("Receiving af_local secret mismatch");
448 return false;
451 else
452 debug_printf ("Receiving af_local secret failed");
453 return rest == 0;
456 bool
457 fhandler_socket_local::af_local_send_secret ()
459 int rest = sizeof connect_secret;
460 char *ptr = (char *) connect_secret;
461 while (rest > 0)
463 int ret = sendto (ptr, rest, 0, NULL, 0);
464 if (ret <= 0)
465 break;
466 rest -= ret;
467 ptr += ret;
469 debug_printf ("Sending af_local secret %s", rest == 0 ? "succeeded"
470 : "failed");
471 return rest == 0;
474 bool
475 fhandler_socket_local::af_local_recv_cred ()
477 struct ucred out = { (pid_t) 0, (uid_t) -1, (gid_t) -1 };
478 int rest = sizeof out;
479 char *ptr = (char *) &out;
480 while (rest > 0)
482 int ret = recvfrom (ptr, rest, 0, NULL, NULL);
483 if (ret <= 0)
484 break;
485 rest -= ret;
486 ptr += ret;
488 if (rest == 0)
490 debug_printf ("Received eid credentials: pid: %d, uid: %d, gid: %d",
491 out.pid, out.uid, out.gid);
492 sec_peer_pid = out.pid;
493 sec_peer_uid = out.uid;
494 sec_peer_gid = out.gid;
496 else
497 debug_printf ("Receiving eid credentials failed");
498 return rest == 0;
501 bool
502 fhandler_socket_local::af_local_send_cred ()
504 struct ucred in = { sec_pid, sec_uid, sec_gid };
505 int rest = sizeof in;
506 char *ptr = (char *) &in;
507 while (rest > 0)
509 int ret = sendto (ptr, rest, 0, NULL, 0);
510 if (ret <= 0)
511 break;
512 rest -= ret;
513 ptr += ret;
515 if (rest == 0)
516 debug_printf ("Sending eid credentials succeeded");
517 else
518 debug_printf ("Sending eid credentials failed");
519 return rest == 0;
523 fhandler_socket_local::af_local_connect ()
525 bool orig_async_io, orig_is_nonblocking;
527 if (get_socket_type () != SOCK_STREAM)
528 return 0;
530 debug_printf ("af_local_connect called, no_getpeereid=%d", no_getpeereid ());
531 if (no_getpeereid ())
532 return 0;
534 af_local_setblocking (orig_async_io, orig_is_nonblocking);
535 if (!af_local_send_secret () || !af_local_recv_secret ()
536 || !af_local_send_cred () || !af_local_recv_cred ())
538 debug_printf ("accept from unauthorized server");
539 ::shutdown (get_socket (), SD_BOTH);
540 WSASetLastError (WSAECONNREFUSED);
541 return -1;
543 af_local_unsetblocking (orig_async_io, orig_is_nonblocking);
544 return 0;
548 fhandler_socket_local::af_local_accept ()
550 bool orig_async_io, orig_is_nonblocking;
552 debug_printf ("af_local_accept called, no_getpeereid=%d", no_getpeereid ());
553 if (no_getpeereid ())
554 return 0;
556 af_local_setblocking (orig_async_io, orig_is_nonblocking);
557 if (!af_local_recv_secret () || !af_local_send_secret ()
558 || !af_local_recv_cred () || !af_local_send_cred ())
560 debug_printf ("connect from unauthorized client");
561 ::shutdown (get_socket (), SD_BOTH);
562 ::closesocket (get_socket ());
563 WSASetLastError (WSAECONNABORTED);
564 return -1;
566 af_local_unsetblocking (orig_async_io, orig_is_nonblocking);
567 return 0;
571 fhandler_socket_local::af_local_set_no_getpeereid ()
573 if (get_addr_family () != AF_LOCAL || get_socket_type () != SOCK_STREAM)
575 set_errno (EINVAL);
576 return -1;
578 if (connect_state () != unconnected)
580 set_errno (EALREADY);
581 return -1;
584 debug_printf ("no_getpeereid set");
585 no_getpeereid (true);
586 return 0;
589 void
590 fhandler_socket_local::af_local_set_cred ()
592 sec_pid = getpid ();
593 sec_uid = geteuid ();
594 sec_gid = getegid ();
595 sec_peer_pid = (pid_t) 0;
596 sec_peer_uid = (uid_t) -1;
597 sec_peer_gid = (gid_t) -1;
600 void
601 fhandler_socket_local::af_local_copy (fhandler_socket_local *sock)
603 sock->connect_secret[0] = connect_secret[0];
604 sock->connect_secret[1] = connect_secret[1];
605 sock->connect_secret[2] = connect_secret[2];
606 sock->connect_secret[3] = connect_secret[3];
607 sock->sec_pid = sec_pid;
608 sock->sec_uid = sec_uid;
609 sock->sec_gid = sec_gid;
610 sock->sec_peer_pid = sec_peer_pid;
611 sock->sec_peer_uid = sec_peer_uid;
612 sock->sec_peer_gid = sec_peer_gid;
613 sock->no_getpeereid (no_getpeereid ());
616 void
617 fhandler_socket_local::af_local_set_secret (char *buf)
619 if (!RtlGenRandom (connect_secret, sizeof (connect_secret)))
620 bzero ((char*) connect_secret, sizeof (connect_secret));
621 __small_sprintf (buf, "%08x-%08x-%08x-%08x",
622 connect_secret [0], connect_secret [1],
623 connect_secret [2], connect_secret [3]);
627 fhandler_socket_local::dup (fhandler_base *child, int flags)
629 if (get_flags () & O_PATH)
630 /* We're viewing the socket as a disk file, but fhandler_base::dup
631 suffices here. */
632 return fhandler_base::dup (child, flags);
634 fhandler_socket_local *fhs = (fhandler_socket_local *) child;
635 fhs->set_sun_path (get_sun_path ());
636 fhs->set_peer_sun_path (get_peer_sun_path ());
637 return fhandler_socket_wsock::dup (child, flags);
641 fhandler_socket_local::open (int flags, mode_t mode)
643 /* We don't support opening sockets unless O_PATH is specified. */
644 if (flags & O_PATH)
645 return open_fs (flags, mode);
647 set_errno (EOPNOTSUPP);
648 return 0;
652 fhandler_socket_local::close ()
654 if (get_flags () & O_PATH)
655 return fhandler_base::close ();
656 else
657 return fhandler_socket_wsock::close ();
661 fhandler_socket_local::fcntl (int cmd, intptr_t arg)
663 if (get_flags () & O_PATH)
664 /* We're viewing the socket as a disk file, but
665 fhandler_base::fcntl suffices here. */
666 return fhandler_base::fcntl (cmd, arg);
667 else
668 return fhandler_socket_wsock::fcntl (cmd, arg);
672 fhandler_socket_local::fstat (struct stat *buf)
674 if (!dev ().isfs ())
675 /* fstat called on a socket. */
676 return fhandler_socket_wsock::fstat (buf);
678 /* stat/lstat on a socket file or fstat on a socket opened w/ O_PATH. */
679 int res = fhandler_base::fstat_fs (buf);
680 if (!res)
682 buf->st_mode = (buf->st_mode & ~S_IFMT) | S_IFSOCK;
683 buf->st_size = 0;
685 return res;
689 fhandler_socket_local::fstatvfs (struct statvfs *sfs)
691 if (!dev ().isfs ())
692 /* fstatvfs called on a socket. */
693 return fhandler_socket_wsock::fstatvfs (sfs);
695 /* statvfs on a socket file or fstatvfs on a socket opened w/ O_PATH. */
696 if (get_flags () & O_PATH)
697 /* We already have a handle. */
699 HANDLE h = get_handle ();
700 if (h)
701 return fstatvfs_by_handle (h, sfs);
703 fhandler_disk_file fh (pc);
704 fh.get_device () = FH_FS;
705 return fh.fstatvfs (sfs);
709 fhandler_socket_local::fchmod (mode_t newmode)
711 if (!dev ().isfs ())
712 /* fchmod called on a socket. */
713 return fhandler_socket_wsock::fchmod (newmode);
715 /* chmod on a socket file. [We won't get here if fchmod is called
716 on a socket opened w/ O_PATH.] */
717 fhandler_disk_file fh (pc);
718 fh.get_device () = FH_FS;
719 return fh.fchmod (S_IFSOCK | adjust_socket_file_mode (newmode));
723 fhandler_socket_local::fchown (uid_t uid, gid_t gid)
725 if (!dev ().isfs ())
726 /* fchown called on a socket. */
727 return fhandler_socket_wsock::fchown (uid, gid);
729 /* chown/lchown on a socket file. [We won't get here if fchown is
730 called on a socket opened w/ O_PATH.] */
731 fhandler_disk_file fh (pc);
732 return fh.fchown (uid, gid);
736 fhandler_socket_local::facl (int cmd, int nentries, aclent_t *aclbufp)
738 if (!dev ().isfs ())
739 /* facl called on a socket. */
740 return fhandler_socket_wsock::facl (cmd, nentries, aclbufp);
742 /* facl on a socket file. [We won't get here if facl is called on a
743 socket opened w/ O_PATH.] */
744 fhandler_disk_file fh (pc);
745 return fh.facl (cmd, nentries, aclbufp);
749 fhandler_socket_local::link (const char *newpath)
751 if (!dev ().isfs ())
752 /* linkat w/ AT_EMPTY_PATH called on a socket not opened w/ O_PATH. */
753 return fhandler_socket_wsock::link (newpath);
754 /* link on a socket file or linkat w/ AT_EMPTY_PATH called on a
755 socket opened w/ O_PATH. */
756 fhandler_disk_file fh (pc);
757 if (get_flags () & O_PATH)
758 fh.set_handle (get_handle ());
759 return fh.link (newpath);
763 fhandler_socket_local::bind (const struct sockaddr *name, int namelen)
765 int res = -1;
767 #define un_addr ((struct sockaddr_un *) name)
768 struct sockaddr_in sin;
769 int len = namelen - offsetof (struct sockaddr_un, sun_path);
771 /* Check that name is within bounds. Don't check if the string is
772 NUL-terminated, because there are projects out there which set
773 namelen to a value which doesn't cover the trailing NUL. */
774 if (len <= 1 || (len = strnlen (un_addr->sun_path, len)) > UNIX_PATH_MAX)
776 set_errno (len <= 1 ? (len == 1 ? ENOENT : EINVAL) : ENAMETOOLONG);
777 return -1;
779 /* Copy over the sun_path string into a buffer big enough to add a
780 trailing NUL. */
781 char sun_path[len + 1];
782 strncpy (sun_path, un_addr->sun_path, len);
783 sun_path[len] = '\0';
785 /* This isn't entirely foolproof, but we check first if the file exists
786 so we can return with EADDRINUSE before having bound the socket.
787 This allows an application to call bind again on the same socket using
788 another filename. If we bind first, the application will not be able
789 to call bind successfully ever again. */
790 path_conv pc (sun_path, PC_SYM_FOLLOW);
791 if (pc.error)
793 set_errno (pc.error);
794 return -1;
796 if (pc.exists ())
798 set_errno (EADDRINUSE);
799 return -1;
802 sin.sin_family = AF_INET;
803 sin.sin_port = 0;
804 sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
805 if (::bind (get_socket (), (sockaddr *) &sin, len = sizeof sin))
807 syscall_printf ("AF_LOCAL: bind failed");
808 set_winsock_errno ();
809 return -1;
811 if (::getsockname (get_socket (), (sockaddr *) &sin, &len))
813 syscall_printf ("AF_LOCAL: getsockname failed");
814 set_winsock_errno ();
815 return -1;
818 sin.sin_port = ntohs (sin.sin_port);
819 debug_printf ("AF_LOCAL: socket bound to port %u", sin.sin_port);
821 mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
822 DWORD fattr = FILE_ATTRIBUTE_SYSTEM;
823 if (!pc.has_acls ()
824 && !(mode & ~cygheap->umask & (S_IWUSR | S_IWGRP | S_IWOTH)))
825 fattr |= FILE_ATTRIBUTE_READONLY;
826 SECURITY_ATTRIBUTES sa = sec_none_nih;
827 NTSTATUS status;
828 HANDLE fh;
829 OBJECT_ATTRIBUTES attr;
830 IO_STATUS_BLOCK io;
831 ULONG access = DELETE | FILE_GENERIC_WRITE;
833 /* If the filesystem supports ACLs, we will overwrite the DACL after the
834 call to NtCreateFile. This requires a handle with READ_CONTROL and
835 WRITE_DAC access, otherwise get_file_sd and set_file_sd both have to
836 open the file again.
837 FIXME: On remote NTFS shares open sometimes fails because even the
838 creator of the file doesn't have the right to change the DACL.
839 I don't know what setting that is or how to recognize such a share,
840 so for now we don't request WRITE_DAC on remote drives. */
841 if (pc.has_acls () && !pc.isremote ())
842 access |= READ_CONTROL | WRITE_DAC | WRITE_OWNER;
844 status = NtCreateFile (&fh, access, pc.get_object_attr (attr, sa), &io,
845 NULL, fattr, 0, FILE_CREATE,
846 FILE_NON_DIRECTORY_FILE
847 | FILE_SYNCHRONOUS_IO_NONALERT
848 | FILE_OPEN_FOR_BACKUP_INTENT,
849 NULL, 0);
850 if (!NT_SUCCESS (status))
852 if (io.Information == FILE_EXISTS)
853 set_errno (EADDRINUSE);
854 else
855 __seterrno_from_nt_status (status);
857 else
859 if (pc.has_acls ())
860 set_created_file_access (fh, pc, mode);
861 char buf[sizeof (SOCKET_COOKIE) + 80];
862 __small_sprintf (buf, "%s%u %c ", SOCKET_COOKIE, sin.sin_port,
863 get_socket_type () == SOCK_STREAM ? 's'
864 : get_socket_type () == SOCK_DGRAM ? 'd' : '-');
865 af_local_set_secret (strchr (buf, '\0'));
866 DWORD blen = strlen (buf) + 1;
867 status = NtWriteFile (fh, NULL, NULL, NULL, &io, buf, blen, NULL, 0);
868 if (!NT_SUCCESS (status))
870 __seterrno_from_nt_status (status);
871 FILE_DISPOSITION_INFORMATION fdi = { TRUE };
872 status = NtSetInformationFile (fh, &io, &fdi, sizeof fdi,
873 FileDispositionInformation);
874 if (!NT_SUCCESS (status))
875 debug_printf ("Setting delete dispostion failed, status = %y",
876 status);
878 else
880 set_sun_path (sun_path);
881 res = 0;
883 NtClose (fh);
885 #undef un_addr
887 return res;
891 fhandler_socket_local::connect (const struct sockaddr *name, int namelen)
893 struct sockaddr_storage sst;
894 int type = 0;
895 bool reset = (name->sa_family == AF_UNSPEC
896 && get_socket_type () == SOCK_DGRAM);
898 if (reset)
900 if (connect_state () == unconnected)
901 return 0;
902 /* To reset a connected DGRAM socket, call Winsock's connect
903 function with the address member of the sockaddr structure
904 filled with zeroes. */
905 memset (&sst, 0, sizeof sst);
906 sst.ss_family = get_addr_family ();
908 else if (get_inet_addr_local (name, namelen, &sst, &namelen, &type,
909 connect_secret) == SOCKET_ERROR)
910 return SOCKET_ERROR;
912 if (get_socket_type () != type && !reset)
914 WSASetLastError (WSAEPROTOTYPE);
915 set_winsock_errno ();
916 return SOCKET_ERROR;
919 if (reset)
920 set_peer_sun_path (NULL);
921 else
922 set_peer_sun_path (name->sa_data);
924 /* Don't move af_local_set_cred into af_local_connect which may be called
925 via select, possibly running under another identity. Call early here,
926 because af_local_connect is called in wait_for_events. */
927 if (get_socket_type () == SOCK_STREAM)
928 af_local_set_cred ();
930 /* Initialize connect state to "connect_pending". In the SOCK_STREAM
931 case, the state is ultimately set to "connected" or "connect_failed" in
932 wait_for_events when the FD_CONNECT event occurs. Note that the
933 underlying OS sockets are always non-blocking in this case and a
934 successfully initiated non-blocking Winsock connect always returns
935 WSAEWOULDBLOCK. Thus it's safe to rely on event handling. For DGRAM
936 sockets, however, connect can return immediately.
938 Check for either unconnected or connect_failed since in both cases it's
939 allowed to retry connecting the socket. It's also ok (albeit ugly) to
940 call connect to check if a previous non-blocking connect finished.
942 Set connect_state before calling connect, otherwise a race condition with
943 an already running select or poll might occur. */
944 if (connect_state () == unconnected || connect_state () == connect_failed)
945 connect_state (connect_pending);
947 int res = ::connect (get_socket (), (struct sockaddr *) &sst, namelen);
948 if (!res)
950 if (reset)
951 connect_state (unconnected);
952 else
953 connect_state (connected);
955 else if (!is_nonblocking ()
956 && res == SOCKET_ERROR
957 && WSAGetLastError () == WSAEWOULDBLOCK)
958 res = wait_for_events (FD_CONNECT | FD_CLOSE, 0);
960 if (res)
962 DWORD err = WSAGetLastError ();
964 /* Some applications use the ugly technique to check if a non-blocking
965 connect succeeded by calling connect again, until it returns EISCONN.
966 This circumvents the event handling and connect_state is never set.
967 Thus we check for this situation here. */
968 if (err == WSAEISCONN)
969 connect_state (connected);
970 /* Winsock returns WSAEWOULDBLOCK if the non-blocking socket cannot be
971 conected immediately. Convert to POSIX/Linux compliant EINPROGRESS. */
972 else if (is_nonblocking () && err == WSAEWOULDBLOCK)
973 WSASetLastError (WSAEINPROGRESS);
974 /* Winsock returns WSAEINVAL if the socket is already a listener.
975 Convert to POSIX/Linux compliant EISCONN. */
976 else if (err == WSAEINVAL && connect_state () == listener)
977 WSASetLastError (WSAEISCONN);
978 /* Any other error except WSAEALREADY means the connect failed. */
979 else if (connect_state () == connect_pending && err != WSAEALREADY)
980 connect_state (connect_failed);
981 set_winsock_errno ();
984 return res;
988 fhandler_socket_local::listen (int backlog)
990 int res = ::listen (get_socket (), backlog);
991 if (res && WSAGetLastError () == WSAEINVAL)
993 /* It's perfectly valid to call listen on an unbound INET socket.
994 In this case the socket is automatically bound to an unused
995 port number, listening on all interfaces. On WinSock, listen
996 fails with WSAEINVAL when it's called on an unbound socket.
997 So we have to bind manually here to have POSIX semantics. */
998 if (get_addr_family () == AF_INET)
1000 struct sockaddr_in sin;
1001 sin.sin_family = AF_INET;
1002 sin.sin_port = 0;
1003 sin.sin_addr.s_addr = INADDR_ANY;
1004 if (!::bind (get_socket (), (struct sockaddr *) &sin, sizeof sin))
1005 res = ::listen (get_socket (), backlog);
1007 else if (get_addr_family () == AF_INET6)
1009 struct sockaddr_in6 sin6;
1010 memset (&sin6, 0, sizeof sin6);
1011 sin6.sin6_family = AF_INET6;
1012 if (!::bind (get_socket (), (struct sockaddr *) &sin6, sizeof sin6))
1013 res = ::listen (get_socket (), backlog);
1016 if (!res)
1018 if (get_addr_family () == AF_LOCAL && get_socket_type () == SOCK_STREAM)
1019 af_local_set_cred ();
1020 connect_state (listener); /* gets set to connected on accepted socket. */
1022 else
1023 set_winsock_errno ();
1024 return res;
1028 fhandler_socket_local::accept4 (struct sockaddr *peer, int *len, int flags)
1030 int ret = -1;
1031 /* Allows NULL peer and len parameters. */
1032 struct sockaddr_storage lpeer;
1033 int llen = sizeof (struct sockaddr_storage);
1035 /* Windows event handling does not check for the validity of the desired
1036 flags so we have to do it here. */
1037 if (connect_state () != listener)
1039 WSASetLastError (WSAEINVAL);
1040 set_winsock_errno ();
1041 return -1;
1044 SOCKET res = INVALID_SOCKET;
1045 while (!(res = wait_for_events (FD_ACCEPT | FD_CLOSE, 0))
1046 && (res = ::accept (get_socket (), (struct sockaddr *) &lpeer, &llen))
1047 == INVALID_SOCKET
1048 && WSAGetLastError () == WSAEWOULDBLOCK)
1050 if (res == INVALID_SOCKET)
1051 set_winsock_errno ();
1052 else
1054 cygheap_fdnew fd;
1056 if (fd >= 0)
1058 fhandler_socket_local *sock = (fhandler_socket_local *)
1059 build_fh_dev (dev ());
1060 if (sock && sock->set_socket_handle (res, get_addr_family (),
1061 get_socket_type (),
1062 get_socket_flags ()) == 0)
1064 sock->async_io (false); /* set_socket_handle disables async. */
1065 sock->set_sun_path (get_sun_path ());
1066 sock->set_peer_sun_path (get_peer_sun_path ());
1067 if (get_socket_type () == SOCK_STREAM)
1069 /* Don't forget to copy credentials from accepting
1070 socket to accepted socket and start transaction
1071 on accepted socket! */
1072 af_local_copy (sock);
1073 ret = sock->af_local_accept ();
1074 if (ret == -1)
1076 delete sock;
1077 set_winsock_errno ();
1078 return -1;
1081 /* No locking necessary at this point. */
1082 sock->wsock_events->events = wsock_events->events | FD_WRITE;
1083 sock->wsock_events->owner = wsock_events->owner;
1084 sock->connect_state (connected);
1085 fd = sock;
1086 if (fd <= 2)
1087 set_std_handle (fd);
1088 ret = fd;
1089 if (peer)
1091 /* FIXME: Right now we have no way to determine the
1092 bound socket name of the peer's socket. For now
1093 we just fake an unbound socket on the other side. */
1094 static struct sockaddr_un un = { AF_LOCAL, "" };
1095 memcpy (peer, &un, MIN (*len, (int) sizeof (un.sun_family)));
1096 *len = (int) sizeof (un.sun_family);
1099 else
1100 delete sock;
1102 if (ret == -1)
1103 ::closesocket (res);
1105 return ret;
1109 fhandler_socket_local::getsockname (struct sockaddr *name, int *namelen)
1111 struct sockaddr_un sun;
1113 sun.sun_family = AF_LOCAL;
1114 sun.sun_path[0] = '\0';
1115 if (get_sun_path ())
1116 strncat (sun.sun_path, get_sun_path (), UNIX_PATH_MAX - 1);
1117 memcpy (name, &sun, MIN (*namelen, (int) SUN_LEN (&sun) + 1));
1118 *namelen = (int) SUN_LEN (&sun) + (get_sun_path () ? 1 : 0);
1119 return 0;
1123 fhandler_socket_local::getpeername (struct sockaddr *name, int *namelen)
1125 /* Always use a local big enough buffer and truncate later as necessary
1126 per POSIX. WinSock unfortunately only returns WSAEFAULT if the buffer
1127 is too small. */
1128 struct sockaddr_storage sock;
1129 int len = sizeof sock;
1130 int res = ::getpeername (get_socket (), (struct sockaddr *) &sock, &len);
1131 if (res)
1132 set_winsock_errno ();
1133 else
1135 struct sockaddr_un sun;
1136 memset (&sun, 0, sizeof sun);
1137 sun.sun_family = AF_LOCAL;
1138 sun.sun_path[0] = '\0';
1139 if (get_peer_sun_path ())
1140 strncat (sun.sun_path, get_peer_sun_path (), UNIX_PATH_MAX - 1);
1141 memcpy (name, &sun, MIN (*namelen, (int) SUN_LEN (&sun) + 1));
1142 *namelen = (int) SUN_LEN (&sun) + (get_peer_sun_path () ? 1 : 0);
1144 return res;
1147 ssize_t
1148 fhandler_socket_local::recv_internal (LPWSAMSG wsamsg, bool use_recvmsg)
1150 ssize_t res = 0;
1151 DWORD ret = 0, wret;
1152 int evt_mask = FD_READ;
1153 LPWSABUF &wsabuf = wsamsg->lpBuffers;
1154 ULONG &wsacnt = wsamsg->dwBufferCount;
1155 static NO_COPY LPFN_WSARECVMSG WSARecvMsg;
1156 int orig_namelen = wsamsg->namelen;
1158 /* CV 2014-10-26: Do not check for the connect_state at this point. In
1159 certain scenarios there's no way to check the connect state reliably.
1160 Example (hexchat): Parent process creates socket, forks, child process
1161 calls connect, parent process calls read. Even if the event handling
1162 allows to check for FD_CONNECT in the parent, there is always yet another
1163 scenario we can easily break. */
1165 DWORD wait_flags = wsamsg->dwFlags;
1166 bool waitall = !!(wait_flags & MSG_WAITALL);
1168 /* Out-of-band data not supported by AF_LOCAL */
1169 if (wsamsg->dwFlags & MSG_OOB)
1171 set_errno (EOPNOTSUPP);
1172 return SOCKET_ERROR;
1175 wsamsg->dwFlags &= (MSG_PEEK | MSG_DONTROUTE);
1176 if (use_recvmsg)
1178 if (!WSARecvMsg
1179 && get_ext_funcptr (get_socket (), &WSARecvMsg) == SOCKET_ERROR)
1181 if (wsamsg->Control.len > 0)
1183 set_winsock_errno ();
1184 return SOCKET_ERROR;
1186 use_recvmsg = false;
1188 else /* Only MSG_PEEK is supported by WSARecvMsg. */
1189 wsamsg->dwFlags &= MSG_PEEK;
1191 if (waitall)
1193 if (get_socket_type () != SOCK_STREAM)
1195 WSASetLastError (WSAEOPNOTSUPP);
1196 set_winsock_errno ();
1197 return SOCKET_ERROR;
1199 if (is_nonblocking () || (wsamsg->dwFlags & MSG_PEEK))
1200 waitall = false;
1203 /* Note: Don't call WSARecvFrom(MSG_PEEK) without actually having data
1204 waiting in the buffers, otherwise the event handling gets messed up
1205 for some reason. */
1206 while (!(res = wait_for_events (evt_mask | FD_CLOSE, wait_flags))
1207 || saw_shutdown_read ())
1209 DWORD dwFlags = wsamsg->dwFlags;
1210 if (use_recvmsg)
1211 res = WSARecvMsg (get_socket (), wsamsg, &wret, NULL, NULL);
1212 /* This is working around a really weird problem in WinSock.
1214 Assume you create a socket, fork the process (thus duplicating
1215 the socket), connect the socket in the child, then call recv
1216 on the original socket handle in the parent process.
1217 In this scenario, calls to WinSock's recvfrom and WSARecvFrom
1218 in the parent will fail with WSAEINVAL, regardless whether both
1219 address parameters, name and namelen, are NULL or point to valid
1220 storage. However, calls to recv and WSARecv succeed as expected.
1221 Per MSDN, WSAEINVAL in the context of recv means "The socket has not
1222 been bound". It is as if the recvfrom functions test if the socket
1223 is bound locally, but in the parent process, WinSock doesn't know
1224 about that and fails, while the same test is omitted in the recv
1225 functions.
1227 This also covers another weird case: WinSock returns WSAEFAULT if
1228 namelen is a valid pointer while name is NULL. Both parameters are
1229 ignored for TCP sockets, so this only occurs when using UDP socket. */
1230 else if (!wsamsg->name || get_socket_type () == SOCK_STREAM)
1231 res = WSARecv (get_socket (), wsabuf, wsacnt, &wret, &dwFlags,
1232 NULL, NULL);
1233 else
1234 res = WSARecvFrom (get_socket (), wsabuf, wsacnt, &wret,
1235 &dwFlags, wsamsg->name, &wsamsg->namelen,
1236 NULL, NULL);
1237 if (!res)
1239 ret += wret;
1240 if (!waitall)
1241 break;
1242 while (wret && wsacnt)
1244 if (wsabuf->len > wret)
1246 wsabuf->len -= wret;
1247 wsabuf->buf += wret;
1248 wret = 0;
1250 else
1252 wret -= wsabuf->len;
1253 ++wsabuf;
1254 --wsacnt;
1257 if (!wsacnt)
1258 break;
1260 else if (WSAGetLastError () != WSAEWOULDBLOCK)
1261 break;
1264 if (res)
1266 /* According to SUSv3, errno isn't set in that case and no error
1267 condition is returned. */
1268 if (WSAGetLastError () == WSAEMSGSIZE)
1269 ret += wret;
1270 else if (!ret)
1272 /* ESHUTDOWN isn't defined for recv in SUSv3. Simply EOF is returned
1273 in this case. */
1274 if (WSAGetLastError () == WSAESHUTDOWN)
1275 ret = 0;
1276 else
1278 set_winsock_errno ();
1279 return SOCKET_ERROR;
1284 if (wsamsg->name != NULL && orig_namelen >= (int) sizeof (sa_family_t))
1286 /* WSARecvFrom copied the sockaddr_in block to wsamsg->name. We have to
1287 overwrite it with a sockaddr_un block. For datagram sockets we
1288 generate a sockaddr_un with a filename analogue to abstract socket
1289 names under Linux. See `man 7 unix' under Linux for a description. */
1290 sockaddr_un *un = (sockaddr_un *) wsamsg->name;
1291 un->sun_family = AF_LOCAL;
1292 int len = orig_namelen - offsetof (struct sockaddr_un, sun_path);
1293 if (len > 0)
1295 if (get_socket_type () == SOCK_DGRAM)
1297 if (len >= 7)
1299 __small_sprintf (un->sun_path + 1, "d%04x",
1300 ((struct sockaddr_in *) wsamsg->name)->sin_port);
1301 wsamsg->namelen = offsetof (struct sockaddr_un, sun_path) + 7;
1303 else
1304 wsamsg->namelen = offsetof (struct sockaddr_un, sun_path) + 1;
1305 un->sun_path[0] = '\0';
1307 else if (!get_peer_sun_path ())
1308 wsamsg->namelen = sizeof (sa_family_t);
1309 else
1311 memset (un->sun_path, 0, len);
1312 strncpy (un->sun_path, get_peer_sun_path (), len);
1313 if (un->sun_path[len - 1] == '\0')
1314 len = strlen (un->sun_path) + 1;
1315 if (len > UNIX_PATH_MAX)
1316 len = UNIX_PATH_MAX;
1317 wsamsg->namelen = offsetof (struct sockaddr_un, sun_path) + len;
1322 return ret;
1325 ssize_t
1326 fhandler_socket_local::sendto (const void *in_ptr, size_t len, int flags,
1327 const struct sockaddr *to, int tolen)
1329 char *ptr = (char *) in_ptr;
1330 struct sockaddr_storage sst;
1332 /* Out-of-band data not supported by AF_LOCAL */
1333 if (flags & MSG_OOB)
1335 set_errno (EOPNOTSUPP);
1336 return SOCKET_ERROR;
1339 if (to && get_inet_addr_local (to, tolen, &sst, &tolen) == SOCKET_ERROR)
1340 return SOCKET_ERROR;
1342 /* size_t is 64 bit, but the len member in WSABUF is 32 bit.
1343 Split buffer if necessary. */
1344 DWORD bufcnt = len / UINT32_MAX + ((!len || (len % UINT32_MAX)) ? 1 : 0);
1345 WSABUF wsabuf[bufcnt];
1346 WSAMSG wsamsg = { to ? (struct sockaddr *) &sst : NULL, tolen,
1347 wsabuf, bufcnt,
1348 { 0, NULL },
1349 0 };
1350 /* Don't use len as loop condition, it could be 0. */
1351 for (WSABUF *wsaptr = wsabuf; bufcnt--; ++wsaptr)
1353 wsaptr->len = MIN (len, UINT32_MAX);
1354 wsaptr->buf = ptr;
1355 len -= wsaptr->len;
1356 ptr += wsaptr->len;
1358 return send_internal (&wsamsg, flags);
1361 ssize_t
1362 fhandler_socket_local::sendmsg (const struct msghdr *msg, int flags)
1364 /* TODO: Descriptor passing on AF_LOCAL sockets. */
1366 struct sockaddr_storage sst;
1367 int len = 0;
1369 /* Out-of-band data not supported by AF_LOCAL */
1370 if (flags & MSG_OOB)
1372 set_errno (EOPNOTSUPP);
1373 return SOCKET_ERROR;
1376 if (msg->msg_name
1377 && get_inet_addr_local ((struct sockaddr *) msg->msg_name,
1378 msg->msg_namelen, &sst, &len) == SOCKET_ERROR)
1379 return SOCKET_ERROR;
1381 WSABUF wsabuf[msg->msg_iovlen];
1382 WSABUF *wsaptr = wsabuf;
1383 const struct iovec *iovptr = msg->msg_iov;
1384 for (int i = 0; i < msg->msg_iovlen; ++i)
1386 wsaptr->len = iovptr->iov_len;
1387 (wsaptr++)->buf = (char *) (iovptr++)->iov_base;
1389 /* Disappointing but true: Even if WSASendMsg is supported, it's only
1390 supported for datagram and raw sockets. */
1391 DWORD controllen = (DWORD) (get_socket_type () == SOCK_STREAM
1392 || get_addr_family () == AF_LOCAL
1393 ? 0 : msg->msg_controllen);
1394 WSAMSG wsamsg = { msg->msg_name ? (struct sockaddr *) &sst : NULL, len,
1395 wsabuf, (DWORD) msg->msg_iovlen,
1396 { controllen, (char *) msg->msg_control },
1397 0 };
1398 return send_internal (&wsamsg, flags);
1401 void
1402 fhandler_socket_local::set_sun_path (const char *path)
1404 sun_path = path ? cstrdup (path) : NULL;
1407 void
1408 fhandler_socket_local::set_peer_sun_path (const char *path)
1410 peer_sun_path = path ? cstrdup (path) : NULL;
1414 fhandler_socket_local::getpeereid (pid_t *pid, uid_t *euid, gid_t *egid)
1416 if (get_socket_type () != SOCK_STREAM)
1418 set_errno (EINVAL);
1419 return -1;
1421 if (no_getpeereid ())
1423 set_errno (ENOTSUP);
1424 return -1;
1426 if (connect_state () != connected)
1428 set_errno (ENOTCONN);
1429 return -1;
1432 __try
1434 if (pid)
1435 *pid = sec_peer_pid;
1436 if (euid)
1437 *euid = sec_peer_uid;
1438 if (egid)
1439 *egid = sec_peer_gid;
1440 return 0;
1442 __except (EFAULT) {}
1443 __endtry
1444 return -1;
1448 fhandler_socket_local::setsockopt (int level, int optname, const void *optval,
1449 socklen_t optlen)
1451 int ret = -1;
1453 /* Preprocessing setsockopt. */
1454 switch (level)
1456 case SOL_SOCKET:
1457 switch (optname)
1459 case SO_PEERCRED:
1460 /* Switch off the AF_LOCAL handshake and thus SO_PEERCRED handling
1461 for AF_LOCAL/SOCK_STREAM sockets. This allows to handle special
1462 situations in which connect is called before a listening socket
1463 accepts connections.
1464 FIXME: In the long run we should find a more generic solution
1465 which doesn't require a blocking handshake in accept/connect
1466 to exchange SO_PEERCRED credentials. */
1467 /* Temporary: Allow SO_PEERCRED to only be zeroed. Two ways to
1468 accomplish this: pass NULL,0 for optval,optlen; or pass the
1469 address,length of an '(int) 0' set up by the caller. */
1470 if ((!optval && !optlen) ||
1471 (optlen == (socklen_t) sizeof (int) && !*(int *) optval))
1472 ret = af_local_set_no_getpeereid ();
1473 else
1474 set_errno (EINVAL);
1475 return ret;
1477 case SO_REUSEADDR:
1478 saw_reuseaddr (*(int *) optval);
1479 return 0;
1481 case SO_RCVTIMEO:
1482 case SO_SNDTIMEO:
1483 if (optlen < (socklen_t) sizeof (struct timeval))
1485 set_errno (EINVAL);
1486 return ret;
1488 if (timeval_to_ms ((struct timeval *) optval,
1489 (optname == SO_RCVTIMEO) ? rcvtimeo ()
1490 : sndtimeo ()))
1491 return 0;
1492 set_errno (EDOM);
1493 return -1;
1495 case SO_DEBUG:
1496 case SO_RCVBUF:
1497 case SO_RCVLOWAT:
1498 case SO_SNDBUF:
1499 case SO_SNDLOWAT:
1500 break;
1502 default:
1503 /* AF_LOCAL sockets simply ignore all other SOL_SOCKET options. */
1504 return 0;
1506 break;
1508 default:
1509 set_errno (ENOPROTOOPT);
1510 return -1;
1513 /* Call Winsock setsockopt */
1514 ret = ::setsockopt (get_socket (), level, optname, (const char *) optval,
1515 optlen);
1516 if (ret == SOCKET_ERROR)
1518 set_winsock_errno ();
1519 return ret;
1522 if (optlen == (socklen_t) sizeof (int))
1523 debug_printf ("setsockopt optval=%x", *(int *) optval);
1525 /* Postprocessing setsockopt, setting fhandler_socket members, etc. */
1526 switch (level)
1528 case SOL_SOCKET:
1529 switch (optname)
1531 case SO_RCVBUF:
1532 rmem (*(int *) optval);
1533 break;
1535 case SO_SNDBUF:
1536 wmem (*(int *) optval);
1537 break;
1539 default:
1540 break;
1542 break;
1544 default:
1545 break;
1548 return ret;
1552 fhandler_socket_local::getsockopt (int level, int optname, const void *optval,
1553 socklen_t *optlen)
1555 int ret = -1;
1557 /* Preprocessing getsockopt.*/
1558 switch (level)
1560 case SOL_SOCKET:
1561 switch (optname)
1563 case SO_PEERCRED:
1565 struct ucred *cred = (struct ucred *) optval;
1567 if (*optlen < (socklen_t) sizeof *cred)
1569 set_errno (EINVAL);
1570 return ret;
1572 ret = getpeereid (&cred->pid, &cred->uid, &cred->gid);
1573 if (!ret)
1574 *optlen = (socklen_t) sizeof *cred;
1575 return ret;
1578 case SO_REUSEADDR:
1580 unsigned int *reuseaddr = (unsigned int *) optval;
1582 if (*optlen < (socklen_t) sizeof *reuseaddr)
1584 set_errno (EINVAL);
1585 return -1;
1587 *reuseaddr = saw_reuseaddr();
1588 *optlen = (socklen_t) sizeof *reuseaddr;
1589 return 0;
1592 case SO_RCVTIMEO:
1593 case SO_SNDTIMEO:
1595 struct timeval *time_out = (struct timeval *) optval;
1597 if (*optlen < (socklen_t) sizeof *time_out)
1599 set_errno (EINVAL);
1600 return ret;
1602 DWORD ms = (optname == SO_RCVTIMEO) ? rcvtimeo () : sndtimeo ();
1603 if (ms == 0 || ms == INFINITE)
1605 time_out->tv_sec = 0;
1606 time_out->tv_usec = 0;
1608 else
1610 time_out->tv_sec = ms / MSPERSEC;
1611 time_out->tv_usec = ((ms % MSPERSEC) * USPERSEC) / MSPERSEC;
1613 *optlen = (socklen_t) sizeof *time_out;
1614 return 0;
1617 case SO_TYPE:
1619 unsigned int *type = (unsigned int *) optval;
1620 *type = get_socket_type ();
1621 *optlen = (socklen_t) sizeof *type;
1622 return 0;
1625 case SO_ACCEPTCONN:
1626 case SO_DEBUG:
1627 case SO_ERROR:
1628 case SO_RCVBUF:
1629 case SO_RCVLOWAT:
1630 case SO_SNDBUF:
1631 case SO_SNDLOWAT:
1632 break;
1634 /* AF_LOCAL sockets simply ignore all other SOL_SOCKET options. */
1636 case SO_LINGER:
1638 struct linger *linger = (struct linger *) optval;
1639 memset (linger, 0, sizeof *linger);
1640 *optlen = (socklen_t) sizeof *linger;
1641 return 0;
1644 default:
1646 unsigned int *val = (unsigned int *) optval;
1647 *val = 0;
1648 *optlen = (socklen_t) sizeof *val;
1649 return 0;
1652 break;
1654 default:
1655 set_errno (ENOPROTOOPT);
1656 return -1;
1659 /* Call Winsock getsockopt */
1660 ret = ::getsockopt (get_socket (), level, optname, (char *) optval,
1661 (int *) optlen);
1662 if (ret == SOCKET_ERROR)
1664 set_winsock_errno ();
1665 return ret;
1668 /* Postprocessing getsockopt, setting fhandler_socket members, etc. */
1669 switch (level)
1671 case SOL_SOCKET:
1672 switch (optname)
1674 case SO_ERROR:
1676 int *e = (int *) optval;
1677 debug_printf ("WinSock SO_ERROR = %d", *e);
1678 *e = find_winsock_errno (*e);
1680 break;
1682 default:
1683 break;
1685 break;
1686 default:
1687 break;
1690 return ret;