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/net.cc')
-rw-r--r--winsup/cygwin/net.cc1380
1 files changed, 593 insertions, 787 deletions
diff --git a/winsup/cygwin/net.cc b/winsup/cygwin/net.cc
index c310c78b3..32b4b2ef1 100644
--- a/winsup/cygwin/net.cc
+++ b/winsup/cygwin/net.cc
@@ -1,6 +1,6 @@
/* net.cc: network-related routines.
- Copyright 1996, 1997, 1998, 1999, 2000, 2001 Red Hat, Inc.
+ Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
This file is part of Cygwin.
@@ -21,7 +21,6 @@ details. */
#include <stdlib.h>
#include <unistd.h>
#include <netdb.h>
-#include <fcntl.h>
#define USE_SYS_TYPES_FD_SET
#include <winsock2.h>
#include "cygerrno.h"
@@ -30,10 +29,10 @@ details. */
#include "path.h"
#include "dtable.h"
#include "cygheap.h"
-#include "sync.h"
#include "sigproc.h"
#include "pinfo.h"
#include "registry.h"
+#include "wsock_event.h"
extern "C" {
int h_errno;
@@ -46,23 +45,6 @@ int __stdcall rresvport (int *);
int sscanf (const char *, const char *, ...);
} /* End of "C" section */
-class wsock_event
-{
- WSAEVENT event;
- WSAOVERLAPPED ovr;
-public:
- wsock_event () : event (NULL) {};
- ~wsock_event ()
- {
- if (event)
- WSACloseEvent (event);
- event = NULL;
- };
-
- LPWSAOVERLAPPED prepare ();
- int wait (int socket, LPDWORD flags);
-};
-
LPWSAOVERLAPPED
wsock_event::prepare ()
{
@@ -88,18 +70,18 @@ wsock_event::wait (int socket, LPDWORD flags)
int ret = -1;
WSAEVENT ev[2] = { event, signal_arrived };
- switch (WSAWaitForMultipleEvents(2, ev, FALSE, WSA_INFINITE, FALSE))
+ switch (WSAWaitForMultipleEvents (2, ev, FALSE, WSA_INFINITE, FALSE))
{
case WSA_WAIT_EVENT_0:
DWORD len;
- if (WSAGetOverlappedResult(socket, &ovr, &len, FALSE, flags))
+ if (WSAGetOverlappedResult (socket, &ovr, &len, FALSE, flags))
ret = (int) len;
break;
case WSA_WAIT_EVENT_0 + 1:
if (!CancelIo ((HANDLE)socket))
{
debug_printf ("CancelIo() %E, fallback to blocking io");
- WSAGetOverlappedResult(socket, &ovr, &len, TRUE, flags);
+ WSAGetOverlappedResult (socket, &ovr, &len, TRUE, flags);
}
else
WSASetLastError (WSAEINTR);
@@ -118,23 +100,30 @@ wsock_event::wait (int socket, LPDWORD flags)
WSADATA wsadata;
/* Cygwin internal */
+static fhandler_socket *
+get (const int fd)
+{
+ cygheap_fdget cfd (fd);
+ if (cfd < 0)
+ return 0;
+
+ fhandler_socket *const fh = cfd->is_socket ();
+ if (!fh)
+ set_errno (ENOTSOCK);
+
+ return fh;
+}
+
+/* Cygwin internal */
static SOCKET __stdcall
set_socket_inheritance (SOCKET sock)
{
- if (wincap.has_set_handle_information ())
- (void) SetHandleInformation ((HANDLE) sock, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT);
+ SOCKET osock = sock;
+ if (!DuplicateHandle (hMainProc, (HANDLE) sock, hMainProc, (HANDLE *) &sock,
+ 0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
+ system_printf ("DuplicateHandle failed %E");
else
- {
- SOCKET newsock;
- if (!DuplicateHandle (hMainProc, (HANDLE) sock, hMainProc, (HANDLE *) &newsock,
- 0, TRUE, DUPLICATE_SAME_ACCESS))
- small_printf ("DuplicateHandle failed %E");
- else
- {
- closesocket (sock);
- sock = newsock;
- }
- }
+ debug_printf ("DuplicateHandle succeeded osock %p, sock %p", osock, sock);
return sock;
}
@@ -203,6 +192,8 @@ cygwin_inet_ntoa (struct in_addr in)
extern "C" unsigned long
cygwin_inet_addr (const char *cp)
{
+ if (check_null_str_errno (cp))
+ return INADDR_NONE;
unsigned long res = inet_addr (cp);
return res;
}
@@ -213,6 +204,9 @@ cygwin_inet_addr (const char *cp)
extern "C" int
cygwin_inet_aton (const char *cp, struct in_addr *inp)
{
+ if (check_null_str_errno (cp) || check_null_invalid_struct_errno (inp))
+ return 0;
+
unsigned long res = inet_addr (cp);
if (res == INADDR_NONE && strcmp (cp, "255.255.255.255"))
return 0;
@@ -227,6 +221,8 @@ extern "C" unsigned int WINAPI inet_network (const char *);
extern "C" unsigned int
cygwin_inet_network (const char *cp)
{
+ if (check_null_str_errno (cp))
+ return INADDR_NONE;
unsigned int res = inet_network (cp);
return res;
}
@@ -240,7 +236,6 @@ inet_netof (struct in_addr in)
{
unsigned long i, res;
-
i = ntohl (in.s_addr);
if (IN_CLASSA (i))
res = (i & IN_CLASSA_NET) >> IN_CLASSA_NSHIFT;
@@ -263,7 +258,6 @@ inet_makeaddr (int net, int lna)
unsigned long i;
struct in_addr in;
-
if (net < IN_CLASSA_MAX)
i = (net << IN_CLASSA_NSHIFT) | (lna & IN_CLASSA_HOST);
else if (net < IN_CLASSB_MAX)
@@ -356,7 +350,7 @@ __set_winsock_errno (const char *fn, int ln)
* Since the member `s' isn't used for debug output we can use it
* for the error text returned by herror and hstrerror.
*/
-const static NO_COPY struct tl host_errmap[] =
+static NO_COPY struct tl host_errmap[] =
{
{WSAHOST_NOT_FOUND, "Unknown host", HOST_NOT_FOUND},
{WSATRY_AGAIN, "Host name lookup failure", TRY_AGAIN},
@@ -423,9 +417,9 @@ dup_addr_list (char **src, unsigned int size)
return NULL;
while (cnt-- > 0)
{
- if (!(dst[cnt] = (char *) malloc(size)))
+ if (!(dst[cnt] = (char *) malloc (size)))
return NULL;
- memcpy(dst[cnt], src[cnt], size);
+ memcpy (dst[cnt], src[cnt], size);
}
return dst;
}
@@ -481,6 +475,8 @@ out:
extern "C" struct protoent *
cygwin_getprotobyname (const char *p)
{
+ if (check_null_str_errno (p))
+ return NULL;
free_protoent_ptr (protoent_buf);
protoent_buf = dup_protoent_ptr (getprotobyname (p));
if (!protoent_buf)
@@ -504,14 +500,23 @@ cygwin_getprotobynumber (int number)
}
fhandler_socket *
-fdsock (int fd, const char *name, SOCKET soc)
+fdsock (int& fd, const char *name, SOCKET soc)
{
- if (wsadata.wVersion < 512) /* < Winsock 2.0 */
+ if (!winsock2_active)
soc = set_socket_inheritance (soc);
+ else if (wincap.has_set_handle_information ())
+ {
+ /* NT systems apparently set sockets to inheritable by default */
+ SetHandleInformation ((HANDLE)soc, HANDLE_FLAG_INHERIT, 0);
+ debug_printf ("reset socket inheritance since winsock2_active %d", winsock2_active);
+ }
+ else
+ debug_printf ("not setting socket inheritance since winsock2_active %d", winsock2_active);
fhandler_socket *fh = (fhandler_socket *) cygheap->fdtab.build_fhandler (fd, FH_SOCKET, name);
fh->set_io_handle ((HANDLE) soc);
- fh->set_flags (O_RDWR);
- cygheap->fdtab.inc_need_fixup_before ();
+ fh->set_flags (O_RDWR | O_BINARY);
+ fh->set_r_no_interrupt (winsock2_active);
+ debug_printf ("fd %d, name '%s', soc %p", fd, name, soc);
return fh;
}
@@ -520,19 +525,16 @@ extern "C" int
cygwin_socket (int af, int type, int protocol)
{
int res = -1;
- SetResourceLock (LOCK_FD_LIST, WRITE_LOCK|READ_LOCK, "socket");
-
- SOCKET soc;
+ SOCKET soc = 0;
+ fhandler_socket* fh = NULL;
- int fd = cygheap->fdtab.find_unused_handle ();
+ cygheap_fdnew fd;
- if (fd < 0)
- set_errno (EMFILE);
- else
+ if (fd >= 0)
{
debug_printf ("socket (%d, %d, %d)", af, type, protocol);
- soc = socket (AF_INET, type, af == AF_UNIX ? 0 : protocol);
+ soc = socket (AF_INET, type, af == AF_LOCAL ? 0 : protocol);
if (soc == INVALID_SOCKET)
{
@@ -546,222 +548,118 @@ cygwin_socket (int af, int type, int protocol)
else
name = (type == SOCK_STREAM ? "/dev/streamsocket" : "/dev/dgsocket");
- fdsock (fd, name, soc)->set_addr_family (af);
+ fh = fdsock (fd, name, soc);
+ if (fh)
+ {
+ fh->set_addr_family (af);
+ fh->set_socket_type (type);
+ }
res = fd;
}
done:
syscall_printf ("%d = socket (%d, %d, %d)", res, af, type, protocol);
- ReleaseResourceLock (LOCK_FD_LIST, WRITE_LOCK|READ_LOCK, "socket");
return res;
}
-/* cygwin internal: map sockaddr into internet domain address */
-
-static int get_inet_addr (const struct sockaddr *in, int inlen,
- struct sockaddr_in *out, int *outlen, int* secret = 0)
-{
- int secret_buf [4];
- int* secret_ptr = (secret ? : secret_buf);
-
- if (in->sa_family == AF_INET)
- {
- *out = * (sockaddr_in *)in;
- *outlen = inlen;
- return 1;
- }
- else if (in->sa_family == AF_UNIX)
- {
- int fd = _open (in->sa_data, O_RDONLY);
- if (fd == -1)
- return 0;
-
- int ret = 0;
- char buf[128];
- memset (buf, 0, sizeof buf);
- if (read (fd, buf, sizeof buf) != -1)
- {
- sockaddr_in sin;
- sin.sin_family = AF_INET;
- sscanf (buf + strlen (SOCKET_COOKIE), "%hu %08x-%08x-%08x-%08x",
- &sin.sin_port,
- secret_ptr, secret_ptr + 1, secret_ptr + 2, secret_ptr + 3);
- sin.sin_port = htons (sin.sin_port);
- sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
- *out = sin;
- *outlen = sizeof sin;
- ret = 1;
- }
- _close (fd);
- return ret;
- }
- else
- {
- set_errno (EAFNOSUPPORT);
- return 0;
- }
-}
-
/* exported as sendto: standards? */
extern "C" int
-cygwin_sendto (int fd,
- const void *buf,
- int len,
- unsigned int flags,
- const struct sockaddr *to,
- int tolen)
+cygwin_sendto (int fd, const void *buf, int len, int flags,
+ const struct sockaddr *to, int tolen)
{
int res;
- wsock_event wsock_evt;
- LPWSAOVERLAPPED ovr;
- fhandler_socket *h = (fhandler_socket *) cygheap->fdtab[fd];
- sockaddr_in sin;
sigframe thisframe (mainthread);
- if (get_inet_addr (to, tolen, &sin, &tolen) == 0)
- return -1;
+ fhandler_socket *fh = get (fd);
- if (h->is_nonblocking () || !(ovr = wsock_evt.prepare ()))
- {
- debug_printf ("Fallback to winsock 1 sendto call");
- if ((res = sendto (h->get_socket (), (const char *) buf, len, flags,
- to, tolen)) == SOCKET_ERROR)
- {
- set_winsock_errno ();
- res = -1;
- }
- }
- else
- {
- WSABUF wsabuf = { len, (char *) buf };
- DWORD ret = 0;
- if (WSASendTo (h->get_socket (), &wsabuf, 1, &ret, (DWORD)flags,
- to, tolen, ovr, NULL) != SOCKET_ERROR)
- res = ret;
- else if ((res = WSAGetLastError ()) != WSA_IO_PENDING)
- {
- set_winsock_errno ();
- res = -1;
- }
- else if ((res = wsock_evt.wait (h->get_socket (), (DWORD *)&flags)) == -1)
- set_winsock_errno ();
- }
+ if ((len && __check_invalid_read_ptr_errno (buf, (unsigned) len))
+ || (to &&__check_invalid_read_ptr_errno (to, tolen))
+ || !fh)
+ res = -1;
+ else if ((res = len) != 0)
+ res = fh->sendto (buf, len, flags, to, tolen);
- syscall_printf ("%d = sendto (%d, %x, %x, %x)", res, fd, buf, len, flags);
+ syscall_printf ("%d = sendto (%d, %p, %d, %x, %p, %d)",
+ res, fd, buf, len, flags, to, tolen);
return res;
}
/* exported as recvfrom: standards? */
extern "C" int
-cygwin_recvfrom (int fd,
- char *buf,
- int len,
- int flags,
- struct sockaddr *from,
- int *fromlen)
+cygwin_recvfrom (int fd, void *buf, int len, int flags,
+ struct sockaddr *from, int *fromlen)
{
int res;
- wsock_event wsock_evt;
- LPWSAOVERLAPPED ovr;
- fhandler_socket *h = (fhandler_socket *) cygheap->fdtab[fd];
sigframe thisframe (mainthread);
- if (h->is_nonblocking () ||!(ovr = wsock_evt.prepare ()))
- {
- debug_printf ("Fallback to winsock 1 recvfrom call");
- if ((res = recvfrom (h->get_socket (), buf, len, flags, from, fromlen))
- == SOCKET_ERROR)
- {
- set_winsock_errno ();
- res = -1;
- }
- }
- else
- {
- WSABUF wsabuf = { len, (char *) buf };
- DWORD ret = 0;
- if (WSARecvFrom (h->get_socket (), &wsabuf, 1, &ret, (DWORD *)&flags,
- from, fromlen, ovr, NULL) != SOCKET_ERROR)
- res = ret;
- else if ((res = WSAGetLastError ()) != WSA_IO_PENDING)
- {
- set_winsock_errno ();
- res = -1;
- }
- else if ((res = wsock_evt.wait (h->get_socket (), (DWORD *)&flags)) == -1)
- set_winsock_errno ();
- }
+ fhandler_socket *fh = get (fd);
- syscall_printf ("%d = recvfrom (%d, %x, %x, %x)", res, fd, buf, len, flags);
+ if ((len && __check_null_invalid_struct_errno (buf, (unsigned) len))
+ || (from
+ && (check_null_invalid_struct_errno (fromlen)
+ ||__check_null_invalid_struct_errno (from, (unsigned) *fromlen)))
+ || !fh)
+ res = -1;
+ else if ((res = len) != 0)
+ res = fh->recvfrom (buf, len, flags, from, fromlen);
- return res;
-}
+ syscall_printf ("%d = recvfrom (%d, %p, %d, %x, %p, %p)",
+ res, fd, buf, len, flags, from, fromlen);
-/* Cygwin internal */
-fhandler_socket *
-get (int fd)
-{
- if (cygheap->fdtab.not_open (fd))
- {
- set_errno (EINVAL);
- return 0;
- }
-
- return cygheap->fdtab[fd]->is_socket ();
+ return res;
}
/* exported as setsockopt: standards? */
extern "C" int
-cygwin_setsockopt (int fd,
- int level,
- int optname,
- const void *optval,
- int optlen)
+cygwin_setsockopt (int fd, int level, int optname, const void *optval,
+ int optlen)
{
- fhandler_socket *h = get (fd);
- int res = -1;
+ int res;
+ fhandler_socket *fh = get (fd);
const char *name = "error";
- if (h)
+ /* For the following debug_printf */
+ switch (optname)
{
- /* For the following debug_printf */
- switch (optname)
- {
- case SO_DEBUG:
- name="SO_DEBUG";
- break;
- case SO_ACCEPTCONN:
- name="SO_ACCEPTCONN";
- break;
- case SO_REUSEADDR:
- name="SO_REUSEADDR";
- break;
- case SO_KEEPALIVE:
- name="SO_KEEPALIVE";
- break;
- case SO_DONTROUTE:
- name="SO_DONTROUTE";
- break;
- case SO_BROADCAST:
- name="SO_BROADCAST";
- break;
- case SO_USELOOPBACK:
- name="SO_USELOOPBACK";
- break;
- case SO_LINGER:
- name="SO_LINGER";
- break;
- case SO_OOBINLINE:
- name="SO_OOBINLINE";
- break;
- case SO_ERROR:
- name="SO_ERROR";
- break;
- }
+ case SO_DEBUG:
+ name="SO_DEBUG";
+ break;
+ case SO_ACCEPTCONN:
+ name="SO_ACCEPTCONN";
+ break;
+ case SO_REUSEADDR:
+ name="SO_REUSEADDR";
+ break;
+ case SO_KEEPALIVE:
+ name="SO_KEEPALIVE";
+ break;
+ case SO_DONTROUTE:
+ name="SO_DONTROUTE";
+ break;
+ case SO_BROADCAST:
+ name="SO_BROADCAST";
+ break;
+ case SO_USELOOPBACK:
+ name="SO_USELOOPBACK";
+ break;
+ case SO_LINGER:
+ name="SO_LINGER";
+ break;
+ case SO_OOBINLINE:
+ name="SO_OOBINLINE";
+ break;
+ case SO_ERROR:
+ name="SO_ERROR";
+ break;
+ }
- res = setsockopt (h->get_socket (), level, optname,
- (const char *) optval, optlen);
+ if ((optval && __check_invalid_read_ptr_errno (optval, optlen)) || !fh)
+ res = -1;
+ else
+ {
+ res = setsockopt (fh->get_socket (), level, optname,
+ (const char *) optval, optlen);
if (optlen == 4)
syscall_printf ("setsockopt optval=%x", *(long *) optval);
@@ -770,61 +668,63 @@ cygwin_setsockopt (int fd,
set_winsock_errno ();
}
- syscall_printf ("%d = setsockopt (%d, %d, %x (%s), %x, %d)",
+ syscall_printf ("%d = setsockopt (%d, %d, %x (%s), %p, %d)",
res, fd, level, optname, name, optval, optlen);
return res;
}
/* exported as getsockopt: standards? */
extern "C" int
-cygwin_getsockopt (int fd,
- int level,
- int optname,
- void *optval,
- int *optlen)
+cygwin_getsockopt (int fd, int level, int optname, void *optval, int *optlen)
{
- fhandler_socket *h = get (fd);
- int res = -1;
+ int res;
+ fhandler_socket *fh = get (fd);
const char *name = "error";
- if (h)
+
+ /* For the following debug_printf */
+ switch (optname)
{
- /* For the following debug_printf */
- switch (optname)
- {
- case SO_DEBUG:
- name="SO_DEBUG";
- break;
- case SO_ACCEPTCONN:
- name="SO_ACCEPTCONN";
- break;
- case SO_REUSEADDR:
- name="SO_REUSEADDR";
- break;
- case SO_KEEPALIVE:
- name="SO_KEEPALIVE";
- break;
- case SO_DONTROUTE:
- name="SO_DONTROUTE";
- break;
- case SO_BROADCAST:
- name="SO_BROADCAST";
- break;
- case SO_USELOOPBACK:
- name="SO_USELOOPBACK";
- break;
- case SO_LINGER:
- name="SO_LINGER";
- break;
- case SO_OOBINLINE:
- name="SO_OOBINLINE";
- break;
- case SO_ERROR:
- name="SO_ERROR";
- break;
- }
+ case SO_DEBUG:
+ name="SO_DEBUG";
+ break;
+ case SO_ACCEPTCONN:
+ name="SO_ACCEPTCONN";
+ break;
+ case SO_REUSEADDR:
+ name="SO_REUSEADDR";
+ break;
+ case SO_KEEPALIVE:
+ name="SO_KEEPALIVE";
+ break;
+ case SO_DONTROUTE:
+ name="SO_DONTROUTE";
+ break;
+ case SO_BROADCAST:
+ name="SO_BROADCAST";
+ break;
+ case SO_USELOOPBACK:
+ name="SO_USELOOPBACK";
+ break;
+ case SO_LINGER:
+ name="SO_LINGER";
+ break;
+ case SO_OOBINLINE:
+ name="SO_OOBINLINE";
+ break;
+ case SO_ERROR:
+ name="SO_ERROR";
+ break;
+ }
- res = getsockopt (h->get_socket (), level, optname,
- (char *) optval, (int *) optlen);
+ if ((optval
+ && (check_null_invalid_struct_errno (optlen)
+ || __check_null_invalid_struct_errno (optval, (unsigned) *optlen)))
+ || !fh)
+ res = -1;
+ else
+ {
+ res = getsockopt (fh->get_socket (), level, optname, (char *) optval,
+ (int *) optlen);
if (optname == SO_ERROR)
{
@@ -836,83 +736,27 @@ cygwin_getsockopt (int fd,
set_winsock_errno ();
}
- syscall_printf ("%d = getsockopt (%d, %d, %x (%s), %x, %d)",
+ syscall_printf ("%d = getsockopt (%d, %d, %x (%s), %p, %p)",
res, fd, level, optname, name, optval, optlen);
return res;
}
/* exported as connect: standards? */
extern "C" int
-cygwin_connect (int fd,
- const struct sockaddr *name,
- int namelen)
+cygwin_connect (int fd, const struct sockaddr *name, int namelen)
{
int res;
- BOOL secret_check_failed = FALSE;
- BOOL in_progress = FALSE;
- fhandler_socket *sock = get (fd);
- sockaddr_in sin;
- int secret [4];
sigframe thisframe (mainthread);
- if (get_inet_addr (name, namelen, &sin, &namelen, secret) == 0)
- return -1;
+ fhandler_socket *fh = get (fd);
- if (!sock)
- {
- res = -1;
- }
+ if (__check_invalid_read_ptr_errno (name, namelen) || !fh)
+ res = -1;
else
- {
- res = connect (sock->get_socket (), (sockaddr *) &sin, namelen);
- if (res)
- {
- /* Special handling for connect to return the correct error code
- when called on a non-blocking socket. */
- if (sock->is_nonblocking ())
- {
- DWORD err = WSAGetLastError ();
- if (err == WSAEWOULDBLOCK || err == WSAEALREADY)
- {
- WSASetLastError (WSAEINPROGRESS);
- in_progress = TRUE;
- }
- else if (err == WSAEINVAL)
- WSASetLastError (WSAEISCONN);
- }
- set_winsock_errno ();
- }
- if (sock->get_addr_family () == AF_UNIX)
- {
- if (!res || in_progress)
- {
- if (!sock->create_secret_event (secret))
- {
- secret_check_failed = TRUE;
- }
- else if (in_progress)
- sock->signal_secret_event ();
- }
+ res = fh->connect (name, namelen);
- if (!secret_check_failed && !res)
- {
- if (!sock->check_peer_secret_event (&sin, secret))
- {
- debug_printf ( "accept from unauthorized server" );
- secret_check_failed = TRUE;
- }
- }
+ syscall_printf ("%d = connect (%d, %p, %d)", res, fd, name, namelen);
- if (secret_check_failed)
- {
- sock->close_secret_event ();
- if (res)
- closesocket (res);
- set_errno (ECONNREFUSED);
- res = -1;
- }
- }
- }
return res;
}
@@ -987,6 +831,10 @@ out:
extern "C" struct servent *
cygwin_getservbyname (const char *name, const char *proto)
{
+ if (check_null_str_errno (name)
+ || (proto != NULL && check_null_str_errno (proto)))
+ return NULL;
+
free_servent_ptr (servent_buf);
servent_buf = dup_servent_ptr (getservbyname (name, proto));
if (!servent_buf)
@@ -1000,6 +848,9 @@ cygwin_getservbyname (const char *name, const char *proto)
extern "C" struct servent *
cygwin_getservbyport (int port, const char *proto)
{
+ if (proto != NULL && check_null_str_errno (proto))
+ return NULL;
+
free_servent_ptr (servent_buf);
servent_buf = dup_servent_ptr (getservbyport (port, proto));
if (!servent_buf)
@@ -1014,6 +865,9 @@ cygwin_gethostname (char *name, size_t len)
{
int PASCAL win32_gethostname (char*, int);
+ if (__check_null_invalid_struct_errno (name, len))
+ return -1;
+
if (wsock32_handle == NULL ||
win32_gethostname (name, len) == SOCKET_ERROR)
{
@@ -1092,6 +946,9 @@ cygwin_gethostbyname (const char *name)
static char *tmp_addr_list[2];
static int a, b, c, d;
+ if (check_null_str_errno (name))
+ return NULL;
+
if (sscanf (name, "%d.%d.%d.%d", &a, &b, &c, &d) == 4)
{
/* In case you don't have DNS, at least x.x.x.x still works */
@@ -1100,7 +957,7 @@ cygwin_gethostbyname (const char *name)
tmp_addr[1] = b;
tmp_addr[2] = c;
tmp_addr[3] = d;
- tmp_addr_list[0] = (char *)tmp_addr;
+ tmp_addr_list[0] = (char *) tmp_addr;
tmp.h_name = name;
tmp.h_aliases = tmp_aliases;
tmp.h_addrtype = 2;
@@ -1128,6 +985,9 @@ cygwin_gethostbyname (const char *name)
extern "C" struct hostent *
cygwin_gethostbyaddr (const char *addr, int len, int type)
{
+ if (__check_invalid_read_ptr_errno (addr, len))
+ return NULL;
+
free_hostent_ptr (hostent_buf);
hostent_buf = dup_hostent_ptr (gethostbyaddr (addr, len, type));
if (!hostent_buf)
@@ -1147,91 +1007,19 @@ cygwin_gethostbyaddr (const char *addr, int len, int type)
extern "C" int
cygwin_accept (int fd, struct sockaddr *peer, int *len)
{
- int res = -1;
- BOOL secret_check_failed = FALSE;
- BOOL in_progress = FALSE;
+ int res;
sigframe thisframe (mainthread);
- fhandler_socket *sock = get (fd);
- if (sock)
- {
- /* Allows NULL peer and len parameters. */
- struct sockaddr_in peer_dummy;
- int len_dummy;
- if (!peer)
- peer = (struct sockaddr *) &peer_dummy;
- if (!len)
- {
- len_dummy = sizeof (struct sockaddr_in);
- len = &len_dummy;
- }
-
- /* accept on NT fails if len < sizeof (sockaddr_in)
- * some programs set len to
- * sizeof (name.sun_family) + strlen (name.sun_path) for UNIX domain
- */
- if (len && ((unsigned) *len < sizeof (struct sockaddr_in)))
- *len = sizeof (struct sockaddr_in);
-
- res = accept (sock->get_socket (), peer, len); // can't use a blocking call inside a lock
+ fhandler_socket *fh = get (fd);
- if ((SOCKET) res == (SOCKET) INVALID_SOCKET &&
- WSAGetLastError () == WSAEWOULDBLOCK)
- in_progress = TRUE;
-
- if (sock->get_addr_family () == AF_UNIX)
- {
- if ((SOCKET) res != (SOCKET) INVALID_SOCKET || in_progress)
- {
- if (!sock->create_secret_event ())
- secret_check_failed = TRUE;
- else if (in_progress)
- sock->signal_secret_event ();
- }
-
- if (!secret_check_failed &&
- (SOCKET) res != (SOCKET) INVALID_SOCKET)
- {
- if (!sock->check_peer_secret_event ((struct sockaddr_in*) peer))
- {
- debug_printf ("connect from unauthorized client");
- secret_check_failed = TRUE;
- }
- }
-
- if (secret_check_failed)
- {
- sock->close_secret_event ();
- if ((SOCKET) res != (SOCKET) INVALID_SOCKET)
- closesocket (res);
- set_errno (ECONNABORTED);
- res = -1;
- goto done;
- }
- }
-
- SetResourceLock (LOCK_FD_LIST, WRITE_LOCK|READ_LOCK, "accept");
+ if ((peer && (check_null_invalid_struct_errno (len)
+ || __check_null_invalid_struct_errno (peer, (unsigned) *len)))
+ || !fh)
+ res = -1;
+ else
+ res = fh->accept (peer, len);
- int res_fd = cygheap->fdtab.find_unused_handle ();
- if (res_fd == -1)
- {
- /* FIXME: what is correct errno? */
- set_errno (EMFILE);
- goto lock_done;
- }
- if ((SOCKET) res == (SOCKET) INVALID_SOCKET)
- set_winsock_errno ();
- else
- {
- fhandler_socket* res_fh = fdsock (res_fd, sock->get_name (), res);
- res_fh->set_addr_family (sock->get_addr_family ());
- res = res_fd;
- }
- }
-lock_done:
- ReleaseResourceLock (LOCK_FD_LIST, WRITE_LOCK|READ_LOCK, "accept");
-done:
- syscall_printf ("%d = accept (%d, %x, %x)", res, fd, peer, len);
+ syscall_printf ("%d = accept (%d, %p, %p)", res, fd, peer, len);
return res;
}
@@ -1239,85 +1027,15 @@ done:
extern "C" int
cygwin_bind (int fd, const struct sockaddr *my_addr, int addrlen)
{
- int res = -1;
-
- fhandler_socket *sock = get (fd);
- if (sock)
- {
- if (my_addr->sa_family == AF_UNIX)
- {
-#define un_addr ((struct sockaddr_un *) my_addr)
- struct sockaddr_in sin;
- int len = sizeof sin;
- int fd;
-
- if (strlen (un_addr->sun_path) >= UNIX_PATH_LEN)
- {
- set_errno (ENAMETOOLONG);
- goto out;
- }
- sin.sin_family = AF_INET;
- sin.sin_port = 0;
- sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
- if (bind (sock->get_socket (), (sockaddr *) &sin, len))
- {
- syscall_printf ("AF_UNIX: bind failed %d", get_errno ());
- set_winsock_errno ();
- goto out;
- }
- if (getsockname (sock->get_socket (), (sockaddr *) &sin, &len))
- {
- syscall_printf ("AF_UNIX: getsockname failed %d", get_errno ());
- set_winsock_errno ();
- goto out;
- }
-
- sin.sin_port = ntohs (sin.sin_port);
- debug_printf ("AF_UNIX: socket bound to port %u", sin.sin_port);
-
- /* bind must fail if file system socket object already exists
- so _open () is called with O_EXCL flag. */
- fd = _open (un_addr->sun_path,
- O_WRONLY | O_CREAT | O_EXCL | O_BINARY,
- 0);
- if (fd < 0)
- {
- if (get_errno () == EEXIST)
- set_errno (EADDRINUSE);
- goto out;
- }
-
- sock->set_connect_secret ();
-
- char buf[sizeof (SOCKET_COOKIE) + 80];
- __small_sprintf (buf, "%s%u ", SOCKET_COOKIE, sin.sin_port);
- sock->get_connect_secret (strchr (buf, '\0'));
- len = strlen (buf) + 1;
+ int res;
+ fhandler_socket *fh = get (fd);
- /* Note that the terminating nul is written. */
- if (_write (fd, buf, len) != len)
- {
- save_errno here;
- _close (fd);
- _unlink (un_addr->sun_path);
- }
- else
- {
- _close (fd);
- chmod (un_addr->sun_path,
- (S_IFSOCK | S_IRWXU | S_IRWXG | S_IRWXO) & ~cygheap->umask);
- res = 0;
- }
-#undef un_addr
- }
- else if (bind (sock->get_socket (), my_addr, addrlen))
- set_winsock_errno ();
- else
- res = 0;
- }
+ if (__check_invalid_read_ptr_errno (my_addr, addrlen) || !fh)
+ res = -1;
+ else
+ res = fh->bind (my_addr, addrlen);
-out:
- syscall_printf ("%d = bind (%d, %x, %d)", res, fd, my_addr, addrlen);
+ syscall_printf ("%d = bind (%d, %p, %d)", res, fd, my_addr, addrlen);
return res;
}
@@ -1325,17 +1043,19 @@ out:
extern "C" int
cygwin_getsockname (int fd, struct sockaddr *addr, int *namelen)
{
- int res = -1;
+ int res;
+ sigframe thisframe (mainthread);
- fhandler_socket *sock = get (fd);
- if (sock)
- {
- res = getsockname (sock->get_socket (), addr, namelen);
- if (res)
- set_winsock_errno ();
+ fhandler_socket *fh = get (fd);
- }
- syscall_printf ("%d = getsockname (%d, %x, %d)", res, fd, addr, namelen);
+ if (check_null_invalid_struct_errno (namelen)
+ || __check_null_invalid_struct_errno (addr, (unsigned) *namelen)
+ || !fh)
+ res = -1;
+ else
+ res = fh->getsockname (addr, namelen);
+
+ syscall_printf ("%d = getsockname (%d, %p, %p)", res, fd, addr, namelen);
return res;
}
@@ -1343,16 +1063,14 @@ cygwin_getsockname (int fd, struct sockaddr *addr, int *namelen)
extern "C" int
cygwin_listen (int fd, int backlog)
{
- int res = -1;
+ int res;
+ fhandler_socket *fh = get (fd);
+ if (!fh)
+ res = -1;
+ else
+ res = fh->listen (backlog);
- fhandler_socket *sock = get (fd);
- if (sock)
- {
- res = listen (sock->get_socket (), backlog);
- if (res)
- set_winsock_errno ();
- }
syscall_printf ("%d = listen (%d, %d)", res, fd, backlog);
return res;
}
@@ -1361,30 +1079,16 @@ cygwin_listen (int fd, int backlog)
extern "C" int
cygwin_shutdown (int fd, int how)
{
- int res = -1;
+ int res;
sigframe thisframe (mainthread);
- fhandler_socket *sock = get (fd);
- if (sock)
- {
- res = shutdown (sock->get_socket (), how);
- if (res)
- set_winsock_errno ();
- else
- switch (how)
- {
- case SHUT_RD:
- sock->set_shutdown_read ();
- break;
- case SHUT_WR:
- sock->set_shutdown_write ();
- break;
- case SHUT_RDWR:
- sock->set_shutdown_read ();
- sock->set_shutdown_write ();
- break;
- }
- }
+ fhandler_socket *fh = get (fd);
+
+ if (!fh)
+ res = -1;
+ else
+ res = fh->shutdown (how);
+
syscall_printf ("%d = shutdown (%d, %d)", res, fd, how);
return res;
}
@@ -1406,6 +1110,8 @@ cygwin_hstrerror (int err)
extern "C" void
cygwin_herror (const char *s)
{
+ if (s && check_null_str (s))
+ return;
if (cygheap->fdtab.not_open (2))
return;
@@ -1438,102 +1144,39 @@ cygwin_herror (const char *s)
extern "C" int
cygwin_getpeername (int fd, struct sockaddr *name, int *len)
{
- fhandler_socket *h = (fhandler_socket *) cygheap->fdtab[fd];
+ int res;
+ sigframe thisframe (mainthread);
- debug_printf ("getpeername %d", h->get_socket ());
- int res = getpeername (h->get_socket (), name, len);
- if (res)
- set_winsock_errno ();
+ fhandler_socket *fh = get (fd);
+
+ if (check_null_invalid_struct_errno (len)
+ || __check_null_invalid_struct_errno (name, (unsigned) *len)
+ || !fh)
+ res = -1;
+ else
+ res = fh->getpeername (name, len);
- debug_printf ("%d = getpeername %d", res, h->get_socket ());
+ syscall_printf ("%d = getpeername %d", res, (fh ? fh->get_socket () : -1));
return res;
}
/* exported as recv: standards? */
extern "C" int
-cygwin_recv (int fd, void *buf, int len, unsigned int flags)
+cygwin_recv (int fd, void *buf, int len, int flags)
{
- int res;
- wsock_event wsock_evt;
- LPWSAOVERLAPPED ovr;
- fhandler_socket *h = (fhandler_socket *) cygheap->fdtab[fd];
- sigframe thisframe (mainthread);
-
- if (h->is_nonblocking () || !(ovr = wsock_evt.prepare ()))
- {
- debug_printf ("Fallback to winsock 1 recv call");
- if ((res = recv (h->get_socket (), (char *) buf, len, flags))
- == SOCKET_ERROR)
- {
- set_winsock_errno ();
- res = -1;
- }
- }
- else
- {
- WSABUF wsabuf = { len, (char *) buf };
- DWORD ret = 0;
- if (WSARecv (h->get_socket (), &wsabuf, 1, &ret, (DWORD *)&flags,
- ovr, NULL) != SOCKET_ERROR)
- res = ret;
- else if ((res = WSAGetLastError ()) != WSA_IO_PENDING)
- {
- set_winsock_errno ();
- res = -1;
- }
- else if ((res = wsock_evt.wait (h->get_socket (), (DWORD *)&flags)) == -1)
- set_winsock_errno ();
- }
-
- syscall_printf ("%d = recv (%d, %x, %x, %x)", res, fd, buf, len, flags);
-
- return res;
+ return cygwin_recvfrom (fd, buf, len, flags, NULL, NULL);
}
/* exported as send: standards? */
extern "C" int
-cygwin_send (int fd, const void *buf, int len, unsigned int flags)
+cygwin_send (int fd, const void *buf, int len, int flags)
{
- int res;
- wsock_event wsock_evt;
- LPWSAOVERLAPPED ovr;
- fhandler_socket *h = (fhandler_socket *) cygheap->fdtab[fd];
- sigframe thisframe (mainthread);
-
- if (h->is_nonblocking () || !(ovr = wsock_evt.prepare ()))
- {
- debug_printf ("Fallback to winsock 1 send call");
- if ((res = send (h->get_socket (), (const char *) buf, len, flags))
- == SOCKET_ERROR)
- {
- set_winsock_errno ();
- res = -1;
- }
- }
- else
- {
- WSABUF wsabuf = { len, (char *) buf };
- DWORD ret = 0;
- if (WSASend (h->get_socket (), &wsabuf, 1, &ret, (DWORD)flags,
- ovr, NULL) != SOCKET_ERROR)
- res = ret;
- else if ((res = WSAGetLastError ()) != WSA_IO_PENDING)
- {
- set_winsock_errno ();
- res = -1;
- }
- else if ((res = wsock_evt.wait (h->get_socket (), (DWORD *)&flags)) == -1)
- set_winsock_errno ();
- }
-
- syscall_printf ("%d = send (%d, %x, %d, %x)", res, fd, buf, len, flags);
-
- return res;
+ return cygwin_sendto (fd, buf, len, flags, NULL, 0);
}
/* getdomainname: standards? */
extern "C" int
-getdomainname (char *domain, int len)
+getdomainname (char *domain, size_t len)
{
/*
* This works for Win95 only if the machine is configured to use MS-TCP.
@@ -1542,10 +1185,14 @@ getdomainname (char *domain, int len)
* in use and include paths for the Domain name in each ?
* Punt for now and assume MS-TCP on Win95.
*/
+ if (__check_null_invalid_struct_errno (domain, len))
+ return -1;
+
reg_key r (HKEY_LOCAL_MACHINE, KEY_READ,
(!wincap.is_winnt ()) ? "System" : "SYSTEM",
"CurrentControlSet", "Services",
- (!wincap.is_winnt ()) ? "MSTCP" : "Tcpip",
+ (!wincap.is_winnt ()) ? "VxD" : "Tcpip",
+ (!wincap.is_winnt ()) ? "MSTCP" : "Parameters",
NULL);
/* FIXME: Are registry keys case sensitive? */
@@ -1569,7 +1216,7 @@ static void
get_2k_ifconf (struct ifconf *ifc, int what)
{
int cnt = 0;
- char eth[2] = "/", ppp[2] = "/", slp[2] = "/";
+ char eth[2] = "/", ppp[2] = "/", slp[2] = "/", sub[2] = "0", tok[2] = "/";
/* Union maps buffer to correct struct */
struct ifreq *ifr = ifc->ifc_req;
@@ -1582,91 +1229,110 @@ get_2k_ifconf (struct ifconf *ifc, int what)
struct sockaddr_in *sa = NULL;
struct sockaddr *so = NULL;
- if (GetIfTable(NULL, &siz_if_table, TRUE) == ERROR_INSUFFICIENT_BUFFER &&
- GetIpAddrTable(NULL, &siz_ip_table, TRUE) == ERROR_INSUFFICIENT_BUFFER &&
+ if (GetIfTable (NULL, &siz_if_table, TRUE) == ERROR_INSUFFICIENT_BUFFER &&
+ GetIpAddrTable (NULL, &siz_ip_table, TRUE) == ERROR_INSUFFICIENT_BUFFER &&
(ift = (PMIB_IFTABLE) alloca (siz_if_table)) &&
(ipt = (PMIB_IPADDRTABLE) alloca (siz_ip_table)) &&
- !GetIfTable(ift, &siz_if_table, TRUE) &&
- !GetIpAddrTable(ipt, &siz_ip_table, TRUE))
+ !GetIfTable (ift, &siz_if_table, TRUE) &&
+ !GetIpAddrTable (ipt, &siz_ip_table, TRUE))
{
+ /* Iterate over all known interfaces */
for (if_cnt = 0; if_cnt < ift->dwNumEntries; ++if_cnt)
{
- switch (ift->table[if_cnt].dwType)
- {
- case MIB_IF_TYPE_ETHERNET:
- ++*eth;
- strcpy (ifr->ifr_name, "eth");
- strcat (ifr->ifr_name, eth);
- break;
- case MIB_IF_TYPE_PPP:
- ++*ppp;
- strcpy (ifr->ifr_name, "ppp");
- strcat (ifr->ifr_name, ppp);
- break;
- case MIB_IF_TYPE_SLIP:
- ++*slp;
- strcpy (ifr->ifr_name, "slp");
- strcat (ifr->ifr_name, slp);
- break;
- case MIB_IF_TYPE_LOOPBACK:
- strcpy (ifr->ifr_name, "lo");
- break;
- default:
- continue;
- }
+ *sub = '0';
+ /* Iterate over all configured IP-addresses */
for (ip_cnt = 0; ip_cnt < ipt->dwNumEntries; ++ip_cnt)
- if (ipt->table[ip_cnt].dwIndex == ift->table[if_cnt].dwIndex)
- {
- switch (what)
- {
- case SIOCGIFCONF:
- case SIOCGIFADDR:
- sa = (struct sockaddr_in *) &ifr->ifr_addr;
- sa->sin_addr.s_addr = ipt->table[ip_cnt].dwAddr;
- sa->sin_family = AF_INET;
- sa->sin_port = 0;
- break;
- case SIOCGIFBRDADDR:
- sa = (struct sockaddr_in *) &ifr->ifr_broadaddr;
+ {
+ /* Does the IP address belong to the interface? */
+ if (ipt->table[ip_cnt].dwIndex == ift->table[if_cnt].dwIndex)
+ {
+ /* Setup the interface name */
+ switch (ift->table[if_cnt].dwType)
+ {
+ case MIB_IF_TYPE_TOKENRING:
+ ++*tok;
+ strcpy (ifr->ifr_name, "tok");
+ strcat (ifr->ifr_name, tok);
+ break;
+ case MIB_IF_TYPE_ETHERNET:
+ if (*sub == '0')
+ ++*eth;
+ strcpy (ifr->ifr_name, "eth");
+ strcat (ifr->ifr_name, eth);
+ break;
+ case MIB_IF_TYPE_PPP:
+ ++*ppp;
+ strcpy (ifr->ifr_name, "ppp");
+ strcat (ifr->ifr_name, ppp);
+ break;
+ case MIB_IF_TYPE_SLIP:
+ ++*slp;
+ strcpy (ifr->ifr_name, "slp");
+ strcat (ifr->ifr_name, slp);
+ break;
+ case MIB_IF_TYPE_LOOPBACK:
+ strcpy (ifr->ifr_name, "lo");
+ break;
+ default:
+ continue;
+ }
+ if (*sub > '0')
+ {
+ strcat (ifr->ifr_name, ":");
+ strcat (ifr->ifr_name, sub);
+ }
+ ++*sub;
+ /* setup sockaddr struct */
+ switch (what)
+ {
+ case SIOCGIFCONF:
+ case SIOCGIFADDR:
+ sa = (struct sockaddr_in *) &ifr->ifr_addr;
+ sa->sin_addr.s_addr = ipt->table[ip_cnt].dwAddr;
+ sa->sin_family = AF_INET;
+ sa->sin_port = 0;
+ break;
+ case SIOCGIFBRDADDR:
+ sa = (struct sockaddr_in *) &ifr->ifr_broadaddr;
#if 0
- /* Unfortunately, the field returns only crap. */
- sa->sin_addr.s_addr = ipt->table[ip_cnt].dwBCastAddr;
+ /* Unfortunately, the field returns only crap. */
+ sa->sin_addr.s_addr = ipt->table[ip_cnt].dwBCastAddr;
#else
- lip = ipt->table[ip_cnt].dwAddr;
- lnp = ipt->table[ip_cnt].dwMask;
- sa->sin_addr.s_addr = lip & lnp | ~lnp;
- sa->sin_family = AF_INET;
- sa->sin_port = 0;
+ lip = ipt->table[ip_cnt].dwAddr;
+ lnp = ipt->table[ip_cnt].dwMask;
+ sa->sin_addr.s_addr = lip & lnp | ~lnp;
+ sa->sin_family = AF_INET;
+ sa->sin_port = 0;
#endif
- break;
- case SIOCGIFNETMASK:
- sa = (struct sockaddr_in *) &ifr->ifr_netmask;
- sa->sin_addr.s_addr = ipt->table[ip_cnt].dwMask;
- sa->sin_family = AF_INET;
- sa->sin_port = 0;
- break;
- case SIOCGIFHWADDR:
- so = &ifr->ifr_hwaddr;
- for (UINT i = 0; i < IFHWADDRLEN; ++i)
- if (i >= ift->table[if_cnt].dwPhysAddrLen)
- so->sa_data[i] = '\0';
- else
- so->sa_data[i] = ift->table[if_cnt].bPhysAddr[i];
- so->sa_family = AF_INET;
- break;
- case SIOCGIFMETRIC:
- ifr->ifr_metric = 1;
- break;
- case SIOCGIFMTU:
- ifr->ifr_mtu = ift->table[if_cnt].dwMtu;
- break;
- }
- ++cnt;
- if ((caddr_t) ++ifr >
- ifc->ifc_buf + ifc->ifc_len - sizeof (struct ifreq))
- goto done;
- break;
- }
+ break;
+ case SIOCGIFNETMASK:
+ sa = (struct sockaddr_in *) &ifr->ifr_netmask;
+ sa->sin_addr.s_addr = ipt->table[ip_cnt].dwMask;
+ sa->sin_family = AF_INET;
+ sa->sin_port = 0;
+ break;
+ case SIOCGIFHWADDR:
+ so = &ifr->ifr_hwaddr;
+ for (UINT i = 0; i < IFHWADDRLEN; ++i)
+ if (i >= ift->table[if_cnt].dwPhysAddrLen)
+ so->sa_data[i] = '\0';
+ else
+ so->sa_data[i] = ift->table[if_cnt].bPhysAddr[i];
+ so->sa_family = AF_INET;
+ break;
+ case SIOCGIFMETRIC:
+ ifr->ifr_metric = 1;
+ break;
+ case SIOCGIFMTU:
+ ifr->ifr_mtu = ift->table[if_cnt].dwMtu;
+ break;
+ }
+ ++cnt;
+ if ((caddr_t) ++ifr >
+ ifc->ifc_buf + ifc->ifc_len - sizeof (struct ifreq))
+ goto done;
+ }
+ }
}
}
done:
@@ -1921,7 +1587,7 @@ get_95_ifconf (struct ifconf *ifc, int what)
++i)
{
HKEY ifkey, subkey;
- char driver[256], classname[256], bindname[256], netname[256];
+ char driver[256], classname[256], netname[256];
char adapter[256], ip[256], np[256];
if (res != ERROR_SUCCESS
@@ -1997,57 +1663,34 @@ get_95_ifconf (struct ifconf *ifc, int what)
RegCloseKey (subkey);
- if (RegOpenKeyEx (ifkey, "Bindings",
- 0, KEY_READ, &subkey) != ERROR_SUCCESS)
- {
+ strcpy (netname, "System\\CurrentControlSet\\Services\\Class\\Net\\");
+ strcat (netname, ifname);
+
+ if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, netname,
+ 0, KEY_READ, &subkey) != ERROR_SUCCESS)
+ {
RegCloseKey (ifkey);
--ifr;
continue;
- }
-
- for (int j = 0;
- (res = RegEnumValue (subkey, j, bindname,
- (size = sizeof bindname, &size),
- 0, NULL, NULL, NULL)) != ERROR_NO_MORE_ITEMS;
- ++j)
- if (!strncasecmp (bindname, "VREDIR\\", 7))
- break;
-
- RegCloseKey (subkey);
-
- if (res == ERROR_SUCCESS)
- {
- strcpy (netname, "System\\CurrentControlSet\\Services\\Class\\Net\\");
- strcat (netname, bindname + 7);
-
- if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, netname,
- 0, KEY_READ, &subkey) != ERROR_SUCCESS)
- {
- RegCloseKey (ifkey);
- --ifr;
- continue;
- }
+ }
- if (RegQueryValueEx (subkey, "AdapterName", 0,
- NULL, (unsigned char *) adapter,
- (size = sizeof adapter, &size)) == ERROR_SUCCESS
+ if (RegQueryValueEx (subkey, "AdapterName", 0,
+ NULL, (unsigned char *) adapter,
+ (size = sizeof adapter, &size)) == ERROR_SUCCESS
&& strcasematch (adapter, "MS$PPP"))
- {
- ++*ppp;
- strcpy (ifr->ifr_name, "ppp");
- strcat (ifr->ifr_name, ppp);
- }
- else
- {
- ++*eth;
- strcpy (ifr->ifr_name, "eth");
- strcat (ifr->ifr_name, eth);
- }
-
- RegCloseKey (subkey);
-
- }
+ {
+ ++*ppp;
+ strcpy (ifr->ifr_name, "ppp");
+ strcat (ifr->ifr_name, ppp);
+ }
+ else
+ {
+ ++*eth;
+ strcpy (ifr->ifr_name, "eth");
+ strcat (ifr->ifr_name, eth);
+ }
+ RegCloseKey (subkey);
RegCloseKey (ifkey);
++cnt;
@@ -2067,6 +1710,9 @@ get_ifconf (struct ifconf *ifc, int what)
unsigned long lip, lnp;
struct sockaddr_in *sa;
+ if (check_null_invalid_struct_errno (ifc))
+ return -1;
+
/* Union maps buffer to correct struct */
struct ifreq *ifr = ifc->ifc_req;
@@ -2141,18 +1787,25 @@ cygwin_rcmd (char **ahost, unsigned short inport, char *locuser,
SOCKET fd2s;
sigframe thisframe (mainthread);
- int res_fd = cygheap->fdtab.find_unused_handle ();
- if (res_fd == -1)
+ if (check_null_invalid_struct_errno (ahost) ||
+ check_null_empty_str_errno (*ahost) ||
+ (locuser && check_null_empty_str_errno (locuser)) ||
+ (remuser && check_null_str_errno (remuser)))
+ return (int) INVALID_SOCKET;
+
+ cygheap_fdnew res_fd;
+ if (res_fd < 0)
goto done;
if (fd2p)
{
- *fd2p = cygheap->fdtab.find_unused_handle (res_fd + 1);
- if (*fd2p == -1)
+ cygheap_fdnew newfd (res_fd, false);
+ if (*fd2p < 0)
goto done;
+ *fd2p = newfd;
}
- res = rcmd (ahost, inport, locuser, remuser, cmd, fd2p? &fd2s: NULL);
+ res = rcmd (ahost, inport, locuser, remuser, cmd, fd2p ? &fd2s : NULL);
if (res == (int) INVALID_SOCKET)
goto done;
else
@@ -2160,10 +1813,10 @@ cygwin_rcmd (char **ahost, unsigned short inport, char *locuser,
fdsock (res_fd, "/dev/tcp", res);
res = res_fd;
}
+
if (fd2p)
- {
- fdsock (*fd2p, "/dev/tcp", fd2s);
- }
+ fdsock (*fd2p, "/dev/tcp", fd2s);
+
done:
syscall_printf ("%d = rcmd (...)", res);
return res;
@@ -2173,22 +1826,26 @@ done:
extern "C" int
cygwin_rresvport (int *port)
{
- int res = -1;
+ int res;
sigframe thisframe (mainthread);
- int res_fd = cygheap->fdtab.find_unused_handle ();
- if (res_fd == -1)
- goto done;
- res = rresvport (port);
+ if (check_null_invalid_struct_errno (port))
+ return -1;
- if (res == (int) INVALID_SOCKET)
- goto done;
+ cygheap_fdnew res_fd;
+ if (res_fd < 0)
+ res = -1;
else
{
- fdsock (res_fd, "/dev/tcp", res);
- res = res_fd;
+ res = rresvport (port);
+
+ if (res != (int) INVALID_SOCKET)
+ {
+ fdsock (res_fd, "/dev/tcp", res);
+ res = res_fd;
+ }
}
-done:
+
syscall_printf ("%d = rresvport (%d)", res, port ? *port : 0);
return res;
}
@@ -2202,14 +1859,21 @@ cygwin_rexec (char **ahost, unsigned short inport, char *locuser,
SOCKET fd2s;
sigframe thisframe (mainthread);
- int res_fd = cygheap->fdtab.find_unused_handle ();
- if (res_fd == -1)
+ if (check_null_invalid_struct_errno (ahost) ||
+ check_null_empty_str_errno (*ahost) ||
+ (locuser && check_null_empty_str_errno (locuser)) ||
+ (password && check_null_str_errno (password)))
+ return (int) INVALID_SOCKET;
+
+ cygheap_fdnew res_fd;
+ if (res_fd < 0)
goto done;
if (fd2p)
{
- *fd2p = cygheap->fdtab.find_unused_handle (res_fd + 1);
- if (*fd2p == -1)
+ cygheap_fdnew newfd (res_fd);
+ if (newfd < 0)
goto done;
+ *fd2p = newfd;
}
res = rexec (ahost, inport, locuser, password, cmd, fd2p ? &fd2s : NULL);
if (res == (int) INVALID_SOCKET)
@@ -2230,29 +1894,48 @@ done:
/* socketpair: standards? */
/* Win32 supports AF_INET only, so ignore domain and protocol arguments */
extern "C" int
-socketpair (int, int type, int, int *sb)
+socketpair (int family, int type, int protocol, int *sb)
{
int res = -1;
SOCKET insock, outsock, newsock;
- struct sockaddr_in sock_in;
- int len = sizeof (sock_in);
+ struct sockaddr_in sock_in, sock_out;
+ int len;
+ cygheap_fdnew sb0;
+ fhandler_socket *fh;
- SetResourceLock (LOCK_FD_LIST, WRITE_LOCK|READ_LOCK, "socketpair");
+ if (__check_null_invalid_struct_errno (sb, 2 * sizeof (int)))
+ return -1;
- sb[0] = cygheap->fdtab.find_unused_handle ();
- if (sb[0] == -1)
+ if (family != AF_LOCAL && family != AF_INET)
+ {
+ set_errno (EAFNOSUPPORT);
+ goto done;
+ }
+ if (type != SOCK_STREAM && type != SOCK_DGRAM)
{
- set_errno (EMFILE);
+ set_errno (EPROTOTYPE);
goto done;
}
- sb[1] = cygheap->fdtab.find_unused_handle (sb[0] + 1);
- if (sb[1] == -1)
+ if ((family == AF_LOCAL && protocol != PF_UNSPEC && protocol != PF_LOCAL)
+ || (family == AF_INET && protocol != PF_UNSPEC && protocol != PF_INET))
{
- set_errno (EMFILE);
+ set_errno (EPROTONOSUPPORT);
goto done;
}
- /* create a listening socket */
+ if (sb0 < 0)
+ goto done;
+ else
+ {
+ sb[0] = sb0;
+ cygheap_fdnew sb1 (sb0, false);
+ if (sb1 < 0)
+ goto done;
+
+ sb[1] = sb1;
+ }
+
+ /* create the first socket */
newsock = socket (AF_INET, type, 0);
if (newsock == INVALID_SOCKET)
{
@@ -2265,7 +1948,6 @@ socketpair (int, int type, int, int *sb)
sock_in.sin_family = AF_INET;
sock_in.sin_port = 0;
sock_in.sin_addr.s_addr = INADDR_ANY;
-
if (bind (newsock, (struct sockaddr *) &sock_in, sizeof (sock_in)) < 0)
{
debug_printf ("bind failed");
@@ -2273,7 +1955,7 @@ socketpair (int, int type, int, int *sb)
closesocket (newsock);
goto done;
}
-
+ len = sizeof (sock_in);
if (getsockname (newsock, (struct sockaddr *) &sock_in, &len) < 0)
{
debug_printf ("getsockname error");
@@ -2282,7 +1964,9 @@ socketpair (int, int type, int, int *sb)
goto done;
}
- listen (newsock, 2);
+ /* For stream sockets, create a listener */
+ if (type == SOCK_STREAM)
+ listen (newsock, 2);
/* create a connecting socket */
outsock = socket (AF_INET, type, 0);
@@ -2294,9 +1978,37 @@ socketpair (int, int type, int, int *sb)
goto done;
}
+ /* For datagram sockets, bind the 2nd socket to an unused address, too */
+ if (type == SOCK_DGRAM)
+ {
+ sock_out.sin_family = AF_INET;
+ sock_out.sin_port = 0;
+ sock_out.sin_addr.s_addr = INADDR_ANY;
+ if (bind (outsock, (struct sockaddr *) &sock_out, sizeof (sock_out)) < 0)
+ {
+ debug_printf ("bind failed");
+ set_winsock_errno ();
+ closesocket (newsock);
+ closesocket (outsock);
+ goto done;
+ }
+ len = sizeof (sock_out);
+ if (getsockname (outsock, (struct sockaddr *) &sock_out, &len) < 0)
+ {
+ debug_printf ("getsockname error");
+ set_winsock_errno ();
+ closesocket (newsock);
+ closesocket (outsock);
+ goto done;
+ }
+ }
+
+ /* Force IP address to loopback */
sock_in.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
+ if (type == SOCK_DGRAM)
+ sock_out.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
- /* Do a connect and accept the connection */
+ /* Do a connect */
if (connect (outsock, (struct sockaddr *) &sock_in,
sizeof (sock_in)) < 0)
{
@@ -2307,26 +2019,68 @@ socketpair (int, int type, int, int *sb)
goto done;
}
- insock = accept (newsock, (struct sockaddr *) &sock_in, &len);
- if (insock == INVALID_SOCKET)
+ if (type == SOCK_STREAM)
{
- debug_printf ("accept error");
- set_winsock_errno ();
+ /* For stream sockets, accept the connection and close the listener */
+ len = sizeof (sock_in);
+ insock = accept (newsock, (struct sockaddr *) &sock_in, &len);
+ if (insock == INVALID_SOCKET)
+ {
+ debug_printf ("accept error");
+ set_winsock_errno ();
+ closesocket (newsock);
+ closesocket (outsock);
+ goto done;
+ }
closesocket (newsock);
- closesocket (outsock);
- goto done;
+ }
+ else
+ {
+ /* For datagram sockets, connect the 2nd socket */
+ if (connect (newsock, (struct sockaddr *) &sock_out,
+ sizeof (sock_out)) < 0)
+ {
+ debug_printf ("connect error");
+ set_winsock_errno ();
+ closesocket (newsock);
+ closesocket (outsock);
+ goto done;
+ }
+ insock = newsock;
}
- closesocket (newsock);
res = 0;
- fdsock (sb[0], "/dev/tcp", insock);
+ if (family == AF_LOCAL)
+ {
- fdsock (sb[1], "/dev/tcp", outsock);
+ fh = fdsock (sb[0],
+ type == SOCK_STREAM ? "/dev/streamsocket" : "/dev/dgsocket",
+ insock);
+ fh->set_sun_path ("");
+ fh->set_addr_family (AF_LOCAL);
+ fh->set_socket_type (type);
+ fh = fdsock (sb[1],
+ type == SOCK_STREAM ? "/dev/streamsocket" : "/dev/dgsocket",
+ outsock);
+ fh->set_sun_path ("");
+ fh->set_addr_family (AF_LOCAL);
+ fh->set_socket_type (type);
+ }
+ else
+ {
+ fh = fdsock (sb[0], type == SOCK_STREAM ? "/dev/tcp" : "/dev/udp",
+ insock);
+ fh->set_addr_family (AF_INET);
+ fh->set_socket_type (type);
+ fh = fdsock (sb[1], type == SOCK_STREAM ? "/dev/tcp" : "/dev/udp",
+ outsock);
+ fh->set_addr_family (AF_INET);
+ fh->set_socket_type (type);
+ }
done:
syscall_printf ("%d = socketpair (...)", res);
- ReleaseResourceLock (LOCK_FD_LIST, WRITE_LOCK|READ_LOCK, "socketpair");
return res;
}
@@ -2341,3 +2095,55 @@ extern "C" void
endhostent (void)
{
}
+
+/* exported as recvmsg: standards? */
+extern "C" int
+cygwin_recvmsg (int fd, struct msghdr *msg, int flags)
+{
+ int res;
+ sigframe thisframe (mainthread);
+
+ fhandler_socket *fh = get (fd);
+
+ if (check_null_invalid_struct_errno (msg)
+ || (msg->msg_name
+ && __check_null_invalid_struct_errno (msg->msg_name,
+ (unsigned) msg->msg_namelen))
+ || !fh)
+ res = -1;
+ else
+ {
+ res = check_iovec_for_read (msg->msg_iov, msg->msg_iovlen);
+ if (res > 0)
+ res = fh->recvmsg (msg, flags, res); // res == iovec tot
+ }
+
+ syscall_printf ("%d = recvmsg (%d, %p, %x)", res, fd, msg, flags);
+ return res;
+}
+
+/* exported as sendmsg: standards? */
+extern "C" int
+cygwin_sendmsg (int fd, const struct msghdr *msg, int flags)
+{
+ int res;
+ sigframe thisframe (mainthread);
+
+ fhandler_socket *fh = get (fd);
+
+ if (__check_invalid_read_ptr_errno (msg, sizeof msg)
+ || (msg->msg_name
+ && __check_invalid_read_ptr_errno (msg->msg_name,
+ (unsigned) msg->msg_namelen))
+ || !fh)
+ res = -1;
+ else
+ {
+ res = check_iovec_for_write (msg->msg_iov, msg->msg_iovlen);
+ if (res > 0)
+ res = fh->sendmsg (msg, flags, res); // res == iovec tot
+ }
+
+ syscall_printf ("%d = sendmsg (%d, %p, %x)", res, fd, msg, flags);
+ return res;
+}