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>
49 /* FIXME: The rest of the socket() cdecl<->stdapi stack corruption problem
52 extern SOCKET WINAPI
socket(INT af
, INT type
, INT protocol
);
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>
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
83 DWORD WINAPI
WsControl(DWORD protocoll
,
86 LPDWORD pcbRequestInfoLen
,
88 LPDWORD pcbResponseInfoLen
)
90 /* Get the command structure into a pointer we can use,
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
);
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)
112 TDIEntityID
*baseptr
= pResponseInfo
;
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
);
126 ERR ("Unable to open /proc filesystem to determine number of network interfaces!\n");
130 if (*pcbResponseInfoLen
< sizeof(TDIEntityID
)*(numInt
*2) )
132 return (STATUS_BUFFER_TOO_SMALL
);
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);
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,
186 IFEntry
*IntInfo
= (IFEntry
*) pResponseInfo
;
192 if (!WSCNTL_GetInterfaceName(pcommand
->toi_entity
.tei_instance
, ifName
))
194 ERR ("Unable to parse /proc filesystem!\n");
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");
205 /* 0 out return structure first */
206 memset (IntInfo
, 0, sizeof(IFEntry
));
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");
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");
235 /* FIXME: Is it correct to assume size of 6? */
236 memcpy(IntInfo
->if_physaddr
, ifInfo
.ifr_enaddr
, 6);
237 IntInfo
->if_physaddrlen
=6;
240 memset (IntInfo
->if_physaddr
, 0, 6);
241 ERR ("Unable to determine MAC Address on your platform!\n");
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");
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 /************************************************************************/
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
275 if (*pcbResponseInfoLen
< sizeof(IPSNMPInfo
) )
277 return (STATUS_BUFFER_TOO_SMALL
);
282 memset(infoStruc
, 0, sizeof(IPSNMPInfo
));
284 /* Get the number of interfaces */
285 numInt
= WSCNTL_GetEntryCount(WSCNTL_COUNT_INTERFACES
);
288 ERR ("Unable to open /proc filesystem to determine number of network interfaces!\n");
291 /* Get the number of routes */
292 numRoutes
= WSCNTL_GetEntryCount(WSCNTL_COUNT_ROUTES
);
295 ERR ("Unable to open /proc filesystem to determine number of network routes!\n");
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
);
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
);
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];
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");
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");
372 memset(baseIPInfo
, 0, sizeof(IPAddrEntry
) );
375 baseIPInfo
->iae_index
= pcommand
->toi_entity
.tei_instance
;
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;
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;
398 struct ws_sockaddr_in
*ipTemp
= (struct ws_sockaddr_in
*)&ifInfo
.ifr_broadaddr
;
399 baseIPInfo
->iae_bcastaddr
= ipTemp
->sin_addr
.S_un
.S_addr
;
403 strcpy(ifInfo
.ifr_name
, ifName
);
404 if (ioctlsocket(sock
, SIOCGIFNETMASK
, (ULONG
*)&ifInfo
) < 0)
406 baseIPInfo
->iae_mask
= 0x0;
410 /* Trying to avoid some compile problems across platforms.
411 (Linux, FreeBSD, Solaris...) */
414 baseIPInfo
->iae_mask
= 0;
415 ERR ("Unable to determine Netmask on your platform!\n");
417 struct ws_sockaddr_in
*ipTemp
= (struct ws_sockaddr_in
*)&ifInfo
.ifr_addr
;
418 baseIPInfo
->iae_mask
= ipTemp
->sin_addr
.S_un
.S_addr
;
421 struct ws_sockaddr_in
*ipTemp
= (struct ws_sockaddr_in
*)&ifInfo
.ifr_netmask
;
422 baseIPInfo
->iae_mask
= ipTemp
->sin_addr
.S_un
.S_addr
;
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
);
439 /* This call returns the routing table.
440 * No official documentation found, even the name of the command is unknown.
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
);
459 ERR ("Unable to open /proc filesystem to determine number of network routes!\n");
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
);
472 ERR ("couldn't malloc space for routeTable!\n");
475 /* get the route table */
476 foundRoutes
= WSCNTL_GetRouteTable(numRoutes
, routeTable
);
479 ERR ("Unable to open /proc filesystem to parse the route entrys!\n");
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 = */
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
);
528 case WSCNTL_TCPIP_ICMP_ECHO
:
530 unsigned int addr
= *(unsigned int*)pRequestInfo
;
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*/
541 FIXME("(ICMP_ECHO) to 0x%08x stub \n", addr
);
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
)
568 char buf
[512]; /* Size optimized for a typical workstation */
576 case WSCNTL_COUNT_INTERFACES
:
578 filename
= PROCFS_NETDEV_FILE
;
579 count
= -2; /* two haeder lines */
583 case WSCNTL_COUNT_ROUTES
:
585 filename
= PROCFS_ROUTE_FILE
;
586 count
= -1; /* one haeder line */
596 /* open /proc filesystem file */
597 fd
= open(filename
, O_RDONLY
);
602 /* read the file and count the EOL's */
603 while ((chrread
= read(fd
, buf
, sizeof(buf
))) != 0)
610 continue; /* read interupted by a signal, try to read again */
618 while ((ptr
= memchr(ptr
, '\n', chrread
- (int) (ptr
- buf
))) > 0)
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
)
637 char buf
[512]; /* Size doesn't matter, something big */
640 /* Open /proc filesystem file for network devices */
641 procfs
= fopen(PROCFS_NETDEV_FILE
, "r");
644 /* If we can't open the file, return an error */
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
667 while (isspace(buf
[i
])) /* Skip initial space(s) */
679 if (buf
[i
] == ':') /* FIXME: Not sure if this block (alias detection) works properly */
681 /* This interface could be an alias... */
683 char *dotname
= intName
;
684 *intName
++ = buf
[i
++];
686 while (isdigit(buf
[i
]))
688 *intName
++ = buf
[i
++];
693 /* ... It wasn't, so back up */
708 *intName
++ = buf
[i
++];
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
)
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");
731 /* If we can't open the file, return an error */
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 */
758 /* Skip initial space(s) */
759 while (isspace(buf
[bufPos
]))
763 /* Skip the name and its trailing spaces (if any) */
766 if (isspace(buf
[bufPos
]))
769 if (buf
[bufPos
] == ':') /* Could be an alias */
773 while(isdigit (buf
[bufPos
]))
775 if (buf
[bufPos
] != ':')
777 if (buf
[bufPos
] == '\0')
789 while (isspace(buf
[bufPos
]))
793 /* This column (#2) is the number of bytes received. */
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) */
807 while (isspace(buf
[bufPos
]))
809 while (!isspace(buf
[bufPos
]))
814 /* This column (#10) is the number of bytes transmitted */
815 while (isspace(buf
[bufPos
]))
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 */
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 */
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
);
855 ERR ("Unable to open /proc filesystem to determine number of network interfaces!\n");
859 /* malloc space for the interface struct array */
860 interface
= (interface_t
*) malloc(sizeof(interface_t
) * nrIntf
);
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");
873 interface
[intfNr
].intfNameLen
= strlen(interface
[intfNr
].intfName
);
876 /* Open /proc filesystem file for routes */
877 file
= fopen(PROCFS_ROUTE_FILE
, "r");
880 /* If we can't open the file, return an error */
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
)) {
895 /* find the interface of the route */
896 while ((strncmp(buf
, interface
[intfNr
].intfName
, interface
[intfNr
].intfNameLen
) != 0)
897 && (intfNr
< nrIntf
))
901 if (intfNr
< nrIntf
) {
903 if (foundRoutes
> numRoutes
) {
904 /* output buffer is to small */
905 ERR("buffer to small to fit all routes found into it!\n");
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 */
928 /* this should never happen */
929 WARN("Skipping route with unknown interface\n");
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
);