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
22 /* FIXME: This hack is fixing a problem in WsControl. When we call socket(),
23 * it will call into ws2_32's WSOCK32_socket (because of the redirection in
24 * our own .spec file).
25 * The problem is that socket() is predefined in a linux system header that
26 * we are including, which is different from the WINE definition.
27 * (cdecl vs. stdapi). The result is stack corruption.
28 * Furthermore WsControl uses Unix macros and types. This forces us to include
29 * the Unix headers which then conflict with the winsock headers. This forces
30 * us to use USE_WS_PREFIX but then ioctlsocket is called WS_ioctlsocket,
31 * which causes link problems. The correct solution is to implement
32 * WsControl using calls to WSAIoctl. Then we should no longer need to use the
33 * Unix headers. This would also have the advantage of reducing code
35 * Until that happens we need this ugly hack.
39 #define socket linux_socket
40 #define recv linux_recv
54 #ifdef HAVE_SYS_IOCTL_H
55 # include <sys/ioctl.h>
58 #include <sys/types.h>
59 #ifdef HAVE_SYS_SOCKET_H
60 #include <sys/socket.h>
62 #ifdef HAVE_SYS_SOCKIO_H
63 # include <sys/sockio.h>
71 #include "wine/debug.h"
74 #include "wscontrol.h"
76 /* FIXME: The rest of the socket() cdecl<->stdapi stack corruption problem
81 extern SOCKET WINAPI
socket(INT af
, INT type
, INT protocol
);
82 extern SOCKET WINAPI
recv(SOCKET
,char*,int,int);
83 /* Plus some missing prototypes, due to the WS_ prefixing */
84 extern int WINAPI
closesocket(SOCKET
);
85 extern int WINAPI
ioctlsocket(SOCKET
,long,u_long
*);
89 WINE_DEFAULT_DEBUG_CHANNEL(winsock
);
92 /***********************************************************************
93 * WsControl (WSOCK32.1001)
95 * WsControl seems to be an undocumented Win95 function. A lot of
96 * discussion about WsControl can be found on the net, e.g.
97 * Subject: Re: WSOCK32.DLL WsControl Exported Function
98 * From: "Peter Rindfuss" <rindfuss-s@medea.wz-berlin.de>
101 * WSCNTL_TCPIP_QUERY_INFO option is partially implemeted based
102 * on observing the behaviour of WsControl with an app in
103 * Windows 98. It is not fully implemented, and there could
104 * be (are?) errors due to incorrect assumptions made.
107 * WsControl returns WSCTL_SUCCESS on success.
108 * STATUS_BUFFER_TOO_SMALL is returned if the output buffer length
109 * (*pcbResponseInfoLen) is too small, otherwise errors return -1.
111 * It doesn't seem to generate errors that can be retrieved by
116 DWORD WINAPI
WsControl(DWORD protocoll
,
119 LPDWORD pcbRequestInfoLen
,
120 LPVOID pResponseInfo
,
121 LPDWORD pcbResponseInfoLen
)
123 /* Get the command structure into a pointer we can use,
125 TDIObjectID
*pcommand
= (TDIObjectID
*)pRequestInfo
;
127 TRACE (" WsControl TOI_ID=>0x%lx<, {TEI_ENTITY=0x%lx, TEI_INSTANCE=0x%lx}, TOI_CLASS=0x%lx, TOI_TYPE=0x%lx\n",
128 pcommand
->toi_id
, pcommand
->toi_entity
.tei_entity
, pcommand
->toi_entity
.tei_instance
,
129 pcommand
->toi_class
, pcommand
->toi_type
);
135 case WSCNTL_TCPIP_QUERY_INFO
:
137 switch (pcommand
->toi_id
)
140 ENTITY_LIST_ID seems to get number of adapters in the system.
141 (almost like an index to be used when calling other WsControl options)
145 TDIEntityID
*baseptr
= pResponseInfo
;
148 if (pcommand
->toi_class
!= INFO_CLASS_GENERIC
&&
149 pcommand
->toi_type
!= INFO_TYPE_PROVIDER
)
151 FIXME ("Unexpected Option for ENTITY_LIST_ID request -> toi_class=0x%lx, toi_type=0x%lx\n",
152 pcommand
->toi_class
, pcommand
->toi_type
);
153 return (WSAEOPNOTSUPP
);
156 numInt
= WSCNTL_GetEntryCount(WSCNTL_COUNT_INTERFACES
);
159 ERR ("Unable to open /proc filesystem to determine number of network interfaces!\n");
163 if (*pcbResponseInfoLen
< sizeof(TDIEntityID
)*(numInt
*2) )
165 return (STATUS_BUFFER_TOO_SMALL
);
169 memset(baseptr
, 0, sizeof(TDIEntityID
)*(numInt
*2));
171 for (i
=0; i
<numInt
; i
++)
173 /* tei_instance is an network interface identifier.
174 I'm not quite sure what the difference is between tei_entity values of
175 CL_NL_ENTITY and IF_ENTITY */
176 baseptr
->tei_entity
= CL_NL_ENTITY
; baseptr
->tei_instance
= i
; baseptr
++;
177 baseptr
->tei_entity
= IF_ENTITY
; baseptr
->tei_instance
= i
; baseptr
++;
180 /* Calculate size of out buffer */
181 *pcbResponseInfoLen
= sizeof(TDIEntityID
)*(numInt
*2);
187 /* ENTITY_TYPE_ID is used to obtain simple information about a
188 network card, such as MAC Address, description, interface type,
189 number of network addresses, etc. */
190 case ENTITY_TYPE_ID
: /* ALSO: IP_MIB_STATS_ID */
192 if (pcommand
->toi_class
== INFO_CLASS_GENERIC
&& pcommand
->toi_type
== INFO_TYPE_PROVIDER
)
194 if (pcommand
->toi_entity
.tei_entity
== IF_ENTITY
)
196 * ((ULONG
*)pResponseInfo
) = IF_MIB
;
198 /* Calculate size of out buffer */
199 *pcbResponseInfoLen
= sizeof (ULONG
);
202 else if (pcommand
->toi_entity
.tei_entity
== CL_NL_ENTITY
)
204 * ((ULONG
*)pResponseInfo
) = CL_NL_IP
;
206 /* Calculate size of out buffer */
207 *pcbResponseInfoLen
= sizeof (ULONG
);
210 else if (pcommand
->toi_class
== INFO_CLASS_PROTOCOL
&&
211 pcommand
->toi_type
== INFO_TYPE_PROVIDER
)
213 if (pcommand
->toi_entity
.tei_entity
== IF_ENTITY
)
215 /* In this case, we are requesting specific information about a
216 a particular network adapter. (MAC Address, speed, data transmitted/received,
219 IFEntry
*IntInfo
= (IFEntry
*) pResponseInfo
;
221 #if defined(SIOCGIFHWADDR) || defined(SIOCGENADDR)
227 if (!WSCNTL_GetInterfaceName(pcommand
->toi_entity
.tei_instance
, ifName
))
229 ERR ("Unable to parse /proc filesystem!\n");
233 /* Get a socket so that we can use ioctl */
234 if ( (sock
= socket(AF_INET
, SOCK_DGRAM
, 0)) == INVALID_SOCKET
)
236 ERR ("Error creating socket!\n");
240 /* 0 out return structure first */
241 memset (IntInfo
, 0, sizeof(IFEntry
));
244 IntInfo
->if_index
= pcommand
->toi_entity
.tei_instance
;
246 /* MAC Address - Let's try to do this in a cross-platform way... */
247 #if defined(SIOCGIFHWADDR) /* Linux */
248 strcpy(ifInfo
.ifr_name
, ifName
);
249 if (ioctlsocket(sock
, SIOCGIFHWADDR
, (ULONG
*)&ifInfo
) < 0)
251 ERR ("Error obtaining MAC Address!\n");
257 /* FIXME: Is it correct to assume size of 6? */
258 memcpy(IntInfo
->if_physaddr
, ifInfo
.ifr_hwaddr
.sa_data
, 6);
259 IntInfo
->if_physaddrlen
=6;
261 #elif defined(SIOCGENADDR) /* Solaris */
262 if (ioctlsocket(sock
, SIOCGENADDR
, (ULONG
*)&ifInfo
) < 0)
264 ERR ("Error obtaining MAC Address!\n");
270 /* FIXME: Is it correct to assume size of 6? */
271 memcpy(IntInfo
->if_physaddr
, ifInfo
.ifr_enaddr
, 6);
272 IntInfo
->if_physaddrlen
=6;
275 memset (IntInfo
->if_physaddr
, 0, 6);
276 ERR ("Unable to determine MAC Address on your platform!\n");
280 /* Interface name and length */
281 strcpy (IntInfo
->if_descr
, ifName
);
282 IntInfo
->if_descrlen
= strlen (IntInfo
->if_descr
);
284 /* Obtain bytes transmitted/received for interface */
285 if ( (WSCNTL_GetTransRecvStat(pcommand
->toi_entity
.tei_instance
,
286 &IntInfo
->if_inoctets
, &IntInfo
->if_outoctets
)) < 0)
288 ERR ("Error obtaining transmit/receive stats for the network interface!\n");
294 /* FIXME: How should the below be properly calculated? ******************/
295 IntInfo
->if_type
= 0x6; /* Ethernet (?) */
296 IntInfo
->if_speed
= 1000000; /* Speed of interface (bits per second?) */
297 /************************************************************************/
300 *pcbResponseInfoLen
= sizeof (IFEntry
) + IntInfo
->if_descrlen
;
302 else if (pcommand
->toi_entity
.tei_entity
== CL_NL_ENTITY
)
304 IPSNMPInfo
*infoStruc
= (IPSNMPInfo
*) pResponseInfo
;
305 int numInt
, numRoutes
;
307 /* This case is used to obtain general statistics about the
310 if (*pcbResponseInfoLen
< sizeof(IPSNMPInfo
) )
312 return (STATUS_BUFFER_TOO_SMALL
);
317 memset(infoStruc
, 0, sizeof(IPSNMPInfo
));
319 /* Get the number of interfaces */
320 numInt
= WSCNTL_GetEntryCount(WSCNTL_COUNT_INTERFACES
);
323 ERR ("Unable to open /proc filesystem to determine number of network interfaces!\n");
326 /* Get the number of routes */
327 numRoutes
= WSCNTL_GetEntryCount(WSCNTL_COUNT_ROUTES
);
330 ERR ("Unable to open /proc filesystem to determine number of network routes!\n");
334 infoStruc
->ipsi_numif
= numInt
; /* # of interfaces */
335 infoStruc
->ipsi_numaddr
= numInt
; /* # of addresses */
336 infoStruc
->ipsi_numroutes
= numRoutes
; /* # of routes */
338 /* FIXME: How should the below be properly calculated? ******************/
339 infoStruc
->ipsi_forwarding
= 0x0;
340 infoStruc
->ipsi_defaultttl
= 0x0;
341 infoStruc
->ipsi_inreceives
= 0x0;
342 infoStruc
->ipsi_inhdrerrors
= 0x0;
343 infoStruc
->ipsi_inaddrerrors
= 0x0;
344 infoStruc
->ipsi_forwdatagrams
= 0x0;
345 infoStruc
->ipsi_inunknownprotos
= 0x0;
346 infoStruc
->ipsi_indiscards
= 0x0;
347 infoStruc
->ipsi_indelivers
= 0x0;
348 infoStruc
->ipsi_outrequests
= 0x0;
349 infoStruc
->ipsi_routingdiscards
= 0x0;
350 infoStruc
->ipsi_outdiscards
= 0x0;
351 infoStruc
->ipsi_outnoroutes
= 0x0;
352 infoStruc
->ipsi_reasmtimeout
= 0x0;
353 infoStruc
->ipsi_reasmreqds
= 0x0;
354 infoStruc
->ipsi_reasmoks
= 0x0;
355 infoStruc
->ipsi_reasmfails
= 0x0;
356 infoStruc
->ipsi_fragoks
= 0x0;
357 infoStruc
->ipsi_fragfails
= 0x0;
358 infoStruc
->ipsi_fragcreates
= 0x0;
359 /************************************************************************/
361 /* Calculate size of out buffer */
362 *pcbResponseInfoLen
= sizeof(IPSNMPInfo
);
368 FIXME ("Unexpected Option for ENTITY_TYPE_ID request -> toi_class=0x%lx, toi_type=0x%lx\n",
369 pcommand
->toi_class
, pcommand
->toi_type
);
371 return (WSAEOPNOTSUPP
);
378 /* IP_MIB_ADDRTABLE_ENTRY_ID is used to obtain more detailed information about a
379 particular network adapter */
380 case IP_MIB_ADDRTABLE_ENTRY_ID
:
382 IPAddrEntry
*baseIPInfo
= (IPAddrEntry
*) pResponseInfo
;
383 char ifName
[IFNAMSIZ
+1];
387 if (*pcbResponseInfoLen
< sizeof(IPAddrEntry
))
389 return (STATUS_BUFFER_TOO_SMALL
);
392 if (!WSCNTL_GetInterfaceName(pcommand
->toi_entity
.tei_instance
, ifName
))
394 ERR ("Unable to parse /proc filesystem!\n");
399 /* Get a socket so we can use ioctl */
400 if ( (sock
= socket(AF_INET
, SOCK_DGRAM
, 0)) == INVALID_SOCKET
)
402 ERR ("Error creating socket!\n");
407 memset(baseIPInfo
, 0, sizeof(IPAddrEntry
) );
410 baseIPInfo
->iae_index
= pcommand
->toi_entity
.tei_instance
;
413 strcpy (ifInfo
.ifr_name
, ifName
);
414 ifInfo
.ifr_addr
.sa_family
= AF_INET
;
415 if (ioctlsocket(sock
, SIOCGIFADDR
, (ULONG
*)&ifInfo
) < 0)
417 baseIPInfo
->iae_addr
= 0x0;
421 struct WS_sockaddr_in
* ipTemp
= (struct WS_sockaddr_in
*)&ifInfo
.ifr_addr
;
422 baseIPInfo
->iae_addr
= ipTemp
->sin_addr
.S_un
.S_addr
;
425 /* Broadcast Address */
426 strcpy (ifInfo
.ifr_name
, ifName
);
427 if (ioctlsocket(sock
, SIOCGIFBRDADDR
, (ULONG
*)&ifInfo
) < 0)
429 baseIPInfo
->iae_bcastaddr
= 0x0;
433 struct WS_sockaddr_in
* ipTemp
= (struct WS_sockaddr_in
*)&ifInfo
.ifr_broadaddr
;
434 baseIPInfo
->iae_bcastaddr
= ipTemp
->sin_addr
.S_un
.S_addr
;
438 strcpy(ifInfo
.ifr_name
, ifName
);
439 if (ioctlsocket(sock
, SIOCGIFNETMASK
, (ULONG
*)&ifInfo
) < 0)
441 baseIPInfo
->iae_mask
= 0x0;
445 /* Trying to avoid some compile problems across platforms.
446 (Linux, FreeBSD, Solaris...) */
449 baseIPInfo
->iae_mask
= 0;
450 ERR ("Unable to determine Netmask on your platform!\n");
452 struct WS_sockaddr_in
* ipTemp
= (struct WS_sockaddr_in
*)&ifInfo
.ifr_addr
;
453 baseIPInfo
->iae_mask
= ipTemp
->sin_addr
.S_un
.S_addr
;
456 struct WS_sockaddr_in
* ipTemp
= (struct WS_sockaddr_in
*)&ifInfo
.ifr_netmask
;
457 baseIPInfo
->iae_mask
= ipTemp
->sin_addr
.S_un
.S_addr
;
461 /* FIXME: How should the below be properly calculated? ******************/
462 baseIPInfo
->iae_reasmsize
= 0x0;
463 baseIPInfo
->iae_context
= 0x0;
464 baseIPInfo
->iae_pad
= 0x0;
465 /************************************************************************/
467 /* Calculate size of out buffer */
468 *pcbResponseInfoLen
= sizeof(IPAddrEntry
);
474 /* This call returns the routing table.
475 * No official documentation found, even the name of the command is unknown.
477 * http://www.cyberport.com/~tangent/programming/winsock/articles/wscontrol.html
478 * and testings done with winipcfg.exe, route.exe and ipconfig.exe.
479 * pcommand->toi_entity.tei_instance seems to be the interface number
480 * but route.exe outputs only the information for the last interface
481 * if only the routes for the pcommand->toi_entity.tei_instance
482 * interface are returned. */
483 case IP_MIB_ROUTETABLE_ENTRY_ID
: /* FIXME: not real name. Value is 0x101 */
485 int numRoutes
, foundRoutes
;
486 wscntl_routeentry
*routeTable
, *routePtr
; /* route table */
488 IPRouteEntry
*winRouteTable
= (IPRouteEntry
*) pResponseInfo
;
490 /* Get the number of routes */
491 numRoutes
= WSCNTL_GetEntryCount(WSCNTL_COUNT_ROUTES
);
494 ERR ("Unable to open /proc filesystem to determine number of network routes!\n");
498 if (*pcbResponseInfoLen
< (sizeof(IPRouteEntry
) * numRoutes
))
500 return (STATUS_BUFFER_TOO_SMALL
);
503 /* malloc space for the routeTable */
504 routeTable
= (wscntl_routeentry
*) malloc(sizeof(wscntl_routeentry
) * numRoutes
);
507 ERR ("couldn't malloc space for routeTable!\n");
510 /* get the route table */
511 foundRoutes
= WSCNTL_GetRouteTable(numRoutes
, routeTable
);
514 ERR ("Unable to open /proc filesystem to parse the route entries!\n");
518 routePtr
= routeTable
;
520 /* first 0 out the output buffer */
521 memset(winRouteTable
, 0, *pcbResponseInfoLen
);
523 /* calculate the length of the data in the output buffer */
524 *pcbResponseInfoLen
= sizeof(IPRouteEntry
) * foundRoutes
;
526 for ( ; foundRoutes
> 0; foundRoutes
--)
528 winRouteTable
->ire_addr
= routePtr
->wre_dest
;
529 winRouteTable
->ire_index
= routePtr
->wre_intf
;
530 winRouteTable
->ire_metric
= routePtr
->wre_metric
;
531 /* winRouteTable->ire_option4 =
532 winRouteTable->ire_option5 =
533 winRouteTable->ire_option6 = */
534 winRouteTable
->ire_gw
= routePtr
->wre_gw
;
535 /* winRouteTable->ire_option8 =
536 winRouteTable->ire_option9 =
537 winRouteTable->ire_option10 = */
538 winRouteTable
->ire_mask
= routePtr
->wre_mask
;
539 /* winRouteTable->ire_option12 = */
552 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",
553 pcommand
->toi_id
, pcommand
->toi_entity
.tei_entity
, pcommand
->toi_entity
.tei_instance
,
554 pcommand
->toi_class
, pcommand
->toi_type
);
556 return (WSAEOPNOTSUPP
);
563 case WSCNTL_TCPIP_ICMP_ECHO
:
565 unsigned int addr
= *(unsigned int*)pRequestInfo
;
567 int timeout
= *(unsigned int*)(inbuf
+4);
568 short x1
= *(unsigned short*)(inbuf
+8);
569 short sendbufsize
= *(unsigned short*)(inbuf
+10);
570 char x2
= *(unsigned char*)(inbuf
+12);
571 char ttl
= *(unsigned char*)(inbuf
+13);
572 char service
= *(unsigned char*)(inbuf
+14);
573 char type
= *(unsigned char*)(inbuf
+15); /* 0x2: don't fragment*/
576 FIXME("(ICMP_ECHO) to 0x%08x stub \n", addr
);
582 FIXME("Protocoll Not Supported -> protocoll=0x%lx, action=0x%lx, Request=%p, RequestLen=%p, Response=%p, ResponseLen=%p\n",
583 protocoll
, action
, pRequestInfo
, pcbRequestInfoLen
, pResponseInfo
, pcbResponseInfoLen
);
585 return (WSAEOPNOTSUPP
);
590 return (WSCTL_SUCCESS
);
596 Helper function for WsControl - Get count of the number of interfaces
597 or routes by parsing /proc filesystem.
599 int WSCNTL_GetEntryCount(const int entrytype
)
603 char buf
[512]; /* Size optimized for a typical workstation */
611 case WSCNTL_COUNT_INTERFACES
:
613 filename
= PROCFS_NETDEV_FILE
;
614 count
= -2; /* two haeder lines */
618 case WSCNTL_COUNT_ROUTES
:
620 filename
= PROCFS_ROUTE_FILE
;
621 count
= -1; /* one haeder line */
631 /* open /proc filesystem file */
632 fd
= open(filename
, O_RDONLY
);
637 /* read the file and count the EOL's */
638 while ((chrread
= read(fd
, buf
, sizeof(buf
))) != 0)
645 continue; /* read interupted by a signal, try to read again */
653 while ((ptr
= memchr(ptr
, '\n', chrread
- (int) (ptr
- buf
))) > 0)
666 Helper function for WsControl - Get name of device from interface number
667 by parsing /proc filesystem.
669 int WSCNTL_GetInterfaceName(int intNumber
, char *intName
)
672 char buf
[512]; /* Size doesn't matter, something big */
675 /* Open /proc filesystem file for network devices */
676 procfs
= fopen(PROCFS_NETDEV_FILE
, "r");
679 /* If we can't open the file, return an error */
683 /* Omit first two lines, they are only headers */
684 fgets(buf
, sizeof(buf
), procfs
);
685 fgets(buf
, sizeof(buf
), procfs
);
687 for (i
=0; i
<intNumber
; i
++)
689 /* Skip the lines that don't interest us. */
690 fgets(buf
, sizeof(buf
), procfs
);
692 fgets(buf
, sizeof(buf
), procfs
); /* This is the line we want */
695 /* Parse out the line, grabbing only the name of the device
696 to the intName variable
698 The Line comes in like this: (we only care about the device name)
699 lo: 21970 377 0 0 0 0 0 0 21970 377 0 0 0 0 0 0
702 while (isspace(buf
[i
])) /* Skip initial space(s) */
714 if (buf
[i
] == ':') /* FIXME: Not sure if this block (alias detection) works properly */
716 /* This interface could be an alias... */
718 char *dotname
= intName
;
719 *intName
++ = buf
[i
++];
721 while (isdigit(buf
[i
]))
723 *intName
++ = buf
[i
++];
728 /* ... It wasn't, so back up */
743 *intName
++ = buf
[i
++];
753 Helper function for WsControl - This function returns the bytes (octets) transmitted
754 and received for the supplied interface number from the /proc fs.
756 int WSCNTL_GetTransRecvStat(int intNumber
, unsigned long *transBytes
, unsigned long *recvBytes
)
759 char buf
[512], result
[512]; /* Size doesn't matter, something big */
760 int i
, bufPos
, resultPos
;
762 /* Open /proc filesystem file for network devices */
763 procfs
= fopen(PROCFS_NETDEV_FILE
, "r");
766 /* If we can't open the file, return an error */
770 /* Omit first two lines, they are only headers */
771 fgets(buf
, sizeof(buf
), procfs
);
772 fgets(buf
, sizeof(buf
), procfs
);
774 for (i
=0; i
<intNumber
; i
++)
776 /* Skip the lines that don't interest us. */
777 fgets(buf
, sizeof(buf
), procfs
);
779 fgets(buf
, sizeof(buf
), procfs
); /* This is the line we want */
783 /* Parse out the line, grabbing the number of bytes transmitted
784 and received on the interface.
786 The Line comes in like this: (we care about columns 2 and 10)
787 lo: 21970 377 0 0 0 0 0 0 21970 377 0 0 0 0 0 0
790 /* Start at character 0 in the buffer */
793 /* Skip initial space(s) */
794 while (isspace(buf
[bufPos
]))
798 /* Skip the name and its trailing spaces (if any) */
801 if (isspace(buf
[bufPos
]))
804 if (buf
[bufPos
] == ':') /* Could be an alias */
808 while(isdigit (buf
[bufPos
]))
810 if (buf
[bufPos
] != ':')
812 if (buf
[bufPos
] == '\0')
824 while (isspace(buf
[bufPos
]))
828 /* This column (#2) is the number of bytes received. */
830 while (!isspace(buf
[bufPos
]))
832 result
[resultPos
] = buf
[bufPos
];
833 result
[resultPos
+1]='\0';
834 resultPos
++; bufPos
++;
836 *recvBytes
= strtoul (result
, NULL
, 10); /* convert string to unsigned long, using base 10 */
839 /* Skip columns #3 to #9 (Don't need them) */
842 while (isspace(buf
[bufPos
]))
844 while (!isspace(buf
[bufPos
]))
849 /* This column (#10) is the number of bytes transmitted */
850 while (isspace(buf
[bufPos
]))
854 while (!isspace(buf
[bufPos
]))
856 result
[resultPos
] = buf
[bufPos
];
857 result
[resultPos
+1]='\0';
858 resultPos
++; bufPos
++;
860 *transBytes
= strtoul (result
, NULL
, 10); /* convert string to unsigned long, using base 10 */
868 /* Parse the procfs route file and put the datas into routeTable.
869 * Return value is the number of found routes */
870 int WSCNTL_GetRouteTable(int numRoutes
, wscntl_routeentry
*routeTable
)
872 int nrIntf
; /* total number of interfaces */
873 char buf
[256]; /* temporary buffer */
874 char *ptr
; /* pointer to temporary buffer */
875 FILE *file
; /* file handle for procfs route file */
876 int foundRoutes
= 0; /* number of found routes */
877 typedef struct interface_t
{
878 char intfName
[IFNAMSIZ
+1]; /* the name of the interface */
879 int intfNameLen
; /* length of interface name */
881 interface_t
*interface
;
882 int intfNr
; /* the interface number */
884 wscntl_routeentry
*routePtr
= routeTable
;
886 /* get the number of interfaces */
887 nrIntf
= WSCNTL_GetEntryCount(WSCNTL_COUNT_INTERFACES
);
890 ERR ("Unable to open /proc filesystem to determine number of network interfaces!\n");
894 /* malloc space for the interface struct array */
895 interface
= (interface_t
*) malloc(sizeof(interface_t
) * nrIntf
);
898 ERR ("couldn't malloc space for interface!\n");
901 for (intfNr
= 0; intfNr
< nrIntf
; intfNr
++) {
902 if (WSCNTL_GetInterfaceName(intfNr
, interface
[intfNr
].intfName
) < 0)
904 ERR ("Unable to open /proc filesystem to determine the name of network interfaces!\n");
908 interface
[intfNr
].intfNameLen
= strlen(interface
[intfNr
].intfName
);
911 /* Open /proc filesystem file for routes */
912 file
= fopen(PROCFS_ROUTE_FILE
, "r");
915 /* If we can't open the file, return an error */
920 /* skip the header line */
921 fgets(buf
, sizeof(buf
), file
);
923 /* parse the rest of the file and put the matching entries into routeTable.
924 Format of procfs route entry:
925 Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT
926 lo 0000007F 00000000 0001 0 0 0 000000FF 0 0 0
928 while (fgets(buf
, sizeof(buf
), file
)) {
930 /* find the interface of the route */
931 while ((strncmp(buf
, interface
[intfNr
].intfName
, interface
[intfNr
].intfNameLen
) != 0)
932 && (intfNr
< nrIntf
))
936 if (intfNr
< nrIntf
) {
938 if (foundRoutes
> numRoutes
) {
939 /* output buffer is to small */
940 ERR("buffer to small to fit all routes found into it!\n");
946 ptr
+= interface
[intfNr
].intfNameLen
;
947 routePtr
->wre_intf
= intfNr
;
948 routePtr
->wre_dest
= strtoul(ptr
, &ptr
, 16); /* destination */
949 routePtr
->wre_gw
= strtoul(ptr
, &ptr
, 16); /* gateway */
950 strtoul(ptr
, &ptr
, 16); /* Flags; unused */
951 strtoul(ptr
, &ptr
, 16); /* RefCnt; unused */
952 strtoul(ptr
, &ptr
, 16); /* Use; unused */
953 routePtr
->wre_metric
= strtoul(ptr
, &ptr
, 16); /* metric */
954 routePtr
->wre_mask
= strtoul(ptr
, &ptr
, 16); /* mask */
955 /* strtoul(ptr, &ptr, 16); MTU; unused */
956 /* strtoul(ptr, &ptr, 16); Window; unused */
957 /* strtoul(ptr, &ptr, 16); IRTT; unused */
963 /* this should never happen */
964 WARN("Skipping route with unknown interface\n");
974 /***********************************************************************
975 * WSARecvEx (WSOCK32.1107)
977 * WSARecvEx is a Microsoft specific extension to winsock that is identical to recv
978 * except that has an in/out argument call flags that has the value MSG_PARTIAL ored
979 * into the flags parameter when a partial packet is read. This only applies to
980 * sockets using the datagram protocol. This method does not seem to be implemented
981 * correctly by microsoft as the winsock implementation does not set the MSG_PARTIAL
982 * flag when a fragmented packet arrives.
984 INT WINAPI
WSARecvEx(SOCKET s
, char *buf
, INT len
, INT
*flags
)
986 FIXME("(WSARecvEx) partial packet return value not set \n");
987 return recv(s
, buf
, len
, *flags
);
991 /***********************************************************************
992 * s_perror (WSOCK32.1108)
994 void WINAPI
s_perror(LPCSTR message
)
996 FIXME("(%s): stub\n",message
);