mshtml: Added DIID_DispHTMLDocument to QueryInterface.
[wine/testsucceed.git] / dlls / iphlpapi / ipstats.c
blobb80cf61133276fd4d2cba1ff41d8a1ab3aec5ebb
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"
23 #include "wine/debug.h"
25 #include <stdarg.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <sys/types.h>
30 #ifdef HAVE_SYS_SOCKET_H
31 #include <sys/socket.h>
32 #endif
33 #ifdef HAVE_NETINET_IN_H
34 #include <netinet/in.h>
35 #endif
36 #ifdef HAVE_ARPA_INET_H
37 #include <arpa/inet.h>
38 #endif
39 #ifdef HAVE_NET_IF_H
40 #include <net/if.h>
41 #endif
42 #ifdef HAVE_NET_ROUTE_H
43 #include <net/route.h>
44 #endif
45 #ifdef HAVE_NET_IF_ARP_H
46 #include <net/if_arp.h>
47 #endif
48 #ifdef HAVE_NETINET_TCP_H
49 #include <netinet/tcp.h>
50 #endif
51 #ifdef HAVE_NETINET_TCP_FSM_H
52 #include <netinet/tcp_fsm.h>
53 #endif
55 #ifdef HAVE_SYS_SYSCTL_H
56 #include <sys/sysctl.h>
57 #endif
59 #define ROUNDUP(a) \
60 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
61 #define ADVANCE(x, n) (x += ROUNDUP(((struct sockaddr *)n)->sa_len))
63 #include "windef.h"
64 #include "winbase.h"
65 #include "iprtrmib.h"
66 #include "ifenum.h"
67 #include "ipstats.h"
69 #ifdef linux
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
76 #define TCPS_CLOSED 7
77 #define TCPS_CLOSE_WAIT 8
78 #define TCPS_LAST_ACK 9
79 #define TCPS_LISTEN 10
80 #define TCPS_CLOSING 11
81 #endif
83 WINE_DEFAULT_DEBUG_CHANNEL(iphlpapi);
85 DWORD getInterfaceStatsByName(const char *name, PMIB_IFROW entry)
87 FILE *fp;
89 if (!name)
90 return ERROR_INVALID_PARAMETER;
91 if (!entry)
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");
97 if (fp) {
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))
105 ptr++;
106 if (strncasecmp(ptr, name, nameLen) == 0 && *(ptr + nameLen) == ':')
107 nameFound = 1;
108 else
109 ptr = fgets(buf, sizeof(buf), fp);
111 if (nameFound) {
112 char *endPtr;
114 ptr += nameLen + 1;
115 if (ptr && *ptr) {
116 entry->dwInOctets = strtoul(ptr, &endPtr, 10);
117 ptr = endPtr;
119 if (ptr && *ptr) {
120 entry->dwInUcastPkts = strtoul(ptr, &endPtr, 10);
121 ptr = endPtr;
123 if (ptr && *ptr) {
124 entry->dwInErrors = strtoul(ptr, &endPtr, 10);
125 ptr = endPtr;
127 if (ptr && *ptr) {
128 entry->dwInDiscards = strtoul(ptr, &endPtr, 10);
129 ptr = endPtr;
131 if (ptr && *ptr) {
132 strtoul(ptr, &endPtr, 10); /* skip */
133 ptr = endPtr;
135 if (ptr && *ptr) {
136 strtoul(ptr, &endPtr, 10); /* skip */
137 ptr = endPtr;
139 if (ptr && *ptr) {
140 strtoul(ptr, &endPtr, 10); /* skip */
141 ptr = endPtr;
143 if (ptr && *ptr) {
144 entry->dwInNUcastPkts = strtoul(ptr, &endPtr, 10);
145 ptr = endPtr;
147 if (ptr && *ptr) {
148 entry->dwOutOctets = strtoul(ptr, &endPtr, 10);
149 ptr = endPtr;
151 if (ptr && *ptr) {
152 entry->dwOutUcastPkts = strtoul(ptr, &endPtr, 10);
153 ptr = endPtr;
155 if (ptr && *ptr) {
156 entry->dwOutErrors = strtoul(ptr, &endPtr, 10);
157 ptr = endPtr;
159 if (ptr && *ptr) {
160 entry->dwOutDiscards = strtoul(ptr, &endPtr, 10);
161 ptr = endPtr;
164 fclose(fp);
166 else
167 ERR ("unimplemented!\n");
169 return NO_ERROR;
172 DWORD getICMPStats(MIB_ICMP *stats)
174 FILE *fp;
176 if (!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");
182 if (fp) {
183 static const char hdr[] = "Icmp:";
184 char buf[512] = { 0 }, *ptr;
186 do {
187 ptr = fgets(buf, sizeof(buf), fp);
188 } while (ptr && strncasecmp(buf, hdr, sizeof(hdr) - 1));
189 if (ptr) {
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) {
193 char *endPtr;
195 ptr += sizeof(hdr);
196 if (ptr && *ptr) {
197 stats->stats.icmpInStats.dwMsgs = strtoul(ptr, &endPtr, 10);
198 ptr = endPtr;
200 if (ptr && *ptr) {
201 stats->stats.icmpInStats.dwErrors = strtoul(ptr, &endPtr, 10);
202 ptr = endPtr;
204 if (ptr && *ptr) {
205 stats->stats.icmpInStats.dwDestUnreachs = strtoul(ptr, &endPtr, 10);
206 ptr = endPtr;
208 if (ptr && *ptr) {
209 stats->stats.icmpInStats.dwTimeExcds = strtoul(ptr, &endPtr, 10);
210 ptr = endPtr;
212 if (ptr && *ptr) {
213 stats->stats.icmpInStats.dwParmProbs = strtoul(ptr, &endPtr, 10);
214 ptr = endPtr;
216 if (ptr && *ptr) {
217 stats->stats.icmpInStats.dwSrcQuenchs = strtoul(ptr, &endPtr, 10);
218 ptr = endPtr;
220 if (ptr && *ptr) {
221 stats->stats.icmpInStats.dwRedirects = strtoul(ptr, &endPtr, 10);
222 ptr = endPtr;
224 if (ptr && *ptr) {
225 stats->stats.icmpInStats.dwEchoReps = strtoul(ptr, &endPtr, 10);
226 ptr = endPtr;
228 if (ptr && *ptr) {
229 stats->stats.icmpInStats.dwTimestamps = strtoul(ptr, &endPtr, 10);
230 ptr = endPtr;
232 if (ptr && *ptr) {
233 stats->stats.icmpInStats.dwTimestampReps = strtoul(ptr, &endPtr, 10);
234 ptr = endPtr;
236 if (ptr && *ptr) {
237 stats->stats.icmpInStats.dwAddrMasks = strtoul(ptr, &endPtr, 10);
238 ptr = endPtr;
240 if (ptr && *ptr) {
241 stats->stats.icmpInStats.dwAddrMaskReps = strtoul(ptr, &endPtr, 10);
242 ptr = endPtr;
244 if (ptr && *ptr) {
245 stats->stats.icmpOutStats.dwMsgs = strtoul(ptr, &endPtr, 10);
246 ptr = endPtr;
248 if (ptr && *ptr) {
249 stats->stats.icmpOutStats.dwErrors = strtoul(ptr, &endPtr, 10);
250 ptr = endPtr;
252 if (ptr && *ptr) {
253 stats->stats.icmpOutStats.dwDestUnreachs = strtoul(ptr, &endPtr, 10);
254 ptr = endPtr;
256 if (ptr && *ptr) {
257 stats->stats.icmpOutStats.dwTimeExcds = strtoul(ptr, &endPtr, 10);
258 ptr = endPtr;
260 if (ptr && *ptr) {
261 stats->stats.icmpOutStats.dwParmProbs = strtoul(ptr, &endPtr, 10);
262 ptr = endPtr;
264 if (ptr && *ptr) {
265 stats->stats.icmpOutStats.dwSrcQuenchs = strtoul(ptr, &endPtr, 10);
266 ptr = endPtr;
268 if (ptr && *ptr) {
269 stats->stats.icmpOutStats.dwRedirects = strtoul(ptr, &endPtr, 10);
270 ptr = endPtr;
272 if (ptr && *ptr) {
273 stats->stats.icmpOutStats.dwEchoReps = strtoul(ptr, &endPtr, 10);
274 ptr = endPtr;
276 if (ptr && *ptr) {
277 stats->stats.icmpOutStats.dwTimestamps = strtoul(ptr, &endPtr, 10);
278 ptr = endPtr;
280 if (ptr && *ptr) {
281 stats->stats.icmpOutStats.dwTimestampReps = strtoul(ptr, &endPtr, 10);
282 ptr = endPtr;
284 if (ptr && *ptr) {
285 stats->stats.icmpOutStats.dwAddrMasks = strtoul(ptr, &endPtr, 10);
286 ptr = endPtr;
288 if (ptr && *ptr) {
289 stats->stats.icmpOutStats.dwAddrMaskReps = strtoul(ptr, &endPtr, 10);
290 ptr = endPtr;
294 fclose(fp);
296 else
297 ERR ("unimplemented!\n");
299 return NO_ERROR;
302 DWORD getIPStats(PMIB_IPSTATS stats)
304 FILE *fp;
306 if (!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");
315 if (fp) {
316 static const char hdr[] = "Ip:";
317 char buf[512] = { 0 }, *ptr;
319 do {
320 ptr = fgets(buf, sizeof(buf), fp);
321 } while (ptr && strncasecmp(buf, hdr, sizeof(hdr) - 1));
322 if (ptr) {
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) {
326 char *endPtr;
328 ptr += sizeof(hdr);
329 if (ptr && *ptr) {
330 stats->dwForwarding = strtoul(ptr, &endPtr, 10);
331 ptr = endPtr;
333 if (ptr && *ptr) {
334 stats->dwDefaultTTL = strtoul(ptr, &endPtr, 10);
335 ptr = endPtr;
337 if (ptr && *ptr) {
338 stats->dwInReceives = strtoul(ptr, &endPtr, 10);
339 ptr = endPtr;
341 if (ptr && *ptr) {
342 stats->dwInHdrErrors = strtoul(ptr, &endPtr, 10);
343 ptr = endPtr;
345 if (ptr && *ptr) {
346 stats->dwInAddrErrors = strtoul(ptr, &endPtr, 10);
347 ptr = endPtr;
349 if (ptr && *ptr) {
350 stats->dwForwDatagrams = strtoul(ptr, &endPtr, 10);
351 ptr = endPtr;
353 if (ptr && *ptr) {
354 stats->dwInUnknownProtos = strtoul(ptr, &endPtr, 10);
355 ptr = endPtr;
357 if (ptr && *ptr) {
358 stats->dwInDiscards = strtoul(ptr, &endPtr, 10);
359 ptr = endPtr;
361 if (ptr && *ptr) {
362 stats->dwInDelivers = strtoul(ptr, &endPtr, 10);
363 ptr = endPtr;
365 if (ptr && *ptr) {
366 stats->dwOutRequests = strtoul(ptr, &endPtr, 10);
367 ptr = endPtr;
369 if (ptr && *ptr) {
370 stats->dwOutDiscards = strtoul(ptr, &endPtr, 10);
371 ptr = endPtr;
373 if (ptr && *ptr) {
374 stats->dwOutNoRoutes = strtoul(ptr, &endPtr, 10);
375 ptr = endPtr;
377 if (ptr && *ptr) {
378 stats->dwReasmTimeout = strtoul(ptr, &endPtr, 10);
379 ptr = endPtr;
381 if (ptr && *ptr) {
382 stats->dwReasmReqds = strtoul(ptr, &endPtr, 10);
383 ptr = endPtr;
385 if (ptr && *ptr) {
386 stats->dwReasmOks = strtoul(ptr, &endPtr, 10);
387 ptr = endPtr;
389 if (ptr && *ptr) {
390 stats->dwReasmFails = strtoul(ptr, &endPtr, 10);
391 ptr = endPtr;
393 if (ptr && *ptr) {
394 stats->dwFragOks = strtoul(ptr, &endPtr, 10);
395 ptr = endPtr;
397 if (ptr && *ptr) {
398 stats->dwFragFails = strtoul(ptr, &endPtr, 10);
399 ptr = endPtr;
401 if (ptr && *ptr) {
402 stats->dwFragCreates = strtoul(ptr, &endPtr, 10);
403 ptr = endPtr;
405 /* hmm, no routingDiscards */
408 fclose(fp);
410 else
411 ERR ("unimplemented!\n");
413 return NO_ERROR;
416 DWORD getTCPStats(MIB_TCPSTATS *stats)
418 FILE *fp;
420 if (!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");
427 if (fp) {
428 static const char hdr[] = "Tcp:";
429 char buf[512] = { 0 }, *ptr;
432 do {
433 ptr = fgets(buf, sizeof(buf), fp);
434 } while (ptr && strncasecmp(buf, hdr, sizeof(hdr) - 1));
435 if (ptr) {
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) {
439 char *endPtr;
441 ptr += sizeof(hdr);
442 if (ptr && *ptr) {
443 stats->dwRtoAlgorithm = 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->dwRtoMin = strtoul(ptr, &endPtr, 10);
452 ptr = endPtr;
454 if (ptr && *ptr) {
455 stats->dwMaxConn = strtoul(ptr, &endPtr, 10);
456 ptr = endPtr;
458 if (ptr && *ptr) {
459 stats->dwActiveOpens = strtoul(ptr, &endPtr, 10);
460 ptr = endPtr;
462 if (ptr && *ptr) {
463 stats->dwPassiveOpens = strtoul(ptr, &endPtr, 10);
464 ptr = endPtr;
466 if (ptr && *ptr) {
467 stats->dwAttemptFails = strtoul(ptr, &endPtr, 10);
468 ptr = endPtr;
470 if (ptr && *ptr) {
471 stats->dwEstabResets = strtoul(ptr, &endPtr, 10);
472 ptr = endPtr;
474 if (ptr && *ptr) {
475 stats->dwCurrEstab = strtoul(ptr, &endPtr, 10);
476 ptr = endPtr;
478 if (ptr && *ptr) {
479 stats->dwInSegs = strtoul(ptr, &endPtr, 10);
480 ptr = endPtr;
482 if (ptr && *ptr) {
483 stats->dwOutSegs = strtoul(ptr, &endPtr, 10);
484 ptr = endPtr;
486 if (ptr && *ptr) {
487 stats->dwRetransSegs = strtoul(ptr, &endPtr, 10);
488 ptr = endPtr;
490 if (ptr && *ptr) {
491 stats->dwInErrs = strtoul(ptr, &endPtr, 10);
492 ptr = endPtr;
494 if (ptr && *ptr) {
495 stats->dwOutRsts = strtoul(ptr, &endPtr, 10);
496 ptr = endPtr;
498 stats->dwNumConns = getNumTcpEntries();
501 fclose(fp);
503 else
504 ERR ("unimplemented!\n");
506 return NO_ERROR;
509 DWORD getUDPStats(MIB_UDPSTATS *stats)
511 FILE *fp;
513 if (!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");
520 if (fp) {
521 static const char hdr[] = "Udp:";
522 char buf[512] = { 0 }, *ptr;
525 do {
526 ptr = fgets(buf, sizeof(buf), fp);
527 } while (ptr && strncasecmp(buf, hdr, sizeof(hdr) - 1));
528 if (ptr) {
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) {
532 char *endPtr;
534 ptr += sizeof(hdr);
535 if (ptr && *ptr) {
536 stats->dwInDatagrams = strtoul(ptr, &endPtr, 10);
537 ptr = endPtr;
539 if (ptr && *ptr) {
540 stats->dwNoPorts = strtoul(ptr, &endPtr, 10);
541 ptr = endPtr;
543 if (ptr && *ptr) {
544 stats->dwInErrors = strtoul(ptr, &endPtr, 10);
545 ptr = endPtr;
547 if (ptr && *ptr) {
548 stats->dwOutDatagrams = strtoul(ptr, &endPtr, 10);
549 ptr = endPtr;
551 if (ptr && *ptr) {
552 stats->dwNumAddrs = strtoul(ptr, &endPtr, 10);
553 ptr = endPtr;
557 fclose(fp);
559 else
560 ERR ("unimplemented!\n");
562 return NO_ERROR;
565 static DWORD getNumWithOneHeader(const char *filename)
567 FILE *fp;
568 int ret = 0;
570 fp = fopen(filename, "r");
571 if (fp) {
572 char buf[512] = { 0 }, *ptr;
575 ptr = fgets(buf, sizeof(buf), fp);
576 if (ptr) {
577 do {
578 ptr = fgets(buf, sizeof(buf), fp);
579 if (ptr)
580 ret++;
581 } while (ptr);
583 fclose(fp);
585 else
586 ERR ("Unable to open '%s' to count entries!\n", filename);
588 return ret;
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};
595 size_t needed;
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");
603 return 0;
606 buf = HeapAlloc (GetProcessHeap (), 0, needed);
607 if (!buf) return 0;
609 if (sysctl (mib, 6, buf, &needed, NULL, 0) < 0)
611 ERR ("sysctl 2 failed!\n");
612 HeapFree (GetProcessHeap (), 0, buf);
613 return 0;
616 lim = buf + needed;
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",
624 rtm->rtm_type);
625 continue;
628 /* Ignore all entries except for gateway routes which aren't
629 multicast */
630 if (!(rtm->rtm_flags & RTF_GATEWAY) || (rtm->rtm_flags & RTF_MULTICAST))
631 continue;
633 RouteCount++;
636 HeapFree (GetProcessHeap (), 0, buf);
637 return RouteCount;
638 #else
639 return getNumWithOneHeader("/proc/net/route");
640 #endif
643 DWORD getRouteTable(PMIB_IPFORWARDTABLE *ppIpForwardTable, HANDLE heap,
644 DWORD flags)
646 DWORD ret;
648 if (!ppIpForwardTable)
649 ret = ERROR_INVALID_PARAMETER;
650 else {
651 DWORD numRoutes = getNumRoutes();
652 PMIB_IPFORWARDTABLE table = HeapAlloc(heap, flags,
653 sizeof(MIB_IPFORWARDTABLE) + (numRoutes - 1) * sizeof(MIB_IPFORWARDROW));
655 if (table) {
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};
658 size_t needed;
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);
666 return NO_ERROR;
669 buf = HeapAlloc (GetProcessHeap (), 0, needed);
670 if (!buf)
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);
681 return NO_ERROR;
684 *ppIpForwardTable = table;
685 table->dwNumEntries = 0;
687 lim = buf + needed;
688 for (next = buf; next < lim; next += rtm->rtm_msglen)
690 int i;
692 rtm = (struct rt_msghdr *)next;
694 if (rtm->rtm_type != RTM_GET)
696 WARN ("Got unexpected message type 0x%x!\n",
697 rtm->rtm_type);
698 continue;
701 /* Ignore all entries except for gateway routes which aren't
702 multicast */
703 if (!(rtm->rtm_flags & RTF_GATEWAY) ||
704 (rtm->rtm_flags & RTF_MULTICAST))
705 continue;
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 =
715 MIB_IPPROTO_LOCAL;
717 addrPtr = (char *)(rtm + 1);
719 for (i = 1; i; i <<= 1)
721 struct sockaddr *sa;
722 DWORD addr;
724 if (!(i & rtm->rtm_addrs))
725 continue;
727 sa = (struct sockaddr *)addrPtr;
728 ADVANCE (addrPtr, sa);
730 /* default routes are encoded by length-zero sockaddr */
731 if (sa->sa_len == 0)
732 addr = 0;
733 else if (sa->sa_family != AF_INET)
735 ERR ("Received unsupported sockaddr family 0x%x\n",
736 sa->sa_family);
737 addr = 0;
739 else
741 struct sockaddr_in *sin = (struct sockaddr_in *)sa;
743 addr = sin->sin_addr.s_addr;
746 switch (i)
748 case RTA_DST:
749 table->table[table->dwNumEntries].dwForwardDest = addr;
750 break;
752 case RTA_GATEWAY:
753 table->table[table->dwNumEntries].dwForwardNextHop = addr;
754 break;
756 case RTA_NETMASK:
757 table->table[table->dwNumEntries].dwForwardMask = addr;
758 break;
760 default:
761 ERR ("Unexpected address type 0x%x\n", i);
765 table->dwNumEntries++;
768 HeapFree (GetProcessHeap (), 0, buf);
769 ret = NO_ERROR;
770 #else
771 FILE *fp;
773 ret = NO_ERROR;
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");
778 if (fp) {
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);
787 if (ptr) {
788 DWORD index;
790 while (!isspace(*ptr))
791 ptr++;
792 *ptr = '\0';
793 ptr++;
794 if (getInterfaceIndexByName(buf, &index) == NO_ERROR) {
795 char *endPtr;
797 table->table[table->dwNumEntries].dwForwardIfIndex = index;
798 if (*ptr) {
799 table->table[table->dwNumEntries].dwForwardDest =
800 strtoul(ptr, &endPtr, 16);
801 ptr = endPtr;
803 if (ptr && *ptr) {
804 table->table[table->dwNumEntries].dwForwardNextHop =
805 strtoul(ptr, &endPtr, 16);
806 ptr = endPtr;
808 if (ptr && *ptr) {
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;
817 else
818 table->table[table->dwNumEntries].dwForwardType =
819 MIB_IPROUTE_TYPE_DIRECT;
820 ptr = endPtr;
822 if (ptr && *ptr) {
823 strtoul(ptr, &endPtr, 16); /* refcount, skip */
824 ptr = endPtr;
826 if (ptr && *ptr) {
827 strtoul(ptr, &endPtr, 16); /* use, skip */
828 ptr = endPtr;
830 if (ptr && *ptr) {
831 table->table[table->dwNumEntries].dwForwardMetric1 =
832 strtoul(ptr, &endPtr, 16);
833 ptr = endPtr;
835 if (ptr && *ptr) {
836 table->table[table->dwNumEntries].dwForwardMask =
837 strtoul(ptr, &endPtr, 16);
838 ptr = endPtr;
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 =
843 MIB_IPPROTO_LOCAL;
844 table->dwNumEntries++;
848 fclose(fp);
850 else
852 ERR ("unimplemented!\n");
853 return ERROR_INVALID_PARAMETER;
855 #endif
857 else
858 ret = ERROR_OUTOFMEMORY;
860 return ret;
863 DWORD getNumArpEntries(void)
865 return getNumWithOneHeader("/proc/net/arp");
868 DWORD getArpTable(PMIB_IPNETTABLE *ppIpNetTable, HANDLE heap, DWORD flags)
870 DWORD ret;
872 #if defined(HAVE_SYS_SYSCTL_H) && defined(NET_RT_DUMP)
873 ERR ("unimplemented!\n");
874 return ERROR_INVALID_PARAMETER;
875 #endif
877 if (!ppIpNetTable)
878 ret = ERROR_INVALID_PARAMETER;
879 else {
880 DWORD numEntries = getNumArpEntries();
881 PMIB_IPNETTABLE table = HeapAlloc(heap, flags,
882 sizeof(MIB_IPNETTABLE) + (numEntries - 1) * sizeof(MIB_IPNETROW));
884 if (table) {
885 FILE *fp;
887 ret = NO_ERROR;
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");
892 if (fp) {
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);
899 if (ptr) {
900 char *endPtr;
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))
905 ptr++;
907 if (ptr && *ptr) {
908 strtoul(ptr, &endPtr, 16); /* hw type (skip) */
909 ptr = endPtr;
911 if (ptr && *ptr) {
912 DWORD flags = strtoul(ptr, &endPtr, 16);
914 #ifdef ATF_COM
915 if (flags & ATF_COM)
916 table->table[table->dwNumEntries].dwType =
917 MIB_IPNET_TYPE_DYNAMIC;
918 else
919 #endif
920 #ifdef ATF_PERM
921 if (flags & ATF_PERM)
922 table->table[table->dwNumEntries].dwType =
923 MIB_IPNET_TYPE_STATIC;
924 else
925 #endif
926 table->table[table->dwNumEntries].dwType = MIB_IPNET_TYPE_OTHER;
928 ptr = endPtr;
930 while (ptr && *ptr && isspace(*ptr))
931 ptr++;
932 while (ptr && *ptr && !isspace(*ptr)) {
933 DWORD byte = strtoul(ptr, &endPtr, 16);
935 if (endPtr && *endPtr) {
936 endPtr++;
937 table->table[table->dwNumEntries].bPhysAddr[
938 table->table[table->dwNumEntries].dwPhysAddrLen++] =
939 byte & 0x0ff;
941 ptr = endPtr;
943 if (ptr && *ptr) {
944 strtoul(ptr, &endPtr, 16); /* mask (skip) */
945 ptr = endPtr;
947 getInterfaceIndexByName(ptr,
948 &table->table[table->dwNumEntries].dwIndex);
949 table->dwNumEntries++;
952 fclose(fp);
955 else
956 ret = ERROR_OUTOFMEMORY;
958 return ret;
961 DWORD getNumUdpEntries(void)
963 return getNumWithOneHeader("/proc/net/udp");
966 DWORD getUdpTable(PMIB_UDPTABLE *ppUdpTable, HANDLE heap, DWORD flags)
968 DWORD ret;
970 #if defined(HAVE_SYS_SYSCTL_H) && defined(NET_RT_DUMP)
971 ERR ("unimplemented!\n");
972 return ERROR_INVALID_PARAMETER;
973 #endif
975 if (!ppUdpTable)
976 ret = ERROR_INVALID_PARAMETER;
977 else {
978 DWORD numEntries = getNumUdpEntries();
979 PMIB_UDPTABLE table = HeapAlloc(heap, flags,
980 sizeof(MIB_UDPTABLE) + (numEntries - 1) * sizeof(MIB_UDPROW));
982 if (table) {
983 FILE *fp;
985 ret = NO_ERROR;
986 *ppUdpTable = table;
987 table->dwNumEntries = 0;
988 /* get from /proc/net/udp, no error if can't */
989 fp = fopen("/proc/net/udp", "r");
990 if (fp) {
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);
998 if (ptr) {
999 char *endPtr;
1001 if (ptr && *ptr) {
1002 strtoul(ptr, &endPtr, 16); /* skip */
1003 ptr = endPtr;
1005 if (ptr && *ptr) {
1006 ptr++;
1007 table->table[table->dwNumEntries].dwLocalAddr = strtoul(ptr,
1008 &endPtr, 16);
1009 ptr = endPtr;
1011 if (ptr && *ptr) {
1012 ptr++;
1013 table->table[table->dwNumEntries].dwLocalPort = strtoul(ptr,
1014 &endPtr, 16);
1015 ptr = endPtr;
1017 table->dwNumEntries++;
1020 fclose(fp);
1023 else
1024 ret = ERROR_OUTOFMEMORY;
1026 return ret;
1029 DWORD getNumTcpEntries(void)
1031 return getNumWithOneHeader("/proc/net/tcp");
1034 DWORD getTcpTable(PMIB_TCPTABLE *ppTcpTable, HANDLE heap, DWORD flags)
1036 DWORD ret;
1038 #if defined(HAVE_SYS_SYSCTL_H) && defined(NET_RT_DUMP)
1039 ERR ("unimplemented!\n");
1040 return ERROR_INVALID_PARAMETER;
1041 #endif
1043 if (!ppTcpTable)
1044 ret = ERROR_INVALID_PARAMETER;
1045 else {
1046 DWORD numEntries = getNumTcpEntries();
1047 PMIB_TCPTABLE table = HeapAlloc(heap, flags,
1048 sizeof(MIB_TCPTABLE) + (numEntries - 1) * sizeof(MIB_TCPROW));
1050 if (table) {
1051 FILE *fp;
1053 ret = NO_ERROR;
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");
1058 if (fp) {
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);
1066 if (ptr) {
1067 char *endPtr;
1069 while (ptr && *ptr && *ptr != ':')
1070 ptr++;
1071 if (ptr && *ptr)
1072 ptr++;
1073 if (ptr && *ptr) {
1074 table->table[table->dwNumEntries].dwLocalAddr = strtoul(ptr,
1075 &endPtr, 16);
1076 ptr = endPtr;
1078 if (ptr && *ptr) {
1079 ptr++;
1080 table->table[table->dwNumEntries].dwLocalPort = strtoul(ptr,
1081 &endPtr, 16);
1082 ptr = endPtr;
1084 if (ptr && *ptr) {
1085 table->table[table->dwNumEntries].dwRemoteAddr = strtoul(ptr,
1086 &endPtr, 16);
1087 ptr = endPtr;
1089 if (ptr && *ptr) {
1090 ptr++;
1091 table->table[table->dwNumEntries].dwRemotePort = strtoul(ptr,
1092 &endPtr, 16);
1093 ptr = endPtr;
1095 if (ptr && *ptr) {
1096 DWORD state = strtoul(ptr, &endPtr, 16);
1098 switch (state)
1100 case TCPS_ESTABLISHED:
1101 table->table[table->dwNumEntries].dwState =
1102 MIB_TCP_STATE_ESTAB;
1103 break;
1104 case TCPS_SYN_SENT:
1105 table->table[table->dwNumEntries].dwState =
1106 MIB_TCP_STATE_SYN_SENT;
1107 break;
1108 case TCPS_SYN_RECEIVED:
1109 table->table[table->dwNumEntries].dwState =
1110 MIB_TCP_STATE_SYN_RCVD;
1111 break;
1112 case TCPS_FIN_WAIT_1:
1113 table->table[table->dwNumEntries].dwState =
1114 MIB_TCP_STATE_FIN_WAIT1;
1115 break;
1116 case TCPS_FIN_WAIT_2:
1117 table->table[table->dwNumEntries].dwState =
1118 MIB_TCP_STATE_FIN_WAIT2;
1119 break;
1120 case TCPS_TIME_WAIT:
1121 table->table[table->dwNumEntries].dwState =
1122 MIB_TCP_STATE_TIME_WAIT;
1123 break;
1124 case TCPS_CLOSED:
1125 table->table[table->dwNumEntries].dwState =
1126 MIB_TCP_STATE_CLOSED;
1127 break;
1128 case TCPS_CLOSE_WAIT:
1129 table->table[table->dwNumEntries].dwState =
1130 MIB_TCP_STATE_CLOSE_WAIT;
1131 break;
1132 case TCPS_LAST_ACK:
1133 table->table[table->dwNumEntries].dwState =
1134 MIB_TCP_STATE_LAST_ACK;
1135 break;
1136 case TCPS_LISTEN:
1137 table->table[table->dwNumEntries].dwState =
1138 MIB_TCP_STATE_LISTEN;
1139 break;
1140 case TCPS_CLOSING:
1141 table->table[table->dwNumEntries].dwState =
1142 MIB_TCP_STATE_CLOSING;
1143 break;
1145 ptr = endPtr;
1147 table->dwNumEntries++;
1150 fclose(fp);
1153 else
1154 ret = ERROR_OUTOFMEMORY;
1156 return ret;