ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/libstatgrab/src/libstatgrab/network_stats.c
Revision: 1.18
Committed: Sun Oct 19 02:03:02 2003 UTC (20 years, 7 months ago) by ats
Content type: text/plain
Branch: MAIN
CVS Tags: LIBSTATGRAB_0_7
Changes since 1.17: +3 -3 lines
Log Message:
Initial support for NetBSD. This adds NetBSD support for everything
except diskio stats (since they're even more disturbingly complex to get
at on NetBSD than the three OSs we already support). Tested against
NetBSD 1.6 on i386.

File Contents

# User Rev Content
1 pajs 1.1 /*
2     * i-scream central monitoring system
3 tdb 1.15 * http://www.i-scream.org
4     * Copyright (C) 2000-2003 i-scream
5 pajs 1.1 *
6     * This program is free software; you can redistribute it and/or
7     * modify it under the terms of the GNU General Public License
8     * as published by the Free Software Foundation; either version 2
9     * of the License, or (at your option) any later version.
10     *
11     * This program is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     *
16     * You should have received a copy of the GNU General Public License
17     * along with this program; if not, write to the Free Software
18     * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19     */
20    
21     #ifdef HAVE_CONFIG_H
22     #include "config.h"
23     #endif
24    
25 tdb 1.4 #include <stdlib.h>
26 pajs 1.6 #include <string.h>
27 pajs 1.1 #include "statgrab.h"
28 tdb 1.11 #include <time.h>
29 pajs 1.1 #ifdef SOLARIS
30     #include <kstat.h>
31     #include <sys/sysinfo.h>
32 pajs 1.6 #endif
33     #ifdef LINUX
34     #include <stdio.h>
35     #include <sys/types.h>
36     #include <regex.h>
37     #include "tools.h"
38 pajs 1.1 #endif
39 ats 1.18 #ifdef ALLBSD
40 pajs 1.14 #include <sys/types.h>
41     #include <sys/socket.h>
42     #include <ifaddrs.h>
43     #include <net/if.h>
44     #endif
45 pajs 1.1
46 pajs 1.3 static network_stat_t *network_stats=NULL;
47     static int interfaces=0;
48 pajs 1.1
49 pajs 1.3 void network_stat_init(int start, int end, network_stat_t *net_stats){
50    
51     for(net_stats+=start; start<end; start++){
52     net_stats->interface_name=NULL;
53     net_stats->tx=0;
54     net_stats->rx=0;
55     net_stats++;
56     }
57     }
58    
59     network_stat_t *network_stat_malloc(int needed_entries, int *cur_entries, network_stat_t *net_stats){
60    
61     if(net_stats==NULL){
62    
63     if((net_stats=malloc(needed_entries * sizeof(network_stat_t)))==NULL){
64 pajs 1.1 return NULL;
65     }
66 pajs 1.3 network_stat_init(0, needed_entries, net_stats);
67     *cur_entries=needed_entries;
68    
69 pajs 1.1 return net_stats;
70     }
71 pajs 1.3
72    
73     if(*cur_entries<needed_entries){
74     net_stats=realloc(net_stats, (sizeof(network_stat_t)*needed_entries));
75     if(net_stats==NULL){
76 pajs 1.1 return NULL;
77     }
78 pajs 1.3 network_stat_init(*cur_entries, needed_entries, net_stats);
79     *cur_entries=needed_entries;
80 pajs 1.1 }
81    
82     return net_stats;
83     }
84    
85 pajs 1.3
86 pajs 1.1 network_stat_t *get_network_stats(int *entries){
87 pajs 1.6
88     static int sizeof_network_stats=0;
89     network_stat_t *network_stat_ptr;
90    
91     #ifdef SOLARIS
92 pajs 1.1 kstat_ctl_t *kc;
93     kstat_t *ksp;
94     kstat_named_t *knp;
95 pajs 1.6 #endif
96 pajs 1.3
97 pajs 1.6 #ifdef LINUX
98     FILE *f;
99 pajs 1.12 /* Horrible big enough, but it should be easily big enough */
100 pajs 1.6 char line[8096];
101     regex_t regex;
102     regmatch_t line_match[4];
103 pajs 1.14 #endif
104 ats 1.18 #ifdef ALLBSD
105 pajs 1.14 struct ifaddrs *net, *net_ptr;
106     struct if_data *net_data;
107     #endif
108    
109 ats 1.18 #ifdef ALLBSD
110 pajs 1.14 if(getifaddrs(&net) != 0){
111     return NULL;
112     }
113    
114     interfaces=0;
115    
116     for(net_ptr=net;net_ptr!=NULL;net_ptr=net_ptr->ifa_next){
117     if(net_ptr->ifa_addr->sa_family != AF_LINK) continue;
118     network_stats=network_stat_malloc((interfaces+1), &sizeof_network_stats, network_stats);
119     if(network_stats==NULL){
120     return NULL;
121     }
122     network_stat_ptr=network_stats+interfaces;
123    
124     if(network_stat_ptr->interface_name!=NULL) free(network_stat_ptr->interface_name);
125     network_stat_ptr->interface_name=strdup(net_ptr->ifa_name);
126     if(network_stat_ptr->interface_name==NULL) return NULL;
127     net_data=(struct if_data *)net_ptr->ifa_data;
128     network_stat_ptr->rx=net_data->ifi_ibytes;
129     network_stat_ptr->tx=net_data->ifi_obytes;
130     network_stat_ptr->systime=time(NULL);
131     interfaces++;
132     }
133     freeifaddrs(net);
134 pajs 1.6 #endif
135 pajs 1.1
136 pajs 1.6 #ifdef SOLARIS
137 pajs 1.1 if ((kc = kstat_open()) == NULL) {
138     return NULL;
139     }
140    
141 pajs 1.6 interfaces=0;
142 pajs 1.3
143 pajs 1.1 for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) {
144     if (!strcmp(ksp->ks_class, "net")) {
145     kstat_read(kc, ksp, NULL);
146    
147 pajs 1.7 #ifdef SOL7
148     #define RLOOKUP "rbytes"
149     #define WLOOKUP "obytes"
150     #define VALTYPE value.ui32
151     #else
152     #define RLOOKUP "rbytes64"
153     #define WLOOKUP "obytes64"
154     #define VALTYPE value.ui64
155     #endif
156    
157     if((knp=kstat_data_lookup(ksp, RLOOKUP))==NULL){
158 pajs 1.1 /* Not a network interface, so skip to the next entry */
159     continue;
160     }
161 pajs 1.3
162     network_stats=network_stat_malloc((interfaces+1), &sizeof_network_stats, network_stats);
163 pajs 1.1 if(network_stats==NULL){
164     return NULL;
165     }
166     network_stat_ptr=network_stats+interfaces;
167 pajs 1.7 network_stat_ptr->rx=knp->VALTYPE;
168 pajs 1.1
169 pajs 1.7 if((knp=kstat_data_lookup(ksp, WLOOKUP))==NULL){
170 pajs 1.1 /* Not a network interface, so skip to the next entry */
171     continue;
172     }
173 pajs 1.7 network_stat_ptr->tx=knp->VALTYPE;
174 pajs 1.1 if(network_stat_ptr->interface_name!=NULL){
175     free(network_stat_ptr->interface_name);
176     }
177     network_stat_ptr->interface_name=strdup(ksp->ks_name);
178 pajs 1.3
179     network_stat_ptr->systime=time(NULL);
180 pajs 1.1 interfaces++;
181     }
182     }
183 pajs 1.2
184     kstat_close(kc);
185 pajs 1.6 #endif
186     #ifdef LINUX
187     f=fopen("/proc/net/dev", "r");
188     if(f==NULL){
189     return NULL;
190     }
191     /* read the 2 lines.. Its the title, so we dont care :) */
192     fgets(line, sizeof(line), f);
193     fgets(line, sizeof(line), f);
194    
195    
196     if((regcomp(&regex, "^[[:space:]]*([^:]+):[[:space:]]*([[:digit:]]+)[[:space:]]+[[:digit:]]+[[:space:]]+[[:digit:]]+[[:space:]]+[[:digit:]]+[[:space:]]+[[:digit:]]+[[:space:]]+[[:digit:]]+[[:space:]]+[[:digit:]]+[[:space:]]+[[:digit:]]+[[:space:]]+([[:digit:]]+)", REG_EXTENDED))!=0){
197     return NULL;
198     }
199    
200     interfaces=0;
201 pajs 1.1
202 pajs 1.6 while((fgets(line, sizeof(line), f)) != NULL){
203     if((regexec(&regex, line, 4, line_match, 0))!=0){
204     continue;
205     }
206     network_stats=network_stat_malloc((interfaces+1), &sizeof_network_stats, network_stats);
207     if(network_stats==NULL){
208     return NULL;
209     }
210     network_stat_ptr=network_stats+interfaces;
211    
212     if(network_stat_ptr->interface_name!=NULL){
213     free(network_stat_ptr->interface_name);
214     }
215    
216     network_stat_ptr->interface_name=get_string_match(line, &line_match[1]);
217     network_stat_ptr->rx=get_ll_match(line, &line_match[2]);
218     network_stat_ptr->tx=get_ll_match(line, &line_match[3]);
219     network_stat_ptr->systime=time(NULL);
220    
221     interfaces++;
222     }
223 pajs 1.12 fclose(f);
224 pajs 1.13 regfree(&regex);
225 pajs 1.6
226     #endif
227 pajs 1.1 *entries=interfaces;
228    
229     return network_stats;
230 pajs 1.3 }
231    
232 pajs 1.8 long long transfer_diff(long long new, long long old){
233 pajs 1.17 #if defined(SOL7) || defined(LINUX) || defined(FREEBSD)
234 pajs 1.8 #define MAXVAL 4294967296
235     #else
236     #define MAXVAL 18446744073709551616
237     #endif
238     long long result;
239 pajs 1.10 if(new>=old){
240 pajs 1.8 result = (new-old);
241     }else{
242     result = (MAXVAL+(new-old));
243     }
244    
245     return result;
246    
247     }
248    
249 pajs 1.3 network_stat_t *get_network_stats_diff(int *entries){
250     static network_stat_t *network_stats_diff=NULL;
251     static int sizeof_net_stats_diff=0;
252     network_stat_t *network_stats_ptr, *network_stats_diff_ptr;
253     int ifaces, x, y;
254    
255     if(network_stats==NULL){
256     network_stats_ptr=get_network_stats(&ifaces);
257     *entries=ifaces;
258     return network_stats_ptr;
259     }
260    
261     network_stats_diff=network_stat_malloc(interfaces, &sizeof_net_stats_diff, network_stats_diff);
262     if(network_stats_diff==NULL){
263     return NULL;
264     }
265    
266     network_stats_ptr=network_stats;
267     network_stats_diff_ptr=network_stats_diff;
268    
269     for(ifaces=0;ifaces<interfaces;ifaces++){
270     if(network_stats_diff_ptr->interface_name!=NULL){
271     free(network_stats_diff_ptr->interface_name);
272     }
273     network_stats_diff_ptr->interface_name=strdup(network_stats_ptr->interface_name);
274     network_stats_diff_ptr->tx=network_stats_ptr->tx;
275     network_stats_diff_ptr->rx=network_stats_ptr->rx;
276     network_stats_diff_ptr->systime=network_stats->systime;
277    
278     network_stats_ptr++;
279     network_stats_diff_ptr++;
280     }
281     network_stats_ptr=get_network_stats(&ifaces);
282     network_stats_diff_ptr=network_stats_diff;
283    
284     for(x=0;x<sizeof_net_stats_diff;x++){
285    
286     if((strcmp(network_stats_diff_ptr->interface_name, network_stats_ptr->interface_name))==0){
287 pajs 1.9 network_stats_diff_ptr->tx = transfer_diff(network_stats_ptr->tx, network_stats_diff_ptr->tx);
288     network_stats_diff_ptr->rx = transfer_diff(network_stats_ptr->rx, network_stats_diff_ptr->rx);
289 pajs 1.3 network_stats_diff_ptr->systime = network_stats_ptr->systime - network_stats_diff_ptr->systime;
290     }else{
291    
292     network_stats_ptr=network_stats;
293     for(y=0;y<ifaces;y++){
294     if((strcmp(network_stats_diff_ptr->interface_name, network_stats_ptr->interface_name))==0){
295 pajs 1.9 network_stats_diff_ptr->tx = transfer_diff(network_stats_ptr->tx, network_stats_diff_ptr->tx);
296     network_stats_diff_ptr->rx = transfer_diff(network_stats_ptr->rx, network_stats_diff_ptr->rx);
297 pajs 1.3 network_stats_diff_ptr->systime = network_stats_ptr->systime - network_stats_diff_ptr->systime;
298     break;
299     }
300    
301     network_stats_ptr++;
302     }
303     }
304    
305     network_stats_ptr++;
306     network_stats_diff_ptr++;
307     }
308    
309 pajs 1.5 *entries=sizeof_net_stats_diff;
310 pajs 1.3 return network_stats_diff;
311     }
312 pajs 1.1