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
52 #ifdef HAVE_SYS_IOCTL_H
53 # include <sys/ioctl.h>
56 #include <sys/types.h>
57 #ifdef HAVE_SYS_SOCKET_H
58 #include <sys/socket.h>
60 #ifdef HAVE_SYS_SOCKIO_H
61 # include <sys/sockio.h>
69 #include "wine/debug.h"
72 #include "wscontrol.h"
74 /* FIXME: The rest of the socket() cdecl<->stdapi stack corruption problem
79 extern SOCKET WINAPI
socket(INT af
, INT type
, INT protocol
);
80 extern SOCKET WINAPI
recv(SOCKET
,char*,int,int);
81 /* Plus some missing prototypes, due to the WS_ prefixing */
82 extern int WINAPI
closesocket(SOCKET
);
83 extern int WINAPI
ioctlsocket(SOCKET
,long,u_long
*);
87 WINE_DEFAULT_DEBUG_CHANNEL(winsock
);
90 /***********************************************************************
91 * WsControl (WSOCK32.1001)
93 * WsControl seems to be an undocumented Win95 function. A lot of
94 * discussion about WsControl can be found on the net, e.g.
95 * Subject: Re: WSOCK32.DLL WsControl Exported Function
96 * From: "Peter Rindfuss" <rindfuss-s@medea.wz-berlin.de>
99 * WSCNTL_TCPIP_QUERY_INFO option is partially implemeted based
100 * on observing the behaviour of WsControl with an app in
101 * Windows 98. It is not fully implemented, and there could
102 * be (are?) errors due to incorrect assumptions made.
105 * WsControl returns WSCTL_SUCCESS on success.
106 * STATUS_BUFFER_TOO_SMALL is returned if the output buffer length
107 * (*pcbResponseInfoLen) is too small, otherwise errors return -1.
109 * It doesn't seem to generate errors that can be retrieved by
114 DWORD WINAPI
WsControl(DWORD protocoll
,
117 LPDWORD pcbRequestInfoLen
,
118 LPVOID pResponseInfo
,
119 LPDWORD pcbResponseInfoLen
)
121 /* Get the command structure into a pointer we can use,
123 TDIObjectID
*pcommand
= (TDIObjectID
*)pRequestInfo
;
125 TRACE (" WsControl TOI_ID=>0x%lx<, {TEI_ENTITY=0x%lx, TEI_INSTANCE=0x%lx}, TOI_CLASS=0x%lx, TOI_TYPE=0x%lx\n",
126 pcommand
->toi_id
, pcommand
->toi_entity
.tei_entity
, pcommand
->toi_entity
.tei_instance
,
127 pcommand
->toi_class
, pcommand
->toi_type
);
133 case WSCNTL_TCPIP_QUERY_INFO
:
135 switch (pcommand
->toi_id
)
138 ENTITY_LIST_ID seems to get number of adapters in the system.
139 (almost like an index to be used when calling other WsControl options)
143 TDIEntityID
*baseptr
= pResponseInfo
;
146 if (pcommand
->toi_class
!= INFO_CLASS_GENERIC
&&
147 pcommand
->toi_type
!= INFO_TYPE_PROVIDER
)
149 FIXME ("Unexpected Option for ENTITY_LIST_ID request -> toi_class=0x%lx, toi_type=0x%lx\n",
150 pcommand
->toi_class
, pcommand
->toi_type
);
151 return (WSAEOPNOTSUPP
);
154 numInt
= WSCNTL_GetEntryCount(WSCNTL_COUNT_INTERFACES
);
157 ERR ("Unable to open /proc filesystem to determine number of network interfaces!\n");
161 if (*pcbResponseInfoLen
< sizeof(TDIEntityID
)*(numInt
*2) )
163 return (STATUS_BUFFER_TOO_SMALL
);
167 memset(baseptr
, 0, sizeof(TDIEntityID
)*(numInt
*2));
169 for (i
=0; i
<numInt
; i
++)
171 /* tei_instance is an network interface identifier.
172 I'm not quite sure what the difference is between tei_entity values of
173 CL_NL_ENTITY and IF_ENTITY */
174 baseptr
->tei_entity
= CL_NL_ENTITY
; baseptr
->tei_instance
= i
; baseptr
++;
175 baseptr
->tei_entity
= IF_ENTITY
; baseptr
->tei_instance
= i
; baseptr
++;
178 /* Calculate size of out buffer */
179 *pcbResponseInfoLen
= sizeof(TDIEntityID
)*(numInt
*2);
185 /* ENTITY_TYPE_ID is used to obtain simple information about a
186 network card, such as MAC Address, description, interface type,
187 number of network addresses, etc. */
188 case ENTITY_TYPE_ID
: /* ALSO: IP_MIB_STATS_ID */
190 if (pcommand
->toi_class
== INFO_CLASS_GENERIC
&& pcommand
->toi_type
== INFO_TYPE_PROVIDER
)
192 if (pcommand
->toi_entity
.tei_entity
== IF_ENTITY
)
194 * ((ULONG
*)pResponseInfo
) = IF_MIB
;
196 /* Calculate size of out buffer */
197 *pcbResponseInfoLen
= sizeof (ULONG
);
200 else if (pcommand
->toi_entity
.tei_entity
== CL_NL_ENTITY
)
202 * ((ULONG
*)pResponseInfo
) = CL_NL_IP
;
204 /* Calculate size of out buffer */
205 *pcbResponseInfoLen
= sizeof (ULONG
);
208 else if (pcommand
->toi_class
== INFO_CLASS_PROTOCOL
&&
209 pcommand
->toi_type
== INFO_TYPE_PROVIDER
)
211 if (pcommand
->toi_entity
.tei_entity
== IF_ENTITY
)
213 /* In this case, we are requesting specific information about a
214 a particular network adapter. (MAC Address, speed, data transmitted/received,
217 IFEntry
*IntInfo
= (IFEntry
*) pResponseInfo
;
219 #if defined(SIOCGIFHWADDR) || defined(SIOCGENADDR)
225 if (!WSCNTL_GetInterfaceName(pcommand
->toi_entity
.tei_instance
, ifName
))
227 ERR ("Unable to parse /proc filesystem!\n");
231 /* Get a socket so that we can use ioctl */
232 if ( (sock
= socket(AF_INET
, SOCK_DGRAM
, 0)) == INVALID_SOCKET
)
234 ERR ("Error creating socket!\n");
238 /* 0 out return structure first */
239 memset (IntInfo
, 0, sizeof(IFEntry
));
242 IntInfo
->if_index
= pcommand
->toi_entity
.tei_instance
;
244 /* MAC Address - Let's try to do this in a cross-platform way... */
245 #if defined(SIOCGIFHWADDR) /* Linux */
246 strcpy(ifInfo
.ifr_name
, ifName
);
247 if (ioctlsocket(sock
, SIOCGIFHWADDR
, (ULONG
*)&ifInfo
) < 0)
249 ERR ("Error obtaining MAC Address!\n");
255 /* FIXME: Is it correct to assume size of 6? */
256 memcpy(IntInfo
->if_physaddr
, ifInfo
.ifr_hwaddr
.sa_data
, 6);
257 IntInfo
->if_physaddrlen
=6;
259 #elif defined(SIOCGENADDR) /* Solaris */
260 if (ioctlsocket(sock
, SIOCGENADDR
, (ULONG
*)&ifInfo
) < 0)
262 ERR ("Error obtaining MAC Address!\n");
268 /* FIXME: Is it correct to assume size of 6? */
269 memcpy(IntInfo
->if_physaddr
, ifInfo
.ifr_enaddr
, 6);
270 IntInfo
->if_physaddrlen
=6;
273 memset (IntInfo
->if_physaddr
, 0, 6);
274 ERR ("Unable to determine MAC Address on your platform!\n");
278 /* Interface name and length */
279 strcpy (IntInfo
->if_descr
, ifName
);
280 IntInfo
->if_descrlen
= strlen (IntInfo
->if_descr
);
282 /* Obtain bytes transmitted/received for interface */
283 if ( (WSCNTL_GetTransRecvStat(pcommand
->toi_entity
.tei_instance
,
284 &IntInfo
->if_inoctets
, &IntInfo
->if_outoctets
)) < 0)
286 ERR ("Error obtaining transmit/receive stats for the network interface!\n");
292 /* FIXME: How should the below be properly calculated? ******************/
293 IntInfo
->if_type
= 0x6; /* Ethernet (?) */
294 IntInfo
->if_speed
= 1000000; /* Speed of interface (bits per second?) */
295 /************************************************************************/
298 *pcbResponseInfoLen
= sizeof (IFEntry
) + IntInfo
->if_descrlen
;
300 else if (pcommand
->toi_entity
.tei_entity
== CL_NL_ENTITY
)
302 IPSNMPInfo
*infoStruc
= (IPSNMPInfo
*) pResponseInfo
;
303 int numInt
, numRoutes
;
305 /* This case is used to obtain general statistics about the
308 if (*pcbResponseInfoLen
< sizeof(IPSNMPInfo
) )
310 return (STATUS_BUFFER_TOO_SMALL
);
315 memset(infoStruc
, 0, sizeof(IPSNMPInfo
));
317 /* Get the number of interfaces */
318 numInt
= WSCNTL_GetEntryCount(WSCNTL_COUNT_INTERFACES
);
321 ERR ("Unable to open /proc filesystem to determine number of network interfaces!\n");
324 /* Get the number of routes */
325 numRoutes
= WSCNTL_GetEntryCount(WSCNTL_COUNT_ROUTES
);
328 ERR ("Unable to open /proc filesystem to determine number of network routes!\n");
332 infoStruc
->ipsi_numif
= numInt
; /* # of interfaces */
333 infoStruc
->ipsi_numaddr
= numInt
; /* # of addresses */
334 infoStruc
->ipsi_numroutes
= numRoutes
; /* # of routes */
336 /* FIXME: How should the below be properly calculated? ******************/
337 infoStruc
->ipsi_forwarding
= 0x0;
338 infoStruc
->ipsi_defaultttl
= 0x0;
339 infoStruc
->ipsi_inreceives
= 0x0;
340 infoStruc
->ipsi_inhdrerrors
= 0x0;
341 infoStruc
->ipsi_inaddrerrors
= 0x0;
342 infoStruc
->ipsi_forwdatagrams
= 0x0;
343 infoStruc
->ipsi_inunknownprotos
= 0x0;
344 infoStruc
->ipsi_indiscards
= 0x0;
345 infoStruc
->ipsi_indelivers
= 0x0;
346 infoStruc
->ipsi_outrequests
= 0x0;
347 infoStruc
->ipsi_routingdiscards
= 0x0;
348 infoStruc
->ipsi_outdiscards
= 0x0;
349 infoStruc
->ipsi_outnoroutes
= 0x0;
350 infoStruc
->ipsi_reasmtimeout
= 0x0;
351 infoStruc
->ipsi_reasmreqds
= 0x0;
352 infoStruc
->ipsi_reasmoks
= 0x0;
353 infoStruc
->ipsi_reasmfails
= 0x0;
354 infoStruc
->ipsi_fragoks
= 0x0;
355 infoStruc
->ipsi_fragfails
= 0x0;
356 infoStruc
->ipsi_fragcreates
= 0x0;
357 /************************************************************************/
359 /* Calculate size of out buffer */
360 *pcbResponseInfoLen
= sizeof(IPSNMPInfo
);
366 FIXME ("Unexpected Option for ENTITY_TYPE_ID request -> toi_class=0x%lx, toi_type=0x%lx\n",
367 pcommand
->toi_class
, pcommand
->toi_type
);
369 return (WSAEOPNOTSUPP
);
376 /* IP_MIB_ADDRTABLE_ENTRY_ID is used to obtain more detailed information about a
377 particular network adapter */
378 case IP_MIB_ADDRTABLE_ENTRY_ID
:
380 IPAddrEntry
*baseIPInfo
= (IPAddrEntry
*) pResponseInfo
;
381 char ifName
[IFNAMSIZ
+1];
385 if (*pcbResponseInfoLen
< sizeof(IPAddrEntry
))
387 return (STATUS_BUFFER_TOO_SMALL
);
390 if (!WSCNTL_GetInterfaceName(pcommand
->toi_entity
.tei_instance
, ifName
))
392 ERR ("Unable to parse /proc filesystem!\n");
397 /* Get a socket so we can use ioctl */
398 if ( (sock
= socket(AF_INET
, SOCK_DGRAM
, 0)) == INVALID_SOCKET
)
400 ERR ("Error creating socket!\n");
405 memset(baseIPInfo
, 0, sizeof(IPAddrEntry
) );
408 baseIPInfo
->iae_index
= pcommand
->toi_entity
.tei_instance
;
411 strcpy (ifInfo
.ifr_name
, ifName
);
412 ifInfo
.ifr_addr
.sa_family
= AF_INET
;
413 if (ioctlsocket(sock
, SIOCGIFADDR
, (ULONG
*)&ifInfo
) < 0)
415 baseIPInfo
->iae_addr
= 0x0;
419 struct WS_sockaddr_in
* ipTemp
= (struct WS_sockaddr_in
*)&ifInfo
.ifr_addr
;
420 baseIPInfo
->iae_addr
= ipTemp
->sin_addr
.S_un
.S_addr
;
423 /* Broadcast Address */
424 strcpy (ifInfo
.ifr_name
, ifName
);
425 if (ioctlsocket(sock
, SIOCGIFBRDADDR
, (ULONG
*)&ifInfo
) < 0)
427 baseIPInfo
->iae_bcastaddr
= 0x0;
431 struct WS_sockaddr_in
* ipTemp
= (struct WS_sockaddr_in
*)&ifInfo
.ifr_broadaddr
;
432 baseIPInfo
->iae_bcastaddr
= ipTemp
->sin_addr
.S_un
.S_addr
;
436 strcpy(ifInfo
.ifr_name
, ifName
);
437 if (ioctlsocket(sock
, SIOCGIFNETMASK
, (ULONG
*)&ifInfo
) < 0)
439 baseIPInfo
->iae_mask
= 0x0;
443 /* Trying to avoid some compile problems across platforms.
444 (Linux, FreeBSD, Solaris...) */
447 baseIPInfo
->iae_mask
= 0;
448 ERR ("Unable to determine Netmask on your platform!\n");
450 struct WS_sockaddr_in
* ipTemp
= (struct WS_sockaddr_in
*)&ifInfo
.ifr_addr
;
451 baseIPInfo
->iae_mask
= ipTemp
->sin_addr
.S_un
.S_addr
;
454 struct WS_sockaddr_in
* ipTemp
= (struct WS_sockaddr_in
*)&ifInfo
.ifr_netmask
;
455 baseIPInfo
->iae_mask
= ipTemp
->sin_addr
.S_un
.S_addr
;
459 /* FIXME: How should the below be properly calculated? ******************/
460 baseIPInfo
->iae_reasmsize
= 0x0;
461 baseIPInfo
->iae_context
= 0x0;
462 baseIPInfo
->iae_pad
= 0x0;
463 /************************************************************************/
465 /* Calculate size of out buffer */
466 *pcbResponseInfoLen
= sizeof(IPAddrEntry
);
472 /* This call returns the routing table.
473 * No official documentation found, even the name of the command is unknown.
475 * http://www.cyberport.com/~tangent/programming/winsock/articles/wscontrol.html
476 * and testings done with winipcfg.exe, route.exe and ipconfig.exe.
477 * pcommand->toi_entity.tei_instance seems to be the interface number
478 * but route.exe outputs only the information for the last interface
479 * if only the routes for the pcommand->toi_entity.tei_instance
480 * interface are returned. */
481 case IP_MIB_ROUTETABLE_ENTRY_ID
: /* FIXME: not real name. Value is 0x101 */
483 int numRoutes
, foundRoutes
;
484 wscntl_routeentry
*routeTable
, *routePtr
; /* route table */
486 IPRouteEntry
*winRouteTable
= (IPRouteEntry
*) pResponseInfo
;
488 /* Get the number of routes */
489 numRoutes
= WSCNTL_GetEntryCount(WSCNTL_COUNT_ROUTES
);
492 ERR ("Unable to open /proc filesystem to determine number of network routes!\n");
496 if (*pcbResponseInfoLen
< (sizeof(IPRouteEntry
) * numRoutes
))
498 return (STATUS_BUFFER_TOO_SMALL
);
501 /* malloc space for the routeTable */
502 routeTable
= (wscntl_routeentry
*) malloc(sizeof(wscntl_routeentry
) * numRoutes
);
505 ERR ("couldn't malloc space for routeTable!\n");
508 /* get the route table */
509 foundRoutes
= WSCNTL_GetRouteTable(numRoutes
, routeTable
);
512 ERR ("Unable to open /proc filesystem to parse the route entries!\n");
516 routePtr
= routeTable
;
518 /* first 0 out the output buffer */
519 memset(winRouteTable
, 0, *pcbResponseInfoLen
);
521 /* calculate the length of the data in the output buffer */
522 *pcbResponseInfoLen
= sizeof(IPRouteEntry
) * foundRoutes
;
524 for ( ; foundRoutes
> 0; foundRoutes
--)
526 winRouteTable
->ire_addr
= routePtr
->wre_dest
;
527 winRouteTable
->ire_index
= routePtr
->wre_intf
;
528 winRouteTable
->ire_metric
= routePtr
->wre_metric
;
529 /* winRouteTable->ire_option4 =
530 winRouteTable->ire_option5 =
531 winRouteTable->ire_option6 = */
532 winRouteTable
->ire_gw
= routePtr
->wre_gw
;
533 /* winRouteTable->ire_option8 =
534 winRouteTable->ire_option9 =
535 winRouteTable->ire_option10 = */
536 winRouteTable
->ire_mask
= routePtr
->wre_mask
;
537 /* winRouteTable->ire_option12 = */
550 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",
551 pcommand
->toi_id
, pcommand
->toi_entity
.tei_entity
, pcommand
->toi_entity
.tei_instance
,
552 pcommand
->toi_class
, pcommand
->toi_type
);
554 return (WSAEOPNOTSUPP
);
561 case WSCNTL_TCPIP_ICMP_ECHO
:
563 unsigned int addr
= *(unsigned int*)pRequestInfo
;
565 int timeout
= *(unsigned int*)(inbuf
+4);
566 short x1
= *(unsigned short*)(inbuf
+8);
567 short sendbufsize
= *(unsigned short*)(inbuf
+10);
568 char x2
= *(unsigned char*)(inbuf
+12);
569 char ttl
= *(unsigned char*)(inbuf
+13);
570 char service
= *(unsigned char*)(inbuf
+14);
571 char type
= *(unsigned char*)(inbuf
+15); /* 0x2: don't fragment*/
574 FIXME("(ICMP_ECHO) to 0x%08x stub \n", addr
);
580 FIXME("Protocoll Not Supported -> protocoll=0x%lx, action=0x%lx, Request=%p, RequestLen=%p, Response=%p, ResponseLen=%p\n",
581 protocoll
, action
, pRequestInfo
, pcbRequestInfoLen
, pResponseInfo
, pcbResponseInfoLen
);
583 return (WSAEOPNOTSUPP
);
588 return (WSCTL_SUCCESS
);
594 Helper function for WsControl - Get count of the number of interfaces
595 or routes by parsing /proc filesystem.
597 int WSCNTL_GetEntryCount(const int entrytype
)
601 char buf
[512]; /* Size optimized for a typical workstation */
609 case WSCNTL_COUNT_INTERFACES
:
611 filename
= PROCFS_NETDEV_FILE
;
612 count
= -2; /* two haeder lines */
616 case WSCNTL_COUNT_ROUTES
:
618 filename
= PROCFS_ROUTE_FILE
;
619 count
= -1; /* one haeder line */
629 /* open /proc filesystem file */
630 fd
= open(filename
, O_RDONLY
);
635 /* read the file and count the EOL's */
636 while ((chrread
= read(fd
, buf
, sizeof(buf
))) != 0)
643 continue; /* read interupted by a signal, try to read again */
651 while ((ptr
= memchr(ptr
, '\n', chrread
- (int) (ptr
- buf
))) > 0)
664 Helper function for WsControl - Get name of device from interface number
665 by parsing /proc filesystem.
667 int WSCNTL_GetInterfaceName(int intNumber
, char *intName
)
670 char buf
[512]; /* Size doesn't matter, something big */
673 /* Open /proc filesystem file for network devices */
674 procfs
= fopen(PROCFS_NETDEV_FILE
, "r");
677 /* If we can't open the file, return an error */
681 /* Omit first two lines, they are only headers */
682 fgets(buf
, sizeof(buf
), procfs
);
683 fgets(buf
, sizeof(buf
), procfs
);
685 for (i
=0; i
<intNumber
; i
++)
687 /* Skip the lines that don't interest us. */
688 fgets(buf
, sizeof(buf
), procfs
);
690 fgets(buf
, sizeof(buf
), procfs
); /* This is the line we want */
693 /* Parse out the line, grabbing only the name of the device
694 to the intName variable
696 The Line comes in like this: (we only care about the device name)
697 lo: 21970 377 0 0 0 0 0 0 21970 377 0 0 0 0 0 0
700 while (isspace(buf
[i
])) /* Skip initial space(s) */
712 if (buf
[i
] == ':') /* FIXME: Not sure if this block (alias detection) works properly */
714 /* This interface could be an alias... */
716 char *dotname
= intName
;
717 *intName
++ = buf
[i
++];
719 while (isdigit(buf
[i
]))
721 *intName
++ = buf
[i
++];
726 /* ... It wasn't, so back up */
741 *intName
++ = buf
[i
++];
751 Helper function for WsControl - This function returns the bytes (octets) transmitted
752 and received for the supplied interface number from the /proc fs.
754 int WSCNTL_GetTransRecvStat(int intNumber
, unsigned long *transBytes
, unsigned long *recvBytes
)
757 char buf
[512], result
[512]; /* Size doesn't matter, something big */
758 int i
, bufPos
, resultPos
;
760 /* Open /proc filesystem file for network devices */
761 procfs
= fopen(PROCFS_NETDEV_FILE
, "r");
764 /* If we can't open the file, return an error */
768 /* Omit first two lines, they are only headers */
769 fgets(buf
, sizeof(buf
), procfs
);
770 fgets(buf
, sizeof(buf
), procfs
);
772 for (i
=0; i
<intNumber
; i
++)
774 /* Skip the lines that don't interest us. */
775 fgets(buf
, sizeof(buf
), procfs
);
777 fgets(buf
, sizeof(buf
), procfs
); /* This is the line we want */
781 /* Parse out the line, grabbing the number of bytes transmitted
782 and received on the interface.
784 The Line comes in like this: (we care about columns 2 and 10)
785 lo: 21970 377 0 0 0 0 0 0 21970 377 0 0 0 0 0 0
788 /* Start at character 0 in the buffer */
791 /* Skip initial space(s) */
792 while (isspace(buf
[bufPos
]))
796 /* Skip the name and its trailing spaces (if any) */
799 if (isspace(buf
[bufPos
]))
802 if (buf
[bufPos
] == ':') /* Could be an alias */
806 while(isdigit (buf
[bufPos
]))
808 if (buf
[bufPos
] != ':')
810 if (buf
[bufPos
] == '\0')
822 while (isspace(buf
[bufPos
]))
826 /* This column (#2) is the number of bytes received. */
828 while (!isspace(buf
[bufPos
]))
830 result
[resultPos
] = buf
[bufPos
];
831 result
[resultPos
+1]='\0';
832 resultPos
++; bufPos
++;
834 *recvBytes
= strtoul (result
, NULL
, 10); /* convert string to unsigned long, using base 10 */
837 /* Skip columns #3 to #9 (Don't need them) */
840 while (isspace(buf
[bufPos
]))
842 while (!isspace(buf
[bufPos
]))
847 /* This column (#10) is the number of bytes transmitted */
848 while (isspace(buf
[bufPos
]))
852 while (!isspace(buf
[bufPos
]))
854 result
[resultPos
] = buf
[bufPos
];
855 result
[resultPos
+1]='\0';
856 resultPos
++; bufPos
++;
858 *transBytes
= strtoul (result
, NULL
, 10); /* convert string to unsigned long, using base 10 */
866 /* Parse the procfs route file and put the datas into routeTable.
867 * Return value is the number of found routes */
868 int WSCNTL_GetRouteTable(int numRoutes
, wscntl_routeentry
*routeTable
)
870 int nrIntf
; /* total number of interfaces */
871 char buf
[256]; /* temporary buffer */
872 char *ptr
; /* pointer to temporary buffer */
873 FILE *file
; /* file handle for procfs route file */
874 int foundRoutes
= 0; /* number of found routes */
875 typedef struct interface_t
{
876 char intfName
[IFNAMSIZ
+1]; /* the name of the interface */
877 int intfNameLen
; /* length of interface name */
879 interface_t
*interface
;
880 int intfNr
; /* the interface number */
882 wscntl_routeentry
*routePtr
= routeTable
;
884 /* get the number of interfaces */
885 nrIntf
= WSCNTL_GetEntryCount(WSCNTL_COUNT_INTERFACES
);
888 ERR ("Unable to open /proc filesystem to determine number of network interfaces!\n");
892 /* malloc space for the interface struct array */
893 interface
= (interface_t
*) malloc(sizeof(interface_t
) * nrIntf
);
896 ERR ("couldn't malloc space for interface!\n");
899 for (intfNr
= 0; intfNr
< nrIntf
; intfNr
++) {
900 if (WSCNTL_GetInterfaceName(intfNr
, interface
[intfNr
].intfName
) < 0)
902 ERR ("Unable to open /proc filesystem to determine the name of network interfaces!\n");
906 interface
[intfNr
].intfNameLen
= strlen(interface
[intfNr
].intfName
);
909 /* Open /proc filesystem file for routes */
910 file
= fopen(PROCFS_ROUTE_FILE
, "r");
913 /* If we can't open the file, return an error */
918 /* skip the header line */
919 fgets(buf
, sizeof(buf
), file
);
921 /* parse the rest of the file and put the matching entries into routeTable.
922 Format of procfs route entry:
923 Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT
924 lo 0000007F 00000000 0001 0 0 0 000000FF 0 0 0
926 while (fgets(buf
, sizeof(buf
), file
)) {
928 /* find the interface of the route */
929 while ((strncmp(buf
, interface
[intfNr
].intfName
, interface
[intfNr
].intfNameLen
) != 0)
930 && (intfNr
< nrIntf
))
934 if (intfNr
< nrIntf
) {
936 if (foundRoutes
> numRoutes
) {
937 /* output buffer is to small */
938 ERR("buffer to small to fit all routes found into it!\n");
944 ptr
+= interface
[intfNr
].intfNameLen
;
945 routePtr
->wre_intf
= intfNr
;
946 routePtr
->wre_dest
= strtoul(ptr
, &ptr
, 16); /* destination */
947 routePtr
->wre_gw
= strtoul(ptr
, &ptr
, 16); /* gateway */
948 strtoul(ptr
, &ptr
, 16); /* Flags; unused */
949 strtoul(ptr
, &ptr
, 16); /* RefCnt; unused */
950 strtoul(ptr
, &ptr
, 16); /* Use; unused */
951 routePtr
->wre_metric
= strtoul(ptr
, &ptr
, 16); /* metric */
952 routePtr
->wre_mask
= strtoul(ptr
, &ptr
, 16); /* mask */
953 /* strtoul(ptr, &ptr, 16); MTU; unused */
954 /* strtoul(ptr, &ptr, 16); Window; unused */
955 /* strtoul(ptr, &ptr, 16); IRTT; unused */
961 /* this should never happen */
962 WARN("Skipping route with unknown interface\n");
972 /***********************************************************************
973 * WSARecvEx (WSOCK32.1107)
975 * WSARecvEx is a Microsoft specific extension to winsock that is identical to recv
976 * except that has an in/out argument call flags that has the value MSG_PARTIAL ored
977 * into the flags parameter when a partial packet is read. This only applies to
978 * sockets using the datagram protocol. This method does not seem to be implemented
979 * correctly by microsoft as the winsock implementation does not set the MSG_PARTIAL
980 * flag when a fragmented packet arrives.
982 INT WINAPI
WSARecvEx(SOCKET s
, char *buf
, INT len
, INT
*flags
)
984 FIXME("(WSARecvEx) partial packet return value not set \n");
985 return recv(s
, buf
, len
, *flags
);
989 /***********************************************************************
990 * s_perror (WSOCK32.1108)
992 void WINAPI
s_perror(LPCSTR message
)
994 FIXME("(%s): stub\n",message
);