2 * WSOCK32 specific functions
4 * Copyright (C) 1993,1994,1996,1997 John Brezak, Erik Bos, Alex Korobka.
8 /* FIXME: This hack is fixing a problem in WsControl. When we call socket(),
9 * it will call into ws2_32's WSOCK32_socket (because of the redirection in
10 * our own .spec file).
11 * The problem is that socket() is predefined in a linux system header that
12 * we are including, which is different from the WINE definition.
13 * (cdecl vs. stdapi). The result is stack corruption.
14 * Furthermore WsControl uses Unix macros and types. This forces us to include
15 * the Unix headers which then conflict with the winsock headers. This forces
16 * us to use USE_WS_PREFIX but then ioctlsocket is called WS_ioctlsocket,
17 * which causes link problems. The correct solution is to implement
18 * WsControl using calls to WSAIoctl. Then we should no longer need to use the
19 * Unix headers. This would also have the advantage of reducing code
21 * Until that happens we need this ugly hack.
25 #define socket linux_socket
26 #define recv linux_recv
38 #include <sys/ioctl.h>
40 #include <sys/types.h>
41 #ifdef HAVE_SYS_SOCKET_H
42 #include <sys/socket.h>
44 #ifdef HAVE_SYS_SOCKIO_H
45 # include <sys/sockio.h>
53 #include "debugtools.h"
56 #include "wscontrol.h"
58 /* FIXME: The rest of the socket() cdecl<->stdapi stack corruption problem
63 extern SOCKET WINAPI socket(INT af, INT type, INT protocol);
64 extern SOCKET WINAPI recv(SOCKET,char*,int,int);
65 /* Plus some missing prototypes, due to the WS_ prefixing */
66 extern int WINAPI closesocket(SOCKET);
67 extern int WINAPI ioctlsocket(SOCKET,long,u_long*);
71 DEFAULT_DEBUG_CHANNEL(winsock);
74 /***********************************************************************
75 * WsControl (WSOCK32.1001)
77 * WsControl seems to be an undocumented Win95 function. A lot of
78 * discussion about WsControl can be found on the net, e.g.
79 * Subject: Re: WSOCK32.DLL WsControl Exported Function
80 * From: "Peter Rindfuss" <rindfuss-s@medea.wz-berlin.de>
83 * WSCNTL_TCPIP_QUERY_INFO option is partially implemeted based
84 * on observing the behaviour of WsControl with an app in
85 * Windows 98. It is not fully implemented, and there could
86 * be (are?) errors due to incorrect assumptions made.
89 * WsControl returns WSCTL_SUCCESS on success.
90 * STATUS_BUFFER_TOO_SMALL is returned if the output buffer length
91 * (*pcbResponseInfoLen) is too small, otherwise errors return -1.
93 * It doesn't seem to generate errors that can be retrieved by
98 DWORD WINAPI WsControl(DWORD protocoll,
101 LPDWORD pcbRequestInfoLen,
102 LPVOID pResponseInfo,
103 LPDWORD pcbResponseInfoLen)
105 /* Get the command structure into a pointer we can use,
107 TDIObjectID *pcommand = (TDIObjectID *)pRequestInfo;
109 TRACE (" WsControl TOI_ID=>0x%lx<, {TEI_ENTITY=0x%lx, TEI_INSTANCE=0x%lx}, TOI_CLASS=0x%lx, TOI_TYPE=0x%lx\n",
110 pcommand->toi_id, pcommand->toi_entity.tei_entity, pcommand->toi_entity.tei_instance,
111 pcommand->toi_class, pcommand->toi_type );
117 case WSCNTL_TCPIP_QUERY_INFO:
119 switch (pcommand->toi_id)
122 ENTITY_LIST_ID seems to get number of adapters in the system.
123 (almost like an index to be used when calling other WsControl options)
127 TDIEntityID *baseptr = pResponseInfo;
130 if (pcommand->toi_class != INFO_CLASS_GENERIC &&
131 pcommand->toi_type != INFO_TYPE_PROVIDER)
133 FIXME ("Unexpected Option for ENTITY_LIST_ID request -> toi_class=0x%lx, toi_type=0x%lx\n",
134 pcommand->toi_class, pcommand->toi_type);
135 return (WSAEOPNOTSUPP);
138 numInt = WSCNTL_GetEntryCount(WSCNTL_COUNT_INTERFACES);
141 ERR ("Unable to open /proc filesystem to determine number of network interfaces!\n");
145 if (*pcbResponseInfoLen < sizeof(TDIEntityID)*(numInt*2) )
147 return (STATUS_BUFFER_TOO_SMALL);
151 memset(baseptr, 0, sizeof(TDIEntityID)*(numInt*2));
153 for (i=0; i<numInt; i++)
155 /* tei_instance is an network interface identifier.
156 I'm not quite sure what the difference is between tei_entity values of
157 CL_NL_ENTITY and IF_ENTITY */
158 baseptr->tei_entity = CL_NL_ENTITY; baseptr->tei_instance = i; baseptr++;
159 baseptr->tei_entity = IF_ENTITY; baseptr->tei_instance = i; baseptr++;
162 /* Calculate size of out buffer */
163 *pcbResponseInfoLen = sizeof(TDIEntityID)*(numInt*2);
169 /* ENTITY_TYPE_ID is used to obtain simple information about a
170 network card, such as MAC Address, description, interface type,
171 number of network addresses, etc. */
172 case ENTITY_TYPE_ID: /* ALSO: IP_MIB_STATS_ID */
174 if (pcommand->toi_class == INFO_CLASS_GENERIC && pcommand->toi_type == INFO_TYPE_PROVIDER)
176 if (pcommand->toi_entity.tei_entity == IF_ENTITY)
178 * ((ULONG *)pResponseInfo) = IF_MIB;
180 /* Calculate size of out buffer */
181 *pcbResponseInfoLen = sizeof (ULONG);
184 else if (pcommand->toi_entity.tei_entity == CL_NL_ENTITY)
186 * ((ULONG *)pResponseInfo) = CL_NL_IP;
188 /* Calculate size of out buffer */
189 *pcbResponseInfoLen = sizeof (ULONG);
192 else if (pcommand->toi_class == INFO_CLASS_PROTOCOL &&
193 pcommand->toi_type == INFO_TYPE_PROVIDER)
195 if (pcommand->toi_entity.tei_entity == IF_ENTITY)
197 /* In this case, we are requesting specific information about a
198 a particular network adapter. (MAC Address, speed, data transmitted/received,
201 IFEntry *IntInfo = (IFEntry *) pResponseInfo;
203 #if defined(SIOCGIFHWADDR) || defined(SIOCGENADDR)
209 if (!WSCNTL_GetInterfaceName(pcommand->toi_entity.tei_instance, ifName))
211 ERR ("Unable to parse /proc filesystem!\n");
215 /* Get a socket so that we can use ioctl */
216 if ( (sock = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET)
218 ERR ("Error creating socket!\n");
222 /* 0 out return structure first */
223 memset (IntInfo, 0, sizeof(IFEntry));
226 IntInfo->if_index = pcommand->toi_entity.tei_instance;
228 /* MAC Address - Let's try to do this in a cross-platform way... */
229 #if defined(SIOCGIFHWADDR) /* Linux */
230 strcpy(ifInfo.ifr_name, ifName);
231 if (ioctlsocket(sock, SIOCGIFHWADDR, (ULONG*)&ifInfo) < 0)
233 ERR ("Error obtaining MAC Address!\n");
239 /* FIXME: Is it correct to assume size of 6? */
240 memcpy(IntInfo->if_physaddr, ifInfo.ifr_hwaddr.sa_data, 6);
241 IntInfo->if_physaddrlen=6;
243 #elif defined(SIOCGENADDR) /* Solaris */
244 if (ioctlsocket(sock, SIOCGENADDR, (ULONG*)&ifInfo) < 0)
246 ERR ("Error obtaining MAC Address!\n");
252 /* FIXME: Is it correct to assume size of 6? */
253 memcpy(IntInfo->if_physaddr, ifInfo.ifr_enaddr, 6);
254 IntInfo->if_physaddrlen=6;
257 memset (IntInfo->if_physaddr, 0, 6);
258 ERR ("Unable to determine MAC Address on your platform!\n");
262 /* Interface name and length */
263 strcpy (IntInfo->if_descr, ifName);
264 IntInfo->if_descrlen= strlen (IntInfo->if_descr);
266 /* Obtain bytes transmitted/received for interface */
267 if ( (WSCNTL_GetTransRecvStat(pcommand->toi_entity.tei_instance,
268 &IntInfo->if_inoctets, &IntInfo->if_outoctets)) < 0)
270 ERR ("Error obtaining transmit/receive stats for the network interface!\n");
276 /* FIXME: How should the below be properly calculated? ******************/
277 IntInfo->if_type = 0x6; /* Ethernet (?) */
278 IntInfo->if_speed = 1000000; /* Speed of interface (bits per second?) */
279 /************************************************************************/
282 *pcbResponseInfoLen = sizeof (IFEntry) + IntInfo->if_descrlen;
284 else if (pcommand->toi_entity.tei_entity == CL_NL_ENTITY)
286 IPSNMPInfo *infoStruc = (IPSNMPInfo *) pResponseInfo;
287 int numInt, numRoutes;
289 /* This case is used to obtain general statistics about the
292 if (*pcbResponseInfoLen < sizeof(IPSNMPInfo) )
294 return (STATUS_BUFFER_TOO_SMALL);
299 memset(infoStruc, 0, sizeof(IPSNMPInfo));
301 /* Get the number of interfaces */
302 numInt = WSCNTL_GetEntryCount(WSCNTL_COUNT_INTERFACES);
305 ERR ("Unable to open /proc filesystem to determine number of network interfaces!\n");
308 /* Get the number of routes */
309 numRoutes = WSCNTL_GetEntryCount(WSCNTL_COUNT_ROUTES);
312 ERR ("Unable to open /proc filesystem to determine number of network routes!\n");
316 infoStruc->ipsi_numif = numInt; /* # of interfaces */
317 infoStruc->ipsi_numaddr = numInt; /* # of addresses */
318 infoStruc->ipsi_numroutes = numRoutes; /* # of routes */
320 /* FIXME: How should the below be properly calculated? ******************/
321 infoStruc->ipsi_forwarding = 0x0;
322 infoStruc->ipsi_defaultttl = 0x0;
323 infoStruc->ipsi_inreceives = 0x0;
324 infoStruc->ipsi_inhdrerrors = 0x0;
325 infoStruc->ipsi_inaddrerrors = 0x0;
326 infoStruc->ipsi_forwdatagrams = 0x0;
327 infoStruc->ipsi_inunknownprotos = 0x0;
328 infoStruc->ipsi_indiscards = 0x0;
329 infoStruc->ipsi_indelivers = 0x0;
330 infoStruc->ipsi_outrequests = 0x0;
331 infoStruc->ipsi_routingdiscards = 0x0;
332 infoStruc->ipsi_outdiscards = 0x0;
333 infoStruc->ipsi_outnoroutes = 0x0;
334 infoStruc->ipsi_reasmtimeout = 0x0;
335 infoStruc->ipsi_reasmreqds = 0x0;
336 infoStruc->ipsi_reasmoks = 0x0;
337 infoStruc->ipsi_reasmfails = 0x0;
338 infoStruc->ipsi_fragoks = 0x0;
339 infoStruc->ipsi_fragfails = 0x0;
340 infoStruc->ipsi_fragcreates = 0x0;
341 /************************************************************************/
343 /* Calculate size of out buffer */
344 *pcbResponseInfoLen = sizeof(IPSNMPInfo);
350 FIXME ("Unexpected Option for ENTITY_TYPE_ID request -> toi_class=0x%lx, toi_type=0x%lx\n",
351 pcommand->toi_class, pcommand->toi_type);
353 return (WSAEOPNOTSUPP);
360 /* IP_MIB_ADDRTABLE_ENTRY_ID is used to obtain more detailed information about a
361 particular network adapter */
362 case IP_MIB_ADDRTABLE_ENTRY_ID:
364 IPAddrEntry *baseIPInfo = (IPAddrEntry *) pResponseInfo;
365 char ifName[IFNAMSIZ+1];
369 if (*pcbResponseInfoLen < sizeof(IPAddrEntry))
371 return (STATUS_BUFFER_TOO_SMALL);
374 if (!WSCNTL_GetInterfaceName(pcommand->toi_entity.tei_instance, ifName))
376 ERR ("Unable to parse /proc filesystem!\n");
381 /* Get a socket so we can use ioctl */
382 if ( (sock = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET)
384 ERR ("Error creating socket!\n");
389 memset(baseIPInfo, 0, sizeof(IPAddrEntry) );
392 baseIPInfo->iae_index = pcommand->toi_entity.tei_instance;
395 strcpy (ifInfo.ifr_name, ifName);
396 ifInfo.ifr_addr.sa_family = AF_INET;
397 if (ioctlsocket(sock, SIOCGIFADDR, (ULONG*)&ifInfo) < 0)
399 baseIPInfo->iae_addr = 0x0;
403 struct WS_sockaddr_in* ipTemp = (struct WS_sockaddr_in*)&ifInfo.ifr_addr;
404 baseIPInfo->iae_addr = ipTemp->sin_addr.S_un.S_addr;
407 /* Broadcast Address */
408 strcpy (ifInfo.ifr_name, ifName);
409 if (ioctlsocket(sock, SIOCGIFBRDADDR, (ULONG *)&ifInfo) < 0)
411 baseIPInfo->iae_bcastaddr = 0x0;
415 struct WS_sockaddr_in* ipTemp = (struct WS_sockaddr_in*)&ifInfo.ifr_broadaddr;
416 baseIPInfo->iae_bcastaddr = ipTemp->sin_addr.S_un.S_addr;
420 strcpy(ifInfo.ifr_name, ifName);
421 if (ioctlsocket(sock, SIOCGIFNETMASK, (ULONG *)&ifInfo) < 0)
423 baseIPInfo->iae_mask = 0x0;
427 /* Trying to avoid some compile problems across platforms.
428 (Linux, FreeBSD, Solaris...) */
431 baseIPInfo->iae_mask = 0;
432 ERR ("Unable to determine Netmask on your platform!\n");
434 struct WS_sockaddr_in* ipTemp = (struct WS_sockaddr_in*)&ifInfo.ifr_addr;
435 baseIPInfo->iae_mask = ipTemp->sin_addr.S_un.S_addr;
438 struct WS_sockaddr_in* ipTemp = (struct WS_sockaddr_in*)&ifInfo.ifr_netmask;
439 baseIPInfo->iae_mask = ipTemp->sin_addr.S_un.S_addr;
443 /* FIXME: How should the below be properly calculated? ******************/
444 baseIPInfo->iae_reasmsize = 0x0;
445 baseIPInfo->iae_context = 0x0;
446 baseIPInfo->iae_pad = 0x0;
447 /************************************************************************/
449 /* Calculate size of out buffer */
450 *pcbResponseInfoLen = sizeof(IPAddrEntry);
456 /* This call returns the routing table.
457 * No official documentation found, even the name of the command is unknown.
459 * http://www.cyberport.com/~tangent/programming/winsock/articles/wscontrol.html
460 * and testings done with winipcfg.exe, route.exe and ipconfig.exe.
461 * pcommand->toi_entity.tei_instance seems to be the interface number
462 * but route.exe outputs only the information for the last interface
463 * if only the routes for the pcommand->toi_entity.tei_instance
464 * interface are returned. */
465 case IP_MIB_ROUTETABLE_ENTRY_ID: /* FIXME: not real name. Value is 0x101 */
467 int numRoutes, foundRoutes;
468 wscntl_routeentry *routeTable, *routePtr; /* route table */
470 IPRouteEntry *winRouteTable = (IPRouteEntry *) pResponseInfo;
472 /* Get the number of routes */
473 numRoutes = WSCNTL_GetEntryCount(WSCNTL_COUNT_ROUTES);
476 ERR ("Unable to open /proc filesystem to determine number of network routes!\n");
480 if (*pcbResponseInfoLen < (sizeof(IPRouteEntry) * numRoutes))
482 return (STATUS_BUFFER_TOO_SMALL);
485 /* malloc space for the routeTable */
486 routeTable = (wscntl_routeentry *) malloc(sizeof(wscntl_routeentry) * numRoutes);
489 ERR ("couldn't malloc space for routeTable!\n");
492 /* get the route table */
493 foundRoutes = WSCNTL_GetRouteTable(numRoutes, routeTable);
496 ERR ("Unable to open /proc filesystem to parse the route entries!\n");
500 routePtr = routeTable;
502 /* first 0 out the output buffer */
503 memset(winRouteTable, 0, *pcbResponseInfoLen);
505 /* calculate the length of the data in the output buffer */
506 *pcbResponseInfoLen = sizeof(IPRouteEntry) * foundRoutes;
508 for ( ; foundRoutes > 0; foundRoutes--)
510 winRouteTable->ire_addr = routePtr->wre_dest;
511 winRouteTable->ire_index = routePtr->wre_intf;
512 winRouteTable->ire_metric = routePtr->wre_metric;
513 /* winRouteTable->ire_option4 =
514 winRouteTable->ire_option5 =
515 winRouteTable->ire_option6 = */
516 winRouteTable->ire_gw = routePtr->wre_gw;
517 /* winRouteTable->ire_option8 =
518 winRouteTable->ire_option9 =
519 winRouteTable->ire_option10 = */
520 winRouteTable->ire_mask = routePtr->wre_mask;
521 /* winRouteTable->ire_option12 = */
534 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",
535 pcommand->toi_id, pcommand->toi_entity.tei_entity, pcommand->toi_entity.tei_instance,
536 pcommand->toi_class, pcommand->toi_type);
538 return (WSAEOPNOTSUPP);
545 case WSCNTL_TCPIP_ICMP_ECHO:
547 unsigned int addr = *(unsigned int*)pRequestInfo;
549 int timeout= *(unsigned int*)(inbuf+4);
550 short x1 = *(unsigned short*)(inbuf+8);
551 short sendbufsize = *(unsigned short*)(inbuf+10);
552 char x2 = *(unsigned char*)(inbuf+12);
553 char ttl = *(unsigned char*)(inbuf+13);
554 char service = *(unsigned char*)(inbuf+14);
555 char type= *(unsigned char*)(inbuf+15); /* 0x2: don't fragment*/
558 FIXME("(ICMP_ECHO) to 0x%08x stub \n", addr);
564 FIXME("Protocoll Not Supported -> protocoll=0x%lx, action=0x%lx, Request=%p, RequestLen=%p, Response=%p, ResponseLen=%p\n",
565 protocoll, action, pRequestInfo, pcbRequestInfoLen, pResponseInfo, pcbResponseInfoLen);
567 return (WSAEOPNOTSUPP);
572 return (WSCTL_SUCCESS);
578 Helper function for WsControl - Get count of the number of interfaces
579 or routes by parsing /proc filesystem.
581 int WSCNTL_GetEntryCount(const int entrytype)
585 char buf[512]; /* Size optimized for a typical workstation */
593 case WSCNTL_COUNT_INTERFACES:
595 filename = PROCFS_NETDEV_FILE;
596 count = -2; /* two haeder lines */
600 case WSCNTL_COUNT_ROUTES:
602 filename = PROCFS_ROUTE_FILE;
603 count = -1; /* one haeder line */
613 /* open /proc filesystem file */
614 fd = open(filename, O_RDONLY);
619 /* read the file and count the EOL's */
620 while ((chrread = read(fd, buf, sizeof(buf))) != 0)
627 continue; /* read interupted by a signal, try to read again */
635 while ((ptr = memchr(ptr, '\n', chrread - (int) (ptr - buf))) > 0)
648 Helper function for WsControl - Get name of device from interface number
649 by parsing /proc filesystem.
651 int WSCNTL_GetInterfaceName(int intNumber, char *intName)
654 char buf[512]; /* Size doesn't matter, something big */
657 /* Open /proc filesystem file for network devices */
658 procfs = fopen(PROCFS_NETDEV_FILE, "r");
661 /* If we can't open the file, return an error */
665 /* Omit first two lines, they are only headers */
666 fgets(buf, sizeof(buf), procfs);
667 fgets(buf, sizeof(buf), procfs);
669 for (i=0; i<intNumber; i++)
671 /* Skip the lines that don't interest us. */
672 fgets(buf, sizeof(buf), procfs);
674 fgets(buf, sizeof(buf), procfs); /* This is the line we want */
677 /* Parse out the line, grabbing only the name of the device
678 to the intName variable
680 The Line comes in like this: (we only care about the device name)
681 lo: 21970 377 0 0 0 0 0 0 21970 377 0 0 0 0 0 0
684 while (isspace(buf[i])) /* Skip initial space(s) */
696 if (buf[i] == ':') /* FIXME: Not sure if this block (alias detection) works properly */
698 /* This interface could be an alias... */
700 char *dotname = intName;
701 *intName++ = buf[i++];
703 while (isdigit(buf[i]))
705 *intName++ = buf[i++];
710 /* ... It wasn't, so back up */
725 *intName++ = buf[i++];
735 Helper function for WsControl - This function returns the bytes (octets) transmitted
736 and received for the supplied interface number from the /proc fs.
738 int WSCNTL_GetTransRecvStat(int intNumber, unsigned long *transBytes, unsigned long *recvBytes)
741 char buf[512], result[512]; /* Size doesn't matter, something big */
742 int i, bufPos, resultPos;
744 /* Open /proc filesystem file for network devices */
745 procfs = fopen(PROCFS_NETDEV_FILE, "r");
748 /* If we can't open the file, return an error */
752 /* Omit first two lines, they are only headers */
753 fgets(buf, sizeof(buf), procfs);
754 fgets(buf, sizeof(buf), procfs);
756 for (i=0; i<intNumber; i++)
758 /* Skip the lines that don't interest us. */
759 fgets(buf, sizeof(buf), procfs);
761 fgets(buf, sizeof(buf), procfs); /* This is the line we want */
765 /* Parse out the line, grabbing the number of bytes transmitted
766 and received on the interface.
768 The Line comes in like this: (we care about columns 2 and 10)
769 lo: 21970 377 0 0 0 0 0 0 21970 377 0 0 0 0 0 0
772 /* Start at character 0 in the buffer */
775 /* Skip initial space(s) */
776 while (isspace(buf[bufPos]))
780 /* Skip the name and its trailing spaces (if any) */
783 if (isspace(buf[bufPos]))
786 if (buf[bufPos] == ':') /* Could be an alias */
790 while(isdigit (buf[bufPos]))
792 if (buf[bufPos] != ':')
794 if (buf[bufPos] == '\0')
806 while (isspace(buf[bufPos]))
810 /* This column (#2) is the number of bytes received. */
812 while (!isspace(buf[bufPos]))
814 result[resultPos] = buf[bufPos];
815 result[resultPos+1]='\0';
816 resultPos++; bufPos++;
818 *recvBytes = strtoul (result, NULL, 10); /* convert string to unsigned long, using base 10 */
821 /* Skip columns #3 to #9 (Don't need them) */
824 while (isspace(buf[bufPos]))
826 while (!isspace(buf[bufPos]))
831 /* This column (#10) is the number of bytes transmitted */
832 while (isspace(buf[bufPos]))
836 while (!isspace(buf[bufPos]))
838 result[resultPos] = buf[bufPos];
839 result[resultPos+1]='\0';
840 resultPos++; bufPos++;
842 *transBytes = strtoul (result, NULL, 10); /* convert string to unsigned long, using base 10 */
850 /* Parse the procfs route file and put the datas into routeTable.
851 * Return value is the number of found routes */
852 int WSCNTL_GetRouteTable(int numRoutes, wscntl_routeentry *routeTable)
854 int nrIntf; /* total number of interfaces */
855 char buf[256]; /* temporary buffer */
856 char *ptr; /* pointer to temporary buffer */
857 FILE *file; /* file handle for procfs route file */
858 int foundRoutes = 0; /* number of found routes */
859 typedef struct interface_t {
860 char intfName[IFNAMSIZ+1]; /* the name of the interface */
861 int intfNameLen; /* length of interface name */
863 interface_t *interface;
864 int intfNr; /* the interface number */
866 wscntl_routeentry *routePtr = routeTable;
868 /* get the number of interfaces */
869 nrIntf = WSCNTL_GetEntryCount(WSCNTL_COUNT_INTERFACES);
872 ERR ("Unable to open /proc filesystem to determine number of network interfaces!\n");
876 /* malloc space for the interface struct array */
877 interface = (interface_t *) malloc(sizeof(interface_t) * nrIntf);
880 ERR ("couldn't malloc space for interface!\n");
883 for (intfNr = 0; intfNr < nrIntf; intfNr++) {
884 if (WSCNTL_GetInterfaceName(intfNr, interface[intfNr].intfName) < 0)
886 ERR ("Unable to open /proc filesystem to determine the name of network interfaces!\n");
890 interface[intfNr].intfNameLen = strlen(interface[intfNr].intfName);
893 /* Open /proc filesystem file for routes */
894 file = fopen(PROCFS_ROUTE_FILE, "r");
897 /* If we can't open the file, return an error */
902 /* skip the header line */
903 fgets(buf, sizeof(buf), file);
905 /* parse the rest of the file and put the matching entries into routeTable.
906 Format of procfs route entry:
907 Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT
908 lo 0000007F 00000000 0001 0 0 0 000000FF 0 0 0
910 while (fgets(buf, sizeof(buf), file)) {
912 /* find the interface of the route */
913 while ((strncmp(buf, interface[intfNr].intfName, interface[intfNr].intfNameLen) != 0)
914 && (intfNr < nrIntf))
918 if (intfNr < nrIntf) {
920 if (foundRoutes > numRoutes) {
921 /* output buffer is to small */
922 ERR("buffer to small to fit all routes found into it!\n");
928 ptr += interface[intfNr].intfNameLen;
929 routePtr->wre_intf = intfNr;
930 routePtr->wre_dest = strtoul(ptr, &ptr, 16); /* destination */
931 routePtr->wre_gw = strtoul(ptr, &ptr, 16); /* gateway */
932 strtoul(ptr, &ptr, 16); /* Flags; unused */
933 strtoul(ptr, &ptr, 16); /* RefCnt; unused */
934 strtoul(ptr, &ptr, 16); /* Use; unused */
935 routePtr->wre_metric = strtoul(ptr, &ptr, 16); /* metric */
936 routePtr->wre_mask = strtoul(ptr, &ptr, 16); /* mask */
937 /* strtoul(ptr, &ptr, 16); MTU; unused */
938 /* strtoul(ptr, &ptr, 16); Window; unused */
939 /* strtoul(ptr, &ptr, 16); IRTT; unused */
945 /* this should never happen */
946 WARN("Skipping route with unknown interface\n");
956 /***********************************************************************
957 * WSARecvEx (WSOCK32.1107)
959 * WSARecvEx is a Microsoft specific extension to winsock that is identical to recv
960 * except that has an in/out argument call flags that has the value MSG_PARTIAL ored
961 * into the flags parameter when a partial packet is read. This only applies to
962 * sockets using the datagram protocol. This method does not seem to be implemented
963 * correctly by microsoft as the winsock implementation does not set the MSG_PARTIAL
964 * flag when a fragmented packet arrives.
966 INT WINAPI WSARecvEx(SOCKET s, char *buf, INT len, INT *flags)
968 FIXME("(WSARecvEx) partial packet return value not set \n");
969 return recv(s, buf, len, *flags);
973 /***********************************************************************
974 * s_perror (WSOCK32.1108)
976 void WINAPI s_perror(LPCSTR message)
978 FIXME("(%s): stub\n",message);