1 /*
2 * Copyright 2003,2005,2006 Bernhard Walle <bernhard@bwalle.de>
3 * Copyright 2010 Florian Rivoal <frivoal@gmail.com>
4 * -------------------------------------------------------------------------------------------------
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation; either version 2 of the License, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program; if not, write to the Free Software Foundation, Inc., 675 Mass
18 * Ave, Cambridge, MA 02139, USA.
19 *
20 * -------------------------------------------------------------------------------------------------
21 */
22
23 /*
24 * This is just a wrapper between the netload-plugin and the wormulon source.
25 * Wormulon is a small command-line util which displays the netload. You can find it
26 * at http://raisdorf.net/wormulon. Most sourcecode is taken from wormulon.
27 *
28 * Thanks to Hendrik Scholz. Only his work made it possible to support a large
29 * number of operating systems quickly without a library! Without him only
30 * Linux and FreeBSD (with foreign code from IceWM) would be supported.
31 */
32 #ifdef HAVE_CONFIG_H
33 #include <config.h>
34 #endif
35
36 #include <libxfce4util/libxfce4util.h>
37
38
39 /* From Wormulon */
40 #include "net.h"
41 #include "os.h"
42 #include "wormulon.h"
43 #include "slurm.h" /* slurm structs */
44
45 #include <sys/types.h>
46 #include <errno.h>
47
48 #if defined(__HPUX__)
49 # include "wormulon/hpux.h"
50 # include "wormulon/hpux.c"
51 #elif defined(__APPLE__)
52 # include "src/macos.h"
53 # include "src/macos.c"
54 #elif (defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__))
55 # include "wormulon/freebsd.h"
56 # include "wormulon/freebsd.c"
57 #elif defined(__linux__)
58 # include "wormulon/linux.h"
59 # include "wormulon/linux.c"
60 #elif (defined(__OpenBSD__) || defined(__MicroBSD__))
61 # include "wormulon/openbsd.h"
62 # include "wormulon/openbsd.c"
63 #elif defined(__NetBSD__)
64 # include "wormulon/netbsd.h"
65 # include "wormulon/netbsd.c"
66 #elif defined(__Solaris__)
67 # include "wormulon/solaris.h"
68 # include "wormulon/solaris.c"
69 #else
70 /* should not get here */
71 # error "OS not supported"
72 #endif
73
74
75 /* ---------------------------------------------------------------------------------------------- */
init_netload(netdata * data,const char * device)76 int init_netload(netdata* data, const char* device)
77 {
78 memset( data, 0, sizeof(netdata) );
79
80 if (device == NULL || strlen(device) == 0)
81 {
82 return TRUE;
83 }
84
85 g_strlcpy(data->ifdata.if_name, device, sizeof(data->ifdata.if_name));
86
87 init_osspecific( data );
88
89 data->ip_address[0] = 0;
90 data->ip_update_count = 0;
91 data->up = FALSE;
92 data->up_update_count = 0;
93
94 if (checkinterface(data) != TRUE)
95 {
96 data->correct_interface = FALSE;
97 return FALSE;
98 }
99
100 /* init in a sane state */
101 get_stat(data);
102 data->backup_in = data->stats.rx_bytes;
103 data->backup_out = data->stats.tx_bytes;
104
105 data->correct_interface = TRUE;
106
107 DBG("The netload plugin was initialized for '%s'.", device);
108
109 return TRUE;
110 }
111
112
113 /* ---------------------------------------------------------------------------------------------- */
get_current_netload(netdata * data,unsigned long * in,unsigned long * out,unsigned long * tot)114 void get_current_netload(netdata* data, unsigned long *in, unsigned long *out, unsigned long *tot)
115 {
116 struct timeval curr_time;
117 double delta_t;
118
119 if (! data->correct_interface)
120 {
121 if (in != NULL && out != NULL && tot != NULL)
122 {
123 *in = *out = *tot = 0;
124 }
125 }
126
127 gettimeofday(&curr_time, NULL);
128
129 delta_t = (double) ((curr_time.tv_sec - data->prev_time.tv_sec) * 1000000L
130 + (curr_time.tv_usec - data->prev_time.tv_usec)) / 1000000.0;
131
132 /* update */
133 get_stat(data);
134 if (data->backup_in > data->stats.rx_bytes)
135 {
136 data->cur_in = (int)( data->stats.rx_bytes / delta_t + 0.5);
137 }
138 else
139 {
140 data->cur_in = (int)( (data->stats.rx_bytes - data->backup_in) / delta_t + 0.5);
141 }
142
143 if (data->backup_out > data->stats.tx_bytes)
144 {
145 data->cur_out = (int)( data->stats.tx_bytes / delta_t + 0.5);
146 }
147 else
148 {
149 data->cur_out = (int)( (data->stats.tx_bytes - data->backup_out) / delta_t + 0.5);
150 }
151
152 if (in != NULL && out != NULL && tot != NULL)
153 {
154 *in = data->cur_in;
155 *out = data->cur_out;
156 *tot = *in + *out;
157 }
158
159 /* save 'new old' values */
160 data->backup_in = data->stats.rx_bytes;
161 data->backup_out = data->stats.tx_bytes;
162
163 /* do the same with time */
164 data->prev_time.tv_sec = curr_time.tv_sec;
165 data->prev_time.tv_usec = curr_time.tv_usec;
166 }
167
168
169 /* ---------------------------------------------------------------------------------------------- */
get_name(netdata * data)170 char* get_name(netdata* data)
171 {
172 return data->ifdata.if_name;
173 }
174
175
176 /* ---------------------------------------------------------------------------------------------- */
get_interface_up(netdata * data)177 int get_interface_up(netdata* data)
178 {
179 int sockfd;
180 struct ifreq ifr;
181
182 /* if the update count is non-zero */
183 if (data->up_update_count > 0)
184 {
185 data->up_update_count--;
186 return data->up;
187 }
188
189 /* get the value from the operating system */
190 if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
191 {
192 DBG("Error in socket: %s", strerror(errno));
193 return FALSE;
194 }
195
196 g_snprintf(ifr.ifr_name, IF_NAMESIZE, "%s", data->ifdata.if_name);
197 if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) != 0)
198 {
199 DBG("Error in ioctl(sockfd): %s", strerror(errno));
200 close(sockfd);
201 return FALSE;
202 }
203 close(sockfd);
204
205 data->up = ((ifr.ifr_flags & IFF_UP) == IFF_UP) ? TRUE : FALSE;
206 data->up_update_count = UP_UPDATE_INTERVAL;
207
208 return data->up;
209 }
210
211
212 /* ---------------------------------------------------------------------------------------------- */
get_ip_address(netdata * data)213 char* get_ip_address(netdata* data)
214 {
215 int sockfd;
216 struct ifreq ifr;
217 struct sockaddr_in *p_sa;
218
219 /* use cached value if possible and if the update count is non-zero */
220 if (data->ip_address && data->ip_update_count > 0)
221 {
222 data->ip_update_count--;
223 return data->ip_address;
224 }
225
226 /* get the value from the operating system */
227 if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
228 {
229 DBG("Error in socket: %s", strerror(errno));
230 return NULL;
231 }
232
233 g_snprintf(ifr.ifr_name, IF_NAMESIZE, "%s", data->ifdata.if_name);
234 if (ioctl(sockfd, SIOCGIFADDR, &ifr) != 0)
235 {
236 if (errno != EADDRNOTAVAIL)
237 {
238 DBG("Error in ioctl(sockfd): %s", strerror(errno));
239 }
240 close(sockfd);
241 return NULL;
242 }
243 close(sockfd);
244
245 p_sa = (struct sockaddr_in*) &ifr.ifr_addr;
246
247 if (!inet_ntop(AF_INET, &p_sa->sin_addr, data->ip_address, IP_ADDRESS_LENGTH))
248 {
249 DBG("Error in inet_ntop: %s", strerror(errno));
250 return NULL;
251 }
252
253 /* now updated */
254 data->ip_update_count = IP_UPDATE_INTERVAL;
255
256 return data->ip_address;
257 }
258
259
260 /* ---------------------------------------------------------------------------------------------- */
close_netload(netdata * data)261 void close_netload(netdata* data)
262 {
263 /* We need not code here */
264 }
265
266