1 /******************************************************************************
2 * bwm-ng parsing and retrieve stuff *
3 * *
4 * Copyright (C) 2004-2007 Volker Gropp (bwmng@gropp.org) *
5 * *
6 * for more info read README. *
7 * *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program; if not, write to the Free Software *
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
21 * *
22 *****************************************************************************/
23
24 #include "sysctl.h"
25
26 #ifdef SYSCTL
27 /* do the actual work, get and print stats if verbose */
get_iface_stats_sysctl(char verbose)28 void get_iface_stats_sysctl (char verbose) {
29 size_t size;
30 int mib[] = {CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, 0};
31 char *bsd_if_buf=NULL, *next=NULL, *lim=NULL;
32 char iface_is_up=0;
33 struct if_msghdr *ifmhdr, *nextifmhdr;
34 struct sockaddr_dl *saddr;
35
36 char *name=NULL;
37
38 int hidden_if=0,current_if_num=0,my_errno=0;
39 t_iface_speed_stats tmp_if_stats;
40 t_iface_speed_stats stats; /* local struct, used to calc total values */
41
42 memset(&stats,0,(size_t)sizeof(t_iface_speed_stats)); /* init it */
43
44 if (sysctl(mib, 6, NULL, &size, NULL, 0) < 0)
45 deinit(1, "sysctl failed: %s\n",strerror(errno));
46 if (!(bsd_if_buf = malloc(size))) deinit(1, "no memory: %s\n",strerror(errno));
47 memset(bsd_if_buf,0,size);
48 if (sysctl(mib, 6, bsd_if_buf, &size, NULL, 0) < 0) {
49 my_errno=errno;
50 free(bsd_if_buf);
51 deinit(1, "sysctl failed: %s\n",strerror(my_errno));
52 }
53
54 lim = (bsd_if_buf + size);
55
56 next = bsd_if_buf;
57 /* loop either while netstat enabled and still lines to read
58 * or still buffer (buf) left */
59 while (next < (bsd_if_buf + size)) {
60 /* BSD sysctl code */
61 ifmhdr = (struct if_msghdr *) next;
62 if (ifmhdr->ifm_type != RTM_IFINFO) break;
63 next += ifmhdr->ifm_msglen;
64 while (next < lim) {
65 nextifmhdr = (struct if_msghdr *) next;
66 if (nextifmhdr->ifm_type != RTM_NEWADDR) break;
67 next += nextifmhdr->ifm_msglen;
68 }
69 saddr = (struct sockaddr_dl *) (ifmhdr + 1);
70 if(saddr->sdl_family != AF_LINK) continue;
71 iface_is_up= (show_all_if || (ifmhdr->ifm_flags & IFF_UP));
72 /* we have to copy here to use saddr->sdl_nlen */
73 name=(char *)malloc(saddr->sdl_nlen+1);
74 if (!name) {
75 deinit(1,"mem alloc failed: %s\n",strerror(errno));
76 }
77
78 strncpy(name,saddr->sdl_data,saddr->sdl_nlen);
79 name[saddr->sdl_nlen]='\0';
80 tmp_if_stats.bytes.in=ifmhdr->ifm_data.ifi_ibytes;
81 tmp_if_stats.bytes.out=ifmhdr->ifm_data.ifi_obytes;
82 tmp_if_stats.packets.in=ifmhdr->ifm_data.ifi_ipackets;
83 tmp_if_stats.packets.out=ifmhdr->ifm_data.ifi_opackets;
84 tmp_if_stats.errors.in=ifmhdr->ifm_data.ifi_ierrors;
85 tmp_if_stats.errors.out=ifmhdr->ifm_data.ifi_oerrors;
86 /* init new interfaces and add fetched data to old or new one */
87 hidden_if = process_if_data (hidden_if, tmp_if_stats, &stats, name, current_if_num, verbose, iface_is_up);
88 free(name);
89 current_if_num++;
90 } /* fgets done (while) */
91 /* add to total stats and output current stats if verbose */
92 finish_iface_stats (verbose, stats, hidden_if,current_if_num);
93 /* close input stream */
94 free(bsd_if_buf);
95 return;
96 }
97 #endif
98
99 #if SYSCTLDISK_IN
100 #ifdef HAVE_STRUCT_SYSCTL
101 #define MIBCOUNT 3
102 #else
103 #define MIBCOUNT 2
104 #endif
get_iface_stats_sysctldisk(char verbose)105 void get_iface_stats_sysctldisk (char verbose) {
106 size_t size;
107 int mib[MIBCOUNT];
108 #if defined(HW_DISKCOUNT) && !defined(HAVE_STRUCT_DISKSTATS_DS_NAME) && defined(HAVE_STRUCT_DISKSTATS)
109 int diskcount = 0;
110 char *name_str = NULL;
111 char **name_arr = NULL;
112 char *ptr = NULL;
113 #endif
114 #if defined(HAVE_STRUCT_DISKSTATS)
115 #define DISK_STRUCT struct diskstats
116 #elif defined(HAVE_STRUCT_DISK_SYSCTL)
117 #define DISK_STRUCT struct disk_sysctl
118 #endif
119 DISK_STRUCT *dstats = NULL;
120 int num,i;
121 char *name=NULL;
122 char free_name=0;
123
124 int hidden_if=0,current_if_num=0;
125 t_iface_speed_stats tmp_if_stats;
126 t_iface_speed_stats stats; /* local struct, used to calc total values */
127
128 memset(&stats,0,(size_t)sizeof(t_iface_speed_stats)); /* init it */
129
130 mib[0]=CTL_HW;
131
132 /* get name list on systems without dk_name */
133 #if defined(HW_DISKCOUNT) && !defined(HAVE_STRUCT_DISKSTATS_DS_NAME) && defined(HAVE_STRUCT_DISKSTATS)
134 mib[1]=HW_DISKCOUNT;
135 if (sysctl(mib, 2, &diskcount, &size, NULL, 0) < 0)
136 deinit(1, "sysctl failed: %s\n",strerror(errno));
137
138 mib[1]=HW_DISKNAMES;
139 if (sysctl(mib, 2, NULL, &size, NULL, 0) < 0)
140 deinit(1, "sysctl failed: %s\n",strerror(errno));
141 if (!(name_str=(char *)malloc(size)))
142 deinit(1, "malloc failed for name_str: %s\n",strerror(errno));
143 if (sysctl(mib, 2, name_str, &size, NULL, 0) < 0) {
144 free(name_str);
145 deinit(1, "malloc failed for name_str: %s\n",strerror(errno));
146 }
147 /* assume comma seperated list as on OpenBSD */
148 if (!(name_arr = (char **)malloc(diskcount * sizeof(char *)))) {
149 free(name_str);
150 deinit(1, "malloc failed for name_arr: %s\n",strerror(errno));
151 }
152 ptr = name_str;
153 i = 0;
154 while (i<diskcount-1 && (next = strchr(ptr,','))) {
155 next[0]=0;
156 next++;
157 name_arr[i] = ptr;
158 ptr = next;
159 i++;
160 }
161 /* add last element aswell */
162 name_arr[i] = ptr;
163 #endif
164
165 /* get actual stats */
166 mib[1] = HW_DISKSTATS;
167 #ifdef HAVE_STRUCT_SYSCTL
168 mib[2] = sizeof(struct sysctl);
169 #endif
170
171 if (sysctl(mib, MIBCOUNT, NULL, &size, NULL, 0) < 0) {
172 #if HW_DISKCOUNT && !defined(HAVE_STRUCT_DISKSTATS_DS_NAME) && defined(HAVE_STRUCT_DISKSTATS)
173 free(name_str);
174 free(name_arr);
175 #endif
176 deinit(1, "sysctl failed: %s\n",strerror(errno));
177 }
178
179 num = size / sizeof(DISK_STRUCT);
180 if (!(dstats = (DISK_STRUCT *)malloc(size))) {
181 #if HW_DISKCOUNT && !defined(HAVE_STRUCT_DISKSTATS_DS_NAME) && defined(HAVE_STRUCT_DISKSTATS)
182 free(name_str);
183 free(name_arr);
184 #endif
185 deinit(1, "malloc failed: %s\n",strerror(errno));
186 }
187
188 if (sysctl(mib, MIBCOUNT, dstats, &size, NULL, 0) < 0) {
189 free(dstats);
190 #if HW_DISKCOUNT && !defined(HAVE_STRUCT_DISKSTATS_DS_NAME) && defined(HAVE_STRUCT_DISKSTATS)
191 free(name_str);
192 free(name_arr);
193 #endif
194 deinit(1, "sysctl failed: %s\n",strerror(errno));
195 }
196 for (i = 0; i < num; i++) {
197
198 #ifdef HAVE_STRUCT_DISKSTATS
199 #ifdef HAVE_STRUCT_DISKSTATS_DS_RBYTES
200 tmp_if_stats.bytes.in = dstats[i].ds_rbytes;
201 tmp_if_stats.bytes.out = dstats[i].ds_wbytes;
202 tmp_if_stats.packets.in = dstats[i].ds_rxfer;
203 tmp_if_stats.packets.out = dstats[i].ds_wxfer;
204 #else
205 tmp_if_stats.bytes.in = tmp_if_stats.bytes.out = (ullong)(dstats[i].ds_bytes / 2);
206 tmp_if_stats.packets.in = tmp_if_stats.packets.out = (ullong)(dstats[i].ds_xfer / 2);
207 #endif
208 #if !defined(HAVE_STRUCT_DISKSTATS_DS_NAME)
209 name = name_arr[i];
210 #else
211 name = dstats[i].ds_name;
212 #endif
213 #else
214 #ifdef HAVE_STRUCT_DISK_SYSCTL_DK_RBYTES
215 tmp_if_stats.bytes.in = dstats[i].dk_rbytes;
216 tmp_if_stats.bytes.out = dstats[i].dk_wbytes;
217 tmp_if_stats.packets.in = dstats[i].dk_rxfer;
218 tmp_if_stats.packets.out = dstats[i].dk_wxfer;
219 #else
220 tmp_if_stats.bytes.in = tmp_if_stats.bytes.out = (ullong)(dstats[i].dk_bytes / 2);
221 tmp_if_stats.packets.in = tmp_if_stats.packets.out = (ullong)(dstats[i].dk_xfer / 2);
222 #endif
223 name = dstats[i].dk_name;
224 #endif
225 tmp_if_stats.errors.in = tmp_if_stats.errors.out = 0;
226
227 if (!name || name[0]==0) {
228 name=malloc(11);
229 snprintf((char *)name,10,"unknown%i",current_if_num);
230 name[10]=0;
231 free_name=1;
232 }
233
234 hidden_if = process_if_data (hidden_if, tmp_if_stats, &stats, name, current_if_num, verbose, (tmp_if_stats.bytes.in != 0 || tmp_if_stats.bytes.out != 0));
235
236 if (free_name) free(name);
237 current_if_num++;
238 }
239 /* add to total stats and output current stats if verbose */
240 finish_iface_stats (verbose, stats, hidden_if,current_if_num);
241 free(dstats);
242 #if HW_DISKCOUNT && !defined(HAVE_STRUCT_DISKSTATS_DS_NAME) && defined(HAVE_STRUCT_DISKSTATS)
243 free(name_str);
244 free(name_arr);
245 #endif
246 }
247 #endif
248
249
250