Merge pull request #1691 from esdrubal/exitevent
[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 = (void **) 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         if (!nilist)
59                 nilist = (void **) g_malloc (sizeof (void*));
60         nilist [i] = NULL;
61         return nilist;
62 }
63
64 /**
65  * mono_network_get_data:
66  * @name: name of the interface
67  * @data: description of data to return
68  *
69  * Return a data item of a network adapter like bytes sent per sec, etc
70  * according to the @data argumet.
71  */
72 gint64
73 mono_network_get_data (char* name, MonoNetworkData data, MonoNetworkError *error)
74 {
75         gint64 val = 0;
76         char buf [512];
77         char cname [256];
78         FILE *f;
79
80         unsigned long rx_bytes, rx_packets, rx_errs, rx_drops,
81                 rx_fifo, rx_frame, tx_bytes, tx_packets, tx_errs, tx_drops,
82                 tx_fifo, tx_colls, tx_carrier, rx_multi;
83
84         *error = MONO_NETWORK_ERROR_OTHER;
85
86         f = fopen ("/proc/net/dev", "r");
87         if (!f) 
88                 return -1;
89
90         if (!fgets (buf, sizeof (buf) / sizeof (char), f))
91                 goto out;
92
93         if (!fgets (buf, sizeof (buf) / sizeof (char), f))
94                 goto out;
95
96         while (fgets (buf, sizeof (buf), f) != NULL) {
97
98                 char *ptr;
99                 buf [sizeof (buf) - 1] = 0;
100                 /* FIXME: This might potentially cause a buffer overflow for cname. */
101                 if ((ptr = strchr (buf, ':')) == NULL ||
102                                 (*ptr++ = 0, sscanf (buf, "%s", cname) != 1))
103                         goto out;
104
105                 if (strcmp (name, cname) != 0) continue;
106
107                 if (sscanf (ptr, "%ld%ld%ld%ld%ld%ld%ld%*d%ld%ld%ld%ld%ld%ld%ld",
108                                                          &rx_bytes, &rx_packets, &rx_errs, &rx_drops,
109                                                          &rx_fifo, &rx_frame, &rx_multi,
110                                                          &tx_bytes, &tx_packets, &tx_errs, &tx_drops,
111                                                          &tx_fifo, &tx_colls, &tx_carrier) != 14) 
112                         goto out;
113
114                 switch (data) {
115                 case MONO_NETWORK_BYTESSENT:
116                         val = tx_bytes;
117                         *error = MONO_NETWORK_ERROR_NONE;
118                         goto out;
119                 case MONO_NETWORK_BYTESREC:
120                         val = rx_bytes;
121                         *error = MONO_NETWORK_ERROR_NONE;
122                         goto out;
123                 case MONO_NETWORK_BYTESTOTAL:
124                         val = rx_bytes + tx_bytes;
125                         *error = MONO_NETWORK_ERROR_NONE;
126                         goto out;
127                 }
128         }
129
130  out:
131         if (f) fclose (f);
132         return val;
133 }
134