summaryrefslogtreecommitdiffstats
path: root/winsup/cygwin/net.cc
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin/net.cc')
-rw-r--r--winsup/cygwin/net.cc154
1 files changed, 52 insertions, 102 deletions
diff --git a/winsup/cygwin/net.cc b/winsup/cygwin/net.cc
index 3de7304f5..91ee74a20 100644
--- a/winsup/cygwin/net.cc
+++ b/winsup/cygwin/net.cc
@@ -29,6 +29,8 @@ details. */
#include <assert.h>
#include "cygerrno.h"
#include "security.h"
+#include "cygwin/version.h"
+#include "perprocess.h"
#include "path.h"
#include "fhandler.h"
#include "dtable.h"
@@ -50,8 +52,6 @@ extern "C"
int sscanf (const char *, const char *, ...);
} /* End of "C" section */
-WSADATA wsadata;
-
static fhandler_socket *
get (const int fd)
{
@@ -68,20 +68,6 @@ get (const int fd)
return fh;
}
-static SOCKET __stdcall
-set_socket_inheritance (SOCKET sock)
-{
- 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
- debug_printf ("DuplicateHandle succeeded osock %p, sock %p", osock, sock);
- VerifyHandle ((HANDLE) sock);
- return sock;
-}
-
/* htonl: standards? */
extern "C" unsigned long int
htonl (unsigned long int x)
@@ -555,24 +541,20 @@ cygwin_getprotobynumber (int number)
bool
fdsock (cygheap_fdmanip& fd, const device *dev, SOCKET soc)
{
- if (!winsock2_active)
- soc = set_socket_inheritance (soc);
- else if (wincap.has_set_handle_information ())
+ 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);
+ debug_printf ("reset socket inheritance");
}
else
- debug_printf ("not setting socket inheritance since winsock2_active %d",
- winsock2_active);
+ debug_printf ("not setting socket inheritance");
fd = build_fh_dev (*dev);
if (!fd.isopen ())
return false;
fd->set_io_handle ((HANDLE) soc);
fd->set_flags (O_RDWR | O_BINARY);
- fd->uninterruptible_io (winsock2_active);
+ fd->uninterruptible_io (true);
cygheap->fdtab.inc_need_fixup_before ();
debug_printf ("fd %d, name '%s', soc %p", (int) fd, dev->name, soc);
return true;
@@ -663,6 +645,27 @@ cygwin_recvfrom (int fd, void *buf, int len, int flags,
return res;
}
+static int
+convert_ws1_ip_optname (int optname)
+{
+ static int ws2_optname[] =
+ {
+ 0,
+ IP_OPTIONS,
+ IP_MULTICAST_IF,
+ IP_MULTICAST_TTL,
+ IP_MULTICAST_LOOP,
+ IP_ADD_MEMBERSHIP,
+ IP_DROP_MEMBERSHIP,
+ IP_TTL,
+ IP_TOS,
+ IP_DONTFRAGMENT
+ };
+ return (optname < 1 || optname > _WS1_IP_DONTFRAGMENT)
+ ? optname
+ : ws2_optname[optname];
+}
+
/* exported as setsockopt: standards? */
extern "C" int
cygwin_setsockopt (int fd, int level, int optname, const void *optval,
@@ -670,48 +673,30 @@ cygwin_setsockopt (int fd, int level, int optname, const void *optval,
{
int res;
fhandler_socket *fh = get (fd);
- const char *name = "error";
-
- /* 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;
- }
myfault efault;
if (efault.faulted (EFAULT) || !fh)
res = -1;
else
{
+ /* Old applications still use the old Winsock1 IPPROTO_IP values. */
+ if (level == IPPROTO_IP && CYGWIN_VERSION_CHECK_FOR_USING_WINSOCK1_VALUES)
+ optname = convert_ws1_ip_optname (optname);
+ /* FOR THE RECORDS:
+
+ Setting IP_TOS is disabled by default since W2K, the official
+ reason being that IP_TOS setting would interfere with Windows
+ QOS settings. As result, setsockopt returns with WinSock error
+ 10022, WSAEINVAL, when running under W2K or later, instead of
+ handling this gracefully.
+
+ The workaround is described in KB article 248611. Add a new
+ registry DWORD value HKLM/System/CurrentControlSet/Services/...
+ ... Tcpip/Parameters/DisableUserTOSSetting, set to 0, and reboot.
+
+ FIXME: Maybe we should simply fake that IP_TOS could be set
+ successfully, if DisableUserTOSSetting is not set to 0 on W2K
+ and above? */
res = setsockopt (fh->get_socket (), level, optname,
(const char *) optval, optlen);
@@ -722,8 +707,8 @@ cygwin_setsockopt (int fd, int level, int optname, const void *optval,
set_winsock_errno ();
}
- syscall_printf ("%d = setsockopt (%d, %d, %x (%s), %p, %d)",
- res, fd, level, optname, name, optval, optlen);
+ syscall_printf ("%d = setsockopt (%d, %d, %x, %p, %d)",
+ res, fd, level, optname, optval, optlen);
return res;
}
@@ -733,44 +718,6 @@ cygwin_getsockopt (int fd, int level, int optname, void *optval, int *optlen)
{
int res;
fhandler_socket *fh = get (fd);
- const char *name = "error";
-
- /* 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_PEERCRED:
- name = "SO_PEERCRED";
- }
myfault efault;
if (efault.faulted (EFAULT) || !fh)
@@ -782,6 +729,9 @@ cygwin_getsockopt (int fd, int level, int optname, void *optval, int *optlen)
}
else
{
+ /* Old applications still use the old Winsock1 IPPROTO_IP values. */
+ if (level == IPPROTO_IP && CYGWIN_VERSION_CHECK_FOR_USING_WINSOCK1_VALUES)
+ optname = convert_ws1_ip_optname (optname);
res = getsockopt (fh->get_socket (), level, optname, (char *) optval,
(int *) optlen);
@@ -797,8 +747,8 @@ cygwin_getsockopt (int fd, int level, int optname, void *optval, int *optlen)
set_winsock_errno ();
}
- syscall_printf ("%d = getsockopt (%d, %d, %x (%s), %p, %p)",
- res, fd, level, optname, name, optval, optlen);
+ syscall_printf ("%d = getsockopt (%d, %d, 0x%x, %p, %p)",
+ res, fd, level, optname, optval, optlen);
return res;
}