ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/libstatgrab/src/libstatgrab/network_stats.c
Revision: 1.14
Committed: Sun Apr 6 00:27:19 2003 UTC (21 years, 1 month ago) by pajs
Content type: text/plain
Branch: MAIN
CVS Tags: LIBSTATGRAB_0_4
Changes since 1.13: +37 -0 lines
Log Message:
Now works on freebsd. This is the last of parts that needed to be ported
so its now "finished" for testing. Solaris and Linux should also be tested
as minor changes in code may of disturbed them (it shouldn't have, i just
may of made a mistake :) )

Certain things will require setgid kmem permissions (swap and processor
stats)

File Contents

# Content
1 /*
2 * i-scream central monitoring system
3 * http://www.i-scream.org.uk
4 * Copyright (C) 2000-2002 i-scream
5 *
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 #include <stdlib.h>
26 #include <string.h>
27 #include "statgrab.h"
28 #include <time.h>
29 #ifdef SOLARIS
30 #include <kstat.h>
31 #include <sys/sysinfo.h>
32 #endif
33 #ifdef LINUX
34 #include <stdio.h>
35 #include <sys/types.h>
36 #include <regex.h>
37 #include "tools.h"
38 #endif
39 #ifdef FREEBSD
40 #include <sys/types.h>
41 #include <sys/socket.h>
42 #include <ifaddrs.h>
43 #include <net/if.h>
44 #endif
45
46 static network_stat_t *network_stats=NULL;
47 static int interfaces=0;
48
49 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 return NULL;
65 }
66 network_stat_init(0, needed_entries, net_stats);
67 *cur_entries=needed_entries;
68
69 return net_stats;
70 }
71
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 return NULL;
77 }
78 network_stat_init(*cur_entries, needed_entries, net_stats);
79 *cur_entries=needed_entries;
80 }
81
82 return net_stats;
83 }
84
85
86 network_stat_t *get_network_stats(int *entries){
87
88 static int sizeof_network_stats=0;
89 network_stat_t *network_stat_ptr;
90
91 #ifdef SOLARIS
92 kstat_ctl_t *kc;
93 kstat_t *ksp;
94 kstat_named_t *knp;
95 #endif
96
97 #ifdef LINUX
98 FILE *f;
99 /* Horrible big enough, but it should be easily big enough */
100 char line[8096];
101 regex_t regex;
102 regmatch_t line_match[4];
103 #endif
104 #ifdef FREEBSD
105 struct ifaddrs *net, *net_ptr;
106 struct if_data *net_data;
107 #endif
108
109 #ifdef FREEBSD
110 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 #endif
135
136 #ifdef SOLARIS
137 if ((kc = kstat_open()) == NULL) {
138 return NULL;
139 }
140
141 interfaces=0;
142
143 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 #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 /* Not a network interface, so skip to the next entry */
159 continue;
160 }
161
162 network_stats=network_stat_malloc((interfaces+1), &sizeof_network_stats, network_stats);
163 if(network_stats==NULL){
164 return NULL;
165 }
166 network_stat_ptr=network_stats+interfaces;
167 network_stat_ptr->rx=knp->VALTYPE;
168
169 if((knp=kstat_data_lookup(ksp, WLOOKUP))==NULL){
170 /* Not a network interface, so skip to the next entry */
171 continue;
172 }
173 network_stat_ptr->tx=knp->VALTYPE;
174 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
179 network_stat_ptr->systime=time(NULL);
180 interfaces++;
181 }
182 }
183
184 kstat_close(kc);
185 #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
202 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 fclose(f);
224 regfree(&regex);
225
226 #endif
227 *entries=interfaces;
228
229 return network_stats;
230 }
231
232 long long transfer_diff(long long new, long long old){
233 #ifdef SOL7
234 #define MAXVAL 4294967296
235 #else
236 #define MAXVAL 18446744073709551616
237 #endif
238 long long result;
239 if(new>=old){
240 result = (new-old);
241 }else{
242 result = (MAXVAL+(new-old));
243 }
244
245 return result;
246
247 }
248
249 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 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 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 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 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 *entries=sizeof_net_stats_diff;
310 return network_stats_diff;
311 }
312