Rewrote the collapsing of . and .. in RtlGetFullPathName_U for better
[wine.git] / dlls / iphlpapi / ipstats.c
blobfc49a0bcdb6df2ad0763ce08d0136a2925c34895
1 /* Copyright (C) 2003 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 * This file implements statistics getting using the /proc filesystem exported
18 * by Linux, and maybe other OSes.
21 #include "config.h"
23 #include <stdarg.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <sys/types.h>
28 #ifdef HAVE_SYS_SOCKET_H
29 #include <sys/socket.h>
30 #endif
31 #ifdef HAVE_NETINET_IN_H
32 #include <netinet/in.h>
33 #endif
34 #ifdef HAVE_ARPA_INET_H
35 #include <arpa/inet.h>
36 #endif
37 #ifdef HAVE_NET_IF_H
38 #include <net/if.h>
39 #endif
40 #ifdef HAVE_NET_IF_ARP_H
41 #include <net/if_arp.h>
42 #endif
43 #ifdef HAVE_NETINET_TCP_H
44 #include <netinet/tcp.h>
45 #endif
46 #ifdef HAVE_NETINET_TCP_FSM_H
47 #include <netinet/tcp_fsm.h>
48 #endif
50 #include "windef.h"
51 #include "winbase.h"
52 #include "iprtrmib.h"
53 #include "ifenum.h"
54 #include "ipstats.h"
56 #ifdef linux
57 #define TCPS_ESTABLISHED 1
58 #define TCPS_SYN_SENT 2
59 #define TCPS_SYN_RECEIVED 3
60 #define TCPS_FIN_WAIT_1 4
61 #define TCPS_FIN_WAIT_2 5
62 #define TCPS_TIME_WAIT 6
63 #define TCPS_CLOSED 7
64 #define TCPS_CLOSE_WAIT 8
65 #define TCPS_LAST_ACK 9
66 #define TCPS_LISTEN 10
67 #define TCPS_CLOSING 11
68 #endif
70 DWORD getInterfaceStatsByName(const char *name, PMIB_IFROW entry)
72 FILE *fp;
74 if (!name)
75 return ERROR_INVALID_PARAMETER;
76 if (!entry)
77 return ERROR_INVALID_PARAMETER;
79 /* get interface stats from /proc/net/dev, no error if can't
80 no inUnknownProtos, outNUcastPkts, outQLen */
81 fp = fopen("/proc/net/dev", "r");
82 if (fp) {
83 char buf[512] = { 0 }, *ptr;
84 int nameLen = strlen(name), nameFound = 0;
87 ptr = fgets(buf, sizeof(buf), fp);
88 while (ptr && !nameFound) {
89 while (*ptr && isspace(*ptr))
90 ptr++;
91 if (strncasecmp(ptr, name, nameLen) == 0 && *(ptr + nameLen) == ':')
92 nameFound = 1;
93 else
94 ptr = fgets(buf, sizeof(buf), fp);
96 if (nameFound) {
97 char *endPtr;
99 ptr += nameLen + 1;
100 if (ptr && *ptr) {
101 entry->dwInOctets = strtoul(ptr, &endPtr, 10);
102 ptr = endPtr;
104 if (ptr && *ptr) {
105 entry->dwInUcastPkts = strtoul(ptr, &endPtr, 10);
106 ptr = endPtr;
108 if (ptr && *ptr) {
109 entry->dwInErrors = strtoul(ptr, &endPtr, 10);
110 ptr = endPtr;
112 if (ptr && *ptr) {
113 entry->dwInDiscards = strtoul(ptr, &endPtr, 10);
114 ptr = endPtr;
116 if (ptr && *ptr) {
117 strtoul(ptr, &endPtr, 10); /* skip */
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 entry->dwInNUcastPkts = strtoul(ptr, &endPtr, 10);
130 ptr = endPtr;
132 if (ptr && *ptr) {
133 entry->dwOutOctets = strtoul(ptr, &endPtr, 10);
134 ptr = endPtr;
136 if (ptr && *ptr) {
137 entry->dwOutUcastPkts = strtoul(ptr, &endPtr, 10);
138 ptr = endPtr;
140 if (ptr && *ptr) {
141 entry->dwOutErrors = strtoul(ptr, &endPtr, 10);
142 ptr = endPtr;
144 if (ptr && *ptr) {
145 entry->dwOutDiscards = strtoul(ptr, &endPtr, 10);
146 ptr = endPtr;
149 fclose(fp);
151 return NO_ERROR;
154 DWORD getICMPStats(MIB_ICMP *stats)
156 FILE *fp;
158 if (!stats)
159 return ERROR_INVALID_PARAMETER;
161 memset(stats, 0, sizeof(MIB_ICMP));
162 /* get most of these stats from /proc/net/snmp, no error if can't */
163 fp = fopen("/proc/net/snmp", "r");
164 if (fp) {
165 const char hdr[] = "Icmp:";
166 char buf[512] = { 0 }, *ptr;
168 do {
169 ptr = fgets(buf, sizeof(buf), fp);
170 } while (ptr && strncasecmp(buf, hdr, sizeof(hdr) - 1));
171 if (ptr) {
172 /* last line was a header, get another */
173 ptr = fgets(buf, sizeof(buf), fp);
174 if (ptr && strncasecmp(buf, hdr, sizeof(hdr) - 1) == 0) {
175 char *endPtr;
177 ptr += sizeof(hdr);
178 if (ptr && *ptr) {
179 stats->stats.icmpInStats.dwMsgs = strtoul(ptr, &endPtr, 10);
180 ptr = endPtr;
182 if (ptr && *ptr) {
183 stats->stats.icmpInStats.dwErrors = strtoul(ptr, &endPtr, 10);
184 ptr = endPtr;
186 if (ptr && *ptr) {
187 stats->stats.icmpInStats.dwDestUnreachs = strtoul(ptr, &endPtr, 10);
188 ptr = endPtr;
190 if (ptr && *ptr) {
191 stats->stats.icmpInStats.dwTimeExcds = strtoul(ptr, &endPtr, 10);
192 ptr = endPtr;
194 if (ptr && *ptr) {
195 stats->stats.icmpInStats.dwParmProbs = strtoul(ptr, &endPtr, 10);
196 ptr = endPtr;
198 if (ptr && *ptr) {
199 stats->stats.icmpInStats.dwSrcQuenchs = strtoul(ptr, &endPtr, 10);
200 ptr = endPtr;
202 if (ptr && *ptr) {
203 stats->stats.icmpInStats.dwRedirects = strtoul(ptr, &endPtr, 10);
204 ptr = endPtr;
206 if (ptr && *ptr) {
207 stats->stats.icmpInStats.dwEchoReps = strtoul(ptr, &endPtr, 10);
208 ptr = endPtr;
210 if (ptr && *ptr) {
211 stats->stats.icmpInStats.dwTimestamps = strtoul(ptr, &endPtr, 10);
212 ptr = endPtr;
214 if (ptr && *ptr) {
215 stats->stats.icmpInStats.dwTimestampReps = strtoul(ptr, &endPtr, 10);
216 ptr = endPtr;
218 if (ptr && *ptr) {
219 stats->stats.icmpInStats.dwAddrMasks = strtoul(ptr, &endPtr, 10);
220 ptr = endPtr;
222 if (ptr && *ptr) {
223 stats->stats.icmpInStats.dwAddrMaskReps = strtoul(ptr, &endPtr, 10);
224 ptr = endPtr;
226 if (ptr && *ptr) {
227 stats->stats.icmpOutStats.dwMsgs = strtoul(ptr, &endPtr, 10);
228 ptr = endPtr;
230 if (ptr && *ptr) {
231 stats->stats.icmpOutStats.dwErrors = strtoul(ptr, &endPtr, 10);
232 ptr = endPtr;
234 if (ptr && *ptr) {
235 stats->stats.icmpOutStats.dwDestUnreachs = strtoul(ptr, &endPtr, 10);
236 ptr = endPtr;
238 if (ptr && *ptr) {
239 stats->stats.icmpOutStats.dwTimeExcds = strtoul(ptr, &endPtr, 10);
240 ptr = endPtr;
242 if (ptr && *ptr) {
243 stats->stats.icmpOutStats.dwParmProbs = strtoul(ptr, &endPtr, 10);
244 ptr = endPtr;
246 if (ptr && *ptr) {
247 stats->stats.icmpOutStats.dwSrcQuenchs = strtoul(ptr, &endPtr, 10);
248 ptr = endPtr;
250 if (ptr && *ptr) {
251 stats->stats.icmpOutStats.dwRedirects = strtoul(ptr, &endPtr, 10);
252 ptr = endPtr;
254 if (ptr && *ptr) {
255 stats->stats.icmpOutStats.dwEchoReps = strtoul(ptr, &endPtr, 10);
256 ptr = endPtr;
258 if (ptr && *ptr) {
259 stats->stats.icmpOutStats.dwTimestamps = strtoul(ptr, &endPtr, 10);
260 ptr = endPtr;
262 if (ptr && *ptr) {
263 stats->stats.icmpOutStats.dwTimestampReps = strtoul(ptr, &endPtr, 10);
264 ptr = endPtr;
266 if (ptr && *ptr) {
267 stats->stats.icmpOutStats.dwAddrMasks = strtoul(ptr, &endPtr, 10);
268 ptr = endPtr;
270 if (ptr && *ptr) {
271 stats->stats.icmpOutStats.dwAddrMaskReps = strtoul(ptr, &endPtr, 10);
272 ptr = endPtr;
276 fclose(fp);
278 return NO_ERROR;
281 DWORD getIPStats(PMIB_IPSTATS stats)
283 FILE *fp;
285 if (!stats)
286 return ERROR_INVALID_PARAMETER;
288 memset(stats, 0, sizeof(MIB_IPSTATS));
289 stats->dwNumIf = stats->dwNumAddr = getNumInterfaces();
290 stats->dwNumRoutes = getNumRoutes();
292 /* get most of these stats from /proc/net/snmp, no error if can't */
293 fp = fopen("/proc/net/snmp", "r");
294 if (fp) {
295 const char hdr[] = "Ip:";
296 char buf[512] = { 0 }, *ptr;
298 do {
299 ptr = fgets(buf, sizeof(buf), fp);
300 } while (ptr && strncasecmp(buf, hdr, sizeof(hdr) - 1));
301 if (ptr) {
302 /* last line was a header, get another */
303 ptr = fgets(buf, sizeof(buf), fp);
304 if (ptr && strncasecmp(buf, hdr, sizeof(hdr) - 1) == 0) {
305 char *endPtr;
307 ptr += sizeof(hdr);
308 if (ptr && *ptr) {
309 stats->dwForwarding = strtoul(ptr, &endPtr, 10);
310 ptr = endPtr;
312 if (ptr && *ptr) {
313 stats->dwDefaultTTL = strtoul(ptr, &endPtr, 10);
314 ptr = endPtr;
316 if (ptr && *ptr) {
317 stats->dwInReceives = strtoul(ptr, &endPtr, 10);
318 ptr = endPtr;
320 if (ptr && *ptr) {
321 stats->dwInHdrErrors = strtoul(ptr, &endPtr, 10);
322 ptr = endPtr;
324 if (ptr && *ptr) {
325 stats->dwInAddrErrors = strtoul(ptr, &endPtr, 10);
326 ptr = endPtr;
328 if (ptr && *ptr) {
329 stats->dwForwDatagrams = strtoul(ptr, &endPtr, 10);
330 ptr = endPtr;
332 if (ptr && *ptr) {
333 stats->dwInUnknownProtos = strtoul(ptr, &endPtr, 10);
334 ptr = endPtr;
336 if (ptr && *ptr) {
337 stats->dwInDiscards = strtoul(ptr, &endPtr, 10);
338 ptr = endPtr;
340 if (ptr && *ptr) {
341 stats->dwInDelivers = strtoul(ptr, &endPtr, 10);
342 ptr = endPtr;
344 if (ptr && *ptr) {
345 stats->dwOutRequests = strtoul(ptr, &endPtr, 10);
346 ptr = endPtr;
348 if (ptr && *ptr) {
349 stats->dwOutDiscards = strtoul(ptr, &endPtr, 10);
350 ptr = endPtr;
352 if (ptr && *ptr) {
353 stats->dwOutNoRoutes = strtoul(ptr, &endPtr, 10);
354 ptr = endPtr;
356 if (ptr && *ptr) {
357 stats->dwReasmTimeout = strtoul(ptr, &endPtr, 10);
358 ptr = endPtr;
360 if (ptr && *ptr) {
361 stats->dwReasmReqds = strtoul(ptr, &endPtr, 10);
362 ptr = endPtr;
364 if (ptr && *ptr) {
365 stats->dwReasmOks = strtoul(ptr, &endPtr, 10);
366 ptr = endPtr;
368 if (ptr && *ptr) {
369 stats->dwReasmFails = strtoul(ptr, &endPtr, 10);
370 ptr = endPtr;
372 if (ptr && *ptr) {
373 stats->dwFragOks = strtoul(ptr, &endPtr, 10);
374 ptr = endPtr;
376 if (ptr && *ptr) {
377 stats->dwFragFails = strtoul(ptr, &endPtr, 10);
378 ptr = endPtr;
380 if (ptr && *ptr) {
381 stats->dwFragCreates = strtoul(ptr, &endPtr, 10);
382 ptr = endPtr;
384 /* hmm, no routingDiscards */
387 fclose(fp);
389 return NO_ERROR;
392 DWORD getTCPStats(MIB_TCPSTATS *stats)
394 FILE *fp;
396 if (!stats)
397 return ERROR_INVALID_PARAMETER;
399 memset(stats, 0, sizeof(MIB_TCPSTATS));
401 /* get from /proc/net/snmp, no error if can't */
402 fp = fopen("/proc/net/snmp", "r");
403 if (fp) {
404 const char hdr[] = "Tcp:";
405 char buf[512] = { 0 }, *ptr;
408 do {
409 ptr = fgets(buf, sizeof(buf), fp);
410 } while (ptr && strncasecmp(buf, hdr, sizeof(hdr) - 1));
411 if (ptr) {
412 /* last line was a header, get another */
413 ptr = fgets(buf, sizeof(buf), fp);
414 if (ptr && strncasecmp(buf, hdr, sizeof(hdr) - 1) == 0) {
415 char *endPtr;
417 ptr += sizeof(hdr);
418 if (ptr && *ptr) {
419 stats->dwRtoAlgorithm = strtoul(ptr, &endPtr, 10);
420 ptr = endPtr;
422 if (ptr && *ptr) {
423 stats->dwRtoMin = 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->dwMaxConn = strtoul(ptr, &endPtr, 10);
432 ptr = endPtr;
434 if (ptr && *ptr) {
435 stats->dwActiveOpens = strtoul(ptr, &endPtr, 10);
436 ptr = endPtr;
438 if (ptr && *ptr) {
439 stats->dwPassiveOpens = strtoul(ptr, &endPtr, 10);
440 ptr = endPtr;
442 if (ptr && *ptr) {
443 stats->dwAttemptFails = strtoul(ptr, &endPtr, 10);
444 ptr = endPtr;
446 if (ptr && *ptr) {
447 stats->dwEstabResets = strtoul(ptr, &endPtr, 10);
448 ptr = endPtr;
450 if (ptr && *ptr) {
451 stats->dwCurrEstab = strtoul(ptr, &endPtr, 10);
452 ptr = endPtr;
454 if (ptr && *ptr) {
455 stats->dwInSegs = strtoul(ptr, &endPtr, 10);
456 ptr = endPtr;
458 if (ptr && *ptr) {
459 stats->dwOutSegs = strtoul(ptr, &endPtr, 10);
460 ptr = endPtr;
462 if (ptr && *ptr) {
463 stats->dwRetransSegs = strtoul(ptr, &endPtr, 10);
464 ptr = endPtr;
466 if (ptr && *ptr) {
467 stats->dwInErrs = strtoul(ptr, &endPtr, 10);
468 ptr = endPtr;
470 if (ptr && *ptr) {
471 stats->dwOutRsts = strtoul(ptr, &endPtr, 10);
472 ptr = endPtr;
474 stats->dwNumConns = getNumTcpEntries();
477 fclose(fp);
479 return NO_ERROR;
482 DWORD getUDPStats(MIB_UDPSTATS *stats)
484 FILE *fp;
486 if (!stats)
487 return ERROR_INVALID_PARAMETER;
489 memset(stats, 0, sizeof(MIB_UDPSTATS));
491 /* get from /proc/net/snmp, no error if can't */
492 fp = fopen("/proc/net/snmp", "r");
493 if (fp) {
494 const char hdr[] = "Udp:";
495 char buf[512] = { 0 }, *ptr;
498 do {
499 ptr = fgets(buf, sizeof(buf), fp);
500 } while (ptr && strncasecmp(buf, hdr, sizeof(hdr) - 1));
501 if (ptr) {
502 /* last line was a header, get another */
503 ptr = fgets(buf, sizeof(buf), fp);
504 if (ptr && strncasecmp(buf, hdr, sizeof(hdr) - 1) == 0) {
505 char *endPtr;
507 ptr += sizeof(hdr);
508 if (ptr && *ptr) {
509 stats->dwInDatagrams = strtoul(ptr, &endPtr, 10);
510 ptr = endPtr;
512 if (ptr && *ptr) {
513 stats->dwNoPorts = strtoul(ptr, &endPtr, 10);
514 ptr = endPtr;
516 if (ptr && *ptr) {
517 stats->dwInErrors = strtoul(ptr, &endPtr, 10);
518 ptr = endPtr;
520 if (ptr && *ptr) {
521 stats->dwOutDatagrams = strtoul(ptr, &endPtr, 10);
522 ptr = endPtr;
524 if (ptr && *ptr) {
525 stats->dwNumAddrs = strtoul(ptr, &endPtr, 10);
526 ptr = endPtr;
530 fclose(fp);
532 return NO_ERROR;
535 static DWORD getNumWithOneHeader(const char *filename)
537 FILE *fp;
538 int ret = 0;
540 fp = fopen(filename, "r");
541 if (fp) {
542 char buf[512] = { 0 }, *ptr;
545 ptr = fgets(buf, sizeof(buf), fp);
546 if (ptr) {
547 do {
548 ptr = fgets(buf, sizeof(buf), fp);
549 if (ptr)
550 ret++;
551 } while (ptr);
553 fclose(fp);
555 return ret;
558 DWORD getNumRoutes(void)
560 return getNumWithOneHeader("/proc/net/route");
563 RouteTable *getRouteTable(void)
565 DWORD numRoutes = getNumRoutes();
566 RouteTable *ret;
568 ret = (RouteTable *)calloc(1, sizeof(RouteTable) +
569 (numRoutes - 1) * sizeof(RouteEntry));
570 if (ret) {
571 FILE *fp;
573 /* get from /proc/net/route, no error if can't */
574 fp = fopen("/proc/net/route", "r");
575 if (fp) {
576 char buf[512] = { 0 }, *ptr;
578 /* skip header line */
579 ptr = fgets(buf, sizeof(buf), fp);
580 while (ptr && ret->numRoutes < numRoutes) {
581 ptr = fgets(buf, sizeof(buf), fp);
582 if (ptr) {
583 DWORD index;
585 while (!isspace(*ptr))
586 ptr++;
587 *ptr = '\0';
588 ptr++;
589 if (getInterfaceIndexByName(buf, &index) == NO_ERROR) {
590 char *endPtr;
592 ret->routes[ret->numRoutes].ifIndex = index;
593 if (*ptr) {
594 ret->routes[ret->numRoutes].dest = strtoul(ptr, &endPtr, 16);
595 ptr = endPtr;
597 if (ptr && *ptr) {
598 ret->routes[ret->numRoutes].gateway = strtoul(ptr, &endPtr, 16);
599 ptr = endPtr;
601 if (ptr && *ptr) {
602 strtoul(ptr, &endPtr, 16); /* flags, skip */
603 ptr = endPtr;
605 if (ptr && *ptr) {
606 strtoul(ptr, &endPtr, 16); /* refcount, skip */
607 ptr = endPtr;
609 if (ptr && *ptr) {
610 strtoul(ptr, &endPtr, 16); /* use, skip */
611 ptr = endPtr;
613 if (ptr && *ptr) {
614 ret->routes[ret->numRoutes].metric = strtoul(ptr, &endPtr, 16);
615 ptr = endPtr;
617 if (ptr && *ptr) {
618 ret->routes[ret->numRoutes].mask = strtoul(ptr, &endPtr, 16);
619 ptr = endPtr;
621 ret->numRoutes++;
625 fclose(fp);
628 return ret;
631 DWORD getNumArpEntries(void)
633 return getNumWithOneHeader("/proc/net/arp");
636 PMIB_IPNETTABLE getArpTable(void)
638 DWORD numEntries = getNumArpEntries();
639 PMIB_IPNETTABLE ret;
641 ret = (PMIB_IPNETTABLE)calloc(1, sizeof(MIB_IPNETTABLE) +
642 (numEntries - 1) * sizeof(MIB_IPNETROW));
643 if (ret) {
644 FILE *fp;
646 /* get from /proc/net/arp, no error if can't */
647 fp = fopen("/proc/net/arp", "r");
648 if (fp) {
649 char buf[512] = { 0 }, *ptr;
651 /* skip header line */
652 ptr = fgets(buf, sizeof(buf), fp);
653 while (ptr && ret->dwNumEntries < numEntries) {
654 ptr = fgets(buf, sizeof(buf), fp);
655 if (ptr) {
656 char *endPtr;
658 ret->table[ret->dwNumEntries].dwAddr = inet_addr(ptr);
659 while (ptr && *ptr && !isspace(*ptr))
660 ptr++;
662 if (ptr && *ptr) {
663 strtoul(ptr, &endPtr, 16); /* hw type (skip) */
664 ptr = endPtr;
666 if (ptr && *ptr) {
667 DWORD flags = strtoul(ptr, &endPtr, 16);
669 #ifdef ATF_COM
670 if (flags & ATF_COM)
671 ret->table[ret->dwNumEntries].dwType = MIB_IPNET_TYPE_DYNAMIC;
672 else
673 #endif
674 #ifdef ATF_PERM
675 if (flags & ATF_PERM)
676 ret->table[ret->dwNumEntries].dwType = MIB_IPNET_TYPE_STATIC;
677 else
678 #endif
679 ret->table[ret->dwNumEntries].dwType = MIB_IPNET_TYPE_OTHER;
681 ptr = endPtr;
683 while (ptr && *ptr && isspace(*ptr))
684 ptr++;
685 while (ptr && *ptr && !isspace(*ptr)) {
686 DWORD byte = strtoul(ptr, &endPtr, 16);
688 if (endPtr && *endPtr) {
689 endPtr++;
690 ret->table[ret->dwNumEntries].bPhysAddr[
691 ret->table[ret->dwNumEntries].dwPhysAddrLen++] = byte & 0x0ff;
693 ptr = endPtr;
695 if (ptr && *ptr) {
696 strtoul(ptr, &endPtr, 16); /* mask (skip) */
697 ptr = endPtr;
699 getInterfaceIndexByName(ptr, &ret->table[ret->dwNumEntries].dwIndex);
700 ret->dwNumEntries++;
703 fclose(fp);
706 return ret;
709 DWORD getNumUdpEntries(void)
711 return getNumWithOneHeader("/proc/net/udp");
714 PMIB_UDPTABLE getUdpTable(void)
716 DWORD numEntries = getNumUdpEntries();
717 PMIB_UDPTABLE ret;
719 ret = (PMIB_UDPTABLE)calloc(1, sizeof(MIB_UDPTABLE) +
720 (numEntries - 1) * sizeof(MIB_UDPROW));
721 if (ret) {
722 FILE *fp;
724 /* get from /proc/net/udp, no error if can't */
725 fp = fopen("/proc/net/udp", "r");
726 if (fp) {
727 char buf[512] = { 0 }, *ptr;
729 /* skip header line */
730 ptr = fgets(buf, sizeof(buf), fp);
731 while (ptr && ret->dwNumEntries < numEntries) {
732 ptr = fgets(buf, sizeof(buf), fp);
733 if (ptr) {
734 char *endPtr;
736 if (ptr && *ptr) {
737 strtoul(ptr, &endPtr, 16); /* skip */
738 ptr = endPtr;
740 if (ptr && *ptr) {
741 ptr++;
742 ret->table[ret->dwNumEntries].dwLocalAddr = strtoul(ptr, &endPtr,
743 16);
744 ptr = endPtr;
746 if (ptr && *ptr) {
747 ptr++;
748 ret->table[ret->dwNumEntries].dwLocalPort = strtoul(ptr, &endPtr,
749 16);
750 ptr = endPtr;
752 ret->dwNumEntries++;
755 fclose(fp);
758 return ret;
761 DWORD getNumTcpEntries(void)
763 return getNumWithOneHeader("/proc/net/tcp");
766 PMIB_TCPTABLE getTcpTable(void)
768 DWORD numEntries = getNumTcpEntries();
769 PMIB_TCPTABLE ret;
771 ret = (PMIB_TCPTABLE)calloc(1, sizeof(MIB_TCPTABLE) +
772 (numEntries - 1) * sizeof(MIB_TCPROW));
773 if (ret) {
774 FILE *fp;
776 /* get from /proc/net/tcp, no error if can't */
777 fp = fopen("/proc/net/tcp", "r");
778 if (fp) {
779 char buf[512] = { 0 }, *ptr;
781 /* skip header line */
782 ptr = fgets(buf, sizeof(buf), fp);
783 while (ptr && ret->dwNumEntries < numEntries) {
784 ptr = fgets(buf, sizeof(buf), fp);
785 if (ptr) {
786 char *endPtr;
788 while (ptr && *ptr && *ptr != ':')
789 ptr++;
790 if (ptr && *ptr)
791 ptr++;
792 if (ptr && *ptr) {
793 ret->table[ret->dwNumEntries].dwLocalAddr = strtoul(ptr, &endPtr,
794 16);
795 ptr = endPtr;
797 if (ptr && *ptr) {
798 ptr++;
799 ret->table[ret->dwNumEntries].dwLocalPort = strtoul(ptr, &endPtr,
800 16);
801 ptr = endPtr;
803 if (ptr && *ptr) {
804 ret->table[ret->dwNumEntries].dwRemoteAddr = strtoul(ptr, &endPtr,
805 16);
806 ptr = endPtr;
808 if (ptr && *ptr) {
809 ptr++;
810 ret->table[ret->dwNumEntries].dwRemotePort = strtoul(ptr, &endPtr,
811 16);
812 ptr = endPtr;
814 if (ptr && *ptr) {
815 DWORD state = strtoul(ptr, &endPtr, 16);
817 switch (state)
819 case TCPS_ESTABLISHED:
820 ret->table[ret->dwNumEntries].dwState = MIB_TCP_STATE_ESTAB;
821 break;
822 case TCPS_SYN_SENT:
823 ret->table[ret->dwNumEntries].dwState = MIB_TCP_STATE_SYN_SENT;
824 break;
825 case TCPS_SYN_RECEIVED:
826 ret->table[ret->dwNumEntries].dwState = MIB_TCP_STATE_SYN_RCVD;
827 break;
828 case TCPS_FIN_WAIT_1:
829 ret->table[ret->dwNumEntries].dwState = MIB_TCP_STATE_FIN_WAIT1;
830 break;
831 case TCPS_FIN_WAIT_2:
832 ret->table[ret->dwNumEntries].dwState = MIB_TCP_STATE_FIN_WAIT2;
833 break;
834 case TCPS_TIME_WAIT:
835 ret->table[ret->dwNumEntries].dwState = MIB_TCP_STATE_TIME_WAIT;
836 break;
837 case TCPS_CLOSED:
838 ret->table[ret->dwNumEntries].dwState = MIB_TCP_STATE_CLOSED;
839 break;
840 case TCPS_CLOSE_WAIT:
841 ret->table[ret->dwNumEntries].dwState =
842 MIB_TCP_STATE_CLOSE_WAIT;
843 break;
844 case TCPS_LAST_ACK:
845 ret->table[ret->dwNumEntries].dwState = MIB_TCP_STATE_LAST_ACK;
846 break;
847 case TCPS_LISTEN:
848 ret->table[ret->dwNumEntries].dwState = MIB_TCP_STATE_LISTEN;
849 break;
850 case TCPS_CLOSING:
851 ret->table[ret->dwNumEntries].dwState = MIB_TCP_STATE_CLOSING;
852 break;
854 ptr = endPtr;
856 ret->dwNumEntries++;
859 fclose(fp);
862 return ret;