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
43 #define setsockopt linux_setsockopt
44 #define getsockopt linux_getsockopt
57 #ifdef HAVE_SYS_IOCTL_H
58 # include <sys/ioctl.h>
61 #include <sys/types.h>
62 #ifdef HAVE_SYS_SOCKET_H
63 #include <sys/socket.h>
65 #ifdef HAVE_SYS_SOCKIO_H
66 # include <sys/sockio.h>
74 #include "wine/debug.h"
77 #include "wscontrol.h"
79 /* FIXME: The rest of the socket() cdecl<->stdapi stack corruption problem
84 extern SOCKET WINAPI socket(INT af, INT type, INT protocol);
85 extern SOCKET WINAPI recv(SOCKET,char*,int,int);
86 /* Plus some missing prototypes, due to the WS_ prefixing */
87 extern int WINAPI closesocket(SOCKET);
88 extern int WINAPI ioctlsocket(SOCKET,long,u_long*);
91 /* for the get/setsockopt forwarders */
94 extern int WINAPI setsockopt(SOCKET s, INT level, INT optname ,char* optval, INT optlen);
95 extern int WINAPI getsockopt(SOCKET s, INT level, INT optname ,char* optval, INT* optlen);
97 WINE_DEFAULT_DEBUG_CHANNEL(winsock);
99 /* internal remapper function for the IP_ constants */
100 static INT _remap_optname(INT level, INT optname)
102 TRACE("level=%d, optname=%d\n", level, optname);
103 if (level == WS_IPPROTO_IP) {
104 switch (optname) { /***** from value *****/
105 case 2: return 9; /* IP_MULTICAST_IF */
106 case 3: return 10; /* IP_MULTICAST_TTL */
107 case 4: return 11; /* IP_MULTICAST_LOOP */
108 case 5: return 12; /* IP_ADD_MEMBERSHIP */
109 case 6: return 13; /* IP_DROP_MEMBERSHIP */
110 case 7: return 4; /* IP_TTL */
111 case 8: return 3; /* IP_TOS */
112 case 9: return 14; /* IP_DONTFRAGMENT */
113 default: FIXME("Unknown optname %d, can't remap!\n", optname); return optname;
116 /* don't need to do anything */
121 /***********************************************************************
122 * setsockopt (WSOCK32.21)
124 * We have these forwarders because, for reasons unknown to us mere mortals,
125 * the values of the IP_ constants changed between winsock.h and winsock2.h.
126 * So, we need to remap them here.
128 INT WINAPI WS1_setsockopt(SOCKET s, INT level, INT optname, char *optval, INT optlen)
130 return setsockopt(s, level, _remap_optname(level, optname), optval, optlen);
133 /***********************************************************************
134 * getsockopt (WSOCK32.7)
136 INT WINAPI WS1_getsockopt(SOCKET s, INT level, INT optname, char *optval, INT *optlen)
138 return getsockopt(s, level, _remap_optname(level, optname), optval, optlen);
141 /***********************************************************************
142 * WsControl (WSOCK32.1001)
144 * WsControl seems to be an undocumented Win95 function. A lot of
145 * discussion about WsControl can be found on the net, e.g.
146 * Subject: Re: WSOCK32.DLL WsControl Exported Function
147 * From: "Peter Rindfuss" <rindfuss-s@medea.wz-berlin.de>
150 * WSCNTL_TCPIP_QUERY_INFO option is partially implemeted based
151 * on observing the behaviour of WsControl with an app in
152 * Windows 98. It is not fully implemented, and there could
153 * be (are?) errors due to incorrect assumptions made.
156 * WsControl returns WSCTL_SUCCESS on success.
157 * STATUS_BUFFER_TOO_SMALL is returned if the output buffer length
158 * (*pcbResponseInfoLen) is too small, otherwise errors return -1.
160 * It doesn't seem to generate errors that can be retrieved by
165 DWORD WINAPI WsControl(DWORD protocoll,
168 LPDWORD pcbRequestInfoLen,
169 LPVOID pResponseInfo,
170 LPDWORD pcbResponseInfoLen)
172 /* Get the command structure into a pointer we can use,
174 TDIObjectID *pcommand = (TDIObjectID *)pRequestInfo;
176 TRACE (" WsControl TOI_ID=>0x%lx<, {TEI_ENTITY=0x%lx, TEI_INSTANCE=0x%lx}, TOI_CLASS=0x%lx, TOI_TYPE=0x%lx\n",
177 pcommand->toi_id, pcommand->toi_entity.tei_entity, pcommand->toi_entity.tei_instance,
178 pcommand->toi_class, pcommand->toi_type );
184 case WSCNTL_TCPIP_QUERY_INFO:
186 switch (pcommand->toi_id)
189 ENTITY_LIST_ID seems to get number of adapters in the system.
190 (almost like an index to be used when calling other WsControl options)
194 TDIEntityID *baseptr = pResponseInfo;
197 if (pcommand->toi_class != INFO_CLASS_GENERIC &&
198 pcommand->toi_type != INFO_TYPE_PROVIDER)
200 FIXME ("Unexpected Option for ENTITY_LIST_ID request -> toi_class=0x%lx, toi_type=0x%lx\n",
201 pcommand->toi_class, pcommand->toi_type);
202 return (WSAEOPNOTSUPP);
205 numInt = WSCNTL_GetEntryCount(WSCNTL_COUNT_INTERFACES);
208 ERR ("Unable to open /proc filesystem to determine number of network interfaces!\n");
212 if (*pcbResponseInfoLen < sizeof(TDIEntityID)*(numInt*2) )
214 return (STATUS_BUFFER_TOO_SMALL);
218 memset(baseptr, 0, sizeof(TDIEntityID)*(numInt*2));
220 for (i=0; i<numInt; i++)
222 /* tei_instance is an network interface identifier.
223 I'm not quite sure what the difference is between tei_entity values of
224 CL_NL_ENTITY and IF_ENTITY */
225 baseptr->tei_entity = CL_NL_ENTITY; baseptr->tei_instance = i; baseptr++;
226 baseptr->tei_entity = IF_ENTITY; baseptr->tei_instance = i; baseptr++;
229 /* Calculate size of out buffer */
230 *pcbResponseInfoLen = sizeof(TDIEntityID)*(numInt*2);
236 /* ENTITY_TYPE_ID is used to obtain simple information about a
237 network card, such as MAC Address, description, interface type,
238 number of network addresses, etc. */
239 case ENTITY_TYPE_ID: /* ALSO: IP_MIB_STATS_ID */
241 if (pcommand->toi_class == INFO_CLASS_GENERIC && pcommand->toi_type == INFO_TYPE_PROVIDER)
243 if (pcommand->toi_entity.tei_entity == IF_ENTITY)
245 * ((ULONG *)pResponseInfo) = IF_MIB;
247 /* Calculate size of out buffer */
248 *pcbResponseInfoLen = sizeof (ULONG);
251 else if (pcommand->toi_entity.tei_entity == CL_NL_ENTITY)
253 * ((ULONG *)pResponseInfo) = CL_NL_IP;
255 /* Calculate size of out buffer */
256 *pcbResponseInfoLen = sizeof (ULONG);
259 else if (pcommand->toi_class == INFO_CLASS_PROTOCOL &&
260 pcommand->toi_type == INFO_TYPE_PROVIDER)
262 if (pcommand->toi_entity.tei_entity == IF_ENTITY)
264 /* In this case, we are requesting specific information about a
265 a particular network adapter. (MAC Address, speed, data transmitted/received,
268 IFEntry *IntInfo = (IFEntry *) pResponseInfo;
270 #if defined(SIOCGIFHWADDR) || defined(SIOCGENADDR)
276 if (!WSCNTL_GetInterfaceName(pcommand->toi_entity.tei_instance, ifName))
278 ERR ("Unable to parse /proc filesystem!\n");
282 /* Get a socket so that we can use ioctl */
283 if ( (sock = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET)
285 ERR ("Error creating socket!\n");
289 /* 0 out return structure first */
290 memset (IntInfo, 0, sizeof(IFEntry));
293 IntInfo->if_index = pcommand->toi_entity.tei_instance;
295 /* MAC Address - Let's try to do this in a cross-platform way... */
296 #if defined(SIOCGIFHWADDR) /* Linux */
297 strcpy(ifInfo.ifr_name, ifName);
298 if (ioctlsocket(sock, SIOCGIFHWADDR, (ULONG*)&ifInfo) < 0)
300 ERR ("Error obtaining MAC Address!\n");
306 /* FIXME: Is it correct to assume size of 6? */
307 memcpy(IntInfo->if_physaddr, ifInfo.ifr_hwaddr.sa_data, 6);
308 IntInfo->if_physaddrlen=6;
310 #elif defined(SIOCGENADDR) /* Solaris */
311 if (ioctlsocket(sock, SIOCGENADDR, (ULONG*)&ifInfo) < 0)
313 ERR ("Error obtaining MAC Address!\n");
319 /* FIXME: Is it correct to assume size of 6? */
320 memcpy(IntInfo->if_physaddr, ifInfo.ifr_enaddr, 6);
321 IntInfo->if_physaddrlen=6;
324 memset (IntInfo->if_physaddr, 0, 6);
325 ERR ("Unable to determine MAC Address on your platform!\n");
329 /* Interface name and length */
330 strcpy (IntInfo->if_descr, ifName);
331 IntInfo->if_descrlen= strlen (IntInfo->if_descr);
333 /* Obtain bytes transmitted/received for interface */
334 if ( (WSCNTL_GetTransRecvStat(pcommand->toi_entity.tei_instance,
335 &IntInfo->if_inoctets, &IntInfo->if_outoctets)) < 0)
337 ERR ("Error obtaining transmit/receive stats for the network interface!\n");
343 /* FIXME: How should the below be properly calculated? ******************/
344 IntInfo->if_type = 0x6; /* Ethernet (?) */
345 IntInfo->if_speed = 1000000; /* Speed of interface (bits per second?) */
346 /************************************************************************/
349 *pcbResponseInfoLen = sizeof (IFEntry) + IntInfo->if_descrlen;
351 else if (pcommand->toi_entity.tei_entity == CL_NL_ENTITY)
353 IPSNMPInfo *infoStruc = (IPSNMPInfo *) pResponseInfo;
354 int numInt, numRoutes;
356 /* This case is used to obtain general statistics about the
359 if (*pcbResponseInfoLen < sizeof(IPSNMPInfo) )
361 return (STATUS_BUFFER_TOO_SMALL);
366 memset(infoStruc, 0, sizeof(IPSNMPInfo));
368 /* Get the number of interfaces */
369 numInt = WSCNTL_GetEntryCount(WSCNTL_COUNT_INTERFACES);
372 ERR ("Unable to open /proc filesystem to determine number of network interfaces!\n");
375 /* Get the number of routes */
376 numRoutes = WSCNTL_GetEntryCount(WSCNTL_COUNT_ROUTES);
379 ERR ("Unable to open /proc filesystem to determine number of network routes!\n");
383 infoStruc->ipsi_numif = numInt; /* # of interfaces */
384 infoStruc->ipsi_numaddr = numInt; /* # of addresses */
385 infoStruc->ipsi_numroutes = numRoutes; /* # of routes */
387 /* FIXME: How should the below be properly calculated? ******************/
388 infoStruc->ipsi_forwarding = 0x0;
389 infoStruc->ipsi_defaultttl = 0x0;
390 infoStruc->ipsi_inreceives = 0x0;
391 infoStruc->ipsi_inhdrerrors = 0x0;
392 infoStruc->ipsi_inaddrerrors = 0x0;
393 infoStruc->ipsi_forwdatagrams = 0x0;
394 infoStruc->ipsi_inunknownprotos = 0x0;
395 infoStruc->ipsi_indiscards = 0x0;
396 infoStruc->ipsi_indelivers = 0x0;
397 infoStruc->ipsi_outrequests = 0x0;
398 infoStruc->ipsi_routingdiscards = 0x0;
399 infoStruc->ipsi_outdiscards = 0x0;
400 infoStruc->ipsi_outnoroutes = 0x0;
401 infoStruc->ipsi_reasmtimeout = 0x0;
402 infoStruc->ipsi_reasmreqds = 0x0;
403 infoStruc->ipsi_reasmoks = 0x0;
404 infoStruc->ipsi_reasmfails = 0x0;
405 infoStruc->ipsi_fragoks = 0x0;
406 infoStruc->ipsi_fragfails = 0x0;
407 infoStruc->ipsi_fragcreates = 0x0;
408 /************************************************************************/
410 /* Calculate size of out buffer */
411 *pcbResponseInfoLen = sizeof(IPSNMPInfo);
417 FIXME ("Unexpected Option for ENTITY_TYPE_ID request -> toi_class=0x%lx, toi_type=0x%lx\n",
418 pcommand->toi_class, pcommand->toi_type);
420 return (WSAEOPNOTSUPP);
427 /* IP_MIB_ADDRTABLE_ENTRY_ID is used to obtain more detailed information about a
428 particular network adapter */
429 case IP_MIB_ADDRTABLE_ENTRY_ID:
431 IPAddrEntry *baseIPInfo = (IPAddrEntry *) pResponseInfo;
432 char ifName[IFNAMSIZ+1];
436 if (*pcbResponseInfoLen < sizeof(IPAddrEntry))
438 return (STATUS_BUFFER_TOO_SMALL);
441 if (!WSCNTL_GetInterfaceName(pcommand->toi_entity.tei_instance, ifName))
443 ERR ("Unable to parse /proc filesystem!\n");
448 /* Get a socket so we can use ioctl */
449 if ( (sock = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET)
451 ERR ("Error creating socket!\n");
456 memset(baseIPInfo, 0, sizeof(IPAddrEntry) );
459 baseIPInfo->iae_index = pcommand->toi_entity.tei_instance;
462 strcpy (ifInfo.ifr_name, ifName);
463 ifInfo.ifr_addr.sa_family = AF_INET;
464 if (ioctlsocket(sock, SIOCGIFADDR, (ULONG*)&ifInfo) < 0)
466 baseIPInfo->iae_addr = 0x0;
470 struct WS_sockaddr_in* ipTemp = (struct WS_sockaddr_in*)&ifInfo.ifr_addr;
471 baseIPInfo->iae_addr = ipTemp->sin_addr.S_un.S_addr;
474 /* Broadcast Address */
475 strcpy (ifInfo.ifr_name, ifName);
476 if (ioctlsocket(sock, SIOCGIFBRDADDR, (ULONG *)&ifInfo) < 0)
478 baseIPInfo->iae_bcastaddr = 0x0;
482 struct WS_sockaddr_in* ipTemp = (struct WS_sockaddr_in*)&ifInfo.ifr_broadaddr;
483 baseIPInfo->iae_bcastaddr = ipTemp->sin_addr.S_un.S_addr;
487 strcpy(ifInfo.ifr_name, ifName);
488 if (ioctlsocket(sock, SIOCGIFNETMASK, (ULONG *)&ifInfo) < 0)
490 baseIPInfo->iae_mask = 0x0;
494 /* Trying to avoid some compile problems across platforms.
495 (Linux, FreeBSD, Solaris...) */
498 baseIPInfo->iae_mask = 0;
499 ERR ("Unable to determine Netmask on your platform!\n");
501 struct WS_sockaddr_in* ipTemp = (struct WS_sockaddr_in*)&ifInfo.ifr_addr;
502 baseIPInfo->iae_mask = ipTemp->sin_addr.S_un.S_addr;
505 struct WS_sockaddr_in* ipTemp = (struct WS_sockaddr_in*)&ifInfo.ifr_netmask;
506 baseIPInfo->iae_mask = ipTemp->sin_addr.S_un.S_addr;
510 /* FIXME: How should the below be properly calculated? ******************/
511 baseIPInfo->iae_reasmsize = 0x0;
512 baseIPInfo->iae_context = 0x0;
513 baseIPInfo->iae_pad = 0x0;
514 /************************************************************************/
516 /* Calculate size of out buffer */
517 *pcbResponseInfoLen = sizeof(IPAddrEntry);
523 /* This call returns the routing table.
524 * No official documentation found, even the name of the command is unknown.
526 * http://www.cyberport.com/~tangent/programming/winsock/articles/wscontrol.html
527 * and testings done with winipcfg.exe, route.exe and ipconfig.exe.
528 * pcommand->toi_entity.tei_instance seems to be the interface number
529 * but route.exe outputs only the information for the last interface
530 * if only the routes for the pcommand->toi_entity.tei_instance
531 * interface are returned. */
532 case IP_MIB_ROUTETABLE_ENTRY_ID: /* FIXME: not real name. Value is 0x101 */
534 int numRoutes, foundRoutes;
535 wscntl_routeentry *routeTable, *routePtr; /* route table */
537 IPRouteEntry *winRouteTable = (IPRouteEntry *) pResponseInfo;
539 /* Get the number of routes */
540 numRoutes = WSCNTL_GetEntryCount(WSCNTL_COUNT_ROUTES);
543 ERR ("Unable to open /proc filesystem to determine number of network routes!\n");
547 if (*pcbResponseInfoLen < (sizeof(IPRouteEntry) * numRoutes))
549 return (STATUS_BUFFER_TOO_SMALL);
552 /* malloc space for the routeTable */
553 routeTable = (wscntl_routeentry *) malloc(sizeof(wscntl_routeentry) * numRoutes);
556 ERR ("couldn't malloc space for routeTable!\n");
559 /* get the route table */
560 foundRoutes = WSCNTL_GetRouteTable(numRoutes, routeTable);
563 ERR ("Unable to open /proc filesystem to parse the route entries!\n");
567 routePtr = routeTable;
569 /* first 0 out the output buffer */
570 memset(winRouteTable, 0, *pcbResponseInfoLen);
572 /* calculate the length of the data in the output buffer */
573 *pcbResponseInfoLen = sizeof(IPRouteEntry) * foundRoutes;
575 for ( ; foundRoutes > 0; foundRoutes--)
577 winRouteTable->ire_addr = routePtr->wre_dest;
578 winRouteTable->ire_index = routePtr->wre_intf;
579 winRouteTable->ire_metric = routePtr->wre_metric;
580 /* winRouteTable->ire_option4 =
581 winRouteTable->ire_option5 =
582 winRouteTable->ire_option6 = */
583 winRouteTable->ire_gw = routePtr->wre_gw;
584 /* winRouteTable->ire_option8 =
585 winRouteTable->ire_option9 =
586 winRouteTable->ire_option10 = */
587 winRouteTable->ire_mask = routePtr->wre_mask;
588 /* winRouteTable->ire_option12 = */
601 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",
602 pcommand->toi_id, pcommand->toi_entity.tei_entity, pcommand->toi_entity.tei_instance,
603 pcommand->toi_class, pcommand->toi_type);
605 return (WSAEOPNOTSUPP);
612 case WSCNTL_TCPIP_ICMP_ECHO:
614 unsigned int addr = *(unsigned int*)pRequestInfo;
616 int timeout= *(unsigned int*)(inbuf+4);
617 short x1 = *(unsigned short*)(inbuf+8);
618 short sendbufsize = *(unsigned short*)(inbuf+10);
619 char x2 = *(unsigned char*)(inbuf+12);
620 char ttl = *(unsigned char*)(inbuf+13);
621 char service = *(unsigned char*)(inbuf+14);
622 char type= *(unsigned char*)(inbuf+15); /* 0x2: don't fragment*/
625 FIXME("(ICMP_ECHO) to 0x%08x stub \n", addr);
631 FIXME("Protocoll Not Supported -> protocoll=0x%lx, action=0x%lx, Request=%p, RequestLen=%p, Response=%p, ResponseLen=%p\n",
632 protocoll, action, pRequestInfo, pcbRequestInfoLen, pResponseInfo, pcbResponseInfoLen);
634 return (WSAEOPNOTSUPP);
639 return (WSCTL_SUCCESS);
645 Helper function for WsControl - Get count of the number of interfaces
646 or routes by parsing /proc filesystem.
648 int WSCNTL_GetEntryCount(const int entrytype)
652 char buf[512]; /* Size optimized for a typical workstation */
660 case WSCNTL_COUNT_INTERFACES:
662 filename = PROCFS_NETDEV_FILE;
663 count = -2; /* two haeder lines */
667 case WSCNTL_COUNT_ROUTES:
669 filename = PROCFS_ROUTE_FILE;
670 count = -1; /* one haeder line */
680 /* open /proc filesystem file */
681 fd = open(filename, O_RDONLY);
686 /* read the file and count the EOL's */
687 while ((chrread = read(fd, buf, sizeof(buf))) != 0)
694 continue; /* read interupted by a signal, try to read again */
702 while ((ptr = memchr(ptr, '\n', chrread - (int) (ptr - buf))) > 0)
715 Helper function for WsControl - Get name of device from interface number
716 by parsing /proc filesystem.
718 int WSCNTL_GetInterfaceName(int intNumber, char *intName)
721 char buf[512]; /* Size doesn't matter, something big */
724 /* Open /proc filesystem file for network devices */
725 procfs = fopen(PROCFS_NETDEV_FILE, "r");
728 /* If we can't open the file, return an error */
732 /* Omit first two lines, they are only headers */
733 fgets(buf, sizeof(buf), procfs);
734 fgets(buf, sizeof(buf), procfs);
736 for (i=0; i<intNumber; i++)
738 /* Skip the lines that don't interest us. */
739 fgets(buf, sizeof(buf), procfs);
741 fgets(buf, sizeof(buf), procfs); /* This is the line we want */
744 /* Parse out the line, grabbing only the name of the device
745 to the intName variable
747 The Line comes in like this: (we only care about the device name)
748 lo: 21970 377 0 0 0 0 0 0 21970 377 0 0 0 0 0 0
751 while (isspace(buf[i])) /* Skip initial space(s) */
763 if (buf[i] == ':') /* FIXME: Not sure if this block (alias detection) works properly */
765 /* This interface could be an alias... */
767 char *dotname = intName;
768 *intName++ = buf[i++];
770 while (isdigit(buf[i]))
772 *intName++ = buf[i++];
777 /* ... It wasn't, so back up */
792 *intName++ = buf[i++];
802 Helper function for WsControl - This function returns the bytes (octets) transmitted
803 and received for the supplied interface number from the /proc fs.
805 int WSCNTL_GetTransRecvStat(int intNumber, unsigned long *transBytes, unsigned long *recvBytes)
808 char buf[512], result[512]; /* Size doesn't matter, something big */
809 int i, bufPos, resultPos;
811 /* Open /proc filesystem file for network devices */
812 procfs = fopen(PROCFS_NETDEV_FILE, "r");
815 /* If we can't open the file, return an error */
819 /* Omit first two lines, they are only headers */
820 fgets(buf, sizeof(buf), procfs);
821 fgets(buf, sizeof(buf), procfs);
823 for (i=0; i<intNumber; i++)
825 /* Skip the lines that don't interest us. */
826 fgets(buf, sizeof(buf), procfs);
828 fgets(buf, sizeof(buf), procfs); /* This is the line we want */
832 /* Parse out the line, grabbing the number of bytes transmitted
833 and received on the interface.
835 The Line comes in like this: (we care about columns 2 and 10)
836 lo: 21970 377 0 0 0 0 0 0 21970 377 0 0 0 0 0 0
839 /* Start at character 0 in the buffer */
842 /* Skip initial space(s) */
843 while (isspace(buf[bufPos]))
847 /* Skip the name and its trailing spaces (if any) */
850 if (isspace(buf[bufPos]))
853 if (buf[bufPos] == ':') /* Could be an alias */
857 while(isdigit (buf[bufPos]))
859 if (buf[bufPos] != ':')
861 if (buf[bufPos] == '\0')
873 while (isspace(buf[bufPos]))
877 /* This column (#2) is the number of bytes received. */
879 while (!isspace(buf[bufPos]))
881 result[resultPos] = buf[bufPos];
882 result[resultPos+1]='\0';
883 resultPos++; bufPos++;
885 *recvBytes = strtoul (result, NULL, 10); /* convert string to unsigned long, using base 10 */
888 /* Skip columns #3 to #9 (Don't need them) */
891 while (isspace(buf[bufPos]))
893 while (!isspace(buf[bufPos]))
898 /* This column (#10) is the number of bytes transmitted */
899 while (isspace(buf[bufPos]))
903 while (!isspace(buf[bufPos]))
905 result[resultPos] = buf[bufPos];
906 result[resultPos+1]='\0';
907 resultPos++; bufPos++;
909 *transBytes = strtoul (result, NULL, 10); /* convert string to unsigned long, using base 10 */
917 /* Parse the procfs route file and put the datas into routeTable.
918 * Return value is the number of found routes */
919 int WSCNTL_GetRouteTable(int numRoutes, wscntl_routeentry *routeTable)
921 int nrIntf; /* total number of interfaces */
922 char buf[256]; /* temporary buffer */
923 char *ptr; /* pointer to temporary buffer */
924 FILE *file; /* file handle for procfs route file */
925 int foundRoutes = 0; /* number of found routes */
926 typedef struct interface_t {
927 char intfName[IFNAMSIZ+1]; /* the name of the interface */
928 int intfNameLen; /* length of interface name */
930 interface_t *interface;
931 int intfNr; /* the interface number */
933 wscntl_routeentry *routePtr = routeTable;
935 /* get the number of interfaces */
936 nrIntf = WSCNTL_GetEntryCount(WSCNTL_COUNT_INTERFACES);
939 ERR ("Unable to open /proc filesystem to determine number of network interfaces!\n");
943 /* malloc space for the interface struct array */
944 interface = (interface_t *) malloc(sizeof(interface_t) * nrIntf);
947 ERR ("couldn't malloc space for interface!\n");
950 for (intfNr = 0; intfNr < nrIntf; intfNr++) {
951 if (WSCNTL_GetInterfaceName(intfNr, interface[intfNr].intfName) < 0)
953 ERR ("Unable to open /proc filesystem to determine the name of network interfaces!\n");
957 interface[intfNr].intfNameLen = strlen(interface[intfNr].intfName);
960 /* Open /proc filesystem file for routes */
961 file = fopen(PROCFS_ROUTE_FILE, "r");
964 /* If we can't open the file, return an error */
969 /* skip the header line */
970 fgets(buf, sizeof(buf), file);
972 /* parse the rest of the file and put the matching entries into routeTable.
973 Format of procfs route entry:
974 Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT
975 lo 0000007F 00000000 0001 0 0 0 000000FF 0 0 0
977 while (fgets(buf, sizeof(buf), file)) {
979 /* find the interface of the route */
980 while ((strncmp(buf, interface[intfNr].intfName, interface[intfNr].intfNameLen) != 0)
981 && (intfNr < nrIntf))
985 if (intfNr < nrIntf) {
987 if (foundRoutes > numRoutes) {
988 /* output buffer is to small */
989 ERR("buffer to small to fit all routes found into it!\n");
995 ptr += interface[intfNr].intfNameLen;
996 routePtr->wre_intf = intfNr;
997 routePtr->wre_dest = strtoul(ptr, &ptr, 16); /* destination */
998 routePtr->wre_gw = strtoul(ptr, &ptr, 16); /* gateway */
999 strtoul(ptr, &ptr, 16); /* Flags; unused */
1000 strtoul(ptr, &ptr, 16); /* RefCnt; unused */
1001 strtoul(ptr, &ptr, 16); /* Use; unused */
1002 routePtr->wre_metric = strtoul(ptr, &ptr, 16); /* metric */
1003 routePtr->wre_mask = strtoul(ptr, &ptr, 16); /* mask */
1004 /* strtoul(ptr, &ptr, 16); MTU; unused */
1005 /* strtoul(ptr, &ptr, 16); Window; unused */
1006 /* strtoul(ptr, &ptr, 16); IRTT; unused */
1012 /* this should never happen */
1013 WARN("Skipping route with unknown interface\n");
1023 /***********************************************************************
1024 * WSARecvEx (WSOCK32.1107)
1026 * WSARecvEx is a Microsoft specific extension to winsock that is identical to recv
1027 * except that has an in/out argument call flags that has the value MSG_PARTIAL ored
1028 * into the flags parameter when a partial packet is read. This only applies to
1029 * sockets using the datagram protocol. This method does not seem to be implemented
1030 * correctly by microsoft as the winsock implementation does not set the MSG_PARTIAL
1031 * flag when a fragmented packet arrives.
1033 INT WINAPI WSARecvEx(SOCKET s, char *buf, INT len, INT *flags)
1035 FIXME("(WSARecvEx) partial packet return value not set \n");
1036 return recv(s, buf, len, *flags);
1040 /***********************************************************************
1041 * s_perror (WSOCK32.1108)
1043 void WINAPI s_perror(LPCSTR message)
1045 FIXME("(%s): stub\n",message);