14677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger/* lnstat.c:  Unified linux network statistics
24677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger *
34677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger * Copyright (C) 2004 by Harald Welte <laforge@gnumonks.org>
44677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger *
54677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger * Development of this code was funded by Astaro AG, http://www.astaro.com/
64677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger *
74677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger * Based on original concept and ideas from predecessor rtstat.c:
84677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger *
94677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger * Copyright 2001 by Robert Olsson <robert.olsson@its.uu.se>
104677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger *                                 Uppsala University, Sweden
114677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger *
124677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger * This program is free software; you can redistribute it and/or modify
134677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger * it under the terms of the GNU General Public License as published by
144677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger * the Free Software Foundation; either version 2 of the License, or
154677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger * (at your option) any later version.
164677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger *
174677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger */
184677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
194677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger#include <unistd.h>
204677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger#include <stdio.h>
214677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger#include <stdlib.h>
224677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger#include <string.h>
234677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger#include <dirent.h>
244677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger#include <limits.h>
254677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger#include <time.h>
264677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
274677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger#include <sys/time.h>
284677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger#include <sys/types.h>
294677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
304677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger#include "lnstat.h"
314677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
324677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger/* size of temp buffer used to read lines from procfiles */
334677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger#define FGETS_BUF_SIZE 1024
344677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
354677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
364677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger#define RTSTAT_COMPAT_LINE "entries  in_hit in_slow_tot in_no_route in_brd in_martian_dst in_martian_src  out_hit out_slow_tot out_slow_mc  gc_total gc_ignored gc_goal_miss gc_dst_overflow in_hlist_search out_hlist_search\n"
374677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
384677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger/* Read (and summarize for SMP) the different stats vars. */
394677a549831336400e16210e6f12251dc07d5232osdl.net!shemmingerstatic int scan_lines(struct lnstat_file *lf, int i)
404677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger{
41db3ef44c5433aa50bae6f88736ad350fb14fc2cfPhil Sutter	char buf[FGETS_BUF_SIZE];
424677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	int j, num_lines = 0;
434677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
444677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	for (j = 0; j < lf->num_fields; j++)
454677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		lf->fields[j].values[i] = 0;
464677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
47db3ef44c5433aa50bae6f88736ad350fb14fc2cfPhil Sutter	rewind(lf->fp);
48db3ef44c5433aa50bae6f88736ad350fb14fc2cfPhil Sutter	/* skip first line */
49db3ef44c5433aa50bae6f88736ad350fb14fc2cfPhil Sutter	if (!lf->compat && !fgets(buf, sizeof(buf)-1, lf->fp))
50db3ef44c5433aa50bae6f88736ad350fb14fc2cfPhil Sutter		return -1;
51db3ef44c5433aa50bae6f88736ad350fb14fc2cfPhil Sutter
52db3ef44c5433aa50bae6f88736ad350fb14fc2cfPhil Sutter	while(!feof(lf->fp) && fgets(buf, sizeof(buf)-1, lf->fp)) {
534677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		char *ptr = buf;
544677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
554677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		num_lines++;
564677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
574677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		gettimeofday(&lf->last_read, NULL);
584677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
59f5f1a6c5836a405381fb9d4be74d5ddf98404db1osdl.net!shemminger		for (j = 0; j < lf->num_fields; j++) {
60f5f1a6c5836a405381fb9d4be74d5ddf98404db1osdl.net!shemminger			unsigned long f = strtoul(ptr, &ptr, 16);
61ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger			if (j == 0)
627339c0bb74e7e55ad70c29ced5628f26dd821900shemminger				lf->fields[j].values[i] = f;
63f5f1a6c5836a405381fb9d4be74d5ddf98404db1osdl.net!shemminger			else
64f5f1a6c5836a405381fb9d4be74d5ddf98404db1osdl.net!shemminger				lf->fields[j].values[i] += f;
65f5f1a6c5836a405381fb9d4be74d5ddf98404db1osdl.net!shemminger		}
664677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	}
674677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	return num_lines;
684677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger}
694677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
70ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemmingerstatic int time_after(struct timeval *last,
71ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger		      struct timeval *tout,
724677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		      struct timeval *now)
734677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger{
744677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	if (now->tv_sec > last->tv_sec + tout->tv_sec)
754677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		return 1;
764677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
774677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	if (now->tv_sec == last->tv_sec + tout->tv_sec) {
784677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		if (now->tv_usec > last->tv_usec + tout->tv_usec)
794677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger			return 1;
804677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	}
814677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
824677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	return 0;
834677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger}
844677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
854677a549831336400e16210e6f12251dc07d5232osdl.net!shemmingerint lnstat_update(struct lnstat_file *lnstat_files)
864677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger{
874677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	struct lnstat_file *lf;
884677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	struct timeval tv;
894677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
904677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	gettimeofday(&tv, NULL);
914677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
924677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	for (lf = lnstat_files; lf; lf = lf->next) {
934677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		if (time_after(&lf->last_read, &lf->interval, &tv)) {
944677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger			int i;
954677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger			struct lnstat_field *lfi;
964677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
974677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger			scan_lines(lf, 1);
984677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
99ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger			for (i = 0, lfi = &lf->fields[i];
1004677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger			     i < lf->num_fields; i++, lfi = &lf->fields[i]) {
1014677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger				if (i == 0)
1024677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger					lfi->result = lfi->values[1];
1034677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger				else
1044677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger					lfi->result = (lfi->values[1]-lfi->values[0])
1054677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger				    			/ lf->interval.tv_sec;
1064677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger			}
1074677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
1084677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger			scan_lines(lf, 0);
1094677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		}
1104677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	}
1114677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
1124677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	return 0;
1134677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger}
1144677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
1154677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger/* scan first template line and fill in per-field data structures */
1164677a549831336400e16210e6f12251dc07d5232osdl.net!shemmingerstatic int __lnstat_scan_fields(struct lnstat_file *lf, char *buf)
1174677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger{
1184677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	char *tok;
1194677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	int i;
1204677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
1214677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	tok = strtok(buf, " \t\n");
1224677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	for (i = 0; i < LNSTAT_MAX_FIELDS_PER_LINE; i++) {
1234677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		lf->fields[i].file = lf;
1244677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		strncpy(lf->fields[i].name, tok, LNSTAT_MAX_FIELD_NAME_LEN);
1254677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		/* has to be null-terminate since we initialize to zero
1264677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		 * and field size is NAME_LEN + 1 */
1274677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		tok = strtok(NULL, " \t\n");
1284677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		if (!tok) {
1294677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger			lf->num_fields = i+1;
1304677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger			return 0;
1314677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		}
1324677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	}
1334677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	return 0;
1344677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger}
1354677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
1364677a549831336400e16210e6f12251dc07d5232osdl.net!shemmingerstatic int lnstat_scan_fields(struct lnstat_file *lf)
1374677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger{
1384677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	char buf[FGETS_BUF_SIZE];
1394677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
1404677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	rewind(lf->fp);
141d572ed4d0af79eb597469d3f1a84456782c64f24Phil Sutter	if (!fgets(buf, sizeof(buf)-1, lf->fp))
142d572ed4d0af79eb597469d3f1a84456782c64f24Phil Sutter		return -1;
1434677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
1444677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	return __lnstat_scan_fields(lf, buf);
1454677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger}
1464677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
1474677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger/* fake function emulating lnstat_scan_fields() for old kernels */
1484677a549831336400e16210e6f12251dc07d5232osdl.net!shemmingerstatic int lnstat_scan_compat_rtstat_fields(struct lnstat_file *lf)
1494677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger{
1504677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	char buf[FGETS_BUF_SIZE];
1514677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
1524677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	strncpy(buf, RTSTAT_COMPAT_LINE, sizeof(buf)-1);
1534677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
1544677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	return __lnstat_scan_fields(lf, buf);
1554677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger}
1564677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
1574677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger/* find out whether string 'name; is in given string array */
1584677a549831336400e16210e6f12251dc07d5232osdl.net!shemmingerstatic int name_in_array(const int num, const char **arr, const char *name)
1594677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger{
1604677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	int i;
1614677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	for (i = 0; i < num; i++) {
1624677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		if (!strcmp(arr[i], name))
1634677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger			return 1;
1644677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	}
1654677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	return 0;
1664677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger}
1674677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
1684677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger/* allocate lnstat_file and open given file */
1694677a549831336400e16210e6f12251dc07d5232osdl.net!shemmingerstatic struct lnstat_file *alloc_and_open(const char *path, const char *file)
1704677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger{
1714677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	struct lnstat_file *lf;
1724677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
1734677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	/* allocate */
1744677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	lf = malloc(sizeof(*lf));
175b90b773ca6aa1b1a39d76186d1a7639a13f5c916Stephen Hemminger	if (!lf) {
176b90b773ca6aa1b1a39d76186d1a7639a13f5c916Stephen Hemminger		fprintf(stderr, "out of memory\n");
1774677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		return NULL;
178b90b773ca6aa1b1a39d76186d1a7639a13f5c916Stephen Hemminger	}
1794677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
1804677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	/* initialize */
1814677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	memset(lf, 0, sizeof(*lf));
1824677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
1834677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	/* de->d_name is guaranteed to be <= NAME_MAX */
1844677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	strcpy(lf->basename, file);
1854677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	strcpy(lf->path, path);
1864677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	strcat(lf->path, "/");
1874677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	strcat(lf->path, lf->basename);
1884677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
1894677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	/* initialize to default */
1904677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	lf->interval.tv_sec = 1;
1914677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
1924677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	/* open */
1934677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	lf->fp = fopen(lf->path, "r");
1944677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	if (!lf->fp) {
195b90b773ca6aa1b1a39d76186d1a7639a13f5c916Stephen Hemminger		perror(lf->path);
1964677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		free(lf);
1974677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		return NULL;
1984677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	}
1994677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
2004677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	return lf;
2014677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger}
2024677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
2034677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
2044677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger/* lnstat_scan_dir - find and parse all available statistics files/fields */
2054677a549831336400e16210e6f12251dc07d5232osdl.net!shemmingerstruct lnstat_file *lnstat_scan_dir(const char *path, const int num_req_files,
2064677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger				    const char **req_files)
2074677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger{
2084677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	DIR *dir;
2094677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	struct lnstat_file *lnstat_files = NULL;
2104677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	struct dirent *de;
2114677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
2124677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	if (!path)
2134677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		path = PROC_NET_STAT;
214ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger
2154677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	dir = opendir(path);
2164677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	if (!dir) {
2174677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		struct lnstat_file *lf;
2184677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		/* Old kernel, before /proc/net/stat was introduced */
2194677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		fprintf(stderr, "Your kernel doesn't have lnstat support. ");
2204677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
2214677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		/* we only support rtstat, not multiple files */
2224677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		if (num_req_files >= 2) {
2234677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger			fputc('\n', stderr);
2244677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger			return NULL;
2254677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		}
2264677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
2274677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		/* we really only accept rt_cache */
2284677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		if (num_req_files && !name_in_array(num_req_files,
2294677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger						    req_files, "rt_cache")) {
2304677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger			fputc('\n', stderr);
2314677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger			return NULL;
2324677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		}
2334677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
2344677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		fprintf(stderr, "Fallback to old rtstat-only operation\n");
2354677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
2364677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		lf = alloc_and_open("/proc/net", "rt_cache_stat");
2374677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		if (!lf)
2384677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger			return NULL;
2394677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		lf->compat = 1;
2404677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		strncpy(lf->basename, "rt_cache", sizeof(lf->basename));
2414677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
2424677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		/* FIXME: support for old files */
2434677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		if (lnstat_scan_compat_rtstat_fields(lf) < 0)
2444677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger			return NULL;
2454677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
2464677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		lf->next = lnstat_files;
2474677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		lnstat_files = lf;
2484677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		return lnstat_files;
2494677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	}
2504677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
2514677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	while ((de = readdir(dir))) {
2524677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		struct lnstat_file *lf;
2534677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
2544677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		if (de->d_type != DT_REG)
2554677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger			continue;
2564677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
2574677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		if (num_req_files && !name_in_array(num_req_files,
2584677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger						    req_files, de->d_name))
2594677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger			continue;
2604677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
2614677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		lf = alloc_and_open(path, de->d_name);
262b90b773ca6aa1b1a39d76186d1a7639a13f5c916Stephen Hemminger		if (!lf) {
263b90b773ca6aa1b1a39d76186d1a7639a13f5c916Stephen Hemminger			closedir(dir);
2644677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger			return NULL;
265b90b773ca6aa1b1a39d76186d1a7639a13f5c916Stephen Hemminger		}
2664677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
2674677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		/* fill in field structure */
268b90b773ca6aa1b1a39d76186d1a7639a13f5c916Stephen Hemminger		if (lnstat_scan_fields(lf) < 0) {
269b90b773ca6aa1b1a39d76186d1a7639a13f5c916Stephen Hemminger			closedir(dir);
2704677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger			return NULL;
271b90b773ca6aa1b1a39d76186d1a7639a13f5c916Stephen Hemminger		}
2724677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
2734677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		/* prepend to global list */
2744677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		lf->next = lnstat_files;
2754677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		lnstat_files = lf;
2764677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	}
2774677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	closedir(dir);
2784677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
2794677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	return lnstat_files;
2804677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger}
2814677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
2824677a549831336400e16210e6f12251dc07d5232osdl.net!shemmingerint lnstat_dump(FILE *outfd, struct lnstat_file *lnstat_files)
2834677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger{
2844677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	struct lnstat_file *lf;
2854677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
2864677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	for (lf = lnstat_files; lf; lf = lf->next) {
2874677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		int i;
2884677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
2894677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		fprintf(outfd, "%s:\n", lf->path);
2904677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
2914677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		for (i = 0; i < lf->num_fields; i++)
2924677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger			fprintf(outfd, "\t%2u: %s\n", i+1, lf->fields[i].name);
2934677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
2944677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	}
2954677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	return 0;
2964677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger}
2974677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
2984677a549831336400e16210e6f12251dc07d5232osdl.net!shemmingerstruct lnstat_field *lnstat_find_field(struct lnstat_file *lnstat_files,
2994677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger				       const char *name)
3004677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger{
3014677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	struct lnstat_file *lf;
3024677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	struct lnstat_field *ret = NULL;
3034677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	const char *colon = strchr(name, ':');
3044677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	char *file;
3054677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	const char *field;
3064677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
3074677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	if (colon) {
3084677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		file = strndup(name, colon-name);
3094677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		field = colon+1;
3104677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	} else {
3114677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		file = NULL;
3124677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		field = name;
3134677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	}
314ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger
3154677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	for (lf = lnstat_files; lf; lf = lf->next) {
3164677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		int i;
3174677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
3184677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		if (file && strcmp(file, lf->basename))
3194677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger			continue;
3204677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
3214677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		for (i = 0; i < lf->num_fields; i++) {
3224677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger			if (!strcmp(field, lf->fields[i].name)) {
3234677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger				ret = &lf->fields[i];
3244677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger				goto out;
3254677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger			}
3264677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		}
3274677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	}
3284677a549831336400e16210e6f12251dc07d5232osdl.net!shemmingerout:
32992de1c2c820816801681d76f5de7137a2b5996dfStephen Hemminger	free(file);
3304677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
3314677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	return ret;
3324677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger}
333