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:
parent
dff3bc9a86
commit
859d215b7e
|
@ -296,6 +296,8 @@ DLL_OFILES:= \
|
||||||
fhandler_registry.o \
|
fhandler_registry.o \
|
||||||
fhandler_serial.o \
|
fhandler_serial.o \
|
||||||
fhandler_socket.o \
|
fhandler_socket.o \
|
||||||
|
fhandler_socket_inet.o \
|
||||||
|
fhandler_socket_local.o \
|
||||||
fhandler_tape.o \
|
fhandler_tape.o \
|
||||||
fhandler_termios.o \
|
fhandler_termios.o \
|
||||||
fhandler_tty.o \
|
fhandler_tty.o \
|
||||||
|
|
|
@ -304,8 +304,8 @@ dtable::init_std_file_from_handle (int fd, HANDLE handle)
|
||||||
dev.parse (name);
|
dev.parse (name);
|
||||||
else if (strcmp (name, ":sock:") == 0
|
else if (strcmp (name, ":sock:") == 0
|
||||||
/* NtQueryObject returns an error when called on an LSP socket
|
/* NtQueryObject returns an error when called on an LSP socket
|
||||||
handle. fdsock tries to fetch the underlying base socket,
|
handle. fhandler_socket::set_socket_handle tries to fetch
|
||||||
but this might fail. */
|
the underlying base socket, but this might fail. */
|
||||||
|| (strcmp (name, unknown_file) == 0
|
|| (strcmp (name, unknown_file) == 0
|
||||||
&& !::getsockopt ((SOCKET) handle, SOL_SOCKET, SO_RCVBUF,
|
&& !::getsockopt ((SOCKET) handle, SOL_SOCKET, SO_RCVBUF,
|
||||||
(char *) &rcv, &len)))
|
(char *) &rcv, &len)))
|
||||||
|
@ -517,10 +517,12 @@ fh_alloc (path_conv& pc)
|
||||||
case FH_TCP:
|
case FH_TCP:
|
||||||
case FH_UDP:
|
case FH_UDP:
|
||||||
case FH_ICMP:
|
case FH_ICMP:
|
||||||
|
fh = cnew (fhandler_socket_inet);
|
||||||
|
break;
|
||||||
case FH_UNIX:
|
case FH_UNIX:
|
||||||
case FH_STREAM:
|
case FH_STREAM:
|
||||||
case FH_DGRAM:
|
case FH_DGRAM:
|
||||||
fh = cnew (fhandler_socket);
|
fh = cnew (fhandler_socket_local);
|
||||||
break;
|
break;
|
||||||
case FH_FS:
|
case FH_FS:
|
||||||
fh = cnew (fhandler_disk_file);
|
fh = cnew (fhandler_disk_file);
|
||||||
|
|
|
@ -479,9 +479,16 @@ struct wsa_event
|
||||||
class fhandler_socket: public fhandler_base
|
class fhandler_socket: public fhandler_base
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
/* permission fake following Linux rules */
|
||||||
|
uid_t uid;
|
||||||
|
uid_t gid;
|
||||||
|
mode_t mode;
|
||||||
|
|
||||||
|
protected:
|
||||||
int addr_family;
|
int addr_family;
|
||||||
int type;
|
int type;
|
||||||
int connect_secret[4];
|
virtual int af_local_connect () = 0;
|
||||||
|
int get_socket_flags ();
|
||||||
|
|
||||||
wsa_event *wsock_events;
|
wsa_event *wsock_events;
|
||||||
HANDLE wsock_mtx;
|
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);
|
int evaluate_events (const long event_mask, long &events, const bool erase);
|
||||||
const HANDLE wsock_event () const { return wsock_evt; }
|
const HANDLE wsock_event () const { return wsock_evt; }
|
||||||
const LONG serial_number () const { return wsock_events->serial_number; }
|
const LONG serial_number () const { return wsock_events->serial_number; }
|
||||||
private:
|
protected:
|
||||||
int wait_for_events (const long event_mask, const DWORD flags);
|
int wait_for_events (const long event_mask, const DWORD flags);
|
||||||
void release_events ();
|
void release_events ();
|
||||||
|
|
||||||
pid_t sec_pid;
|
protected:
|
||||||
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:
|
|
||||||
int _rmem;
|
int _rmem;
|
||||||
int _wmem;
|
int _wmem;
|
||||||
public:
|
public:
|
||||||
|
@ -525,22 +511,20 @@ class fhandler_socket: public fhandler_base
|
||||||
void rmem (int nrmem) { _rmem = nrmem; }
|
void rmem (int nrmem) { _rmem = nrmem; }
|
||||||
void wmem (int nwmem) { _wmem = nwmem; }
|
void wmem (int nwmem) { _wmem = nwmem; }
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
DWORD _rcvtimeo; /* msecs */
|
DWORD _rcvtimeo; /* msecs */
|
||||||
DWORD _sndtimeo; /* msecs */
|
DWORD _sndtimeo; /* msecs */
|
||||||
public:
|
public:
|
||||||
DWORD &rcvtimeo () { return _rcvtimeo; }
|
DWORD &rcvtimeo () { return _rcvtimeo; }
|
||||||
DWORD &sndtimeo () { return _sndtimeo; }
|
DWORD &sndtimeo () { return _sndtimeo; }
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
struct _WSAPROTOCOL_INFOW *prot_info_ptr;
|
struct _WSAPROTOCOL_INFOW *prot_info_ptr;
|
||||||
public:
|
public:
|
||||||
void init_fixup_before ();
|
void init_fixup_before ();
|
||||||
bool need_fixup_before () const {return prot_info_ptr != NULL;}
|
bool need_fixup_before () const {return prot_info_ptr != NULL;}
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
char *sun_path;
|
|
||||||
char *peer_sun_path;
|
|
||||||
struct status_flags
|
struct status_flags
|
||||||
{
|
{
|
||||||
unsigned async_io : 1; /* async I/O */
|
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 (conn_state, connect_state)
|
||||||
IMPLEMENT_STATUS_FLAG (bool, no_getpeereid)
|
IMPLEMENT_STATUS_FLAG (bool, no_getpeereid)
|
||||||
|
|
||||||
int socket (int af, int type, int protocol, int flags);
|
virtual int socket (int af, int type, int protocol, int flags) = 0;
|
||||||
int bind (const struct sockaddr *name, int namelen);
|
virtual int socketpair (int af, int type, int protocol, int flags,
|
||||||
int connect (const struct sockaddr *name, int namelen);
|
fhandler_socket *fh_out) = 0;
|
||||||
int listen (int backlog);
|
virtual int bind (const struct sockaddr *name, int namelen) = 0;
|
||||||
int accept4 (struct sockaddr *peer, int *len, int flags);
|
virtual int listen (int backlog) = 0;
|
||||||
int getsockname (struct sockaddr *name, int *namelen);
|
virtual int accept4 (struct sockaddr *peer, int *len, int flags) = 0;
|
||||||
int getpeername (struct sockaddr *name, int *namelen);
|
virtual int connect (const struct sockaddr *name, int namelen) = 0;
|
||||||
int getpeereid (pid_t *pid, uid_t *euid, gid_t *egid);
|
virtual int getsockname (struct sockaddr *name, int *namelen) = 0;
|
||||||
int socketpair (int af, int type, int protocol, int flags,
|
virtual int getpeername (struct sockaddr *name, int *namelen) = 0;
|
||||||
fhandler_socket *fh_out);
|
virtual int getpeereid (pid_t *pid, uid_t *euid, gid_t *egid);
|
||||||
int setsockopt (int level, int optname, const void *optval,
|
virtual int setsockopt (int level, int optname, const void *optval,
|
||||||
__socklen_t optlen);
|
__socklen_t optlen) = 0;
|
||||||
int getsockopt (int level, int optname, const void *optval,
|
virtual int getsockopt (int level, int optname, const void *optval,
|
||||||
__socklen_t *optlen);
|
__socklen_t *optlen) = 0;
|
||||||
|
|
||||||
int open (int flags, mode_t mode = 0);
|
int open (int flags, mode_t mode = 0);
|
||||||
void __reg3 read (void *ptr, size_t& len);
|
virtual ssize_t recvfrom (void *ptr, size_t len, int flags,
|
||||||
ssize_t __stdcall readv (const struct iovec *, int iovcnt, ssize_t tot = -1);
|
struct sockaddr *from, int *fromlen) = 0;
|
||||||
inline ssize_t __reg3 recv_internal (struct _WSAMSG *wsamsg, bool use_recvmsg);
|
virtual ssize_t recvmsg (struct msghdr *msg, int flags) = 0;
|
||||||
ssize_t recvfrom (void *ptr, size_t len, int flags,
|
virtual void __reg3 read (void *ptr, size_t& len) = 0;
|
||||||
struct sockaddr *from, int *fromlen);
|
virtual ssize_t __stdcall readv (const struct iovec *, int iovcnt,
|
||||||
ssize_t recvmsg (struct msghdr *msg, int flags);
|
ssize_t tot = -1) = 0;
|
||||||
|
|
||||||
ssize_t __stdcall write (const void *ptr, size_t len);
|
virtual ssize_t sendto (const void *ptr, size_t len, int flags,
|
||||||
ssize_t __stdcall writev (const struct iovec *, int iovcnt, ssize_t tot = -1);
|
const struct sockaddr *to, int tolen) = 0;
|
||||||
inline ssize_t send_internal (struct _WSAMSG *wsamsg, int flags);
|
virtual ssize_t sendmsg (const struct msghdr *msg, int flags) = 0;
|
||||||
ssize_t sendto (const void *ptr, size_t len, int flags,
|
virtual ssize_t __stdcall write (const void *ptr, size_t len) = 0;
|
||||||
const struct sockaddr *to, int tolen);
|
virtual ssize_t __stdcall writev (const struct iovec *, int iovcnt, ssize_t tot = -1) = 0;
|
||||||
ssize_t sendmsg (const struct msghdr *msg, int flags);
|
|
||||||
|
|
||||||
int ioctl (unsigned int cmd, void *);
|
int ioctl (unsigned int cmd, void *);
|
||||||
int fcntl (int cmd, intptr_t);
|
int fcntl (int cmd, intptr_t);
|
||||||
|
@ -635,31 +618,159 @@ class fhandler_socket: public fhandler_base
|
||||||
int get_addr_family () {return addr_family;}
|
int get_addr_family () {return addr_family;}
|
||||||
void set_socket_type (int st) { type = st;}
|
void set_socket_type (int st) { type = st;}
|
||||||
int get_socket_type () {return type;}
|
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);
|
void set_sun_path (const char *path);
|
||||||
char *get_sun_path () {return sun_path;}
|
char *get_sun_path () {return sun_path;}
|
||||||
void set_peer_sun_path (const char *path);
|
void set_peer_sun_path (const char *path);
|
||||||
char *get_peer_sun_path () {return peer_sun_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 fstat (struct stat *buf);
|
||||||
int __reg2 fstatvfs (struct statvfs *buf);
|
int __reg2 fstatvfs (struct statvfs *buf);
|
||||||
int __reg1 fchmod (mode_t mode);
|
int __reg1 fchmod (mode_t newmode);
|
||||||
int __reg2 fchown (uid_t uid, gid_t gid);
|
int __reg2 fchown (uid_t newuid, gid_t newgid);
|
||||||
int __reg3 facl (int, int, struct acl *);
|
int __reg3 facl (int, int, struct acl *);
|
||||||
int __reg2 link (const char *);
|
int __reg2 link (const char *);
|
||||||
|
|
||||||
fhandler_socket (void *) {}
|
/* from here on: CLONING */
|
||||||
|
fhandler_socket_local (void *) {}
|
||||||
|
|
||||||
void copyto (fhandler_base *x)
|
void copyto (fhandler_base *x)
|
||||||
{
|
{
|
||||||
x->pc.free_strings ();
|
x->pc.free_strings ();
|
||||||
*reinterpret_cast<fhandler_socket *> (x) = *this;
|
*reinterpret_cast<fhandler_socket_local *> (x) = *this;
|
||||||
x->reset (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));
|
void *ptr = (void *) ccalloc (malloc_type, 1, sizeof (fhandler_socket_local));
|
||||||
fhandler_socket *fh = new (ptr) fhandler_socket (ptr);
|
fhandler_socket_local *fh = new (ptr) fhandler_socket_local (ptr);
|
||||||
copyto (fh);
|
copyto (fh);
|
||||||
return fh;
|
return fh;
|
||||||
}
|
}
|
||||||
|
@ -2223,6 +2334,8 @@ typedef union
|
||||||
char __registry[sizeof (fhandler_registry)];
|
char __registry[sizeof (fhandler_registry)];
|
||||||
char __serial[sizeof (fhandler_serial)];
|
char __serial[sizeof (fhandler_serial)];
|
||||||
char __socket[sizeof (fhandler_socket)];
|
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 __termios[sizeof (fhandler_termios)];
|
||||||
char __pty_common[sizeof (fhandler_pty_common)];
|
char __pty_common[sizeof (fhandler_pty_common)];
|
||||||
char __pty_slave[sizeof (fhandler_pty_slave)];
|
char __pty_slave[sizeof (fhandler_pty_slave)];
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -500,146 +500,6 @@ cygwin_getprotobynumber (int number)
|
||||||
return dup_ent (getprotobynumber (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 */
|
/* exported as socket: POSIX.1-2001, POSIX.1-2008, 4.4BSD */
|
||||||
extern "C" int
|
extern "C" int
|
||||||
cygwin_socket (int af, int type, int protocol)
|
cygwin_socket (int af, int type, int protocol)
|
||||||
|
|
|
@ -17,6 +17,7 @@ details. */
|
||||||
|
|
||||||
/* UID/GID */
|
/* UID/GID */
|
||||||
void uinfo_init ();
|
void uinfo_init ();
|
||||||
|
bool check_token_membership (PSID);
|
||||||
|
|
||||||
#define ILLEGAL_UID ((uid_t)-1)
|
#define ILLEGAL_UID ((uid_t)-1)
|
||||||
#define ILLEGAL_GID ((gid_t)-1)
|
#define ILLEGAL_GID ((gid_t)-1)
|
||||||
|
|
|
@ -185,17 +185,12 @@ static enum {
|
||||||
static int syslogd_sock = -1;
|
static int syslogd_sock = -1;
|
||||||
extern "C" int cygwin_socket (int, int, int);
|
extern "C" int cygwin_socket (int, int, int);
|
||||||
extern "C" int cygwin_connect (int, const struct sockaddr *, 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
|
static void
|
||||||
connect_syslogd ()
|
connect_syslogd ()
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
struct sockaddr_un sun;
|
struct sockaddr_un sun;
|
||||||
struct sockaddr_storage sst;
|
|
||||||
int len, type;
|
|
||||||
|
|
||||||
if (syslogd_inited != not_inited && syslogd_sock >= 0)
|
if (syslogd_inited != not_inited && syslogd_sock >= 0)
|
||||||
close (syslogd_sock);
|
close (syslogd_sock);
|
||||||
|
@ -203,20 +198,38 @@ connect_syslogd ()
|
||||||
syslogd_sock = -1;
|
syslogd_sock = -1;
|
||||||
sun.sun_family = AF_LOCAL;
|
sun.sun_family = AF_LOCAL;
|
||||||
strncpy (sun.sun_path, _PATH_LOG, sizeof sun.sun_path);
|
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)
|
|
||||||
return;
|
return;
|
||||||
if (cygwin_connect (fd, (struct sockaddr *) &sun, sizeof sun) == 0)
|
if (cygwin_connect (fd, (struct sockaddr *) &sun, sizeof sun) == 0)
|
||||||
|
syslogd_inited = inited_stream;
|
||||||
|
else
|
||||||
{
|
{
|
||||||
/* connect on a dgram socket always succeeds. We still don't know
|
close (fd);
|
||||||
if syslogd is actually listening. */
|
if ((fd = cygwin_socket (AF_LOCAL, SOCK_DGRAM | SOCK_CLOEXEC, 0)) < 0)
|
||||||
if (type == SOCK_DGRAM)
|
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. */
|
||||||
|
cygheap_fdget cfd (fd);
|
||||||
|
fhandler_socket_local *const fh = (fhandler_socket_local *)
|
||||||
|
cfd->is_socket ();
|
||||||
tmp_pathbuf tp;
|
tmp_pathbuf tp;
|
||||||
PMIB_UDPTABLE tab = (PMIB_UDPTABLE) tp.w_get ();
|
PMIB_UDPTABLE tab = (PMIB_UDPTABLE) tp.w_get ();
|
||||||
DWORD size = 65536;
|
DWORD size = 65536;
|
||||||
bool found = false;
|
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;
|
struct sockaddr_in *sa = (struct sockaddr_in *) &sst;
|
||||||
|
|
||||||
if (GetUdpTable (tab, &size, FALSE) == NO_ERROR)
|
if (GetUdpTable (tab, &size, FALSE) == NO_ERROR)
|
||||||
|
@ -235,11 +248,12 @@ connect_syslogd ()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
syslogd_inited = inited_dgram;
|
||||||
}
|
}
|
||||||
syslogd_inited = type == SOCK_DGRAM ? inited_dgram : inited_stream;
|
else
|
||||||
|
close (fd);
|
||||||
}
|
}
|
||||||
syslogd_sock = fd;
|
syslogd_sock = fd;
|
||||||
fcntl64 (syslogd_sock, F_SETFD, FD_CLOEXEC);
|
|
||||||
debug_printf ("found /dev/log, fd = %d, type = %s",
|
debug_printf ("found /dev/log, fd = %d, type = %s",
|
||||||
fd, syslogd_inited == inited_stream ? "STREAM" : "DGRAM");
|
fd, syslogd_inited == inited_stream ? "STREAM" : "DGRAM");
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -117,7 +117,7 @@ cygheap_user::init ()
|
||||||
|
|
||||||
This needs careful checking should we use check_token_membership in other
|
This needs careful checking should we use check_token_membership in other
|
||||||
circumstances. */
|
circumstances. */
|
||||||
static bool
|
bool
|
||||||
check_token_membership (PSID sid)
|
check_token_membership (PSID sid)
|
||||||
{
|
{
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
|
@ -142,7 +142,7 @@ check_token_membership (PSID sid)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
internal_getlogin (cygheap_user &user)
|
internal_getlogin (cygheap_user &user)
|
||||||
{
|
{
|
||||||
struct passwd *pwd;
|
struct passwd *pwd;
|
||||||
|
|
Loading…
Reference in New Issue