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
0515480d
Commit
0515480d
authored
Aug 02, 2021
by
Huw Davies
Committed by
Alexandre Julliard
Aug 02, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
iphlpapi: Implement GetIpForwardTable() on top of nsi.
Signed-off-by:
Huw Davies
<
huw@codeweavers.com
>
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
8f207fe7
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
146 additions
and
77 deletions
+146
-77
iphlpapi_main.c
dlls/iphlpapi/iphlpapi_main.c
+78
-29
iphlpapi.c
dlls/iphlpapi/tests/iphlpapi.c
+68
-48
No files found.
dlls/iphlpapi/iphlpapi_main.c
View file @
0515480d
...
...
@@ -2182,51 +2182,100 @@ DWORD WINAPI AllocateAndGetIpAddrTableFromStack( MIB_IPADDRTABLE **table, BOOL s
return
err
;
}
static
int
ipforward_row_cmp
(
const
void
*
a
,
const
void
*
b
)
{
const
MIB_IPFORWARDROW
*
rowA
=
a
;
const
MIB_IPFORWARDROW
*
rowB
=
b
;
int
ret
;
if
((
ret
=
rowA
->
dwForwardDest
-
rowB
->
dwForwardDest
)
!=
0
)
return
ret
;
if
((
ret
=
rowA
->
u2
.
dwForwardProto
-
rowB
->
u2
.
dwForwardProto
)
!=
0
)
return
ret
;
if
((
ret
=
rowA
->
dwForwardPolicy
-
rowB
->
dwForwardPolicy
)
!=
0
)
return
ret
;
return
rowA
->
dwForwardNextHop
-
rowB
->
dwForwardNextHop
;
}
/******************************************************************
* GetIpForwardTable (IPHLPAPI.@)
*
* Get the route table.
*
* PARAMS
*
pIpForwardTable
[Out] buffer for route table
*
pdwSize
[In/Out] length of output buffer
*
bOrder
[In] whether to sort the table
*
table
[Out] buffer for route table
*
size
[In/Out] length of output buffer
*
sort
[In] whether to sort the table
*
* RETURNS
* Success: NO_ERROR
* Failure: error code from winerror.h
*
* NOTES
* If pdwSize is less than required, the function will return
* ERROR_INSUFFICIENT_BUFFER, and *pdwSize will be set to the required byte
* size.
* If bOrder is true, the returned table will be sorted by the next hop and
* an assortment of arbitrary parameters.
*/
DWORD
WINAPI
GetIpForwardTable
(
PMIB_IPFORWARDTABLE
pIpForwardTable
,
PULONG
pdwSize
,
BOOL
bOrder
)
DWORD
WINAPI
GetIpForwardTable
(
MIB_IPFORWARDTABLE
*
table
,
ULONG
*
size
,
BOOL
sort
)
{
DWORD
ret
;
PMIB_IPFORWARDTABLE
table
;
DWORD
err
,
count
,
uni_count
,
needed
,
i
,
addr
;
struct
nsi_ipv4_forward_key
*
keys
;
struct
nsi_ip_forward_rw
*
rw
;
struct
nsi_ipv4_forward_dynamic
*
dyn
;
struct
nsi_ip_forward_static
*
stat
;
struct
nsi_ipv4_unicast_key
*
uni_keys
=
NULL
;
TRACE
(
"pIpForwardTable %p, pdwSize %p, bOrder %d
\n
"
,
pIpForwardTable
,
pdwSize
,
bOrder
);
TRACE
(
"table %p, size %p, sort %d
\n
"
,
table
,
size
,
sort
);
if
(
!
size
)
return
ERROR_INVALID_PARAMETER
;
if
(
!
pdwSize
)
return
ERROR_INVALID_PARAMETER
;
err
=
NsiAllocateAndGetTable
(
1
,
&
NPI_MS_IPV4_MODULEID
,
NSI_IP_FORWARD_TABLE
,
(
void
**
)
&
keys
,
sizeof
(
*
keys
),
(
void
**
)
&
rw
,
sizeof
(
*
rw
),
(
void
**
)
&
dyn
,
sizeof
(
*
dyn
),
(
void
**
)
&
stat
,
sizeof
(
*
stat
),
&
count
,
0
);
if
(
err
)
return
err
;
ret
=
AllocateAndGetIpForwardTableFromStack
(
&
table
,
bOrder
,
GetProcessHeap
(),
0
);
if
(
!
ret
)
{
DWORD
size
=
FIELD_OFFSET
(
MIB_IPFORWARDTABLE
,
table
[
table
->
dwNumEntries
]
);
if
(
!
pIpForwardTable
||
*
pdwSize
<
size
)
{
*
pdwSize
=
size
;
ret
=
ERROR_INSUFFICIENT_BUFFER
;
}
else
{
*
pdwSize
=
size
;
memcpy
(
pIpForwardTable
,
table
,
size
);
}
HeapFree
(
GetProcessHeap
(),
0
,
table
);
needed
=
FIELD_OFFSET
(
MIB_IPFORWARDTABLE
,
table
[
count
]
);
if
(
!
table
||
*
size
<
needed
)
{
*
size
=
needed
;
err
=
ERROR_INSUFFICIENT_BUFFER
;
goto
err
;
}
TRACE
(
"returning %d
\n
"
,
ret
);
return
ret
;
err
=
NsiAllocateAndGetTable
(
1
,
&
NPI_MS_IPV4_MODULEID
,
NSI_IP_UNICAST_TABLE
,
(
void
**
)
&
uni_keys
,
sizeof
(
*
uni_keys
),
NULL
,
0
,
NULL
,
0
,
NULL
,
0
,
&
uni_count
,
0
);
if
(
err
)
goto
err
;
table
->
dwNumEntries
=
count
;
for
(
i
=
0
;
i
<
count
;
i
++
)
{
MIB_IPFORWARDROW
*
row
=
table
->
table
+
i
;
row
->
dwForwardDest
=
keys
[
i
].
prefix
.
WS_s_addr
;
ConvertLengthToIpv4Mask
(
keys
[
i
].
prefix_len
,
&
row
->
dwForwardMask
);
row
->
dwForwardPolicy
=
0
;
row
->
dwForwardNextHop
=
keys
[
i
].
next_hop
.
WS_s_addr
;
row
->
u1
.
dwForwardType
=
row
->
dwForwardNextHop
?
MIB_IPROUTE_TYPE_INDIRECT
:
MIB_IPROUTE_TYPE_DIRECT
;
if
(
!
row
->
dwForwardNextHop
)
/* find the interface's addr */
{
for
(
addr
=
0
;
addr
<
uni_count
;
addr
++
)
{
if
(
uni_keys
[
addr
].
luid
.
Value
==
keys
[
i
].
luid
.
Value
)
{
row
->
dwForwardNextHop
=
uni_keys
[
addr
].
addr
.
WS_s_addr
;
break
;
}
}
}
row
->
dwForwardIfIndex
=
stat
[
i
].
if_index
;
row
->
u2
.
dwForwardProto
=
rw
[
i
].
protocol
;
row
->
dwForwardAge
=
dyn
[
i
].
age
;
row
->
dwForwardNextHopAS
=
0
;
row
->
dwForwardMetric1
=
rw
[
i
].
metric
;
/* FIXME: add interface metric */
row
->
dwForwardMetric2
=
0
;
row
->
dwForwardMetric3
=
0
;
row
->
dwForwardMetric4
=
0
;
row
->
dwForwardMetric5
=
0
;
}
if
(
sort
)
qsort
(
table
->
table
,
count
,
sizeof
(
MIB_IPFORWARDROW
),
ipforward_row_cmp
);
err:
NsiFreeTable
(
uni_keys
,
NULL
,
NULL
,
NULL
);
NsiFreeTable
(
keys
,
rw
,
dyn
,
stat
);
return
err
;
}
static
void
forward_row2_fill
(
MIB_IPFORWARD_ROW2
*
row
,
USHORT
fam
,
void
*
key
,
struct
nsi_ip_forward_rw
*
rw
,
...
...
dlls/iphlpapi/tests/iphlpapi.c
View file @
0515480d
...
...
@@ -286,63 +286,83 @@ static void testGetIfTable(void)
static
void
testGetIpForwardTable
(
void
)
{
DWORD
apiReturn
;
ULONG
dwSize
=
0
;
DWORD
err
,
i
,
j
;
ULONG
size
=
0
;
MIB_IPFORWARDTABLE
*
buf
;
MIB_IPFORWARD_TABLE2
*
table2
;
MIB_UNICASTIPADDRESS_TABLE
*
unicast
;
apiReturn
=
GetIpForwardTable
(
NULL
,
NULL
,
FALSE
);
if
(
apiReturn
==
ERROR_NOT_SUPPORTED
)
{
skip
(
"GetIpForwardTable is not supported
\n
"
);
return
;
}
ok
(
apiReturn
==
ERROR_INVALID_PARAMETER
,
"GetIpForwardTable(NULL, NULL, FALSE) returned %d, expected ERROR_INVALID_PARAMETER
\n
"
,
apiReturn
);
apiReturn
=
GetIpForwardTable
(
NULL
,
&
dwSize
,
FALSE
);
ok
(
apiReturn
==
ERROR_INSUFFICIENT_BUFFER
,
"GetIpForwardTable(NULL, &dwSize, FALSE) returned %d, expected ERROR_INSUFFICIENT_BUFFER
\n
"
,
apiReturn
);
if
(
apiReturn
==
ERROR_INSUFFICIENT_BUFFER
)
{
PMIB_IPFORWARDTABLE
buf
=
HeapAlloc
(
GetProcessHeap
(),
0
,
dwSize
);
err
=
GetIpForwardTable
(
NULL
,
NULL
,
FALSE
);
ok
(
err
==
ERROR_INVALID_PARAMETER
,
"got %d
\n
"
,
err
);
apiReturn
=
GetIpForwardTable
(
buf
,
&
dwSize
,
FALSE
);
ok
(
apiReturn
==
NO_ERROR
,
"GetIpForwardTable(buf, &dwSize, FALSE) returned %d, expected NO_ERROR
\n
"
,
apiReturn
);
err
=
GetIpForwardTable
(
NULL
,
&
size
,
FALSE
);
ok
(
err
==
ERROR_INSUFFICIENT_BUFFER
,
"got %d
\n
"
,
err
);
if
(
apiReturn
==
NO_ERROR
)
{
DWORD
i
;
buf
=
malloc
(
size
);
err
=
GetIpForwardTable
(
buf
,
&
size
,
FALSE
);
ok
(
!
err
,
"got %d
\n
"
,
err
)
;
trace
(
"IP forward table: %u entries
\n
"
,
buf
->
dwNumEntries
);
for
(
i
=
0
;
i
<
buf
->
dwNumEntries
;
i
++
)
err
=
GetIpForwardTable2
(
AF_INET
,
&
table2
);
ok
(
!
err
,
"got %d
\n
"
,
err
);
ok
(
buf
->
dwNumEntries
==
table2
->
NumEntries
,
"got %d vs %d
\n
"
,
buf
->
dwNumEntries
,
table2
->
NumEntries
);
err
=
GetUnicastIpAddressTable
(
AF_INET
,
&
unicast
);
ok
(
!
err
,
"got %d
\n
"
,
err
);
trace
(
"IP forward table: %u entries
\n
"
,
buf
->
dwNumEntries
);
for
(
i
=
0
;
i
<
buf
->
dwNumEntries
;
i
++
)
{
MIB_IPFORWARDROW
*
row
=
buf
->
table
+
i
;
MIB_IPFORWARD_ROW2
*
row2
=
table2
->
Table
+
i
;
DWORD
mask
,
next_hop
;
winetest_push_context
(
"%d"
,
i
);
trace
(
"dest %s mask %s gw %s if %u type %u proto %u
\n
"
,
ntoa
(
row
->
dwForwardDest
),
ntoa
(
row
->
dwForwardMask
),
ntoa
(
row
->
dwForwardNextHop
),
row
->
dwForwardIfIndex
,
row
->
dwForwardType
,
row
->
dwForwardProto
);
ok
(
row
->
dwForwardDest
==
row2
->
DestinationPrefix
.
Prefix
.
Ipv4
.
sin_addr
.
s_addr
,
"got %08x vs %08x
\n
"
,
row
->
dwForwardDest
,
row2
->
DestinationPrefix
.
Prefix
.
Ipv4
.
sin_addr
.
s_addr
);
ConvertLengthToIpv4Mask
(
row2
->
DestinationPrefix
.
PrefixLength
,
&
mask
);
ok
(
row
->
dwForwardMask
==
mask
,
"got %08x vs %08x
\n
"
,
row
->
dwForwardMask
,
mask
);
ok
(
row
->
dwForwardPolicy
==
0
,
"got %d
\n
"
,
row
->
dwForwardPolicy
);
next_hop
=
row2
->
NextHop
.
Ipv4
.
sin_addr
.
s_addr
;
if
(
!
next_hop
)
/* for direct addresses, dwForwardNextHop is set to the address of the appropriate interface */
{
for
(
j
=
0
;
j
<
unicast
->
NumEntries
;
j
++
)
{
if
(
!
U1
(
buf
->
table
[
i
]).
dwForwardDest
)
/* Default route */
{
todo_wine
ok
(
U1
(
buf
->
table
[
i
]).
dwForwardProto
==
MIB_IPPROTO_NETMGMT
,
"Unexpected dwForwardProto %d
\n
"
,
U1
(
buf
->
table
[
i
]).
dwForwardProto
);
ok
(
U1
(
buf
->
table
[
i
]).
dwForwardType
==
MIB_IPROUTE_TYPE_INDIRECT
,
"Unexpected dwForwardType %d
\n
"
,
U1
(
buf
->
table
[
i
]).
dwForwardType
);
}
else
if
(
unicast
->
Table
[
j
].
InterfaceLuid
.
Value
==
row2
->
InterfaceLuid
.
Value
)
{
/* In general we should get MIB_IPPROTO_LOCAL but does not work
* for Vista, 2008 and 7. */
ok
(
U1
(
buf
->
table
[
i
]).
dwForwardProto
==
MIB_IPPROTO_LOCAL
||
broken
(
U1
(
buf
->
table
[
i
]).
dwForwardProto
==
MIB_IPPROTO_NETMGMT
),
"Unexpected dwForwardProto %d
\n
"
,
U1
(
buf
->
table
[
i
]).
dwForwardProto
);
/* The forward type varies depending on the address and gateway
* value so it is not worth testing in this case. */
next_hop
=
unicast
->
Table
[
j
].
Address
.
Ipv4
.
sin_addr
.
s_addr
;
break
;
}
trace
(
"%u: dest %s mask %s gw %s if %u type %u proto %u
\n
"
,
i
,
ntoa
(
buf
->
table
[
i
].
dwForwardDest
),
ntoa
(
buf
->
table
[
i
].
dwForwardMask
),
ntoa
(
buf
->
table
[
i
].
dwForwardNextHop
),
buf
->
table
[
i
].
dwForwardIfIndex
,
U1
(
buf
->
table
[
i
]).
dwForwardType
,
U1
(
buf
->
table
[
i
]).
dwForwardProto
);
}
}
HeapFree
(
GetProcessHeap
(),
0
,
buf
);
}
ok
(
row
->
dwForwardNextHop
==
next_hop
,
"got %08x vs %08x
\n
"
,
row
->
dwForwardNextHop
,
next_hop
);
ok
(
row
->
dwForwardIfIndex
==
row2
->
InterfaceIndex
,
"got %d vs %d
\n
"
,
row
->
dwForwardIfIndex
,
row2
->
InterfaceIndex
);
if
(
!
row2
->
NextHop
.
Ipv4
.
sin_addr
.
s_addr
)
ok
(
buf
->
table
[
i
].
dwForwardType
==
MIB_IPROUTE_TYPE_DIRECT
,
"got %d
\n
"
,
buf
->
table
[
i
].
dwForwardType
);
else
ok
(
buf
->
table
[
i
].
dwForwardType
==
MIB_IPROUTE_TYPE_INDIRECT
,
"got %d
\n
"
,
buf
->
table
[
i
].
dwForwardType
);
ok
(
row
->
dwForwardProto
==
row2
->
Protocol
,
"got %d vs %d
\n
"
,
row
->
dwForwardProto
,
row2
->
Protocol
);
ok
(
row
->
dwForwardAge
==
row2
->
Age
,
"got %d vs %d
\n
"
,
row
->
dwForwardAge
,
row2
->
Age
);
ok
(
row
->
dwForwardNextHopAS
==
0
,
"got %08x
\n
"
,
row
->
dwForwardNextHopAS
);
/* FIXME: need to add the interface's metric from GetIpInterfaceTable() */
ok
(
row
->
dwForwardMetric1
>=
row2
->
Metric
,
"got %d vs %d
\n
"
,
row
->
dwForwardMetric1
,
row2
->
Metric
);
ok
(
row
->
dwForwardMetric2
==
0
,
"got %d
\n
"
,
row
->
dwForwardMetric2
);
ok
(
row
->
dwForwardMetric3
==
0
,
"got %d
\n
"
,
row
->
dwForwardMetric3
);
ok
(
row
->
dwForwardMetric4
==
0
,
"got %d
\n
"
,
row
->
dwForwardMetric4
);
ok
(
row
->
dwForwardMetric5
==
0
,
"got %d
\n
"
,
row
->
dwForwardMetric5
);
winetest_pop_context
();
}
FreeMibTable
(
unicast
);
FreeMibTable
(
table2
);
free
(
buf
);
}
static
void
testGetIpNetTable
(
void
)
...
...
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