1 /* Copyright (C) 2007 Henry Zhang
2 This file is part of LibGTop 2.20.
3
4 Contributed by Henry Zhang <hua.zhang@sun.com>, October 2007.
5
6 LibGTop is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License,
9 or (at your option) any later version.
10
11 LibGTop 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
14 for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with LibGTop; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
20 */
21
22 #include <config.h>
23 #include <glibtop.h>
24 #include <glibtop/error.h>
25 #include <glibtop/netload.h>
26
27 #include "glibtop_private.h"
28
29 #include <errno.h>
30 #include <string.h>
31 #include <kstat.h>
32
33 #include <sys/types.h>
34 #include <sys/socket.h>
35 #include <sys/ioctl.h>
36 #include <sys/sockio.h>
37
38 #include <net/if.h>
39
40
41 static const unsigned long _glibtop_sysdeps_netload =
42 (1L << GLIBTOP_NETLOAD_ERRORS_IN) +
43 (1L << GLIBTOP_NETLOAD_ERRORS_OUT) +
44 (1L << GLIBTOP_NETLOAD_COLLISIONS);
45
46 static const unsigned long _glibtop_sysdeps_netload_data =
47 (1L << GLIBTOP_NETLOAD_ADDRESS) +
48 (1L << GLIBTOP_NETLOAD_SUBNET) +
49 (1L << GLIBTOP_NETLOAD_MTU);
50
51 static const unsigned long _glibtop_sysdeps_netload_bytes =
52 (1L << GLIBTOP_NETLOAD_BYTES_IN) +
53 (1L << GLIBTOP_NETLOAD_BYTES_OUT) +
54 (1L << GLIBTOP_NETLOAD_BYTES_TOTAL);
55
56 static const unsigned long _glibtop_sysdeps_netload_packets =
57 (1L << GLIBTOP_NETLOAD_PACKETS_IN) +
58 (1L << GLIBTOP_NETLOAD_PACKETS_OUT) +
59 (1L << GLIBTOP_NETLOAD_PACKETS_TOTAL);
60
61 static const unsigned long _glibtop_sysdeps_netload_total =
62 (1L << GLIBTOP_NETLOAD_PACKETS_TOTAL) +
63 (1L << GLIBTOP_NETLOAD_BYTES_TOTAL);
64
65 static const unsigned long _glibtop_sysdeps_netload_in =
66 (1L << GLIBTOP_NETLOAD_PACKETS_TOTAL) +
67 (1L << GLIBTOP_NETLOAD_BYTES_TOTAL) +
68 (1L << GLIBTOP_NETLOAD_PACKETS_IN) +
69 (1L << GLIBTOP_NETLOAD_BYTES_IN);
70
71 static const unsigned long _glibtop_sysdeps_netload_out =
72 (1L << GLIBTOP_NETLOAD_PACKETS_TOTAL) +
73 (1L << GLIBTOP_NETLOAD_BYTES_TOTAL) +
74 (1L << GLIBTOP_NETLOAD_PACKETS_OUT) +
75 (1L << GLIBTOP_NETLOAD_BYTES_OUT);
76
77 static const unsigned long _glibtop_sysdeps_netload_6 =
78 (1L << GLIBTOP_NETLOAD_ADDRESS6) +
79 (1L << GLIBTOP_NETLOAD_PREFIX6) +
80 (1L << GLIBTOP_NETLOAD_SCOPE6);
81
82 /* Init function. */
83
84 void
_glibtop_init_netload_s(glibtop * server)85 _glibtop_init_netload_s (glibtop *server)
86 {
87 server->sysdeps.netload = _glibtop_sysdeps_netload |
88 _glibtop_sysdeps_netload_bytes |
89 _glibtop_sysdeps_netload_packets;
90 }
91
92 static int
solaris_stats(glibtop * server,glibtop_netload * buf,const char * interface)93 solaris_stats(glibtop *server,
94 glibtop_netload *buf,
95 const char *interface)
96 {
97 char *name = interface;
98 char *module;
99 char *ptr;
100 kstat_ctl_t * const kctl = server->machine->kc;
101 kstat_t *ksp;
102 kstat_named_t *kdata;
103 int have_bytes = 1;
104
105 /*
106 * chop off the trailing interface
107 */
108 module = strdup( name );
109 ptr = module + strlen( module ) - 1;
110 while( (ptr > module) && isdigit( (int) *ptr ) ) {
111 *ptr = '\0';
112 ptr--;
113 }
114
115 /*
116 * get a kstat handle and update the user's kstat chain
117 */
118 if( kctl == NULL ){
119 glibtop_warn_io_r (server, "kstat_open ()");
120 free( module );
121 return( 0 );
122 }
123 while( kstat_chain_update( kctl ) != 0 )
124 ;
125
126 /*
127 * traverse the kstat chain
128 * to find the appropriate statistics
129 */
130 if( (ksp = kstat_lookup( kctl,
131 module, 0, name )) == NULL ) {
132 free( module );
133 return( 0 );
134 }
135 if( kstat_read( kctl, ksp, NULL ) == -1 ) {
136 free( module );
137 return( 0 );
138 }
139 free( module );
140
141 /*
142 * lookup & store the data
143 */
144 kdata = (kstat_named_t *) kstat_data_lookup( ksp, "ipackets" );
145 if( kdata != NULL ) {
146 buf->packets_in= kdata->value.ul;
147 }
148 kdata = (kstat_named_t *) kstat_data_lookup( ksp, "opackets" );
149 if( kdata != NULL ) {
150 buf->packets_out = kdata->value.ul;
151 }
152 kdata = (kstat_named_t *) kstat_data_lookup( ksp, "rbytes" );
153 if( kdata != NULL ) {
154 buf->bytes_in =kdata->value.ul;
155 }
156 kdata = (kstat_named_t *) kstat_data_lookup( ksp, "obytes" );
157 if( kdata != NULL ) {
158 buf->bytes_out =kdata->value.ul;
159 }
160 kdata = (kstat_named_t *) kstat_data_lookup( ksp, "ierrors" );
161 if( kdata != NULL ) {
162 buf->errors_in = kdata->value.ul;
163 }
164 kdata = (kstat_named_t *) kstat_data_lookup( ksp, "oerrors" );
165 if( kdata != NULL ) {
166 buf->errors_out = kdata->value.ul;
167 }
168 kdata = (kstat_named_t *) kstat_data_lookup( ksp, "collisions" );
169 if( kdata != NULL ) {
170 buf->collisions = kdata->value.ul;
171 }
172
173 /* Compute total valules. */
174
175 buf->bytes_total = buf->bytes_in + buf->bytes_out;
176 buf->packets_total = buf->packets_in + buf->packets_out;
177 buf->errors_total = buf->errors_in + buf->errors_out;
178 /* And now the flags. */
179 buf->flags |= _glibtop_sysdeps_netload;
180 buf->flags |= _glibtop_sysdeps_netload_bytes;
181 buf->flags |= _glibtop_sysdeps_netload_packets;
182
183 /* finished */
184 }
185
186 /* Provides network statistics. */
187
188 void
glibtop_get_netload_s(glibtop * server,glibtop_netload * buf,const char * interface)189 glibtop_get_netload_s (glibtop *server, glibtop_netload *buf,
190 const char *interface)
191 {
192 int skfd;
193 memset (buf, 0, sizeof (glibtop_netload));
194
195 /* set flag */
196 skfd = socket (PF_INET, SOCK_DGRAM, 0);
197 if (skfd) {
198 struct ifreq ifr;
199
200 g_strlcpy (ifr.ifr_name, interface, sizeof ifr.ifr_name);
201 if (ioctl (skfd, SIOCGIFFLAGS, &ifr) >= 0) {
202 const unsigned long long flags = ifr.ifr_flags;
203
204 buf->flags |= (1L << GLIBTOP_NETLOAD_IF_FLAGS);
205
206 if (flags & IFF_UP)
207 buf->if_flags |= (1L << GLIBTOP_IF_FLAGS_UP);
208
209 if (flags & IFF_BROADCAST)
210 buf->if_flags |= (1L << GLIBTOP_IF_FLAGS_BROADCAST);
211
212 if (flags & IFF_DEBUG)
213 buf->if_flags |= (1L << GLIBTOP_IF_FLAGS_DEBUG);
214
215 if (flags & IFF_LOOPBACK)
216 buf->if_flags |= (1L << GLIBTOP_IF_FLAGS_LOOPBACK);
217
218 if (flags & IFF_POINTOPOINT)
219 buf->if_flags |= (1L << GLIBTOP_IF_FLAGS_POINTOPOINT);
220
221 if (flags & IFF_RUNNING)
222 buf->if_flags |= (1L << GLIBTOP_IF_FLAGS_RUNNING);
223
224 if (flags & IFF_NOARP)
225 buf->if_flags |= (1L << GLIBTOP_IF_FLAGS_NOARP);
226
227 if (flags & IFF_PROMISC)
228 buf->if_flags |= (1L << GLIBTOP_IF_FLAGS_PROMISC);
229
230 if (flags & IFF_ALLMULTI)
231 buf->if_flags |= (1L << GLIBTOP_IF_FLAGS_ALLMULTI);
232
233 if (flags & IFF_MULTICAST)
234 buf->if_flags |= (1L << GLIBTOP_IF_FLAGS_MULTICAST);
235 }
236
237 g_strlcpy (ifr.ifr_name, interface, sizeof ifr.ifr_name);
238 if (!ioctl (skfd, SIOCGIFADDR, &ifr)) {
239 buf->address = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr;
240 buf->flags |= (1L << GLIBTOP_NETLOAD_ADDRESS);
241 }
242
243 g_strlcpy (ifr.ifr_name, interface, sizeof ifr.ifr_name);
244 if (!ioctl (skfd, SIOCGIFNETMASK, &ifr)) {
245 buf->subnet = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr;
246 buf->flags |= (1L << GLIBTOP_NETLOAD_SUBNET);
247 }
248 close (skfd);
249 }
250
251 /*
252 * Statistics
253 */
254
255 solaris_stats(server, buf, interface);
256
257 }
258