"Fossies" - the Fresh Open Source Software Archive 
Member "vnstat-2.9/src/ifinfo.c" (22 Aug 2021, 10704 Bytes) of package /linux/misc/vnstat-2.9.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "ifinfo.c" see the
Fossies "Dox" file reference documentation and the last
Fossies "Diffs" side-by-side code changes report:
2.7_vs_2.8.
1 #include "common.h"
2 #include "ibw.h"
3 #include "ifinfo.h"
4
5 int getifinfo(const char *iface)
6 {
7 char inface[32];
8
9 ifinfo.filled = 0;
10 ifinfo.timestamp = 0;
11
12 #if defined(__linux__) && HAVE_LINUX_RTNETLINK_H
13 if (cfg.is64bit == -2) {
14 #if HAVE_DECL_IFLA_STATS64
15 ifinfo.is64bit = 1;
16 #else
17 ifinfo.is64bit = 0;
18 #endif
19 } else {
20 ifinfo.is64bit = (short)cfg.is64bit;
21 }
22 #else
23 if (cfg.is64bit < 0) {
24 ifinfo.is64bit = -1;
25 } else {
26 ifinfo.is64bit = (short)cfg.is64bit;
27 }
28 #endif
29
30 if (strcmp(iface, "default") == 0) {
31 strncpy_nt(inface, cfg.iface, 32);
32 } else {
33 strncpy_nt(inface, iface, 32);
34 }
35
36 #if defined(__linux__) || defined(CHECK_VNSTAT)
37 /* try getting interface info from /proc */
38 if (readproc(inface) == 1) {
39 ifinfo.timestamp = time(NULL);
40 return 1;
41 } else {
42 if (debug)
43 printf("Failed to use %s as source.\n", PROCNETDEV);
44 }
45
46 /* try getting interface info from /sys */
47 if (readsysclassnet(inface) == 1) {
48 ifinfo.timestamp = time(NULL);
49 return 1;
50 }
51
52 #elif defined(BSD_VNSTAT)
53 if (readifaddrs(inface) == 1) {
54 ifinfo.timestamp = time(NULL);
55 return 1;
56 }
57 #endif
58
59 snprintf(errorstring, 1024, "Unable to get interface \"%s\" statistics.", inface);
60 printe(PT_Error);
61 return 0;
62 }
63
64 int getifliststring(char **ifacelist, int showspeed)
65 {
66 char temp[64];
67 iflist *ifl = NULL, *ifl_iterator = NULL;
68
69 /* initialize list string */
70 *ifacelist = (char *)malloc(sizeof(char));
71 if (*ifacelist == NULL) {
72 panicexit(__FILE__, __LINE__);
73 }
74 *ifacelist[0] = '\0';
75
76 if (getiflist(&ifl, showspeed, 1) > 0) {
77
78 ifl_iterator = ifl;
79
80 while (ifl_iterator != NULL) {
81 *ifacelist = (char *)realloc(*ifacelist, ((strlen(*ifacelist) + strlen(ifl_iterator->interface) + 2) * sizeof(char)));
82 if (*ifacelist == NULL) {
83 panicexit(__FILE__, __LINE__);
84 }
85 strcat(*ifacelist, ifl_iterator->interface);
86 strcat(*ifacelist, " ");
87
88 if (showspeed && ifl_iterator->bandwidth > 0) {
89 snprintf(temp, 64, "(%u Mbit) ", ifl_iterator->bandwidth);
90 *ifacelist = (char *)realloc(*ifacelist, ((strlen(*ifacelist) + strlen(temp) + 1) * sizeof(char)));
91 if (*ifacelist == NULL) {
92 panicexit(__FILE__, __LINE__);
93 }
94 strcat(*ifacelist, temp);
95 }
96
97 ifl_iterator = ifl_iterator->next;
98 }
99
100 iflistfree(&ifl);
101 return 1;
102 }
103
104 iflistfree(&ifl);
105 return 0;
106 }
107
108 int getiflist(iflist **ifl, const int getspeed, const int validate)
109 {
110 int result = 0;
111 int32_t maxbw = cfg.maxbw;
112
113 /* disable MaxBandwidth during list creation to avoid having it being set as the default value when nothing is detected */
114 cfg.maxbw = 0;
115 #if defined(__linux__) || defined(CHECK_VNSTAT)
116 result = getiflist_linux(ifl, getspeed, validate);
117 #elif defined(BSD_VNSTAT)
118 result = getiflist_bsd(ifl, getspeed, validate);
119 #else
120 #error vnStat only supports Linux and BSD like systems
121 #endif
122 cfg.maxbw = maxbw;
123 return result;
124 }
125
126 #if defined(__linux__) || defined(CHECK_VNSTAT)
127 int getiflist_linux(iflist **ifl, const int getspeed, const int validate)
128 {
129 char temp[64];
130 char interface[32];
131 FILE *fp;
132 DIR *dp;
133 struct dirent *di;
134 char procline[512];
135 uint32_t bwlimit = 0;
136
137 if ((fp = fopen(PROCNETDEV, "r")) != NULL) {
138
139 /* make list of interfaces */
140 while (fgets(procline, 512, fp) != NULL) {
141 sscanf(procline, "%63s", temp);
142 if (strlen(temp) > 0 && (isdigit(temp[(strlen(temp) - 1)]) || temp[(strlen(temp) - 1)] == ':')) {
143 sscanf(temp, "%31[^':']s", interface);
144 if (validate && !isifvalid(interface)) {
145 continue;
146 }
147 bwlimit = 0;
148 if (getspeed && ibwget(interface, &bwlimit)) {
149 iflistadd(ifl, interface, bwlimit);
150 } else {
151 iflistadd(ifl, interface, 0);
152 }
153 }
154 }
155
156 fclose(fp);
157 return 1;
158
159 } else {
160
161 if ((dp = opendir(SYSCLASSNET)) != NULL) {
162
163 /* make list of interfaces */
164 while ((di = readdir(dp))) {
165 if (di->d_name[0] == '.' || strlen(di->d_name) > 31) {
166 continue;
167 }
168 if (validate && !isifvalid(di->d_name)) {
169 continue;
170 }
171 bwlimit = 0;
172 if (getspeed && ibwget(di->d_name, &bwlimit)) {
173 iflistadd(ifl, di->d_name, bwlimit);
174 } else {
175 iflistadd(ifl, di->d_name, 0);
176 }
177 }
178
179 closedir(dp);
180 return 1;
181 }
182 }
183
184 return 0;
185 }
186 #elif defined(BSD_VNSTAT)
187 int getiflist_bsd(iflist **ifl, const int getspeed, const int validate)
188 {
189 struct ifaddrs *ifap, *ifa;
190 uint32_t bwlimit = 0;
191
192 if (getifaddrs(&ifap) >= 0) {
193
194 /* make list of interfaces */
195 for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
196 if (ifa->ifa_addr->sa_family != AF_LINK || strlen(ifa->ifa_name) > 31) {
197 continue;
198 }
199 if (validate && !isifvalid(ifa->ifa_name)) {
200 continue;
201 }
202 bwlimit = 0;
203 if (getspeed && ibwget(ifa->ifa_name, &bwlimit)) {
204 iflistadd(ifl, ifa->ifa_name, getifspeed(ifa->ifa_name));
205 } else {
206 iflistadd(ifl, ifa->ifa_name, 0);
207 }
208 }
209
210 freeifaddrs(ifap);
211 return 1;
212 }
213
214 return 0;
215 }
216 #endif
217
218 int readproc(const char *iface)
219 {
220 FILE *fp;
221 char temp[4][64], procline[512], *proclineptr, ifaceid[33];
222 int check;
223
224 if ((fp = fopen(PROCNETDEV, "r")) == NULL) {
225 if (debug)
226 printf("Error (debug): Unable to read %s: %s\n", PROCNETDEV, strerror(errno));
227 return 0;
228 }
229
230 strncpy_nt(ifaceid, iface, 32);
231 strcat(ifaceid, ":");
232
233 check = 0;
234 while (fgets(procline, 512, fp) != NULL) {
235 sscanf(procline, "%63s", temp[0]);
236 if (strncmp(ifaceid, temp[0], strlen(ifaceid)) == 0) {
237 /* if (debug)
238 printf("\n%s\n", procline); */
239 check = 1;
240 break;
241 }
242 }
243 fclose(fp);
244
245 if (check == 0) {
246 if (debug)
247 printf("Requested interface \"%s\" not found.\n", iface);
248 return 0;
249 } else {
250
251 strncpy_nt(ifinfo.name, iface, 32);
252
253 /* get rx and tx from procline */
254 proclineptr = strchr(procline, ':');
255 sscanf(proclineptr + 1, "%63s %63s %*s %*s %*s %*s %*s %*s %63s %63s", temp[0], temp[1], temp[2], temp[3]);
256
257 ifinfo.rx = strtoull(temp[0], (char **)NULL, 0);
258 ifinfo.tx = strtoull(temp[2], (char **)NULL, 0);
259
260 /* daemon doesn't need packet data */
261 if (!noexit) {
262 ifinfo.rxp = strtoull(temp[1], (char **)NULL, 0);
263 ifinfo.txp = strtoull(temp[3], (char **)NULL, 0);
264 }
265
266 ifinfo.filled = 1;
267 }
268
269 return 1;
270 }
271
272 int readsysclassnet(const char *iface)
273 {
274 FILE *fp;
275 char path[64], file[76], buffer[64];
276
277 strncpy_nt(ifinfo.name, iface, 32);
278
279 snprintf(path, 64, "%s/%s/statistics", SYSCLASSNET, iface);
280
281 if (debug)
282 printf("path: %s\n", path);
283
284 /* rx bytes */
285 snprintf(file, 76, "%s/rx_bytes", path);
286 if ((fp = fopen(file, "r")) == NULL) {
287 if (debug)
288 printf("Unable to read: %s - %s\n", file, strerror(errno));
289 return 0;
290 } else {
291 if (fgets(buffer, 64, fp) != NULL) {
292 ifinfo.rx = strtoull(buffer, (char **)NULL, 0);
293 } else {
294 fclose(fp);
295 return 0;
296 }
297 }
298 fclose(fp);
299
300 /* tx bytes */
301 snprintf(file, 76, "%s/tx_bytes", path);
302 if ((fp = fopen(file, "r")) == NULL) {
303 if (debug)
304 printf("Unable to read: %s - %s\n", file, strerror(errno));
305 return 0;
306 } else {
307 if (fgets(buffer, 64, fp) != NULL) {
308 ifinfo.tx = strtoull(buffer, (char **)NULL, 0);
309 } else {
310 fclose(fp);
311 return 0;
312 }
313 }
314 fclose(fp);
315
316 /* daemon doesn't need packet data */
317 if (!noexit) {
318
319 /* rx packets */
320 snprintf(file, 76, "%s/rx_packets", path);
321 if ((fp = fopen(file, "r")) == NULL) {
322 if (debug)
323 printf("Unable to read: %s - %s\n", file, strerror(errno));
324 return 0;
325 } else {
326 if (fgets(buffer, 64, fp) != NULL) {
327 ifinfo.rxp = strtoull(buffer, (char **)NULL, 0);
328 } else {
329 fclose(fp);
330 return 0;
331 }
332 }
333 fclose(fp);
334
335 /* tx packets */
336 snprintf(file, 76, "%s/tx_packets", path);
337 if ((fp = fopen(file, "r")) == NULL) {
338 if (debug)
339 printf("Unable to read: %s - %s\n", file, strerror(errno));
340 return 0;
341 } else {
342 if (fgets(buffer, 64, fp) != NULL) {
343 ifinfo.txp = strtoull(buffer, (char **)NULL, 0);
344 } else {
345 fclose(fp);
346 return 0;
347 }
348 }
349 fclose(fp);
350 }
351
352 ifinfo.filled = 1;
353
354 return 1;
355 }
356
357 #if defined(BSD_VNSTAT)
358 int getifdata(const char *iface, struct if_data *ifd)
359 {
360 struct ifaddrs *ifap, *ifa;
361 int check = 0;
362
363 if (getifaddrs(&ifap) < 0) {
364 if (debug)
365 printf("readifaddrs:getifaddrs() failed.\n");
366 return 0;
367 }
368 for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
369 if ((strcmp(ifa->ifa_name, iface) == 0) && (ifa->ifa_addr->sa_family == AF_LINK)) {
370 if (ifa->ifa_data != NULL) {
371 memcpy(ifd, ifa->ifa_data, sizeof(struct if_data));
372 check = 1;
373 }
374 break;
375 }
376 }
377 freeifaddrs(ifap);
378
379 return check;
380 }
381
382 int readifaddrs(const char *iface)
383 {
384 struct if_data ifd;
385
386 if (!getifdata(iface, &ifd)) {
387 if (debug)
388 printf("Requested interface \"%s\" not found.\n", iface);
389 return 0;
390 } else {
391 strncpy_nt(ifinfo.name, iface, 32);
392 ifinfo.rx = ifd.ifi_ibytes;
393 ifinfo.tx = ifd.ifi_obytes;
394 ifinfo.rxp = ifd.ifi_ipackets;
395 ifinfo.txp = ifd.ifi_opackets;
396 ifinfo.filled = 1;
397
398 if (cfg.is64bit == -2) {
399 if (sizeof(ifd.ifi_ibytes) == 8) {
400 ifinfo.is64bit = 1;
401 } else {
402 ifinfo.is64bit = 0;
403 }
404 }
405 }
406
407 return 1;
408 }
409 #endif
410
411 uint32_t getifspeed(const char *iface)
412 {
413 uint64_t speed = 0;
414
415 #if defined(__linux__)
416
417 FILE *fp;
418 char file[64], buffer[64];
419
420 snprintf(file, 64, "%s/%s/speed", SYSCLASSNET, iface);
421
422 if ((fp = fopen(file, "r")) == NULL) {
423 if (debug)
424 printf("Unable to open: %s - %s\n", file, strerror(errno));
425 return 0;
426 } else {
427 if (fgets(buffer, 64, fp) != NULL) {
428 speed = strtoull(buffer, (char **)NULL, 0);
429 } else {
430 if (debug)
431 printf("Unable to read: %s - %s\n", file, strerror(errno));
432 fclose(fp);
433 return 0;
434 }
435 }
436 fclose(fp);
437
438 #elif defined(BSD_VNSTAT)
439
440 struct if_data ifd;
441
442 if (!getifdata(iface, &ifd)) {
443 if (debug)
444 printf("Requested interface \"%s\" not found.\n", iface);
445 return 0;
446 } else {
447 speed = (uint64_t)ifd.ifi_baudrate;
448 }
449
450 #endif
451
452 if (debug)
453 printf("getifspeed: \"%s\": %" PRIu64 "\n", iface, speed);
454
455 if (speed > 1000000) {
456 speed = 0;
457 }
458 return (uint32_t)speed;
459 }
460
461 int isifavailable(const char *iface)
462 {
463 int ret = 0, printstatus;
464
465 printstatus = disableprints;
466 disableprints = 1;
467 ret = getifinfo(iface);
468 disableprints = printstatus;
469
470 return ret;
471 }
472
473 int isifvalid(const char *iface)
474 {
475 if (strstr(iface, ":") != NULL) {
476 return 0;
477 } else if (strcmp(iface, "lo") == 0) {
478 return 0;
479 } else if (strcmp(iface, "lo0") == 0) {
480 return 0;
481 } else if (strcmp(iface, "sit0") == 0) {
482 return 0;
483 }
484 return 1;
485 }
486
487 /* tun interfaces have speed hardcoded as 10 in the Linux kernel regardless of used interface and can't
488 be trusted to provide correct details as a result even if the information is available:
489 https://github.com/torvalds/linux/blob/9d31d2338950293ec19d9b095fbaa9030899dcb4/drivers/net/tun.c#L3456 */
490 int istun(const char *iface)
491 {
492 #if defined(__linux__)
493 if (strlen(iface) > 3 && strncmp(iface, "tun", 3) == 0) {
494 if (isdigit(iface[3])) {
495 return 1;
496 }
497 }
498 #endif
499 return 0;
500 }