2 * WSOCK32 specific functions
4 * Copyright (C) 1993,1994,1996,1997 John Brezak, Erik Bos, Alex Korobka.
9 FIXME: This hack is fixing a problem in WsControl. When we call socket(),
10 it is supposed to call into ws2_32's WSOCK32_socket.
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.
15 The correct answer to this problem is to make winsock.h not dependent
16 on system headers, that way all of our functions are defined consistently.
17 Until that happens we need this hack.
19 #define socket linux_socket
25 #include <sys/types.h>
28 #include "debugtools.h"
31 #include "wscontrol.h"
33 #include <sys/ioctl.h>
37 #ifdef HAVE_SYS_SOCKIO_H
38 # include <sys/sockio.h>
46 /* FIXME: The rest of the socket() cdecl<->stdapi stack corruption problem
49 extern SOCKET WINAPI socket(INT af, INT type, INT protocol);
53 DEFAULT_DEBUG_CHANNEL(winsock);
56 /***********************************************************************
59 * WsControl seems to be an undocumented Win95 function. A lot of
60 * discussion about WsControl can be found on the net, e.g.
61 * Subject: Re: WSOCK32.DLL WsControl Exported Function
62 * From: "Peter Rindfuss" <rindfuss-s@medea.wz-berlin.de>
65 * WSCNTL_TCPIP_QUERY_INFO option is partially implemeted based
66 * on observing the behaviour of WsControl with an app in
67 * Windows 98. It is not fully implemented, and there could
68 * be (are?) errors due to incorrect assumptions made.
71 * WsControl returns WSCTL_SUCCESS on success.
72 * STATUS_BUFFER_TOO_SMALL is returned if the output buffer length
73 * (*pcbResponseInfoLen) is too small, otherwise errors return -1.
75 * It doesn't seem to generate errors that can be retrieved by
80 DWORD WINAPI WsControl(DWORD protocoll,
83 LPDWORD pcbRequestInfoLen,
85 LPDWORD pcbResponseInfoLen)
87 /* Get the command structure into a pointer we can use,
89 TDIObjectID *pcommand = (TDIObjectID *)pRequestInfo;
91 TRACE (" WsControl TOI_ID=>0x%lx<, {TEI_ENTITY=0x%lx, TEI_INSTANCE=0x%lx}, TOI_CLASS=0x%lx, TOI_TYPE=0x%lx\n",
92 pcommand->toi_id, pcommand->toi_entity.tei_entity, pcommand->toi_entity.tei_instance,
93 pcommand->toi_class, pcommand->toi_type );
99 case WSCNTL_TCPIP_QUERY_INFO:
101 switch (pcommand->toi_id)
104 ENTITY_LIST_ID seems to get number of adapters in the system.
105 (almost like an index to be used when calling other WsControl options)
109 TDIEntityID *baseptr = pResponseInfo;
112 if (pcommand->toi_class != INFO_CLASS_GENERIC &&
113 pcommand->toi_type != INFO_TYPE_PROVIDER)
115 FIXME ("Unexpected Option for ENTITY_LIST_ID request -> toi_class=0x%lx, toi_type=0x%lx\n",
116 pcommand->toi_class, pcommand->toi_type);
117 return (WSAEOPNOTSUPP);
120 numInt = WSCNTL_GetEntryCount(WSCNTL_COUNT_INTERFACES);
123 ERR ("Unable to open /proc filesystem to determine number of network interfaces!\n");
127 if (*pcbResponseInfoLen < sizeof(TDIEntityID)*(numInt*2) )
129 return (STATUS_BUFFER_TOO_SMALL);
133 memset(baseptr, 0, sizeof(TDIEntityID)*(numInt*2));
135 for (i=0; i<numInt; i++)
137 /* tei_instance is an network interface identifier.
138 I'm not quite sure what the difference is between tei_entity values of
139 CL_NL_ENTITY and IF_ENTITY */
140 baseptr->tei_entity = CL_NL_ENTITY; baseptr->tei_instance = i; baseptr++;
141 baseptr->tei_entity = IF_ENTITY; baseptr->tei_instance = i; baseptr++;
144 /* Calculate size of out buffer */
145 *pcbResponseInfoLen = sizeof(TDIEntityID)*(numInt*2);
151 /* ENTITY_TYPE_ID is used to obtain simple information about a
152 network card, such as MAC Address, description, interface type,
153 number of network addresses, etc. */
154 case ENTITY_TYPE_ID: /* ALSO: IP_MIB_STATS_ID */
156 if (pcommand->toi_class == INFO_CLASS_GENERIC && pcommand->toi_type == INFO_TYPE_PROVIDER)
158 if (pcommand->toi_entity.tei_entity == IF_ENTITY)
160 * ((ULONG *)pResponseInfo) = IF_MIB;
162 /* Calculate size of out buffer */
163 *pcbResponseInfoLen = sizeof (ULONG);
166 else if (pcommand->toi_entity.tei_entity == CL_NL_ENTITY)
168 * ((ULONG *)pResponseInfo) = CL_NL_IP;
170 /* Calculate size of out buffer */
171 *pcbResponseInfoLen = sizeof (ULONG);
174 else if (pcommand->toi_class == INFO_CLASS_PROTOCOL &&
175 pcommand->toi_type == INFO_TYPE_PROVIDER)
177 if (pcommand->toi_entity.tei_entity == IF_ENTITY)
179 /* In this case, we are requesting specific information about a
180 a particular network adapter. (MAC Address, speed, data transmitted/received,
183 IFEntry *IntInfo = (IFEntry *) pResponseInfo;
189 if (!WSCNTL_GetInterfaceName(pcommand->toi_entity.tei_instance, ifName))
191 ERR ("Unable to parse /proc filesystem!\n");
195 /* Get a socket so that we can use ioctl */
196 if ( (sock = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
198 ERR ("Error creating socket!\n");
202 /* 0 out return structure first */
203 memset (IntInfo, 0, sizeof(IFEntry));
206 IntInfo->if_index = pcommand->toi_entity.tei_instance;
208 /* MAC Address - Let's try to do this in a cross-platform way... */
209 #if defined(SIOCGIFHWADDR) /* Linux */
210 strcpy(ifInfo.ifr_name, ifName);
211 if (ioctlsocket(sock, SIOCGIFHWADDR, (ULONG*)&ifInfo) < 0)
213 ERR ("Error obtaining MAC Address!\n");
219 /* FIXME: Is it correct to assume size of 6? */
220 memcpy(IntInfo->if_physaddr, ifInfo.ifr_hwaddr.sa_data, 6);
221 IntInfo->if_physaddrlen=6;
223 #elif defined(SIOCGENADDR) /* Solaris */
224 if (ioctlsocket(sock, SIOCGENADDR, (ULONG*)&ifInfo) < 0)
226 ERR ("Error obtaining MAC Address!\n");
232 /* FIXME: Is it correct to assume size of 6? */
233 memcpy(IntInfo->if_physaddr, ifInfo.ifr_enaddr, 6);
234 IntInfo->if_physaddrlen=6;
237 memset (IntInfo->if_physaddr, 0, 6);
238 ERR ("Unable to determine MAC Address on your platform!\n");
242 /* Interface name and length */
243 strcpy (IntInfo->if_descr, ifName);
244 IntInfo->if_descrlen= strlen (IntInfo->if_descr);
246 /* Obtain bytes transmitted/received for interface */
247 if ( (WSCNTL_GetTransRecvStat(pcommand->toi_entity.tei_instance,
248 &IntInfo->if_inoctets, &IntInfo->if_outoctets)) < 0)
250 ERR ("Error obtaining transmit/receive stats for the network interface!\n");
256 /* FIXME: How should the below be properly calculated? ******************/
257 IntInfo->if_type = 0x6; /* Ethernet (?) */
258 IntInfo->if_speed = 1000000; /* Speed of interface (bits per second?) */
259 /************************************************************************/
262 *pcbResponseInfoLen = sizeof (IFEntry) + IntInfo->if_descrlen;
264 else if (pcommand->toi_entity.tei_entity == CL_NL_ENTITY)
266 IPSNMPInfo *infoStruc = (IPSNMPInfo *) pResponseInfo;
267 int numInt, numRoutes;
269 /* This case is used to obtain general statistics about the
272 if (*pcbResponseInfoLen < sizeof(IPSNMPInfo) )
274 return (STATUS_BUFFER_TOO_SMALL);
279 memset(infoStruc, 0, sizeof(IPSNMPInfo));
281 /* Get the number of interfaces */
282 numInt = WSCNTL_GetEntryCount(WSCNTL_COUNT_INTERFACES);
285 ERR ("Unable to open /proc filesystem to determine number of network interfaces!\n");
288 /* Get the number of routes */
289 numRoutes = WSCNTL_GetEntryCount(WSCNTL_COUNT_ROUTES);
292 ERR ("Unable to open /proc filesystem to determine number of network routes!\n");
296 infoStruc->ipsi_numif = numInt; /* # of interfaces */
297 infoStruc->ipsi_numaddr = numInt; /* # of addresses */
298 infoStruc->ipsi_numroutes = numRoutes; /* # of routes */
300 /* FIXME: How should the below be properly calculated? ******************/
301 infoStruc->ipsi_forwarding = 0x0;
302 infoStruc->ipsi_defaultttl = 0x0;
303 infoStruc->ipsi_inreceives = 0x0;
304 infoStruc->ipsi_inhdrerrors = 0x0;
305 infoStruc->ipsi_inaddrerrors = 0x0;
306 infoStruc->ipsi_forwdatagrams = 0x0;
307 infoStruc->ipsi_inunknownprotos = 0x0;
308 infoStruc->ipsi_indiscards = 0x0;
309 infoStruc->ipsi_indelivers = 0x0;
310 infoStruc->ipsi_outrequests = 0x0;
311 infoStruc->ipsi_routingdiscards = 0x0;
312 infoStruc->ipsi_outdiscards = 0x0;
313 infoStruc->ipsi_outnoroutes = 0x0;
314 infoStruc->ipsi_reasmtimeout = 0x0;
315 infoStruc->ipsi_reasmreqds = 0x0;
316 infoStruc->ipsi_reasmoks = 0x0;
317 infoStruc->ipsi_reasmfails = 0x0;
318 infoStruc->ipsi_fragoks = 0x0;
319 infoStruc->ipsi_fragfails = 0x0;
320 infoStruc->ipsi_fragcreates = 0x0;
321 /************************************************************************/
323 /* Calculate size of out buffer */
324 *pcbResponseInfoLen = sizeof(IPSNMPInfo);
330 FIXME ("Unexpected Option for ENTITY_TYPE_ID request -> toi_class=0x%lx, toi_type=0x%lx\n",
331 pcommand->toi_class, pcommand->toi_type);
333 return (WSAEOPNOTSUPP);
340 /* IP_MIB_ADDRTABLE_ENTRY_ID is used to obtain more detailed information about a
341 particular network adapter */
342 case IP_MIB_ADDRTABLE_ENTRY_ID:
344 IPAddrEntry *baseIPInfo = (IPAddrEntry *) pResponseInfo;
345 char ifName[IFNAMSIZ+1];
349 if (*pcbResponseInfoLen < sizeof(IPAddrEntry))
351 return (STATUS_BUFFER_TOO_SMALL);
354 if (!WSCNTL_GetInterfaceName(pcommand->toi_entity.tei_instance, ifName))
356 ERR ("Unable to parse /proc filesystem!\n");
361 /* Get a socket so we can use ioctl */
362 if ( (sock = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
364 ERR ("Error creating socket!\n");
369 memset(baseIPInfo, 0, sizeof(IPAddrEntry) );
372 baseIPInfo->iae_index = pcommand->toi_entity.tei_instance;
375 strcpy (ifInfo.ifr_name, ifName);
376 ifInfo.ifr_addr.sa_family = AF_INET;
377 if (ioctlsocket(sock, SIOCGIFADDR, (ULONG*)&ifInfo) < 0)
379 baseIPInfo->iae_addr = 0x0;
383 struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_addr;
384 baseIPInfo->iae_addr = ipTemp->sin_addr.S_un.S_addr;
387 /* Broadcast Address */
388 strcpy (ifInfo.ifr_name, ifName);
389 if (ioctlsocket(sock, SIOCGIFBRDADDR, (ULONG *)&ifInfo) < 0)
391 baseIPInfo->iae_bcastaddr = 0x0;
395 struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_broadaddr;
396 baseIPInfo->iae_bcastaddr = ipTemp->sin_addr.S_un.S_addr;
400 strcpy(ifInfo.ifr_name, ifName);
401 if (ioctlsocket(sock, SIOCGIFNETMASK, (ULONG *)&ifInfo) < 0)
403 baseIPInfo->iae_mask = 0x0;
407 /* Trying to avoid some compile problems across platforms.
408 (Linux, FreeBSD, Solaris...) */
411 baseIPInfo->iae_mask = 0;
412 ERR ("Unable to determine Netmask on your platform!\n");
414 struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_addr;
415 baseIPInfo->iae_mask = ipTemp->sin_addr.S_un.S_addr;
418 struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_netmask;
419 baseIPInfo->iae_mask = ipTemp->sin_addr.S_un.S_addr;
423 /* FIXME: How should the below be properly calculated? ******************/
424 baseIPInfo->iae_reasmsize = 0x0;
425 baseIPInfo->iae_context = 0x0;
426 baseIPInfo->iae_pad = 0x0;
427 /************************************************************************/
429 /* Calculate size of out buffer */
430 *pcbResponseInfoLen = sizeof(IPAddrEntry);
436 /* This call returns the routing table.
437 * No official documentation found, even the name of the command is unknown.
439 * http://www.cyberport.com/~tangent/programming/winsock/articles/wscontrol.html
440 * and testings done with winipcfg.exe, route.exe and ipconfig.exe.
441 * pcommand->toi_entity.tei_instance seems to be the interface number
442 * but route.exe outputs only the information for the last interface
443 * if only the routes for the pcommand->toi_entity.tei_instance
444 * interface are returned. */
445 case IP_MIB_ROUTETABLE_ENTRY_ID: /* FIXME: not real name. Value is 0x101 */
447 int numRoutes, foundRoutes;
448 wscntl_routeentry *routeTable, *routePtr; /* route table */
450 IPRouteEntry *winRouteTable = (IPRouteEntry *) pResponseInfo;
452 /* Get the number of routes */
453 numRoutes = WSCNTL_GetEntryCount(WSCNTL_COUNT_ROUTES);
456 ERR ("Unable to open /proc filesystem to determine number of network routes!\n");
460 if (*pcbResponseInfoLen < (sizeof(IPRouteEntry) * numRoutes))
462 return (STATUS_BUFFER_TOO_SMALL);
465 /* malloc space for the routeTable */
466 routeTable = (wscntl_routeentry *) malloc(sizeof(wscntl_routeentry) * numRoutes);
469 ERR ("couldn't malloc space for routeTable!\n");
472 /* get the route table */
473 foundRoutes = WSCNTL_GetRouteTable(numRoutes, routeTable);
476 ERR ("Unable to open /proc filesystem to parse the route entrys!\n");
480 routePtr = routeTable;
482 /* first 0 out the output buffer */
483 memset(winRouteTable, 0, *pcbResponseInfoLen);
485 /* calculate the length of the data in the output buffer */
486 *pcbResponseInfoLen = sizeof(IPRouteEntry) * foundRoutes;
488 for ( ; foundRoutes > 0; foundRoutes--)
490 winRouteTable->ire_addr = routePtr->wre_dest;
491 winRouteTable->ire_index = routePtr->wre_intf;
492 winRouteTable->ire_metric = routePtr->wre_metric;
493 /* winRouteTable->ire_option4 =
494 winRouteTable->ire_option5 =
495 winRouteTable->ire_option6 = */
496 winRouteTable->ire_gw = routePtr->wre_gw;
497 /* winRouteTable->ire_option8 =
498 winRouteTable->ire_option9 =
499 winRouteTable->ire_option10 = */
500 winRouteTable->ire_mask = routePtr->wre_mask;
501 /* winRouteTable->ire_option12 = */
514 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",
515 pcommand->toi_id, pcommand->toi_entity.tei_entity, pcommand->toi_entity.tei_instance,
516 pcommand->toi_class, pcommand->toi_type);
518 return (WSAEOPNOTSUPP);
525 case WSCNTL_TCPIP_ICMP_ECHO:
527 unsigned int addr = *(unsigned int*)pRequestInfo;
529 int timeout= *(unsigned int*)(inbuf+4);
530 short x1 = *(unsigned short*)(inbuf+8);
531 short sendbufsize = *(unsigned short*)(inbuf+10);
532 char x2 = *(unsigned char*)(inbuf+12);
533 char ttl = *(unsigned char*)(inbuf+13);
534 char service = *(unsigned char*)(inbuf+14);
535 char type= *(unsigned char*)(inbuf+15); /* 0x2: don't fragment*/
538 FIXME("(ICMP_ECHO) to 0x%08x stub \n", addr);
544 FIXME("Protocoll Not Supported -> protocoll=0x%lx, action=0x%lx, Request=%p, RequestLen=%p, Response=%p, ResponseLen=%p\n",
545 protocoll, action, pRequestInfo, pcbRequestInfoLen, pResponseInfo, pcbResponseInfoLen);
547 return (WSAEOPNOTSUPP);
552 return (WSCTL_SUCCESS);
558 Helper function for WsControl - Get count of the number of interfaces
559 or routes by parsing /proc filesystem.
561 int WSCNTL_GetEntryCount(const int entrytype)
565 char buf[512]; /* Size optimized for a typical workstation */
573 case WSCNTL_COUNT_INTERFACES:
575 filename = PROCFS_NETDEV_FILE;
576 count = -2; /* two haeder lines */
580 case WSCNTL_COUNT_ROUTES:
582 filename = PROCFS_ROUTE_FILE;
583 count = -1; /* one haeder line */
593 /* open /proc filesystem file */
594 fd = open(filename, O_RDONLY);
599 /* read the file and count the EOL's */
600 while ((chrread = read(fd, buf, sizeof(buf))) != 0)
607 continue; /* read interupted by a signal, try to read again */
615 while ((ptr = memchr(ptr, '\n', chrread - (int) (ptr - buf))) > 0)
628 Helper function for WsControl - Get name of device from interface number
629 by parsing /proc filesystem.
631 int WSCNTL_GetInterfaceName(int intNumber, char *intName)
634 char buf[512]; /* Size doesn't matter, something big */
637 /* Open /proc filesystem file for network devices */
638 procfs = fopen(PROCFS_NETDEV_FILE, "r");
641 /* If we can't open the file, return an error */
645 /* Omit first two lines, they are only headers */
646 fgets(buf, sizeof(buf), procfs);
647 fgets(buf, sizeof(buf), procfs);
649 for (i=0; i<intNumber; i++)
651 /* Skip the lines that don't interest us. */
652 fgets(buf, sizeof(buf), procfs);
654 fgets(buf, sizeof(buf), procfs); /* This is the line we want */
657 /* Parse out the line, grabbing only the name of the device
658 to the intName variable
660 The Line comes in like this: (we only care about the device name)
661 lo: 21970 377 0 0 0 0 0 0 21970 377 0 0 0 0 0 0
664 while (isspace(buf[i])) /* Skip initial space(s) */
676 if (buf[i] == ':') /* FIXME: Not sure if this block (alias detection) works properly */
678 /* This interface could be an alias... */
680 char *dotname = intName;
681 *intName++ = buf[i++];
683 while (isdigit(buf[i]))
685 *intName++ = buf[i++];
690 /* ... It wasn't, so back up */
705 *intName++ = buf[i++];
715 Helper function for WsControl - This function returns the bytes (octets) transmitted
716 and received for the supplied interface number from the /proc fs.
718 int WSCNTL_GetTransRecvStat(int intNumber, unsigned long *transBytes, unsigned long *recvBytes)
721 char buf[512], result[512]; /* Size doesn't matter, something big */
722 int i, bufPos, resultPos;
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 */
745 /* Parse out the line, grabbing the number of bytes transmitted
746 and received on the interface.
748 The Line comes in like this: (we care about columns 2 and 10)
749 lo: 21970 377 0 0 0 0 0 0 21970 377 0 0 0 0 0 0
752 /* Start at character 0 in the buffer */
755 /* Skip initial space(s) */
756 while (isspace(buf[bufPos]))
760 /* Skip the name and its trailing spaces (if any) */
763 if (isspace(buf[bufPos]))
766 if (buf[bufPos] == ':') /* Could be an alias */
770 while(isdigit (buf[bufPos]))
772 if (buf[bufPos] != ':')
774 if (buf[bufPos] == '\0')
786 while (isspace(buf[bufPos]))
790 /* This column (#2) is the number of bytes received. */
792 while (!isspace(buf[bufPos]))
794 result[resultPos] = buf[bufPos];
795 result[resultPos+1]='\0';
796 resultPos++; bufPos++;
798 *recvBytes = strtoul (result, NULL, 10); /* convert string to unsigned long, using base 10 */
801 /* Skip columns #3 to #9 (Don't need them) */
804 while (isspace(buf[bufPos]))
806 while (!isspace(buf[bufPos]))
811 /* This column (#10) is the number of bytes transmitted */
812 while (isspace(buf[bufPos]))
816 while (!isspace(buf[bufPos]))
818 result[resultPos] = buf[bufPos];
819 result[resultPos+1]='\0';
820 resultPos++; bufPos++;
822 *transBytes = strtoul (result, NULL, 10); /* convert string to unsigned long, using base 10 */
830 /* Parse the procfs route file and put the datas into routeTable.
831 * Return value is the number of found routes */
832 int WSCNTL_GetRouteTable(int numRoutes, wscntl_routeentry *routeTable)
834 int nrIntf; /* total number of interfaces */
835 char buf[256]; /* temporary buffer */
836 char *ptr; /* pointer to temporary buffer */
837 FILE *file; /* file handle for procfs route file */
838 int foundRoutes = 0; /* number of found routes */
839 typedef struct interface_t {
840 char intfName[IFNAMSIZ+1]; /* the name of the interface */
841 int intfNameLen; /* length of interface name */
843 interface_t *interface;
844 int intfNr; /* the interface number */
846 wscntl_routeentry *routePtr = routeTable;
848 /* get the number of interfaces */
849 nrIntf = WSCNTL_GetEntryCount(WSCNTL_COUNT_INTERFACES);
852 ERR ("Unable to open /proc filesystem to determine number of network interfaces!\n");
856 /* malloc space for the interface struct array */
857 interface = (interface_t *) malloc(sizeof(interface_t) * nrIntf);
860 ERR ("couldn't malloc space for interface!\n");
863 for (intfNr = 0; intfNr < nrIntf; intfNr++) {
864 if (WSCNTL_GetInterfaceName(intfNr, interface[intfNr].intfName) < 0)
866 ERR ("Unable to open /proc filesystem to determine the name of network interfaces!\n");
870 interface[intfNr].intfNameLen = strlen(interface[intfNr].intfName);
873 /* Open /proc filesystem file for routes */
874 file = fopen(PROCFS_ROUTE_FILE, "r");
877 /* If we can't open the file, return an error */
882 /* skip the header line */
883 fgets(buf, sizeof(buf), file);
885 /* parse the rest of the file and put the matching entrys into routeTable.
886 Format of procfs route entry:
887 Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT
888 lo 0000007F 00000000 0001 0 0 0 000000FF 0 0 0
890 while (fgets(buf, sizeof(buf), file)) {
892 /* find the interface of the route */
893 while ((strncmp(buf, interface[intfNr].intfName, interface[intfNr].intfNameLen) != 0)
894 && (intfNr < nrIntf))
898 if (intfNr < nrIntf) {
900 if (foundRoutes > numRoutes) {
901 /* output buffer is to small */
902 ERR("buffer to small to fit all routes found into it!\n");
908 ptr += interface[intfNr].intfNameLen;
909 routePtr->wre_intf = intfNr;
910 routePtr->wre_dest = strtoul(ptr, &ptr, 16); /* destination */
911 routePtr->wre_gw = strtoul(ptr, &ptr, 16); /* gateway */
912 strtoul(ptr, &ptr, 16); /* Flags; unused */
913 strtoul(ptr, &ptr, 16); /* RefCnt; unused */
914 strtoul(ptr, &ptr, 16); /* Use; unused */
915 routePtr->wre_metric = strtoul(ptr, &ptr, 16); /* metric */
916 routePtr->wre_mask = strtoul(ptr, &ptr, 16); /* mask */
917 /* strtoul(ptr, &ptr, 16); MTU; unused */
918 /* strtoul(ptr, &ptr, 16); Window; unused */
919 /* strtoul(ptr, &ptr, 16); IRTT; unused */
925 /* this should never happen */
926 WARN("Skipping route with unknown interface\n");
936 /***********************************************************************
937 * WSARecvEx() (WSOCK32.1107)
939 * WSARecvEx is a Microsoft specific extension to winsock that is identical to recv
940 * except that has an in/out argument call flags that has the value MSG_PARTIAL ored
941 * into the flags parameter when a partial packet is read. This only applies to
942 * sockets using the datagram protocol. This method does not seem to be implemented
943 * correctly by microsoft as the winsock implementation does not set the MSG_PARTIAL
944 * flag when a fragmented packet arrives.
946 INT WINAPI WSARecvEx(SOCKET s, char *buf, INT len, INT *flags)
948 FIXME("(WSARecvEx) partial packet return value not set \n");
949 return recv(s, buf, len, *flags);
953 /***********************************************************************
954 * WS_s_perror (WSOCK32.1108)
956 void WINAPI WS_s_perror(LPCSTR message)
958 FIXME("(%s): stub\n",message);