Cygwin: split out fhandler_socket into inet and local classes
First cut, still incomplete * fhandler_socket is now base class for other socket classes * fhandler_socket_inet handles AF_INET and AF_INET6 sockets * fhandler_socket_local handles AF_LOCAL/AF_UNIX sockets * finally get rid of fdsock by using set_socket_handle in accept4 * align file-related calls (fstat, fstatvfs, fchown, fchmod, facl) to Linux. Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This commit is contained in:
		| @@ -296,6 +296,8 @@ DLL_OFILES:= \ | ||||
| 	fhandler_registry.o \ | ||||
| 	fhandler_serial.o \ | ||||
| 	fhandler_socket.o \ | ||||
| 	fhandler_socket_inet.o \ | ||||
| 	fhandler_socket_local.o \ | ||||
| 	fhandler_tape.o \ | ||||
| 	fhandler_termios.o \ | ||||
| 	fhandler_tty.o \ | ||||
|   | ||||
| @@ -304,8 +304,8 @@ dtable::init_std_file_from_handle (int fd, HANDLE handle) | ||||
| 	dev.parse (name); | ||||
|       else if (strcmp (name, ":sock:") == 0 | ||||
| 	       /* NtQueryObject returns an error when called on an LSP socket | ||||
| 		  handle.  fdsock tries to fetch the underlying base socket, | ||||
| 		  but this might fail. */ | ||||
| 		  handle.  fhandler_socket::set_socket_handle tries to fetch | ||||
| 		  the underlying base socket, but this might fail. */ | ||||
| 	       || (strcmp (name, unknown_file) == 0 | ||||
| 		   && !::getsockopt ((SOCKET) handle, SOL_SOCKET, SO_RCVBUF, | ||||
| 				     (char *) &rcv, &len))) | ||||
| @@ -517,10 +517,12 @@ fh_alloc (path_conv& pc) | ||||
| 	case FH_TCP: | ||||
| 	case FH_UDP: | ||||
| 	case FH_ICMP: | ||||
| 	  fh = cnew (fhandler_socket_inet); | ||||
| 	  break; | ||||
| 	case FH_UNIX: | ||||
| 	case FH_STREAM: | ||||
| 	case FH_DGRAM: | ||||
| 	  fh = cnew (fhandler_socket); | ||||
| 	  fh = cnew (fhandler_socket_local); | ||||
| 	  break; | ||||
| 	case FH_FS: | ||||
| 	  fh = cnew (fhandler_disk_file); | ||||
|   | ||||
| @@ -479,9 +479,16 @@ struct wsa_event | ||||
| class fhandler_socket: public fhandler_base | ||||
| { | ||||
|  private: | ||||
|    /* permission fake following Linux rules */ | ||||
|    uid_t uid; | ||||
|    uid_t gid; | ||||
|    mode_t mode; | ||||
|  | ||||
|  protected: | ||||
|   int addr_family; | ||||
|   int type; | ||||
|   int connect_secret[4]; | ||||
|   virtual int af_local_connect () = 0; | ||||
|   int get_socket_flags (); | ||||
|  | ||||
|   wsa_event *wsock_events; | ||||
|   HANDLE wsock_mtx; | ||||
| @@ -491,32 +498,11 @@ class fhandler_socket: public fhandler_base | ||||
|   int evaluate_events (const long event_mask, long &events, const bool erase); | ||||
|   const HANDLE wsock_event () const { return wsock_evt; } | ||||
|   const LONG serial_number () const { return wsock_events->serial_number; } | ||||
|  private: | ||||
|  protected: | ||||
|   int wait_for_events (const long event_mask, const DWORD flags); | ||||
|   void release_events (); | ||||
|  | ||||
|   pid_t sec_pid; | ||||
|   uid_t sec_uid; | ||||
|   gid_t sec_gid; | ||||
|   pid_t sec_peer_pid; | ||||
|   uid_t sec_peer_uid; | ||||
|   gid_t sec_peer_gid; | ||||
|   void af_local_set_secret (char *); | ||||
|   void af_local_setblocking (bool &, bool &); | ||||
|   void af_local_unsetblocking (bool, bool); | ||||
|   void af_local_set_cred (); | ||||
|   void af_local_copy (fhandler_socket *); | ||||
|   bool af_local_recv_secret (); | ||||
|   bool af_local_send_secret (); | ||||
|   bool af_local_recv_cred (); | ||||
|   bool af_local_send_cred (); | ||||
|   int af_local_accept (); | ||||
|  public: | ||||
|   int af_local_connect (); | ||||
|   int af_local_set_no_getpeereid (); | ||||
|   void af_local_set_sockpair_cred (); | ||||
|  | ||||
|  private: | ||||
|  protected: | ||||
|   int	    _rmem; | ||||
|   int	    _wmem; | ||||
|  public: | ||||
| @@ -525,22 +511,20 @@ class fhandler_socket: public fhandler_base | ||||
|   void rmem (int nrmem) { _rmem = nrmem; } | ||||
|   void wmem (int nwmem) { _wmem = nwmem; } | ||||
|  | ||||
|  private: | ||||
|  protected: | ||||
|   DWORD _rcvtimeo; /* msecs */ | ||||
|   DWORD _sndtimeo; /* msecs */ | ||||
|  public: | ||||
|   DWORD &rcvtimeo () { return _rcvtimeo; } | ||||
|   DWORD &sndtimeo () { return _sndtimeo; } | ||||
|  | ||||
|  private: | ||||
|  protected: | ||||
|   struct _WSAPROTOCOL_INFOW *prot_info_ptr; | ||||
|  public: | ||||
|   void init_fixup_before (); | ||||
|   bool need_fixup_before () const {return prot_info_ptr != NULL;} | ||||
|  | ||||
|  private: | ||||
|   char *sun_path; | ||||
|   char *peer_sun_path; | ||||
|  protected: | ||||
|   struct status_flags | ||||
|   { | ||||
|     unsigned async_io		   : 1; /* async I/O */ | ||||
| @@ -580,35 +564,34 @@ class fhandler_socket: public fhandler_base | ||||
|   IMPLEMENT_STATUS_FLAG (conn_state, connect_state) | ||||
|   IMPLEMENT_STATUS_FLAG (bool, no_getpeereid) | ||||
|  | ||||
|   int socket (int af, int type, int protocol, int flags); | ||||
|   int bind (const struct sockaddr *name, int namelen); | ||||
|   int connect (const struct sockaddr *name, int namelen); | ||||
|   int listen (int backlog); | ||||
|   int accept4 (struct sockaddr *peer, int *len, int flags); | ||||
|   int getsockname (struct sockaddr *name, int *namelen); | ||||
|   int getpeername (struct sockaddr *name, int *namelen); | ||||
|   int getpeereid (pid_t *pid, uid_t *euid, gid_t *egid); | ||||
|   int socketpair (int af, int type, int protocol, int flags, | ||||
| 		  fhandler_socket *fh_out); | ||||
|   int setsockopt (int level, int optname, const void *optval, | ||||
| 		  __socklen_t optlen); | ||||
|   int getsockopt (int level, int optname, const void *optval, | ||||
| 		  __socklen_t *optlen); | ||||
|   virtual int socket (int af, int type, int protocol, int flags) = 0; | ||||
|   virtual int socketpair (int af, int type, int protocol, int flags, | ||||
| 			  fhandler_socket *fh_out) = 0; | ||||
|   virtual int bind (const struct sockaddr *name, int namelen) = 0; | ||||
|   virtual int listen (int backlog) = 0; | ||||
|   virtual int accept4 (struct sockaddr *peer, int *len, int flags) = 0; | ||||
|   virtual int connect (const struct sockaddr *name, int namelen) = 0; | ||||
|   virtual int getsockname (struct sockaddr *name, int *namelen) = 0; | ||||
|   virtual int getpeername (struct sockaddr *name, int *namelen) = 0; | ||||
|   virtual int getpeereid (pid_t *pid, uid_t *euid, gid_t *egid); | ||||
|   virtual int setsockopt (int level, int optname, const void *optval, | ||||
| 			  __socklen_t optlen) = 0; | ||||
|   virtual int getsockopt (int level, int optname, const void *optval, | ||||
| 			  __socklen_t *optlen) = 0; | ||||
|  | ||||
|   int open (int flags, mode_t mode = 0); | ||||
|   void __reg3 read (void *ptr, size_t& len); | ||||
|   ssize_t __stdcall readv (const struct iovec *, int iovcnt, ssize_t tot = -1); | ||||
|   inline ssize_t __reg3 recv_internal (struct _WSAMSG *wsamsg, bool use_recvmsg); | ||||
|   ssize_t recvfrom (void *ptr, size_t len, int flags, | ||||
| 		    struct sockaddr *from, int *fromlen); | ||||
|   ssize_t recvmsg (struct msghdr *msg, int flags); | ||||
|   virtual ssize_t recvfrom (void *ptr, size_t len, int flags, | ||||
| 			    struct sockaddr *from, int *fromlen) = 0; | ||||
|   virtual ssize_t recvmsg (struct msghdr *msg, int flags) = 0; | ||||
|   virtual void __reg3 read (void *ptr, size_t& len) = 0; | ||||
|   virtual ssize_t __stdcall readv (const struct iovec *, int iovcnt, | ||||
| 				   ssize_t tot = -1) = 0; | ||||
|  | ||||
|   ssize_t __stdcall write (const void *ptr, size_t len); | ||||
|   ssize_t __stdcall writev (const struct iovec *, int iovcnt, ssize_t tot = -1); | ||||
|   inline ssize_t send_internal (struct _WSAMSG *wsamsg, int flags); | ||||
|   ssize_t sendto (const void *ptr, size_t len, int flags, | ||||
| 	      const struct sockaddr *to, int tolen); | ||||
|   ssize_t sendmsg (const struct msghdr *msg, int flags); | ||||
|   virtual ssize_t sendto (const void *ptr, size_t len, int flags, | ||||
| 	      const struct sockaddr *to, int tolen) = 0; | ||||
|   virtual ssize_t sendmsg (const struct msghdr *msg, int flags) = 0; | ||||
|   virtual ssize_t __stdcall write (const void *ptr, size_t len) = 0; | ||||
|   virtual ssize_t __stdcall writev (const struct iovec *, int iovcnt, ssize_t tot = -1) = 0; | ||||
|  | ||||
|   int ioctl (unsigned int cmd, void *); | ||||
|   int fcntl (int cmd, intptr_t); | ||||
| @@ -635,31 +618,159 @@ class fhandler_socket: public fhandler_base | ||||
|   int get_addr_family () {return addr_family;} | ||||
|   void set_socket_type (int st) { type = st;} | ||||
|   int get_socket_type () {return type;} | ||||
|  | ||||
|   int __reg2 fstat (struct stat *buf); | ||||
|   int __reg2 fstatvfs (struct statvfs *buf); | ||||
|   int __reg1 fchmod (mode_t newmode); | ||||
|   int __reg2 fchown (uid_t newuid, gid_t newgid); | ||||
|   int __reg3 facl (int, int, struct acl *); | ||||
|   int __reg2 link (const char *); | ||||
| }; | ||||
|  | ||||
| class fhandler_socket_inet: public fhandler_socket | ||||
| { | ||||
|  protected: | ||||
|   int af_local_connect () { return 0; } | ||||
|  | ||||
|  private: | ||||
|   inline ssize_t recv_internal (struct _WSAMSG *wsamsg, bool use_recvmsg); | ||||
|   inline ssize_t send_internal (struct _WSAMSG *wsamsg, int flags); | ||||
|  | ||||
|  public: | ||||
|   fhandler_socket_inet (); | ||||
|   ~fhandler_socket_inet (); | ||||
|  | ||||
|   int socket (int af, int type, int protocol, int flags); | ||||
|   int socketpair (int af, int type, int protocol, int flags, | ||||
| 		  fhandler_socket *fh_out); | ||||
|   int bind (const struct sockaddr *name, int namelen); | ||||
|   int listen (int backlog); | ||||
|   int accept4 (struct sockaddr *peer, int *len, int flags); | ||||
|   int connect (const struct sockaddr *name, int namelen); | ||||
|   int getsockname (struct sockaddr *name, int *namelen); | ||||
|   int getpeername (struct sockaddr *name, int *namelen); | ||||
|   int setsockopt (int level, int optname, const void *optval, | ||||
| 		  __socklen_t optlen); | ||||
|   int getsockopt (int level, int optname, const void *optval, | ||||
| 		  __socklen_t *optlen); | ||||
|   ssize_t recvfrom (void *ptr, size_t len, int flags, | ||||
| 		    struct sockaddr *from, int *fromlen); | ||||
|   ssize_t recvmsg (struct msghdr *msg, int flags); | ||||
|   void __reg3 read (void *ptr, size_t& len); | ||||
|   ssize_t __stdcall readv (const struct iovec *, int iovcnt, ssize_t tot = -1); | ||||
|   ssize_t sendto (const void *ptr, size_t len, int flags, | ||||
| 	      const struct sockaddr *to, int tolen); | ||||
|   ssize_t sendmsg (const struct msghdr *msg, int flags); | ||||
|   ssize_t __stdcall write (const void *ptr, size_t len); | ||||
|   ssize_t __stdcall writev (const struct iovec *, int iovcnt, ssize_t tot = -1); | ||||
|  | ||||
|   /* from here on: CLONING */ | ||||
|   fhandler_socket_inet (void *) {} | ||||
|  | ||||
|   void copyto (fhandler_base *x) | ||||
|   { | ||||
|     x->pc.free_strings (); | ||||
|     *reinterpret_cast<fhandler_socket_inet *> (x) = *this; | ||||
|     x->reset (this); | ||||
|   } | ||||
|  | ||||
|   fhandler_socket_inet *clone (cygheap_types malloc_type = HEAP_FHANDLER) | ||||
|   { | ||||
|     void *ptr = (void *) ccalloc (malloc_type, 1, sizeof (fhandler_socket_inet)); | ||||
|     fhandler_socket_inet *fh = new (ptr) fhandler_socket_inet (ptr); | ||||
|     copyto (fh); | ||||
|     return fh; | ||||
|   } | ||||
| }; | ||||
|  | ||||
| class fhandler_socket_local: public fhandler_socket | ||||
| { | ||||
|  protected: | ||||
|   char *sun_path; | ||||
|   char *peer_sun_path; | ||||
|   void set_sun_path (const char *path); | ||||
|   char *get_sun_path () {return sun_path;} | ||||
|   void set_peer_sun_path (const char *path); | ||||
|   char *get_peer_sun_path () {return peer_sun_path;} | ||||
|  | ||||
|  protected: | ||||
|   int connect_secret[4]; | ||||
|   pid_t sec_pid; | ||||
|   uid_t sec_uid; | ||||
|   gid_t sec_gid; | ||||
|   pid_t sec_peer_pid; | ||||
|   uid_t sec_peer_uid; | ||||
|   gid_t sec_peer_gid; | ||||
|   void af_local_set_secret (char *); | ||||
|   void af_local_setblocking (bool &, bool &); | ||||
|   void af_local_unsetblocking (bool, bool); | ||||
|   void af_local_set_cred (); | ||||
|   void af_local_copy (fhandler_socket_local *); | ||||
|   bool af_local_recv_secret (); | ||||
|   bool af_local_send_secret (); | ||||
|   bool af_local_recv_cred (); | ||||
|   bool af_local_send_cred (); | ||||
|   int af_local_accept (); | ||||
|   int af_local_connect (); | ||||
|   int af_local_set_no_getpeereid (); | ||||
|   void af_local_set_sockpair_cred (); | ||||
|  | ||||
|  private: | ||||
|   inline ssize_t recv_internal (struct _WSAMSG *wsamsg, bool use_recvmsg); | ||||
|   inline ssize_t send_internal (struct _WSAMSG *wsamsg, int flags); | ||||
|  | ||||
|  public: | ||||
|   fhandler_socket_local (); | ||||
|   ~fhandler_socket_local (); | ||||
|  | ||||
|   int dup (fhandler_base *child, int); | ||||
|  | ||||
|   int socket (int af, int type, int protocol, int flags); | ||||
|   int socketpair (int af, int type, int protocol, int flags, | ||||
| 		  fhandler_socket *fh_out); | ||||
|   int bind (const struct sockaddr *name, int namelen); | ||||
|   int listen (int backlog); | ||||
|   int accept4 (struct sockaddr *peer, int *len, int flags); | ||||
|   int connect (const struct sockaddr *name, int namelen); | ||||
|   int getsockname (struct sockaddr *name, int *namelen); | ||||
|   int getpeername (struct sockaddr *name, int *namelen); | ||||
|   int getpeereid (pid_t *pid, uid_t *euid, gid_t *egid); | ||||
|   int setsockopt (int level, int optname, const void *optval, | ||||
| 		  __socklen_t optlen); | ||||
|   int getsockopt (int level, int optname, const void *optval, | ||||
| 		  __socklen_t *optlen); | ||||
|   ssize_t recvfrom (void *ptr, size_t len, int flags, | ||||
| 		    struct sockaddr *from, int *fromlen); | ||||
|   ssize_t recvmsg (struct msghdr *msg, int flags); | ||||
|   void __reg3 read (void *ptr, size_t& len); | ||||
|   ssize_t __stdcall readv (const struct iovec *, int iovcnt, ssize_t tot = -1); | ||||
|   ssize_t sendto (const void *ptr, size_t len, int flags, | ||||
| 	      const struct sockaddr *to, int tolen); | ||||
|   ssize_t sendmsg (const struct msghdr *msg, int flags); | ||||
|   ssize_t __stdcall write (const void *ptr, size_t len); | ||||
|   ssize_t __stdcall writev (const struct iovec *, int iovcnt, ssize_t tot = -1); | ||||
|  | ||||
|   int __reg2 fstat (struct stat *buf); | ||||
|   int __reg2 fstatvfs (struct statvfs *buf); | ||||
|   int __reg1 fchmod (mode_t mode); | ||||
|   int __reg2 fchown (uid_t uid, gid_t gid); | ||||
|   int __reg1 fchmod (mode_t newmode); | ||||
|   int __reg2 fchown (uid_t newuid, gid_t newgid); | ||||
|   int __reg3 facl (int, int, struct acl *); | ||||
|   int __reg2 link (const char *); | ||||
|  | ||||
|   fhandler_socket (void *) {} | ||||
|   /* from here on: CLONING */ | ||||
|   fhandler_socket_local (void *) {} | ||||
|  | ||||
|   void copyto (fhandler_base *x) | ||||
|   { | ||||
|     x->pc.free_strings (); | ||||
|     *reinterpret_cast<fhandler_socket *> (x) = *this; | ||||
|     *reinterpret_cast<fhandler_socket_local *> (x) = *this; | ||||
|     x->reset (this); | ||||
|   } | ||||
|  | ||||
|   fhandler_socket *clone (cygheap_types malloc_type = HEAP_FHANDLER) | ||||
|   fhandler_socket_local *clone (cygheap_types malloc_type = HEAP_FHANDLER) | ||||
|   { | ||||
|     void *ptr = (void *) ccalloc (malloc_type, 1, sizeof (fhandler_socket)); | ||||
|     fhandler_socket *fh = new (ptr) fhandler_socket (ptr); | ||||
|     void *ptr = (void *) ccalloc (malloc_type, 1, sizeof (fhandler_socket_local)); | ||||
|     fhandler_socket_local *fh = new (ptr) fhandler_socket_local (ptr); | ||||
|     copyto (fh); | ||||
|     return fh; | ||||
|   } | ||||
| @@ -2223,6 +2334,8 @@ typedef union | ||||
|   char __registry[sizeof (fhandler_registry)]; | ||||
|   char __serial[sizeof (fhandler_serial)]; | ||||
|   char __socket[sizeof (fhandler_socket)]; | ||||
|   char __socket_inet[sizeof (fhandler_socket_inet)]; | ||||
|   char __socket_local[sizeof (fhandler_socket_local)]; | ||||
|   char __termios[sizeof (fhandler_termios)]; | ||||
|   char __pty_common[sizeof (fhandler_pty_common)]; | ||||
|   char __pty_slave[sizeof (fhandler_pty_slave)]; | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1163
									
								
								winsup/cygwin/fhandler_socket_inet.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1163
									
								
								winsup/cygwin/fhandler_socket_inet.cc
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1844
									
								
								winsup/cygwin/fhandler_socket_local.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1844
									
								
								winsup/cygwin/fhandler_socket_local.cc
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -500,146 +500,6 @@ cygwin_getprotobynumber (int number) | ||||
|   return dup_ent (getprotobynumber (number)); | ||||
| } | ||||
|  | ||||
| #ifndef SIO_BASE_HANDLE | ||||
| #define SIO_BASE_HANDLE _WSAIOR(IOC_WS2,34) | ||||
| #endif | ||||
|  | ||||
| bool | ||||
| fdsock (cygheap_fdmanip& fd, const device *dev, SOCKET soc) | ||||
| { | ||||
|   fd = build_fh_dev (*dev); | ||||
|   if (!fd.isopen ()) | ||||
|     return false; | ||||
|  | ||||
|   /* Usually sockets are inheritable IFS objects.  Unfortunately some virus | ||||
|      scanners or other network-oriented software replace normal sockets | ||||
|      with their own kind, which is running through a filter driver called | ||||
|      "layered service provider" (LSP). | ||||
|  | ||||
|      LSP sockets are not kernel objects.  They are typically not marked as | ||||
|      inheritable, nor are they IFS handles.  They are in fact not inheritable | ||||
|      to child processes, and it does not help to mark them inheritable via | ||||
|      SetHandleInformation.  Subsequent socket calls in the child process fail | ||||
|      with error 10038, WSAENOTSOCK. | ||||
|  | ||||
|      There's a neat way to workaround these annoying LSP sockets.  WSAIoctl | ||||
|      allows to fetch the underlying base socket, which is a normal, inheritable | ||||
|      IFS handle.  So we fetch the base socket, duplicate it, and close the | ||||
|      original socket.  Now we have a standard IFS socket which (hopefully) | ||||
|      works as expected. | ||||
|  | ||||
|      If that doesn't work for some reason, mark the sockets for duplication | ||||
|      via WSADuplicateSocket/WSASocket.  This requires to start the child | ||||
|      process in SUSPENDED state so we only do this if really necessary. */ | ||||
|   DWORD flags; | ||||
|   bool fixup = false; | ||||
|   if (!GetHandleInformation ((HANDLE) soc, &flags) | ||||
|       || !(flags & HANDLE_FLAG_INHERIT)) | ||||
|     { | ||||
|       int ret; | ||||
|       SOCKET base_soc; | ||||
|       DWORD bret; | ||||
|  | ||||
|       fixup = true; | ||||
|       debug_printf ("LSP handle: %p", soc); | ||||
|       ret = WSAIoctl (soc, SIO_BASE_HANDLE, NULL, 0, (void *) &base_soc, | ||||
| 		      sizeof (base_soc), &bret, NULL, NULL); | ||||
|       if (ret) | ||||
| 	debug_printf ("WSAIoctl: %u", WSAGetLastError ()); | ||||
|       else if (base_soc != soc) | ||||
| 	{ | ||||
| 	  if (GetHandleInformation ((HANDLE) base_soc, &flags) | ||||
| 	      && (flags & HANDLE_FLAG_INHERIT)) | ||||
| 	    { | ||||
| 	      if (!DuplicateHandle (GetCurrentProcess (), (HANDLE) base_soc, | ||||
| 				    GetCurrentProcess (), (PHANDLE) &base_soc, | ||||
| 				    0, TRUE, DUPLICATE_SAME_ACCESS)) | ||||
| 		debug_printf ("DuplicateHandle failed, %E"); | ||||
| 	      else | ||||
| 		{ | ||||
| 		  closesocket (soc); | ||||
| 		  soc = base_soc; | ||||
| 		  fixup = false; | ||||
| 		} | ||||
| 	    } | ||||
| 	} | ||||
|     } | ||||
|   fd->set_io_handle ((HANDLE) soc); | ||||
|   if (!((fhandler_socket *) fd)->init_events ()) | ||||
|     return false; | ||||
|   if (fixup) | ||||
|     ((fhandler_socket *) fd)->init_fixup_before (); | ||||
|   fd->set_flags (O_RDWR | O_BINARY); | ||||
|   debug_printf ("fd %d, name '%s', soc %p", (int) fd, dev->name (), soc); | ||||
|  | ||||
|   /* Raise default buffer sizes (instead of WinSock default 8K). | ||||
|  | ||||
|      64K appear to have the best size/performance ratio for a default | ||||
|      value.  Tested with ssh/scp on Vista over Gigabit LAN. | ||||
|  | ||||
|      NOTE.  If the SO_RCVBUF size exceeds 65535(*), and if the socket is | ||||
|      connected to a remote machine, then calling WSADuplicateSocket on | ||||
|      fork/exec fails with WinSock error 10022, WSAEINVAL.  Fortunately | ||||
|      we don't use WSADuplicateSocket anymore, rather we just utilize | ||||
|      handle inheritance.  An explanation for this weird behaviour would | ||||
|      be nice, though. | ||||
|  | ||||
|      NOTE 2.  Testing on x86_64 (Vista, 2008 R2, W8) indicates that | ||||
|      this is no problem on 64 bit.  So we set the default buffer size to | ||||
|      the default values in current 3.x Linux versions. | ||||
|  | ||||
|      NOTE 3. Setting the window size to 65535 results in extremely bad | ||||
|      performance for apps that send data in multiples of Kb, as they | ||||
|      eventually end up sending 1 byte on the network and naggle + delay | ||||
|      ack kicks in. For example, iperf on a 10Gb network gives only 10 | ||||
|      Mbits/sec with a 65535 send buffer. We want this to be a multiple | ||||
|      of 1k, but since 64k breaks WSADuplicateSocket we use 63Kb. | ||||
|  | ||||
|      NOTE 4.  Tests with iperf uncover a problem in setting the SO_RCVBUF | ||||
|      and SO_SNDBUF sizes.  Windows is using autotuning since Windows Vista. | ||||
|      Manually setting SO_RCVBUF/SO_SNDBUF disables autotuning and leads to | ||||
|      inferior send/recv performance in scenarios with larger RTTs, as is | ||||
|      basically standard when accessing the internet.  For a discussion, | ||||
|      see https://cygwin.com/ml/cygwin-patches/2017-q1/msg00010.html. | ||||
|  | ||||
|      (*) Maximum normal TCP window size.  Coincidence?  */ | ||||
| #ifdef __x86_64__ | ||||
|   ((fhandler_socket *) fd)->rmem () = 212992; | ||||
|   ((fhandler_socket *) fd)->wmem () = 212992; | ||||
| #else | ||||
|   ((fhandler_socket *) fd)->rmem () = 64512; | ||||
|   ((fhandler_socket *) fd)->wmem () = 64512; | ||||
| #endif | ||||
| #if 0 /* See NOTE 4 above. */ | ||||
|   int size; | ||||
|  | ||||
|   if (::setsockopt (soc, SOL_SOCKET, SO_RCVBUF, | ||||
| 		    (char *) &((fhandler_socket *) fd)->rmem (), sizeof (int))) | ||||
|     { | ||||
|       debug_printf ("setsockopt(SO_RCVBUF) failed, %u", WSAGetLastError ()); | ||||
|       if (::getsockopt (soc, SOL_SOCKET, SO_RCVBUF, | ||||
| 			(char *) &((fhandler_socket *) fd)->rmem (), | ||||
| 			(size = sizeof (int), &size))) | ||||
| 	system_printf ("getsockopt(SO_RCVBUF) failed, %u", WSAGetLastError ()); | ||||
|     } | ||||
|   if (::setsockopt (soc, SOL_SOCKET, SO_SNDBUF, | ||||
| 		    (char *) &((fhandler_socket *) fd)->wmem (), sizeof (int))) | ||||
|     { | ||||
|       debug_printf ("setsockopt(SO_SNDBUF) failed, %u", WSAGetLastError ()); | ||||
|       if (::getsockopt (soc, SOL_SOCKET, SO_SNDBUF, | ||||
| 			(char *) &((fhandler_socket *) fd)->wmem (), | ||||
| 			(size = sizeof (int), &size))) | ||||
| 	system_printf ("getsockopt(SO_SNDBUF) failed, %u", WSAGetLastError ()); | ||||
|     } | ||||
| #endif | ||||
|   /* A unique ID is necessary to recognize fhandler entries which are | ||||
|      duplicated by dup(2) or fork(2).  This is used in BSD flock calls | ||||
|      to identify the descriptor. */ | ||||
|   ((fhandler_socket *) fd)->set_unique_id (); | ||||
|  | ||||
|   return true; | ||||
| } | ||||
|  | ||||
| /* exported as socket: POSIX.1-2001, POSIX.1-2008, 4.4BSD */ | ||||
| extern "C" int | ||||
| cygwin_socket (int af, int type, int protocol) | ||||
|   | ||||
| @@ -17,6 +17,7 @@ details. */ | ||||
|  | ||||
| /* UID/GID */ | ||||
| void uinfo_init (); | ||||
| bool check_token_membership (PSID); | ||||
|  | ||||
| #define ILLEGAL_UID ((uid_t)-1) | ||||
| #define ILLEGAL_GID ((gid_t)-1) | ||||
|   | ||||
| @@ -185,17 +185,12 @@ static enum { | ||||
| static int syslogd_sock = -1; | ||||
| extern "C" int cygwin_socket (int, int, int); | ||||
| extern "C" int cygwin_connect (int, const struct sockaddr *, int); | ||||
| extern int get_inet_addr (const struct sockaddr *, int, | ||||
| 			  struct sockaddr_storage *, int *, | ||||
| 			  int * = NULL, int * = NULL); | ||||
|  | ||||
| static void | ||||
| connect_syslogd () | ||||
| { | ||||
|   int fd; | ||||
|   struct sockaddr_un sun; | ||||
|   struct sockaddr_storage sst; | ||||
|   int len, type; | ||||
|  | ||||
|   if (syslogd_inited != not_inited && syslogd_sock >= 0) | ||||
|     close (syslogd_sock); | ||||
| @@ -203,20 +198,38 @@ connect_syslogd () | ||||
|   syslogd_sock = -1; | ||||
|   sun.sun_family = AF_LOCAL; | ||||
|   strncpy (sun.sun_path, _PATH_LOG, sizeof sun.sun_path); | ||||
|   if (get_inet_addr ((struct sockaddr *) &sun, sizeof sun, &sst, &len, &type)) | ||||
|   if ((fd = cygwin_socket (AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0)) < 0) | ||||
|     return; | ||||
|   if ((fd = cygwin_socket (AF_LOCAL, type, 0)) < 0) | ||||
|   if (cygwin_connect (fd, (struct sockaddr *) &sun, sizeof sun) == 0) | ||||
|     syslogd_inited = inited_stream; | ||||
|   else | ||||
|     { | ||||
|       close (fd); | ||||
|       if ((fd = cygwin_socket (AF_LOCAL, SOCK_DGRAM | SOCK_CLOEXEC, 0)) < 0) | ||||
| 	return; | ||||
|       if (cygwin_connect (fd, (struct sockaddr *) &sun, sizeof sun) == 0) | ||||
| 	{ | ||||
| 	  /* | ||||
| 	   * FIXME | ||||
| 	   * | ||||
| 	   * As soon as AF_LOCAL sockets are using pipes, this code has to | ||||
| 	   * got away. | ||||
| 	   */ | ||||
|  | ||||
| 	  /* connect on a dgram socket always succeeds.  We still don't know | ||||
| 	     if syslogd is actually listening. */ | ||||
|       if (type == SOCK_DGRAM) | ||||
| 	{ | ||||
| 	  cygheap_fdget cfd (fd); | ||||
| 	  fhandler_socket_local *const fh = (fhandler_socket_local *) | ||||
| 					    cfd->is_socket (); | ||||
| 	  tmp_pathbuf tp; | ||||
| 	  PMIB_UDPTABLE tab = (PMIB_UDPTABLE) tp.w_get (); | ||||
| 	  DWORD size = 65536; | ||||
| 	  bool found = false; | ||||
| 	  struct sockaddr_storage sst; | ||||
| 	  int len; | ||||
|  | ||||
| 	  len = sizeof sst; | ||||
| 	  ::getsockname (fh->get_socket (), (struct sockaddr *) &sst, &len); | ||||
| 	  struct sockaddr_in *sa = (struct sockaddr_in *) &sst; | ||||
|  | ||||
| 	  if (GetUdpTable (tab, &size, FALSE) == NO_ERROR) | ||||
| @@ -235,11 +248,12 @@ connect_syslogd () | ||||
| 		  return; | ||||
| 		} | ||||
| 	    } | ||||
| 	  syslogd_inited = inited_dgram; | ||||
| 	} | ||||
|       syslogd_inited = type == SOCK_DGRAM ? inited_dgram : inited_stream; | ||||
|       else | ||||
|       	close (fd); | ||||
|     } | ||||
|   syslogd_sock = fd; | ||||
|   fcntl64 (syslogd_sock, F_SETFD, FD_CLOEXEC); | ||||
|   debug_printf ("found /dev/log, fd = %d, type = %s", | ||||
| 		fd, syslogd_inited == inited_stream ? "STREAM" : "DGRAM"); | ||||
|   return; | ||||
|   | ||||
| @@ -117,7 +117,7 @@ cygheap_user::init () | ||||
|  | ||||
|    This needs careful checking should we use check_token_membership in other | ||||
|    circumstances. */ | ||||
| static bool | ||||
| bool | ||||
| check_token_membership (PSID sid) | ||||
| { | ||||
|   NTSTATUS status; | ||||
| @@ -142,7 +142,7 @@ check_token_membership (PSID sid) | ||||
|   return false; | ||||
| } | ||||
|  | ||||
| void | ||||
| static void | ||||
| internal_getlogin (cygheap_user &user) | ||||
| { | ||||
|   struct passwd *pwd; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user