Update the address of the Free Software Foundation.
[wine.git] / dlls / iphlpapi / ipstats.c
blob129380c30383b4eeb7a9befee19cea86259710ee
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.
21 #include "config.h"
22 #include "wine/port.h"
24 #include <stdarg.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <sys/types.h>
29 #ifdef HAVE_SYS_SOCKET_H
30 #include <sys/socket.h>
31 #endif
32 #ifdef HAVE_NETINET_IN_H
33 #include <netinet/in.h>
34 #endif
35 #ifdef HAVE_ARPA_INET_H
36 #include <arpa/inet.h>
37 #endif
38 #ifdef HAVE_NET_IF_H
39 #include <net/if.h>
40 #endif
41 #ifdef HAVE_NET_ROUTE_H
42 #include <net/route.h>
43 #endif
44 #ifdef HAVE_NET_IF_ARP_H
45 #include <net/if_arp.h>
46 #endif
47 #ifdef HAVE_NETINET_TCP_H
48 #include <netinet/tcp.h>
49 #endif
50 #ifdef HAVE_NETINET_TCP_FSM_H
51 #include <netinet/tcp_fsm.h>
52 #endif
54 #include "windef.h"
55 #include "winbase.h"
56 #include "iprtrmib.h"
57 #include "ifenum.h"
58 #include "ipstats.h"
60 #ifdef linux
61 #define TCPS_ESTABLISHED 1
62 #define TCPS_SYN_SENT 2
63 #define TCPS_SYN_RECEIVED 3
64 #define TCPS_FIN_WAIT_1 4
65 #define TCPS_FIN_WAIT_2 5
66 #define TCPS_TIME_WAIT 6
67 #define TCPS_CLOSED 7
68 #define TCPS_CLOSE_WAIT 8
69 #define TCPS_LAST_ACK 9
70 #define TCPS_LISTEN 10
71 #define TCPS_CLOSING 11
72 #endif
74 DWORD getInterfaceStatsByName(const char *name, PMIB_IFROW entry)
76 FILE *fp;
78 if (!name)
79 return ERROR_INVALID_PARAMETER;
80 if (!entry)
81 return ERROR_INVALID_PARAMETER;
83 /* get interface stats from /proc/net/dev, no error if can't
84 no inUnknownProtos, outNUcastPkts, outQLen */
85 fp = fopen("/proc/net/dev", "r");
86 if (fp) {
87 char buf[512] = { 0 }, *ptr;
88 int nameLen = strlen(name), nameFound = 0;
91 ptr = fgets(buf, sizeof(buf), fp);
92 while (ptr && !nameFound) {
93 while (*ptr && isspace(*ptr))
94 ptr++;
95 if (strncasecmp(ptr, name, nameLen) == 0 && *(ptr + nameLen) == ':')
96 nameFound = 1;
97 else
98 ptr = fgets(buf, sizeof(buf), fp);
100 if (nameFound) {
101 char *endPtr;
103 ptr += nameLen + 1;
104 if (ptr && *ptr) {
105 entry->dwInOctets = strtoul(ptr, &endPtr, 10);
106 ptr = endPtr;
108 if (ptr && *ptr) {
109 entry->dwInUcastPkts = strtoul(ptr, &endPtr, 10);
110 ptr = endPtr;
112 if (ptr && *ptr) {
113 entry->dwInErrors = strtoul(ptr, &endPtr, 10);
114 ptr = endPtr;
116 if (ptr && *ptr) {
117 entry->dwInDiscards = strtoul(ptr, &endPtr, 10);
118 ptr = endPtr;
120 if (ptr && *ptr) {
121 strtoul(ptr, &endPtr, 10); /* skip */
122 ptr = endPtr;
124 if (ptr && *ptr) {
125 strtoul(ptr, &endPtr, 10); /* skip */
126 ptr = endPtr;
128 if (ptr && *ptr) {
129 strtoul(ptr, &endPtr, 10); /* skip */
130 ptr = endPtr;
132 if (ptr && *ptr) {
133 entry->dwInNUcastPkts = strtoul(ptr, &endPtr, 10);
134 ptr = endPtr;
136 if (ptr && *ptr) {
137 entry->dwOutOctets = strtoul(ptr, &endPtr, 10);
138 ptr = endPtr;
140 if (ptr && *ptr) {
141 entry->dwOutUcastPkts = strtoul(ptr, &endPtr, 10);
142 ptr = endPtr;
144 if (ptr && *ptr) {
145 entry->dwOutErrors = strtoul(ptr, &endPtr, 10);
146 ptr = endPtr;
148 if (ptr && *ptr) {
149 entry->dwOutDiscards = strtoul(ptr, &endPtr, 10);
150 ptr = endPtr;
153 fclose(fp);
155 return NO_ERROR;
158 DWORD getICMPStats(MIB_ICMP *stats)
160 FILE *fp;
162 if (!stats)
163 return ERROR_INVALID_PARAMETER;
165 memset(stats, 0, sizeof(MIB_ICMP));
166 /* get most of these stats from /proc/net/snmp, no error if can't */
167 fp = fopen("/proc/net/snmp", "r");
168 if (fp) {
169 static const char hdr[] = "Icmp:";
170 char buf[512] = { 0 }, *ptr;
172 do {
173 ptr = fgets(buf, sizeof(buf), fp);
174 } while (ptr && strncasecmp(buf, hdr, sizeof(hdr) - 1));
175 if (ptr) {
176 /* last line was a header, get another */
177 ptr = fgets(buf, sizeof(buf), fp);
178 if (ptr && strncasecmp(buf, hdr, sizeof(hdr) - 1) == 0) {
179 char *endPtr;
181 ptr += sizeof(hdr);
182 if (ptr && *ptr) {
183 stats->stats.icmpInStats.dwMsgs = strtoul(ptr, &endPtr, 10);
184 ptr = endPtr;
186 if (ptr && *ptr) {
187 stats->stats.icmpInStats.dwErrors = strtoul(ptr, &endPtr, 10);
188 ptr = endPtr;
190 if (ptr && *ptr) {
191 stats->stats.icmpInStats.dwDestUnreachs = strtoul(ptr, &endPtr, 10);
192 ptr = endPtr;
194 if (ptr && *ptr) {
195 stats->stats.icmpInStats.dwTimeExcds = strtoul(ptr, &endPtr, 10);
196 ptr = endPtr;
198 if (ptr && *ptr) {
199 stats->stats.icmpInStats.dwParmProbs = strtoul(ptr, &endPtr, 10);
200 ptr = endPtr;
202 if (ptr && *ptr) {
203 stats->stats.icmpInStats.dwSrcQuenchs = strtoul(ptr, &endPtr, 10);
204 ptr = endPtr;
206 if (ptr && *ptr) {
207 stats->stats.icmpInStats.dwRedirects = strtoul(ptr, &endPtr, 10);
208 ptr = endPtr;
210 if (ptr && *ptr) {
211 stats->stats.icmpInStats.dwEchoReps = strtoul(ptr, &endPtr, 10);
212 ptr = endPtr;
214 if (ptr && *ptr) {
215 stats->stats.icmpInStats.dwTimestamps = strtoul(ptr, &endPtr, 10);
216 ptr = endPtr;
218 if (ptr && *ptr) {
219 stats->stats.icmpInStats.dwTimestampReps = strtoul(ptr, &endPtr, 10);
220 ptr = endPtr;
222 if (ptr && *ptr) {
223 stats->stats.icmpInStats.dwAddrMasks = strtoul(ptr, &endPtr, 10);
224 ptr = endPtr;
226 if (ptr && *ptr) {
227 stats->stats.icmpInStats.dwAddrMaskReps = strtoul(ptr, &endPtr, 10);
228 ptr = endPtr;
230 if (ptr && *ptr) {
231 stats->stats.icmpOutStats.dwMsgs = strtoul(ptr, &endPtr, 10);
232 ptr = endPtr;
234 if (ptr && *ptr) {
235 stats->stats.icmpOutStats.dwErrors = strtoul(ptr, &endPtr, 10);
236 ptr = endPtr;
238 if (ptr && *ptr) {
239 stats->stats.icmpOutStats.dwDestUnreachs = strtoul(ptr, &endPtr, 10);
240 ptr = endPtr;
242 if (ptr && *ptr) {
243 stats->stats.icmpOutStats.dwTimeExcds = strtoul(ptr, &endPtr, 10);
244 ptr = endPtr;
246 if (ptr && *ptr) {
247 stats->stats.icmpOutStats.dwParmProbs = strtoul(ptr, &endPtr, 10);
248 ptr = endPtr;
250 if (ptr && *ptr) {
251 stats->stats.icmpOutStats.dwSrcQuenchs = strtoul(ptr, &endPtr, 10);
252 ptr = endPtr;
254 if (ptr && *ptr) {
255 stats->stats.icmpOutStats.dwRedirects = strtoul(ptr, &endPtr, 10);
256 ptr = endPtr;
258 if (ptr && *ptr) {
259 stats->stats.icmpOutStats.dwEchoReps = strtoul(ptr, &endPtr, 10);
260 ptr = endPtr;
262 if (ptr && *ptr) {
263 stats->stats.icmpOutStats.dwTimestamps = strtoul(ptr, &endPtr, 10);
264 ptr = endPtr;
266 if (ptr && *ptr) {
267 stats->stats.icmpOutStats.dwTimestampReps = strtoul(ptr, &endPtr, 10);
268 ptr = endPtr;
270 if (ptr && *ptr) {
271 stats->stats.icmpOutStats.dwAddrMasks = strtoul(ptr, &endPtr, 10);
272 ptr = endPtr;
274 if (ptr && *ptr) {
275 stats->stats.icmpOutStats.dwAddrMaskReps = strtoul(ptr, &endPtr, 10);
276 ptr = endPtr;
280 fclose(fp);
282 return NO_ERROR;
285 DWORD getIPStats(PMIB_IPSTATS stats)
287 FILE *fp;
289 if (!stats)
290 return ERROR_INVALID_PARAMETER;
292 memset(stats, 0, sizeof(MIB_IPSTATS));
293 stats->dwNumIf = stats->dwNumAddr = getNumInterfaces();
294 stats->dwNumRoutes = getNumRoutes();
296 /* get most of these stats from /proc/net/snmp, no error if can't */
297 fp = fopen("/proc/net/snmp", "r");
298 if (fp) {
299 static const char hdr[] = "Ip:";
300 char buf[512] = { 0 }, *ptr;
302 do {
303 ptr = fgets(buf, sizeof(buf), fp);
304 } while (ptr && strncasecmp(buf, hdr, sizeof(hdr) - 1));
305 if (ptr) {
306 /* last line was a header, get another */
307 ptr = fgets(buf, sizeof(buf), fp);
308 if (ptr && strncasecmp(buf, hdr, sizeof(hdr) - 1) == 0) {
309 char *endPtr;
311 ptr += sizeof(hdr);
312 if (ptr && *ptr) {
313 stats->dwForwarding = strtoul(ptr, &endPtr, 10);
314 ptr = endPtr;
316 if (ptr && *ptr) {
317 stats->dwDefaultTTL = strtoul(ptr, &endPtr, 10);
318 ptr = endPtr;
320 if (ptr && *ptr) {
321 stats->dwInReceives = strtoul(ptr, &endPtr, 10);
322 ptr = endPtr;
324 if (ptr && *ptr) {
325 stats->dwInHdrErrors = strtoul(ptr, &endPtr, 10);
326 ptr = endPtr;
328 if (ptr && *ptr) {
329 stats->dwInAddrErrors = strtoul(ptr, &endPtr, 10);
330 ptr = endPtr;
332 if (ptr && *ptr) {
333 stats->dwForwDatagrams = strtoul(ptr, &endPtr, 10);
334 ptr = endPtr;
336 if (ptr && *ptr) {
337 stats->dwInUnknownProtos = strtoul(ptr, &endPtr, 10);
338 ptr = endPtr;
340 if (ptr && *ptr) {
341 stats->dwInDiscards = strtoul(ptr, &endPtr, 10);
342 ptr = endPtr;
344 if (ptr && *ptr) {
345 stats->dwInDelivers = strtoul(ptr, &endPtr, 10);
346 ptr = endPtr;
348 if (ptr && *ptr) {
349 stats->dwOutRequests = strtoul(ptr, &endPtr, 10);
350 ptr = endPtr;
352 if (ptr && *ptr) {
353 stats->dwOutDiscards = strtoul(ptr, &endPtr, 10);
354 ptr = endPtr;
356 if (ptr && *ptr) {
357 stats->dwOutNoRoutes = strtoul(ptr, &endPtr, 10);
358 ptr = endPtr;
360 if (ptr && *ptr) {
361 stats->dwReasmTimeout = strtoul(ptr, &endPtr, 10);
362 ptr = endPtr;
364 if (ptr && *ptr) {
365 stats->dwReasmReqds = strtoul(ptr, &endPtr, 10);
366 ptr = endPtr;
368 if (ptr && *ptr) {
369 stats->dwReasmOks = strtoul(ptr, &endPtr, 10);
370 ptr = endPtr;
372 if (ptr && *ptr) {
373 stats->dwReasmFails = strtoul(ptr, &endPtr, 10);
374 ptr = endPtr;
376 if (ptr && *ptr) {
377 stats->dwFragOks = strtoul(ptr, &endPtr, 10);
378 ptr = endPtr;
380 if (ptr && *ptr) {
381 stats->dwFragFails = strtoul(ptr, &endPtr, 10);
382 ptr = endPtr;
384 if (ptr && *ptr) {
385 stats->dwFragCreates = strtoul(ptr, &endPtr, 10);
386 ptr = endPtr;
388 /* hmm, no routingDiscards */
391 fclose(fp);
393 return NO_ERROR;
396 DWORD getTCPStats(MIB_TCPSTATS *stats)
398 FILE *fp;
400 if (!stats)
401 return ERROR_INVALID_PARAMETER;
403 memset(stats, 0, sizeof(MIB_TCPSTATS));
405 /* get from /proc/net/snmp, no error if can't */
406 fp = fopen("/proc/net/snmp", "r");
407 if (fp) {
408 static const char hdr[] = "Tcp:";
409 char buf[512] = { 0 }, *ptr;
412 do {
413 ptr = fgets(buf, sizeof(buf), fp);
414 } while (ptr && strncasecmp(buf, hdr, sizeof(hdr) - 1));
415 if (ptr) {
416 /* last line was a header, get another */
417 ptr = fgets(buf, sizeof(buf), fp);
418 if (ptr && strncasecmp(buf, hdr, sizeof(hdr) - 1) == 0) {
419 char *endPtr;
421 ptr += sizeof(hdr);
422 if (ptr && *ptr) {
423 stats->dwRtoAlgorithm = strtoul(ptr, &endPtr, 10);
424 ptr = endPtr;
426 if (ptr && *ptr) {
427 stats->dwRtoMin = strtoul(ptr, &endPtr, 10);
428 ptr = endPtr;
430 if (ptr && *ptr) {
431 stats->dwRtoMin = strtoul(ptr, &endPtr, 10);
432 ptr = endPtr;
434 if (ptr && *ptr) {
435 stats->dwMaxConn = strtoul(ptr, &endPtr, 10);
436 ptr = endPtr;
438 if (ptr && *ptr) {
439 stats->dwActiveOpens = strtoul(ptr, &endPtr, 10);
440 ptr = endPtr;
442 if (ptr && *ptr) {
443 stats->dwPassiveOpens = strtoul(ptr, &endPtr, 10);
444 ptr = endPtr;
446 if (ptr && *ptr) {
447 stats->dwAttemptFails = strtoul(ptr, &endPtr, 10);
448 ptr = endPtr;
450 if (ptr && *ptr) {
451 stats->dwEstabResets = strtoul(ptr, &endPtr, 10);
452 ptr = endPtr;
454 if (ptr && *ptr) {
455 stats->dwCurrEstab = strtoul(ptr, &endPtr, 10);
456 ptr = endPtr;
458 if (ptr && *ptr) {
459 stats->dwInSegs = strtoul(ptr, &endPtr, 10);
460 ptr = endPtr;
462 if (ptr && *ptr) {
463 stats->dwOutSegs = strtoul(ptr, &endPtr, 10);
464 ptr = endPtr;
466 if (ptr && *ptr) {
467 stats->dwRetransSegs = strtoul(ptr, &endPtr, 10);
468 ptr = endPtr;
470 if (ptr && *ptr) {
471 stats->dwInErrs = strtoul(ptr, &endPtr, 10);
472 ptr = endPtr;
474 if (ptr && *ptr) {
475 stats->dwOutRsts = strtoul(ptr, &endPtr, 10);
476 ptr = endPtr;
478 stats->dwNumConns = getNumTcpEntries();
481 fclose(fp);
483 return NO_ERROR;
486 DWORD getUDPStats(MIB_UDPSTATS *stats)
488 FILE *fp;
490 if (!stats)
491 return ERROR_INVALID_PARAMETER;
493 memset(stats, 0, sizeof(MIB_UDPSTATS));
495 /* get from /proc/net/snmp, no error if can't */
496 fp = fopen("/proc/net/snmp", "r");
497 if (fp) {
498 static const char hdr[] = "Udp:";
499 char buf[512] = { 0 }, *ptr;
502 do {
503 ptr = fgets(buf, sizeof(buf), fp);
504 } while (ptr && strncasecmp(buf, hdr, sizeof(hdr) - 1));
505 if (ptr) {
506 /* last line was a header, get another */
507 ptr = fgets(buf, sizeof(buf), fp);
508 if (ptr && strncasecmp(buf, hdr, sizeof(hdr) - 1) == 0) {
509 char *endPtr;
511 ptr += sizeof(hdr);
512 if (ptr && *ptr) {
513 stats->dwInDatagrams = strtoul(ptr, &endPtr, 10);
514 ptr = endPtr;
516 if (ptr && *ptr) {
517 stats->dwNoPorts = strtoul(ptr, &endPtr, 10);
518 ptr = endPtr;
520 if (ptr && *ptr) {
521 stats->dwInErrors = strtoul(ptr, &endPtr, 10);
522 ptr = endPtr;
524 if (ptr && *ptr) {
525 stats->dwOutDatagrams = strtoul(ptr, &endPtr, 10);
526 ptr = endPtr;
528 if (ptr && *ptr) {
529 stats->dwNumAddrs = strtoul(ptr, &endPtr, 10);
530 ptr = endPtr;
534 fclose(fp);
536 return NO_ERROR;
539 static DWORD getNumWithOneHeader(const char *filename)
541 FILE *fp;
542 int ret = 0;
544 fp = fopen(filename, "r");
545 if (fp) {
546 char buf[512] = { 0 }, *ptr;
549 ptr = fgets(buf, sizeof(buf), fp);
550 if (ptr) {
551 do {
552 ptr = fgets(buf, sizeof(buf), fp);
553 if (ptr)
554 ret++;
555 } while (ptr);
557 fclose(fp);
559 return ret;
562 DWORD getNumRoutes(void)
564 return getNumWithOneHeader("/proc/net/route");
567 DWORD getRouteTable(PMIB_IPFORWARDTABLE *ppIpForwardTable, HANDLE heap,
568 DWORD flags)
570 DWORD ret;
572 if (!ppIpForwardTable)
573 ret = ERROR_INVALID_PARAMETER;
574 else {
575 DWORD numRoutes = getNumRoutes();
576 PMIB_IPFORWARDTABLE table = HeapAlloc(heap, flags,
577 sizeof(MIB_IPFORWARDTABLE) + (numRoutes - 1) * sizeof(MIB_IPFORWARDROW));
579 if (table) {
580 FILE *fp;
582 ret = NO_ERROR;
583 *ppIpForwardTable = table;
584 table->dwNumEntries = 0;
585 /* get from /proc/net/route, no error if can't */
586 fp = fopen("/proc/net/route", "r");
587 if (fp) {
588 char buf[512] = { 0 }, *ptr;
590 /* skip header line */
591 ptr = fgets(buf, sizeof(buf), fp);
592 while (ptr && table->dwNumEntries < numRoutes) {
593 memset(&table->table[table->dwNumEntries], 0,
594 sizeof(MIB_IPFORWARDROW));
595 ptr = fgets(buf, sizeof(buf), fp);
596 if (ptr) {
597 DWORD index;
599 while (!isspace(*ptr))
600 ptr++;
601 *ptr = '\0';
602 ptr++;
603 if (getInterfaceIndexByName(buf, &index) == NO_ERROR) {
604 char *endPtr;
606 table->table[table->dwNumEntries].dwForwardIfIndex = index;
607 if (*ptr) {
608 table->table[table->dwNumEntries].dwForwardDest =
609 strtoul(ptr, &endPtr, 16);
610 ptr = endPtr;
612 if (ptr && *ptr) {
613 table->table[table->dwNumEntries].dwForwardNextHop =
614 strtoul(ptr, &endPtr, 16);
615 ptr = endPtr;
617 if (ptr && *ptr) {
618 DWORD flags = strtoul(ptr, &endPtr, 16);
620 if (!(flags & RTF_UP))
621 table->table[table->dwNumEntries].dwForwardType =
622 MIB_IPROUTE_TYPE_INVALID;
623 else if (flags & RTF_GATEWAY)
624 table->table[table->dwNumEntries].dwForwardType =
625 MIB_IPROUTE_TYPE_INDIRECT;
626 else
627 table->table[table->dwNumEntries].dwForwardType =
628 MIB_IPROUTE_TYPE_DIRECT;
629 ptr = endPtr;
631 if (ptr && *ptr) {
632 strtoul(ptr, &endPtr, 16); /* refcount, skip */
633 ptr = endPtr;
635 if (ptr && *ptr) {
636 strtoul(ptr, &endPtr, 16); /* use, skip */
637 ptr = endPtr;
639 if (ptr && *ptr) {
640 table->table[table->dwNumEntries].dwForwardMetric1 =
641 strtoul(ptr, &endPtr, 16);
642 ptr = endPtr;
644 if (ptr && *ptr) {
645 table->table[table->dwNumEntries].dwForwardMask =
646 strtoul(ptr, &endPtr, 16);
647 ptr = endPtr;
649 /* FIXME: other protos might be appropriate, e.g. the default
650 * route is typically set with MIB_IPPROTO_NETMGMT instead */
651 table->table[table->dwNumEntries].dwForwardProto =
652 MIB_IPPROTO_LOCAL;
653 table->dwNumEntries++;
657 fclose(fp);
660 else
661 ret = ERROR_OUTOFMEMORY;
663 return ret;
666 DWORD getNumArpEntries(void)
668 return getNumWithOneHeader("/proc/net/arp");
671 DWORD getArpTable(PMIB_IPNETTABLE *ppIpNetTable, HANDLE heap, DWORD flags)
673 DWORD ret;
675 if (!ppIpNetTable)
676 ret = ERROR_INVALID_PARAMETER;
677 else {
678 DWORD numEntries = getNumArpEntries();
679 PMIB_IPNETTABLE table = HeapAlloc(heap, flags,
680 sizeof(MIB_IPNETTABLE) + (numEntries - 1) * sizeof(MIB_IPNETROW));
682 if (table) {
683 FILE *fp;
685 ret = NO_ERROR;
686 *ppIpNetTable = table;
687 table->dwNumEntries = 0;
688 /* get from /proc/net/arp, no error if can't */
689 fp = fopen("/proc/net/arp", "r");
690 if (fp) {
691 char buf[512] = { 0 }, *ptr;
693 /* skip header line */
694 ptr = fgets(buf, sizeof(buf), fp);
695 while (ptr && table->dwNumEntries < numEntries) {
696 ptr = fgets(buf, sizeof(buf), fp);
697 if (ptr) {
698 char *endPtr;
700 memset(&table->table[table->dwNumEntries], 0, sizeof(MIB_IPNETROW));
701 table->table[table->dwNumEntries].dwAddr = inet_addr(ptr);
702 while (ptr && *ptr && !isspace(*ptr))
703 ptr++;
705 if (ptr && *ptr) {
706 strtoul(ptr, &endPtr, 16); /* hw type (skip) */
707 ptr = endPtr;
709 if (ptr && *ptr) {
710 DWORD flags = strtoul(ptr, &endPtr, 16);
712 #ifdef ATF_COM
713 if (flags & ATF_COM)
714 table->table[table->dwNumEntries].dwType =
715 MIB_IPNET_TYPE_DYNAMIC;
716 else
717 #endif
718 #ifdef ATF_PERM
719 if (flags & ATF_PERM)
720 table->table[table->dwNumEntries].dwType =
721 MIB_IPNET_TYPE_STATIC;
722 else
723 #endif
724 table->table[table->dwNumEntries].dwType = MIB_IPNET_TYPE_OTHER;
726 ptr = endPtr;
728 while (ptr && *ptr && isspace(*ptr))
729 ptr++;
730 while (ptr && *ptr && !isspace(*ptr)) {
731 DWORD byte = strtoul(ptr, &endPtr, 16);
733 if (endPtr && *endPtr) {
734 endPtr++;
735 table->table[table->dwNumEntries].bPhysAddr[
736 table->table[table->dwNumEntries].dwPhysAddrLen++] =
737 byte & 0x0ff;
739 ptr = endPtr;
741 if (ptr && *ptr) {
742 strtoul(ptr, &endPtr, 16); /* mask (skip) */
743 ptr = endPtr;
745 getInterfaceIndexByName(ptr,
746 &table->table[table->dwNumEntries].dwIndex);
747 table->dwNumEntries++;
750 fclose(fp);
753 else
754 ret = ERROR_OUTOFMEMORY;
756 return ret;
759 DWORD getNumUdpEntries(void)
761 return getNumWithOneHeader("/proc/net/udp");
764 DWORD getUdpTable(PMIB_UDPTABLE *ppUdpTable, HANDLE heap, DWORD flags)
766 DWORD ret;
768 if (!ppUdpTable)
769 ret = ERROR_INVALID_PARAMETER;
770 else {
771 DWORD numEntries = getNumUdpEntries();
772 PMIB_UDPTABLE table = HeapAlloc(heap, flags,
773 sizeof(MIB_UDPTABLE) + (numEntries - 1) * sizeof(MIB_UDPROW));
775 if (table) {
776 FILE *fp;
778 ret = NO_ERROR;
779 *ppUdpTable = table;
780 table->dwNumEntries = 0;
781 /* get from /proc/net/udp, no error if can't */
782 fp = fopen("/proc/net/udp", "r");
783 if (fp) {
784 char buf[512] = { 0 }, *ptr;
786 /* skip header line */
787 ptr = fgets(buf, sizeof(buf), fp);
788 while (ptr && table->dwNumEntries < numEntries) {
789 memset(&table->table[table->dwNumEntries], 0, sizeof(MIB_UDPROW));
790 ptr = fgets(buf, sizeof(buf), fp);
791 if (ptr) {
792 char *endPtr;
794 if (ptr && *ptr) {
795 strtoul(ptr, &endPtr, 16); /* skip */
796 ptr = endPtr;
798 if (ptr && *ptr) {
799 ptr++;
800 table->table[table->dwNumEntries].dwLocalAddr = strtoul(ptr,
801 &endPtr, 16);
802 ptr = endPtr;
804 if (ptr && *ptr) {
805 ptr++;
806 table->table[table->dwNumEntries].dwLocalPort = strtoul(ptr,
807 &endPtr, 16);
808 ptr = endPtr;
810 table->dwNumEntries++;
813 fclose(fp);
816 else
817 ret = ERROR_OUTOFMEMORY;
819 return ret;
822 DWORD getNumTcpEntries(void)
824 return getNumWithOneHeader("/proc/net/tcp");
827 DWORD getTcpTable(PMIB_TCPTABLE *ppTcpTable, HANDLE heap, DWORD flags)
829 DWORD ret;
831 if (!ppTcpTable)
832 ret = ERROR_INVALID_PARAMETER;
833 else {
834 DWORD numEntries = getNumTcpEntries();
835 PMIB_TCPTABLE table = HeapAlloc(heap, flags,
836 sizeof(MIB_TCPTABLE) + (numEntries - 1) * sizeof(MIB_TCPROW));
838 if (table) {
839 FILE *fp;
841 ret = NO_ERROR;
842 *ppTcpTable = table;
843 table->dwNumEntries = 0;
844 /* get from /proc/net/tcp, no error if can't */
845 fp = fopen("/proc/net/tcp", "r");
846 if (fp) {
847 char buf[512] = { 0 }, *ptr;
849 /* skip header line */
850 ptr = fgets(buf, sizeof(buf), fp);
851 while (ptr && table->dwNumEntries < numEntries) {
852 memset(&table->table[table->dwNumEntries], 0, sizeof(MIB_TCPROW));
853 ptr = fgets(buf, sizeof(buf), fp);
854 if (ptr) {
855 char *endPtr;
857 while (ptr && *ptr && *ptr != ':')
858 ptr++;
859 if (ptr && *ptr)
860 ptr++;
861 if (ptr && *ptr) {
862 table->table[table->dwNumEntries].dwLocalAddr = strtoul(ptr,
863 &endPtr, 16);
864 ptr = endPtr;
866 if (ptr && *ptr) {
867 ptr++;
868 table->table[table->dwNumEntries].dwLocalPort = strtoul(ptr,
869 &endPtr, 16);
870 ptr = endPtr;
872 if (ptr && *ptr) {
873 table->table[table->dwNumEntries].dwRemoteAddr = strtoul(ptr,
874 &endPtr, 16);
875 ptr = endPtr;
877 if (ptr && *ptr) {
878 ptr++;
879 table->table[table->dwNumEntries].dwRemotePort = strtoul(ptr,
880 &endPtr, 16);
881 ptr = endPtr;
883 if (ptr && *ptr) {
884 DWORD state = strtoul(ptr, &endPtr, 16);
886 switch (state)
888 case TCPS_ESTABLISHED:
889 table->table[table->dwNumEntries].dwState =
890 MIB_TCP_STATE_ESTAB;
891 break;
892 case TCPS_SYN_SENT:
893 table->table[table->dwNumEntries].dwState =
894 MIB_TCP_STATE_SYN_SENT;
895 break;
896 case TCPS_SYN_RECEIVED:
897 table->table[table->dwNumEntries].dwState =
898 MIB_TCP_STATE_SYN_RCVD;
899 break;
900 case TCPS_FIN_WAIT_1:
901 table->table[table->dwNumEntries].dwState =
902 MIB_TCP_STATE_FIN_WAIT1;
903 break;
904 case TCPS_FIN_WAIT_2:
905 table->table[table->dwNumEntries].dwState =
906 MIB_TCP_STATE_FIN_WAIT2;
907 break;
908 case TCPS_TIME_WAIT:
909 table->table[table->dwNumEntries].dwState =
910 MIB_TCP_STATE_TIME_WAIT;
911 break;
912 case TCPS_CLOSED:
913 table->table[table->dwNumEntries].dwState =
914 MIB_TCP_STATE_CLOSED;
915 break;
916 case TCPS_CLOSE_WAIT:
917 table->table[table->dwNumEntries].dwState =
918 MIB_TCP_STATE_CLOSE_WAIT;
919 break;
920 case TCPS_LAST_ACK:
921 table->table[table->dwNumEntries].dwState =
922 MIB_TCP_STATE_LAST_ACK;
923 break;
924 case TCPS_LISTEN:
925 table->table[table->dwNumEntries].dwState =
926 MIB_TCP_STATE_LISTEN;
927 break;
928 case TCPS_CLOSING:
929 table->table[table->dwNumEntries].dwState =
930 MIB_TCP_STATE_CLOSING;
931 break;
933 ptr = endPtr;
935 table->dwNumEntries++;
938 fclose(fp);
941 else
942 ret = ERROR_OUTOFMEMORY;
944 return ret;