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 #include <sys/ioctl.h>
54 #include <sys/types.h>
55 #ifdef HAVE_SYS_SOCKET_H
56 #include <sys/socket.h>
58 #ifdef HAVE_SYS_SOCKIO_H
59 # include <sys/sockio.h>
67 #include "wine/debug.h"
70 #include "wscontrol.h"
72 /* FIXME: The rest of the socket() cdecl<->stdapi stack corruption problem
77 extern SOCKET WINAPI
socket(INT af
, INT type
, INT protocol
);
78 extern SOCKET WINAPI
recv(SOCKET
,char*,int,int);
79 /* Plus some missing prototypes, due to the WS_ prefixing */
80 extern int WINAPI
closesocket(SOCKET
);
81 extern int WINAPI
ioctlsocket(SOCKET
,long,u_long
*);
85 WINE_DEFAULT_DEBUG_CHANNEL(winsock
);
88 /***********************************************************************
89 * WsControl (WSOCK32.1001)
91 * WsControl seems to be an undocumented Win95 function. A lot of
92 * discussion about WsControl can be found on the net, e.g.
93 * Subject: Re: WSOCK32.DLL WsControl Exported Function
94 * From: "Peter Rindfuss" <rindfuss-s@medea.wz-berlin.de>
97 * WSCNTL_TCPIP_QUERY_INFO option is partially implemeted based
98 * on observing the behaviour of WsControl with an app in
99 * Windows 98. It is not fully implemented, and there could
100 * be (are?) errors due to incorrect assumptions made.
103 * WsControl returns WSCTL_SUCCESS on success.
104 * STATUS_BUFFER_TOO_SMALL is returned if the output buffer length
105 * (*pcbResponseInfoLen) is too small, otherwise errors return -1.
107 * It doesn't seem to generate errors that can be retrieved by
112 DWORD WINAPI
WsControl(DWORD protocoll
,
115 LPDWORD pcbRequestInfoLen
,
116 LPVOID pResponseInfo
,
117 LPDWORD pcbResponseInfoLen
)
119 /* Get the command structure into a pointer we can use,
121 TDIObjectID
*pcommand
= (TDIObjectID
*)pRequestInfo
;
123 TRACE (" WsControl TOI_ID=>0x%lx<, {TEI_ENTITY=0x%lx, TEI_INSTANCE=0x%lx}, TOI_CLASS=0x%lx, TOI_TYPE=0x%lx\n",
124 pcommand
->toi_id
, pcommand
->toi_entity
.tei_entity
, pcommand
->toi_entity
.tei_instance
,
125 pcommand
->toi_class
, pcommand
->toi_type
);
131 case WSCNTL_TCPIP_QUERY_INFO
:
133 switch (pcommand
->toi_id
)
136 ENTITY_LIST_ID seems to get number of adapters in the system.
137 (almost like an index to be used when calling other WsControl options)
141 TDIEntityID
*baseptr
= pResponseInfo
;
144 if (pcommand
->toi_class
!= INFO_CLASS_GENERIC
&&
145 pcommand
->toi_type
!= INFO_TYPE_PROVIDER
)
147 FIXME ("Unexpected Option for ENTITY_LIST_ID request -> toi_class=0x%lx, toi_type=0x%lx\n",
148 pcommand
->toi_class
, pcommand
->toi_type
);
149 return (WSAEOPNOTSUPP
);
152 numInt
= WSCNTL_GetEntryCount(WSCNTL_COUNT_INTERFACES
);
155 ERR ("Unable to open /proc filesystem to determine number of network interfaces!\n");
159 if (*pcbResponseInfoLen
< sizeof(TDIEntityID
)*(numInt
*2) )
161 return (STATUS_BUFFER_TOO_SMALL
);
165 memset(baseptr
, 0, sizeof(TDIEntityID
)*(numInt
*2));
167 for (i
=0; i
<numInt
; i
++)
169 /* tei_instance is an network interface identifier.
170 I'm not quite sure what the difference is between tei_entity values of
171 CL_NL_ENTITY and IF_ENTITY */
172 baseptr
->tei_entity
= CL_NL_ENTITY
; baseptr
->tei_instance
= i
; baseptr
++;
173 baseptr
->tei_entity
= IF_ENTITY
; baseptr
->tei_instance
= i
; baseptr
++;
176 /* Calculate size of out buffer */
177 *pcbResponseInfoLen
= sizeof(TDIEntityID
)*(numInt
*2);
183 /* ENTITY_TYPE_ID is used to obtain simple information about a
184 network card, such as MAC Address, description, interface type,
185 number of network addresses, etc. */
186 case ENTITY_TYPE_ID
: /* ALSO: IP_MIB_STATS_ID */
188 if (pcommand
->toi_class
== INFO_CLASS_GENERIC
&& pcommand
->toi_type
== INFO_TYPE_PROVIDER
)
190 if (pcommand
->toi_entity
.tei_entity
== IF_ENTITY
)
192 * ((ULONG
*)pResponseInfo
) = IF_MIB
;
194 /* Calculate size of out buffer */
195 *pcbResponseInfoLen
= sizeof (ULONG
);
198 else if (pcommand
->toi_entity
.tei_entity
== CL_NL_ENTITY
)
200 * ((ULONG
*)pResponseInfo
) = CL_NL_IP
;
202 /* Calculate size of out buffer */
203 *pcbResponseInfoLen
= sizeof (ULONG
);
206 else if (pcommand
->toi_class
== INFO_CLASS_PROTOCOL
&&
207 pcommand
->toi_type
== INFO_TYPE_PROVIDER
)
209 if (pcommand
->toi_entity
.tei_entity
== IF_ENTITY
)
211 /* In this case, we are requesting specific information about a
212 a particular network adapter. (MAC Address, speed, data transmitted/received,
215 IFEntry
*IntInfo
= (IFEntry
*) pResponseInfo
;
217 #if defined(SIOCGIFHWADDR) || defined(SIOCGENADDR)
223 if (!WSCNTL_GetInterfaceName(pcommand
->toi_entity
.tei_instance
, ifName
))
225 ERR ("Unable to parse /proc filesystem!\n");
229 /* Get a socket so that we can use ioctl */
230 if ( (sock
= socket(AF_INET
, SOCK_DGRAM
, 0)) == INVALID_SOCKET
)
232 ERR ("Error creating socket!\n");
236 /* 0 out return structure first */
237 memset (IntInfo
, 0, sizeof(IFEntry
));
240 IntInfo
->if_index
= pcommand
->toi_entity
.tei_instance
;
242 /* MAC Address - Let's try to do this in a cross-platform way... */
243 #if defined(SIOCGIFHWADDR) /* Linux */
244 strcpy(ifInfo
.ifr_name
, ifName
);
245 if (ioctlsocket(sock
, SIOCGIFHWADDR
, (ULONG
*)&ifInfo
) < 0)
247 ERR ("Error obtaining MAC Address!\n");
253 /* FIXME: Is it correct to assume size of 6? */
254 memcpy(IntInfo
->if_physaddr
, ifInfo
.ifr_hwaddr
.sa_data
, 6);
255 IntInfo
->if_physaddrlen
=6;
257 #elif defined(SIOCGENADDR) /* Solaris */
258 if (ioctlsocket(sock
, SIOCGENADDR
, (ULONG
*)&ifInfo
) < 0)
260 ERR ("Error obtaining MAC Address!\n");
266 /* FIXME: Is it correct to assume size of 6? */
267 memcpy(IntInfo
->if_physaddr
, ifInfo
.ifr_enaddr
, 6);
268 IntInfo
->if_physaddrlen
=6;
271 memset (IntInfo
->if_physaddr
, 0, 6);
272 ERR ("Unable to determine MAC Address on your platform!\n");
276 /* Interface name and length */
277 strcpy (IntInfo
->if_descr
, ifName
);
278 IntInfo
->if_descrlen
= strlen (IntInfo
->if_descr
);
280 /* Obtain bytes transmitted/received for interface */
281 if ( (WSCNTL_GetTransRecvStat(pcommand
->toi_entity
.tei_instance
,
282 &IntInfo
->if_inoctets
, &IntInfo
->if_outoctets
)) < 0)
284 ERR ("Error obtaining transmit/receive stats for the network interface!\n");
290 /* FIXME: How should the below be properly calculated? ******************/
291 IntInfo
->if_type
= 0x6; /* Ethernet (?) */
292 IntInfo
->if_speed
= 1000000; /* Speed of interface (bits per second?) */
293 /************************************************************************/
296 *pcbResponseInfoLen
= sizeof (IFEntry
) + IntInfo
->if_descrlen
;
298 else if (pcommand
->toi_entity
.tei_entity
== CL_NL_ENTITY
)
300 IPSNMPInfo
*infoStruc
= (IPSNMPInfo
*) pResponseInfo
;
301 int numInt
, numRoutes
;
303 /* This case is used to obtain general statistics about the
306 if (*pcbResponseInfoLen
< sizeof(IPSNMPInfo
) )
308 return (STATUS_BUFFER_TOO_SMALL
);
313 memset(infoStruc
, 0, sizeof(IPSNMPInfo
));
315 /* Get the number of interfaces */
316 numInt
= WSCNTL_GetEntryCount(WSCNTL_COUNT_INTERFACES
);
319 ERR ("Unable to open /proc filesystem to determine number of network interfaces!\n");
322 /* Get the number of routes */
323 numRoutes
= WSCNTL_GetEntryCount(WSCNTL_COUNT_ROUTES
);
326 ERR ("Unable to open /proc filesystem to determine number of network routes!\n");
330 infoStruc
->ipsi_numif
= numInt
; /* # of interfaces */
331 infoStruc
->ipsi_numaddr
= numInt
; /* # of addresses */
332 infoStruc
->ipsi_numroutes
= numRoutes
; /* # of routes */
334 /* FIXME: How should the below be properly calculated? ******************/
335 infoStruc
->ipsi_forwarding
= 0x0;
336 infoStruc
->ipsi_defaultttl
= 0x0;
337 infoStruc
->ipsi_inreceives
= 0x0;
338 infoStruc
->ipsi_inhdrerrors
= 0x0;
339 infoStruc
->ipsi_inaddrerrors
= 0x0;
340 infoStruc
->ipsi_forwdatagrams
= 0x0;
341 infoStruc
->ipsi_inunknownprotos
= 0x0;
342 infoStruc
->ipsi_indiscards
= 0x0;
343 infoStruc
->ipsi_indelivers
= 0x0;
344 infoStruc
->ipsi_outrequests
= 0x0;
345 infoStruc
->ipsi_routingdiscards
= 0x0;
346 infoStruc
->ipsi_outdiscards
= 0x0;
347 infoStruc
->ipsi_outnoroutes
= 0x0;
348 infoStruc
->ipsi_reasmtimeout
= 0x0;
349 infoStruc
->ipsi_reasmreqds
= 0x0;
350 infoStruc
->ipsi_reasmoks
= 0x0;
351 infoStruc
->ipsi_reasmfails
= 0x0;
352 infoStruc
->ipsi_fragoks
= 0x0;
353 infoStruc
->ipsi_fragfails
= 0x0;
354 infoStruc
->ipsi_fragcreates
= 0x0;
355 /************************************************************************/
357 /* Calculate size of out buffer */
358 *pcbResponseInfoLen
= sizeof(IPSNMPInfo
);
364 FIXME ("Unexpected Option for ENTITY_TYPE_ID request -> toi_class=0x%lx, toi_type=0x%lx\n",
365 pcommand
->toi_class
, pcommand
->toi_type
);
367 return (WSAEOPNOTSUPP
);
374 /* IP_MIB_ADDRTABLE_ENTRY_ID is used to obtain more detailed information about a
375 particular network adapter */
376 case IP_MIB_ADDRTABLE_ENTRY_ID
:
378 IPAddrEntry
*baseIPInfo
= (IPAddrEntry
*) pResponseInfo
;
379 char ifName
[IFNAMSIZ
+1];
383 if (*pcbResponseInfoLen
< sizeof(IPAddrEntry
))
385 return (STATUS_BUFFER_TOO_SMALL
);
388 if (!WSCNTL_GetInterfaceName(pcommand
->toi_entity
.tei_instance
, ifName
))
390 ERR ("Unable to parse /proc filesystem!\n");
395 /* Get a socket so we can use ioctl */
396 if ( (sock
= socket(AF_INET
, SOCK_DGRAM
, 0)) == INVALID_SOCKET
)
398 ERR ("Error creating socket!\n");
403 memset(baseIPInfo
, 0, sizeof(IPAddrEntry
) );
406 baseIPInfo
->iae_index
= pcommand
->toi_entity
.tei_instance
;
409 strcpy (ifInfo
.ifr_name
, ifName
);
410 ifInfo
.ifr_addr
.sa_family
= AF_INET
;
411 if (ioctlsocket(sock
, SIOCGIFADDR
, (ULONG
*)&ifInfo
) < 0)
413 baseIPInfo
->iae_addr
= 0x0;
417 struct WS_sockaddr_in
* ipTemp
= (struct WS_sockaddr_in
*)&ifInfo
.ifr_addr
;
418 baseIPInfo
->iae_addr
= ipTemp
->sin_addr
.S_un
.S_addr
;
421 /* Broadcast Address */
422 strcpy (ifInfo
.ifr_name
, ifName
);
423 if (ioctlsocket(sock
, SIOCGIFBRDADDR
, (ULONG
*)&ifInfo
) < 0)
425 baseIPInfo
->iae_bcastaddr
= 0x0;
429 struct WS_sockaddr_in
* ipTemp
= (struct WS_sockaddr_in
*)&ifInfo
.ifr_broadaddr
;
430 baseIPInfo
->iae_bcastaddr
= ipTemp
->sin_addr
.S_un
.S_addr
;
434 strcpy(ifInfo
.ifr_name
, ifName
);
435 if (ioctlsocket(sock
, SIOCGIFNETMASK
, (ULONG
*)&ifInfo
) < 0)
437 baseIPInfo
->iae_mask
= 0x0;
441 /* Trying to avoid some compile problems across platforms.
442 (Linux, FreeBSD, Solaris...) */
445 baseIPInfo
->iae_mask
= 0;
446 ERR ("Unable to determine Netmask on your platform!\n");
448 struct WS_sockaddr_in
* ipTemp
= (struct WS_sockaddr_in
*)&ifInfo
.ifr_addr
;
449 baseIPInfo
->iae_mask
= ipTemp
->sin_addr
.S_un
.S_addr
;
452 struct WS_sockaddr_in
* ipTemp
= (struct WS_sockaddr_in
*)&ifInfo
.ifr_netmask
;
453 baseIPInfo
->iae_mask
= ipTemp
->sin_addr
.S_un
.S_addr
;
457 /* FIXME: How should the below be properly calculated? ******************/
458 baseIPInfo
->iae_reasmsize
= 0x0;
459 baseIPInfo
->iae_context
= 0x0;
460 baseIPInfo
->iae_pad
= 0x0;
461 /************************************************************************/
463 /* Calculate size of out buffer */
464 *pcbResponseInfoLen
= sizeof(IPAddrEntry
);
470 /* This call returns the routing table.
471 * No official documentation found, even the name of the command is unknown.
473 * http://www.cyberport.com/~tangent/programming/winsock/articles/wscontrol.html
474 * and testings done with winipcfg.exe, route.exe and ipconfig.exe.
475 * pcommand->toi_entity.tei_instance seems to be the interface number
476 * but route.exe outputs only the information for the last interface
477 * if only the routes for the pcommand->toi_entity.tei_instance
478 * interface are returned. */
479 case IP_MIB_ROUTETABLE_ENTRY_ID
: /* FIXME: not real name. Value is 0x101 */
481 int numRoutes
, foundRoutes
;
482 wscntl_routeentry
*routeTable
, *routePtr
; /* route table */
484 IPRouteEntry
*winRouteTable
= (IPRouteEntry
*) pResponseInfo
;
486 /* Get the number of routes */
487 numRoutes
= WSCNTL_GetEntryCount(WSCNTL_COUNT_ROUTES
);
490 ERR ("Unable to open /proc filesystem to determine number of network routes!\n");
494 if (*pcbResponseInfoLen
< (sizeof(IPRouteEntry
) * numRoutes
))
496 return (STATUS_BUFFER_TOO_SMALL
);
499 /* malloc space for the routeTable */
500 routeTable
= (wscntl_routeentry
*) malloc(sizeof(wscntl_routeentry
) * numRoutes
);
503 ERR ("couldn't malloc space for routeTable!\n");
506 /* get the route table */
507 foundRoutes
= WSCNTL_GetRouteTable(numRoutes
, routeTable
);
510 ERR ("Unable to open /proc filesystem to parse the route entries!\n");
514 routePtr
= routeTable
;
516 /* first 0 out the output buffer */
517 memset(winRouteTable
, 0, *pcbResponseInfoLen
);
519 /* calculate the length of the data in the output buffer */
520 *pcbResponseInfoLen
= sizeof(IPRouteEntry
) * foundRoutes
;
522 for ( ; foundRoutes
> 0; foundRoutes
--)
524 winRouteTable
->ire_addr
= routePtr
->wre_dest
;
525 winRouteTable
->ire_index
= routePtr
->wre_intf
;
526 winRouteTable
->ire_metric
= routePtr
->wre_metric
;
527 /* winRouteTable->ire_option4 =
528 winRouteTable->ire_option5 =
529 winRouteTable->ire_option6 = */
530 winRouteTable
->ire_gw
= routePtr
->wre_gw
;
531 /* winRouteTable->ire_option8 =
532 winRouteTable->ire_option9 =
533 winRouteTable->ire_option10 = */
534 winRouteTable
->ire_mask
= routePtr
->wre_mask
;
535 /* winRouteTable->ire_option12 = */
548 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",
549 pcommand
->toi_id
, pcommand
->toi_entity
.tei_entity
, pcommand
->toi_entity
.tei_instance
,
550 pcommand
->toi_class
, pcommand
->toi_type
);
552 return (WSAEOPNOTSUPP
);
559 case WSCNTL_TCPIP_ICMP_ECHO
:
561 unsigned int addr
= *(unsigned int*)pRequestInfo
;
563 int timeout
= *(unsigned int*)(inbuf
+4);
564 short x1
= *(unsigned short*)(inbuf
+8);
565 short sendbufsize
= *(unsigned short*)(inbuf
+10);
566 char x2
= *(unsigned char*)(inbuf
+12);
567 char ttl
= *(unsigned char*)(inbuf
+13);
568 char service
= *(unsigned char*)(inbuf
+14);
569 char type
= *(unsigned char*)(inbuf
+15); /* 0x2: don't fragment*/
572 FIXME("(ICMP_ECHO) to 0x%08x stub \n", addr
);
578 FIXME("Protocoll Not Supported -> protocoll=0x%lx, action=0x%lx, Request=%p, RequestLen=%p, Response=%p, ResponseLen=%p\n",
579 protocoll
, action
, pRequestInfo
, pcbRequestInfoLen
, pResponseInfo
, pcbResponseInfoLen
);
581 return (WSAEOPNOTSUPP
);
586 return (WSCTL_SUCCESS
);
592 Helper function for WsControl - Get count of the number of interfaces
593 or routes by parsing /proc filesystem.
595 int WSCNTL_GetEntryCount(const int entrytype
)
599 char buf
[512]; /* Size optimized for a typical workstation */
607 case WSCNTL_COUNT_INTERFACES
:
609 filename
= PROCFS_NETDEV_FILE
;
610 count
= -2; /* two haeder lines */
614 case WSCNTL_COUNT_ROUTES
:
616 filename
= PROCFS_ROUTE_FILE
;
617 count
= -1; /* one haeder line */
627 /* open /proc filesystem file */
628 fd
= open(filename
, O_RDONLY
);
633 /* read the file and count the EOL's */
634 while ((chrread
= read(fd
, buf
, sizeof(buf
))) != 0)
641 continue; /* read interupted by a signal, try to read again */
649 while ((ptr
= memchr(ptr
, '\n', chrread
- (int) (ptr
- buf
))) > 0)
662 Helper function for WsControl - Get name of device from interface number
663 by parsing /proc filesystem.
665 int WSCNTL_GetInterfaceName(int intNumber
, char *intName
)
668 char buf
[512]; /* Size doesn't matter, something big */
671 /* Open /proc filesystem file for network devices */
672 procfs
= fopen(PROCFS_NETDEV_FILE
, "r");
675 /* If we can't open the file, return an error */
679 /* Omit first two lines, they are only headers */
680 fgets(buf
, sizeof(buf
), procfs
);
681 fgets(buf
, sizeof(buf
), procfs
);
683 for (i
=0; i
<intNumber
; i
++)
685 /* Skip the lines that don't interest us. */
686 fgets(buf
, sizeof(buf
), procfs
);
688 fgets(buf
, sizeof(buf
), procfs
); /* This is the line we want */
691 /* Parse out the line, grabbing only the name of the device
692 to the intName variable
694 The Line comes in like this: (we only care about the device name)
695 lo: 21970 377 0 0 0 0 0 0 21970 377 0 0 0 0 0 0
698 while (isspace(buf
[i
])) /* Skip initial space(s) */
710 if (buf
[i
] == ':') /* FIXME: Not sure if this block (alias detection) works properly */
712 /* This interface could be an alias... */
714 char *dotname
= intName
;
715 *intName
++ = buf
[i
++];
717 while (isdigit(buf
[i
]))
719 *intName
++ = buf
[i
++];
724 /* ... It wasn't, so back up */
739 *intName
++ = buf
[i
++];
749 Helper function for WsControl - This function returns the bytes (octets) transmitted
750 and received for the supplied interface number from the /proc fs.
752 int WSCNTL_GetTransRecvStat(int intNumber
, unsigned long *transBytes
, unsigned long *recvBytes
)
755 char buf
[512], result
[512]; /* Size doesn't matter, something big */
756 int i
, bufPos
, resultPos
;
758 /* Open /proc filesystem file for network devices */
759 procfs
= fopen(PROCFS_NETDEV_FILE
, "r");
762 /* If we can't open the file, return an error */
766 /* Omit first two lines, they are only headers */
767 fgets(buf
, sizeof(buf
), procfs
);
768 fgets(buf
, sizeof(buf
), procfs
);
770 for (i
=0; i
<intNumber
; i
++)
772 /* Skip the lines that don't interest us. */
773 fgets(buf
, sizeof(buf
), procfs
);
775 fgets(buf
, sizeof(buf
), procfs
); /* This is the line we want */
779 /* Parse out the line, grabbing the number of bytes transmitted
780 and received on the interface.
782 The Line comes in like this: (we care about columns 2 and 10)
783 lo: 21970 377 0 0 0 0 0 0 21970 377 0 0 0 0 0 0
786 /* Start at character 0 in the buffer */
789 /* Skip initial space(s) */
790 while (isspace(buf
[bufPos
]))
794 /* Skip the name and its trailing spaces (if any) */
797 if (isspace(buf
[bufPos
]))
800 if (buf
[bufPos
] == ':') /* Could be an alias */
804 while(isdigit (buf
[bufPos
]))
806 if (buf
[bufPos
] != ':')
808 if (buf
[bufPos
] == '\0')
820 while (isspace(buf
[bufPos
]))
824 /* This column (#2) is the number of bytes received. */
826 while (!isspace(buf
[bufPos
]))
828 result
[resultPos
] = buf
[bufPos
];
829 result
[resultPos
+1]='\0';
830 resultPos
++; bufPos
++;
832 *recvBytes
= strtoul (result
, NULL
, 10); /* convert string to unsigned long, using base 10 */
835 /* Skip columns #3 to #9 (Don't need them) */
838 while (isspace(buf
[bufPos
]))
840 while (!isspace(buf
[bufPos
]))
845 /* This column (#10) is the number of bytes transmitted */
846 while (isspace(buf
[bufPos
]))
850 while (!isspace(buf
[bufPos
]))
852 result
[resultPos
] = buf
[bufPos
];
853 result
[resultPos
+1]='\0';
854 resultPos
++; bufPos
++;
856 *transBytes
= strtoul (result
, NULL
, 10); /* convert string to unsigned long, using base 10 */
864 /* Parse the procfs route file and put the datas into routeTable.
865 * Return value is the number of found routes */
866 int WSCNTL_GetRouteTable(int numRoutes
, wscntl_routeentry
*routeTable
)
868 int nrIntf
; /* total number of interfaces */
869 char buf
[256]; /* temporary buffer */
870 char *ptr
; /* pointer to temporary buffer */
871 FILE *file
; /* file handle for procfs route file */
872 int foundRoutes
= 0; /* number of found routes */
873 typedef struct interface_t
{
874 char intfName
[IFNAMSIZ
+1]; /* the name of the interface */
875 int intfNameLen
; /* length of interface name */
877 interface_t
*interface
;
878 int intfNr
; /* the interface number */
880 wscntl_routeentry
*routePtr
= routeTable
;
882 /* get the number of interfaces */
883 nrIntf
= WSCNTL_GetEntryCount(WSCNTL_COUNT_INTERFACES
);
886 ERR ("Unable to open /proc filesystem to determine number of network interfaces!\n");
890 /* malloc space for the interface struct array */
891 interface
= (interface_t
*) malloc(sizeof(interface_t
) * nrIntf
);
894 ERR ("couldn't malloc space for interface!\n");
897 for (intfNr
= 0; intfNr
< nrIntf
; intfNr
++) {
898 if (WSCNTL_GetInterfaceName(intfNr
, interface
[intfNr
].intfName
) < 0)
900 ERR ("Unable to open /proc filesystem to determine the name of network interfaces!\n");
904 interface
[intfNr
].intfNameLen
= strlen(interface
[intfNr
].intfName
);
907 /* Open /proc filesystem file for routes */
908 file
= fopen(PROCFS_ROUTE_FILE
, "r");
911 /* If we can't open the file, return an error */
916 /* skip the header line */
917 fgets(buf
, sizeof(buf
), file
);
919 /* parse the rest of the file and put the matching entries into routeTable.
920 Format of procfs route entry:
921 Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT
922 lo 0000007F 00000000 0001 0 0 0 000000FF 0 0 0
924 while (fgets(buf
, sizeof(buf
), file
)) {
926 /* find the interface of the route */
927 while ((strncmp(buf
, interface
[intfNr
].intfName
, interface
[intfNr
].intfNameLen
) != 0)
928 && (intfNr
< nrIntf
))
932 if (intfNr
< nrIntf
) {
934 if (foundRoutes
> numRoutes
) {
935 /* output buffer is to small */
936 ERR("buffer to small to fit all routes found into it!\n");
942 ptr
+= interface
[intfNr
].intfNameLen
;
943 routePtr
->wre_intf
= intfNr
;
944 routePtr
->wre_dest
= strtoul(ptr
, &ptr
, 16); /* destination */
945 routePtr
->wre_gw
= strtoul(ptr
, &ptr
, 16); /* gateway */
946 strtoul(ptr
, &ptr
, 16); /* Flags; unused */
947 strtoul(ptr
, &ptr
, 16); /* RefCnt; unused */
948 strtoul(ptr
, &ptr
, 16); /* Use; unused */
949 routePtr
->wre_metric
= strtoul(ptr
, &ptr
, 16); /* metric */
950 routePtr
->wre_mask
= strtoul(ptr
, &ptr
, 16); /* mask */
951 /* strtoul(ptr, &ptr, 16); MTU; unused */
952 /* strtoul(ptr, &ptr, 16); Window; unused */
953 /* strtoul(ptr, &ptr, 16); IRTT; unused */
959 /* this should never happen */
960 WARN("Skipping route with unknown interface\n");
970 /***********************************************************************
971 * WSARecvEx (WSOCK32.1107)
973 * WSARecvEx is a Microsoft specific extension to winsock that is identical to recv
974 * except that has an in/out argument call flags that has the value MSG_PARTIAL ored
975 * into the flags parameter when a partial packet is read. This only applies to
976 * sockets using the datagram protocol. This method does not seem to be implemented
977 * correctly by microsoft as the winsock implementation does not set the MSG_PARTIAL
978 * flag when a fragmented packet arrives.
980 INT WINAPI
WSARecvEx(SOCKET s
, char *buf
, INT len
, INT
*flags
)
982 FIXME("(WSARecvEx) partial packet return value not set \n");
983 return recv(s
, buf
, len
, *flags
);
987 /***********************************************************************
988 * s_perror (WSOCK32.1108)
990 void WINAPI
s_perror(LPCSTR message
)
992 FIXME("(%s): stub\n",message
);