* fhandler.h (fhandler_socket::bind): Add method definition.
(fhandler_socket::connect): Ditto. (fhandler_socket::listen): Ditto. (fhandler_socket::accept): Ditto. (fhandler_socket::getsockname): Ditto. (fhandler_socket::getpeername): Ditto. (fhandler_socket::recvfrom): Ditto. (fhandler_socket::recvmsg): Ditto. (fhandler_socket::sendto): Ditto. (fhandler_socket::sendmsg): Ditto. (fhandler_socket::shutdown): Ditto. * fhandler_socket.cc (get_inet_addr): Move here from net.cc. (fhandler_socket::bind): New method. (fhandler_socket::connect): Ditto. (fhandler_socket::listen): Ditto. (fhandler_socket::accept): Ditto. (fhandler_socket::getsockname): Ditto. (fhandler_socket::getpeername): Ditto. (fhandler_socket::recvfrom): Ditto. (fhandler_socket::recvmsg): Ditto. (fhandler_socket::sendto): Ditto. (fhandler_socket::sendmsg): Ditto. (fhandler_socket::shutdown): Ditto. * net.cc: Various formatting cleanups throughout. (get_inet_addr): Move to fhandler_socket.cc. (cygwin_bind): Move base functionality to appropriate fhandler_socket method. (cygwin_connect): Ditto. (cygwin_listen): Ditto. (cygwin_accept): Ditto. (cygwin_getsockname): Ditto. (cygwin_getpeername): Ditto. (cygwin_recvfrom): Ditto. (cygwin_recvmsg): Ditto. (cygwin_sendto): Ditto. (cygwin_sendmsg): Ditto. (cygwin_shutdown): Ditto.
This commit is contained in:
		| @@ -1,3 +1,43 @@ | ||||
