1 /* Copyright (C) 2003,2006 Juan Lang
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 2.1 of the License, or (at your option) any later version.
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17 * This file implements statistics getting using the /proc filesystem exported
18 * by Linux, and maybe other OSes.
22 #include "wine/port.h"
23 #include "wine/debug.h"
29 #include <sys/types.h>
30 #ifdef HAVE_SYS_SOCKET_H
31 #include <sys/socket.h>
33 #ifdef HAVE_NETINET_IN_H
34 #include <netinet/in.h>
36 #ifdef HAVE_ARPA_INET_H
37 #include <arpa/inet.h>
42 #ifdef HAVE_NET_ROUTE_H
43 #include <net/route.h>
45 #ifdef HAVE_NET_IF_ARP_H
46 #include <net/if_arp.h>
48 #ifdef HAVE_NETINET_TCP_H
49 #include <netinet/tcp.h>
51 #ifdef HAVE_NETINET_TCP_FSM_H
52 #include <netinet/tcp_fsm.h>
55 #ifdef HAVE_SYS_SYSCTL_H
56 #include <sys/sysctl.h>
60 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
61 #define ADVANCE(x, n) (x += ROUNDUP(((struct sockaddr *)n)->sa_len))
70 #define TCPS_ESTABLISHED 1
71 #define TCPS_SYN_SENT 2
72 #define TCPS_SYN_RECEIVED 3
73 #define TCPS_FIN_WAIT_1 4
74 #define TCPS_FIN_WAIT_2 5
75 #define TCPS_TIME_WAIT 6
77 #define TCPS_CLOSE_WAIT 8
78 #define TCPS_LAST_ACK 9
79 #define TCPS_LISTEN 10
80 #define TCPS_CLOSING 11
83 WINE_DEFAULT_DEBUG_CHANNEL(iphlpapi
);
85 DWORD
getInterfaceStatsByName(const char *name
, PMIB_IFROW entry
)
90 return ERROR_INVALID_PARAMETER
;
92 return ERROR_INVALID_PARAMETER
;
94 /* get interface stats from /proc/net/dev, no error if can't
95 no inUnknownProtos, outNUcastPkts, outQLen */
96 fp
= fopen("/proc/net/dev", "r");
98 char buf
[512] = { 0 }, *ptr
;
99 int nameLen
= strlen(name
), nameFound
= 0;
102 ptr
= fgets(buf
, sizeof(buf
), fp
);
103 while (ptr
&& !nameFound
) {
104 while (*ptr
&& isspace(*ptr
))
106 if (strncasecmp(ptr
, name
, nameLen
) == 0 && *(ptr
+ nameLen
) == ':')
109 ptr
= fgets(buf
, sizeof(buf
), fp
);
116 entry
->dwInOctets
= strtoul(ptr
, &endPtr
, 10);
120 entry
->dwInUcastPkts
= strtoul(ptr
, &endPtr
, 10);
124 entry
->dwInErrors
= strtoul(ptr
, &endPtr
, 10);
128 entry
->dwInDiscards
= strtoul(ptr
, &endPtr
, 10);
132 strtoul(ptr
, &endPtr
, 10); /* skip */
136 strtoul(ptr
, &endPtr
, 10); /* skip */
140 strtoul(ptr
, &endPtr
, 10); /* skip */
144 entry
->dwInNUcastPkts
= strtoul(ptr
, &endPtr
, 10);
148 entry
->dwOutOctets
= strtoul(ptr
, &endPtr
, 10);
152 entry
->dwOutUcastPkts
= strtoul(ptr
, &endPtr
, 10);
156 entry
->dwOutErrors
= strtoul(ptr
, &endPtr
, 10);
160 entry
->dwOutDiscards
= strtoul(ptr
, &endPtr
, 10);
167 ERR ("unimplemented!\n");
172 DWORD
getICMPStats(MIB_ICMP
*stats
)
177 return ERROR_INVALID_PARAMETER
;
179 memset(stats
, 0, sizeof(MIB_ICMP
));
180 /* get most of these stats from /proc/net/snmp, no error if can't */
181 fp
= fopen("/proc/net/snmp", "r");
183 static const char hdr
[] = "Icmp:";
184 char buf
[512] = { 0 }, *ptr
;
187 ptr
= fgets(buf
, sizeof(buf
), fp
);
188 } while (ptr
&& strncasecmp(buf
, hdr
, sizeof(hdr
) - 1));
190 /* last line was a header, get another */
191 ptr
= fgets(buf
, sizeof(buf
), fp
);
192 if (ptr
&& strncasecmp(buf
, hdr
, sizeof(hdr
) - 1) == 0) {
197 stats
->stats
.icmpInStats
.dwMsgs
= strtoul(ptr
, &endPtr
, 10);
201 stats
->stats
.icmpInStats
.dwErrors
= strtoul(ptr
, &endPtr
, 10);
205 stats
->stats
.icmpInStats
.dwDestUnreachs
= strtoul(ptr
, &endPtr
, 10);
209 stats
->stats
.icmpInStats
.dwTimeExcds
= strtoul(ptr
, &endPtr
, 10);
213 stats
->stats
.icmpInStats
.dwParmProbs
= strtoul(ptr
, &endPtr
, 10);
217 stats
->stats
.icmpInStats
.dwSrcQuenchs
= strtoul(ptr
, &endPtr
, 10);
221 stats
->stats
.icmpInStats
.dwRedirects
= strtoul(ptr
, &endPtr
, 10);
225 stats
->stats
.icmpInStats
.dwEchoReps
= strtoul(ptr
, &endPtr
, 10);
229 stats
->stats
.icmpInStats
.dwTimestamps
= strtoul(ptr
, &endPtr
, 10);
233 stats
->stats
.icmpInStats
.dwTimestampReps
= strtoul(ptr
, &endPtr
, 10);
237 stats
->stats
.icmpInStats
.dwAddrMasks
= strtoul(ptr
, &endPtr
, 10);
241 stats
->stats
.icmpInStats
.dwAddrMaskReps
= strtoul(ptr
, &endPtr
, 10);
245 stats
->stats
.icmpOutStats
.dwMsgs
= strtoul(ptr
, &endPtr
, 10);
249 stats
->stats
.icmpOutStats
.dwErrors
= strtoul(ptr
, &endPtr
, 10);
253 stats
->stats
.icmpOutStats
.dwDestUnreachs
= strtoul(ptr
, &endPtr
, 10);
257 stats
->stats
.icmpOutStats
.dwTimeExcds
= strtoul(ptr
, &endPtr
, 10);
261 stats
->stats
.icmpOutStats
.dwParmProbs
= strtoul(ptr
, &endPtr
, 10);
265 stats
->stats
.icmpOutStats
.dwSrcQuenchs
= strtoul(ptr
, &endPtr
, 10);
269 stats
->stats
.icmpOutStats
.dwRedirects
= strtoul(ptr
, &endPtr
, 10);
273 stats
->stats
.icmpOutStats
.dwEchoReps
= strtoul(ptr
, &endPtr
, 10);
277 stats
->stats
.icmpOutStats
.dwTimestamps
= strtoul(ptr
, &endPtr
, 10);
281 stats
->stats
.icmpOutStats
.dwTimestampReps
= strtoul(ptr
, &endPtr
, 10);
285 stats
->stats
.icmpOutStats
.dwAddrMasks
= strtoul(ptr
, &endPtr
, 10);
289 stats
->stats
.icmpOutStats
.dwAddrMaskReps
= strtoul(ptr
, &endPtr
, 10);
297 ERR ("unimplemented!\n");
302 DWORD
getIPStats(PMIB_IPSTATS stats
)
307 return ERROR_INVALID_PARAMETER
;
309 memset(stats
, 0, sizeof(MIB_IPSTATS
));
310 stats
->dwNumIf
= stats
->dwNumAddr
= getNumInterfaces();
311 stats
->dwNumRoutes
= getNumRoutes();
313 /* get most of these stats from /proc/net/snmp, no error if can't */
314 fp
= fopen("/proc/net/snmp", "r");
316 static const char hdr
[] = "Ip:";
317 char buf
[512] = { 0 }, *ptr
;
320 ptr
= fgets(buf
, sizeof(buf
), fp
);
321 } while (ptr
&& strncasecmp(buf
, hdr
, sizeof(hdr
) - 1));
323 /* last line was a header, get another */
324 ptr
= fgets(buf
, sizeof(buf
), fp
);
325 if (ptr
&& strncasecmp(buf
, hdr
, sizeof(hdr
) - 1) == 0) {
330 stats
->dwForwarding
= strtoul(ptr
, &endPtr
, 10);
334 stats
->dwDefaultTTL
= strtoul(ptr
, &endPtr
, 10);
338 stats
->dwInReceives
= strtoul(ptr
, &endPtr
, 10);
342 stats
->dwInHdrErrors
= strtoul(ptr
, &endPtr
, 10);
346 stats
->dwInAddrErrors
= strtoul(ptr
, &endPtr
, 10);
350 stats
->dwForwDatagrams
= strtoul(ptr
, &endPtr
, 10);
354 stats
->dwInUnknownProtos
= strtoul(ptr
, &endPtr
, 10);
358 stats
->dwInDiscards
= strtoul(ptr
, &endPtr
, 10);
362 stats
->dwInDelivers
= strtoul(ptr
, &endPtr
, 10);
366 stats
->dwOutRequests
= strtoul(ptr
, &endPtr
, 10);
370 stats
->dwOutDiscards
= strtoul(ptr
, &endPtr
, 10);
374 stats
->dwOutNoRoutes
= strtoul(ptr
, &endPtr
, 10);
378 stats
->dwReasmTimeout
= strtoul(ptr
, &endPtr
, 10);
382 stats
->dwReasmReqds
= strtoul(ptr
, &endPtr
, 10);
386 stats
->dwReasmOks
= strtoul(ptr
, &endPtr
, 10);
390 stats
->dwReasmFails
= strtoul(ptr
, &endPtr
, 10);
394 stats
->dwFragOks
= strtoul(ptr
, &endPtr
, 10);
398 stats
->dwFragFails
= strtoul(ptr
, &endPtr
, 10);
402 stats
->dwFragCreates
= strtoul(ptr
, &endPtr
, 10);
405 /* hmm, no routingDiscards */
411 ERR ("unimplemented!\n");
416 DWORD
getTCPStats(MIB_TCPSTATS
*stats
)
421 return ERROR_INVALID_PARAMETER
;
423 memset(stats
, 0, sizeof(MIB_TCPSTATS
));
425 /* get from /proc/net/snmp, no error if can't */
426 fp
= fopen("/proc/net/snmp", "r");
428 static const char hdr
[] = "Tcp:";
429 char buf
[512] = { 0 }, *ptr
;
433 ptr
= fgets(buf
, sizeof(buf
), fp
);
434 } while (ptr
&& strncasecmp(buf
, hdr
, sizeof(hdr
) - 1));
436 /* last line was a header, get another */
437 ptr
= fgets(buf
, sizeof(buf
), fp
);
438 if (ptr
&& strncasecmp(buf
, hdr
, sizeof(hdr
) - 1) == 0) {
443 stats
->dwRtoAlgorithm
= strtoul(ptr
, &endPtr
, 10);
447 stats
->dwRtoMin
= strtoul(ptr
, &endPtr
, 10);
451 stats
->dwRtoMin
= strtoul(ptr
, &endPtr
, 10);
455 stats
->dwMaxConn
= strtoul(ptr
, &endPtr
, 10);
459 stats
->dwActiveOpens
= strtoul(ptr
, &endPtr
, 10);
463 stats
->dwPassiveOpens
= strtoul(ptr
, &endPtr
, 10);
467 stats
->dwAttemptFails
= strtoul(ptr
, &endPtr
, 10);
471 stats
->dwEstabResets
= strtoul(ptr
, &endPtr
, 10);
475 stats
->dwCurrEstab
= strtoul(ptr
, &endPtr
, 10);
479 stats
->dwInSegs
= strtoul(ptr
, &endPtr
, 10);
483 stats
->dwOutSegs
= strtoul(ptr
, &endPtr
, 10);
487 stats
->dwRetransSegs
= strtoul(ptr
, &endPtr
, 10);
491 stats
->dwInErrs
= strtoul(ptr
, &endPtr
, 10);
495 stats
->dwOutRsts
= strtoul(ptr
, &endPtr
, 10);
498 stats
->dwNumConns
= getNumTcpEntries();
504 ERR ("unimplemented!\n");
509 DWORD
getUDPStats(MIB_UDPSTATS
*stats
)
514 return ERROR_INVALID_PARAMETER
;
516 memset(stats
, 0, sizeof(MIB_UDPSTATS
));
518 /* get from /proc/net/snmp, no error if can't */
519 fp
= fopen("/proc/net/snmp", "r");
521 static const char hdr
[] = "Udp:";
522 char buf
[512] = { 0 }, *ptr
;
526 ptr
= fgets(buf
, sizeof(buf
), fp
);
527 } while (ptr
&& strncasecmp(buf
, hdr
, sizeof(hdr
) - 1));
529 /* last line was a header, get another */
530 ptr
= fgets(buf
, sizeof(buf
), fp
);
531 if (ptr
&& strncasecmp(buf
, hdr
, sizeof(hdr
) - 1) == 0) {
536 stats
->dwInDatagrams
= strtoul(ptr
, &endPtr
, 10);
540 stats
->dwNoPorts
= strtoul(ptr
, &endPtr
, 10);
544 stats
->dwInErrors
= strtoul(ptr
, &endPtr
, 10);
548 stats
->dwOutDatagrams
= strtoul(ptr
, &endPtr
, 10);
552 stats
->dwNumAddrs
= strtoul(ptr
, &endPtr
, 10);
560 ERR ("unimplemented!\n");
565 static DWORD
getNumWithOneHeader(const char *filename
)
570 fp
= fopen(filename
, "r");
572 char buf
[512] = { 0 }, *ptr
;
575 ptr
= fgets(buf
, sizeof(buf
), fp
);
578 ptr
= fgets(buf
, sizeof(buf
), fp
);
586 ERR ("Unable to open '%s' to count entries!\n", filename
);
591 DWORD
getNumRoutes(void)
593 #if defined(HAVE_SYS_SYSCTL_H) && defined(NET_RT_DUMP)
594 int mib
[6] = {CTL_NET
, PF_ROUTE
, 0, PF_INET
, NET_RT_DUMP
, 0};
596 char *buf
, *lim
, *next
;
597 struct rt_msghdr
*rtm
;
598 DWORD RouteCount
= 0;
600 if (sysctl (mib
, 6, NULL
, &needed
, NULL
, 0) < 0)
602 ERR ("sysctl 1 failed!\n");
606 buf
= HeapAlloc (GetProcessHeap (), 0, needed
);
609 if (sysctl (mib
, 6, buf
, &needed
, NULL
, 0) < 0)
611 ERR ("sysctl 2 failed!\n");
612 HeapFree (GetProcessHeap (), 0, buf
);
617 for (next
= buf
; next
< lim
; next
+= rtm
->rtm_msglen
)
619 rtm
= (struct rt_msghdr
*)next
;
621 if (rtm
->rtm_type
!= RTM_GET
)
623 WARN ("Got unexpected message type 0x%x!\n",
628 /* Ignore all entries except for gateway routes which aren't
630 if (!(rtm
->rtm_flags
& RTF_GATEWAY
) || (rtm
->rtm_flags
& RTF_MULTICAST
))
636 HeapFree (GetProcessHeap (), 0, buf
);
639 return getNumWithOneHeader("/proc/net/route");
643 DWORD
getRouteTable(PMIB_IPFORWARDTABLE
*ppIpForwardTable
, HANDLE heap
,
648 if (!ppIpForwardTable
)
649 ret
= ERROR_INVALID_PARAMETER
;
651 DWORD numRoutes
= getNumRoutes();
652 PMIB_IPFORWARDTABLE table
= HeapAlloc(heap
, flags
,
653 sizeof(MIB_IPFORWARDTABLE
) + (numRoutes
- 1) * sizeof(MIB_IPFORWARDROW
));
656 #if defined(HAVE_SYS_SYSCTL_H) && defined(NET_RT_DUMP)
657 int mib
[6] = {CTL_NET
, PF_ROUTE
, 0, PF_INET
, NET_RT_DUMP
, 0};
659 char *buf
, *lim
, *next
, *addrPtr
;
660 struct rt_msghdr
*rtm
;
662 if (sysctl (mib
, 6, NULL
, &needed
, NULL
, 0) < 0)
664 ERR ("sysctl 1 failed!\n");
665 HeapFree (GetProcessHeap (), 0, table
);
669 buf
= HeapAlloc (GetProcessHeap (), 0, needed
);
672 HeapFree (GetProcessHeap (), 0, table
);
673 return ERROR_OUTOFMEMORY
;
676 if (sysctl (mib
, 6, buf
, &needed
, NULL
, 0) < 0)
678 ERR ("sysctl 2 failed!\n");
679 HeapFree (GetProcessHeap (), 0, table
);
680 HeapFree (GetProcessHeap (), 0, buf
);
684 *ppIpForwardTable
= table
;
685 table
->dwNumEntries
= 0;
688 for (next
= buf
; next
< lim
; next
+= rtm
->rtm_msglen
)
692 rtm
= (struct rt_msghdr
*)next
;
694 if (rtm
->rtm_type
!= RTM_GET
)
696 WARN ("Got unexpected message type 0x%x!\n",
701 /* Ignore all entries except for gateway routes which aren't
703 if (!(rtm
->rtm_flags
& RTF_GATEWAY
) ||
704 (rtm
->rtm_flags
& RTF_MULTICAST
))
707 memset (&table
->table
[table
->dwNumEntries
], 0,
708 sizeof (MIB_IPFORWARDROW
));
709 table
->table
[table
->dwNumEntries
].dwForwardIfIndex
= rtm
->rtm_index
;
710 table
->table
[table
->dwNumEntries
].dwForwardType
=
711 MIB_IPROUTE_TYPE_INDIRECT
;
712 table
->table
[table
->dwNumEntries
].dwForwardMetric1
=
713 rtm
->rtm_rmx
.rmx_hopcount
;
714 table
->table
[table
->dwNumEntries
].dwForwardProto
=
717 addrPtr
= (char *)(rtm
+ 1);
719 for (i
= 1; i
; i
<<= 1)
724 if (!(i
& rtm
->rtm_addrs
))
727 sa
= (struct sockaddr
*)addrPtr
;
728 ADVANCE (addrPtr
, sa
);
730 /* default routes are encoded by length-zero sockaddr */
733 else if (sa
->sa_family
!= AF_INET
)
735 ERR ("Received unsupported sockaddr family 0x%x\n",
741 struct sockaddr_in
*sin
= (struct sockaddr_in
*)sa
;
743 addr
= sin
->sin_addr
.s_addr
;
749 table
->table
[table
->dwNumEntries
].dwForwardDest
= addr
;
753 table
->table
[table
->dwNumEntries
].dwForwardNextHop
= addr
;
757 table
->table
[table
->dwNumEntries
].dwForwardMask
= addr
;
761 ERR ("Unexpected address type 0x%x\n", i
);
765 table
->dwNumEntries
++;
768 HeapFree (GetProcessHeap (), 0, buf
);
774 *ppIpForwardTable
= table
;
775 table
->dwNumEntries
= 0;
776 /* get from /proc/net/route, no error if can't */
777 fp
= fopen("/proc/net/route", "r");
779 char buf
[512] = { 0 }, *ptr
;
781 /* skip header line */
782 ptr
= fgets(buf
, sizeof(buf
), fp
);
783 while (ptr
&& table
->dwNumEntries
< numRoutes
) {
784 memset(&table
->table
[table
->dwNumEntries
], 0,
785 sizeof(MIB_IPFORWARDROW
));
786 ptr
= fgets(buf
, sizeof(buf
), fp
);
790 while (!isspace(*ptr
))
794 if (getInterfaceIndexByName(buf
, &index
) == NO_ERROR
) {
797 table
->table
[table
->dwNumEntries
].dwForwardIfIndex
= index
;
799 table
->table
[table
->dwNumEntries
].dwForwardDest
=
800 strtoul(ptr
, &endPtr
, 16);
804 table
->table
[table
->dwNumEntries
].dwForwardNextHop
=
805 strtoul(ptr
, &endPtr
, 16);
809 DWORD flags
= strtoul(ptr
, &endPtr
, 16);
811 if (!(flags
& RTF_UP
))
812 table
->table
[table
->dwNumEntries
].dwForwardType
=
813 MIB_IPROUTE_TYPE_INVALID
;
814 else if (flags
& RTF_GATEWAY
)
815 table
->table
[table
->dwNumEntries
].dwForwardType
=
816 MIB_IPROUTE_TYPE_INDIRECT
;
818 table
->table
[table
->dwNumEntries
].dwForwardType
=
819 MIB_IPROUTE_TYPE_DIRECT
;
823 strtoul(ptr
, &endPtr
, 16); /* refcount, skip */
827 strtoul(ptr
, &endPtr
, 16); /* use, skip */
831 table
->table
[table
->dwNumEntries
].dwForwardMetric1
=
832 strtoul(ptr
, &endPtr
, 16);
836 table
->table
[table
->dwNumEntries
].dwForwardMask
=
837 strtoul(ptr
, &endPtr
, 16);
840 /* FIXME: other protos might be appropriate, e.g. the default
841 * route is typically set with MIB_IPPROTO_NETMGMT instead */
842 table
->table
[table
->dwNumEntries
].dwForwardProto
=
844 table
->dwNumEntries
++;
852 ERR ("unimplemented!\n");
853 return ERROR_INVALID_PARAMETER
;
858 ret
= ERROR_OUTOFMEMORY
;
863 DWORD
getNumArpEntries(void)
865 return getNumWithOneHeader("/proc/net/arp");
868 DWORD
getArpTable(PMIB_IPNETTABLE
*ppIpNetTable
, HANDLE heap
, DWORD flags
)
872 #if defined(HAVE_SYS_SYSCTL_H) && defined(NET_RT_DUMP)
873 ERR ("unimplemented!\n");
874 return ERROR_INVALID_PARAMETER
;
878 ret
= ERROR_INVALID_PARAMETER
;
880 DWORD numEntries
= getNumArpEntries();
881 PMIB_IPNETTABLE table
= HeapAlloc(heap
, flags
,
882 sizeof(MIB_IPNETTABLE
) + (numEntries
- 1) * sizeof(MIB_IPNETROW
));
888 *ppIpNetTable
= table
;
889 table
->dwNumEntries
= 0;
890 /* get from /proc/net/arp, no error if can't */
891 fp
= fopen("/proc/net/arp", "r");
893 char buf
[512] = { 0 }, *ptr
;
895 /* skip header line */
896 ptr
= fgets(buf
, sizeof(buf
), fp
);
897 while (ptr
&& table
->dwNumEntries
< numEntries
) {
898 ptr
= fgets(buf
, sizeof(buf
), fp
);
902 memset(&table
->table
[table
->dwNumEntries
], 0, sizeof(MIB_IPNETROW
));
903 table
->table
[table
->dwNumEntries
].dwAddr
= inet_addr(ptr
);
904 while (ptr
&& *ptr
&& !isspace(*ptr
))
908 strtoul(ptr
, &endPtr
, 16); /* hw type (skip) */
912 DWORD flags
= strtoul(ptr
, &endPtr
, 16);
916 table
->table
[table
->dwNumEntries
].dwType
=
917 MIB_IPNET_TYPE_DYNAMIC
;
921 if (flags
& ATF_PERM
)
922 table
->table
[table
->dwNumEntries
].dwType
=
923 MIB_IPNET_TYPE_STATIC
;
926 table
->table
[table
->dwNumEntries
].dwType
= MIB_IPNET_TYPE_OTHER
;
930 while (ptr
&& *ptr
&& isspace(*ptr
))
932 while (ptr
&& *ptr
&& !isspace(*ptr
)) {
933 DWORD byte
= strtoul(ptr
, &endPtr
, 16);
935 if (endPtr
&& *endPtr
) {
937 table
->table
[table
->dwNumEntries
].bPhysAddr
[
938 table
->table
[table
->dwNumEntries
].dwPhysAddrLen
++] =
944 strtoul(ptr
, &endPtr
, 16); /* mask (skip) */
947 getInterfaceIndexByName(ptr
,
948 &table
->table
[table
->dwNumEntries
].dwIndex
);
949 table
->dwNumEntries
++;
956 ret
= ERROR_OUTOFMEMORY
;
961 DWORD
getNumUdpEntries(void)
963 return getNumWithOneHeader("/proc/net/udp");
966 DWORD
getUdpTable(PMIB_UDPTABLE
*ppUdpTable
, HANDLE heap
, DWORD flags
)
970 #if defined(HAVE_SYS_SYSCTL_H) && defined(NET_RT_DUMP)
971 ERR ("unimplemented!\n");
972 return ERROR_INVALID_PARAMETER
;
976 ret
= ERROR_INVALID_PARAMETER
;
978 DWORD numEntries
= getNumUdpEntries();
979 PMIB_UDPTABLE table
= HeapAlloc(heap
, flags
,
980 sizeof(MIB_UDPTABLE
) + (numEntries
- 1) * sizeof(MIB_UDPROW
));
987 table
->dwNumEntries
= 0;
988 /* get from /proc/net/udp, no error if can't */
989 fp
= fopen("/proc/net/udp", "r");
991 char buf
[512] = { 0 }, *ptr
;
993 /* skip header line */
994 ptr
= fgets(buf
, sizeof(buf
), fp
);
995 while (ptr
&& table
->dwNumEntries
< numEntries
) {
996 memset(&table
->table
[table
->dwNumEntries
], 0, sizeof(MIB_UDPROW
));
997 ptr
= fgets(buf
, sizeof(buf
), fp
);
1002 strtoul(ptr
, &endPtr
, 16); /* skip */
1007 table
->table
[table
->dwNumEntries
].dwLocalAddr
= strtoul(ptr
,
1013 table
->table
[table
->dwNumEntries
].dwLocalPort
= strtoul(ptr
,
1017 table
->dwNumEntries
++;
1024 ret
= ERROR_OUTOFMEMORY
;
1029 DWORD
getNumTcpEntries(void)
1031 return getNumWithOneHeader("/proc/net/tcp");
1034 DWORD
getTcpTable(PMIB_TCPTABLE
*ppTcpTable
, HANDLE heap
, DWORD flags
)
1038 #if defined(HAVE_SYS_SYSCTL_H) && defined(NET_RT_DUMP)
1039 ERR ("unimplemented!\n");
1040 return ERROR_INVALID_PARAMETER
;
1044 ret
= ERROR_INVALID_PARAMETER
;
1046 DWORD numEntries
= getNumTcpEntries();
1047 PMIB_TCPTABLE table
= HeapAlloc(heap
, flags
,
1048 sizeof(MIB_TCPTABLE
) + (numEntries
- 1) * sizeof(MIB_TCPROW
));
1054 *ppTcpTable
= table
;
1055 table
->dwNumEntries
= 0;
1056 /* get from /proc/net/tcp, no error if can't */
1057 fp
= fopen("/proc/net/tcp", "r");
1059 char buf
[512] = { 0 }, *ptr
;
1061 /* skip header line */
1062 ptr
= fgets(buf
, sizeof(buf
), fp
);
1063 while (ptr
&& table
->dwNumEntries
< numEntries
) {
1064 memset(&table
->table
[table
->dwNumEntries
], 0, sizeof(MIB_TCPROW
));
1065 ptr
= fgets(buf
, sizeof(buf
), fp
);
1069 while (ptr
&& *ptr
&& *ptr
!= ':')
1074 table
->table
[table
->dwNumEntries
].dwLocalAddr
= strtoul(ptr
,
1080 table
->table
[table
->dwNumEntries
].dwLocalPort
= strtoul(ptr
,
1085 table
->table
[table
->dwNumEntries
].dwRemoteAddr
= strtoul(ptr
,
1091 table
->table
[table
->dwNumEntries
].dwRemotePort
= strtoul(ptr
,
1096 DWORD state
= strtoul(ptr
, &endPtr
, 16);
1100 case TCPS_ESTABLISHED
:
1101 table
->table
[table
->dwNumEntries
].dwState
=
1102 MIB_TCP_STATE_ESTAB
;
1105 table
->table
[table
->dwNumEntries
].dwState
=
1106 MIB_TCP_STATE_SYN_SENT
;
1108 case TCPS_SYN_RECEIVED
:
1109 table
->table
[table
->dwNumEntries
].dwState
=
1110 MIB_TCP_STATE_SYN_RCVD
;
1112 case TCPS_FIN_WAIT_1
:
1113 table
->table
[table
->dwNumEntries
].dwState
=
1114 MIB_TCP_STATE_FIN_WAIT1
;
1116 case TCPS_FIN_WAIT_2
:
1117 table
->table
[table
->dwNumEntries
].dwState
=
1118 MIB_TCP_STATE_FIN_WAIT2
;
1120 case TCPS_TIME_WAIT
:
1121 table
->table
[table
->dwNumEntries
].dwState
=
1122 MIB_TCP_STATE_TIME_WAIT
;
1125 table
->table
[table
->dwNumEntries
].dwState
=
1126 MIB_TCP_STATE_CLOSED
;
1128 case TCPS_CLOSE_WAIT
:
1129 table
->table
[table
->dwNumEntries
].dwState
=
1130 MIB_TCP_STATE_CLOSE_WAIT
;
1133 table
->table
[table
->dwNumEntries
].dwState
=
1134 MIB_TCP_STATE_LAST_ACK
;
1137 table
->table
[table
->dwNumEntries
].dwState
=
1138 MIB_TCP_STATE_LISTEN
;
1141 table
->table
[table
->dwNumEntries
].dwState
=
1142 MIB_TCP_STATE_CLOSING
;
1147 table
->dwNumEntries
++;
1154 ret
= ERROR_OUTOFMEMORY
;