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
20 #define recv linux_recv
26 #include <sys/types.h>
29 #include "debugtools.h"
32 #include "wscontrol.h"
34 #include <sys/ioctl.h>
38 #ifdef HAVE_SYS_SOCKIO_H
39 # include <sys/sockio.h>
50 /* FIXME: The rest of the socket() cdecl<->stdapi stack corruption problem
54 extern SOCKET WINAPI socket(INT af, INT type, INT protocol);
55 extern SOCKET WINAPI recv(SOCKET,char*,int,int);
59 DEFAULT_DEBUG_CHANNEL(winsock);
62 /***********************************************************************
63 * WsControl (WSOCK32.1001)
65 * WsControl seems to be an undocumented Win95 function. A lot of
66 * discussion about WsControl can be found on the net, e.g.
67 * Subject: Re: WSOCK32.DLL WsControl Exported Function
68 * From: "Peter Rindfuss" <rindfuss-s@medea.wz-berlin.de>
71 * WSCNTL_TCPIP_QUERY_INFO option is partially implemeted based
72 * on observing the behaviour of WsControl with an app in
73 * Windows 98. It is not fully implemented, and there could
74 * be (are?) errors due to incorrect assumptions made.
77 * WsControl returns WSCTL_SUCCESS on success.
78 * STATUS_BUFFER_TOO_SMALL is returned if the output buffer length
79 * (*pcbResponseInfoLen) is too small, otherwise errors return -1.
81 * It doesn't seem to generate errors that can be retrieved by
86 DWORD WINAPI WsControl(DWORD protocoll,
89 LPDWORD pcbRequestInfoLen,
91 LPDWORD pcbResponseInfoLen)
93 /* Get the command structure into a pointer we can use,
95 TDIObjectID *pcommand = (TDIObjectID *)pRequestInfo;
97 TRACE (" WsControl TOI_ID=>0x%lx<, {TEI_ENTITY=0x%lx, TEI_INSTANCE=0x%lx}, TOI_CLASS=0x%lx, TOI_TYPE=0x%lx\n",
98 pcommand->toi_id, pcommand->toi_entity.tei_entity, pcommand->toi_entity.tei_instance,
99 pcommand->toi_class, pcommand->toi_type );
105 case WSCNTL_TCPIP_QUERY_INFO:
107 switch (pcommand->toi_id)
110 ENTITY_LIST_ID seems to get number of adapters in the system.
111 (almost like an index to be used when calling other WsControl options)
115 TDIEntityID *baseptr = pResponseInfo;
118 if (pcommand->toi_class != INFO_CLASS_GENERIC &&
119 pcommand->toi_type != INFO_TYPE_PROVIDER)
121 FIXME ("Unexpected Option for ENTITY_LIST_ID request -> toi_class=0x%lx, toi_type=0x%lx\n",
122 pcommand->toi_class, pcommand->toi_type);
123 return (WSAEOPNOTSUPP);
126 numInt = WSCNTL_GetEntryCount(WSCNTL_COUNT_INTERFACES);
129 ERR ("Unable to open /proc filesystem to determine number of network interfaces!\n");
133 if (*pcbResponseInfoLen < sizeof(TDIEntityID)*(numInt*2) )
135 return (STATUS_BUFFER_TOO_SMALL);
139 memset(baseptr, 0, sizeof(TDIEntityID)*(numInt*2));
141 for (i=0; i<numInt; i++)
143 /* tei_instance is an network interface identifier.
144 I'm not quite sure what the difference is between tei_entity values of
145 CL_NL_ENTITY and IF_ENTITY */
146 baseptr->tei_entity = CL_NL_ENTITY; baseptr->tei_instance = i; baseptr++;
147 baseptr->tei_entity = IF_ENTITY; baseptr->tei_instance = i; baseptr++;
150 /* Calculate size of out buffer */
151 *pcbResponseInfoLen = sizeof(TDIEntityID)*(numInt*2);
157 /* ENTITY_TYPE_ID is used to obtain simple information about a
158 network card, such as MAC Address, description, interface type,
159 number of network addresses, etc. */
160 case ENTITY_TYPE_ID: /* ALSO: IP_MIB_STATS_ID */
162 if (pcommand->toi_class == INFO_CLASS_GENERIC && pcommand->toi_type == INFO_TYPE_PROVIDER)
164 if (pcommand->toi_entity.tei_entity == IF_ENTITY)
166 * ((ULONG *)pResponseInfo) = IF_MIB;
168 /* Calculate size of out buffer */
169 *pcbResponseInfoLen = sizeof (ULONG);
172 else if (pcommand->toi_entity.tei_entity == CL_NL_ENTITY)
174 * ((ULONG *)pResponseInfo) = CL_NL_IP;
176 /* Calculate size of out buffer */
177 *pcbResponseInfoLen = sizeof (ULONG);
180 else if (pcommand->toi_class == INFO_CLASS_PROTOCOL &&
181 pcommand->toi_type == INFO_TYPE_PROVIDER)
183 if (pcommand->toi_entity.tei_entity == IF_ENTITY)
185 /* In this case, we are requesting specific information about a
186 a particular network adapter. (MAC Address, speed, data transmitted/received,
189 IFEntry *IntInfo = (IFEntry *) pResponseInfo;
195 if (!WSCNTL_GetInterfaceName(pcommand->toi_entity.tei_instance, ifName))
197 ERR ("Unable to parse /proc filesystem!\n");
201 /* Get a socket so that we can use ioctl */
202 if ( (sock = socket (AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET)
204 ERR ("Error creating socket!\n");
208 /* 0 out return structure first */
209 memset (IntInfo, 0, sizeof(IFEntry));
212 IntInfo->if_index = pcommand->toi_entity.tei_instance;
214 /* MAC Address - Let's try to do this in a cross-platform way... */
215 #if defined(SIOCGIFHWADDR) /* Linux */
216 strcpy(ifInfo.ifr_name, ifName);
217 if (ioctlsocket(sock, SIOCGIFHWADDR, (ULONG*)&ifInfo) < 0)
219 ERR ("Error obtaining MAC Address!\n");
225 /* FIXME: Is it correct to assume size of 6? */
226 memcpy(IntInfo->if_physaddr, ifInfo.ifr_hwaddr.sa_data, 6);
227 IntInfo->if_physaddrlen=6;
229 #elif defined(SIOCGENADDR) /* Solaris */
230 if (ioctlsocket(sock, SIOCGENADDR, (ULONG*)&ifInfo) < 0)
232 ERR ("Error obtaining MAC Address!\n");
238 /* FIXME: Is it correct to assume size of 6? */
239 memcpy(IntInfo->if_physaddr, ifInfo.ifr_enaddr, 6);
240 IntInfo->if_physaddrlen=6;
243 memset (IntInfo->if_physaddr, 0, 6);
244 ERR ("Unable to determine MAC Address on your platform!\n");
248 /* Interface name and length */
249 strcpy (IntInfo->if_descr, ifName);
250 IntInfo->if_descrlen= strlen (IntInfo->if_descr);
252 /* Obtain bytes transmitted/received for interface */
253 if ( (WSCNTL_GetTransRecvStat(pcommand->toi_entity.tei_instance,
254 &IntInfo->if_inoctets, &IntInfo->if_outoctets)) < 0)
256 ERR ("Error obtaining transmit/receive stats for the network interface!\n");
262 /* FIXME: How should the below be properly calculated? ******************/
263 IntInfo->if_type = 0x6; /* Ethernet (?) */
264 IntInfo->if_speed = 1000000; /* Speed of interface (bits per second?) */
265 /************************************************************************/
268 *pcbResponseInfoLen = sizeof (IFEntry) + IntInfo->if_descrlen;
270 else if (pcommand->toi_entity.tei_entity == CL_NL_ENTITY)
272 IPSNMPInfo *infoStruc = (IPSNMPInfo *) pResponseInfo;
273 int numInt, numRoutes;
275 /* This case is used to obtain general statistics about the
278 if (*pcbResponseInfoLen < sizeof(IPSNMPInfo) )
280 return (STATUS_BUFFER_TOO_SMALL);
285 memset(infoStruc, 0, sizeof(IPSNMPInfo));
287 /* Get the number of interfaces */
288 numInt = WSCNTL_GetEntryCount(WSCNTL_COUNT_INTERFACES);
291 ERR ("Unable to open /proc filesystem to determine number of network interfaces!\n");
294 /* Get the number of routes */
295 numRoutes = WSCNTL_GetEntryCount(WSCNTL_COUNT_ROUTES);
298 ERR ("Unable to open /proc filesystem to determine number of network routes!\n");
302 infoStruc->ipsi_numif = numInt; /* # of interfaces */
303 infoStruc->ipsi_numaddr = numInt; /* # of addresses */
304 infoStruc->ipsi_numroutes = numRoutes; /* # of routes */
306 /* FIXME: How should the below be properly calculated? ******************/
307 infoStruc->ipsi_forwarding = 0x0;
308 infoStruc->ipsi_defaultttl = 0x0;
309 infoStruc->ipsi_inreceives = 0x0;
310 infoStruc->ipsi_inhdrerrors = 0x0;
311 infoStruc->ipsi_inaddrerrors = 0x0;
312 infoStruc->ipsi_forwdatagrams = 0x0;
313 infoStruc->ipsi_inunknownprotos = 0x0;
314 infoStruc->ipsi_indiscards = 0x0;
315 infoStruc->ipsi_indelivers = 0x0;
316 infoStruc->ipsi_outrequests = 0x0;
317 infoStruc->ipsi_routingdiscards = 0x0;
318 infoStruc->ipsi_outdiscards = 0x0;
319 infoStruc->ipsi_outnoroutes = 0x0;
320 infoStruc->ipsi_reasmtimeout = 0x0;
321 infoStruc->ipsi_reasmreqds = 0x0;
322 infoStruc->ipsi_reasmoks = 0x0;
323 infoStruc->ipsi_reasmfails = 0x0;
324 infoStruc->ipsi_fragoks = 0x0;
325 infoStruc->ipsi_fragfails = 0x0;
326 infoStruc->ipsi_fragcreates = 0x0;
327 /************************************************************************/
329 /* Calculate size of out buffer */
330 *pcbResponseInfoLen = sizeof(IPSNMPInfo);
336 FIXME ("Unexpected Option for ENTITY_TYPE_ID request -> toi_class=0x%lx, toi_type=0x%lx\n",
337 pcommand->toi_class, pcommand->toi_type);
339 return (WSAEOPNOTSUPP);
346 /* IP_MIB_ADDRTABLE_ENTRY_ID is used to obtain more detailed information about a
347 particular network adapter */
348 case IP_MIB_ADDRTABLE_ENTRY_ID:
350 IPAddrEntry *baseIPInfo = (IPAddrEntry *) pResponseInfo;
351 char ifName[IFNAMSIZ+1];
355 if (*pcbResponseInfoLen < sizeof(IPAddrEntry))
357 return (STATUS_BUFFER_TOO_SMALL);
360 if (!WSCNTL_GetInterfaceName(pcommand->toi_entity.tei_instance, ifName))
362 ERR ("Unable to parse /proc filesystem!\n");
367 /* Get a socket so we can use ioctl */
368 if ( (sock = socket (AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET)
370 ERR ("Error creating socket!\n");
375 memset(baseIPInfo, 0, sizeof(IPAddrEntry) );
378 baseIPInfo->iae_index = pcommand->toi_entity.tei_instance;
381 strcpy (ifInfo.ifr_name, ifName);
382 ifInfo.ifr_addr.sa_family = AF_INET;
383 if (ioctlsocket(sock, SIOCGIFADDR, (ULONG*)&ifInfo) < 0)
385 baseIPInfo->iae_addr = 0x0;
389 struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_addr;
390 baseIPInfo->iae_addr = ipTemp->sin_addr.S_un.S_addr;
393 /* Broadcast Address */
394 strcpy (ifInfo.ifr_name, ifName);
395 if (ioctlsocket(sock, SIOCGIFBRDADDR, (ULONG *)&ifInfo) < 0)
397 baseIPInfo->iae_bcastaddr = 0x0;
401 struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_broadaddr;
402 baseIPInfo->iae_bcastaddr = ipTemp->sin_addr.S_un.S_addr;
406 strcpy(ifInfo.ifr_name, ifName);
407 if (ioctlsocket(sock, SIOCGIFNETMASK, (ULONG *)&ifInfo) < 0)
409 baseIPInfo->iae_mask = 0x0;
413 /* Trying to avoid some compile problems across platforms.
414 (Linux, FreeBSD, Solaris...) */
417 baseIPInfo->iae_mask = 0;
418 ERR ("Unable to determine Netmask on your platform!\n");
420 struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_addr;
421 baseIPInfo->iae_mask = ipTemp->sin_addr.S_un.S_addr;
424 struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_netmask;
425 baseIPInfo->iae_mask = ipTemp->sin_addr.S_un.S_addr;
429 /* FIXME: How should the below be properly calculated? ******************/
430 baseIPInfo->iae_reasmsize = 0x0;
431 baseIPInfo->iae_context = 0x0;
432 baseIPInfo->iae_pad = 0x0;
433 /************************************************************************/
435 /* Calculate size of out buffer */
436 *pcbResponseInfoLen = sizeof(IPAddrEntry);
442 /* This call returns the routing table.
443 * No official documentation found, even the name of the command is unknown.
445 * http://www.cyberport.com/~tangent/programming/winsock/articles/wscontrol.html
446 * and testings done with winipcfg.exe, route.exe and ipconfig.exe.
447 * pcommand->toi_entity.tei_instance seems to be the interface number
448 * but route.exe outputs only the information for the last interface
449 * if only the routes for the pcommand->toi_entity.tei_instance
450 * interface are returned. */
451 case IP_MIB_ROUTETABLE_ENTRY_ID: /* FIXME: not real name. Value is 0x101 */
453 int numRoutes, foundRoutes;
454 wscntl_routeentry *routeTable, *routePtr; /* route table */
456 IPRouteEntry *winRouteTable = (IPRouteEntry *) pResponseInfo;
458 /* Get the number of routes */
459 numRoutes = WSCNTL_GetEntryCount(WSCNTL_COUNT_ROUTES);
462 ERR ("Unable to open /proc filesystem to determine number of network routes!\n");
466 if (*pcbResponseInfoLen < (sizeof(IPRouteEntry) * numRoutes))
468 return (STATUS_BUFFER_TOO_SMALL);
471 /* malloc space for the routeTable */
472 routeTable = (wscntl_routeentry *) malloc(sizeof(wscntl_routeentry) * numRoutes);
475 ERR ("couldn't malloc space for routeTable!\n");
478 /* get the route table */
479 foundRoutes = WSCNTL_GetRouteTable(numRoutes, routeTable);
482 ERR ("Unable to open /proc filesystem to parse the route entrys!\n");
486 routePtr = routeTable;
488 /* first 0 out the output buffer */
489 memset(winRouteTable, 0, *pcbResponseInfoLen);
491 /* calculate the length of the data in the output buffer */
492 *pcbResponseInfoLen = sizeof(IPRouteEntry) * foundRoutes;
494 for ( ; foundRoutes > 0; foundRoutes--)
496 winRouteTable->ire_addr = routePtr->wre_dest;
497 winRouteTable->ire_index = routePtr->wre_intf;
498 winRouteTable->ire_metric = routePtr->wre_metric;
499 /* winRouteTable->ire_option4 =
500 winRouteTable->ire_option5 =
501 winRouteTable->ire_option6 = */
502 winRouteTable->ire_gw = routePtr->wre_gw;
503 /* winRouteTable->ire_option8 =
504 winRouteTable->ire_option9 =
505 winRouteTable->ire_option10 = */
506 winRouteTable->ire_mask = routePtr->wre_mask;
507 /* winRouteTable->ire_option12 = */
520 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",
521 pcommand->toi_id, pcommand->toi_entity.tei_entity, pcommand->toi_entity.tei_instance,
522 pcommand->toi_class, pcommand->toi_type);
524 return (WSAEOPNOTSUPP);
531 case WSCNTL_TCPIP_ICMP_ECHO:
533 unsigned int addr = *(unsigned int*)pRequestInfo;
535 int timeout= *(unsigned int*)(inbuf+4);
536 short x1 = *(unsigned short*)(inbuf+8);
537 short sendbufsize = *(unsigned short*)(inbuf+10);
538 char x2 = *(unsigned char*)(inbuf+12);
539 char ttl = *(unsigned char*)(inbuf+13);
540 char service = *(unsigned char*)(inbuf+14);
541 char type= *(unsigned char*)(inbuf+15); /* 0x2: don't fragment*/
544 FIXME("(ICMP_ECHO) to 0x%08x stub \n", addr);
550 FIXME("Protocoll Not Supported -> protocoll=0x%lx, action=0x%lx, Request=%p, RequestLen=%p, Response=%p, ResponseLen=%p\n",
551 protocoll, action, pRequestInfo, pcbRequestInfoLen, pResponseInfo, pcbResponseInfoLen);
553 return (WSAEOPNOTSUPP);
558 return (WSCTL_SUCCESS);
564 Helper function for WsControl - Get count of the number of interfaces
565 or routes by parsing /proc filesystem.
567 int WSCNTL_GetEntryCount(const int entrytype)
571 char buf[512]; /* Size optimized for a typical workstation */
579 case WSCNTL_COUNT_INTERFACES:
581 filename = PROCFS_NETDEV_FILE;
582 count = -2; /* two haeder lines */
586 case WSCNTL_COUNT_ROUTES:
588 filename = PROCFS_ROUTE_FILE;
589 count = -1; /* one haeder line */
599 /* open /proc filesystem file */
600 fd = open(filename, O_RDONLY);
605 /* read the file and count the EOL's */
606 while ((chrread = read(fd, buf, sizeof(buf))) != 0)
613 continue; /* read interupted by a signal, try to read again */
621 while ((ptr = memchr(ptr, '\n', chrread - (int) (ptr - buf))) > 0)
634 Helper function for WsControl - Get name of device from interface number
635 by parsing /proc filesystem.
637 int WSCNTL_GetInterfaceName(int intNumber, char *intName)
640 char buf[512]; /* Size doesn't matter, something big */
643 /* Open /proc filesystem file for network devices */
644 procfs = fopen(PROCFS_NETDEV_FILE, "r");
647 /* If we can't open the file, return an error */
651 /* Omit first two lines, they are only headers */
652 fgets(buf, sizeof(buf), procfs);
653 fgets(buf, sizeof(buf), procfs);
655 for (i=0; i<intNumber; i++)
657 /* Skip the lines that don't interest us. */
658 fgets(buf, sizeof(buf), procfs);
660 fgets(buf, sizeof(buf), procfs); /* This is the line we want */
663 /* Parse out the line, grabbing only the name of the device
664 to the intName variable
666 The Line comes in like this: (we only care about the device name)
667 lo: 21970 377 0 0 0 0 0 0 21970 377 0 0 0 0 0 0
670 while (isspace(buf[i])) /* Skip initial space(s) */
682 if (buf[i] == ':') /* FIXME: Not sure if this block (alias detection) works properly */
684 /* This interface could be an alias... */
686 char *dotname = intName;
687 *intName++ = buf[i++];
689 while (isdigit(buf[i]))
691 *intName++ = buf[i++];
696 /* ... It wasn't, so back up */
711 *intName++ = buf[i++];
721 Helper function for WsControl - This function returns the bytes (octets) transmitted
722 and received for the supplied interface number from the /proc fs.
724 int WSCNTL_GetTransRecvStat(int intNumber, unsigned long *transBytes, unsigned long *recvBytes)
727 char buf[512], result[512]; /* Size doesn't matter, something big */
728 int i, bufPos, resultPos;
730 /* Open /proc filesystem file for network devices */
731 procfs = fopen(PROCFS_NETDEV_FILE, "r");
734 /* If we can't open the file, return an error */
738 /* Omit first two lines, they are only headers */
739 fgets(buf, sizeof(buf), procfs);
740 fgets(buf, sizeof(buf), procfs);
742 for (i=0; i<intNumber; i++)
744 /* Skip the lines that don't interest us. */
745 fgets(buf, sizeof(buf), procfs);
747 fgets(buf, sizeof(buf), procfs); /* This is the line we want */
751 /* Parse out the line, grabbing the number of bytes transmitted
752 and received on the interface.
754 The Line comes in like this: (we care about columns 2 and 10)
755 lo: 21970 377 0 0 0 0 0 0 21970 377 0 0 0 0 0 0
758 /* Start at character 0 in the buffer */
761 /* Skip initial space(s) */
762 while (isspace(buf[bufPos]))
766 /* Skip the name and its trailing spaces (if any) */
769 if (isspace(buf[bufPos]))
772 if (buf[bufPos] == ':') /* Could be an alias */
776 while(isdigit (buf[bufPos]))
778 if (buf[bufPos] != ':')
780 if (buf[bufPos] == '\0')
792 while (isspace(buf[bufPos]))
796 /* This column (#2) is the number of bytes received. */
798 while (!isspace(buf[bufPos]))
800 result[resultPos] = buf[bufPos];
801 result[resultPos+1]='\0';
802 resultPos++; bufPos++;
804 *recvBytes = strtoul (result, NULL, 10); /* convert string to unsigned long, using base 10 */
807 /* Skip columns #3 to #9 (Don't need them) */
810 while (isspace(buf[bufPos]))
812 while (!isspace(buf[bufPos]))
817 /* This column (#10) is the number of bytes transmitted */
818 while (isspace(buf[bufPos]))
822 while (!isspace(buf[bufPos]))
824 result[resultPos] = buf[bufPos];
825 result[resultPos+1]='\0';
826 resultPos++; bufPos++;
828 *transBytes = strtoul (result, NULL, 10); /* convert string to unsigned long, using base 10 */
836 /* Parse the procfs route file and put the datas into routeTable.
837 * Return value is the number of found routes */
838 int WSCNTL_GetRouteTable(int numRoutes, wscntl_routeentry *routeTable)
840 int nrIntf; /* total number of interfaces */
841 char buf[256]; /* temporary buffer */
842 char *ptr; /* pointer to temporary buffer */
843 FILE *file; /* file handle for procfs route file */
844 int foundRoutes = 0; /* number of found routes */
845 typedef struct interface_t {
846 char intfName[IFNAMSIZ+1]; /* the name of the interface */
847 int intfNameLen; /* length of interface name */
849 interface_t *interface;
850 int intfNr; /* the interface number */
852 wscntl_routeentry *routePtr = routeTable;
854 /* get the number of interfaces */
855 nrIntf = WSCNTL_GetEntryCount(WSCNTL_COUNT_INTERFACES);
858 ERR ("Unable to open /proc filesystem to determine number of network interfaces!\n");
862 /* malloc space for the interface struct array */
863 interface = (interface_t *) malloc(sizeof(interface_t) * nrIntf);
866 ERR ("couldn't malloc space for interface!\n");
869 for (intfNr = 0; intfNr < nrIntf; intfNr++) {
870 if (WSCNTL_GetInterfaceName(intfNr, interface[intfNr].intfName) < 0)
872 ERR ("Unable to open /proc filesystem to determine the name of network interfaces!\n");
876 interface[intfNr].intfNameLen = strlen(interface[intfNr].intfName);
879 /* Open /proc filesystem file for routes */
880 file = fopen(PROCFS_ROUTE_FILE, "r");
883 /* If we can't open the file, return an error */
888 /* skip the header line */
889 fgets(buf, sizeof(buf), file);
891 /* parse the rest of the file and put the matching entrys into routeTable.
892 Format of procfs route entry:
893 Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT
894 lo 0000007F 00000000 0001 0 0 0 000000FF 0 0 0
896 while (fgets(buf, sizeof(buf), file)) {
898 /* find the interface of the route */
899 while ((strncmp(buf, interface[intfNr].intfName, interface[intfNr].intfNameLen) != 0)
900 && (intfNr < nrIntf))
904 if (intfNr < nrIntf) {
906 if (foundRoutes > numRoutes) {
907 /* output buffer is to small */
908 ERR("buffer to small to fit all routes found into it!\n");
914 ptr += interface[intfNr].intfNameLen;
915 routePtr->wre_intf = intfNr;
916 routePtr->wre_dest = strtoul(ptr, &ptr, 16); /* destination */
917 routePtr->wre_gw = strtoul(ptr, &ptr, 16); /* gateway */
918 strtoul(ptr, &ptr, 16); /* Flags; unused */
919 strtoul(ptr, &ptr, 16); /* RefCnt; unused */
920 strtoul(ptr, &ptr, 16); /* Use; unused */
921 routePtr->wre_metric = strtoul(ptr, &ptr, 16); /* metric */
922 routePtr->wre_mask = strtoul(ptr, &ptr, 16); /* mask */
923 /* strtoul(ptr, &ptr, 16); MTU; unused */
924 /* strtoul(ptr, &ptr, 16); Window; unused */
925 /* strtoul(ptr, &ptr, 16); IRTT; unused */
931 /* this should never happen */
932 WARN("Skipping route with unknown interface\n");
942 /***********************************************************************
943 * WSARecvEx (WSOCK32.1107)
945 * WSARecvEx is a Microsoft specific extension to winsock that is identical to recv
946 * except that has an in/out argument call flags that has the value MSG_PARTIAL ored
947 * into the flags parameter when a partial packet is read. This only applies to
948 * sockets using the datagram protocol. This method does not seem to be implemented
949 * correctly by microsoft as the winsock implementation does not set the MSG_PARTIAL
950 * flag when a fragmented packet arrives.
952 INT WINAPI WSARecvEx(SOCKET s, char *buf, INT len, INT *flags)
954 FIXME("(WSARecvEx) partial packet return value not set \n");
955 return recv(s, buf, len, *flags);
959 /***********************************************************************
960 * s_perror (WSOCK32.1108)
962 void WINAPI WS_s_perror(LPCSTR message)
964 FIXME("(%s): stub\n",message);