2 * WSOCK32 specific functions
4 * Copyright (C) 1993,1994,1996,1997 John Brezak, Erik Bos, Alex Korobka.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include "wine/debug.h"
28 #include "wscontrol.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(winsock
);
33 /* internal remapper function for the IP_ constants */
34 static INT
_remap_optname(INT level
, INT optname
)
36 TRACE("level=%d, optname=%d\n", level
, optname
);
37 if (level
== IPPROTO_IP
) {
38 switch (optname
) { /***** from value *****/
39 case 2: return 9; /* IP_MULTICAST_IF */
40 case 3: return 10; /* IP_MULTICAST_TTL */
41 case 4: return 11; /* IP_MULTICAST_LOOP */
42 case 5: return 12; /* IP_ADD_MEMBERSHIP */
43 case 6: return 13; /* IP_DROP_MEMBERSHIP */
44 case 7: return 4; /* IP_TTL */
45 case 8: return 3; /* IP_TOS */
46 case 9: return 14; /* IP_DONTFRAGMENT */
47 default: FIXME("Unknown optname %d, can't remap!\n", optname
); return optname
;
50 /* don't need to do anything */
55 /***********************************************************************
56 * setsockopt (WSOCK32.21)
58 * We have these forwarders because, for reasons unknown to us mere mortals,
59 * the values of the IP_ constants changed between winsock.h and winsock2.h.
60 * So, we need to remap them here.
62 INT WINAPI
WS1_setsockopt(SOCKET s
, INT level
, INT optname
, char *optval
, INT optlen
)
64 return setsockopt(s
, level
, _remap_optname(level
, optname
), optval
, optlen
);
67 /***********************************************************************
68 * getsockopt (WSOCK32.7)
70 INT WINAPI
WS1_getsockopt(SOCKET s
, INT level
, INT optname
, char *optval
, INT
*optlen
)
72 return getsockopt(s
, level
, _remap_optname(level
, optname
), optval
, optlen
);
75 /***********************************************************************
76 * WsControl (WSOCK32.1001)
78 * WsControl seems to be an undocumented Win95 function. A lot of
79 * discussion about WsControl can be found on the net, e.g.
80 * Subject: Re: WSOCK32.DLL WsControl Exported Function
81 * From: "Peter Rindfuss" <rindfuss-s@medea.wz-berlin.de>
84 * WSCNTL_TCPIP_QUERY_INFO option is partially implemeted based
85 * on observing the behaviour of WsControl with an app in
86 * Windows 98. It is not fully implemented, and there could
87 * be (are?) errors due to incorrect assumptions made.
90 * WsControl returns WSCTL_SUCCESS on success.
91 * STATUS_BUFFER_TOO_SMALL is returned if the output buffer length
92 * (*pcbResponseInfoLen) is too small, otherwise errors return -1.
94 * It doesn't seem to generate errors that can be retrieved by
99 DWORD WINAPI
WsControl(DWORD protocoll
,
102 LPDWORD pcbRequestInfoLen
,
103 LPVOID pResponseInfo
,
104 LPDWORD pcbResponseInfoLen
)
107 /* Get the command structure into a pointer we can use,
109 TDIObjectID
*pcommand
= (TDIObjectID
*)pRequestInfo
;
111 TRACE (" WsControl TOI_ID=>0x%lx<, {TEI_ENTITY=0x%lx, TEI_INSTANCE=0x%lx}, TOI_CLASS=0x%lx, TOI_TYPE=0x%lx\n",
112 pcommand
->toi_id
, pcommand
->toi_entity
.tei_entity
, pcommand
->toi_entity
.tei_instance
,
113 pcommand
->toi_class
, pcommand
->toi_type
);
119 case WSCNTL_TCPIP_QUERY_INFO
:
121 switch (pcommand
->toi_id
)
124 ENTITY_LIST_ID seems to get number of adapters in the system.
125 (almost like an index to be used when calling other WsControl options)
129 TDIEntityID
*baseptr
= pResponseInfo
;
130 DWORD numInt
, i
, ipAddrTableSize
;
131 PMIB_IPADDRTABLE table
;
133 if (pcommand
->toi_class
!= INFO_CLASS_GENERIC
&&
134 pcommand
->toi_type
!= INFO_TYPE_PROVIDER
)
136 FIXME ("Unexpected Option for ENTITY_LIST_ID request -> toi_class=0x%lx, toi_type=0x%lx\n",
137 pcommand
->toi_class
, pcommand
->toi_type
);
138 return (WSAEOPNOTSUPP
);
141 GetNumberOfInterfaces(&numInt
);
143 if (*pcbResponseInfoLen
< sizeof(TDIEntityID
)*(numInt
*2) )
145 return (STATUS_BUFFER_TOO_SMALL
);
148 /* expect a 1:1 correspondence between interfaces and IP
149 addresses, so use the cheaper (less memory allocated)
150 GetIpAddrTable rather than GetIfTable */
152 GetIpAddrTable(NULL
, &ipAddrTableSize
, FALSE
);
153 table
= (PMIB_IPADDRTABLE
)calloc(1, ipAddrTableSize
);
154 if (!table
) return -1; /* FIXME: better error code */
155 GetIpAddrTable(table
, &ipAddrTableSize
, FALSE
);
158 memset(baseptr
, 0, sizeof(TDIEntityID
)*(table
->dwNumEntries
*2));
160 for (i
=0; i
<table
->dwNumEntries
; i
++)
162 /* tei_instance is an network interface identifier.
163 I'm not quite sure what the difference is between tei_entity values of
164 CL_NL_ENTITY and IF_ENTITY */
165 baseptr
->tei_entity
= CL_NL_ENTITY
; baseptr
->tei_instance
= table
->table
[i
].dwIndex
; baseptr
++;
166 baseptr
->tei_entity
= IF_ENTITY
; baseptr
->tei_instance
= table
->table
[i
].dwIndex
; baseptr
++;
169 /* Calculate size of out buffer */
170 *pcbResponseInfoLen
= sizeof(TDIEntityID
)*(table
->dwNumEntries
*2);
177 /* ENTITY_TYPE_ID is used to obtain simple information about a
178 network card, such as MAC Address, description, interface type,
179 number of network addresses, etc. */
180 case ENTITY_TYPE_ID
: /* ALSO: IP_MIB_STATS_ID */
182 if (pcommand
->toi_class
== INFO_CLASS_GENERIC
&& pcommand
->toi_type
== INFO_TYPE_PROVIDER
)
184 if (pcommand
->toi_entity
.tei_entity
== IF_ENTITY
)
186 * ((ULONG
*)pResponseInfo
) = IF_MIB
;
188 /* Calculate size of out buffer */
189 *pcbResponseInfoLen
= sizeof (ULONG
);
192 else if (pcommand
->toi_entity
.tei_entity
== CL_NL_ENTITY
)
194 * ((ULONG
*)pResponseInfo
) = CL_NL_IP
;
196 /* Calculate size of out buffer */
197 *pcbResponseInfoLen
= sizeof (ULONG
);
200 else if (pcommand
->toi_class
== INFO_CLASS_PROTOCOL
&&
201 pcommand
->toi_type
== INFO_TYPE_PROVIDER
)
203 if (pcommand
->toi_entity
.tei_entity
== IF_ENTITY
)
206 DWORD index
= pcommand
->toi_entity
.tei_instance
, ret
;
207 DWORD size
= sizeof(row
) - sizeof(row
.wszName
) -
210 if (*pcbResponseInfoLen
< size
)
212 return (STATUS_BUFFER_TOO_SMALL
);
215 ret
= GetIfEntry(&row
);
218 ERR ("Error retrieving data for interface index %lu\n", index
);
219 return -1; /* FIXME: better error code */
221 size
= sizeof(row
) - sizeof(row
.wszName
) -
222 sizeof(row
.bDescr
) + row
.dwDescrLen
;
223 if (*pcbResponseInfoLen
< size
)
225 return (STATUS_BUFFER_TOO_SMALL
);
227 memcpy(pResponseInfo
, &row
.dwIndex
, size
);
228 *pcbResponseInfoLen
= size
;
230 else if (pcommand
->toi_entity
.tei_entity
== CL_NL_ENTITY
)
232 /* This case is used to obtain general statistics about the
235 if (*pcbResponseInfoLen
< sizeof(MIB_IPSTATS
))
237 return (STATUS_BUFFER_TOO_SMALL
);
239 GetIpStatistics((PMIB_IPSTATS
)pResponseInfo
);
241 /* Calculate size of out buffer */
242 *pcbResponseInfoLen
= sizeof(MIB_IPSTATS
);
247 FIXME ("Unexpected Option for ENTITY_TYPE_ID request -> toi_class=0x%lx, toi_type=0x%lx\n",
248 pcommand
->toi_class
, pcommand
->toi_type
);
250 return (WSAEOPNOTSUPP
);
257 /* IP_MIB_ADDRTABLE_ENTRY_ID is used to obtain more detailed information about a
258 particular network adapter */
259 case IP_MIB_ADDRTABLE_ENTRY_ID
:
261 DWORD index
= pcommand
->toi_entity
.tei_instance
;
262 PMIB_IPADDRROW baseIPInfo
= (PMIB_IPADDRROW
) pResponseInfo
;
263 PMIB_IPADDRTABLE table
;
266 if (*pcbResponseInfoLen
< sizeof(MIB_IPADDRROW
))
268 return (STATUS_BUFFER_TOO_SMALL
);
271 /* overkill, get entire table, because there isn't an
272 exported function that gets just one entry, and don't
273 necessarily want our own private export. */
275 GetIpAddrTable(NULL
, &tableSize
, FALSE
);
276 table
= (PMIB_IPADDRTABLE
)calloc(1, tableSize
);
277 if (!table
) return -1; /* FIXME: better error code */
278 GetIpAddrTable(table
, &tableSize
, FALSE
);
279 for (i
= 0; i
< table
->dwNumEntries
; i
++)
281 if (table
->table
[i
].dwIndex
== index
)
283 memcpy(baseIPInfo
, &table
->table
[i
],
284 sizeof(MIB_IPADDRROW
));
290 /************************************************************************/
292 /* Calculate size of out buffer */
293 *pcbResponseInfoLen
= sizeof(MIB_IPADDRROW
);
298 /* This call returns the routing table.
299 * No official documentation found, even the name of the command is unknown.
301 * http://www.cyberport.com/~tangent/programming/winsock/articles/wscontrol.html
302 * and testings done with winipcfg.exe, route.exe and ipconfig.exe.
303 * pcommand->toi_entity.tei_instance seems to be the interface number
304 * but route.exe outputs only the information for the last interface
305 * if only the routes for the pcommand->toi_entity.tei_instance
306 * interface are returned. */
307 case IP_MIB_ROUTETABLE_ENTRY_ID
: /* FIXME: not real name. Value is 0x101 */
309 DWORD routeTableSize
, numRoutes
, ndx
;
310 PMIB_IPFORWARDTABLE table
;
311 IPRouteEntry
*winRouteTable
= (IPRouteEntry
*) pResponseInfo
;
313 GetIpForwardTable(NULL
, &routeTableSize
, FALSE
);
314 numRoutes
= min(routeTableSize
- sizeof(MIB_IPFORWARDTABLE
), 0)
315 / sizeof(MIB_IPFORWARDROW
) + 1;
316 if (*pcbResponseInfoLen
< sizeof(IPRouteEntry
) * numRoutes
)
318 return (STATUS_BUFFER_TOO_SMALL
);
320 table
= (PMIB_IPFORWARDTABLE
)calloc(1, routeTableSize
);
321 if (!table
) return -1; /* FIXME: better return value */
322 GetIpForwardTable(table
, &routeTableSize
, FALSE
);
324 memset(pResponseInfo
, 0, sizeof(IPRouteEntry
) * numRoutes
);
325 for (ndx
= 0; ndx
< table
->dwNumEntries
; ndx
++)
327 winRouteTable
->ire_addr
=
328 table
->table
[ndx
].dwForwardDest
;
329 winRouteTable
->ire_index
=
330 table
->table
[ndx
].dwForwardIfIndex
;
331 winRouteTable
->ire_metric
=
332 table
->table
[ndx
].dwForwardMetric1
;
333 /* winRouteTable->ire_option4 =
334 winRouteTable->ire_option5 =
335 winRouteTable->ire_option6 = */
336 winRouteTable
->ire_gw
= table
->table
[ndx
].dwForwardNextHop
;
337 /* winRouteTable->ire_option8 =
338 winRouteTable->ire_option9 =
339 winRouteTable->ire_option10 = */
340 winRouteTable
->ire_mask
= table
->table
[ndx
].dwForwardMask
;
341 /* winRouteTable->ire_option12 = */
345 /* calculate the length of the data in the output buffer */
346 *pcbResponseInfoLen
= sizeof(IPRouteEntry
) *
356 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",
357 pcommand
->toi_id
, pcommand
->toi_entity
.tei_entity
, pcommand
->toi_entity
.tei_instance
,
358 pcommand
->toi_class
, pcommand
->toi_type
);
360 return (WSAEOPNOTSUPP
);
367 case WSCNTL_TCPIP_ICMP_ECHO
:
369 unsigned int addr
= *(unsigned int*)pRequestInfo
;
371 int timeout
= *(unsigned int*)(inbuf
+4);
372 short x1
= *(unsigned short*)(inbuf
+8);
373 short sendbufsize
= *(unsigned short*)(inbuf
+10);
374 char x2
= *(unsigned char*)(inbuf
+12);
375 char ttl
= *(unsigned char*)(inbuf
+13);
376 char service
= *(unsigned char*)(inbuf
+14);
377 char type
= *(unsigned char*)(inbuf
+15); /* 0x2: don't fragment*/
380 FIXME("(ICMP_ECHO) to 0x%08x stub \n", addr
);
386 FIXME("Protocoll Not Supported -> protocoll=0x%lx, action=0x%lx, Request=%p, RequestLen=%p, Response=%p, ResponseLen=%p\n",
387 protocoll
, action
, pRequestInfo
, pcbRequestInfoLen
, pResponseInfo
, pcbResponseInfoLen
);
389 return (WSAEOPNOTSUPP
);
394 return (WSCTL_SUCCESS
);
399 /***********************************************************************
400 * WSARecvEx (WSOCK32.1107)
402 * WSARecvEx is a Microsoft specific extension to winsock that is identical to recv
403 * except that has an in/out argument call flags that has the value MSG_PARTIAL ored
404 * into the flags parameter when a partial packet is read. This only applies to
405 * sockets using the datagram protocol. This method does not seem to be implemented
406 * correctly by microsoft as the winsock implementation does not set the MSG_PARTIAL
407 * flag when a fragmented packet arrives.
409 INT WINAPI
WSARecvEx(SOCKET s
, char *buf
, INT len
, INT
*flags
)
411 FIXME("(WSARecvEx) partial packet return value not set \n");
412 return recv(s
, buf
, len
, *flags
);
416 /***********************************************************************
417 * s_perror (WSOCK32.1108)
419 void WINAPI
s_perror(LPCSTR message
)
421 FIXME("(%s): stub\n",message
);