| 2002-06-26  Corinna Vinschen  <corinna@vinschen.de> | ||||
|  | ||||
| 	* fhandler.h (fhandler_socket::bind): Add method definition. | ||||
| 	(fhandler_socket::connect): Ditto. | ||||
| 	(fhandler_socket::listen): Ditto. | ||||
| 	(fhandler_socket::accept): Ditto. | ||||
| 	(fhandler_socket::getsockname): Ditto. | ||||
| 	(fhandler_socket::getpeername): Ditto. | ||||
| 	(fhandler_socket::recvfrom): Ditto. | ||||
| 	(fhandler_socket::recvmsg): Ditto. | ||||
| 	(fhandler_socket::sendto): Ditto. | ||||
| 	(fhandler_socket::sendmsg): Ditto. | ||||
| 	(fhandler_socket::shutdown): Ditto. | ||||
| 	* fhandler_socket.cc (get_inet_addr): Move here from net.cc. | ||||
| 	(fhandler_socket::bind): New method. | ||||
| 	(fhandler_socket::connect): Ditto. | ||||
| 	(fhandler_socket::listen): Ditto. | ||||
| 	(fhandler_socket::accept): Ditto. | ||||
| 	(fhandler_socket::getsockname): Ditto. | ||||
| 	(fhandler_socket::getpeername): Ditto. | ||||
| 	(fhandler_socket::recvfrom): Ditto. | ||||
| 	(fhandler_socket::recvmsg): Ditto. | ||||
| 	(fhandler_socket::sendto): Ditto. | ||||
| 	(fhandler_socket::sendmsg): Ditto. | ||||
| 	(fhandler_socket::shutdown): Ditto. | ||||
| 	* net.cc: Various formatting cleanups throughout. | ||||
| 	(get_inet_addr): Move to fhandler_socket.cc. | ||||
| 	(cygwin_bind): Move base functionality to appropriate fhandler_socket | ||||
| 	method. | ||||
| 	(cygwin_connect): Ditto. | ||||
| 	(cygwin_listen): Ditto. | ||||
| 	(cygwin_accept): Ditto. | ||||
| 	(cygwin_getsockname): Ditto. | ||||
| 	(cygwin_getpeername): Ditto. | ||||
| 	(cygwin_recvfrom): Ditto. | ||||
| 	(cygwin_recvmsg): Ditto. | ||||
| 	(cygwin_sendto): Ditto. | ||||
| 	(cygwin_sendmsg): Ditto. | ||||
| 	(cygwin_shutdown): Ditto. | ||||
|  | ||||
| 2002-06-26  Corinna Vinschen  <corinna@vinschen.de> | ||||
|  | ||||
| 	* pwdgrp.h (pwdgrp_read::~pwdgrp_read): Avoid compiler warning. | ||||
|   | ||||
| @@ -380,15 +380,30 @@ class fhandler_socket: public fhandler_base | ||||
|   void set_shutdown_read () {FHSETF (SHUTRD);} | ||||
|   void set_shutdown_write () {FHSETF (SHUTWR);} | ||||
|  | ||||
|   int bind (const struct sockaddr *name, int namelen); | ||||
|   int connect (const struct sockaddr *name, int namelen); | ||||
|   int listen (int backlog); | ||||
|   int accept (struct sockaddr *peer, int *len); | ||||
|   int getsockname (struct sockaddr *name, int *namelen); | ||||
|   int getpeername (struct sockaddr *name, int *namelen); | ||||
|  | ||||
|   int recv (void *ptr, size_t len, unsigned int flags); | ||||
|   int __stdcall read (void *ptr, size_t len) __attribute__ ((regparm (3))); | ||||
|   int recvfrom (void *ptr, size_t len, unsigned int flags, | ||||
| 		struct sockaddr *from, int *fromlen); | ||||
|   int recvmsg (struct msghdr *msg, int flags); | ||||
|  | ||||
|   int send (const void *ptr, size_t len, unsigned int flags); | ||||
|   int write (const void *ptr, size_t len); | ||||
|  | ||||
|   int sendto (const void *ptr, size_t len, unsigned int flags, | ||||
| 	      const struct sockaddr *to, int tolen); | ||||
|   int sendmsg (const struct msghdr *msg, int flags); | ||||
|  | ||||
|   int ioctl (unsigned int cmd, void *); | ||||
|   int fcntl (int cmd, void *); | ||||
|   __off64_t lseek (__off64_t, int) { return 0; } | ||||
|   int shutdown (int how); | ||||
|   int close (); | ||||
|   void hclose (HANDLE) {close ();} | ||||
|   int dup (fhandler_base *child); | ||||
|   | ||||
| @@ -15,6 +15,8 @@ | ||||
| #include "winsup.h" | ||||
| #include <errno.h> | ||||
| #include <sys/socket.h> | ||||
| #include <sys/un.h> | ||||
| #include <sys/uio.h> | ||||
| #include <asm/byteorder.h> | ||||
|  | ||||
| #include <stdlib.h> | ||||
| @@ -36,8 +38,59 @@ | ||||
| #define ENTROPY_SOURCE_NAME "/dev/urandom" | ||||
| #define ENTROPY_SOURCE_DEV_UNIT 9 | ||||
|  | ||||
| extern fhandler_socket *fdsock (int& fd, const char *name, SOCKET soc); | ||||
| extern "C" { | ||||
| int sscanf (const char *, const char *, ...); | ||||
| } /* End of "C" section */ | ||||
|  | ||||
| fhandler_dev_random* entropy_source; | ||||
|  | ||||
| /* cygwin internal: map sockaddr into internet domain address */ | ||||
| static int | ||||
| get_inet_addr (const struct sockaddr *in, int inlen, | ||||
|                struct sockaddr_in *out, int *outlen, int* secret = 0) | ||||
| { | ||||
|   int secret_buf [4]; | ||||
|   int* secret_ptr = (secret ? : secret_buf); | ||||
|  | ||||
|   if (in->sa_family == AF_INET) | ||||
|     { | ||||
|       *out = * (sockaddr_in *)in; | ||||
|       *outlen = inlen; | ||||
|       return 1; | ||||
|     } | ||||
|   else if (in->sa_family == AF_LOCAL) | ||||
|     { | ||||
|       int fd = _open (in->sa_data, O_RDONLY); | ||||
|       if (fd == -1) | ||||
|         return 0; | ||||
|  | ||||
|       int ret = 0; | ||||
|       char buf[128]; | ||||
|       memset (buf, 0, sizeof buf); | ||||
|       if (read (fd, buf, sizeof buf) != -1) | ||||
|         { | ||||
|           sockaddr_in sin; | ||||
|           sin.sin_family = AF_INET; | ||||
|           sscanf (buf + strlen (SOCKET_COOKIE), "%hu %08x-%08x-%08x-%08x", | ||||
|                   &sin.sin_port, | ||||
|                   secret_ptr, secret_ptr + 1, secret_ptr + 2, secret_ptr + 3); | ||||
|           sin.sin_port = htons (sin.sin_port); | ||||
|           sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK); | ||||
|           *out = sin; | ||||
|           *outlen = sizeof sin; | ||||
|           ret = 1; | ||||
|         } | ||||
|       _close (fd); | ||||
|       return ret; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       set_errno (EAFNOSUPPORT); | ||||
|       return 0; | ||||
|     } | ||||
| } | ||||
|  | ||||
| /**********************************************************************/ | ||||
| /* fhandler_socket */ | ||||
|  | ||||
| @@ -93,7 +146,7 @@ fhandler_socket::create_secret_event (int* secret) | ||||
|   struct sockaddr_in sin; | ||||
|   int sin_len = sizeof (sin); | ||||
|  | ||||
|   if (getsockname (get_socket (), (struct sockaddr*) &sin, &sin_len)) | ||||
|   if (::getsockname (get_socket (), (struct sockaddr*) &sin, &sin_len)) | ||||
|     { | ||||
|       debug_printf ("error getting local socket name (%d)", WSAGetLastError ()); | ||||
|       return NULL; | ||||
| @@ -256,6 +309,293 @@ fhandler_socket::fstat (struct __stat64 *buf, path_conv *pc) | ||||
|   return res; | ||||
| } | ||||
|  | ||||
| int | ||||
| fhandler_socket::bind (const struct sockaddr *name, int namelen) | ||||
| { | ||||
|   int res = -1; | ||||
|  | ||||
|   if (name->sa_family == AF_LOCAL) | ||||
|     { | ||||
| #define un_addr ((struct sockaddr_un *) name) | ||||
|       struct sockaddr_in sin; | ||||
|       int len = sizeof sin;  | ||||
|       int fd; | ||||
|  | ||||
|       if (strlen (un_addr->sun_path) >= UNIX_PATH_LEN) | ||||
| 	{ | ||||
| 	  set_errno (ENAMETOOLONG); | ||||
| 	  goto out; | ||||
| 	} | ||||
|       sin.sin_family = AF_INET; | ||||
|       sin.sin_port = 0; | ||||
|       sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK); | ||||
|       if (::bind (get_socket (), (sockaddr *) &sin, len)) | ||||
| 	{ | ||||
| 	  syscall_printf ("AF_LOCAL: bind failed %d", get_errno ()); | ||||
| 	  set_winsock_errno (); | ||||
| 	  goto out; | ||||
| 	} | ||||
|       if (::getsockname (get_socket (), (sockaddr *) &sin, &len)) | ||||
| 	{ | ||||
| 	  syscall_printf ("AF_LOCAL: getsockname failed %d", get_errno ()); | ||||
| 	  set_winsock_errno (); | ||||
| 	  goto out; | ||||
| 	} | ||||
|  | ||||
|       sin.sin_port = ntohs (sin.sin_port); | ||||
|       debug_printf ("AF_LOCAL: socket bound to port %u", sin.sin_port); | ||||
|  | ||||
|       /* bind must fail if file system socket object already exists | ||||
| 	 so _open () is called with O_EXCL flag. */ | ||||
|       fd = _open (un_addr->sun_path, | ||||
| 		  O_WRONLY | O_CREAT | O_EXCL | O_BINARY, | ||||
| 		  0); | ||||
|       if (fd < 0) | ||||
| 	{ | ||||
| 	  if (get_errno () == EEXIST) | ||||
| 	    set_errno (EADDRINUSE); | ||||
| 	  goto out; | ||||
| 	} | ||||
|  | ||||
|       set_connect_secret (); | ||||
|  | ||||
|       char buf[sizeof (SOCKET_COOKIE) + 80]; | ||||
|       __small_sprintf (buf, "%s%u ", SOCKET_COOKIE, sin.sin_port); | ||||
|       get_connect_secret (strchr (buf, '\0')); | ||||
|       len = strlen (buf) + 1; | ||||
|  | ||||
|       /* Note that the terminating nul is written.  */ | ||||
|       if (_write (fd, buf, len) != len) | ||||
| 	{ | ||||
| 	  save_errno here; | ||||
| 	  _close (fd); | ||||
| 	  _unlink (un_addr->sun_path); | ||||
| 	} | ||||
|       else | ||||
| 	{ | ||||
| 	  _close (fd); | ||||
| 	  chmod (un_addr->sun_path, | ||||
| 	    (S_IFSOCK | S_IRWXU | S_IRWXG | S_IRWXO) & ~cygheap->umask); | ||||
| 	  set_sun_path (un_addr->sun_path); | ||||
| 	  res = 0; | ||||
| 	} | ||||
| #undef un_addr | ||||
|     } | ||||
|   else if (::bind (get_socket (), name, namelen)) | ||||
|     set_winsock_errno (); | ||||
|   else | ||||
|     res = 0; | ||||
|  | ||||
| out: | ||||
|   return res; | ||||
| } | ||||
|  | ||||
| int | ||||
| fhandler_socket::connect (const struct sockaddr *name, int namelen) | ||||
| { | ||||
|   int res = -1; | ||||
|   BOOL secret_check_failed = FALSE; | ||||
|   BOOL in_progress = FALSE; | ||||
|   sockaddr_in sin; | ||||
|   int secret [4]; | ||||
|  | ||||
|   sigframe thisframe (mainthread); | ||||
|  | ||||
|   if (!get_inet_addr (name, namelen, &sin, &namelen, secret)) | ||||
|     return -1; | ||||
|  | ||||
|   res = ::connect (get_socket (), (sockaddr *) &sin, namelen); | ||||
|   if (res) | ||||
|     { | ||||
|       /* Special handling for connect to return the correct error code | ||||
| 	 when called on a non-blocking socket. */ | ||||
|       if (is_nonblocking ()) | ||||
| 	{ | ||||
| 	  DWORD err = WSAGetLastError (); | ||||
| 	  if (err == WSAEWOULDBLOCK || err == WSAEALREADY) | ||||
| 	    { | ||||
| 	      WSASetLastError (WSAEINPROGRESS); | ||||
| 	      in_progress = TRUE; | ||||
| 	    } | ||||
| 	  else if (err == WSAEINVAL) | ||||
| 	    WSASetLastError (WSAEISCONN); | ||||
| 	} | ||||
|       set_winsock_errno (); | ||||
|     } | ||||
|   if (get_addr_family () == AF_LOCAL && get_socket_type () == SOCK_STREAM) | ||||
|     { | ||||
|       if (!res || in_progress) | ||||
| 	{ | ||||
| 	  if (!create_secret_event (secret)) | ||||
| 	    { | ||||
| 	      secret_check_failed = TRUE; | ||||
| 	    } | ||||
| 	  else if (in_progress) | ||||
| 	    signal_secret_event (); | ||||
| 	} | ||||
|  | ||||
|       if (!secret_check_failed && !res) | ||||
| 	{ | ||||
| 	  if (!check_peer_secret_event (&sin, secret)) | ||||
| 	    { | ||||
| 	      debug_printf ( "accept from unauthorized server" ); | ||||
| 	      secret_check_failed = TRUE; | ||||
| 	    } | ||||
|        } | ||||
|  | ||||
|       if (secret_check_failed) | ||||
| 	{ | ||||
| 	  close_secret_event (); | ||||
| 	  if (res) | ||||
| 	    closesocket (res); | ||||
| 	  set_errno (ECONNREFUSED); | ||||
| 	  res = -1; | ||||
| 	} | ||||
|     } | ||||
|  | ||||
|   return res; | ||||
| } | ||||
|  | ||||
| int | ||||
| fhandler_socket::listen (int backlog) | ||||
| { | ||||
|   int res = ::listen (get_socket (), backlog); | ||||
|   if (res) | ||||
|     set_winsock_errno (); | ||||
|   return res; | ||||
| } | ||||
|  | ||||
| int | ||||
| fhandler_socket::accept (struct sockaddr *peer, int *len) | ||||
| { | ||||
|   int res = -1; | ||||
|   BOOL secret_check_failed = FALSE; | ||||
|   BOOL in_progress = FALSE; | ||||
|  | ||||
|   sigframe thisframe (mainthread); | ||||
|  | ||||
|   /* Allows NULL peer and len parameters. */ | ||||
|   struct sockaddr_in peer_dummy; | ||||
|   int len_dummy; | ||||
|   if (!peer) | ||||
|     peer = (struct sockaddr *) &peer_dummy; | ||||
|   if (!len) | ||||
|     { | ||||
|       len_dummy = sizeof (struct sockaddr_in); | ||||
|       len = &len_dummy; | ||||
|     } | ||||
|  | ||||
|   /* accept on NT fails if len < sizeof (sockaddr_in) | ||||
|    * some programs set len to | ||||
|    * sizeof (name.sun_family) + strlen (name.sun_path) for UNIX domain | ||||
|    */ | ||||
|   if (len && ((unsigned) *len < sizeof (struct sockaddr_in))) | ||||
|     *len = sizeof (struct sockaddr_in); | ||||
|  | ||||
|   res = ::accept (get_socket (), peer, len);  // can't use a blocking call inside a lock | ||||
|  | ||||
|   if ((SOCKET) res == (SOCKET) INVALID_SOCKET && | ||||
|       WSAGetLastError () == WSAEWOULDBLOCK) | ||||
|     in_progress = TRUE; | ||||
|  | ||||
|   if (get_addr_family () == AF_LOCAL && get_socket_type () == SOCK_STREAM) | ||||
|     { | ||||
|       if ((SOCKET) res != (SOCKET) INVALID_SOCKET || in_progress) | ||||
| 	{ | ||||
| 	  if (!create_secret_event ()) | ||||
| 	    secret_check_failed = TRUE; | ||||
| 	  else if (in_progress)  | ||||
| 	    signal_secret_event (); | ||||
| 	} | ||||
|  | ||||
|       if (!secret_check_failed && | ||||
| 	  (SOCKET) res != (SOCKET) INVALID_SOCKET) | ||||
| 	{ | ||||
| 	  if (!check_peer_secret_event ((struct sockaddr_in*) peer)) | ||||
| 	    { | ||||
| 	      debug_printf ("connect from unauthorized client"); | ||||
| 	      secret_check_failed = TRUE; | ||||
| 	    } | ||||
| 	} | ||||
|  | ||||
|       if (secret_check_failed) | ||||
| 	{ | ||||
| 	  close_secret_event (); | ||||
| 	  if ((SOCKET) res != (SOCKET) INVALID_SOCKET) | ||||
| 	    closesocket (res); | ||||
| 	  set_errno (ECONNABORTED); | ||||
| 	  res = -1; | ||||
| 	  return res; | ||||
| 	} | ||||
|     } | ||||
|  | ||||
|   cygheap_fdnew res_fd; | ||||
|   if (res_fd < 0) | ||||
|     /* FIXME: what is correct errno? */; | ||||
|   else if ((SOCKET) res == (SOCKET) INVALID_SOCKET) | ||||
|     set_winsock_errno (); | ||||
|   else | ||||
|     { | ||||
|       fhandler_socket* res_fh = fdsock (res_fd, get_name (), res); | ||||
|       if (get_addr_family () == AF_LOCAL) | ||||
| 	res_fh->set_sun_path (get_sun_path ()); | ||||
|       res_fh->set_addr_family (get_addr_family ()); | ||||
|       res_fh->set_socket_type (get_socket_type ()); | ||||
|       res = res_fd; | ||||
|     } | ||||
|  | ||||
|   return res; | ||||
| } | ||||
|  | ||||
| int | ||||
| fhandler_socket::getsockname (struct sockaddr *name, int *namelen) | ||||
| { | ||||
|   int res = -1; | ||||
|  | ||||
|   sigframe thisframe (mainthread); | ||||
|  | ||||
|   if (get_addr_family () == AF_LOCAL) | ||||
|     { | ||||
|       struct sockaddr_un *sun = (struct sockaddr_un *) name; | ||||
|       memset (sun, 0, *namelen); | ||||
|       sun->sun_family = AF_LOCAL; | ||||
|  | ||||
|       if (!get_sun_path ()) | ||||
| 	sun->sun_path[0] = '\0'; | ||||
|       else | ||||
| 	/* According to SUSv2 "If the actual length of the address is | ||||
| 	   greater than the length of the supplied sockaddr structure, the | ||||
| 	   stored address will be truncated."  We play it save here so | ||||
| 	   that the path always has a trailing 0 even if it's truncated. */ | ||||
| 	strncpy (sun->sun_path, get_sun_path (), | ||||
| 		 *namelen - sizeof *sun + sizeof sun->sun_path - 1); | ||||
|  | ||||
|       *namelen = sizeof *sun - sizeof sun->sun_path | ||||
| 		 + strlen (sun->sun_path) + 1; | ||||
|       res = 0; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       res = ::getsockname (get_socket (), name, namelen); | ||||
|       if (res) | ||||
| 	set_winsock_errno (); | ||||
|     } | ||||
|  | ||||
|   return res; | ||||
| } | ||||
|  | ||||
| int | ||||
| fhandler_socket::getpeername (struct sockaddr *name, int *namelen) | ||||
| { | ||||
|   sigframe thisframe (mainthread); | ||||
|  | ||||
|   int res = ::getpeername (get_socket (), name, namelen); | ||||
|   if (res) | ||||
|     set_winsock_errno (); | ||||
|  | ||||
|   return res; | ||||
| } | ||||
|  | ||||
| int | ||||
| fhandler_socket::recv (void *ptr, size_t len, unsigned int flags) | ||||
| { | ||||
| @@ -264,6 +604,7 @@ fhandler_socket::recv (void *ptr, size_t len, unsigned int flags) | ||||
|   LPWSAOVERLAPPED ovr; | ||||
|  | ||||
|   sigframe thisframe (mainthread); | ||||
|  | ||||
|   if (is_nonblocking () || !(ovr = wsock_evt.prepare ())) | ||||
|     { | ||||
|       debug_printf ("Fallback to winsock 1 recv call"); | ||||
| @@ -298,6 +639,88 @@ fhandler_socket::read (void *ptr, size_t len) | ||||
|   return recv (ptr, len, 0); | ||||
| } | ||||
|  | ||||
| int | ||||
| fhandler_socket::recvfrom (void *ptr, size_t len, unsigned int flags, | ||||
| 			   struct sockaddr *from, int *fromlen) | ||||
| { | ||||
|   int res = -1; | ||||
|   wsock_event wsock_evt; | ||||
|   LPWSAOVERLAPPED ovr; | ||||
|  | ||||
|   sigframe thisframe (mainthread); | ||||
|  | ||||
|   if (is_nonblocking () || !(ovr = wsock_evt.prepare ())) | ||||
|     { | ||||
|       debug_printf ("Fallback to winsock 1 recvfrom call"); | ||||
|       if ((res = ::recvfrom (get_socket (), (char *) ptr, len, flags, from, | ||||
| 			     fromlen)) | ||||
| 	  == SOCKET_ERROR) | ||||
| 	{ | ||||
| 	  set_winsock_errno (); | ||||
| 	  res = -1; | ||||
| 	} | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       WSABUF wsabuf = { len, (char *) ptr }; | ||||
|       DWORD ret = 0; | ||||
|       if (WSARecvFrom (get_socket (), &wsabuf, 1, &ret, (DWORD *)&flags, | ||||
| 		       from, fromlen, ovr, NULL) != SOCKET_ERROR) | ||||
| 	res = ret; | ||||
|       else if ((res = WSAGetLastError ()) != WSA_IO_PENDING) | ||||
| 	{ | ||||
| 	  set_winsock_errno (); | ||||
| 	  res = -1; | ||||
| 	} | ||||
|       else if ((res = wsock_evt.wait (get_socket (), (DWORD *)&flags)) == -1) | ||||
| 	set_winsock_errno (); | ||||
|     } | ||||
|  | ||||
|   return res; | ||||
| } | ||||
|  | ||||
| int | ||||
| fhandler_socket::recvmsg (struct msghdr *msg, int flags) | ||||
| { | ||||
|   int res = -1; | ||||
|   int nb; | ||||
|   size_t tot = 0; | ||||
|   char *buf, *p; | ||||
|   struct iovec *iov = msg->msg_iov; | ||||
|  | ||||
|   sigframe thisframe (mainthread); | ||||
|  | ||||
|   if (get_addr_family () == AF_LOCAL) | ||||
|     { | ||||
|       /* On AF_LOCAL sockets the (fixed-size) name of the shared memory | ||||
| 	 area used for descriptor passing is transmitted first. | ||||
| 	 If this string is empty, no descriptors are passed and we can | ||||
| 	 go ahead recv'ing the normal data blocks.  Otherwise start | ||||
| 	 special handling for descriptor passing. */ | ||||
|       /*TODO*/ | ||||
|     } | ||||
|   for (int i = 0; i < msg->msg_iovlen; ++i) | ||||
|     tot += iov[i].iov_len; | ||||
|   buf = (char *) alloca (tot); | ||||
|   if (tot != 0 && buf == NULL) | ||||
|     { | ||||
|       set_errno (ENOMEM); | ||||
|       return -1; | ||||
|     } | ||||
|   nb = res = recvfrom (buf, tot, flags, (struct sockaddr *) msg->msg_name, | ||||
| 		       (int *) &msg->msg_namelen); | ||||
|   p = buf; | ||||
|   while (nb > 0) | ||||
|     { | ||||
|       ssize_t cnt = min(nb, iov->iov_len); | ||||
|       memcpy (iov->iov_base, p, cnt); | ||||
|       p += cnt; | ||||
|       nb -= cnt; | ||||
|       ++iov; | ||||
|     } | ||||
|   return res; | ||||
| } | ||||
|  | ||||
| int | ||||
| fhandler_socket::send (const void *ptr, size_t len, unsigned int flags) | ||||
| { | ||||
| @@ -306,6 +729,7 @@ fhandler_socket::send (const void *ptr, size_t len, unsigned int flags) | ||||
|   LPWSAOVERLAPPED ovr; | ||||
|  | ||||
|   sigframe thisframe (mainthread); | ||||
|  | ||||
|   if (is_nonblocking () || !(ovr = wsock_evt.prepare ())) | ||||
|     { | ||||
|       debug_printf ("Fallback to winsock 1 send call"); | ||||
| @@ -340,11 +764,111 @@ fhandler_socket::write (const void *ptr, size_t len) | ||||
|   return send (ptr, len, 0); | ||||
| } | ||||
|  | ||||
| /* Cygwin internal */ | ||||
| int | ||||
| fhandler_socket::sendto (const void *ptr, size_t len, unsigned int flags, | ||||
| 			 const struct sockaddr *to, int tolen) | ||||
| { | ||||
|   int res = -1; | ||||
|   wsock_event wsock_evt; | ||||
|   LPWSAOVERLAPPED ovr; | ||||
|   sockaddr_in sin; | ||||
|  | ||||
|   sigframe thisframe (mainthread); | ||||
|  | ||||
|   if (!get_inet_addr (to, tolen, &sin, &tolen)) | ||||
|     return -1; | ||||
|  | ||||
|   if (is_nonblocking () || !(ovr = wsock_evt.prepare ())) | ||||
|     { | ||||
|       debug_printf ("Fallback to winsock 1 sendto call"); | ||||
|       if ((res = ::sendto (get_socket (), (const char *) ptr, len, flags, | ||||
| 			   (sockaddr *) &sin, tolen)) == SOCKET_ERROR) | ||||
| 	{ | ||||
| 	  set_winsock_errno (); | ||||
| 	  res = -1; | ||||
| 	} | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       WSABUF wsabuf = { len, (char *) ptr }; | ||||
|       DWORD ret = 0; | ||||
|       if (WSASendTo (get_socket (), &wsabuf, 1, &ret, (DWORD)flags, | ||||
| 		     (sockaddr *) &sin, tolen, ovr, NULL) != SOCKET_ERROR) | ||||
| 	res = ret; | ||||
|       else if ((res = WSAGetLastError ()) != WSA_IO_PENDING) | ||||
| 	{ | ||||
| 	  set_winsock_errno (); | ||||
| 	  res = -1; | ||||
| 	} | ||||
|       else if ((res = wsock_evt.wait (get_socket (), (DWORD *)&flags)) == -1) | ||||
| 	set_winsock_errno (); | ||||
|     } | ||||
|  | ||||
|   return res; | ||||
| } | ||||
|  | ||||
| int | ||||
| fhandler_socket::sendmsg (const struct msghdr *msg, int flags) | ||||
| { | ||||
|     size_t tot = 0; | ||||
|     char *buf, *p; | ||||
|     struct iovec *iov = msg->msg_iov; | ||||
|  | ||||
|     if (get_addr_family () == AF_LOCAL) | ||||
|       { | ||||
|         /* For AF_LOCAL/AF_UNIX sockets, if descriptors are given, start | ||||
|            the special handling for descriptor passing.  Otherwise just | ||||
|            transmit an empty string to tell the receiver that no | ||||
|            descriptor passing is done. */ | ||||
|       /*TODO*/ | ||||
|       } | ||||
|     for(int i = 0; i < msg->msg_iovlen; ++i) | ||||
|         tot += iov[i].iov_len; | ||||
|     buf = (char *) alloca (tot); | ||||
|     if (tot != 0 && buf == NULL) | ||||
|       { | ||||
|         set_errno (ENOMEM); | ||||
|         return -1; | ||||
|       } | ||||
|     p = buf; | ||||
|     for (int i = 0; i < msg->msg_iovlen; ++i) | ||||
|       { | ||||
|         memcpy (p, iov[i].iov_base, iov[i].iov_len); | ||||
|         p += iov[i].iov_len; | ||||
|       } | ||||
|     return sendto (buf, tot, flags, (struct sockaddr *) msg->msg_name, | ||||
| 		   msg->msg_namelen); | ||||
| } | ||||
|  | ||||
| int | ||||
| fhandler_socket::shutdown (int how) | ||||
| { | ||||
|   int res = ::shutdown (get_socket (), how); | ||||
|  | ||||
|   if (res) | ||||
|     set_winsock_errno (); | ||||
|   else | ||||
|     switch (how) | ||||
|       { | ||||
|       case SHUT_RD: | ||||
| 	set_shutdown_read (); | ||||
| 	break; | ||||
|       case SHUT_WR: | ||||
| 	set_shutdown_write (); | ||||
| 	break; | ||||
|       case SHUT_RDWR: | ||||
| 	set_shutdown_read (); | ||||
| 	set_shutdown_write (); | ||||
| 	break; | ||||
|       } | ||||
|   return res; | ||||
| } | ||||
|  | ||||
| int | ||||
| fhandler_socket::close () | ||||
| { | ||||
|   int res = 0; | ||||
|  | ||||
|   sigframe thisframe (mainthread); | ||||
|  | ||||
|   /* HACK to allow a graceful shutdown even if shutdown() hasn't been | ||||
| @@ -381,7 +905,6 @@ fhandler_socket::close () | ||||
|  | ||||
| #define ASYNC_MASK (FD_READ|FD_WRITE|FD_OOB|FD_ACCEPT|FD_CONNECT) | ||||
|  | ||||
| /* Cygwin internal */ | ||||
| int | ||||
| fhandler_socket::ioctl (unsigned int cmd, void *p) | ||||
| { | ||||
| @@ -389,6 +912,7 @@ fhandler_socket::ioctl (unsigned int cmd, void *p) | ||||
|   int res; | ||||
|   struct ifconf ifc, *ifcp; | ||||
|   struct ifreq *ifr, *ifrp; | ||||
|  | ||||
|   sigframe thisframe (mainthread); | ||||
|  | ||||
|   switch (cmd) | ||||
|   | ||||
| @@ -33,7 +33,6 @@ details. */ | ||||
| #include "pinfo.h" | ||||
| #include "registry.h" | ||||
| #include "wsock_event.h" | ||||
| #include <sys/uio.h> | ||||
|  | ||||
| extern "C" { | ||||
| int h_errno; | ||||
| @@ -558,104 +557,20 @@ done: | ||||
|   return res; | ||||
| } | ||||
|  | ||||
| /* cygwin internal: map sockaddr into internet domain address */ | ||||
|  | ||||
| static int get_inet_addr (const struct sockaddr *in, int inlen, | ||||
| 			   struct sockaddr_in *out, int *outlen, int* secret = 0) | ||||
| { | ||||
|   int secret_buf [4]; | ||||
|   int* secret_ptr = (secret ? : secret_buf); | ||||
|  | ||||
|   if (in->sa_family == AF_INET) | ||||
|     { | ||||
|       *out = * (sockaddr_in *)in; | ||||
|       *outlen = inlen; | ||||
|       return 1; | ||||
|     } | ||||
|   else if (in->sa_family == AF_LOCAL) | ||||
|     { | ||||
|       int fd = _open (in->sa_data, O_RDONLY); | ||||
|       if (fd == -1) | ||||
| 	return 0; | ||||
|  | ||||
|       int ret = 0; | ||||
|       char buf[128]; | ||||
|       memset (buf, 0, sizeof buf); | ||||
|       if (read (fd, buf, sizeof buf) != -1) | ||||
| 	{ | ||||
| 	  sockaddr_in sin; | ||||
| 	  sin.sin_family = AF_INET; | ||||
| 	  sscanf (buf + strlen (SOCKET_COOKIE), "%hu %08x-%08x-%08x-%08x", | ||||
| 		  &sin.sin_port, | ||||
| 		  secret_ptr, secret_ptr + 1, secret_ptr + 2, secret_ptr + 3); | ||||
| 	  sin.sin_port = htons (sin.sin_port); | ||||
| 	  sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK); | ||||
| 	  *out = sin; | ||||
| 	  *outlen = sizeof sin; | ||||
| 	  ret = 1; | ||||
| 	} | ||||
|       _close (fd); | ||||
|       return ret; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       set_errno (EAFNOSUPPORT); | ||||
|       return 0; | ||||
|     } | ||||
| } | ||||
|  | ||||
| /* exported as sendto: standards? */ | ||||
| extern "C" int | ||||
| cygwin_sendto (int fd, | ||||
| 	       const void *buf, | ||||
| 	       int len, | ||||
| 	       unsigned int flags, | ||||
| 	       const struct sockaddr *to, | ||||
| 	       int tolen) | ||||
| cygwin_sendto (int fd, const void *buf, int len, unsigned int flags, | ||||
| 	       const struct sockaddr *to, int tolen) | ||||
| { | ||||
|   int res; | ||||
|   wsock_event wsock_evt; | ||||
|   LPWSAOVERLAPPED ovr; | ||||
|   fhandler_socket *h = get (fd); | ||||
|   fhandler_socket *fh = get (fd); | ||||
|  | ||||
|   if ((len && __check_invalid_read_ptr_errno (buf, (unsigned) len)) | ||||
|       || __check_null_invalid_struct_errno (to, tolen) | ||||
|       || !h) | ||||
|       || !fh) | ||||
|     res = -1; | ||||
|   else | ||||
|     { | ||||
|       sockaddr_in sin; | ||||
|       sigframe thisframe (mainthread); | ||||
|  | ||||
|       if (get_inet_addr (to, tolen, &sin, &tolen) == 0) | ||||
| 	return -1; | ||||
|  | ||||
|       if (h->is_nonblocking () || !(ovr = wsock_evt.prepare ())) | ||||
| 	{ | ||||
| 	  debug_printf ("Fallback to winsock 1 sendto call"); | ||||
| 	  if ((res = sendto (h->get_socket (), (const char *) buf, len, flags, | ||||
| 			     (sockaddr *) &sin, tolen)) == SOCKET_ERROR) | ||||
| 	    { | ||||
| 	      set_winsock_errno (); | ||||
| 	      res = -1; | ||||
| 	    } | ||||
| 	} | ||||
|       else | ||||
| 	{ | ||||
| 	  WSABUF wsabuf = { len, (char *) buf }; | ||||
| 	  DWORD ret = 0; | ||||
| 	  if (WSASendTo (h->get_socket (), &wsabuf, 1, &ret, (DWORD)flags, | ||||
| 			 (sockaddr *) &sin, tolen, ovr, NULL) != SOCKET_ERROR) | ||||
| 	    res = ret; | ||||
| 	  else if ((res = WSAGetLastError ()) != WSA_IO_PENDING) | ||||
| 	    { | ||||
| 	      set_winsock_errno (); | ||||
| 	      res = -1; | ||||
| 	    } | ||||
| 	  else if ((res = wsock_evt.wait (h->get_socket (), (DWORD *)&flags)) == -1) | ||||
| 	    set_winsock_errno (); | ||||
| 	} | ||||
|     } | ||||
|     res = fh->sendto (buf, len, flags, to, tolen); | ||||
|  | ||||
|   syscall_printf ("%d = sendto (%d, %x, %x, %x)", res, fd, buf, len, flags); | ||||
|  | ||||
| @@ -664,53 +579,19 @@ cygwin_sendto (int fd, | ||||
|  | ||||
| /* exported as recvfrom: standards? */ | ||||
| extern "C" int | ||||
| cygwin_recvfrom (int fd, | ||||
| 		   char *buf, | ||||
| 		   int len, | ||||
| 		   int flags, | ||||
| 		   struct sockaddr *from, | ||||
| 		   int *fromlen) | ||||
| cygwin_recvfrom (int fd, char *buf, int len, int flags, struct sockaddr *from, | ||||
| 		 int *fromlen) | ||||
| { | ||||
|   int res; | ||||
|   wsock_event wsock_evt; | ||||
|   LPWSAOVERLAPPED ovr; | ||||
|   fhandler_socket *h = get (fd); | ||||
|   fhandler_socket *fh = get (fd); | ||||
|  | ||||
|   if (__check_null_invalid_struct_errno (buf, (unsigned) len) | ||||
|       || check_null_invalid_struct_errno (fromlen) | ||||
|       || (from && __check_null_invalid_struct_errno (from, (unsigned) *fromlen)) | ||||
|       || !h) | ||||
|       || !fh) | ||||
|     res = -1; | ||||
|   else | ||||
|     { | ||||
|       sigframe thisframe (mainthread); | ||||
|  | ||||
|       if (h->is_nonblocking () ||!(ovr = wsock_evt.prepare ())) | ||||
| 	{ | ||||
| 	  debug_printf ("Fallback to winsock 1 recvfrom call"); | ||||
| 	  if ((res = recvfrom (h->get_socket (), buf, len, flags, from, fromlen)) | ||||
| 	      == SOCKET_ERROR) | ||||
| 	    { | ||||
| 	      set_winsock_errno (); | ||||
| 	      res = -1; | ||||
| 	    } | ||||
| 	} | ||||
|       else | ||||
| 	{ | ||||
| 	  WSABUF wsabuf = { len, (char *) buf }; | ||||
| 	  DWORD ret = 0; | ||||
| 	  if (WSARecvFrom (h->get_socket (), &wsabuf, 1, &ret, (DWORD *)&flags, | ||||
| 			   from, fromlen, ovr, NULL) != SOCKET_ERROR) | ||||
| 	    res = ret; | ||||
| 	  else if ((res = WSAGetLastError ()) != WSA_IO_PENDING) | ||||
| 	    { | ||||
| 	      set_winsock_errno (); | ||||
| 	      res = -1; | ||||
| 	    } | ||||
| 	  else if ((res = wsock_evt.wait (h->get_socket (), (DWORD *)&flags)) == -1) | ||||
| 	    set_winsock_errno (); | ||||
| 	} | ||||
|     } | ||||
|     res = fh->recvfrom (buf, len, flags, from, fromlen); | ||||
|  | ||||
|   syscall_printf ("%d = recvfrom (%d, %x, %x, %x)", res, fd, buf, len, flags); | ||||
|  | ||||
| @@ -719,17 +600,14 @@ cygwin_recvfrom (int fd, | ||||
|  | ||||
| /* exported as setsockopt: standards? */ | ||||
| extern "C" int | ||||
| cygwin_setsockopt (int fd, | ||||
| 		     int level, | ||||
| 		     int optname, | ||||
| 		     const void *optval, | ||||
| 		     int optlen) | ||||
| cygwin_setsockopt (int fd, int level, int optname, const void *optval, | ||||
| 		   int optlen) | ||||
| { | ||||
|   fhandler_socket *h = get (fd); | ||||
|   fhandler_socket *fh = get (fd); | ||||
|   int res = -1; | ||||
|   const char *name = "error"; | ||||
|  | ||||
|   if ((!optval || !__check_invalid_read_ptr_errno (optval, optlen)) && h) | ||||
|   if ((!optval || !__check_invalid_read_ptr_errno (optval, optlen)) && fh) | ||||
|     { | ||||
|       /* For the following debug_printf */ | ||||
|       switch (optname) | ||||
| @@ -766,8 +644,8 @@ cygwin_setsockopt (int fd, | ||||
| 	  break; | ||||
| 	} | ||||
|  | ||||
|       res = setsockopt (h->get_socket (), level, optname, | ||||
| 				     (const char *) optval, optlen); | ||||
|       res = setsockopt (fh->get_socket (), level, optname, | ||||
| 			(const char *) optval, optlen); | ||||
|  | ||||
|       if (optlen == 4) | ||||
| 	syscall_printf ("setsockopt optval=%x", *(long *) optval); | ||||
| @@ -783,18 +661,15 @@ cygwin_setsockopt (int fd, | ||||
|  | ||||
| /* exported as getsockopt: standards? */ | ||||
| extern "C" int | ||||
| cygwin_getsockopt (int fd, | ||||
| 		     int level, | ||||
| 		     int optname, | ||||
| 		     void *optval, | ||||
| 		     int *optlen) | ||||
| cygwin_getsockopt (int fd, int level, int optname, void *optval, int *optlen) | ||||
| { | ||||
|   fhandler_socket *h = get (fd); | ||||
|   fhandler_socket *fh = get (fd); | ||||
|   int res = -1; | ||||
|   const char *name = "error"; | ||||
|   if (!check_null_invalid_struct_errno (optlen) | ||||
|       && (!optval || !__check_null_invalid_struct_errno (optval, (unsigned) *optlen)) | ||||
|       && h) | ||||
|       && (!optval | ||||
|           || !__check_null_invalid_struct_errno (optval, (unsigned) *optlen)) | ||||
|       && fh) | ||||
|     { | ||||
|       /* For the following debug_printf */ | ||||
|       switch (optname) | ||||
| @@ -831,8 +706,8 @@ cygwin_getsockopt (int fd, | ||||
| 	  break; | ||||
| 	} | ||||
|  | ||||
|       res = getsockopt (h->get_socket (), level, optname, | ||||
| 				       (char *) optval, (int *) optlen); | ||||
|       res = getsockopt (fh->get_socket (), level, optname, (char *) optval, | ||||
|       			(int *) optlen); | ||||
|  | ||||
|       if (optname == SO_ERROR) | ||||
| 	{ | ||||
| @@ -851,78 +726,21 @@ cygwin_getsockopt (int fd, | ||||
|  | ||||
| /* exported as connect: standards? */ | ||||
| extern "C" int | ||||
| cygwin_connect (int fd, | ||||
| 		  const struct sockaddr *name, | ||||
| 		  int namelen) | ||||
| cygwin_connect (int fd, const struct sockaddr *name, int namelen) | ||||
| { | ||||
|   int res; | ||||
|   BOOL secret_check_failed = FALSE; | ||||
|   BOOL in_progress = FALSE; | ||||
|   fhandler_socket *sock = get (fd); | ||||
|   sockaddr_in sin; | ||||
|   int secret [4]; | ||||
|   sigframe thisframe (mainthread); | ||||
|   fhandler_socket *fh = get (fd); | ||||
|  | ||||
|   if (__check_invalid_read_ptr_errno (name, namelen)) | ||||
|     return -1; | ||||
|  | ||||
|   if (get_inet_addr (name, namelen, &sin, &namelen, secret) == 0) | ||||
|     return -1; | ||||
|  | ||||
|   if (!sock) | ||||
|   if (!fh) | ||||
|     res = -1; | ||||
|   else | ||||
|     { | ||||
|       res = connect (sock->get_socket (), (sockaddr *) &sin, namelen); | ||||
|       if (res) | ||||
| 	{ | ||||
| 	  /* Special handling for connect to return the correct error code | ||||
| 	     when called on a non-blocking socket. */ | ||||
| 	  if (sock->is_nonblocking ()) | ||||
| 	    { | ||||
| 	      DWORD err = WSAGetLastError (); | ||||
| 	      if (err == WSAEWOULDBLOCK || err == WSAEALREADY) | ||||
| 		{ | ||||
| 		  WSASetLastError (WSAEINPROGRESS); | ||||
| 		  in_progress = TRUE; | ||||
| 		} | ||||
| 	      else if (err == WSAEINVAL) | ||||
| 		WSASetLastError (WSAEISCONN); | ||||
| 	    } | ||||
| 	  set_winsock_errno (); | ||||
| 	} | ||||
|       if (sock->get_addr_family () == AF_LOCAL && | ||||
| 	  sock->get_socket_type () == SOCK_STREAM) | ||||
| 	{ | ||||
| 	  if (!res || in_progress) | ||||
| 	    { | ||||
| 	      if (!sock->create_secret_event (secret)) | ||||
| 		{ | ||||
| 		  secret_check_failed = TRUE; | ||||
| 		} | ||||
| 	      else if (in_progress) | ||||
| 		sock->signal_secret_event (); | ||||
| 	    } | ||||
|     res = fh->connect (name, namelen); | ||||
|  | ||||
| 	  if (!secret_check_failed && !res) | ||||
| 	    { | ||||
| 	      if (!sock->check_peer_secret_event (&sin, secret)) | ||||
| 		{ | ||||
| 		  debug_printf ( "accept from unauthorized server" ); | ||||
| 		  secret_check_failed = TRUE; | ||||
| 		} | ||||
| 	   } | ||||
|   syscall_printf ("%d = connect (%d, %x, %x)", res, fd, name, namelen); | ||||
|  | ||||
| 	  if (secret_check_failed) | ||||
| 	    { | ||||
| 	      sock->close_secret_event (); | ||||
| 	      if (res) | ||||
| 		closesocket (res); | ||||
| 	      set_errno (ECONNREFUSED); | ||||
| 	      res = -1; | ||||
| 	    } | ||||
| 	} | ||||
|     } | ||||
|   return res; | ||||
| } | ||||
|  | ||||
| @@ -1179,86 +997,11 @@ cygwin_accept (int fd, struct sockaddr *peer, int *len) | ||||
|     return -1; | ||||
|  | ||||
|   int res = -1; | ||||
|   BOOL secret_check_failed = FALSE; | ||||
|   BOOL in_progress = FALSE; | ||||
|   sigframe thisframe (mainthread); | ||||
|  | ||||
|   fhandler_socket *sock = get (fd); | ||||
|   if (sock) | ||||
|     { | ||||
|       /* Allows NULL peer and len parameters. */ | ||||
|       struct sockaddr_in peer_dummy; | ||||
|       int len_dummy; | ||||
|       if (!peer) | ||||
| 	peer = (struct sockaddr *) &peer_dummy; | ||||
|       if (!len) | ||||
| 	{ | ||||
| 	  len_dummy = sizeof (struct sockaddr_in); | ||||
| 	  len = &len_dummy; | ||||
| 	} | ||||
|   fhandler_socket *fh = get (fd); | ||||
|   if (fh) | ||||
|     res = fh->accept (peer, len); | ||||
|  | ||||
|       /* accept on NT fails if len < sizeof (sockaddr_in) | ||||
|        * some programs set len to | ||||
|        * sizeof (name.sun_family) + strlen (name.sun_path) for UNIX domain | ||||
|        */ | ||||
|       if (len && ((unsigned) *len < sizeof (struct sockaddr_in))) | ||||
| 	*len = sizeof (struct sockaddr_in); | ||||
|  | ||||
|       res = accept (sock->get_socket (), peer, len);  // can't use a blocking call inside a lock | ||||
|  | ||||
|       if ((SOCKET) res == (SOCKET) INVALID_SOCKET && | ||||
| 	  WSAGetLastError () == WSAEWOULDBLOCK) | ||||
| 	in_progress = TRUE; | ||||
|  | ||||
|       if (sock->get_addr_family () == AF_LOCAL && | ||||
| 	  sock->get_socket_type () == SOCK_STREAM) | ||||
| 	{ | ||||
| 	  if ((SOCKET) res != (SOCKET) INVALID_SOCKET || in_progress) | ||||
| 	    { | ||||
| 	      if (!sock->create_secret_event ()) | ||||
| 		secret_check_failed = TRUE; | ||||
| 	      else if (in_progress) | ||||
| 		sock->signal_secret_event (); | ||||
| 	    } | ||||
|  | ||||
| 	  if (!secret_check_failed && | ||||
| 	      (SOCKET) res != (SOCKET) INVALID_SOCKET) | ||||
| 	    { | ||||
| 	      if (!sock->check_peer_secret_event ((struct sockaddr_in*) peer)) | ||||
| 		{ | ||||
| 		  debug_printf ("connect from unauthorized client"); | ||||
| 		  secret_check_failed = TRUE; | ||||
| 		} | ||||
| 	    } | ||||
|  | ||||
| 	  if (secret_check_failed) | ||||
| 	    { | ||||
| 	      sock->close_secret_event (); | ||||
| 	      if ((SOCKET) res != (SOCKET) INVALID_SOCKET) | ||||
| 		closesocket (res); | ||||
| 	      set_errno (ECONNABORTED); | ||||
| 	      res = -1; | ||||
| 	      goto done; | ||||
| 	    } | ||||
| 	} | ||||
|  | ||||
|  | ||||
|       cygheap_fdnew res_fd; | ||||
|       if (res_fd < 0) | ||||
| 	/* FIXME: what is correct errno? */; | ||||
|       else if ((SOCKET) res == (SOCKET) INVALID_SOCKET) | ||||
| 	set_winsock_errno (); | ||||
|       else | ||||
| 	{ | ||||
| 	  fhandler_socket* res_fh = fdsock (res_fd, sock->get_name (), res); | ||||
| 	  if (sock->get_addr_family () == AF_LOCAL) | ||||
| 	    res_fh->set_sun_path (sock->get_sun_path ()); | ||||
| 	  res_fh->set_addr_family (sock->get_addr_family ()); | ||||
| 	  res_fh->set_socket_type (sock->get_socket_type ()); | ||||
| 	  res = res_fd; | ||||
| 	} | ||||
|     } | ||||
|  done: | ||||
|   syscall_printf ("%d = accept (%d, %x, %x)", res, fd, peer, len); | ||||
|   return res; | ||||
| } | ||||
| @@ -1272,83 +1015,10 @@ cygwin_bind (int fd, const struct sockaddr *my_addr, int addrlen) | ||||
|  | ||||
|   int res = -1; | ||||
|  | ||||
|   fhandler_socket *sock = get (fd); | ||||
|   if (sock) | ||||
|     { | ||||
|       if (my_addr->sa_family == AF_LOCAL) | ||||
| 	{ | ||||
| #define un_addr ((struct sockaddr_un *) my_addr) | ||||
| 	  struct sockaddr_in sin; | ||||
| 	  int len = sizeof sin; | ||||
| 	  int fd; | ||||
|   fhandler_socket *fh = get (fd); | ||||
|   if (fh) | ||||
|     res = fh->bind (my_addr, addrlen); | ||||
|  | ||||
| 	  if (strlen (un_addr->sun_path) >= UNIX_PATH_LEN) | ||||
| 	    { | ||||
| 	      set_errno (ENAMETOOLONG); | ||||
| 	      goto out; | ||||
| 	    } | ||||
| 	  sin.sin_family = AF_INET; | ||||
| 	  sin.sin_port = 0; | ||||
| 	  sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK); | ||||
| 	  if (bind (sock->get_socket (), (sockaddr *) &sin, len)) | ||||
| 	    { | ||||
| 	      syscall_printf ("AF_LOCAL: bind failed %d", get_errno ()); | ||||
| 	      set_winsock_errno (); | ||||
| 	      goto out; | ||||
| 	    } | ||||
| 	  if (getsockname (sock->get_socket (), (sockaddr *) &sin, &len)) | ||||
| 	    { | ||||
| 	      syscall_printf ("AF_LOCAL: getsockname failed %d", get_errno ()); | ||||
| 	      set_winsock_errno (); | ||||
| 	      goto out; | ||||
| 	    } | ||||
|  | ||||
| 	  sin.sin_port = ntohs (sin.sin_port); | ||||
| 	  debug_printf ("AF_LOCAL: socket bound to port %u", sin.sin_port); | ||||
|  | ||||
| 	  /* bind must fail if file system socket object already exists | ||||
| 	     so _open () is called with O_EXCL flag. */ | ||||
| 	  fd = _open (un_addr->sun_path, | ||||
| 		      O_WRONLY | O_CREAT | O_EXCL | O_BINARY, | ||||
| 		      0); | ||||
| 	  if (fd < 0) | ||||
| 	    { | ||||
| 	      if (get_errno () == EEXIST) | ||||
| 		set_errno (EADDRINUSE); | ||||
| 	      goto out; | ||||
| 	    } | ||||
|  | ||||
| 	  sock->set_connect_secret (); | ||||
|  | ||||
| 	  char buf[sizeof (SOCKET_COOKIE) + 80]; | ||||
| 	  __small_sprintf (buf, "%s%u ", SOCKET_COOKIE, sin.sin_port); | ||||
| 	  sock->get_connect_secret (strchr (buf, '\0')); | ||||
| 	  len = strlen (buf) + 1; | ||||
|  | ||||
| 	  /* Note that the terminating nul is written.  */ | ||||
| 	  if (_write (fd, buf, len) != len) | ||||
| 	    { | ||||
| 	      save_errno here; | ||||
| 	      _close (fd); | ||||
| 	      _unlink (un_addr->sun_path); | ||||
| 	    } | ||||
| 	  else | ||||
| 	    { | ||||
| 	      _close (fd); | ||||
| 	      chmod (un_addr->sun_path, | ||||
| 		(S_IFSOCK | S_IRWXU | S_IRWXG | S_IRWXO) & ~cygheap->umask); | ||||
| 	      sock->set_sun_path (un_addr->sun_path); | ||||
| 	      res = 0; | ||||
| 	    } | ||||
| #undef un_addr | ||||
| 	} | ||||
|       else if (bind (sock->get_socket (), my_addr, addrlen)) | ||||
| 	set_winsock_errno (); | ||||
|       else | ||||
| 	res = 0; | ||||
|     } | ||||
|  | ||||
| out: | ||||
|   syscall_printf ("%d = bind (%d, %x, %d)", res, fd, my_addr, addrlen); | ||||
|   return res; | ||||
| } | ||||
| @@ -1363,36 +1033,10 @@ cygwin_getsockname (int fd, struct sockaddr *addr, int *namelen) | ||||
|  | ||||
|   int res = -1; | ||||
|  | ||||
|   fhandler_socket *sock = get (fd); | ||||
|   if (sock) | ||||
|     { | ||||
|       if (sock->get_addr_family () == AF_LOCAL) | ||||
| 	{ | ||||
| 	  struct sockaddr_un *sun = (struct sockaddr_un *) addr; | ||||
| 	  memset (sun, 0, *namelen); | ||||
| 	  sun->sun_family = AF_LOCAL; | ||||
|   fhandler_socket *fh = get (fd); | ||||
|   if (fh) | ||||
|     res = fh->getsockname (addr, namelen); | ||||
|  | ||||
| 	  if (!sock->get_sun_path ()) | ||||
| 	    sun->sun_path[0] = '\0'; | ||||
| 	  else | ||||
| 	    /* According to SUSv2 "If the actual length of the address is | ||||
| 	       greater than the length of the supplied sockaddr structure, the | ||||
| 	       stored address will be truncated."  We play it save here so | ||||
| 	       that the path always has a trailing 0 even if it's truncated. */ | ||||
| 	    strncpy (sun->sun_path, sock->get_sun_path (), | ||||
| 		     *namelen - sizeof *sun + sizeof sun->sun_path - 1); | ||||
|  | ||||
| 	  *namelen = sizeof *sun - sizeof sun->sun_path | ||||
| 		     + strlen (sun->sun_path) + 1; | ||||
| 	  res = 0; | ||||
| 	} | ||||
|       else | ||||
| 	{ | ||||
| 	  res = getsockname (sock->get_socket (), addr, namelen); | ||||
| 	  if (res) | ||||
| 	    set_winsock_errno (); | ||||
| 	} | ||||
|     } | ||||
|   syscall_printf ("%d = getsockname (%d, %x, %d)", res, fd, addr, namelen); | ||||
|   return res; | ||||
| } | ||||
| @@ -1403,14 +1047,10 @@ cygwin_listen (int fd, int backlog) | ||||
| { | ||||
|   int res = -1; | ||||
|  | ||||
|   fhandler_socket *fh = get (fd); | ||||
|   if (fh) | ||||
|     res = fh->listen (backlog); | ||||
|  | ||||
|   fhandler_socket *sock = get (fd); | ||||
|   if (sock) | ||||
|     { | ||||
|       res = listen (sock->get_socket (), backlog); | ||||
|       if (res) | ||||
| 	set_winsock_errno (); | ||||
|     } | ||||
|   syscall_printf ("%d = listen (%d, %d)", res, fd, backlog); | ||||
|   return res; | ||||
| } | ||||
| @@ -1422,27 +1062,10 @@ cygwin_shutdown (int fd, int how) | ||||
|   int res = -1; | ||||
|   sigframe thisframe (mainthread); | ||||
|  | ||||
|   fhandler_socket *sock = get (fd); | ||||
|   if (sock) | ||||
|     { | ||||
|       res = shutdown (sock->get_socket (), how); | ||||
|       if (res) | ||||
| 	set_winsock_errno (); | ||||
|       else | ||||
| 	switch (how) | ||||
| 	  { | ||||
| 	  case SHUT_RD: | ||||
| 	    sock->set_shutdown_read (); | ||||
| 	    break; | ||||
| 	  case SHUT_WR: | ||||
| 	    sock->set_shutdown_write (); | ||||
| 	    break; | ||||
| 	  case SHUT_RDWR: | ||||
| 	    sock->set_shutdown_read (); | ||||
| 	    sock->set_shutdown_write (); | ||||
| 	    break; | ||||
| 	  } | ||||
|     } | ||||
|   fhandler_socket *fh = get (fd); | ||||
|   if (fh) | ||||
|     res = fh->shutdown (how); | ||||
|  | ||||
|   syscall_printf ("%d = shutdown (%d, %d)", res, fd, how); | ||||
|   return res; | ||||
| } | ||||
| @@ -1498,23 +1121,18 @@ cygwin_herror (const char *s) | ||||
| extern "C" int | ||||
| cygwin_getpeername (int fd, struct sockaddr *name, int *len) | ||||
| { | ||||
|   int res; | ||||
|   int res = -1; | ||||
|  | ||||
|   if (check_null_invalid_struct_errno (len) | ||||
|       || __check_null_invalid_struct_errno (name, (unsigned) *len)) | ||||
|     return -1; | ||||
|  | ||||
|   fhandler_socket *h = get (fd); | ||||
|   fhandler_socket *fh = get (fd); | ||||
|   if (fh) | ||||
|     res = fh->getpeername (name, len); | ||||
|  | ||||
|   if (!h) | ||||
|     res = -1; | ||||
|   else | ||||
|     { | ||||
|       res = getpeername (h->get_socket (), name, len); | ||||
|       if (res) | ||||
| 	set_winsock_errno (); | ||||
|     } | ||||
|   syscall_printf ("%d = getpeername %d", res, fh->get_socket ()); | ||||
|  | ||||
|   debug_printf ("%d = getpeername %d", res, h->get_socket ()); | ||||
|   return res; | ||||
| } | ||||
|  | ||||
| @@ -2476,64 +2094,32 @@ endhostent (void) | ||||
|  | ||||
| /* exported as recvmsg: standards? */ | ||||
| extern "C" int | ||||
| cygwin_recvmsg(int s, struct msghdr *msg, int flags) | ||||
| cygwin_recvmsg (int s, struct msghdr *msg, int flags) | ||||
| { | ||||
|     int ret, nb; | ||||
|     size_t tot = 0; | ||||
|     int i; | ||||
|     char *buf, *p; | ||||
|     struct iovec *iov = msg->msg_iov; | ||||
|   if (check_null_invalid_struct_errno (msg)) | ||||
|     return -1; | ||||
|  | ||||
|     for(i = 0; i < msg->msg_iovlen; ++i) | ||||
| 	tot += iov[i].iov_len; | ||||
|     buf = (char *) malloc(tot); | ||||
|     if (tot != 0 && buf == NULL) | ||||
|       { | ||||
| 	errno = ENOMEM; | ||||
| 	return -1; | ||||
|       } | ||||
|     nb = ret = cygwin_recvfrom (s, buf, tot, flags, | ||||
|       (struct sockaddr *) msg->msg_name, (int *) &msg->msg_namelen); | ||||
|     p = buf; | ||||
|     while (nb > 0) | ||||
|       { | ||||
| 	ssize_t cnt = min(nb, iov->iov_len); | ||||
|  | ||||
| 	memcpy (iov->iov_base, p, cnt); | ||||
| 	p += cnt; | ||||
| 	nb -= cnt; | ||||
| 	++iov; | ||||
|       } | ||||
|     free(buf); | ||||
|     return ret; | ||||
|   fhandler_socket *fh = get (s); | ||||
|   if (!fh) | ||||
|     { | ||||
|       set_errno (EINVAL); | ||||
|       return -1; | ||||
|     } | ||||
|   return fh->recvmsg (msg, flags); | ||||
| } | ||||
|  | ||||
| /* exported as sendmsg: standards? */ | ||||
| extern "C" int | ||||
| cygwin_sendmsg(int s, const struct msghdr *msg, int flags) | ||||
| cygwin_sendmsg (int s, const struct msghdr *msg, int flags) | ||||
| { | ||||
|     int ret; | ||||
|     size_t tot = 0; | ||||
|     int i; | ||||
|     char *buf, *p; | ||||
|     struct iovec *iov = msg->msg_iov; | ||||
|     if (__check_invalid_read_ptr_errno (msg, sizeof msg)) | ||||
|       return -1; | ||||
|  | ||||
|     for(i = 0; i < msg->msg_iovlen; ++i) | ||||
| 	tot += iov[i].iov_len; | ||||
|     buf = (char *) malloc(tot); | ||||
|     if (tot != 0 && buf == NULL) | ||||
|     fhandler_socket *fh = get (s); | ||||
|     if (!fh) | ||||
|       { | ||||
| 	errno = ENOMEM; | ||||
|         set_errno (EINVAL); | ||||
| 	return -1; | ||||
|       } | ||||
|     p = buf; | ||||
|     for (i = 0; i < msg->msg_iovlen; ++i) | ||||
|       { | ||||
| 	memcpy (p, iov[i].iov_base, iov[i].iov_len); | ||||
| 	p += iov[i].iov_len; | ||||
|       } | ||||
|     ret = cygwin_sendto (s, buf, tot, flags, | ||||
|       (struct sockaddr *) msg->msg_name, msg->msg_namelen); | ||||
|     free (buf); | ||||
|     return ret; | ||||
|     return fh->sendmsg (msg, flags); | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user