Patch by Joel Reed that implements a few network interface counters
[mono.git] / mono / utils / mono-networkinterfaces.c
1 #include "config.h"
2 #include "utils/mono-networkinterfaces.h"
3
4 #include <stdlib.h>
5 #include <stdio.h>
6 #include <string.h>
7
8 /* FIXME: bsds untested */
9
10 /**
11  * mono_networkinterface_list:
12  * @size: a pointer to a location where the size of the returned array is stored
13  *
14  * Return an array of names for the interfaces currently on the system.
15  * The size of the array is stored in @size.
16  */
17 gpointer*
18 mono_networkinterface_list (int *size)
19 {
20         int i = 0, count = 0;
21         void **nilist = NULL;
22         char buf [512];
23         FILE *f;
24         char name [256];
25
26         f = fopen ("/proc/net/dev", "r");
27         if (!f) 
28                 return NULL;
29
30         if (!fgets (buf, sizeof (buf) / sizeof (char), f))
31                 goto out;
32
33         if (!fgets (buf, sizeof (buf) / sizeof (char), f))
34                 goto out;
35
36         while (fgets (buf, sizeof (buf), f) != NULL) {
37                 char *ptr;
38                 buf [sizeof(buf) - 1] = 0;
39                 if ((ptr = strchr (buf, ':')) == NULL || (*ptr++ = 0, sscanf (buf, "%s", name) != 1))
40                         goto out;
41
42                 if (i >= count) {
43                         if (!count)
44                                 count = 16;
45                         else
46                                 count *= 2;
47                 }
48
49                 nilist = g_realloc (nilist, count * sizeof (void*));
50                 nilist [i++] = g_strdup (name);
51         }
52
53  out:
54         if (f) fclose(f);
55         if (size)
56                 *size = i;
57
58         nilist [i] = NULL;
59         return nilist;
60 }
61
62 /**
63  * mono_network_get_data:
64  * @name: name of the interface
65  * @data: description of data to return
66  *
67  * Return a data item of a network adapter like bytes sent per sec, etc
68  * according to the @data argumet.
69  */
70 gint64
71 mono_network_get_data (char* name, MonoNetworkData data, MonoNetworkError *error)
72 {
73         gint64 val = 0;
74         char buf [512];
75         char cname [256];
76         FILE *f;
77
78         unsigned long rx_bytes, rx_packets, rx_errs, rx_drops,
79                 rx_fifo, rx_frame, tx_bytes, tx_packets, tx_errs, tx_drops,
80                 tx_fifo, tx_colls, tx_carrier, rx_multi;
81
82         if (error)
83                 *error = MONO_NETWORK_ERROR_OTHER;
84
85         f = fopen ("/proc/net/dev", "r");
86         if (!f) 
87                 return -1;
88
89         if (!fgets (buf, sizeof (buf) / sizeof (char), f))
90                 goto out;
91
92         if (!fgets (buf, sizeof (buf) / sizeof (char), f))
93                 goto out;
94
95         while (fgets (buf, sizeof (buf), f) != NULL) {
96
97                 char *ptr;
98                 buf [sizeof (buf) - 1] = 0;
99                 if ((ptr = strchr (buf, ':')) == NULL ||
100                                 (*ptr++ = 0, sscanf (buf, "%s", cname) != 1))
101                         goto out;
102
103                 if (strcmp (name, cname) != 0) continue;
104
105                 if (sscanf (ptr, "%ld%ld%ld%ld%ld%ld%ld%*d%ld%ld%ld%ld%ld%ld%ld",
106                                                          &rx_bytes, &rx_packets, &rx_errs, &rx_drops,
107                                                          &rx_fifo, &rx_frame, &rx_multi,
108                                                          &tx_bytes, &tx_packets, &tx_errs, &tx_drops,
109                                                          &tx_fifo, &tx_colls, &tx_carrier) != 14) 
110                         goto out;
111
112                 switch (data) {
113                 case MONO_NETWORK_BYTESSENT:
114                         val = tx_bytes;
115                         *error = MONO_NETWORK_ERROR_NONE;
116                         goto out;
117                 case MONO_NETWORK_BYTESREC:
118                         val = rx_bytes;
119                         *error = MONO_NETWORK_ERROR_NONE;
120                         goto out;
121                 case MONO_NETWORK_BYTESTOTAL:
122                         val = rx_bytes + tx_bytes;
123                         *error = MONO_NETWORK_ERROR_NONE;
124                         goto out;
125                 }
126         }
127
128  out:
129         if (f) fclose (f);
130         return val;
131 }
132