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
2a4df565
Commit
2a4df565
authored
Dec 04, 2006
by
Kai Blin
Committed by
Alexandre Julliard
Dec 04, 2006
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ws2_32: Rewrite getsockopt to make it more readable.
parent
84fb1e1f
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
308 additions
and
113 deletions
+308
-113
socket.c
dlls/ws2_32/socket.c
+274
-112
sock.c
dlls/ws2_32/tests/sock.c
+34
-1
No files found.
dlls/ws2_32/socket.c
View file @
2a4df565
...
...
@@ -1814,139 +1814,301 @@ INT WINAPI WS_getsockopt(SOCKET s, INT level,
TRACE
(
"socket: %04x, level 0x%x, name 0x%x, 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
||
*
optlen
<
sizeof
(
int
)
||
!
optval
)
case
WS_SOL_SOCKET
:
{
switch
(
optname
)
{
SetLastError
(
WSAEFAULT
);
return
SOCKET_ERROR
;
/* Handle common cases. The special cases are below, sorted
* alphabetically */
case
WS_SO_ACCEPTCONN
:
case
WS_SO_BROADCAST
:
case
WS_SO_DEBUG
:
case
WS_SO_ERROR
:
case
WS_SO_KEEPALIVE
:
case
WS_SO_OOBINLINE
:
case
WS_SO_RCVBUF
:
case
WS_SO_SNDBUF
:
case
WS_SO_TYPE
:
if
(
(
fd
=
get_sock_fd
(
s
,
0
,
NULL
))
==
-
1
)
return
SOCKET_ERROR
;
convert_sockopt
(
&
level
,
&
optname
);
if
(
getsockopt
(
fd
,(
int
)
level
,
optname
,
optval
,
(
unsigned
int
*
)
optlen
)
!=
0
)
{
SetLastError
((
errno
==
EBADF
)
?
WSAENOTSOCK
:
wsaErrno
());
ret
=
SOCKET_ERROR
;
}
release_sock_fd
(
s
,
fd
);
return
ret
;
case
WS_SO_DONTLINGER
:
{
struct
linger
lingval
;
unsigned
int
len
=
sizeof
(
struct
linger
);
if
(
!
optlen
||
*
optlen
<
sizeof
(
BOOL
)
||
!
optval
)
{
SetLastError
(
WSAEFAULT
);
return
SOCKET_ERROR
;
}
if
(
(
fd
=
get_sock_fd
(
s
,
0
,
NULL
))
==
-
1
)
return
SOCKET_ERROR
;
if
(
getsockopt
(
fd
,
SOL_SOCKET
,
SO_LINGER
,
&
lingval
,
&
len
)
!=
0
)
{
SetLastError
((
errno
==
EBADF
)
?
WSAENOTSOCK
:
wsaErrno
());
ret
=
SOCKET_ERROR
;
}
else
{
*
(
BOOL
*
)
optval
=
(
lingval
.
l_onoff
)
?
FALSE
:
TRUE
;
*
optlen
=
sizeof
(
BOOL
);
}
release_sock_fd
(
s
,
fd
);
return
ret
;
}
*
(
int
*
)
optval
=
get_per_thread_data
()
->
opentype
;
*
optlen
=
sizeof
(
int
);
TRACE
(
"getting global SO_OPENTYPE = 0x%x
\n
"
,
*
((
int
*
)
optval
)
);
return
0
;
}
if
(
level
==
WS_SOL_SOCKET
&&
optname
==
WS_SO_MAX_MSG_SIZE
)
{
if
(
!
optlen
||
*
optlen
<
sizeof
(
int
)
||
!
optval
)
/* As mentioned in setsockopt, Windows ignores this, so we
* always return true here */
case
WS_SO_DONTROUTE
:
if
(
!
optlen
||
*
optlen
<
sizeof
(
BOOL
)
||
!
optval
)
{
SetLastError
(
WSAEFAULT
);
return
SOCKET_ERROR
;
}
*
(
BOOL
*
)
optval
=
TRUE
;
*
optlen
=
sizeof
(
BOOL
);
return
0
;
case
WS_SO_LINGER
:
{
SetLastError
(
WSAEFAULT
);
return
SOCKET_ERROR
;
struct
linger
lingval
;
unsigned
int
len
=
sizeof
(
struct
linger
);
/* struct linger and LINGER have different sizes */
if
(
!
optlen
||
*
optlen
<
sizeof
(
LINGER
)
||
!
optval
)
{
SetLastError
(
WSAEFAULT
);
return
SOCKET_ERROR
;
}
if
(
(
fd
=
get_sock_fd
(
s
,
0
,
NULL
))
==
-
1
)
return
SOCKET_ERROR
;
if
(
getsockopt
(
fd
,
SOL_SOCKET
,
SO_LINGER
,
&
lingval
,
&
len
)
!=
0
)
{
SetLastError
((
errno
==
EBADF
)
?
WSAENOTSOCK
:
wsaErrno
());
ret
=
SOCKET_ERROR
;
}
else
{
((
LINGER
*
)
optval
)
->
l_onoff
=
lingval
.
l_onoff
;
((
LINGER
*
)
optval
)
->
l_linger
=
lingval
.
l_linger
;
*
optlen
=
sizeof
(
struct
linger
);
}
release_sock_fd
(
s
,
fd
);
return
ret
;
}
TRACE
(
"getting global SO_MAX_MSG_SIZE = 65507
\n
"
);
*
(
int
*
)
optval
=
65507
;
*
optlen
=
sizeof
(
int
);
return
0
;
}
case
WS_SO_MAX_MSG_SIZE
:
if
(
!
optlen
||
*
optlen
<
sizeof
(
int
)
||
!
optval
)
{
SetLastError
(
WSAEFAULT
);
return
SOCKET_ERROR
;
}
TRACE
(
"getting global SO_MAX_MSG_SIZE = 65507
\n
"
);
*
(
int
*
)
optval
=
65507
;
*
optlen
=
sizeof
(
int
);
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
;
}
*
(
int
*
)
optval
=
get_per_thread_data
()
->
opentype
;
*
optlen
=
sizeof
(
int
);
TRACE
(
"getting global SO_OPENTYPE = 0x%x
\n
"
,
*
((
int
*
)
optval
)
);
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)
{
struct
timeval
tv
;
unsigned
int
len
=
sizeof
(
struct
timeval
);
if
(
!
optlen
||
*
optlen
<
sizeof
(
int
)
||
!
optval
)
{
SetLastError
(
WSAEFAULT
);
return
SOCKET_ERROR
;
}
if
(
(
fd
=
get_sock_fd
(
s
,
0
,
NULL
))
==
-
1
)
return
SOCKET_ERROR
;
convert_sockopt
(
&
level
,
&
optname
);
if
(
getsockopt
(
fd
,(
int
)
level
,
optname
,
&
tv
,
&
len
)
!=
0
)
{
SetLastError
((
errno
==
EBADF
)
?
WSAENOTSOCK
:
wsaErrno
());
ret
=
SOCKET_ERROR
;
}
else
{
*
(
int
*
)
optval
=
tv
.
tv_sec
*
1000
+
tv
.
tv_usec
/
1000
;
*
optlen
=
sizeof
(
int
);
}
release_sock_fd
(
s
,
fd
);
return
ret
;
}
#endif
/* As mentioned in setsockopt, the windows style SO_REUSEADDR is
* not possible in Unix, so always return false here. */
case
WS_SO_REUSEADDR
:
if
(
!
optlen
||
*
optlen
<
sizeof
(
int
)
||
!
optval
)
{
SetLastError
(
WSAEFAULT
);
return
SOCKET_ERROR
;
}
*
(
int
*
)
optval
=
0
;
*
optlen
=
sizeof
(
int
);
return
0
;
default:
TRACE
(
"Unknown SOL_SOCKET optname: 0x%08x
\n
"
,
optname
);
SetLastError
(
WSAENOPROTOOPT
);
return
SOCKET_ERROR
;
}
/* end switch(optname) */
}
/* end case WS_SOL_SOCKET */
#ifdef HAVE_IPX
if
(
level
==
NSPROTO_IPX
)
case
NSPROTO_IPX
:
{
struct
WS_sockaddr_ipx
addr
;
IPX_ADDRESS_DATA
*
data
;
int
namelen
;
switch
(
optname
)
{
case
IPX_PTYPE
:
fd
=
get_sock_fd
(
s
,
0
,
NULL
)
;
struct
WS_sockaddr_ipx
addr
;
IPX_ADDRESS_DATA
*
data
;
int
namelen
;
switch
(
optname
)
{
case
IPX_PTYPE
:
if
((
fd
=
get_sock_fd
(
s
,
0
,
NULL
))
==
-
1
)
return
SOCKET_ERROR
;
#ifdef SOL_IPX
if
(
getsockopt
(
fd
,
SOL_IPX
,
IPX_TYPE
,
optval
,
(
unsigned
int
*
)
optlen
)
==
-
1
)
{
return
SOCKET_ERROR
;
}
if
(
getsockopt
(
fd
,
SOL_IPX
,
IPX_TYPE
,
optval
,
(
unsigned
int
*
)
optlen
)
==
-
1
)
{
ret
=
SOCKET_ERROR
;
}
#else
{
struct
ipx
val
;
socklen_t
len
=
sizeof
(
struct
ipx
);
if
(
getsockopt
(
fd
,
0
,
SO_DEFAULT_HEADERS
,
&
val
,
&
len
)
==
-
1
)
return
SOCKET_ERROR
;
{
struct
ipx
val
;
socklen_t
len
=
sizeof
(
struct
ipx
);
if
(
getsockopt
(
fd
,
0
,
SO_DEFAULT_HEADERS
,
&
val
,
&
len
)
==
-
1
)
ret
=
SOCKET_ERROR
;
else
*
optval
=
(
int
)
val
.
ipx_pt
;
}
#endif
TRACE
(
"ptype: %d (fd: %d)
\n
"
,
*
(
int
*
)
optval
,
fd
);
release_sock_fd
(
s
,
fd
);
return
0
;
case
IPX_ADDRESS
:
/*
* On a Win2000 system with one network card there are usually three ipx devices one with a speed of 28.8kbps, 10Mbps and 100Mbps.
* Using this call you can then retrieve info about this all. In case of Linux it is a bit different. Usually you have
* only "one" device active and further it is not possible to query things like the linkspeed.
*/
FIXME
(
"IPX_ADDRESS
\n
"
);
namelen
=
sizeof
(
struct
WS_sockaddr_ipx
);
memset
(
&
addr
,
0
,
sizeof
(
struct
WS_sockaddr_ipx
));
WS_getsockname
(
s
,
(
struct
WS_sockaddr
*
)
&
addr
,
&
namelen
);
data
=
(
IPX_ADDRESS_DATA
*
)
optval
;
memcpy
(
data
->
nodenum
,
&
addr
.
sa_nodenum
,
sizeof
(
data
->
nodenum
));
memcpy
(
data
->
netnum
,
&
addr
.
sa_netnum
,
sizeof
(
data
->
netnum
));
data
->
adapternum
=
0
;
data
->
wan
=
FALSE
;
/* We are not on a wan for now .. */
data
->
status
=
FALSE
;
/* Since we are not on a wan, the wan link isn't up */
data
->
maxpkt
=
1467
;
/* This value is the default one, at least on Win2k/WinXP */
data
->
linkspeed
=
100000
;
/* Set the line speed in 100bit/s to 10 Mbit; note 1MB = 1000kB in this case */
return
0
;
case
IPX_MAX_ADAPTER_NUM
:
FIXME
(
"IPX_MAX_ADAPTER_NUM
\n
"
);
*
(
int
*
)
optval
=
1
;
/* As noted under IPX_ADDRESS we have just one card. */
return
0
;
default:
FIXME
(
"IPX optname:%x
\n
"
,
optname
);
return
SOCKET_ERROR
;
}
}
}
#endif
TRACE
(
"ptype: %d (fd: %d)
\n
"
,
*
(
int
*
)
optval
,
fd
);
release_sock_fd
(
s
,
fd
);
return
ret
;
case
IPX_ADDRESS
:
/*
* On a Win2000 system with one network card there are usually
* three ipx devices one with a speed of 28.8kbps, 10Mbps and 100Mbps.
* Using this call you can then retrieve info about this all.
* In case of Linux it is a bit different. Usually you have
* only "one" device active and further it is not possible to
* query things like the linkspeed.
*/
FIXME
(
"IPX_ADDRESS
\n
"
);
namelen
=
sizeof
(
struct
WS_sockaddr_ipx
);
memset
(
&
addr
,
0
,
sizeof
(
struct
WS_sockaddr_ipx
));
WS_getsockname
(
s
,
(
struct
WS_sockaddr
*
)
&
addr
,
&
namelen
);
data
=
(
IPX_ADDRESS_DATA
*
)
optval
;
memcpy
(
data
->
nodenum
,
&
addr
.
sa_nodenum
,
sizeof
(
data
->
nodenum
));
memcpy
(
data
->
netnum
,
&
addr
.
sa_netnum
,
sizeof
(
data
->
netnum
));
data
->
adapternum
=
0
;
data
->
wan
=
FALSE
;
/* We are not on a wan for now .. */
data
->
status
=
FALSE
;
/* Since we are not on a wan, the wan link isn't up */
data
->
maxpkt
=
1467
;
/* This value is the default one, at least on Win2k/WinXP */
data
->
linkspeed
=
100000
;
/* Set the line speed in 100bit/s to 10 Mbit;
* note 1MB = 1000kB in this case */
return
0
;
if
(
(
fd
=
get_sock_fd
(
s
,
0
,
NULL
))
==
-
1
)
return
SOCKET_ERROR
;
case
IPX_MAX_ADAPTER_NUM
:
FIXME
(
"IPX_MAX_ADAPTER_NUM
\n
"
);
*
(
int
*
)
optval
=
1
;
/* As noted under IPX_ADDRESS we have just one card. */
return
0
;
if
(
!
convert_sockopt
(
&
level
,
&
optname
))
{
SetLastError
(
WSAENOPROTOOPT
);
/* Unknown option */
ret
=
SOCKET_ERROR
;
}
else
{
struct
timeval
tv
;
struct
linger
lingval
;
unsigned
int
len
,
*
plen
=
(
unsigned
int
*
)
optlen
;
char
*
pval
=
optval
;
if
(
level
==
SOL_SOCKET
&&
is_timeout_option
(
optname
))
{
len
=
sizeof
(
tv
);
plen
=
&
len
;
pval
=
(
char
*
)
&
tv
;
}
else
if
(
level
==
SOL_SOCKET
&&
optname
==
SO_LINGER
)
{
len
=
sizeof
(
lingval
);
plen
=
&
len
;
pval
=
(
char
*
)
&
lingval
;
}
if
(
getsockopt
(
fd
,
(
int
)
level
,
optname
,
pval
,
plen
)
!=
0
)
{
SetLastError
((
errno
==
EBADF
)
?
WSAENOTSOCK
:
wsaErrno
());
ret
=
SOCKET_ERROR
;
}
else
if
(
level
==
SOL_SOCKET
&&
is_timeout_option
(
optname
))
{
if
(
*
optlen
>=
sizeof
(
INT
)
)
{
*
optlen
=
sizeof
(
INT
);
*
(
INT
*
)
optval
=
tv
.
tv_sec
*
1000
+
tv
.
tv_usec
/
1000
;
}
else
{
SetLastError
(
WSAEFAULT
);
default:
FIXME
(
"IPX optname:%x
\n
"
,
optname
);
return
SOCKET_ERROR
;
}
/* end switch(optname) */
}
/* end case NSPROTO_IPX */
#endif
/* Levels WS_IPPROTO_TCP and WS_IPPROTO_IP convert directly */
case
WS_IPPROTO_TCP
:
switch
(
optname
)
{
case
WS_TCP_NODELAY
:
if
(
(
fd
=
get_sock_fd
(
s
,
0
,
NULL
))
==
-
1
)
return
SOCKET_ERROR
;
convert_sockopt
(
&
level
,
&
optname
);
if
(
getsockopt
(
fd
,(
int
)
level
,
optname
,
optval
,
(
unsigned
int
*
)
optlen
)
!=
0
)
{
SetLastError
((
errno
==
EBADF
)
?
WSAENOTSOCK
:
wsaErrno
());
ret
=
SOCKET_ERROR
;
}
}
else
if
(
level
==
SOL_SOCKET
&&
optname
==
SO_LINGER
)
{
if
(
*
optlen
>=
sizeof
(
LINGER
)
)
{
((
LINGER
*
)
optval
)
->
l_onoff
=
lingval
.
l_onoff
;
((
LINGER
*
)
optval
)
->
l_linger
=
lingval
.
l_linger
;
}
else
{
SetLastError
(
WSAEFAULT
);
release_sock_fd
(
s
,
fd
);
return
ret
;
}
FIXME
(
"Unknown IPPROTO_TCP optname 0x%08x
\n
"
,
optname
);
return
SOCKET_ERROR
;
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
:
if
(
(
fd
=
get_sock_fd
(
s
,
0
,
NULL
))
==
-
1
)
return
SOCKET_ERROR
;
convert_sockopt
(
&
level
,
&
optname
);
if
(
getsockopt
(
fd
,(
int
)
level
,
optname
,
optval
,
(
unsigned
int
*
)
optlen
)
!=
0
)
{
SetLastError
((
errno
==
EBADF
)
?
WSAENOTSOCK
:
wsaErrno
());
ret
=
SOCKET_ERROR
;
}
release_sock_fd
(
s
,
fd
);
return
ret
;
}
}
release_sock_fd
(
s
,
fd
);
return
ret
;
}
FIXME
(
"Unknown IPPROTO_IP optname 0x%08x
\n
"
,
optname
);
return
SOCKET_ERROR
;
default:
FIXME
(
"Unknown level: 0x%08x
\n
"
,
level
);
return
SOCKET_ERROR
;
}
/* end switch(level) */
}
/***********************************************************************
* htonl (WINSOCK.8)
...
...
dlls/ws2_32/tests/sock.c
View file @
2a4df565
...
...
@@ -1417,6 +1417,8 @@ static void test_extendedSocketOptions()
struct
sockaddr_in
sa
;
int
sa_len
=
sizeof
(
struct
sockaddr_in
);
int
optval
,
optlen
=
sizeof
(
int
),
ret
;
BOOL
bool_opt_val
;
LINGER
linger_val
;
if
(
WSAStartup
(
MAKEWORD
(
2
,
0
),
&
wsa
)){
trace
(
"Winsock failed: 0x%08x. Aborting test
\n
"
,
WSAGetLastError
());
...
...
@@ -1442,11 +1444,42 @@ static void test_extendedSocketOptions()
return
;
}
ret
=
getsockopt
(
sock
,
SOL_SOCKET
,
SO_MAX_MSG_SIZE
,
(
char
*
)
&
optval
,
(
int
*
)
&
optlen
);
ret
=
getsockopt
(
sock
,
SOL_SOCKET
,
SO_MAX_MSG_SIZE
,
(
char
*
)
&
optval
,
&
optlen
);
ok
(
ret
==
0
,
"getsockopt failed to query SO_MAX_MSG_SIZE, return value is 0x%08x
\n
"
,
ret
);
ok
(
optval
==
65507
,
"SO_MAX_MSG_SIZE reported %d, expected 65507
\n
"
,
optval
);
optlen
=
sizeof
(
LINGER
);
ret
=
getsockopt
(
sock
,
SOL_SOCKET
,
SO_LINGER
,
(
char
*
)
&
linger_val
,
&
optlen
);
todo_wine
{
ok
(
ret
==
SOCKET_ERROR
,
"getsockopt should fail for UDP sockets but return value is 0x%08x
\n
"
,
ret
);
}
closesocket
(
sock
);
if
((
sock
=
socket
(
PF_INET
,
SOCK_STREAM
,
IPPROTO_IP
))
<
0
){
trace
(
"Creating the socket failed: 0x%08x
\n
"
,
WSAGetLastError
());
WSACleanup
();
return
;
}
if
(
bind
(
sock
,
(
struct
sockaddr
*
)
&
sa
,
sa_len
)
<
0
){
trace
(
"Failed to bind socket: 0x%08x
\n
"
,
WSAGetLastError
());
closesocket
(
sock
);
WSACleanup
();
return
;
}
ret
=
getsockopt
(
sock
,
SOL_SOCKET
,
SO_LINGER
,
(
char
*
)
&
linger_val
,
&
optlen
);
ok
(
ret
==
0
,
"getsockopt failed to query SO_LINGER, return value is 0x%08x
\n
"
,
ret
);
optlen
=
sizeof
(
BOOL
);
ret
=
getsockopt
(
sock
,
SOL_SOCKET
,
SO_DONTLINGER
,
(
char
*
)
&
bool_opt_val
,
&
optlen
);
ok
(
ret
==
0
,
"getsockopt failed to query SO_DONTLINGER, return value is 0x%08x
\n
"
,
ret
);
ok
((
linger_val
.
l_onoff
&&
!
bool_opt_val
)
||
(
!
linger_val
.
l_onoff
&&
bool_opt_val
),
"Return value of SO_DONTLINGER is %d, but SO_LINGER returned l_onoff == %d.
\n
"
,
bool_opt_val
,
linger_val
.
l_onoff
);
closesocket
(
sock
);
WSACleanup
();
}
...
...
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