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
c24fc00f
Commit
c24fc00f
authored
Aug 29, 2003
by
Juan Lang
Committed by
Alexandre Julliard
Aug 29, 2003
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
- improve WsControl error checking
- make WsControl output more closely match Win98's - document WsControl behavior a bit better
parent
ec42ea4d
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
405 additions
and
306 deletions
+405
-306
socket.c
dlls/wsock32/socket.c
+347
-235
wscontrol.h
dlls/wsock32/wscontrol.h
+58
-71
No files found.
dlls/wsock32/socket.c
View file @
c24fc00f
...
...
@@ -2,6 +2,7 @@
* WSOCK32 specific functions
*
* Copyright (C) 1993,1994,1996,1997 John Brezak, Erik Bos, Alex Korobka.
* Copyright (C) 2003 Juan Lang.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
...
...
@@ -81,22 +82,21 @@ INT WINAPI WS1_getsockopt(SOCKET s, INT level, INT optname, char *optval, INT *o
* From: "Peter Rindfuss" <rindfuss-s@medea.wz-berlin.de>
* Date: 1997/08/17
*
*
WSCNTL_TCPIP_QUERY_INFO option is partially impleme
ted based
*
The WSCNTL_TCPIP_QUERY_INFO option is partially implemen
ted based
* on observing the behaviour of WsControl with an app in
* Windows 98. It is not fully implemented, and there could
* be (are?) errors due to incorrect assumptions made.
*
*
* WsControl returns WSCTL_SUCCESS on success.
* STATUS_BUFFER_TOO_SMALL is returned if the output buffer length
* (*pcbResponseInfoLen) is too small, otherwise errors return -1.
*
* It doesn't seem to generate errors that can be retrieved by
* WSAGetLastError().
* ERROR_LOCK_VIOLATION is returned if the output buffer length
* (*pcbResponseInfoLen) is too small. This is an unusual error code, but
* it matches Win98's behavior. Other errors come from winerror.h, not from
* winsock.h. Again, this is to match Win98 behavior.
*
*/
DWORD
WINAPI
WsControl
(
DWORD
protocol
l
,
DWORD
WINAPI
WsControl
(
DWORD
protocol
,
DWORD
action
,
LPVOID
pRequestInfo
,
LPDWORD
pcbRequestInfoLen
,
...
...
@@ -108,288 +108,400 @@ DWORD WINAPI WsControl(DWORD protocoll,
rather than void */
TDIObjectID
*
pcommand
=
(
TDIObjectID
*
)
pRequestInfo
;
TRACE
(
" WsControl TOI_ID=>0x%lx<, {TEI_ENTITY=0x%lx, TEI_INSTANCE=0x%lx}, TOI_CLASS=0x%lx, TOI_TYPE=0x%lx
\n
"
,
pcommand
->
toi_id
,
pcommand
->
toi_entity
.
tei_entity
,
pcommand
->
toi_entity
.
tei_instance
,
pcommand
->
toi_class
,
pcommand
->
toi_type
);
/* validate input parameters. Error codes are from winerror.h, not from
* winsock.h. pcbResponseInfoLen is apparently allowed to be NULL for some
* commands, since winipcfg.exe fails if we ensure it's non-NULL in every
* case.
*/
if
(
protocol
!=
IPPROTO_TCP
)
return
ERROR_INVALID_PARAMETER
;
if
(
!
pcommand
)
return
ERROR_INVALID_PARAMETER
;
if
(
!
pcbRequestInfoLen
)
return
ERROR_INVALID_ACCESS
;
if
(
*
pcbRequestInfoLen
<
sizeof
(
TDIObjectID
))
return
ERROR_INVALID_ACCESS
;
if
(
!
pResponseInfo
)
return
ERROR_INVALID_PARAMETER
;
if
(
pcommand
->
toi_type
!=
INFO_TYPE_PROVIDER
)
return
ERROR_INVALID_PARAMETER
;
TRACE
(
" WsControl TOI_ID=>0x%lx<, {TEI_ENTITY=0x%lx, TEI_INSTANCE=0x%lx}, TOI_CLASS=0x%lx, TOI_TYPE=0x%lx
\n
"
,
pcommand
->
toi_id
,
pcommand
->
toi_entity
.
tei_entity
,
pcommand
->
toi_entity
.
tei_instance
,
pcommand
->
toi_class
,
pcommand
->
toi_type
);
switch
(
action
)
{
case
WSCNTL_TCPIP_QUERY_INFO
:
case
WSCNTL_TCPIP_QUERY_INFO
:
{
if
(
pcommand
->
toi_class
!=
INFO_CLASS_GENERIC
&&
pcommand
->
toi_class
!=
INFO_CLASS_PROTOCOL
)
{
switch
(
pcommand
->
toi_id
)
{
/*
ENTITY_LIST_ID seems to get number of adapters in the system.
(almost like an index to be used when calling other WsControl options)
*/
case
ENTITY_LIST_ID
:
{
TDIEntityID
*
baseptr
=
pResponseInfo
;
DWORD
numInt
,
i
,
ipAddrTableSize
;
PMIB_IPADDRTABLE
table
;
if
(
pcommand
->
toi_class
!=
INFO_CLASS_GENERIC
&&
pcommand
->
toi_type
!=
INFO_TYPE_PROVIDER
)
{
FIXME
(
"Unexpected Option for ENTITY_LIST_ID request -> toi_class=0x%lx, toi_type=0x%lx
\n
"
,
pcommand
->
toi_class
,
pcommand
->
toi_type
);
return
(
WSAEOPNOTSUPP
);
}
ERR
(
"Unexpected class %ld for WSCNTL_TCPIP_QUERY_INFO"
,
pcommand
->
toi_class
);
return
ERROR_BAD_ENVIRONMENT
;
}
GetNumberOfInterfaces
(
&
numInt
);
switch
(
pcommand
->
toi_id
)
{
/* ENTITY_LIST_ID gets the list of "entity IDs", where an entity
may represent an interface, or a datagram service, or address
translation, or other fun things. Typically an entity ID represents
a class of service, which is further queried for what type it is.
Different types will then have more specific queries defined.
*/
case
ENTITY_LIST_ID
:
{
TDIEntityID
*
baseptr
=
(
TDIEntityID
*
)
pResponseInfo
;
DWORD
numInt
,
i
,
ifTable
,
spaceNeeded
;
PMIB_IFTABLE
table
;
if
(
*
pcbResponseInfoLen
<
sizeof
(
TDIEntityID
)
*
(
numInt
*
2
)
)
{
return
(
STATUS_BUFFER_TOO_SMALL
);
}
if
(
!
pcbResponseInfoLen
)
return
ERROR_BAD_ENVIRONMENT
;
if
(
pcommand
->
toi_class
!=
INFO_CLASS_GENERIC
)
{
FIXME
(
"Unexpected Option for ENTITY_LIST_ID request -> toi_class=0x%lx"
,
pcommand
->
toi_class
);
return
(
ERROR_BAD_ENVIRONMENT
);
}
/* expect a 1:1 correspondence between interfaces and IP
addresses, so use the cheaper (less memory allocated)
GetIpAddrTable rather than GetIfTable */
ipAddrTableSize
=
0
;
GetIpAddrTable
(
NULL
,
&
ipAddrTableSize
,
FALSE
);
table
=
(
PMIB_IPADDRTABLE
)
calloc
(
1
,
ipAddrTableSize
);
if
(
!
table
)
return
-
1
;
/* FIXME: better error code */
GetIpAddrTable
(
table
,
&
ipAddrTableSize
,
FALSE
);
GetNumberOfInterfaces
(
&
numInt
);
spaceNeeded
=
sizeof
(
TDIEntityID
)
*
(
numInt
+
4
);
/* 0 it out first */
memset
(
baseptr
,
0
,
sizeof
(
TDIEntityID
)
*
(
table
->
dwNumEntries
*
2
)
);
if
(
*
pcbResponseInfoLen
<
spaceNeeded
)
return
(
ERROR_LOCK_VIOLATION
);
for
(
i
=
0
;
i
<
table
->
dwNumEntries
;
i
++
)
{
/* tei_instance is an network interface identifier.
I'm not quite sure what the difference is between tei_entity values of
CL_NL_ENTITY and IF_ENTITY */
baseptr
->
tei_entity
=
CL_NL_ENTITY
;
baseptr
->
tei_instance
=
table
->
table
[
i
].
dwIndex
;
baseptr
++
;
baseptr
->
tei_entity
=
IF_ENTITY
;
baseptr
->
tei_instance
=
table
->
table
[
i
].
dwIndex
;
baseptr
++
;
}
ifTable
=
0
;
GetIfTable
(
NULL
,
&
ifTable
,
FALSE
);
table
=
(
PMIB_IFTABLE
)
calloc
(
1
,
ifTable
);
if
(
!
table
)
return
ERROR_NOT_ENOUGH_MEMORY
;
GetIfTable
(
table
,
&
ifTable
,
FALSE
);
/* Calculate size of out buffer */
*
pcbResponseInfoLen
=
sizeof
(
TDIEntityID
)
*
(
table
->
dwNumEntries
*
2
);
spaceNeeded
=
sizeof
(
TDIEntityID
)
*
(
table
->
dwNumEntries
+
4
);
if
(
*
pcbResponseInfoLen
<
spaceNeeded
)
{
free
(
table
);
break
;
return
(
ERROR_LOCK_VIOLATION
);
}
memset
(
baseptr
,
0
,
spaceNeeded
);
/* ENTITY_TYPE_ID is used to obtain simple information about a
network card, such as MAC Address, description, interface type,
number of network addresses, etc. */
case
ENTITY_TYPE_ID
:
/* ALSO: IP_MIB_STATS_ID */
for
(
i
=
0
;
i
<
table
->
dwNumEntries
;
i
++
)
{
if
(
pcommand
->
toi_class
==
INFO_CLASS_GENERIC
&&
pcommand
->
toi_type
==
INFO_TYPE_PROVIDER
)
/* Return IF_GENERIC on every interface, and AT_ENTITY,
* CL_NL_ENTITY, CL_TL_ENTITY, and CO_TL_ENTITY on the first
* interface. MS returns them only on the loopback
* interface, but it doesn't seem to matter.
*/
if
(
i
==
0
)
{
if
(
pcommand
->
toi_entity
.
tei_entity
==
IF_ENTITY
)
{
*
((
ULONG
*
)
pResponseInfo
)
=
IF_MIB
;
baseptr
->
tei_entity
=
CO_TL_ENTITY
;
baseptr
->
tei_instance
=
table
->
table
[
i
].
dwIndex
;
baseptr
++
;
baseptr
->
tei_entity
=
CL_TL_ENTITY
;
baseptr
->
tei_instance
=
table
->
table
[
i
].
dwIndex
;
baseptr
++
;
baseptr
->
tei_entity
=
CL_NL_ENTITY
;
baseptr
->
tei_instance
=
table
->
table
[
i
].
dwIndex
;
baseptr
++
;
baseptr
->
tei_entity
=
AT_ENTITY
;
baseptr
->
tei_instance
=
table
->
table
[
i
].
dwIndex
;
baseptr
++
;
}
baseptr
->
tei_entity
=
IF_GENERIC
;
baseptr
->
tei_instance
=
table
->
table
[
i
].
dwIndex
;
baseptr
++
;
}
/* Calculate size of out buffer */
*
pcbResponseInfoLen
=
sizeof
(
ULONG
);
*
pcbResponseInfoLen
=
spaceNeeded
;
free
(
table
);
}
else
if
(
pcommand
->
toi_entity
.
tei_entity
==
CL_NL_ENTITY
)
{
*
((
ULONG
*
)
pResponseInfo
)
=
CL_NL_IP
;
break
;
}
/* Calculate size of out buffer */
*
pcbResponseInfoLen
=
sizeof
(
ULONG
);
}
/* Returns MIB-II statistics for an interface */
case
ENTITY_TYPE_ID
:
switch
(
pcommand
->
toi_entity
.
tei_entity
)
{
case
IF_GENERIC
:
if
(
pcommand
->
toi_class
==
INFO_CLASS_GENERIC
)
{
if
(
!
pcbResponseInfoLen
)
return
ERROR_BAD_ENVIRONMENT
;
*
((
ULONG
*
)
pResponseInfo
)
=
IF_MIB
;
*
pcbResponseInfoLen
=
sizeof
(
ULONG
);
}
else
if
(
pcommand
->
toi_class
==
INFO_CLASS_PROTOCOL
&&
pcommand
->
toi_type
==
INFO_TYPE_PROVIDER
)
else
if
(
pcommand
->
toi_class
==
INFO_CLASS_PROTOCOL
)
{
if
(
pcommand
->
toi_entity
.
tei_entity
==
IF_ENTITY
)
MIB_IFROW
row
;
DWORD
index
=
pcommand
->
toi_entity
.
tei_instance
,
ret
;
DWORD
size
=
sizeof
(
row
)
-
sizeof
(
row
.
wszName
)
-
sizeof
(
row
.
bDescr
);
if
(
!
pcbResponseInfoLen
)
return
ERROR_BAD_ENVIRONMENT
;
if
(
*
pcbResponseInfoLen
<
size
)
return
(
ERROR_LOCK_VIOLATION
);
row
.
dwIndex
=
index
;
ret
=
GetIfEntry
(
&
row
);
if
(
ret
!=
NO_ERROR
)
{
MIB_IFROW
row
;
DWORD
index
=
pcommand
->
toi_entity
.
tei_instance
,
ret
;
DWORD
size
=
sizeof
(
row
)
-
sizeof
(
row
.
wszName
)
-
sizeof
(
row
.
bDescr
);
if
(
*
pcbResponseInfoLen
<
size
)
{
return
(
STATUS_BUFFER_TOO_SMALL
);
}
row
.
dwIndex
=
index
;
ret
=
GetIfEntry
(
&
row
);
if
(
ret
!=
NO_ERROR
)
{
ERR
(
"Error retrieving data for interface index %lu
\n
"
,
index
);
return
-
1
;
/* FIXME: better error code */
}
size
=
sizeof
(
row
)
-
sizeof
(
row
.
wszName
)
-
sizeof
(
row
.
bDescr
)
+
row
.
dwDescrLen
;
if
(
*
pcbResponseInfoLen
<
size
)
{
return
(
STATUS_BUFFER_TOO_SMALL
);
}
memcpy
(
pResponseInfo
,
&
row
.
dwIndex
,
size
);
*
pcbResponseInfoLen
=
size
;
ERR
(
"Error retrieving data for interface index %lu
\n
"
,
index
);
return
ret
;
}
else
if
(
pcommand
->
toi_entity
.
tei_entity
==
CL_NL_ENTITY
)
{
/* This case is used to obtain general statistics about the
network */
if
(
*
pcbResponseInfoLen
<
sizeof
(
MIB_IPSTATS
))
{
return
(
STATUS_BUFFER_TOO_SMALL
);
}
GetIpStatistics
((
PMIB_IPSTATS
)
pResponseInfo
);
size
=
sizeof
(
row
)
-
sizeof
(
row
.
wszName
)
-
sizeof
(
row
.
bDescr
)
+
row
.
dwDescrLen
;
if
(
*
pcbResponseInfoLen
<
size
)
return
(
ERROR_LOCK_VIOLATION
);
memcpy
(
pResponseInfo
,
&
row
.
dwIndex
,
size
);
*
pcbResponseInfoLen
=
size
;
}
break
;
/* Calculate size of out buffer */
*
pcbResponseInfoLen
=
sizeof
(
MIB_IPSTATS
);
}
/* Returns address-translation related data. In our case, this is
* ARP.
* FIXME: Win98 seems to assume ARP will always be on interface
* index 1, so arp.exe fails when this isn't the case.
*/
case
AT_ENTITY
:
if
(
pcommand
->
toi_class
==
INFO_CLASS_GENERIC
)
{
if
(
!
pcbResponseInfoLen
)
return
ERROR_BAD_ENVIRONMENT
;
*
((
ULONG
*
)
pResponseInfo
)
=
AT_ARP
;
*
pcbResponseInfoLen
=
sizeof
(
ULONG
);
}
else
else
if
(
pcommand
->
toi_class
==
INFO_CLASS_PROTOCOL
)
{
FIXME
(
"Unexpected Option for ENTITY_TYPE_ID request -> toi_class=0x%lx, toi_type=0x%lx
\n
"
,
pcommand
->
toi_class
,
pcommand
->
toi_type
);
return
(
WSAEOPNOTSUPP
);
PMIB_IPNETTABLE
table
;
DWORD
size
;
PULONG
output
=
(
PULONG
)
pResponseInfo
;
if
(
!
pcbResponseInfoLen
)
return
ERROR_BAD_ENVIRONMENT
;
if
(
*
pcbResponseInfoLen
<
sizeof
(
ULONG
)
*
2
)
return
(
ERROR_LOCK_VIOLATION
);
GetIpNetTable
(
NULL
,
&
size
,
FALSE
);
table
=
(
PMIB_IPNETTABLE
)
calloc
(
1
,
size
);
if
(
!
table
)
return
ERROR_NOT_ENOUGH_MEMORY
;
GetIpNetTable
(
table
,
&
size
,
FALSE
);
/* FIXME: I don't understand the meaning of the ARP output
* very well, but it seems to indicate how many ARP entries
* exist. I don't know whether this should reflect the
* number per interface, as I'm only testing with a single
* interface. So, I lie and say all ARP entries exist on
* a single interface--the first one that appears in the
* ARP table.
*/
*
(
output
++
)
=
table
->
dwNumEntries
;
*
output
=
table
->
table
[
0
].
dwIndex
;
free
(
table
);
*
pcbResponseInfoLen
=
sizeof
(
ULONG
)
*
2
;
}
break
;
}
/* Returns connectionless network layer statistics--in our case,
* this is IP.
*/
case
CL_NL_ENTITY
:
if
(
pcommand
->
toi_class
==
INFO_CLASS_GENERIC
)
{
if
(
!
pcbResponseInfoLen
)
return
ERROR_BAD_ENVIRONMENT
;
*
((
ULONG
*
)
pResponseInfo
)
=
CL_NL_IP
;
*
pcbResponseInfoLen
=
sizeof
(
ULONG
);
}
else
if
(
pcommand
->
toi_class
==
INFO_CLASS_PROTOCOL
)
{
if
(
!
pcbResponseInfoLen
)
return
ERROR_BAD_ENVIRONMENT
;
if
(
*
pcbResponseInfoLen
<
sizeof
(
MIB_IPSTATS
))
return
ERROR_LOCK_VIOLATION
;
GetIpStatistics
((
PMIB_IPSTATS
)
pResponseInfo
);
/* IP_MIB_ADDRTABLE_ENTRY_ID is used to obtain more detailed information about a
particular network adapter */
case
IP_MIB_ADDRTABLE_ENTRY_ID
:
{
DWORD
index
=
pcommand
->
toi_entity
.
tei_instance
;
PMIB_IPADDRROW
baseIPInfo
=
(
PMIB_IPADDRROW
)
pResponseInfo
;
PMIB_IPADDRTABLE
table
;
DWORD
tableSize
,
i
;
*
pcbResponseInfoLen
=
sizeof
(
MIB_IPSTATS
);
}
break
;
if
(
*
pcbResponseInfoLen
<
sizeof
(
MIB_IPADDRROW
))
/* Returns connectionless transport layer statistics--in our case,
* this is UDP.
*/
case
CL_TL_ENTITY
:
if
(
pcommand
->
toi_class
==
INFO_CLASS_GENERIC
)
{
return
(
STATUS_BUFFER_TOO_SMALL
);
if
(
!
pcbResponseInfoLen
)
return
ERROR_BAD_ENVIRONMENT
;
*
((
ULONG
*
)
pResponseInfo
)
=
CL_TL_UDP
;
*
pcbResponseInfoLen
=
sizeof
(
ULONG
);
}
/* overkill, get entire table, because there isn't an
exported function that gets just one entry, and don't
necessarily want our own private export. */
tableSize
=
0
;
GetIpAddrTable
(
NULL
,
&
tableSize
,
FALSE
);
table
=
(
PMIB_IPADDRTABLE
)
calloc
(
1
,
tableSize
);
if
(
!
table
)
return
-
1
;
/* FIXME: better error code */
GetIpAddrTable
(
table
,
&
tableSize
,
FALSE
);
for
(
i
=
0
;
i
<
table
->
dwNumEntries
;
i
++
)
else
if
(
pcommand
->
toi_class
==
INFO_CLASS_PROTOCOL
)
{
if
(
table
->
table
[
i
].
dwIndex
==
index
)
{
memcpy
(
baseIPInfo
,
&
table
->
table
[
i
],
sizeof
(
MIB_IPADDRROW
))
;
break
;
}
if
(
!
pcbResponseInfoLen
)
return
ERROR_BAD_ENVIRONMENT
;
if
(
*
pcbResponseInfoLen
<
sizeof
(
MIB_UDPSTATS
))
return
ERROR_LOCK_VIOLATION
;
GetUdpStatistics
((
PMIB_UDPSTATS
)
pResponseInfo
)
;
*
pcbResponseInfoLen
=
sizeof
(
MIB_UDPSTATS
);
}
free
(
table
);
/************************************************************************/
break
;
/* Calculate size of out buffer */
*
pcbResponseInfoLen
=
sizeof
(
MIB_IPADDRROW
);
/* Returns connection-oriented transport layer statistics--in our
* case, this is TCP.
*/
case
CO_TL_ENTITY
:
if
(
pcommand
->
toi_class
==
INFO_CLASS_GENERIC
)
{
if
(
!
pcbResponseInfoLen
)
return
ERROR_BAD_ENVIRONMENT
;
*
((
ULONG
*
)
pResponseInfo
)
=
CO_TL_TCP
;
*
pcbResponseInfoLen
=
sizeof
(
ULONG
);
}
else
if
(
pcommand
->
toi_class
==
INFO_CLASS_PROTOCOL
)
{
if
(
!
pcbResponseInfoLen
)
return
ERROR_BAD_ENVIRONMENT
;
if
(
*
pcbResponseInfoLen
<
sizeof
(
MIB_TCPSTATS
))
return
ERROR_LOCK_VIOLATION
;
GetTcpStatistics
((
PMIB_TCPSTATS
)
pResponseInfo
);
*
pcbResponseInfoLen
=
sizeof
(
MIB_TCPSTATS
);
}
break
;
}
default:
ERR
(
"Unknown entity %ld for ENTITY_TYPE_ID query"
,
pcommand
->
toi_entity
.
tei_entity
);
}
break
;
/* This call returns the routing table.
* No official documentation found, even the name of the command is unknown.
* Work is based on
* http://www.cyberport.com/~tangent/programming/winsock/articles/wscontrol.html
* and testings done with winipcfg.exe, route.exe and ipconfig.exe.
* pcommand->toi_entity.tei_instance seems to be the interface number
* but route.exe outputs only the information for the last interface
* if only the routes for the pcommand->toi_entity.tei_instance
* interface are returned. */
case
IP_MIB_ROUTETABLE_ENTRY_ID
:
/* FIXME: not real name. Value is 0x101 */
/* This call returns the IP address, subnet mask, and broadcast
* address for an interface. If there are multiple IP addresses for
* the interface with the given index, returns the "first" one.
*/
case
IP_MIB_ADDRTABLE_ENTRY_ID
:
{
DWORD
index
=
pcommand
->
toi_entity
.
tei_instance
;
PMIB_IPADDRROW
baseIPInfo
=
(
PMIB_IPADDRROW
)
pResponseInfo
;
PMIB_IPADDRTABLE
table
;
DWORD
tableSize
,
i
;
if
(
!
pcbResponseInfoLen
)
return
ERROR_BAD_ENVIRONMENT
;
if
(
*
pcbResponseInfoLen
<
sizeof
(
MIB_IPADDRROW
))
return
(
ERROR_LOCK_VIOLATION
);
/* get entire table, because there isn't an exported function that
gets just one entry. */
tableSize
=
0
;
GetIpAddrTable
(
NULL
,
&
tableSize
,
FALSE
);
table
=
(
PMIB_IPADDRTABLE
)
calloc
(
1
,
tableSize
);
if
(
!
table
)
return
ERROR_NOT_ENOUGH_MEMORY
;
GetIpAddrTable
(
table
,
&
tableSize
,
FALSE
);
for
(
i
=
0
;
i
<
table
->
dwNumEntries
;
i
++
)
{
DWORD
routeTableSize
,
numRoutes
,
ndx
;
PMIB_IPFORWARDTABLE
table
;
IPRouteEntry
*
winRouteTable
=
(
IPRouteEntry
*
)
pResponseInfo
;
GetIpForwardTable
(
NULL
,
&
routeTableSize
,
FALSE
);
numRoutes
=
min
(
routeTableSize
-
sizeof
(
MIB_IPFORWARDTABLE
),
0
)
/
sizeof
(
MIB_IPFORWARDROW
)
+
1
;
if
(
*
pcbResponseInfoLen
<
sizeof
(
IPRouteEntry
)
*
numRoutes
)
{
return
(
STATUS_BUFFER_TOO_SMALL
);
}
table
=
(
PMIB_IPFORWARDTABLE
)
calloc
(
1
,
routeTableSize
);
if
(
!
table
)
return
-
1
;
/* FIXME: better return value */
GetIpForwardTable
(
table
,
&
routeTableSize
,
FALSE
);
memset
(
pResponseInfo
,
0
,
sizeof
(
IPRouteEntry
)
*
numRoutes
);
for
(
ndx
=
0
;
ndx
<
table
->
dwNumEntries
;
ndx
++
)
{
winRouteTable
->
ire_addr
=
table
->
table
[
ndx
].
dwForwardDest
;
winRouteTable
->
ire_index
=
table
->
table
[
ndx
].
dwForwardIfIndex
;
winRouteTable
->
ire_metric
=
table
->
table
[
ndx
].
dwForwardMetric1
;
/* winRouteTable->ire_option4 =
winRouteTable->ire_option5 =
winRouteTable->ire_option6 = */
winRouteTable
->
ire_gw
=
table
->
table
[
ndx
].
dwForwardNextHop
;
/* winRouteTable->ire_option8 =
winRouteTable->ire_option9 =
winRouteTable->ire_option10 = */
winRouteTable
->
ire_mask
=
table
->
table
[
ndx
].
dwForwardMask
;
/* winRouteTable->ire_option12 = */
winRouteTable
++
;
}
/* calculate the length of the data in the output buffer */
*
pcbResponseInfoLen
=
sizeof
(
IPRouteEntry
)
*
table
->
dwNumEntries
;
free
(
table
);
break
;
if
(
table
->
table
[
i
].
dwIndex
==
index
)
{
memcpy
(
baseIPInfo
,
&
table
->
table
[
i
],
sizeof
(
MIB_IPADDRROW
));
break
;
}
}
free
(
table
);
*
pcbResponseInfoLen
=
sizeof
(
MIB_IPADDRROW
);
break
;
}
default:
/* This call returns the routing table.
* No official documentation found, even the name of the command is unknown.
* Work is based on
* http://www.cyberport.com/~tangent/programming/winsock/articles/wscontrol.html
* and testings done with winipcfg.exe, route.exe and ipconfig.exe.
* pcommand->toi_entity.tei_instance seems to be the interface number
* but route.exe outputs only the information for the last interface
* if only the routes for the pcommand->toi_entity.tei_instance
* interface are returned. */
case
IP_MIB_ROUTETABLE_ENTRY_ID
:
/* FIXME: not real name. Value is 0x101 */
{
DWORD
routeTableSize
,
numRoutes
,
ndx
;
PMIB_IPFORWARDTABLE
table
;
IPRouteEntry
*
winRouteTable
=
(
IPRouteEntry
*
)
pResponseInfo
;
if
(
!
pcbResponseInfoLen
)
return
ERROR_BAD_ENVIRONMENT
;
GetIpForwardTable
(
NULL
,
&
routeTableSize
,
FALSE
);
numRoutes
=
min
(
routeTableSize
-
sizeof
(
MIB_IPFORWARDTABLE
),
0
)
/
sizeof
(
MIB_IPFORWARDROW
)
+
1
;
if
(
*
pcbResponseInfoLen
<
sizeof
(
IPRouteEntry
)
*
numRoutes
)
return
(
ERROR_LOCK_VIOLATION
);
table
=
(
PMIB_IPFORWARDTABLE
)
calloc
(
1
,
routeTableSize
);
if
(
!
table
)
return
ERROR_NOT_ENOUGH_MEMORY
;
GetIpForwardTable
(
table
,
&
routeTableSize
,
FALSE
);
memset
(
pResponseInfo
,
0
,
sizeof
(
IPRouteEntry
)
*
numRoutes
);
for
(
ndx
=
0
;
ndx
<
table
->
dwNumEntries
;
ndx
++
)
{
FIXME
(
"Command ID Not Supported -> toi_id=0x%lx, toi_entity={tei_entity=0x%lx, tei_instance=0x%lx}, toi_class=0x%lx, toi_type=0x%lx
\n
"
,
pcommand
->
toi_id
,
pcommand
->
toi_entity
.
tei_entity
,
pcommand
->
toi_entity
.
tei_instance
,
pcommand
->
toi_class
,
pcommand
->
toi_type
);
return
(
WSAEOPNOTSUPP
);
winRouteTable
->
ire_addr
=
table
->
table
[
ndx
].
dwForwardDest
;
winRouteTable
->
ire_index
=
table
->
table
[
ndx
].
dwForwardIfIndex
;
winRouteTable
->
ire_metric
=
table
->
table
[
ndx
].
dwForwardMetric1
;
/* winRouteTable->ire_option4 =
winRouteTable->ire_option5 =
winRouteTable->ire_option6 = */
winRouteTable
->
ire_gw
=
table
->
table
[
ndx
].
dwForwardNextHop
;
/* winRouteTable->ire_option8 =
winRouteTable->ire_option9 =
winRouteTable->ire_option10 = */
winRouteTable
->
ire_mask
=
table
->
table
[
ndx
].
dwForwardMask
;
/* winRouteTable->ire_option12 = */
winRouteTable
++
;
}
/* calculate the length of the data in the output buffer */
*
pcbResponseInfoLen
=
sizeof
(
IPRouteEntry
)
*
table
->
dwNumEntries
;
free
(
table
);
break
;
}
break
;
}
case
WSCNTL_TCPIP_ICMP_ECHO
:
{
unsigned
int
addr
=
*
(
unsigned
int
*
)
pRequestInfo
;
#if 0
int timeout= *(unsigned int*)(inbuf+4);
short x1 = *(unsigned short*)(inbuf+8);
short sendbufsize = *(unsigned short*)(inbuf+10);
char x2 = *(unsigned char*)(inbuf+12);
char ttl = *(unsigned char*)(inbuf+13);
char service = *(unsigned char*)(inbuf+14);
char type= *(unsigned char*)(inbuf+15); /* 0x2: don't fragment*/
#endif
FIXME
(
"(ICMP_ECHO) to 0x%08x stub
\n
"
,
addr
);
break
;
default:
{
FIXME
(
"Command ID Not Supported -> toi_id=0x%lx, toi_entity={tei_entity=0x%lx, tei_instance=0x%lx}, toi_class=0x%lx
\n
"
,
pcommand
->
toi_id
,
pcommand
->
toi_entity
.
tei_entity
,
pcommand
->
toi_entity
.
tei_instance
,
pcommand
->
toi_class
);
return
(
ERROR_BAD_ENVIRONMENT
);
}
}
default:
{
FIXME
(
"Protocoll Not Supported -> protocoll=0x%lx, action=0x%lx, Request=%p, RequestLen=%p, Response=%p, ResponseLen=%p
\n
"
,
protocoll
,
action
,
pRequestInfo
,
pcbRequestInfoLen
,
pResponseInfo
,
pcbResponseInfoLen
);
break
;
}
return
(
WSAEOPNOTSUPP
);
}
case
WSCNTL_TCPIP_ICMP_ECHO
:
{
unsigned
int
addr
=
*
(
unsigned
int
*
)
pRequestInfo
;
#if 0
int timeout= *(unsigned int*)(inbuf+4);
short x1 = *(unsigned short*)(inbuf+8);
short sendbufsize = *(unsigned short*)(inbuf+10);
char x2 = *(unsigned char*)(inbuf+12);
char ttl = *(unsigned char*)(inbuf+13);
char service = *(unsigned char*)(inbuf+14);
char type= *(unsigned char*)(inbuf+15); /* 0x2: don't fragment*/
#endif
FIXME
(
"(ICMP_ECHO) to 0x%08x stub
\n
"
,
addr
);
break
;
}
default:
FIXME
(
"Protocol Not Supported -> protocol=0x%lx, action=0x%lx, Request=%p, RequestLen=%p, Response=%p, ResponseLen=%p
\n
"
,
protocol
,
action
,
pRequestInfo
,
pcbRequestInfoLen
,
pResponseInfo
,
pcbResponseInfoLen
);
return
(
WSAEOPNOTSUPP
);
}
return
(
WSCTL_SUCCESS
);
}
...
...
dlls/wsock32/wscontrol.h
View file @
c24fc00f
...
...
@@ -6,9 +6,12 @@
*
* The functionality of WsControl was created by observing its behaviour
* in Windows 98, so there are likely to be bugs with the assumptions
* that were made.
* that were made. A significant amount of help came from
* http://tangentsoft.net/wskfaq/articles/wscontrol.html , especially the
* trace by Thomas Divine (www.pcausa.net).
*
* Copyright 2000 James Hatheway
* Copyright 2003 Juan Lang
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
...
...
@@ -28,8 +31,6 @@
#ifndef WSCONTROL_H_INCLUDED
#define WSCONTROL_H_INCLUDED
typedef
unsigned
char
uchar
;
/* This doesn't seem to be in any standard headers */
#define WSCTL_SUCCESS 0
/*
...
...
@@ -57,44 +58,6 @@ typedef struct TDIObjectID
unsigned
long
toi_id
;
}
TDIObjectID
;
typedef
struct
IPSNMPInfo
{
unsigned
long
ipsi_forwarding
;
unsigned
long
ipsi_defaultttl
;
unsigned
long
ipsi_inreceives
;
unsigned
long
ipsi_inhdrerrors
;
unsigned
long
ipsi_inaddrerrors
;
unsigned
long
ipsi_forwdatagrams
;
unsigned
long
ipsi_inunknownprotos
;
unsigned
long
ipsi_indiscards
;
unsigned
long
ipsi_indelivers
;
unsigned
long
ipsi_outrequests
;
unsigned
long
ipsi_routingdiscards
;
unsigned
long
ipsi_outdiscards
;
unsigned
long
ipsi_outnoroutes
;
unsigned
long
ipsi_reasmtimeout
;
unsigned
long
ipsi_reasmreqds
;
unsigned
long
ipsi_reasmoks
;
unsigned
long
ipsi_reasmfails
;
unsigned
long
ipsi_fragoks
;
unsigned
long
ipsi_fragfails
;
unsigned
long
ipsi_fragcreates
;
unsigned
long
ipsi_numif
;
unsigned
long
ipsi_numaddr
;
unsigned
long
ipsi_numroutes
;
}
IPSNMPInfo
;
typedef
struct
IPAddrEntry
{
unsigned
long
iae_addr
;
unsigned
long
iae_index
;
unsigned
long
iae_mask
;
unsigned
long
iae_bcastaddr
;
unsigned
long
iae_reasmsize
;
ushort
iae_context
;
ushort
iae_pad
;
}
IPAddrEntry
;
#ifdef if_type
#undef if_type
#endif
...
...
@@ -114,7 +77,7 @@ typedef struct IFEntry
unsigned
long
if_mtu
;
unsigned
long
if_speed
;
unsigned
long
if_physaddrlen
;
u
char
if_physaddr
[
MAX_PHYSADDR_SIZE
];
u
nsigned
char
if_physaddr
[
MAX_PHYSADDR_SIZE
];
unsigned
long
if_adminstatus
;
unsigned
long
if_operstatus
;
unsigned
long
if_lastchange
;
...
...
@@ -131,7 +94,7 @@ typedef struct IFEntry
unsigned
long
if_outerrors
;
unsigned
long
if_outqlen
;
unsigned
long
if_descrlen
;
u
char
if_descr
[
1
];
u
nsigned
char
if_descr
[
1
];
}
IFEntry
;
...
...
@@ -153,34 +116,58 @@ typedef struct IPRouteEntry {
}
IPRouteEntry
;
/* Not sure what EXACTLY most of this stuff does.
WsControl was implemented mainly by observing
its behaviour in Win98 ************************/
#define INFO_CLASS_GENERIC 0x100
#define INFO_CLASS_PROTOCOL 0x200
#define INFO_TYPE_PROVIDER 0x100
#define ENTITY_LIST_ID 0
#define CL_NL_ENTITY 0x301
#define IF_ENTITY 0x200
#define ENTITY_TYPE_ID 1
#define IP_MIB_ADDRTABLE_ENTRY_ID 0x102
#define IP_MIB_ROUTETABLE_ENTRY_ID 0x101
/* FIXME: not real name */
/************************************************/
/* Valid values to get back from entity type ID query */
#define CO_TL_NBF 0x400
/* Entity implements NBF prot. */
#define CO_TL_SPX 0x402
/* Entity implements SPX prot. */
#define CO_TL_TCP 0x404
/* Entity implements TCP prot. */
#define CO_TL_SPP 0x406
/* Entity implements SPP prot. */
#define CL_TL_NBF 0x401
/* CL NBF protocol */
#define CL_TL_UDP 0x403
/* Entity implements UDP */
#define ER_ICMP 0x380
/* The ICMP protocol */
#define CL_NL_IPX 0x301
/* Entity implements IPX */
#define CL_NL_IP 0x303
/* Entity implements IP */
#define AT_ARP 0x280
/* Entity implements ARP */
#define AT_NULL 0x282
/* Entity does no address */
#define IF_GENERIC 0x200
/* Generic interface */
#define IF_MIB 0x202
/* Supports MIB-2 interface */
/* Constants for use in the toi_id field */
#define ENTITY_LIST_ID 0
/* to get the list of entity IDs */
#define ENTITY_TYPE_ID 1
/* it's an interface; what type of interface is it? */
#define IP_MIB_ROUTETABLE_ENTRY_ID 0x101
/* not real name */
#define IP_MIB_ADDRTABLE_ENTRY_ID 0x102
/* Constants for use in the toi_class field */
#define INFO_CLASS_GENERIC 0x100
#define INFO_CLASS_PROTOCOL 0x200
/* Constants for use in the toi_type field */
#define INFO_TYPE_PROVIDER 0x100
/* Interface types. The first one can be returned in the entity ID list--it's
* an interface, and it can be further queried for what type of interface it is.
*/
#define IF_GENERIC 0x200
/* generic interface */
#define IF_MIB 0x202
/* supports MIB-2 interface */
/* address translation types. The first can be turned in the entity ID list--
* it supports address translation of some type, and it can be further queried
* for what type of address translation it supports (I think).
*/
#define AT_ENTITY 0x280
#define AT_ARP 0x280
#define AT_NULL 0x282
/* doesn't do address translation after all (liar) */
/* network layer service providers. The first one can be returned in the
* entity list ID--it supports a network layer (datagram) service, and it can
* be further queried for what type of network layer service it provides.
*/
#define CL_NL_ENTITY 0x301
#define CL_NL_IPX 0x301
/* implements IPX--probably won't see this, since
* we're querying the TCP protocol */
#define CL_NL_IP 0x303
/* implements IP */
/* echo request/response types. The first can be returned in the entity ID
* list--it can be further queried for what type of echo it supports (I think).
*/
#define ER_ENTITY 0x380
#define ER_ICMP 0x380
/* connection-oriented transport layer protocols--you know the drill by now */
#define CO_TL_ENTITY 0x400
#define CO_TL_NBF 0x400
#define CO_TL_SPX 0x402
#define CO_TL_TCP 0x404
#define CO_TL_SPP 0x406
/* connectionless transport layer protocols--you know the drill by now */
#define CL_TL_ENTITY 0x401
#define CL_TL_NBF 0x401
#define CL_TL_UDP 0x403
#endif
/* WSCONTROL_H_INCLUDED */
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