Use #ifdef instead of #if for all feature tests.
[wine/wine64.git] / dlls / iphlpapi / ipstats.c
blob4de13a419f6ba909c34f447031906700347c5045
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 #ifndef TCPS_ESTABLISHED
57 # define TCPS_ESTABLISHED TCP_ESTABLISHED
58 #endif
59 #ifndef TCPS_SYN_SENT
60 # define TCPS_SYN_SENT TCP_SYN_SENT
61 #endif
62 #ifndef TCPS_SYN_RECEIVED
63 # define TCPS_SYN_RECEIVED TCP_SYN_RECV
64 #endif
65 #ifndef TCPS_FIN_WAIT_1
66 # define TCPS_FIN_WAIT_1 TCP_FIN_WAIT1
67 #endif
68 #ifndef TCPS_FIN_WAIT_2
69 # define TCPS_FIN_WAIT_2 TCP_FIN_WAIT2
70 #endif
71 #ifndef TCPS_TIME_WAIT
72 # define TCPS_TIME_WAIT TCP_TIME_WAIT
73 #endif
74 #ifndef TCPS_CLOSED
75 # define TCPS_CLOSED TCP_CLOSE
76 #endif
77 #ifndef TCPS_CLOSE_WAIT
78 # define TCPS_CLOSE_WAIT TCP_CLOSE_WAIT
79 #endif
80 #ifndef TCPS_LAST_ACK
81 # define TCPS_LAST_ACK TCP_LAST_ACK
82 #endif
83 #ifndef TCPS_LISTEN
84 # define TCPS_LISTEN TCP_LISTEN
85 #endif
86 #ifndef TCPS_CLOSING
87 # define TCPS_CLOSING TCP_CLOSING
88 #endif
90 DWORD getInterfaceStatsByName(const char *name, PMIB_IFROW entry)
92 FILE *fp;
94 if (!name)
95 return ERROR_INVALID_PARAMETER;
96 if (!entry)
97 return ERROR_INVALID_PARAMETER;
99 /* get interface stats from /proc/net/dev, no error if can't
100 no inUnknownProtos, outNUcastPkts, outQLen */
101 fp = fopen("/proc/net/dev", "r");
102 if (fp) {
103 char buf[512] = { 0 }, *ptr;
104 int nameLen = strlen(name), nameFound = 0;
107 ptr = fgets(buf, sizeof(buf), fp);
108 while (ptr && !nameFound) {
109 while (*ptr && isspace(*ptr))
110 ptr++;
111 if (strncasecmp(ptr, name, nameLen) == 0 && *(ptr + nameLen) == ':')
112 nameFound = 1;
113 else
114 ptr = fgets(buf, sizeof(buf), fp);
116 if (nameFound) {
117 char *endPtr;
119 ptr += nameLen + 1;
120 if (ptr && *ptr) {
121 entry->dwInOctets = strtoul(ptr, &endPtr, 10);
122 ptr = endPtr;
124 if (ptr && *ptr) {
125 entry->dwInUcastPkts = strtoul(ptr, &endPtr, 10);
126 ptr = endPtr;
128 if (ptr && *ptr) {
129 entry->dwInErrors = strtoul(ptr, &endPtr, 10);
130 ptr = endPtr;
132 if (ptr && *ptr) {
133 entry->dwInDiscards = strtoul(ptr, &endPtr, 10);
134 ptr = endPtr;
136 if (ptr && *ptr) {
137 strtoul(ptr, &endPtr, 10); /* skip */
138 ptr = endPtr;
140 if (ptr && *ptr) {
141 strtoul(ptr, &endPtr, 10); /* skip */
142 ptr = endPtr;
144 if (ptr && *ptr) {
145 strtoul(ptr, &endPtr, 10); /* skip */
146 ptr = endPtr;
148 if (ptr && *ptr) {
149 entry->dwInNUcastPkts = strtoul(ptr, &endPtr, 10);
150 ptr = endPtr;
152 if (ptr && *ptr) {
153 entry->dwOutOctets = strtoul(ptr, &endPtr, 10);
154 ptr = endPtr;
156 if (ptr && *ptr) {
157 entry->dwOutUcastPkts = strtoul(ptr, &endPtr, 10);
158 ptr = endPtr;
160 if (ptr && *ptr) {
161 entry->dwOutErrors = strtoul(ptr, &endPtr, 10);
162 ptr = endPtr;
164 if (ptr && *ptr) {
165 entry->dwOutDiscards = strtoul(ptr, &endPtr, 10);
166 ptr = endPtr;
169 fclose(fp);
171 return NO_ERROR;
174 DWORD getICMPStats(MIB_ICMP *stats)
176 FILE *fp;
178 if (!stats)
179 return ERROR_INVALID_PARAMETER;
181 memset(stats, 0, sizeof(MIB_ICMP));
182 /* get most of these stats from /proc/net/snmp, no error if can't */
183 fp = fopen("/proc/net/snmp", "r");
184 if (fp) {
185 const char hdr[] = "Icmp:";
186 char buf[512] = { 0 }, *ptr;
188 do {
189 ptr = fgets(buf, sizeof(buf), fp);
190 } while (ptr && strncasecmp(buf, hdr, sizeof(hdr) - 1));
191 if (ptr) {
192 /* last line was a header, get another */
193 ptr = fgets(buf, sizeof(buf), fp);
194 if (ptr && strncasecmp(buf, hdr, sizeof(hdr) - 1) == 0) {
195 char *endPtr;
197 ptr += sizeof(hdr);
198 if (ptr && *ptr) {
199 stats->stats.icmpInStats.dwMsgs = strtoul(ptr, &endPtr, 10);
200 ptr = endPtr;
202 if (ptr && *ptr) {
203 stats->stats.icmpInStats.dwErrors = strtoul(ptr, &endPtr, 10);
204 ptr = endPtr;
206 if (ptr && *ptr) {
207 stats->stats.icmpInStats.dwDestUnreachs = strtoul(ptr, &endPtr, 10);
208 ptr = endPtr;
210 if (ptr && *ptr) {
211 stats->stats.icmpInStats.dwTimeExcds = strtoul(ptr, &endPtr, 10);
212 ptr = endPtr;
214 if (ptr && *ptr) {
215 stats->stats.icmpInStats.dwParmProbs = strtoul(ptr, &endPtr, 10);
216 ptr = endPtr;
218 if (ptr && *ptr) {
219 stats->stats.icmpInStats.dwSrcQuenchs = strtoul(ptr, &endPtr, 10);
220 ptr = endPtr;
222 if (ptr && *ptr) {
223 stats->stats.icmpInStats.dwRedirects = strtoul(ptr, &endPtr, 10);
224 ptr = endPtr;
226 if (ptr && *ptr) {
227 stats->stats.icmpInStats.dwEchoReps = strtoul(ptr, &endPtr, 10);
228 ptr = endPtr;
230 if (ptr && *ptr) {
231 stats->stats.icmpInStats.dwTimestamps = strtoul(ptr, &endPtr, 10);
232 ptr = endPtr;
234 if (ptr && *ptr) {
235 stats->stats.icmpInStats.dwTimestampReps = strtoul(ptr, &endPtr, 10);
236 ptr = endPtr;
238 if (ptr && *ptr) {
239 stats->stats.icmpInStats.dwAddrMasks = strtoul(ptr, &endPtr, 10);
240 ptr = endPtr;
242 if (ptr && *ptr) {
243 stats->stats.icmpInStats.dwAddrMaskReps = strtoul(ptr, &endPtr, 10);
244 ptr = endPtr;
246 if (ptr && *ptr) {
247 stats->stats.icmpOutStats.dwMsgs = strtoul(ptr, &endPtr, 10);
248 ptr = endPtr;
250 if (ptr && *ptr) {
251 stats->stats.icmpOutStats.dwErrors = strtoul(ptr, &endPtr, 10);
252 ptr = endPtr;
254 if (ptr && *ptr) {
255 stats->stats.icmpOutStats.dwDestUnreachs = strtoul(ptr, &endPtr, 10);
256 ptr = endPtr;
258 if (ptr && *ptr) {
259 stats->stats.icmpOutStats.dwTimeExcds = strtoul(ptr, &endPtr, 10);
260 ptr = endPtr;
262 if (ptr && *ptr) {
263 stats->stats.icmpOutStats.dwParmProbs = strtoul(ptr, &endPtr, 10);
264 ptr = endPtr;
266 if (ptr && *ptr) {
267 stats->stats.icmpOutStats.dwSrcQuenchs = strtoul(ptr, &endPtr, 10);
268 ptr = endPtr;
270 if (ptr && *ptr) {
271 stats->stats.icmpOutStats.dwRedirects = strtoul(ptr, &endPtr, 10);
272 ptr = endPtr;
274 if (ptr && *ptr) {
275 stats->stats.icmpOutStats.dwEchoReps = strtoul(ptr, &endPtr, 10);
276 ptr = endPtr;
278 if (ptr && *ptr) {
279 stats->stats.icmpOutStats.dwTimestamps = strtoul(ptr, &endPtr, 10);
280 ptr = endPtr;
282 if (ptr && *ptr) {
283 stats->stats.icmpOutStats.dwTimestampReps = strtoul(ptr, &endPtr, 10);
284 ptr = endPtr;
286 if (ptr && *ptr) {
287 stats->stats.icmpOutStats.dwAddrMasks = strtoul(ptr, &endPtr, 10);
288 ptr = endPtr;
290 if (ptr && *ptr) {
291 stats->stats.icmpOutStats.dwAddrMaskReps = strtoul(ptr, &endPtr, 10);
292 ptr = endPtr;
296 fclose(fp);
298 return NO_ERROR;
301 DWORD getIPStats(PMIB_IPSTATS stats)
303 FILE *fp;
305 if (!stats)
306 return ERROR_INVALID_PARAMETER;
308 memset(stats, 0, sizeof(MIB_IPSTATS));
309 stats->dwNumIf = stats->dwNumAddr = getNumInterfaces();
310 stats->dwNumRoutes = getNumRoutes();
312 /* get most of these stats from /proc/net/snmp, no error if can't */
313 fp = fopen("/proc/net/snmp", "r");
314 if (fp) {
315 const char hdr[] = "Ip:";
316 char buf[512] = { 0 }, *ptr;
318 do {
319 ptr = fgets(buf, sizeof(buf), fp);
320 } while (ptr && strncasecmp(buf, hdr, sizeof(hdr) - 1));
321 if (ptr) {
322 /* last line was a header, get another */
323 ptr = fgets(buf, sizeof(buf), fp);
324 if (ptr && strncasecmp(buf, hdr, sizeof(hdr) - 1) == 0) {
325 char *endPtr;
327 ptr += sizeof(hdr);
328 if (ptr && *ptr) {
329 stats->dwForwarding = strtoul(ptr, &endPtr, 10);
330 ptr = endPtr;
332 if (ptr && *ptr) {
333 stats->dwDefaultTTL = strtoul(ptr, &endPtr, 10);
334 ptr = endPtr;
336 if (ptr && *ptr) {
337 stats->dwInReceives = strtoul(ptr, &endPtr, 10);
338 ptr = endPtr;
340 if (ptr && *ptr) {
341 stats->dwInHdrErrors = strtoul(ptr, &endPtr, 10);
342 ptr = endPtr;
344 if (ptr && *ptr) {
345 stats->dwInAddrErrors = strtoul(ptr, &endPtr, 10);
346 ptr = endPtr;
348 if (ptr && *ptr) {
349 stats->dwForwDatagrams = strtoul(ptr, &endPtr, 10);
350 ptr = endPtr;
352 if (ptr && *ptr) {
353 stats->dwInUnknownProtos = strtoul(ptr, &endPtr, 10);
354 ptr = endPtr;
356 if (ptr && *ptr) {
357 stats->dwInDiscards = strtoul(ptr, &endPtr, 10);
358 ptr = endPtr;
360 if (ptr && *ptr) {
361 stats->dwInDelivers = strtoul(ptr, &endPtr, 10);
362 ptr = endPtr;
364 if (ptr && *ptr) {
365 stats->dwOutRequests = strtoul(ptr, &endPtr, 10);
366 ptr = endPtr;
368 if (ptr && *ptr) {
369 stats->dwOutDiscards = strtoul(ptr, &endPtr, 10);
370 ptr = endPtr;
372 if (ptr && *ptr) {
373 stats->dwOutNoRoutes = strtoul(ptr, &endPtr, 10);
374 ptr = endPtr;
376 if (ptr && *ptr) {
377 stats->dwReasmTimeout = strtoul(ptr, &endPtr, 10);
378 ptr = endPtr;
380 if (ptr && *ptr) {
381 stats->dwReasmReqds = strtoul(ptr, &endPtr, 10);
382 ptr = endPtr;
384 if (ptr && *ptr) {
385 stats->dwReasmOks = strtoul(ptr, &endPtr, 10);
386 ptr = endPtr;
388 if (ptr && *ptr) {
389 stats->dwReasmFails = strtoul(ptr, &endPtr, 10);
390 ptr = endPtr;
392 if (ptr && *ptr) {
393 stats->dwFragOks = strtoul(ptr, &endPtr, 10);
394 ptr = endPtr;
396 if (ptr && *ptr) {
397 stats->dwFragFails = strtoul(ptr, &endPtr, 10);
398 ptr = endPtr;
400 if (ptr && *ptr) {
401 stats->dwFragCreates = strtoul(ptr, &endPtr, 10);
402 ptr = endPtr;
404 /* hmm, no routingDiscards */
407 fclose(fp);
409 return NO_ERROR;
412 DWORD getTCPStats(MIB_TCPSTATS *stats)
414 FILE *fp;
416 if (!stats)
417 return ERROR_INVALID_PARAMETER;
419 memset(stats, 0, sizeof(MIB_TCPSTATS));
421 /* get from /proc/net/snmp, no error if can't */
422 fp = fopen("/proc/net/snmp", "r");
423 if (fp) {
424 const char hdr[] = "Tcp:";
425 char buf[512] = { 0 }, *ptr;
428 do {
429 ptr = fgets(buf, sizeof(buf), fp);
430 } while (ptr && strncasecmp(buf, hdr, sizeof(hdr) - 1));
431 if (ptr) {
432 /* last line was a header, get another */
433 ptr = fgets(buf, sizeof(buf), fp);
434 if (ptr && strncasecmp(buf, hdr, sizeof(hdr) - 1) == 0) {
435 char *endPtr;
437 ptr += sizeof(hdr);
438 if (ptr && *ptr) {
439 stats->dwRtoAlgorithm = strtoul(ptr, &endPtr, 10);
440 ptr = endPtr;
442 if (ptr && *ptr) {
443 stats->dwRtoMin = strtoul(ptr, &endPtr, 10);
444 ptr = endPtr;
446 if (ptr && *ptr) {
447 stats->dwRtoMin = strtoul(ptr, &endPtr, 10);
448 ptr = endPtr;
450 if (ptr && *ptr) {
451 stats->dwMaxConn = strtoul(ptr, &endPtr, 10);
452 ptr = endPtr;
454 if (ptr && *ptr) {
455 stats->dwActiveOpens = strtoul(ptr, &endPtr, 10);
456 ptr = endPtr;
458 if (ptr && *ptr) {
459 stats->dwPassiveOpens = strtoul(ptr, &endPtr, 10);
460 ptr = endPtr;
462 if (ptr && *ptr) {
463 stats->dwAttemptFails = strtoul(ptr, &endPtr, 10);
464 ptr = endPtr;
466 if (ptr && *ptr) {
467 stats->dwEstabResets = strtoul(ptr, &endPtr, 10);
468 ptr = endPtr;
470 if (ptr && *ptr) {
471 stats->dwCurrEstab = strtoul(ptr, &endPtr, 10);
472 ptr = endPtr;
474 if (ptr && *ptr) {
475 stats->dwInSegs = strtoul(ptr, &endPtr, 10);
476 ptr = endPtr;
478 if (ptr && *ptr) {
479 stats->dwOutSegs = strtoul(ptr, &endPtr, 10);
480 ptr = endPtr;
482 if (ptr && *ptr) {
483 stats->dwRetransSegs = strtoul(ptr, &endPtr, 10);
484 ptr = endPtr;
486 if (ptr && *ptr) {
487 stats->dwInErrs = strtoul(ptr, &endPtr, 10);
488 ptr = endPtr;
490 if (ptr && *ptr) {
491 stats->dwOutRsts = strtoul(ptr, &endPtr, 10);
492 ptr = endPtr;
494 stats->dwNumConns = getNumTcpEntries();
497 fclose(fp);
499 return NO_ERROR;
502 DWORD getUDPStats(MIB_UDPSTATS *stats)
504 FILE *fp;
506 if (!stats)
507 return ERROR_INVALID_PARAMETER;
509 memset(stats, 0, sizeof(MIB_UDPSTATS));
511 /* get from /proc/net/snmp, no error if can't */
512 fp = fopen("/proc/net/snmp", "r");
513 if (fp) {
514 const char hdr[] = "Udp:";
515 char buf[512] = { 0 }, *ptr;
518 do {
519 ptr = fgets(buf, sizeof(buf), fp);
520 } while (ptr && strncasecmp(buf, hdr, sizeof(hdr) - 1));
521 if (ptr) {
522 /* last line was a header, get another */
523 ptr = fgets(buf, sizeof(buf), fp);
524 if (ptr && strncasecmp(buf, hdr, sizeof(hdr) - 1) == 0) {
525 char *endPtr;
527 ptr += sizeof(hdr);
528 if (ptr && *ptr) {
529 stats->dwInDatagrams = strtoul(ptr, &endPtr, 10);
530 ptr = endPtr;
532 if (ptr && *ptr) {
533 stats->dwNoPorts = strtoul(ptr, &endPtr, 10);
534 ptr = endPtr;
536 if (ptr && *ptr) {
537 stats->dwInErrors = strtoul(ptr, &endPtr, 10);
538 ptr = endPtr;
540 if (ptr && *ptr) {
541 stats->dwOutDatagrams = strtoul(ptr, &endPtr, 10);
542 ptr = endPtr;
544 if (ptr && *ptr) {
545 stats->dwNumAddrs = strtoul(ptr, &endPtr, 10);
546 ptr = endPtr;
550 fclose(fp);
552 return NO_ERROR;
555 static DWORD getNumWithOneHeader(const char *filename)
557 FILE *fp;
558 int ret = 0;
560 fp = fopen(filename, "r");
561 if (fp) {
562 char buf[512] = { 0 }, *ptr;
565 ptr = fgets(buf, sizeof(buf), fp);
566 if (ptr) {
567 do {
568 ptr = fgets(buf, sizeof(buf), fp);
569 if (ptr)
570 ret++;
571 } while (ptr);
573 fclose(fp);
575 return ret;
578 DWORD getNumRoutes(void)
580 return getNumWithOneHeader("/proc/net/route");
583 RouteTable *getRouteTable(void)
585 DWORD numRoutes = getNumRoutes();
586 RouteTable *ret;
588 ret = (RouteTable *)calloc(1, sizeof(RouteTable) +
589 (numRoutes - 1) * sizeof(RouteEntry));
590 if (ret) {
591 FILE *fp;
593 /* get from /proc/net/route, no error if can't */
594 fp = fopen("/proc/net/route", "r");
595 if (fp) {
596 char buf[512] = { 0 }, *ptr;
598 /* skip header line */
599 ptr = fgets(buf, sizeof(buf), fp);
600 while (ptr && ret->numRoutes < numRoutes) {
601 ptr = fgets(buf, sizeof(buf), fp);
602 if (ptr) {
603 DWORD index;
605 while (!isspace(*ptr))
606 ptr++;
607 *ptr = '\0';
608 ptr++;
609 if (getInterfaceIndexByName(buf, &index) == NO_ERROR) {
610 char *endPtr;
612 ret->routes[ret->numRoutes].ifIndex = index;
613 if (*ptr) {
614 ret->routes[ret->numRoutes].dest = strtoul(ptr, &endPtr, 16);
615 ptr = endPtr;
617 if (ptr && *ptr) {
618 ret->routes[ret->numRoutes].gateway = strtoul(ptr, &endPtr, 16);
619 ptr = endPtr;
621 if (ptr && *ptr) {
622 strtoul(ptr, &endPtr, 16); /* flags, skip */
623 ptr = endPtr;
625 if (ptr && *ptr) {
626 strtoul(ptr, &endPtr, 16); /* refcount, skip */
627 ptr = endPtr;
629 if (ptr && *ptr) {
630 strtoul(ptr, &endPtr, 16); /* use, skip */
631 ptr = endPtr;
633 if (ptr && *ptr) {
634 ret->routes[ret->numRoutes].metric = strtoul(ptr, &endPtr, 16);
635 ptr = endPtr;
637 if (ptr && *ptr) {
638 ret->routes[ret->numRoutes].mask = strtoul(ptr, &endPtr, 16);
639 ptr = endPtr;
641 ret->numRoutes++;
645 fclose(fp);
648 return ret;
651 DWORD getNumArpEntries(void)
653 return getNumWithOneHeader("/proc/net/arp");
656 PMIB_IPNETTABLE getArpTable(void)
658 DWORD numEntries = getNumArpEntries();
659 PMIB_IPNETTABLE ret;
661 ret = (PMIB_IPNETTABLE)calloc(1, sizeof(MIB_IPNETTABLE) +
662 (numEntries - 1) * sizeof(MIB_IPNETROW));
663 if (ret) {
664 FILE *fp;
666 /* get from /proc/net/arp, no error if can't */
667 fp = fopen("/proc/net/arp", "r");
668 if (fp) {
669 char buf[512] = { 0 }, *ptr;
671 /* skip header line */
672 ptr = fgets(buf, sizeof(buf), fp);
673 while (ptr && ret->dwNumEntries < numEntries) {
674 ptr = fgets(buf, sizeof(buf), fp);
675 if (ptr) {
676 char *endPtr;
678 ret->table[ret->dwNumEntries].dwAddr = inet_addr(ptr);
679 while (ptr && *ptr && !isspace(*ptr))
680 ptr++;
682 if (ptr && *ptr) {
683 strtoul(ptr, &endPtr, 16); /* hw type (skip) */
684 ptr = endPtr;
686 if (ptr && *ptr) {
687 DWORD flags = strtoul(ptr, &endPtr, 16);
689 if (flags & ATF_COM)
690 ret->table[ret->dwNumEntries].dwType = MIB_IPNET_TYPE_DYNAMIC;
691 else if (flags & ATF_PERM)
692 ret->table[ret->dwNumEntries].dwType = MIB_IPNET_TYPE_STATIC;
693 else
694 ret->table[ret->dwNumEntries].dwType = MIB_IPNET_TYPE_OTHER;
696 ptr = endPtr;
698 while (ptr && *ptr && isspace(*ptr))
699 ptr++;
700 while (ptr && *ptr && !isspace(*ptr)) {
701 DWORD byte = strtoul(ptr, &endPtr, 16);
703 if (endPtr && *endPtr) {
704 endPtr++;
705 ret->table[ret->dwNumEntries].bPhysAddr[
706 ret->table[ret->dwNumEntries].dwPhysAddrLen++] = byte & 0x0ff;
708 ptr = endPtr;
710 if (ptr && *ptr) {
711 strtoul(ptr, &endPtr, 16); /* mask (skip) */
712 ptr = endPtr;
714 getInterfaceIndexByName(ptr, &ret->table[ret->dwNumEntries].dwIndex);
715 ret->dwNumEntries++;
718 fclose(fp);
721 return ret;
724 DWORD getNumUdpEntries(void)
726 return getNumWithOneHeader("/proc/net/udp");
729 PMIB_UDPTABLE getUdpTable(void)
731 DWORD numEntries = getNumUdpEntries();
732 PMIB_UDPTABLE ret;
734 ret = (PMIB_UDPTABLE)calloc(1, sizeof(MIB_UDPTABLE) +
735 (numEntries - 1) * sizeof(MIB_UDPROW));
736 if (ret) {
737 FILE *fp;
739 /* get from /proc/net/udp, no error if can't */
740 fp = fopen("/proc/net/udp", "r");
741 if (fp) {
742 char buf[512] = { 0 }, *ptr;
744 /* skip header line */
745 ptr = fgets(buf, sizeof(buf), fp);
746 while (ptr && ret->dwNumEntries < numEntries) {
747 ptr = fgets(buf, sizeof(buf), fp);
748 if (ptr) {
749 char *endPtr;
751 if (ptr && *ptr) {
752 strtoul(ptr, &endPtr, 16); /* skip */
753 ptr = endPtr;
755 if (ptr && *ptr) {
756 ptr++;
757 ret->table[ret->dwNumEntries].dwLocalAddr = strtoul(ptr, &endPtr,
758 16);
759 ptr = endPtr;
761 if (ptr && *ptr) {
762 ptr++;
763 ret->table[ret->dwNumEntries].dwLocalPort = strtoul(ptr, &endPtr,
764 16);
765 ptr = endPtr;
767 ret->dwNumEntries++;
770 fclose(fp);
773 return ret;
776 DWORD getNumTcpEntries(void)
778 return getNumWithOneHeader("/proc/net/tcp");
781 PMIB_TCPTABLE getTcpTable(void)
783 DWORD numEntries = getNumTcpEntries();
784 PMIB_TCPTABLE ret;
786 ret = (PMIB_TCPTABLE)calloc(1, sizeof(MIB_TCPTABLE) +
787 (numEntries - 1) * sizeof(MIB_TCPROW));
788 if (ret) {
789 FILE *fp;
791 /* get from /proc/net/tcp, no error if can't */
792 fp = fopen("/proc/net/tcp", "r");
793 if (fp) {
794 char buf[512] = { 0 }, *ptr;
796 /* skip header line */
797 ptr = fgets(buf, sizeof(buf), fp);
798 while (ptr && ret->dwNumEntries < numEntries) {
799 ptr = fgets(buf, sizeof(buf), fp);
800 if (ptr) {
801 char *endPtr;
803 while (ptr && *ptr && *ptr != ':')
804 ptr++;
805 if (ptr && *ptr)
806 ptr++;
807 if (ptr && *ptr) {
808 ret->table[ret->dwNumEntries].dwLocalAddr = strtoul(ptr, &endPtr,
809 16);
810 ptr = endPtr;
812 if (ptr && *ptr) {
813 ptr++;
814 ret->table[ret->dwNumEntries].dwLocalPort = strtoul(ptr, &endPtr,
815 16);
816 ptr = endPtr;
818 if (ptr && *ptr) {
819 ret->table[ret->dwNumEntries].dwRemoteAddr = strtoul(ptr, &endPtr,
820 16);
821 ptr = endPtr;
823 if (ptr && *ptr) {
824 ptr++;
825 ret->table[ret->dwNumEntries].dwRemotePort = strtoul(ptr, &endPtr,
826 16);
827 ptr = endPtr;
829 if (ptr && *ptr) {
830 DWORD state = strtoul(ptr, &endPtr, 16);
832 switch (state)
834 case TCPS_ESTABLISHED:
835 ret->table[ret->dwNumEntries].dwState = MIB_TCP_STATE_ESTAB;
836 break;
837 case TCPS_SYN_SENT:
838 ret->table[ret->dwNumEntries].dwState = MIB_TCP_STATE_SYN_SENT;
839 break;
840 case TCPS_SYN_RECEIVED:
841 ret->table[ret->dwNumEntries].dwState = MIB_TCP_STATE_SYN_RCVD;
842 break;
843 case TCPS_FIN_WAIT_1:
844 ret->table[ret->dwNumEntries].dwState = MIB_TCP_STATE_FIN_WAIT1;
845 break;
846 case TCPS_FIN_WAIT_2:
847 ret->table[ret->dwNumEntries].dwState = MIB_TCP_STATE_FIN_WAIT2;
848 break;
849 case TCPS_TIME_WAIT:
850 ret->table[ret->dwNumEntries].dwState = MIB_TCP_STATE_TIME_WAIT;
851 break;
852 case TCPS_CLOSED:
853 ret->table[ret->dwNumEntries].dwState = MIB_TCP_STATE_CLOSED;
854 break;
855 case TCPS_CLOSE_WAIT:
856 ret->table[ret->dwNumEntries].dwState =
857 MIB_TCP_STATE_CLOSE_WAIT;
858 break;
859 case TCPS_LAST_ACK:
860 ret->table[ret->dwNumEntries].dwState = MIB_TCP_STATE_LAST_ACK;
861 break;
862 case TCPS_LISTEN:
863 ret->table[ret->dwNumEntries].dwState = MIB_TCP_STATE_LISTEN;
864 break;
865 case TCPS_CLOSING:
866 ret->table[ret->dwNumEntries].dwState = MIB_TCP_STATE_CLOSING;
867 break;
869 ptr = endPtr;
871 ret->dwNumEntries++;
874 fclose(fp);
877 return ret;