Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
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-cw
Commits
54b4f836
Commit
54b4f836
authored
Dec 05, 2010
by
Erich Hoover
Committed by
Alexandre Julliard
Dec 07, 2010
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ws2_32: Add support for WSARecvMsg and IP_PKTINFO.
parent
39b260e8
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
159 additions
and
22 deletions
+159
-22
socket.c
dlls/ws2_32/socket.c
+159
-22
No files found.
dlls/ws2_32/socket.c
View file @
54b4f836
...
...
@@ -171,9 +171,9 @@ WINE_DECLARE_DEBUG_CHANNEL(winediag);
/*
* The actual definition of WSASendTo
/WSARecvFrom, wrapped in a different
*
function name, so that internal calls from ws2_32 itself will not trigger
*
programs like
Garena, which hooks WSASendTo/WSARecvFrom calls.
* The actual definition of WSASendTo
, wrapped in a different function name
*
so that internal calls from ws2_32 itself will not trigger programs like
* Garena, which hooks WSASendTo/WSARecvFrom calls.
*/
static
int
WS2_sendto
(
SOCKET
s
,
LPWSABUF
lpBuffers
,
DWORD
dwBufferCount
,
LPDWORD
lpNumberOfBytesSent
,
DWORD
dwFlags
,
...
...
@@ -181,11 +181,16 @@ static int WS2_sendto( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
LPWSAOVERLAPPED
lpOverlapped
,
LPWSAOVERLAPPED_COMPLETION_ROUTINE
lpCompletionRoutine
);
static
int
WS2_recvfrom
(
SOCKET
s
,
LPWSABUF
lpBuffers
,
DWORD
dwBufferCount
,
LPDWORD
lpNumberOfBytesRecvd
,
LPDWORD
lpFlags
,
struct
WS_sockaddr
*
lpFrom
,
LPINT
lpFromlen
,
LPWSAOVERLAPPED
lpOverlapped
,
LPWSAOVERLAPPED_COMPLETION_ROUTINE
lpCompletionRoutine
);
/*
* Internal fundamental receive function, essentially WSARecvFrom with an
* additional parameter to support message control headers.
*/
static
int
WS2_recv_base
(
SOCKET
s
,
LPWSABUF
lpBuffers
,
DWORD
dwBufferCount
,
LPDWORD
lpNumberOfBytesRecvd
,
LPDWORD
lpFlags
,
struct
WS_sockaddr
*
lpFrom
,
LPINT
lpFromlen
,
LPWSAOVERLAPPED
lpOverlapped
,
LPWSAOVERLAPPED_COMPLETION_ROUTINE
lpCompletionRoutine
,
LPWSABUF
lpControlBuffer
);
/* critical section to protect some non-reentrant net function */
static
CRITICAL_SECTION
csWSgetXXXbyYYY
;
...
...
@@ -261,6 +266,8 @@ typedef struct ws2_async
int
*
ptr
;
/* for recv operations */
}
addrlen
;
DWORD
flags
;
DWORD
*
lpFlags
;
WSABUF
*
control
;
unsigned
int
n_iovecs
;
unsigned
int
first_iovec
;
struct
iovec
iovec
[
1
];
...
...
@@ -375,6 +382,9 @@ static const int ws_ip_map[][2] =
#endif
MAP_OPTION
(
IP_TOS
),
MAP_OPTION
(
IP_TTL
),
#ifdef IP_PKTINFO
MAP_OPTION
(
IP_PKTINFO
),
#endif
};
static
const
int
ws_ipv6_map
[][
2
]
=
...
...
@@ -468,6 +478,75 @@ static const int ws_eai_map[][2] =
static
const
char
magic_loopback_addr
[]
=
{
127
,
12
,
34
,
56
};
#ifndef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
static
inline
WSACMSGHDR
*
fill_control_message
(
int
level
,
int
type
,
WSACMSGHDR
*
current
,
ULONG
*
maxsize
,
void
*
data
,
int
len
)
{
ULONG
msgsize
=
sizeof
(
WSACMSGHDR
)
+
WSA_CMSG_ALIGN
(
len
);
char
*
ptr
=
(
char
*
)
current
+
sizeof
(
WSACMSGHDR
);
/* Make sure there is at least enough room for this entry */
if
(
msgsize
>
*
maxsize
)
return
NULL
;
*
maxsize
-=
msgsize
;
/* Fill in the entry */
current
->
cmsg_len
=
sizeof
(
WSACMSGHDR
)
+
len
;
current
->
cmsg_level
=
level
;
current
->
cmsg_type
=
type
;
memcpy
(
ptr
,
data
,
len
);
/* Return the pointer to where next entry should go */
return
(
WSACMSGHDR
*
)
(
ptr
+
WSA_CMSG_ALIGN
(
len
));
}
static
inline
int
convert_control_headers
(
struct
msghdr
*
hdr
,
WSABUF
*
control
)
{
#ifdef IP_PKTINFO
WSACMSGHDR
*
cmsg_win
=
(
WSACMSGHDR
*
)
control
->
buf
,
*
ptr
;
ULONG
ctlsize
=
control
->
len
;
struct
cmsghdr
*
cmsg_unix
;
ptr
=
cmsg_win
;
/* Loop over all the headers, converting as appropriate */
for
(
cmsg_unix
=
CMSG_FIRSTHDR
(
hdr
);
cmsg_unix
!=
NULL
;
cmsg_unix
=
CMSG_NXTHDR
(
hdr
,
cmsg_unix
))
{
switch
(
cmsg_unix
->
cmsg_level
)
{
case
IPPROTO_IP
:
switch
(
cmsg_unix
->
cmsg_type
)
{
case
IP_PKTINFO
:
{
/* Convert the Unix IP_PKTINFO structure to the Windows version */
struct
in_pktinfo
*
data_unix
=
(
struct
in_pktinfo
*
)
CMSG_DATA
(
cmsg_unix
);
struct
WS_in_pktinfo
data_win
;
memcpy
(
&
data_win
.
ipi_addr
,
&
data_unix
->
ipi_addr
.
s_addr
,
4
);
/* 4 bytes = 32 address bits */
data_win
.
ipi_ifindex
=
data_unix
->
ipi_ifindex
;
ptr
=
fill_control_message
(
WS_IPPROTO_IP
,
WS_IP_PKTINFO
,
ptr
,
&
ctlsize
,
(
void
*
)
&
data_win
,
sizeof
(
data_win
));
if
(
!
ptr
)
goto
error
;
}
break
;
default:
FIXME
(
"Unhandled IPPROTO_IP message header type %d
\n
"
,
cmsg_unix
->
cmsg_type
);
break
;
}
break
;
default:
FIXME
(
"Unhandled message header level %d
\n
"
,
cmsg_unix
->
cmsg_level
);
break
;
}
}
error:
/* Set the length of the returned control headers */
control
->
len
=
(
ptr
==
NULL
?
0
:
(
char
*
)
ptr
-
(
char
*
)
cmsg_win
);
return
(
ptr
!=
NULL
);
#else
/* IP_PKTINFO */
control
->
len
=
0
;
return
1
;
#endif
/* IP_PKTINFO */
}
#endif
/* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
/* ----------------------------------- error handling */
static
NTSTATUS
sock_get_ntstatus
(
int
err
)
...
...
@@ -1411,6 +1490,9 @@ static void WINAPI ws2_async_apc( void *arg, IO_STATUS_BLOCK *iosb, ULONG reserv
*/
static
int
WS2_recv
(
int
fd
,
struct
ws2_async
*
wsa
)
{
#ifndef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
char
pktbuf
[
512
];
#endif
struct
msghdr
hdr
;
union
generic_unix_sockaddr
unix_sockaddr
;
int
n
;
...
...
@@ -1431,14 +1513,30 @@ static int WS2_recv( int fd, struct ws2_async *wsa )
hdr
.
msg_accrights
=
NULL
;
hdr
.
msg_accrightslen
=
0
;
#else
hdr
.
msg_control
=
NULL
;
hdr
.
msg_controllen
=
0
;
hdr
.
msg_control
=
pktbuf
;
hdr
.
msg_controllen
=
sizeof
(
pktbuf
)
;
hdr
.
msg_flags
=
0
;
#endif
if
(
(
n
=
recvmsg
(
fd
,
&
hdr
,
wsa
->
flags
))
==
-
1
)
return
-
1
;
#ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
if
(
wsa
->
control
)
{
ERR
(
"Message control headers cannot be properly supported on this system.
\n
"
);
control
->
len
=
0
;
}
#else
if
(
wsa
->
control
&&
!
convert_control_headers
(
&
hdr
,
wsa
->
control
))
{
WARN
(
"Application passed insufficient room for control headers.
\n
"
);
*
wsa
->
lpFlags
|=
WS_MSG_CTRUNC
;
errno
=
EMSGSIZE
;
return
-
1
;
}
#endif
/* if this socket is connected and lpFrom is not NULL, Linux doesn't give us
* msg_name and msg_namelen from recvmsg, but it does set msg_namelen to zero.
*
...
...
@@ -1914,8 +2012,10 @@ static BOOL WINAPI WS2_AcceptEx(SOCKET listener, SOCKET acceptor, PVOID dest, DW
wsa
->
read
->
hSocket
=
wsa
->
accept_socket
;
wsa
->
read
->
flags
=
0
;
wsa
->
read
->
lpFlags
=
&
wsa
->
read
->
flags
;
wsa
->
read
->
addr
=
NULL
;
wsa
->
read
->
addrlen
.
ptr
=
NULL
;
wsa
->
read
->
control
=
NULL
;
wsa
->
read
->
n_iovecs
=
1
;
wsa
->
read
->
first_iovec
=
0
;
wsa
->
read
->
iovec
[
0
].
iov_base
=
wsa
->
buf
;
...
...
@@ -1962,6 +2062,29 @@ static void WINAPI WS2_GetAcceptExSockaddrs(PVOID buffer, DWORD data_size, DWORD
}
/***********************************************************************
* WSARecvMsg
*
* Perform a receive operation that is capable of returning message
* control headers. It is important to note that the WSAMSG parameter
* must remain valid throughout the operation, even when an overlapped
* receive is performed.
*/
static
int
WINAPI
WS2_WSARecvMsg
(
SOCKET
s
,
LPWSAMSG
msg
,
LPDWORD
lpNumberOfBytesRecvd
,
LPWSAOVERLAPPED
lpOverlapped
,
LPWSAOVERLAPPED_COMPLETION_ROUTINE
lpCompletionRoutine
)
{
if
(
!
msg
)
{
SetLastError
(
WSAEFAULT
);
return
SOCKET_ERROR
;
}
return
WS2_recv_base
(
s
,
msg
->
lpBuffers
,
msg
->
dwBufferCount
,
lpNumberOfBytesRecvd
,
&
msg
->
dwFlags
,
msg
->
name
,
&
msg
->
namelen
,
lpOverlapped
,
lpCompletionRoutine
,
&
msg
->
Control
);
}
/***********************************************************************
* bind (WS2_32.2)
*/
int
WINAPI
WS_bind
(
SOCKET
s
,
const
struct
WS_sockaddr
*
name
,
int
namelen
)
...
...
@@ -2213,6 +2336,8 @@ static BOOL WINAPI WS2_ConnectEx(SOCKET s, const struct WS_sockaddr* name, int n
wsa
->
addr
=
NULL
;
wsa
->
addrlen
.
val
=
0
;
wsa
->
flags
=
0
;
wsa
->
lpFlags
=
&
wsa
->
flags
;
wsa
->
control
=
NULL
;
wsa
->
n_iovecs
=
sendBuf
?
1
:
0
;
wsa
->
first_iovec
=
0
;
wsa
->
completion_func
=
NULL
;
...
...
@@ -2674,6 +2799,9 @@ INT WINAPI WS_getsockopt(SOCKET s, INT level,
case
WS_IP_MULTICAST_LOOP
:
case
WS_IP_MULTICAST_TTL
:
case
WS_IP_OPTIONS
:
#ifdef IP_PKTINFO
case
WS_IP_PKTINFO
:
#endif
case
WS_IP_TOS
:
case
WS_IP_TTL
:
if
(
(
fd
=
get_sock_fd
(
s
,
0
,
NULL
))
==
-
1
)
...
...
@@ -3199,7 +3327,8 @@ INT WINAPI WSAIoctl(SOCKET s,
}
else
if
(
IsEqualGUID
(
&
wsarecvmsg_guid
,
lpvInBuffer
)
)
{
FIXME
(
"SIO_GET_EXTENSION_FUNCTION_POINTER: unimplemented WSARecvMsg
\n
"
);
*
(
LPFN_WSARECVMSG
*
)
lpbOutBuffer
=
WS2_WSARecvMsg
;
return
0
;
}
else
if
(
IsEqualGUID
(
&
wsasendmsg_guid
,
lpvInBuffer
)
)
{
...
...
@@ -3459,7 +3588,7 @@ int WINAPI WS_recv(SOCKET s, char *buf, int len, int flags)
wsabuf
.
len
=
len
;
wsabuf
.
buf
=
buf
;
if
(
WS2_recv
from
(
s
,
&
wsabuf
,
1
,
&
n
,
&
dwFlags
,
NULL
,
NULL
,
NULL
,
NULL
)
==
SOCKET_ERROR
)
if
(
WS2_recv
_base
(
s
,
&
wsabuf
,
1
,
&
n
,
&
dwFlags
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
)
==
SOCKET_ERROR
)
return
SOCKET_ERROR
;
else
return
n
;
...
...
@@ -3477,7 +3606,7 @@ int WINAPI WS_recvfrom(SOCKET s, char *buf, INT len, int flags,
wsabuf
.
len
=
len
;
wsabuf
.
buf
=
buf
;
if
(
WS2_recv
from
(
s
,
&
wsabuf
,
1
,
&
n
,
&
dwFlags
,
from
,
fromlen
,
NULL
,
NULL
)
==
SOCKET_ERROR
)
if
(
WS2_recv
_base
(
s
,
&
wsabuf
,
1
,
&
n
,
&
dwFlags
,
from
,
fromlen
,
NULL
,
NULL
,
NULL
)
==
SOCKET_ERROR
)
return
SOCKET_ERROR
;
else
return
n
;
...
...
@@ -3743,6 +3872,8 @@ static int WS2_sendto( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
wsa
->
addr
=
(
struct
WS_sockaddr
*
)
to
;
wsa
->
addrlen
.
val
=
tolen
;
wsa
->
flags
=
dwFlags
;
wsa
->
lpFlags
=
&
wsa
->
flags
;
wsa
->
control
=
NULL
;
wsa
->
n_iovecs
=
dwBufferCount
;
wsa
->
first_iovec
=
0
;
for
(
i
=
0
;
i
<
dwBufferCount
;
i
++
)
...
...
@@ -4139,6 +4270,9 @@ int WINAPI WS_setsockopt(SOCKET s, int level, int optname,
case
WS_IP_MULTICAST_LOOP
:
case
WS_IP_MULTICAST_TTL
:
case
WS_IP_OPTIONS
:
#ifdef IP_PKTINFO
case
WS_IP_PKTINFO
:
#endif
case
WS_IP_TOS
:
case
WS_IP_TTL
:
convert_sockopt
(
&
level
,
&
optname
);
...
...
@@ -5514,15 +5648,16 @@ int WINAPI WSARecv(SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
LPWSAOVERLAPPED
lpOverlapped
,
LPWSAOVERLAPPED_COMPLETION_ROUTINE
lpCompletionRoutine
)
{
return
WS2_recv
from
(
s
,
lpBuffers
,
dwBufferCount
,
NumberOfBytesReceived
,
lpFlags
,
NULL
,
NULL
,
lpOverlapped
,
lpCompletionRoutine
);
return
WS2_recv
_base
(
s
,
lpBuffers
,
dwBufferCount
,
NumberOfBytesReceived
,
lpFlags
,
NULL
,
NULL
,
lpOverlapped
,
lpCompletionRoutine
,
NULL
);
}
static
int
WS2_recvfrom
(
SOCKET
s
,
LPWSABUF
lpBuffers
,
DWORD
dwBufferCount
,
LPDWORD
lpNumberOfBytesRecvd
,
LPDWORD
lpFlags
,
struct
WS_sockaddr
*
lpFrom
,
LPINT
lpFromlen
,
LPWSAOVERLAPPED
lpOverlapped
,
LPWSAOVERLAPPED_COMPLETION_ROUTINE
lpCompletionRoutine
)
static
int
WS2_recv_base
(
SOCKET
s
,
LPWSABUF
lpBuffers
,
DWORD
dwBufferCount
,
LPDWORD
lpNumberOfBytesRecvd
,
LPDWORD
lpFlags
,
struct
WS_sockaddr
*
lpFrom
,
LPINT
lpFromlen
,
LPWSAOVERLAPPED
lpOverlapped
,
LPWSAOVERLAPPED_COMPLETION_ROUTINE
lpCompletionRoutine
,
LPWSABUF
lpControlBuffer
)
{
unsigned
int
i
,
options
;
int
n
,
fd
,
err
;
...
...
@@ -5548,8 +5683,10 @@ static int WS2_recvfrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
wsa
->
hSocket
=
SOCKET2HANDLE
(
s
);
wsa
->
flags
=
*
lpFlags
;
wsa
->
lpFlags
=
lpFlags
;
wsa
->
addr
=
lpFrom
;
wsa
->
addrlen
.
ptr
=
lpFromlen
;
wsa
->
control
=
lpControlBuffer
;
wsa
->
n_iovecs
=
dwBufferCount
;
wsa
->
first_iovec
=
0
;
for
(
i
=
0
;
i
<
dwBufferCount
;
i
++
)
...
...
@@ -5683,10 +5820,10 @@ INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
LPWSAOVERLAPPED_COMPLETION_ROUTINE
lpCompletionRoutine
)
{
return
WS2_recv
from
(
s
,
lpBuffers
,
dwBufferCount
,
return
WS2_recv
_base
(
s
,
lpBuffers
,
dwBufferCount
,
lpNumberOfBytesRecvd
,
lpFlags
,
lpFrom
,
lpFromlen
,
lpOverlapped
,
lpCompletionRoutine
);
lpOverlapped
,
lpCompletionRoutine
,
NULL
);
}
/***********************************************************************
...
...
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