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{
414677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	int j, num_lines = 0;
424677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
434677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	for (j = 0; j < lf->num_fields; j++)
444677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		lf->fields[j].values[i] = 0;
454677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
464677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	while(!feof(lf->fp)) {
474677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		char buf[FGETS_BUF_SIZE];
484677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		char *ptr = buf;
494677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
504677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		num_lines++;
514677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
52ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger		fgets(buf, sizeof(buf)-1, lf->fp);
534677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		gettimeofday(&lf->last_read, NULL);
544677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
55f5f1a6c5836a405381fb9d4be74d5ddf98404db1osdl.net!shemminger		for (j = 0; j < lf->num_fields; j++) {
56f5f1a6c5836a405381fb9d4be74d5ddf98404db1osdl.net!shemminger			unsigned long f = strtoul(ptr, &ptr, 16);
57ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger			if (j == 0)
587339c0bb74e7e55ad70c29ced5628f26dd821900shemminger				lf->fields[j].values[i] = f;
59f5f1a6c5836a405381fb9d4be74d5ddf98404db1osdl.net!shemminger			else
60f5f1a6c5836a405381fb9d4be74d5ddf98404db1osdl.net!shemminger				lf->fields[j].values[i] += f;
61f5f1a6c5836a405381fb9d4be74d5ddf98404db1osdl.net!shemminger		}
624677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	}
634677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	return num_lines;
644677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger}
654677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
66ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemmingerstatic int time_after(struct timeval *last,
67ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger		      struct timeval *tout,
684677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		      struct timeval *now)
694677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger{
704677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	if (now->tv_sec > last->tv_sec + tout->tv_sec)
714677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		return 1;
724677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
734677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	if (now->tv_sec == last->tv_sec + tout->tv_sec) {
744677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		if (now->tv_usec > last->tv_usec + tout->tv_usec)
754677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger			return 1;
764677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	}
774677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
784677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	return 0;
794677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger}
804677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
814677a549831336400e16210e6f12251dc07d5232osdl.net!shemmingerint lnstat_update(struct lnstat_file *lnstat_files)
824677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger{
834677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	struct lnstat_file *lf;
844677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	char buf[FGETS_BUF_SIZE];
854677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	struct timeval tv;
864677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
874677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	gettimeofday(&tv, NULL);
884677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
894677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	for (lf = lnstat_files; lf; lf = lf->next) {
904677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		if (time_after(&lf->last_read, &lf->interval, &tv)) {
914677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger			int i;
924677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger			struct lnstat_field *lfi;
934677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
944677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger			rewind(lf->fp);
954677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger			if (!lf->compat) {
964677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger				/* skip first line */
974677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger				fgets(buf, sizeof(buf)-1, lf->fp);
984677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger			}
994677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger			scan_lines(lf, 1);
1004677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
101ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger			for (i = 0, lfi = &lf->fields[i];
1024677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger			     i < lf->num_fields; i++, lfi = &lf->fields[i]) {
1034677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger				if (i == 0)
1044677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger					lfi->result = lfi->values[1];
1054677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger				else
1064677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger					lfi->result = (lfi->values[1]-lfi->values[0])
1074677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger				    			/ lf->interval.tv_sec;
1084677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger			}
1094677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
1104677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger			rewind(lf->fp);
1114677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger			fgets(buf, sizeof(buf)-1, lf->fp);
1124677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger			scan_lines(lf, 0);
1134677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		}
1144677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	}
1154677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
1164677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	return 0;
1174677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger}
1184677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
1194677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger/* scan first template line and fill in per-field data structures */
1204677a549831336400e16210e6f12251dc07d5232osdl.net!shemmingerstatic int __lnstat_scan_fields(struct lnstat_file *lf, char *buf)
1214677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger{
1224677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	char *tok;
1234677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	int i;
1244677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
1254677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	tok = strtok(buf, " \t\n");
1264677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	for (i = 0; i < LNSTAT_MAX_FIELDS_PER_LINE; i++) {
1274677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		lf->fields[i].file = lf;
1284677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		strncpy(lf->fields[i].name, tok, LNSTAT_MAX_FIELD_NAME_LEN);
1294677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		/* has to be null-terminate since we initialize to zero
1304677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		 * and field size is NAME_LEN + 1 */
1314677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		tok = strtok(NULL, " \t\n");
1324677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		if (!tok) {
1334677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger			lf->num_fields = i+1;
1344677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger			return 0;
1354677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		}
1364677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	}
1374677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	return 0;
1384677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger}
1394677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
1404677a549831336400e16210e6f12251dc07d5232osdl.net!shemmingerstatic int lnstat_scan_fields(struct lnstat_file *lf)
1414677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger{
1424677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	char buf[FGETS_BUF_SIZE];
1434677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
1444677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	rewind(lf->fp);
1454677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	fgets(buf, sizeof(buf)-1, lf->fp);
1464677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
1474677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	return __lnstat_scan_fields(lf, buf);
1484677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger}
1494677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
1504677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger/* fake function emulating lnstat_scan_fields() for old kernels */
1514677a549831336400e16210e6f12251dc07d5232osdl.net!shemmingerstatic int lnstat_scan_compat_rtstat_fields(struct lnstat_file *lf)
1524677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger{
1534677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	char buf[FGETS_BUF_SIZE];
1544677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
1554677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	strncpy(buf, RTSTAT_COMPAT_LINE, sizeof(buf)-1);
1564677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
1574677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	return __lnstat_scan_fields(lf, buf);
1584677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger}
1594677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
1604677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger/* find out whether string 'name; is in given string array */
1614677a549831336400e16210e6f12251dc07d5232osdl.net!shemmingerstatic int name_in_array(const int num, const char **arr, const char *name)
1624677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger{
1634677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	int i;
1644677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	for (i = 0; i < num; i++) {
1654677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		if (!strcmp(arr[i], name))
1664677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger			return 1;
1674677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	}
1684677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	return 0;
1694677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger}
1704677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
1714677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger/* allocate lnstat_file and open given file */
1724677a549831336400e16210e6f12251dc07d5232osdl.net!shemmingerstatic struct lnstat_file *alloc_and_open(const char *path, const char *file)
1734677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger{
1744677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	struct lnstat_file *lf;
1754677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
1764677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	/* allocate */
1774677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	lf = malloc(sizeof(*lf));
1784677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	if (!lf)
1794677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		return NULL;
1804677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
1814677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	/* initialize */
1824677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	memset(lf, 0, sizeof(*lf));
1834677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
1844677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	/* de->d_name is guaranteed to be <= NAME_MAX */
1854677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	strcpy(lf->basename, file);
1864677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	strcpy(lf->path, path);
1874677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	strcat(lf->path, "/");
1884677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	strcat(lf->path, lf->basename);
1894677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
1904677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	/* initialize to default */
1914677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	lf->interval.tv_sec = 1;
1924677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
1934677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	/* open */
1944677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	lf->fp = fopen(lf->path, "r");
1954677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	if (!lf->fp) {
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);
2624677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		if (!lf)
2634677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger			return NULL;
2644677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
2654677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		/* fill in field structure */
2664677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		if (lnstat_scan_fields(lf) < 0)
2674677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger			return NULL;
2684677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
2694677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		/* prepend to global list */
2704677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		lf->next = lnstat_files;
2714677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		lnstat_files = lf;
2724677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	}
2734677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	closedir(dir);
2744677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
2754677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	return lnstat_files;
2764677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger}
2774677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
2784677a549831336400e16210e6f12251dc07d5232osdl.net!shemmingerint lnstat_dump(FILE *outfd, struct lnstat_file *lnstat_files)
2794677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger{
2804677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	struct lnstat_file *lf;
2814677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
2824677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	for (lf = lnstat_files; lf; lf = lf->next) {
2834677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		int i;
2844677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
2854677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		fprintf(outfd, "%s:\n", lf->path);
2864677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
2874677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		for (i = 0; i < lf->num_fields; i++)
2884677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger			fprintf(outfd, "\t%2u: %s\n", i+1, lf->fields[i].name);
2894677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
2904677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	}
2914677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	return 0;
2924677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger}
2934677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
2944677a549831336400e16210e6f12251dc07d5232osdl.net!shemmingerstruct lnstat_field *lnstat_find_field(struct lnstat_file *lnstat_files,
2954677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger				       const char *name)
2964677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger{
2974677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	struct lnstat_file *lf;
2984677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	struct lnstat_field *ret = NULL;
2994677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	const char *colon = strchr(name, ':');
3004677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	char *file;
3014677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	const char *field;
3024677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
3034677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	if (colon) {
3044677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		file = strndup(name, colon-name);
3054677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		field = colon+1;
3064677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	} else {
3074677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		file = NULL;
3084677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		field = name;
3094677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	}
310ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger
3114677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	for (lf = lnstat_files; lf; lf = lf->next) {
3124677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		int i;
3134677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
3144677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		if (file && strcmp(file, lf->basename))
3154677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger			continue;
3164677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
3174677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		for (i = 0; i < lf->num_fields; i++) {
3184677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger			if (!strcmp(field, lf->fields[i].name)) {
3194677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger				ret = &lf->fields[i];
3204677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger				goto out;
3214677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger			}
3224677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		}
3234677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	}
3244677a549831336400e16210e6f12251dc07d5232osdl.net!shemmingerout:
3254677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	if (file)
3264677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger		free(file);
3274677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger
3284677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger	return ret;
3294677a549831336400e16210e6f12251dc07d5232osdl.net!shemminger}
330