Implemented msvcrt._mbspbrk.
[wine.git] / dlls / wsock32 / socket.c
blob95b351648e7c564535a01f8412cbe56fe7bb9004
1 /*
2 * WSOCK32 specific functions
4 * Copyright (C) 1993,1994,1996,1997 John Brezak, Erik Bos, Alex Korobka.
5 */
8 /*
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 /* */
22 #include "config.h"
24 #include <string.h>
25 #include <sys/types.h>
26 #include "windef.h"
27 #include "winbase.h"
28 #include "debugtools.h"
29 #include "winsock2.h"
30 #include "winnt.h"
31 #include "wscontrol.h"
32 #include <ctype.h>
33 #include <sys/ioctl.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <unistd.h>
37 #ifdef HAVE_SYS_SOCKIO_H
38 # include <sys/sockio.h>
39 #endif
40 #ifdef HAVE_NET_IF_H
41 # include <net/if.h>
42 #endif
43 #include <errno.h>
45 #ifdef __NetBSD__
46 #undef if_type
47 #endif
49 /* FIXME: The rest of the socket() cdecl<->stdapi stack corruption problem
50 discussed above. */
51 #undef socket
52 extern SOCKET WINAPI socket(INT af, INT type, INT protocol);
53 /* */
56 DEFAULT_DEBUG_CHANNEL(winsock);
59 /***********************************************************************
60 * WsControl (WSOCK32.1001)
62 * WsControl seems to be an undocumented Win95 function. A lot of
63 * discussion about WsControl can be found on the net, e.g.
64 * Subject: Re: WSOCK32.DLL WsControl Exported Function
65 * From: "Peter Rindfuss" <rindfuss-s@medea.wz-berlin.de>
66 * Date: 1997/08/17
68 * WSCNTL_TCPIP_QUERY_INFO option is partially implemeted based
69 * on observing the behaviour of WsControl with an app in
70 * Windows 98. It is not fully implemented, and there could
71 * be (are?) errors due to incorrect assumptions made.
74 * WsControl returns WSCTL_SUCCESS on success.
75 * STATUS_BUFFER_TOO_SMALL is returned if the output buffer length
76 * (*pcbResponseInfoLen) is too small, otherwise errors return -1.
78 * It doesn't seem to generate errors that can be retrieved by
79 * WSAGetLastError().
83 DWORD WINAPI WsControl(DWORD protocoll,
84 DWORD action,
85 LPVOID pRequestInfo,
86 LPDWORD pcbRequestInfoLen,
87 LPVOID pResponseInfo,
88 LPDWORD pcbResponseInfoLen)
90 /* Get the command structure into a pointer we can use,
91 rather than void */
92 TDIObjectID *pcommand = (TDIObjectID *)pRequestInfo;
94 TRACE (" WsControl TOI_ID=>0x%lx<, {TEI_ENTITY=0x%lx, TEI_INSTANCE=0x%lx}, TOI_CLASS=0x%lx, TOI_TYPE=0x%lx\n",
95 pcommand->toi_id, pcommand->toi_entity.tei_entity, pcommand->toi_entity.tei_instance,
96 pcommand->toi_class, pcommand->toi_type );
100 switch (action)
102 case WSCNTL_TCPIP_QUERY_INFO:
104 switch (pcommand->toi_id)
107 ENTITY_LIST_ID seems to get number of adapters in the system.
108 (almost like an index to be used when calling other WsControl options)
110 case ENTITY_LIST_ID:
112 TDIEntityID *baseptr = pResponseInfo;
113 int numInt = 0, i;
115 if (pcommand->toi_class != INFO_CLASS_GENERIC &&
116 pcommand->toi_type != INFO_TYPE_PROVIDER)
118 FIXME ("Unexpected Option for ENTITY_LIST_ID request -> toi_class=0x%lx, toi_type=0x%lx\n",
119 pcommand->toi_class, pcommand->toi_type);
120 return (WSAEOPNOTSUPP);
123 numInt = WSCNTL_GetEntryCount(WSCNTL_COUNT_INTERFACES);
124 if (numInt < 0)
126 ERR ("Unable to open /proc filesystem to determine number of network interfaces!\n");
127 return (-1);
130 if (*pcbResponseInfoLen < sizeof(TDIEntityID)*(numInt*2) )
132 return (STATUS_BUFFER_TOO_SMALL);
135 /* 0 it out first */
136 memset(baseptr, 0, sizeof(TDIEntityID)*(numInt*2));
138 for (i=0; i<numInt; i++)
140 /* tei_instance is an network interface identifier.
141 I'm not quite sure what the difference is between tei_entity values of
142 CL_NL_ENTITY and IF_ENTITY */
143 baseptr->tei_entity = CL_NL_ENTITY; baseptr->tei_instance = i; baseptr++;
144 baseptr->tei_entity = IF_ENTITY; baseptr->tei_instance = i; baseptr++;
147 /* Calculate size of out buffer */
148 *pcbResponseInfoLen = sizeof(TDIEntityID)*(numInt*2);
150 break;
154 /* ENTITY_TYPE_ID is used to obtain simple information about a
155 network card, such as MAC Address, description, interface type,
156 number of network addresses, etc. */
157 case ENTITY_TYPE_ID: /* ALSO: IP_MIB_STATS_ID */
159 if (pcommand->toi_class == INFO_CLASS_GENERIC && pcommand->toi_type == INFO_TYPE_PROVIDER)
161 if (pcommand->toi_entity.tei_entity == IF_ENTITY)
163 * ((ULONG *)pResponseInfo) = IF_MIB;
165 /* Calculate size of out buffer */
166 *pcbResponseInfoLen = sizeof (ULONG);
169 else if (pcommand->toi_entity.tei_entity == CL_NL_ENTITY)
171 * ((ULONG *)pResponseInfo) = CL_NL_IP;
173 /* Calculate size of out buffer */
174 *pcbResponseInfoLen = sizeof (ULONG);
177 else if (pcommand->toi_class == INFO_CLASS_PROTOCOL &&
178 pcommand->toi_type == INFO_TYPE_PROVIDER)
180 if (pcommand->toi_entity.tei_entity == IF_ENTITY)
182 /* In this case, we are requesting specific information about a
183 a particular network adapter. (MAC Address, speed, data transmitted/received,
184 etc.)
186 IFEntry *IntInfo = (IFEntry *) pResponseInfo;
187 char ifName[512];
188 struct ifreq ifInfo;
189 SOCKET sock;
192 if (!WSCNTL_GetInterfaceName(pcommand->toi_entity.tei_instance, ifName))
194 ERR ("Unable to parse /proc filesystem!\n");
195 return (-1);
198 /* Get a socket so that we can use ioctl */
199 if ( (sock = socket (AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET)
201 ERR ("Error creating socket!\n");
202 return (-1);
205 /* 0 out return structure first */
206 memset (IntInfo, 0, sizeof(IFEntry));
208 /* Interface ID */
209 IntInfo->if_index = pcommand->toi_entity.tei_instance;
211 /* MAC Address - Let's try to do this in a cross-platform way... */
212 #if defined(SIOCGIFHWADDR) /* Linux */
213 strcpy(ifInfo.ifr_name, ifName);
214 if (ioctlsocket(sock, SIOCGIFHWADDR, (ULONG*)&ifInfo) < 0)
216 ERR ("Error obtaining MAC Address!\n");
217 closesocket(sock);
218 return (-1);
220 else
222 /* FIXME: Is it correct to assume size of 6? */
223 memcpy(IntInfo->if_physaddr, ifInfo.ifr_hwaddr.sa_data, 6);
224 IntInfo->if_physaddrlen=6;
226 #elif defined(SIOCGENADDR) /* Solaris */
227 if (ioctlsocket(sock, SIOCGENADDR, (ULONG*)&ifInfo) < 0)
229 ERR ("Error obtaining MAC Address!\n");
230 closesocket(sock);
231 return (-1);
233 else
235 /* FIXME: Is it correct to assume size of 6? */
236 memcpy(IntInfo->if_physaddr, ifInfo.ifr_enaddr, 6);
237 IntInfo->if_physaddrlen=6;
239 #else
240 memset (IntInfo->if_physaddr, 0, 6);
241 ERR ("Unable to determine MAC Address on your platform!\n");
242 #endif
245 /* Interface name and length */
246 strcpy (IntInfo->if_descr, ifName);
247 IntInfo->if_descrlen= strlen (IntInfo->if_descr);
249 /* Obtain bytes transmitted/received for interface */
250 if ( (WSCNTL_GetTransRecvStat(pcommand->toi_entity.tei_instance,
251 &IntInfo->if_inoctets, &IntInfo->if_outoctets)) < 0)
253 ERR ("Error obtaining transmit/receive stats for the network interface!\n");
254 closesocket(sock);
255 return (-1);
259 /* FIXME: How should the below be properly calculated? ******************/
260 IntInfo->if_type = 0x6; /* Ethernet (?) */
261 IntInfo->if_speed = 1000000; /* Speed of interface (bits per second?) */
262 /************************************************************************/
264 closesocket(sock);
265 *pcbResponseInfoLen = sizeof (IFEntry) + IntInfo->if_descrlen;
267 else if (pcommand->toi_entity.tei_entity == CL_NL_ENTITY)
269 IPSNMPInfo *infoStruc = (IPSNMPInfo *) pResponseInfo;
270 int numInt, numRoutes;
272 /* This case is used to obtain general statistics about the
273 network */
275 if (*pcbResponseInfoLen < sizeof(IPSNMPInfo) )
277 return (STATUS_BUFFER_TOO_SMALL);
279 else
281 /* 0 it out first */
282 memset(infoStruc, 0, sizeof(IPSNMPInfo));
284 /* Get the number of interfaces */
285 numInt = WSCNTL_GetEntryCount(WSCNTL_COUNT_INTERFACES);
286 if (numInt < 0)
288 ERR ("Unable to open /proc filesystem to determine number of network interfaces!\n");
289 return (-1);
291 /* Get the number of routes */
292 numRoutes = WSCNTL_GetEntryCount(WSCNTL_COUNT_ROUTES);
293 if (numRoutes < 0)
295 ERR ("Unable to open /proc filesystem to determine number of network routes!\n");
296 return (-1);
299 infoStruc->ipsi_numif = numInt; /* # of interfaces */
300 infoStruc->ipsi_numaddr = numInt; /* # of addresses */
301 infoStruc->ipsi_numroutes = numRoutes; /* # of routes */
303 /* FIXME: How should the below be properly calculated? ******************/
304 infoStruc->ipsi_forwarding = 0x0;
305 infoStruc->ipsi_defaultttl = 0x0;
306 infoStruc->ipsi_inreceives = 0x0;
307 infoStruc->ipsi_inhdrerrors = 0x0;
308 infoStruc->ipsi_inaddrerrors = 0x0;
309 infoStruc->ipsi_forwdatagrams = 0x0;
310 infoStruc->ipsi_inunknownprotos = 0x0;
311 infoStruc->ipsi_indiscards = 0x0;
312 infoStruc->ipsi_indelivers = 0x0;
313 infoStruc->ipsi_outrequests = 0x0;
314 infoStruc->ipsi_routingdiscards = 0x0;
315 infoStruc->ipsi_outdiscards = 0x0;
316 infoStruc->ipsi_outnoroutes = 0x0;
317 infoStruc->ipsi_reasmtimeout = 0x0;
318 infoStruc->ipsi_reasmreqds = 0x0;
319 infoStruc->ipsi_reasmoks = 0x0;
320 infoStruc->ipsi_reasmfails = 0x0;
321 infoStruc->ipsi_fragoks = 0x0;
322 infoStruc->ipsi_fragfails = 0x0;
323 infoStruc->ipsi_fragcreates = 0x0;
324 /************************************************************************/
326 /* Calculate size of out buffer */
327 *pcbResponseInfoLen = sizeof(IPSNMPInfo);
331 else
333 FIXME ("Unexpected Option for ENTITY_TYPE_ID request -> toi_class=0x%lx, toi_type=0x%lx\n",
334 pcommand->toi_class, pcommand->toi_type);
336 return (WSAEOPNOTSUPP);
339 break;
343 /* IP_MIB_ADDRTABLE_ENTRY_ID is used to obtain more detailed information about a
344 particular network adapter */
345 case IP_MIB_ADDRTABLE_ENTRY_ID:
347 IPAddrEntry *baseIPInfo = (IPAddrEntry *) pResponseInfo;
348 char ifName[IFNAMSIZ+1];
349 struct ifreq ifInfo;
350 SOCKET sock;
352 if (*pcbResponseInfoLen < sizeof(IPAddrEntry))
354 return (STATUS_BUFFER_TOO_SMALL);
357 if (!WSCNTL_GetInterfaceName(pcommand->toi_entity.tei_instance, ifName))
359 ERR ("Unable to parse /proc filesystem!\n");
360 return (-1);
364 /* Get a socket so we can use ioctl */
365 if ( (sock = socket (AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET)
367 ERR ("Error creating socket!\n");
368 return (-1);
371 /* 0 it out first */
372 memset(baseIPInfo, 0, sizeof(IPAddrEntry) );
374 /* Interface Id */
375 baseIPInfo->iae_index = pcommand->toi_entity.tei_instance;
377 /* IP Address */
378 strcpy (ifInfo.ifr_name, ifName);
379 ifInfo.ifr_addr.sa_family = AF_INET;
380 if (ioctlsocket(sock, SIOCGIFADDR, (ULONG*)&ifInfo) < 0)
382 baseIPInfo->iae_addr = 0x0;
384 else
386 struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_addr;
387 baseIPInfo->iae_addr = ipTemp->sin_addr.S_un.S_addr;
390 /* Broadcast Address */
391 strcpy (ifInfo.ifr_name, ifName);
392 if (ioctlsocket(sock, SIOCGIFBRDADDR, (ULONG *)&ifInfo) < 0)
394 baseIPInfo->iae_bcastaddr = 0x0;
396 else
398 struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_broadaddr;
399 baseIPInfo->iae_bcastaddr = ipTemp->sin_addr.S_un.S_addr;
402 /* Subnet Mask */
403 strcpy(ifInfo.ifr_name, ifName);
404 if (ioctlsocket(sock, SIOCGIFNETMASK, (ULONG *)&ifInfo) < 0)
406 baseIPInfo->iae_mask = 0x0;
408 else
410 /* Trying to avoid some compile problems across platforms.
411 (Linux, FreeBSD, Solaris...) */
412 #ifndef ifr_netmask
413 #ifndef ifr_addr
414 baseIPInfo->iae_mask = 0;
415 ERR ("Unable to determine Netmask on your platform!\n");
416 #else
417 struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_addr;
418 baseIPInfo->iae_mask = ipTemp->sin_addr.S_un.S_addr;
419 #endif
420 #else
421 struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_netmask;
422 baseIPInfo->iae_mask = ipTemp->sin_addr.S_un.S_addr;
423 #endif
426 /* FIXME: How should the below be properly calculated? ******************/
427 baseIPInfo->iae_reasmsize = 0x0;
428 baseIPInfo->iae_context = 0x0;
429 baseIPInfo->iae_pad = 0x0;
430 /************************************************************************/
432 /* Calculate size of out buffer */
433 *pcbResponseInfoLen = sizeof(IPAddrEntry);
434 closesocket(sock);
435 break;
439 /* This call returns the routing table.
440 * No official documentation found, even the name of the command is unknown.
441 * Work is based on
442 * http://www.cyberport.com/~tangent/programming/winsock/articles/wscontrol.html
443 * and testings done with winipcfg.exe, route.exe and ipconfig.exe.
444 * pcommand->toi_entity.tei_instance seems to be the interface number
445 * but route.exe outputs only the information for the last interface
446 * if only the routes for the pcommand->toi_entity.tei_instance
447 * interface are returned. */
448 case IP_MIB_ROUTETABLE_ENTRY_ID: /* FIXME: not real name. Value is 0x101 */
450 int numRoutes, foundRoutes;
451 wscntl_routeentry *routeTable, *routePtr; /* route table */
453 IPRouteEntry *winRouteTable = (IPRouteEntry *) pResponseInfo;
455 /* Get the number of routes */
456 numRoutes = WSCNTL_GetEntryCount(WSCNTL_COUNT_ROUTES);
457 if (numRoutes < 0)
459 ERR ("Unable to open /proc filesystem to determine number of network routes!\n");
460 return (-1);
463 if (*pcbResponseInfoLen < (sizeof(IPRouteEntry) * numRoutes))
465 return (STATUS_BUFFER_TOO_SMALL);
468 /* malloc space for the routeTable */
469 routeTable = (wscntl_routeentry *) malloc(sizeof(wscntl_routeentry) * numRoutes);
470 if (!routeTable)
472 ERR ("couldn't malloc space for routeTable!\n");
475 /* get the route table */
476 foundRoutes = WSCNTL_GetRouteTable(numRoutes, routeTable);
477 if (foundRoutes < 0)
479 ERR ("Unable to open /proc filesystem to parse the route entrys!\n");
480 free(routeTable);
481 return -1;
483 routePtr = routeTable;
485 /* first 0 out the output buffer */
486 memset(winRouteTable, 0, *pcbResponseInfoLen);
488 /* calculate the length of the data in the output buffer */
489 *pcbResponseInfoLen = sizeof(IPRouteEntry) * foundRoutes;
491 for ( ; foundRoutes > 0; foundRoutes--)
493 winRouteTable->ire_addr = routePtr->wre_dest;
494 winRouteTable->ire_index = routePtr->wre_intf;
495 winRouteTable->ire_metric = routePtr->wre_metric;
496 /* winRouteTable->ire_option4 =
497 winRouteTable->ire_option5 =
498 winRouteTable->ire_option6 = */
499 winRouteTable->ire_gw = routePtr->wre_gw;
500 /* winRouteTable->ire_option8 =
501 winRouteTable->ire_option9 =
502 winRouteTable->ire_option10 = */
503 winRouteTable->ire_mask = routePtr->wre_mask;
504 /* winRouteTable->ire_option12 = */
506 winRouteTable++;
507 routePtr++;
510 free(routeTable);
511 break;
515 default:
517 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",
518 pcommand->toi_id, pcommand->toi_entity.tei_entity, pcommand->toi_entity.tei_instance,
519 pcommand->toi_class, pcommand->toi_type);
521 return (WSAEOPNOTSUPP);
525 break;
528 case WSCNTL_TCPIP_ICMP_ECHO:
530 unsigned int addr = *(unsigned int*)pRequestInfo;
531 #if 0
532 int timeout= *(unsigned int*)(inbuf+4);
533 short x1 = *(unsigned short*)(inbuf+8);
534 short sendbufsize = *(unsigned short*)(inbuf+10);
535 char x2 = *(unsigned char*)(inbuf+12);
536 char ttl = *(unsigned char*)(inbuf+13);
537 char service = *(unsigned char*)(inbuf+14);
538 char type= *(unsigned char*)(inbuf+15); /* 0x2: don't fragment*/
539 #endif
541 FIXME("(ICMP_ECHO) to 0x%08x stub \n", addr);
542 break;
545 default:
547 FIXME("Protocoll Not Supported -> protocoll=0x%lx, action=0x%lx, Request=%p, RequestLen=%p, Response=%p, ResponseLen=%p\n",
548 protocoll, action, pRequestInfo, pcbRequestInfoLen, pResponseInfo, pcbResponseInfoLen);
550 return (WSAEOPNOTSUPP);
555 return (WSCTL_SUCCESS);
561 Helper function for WsControl - Get count of the number of interfaces
562 or routes by parsing /proc filesystem.
564 int WSCNTL_GetEntryCount(const int entrytype)
566 char *filename;
567 int fd;
568 char buf[512]; /* Size optimized for a typical workstation */
569 char *ptr;
570 int count;
571 int chrread;
574 switch (entrytype)
576 case WSCNTL_COUNT_INTERFACES:
578 filename = PROCFS_NETDEV_FILE;
579 count = -2; /* two haeder lines */
580 break;
583 case WSCNTL_COUNT_ROUTES:
585 filename = PROCFS_ROUTE_FILE;
586 count = -1; /* one haeder line */
587 break;
590 default:
592 return -1;
596 /* open /proc filesystem file */
597 fd = open(filename, O_RDONLY);
598 if (fd < 0) {
599 return -1;
602 /* read the file and count the EOL's */
603 while ((chrread = read(fd, buf, sizeof(buf))) != 0)
605 ptr = buf;
606 if (chrread < 0)
608 if (errno == EINTR)
610 continue; /* read interupted by a signal, try to read again */
612 else
614 close(fd);
615 return -1;
618 while ((ptr = memchr(ptr, '\n', chrread - (int) (ptr - buf))) > 0)
620 count++;
621 ptr++;
625 close(fd);
626 return count;
631 Helper function for WsControl - Get name of device from interface number
632 by parsing /proc filesystem.
634 int WSCNTL_GetInterfaceName(int intNumber, char *intName)
636 FILE *procfs;
637 char buf[512]; /* Size doesn't matter, something big */
638 int i;
640 /* Open /proc filesystem file for network devices */
641 procfs = fopen(PROCFS_NETDEV_FILE, "r");
642 if (!procfs)
644 /* If we can't open the file, return an error */
645 return (-1);
648 /* Omit first two lines, they are only headers */
649 fgets(buf, sizeof(buf), procfs);
650 fgets(buf, sizeof(buf), procfs);
652 for (i=0; i<intNumber; i++)
654 /* Skip the lines that don't interest us. */
655 fgets(buf, sizeof(buf), procfs);
657 fgets(buf, sizeof(buf), procfs); /* This is the line we want */
660 /* Parse out the line, grabbing only the name of the device
661 to the intName variable
663 The Line comes in like this: (we only care about the device name)
664 lo: 21970 377 0 0 0 0 0 0 21970 377 0 0 0 0 0 0
666 i=0;
667 while (isspace(buf[i])) /* Skip initial space(s) */
669 i++;
672 while (buf[i])
674 if (isspace(buf[i]))
676 break;
679 if (buf[i] == ':') /* FIXME: Not sure if this block (alias detection) works properly */
681 /* This interface could be an alias... */
682 int hold = i;
683 char *dotname = intName;
684 *intName++ = buf[i++];
686 while (isdigit(buf[i]))
688 *intName++ = buf[i++];
691 if (buf[i] != ':')
693 /* ... It wasn't, so back up */
694 i = hold;
695 intName = dotname;
698 if (buf[i] == '\0')
700 fclose(procfs);
701 return(FALSE);
704 i++;
705 break;
708 *intName++ = buf[i++];
710 *intName++ = '\0';
712 fclose(procfs);
713 return(TRUE);
718 Helper function for WsControl - This function returns the bytes (octets) transmitted
719 and received for the supplied interface number from the /proc fs.
721 int WSCNTL_GetTransRecvStat(int intNumber, unsigned long *transBytes, unsigned long *recvBytes)
723 FILE *procfs;
724 char buf[512], result[512]; /* Size doesn't matter, something big */
725 int i, bufPos, resultPos;
727 /* Open /proc filesystem file for network devices */
728 procfs = fopen(PROCFS_NETDEV_FILE, "r");
729 if (!procfs)
731 /* If we can't open the file, return an error */
732 return (-1);
735 /* Omit first two lines, they are only headers */
736 fgets(buf, sizeof(buf), procfs);
737 fgets(buf, sizeof(buf), procfs);
739 for (i=0; i<intNumber; i++)
741 /* Skip the lines that don't interest us. */
742 fgets(buf, sizeof(buf), procfs);
744 fgets(buf, sizeof(buf), procfs); /* This is the line we want */
748 /* Parse out the line, grabbing the number of bytes transmitted
749 and received on the interface.
751 The Line comes in like this: (we care about columns 2 and 10)
752 lo: 21970 377 0 0 0 0 0 0 21970 377 0 0 0 0 0 0
755 /* Start at character 0 in the buffer */
756 bufPos=0;
758 /* Skip initial space(s) */
759 while (isspace(buf[bufPos]))
760 bufPos++;
763 /* Skip the name and its trailing spaces (if any) */
764 while (buf[bufPos])
766 if (isspace(buf[bufPos]))
767 break;
769 if (buf[bufPos] == ':') /* Could be an alias */
771 int hold = bufPos;
773 while(isdigit (buf[bufPos]))
774 bufPos++;
775 if (buf[bufPos] != ':')
776 bufPos = hold;
777 if (buf[bufPos] == '\0')
779 fclose(procfs);
780 return(FALSE);
783 bufPos++;
784 break;
787 bufPos++;
789 while (isspace(buf[bufPos]))
790 bufPos++;
793 /* This column (#2) is the number of bytes received. */
794 resultPos = 0;
795 while (!isspace(buf[bufPos]))
797 result[resultPos] = buf[bufPos];
798 result[resultPos+1]='\0';
799 resultPos++; bufPos++;
801 *recvBytes = strtoul (result, NULL, 10); /* convert string to unsigned long, using base 10 */
804 /* Skip columns #3 to #9 (Don't need them) */
805 for (i=0; i<7; i++)
807 while (isspace(buf[bufPos]))
808 bufPos++;
809 while (!isspace(buf[bufPos]))
810 bufPos++;
814 /* This column (#10) is the number of bytes transmitted */
815 while (isspace(buf[bufPos]))
816 bufPos++;
818 resultPos = 0;
819 while (!isspace(buf[bufPos]))
821 result[resultPos] = buf[bufPos];
822 result[resultPos+1]='\0';
823 resultPos++; bufPos++;
825 *transBytes = strtoul (result, NULL, 10); /* convert string to unsigned long, using base 10 */
828 fclose(procfs);
829 return(TRUE);
833 /* Parse the procfs route file and put the datas into routeTable.
834 * Return value is the number of found routes */
835 int WSCNTL_GetRouteTable(int numRoutes, wscntl_routeentry *routeTable)
837 int nrIntf; /* total number of interfaces */
838 char buf[256]; /* temporary buffer */
839 char *ptr; /* pointer to temporary buffer */
840 FILE *file; /* file handle for procfs route file */
841 int foundRoutes = 0; /* number of found routes */
842 typedef struct interface_t {
843 char intfName[IFNAMSIZ+1]; /* the name of the interface */
844 int intfNameLen; /* length of interface name */
845 } interface_t;
846 interface_t *interface;
847 int intfNr; /* the interface number */
849 wscntl_routeentry *routePtr = routeTable;
851 /* get the number of interfaces */
852 nrIntf = WSCNTL_GetEntryCount(WSCNTL_COUNT_INTERFACES);
853 if (nrIntf < 0)
855 ERR ("Unable to open /proc filesystem to determine number of network interfaces!\n");
856 return (-1);
859 /* malloc space for the interface struct array */
860 interface = (interface_t *) malloc(sizeof(interface_t) * nrIntf);
861 if (!routeTable)
863 ERR ("couldn't malloc space for interface!\n");
866 for (intfNr = 0; intfNr < nrIntf; intfNr++) {
867 if (WSCNTL_GetInterfaceName(intfNr, interface[intfNr].intfName) < 0)
869 ERR ("Unable to open /proc filesystem to determine the name of network interfaces!\n");
870 free(interface);
871 return (-1);
873 interface[intfNr].intfNameLen = strlen(interface[intfNr].intfName);
876 /* Open /proc filesystem file for routes */
877 file = fopen(PROCFS_ROUTE_FILE, "r");
878 if (!file)
880 /* If we can't open the file, return an error */
881 free(interface);
882 return (-1);
885 /* skip the header line */
886 fgets(buf, sizeof(buf), file);
888 /* parse the rest of the file and put the matching entrys into routeTable.
889 Format of procfs route entry:
890 Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT
891 lo 0000007F 00000000 0001 0 0 0 000000FF 0 0 0
893 while (fgets(buf, sizeof(buf), file)) {
894 intfNr = 0;
895 /* find the interface of the route */
896 while ((strncmp(buf, interface[intfNr].intfName, interface[intfNr].intfNameLen) != 0)
897 && (intfNr < nrIntf))
899 intfNr++;
901 if (intfNr < nrIntf) {
902 foundRoutes++;
903 if (foundRoutes > numRoutes) {
904 /* output buffer is to small */
905 ERR("buffer to small to fit all routes found into it!\n");
906 free(interface);
907 fclose(file);
908 return -1;
910 ptr = buf;
911 ptr += interface[intfNr].intfNameLen;
912 routePtr->wre_intf = intfNr;
913 routePtr->wre_dest = strtoul(ptr, &ptr, 16); /* destination */
914 routePtr->wre_gw = strtoul(ptr, &ptr, 16); /* gateway */
915 strtoul(ptr, &ptr, 16); /* Flags; unused */
916 strtoul(ptr, &ptr, 16); /* RefCnt; unused */
917 strtoul(ptr, &ptr, 16); /* Use; unused */
918 routePtr->wre_metric = strtoul(ptr, &ptr, 16); /* metric */
919 routePtr->wre_mask = strtoul(ptr, &ptr, 16); /* mask */
920 /* strtoul(ptr, &ptr, 16); MTU; unused */
921 /* strtoul(ptr, &ptr, 16); Window; unused */
922 /* strtoul(ptr, &ptr, 16); IRTT; unused */
924 routePtr++;
926 else
928 /* this should never happen */
929 WARN("Skipping route with unknown interface\n");
933 free(interface);
934 fclose(file);
935 return foundRoutes;
939 /***********************************************************************
940 * WSARecvEx (WSOCK32.1107)
942 * WSARecvEx is a Microsoft specific extension to winsock that is identical to recv
943 * except that has an in/out argument call flags that has the value MSG_PARTIAL ored
944 * into the flags parameter when a partial packet is read. This only applies to
945 * sockets using the datagram protocol. This method does not seem to be implemented
946 * correctly by microsoft as the winsock implementation does not set the MSG_PARTIAL
947 * flag when a fragmented packet arrives.
949 INT WINAPI WSARecvEx(SOCKET s, char *buf, INT len, INT *flags)
951 FIXME("(WSARecvEx) partial packet return value not set \n");
952 return recv(s, buf, len, *flags);
956 /***********************************************************************
957 * s_perror (WSOCK32.1108)
959 void WINAPI WS_s_perror(LPCSTR message)
961 FIXME("(%s): stub\n",message);
962 return;