Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
829e6f14
Commit
829e6f14
authored
Dec 05, 2006
by
Kai Blin
Committed by
Alexandre Julliard
Dec 05, 2006
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ws2_32: Rewrite setsockopt to be more readable.
parent
a10c40df
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
179 additions
and
104 deletions
+179
-104
socket.c
dlls/ws2_32/socket.c
+179
-104
No files found.
dlls/ws2_32/socket.c
View file @
829e6f14
...
...
@@ -4,6 +4,7 @@
*
* Copyright (C) 1993,1994,1996,1997 John Brezak, Erik Bos, Alex Korobka.
* Copyright (C) 2005 Marcus Meissner
* Copyright (C) 2006 Kai Blin
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
...
...
@@ -2870,117 +2871,100 @@ int WINAPI WS_setsockopt(SOCKET s, int level, int optname,
TRACE
(
"socket: %04x, level %d, name %d, ptr %p, len %d
\n
"
,
s
,
level
,
optname
,
optval
,
optlen
);
/* SO_OPENTYPE does not require a valid socket handle. */
if
(
level
==
WS_SOL_SOCKET
&&
optname
==
WS_SO_OPENTYPE
)
switch
(
level
)
{
if
(
optlen
<
sizeof
(
int
)
||
!
optval
)
case
WS_SOL_SOCKET
:
switch
(
optname
)
{
SetLastError
(
WSAEFAULT
);
return
SOCKET_ERROR
;
}
get_per_thread_data
()
->
opentype
=
*
(
const
int
*
)
optval
;
TRACE
(
"setting global SO_OPENTYPE to 0x%x
\n
"
,
*
(
const
int
*
)
optval
);
return
0
;
}
/* For some reason the game GrandPrixLegends does set SO_DONTROUTE on its
* socket. According to MSDN, this option is silently ignored.*/
if
(
level
==
WS_SOL_SOCKET
&&
optname
==
WS_SO_DONTROUTE
)
{
TRACE
(
"Ignoring SO_DONTROUTE.
\n
"
);
return
0
;
}
/* SO_EXCLUSIVEADDRUSE stops applications from binding to a port that is
* already used. This never works on Unix systems, so just ignore this
* setting*/
if
(
level
==
WS_SOL_SOCKET
&&
optname
==
WS_SO_EXCLUSIVEADDRUSE
)
{
TRACE
(
"Ignoring SO_EXCLUSIVEADDRUSE
\n
"
);
return
0
;
}
#ifdef HAVE_IPX
if
(
level
==
NSPROTO_IPX
)
{
switch
(
optname
)
{
case
IPX_PTYPE
:
fd
=
get_sock_fd
(
s
,
0
,
NULL
);
TRACE
(
"trying to set IPX_PTYPE: %d (fd: %d)
\n
"
,
*
(
const
int
*
)
optval
,
fd
);
/* We try to set the ipx type on ipx socket level. */
#ifdef SOL_IPX
if
(
setsockopt
(
fd
,
SOL_IPX
,
IPX_TYPE
,
optval
,
optlen
)
==
-
1
)
{
ERR
(
"IPX: could not set ipx option type; expect weird behaviour
\n
"
);
return
SOCKET_ERROR
;
}
#else
{
struct
ipx
val
;
/* Should we retrieve val using a getsockopt call and then
* set the modified one? */
val
.
ipx_pt
=
*
optval
;
setsockopt
(
fd
,
0
,
SO_DEFAULT_HEADERS
,
&
val
,
sizeof
(
struct
ipx
));
}
#endif
release_sock_fd
(
s
,
fd
);
return
0
;
case
IPX_FILTERPTYPE
:
/* Sets the receive filter packet type, at the moment we don't support it */
FIXME
(
"IPX_FILTERPTYPE: %x
\n
"
,
*
optval
);
/* Returning 0 is better for now than returning a SOCKET_ERROR */
return
0
;
default:
FIXME
(
"opt_name:%x
\n
"
,
optname
);
return
SOCKET_ERROR
;
}
return
0
;
}
#endif
/* Some options need some conversion before they can be sent to
* setsockopt. The conversions are done here, then they will fall though
* to the general case. Special options that are not passed to
* setsockopt follow below that.*/
/* Is a privileged and useless operation, so we don't. */
if
((
optname
==
WS_SO_DEBUG
)
&&
(
level
==
WS_SOL_SOCKET
))
{
FIXME
(
"(%d,SOL_SOCKET,SO_DEBUG,%p(%d)) attempted (is privileged). Ignoring.
\n
"
,
s
,
optval
,
*
(
const
DWORD
*
)
optval
);
return
0
;
}
case
WS_SO_DONTLINGER
:
linger
.
l_onoff
=
*
((
const
int
*
)
optval
)
?
0
:
1
;
linger
.
l_linger
=
0
;
level
=
SOL_SOCKET
;
optname
=
SO_LINGER
;
optval
=
(
char
*
)
&
linger
;
optlen
=
sizeof
(
struct
linger
);
break
;
if
(
optname
==
WS_SO_DONTLINGER
&&
level
==
WS_SOL_SOCKET
)
{
/* This is unique to WinSock and takes special conversion */
linger
.
l_onoff
=
*
((
const
int
*
)
optval
)
?
0
:
1
;
linger
.
l_linger
=
0
;
optname
=
SO_LINGER
;
optval
=
(
char
*
)
&
linger
;
optlen
=
sizeof
(
struct
linger
);
level
=
SOL_SOCKET
;
}
else
{
if
(
!
convert_sockopt
(
&
level
,
&
optname
))
{
ERR
(
"Invalid level (%d) or optname (%d)
\n
"
,
level
,
optname
);
SetLastError
(
WSAENOPROTOOPT
);
return
SOCKET_ERROR
;
}
if
(
optname
==
SO_LINGER
&&
optval
)
{
case
WS_SO_LINGER
:
linger
.
l_onoff
=
((
LINGER
*
)
optval
)
->
l_onoff
;
linger
.
l_linger
=
((
LINGER
*
)
optval
)
->
l_linger
;
/* FIXME: what is documented behavior if SO_LINGER optval
is null?? */
level
=
SOL_SOCKET
;
optname
=
SO_LINGER
;
optval
=
(
char
*
)
&
linger
;
optlen
=
sizeof
(
struct
linger
);
}
else
if
(
optval
&&
optlen
<
sizeof
(
int
))
{
woptval
=
*
((
const
INT16
*
)
optval
);
optval
=
(
char
*
)
&
woptval
;
optlen
=
sizeof
(
int
);
}
if
(
level
==
SOL_SOCKET
&&
is_timeout_option
(
optname
))
{
if
(
optlen
==
sizeof
(
UINT32
))
{
break
;
case
WS_SO_RCVBUF
:
if
(
*
(
const
int
*
)
optval
<
2048
)
{
WARN
(
"SO_RCVBF for %d bytes is too small: ignored
\n
"
,
*
(
const
int
*
)
optval
);
return
0
;
}
/* Fall through */
/* The options listed here don't need any special handling. Thanks to
* the conversion happening above, options from there will fall through
* to this, too.*/
case
WS_SO_ACCEPTCONN
:
case
WS_SO_BROADCAST
:
case
WS_SO_ERROR
:
case
WS_SO_KEEPALIVE
:
case
WS_SO_OOBINLINE
:
case
WS_SO_SNDBUF
:
case
WS_SO_TYPE
:
convert_sockopt
(
&
level
,
&
optname
);
break
;
/* SO_DEBUG is a privileged operation, ignore it. */
case
WS_SO_DEBUG
:
TRACE
(
"Ignoring SO_DEBUG
\n
"
);
return
0
;
/* For some reason the game GrandPrixLegends does set SO_DONTROUTE on its
* socket. According to MSDN, this option is silently ignored.*/
case
WS_SO_DONTROUTE
:
TRACE
(
"Ignoring SO_DONTROUTE
\n
"
);
return
0
;
/* Stops two sockets from being bound to the same port. Always happens
* on unix systems, so just drop it. */
case
WS_SO_EXCLUSIVEADDRUSE
:
TRACE
(
"Ignoring SO_EXCLUSIVEADDRUSE, is always set.
\n
"
);
return
0
;
/* SO_OPENTYPE does not require a valid socket handle. */
case
WS_SO_OPENTYPE
:
if
(
!
optlen
||
optlen
<
sizeof
(
int
)
||
!
optval
)
{
SetLastError
(
WSAEFAULT
);
return
SOCKET_ERROR
;
}
get_per_thread_data
()
->
opentype
=
*
(
const
int
*
)
optval
;
TRACE
(
"setting global SO_OPENTYPE = 0x%x
\n
"
,
*
((
int
*
)
optval
)
);
return
0
;
/* SO_REUSEADDR allows two applications to bind to the same port at at
* same time. There is no direct way to do that in unix. While Wineserver
* might do this, it does not seem useful for now, so just ignore it.*/
case
WS_SO_REUSEADDR
:
FIXME
(
"Ignoring SO_REUSEADDR, does not translate
\n
"
);
return
0
;
#ifdef SO_RCVTIMEO
case
WS_SO_RCVTIMEO
:
#endif
#ifdef SO_SNDTIMEO
case
WS_SO_SNDTIMEO
:
#endif
#if defined(SO_RCVTIMEO) || defined(SO_SNDTIMEO)
if
(
optval
&&
optlen
==
sizeof
(
UINT32
))
{
/* WinSock passes miliseconds instead of struct timeval */
tval
.
tv_usec
=
(
*
(
const
UINT32
*
)
optval
%
1000
)
*
1000
;
tval
.
tv_sec
=
*
(
const
UINT32
*
)
optval
/
1000
;
...
...
@@ -2995,15 +2979,105 @@ int WINAPI WS_setsockopt(SOCKET s, int level, int optname,
WARN
(
"SO_SND/RCVTIMEO for %d bytes is weird: ignored
\n
"
,
optlen
);
return
0
;
}
convert_sockopt
(
&
level
,
&
optname
);
break
;
#endif
default:
TRACE
(
"Unknown SOL_SOCKET optname: 0x%08x
\n
"
,
optname
);
SetLastError
(
WSAENOPROTOOPT
);
return
SOCKET_ERROR
;
}
if
(
level
==
SOL_SOCKET
&&
optname
==
SO_RCVBUF
&&
*
(
const
int
*
)
optval
<
2048
)
break
;
/* case WS_SOL_SOCKET */
#ifdef HAVE_IPX
case
NSPROTO_IPX
:
switch
(
optname
)
{
WARN
(
"SO_RCVBF for %d bytes is too small: ignored
\n
"
,
*
(
const
int
*
)
optval
);
case
IPX_PTYPE
:
fd
=
get_sock_fd
(
s
,
0
,
NULL
);
TRACE
(
"trying to set IPX_PTYPE: %d (fd: %d)
\n
"
,
*
(
const
int
*
)
optval
,
fd
);
/* We try to set the ipx type on ipx socket level. */
#ifdef SOL_IPX
if
(
setsockopt
(
fd
,
SOL_IPX
,
IPX_TYPE
,
optval
,
optlen
)
==
-
1
)
{
ERR
(
"IPX: could not set ipx option type; expect weird behaviour
\n
"
);
release_sock_fd
(
s
,
fd
);
return
SOCKET_ERROR
;
}
#else
{
struct
ipx
val
;
/* Should we retrieve val using a getsockopt call and then
* set the modified one? */
val
.
ipx_pt
=
*
optval
;
setsockopt
(
fd
,
0
,
SO_DEFAULT_HEADERS
,
&
val
,
sizeof
(
struct
ipx
));
}
#endif
release_sock_fd
(
s
,
fd
);
return
0
;
case
IPX_FILTERPTYPE
:
/* Sets the receive filter packet type, at the moment we don't support it */
FIXME
(
"IPX_FILTERPTYPE: %x
\n
"
,
*
optval
);
/* Returning 0 is better for now than returning a SOCKET_ERROR */
return
0
;
default:
FIXME
(
"opt_name:%x
\n
"
,
optname
);
return
SOCKET_ERROR
;
}
}
break
;
/* case NSPROTO_IPX */
#endif
/* Levels WS_IPPROTO_TCP and WS_IPPROTO_IP convert directly */
case
WS_IPPROTO_TCP
:
switch
(
optname
)
{
case
WS_TCP_NODELAY
:
convert_sockopt
(
&
level
,
&
optname
);
break
;
default:
FIXME
(
"Unknown IPPROTO_TCP optname 0x%08x
\n
"
,
optname
);
return
SOCKET_ERROR
;
}
break
;
case
WS_IPPROTO_IP
:
switch
(
optname
)
{
case
WS_IP_ADD_MEMBERSHIP
:
case
WS_IP_DROP_MEMBERSHIP
:
#ifdef IP_HDRINCL
case
WS_IP_HDRINCL
:
#endif
case
WS_IP_MULTICAST_IF
:
case
WS_IP_MULTICAST_LOOP
:
case
WS_IP_MULTICAST_TTL
:
case
WS_IP_OPTIONS
:
case
WS_IP_TOS
:
case
WS_IP_TTL
:
convert_sockopt
(
&
level
,
&
optname
);
break
;
default:
FIXME
(
"Unknown IPPROTO_IP optname 0x%08x
\n
"
,
optname
);
return
SOCKET_ERROR
;
}
break
;
default:
FIXME
(
"Unknown level: 0x%08x
\n
"
,
level
);
return
SOCKET_ERROR
;
}
/* end switch(level) */
/* avoid endianness issues if argument is a 16-bit int */
if
(
optval
&&
optlen
<
sizeof
(
int
))
{
woptval
=
*
((
const
INT16
*
)
optval
);
optval
=
(
char
*
)
&
woptval
;
optlen
=
sizeof
(
int
);
}
fd
=
get_sock_fd
(
s
,
0
,
NULL
);
if
(
fd
==
-
1
)
return
SOCKET_ERROR
;
...
...
@@ -3015,6 +3089,7 @@ int WINAPI WS_setsockopt(SOCKET s, int level, int optname,
TRACE
(
"Setting socket error, %d
\n
"
,
wsaErrno
());
SetLastError
(
wsaErrno
());
release_sock_fd
(
s
,
fd
);
return
SOCKET_ERROR
;
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment