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
a9ae1e04
Commit
a9ae1e04
authored
Oct 31, 2022
by
Paul Gofman
Committed by
Alexandre Julliard
Nov 04, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
server: Support SO_EXCLUSIVEADDRUSE socket option.
parent
003ee620
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
35 additions
and
20 deletions
+35
-20
sock.c
dlls/ws2_32/tests/sock.c
+9
-13
sock.c
server/sock.c
+26
-7
No files found.
dlls/ws2_32/tests/sock.c
View file @
a9ae1e04
...
...
@@ -2043,19 +2043,18 @@ static void test_reuseaddr(void)
}
s
[
2
];
int
error
;
BOOL
todo
;
}
tests_exclusive
[]
=
{
{
{{
AF_INET
,
(
struct
sockaddr
*
)
&
saddr_in_any
,
sizeof
(
saddr_in_any
),
TRUE
,
},
{
AF_INET
,
(
struct
sockaddr
*
)
&
saddr_in_loopback
,
sizeof
(
saddr_in_loopback
),
FALSE
,
}},
WSAEACCES
,
TRUE
,
WSAEACCES
,
},
{
{{
AF_INET6
,
(
struct
sockaddr
*
)
&
saddr_in6_any
,
sizeof
(
saddr_in6_any
),
TRUE
,
},
{
AF_INET
,
(
struct
sockaddr
*
)
&
saddr_in_loopback
,
sizeof
(
saddr_in_loopback
),
FALSE
,
}},
WSAEACCES
,
TRUE
,
WSAEACCES
,
},
{
{{
AF_INET
,
(
struct
sockaddr
*
)
&
saddr_in_any
,
sizeof
(
saddr_in_any
),
FALSE
,
},
...
...
@@ -2065,7 +2064,7 @@ static void test_reuseaddr(void)
{
{{
AF_INET
,
(
struct
sockaddr
*
)
&
saddr_in_any
,
sizeof
(
saddr_in_any
),
TRUE
,
},
{
AF_INET
,
(
struct
sockaddr
*
)
&
saddr_in_loopback
,
sizeof
(
saddr_in_loopback
),
TRUE
,
}},
WSAEACCES
,
TRUE
,
WSAEACCES
,
},
{
{{
AF_INET
,
(
struct
sockaddr
*
)
&
saddr_in_loopback
,
sizeof
(
saddr_in_loopback
),
TRUE
,
},
...
...
@@ -2075,12 +2074,12 @@ static void test_reuseaddr(void)
{
{{
AF_INET
,
(
struct
sockaddr
*
)
&
saddr_in_loopback
,
sizeof
(
saddr_in_loopback
),
FALSE
,
},
{
AF_INET
,
(
struct
sockaddr
*
)
&
saddr_in_any
,
sizeof
(
saddr_in_any
),
TRUE
,
}},
WSAEADDRINUSE
,
TRUE
,
WSAEADDRINUSE
,
},
{
{{
AF_INET
,
(
struct
sockaddr
*
)
&
saddr_in_loopback
,
sizeof
(
saddr_in_loopback
),
FALSE
,
},
{
AF_INET6
,
(
struct
sockaddr
*
)
&
saddr_in6_any
,
sizeof
(
saddr_in6_any
),
TRUE
,
}},
WSAEADDRINUSE
,
TRUE
,
WSAEADDRINUSE
,
},
{
{{
AF_INET6
,
(
struct
sockaddr
*
)
&
saddr_in6_loopback
,
sizeof
(
saddr_in6_loopback
),
FALSE
,
},
...
...
@@ -2095,17 +2094,17 @@ static void test_reuseaddr(void)
{
{{
AF_INET6
,
(
struct
sockaddr
*
)
&
saddr_in6_loopback_v4mapped
,
sizeof
(
saddr_in6_loopback_v4mapped
),
FALSE
,
},
{
AF_INET
,
(
struct
sockaddr
*
)
&
saddr_in_any
,
sizeof
(
saddr_in_any
),
TRUE
,
}},
WSAEADDRINUSE
,
TRUE
,
WSAEADDRINUSE
,
},
{
{{
AF_INET6
,
(
struct
sockaddr
*
)
&
saddr_in6_any
,
sizeof
(
saddr_in6_any
),
TRUE
,
},
{
AF_INET
,
(
struct
sockaddr
*
)
&
saddr_in_any
,
sizeof
(
saddr_in_any
),
FALSE
,
}},
WSAEACCES
,
TRUE
,
WSAEACCES
,
},
{
{{
AF_INET6
,
(
struct
sockaddr
*
)
&
saddr_in6_any
,
sizeof
(
saddr_in6_any
),
FALSE
,
},
{
AF_INET
,
(
struct
sockaddr
*
)
&
saddr_in_any
,
sizeof
(
saddr_in_any
),
TRUE
,
}},
NOERROR
,
TRUE
,
NOERROR
,
},
{
{{
AF_INET
,
(
struct
sockaddr
*
)
&
saddr_in_any
,
sizeof
(
saddr_in_any
),
FALSE
,
},
...
...
@@ -2120,7 +2119,7 @@ static void test_reuseaddr(void)
{
{{
AF_INET6
,
(
struct
sockaddr
*
)
&
saddr_in6_any
,
sizeof
(
saddr_in6_any
),
FALSE
,
},
{
AF_INET
,
(
struct
sockaddr
*
)
&
saddr_in_any
,
sizeof
(
saddr_in_any
),
FALSE
,
}},
NOERROR
,
TRUE
,
NOERROR
,
},
{
{{
AF_INET6
,
(
struct
sockaddr
*
)
&
saddr_in6_any_v4mapped
,
sizeof
(
saddr_in6_any_v4mapped
),
FALSE
,
},
...
...
@@ -2398,14 +2397,11 @@ static void test_reuseaddr(void)
rc
=
bind
(
s
[
1
],
tests_exclusive
[
i
].
s
[
1
].
addr
,
tests_exclusive
[
i
].
s
[
1
].
addrlen
);
todo_wine_if
(
tests_exclusive
[
i
].
todo
)
{
if
(
tests_exclusive
[
i
].
error
)
ok
(
rc
==
SOCKET_ERROR
&&
WSAGetLastError
()
==
tests_exclusive
[
i
].
error
,
"got rc %d, error %d, expected error %d.
\n
"
,
rc
,
WSAGetLastError
(),
tests_exclusive
[
i
].
error
);
else
ok
(
!
rc
,
"got error %d.
\n
"
,
WSAGetLastError
());
}
closesocket
(
s
[
0
]);
closesocket
(
s
[
1
]);
...
...
server/sock.c
View file @
a9ae1e04
...
...
@@ -187,6 +187,7 @@ struct bound_addr
{
struct
rb_entry
entry
;
union
unix_sockaddr
addr
;
int
match_any_addr
;
int
reuse_count
;
};
...
...
@@ -276,7 +277,8 @@ static int addr_compare( const void *key, const struct wine_rb_entry *entry )
{
if
(
addr
->
addr
.
in
.
sin_port
!=
bound_addr
->
addr
.
in
.
sin_port
)
return
addr
->
addr
.
in
.
sin_port
<
bound_addr
->
addr
.
in
.
sin_port
?
-
1
:
1
;
if
(
addr
->
addr
.
in
.
sin_addr
.
s_addr
==
bound_addr
->
addr
.
in
.
sin_addr
.
s_addr
)
if
(
bound_addr
->
match_any_addr
||
addr
->
match_any_addr
||
addr
->
addr
.
in
.
sin_addr
.
s_addr
==
bound_addr
->
addr
.
in
.
sin_addr
.
s_addr
)
return
0
;
return
addr
->
addr
.
in
.
sin_addr
.
s_addr
<
bound_addr
->
addr
.
in
.
sin_addr
.
s_addr
?
-
1
:
1
;
}
...
...
@@ -284,14 +286,16 @@ static int addr_compare( const void *key, const struct wine_rb_entry *entry )
assert
(
addr
->
addr
.
addr
.
sa_family
==
AF_INET6
);
if
(
addr
->
addr
.
in6
.
sin6_port
!=
bound_addr
->
addr
.
in6
.
sin6_port
)
return
addr
->
addr
.
in6
.
sin6_port
<
bound_addr
->
addr
.
in6
.
sin6_port
?
-
1
:
1
;
if
(
bound_addr
->
match_any_addr
||
addr
->
match_any_addr
)
return
0
;
return
memcmp
(
&
addr
->
addr
.
in6
.
sin6_addr
,
&
bound_addr
->
addr
.
in6
.
sin6_addr
,
sizeof
(
addr
->
addr
.
in6
.
sin6_addr
)
);
}
static
int
ipv4addr_from_v6
(
union
unix_sockaddr
*
v4addr
,
const
struct
sockaddr_in6
*
in6
)
static
int
ipv4addr_from_v6
(
union
unix_sockaddr
*
v4addr
,
const
struct
sockaddr_in6
*
in6
,
int
map_unspecified
)
{
v4addr
->
in
.
sin_family
=
AF_INET
;
v4addr
->
in
.
sin_port
=
in6
->
sin6_port
;
if
(
IN6_IS_ADDR_UNSPECIFIED
(
&
in6
->
sin6_addr
))
if
(
map_unspecified
&&
IN6_IS_ADDR_UNSPECIFIED
(
&
in6
->
sin6_addr
))
{
v4addr
->
in
.
sin_addr
.
s_addr
=
htonl
(
INADDR_ANY
);
return
1
;
...
...
@@ -318,6 +322,15 @@ static int should_track_conflicts_for_addr( struct sock *sock, const union unix_
return
0
;
}
static
int
is_any_addr
(
const
union
unix_sockaddr
*
addr
)
{
if
(
addr
->
addr
.
sa_family
==
AF_INET
&&
addr
->
in
.
sin_addr
.
s_addr
==
htonl
(
INADDR_ANY
))
return
1
;
if
(
addr
->
addr
.
sa_family
==
AF_INET6
&&
IN6_IS_ADDR_UNSPECIFIED
(
&
addr
->
in6
.
sin6_addr
))
return
1
;
return
0
;
}
static
int
check_addr_usage
(
struct
sock
*
sock
,
const
union
unix_sockaddr
*
addr
,
int
v6only
)
{
struct
bound_addr
*
bound_addr
,
search_addr
;
...
...
@@ -326,26 +339,30 @@ static int check_addr_usage( struct sock *sock, const union unix_sockaddr *addr,
if
(
!
should_track_conflicts_for_addr
(
sock
,
addr
))
return
0
;
search_addr
.
addr
=
*
addr
;
search_addr
.
match_any_addr
=
sock
->
exclusiveaddruse
&&
is_any_addr
(
addr
);
if
((
entry
=
rb_get
(
&
bound_addresses_tree
,
&
search_addr
)))
{
bound_addr
=
WINE_RB_ENTRY_VALUE
(
entry
,
struct
bound_addr
,
entry
);
if
(
bound_addr
->
reuse_count
==
-
1
||
!
sock
->
reuseaddr
)
{
set_error
(
sock
->
reuseaddr
?
STATUS_ACCESS_DENIED
:
STATUS_SHARING_VIOLATION
);
set_error
(
sock
->
reuseaddr
||
bound_addr
->
match_any_addr
?
STATUS_ACCESS_DENIED
:
STATUS_SHARING_VIOLATION
);
return
1
;
}
}
if
(
sock
->
family
!=
WS_AF_INET6
||
v6only
)
return
0
;
if
(
!
ipv4addr_from_v6
(
&
search_addr
.
addr
,
&
addr
->
in6
))
return
0
;
if
(
!
ipv4addr_from_v6
(
&
search_addr
.
addr
,
&
addr
->
in6
,
sock
->
exclusiveaddruse
))
return
0
;
search_addr
.
match_any_addr
=
sock
->
exclusiveaddruse
&&
is_any_addr
(
&
search_addr
.
addr
);
if
((
entry
=
rb_get
(
&
bound_addresses_tree
,
&
search_addr
)))
{
bound_addr
=
WINE_RB_ENTRY_VALUE
(
entry
,
struct
bound_addr
,
entry
);
if
(
bound_addr
->
reuse_count
==
-
1
||
!
sock
->
reuseaddr
)
{
set_error
(
sock
->
reuseaddr
?
STATUS_ACCESS_DENIED
:
STATUS_SHARING_VIOLATION
);
set_error
(
sock
->
reuseaddr
||
bound_addr
->
match_any_addr
?
STATUS_ACCESS_DENIED
:
STATUS_SHARING_VIOLATION
);
return
1
;
}
}
...
...
@@ -360,6 +377,7 @@ static struct bound_addr *register_bound_address( struct sock *sock, const union
return
NULL
;
bound_addr
->
addr
=
*
addr
;
bound_addr
->
match_any_addr
=
sock
->
exclusiveaddruse
&&
is_any_addr
(
addr
);
if
(
rb_put
(
&
bound_addresses_tree
,
bound_addr
,
&
bound_addr
->
entry
))
{
...
...
@@ -392,7 +410,8 @@ static void update_addr_usage( struct sock *sock, const union unix_sockaddr *add
sock
->
bound_addr
[
0
]
=
register_bound_address
(
sock
,
addr
);
if
(
sock
->
family
!=
WS_AF_INET6
||
v6only
)
return
;
if
(
!
ipv4addr_from_v6
(
&
v4addr
,
&
addr
->
in6
))
return
;
if
(
!
ipv4addr_from_v6
(
&
v4addr
,
&
addr
->
in6
,
sock
->
exclusiveaddruse
))
return
;
sock
->
bound_addr
[
1
]
=
register_bound_address
(
sock
,
&
v4addr
);
}
...
...
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