Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin/fhandler_socket.cc')
-rw-r--r--winsup/cygwin/fhandler_socket.cc1673
1 files changed, 0 insertions, 1673 deletions
diff --git a/winsup/cygwin/fhandler_socket.cc b/winsup/cygwin/fhandler_socket.cc
deleted file mode 100644
index b5e5248ec..000000000
--- a/winsup/cygwin/fhandler_socket.cc
+++ /dev/null
@@ -1,1673 +0,0 @@
-/* fhandler_socket.cc. See fhandler.h for a description of the fhandler classes.
-
- Copyright 2000, 2001, 2002, 2003, 2004, 2005 Red Hat, Inc.
-
- This file is part of Cygwin.
-
- This software is a copyrighted work licensed under the terms of the
- Cygwin license. Please consult the file "CYGWIN_LICENSE" for
- details. */
-
-/* #define DEBUG_NEST_ON 1 */
-
-#define __INSIDE_CYGWIN_NET__
-
-#include "winsup.h"
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <sys/uio.h>
-#include <asm/byteorder.h>
-
-#include <stdlib.h>
-#define USE_SYS_TYPES_FD_SET
-#include <winsock2.h>
-#include "cygerrno.h"
-#include "security.h"
-#include "cygwin/version.h"
-#include "perprocess.h"
-#include "path.h"
-#include "fhandler.h"
-#include "dtable.h"
-#include "cygheap.h"
-#include "sigproc.h"
-#include "cygthread.h"
-#include "select.h"
-#include "wininfo.h"
-#include <unistd.h>
-#include <sys/acl.h>
-#include "cygtls.h"
-
-#define ASYNC_MASK (FD_READ|FD_WRITE|FD_OOB|FD_ACCEPT|FD_CONNECT)
-
-extern bool fdsock (cygheap_fdmanip& fd, const device *, 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 *type = NULL, int *secret = NULL)
-{
- int secret_buf [4];
- int* secret_ptr = (secret ? : secret_buf);
-
- if (in->sa_family == AF_INET)
- {
- *out = * (struct sockaddr_in *)in;
- *outlen = inlen;
- return 1;
- }
- else if (in->sa_family == AF_LOCAL)
- {
- path_conv pc (in->sa_data, PC_SYM_FOLLOW);
- if (pc.error)
- {
- set_errno (pc.error);
- return 0;
- }
- if (!pc.exists ())
- {
- set_errno (ENOENT);
- return 0;
- }
- if (!pc.issocket ())
- {
- set_errno (EBADF);
- return 0;
- }
- HANDLE fh = CreateFile (pc, GENERIC_READ, wincap.shared (), &sec_none,
- OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
- if (fh == INVALID_HANDLE_VALUE)
- {
- __seterrno ();
- return 0;
- }
- int ret = 0;
- DWORD len = 0;
- char buf[128];
- memset (buf, 0, sizeof buf);
- if (ReadFile (fh, buf, 128, &len, 0))
- {
- struct sockaddr_in sin;
- char ctype;
- sin.sin_family = AF_INET;
- sscanf (buf + strlen (SOCKET_COOKIE), "%hu %c %08x-%08x-%08x-%08x",
- &sin.sin_port,
- &ctype,
- 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;
- if (type)
- *type = (ctype == 's' ? SOCK_STREAM :
- ctype == 'd' ? SOCK_DGRAM
- : 0);
- ret = 1;
- }
- else
- __seterrno ();
- CloseHandle (fh);
- return ret;
- }
- else
- {
- set_errno (EAFNOSUPPORT);
- return 0;
- }
-}
-
-/**********************************************************************/
-/* fhandler_socket */
-
-fhandler_socket::fhandler_socket () :
- fhandler_base (),
- sun_path (NULL),
- status ()
-{
- need_fork_fixup (true);
- prot_info_ptr = (LPWSAPROTOCOL_INFOA) cmalloc (HEAP_BUF,
- sizeof (WSAPROTOCOL_INFOA));
-#if 0
- if (pc.is_fs_special ())
- {
- fhandler_socket * fhs = (fhandler_socket *) fh;
- fhs->set_addr_family (AF_LOCAL);
- fhs->set_sun_path (posix_path);
- }
-#endif
-}
-
-fhandler_socket::~fhandler_socket ()
-{
- if (prot_info_ptr)
- cfree (prot_info_ptr);
- if (sun_path)
- cfree (sun_path);
-}
-
-char *
-fhandler_socket::get_proc_fd_name (char *buf)
-{
- __small_sprintf (buf, "socket:[%d]", get_socket ());
- return buf;
-}
-
-int
-fhandler_socket::open (int flags, mode_t mode)
-{
- set_errno (ENXIO);
- return 0;
-}
-
-void
-fhandler_socket::af_local_set_sockpair_cred ()
-{
- sec_pid = sec_peer_pid = getpid ();
- sec_uid = sec_peer_uid = geteuid32 ();
- sec_gid = sec_peer_gid = getegid32 ();
-}
-
-void
-fhandler_socket::af_local_setblocking (bool &async, bool &nonblocking)
-{
- async = async_io ();
- nonblocking = is_nonblocking ();
- if (async || nonblocking)
- WSAAsyncSelect (get_socket (), winmsg, 0, 0);
- unsigned long p = 0;
- ioctlsocket (get_socket (), FIONBIO, &p);
- set_nonblocking (false);
- async_io (false);
-}
-
-void
-fhandler_socket::af_local_unsetblocking (bool async, bool nonblocking)
-{
- if (nonblocking)
- {
- unsigned long p = 1;
- ioctlsocket (get_socket (), FIONBIO, &p);
- set_nonblocking (true);
- }
- if (async)
- {
- WSAAsyncSelect (get_socket (), winmsg, WM_ASYNCIO, ASYNC_MASK);
- async_io (true);
- }
-}
-
-bool
-fhandler_socket::af_local_recv_secret ()
-{
- int out[4] = { 0, 0, 0, 0 };
- int rest = sizeof out;
- char *ptr = (char *) out;
- while (rest > 0)
- {
- int ret = recvfrom (ptr, rest, 0, NULL, NULL);
- if (ret <= 0)
- break;
- rest -= ret;
- ptr += ret;
- }
- if (rest == 0)
- {
- debug_printf ("Received af_local secret: %08x-%08x-%08x-%08x",
- out[0], out[1], out[2], out[3]);
- if (out[0] != connect_secret[0] || out[1] != connect_secret[1]
- || out[2] != connect_secret[2] || out[3] != connect_secret[3])
- {
- debug_printf ("Receiving af_local secret mismatch");
- return false;
- }
- }
- else
- debug_printf ("Receiving af_local secret failed");
- return rest == 0;
-}
-
-bool
-fhandler_socket::af_local_send_secret ()
-{
- int rest = sizeof connect_secret;
- char *ptr = (char *) connect_secret;
- while (rest > 0)
- {
- int ret = sendto (ptr, rest, 0, NULL, 0);
- if (ret <= 0)
- break;
- rest -= ret;
- ptr += ret;
- }
- debug_printf ("Sending af_local secret %s", rest == 0 ? "succeeded"
- : "failed");
- return rest == 0;
-}
-
-bool
-fhandler_socket::af_local_recv_cred ()
-{
- struct ucred out = { (pid_t) 0, (__uid32_t) -1, (__gid32_t) -1 };
- int rest = sizeof out;
- char *ptr = (char *) &out;
- while (rest > 0)
- {
- int ret = recvfrom (ptr, rest, 0, NULL, NULL);
- if (ret <= 0)
- break;
- rest -= ret;
- ptr += ret;
- }
- if (rest == 0)
- {
- debug_printf ("Received eid credentials: pid: %d, uid: %d, gid: %d",
- out.pid, out.uid, out.gid);
- sec_peer_pid = out.pid;
- sec_peer_uid = out.uid;
- sec_peer_gid = out.gid;
- }
- else
- debug_printf ("Receiving eid credentials failed");
- return rest == 0;
-}
-
-bool
-fhandler_socket::af_local_send_cred ()
-{
- struct ucred in = { sec_pid, sec_uid, sec_gid };
- int rest = sizeof in;
- char *ptr = (char *) &in;
- while (rest > 0)
- {
- int ret = sendto (ptr, rest, 0, NULL, 0);
- if (ret <= 0)
- break;
- rest -= ret;
- ptr += ret;
- }
- if (rest == 0)
- debug_printf ("Sending eid credentials succeeded");
- else
- debug_printf ("Sending eid credentials failed");
- return rest == 0;
-}
-
-int
-fhandler_socket::af_local_connect ()
-{
- /* This keeps the test out of select. */
- if (get_addr_family () != AF_LOCAL || get_socket_type () != SOCK_STREAM)
- return 0;
-
- debug_printf ("af_local_connect called");
- bool orig_async_io, orig_is_nonblocking;
- af_local_setblocking (orig_async_io, orig_is_nonblocking);
- if (!af_local_send_secret () || !af_local_recv_secret ()
- || !af_local_send_cred () || !af_local_recv_cred ())
- {
- debug_printf ("accept from unauthorized server");
- ::shutdown (get_socket (), SD_BOTH);
- WSASetLastError (WSAECONNREFUSED);
- return -1;
- }
- af_local_unsetblocking (orig_async_io, orig_is_nonblocking);
- return 0;
-}
-
-int
-fhandler_socket::af_local_accept ()
-{
- debug_printf ("af_local_accept called");
- bool orig_async_io, orig_is_nonblocking;
- af_local_setblocking (orig_async_io, orig_is_nonblocking);
- if (!af_local_recv_secret () || !af_local_send_secret ()
- || !af_local_recv_cred () || !af_local_send_cred ())
- {
- debug_printf ("connect from unauthorized client");
- ::shutdown (get_socket (), SD_BOTH);
- ::closesocket (get_socket ());
- WSASetLastError (WSAECONNABORTED);
- return -1;
- }
- af_local_unsetblocking (orig_async_io, orig_is_nonblocking);
- return 0;
-}
-
-void
-fhandler_socket::af_local_set_cred ()
-{
- sec_pid = getpid ();
- sec_uid = geteuid32 ();
- sec_gid = getegid32 ();
- sec_peer_pid = (pid_t) 0;
- sec_peer_uid = (__uid32_t) -1;
- sec_peer_gid = (__gid32_t) -1;
-}
-
-void
-fhandler_socket::af_local_copy (fhandler_socket *sock)
-{
- sock->connect_secret[0] = connect_secret[0];
- sock->connect_secret[1] = connect_secret[1];
- sock->connect_secret[2] = connect_secret[2];
- sock->connect_secret[3] = connect_secret[3];
- sock->sec_pid = sec_pid;
- sock->sec_uid = sec_uid;
- sock->sec_gid = sec_gid;
- sock->sec_peer_pid = sec_peer_pid;
- sock->sec_peer_uid = sec_peer_uid;
- sock->sec_peer_gid = sec_peer_gid;
-}
-
-void
-fhandler_socket::af_local_set_secret (char *buf)
-{
- if (!entropy_source)
- {
- void *buf = malloc (sizeof (fhandler_dev_random));
- entropy_source = new (buf) fhandler_dev_random ();
- entropy_source->dev () = *urandom_dev;
- }
- if (entropy_source &&
- !entropy_source->open (O_RDONLY))
- {
- delete entropy_source;
- entropy_source = NULL;
- }
- if (entropy_source)
- {
- size_t len = sizeof (connect_secret);
- entropy_source->read (connect_secret, len);
- if (len != sizeof (connect_secret))
- bzero ((char*) connect_secret, sizeof (connect_secret));
- }
- __small_sprintf (buf, "%08x-%08x-%08x-%08x",
- connect_secret [0], connect_secret [1],
- connect_secret [2], connect_secret [3]);
-}
-
-void
-fhandler_socket::fixup_before_fork_exec (DWORD win_proc_id)
-{
- if (!winsock2_active)
- {
- fhandler_base::fixup_before_fork_exec (win_proc_id);
- debug_printf ("Without Winsock 2.0");
- }
- else if (!WSADuplicateSocketA (get_socket (), win_proc_id, prot_info_ptr))
- debug_printf ("WSADuplicateSocket went fine, sock %p, win_proc_id %d, prot_info_ptr %p",
- get_socket (), win_proc_id, prot_info_ptr);
- else
- {
- debug_printf ("WSADuplicateSocket error, sock %p, win_proc_id %d, prot_info_ptr %p",
- get_socket (), win_proc_id, prot_info_ptr);
- set_winsock_errno ();
- }
-}
-
-extern "C" void __stdcall load_wsock32 ();
-void
-fhandler_socket::fixup_after_fork (HANDLE parent)
-{
- SOCKET new_sock;
-
- debug_printf ("WSASocket begin, dwServiceFlags1=%d",
- prot_info_ptr->dwServiceFlags1);
-
- if ((new_sock = WSASocketA (FROM_PROTOCOL_INFO,
- FROM_PROTOCOL_INFO,
- FROM_PROTOCOL_INFO,
- prot_info_ptr, 0, 0)) == INVALID_SOCKET)
- {
- debug_printf ("WSASocket error");
- set_io_handle ((HANDLE)INVALID_SOCKET);
- set_winsock_errno ();
- }
- else if (!new_sock && !winsock2_active)
- {
- load_wsock32 ();
- fhandler_base::fixup_after_fork (parent);
- debug_printf ("Without Winsock 2.0");
- }
- else
- {
- debug_printf ("WSASocket went fine new_sock %p, old_sock %p", new_sock, get_io_handle ());
- set_io_handle ((HANDLE) new_sock);
- }
-}
-
-void
-fhandler_socket::fixup_after_exec ()
-{
- debug_printf ("here");
- if (!close_on_exec ())
- fixup_after_fork (NULL);
-#if 0
- else if (!winsock2_active)
- closesocket (get_socket ());
-#endif
-}
-
-int
-fhandler_socket::dup (fhandler_base *child)
-{
- HANDLE nh;
-
- debug_printf ("here");
- fhandler_socket *fhs = (fhandler_socket *) child;
- fhs->addr_family = addr_family;
- fhs->set_socket_type (get_socket_type ());
- if (get_addr_family () == AF_LOCAL)
- {
- fhs->set_sun_path (get_sun_path ());
- if (get_socket_type () == SOCK_STREAM)
- {
- fhs->sec_pid = sec_pid;
- fhs->sec_uid = sec_uid;
- fhs->sec_gid = sec_gid;
- fhs->sec_peer_pid = sec_peer_pid;
- fhs->sec_peer_uid = sec_peer_uid;
- fhs->sec_peer_gid = sec_peer_gid;
- }
- }
- fhs->connect_state (connect_state ());
-
- if (winsock2_active)
- {
- /* Since WSADuplicateSocket() fails on NT systems when the process
- is currently impersonating a non-privileged account, we revert
- to the original account before calling WSADuplicateSocket() and
- switch back afterwards as it's also in fork().
- If WSADuplicateSocket() still fails for some reason, we fall back
- to DuplicateHandle(). */
- WSASetLastError (0);
- cygheap->user.deimpersonate ();
- fhs->set_io_handle (get_io_handle ());
- fhs->fixup_before_fork_exec (GetCurrentProcessId ());
- cygheap->user.reimpersonate ();
- if (!WSAGetLastError ())
- {
- fhs->fixup_after_fork (hMainProc);
- if (fhs->get_io_handle() != (HANDLE) INVALID_SOCKET)
- {
- cygheap->fdtab.inc_need_fixup_before ();
- return 0;
- }
- }
- debug_printf ("WSADuplicateSocket failed, trying DuplicateHandle");
- }
-
- /* We don't call fhandler_base::dup here since that requires
- having winsock called from fhandler_base and it creates only
- inheritable sockets which is wrong for winsock2. */
-
- if (!DuplicateHandle (hMainProc, get_io_handle (), hMainProc, &nh, 0,
- !winsock2_active, DUPLICATE_SAME_ACCESS))
- {
- system_printf ("!DuplicateHandle(%x) failed, %E", get_io_handle ());
- __seterrno ();
- return -1;
- }
- VerifyHandle (nh);
- fhs->set_io_handle (nh);
- cygheap->fdtab.inc_need_fixup_before ();
- return 0;
-}
-
-int __stdcall
-fhandler_socket::fstat (struct __stat64 *buf)
-{
- int res;
- if (get_device () == FH_UNIX)
- {
- res = fhandler_base::fstat_fs (buf);
- if (!res)
- {
- buf->st_mode = (buf->st_mode & ~S_IFMT) | S_IFSOCK;
- }
- }
- else
- {
- res = fhandler_base::fstat (buf);
- if (!res)
- {
- buf->st_dev = 0;
- buf->st_ino = (__ino64_t) ((DWORD) get_handle ());
- buf->st_mode = S_IFSOCK | S_IRWXU | S_IRWXG | S_IRWXO;
- }
- }
- return res;
-}
-
-int
-fhandler_socket::fchmod (mode_t mode)
-{
- if (get_device () == FH_UNIX)
- {
- fhandler_disk_file fh (pc);
- fh.get_device () = FH_FS;
- int ret = fh.fchmod (mode);
- SetFileAttributes (pc, GetFileAttributes (pc) | FILE_ATTRIBUTE_SYSTEM);
- return ret;
- }
- return 0;
-}
-
-int
-fhandler_socket::fchown (__uid32_t uid, __gid32_t gid)
-{
- if (get_device () == FH_UNIX)
- {
- fhandler_disk_file fh (pc);
- return fh.fchown (uid, gid);
- }
- return 0;
-}
-
-int
-fhandler_socket::facl (int cmd, int nentries, __aclent32_t *aclbufp)
-{
- if (get_device () == FH_UNIX)
- {
- fhandler_disk_file fh (pc);
- return fh.facl (cmd, nentries, aclbufp);
- }
- return fhandler_base::facl (cmd, nentries, aclbufp);
-}
-
-int
-fhandler_socket::link (const char *newpath)
-{
- if (get_device () == FH_UNIX)
- {
- fhandler_disk_file fh (pc);
- return fh.link (newpath);
- }
- return fhandler_base::link (newpath);
-}
-
-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;
-
- 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);
-
- path_conv pc (un_addr->sun_path, PC_SYM_FOLLOW);
- if (pc.error)
- {
- set_errno (pc.error);
- goto out;
- }
- if (pc.exists ())
- {
- set_errno (EADDRINUSE);
- goto out;
- }
- mode_t mode = (S_IRWXU | S_IRWXG | S_IRWXO) & ~cygheap->umask;
- DWORD attr = FILE_ATTRIBUTE_SYSTEM;
- if (!(mode & (S_IWUSR | S_IWGRP | S_IWOTH)))
- attr |= FILE_ATTRIBUTE_READONLY;
- SECURITY_ATTRIBUTES sa = sec_none;
- security_descriptor sd;
- if (allow_ntsec && pc.has_acls ())
- set_security_attribute (mode, &sa, sd);
- HANDLE fh = CreateFile (pc, GENERIC_WRITE, 0, &sa, CREATE_NEW, attr, 0);
- if (fh == INVALID_HANDLE_VALUE)
- {
- if (GetLastError () == ERROR_ALREADY_EXISTS)
- set_errno (EADDRINUSE);
- else
- __seterrno ();
- }
-
- char buf[sizeof (SOCKET_COOKIE) + 80];
- __small_sprintf (buf, "%s%u %c ", SOCKET_COOKIE, sin.sin_port, get_socket_type () == SOCK_STREAM ? 's' : get_socket_type () == SOCK_DGRAM ? 'd' : '-');
- af_local_set_secret (strchr (buf, '\0'));
- DWORD blen = strlen (buf) + 1;
- if (!WriteFile (fh, buf, blen, &blen, 0))
- {
- __seterrno ();
- CloseHandle (fh);
- DeleteFile (pc);
- }
- else
- {
- CloseHandle (fh);
- 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 in_progress = false;
- struct sockaddr_in sin;
- DWORD err;
- int type;
-
- if (!get_inet_addr (name, namelen, &sin, &namelen, &type, connect_secret))
- return -1;
-
- if (get_addr_family () == AF_LOCAL && get_socket_type () != type)
- {
- WSASetLastError (WSAEPROTOTYPE);
- set_winsock_errno ();
- return -1;
- }
-
- res = ::connect (get_socket (), (struct sockaddr *) &sin, namelen);
-
- if (!res)
- err = 0;
- else
- {
- err = WSAGetLastError ();
- /* Special handling for connect to return the correct error code
- when called on a non-blocking socket. */
- if (is_nonblocking ())
- {
- if (err == WSAEWOULDBLOCK || err == WSAEALREADY)
- in_progress = true;
-
- if (err == WSAEWOULDBLOCK)
- WSASetLastError (err = WSAEINPROGRESS);
- else if (err == WSAEINVAL)
- WSASetLastError (err = WSAEISCONN);
- }
- set_winsock_errno ();
- }
-
- if (get_addr_family () == AF_LOCAL && (!res || in_progress))
- set_sun_path (name->sa_data);
-
- if (get_addr_family () == AF_LOCAL && get_socket_type () == SOCK_STREAM)
- {
- af_local_set_cred (); /* Don't move into af_local_connect since
- af_local_connect is called from select,
- possibly running under another identity. */
- if (!res && af_local_connect ())
- {
- set_winsock_errno ();
- return -1;
- }
- }
-
- if (err == WSAEINPROGRESS || err == WSAEALREADY)
- connect_state (connect_pending);
- else if (err)
- connect_state (connect_failed);
- else
- connect_state (connected);
-
- return res;
-}
-
-int
-fhandler_socket::listen (int backlog)
-{
- int res = ::listen (get_socket (), backlog);
- if (res)
- set_winsock_errno ();
- else
- {
- if (get_addr_family () == AF_LOCAL && get_socket_type () == SOCK_STREAM)
- af_local_set_cred ();
- connect_state (connected);
- }
- return res;
-}
-
-int
-fhandler_socket::accept (struct sockaddr *peer, int *len)
-{
- int res = -1;
-
- /* 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);
-
- if (res == (int) INVALID_SOCKET)
- set_winsock_errno ();
- else
- {
- cygheap_fdnew res_fd;
- if (res_fd >= 0 && fdsock (res_fd, &dev (), res))
- {
- fhandler_socket *sock = (fhandler_socket *) res_fd;
- sock->set_addr_family (get_addr_family ());
- sock->set_socket_type (get_socket_type ());
- sock->async_io (async_io ());
- sock->set_nonblocking (is_nonblocking ());
- if (get_addr_family () == AF_LOCAL)
- {
- sock->set_sun_path (get_sun_path ());
- if (get_socket_type () == SOCK_STREAM)
- {
- /* Don't forget to copy credentials from accepting
- socket to accepted socket and start transaction
- on accepted socket! */
- af_local_copy (sock);
- res = sock->af_local_accept ();
- if (res == -1)
- {
- res_fd.release ();
- set_winsock_errno ();
- goto out;
- }
- }
- }
- sock->connect_state (connected);
- res = res_fd;
- }
- else
- {
- closesocket (res);
- res = -1;
- }
- }
-
-out:
- debug_printf ("res %d", res);
- return res;
-}
-
-int
-fhandler_socket::getsockname (struct sockaddr *name, int *namelen)
-{
- int res = -1;
-
- 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)
-{
- int res = ::getpeername (get_socket (), name, namelen);
- if (res)
- set_winsock_errno ();
-
- return res;
-}
-
-bool
-fhandler_socket::prepare (HANDLE &event, long event_mask)
-{
- WSASetLastError (0);
- closed (false);
- if ((event = WSACreateEvent ()) == WSA_INVALID_EVENT)
- {
- debug_printf ("WSACreateEvent, %E");
- return false;
- }
- if (WSAEventSelect (get_socket (), event, event_mask) == SOCKET_ERROR)
- {
- debug_printf ("WSAEventSelect, %E");
- return false;
- }
- return true;
-}
-
-int
-fhandler_socket::wait (HANDLE event, int flags)
-{
- int ret = SOCKET_ERROR;
- int wsa_err = 0;
- WSAEVENT ev[2] = { event, signal_arrived };
- WSANETWORKEVENTS evts;
-
- switch (WSAWaitForMultipleEvents (2, ev, FALSE, 10, FALSE))
- {
- case WSA_WAIT_TIMEOUT:
- ret = 0;
- break;
- case WSA_WAIT_EVENT_0:
- if (!WSAEnumNetworkEvents (get_socket (), event, &evts))
- {
- if (!evts.lNetworkEvents)
- {
- ret = 0;
- break;
- }
- if (evts.lNetworkEvents & FD_OOB)
- {
- if (evts.iErrorCode[FD_OOB_BIT])
- wsa_err = evts.iErrorCode[FD_OOB_BIT];
- else if (flags & MSG_OOB)
- ret = 0;
- else
- {
- raise (SIGURG);
- WSASetLastError (WSAEINTR);
- break;
- }
- }
- if (evts.lNetworkEvents & FD_READ)
- {
- if (evts.iErrorCode[FD_READ_BIT])
- wsa_err = evts.iErrorCode[FD_READ_BIT];
- else
- ret = 0;
- }
- else if (evts.lNetworkEvents & FD_WRITE)
- {
- if (evts.iErrorCode[FD_WRITE_BIT])
- wsa_err = evts.iErrorCode[FD_WRITE_BIT];
- else
- ret = 0;
- }
- if (evts.lNetworkEvents & FD_CLOSE)
- {
- closed (true);
- if (!wsa_err)
- {
- if (evts.iErrorCode[FD_CLOSE_BIT])
- wsa_err = evts.iErrorCode[FD_CLOSE_BIT];
- else
- ret = 0;
- }
- }
- if (wsa_err)
- WSASetLastError (wsa_err);
- }
- break;
- case WSA_WAIT_EVENT_0 + 1:
- WSASetLastError (WSAEINTR);
- break;
- default:
- WSASetLastError (WSAEFAULT);
- break;
- }
- return ret;
-}
-
-void
-fhandler_socket::release (HANDLE event)
-{
- int last_err = WSAGetLastError ();
- /* KB 168349: NT4 fails if the event parameter is not NULL. */
- WSAEventSelect (get_socket (), NULL, 0);
- WSACloseEvent (event);
- unsigned long non_block = 0;
- if (ioctlsocket (get_socket (), FIONBIO, &non_block))
- debug_printf ("return to blocking failed: %d", WSAGetLastError ());
- else
- WSASetLastError (last_err);
-}
-
-int
-fhandler_socket::readv (const struct iovec *const iov, const int iovcnt,
- ssize_t tot)
-{
- struct msghdr msg =
- {
- msg_name: NULL,
- msg_namelen: 0,
- msg_iov: (struct iovec *) iov, // const_cast
- msg_iovlen: iovcnt,
- msg_accrights: NULL,
- msg_accrightslen: 0
- };
-
- return recvmsg (&msg, 0, tot);
-}
-
-int
-fhandler_socket::recvfrom (void *ptr, size_t len, int flags,
- struct sockaddr *from, int *fromlen)
-{
- int res = SOCKET_ERROR;
- DWORD ret = 0;
-
- flags &= MSG_WINMASK;
- if (!winsock2_active)
- ret = res = ::recvfrom (get_socket (),
- (char *) ptr, len, flags,
- from, fromlen);
- else
- {
- WSABUF wsabuf = { len, (char *) ptr };
-
- if (is_nonblocking () || closed () || async_io ())
- res = WSARecvFrom (get_socket (), &wsabuf, 1, &ret,
- (DWORD *) &flags, from, fromlen, NULL, NULL);
- else
- {
- HANDLE evt;
- if (prepare (evt, FD_CLOSE | FD_READ | (owner () ? FD_OOB : 0)))
- {
- do
- {
- DWORD lflags = (DWORD) flags;
- res = WSARecvFrom (get_socket (), &wsabuf, 1, &ret, &lflags,
- from, fromlen, NULL, NULL);
- }
- while (res == SOCKET_ERROR
- && WSAGetLastError () == WSAEWOULDBLOCK
- && !closed ()
- && !(res = wait (evt, flags)));
- release (evt);
- }
- }
- }
-
- if (res == SOCKET_ERROR)
- {
- /* According to SUSv3, errno isn't set in that case and no error
- condition is returned. */
- if (WSAGetLastError () == WSAEMSGSIZE)
- return len;
-
- set_winsock_errno ();
- }
- else
- res = ret;
-
- return res;
-}
-
-int
-fhandler_socket::recvmsg (struct msghdr *msg, int flags, ssize_t tot)
-{
- 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*/
- msg->msg_accrightslen = 0;
- }
-
- struct iovec *const iov = msg->msg_iov;
- const int iovcnt = msg->msg_iovlen;
-
- struct sockaddr *from = (struct sockaddr *) msg->msg_name;
- int *fromlen = from ? &msg->msg_namelen : NULL;
-
- int res = SOCKET_ERROR;
-
- if (!winsock2_active)
- {
- if (iovcnt == 1)
- res = recvfrom (iov->iov_base, iov->iov_len, flags, from, fromlen);
- else
- {
- if (tot == -1) // i.e. if not pre-calculated by the caller.
- {
- tot = 0;
- const struct iovec *iovptr = iov + iovcnt;
- do
- {
- iovptr -= 1;
- tot += iovptr->iov_len;
- }
- while (iovptr != iov);
- }
-
- char *buf = (char *) alloca (tot);
-
- if (!buf)
- {
- set_errno (ENOMEM);
- res = SOCKET_ERROR;
- }
- else
- {
- res = recvfrom (buf, tot, flags, from, fromlen);
-
- const struct iovec *iovptr = iov;
- int nbytes = res;
-
- while (nbytes > 0)
- {
- const int frag = min (nbytes, (ssize_t) iovptr->iov_len);
- memcpy (iovptr->iov_base, buf, frag);
- buf += frag;
- iovptr += 1;
- nbytes -= frag;
- }
- }
- }
- }
- else
- {
- WSABUF wsabuf[iovcnt];
- unsigned long len = 0L;
-
- {
- const struct iovec *iovptr = iov + iovcnt;
- WSABUF *wsaptr = wsabuf + iovcnt;
- do
- {
- iovptr -= 1;
- wsaptr -= 1;
- len += wsaptr->len = iovptr->iov_len;
- wsaptr->buf = (char *) iovptr->iov_base;
- }
- while (wsaptr != wsabuf);
- }
-
- DWORD ret = 0;
-
- if (is_nonblocking () || closed () || async_io ())
- res = WSARecvFrom (get_socket (), wsabuf, iovcnt, &ret,
- (DWORD *) &flags, from, fromlen, NULL, NULL);
- else
- {
- HANDLE evt;
- if (prepare (evt, FD_CLOSE | FD_READ | (owner () ? FD_OOB : 0)))
- {
- do
- {
- DWORD lflags = (DWORD) flags;
- res = WSARecvFrom (get_socket (), wsabuf, iovcnt, &ret,
- &lflags, from, fromlen, NULL, NULL);
- }
- while (res == SOCKET_ERROR
- && WSAGetLastError () == WSAEWOULDBLOCK
- && !closed ()
- && !(res = wait (evt, flags)));
- release (evt);
- }
- }
-
- if (res == SOCKET_ERROR)
- {
- /* According to SUSv3, errno isn't set in that case and no error
- condition is returned. */
- if (WSAGetLastError () == WSAEMSGSIZE)
- return len;
-
- set_winsock_errno ();
- }
- else
- res = ret;
- }
-
- return res;
-}
-
-int
-fhandler_socket::writev (const struct iovec *const iov, const int iovcnt,
- ssize_t tot)
-{
- struct msghdr msg =
- {
- msg_name: NULL,
- msg_namelen: 0,
- msg_iov: (struct iovec *) iov, // const_cast
- msg_iovlen: iovcnt,
- msg_accrights: NULL,
- msg_accrightslen: 0
- };
-
- return sendmsg (&msg, 0, tot);
-}
-
-int
-fhandler_socket::sendto (const void *ptr, size_t len, int flags,
- const struct sockaddr *to, int tolen)
-{
- struct sockaddr_in sin;
-
- if (to && !get_inet_addr (to, tolen, &sin, &tolen))
- return SOCKET_ERROR;
-
- int res = SOCKET_ERROR;
- DWORD ret = 0;
-
- if (!winsock2_active)
- ret = res = ::sendto (get_socket (), (const char *) ptr, len,
- flags & MSG_WINMASK,
- (to ? (const struct sockaddr *) &sin : NULL), tolen);
- else
- {
- WSABUF wsabuf = { len, (char *) ptr };
-
- if (is_nonblocking () || closed () || async_io ())
- res = WSASendTo (get_socket (), &wsabuf, 1, &ret,
- flags & MSG_WINMASK,
- (to ? (const struct sockaddr *) &sin : NULL), tolen,
- NULL, NULL);
- else
- {
- HANDLE evt;
- if (prepare (evt, FD_CLOSE | FD_WRITE | (owner () ? FD_OOB : 0)))
- {
- do
- {
- res = WSASendTo (get_socket (), &wsabuf, 1, &ret,
- flags & MSG_WINMASK,
- (to ? (const struct sockaddr *) &sin : NULL),
- tolen, NULL, NULL);
- }
- while (res == SOCKET_ERROR
- && WSAGetLastError () == WSAEWOULDBLOCK
- && !(res = wait (evt, 0))
- && !closed ());
- release (evt);
- }
- }
- }
-
- if (res == SOCKET_ERROR)
- set_winsock_errno ();
- else
- res = ret;
-
- /* Special handling for EPIPE and SIGPIPE.
-
- EPIPE is generated if the local end has been shut down on a connection
- oriented socket. In this case the process will also receive a SIGPIPE
- unless MSG_NOSIGNAL is set. */
- if (res == SOCKET_ERROR && get_errno () == ESHUTDOWN
- && get_socket_type () == SOCK_STREAM)
- {
- set_errno (EPIPE);
- if (! (flags & MSG_NOSIGNAL))
- raise (SIGPIPE);
- }
-
- return res;
-}
-
-int
-fhandler_socket::sendmsg (const struct msghdr *msg, int flags, ssize_t tot)
-{
- 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*/
- }
-
- struct iovec *const iov = msg->msg_iov;
- const int iovcnt = msg->msg_iovlen;
-
- int res = SOCKET_ERROR;
-
- if (!winsock2_active)
- {
- if (iovcnt == 1)
- res = sendto (iov->iov_base, iov->iov_len, flags,
- (struct sockaddr *) msg->msg_name,
- msg->msg_namelen);
- else
- {
- if (tot == -1) // i.e. if not pre-calculated by the caller.
- {
- tot = 0;
- const struct iovec *iovptr = iov + iovcnt;
- do
- {
- iovptr -= 1;
- tot += iovptr->iov_len;
- }
- while (iovptr != iov);
- }
-
- char *const buf = (char *) alloca (tot);
-
- if (!buf)
- {
- set_errno (ENOMEM);
- res = SOCKET_ERROR;
- }
- else
- {
- char *bufptr = buf;
- const struct iovec *iovptr = iov;
- int nbytes = tot;
-
- while (nbytes != 0)
- {
- const int frag = min (nbytes, (ssize_t) iovptr->iov_len);
- memcpy (bufptr, iovptr->iov_base, frag);
- bufptr += frag;
- iovptr += 1;
- nbytes -= frag;
- }
-
- res = sendto (buf, tot, flags,
- (struct sockaddr *) msg->msg_name,
- msg->msg_namelen);
- }
- }
- }
- else
- {
- WSABUF wsabuf[iovcnt];
-
- {
- const struct iovec *iovptr = iov + iovcnt;
- WSABUF *wsaptr = wsabuf + iovcnt;
- do
- {
- iovptr -= 1;
- wsaptr -= 1;
- wsaptr->len = iovptr->iov_len;
- wsaptr->buf = (char *) iovptr->iov_base;
- }
- while (wsaptr != wsabuf);
- }
-
- DWORD ret = 0;
-
- if (is_nonblocking () || closed () || async_io ())
- res = WSASendTo (get_socket (), wsabuf, iovcnt, &ret,
- flags, (struct sockaddr *) msg->msg_name,
- msg->msg_namelen, NULL, NULL);
- else
- {
- HANDLE evt;
- if (prepare (evt, FD_CLOSE | FD_WRITE | (owner () ? FD_OOB : 0)))
- {
- do
- {
- res = WSASendTo (get_socket (), wsabuf, iovcnt,
- &ret, flags,
- (struct sockaddr *) msg->msg_name,
- msg->msg_namelen, NULL, NULL);
- }
- while (res == SOCKET_ERROR
- && WSAGetLastError () == WSAEWOULDBLOCK
- && !(res = wait (evt, 0))
- && !closed ());
- release (evt);
- }
- }
-
- if (res == SOCKET_ERROR)
- set_winsock_errno ();
- else
- res = ret;
- }
-
- /* Special handling for EPIPE and SIGPIPE.
-
- EPIPE is generated if the local end has been shut down on a connection
- oriented socket. In this case the process will also receive a SIGPIPE
- unless MSG_NOSIGNAL is set. */
- if (res == SOCKET_ERROR && get_errno () == ESHUTDOWN
- && get_socket_type () == SOCK_STREAM)
- {
- set_errno (EPIPE);
- if (! (flags & MSG_NOSIGNAL))
- raise (SIGPIPE);
- }
-
- return res;
-}
-
-int
-fhandler_socket::shutdown (int how)
-{
- int res = ::shutdown (get_socket (), how);
-
- if (res)
- set_winsock_errno ();
- else
- switch (how)
- {
- case SHUT_RD:
- saw_shutdown_read (true);
- break;
- case SHUT_WR:
- saw_shutdown_write (true);
- break;
- case SHUT_RDWR:
- saw_shutdown_read (true);
- saw_shutdown_write (true);
- break;
- }
- return res;
-}
-
-int
-fhandler_socket::close ()
-{
- int res = 0;
-
- /* HACK to allow a graceful shutdown even if shutdown() hasn't been
- called by the application. Note that this isn't the ultimate
- solution but it helps in many cases. */
- struct linger linger;
- linger.l_onoff = 1;
- linger.l_linger = 240; /* secs. default 2MSL value according to MSDN. */
- setsockopt (get_socket (), SOL_SOCKET, SO_LINGER,
- (const char *)&linger, sizeof linger);
-
- while ((res = closesocket (get_socket ())) != 0)
- {
- if (WSAGetLastError () != WSAEWOULDBLOCK)
- {
- set_winsock_errno ();
- res = -1;
- break;
- }
- if (WaitForSingleObject (signal_arrived, 10) == WAIT_OBJECT_0)
- {
- set_errno (EINTR);
- res = -1;
- break;
- }
- WSASetLastError (0);
- }
-
- debug_printf ("%d = fhandler_socket::close()", res);
- return res;
-}
-
-int
-fhandler_socket::ioctl (unsigned int cmd, void *p)
-{
- extern int get_ifconf (struct ifconf *ifc, int what); /* net.cc */
- int res;
- struct ifconf ifc, *ifcp;
- struct ifreq *ifr, *ifrp;
-
- switch (cmd)
- {
- case SIOCGIFCONF:
- ifcp = (struct ifconf *) p;
- if (!ifcp)
- {
- set_errno (EINVAL);
- return -1;
- }
- res = get_ifconf (ifcp, cmd);
- if (res)
- debug_printf ("error in get_ifconf");
- break;
- case SIOCGIFFLAGS:
- ifr = (struct ifreq *) p;
- if (ifr == 0)
- {
- set_errno (EINVAL);
- return -1;
- }
- ifr->ifr_flags = IFF_NOTRAILERS | IFF_UP | IFF_RUNNING;
- if (!strncmp(ifr->ifr_name, "lo", 2)
- || ntohl (((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr)
- == INADDR_LOOPBACK)
- ifr->ifr_flags |= IFF_LOOPBACK;
- else
- ifr->ifr_flags |= IFF_BROADCAST;
- res = 0;
- break;
- case SIOCGIFBRDADDR:
- case SIOCGIFNETMASK:
- case SIOCGIFADDR:
- case SIOCGIFHWADDR:
- case SIOCGIFMETRIC:
- case SIOCGIFMTU:
- {
- ifc.ifc_len = 2048;
- ifc.ifc_buf = (char *) alloca (2048);
-
- ifr = (struct ifreq *) p;
- if (ifr == 0)
- {
- debug_printf ("ifr == NULL");
- set_errno (EINVAL);
- return -1;
- }
-
- res = get_ifconf (&ifc, cmd);
- if (res)
- {
- debug_printf ("error in get_ifconf");
- break;
- }
-
- debug_printf (" name: %s", ifr->ifr_name);
- for (ifrp = ifc.ifc_req;
- (caddr_t) ifrp < ifc.ifc_buf + ifc.ifc_len;
- ++ifrp)
- {
- debug_printf ("testname: %s", ifrp->ifr_name);
- if (! strcmp (ifrp->ifr_name, ifr->ifr_name))
- {
- switch (cmd)
- {
- case SIOCGIFADDR:
- ifr->ifr_addr = ifrp->ifr_addr;
- break;
- case SIOCGIFBRDADDR:
- ifr->ifr_broadaddr = ifrp->ifr_broadaddr;
- break;
- case SIOCGIFNETMASK:
- ifr->ifr_netmask = ifrp->ifr_netmask;
- break;
- case SIOCGIFHWADDR:
- ifr->ifr_hwaddr = ifrp->ifr_hwaddr;
- break;
- case SIOCGIFMETRIC:
- ifr->ifr_metric = ifrp->ifr_metric;
- break;
- case SIOCGIFMTU:
- ifr->ifr_mtu = ifrp->ifr_mtu;
- break;
- }
- break;
- }
- }
- if ((caddr_t) ifrp >= ifc.ifc_buf + ifc.ifc_len)
- {
- set_errno (EINVAL);
- return -1;
- }
- break;
- }
- case FIOASYNC:
- res = WSAAsyncSelect (get_socket (), winmsg, WM_ASYNCIO,
- *(int *) p ? ASYNC_MASK : 0);
- syscall_printf ("Async I/O on socket %s",
- *(int *) p ? "started" : "cancelled");
- async_io (*(int *) p != 0);
- break;
- case FIONREAD:
- res = ioctlsocket (get_socket (), FIONREAD, (unsigned long *) p);
- if (res == SOCKET_ERROR)
- set_winsock_errno ();
- break;
- default:
- /* We must cancel WSAAsyncSelect (if any) before setting socket to
- * blocking mode
- */
- if (cmd == FIONBIO && async_io () && *(int *) p == 0)
- WSAAsyncSelect (get_socket (), winmsg, 0, 0);
- res = ioctlsocket (get_socket (), cmd, (unsigned long *) p);
- if (res == SOCKET_ERROR)
- set_winsock_errno ();
- if (cmd == FIONBIO)
- {
- syscall_printf ("socket is now %sblocking",
- *(int *) p ? "non" : "");
- /* Start AsyncSelect if async socket unblocked */
- if (*(int *) p && async_io ())
- WSAAsyncSelect (get_socket (), winmsg, WM_ASYNCIO, ASYNC_MASK);
-
- set_nonblocking (*(int *) p);
- }
- break;
- }
- syscall_printf ("%d = ioctl_socket (%x, %x)", res, cmd, p);
- return res;
-}
-
-int
-fhandler_socket::fcntl (int cmd, void *arg)
-{
- int res = 0;
- int request, current;
-
- switch (cmd)
- {
- case F_SETOWN:
- {
- /* Urgh! Bad hack! */
- pid_t pid = (pid_t) arg;
- owner (pid == getpid ());
- debug_printf ("owner set to %d", owner ());
- }
- break;
- case F_SETFL:
- {
- /* Carefully test for the O_NONBLOCK or deprecated OLD_O_NDELAY flag.
- Set only the flag that has been passed in. If both are set, just
- record O_NONBLOCK. */
- int new_flags = (int) arg & O_NONBLOCK_MASK;
- if ((new_flags & OLD_O_NDELAY) && (new_flags & O_NONBLOCK))
- new_flags = O_NONBLOCK;
- current = get_flags () & O_NONBLOCK_MASK;
- request = new_flags ? 1 : 0;
- if (!!current != !!new_flags && (res = ioctl (FIONBIO, &request)))
- break;
- set_flags ((get_flags () & ~O_NONBLOCK_MASK) | new_flags);
- break;
- }
- default:
- res = fhandler_base::fcntl (cmd, arg);
- break;
- }
- return res;
-}
-
-void
-fhandler_socket::set_close_on_exec (bool val)
-{
- if (!winsock2_active) /* < Winsock 2.0 */
- set_no_inheritance (get_handle (), val);
- close_on_exec (val);
- debug_printf ("set close_on_exec for %s to %d", get_name (), val);
-}
-
-void
-fhandler_socket::set_sun_path (const char *path)
-{
- sun_path = path ? cstrdup (path) : NULL;
-}
-
-int
-fhandler_socket::getpeereid (pid_t *pid, __uid32_t *euid, __gid32_t *egid)
-{
- if (get_addr_family () != AF_LOCAL || get_socket_type () != SOCK_STREAM)
- {
- set_errno (EINVAL);
- return -1;
- }
- if (connect_state () != connected)
- {
- set_errno (ENOTCONN);
- return -1;
- }
- if (sec_peer_pid == (pid_t) 0)
- {
- set_errno (ENOTCONN); /* Usually when calling getpeereid on
- accepting (instead of accepted) socket. */
- return -1;
- }
-
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
- if (pid)
- *pid = sec_peer_pid;
- if (euid)
- *euid = sec_peer_uid;
- if (egid)
- *egid = sec_peer_gid;
- return 0;
-}