Reserve extra space for conversions.
[wine] / dlls / iphlpapi / ipstats.c
1 /* Copyright (C) 2003 Juan Lang
2  *
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.
7  *
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.
12  *
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
16  *
17  * This file implements statistics getting using the /proc filesystem exported
18  * by Linux, and maybe other OSes.
19  */
20
21 #include "config.h"
22 #include "wine/port.h"
23
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_IF_ARP_H
42 #include <net/if_arp.h>
43 #endif
44 #ifdef HAVE_NETINET_TCP_H
45 #include <netinet/tcp.h>
46 #endif
47 #ifdef HAVE_NETINET_TCP_FSM_H
48 #include <netinet/tcp_fsm.h>
49 #endif
50
51 #include "windef.h"
52 #include "winbase.h"
53 #include "iprtrmib.h"
54 #include "ifenum.h"
55 #include "ipstats.h"
56
57 #ifdef linux
58 #define TCPS_ESTABLISHED  1
59 #define TCPS_SYN_SENT     2
60 #define TCPS_SYN_RECEIVED 3
61 #define TCPS_FIN_WAIT_1   4
62 #define TCPS_FIN_WAIT_2   5
63 #define TCPS_TIME_WAIT    6
64 #define TCPS_CLOSED       7
65 #define TCPS_CLOSE_WAIT   8
66 #define TCPS_LAST_ACK     9
67 #define TCPS_LISTEN      10
68 #define TCPS_CLOSING     11
69 #endif
70
71 DWORD getInterfaceStatsByName(const char *name, PMIB_IFROW entry)
72 {
73   FILE *fp;
74
75   if (!name)
76     return ERROR_INVALID_PARAMETER;
77   if (!entry)
78     return ERROR_INVALID_PARAMETER;
79
80   /* get interface stats from /proc/net/dev, no error if can't
81      no inUnknownProtos, outNUcastPkts, outQLen */
82   fp = fopen("/proc/net/dev", "r");
83   if (fp) {
84     char buf[512] = { 0 }, *ptr;
85     int nameLen = strlen(name), nameFound = 0;
86
87
88     ptr = fgets(buf, sizeof(buf), fp);
89     while (ptr && !nameFound) {
90       while (*ptr && isspace(*ptr))
91         ptr++;
92       if (strncasecmp(ptr, name, nameLen) == 0 && *(ptr + nameLen) == ':')
93         nameFound = 1;
94       else
95         ptr = fgets(buf, sizeof(buf), fp);
96     }
97     if (nameFound) {
98       char *endPtr;
99
100       ptr += nameLen + 1;
101       if (ptr && *ptr) {
102         entry->dwInOctets = strtoul(ptr, &endPtr, 10);
103         ptr = endPtr;
104       }
105       if (ptr && *ptr) {
106         entry->dwInUcastPkts = strtoul(ptr, &endPtr, 10);
107         ptr = endPtr;
108       }
109       if (ptr && *ptr) {
110         entry->dwInErrors = strtoul(ptr, &endPtr, 10);
111         ptr = endPtr;
112       }
113       if (ptr && *ptr) {
114         entry->dwInDiscards = strtoul(ptr, &endPtr, 10);
115         ptr = endPtr;
116       }
117       if (ptr && *ptr) {
118         strtoul(ptr, &endPtr, 10); /* skip */
119         ptr = endPtr;
120       }
121       if (ptr && *ptr) {
122         strtoul(ptr, &endPtr, 10); /* skip */
123         ptr = endPtr;
124       }
125       if (ptr && *ptr) {
126         strtoul(ptr, &endPtr, 10); /* skip */
127         ptr = endPtr;
128       }
129       if (ptr && *ptr) {
130         entry->dwInNUcastPkts = strtoul(ptr, &endPtr, 10);
131         ptr = endPtr;
132       }
133       if (ptr && *ptr) {
134         entry->dwOutOctets = strtoul(ptr, &endPtr, 10);
135         ptr = endPtr;
136       }
137       if (ptr && *ptr) {
138         entry->dwOutUcastPkts = strtoul(ptr, &endPtr, 10);
139         ptr = endPtr;
140       }
141       if (ptr && *ptr) {
142         entry->dwOutErrors = strtoul(ptr, &endPtr, 10);
143         ptr = endPtr;
144       }
145       if (ptr && *ptr) {
146         entry->dwOutDiscards = strtoul(ptr, &endPtr, 10);
147         ptr = endPtr;
148       }
149     }
150     fclose(fp);
151   }
152   return NO_ERROR;
153 }
154
155 DWORD getICMPStats(MIB_ICMP *stats)
156 {
157   FILE *fp;
158
159   if (!stats)
160     return ERROR_INVALID_PARAMETER;
161
162   memset(stats, 0, sizeof(MIB_ICMP));
163   /* get most of these stats from /proc/net/snmp, no error if can't */
164   fp = fopen("/proc/net/snmp", "r");
165   if (fp) {
166     static const char hdr[] = "Icmp:";
167     char buf[512] = { 0 }, *ptr;
168
169     do {
170       ptr = fgets(buf, sizeof(buf), fp);
171     } while (ptr && strncasecmp(buf, hdr, sizeof(hdr) - 1));
172     if (ptr) {
173       /* last line was a header, get another */
174       ptr = fgets(buf, sizeof(buf), fp);
175       if (ptr && strncasecmp(buf, hdr, sizeof(hdr) - 1) == 0) {
176         char *endPtr;
177
178         ptr += sizeof(hdr);
179         if (ptr && *ptr) {
180           stats->stats.icmpInStats.dwMsgs = strtoul(ptr, &endPtr, 10);
181           ptr = endPtr;
182         }
183         if (ptr && *ptr) {
184           stats->stats.icmpInStats.dwErrors = strtoul(ptr, &endPtr, 10);
185           ptr = endPtr;
186         }
187         if (ptr && *ptr) {
188           stats->stats.icmpInStats.dwDestUnreachs = strtoul(ptr, &endPtr, 10);
189           ptr = endPtr;
190         }
191         if (ptr && *ptr) {
192           stats->stats.icmpInStats.dwTimeExcds = strtoul(ptr, &endPtr, 10);
193           ptr = endPtr;
194         }
195         if (ptr && *ptr) {
196           stats->stats.icmpInStats.dwParmProbs = strtoul(ptr, &endPtr, 10);
197           ptr = endPtr;
198         }
199         if (ptr && *ptr) {
200           stats->stats.icmpInStats.dwSrcQuenchs = strtoul(ptr, &endPtr, 10);
201           ptr = endPtr;
202         }
203         if (ptr && *ptr) {
204           stats->stats.icmpInStats.dwRedirects = strtoul(ptr, &endPtr, 10);
205           ptr = endPtr;
206         }
207         if (ptr && *ptr) {
208           stats->stats.icmpInStats.dwEchoReps = strtoul(ptr, &endPtr, 10);
209           ptr = endPtr;
210         }
211         if (ptr && *ptr) {
212           stats->stats.icmpInStats.dwTimestamps = strtoul(ptr, &endPtr, 10);
213           ptr = endPtr;
214         }
215         if (ptr && *ptr) {
216           stats->stats.icmpInStats.dwTimestampReps = strtoul(ptr, &endPtr, 10);
217           ptr = endPtr;
218         }
219         if (ptr && *ptr) {
220           stats->stats.icmpInStats.dwAddrMasks = strtoul(ptr, &endPtr, 10);
221           ptr = endPtr;
222         }
223         if (ptr && *ptr) {
224           stats->stats.icmpInStats.dwAddrMaskReps = strtoul(ptr, &endPtr, 10);
225           ptr = endPtr;
226         }
227         if (ptr && *ptr) {
228           stats->stats.icmpOutStats.dwMsgs = strtoul(ptr, &endPtr, 10);
229           ptr = endPtr;
230         }
231         if (ptr && *ptr) {
232           stats->stats.icmpOutStats.dwErrors = strtoul(ptr, &endPtr, 10);
233           ptr = endPtr;
234         }
235         if (ptr && *ptr) {
236           stats->stats.icmpOutStats.dwDestUnreachs = strtoul(ptr, &endPtr, 10);
237           ptr = endPtr;
238         }
239         if (ptr && *ptr) {
240           stats->stats.icmpOutStats.dwTimeExcds = strtoul(ptr, &endPtr, 10);
241           ptr = endPtr;
242         }
243         if (ptr && *ptr) {
244           stats->stats.icmpOutStats.dwParmProbs = strtoul(ptr, &endPtr, 10);
245           ptr = endPtr;
246         }
247         if (ptr && *ptr) {
248           stats->stats.icmpOutStats.dwSrcQuenchs = strtoul(ptr, &endPtr, 10);
249           ptr = endPtr;
250         }
251         if (ptr && *ptr) {
252           stats->stats.icmpOutStats.dwRedirects = strtoul(ptr, &endPtr, 10);
253           ptr = endPtr;
254         }
255         if (ptr && *ptr) {
256           stats->stats.icmpOutStats.dwEchoReps = strtoul(ptr, &endPtr, 10);
257           ptr = endPtr;
258         }
259         if (ptr && *ptr) {
260           stats->stats.icmpOutStats.dwTimestamps = strtoul(ptr, &endPtr, 10);
261           ptr = endPtr;
262         }
263         if (ptr && *ptr) {
264           stats->stats.icmpOutStats.dwTimestampReps = strtoul(ptr, &endPtr, 10);
265           ptr = endPtr;
266         }
267         if (ptr && *ptr) {
268           stats->stats.icmpOutStats.dwAddrMasks = strtoul(ptr, &endPtr, 10);
269           ptr = endPtr;
270         }
271         if (ptr && *ptr) {
272           stats->stats.icmpOutStats.dwAddrMaskReps = strtoul(ptr, &endPtr, 10);
273           ptr = endPtr;
274         }
275       }
276     }
277     fclose(fp);
278   }
279   return NO_ERROR;
280 }
281
282 DWORD getIPStats(PMIB_IPSTATS stats)
283 {
284   FILE *fp;
285
286   if (!stats)
287     return ERROR_INVALID_PARAMETER;
288
289   memset(stats, 0, sizeof(MIB_IPSTATS));
290   stats->dwNumIf = stats->dwNumAddr = getNumInterfaces();
291   stats->dwNumRoutes = getNumRoutes();
292
293   /* get most of these stats from /proc/net/snmp, no error if can't */
294   fp = fopen("/proc/net/snmp", "r");
295   if (fp) {
296     static const char hdr[] = "Ip:";
297     char buf[512] = { 0 }, *ptr;
298
299     do {
300       ptr = fgets(buf, sizeof(buf), fp);
301     } while (ptr && strncasecmp(buf, hdr, sizeof(hdr) - 1));
302     if (ptr) {
303       /* last line was a header, get another */
304       ptr = fgets(buf, sizeof(buf), fp);
305       if (ptr && strncasecmp(buf, hdr, sizeof(hdr) - 1) == 0) {
306         char *endPtr;
307
308         ptr += sizeof(hdr);
309         if (ptr && *ptr) {
310           stats->dwForwarding = strtoul(ptr, &endPtr, 10);
311           ptr = endPtr;
312         }
313         if (ptr && *ptr) {
314           stats->dwDefaultTTL = strtoul(ptr, &endPtr, 10);
315           ptr = endPtr;
316         }
317         if (ptr && *ptr) {
318           stats->dwInReceives = strtoul(ptr, &endPtr, 10);
319           ptr = endPtr;
320         }
321         if (ptr && *ptr) {
322           stats->dwInHdrErrors = strtoul(ptr, &endPtr, 10);
323           ptr = endPtr;
324         }
325         if (ptr && *ptr) {
326           stats->dwInAddrErrors = strtoul(ptr, &endPtr, 10);
327           ptr = endPtr;
328         }
329         if (ptr && *ptr) {
330           stats->dwForwDatagrams = strtoul(ptr, &endPtr, 10);
331           ptr = endPtr;
332         }
333         if (ptr && *ptr) {
334           stats->dwInUnknownProtos = strtoul(ptr, &endPtr, 10);
335           ptr = endPtr;
336         }
337         if (ptr && *ptr) {
338           stats->dwInDiscards = strtoul(ptr, &endPtr, 10);
339           ptr = endPtr;
340         }
341         if (ptr && *ptr) {
342           stats->dwInDelivers = strtoul(ptr, &endPtr, 10);
343           ptr = endPtr;
344         }
345         if (ptr && *ptr) {
346           stats->dwOutRequests = strtoul(ptr, &endPtr, 10);
347           ptr = endPtr;
348         }
349         if (ptr && *ptr) {
350           stats->dwOutDiscards = strtoul(ptr, &endPtr, 10);
351           ptr = endPtr;
352         }
353         if (ptr && *ptr) {
354           stats->dwOutNoRoutes = strtoul(ptr, &endPtr, 10);
355           ptr = endPtr;
356         }
357         if (ptr && *ptr) {
358           stats->dwReasmTimeout = strtoul(ptr, &endPtr, 10);
359           ptr = endPtr;
360         }
361         if (ptr && *ptr) {
362           stats->dwReasmReqds = strtoul(ptr, &endPtr, 10);
363           ptr = endPtr;
364         }
365         if (ptr && *ptr) {
366           stats->dwReasmOks = strtoul(ptr, &endPtr, 10);
367           ptr = endPtr;
368         }
369         if (ptr && *ptr) {
370           stats->dwReasmFails = strtoul(ptr, &endPtr, 10);
371           ptr = endPtr;
372         }
373         if (ptr && *ptr) {
374           stats->dwFragOks = strtoul(ptr, &endPtr, 10);
375           ptr = endPtr;
376         }
377         if (ptr && *ptr) {
378           stats->dwFragFails = strtoul(ptr, &endPtr, 10);
379           ptr = endPtr;
380         }
381         if (ptr && *ptr) {
382           stats->dwFragCreates = strtoul(ptr, &endPtr, 10);
383           ptr = endPtr;
384         }
385         /* hmm, no routingDiscards */
386       }
387     }
388     fclose(fp);
389   }
390   return NO_ERROR;
391 }
392
393 DWORD getTCPStats(MIB_TCPSTATS *stats)
394 {
395   FILE *fp;
396
397   if (!stats)
398     return ERROR_INVALID_PARAMETER;
399
400   memset(stats, 0, sizeof(MIB_TCPSTATS));
401
402   /* get from /proc/net/snmp, no error if can't */
403   fp = fopen("/proc/net/snmp", "r");
404   if (fp) {
405     static const char hdr[] = "Tcp:";
406     char buf[512] = { 0 }, *ptr;
407
408
409     do {
410       ptr = fgets(buf, sizeof(buf), fp);
411     } while (ptr && strncasecmp(buf, hdr, sizeof(hdr) - 1));
412     if (ptr) {
413       /* last line was a header, get another */
414       ptr = fgets(buf, sizeof(buf), fp);
415       if (ptr && strncasecmp(buf, hdr, sizeof(hdr) - 1) == 0) {
416         char *endPtr;
417
418         ptr += sizeof(hdr);
419         if (ptr && *ptr) {
420           stats->dwRtoAlgorithm = strtoul(ptr, &endPtr, 10);
421           ptr = endPtr;
422         }
423         if (ptr && *ptr) {
424           stats->dwRtoMin = strtoul(ptr, &endPtr, 10);
425           ptr = endPtr;
426         }
427         if (ptr && *ptr) {
428           stats->dwRtoMin = strtoul(ptr, &endPtr, 10);
429           ptr = endPtr;
430         }
431         if (ptr && *ptr) {
432           stats->dwMaxConn = strtoul(ptr, &endPtr, 10);
433           ptr = endPtr;
434         }
435         if (ptr && *ptr) {
436           stats->dwActiveOpens = strtoul(ptr, &endPtr, 10);
437           ptr = endPtr;
438         }
439         if (ptr && *ptr) {
440           stats->dwPassiveOpens = strtoul(ptr, &endPtr, 10);
441           ptr = endPtr;
442         }
443         if (ptr && *ptr) {
444           stats->dwAttemptFails = strtoul(ptr, &endPtr, 10);
445           ptr = endPtr;
446         }
447         if (ptr && *ptr) {
448           stats->dwEstabResets = strtoul(ptr, &endPtr, 10);
449           ptr = endPtr;
450         }
451         if (ptr && *ptr) {
452           stats->dwCurrEstab = strtoul(ptr, &endPtr, 10);
453           ptr = endPtr;
454         }
455         if (ptr && *ptr) {
456           stats->dwInSegs = strtoul(ptr, &endPtr, 10);
457           ptr = endPtr;
458         }
459         if (ptr && *ptr) {
460           stats->dwOutSegs = strtoul(ptr, &endPtr, 10);
461           ptr = endPtr;
462         }
463         if (ptr && *ptr) {
464           stats->dwRetransSegs = strtoul(ptr, &endPtr, 10);
465           ptr = endPtr;
466         }
467         if (ptr && *ptr) {
468           stats->dwInErrs = strtoul(ptr, &endPtr, 10);
469           ptr = endPtr;
470         }
471         if (ptr && *ptr) {
472           stats->dwOutRsts = strtoul(ptr, &endPtr, 10);
473           ptr = endPtr;
474         }
475         stats->dwNumConns = getNumTcpEntries();
476       }
477     }
478     fclose(fp);
479   }
480   return NO_ERROR;
481 }
482
483 DWORD getUDPStats(MIB_UDPSTATS *stats)
484 {
485   FILE *fp;
486
487   if (!stats)
488     return ERROR_INVALID_PARAMETER;
489
490   memset(stats, 0, sizeof(MIB_UDPSTATS));
491
492   /* get from /proc/net/snmp, no error if can't */
493   fp = fopen("/proc/net/snmp", "r");
494   if (fp) {
495     static const char hdr[] = "Udp:";
496     char buf[512] = { 0 }, *ptr;
497
498
499     do {
500       ptr = fgets(buf, sizeof(buf), fp);
501     } while (ptr && strncasecmp(buf, hdr, sizeof(hdr) - 1));
502     if (ptr) {
503       /* last line was a header, get another */
504       ptr = fgets(buf, sizeof(buf), fp);
505       if (ptr && strncasecmp(buf, hdr, sizeof(hdr) - 1) == 0) {
506         char *endPtr;
507
508         ptr += sizeof(hdr);
509         if (ptr && *ptr) {
510           stats->dwInDatagrams = strtoul(ptr, &endPtr, 10);
511           ptr = endPtr;
512         }
513         if (ptr && *ptr) {
514           stats->dwNoPorts = strtoul(ptr, &endPtr, 10);
515           ptr = endPtr;
516         }
517         if (ptr && *ptr) {
518           stats->dwInErrors = strtoul(ptr, &endPtr, 10);
519           ptr = endPtr;
520         }
521         if (ptr && *ptr) {
522           stats->dwOutDatagrams = strtoul(ptr, &endPtr, 10);
523           ptr = endPtr;
524         }
525         if (ptr && *ptr) {
526           stats->dwNumAddrs = strtoul(ptr, &endPtr, 10);
527           ptr = endPtr;
528         }
529       }
530     }
531     fclose(fp);
532   }
533   return NO_ERROR;
534 }
535
536 static DWORD getNumWithOneHeader(const char *filename)
537 {
538   FILE *fp;
539   int ret = 0;
540
541   fp = fopen(filename, "r");
542   if (fp) {
543     char buf[512] = { 0 }, *ptr;
544
545
546     ptr = fgets(buf, sizeof(buf), fp);
547     if (ptr) {
548       do {
549         ptr = fgets(buf, sizeof(buf), fp);
550         if (ptr)
551           ret++;
552       } while (ptr);
553     }
554     fclose(fp);
555   }
556   return ret;
557 }
558
559 DWORD getNumRoutes(void)
560 {
561   return getNumWithOneHeader("/proc/net/route");
562 }
563
564 RouteTable *getRouteTable(void)
565 {
566   DWORD numRoutes = getNumRoutes();
567   RouteTable *ret;
568
569   ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
570    sizeof(RouteTable) + (numRoutes - 1) * sizeof(RouteEntry));
571   if (ret) {
572     FILE *fp;
573
574     /* get from /proc/net/route, no error if can't */
575     fp = fopen("/proc/net/route", "r");
576     if (fp) {
577       char buf[512] = { 0 }, *ptr;
578
579       /* skip header line */
580       ptr = fgets(buf, sizeof(buf), fp);
581       while (ptr && ret->numRoutes < numRoutes) {
582         ptr = fgets(buf, sizeof(buf), fp);
583         if (ptr) {
584           DWORD index;
585
586           while (!isspace(*ptr))
587             ptr++;
588           *ptr = '\0';
589           ptr++;
590           if (getInterfaceIndexByName(buf, &index) == NO_ERROR) {
591             char *endPtr;
592
593             ret->routes[ret->numRoutes].ifIndex = index;
594             if (*ptr) {
595               ret->routes[ret->numRoutes].dest = strtoul(ptr, &endPtr, 16);
596               ptr = endPtr;
597             }
598             if (ptr && *ptr) {
599               ret->routes[ret->numRoutes].gateway = strtoul(ptr, &endPtr, 16);
600               ptr = endPtr;
601             }
602             if (ptr && *ptr) {
603               strtoul(ptr, &endPtr, 16); /* flags, skip */
604               ptr = endPtr;
605             }
606             if (ptr && *ptr) {
607               strtoul(ptr, &endPtr, 16); /* refcount, skip */
608               ptr = endPtr;
609             }
610             if (ptr && *ptr) {
611               strtoul(ptr, &endPtr, 16); /* use, skip */
612               ptr = endPtr;
613             }
614             if (ptr && *ptr) {
615               ret->routes[ret->numRoutes].metric = strtoul(ptr, &endPtr, 16);
616               ptr = endPtr;
617             }
618             if (ptr && *ptr) {
619               ret->routes[ret->numRoutes].mask = strtoul(ptr, &endPtr, 16);
620               ptr = endPtr;
621             }
622             ret->numRoutes++;
623           }
624         }
625       }
626       fclose(fp);
627     }
628   }
629   return ret;
630 }
631
632 DWORD getNumArpEntries(void)
633 {
634   return getNumWithOneHeader("/proc/net/arp");
635 }
636
637 PMIB_IPNETTABLE getArpTable(void)
638 {
639   DWORD numEntries = getNumArpEntries();
640   PMIB_IPNETTABLE ret;
641
642   ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
643    sizeof(MIB_IPNETTABLE) + (numEntries - 1) * sizeof(MIB_IPNETROW));
644   if (ret) {
645     FILE *fp;
646
647     /* get from /proc/net/arp, no error if can't */
648     fp = fopen("/proc/net/arp", "r");
649     if (fp) {
650       char buf[512] = { 0 }, *ptr;
651
652       /* skip header line */
653       ptr = fgets(buf, sizeof(buf), fp);
654       while (ptr && ret->dwNumEntries < numEntries) {
655         ptr = fgets(buf, sizeof(buf), fp);
656         if (ptr) {
657           char *endPtr;
658
659           ret->table[ret->dwNumEntries].dwAddr = inet_addr(ptr);
660           while (ptr && *ptr && !isspace(*ptr))
661             ptr++;
662
663           if (ptr && *ptr) {
664             strtoul(ptr, &endPtr, 16); /* hw type (skip) */
665             ptr = endPtr;
666           }
667           if (ptr && *ptr) {
668             DWORD flags = strtoul(ptr, &endPtr, 16);
669
670 #ifdef ATF_COM
671             if (flags & ATF_COM)
672               ret->table[ret->dwNumEntries].dwType = MIB_IPNET_TYPE_DYNAMIC;
673             else
674 #endif
675 #ifdef ATF_PERM
676             if (flags & ATF_PERM)
677               ret->table[ret->dwNumEntries].dwType = MIB_IPNET_TYPE_STATIC;
678             else
679 #endif
680               ret->table[ret->dwNumEntries].dwType = MIB_IPNET_TYPE_OTHER;
681
682             ptr = endPtr;
683           }
684           while (ptr && *ptr && isspace(*ptr))
685             ptr++;
686           while (ptr && *ptr && !isspace(*ptr)) {
687             DWORD byte = strtoul(ptr, &endPtr, 16);
688
689             if (endPtr && *endPtr) {
690               endPtr++;
691               ret->table[ret->dwNumEntries].bPhysAddr[
692                ret->table[ret->dwNumEntries].dwPhysAddrLen++] = byte & 0x0ff;
693             }
694             ptr = endPtr;
695           }
696           if (ptr && *ptr) {
697             strtoul(ptr, &endPtr, 16); /* mask (skip) */
698             ptr = endPtr;
699           }
700           getInterfaceIndexByName(ptr, &ret->table[ret->dwNumEntries].dwIndex);
701           ret->dwNumEntries++;
702         }
703       }
704       fclose(fp);
705     }
706   }
707   return ret;
708 }
709
710 DWORD getNumUdpEntries(void)
711 {
712   return getNumWithOneHeader("/proc/net/udp");
713 }
714
715 PMIB_UDPTABLE getUdpTable(void)
716 {
717   DWORD numEntries = getNumUdpEntries();
718   PMIB_UDPTABLE ret;
719
720   ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
721    sizeof(MIB_UDPTABLE) + (numEntries - 1) * sizeof(MIB_UDPROW));
722   if (ret) {
723     FILE *fp;
724
725     /* get from /proc/net/udp, no error if can't */
726     fp = fopen("/proc/net/udp", "r");
727     if (fp) {
728       char buf[512] = { 0 }, *ptr;
729
730       /* skip header line */
731       ptr = fgets(buf, sizeof(buf), fp);
732       while (ptr && ret->dwNumEntries < numEntries) {
733         ptr = fgets(buf, sizeof(buf), fp);
734         if (ptr) {
735           char *endPtr;
736
737           if (ptr && *ptr) {
738             strtoul(ptr, &endPtr, 16); /* skip */
739             ptr = endPtr;
740           }
741           if (ptr && *ptr) {
742             ptr++;
743             ret->table[ret->dwNumEntries].dwLocalAddr = strtoul(ptr, &endPtr,
744              16);
745             ptr = endPtr;
746           }
747           if (ptr && *ptr) {
748             ptr++;
749             ret->table[ret->dwNumEntries].dwLocalPort = strtoul(ptr, &endPtr,
750              16);
751             ptr = endPtr;
752           }
753           ret->dwNumEntries++;
754         }
755       }
756       fclose(fp);
757     }
758   }
759   return ret;
760 }
761
762 DWORD getNumTcpEntries(void)
763 {
764   return getNumWithOneHeader("/proc/net/tcp");
765 }
766
767 PMIB_TCPTABLE getTcpTable(void)
768 {
769   DWORD numEntries = getNumTcpEntries();
770   PMIB_TCPTABLE ret;
771
772   ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
773    sizeof(MIB_TCPTABLE) + (numEntries - 1) * sizeof(MIB_TCPROW));
774   if (ret) {
775     FILE *fp;
776
777     /* get from /proc/net/tcp, no error if can't */
778     fp = fopen("/proc/net/tcp", "r");
779     if (fp) {
780       char buf[512] = { 0 }, *ptr;
781
782       /* skip header line */
783       ptr = fgets(buf, sizeof(buf), fp);
784       while (ptr && ret->dwNumEntries < numEntries) {
785         ptr = fgets(buf, sizeof(buf), fp);
786         if (ptr) {
787           char *endPtr;
788
789           while (ptr && *ptr && *ptr != ':')
790             ptr++;
791           if (ptr && *ptr)
792             ptr++;
793           if (ptr && *ptr) {
794             ret->table[ret->dwNumEntries].dwLocalAddr = strtoul(ptr, &endPtr,
795              16);
796             ptr = endPtr;
797           }
798           if (ptr && *ptr) {
799             ptr++;
800             ret->table[ret->dwNumEntries].dwLocalPort = strtoul(ptr, &endPtr,
801              16);
802             ptr = endPtr;
803           }
804           if (ptr && *ptr) {
805             ret->table[ret->dwNumEntries].dwRemoteAddr = strtoul(ptr, &endPtr,
806              16);
807             ptr = endPtr;
808           }
809           if (ptr && *ptr) {
810             ptr++;
811             ret->table[ret->dwNumEntries].dwRemotePort = strtoul(ptr, &endPtr,
812              16);
813             ptr = endPtr;
814           }
815           if (ptr && *ptr) {
816             DWORD state = strtoul(ptr, &endPtr, 16);
817
818             switch (state)
819             {
820               case TCPS_ESTABLISHED:
821                 ret->table[ret->dwNumEntries].dwState = MIB_TCP_STATE_ESTAB;
822                 break;
823               case TCPS_SYN_SENT:
824                 ret->table[ret->dwNumEntries].dwState = MIB_TCP_STATE_SYN_SENT;
825                 break;
826               case TCPS_SYN_RECEIVED:
827                 ret->table[ret->dwNumEntries].dwState = MIB_TCP_STATE_SYN_RCVD;
828                 break;
829               case TCPS_FIN_WAIT_1:
830                 ret->table[ret->dwNumEntries].dwState = MIB_TCP_STATE_FIN_WAIT1;
831                 break;
832               case TCPS_FIN_WAIT_2:
833                 ret->table[ret->dwNumEntries].dwState = MIB_TCP_STATE_FIN_WAIT2;
834                 break;
835               case TCPS_TIME_WAIT:
836                 ret->table[ret->dwNumEntries].dwState = MIB_TCP_STATE_TIME_WAIT;
837                 break;
838               case TCPS_CLOSED:
839                 ret->table[ret->dwNumEntries].dwState = MIB_TCP_STATE_CLOSED;
840                 break;
841               case TCPS_CLOSE_WAIT:
842                 ret->table[ret->dwNumEntries].dwState =
843                  MIB_TCP_STATE_CLOSE_WAIT;
844                 break;
845               case TCPS_LAST_ACK:
846                 ret->table[ret->dwNumEntries].dwState = MIB_TCP_STATE_LAST_ACK;
847                 break;
848               case TCPS_LISTEN:
849                 ret->table[ret->dwNumEntries].dwState = MIB_TCP_STATE_LISTEN;
850                 break;
851               case TCPS_CLOSING:
852                 ret->table[ret->dwNumEntries].dwState = MIB_TCP_STATE_CLOSING;
853                 break;
854             }
855             ptr = endPtr;
856           }
857           ret->dwNumEntries++;
858         }
859       }
860       fclose(fp);
861     }
862   }
863   return ret;
864 }