ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/libstatgrab/src/libstatgrab/network_stats.c
Revision: 1.7
Committed: Tue Mar 11 14:30:39 2003 UTC (21 years, 2 months ago) by pajs
Content type: text/plain
Branch: MAIN
Changes since 1.6: +14 -4 lines
Log Message:
Make network stats work on pre sol8.
BUGS: On pre sol8 systems, it doesn't cope with a wrap around once the
32bit uint becomes too big. So when this happens it will report one set
of dodgy data, then continue. This bug technically is there in the 64bit
version too, but it will need to of sent 9223372036854775808 bytes first.
(8388608 terrabytes, so basically a *big enough* number that will come around
and byte me in 20 years time or something ;) )

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
40 static network_stat_t *network_stats=NULL;
41 static int interfaces=0;
42
43 void network_stat_init(int start, int end, network_stat_t *net_stats){
44
45 for(net_stats+=start; start<end; start++){
46 net_stats->interface_name=NULL;
47 net_stats->tx=0;
48 net_stats->rx=0;
49 net_stats++;
50 }
51 }
52
53 network_stat_t *network_stat_malloc(int needed_entries, int *cur_entries, network_stat_t *net_stats){
54
55 if(net_stats==NULL){
56
57 if((net_stats=malloc(needed_entries * sizeof(network_stat_t)))==NULL){
58 return NULL;
59 }
60 network_stat_init(0, needed_entries, net_stats);
61 *cur_entries=needed_entries;
62
63 return net_stats;
64 }
65
66
67 if(*cur_entries<needed_entries){
68 net_stats=realloc(net_stats, (sizeof(network_stat_t)*needed_entries));
69 if(net_stats==NULL){
70 return NULL;
71 }
72 network_stat_init(*cur_entries, needed_entries, net_stats);
73 *cur_entries=needed_entries;
74 }
75
76 return net_stats;
77 }
78
79
80 network_stat_t *get_network_stats(int *entries){
81
82 static int sizeof_network_stats=0;
83 network_stat_t *network_stat_ptr;
84
85 #ifdef SOLARIS
86 kstat_ctl_t *kc;
87 kstat_t *ksp;
88 kstat_named_t *knp;
89 #endif
90
91 #ifdef LINUX
92 FILE *f;
93 /* Horrible big enough, but it should be quite easily */
94 char line[8096];
95 regex_t regex;
96 regmatch_t line_match[4];
97 #endif
98
99 #ifdef SOLARIS
100 if ((kc = kstat_open()) == NULL) {
101 return NULL;
102 }
103
104 interfaces=0;
105
106 for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) {
107 if (!strcmp(ksp->ks_class, "net")) {
108 kstat_read(kc, ksp, NULL);
109
110 #ifdef SOL7
111 #define RLOOKUP "rbytes"
112 #define WLOOKUP "obytes"
113 #define VALTYPE value.ui32
114 #else
115 #define RLOOKUP "rbytes64"
116 #define WLOOKUP "obytes64"
117 #define VALTYPE value.ui64
118 #endif
119
120 if((knp=kstat_data_lookup(ksp, RLOOKUP))==NULL){
121 /* Not a network interface, so skip to the next entry */
122 continue;
123 }
124
125 network_stats=network_stat_malloc((interfaces+1), &sizeof_network_stats, network_stats);
126 if(network_stats==NULL){
127 return NULL;
128 }
129 network_stat_ptr=network_stats+interfaces;
130 network_stat_ptr->rx=knp->VALTYPE;
131
132 if((knp=kstat_data_lookup(ksp, WLOOKUP))==NULL){
133 /* Not a network interface, so skip to the next entry */
134 continue;
135 }
136 network_stat_ptr->tx=knp->VALTYPE;
137 if(network_stat_ptr->interface_name!=NULL){
138 free(network_stat_ptr->interface_name);
139 }
140 network_stat_ptr->interface_name=strdup(ksp->ks_name);
141
142 network_stat_ptr->systime=time(NULL);
143 interfaces++;
144 }
145 }
146
147 kstat_close(kc);
148 #endif
149 #ifdef LINUX
150 f=fopen("/proc/net/dev", "r");
151 if(f==NULL){
152 return NULL;
153 }
154 /* read the 2 lines.. Its the title, so we dont care :) */
155 fgets(line, sizeof(line), f);
156 fgets(line, sizeof(line), f);
157
158
159 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){
160 return NULL;
161 }
162
163 interfaces=0;
164
165 while((fgets(line, sizeof(line), f)) != NULL){
166 if((regexec(&regex, line, 4, line_match, 0))!=0){
167 continue;
168 }
169 network_stats=network_stat_malloc((interfaces+1), &sizeof_network_stats, network_stats);
170 if(network_stats==NULL){
171 return NULL;
172 }
173 network_stat_ptr=network_stats+interfaces;
174
175 if(network_stat_ptr->interface_name!=NULL){
176 free(network_stat_ptr->interface_name);
177 }
178
179 network_stat_ptr->interface_name=get_string_match(line, &line_match[1]);
180 network_stat_ptr->rx=get_ll_match(line, &line_match[2]);
181 network_stat_ptr->tx=get_ll_match(line, &line_match[3]);
182 network_stat_ptr->systime=time(NULL);
183
184 interfaces++;
185 }
186
187 #endif
188 *entries=interfaces;
189
190 return network_stats;
191 }
192
193 network_stat_t *get_network_stats_diff(int *entries){
194 static network_stat_t *network_stats_diff=NULL;
195 static int sizeof_net_stats_diff=0;
196 network_stat_t *network_stats_ptr, *network_stats_diff_ptr;
197 int ifaces, x, y;
198
199 if(network_stats==NULL){
200 network_stats_ptr=get_network_stats(&ifaces);
201 *entries=ifaces;
202 return network_stats_ptr;
203 }
204
205 network_stats_diff=network_stat_malloc(interfaces, &sizeof_net_stats_diff, network_stats_diff);
206 if(network_stats_diff==NULL){
207 return NULL;
208 }
209
210 network_stats_ptr=network_stats;
211 network_stats_diff_ptr=network_stats_diff;
212
213 for(ifaces=0;ifaces<interfaces;ifaces++){
214 if(network_stats_diff_ptr->interface_name!=NULL){
215 free(network_stats_diff_ptr->interface_name);
216 }
217 network_stats_diff_ptr->interface_name=strdup(network_stats_ptr->interface_name);
218 network_stats_diff_ptr->tx=network_stats_ptr->tx;
219 network_stats_diff_ptr->rx=network_stats_ptr->rx;
220 network_stats_diff_ptr->systime=network_stats->systime;
221
222 network_stats_ptr++;
223 network_stats_diff_ptr++;
224 }
225 network_stats_ptr=get_network_stats(&ifaces);
226 network_stats_diff_ptr=network_stats_diff;
227
228 for(x=0;x<sizeof_net_stats_diff;x++){
229
230 if((strcmp(network_stats_diff_ptr->interface_name, network_stats_ptr->interface_name))==0){
231 network_stats_diff_ptr->tx = network_stats_ptr->tx - network_stats_diff_ptr->tx;
232 network_stats_diff_ptr->rx = network_stats_ptr->rx - network_stats_diff_ptr->rx;
233 network_stats_diff_ptr->systime = network_stats_ptr->systime - network_stats_diff_ptr->systime;
234 }else{
235
236 network_stats_ptr=network_stats;
237 for(y=0;y<ifaces;y++){
238 if((strcmp(network_stats_diff_ptr->interface_name, network_stats_ptr->interface_name))==0){
239 network_stats_diff_ptr->tx = network_stats_ptr->tx - network_stats_diff_ptr->tx;
240 network_stats_diff_ptr->rx = network_stats_ptr->rx - network_stats_diff_ptr->rx;
241 network_stats_diff_ptr->systime = network_stats_ptr->systime - network_stats_diff_ptr->systime;
242 break;
243 }
244
245 network_stats_ptr++;
246 }
247 }
248
249 network_stats_ptr++;
250 network_stats_diff_ptr++;
251 }
252
253 *entries=sizeof_net_stats_diff;
254 return network_stats_diff;
255 }
256