Example #1
0
static void server_loop(int fd)
{
	struct timeval snaptime = { 0 };
	struct pollfd p;

	p.fd = fd;
	p.events = p.revents = POLLIN;

	sprintf(info_source, "%d.%lu sampling_interval=%d time_const=%d",
		getpid(), (unsigned long)random(), scan_interval/1000, time_constant/1000);

	load_info();

	for (;;) {
		int status;
		time_t tdiff;
		struct timeval now;

		gettimeofday(&now, NULL);
		tdiff = T_DIFF(now, snaptime);
		if (tdiff >= scan_interval) {
			update_db(tdiff);
			snaptime = now;
			tdiff = 0;
		}

		if (poll(&p, 1, scan_interval - tdiff) > 0
		    && (p.revents&POLLIN)) {
			int clnt = accept(fd, NULL, NULL);

			if (clnt >= 0) {
				pid_t pid;

				if (children >= 5) {
					close(clnt);
				} else if ((pid = fork()) != 0) {
					if (pid > 0)
						children++;
					close(clnt);
				} else {
					FILE *fp = fdopen(clnt, "w");

					if (fp)
						dump_raw_db(fp, 0);
					exit(0);
				}
			}
		}
		while (children && waitpid(-1, &status, WNOHANG) > 0)
			children--;
	}
}
Example #2
0
static void server_loop(int fd)
{
	struct timeval snaptime;
	struct pollfd p;
	
	memset(&snaptime, 0, sizeof(snaptime));
	
	p.fd = fd;
	p.events = p.revents = POLLIN;

	load_info();

	for (;;) {
		int status;
		int tdiff;
		struct timeval now;

		gettimeofday(&now, NULL);
		tdiff = T_DIFF(now, snaptime);

//		if (tdiff >= 0) { 
			update_db(tdiff);
			snaptime = now;
			tdiff = 0;
//		}
		if (poll(&p, 1, conf.scan_interval-tdiff) > 0
		    && (p.revents&POLLIN)) {
			int clnt = accept(fd, NULL, NULL);

			if (clnt >= 0) {
				pid_t pid;

				/*
				  We assume forking will be ok
				  so update database here not
				  have races with forked process
				*/

				gettimeofday(&now, NULL);
				tdiff = T_DIFF(now, snaptime);
//				if (tdiff >= min_interval) {
					update_db(tdiff);
					snaptime = now;
					tdiff = 0;
//				}
				poll_client(clnt);
				
				sprintf(info_source,
					"pid=%d sampling_interval=%d "
					"time_const=%d",
					getpid(),
					conf.scan_interval/1000,
					conf.time_constant/1000);

				if (children >= 5) {
					close(clnt);
				} else if ((pid = fork()) != 0) {

					if (pid>0) 
						children++;
					close(clnt);
				} else {
					FILE *fp = fdopen(clnt, "w");
					if (fp) {
						/* Write on clients socket */
						dump_raw_db(fp);
					}
					exit(0);
				}
			}
		}
		while (children && waitpid(-1, &status, WNOHANG) > 0)
			children--;
	}
}
Example #3
0
int main(int argc, char *argv[])
{
	char hist_name[128];
	struct sockaddr_un sun;
	FILE *hist_fp = NULL;
	int ch;
	int fd;

	while ((ch = getopt_long(argc, argv, "hjpvVzrnasd:t:e",
			longopts, NULL)) != EOF) {
		switch (ch) {
		case 'z':
			dump_zeros = 1;
			break;
		case 'r':
			reset_history = 1;
			break;
		case 'a':
			ignore_history = 1;
			break;
		case 's':
			no_update = 1;
			break;
		case 'n':
			no_output = 1;
			break;
		case 'e':
			show_errors = 1;
			break;
		case 'j':
			json_output = 1;
			break;
		case 'p':
			pretty = 1;
			break;
		case 'd':
			scan_interval = atoi(optarg) * 1000;
			if (scan_interval <= 0) {
				fprintf(stderr, "ifstat: invalid scan interval\n");
				exit(-1);
			}
			break;
		case 't':
			time_constant = atoi(optarg);
			if (time_constant <= 0) {
				fprintf(stderr, "ifstat: invalid time constant divisor\n");
				exit(-1);
			}
			break;
		case 'v':
		case 'V':
			printf("ifstat utility, iproute2-ss%s\n", SNAPSHOT);
			exit(0);
		case 'h':
		case '?':
		default:
			usage();
		}
	}

	argc -= optind;
	argv += optind;

	sun.sun_family = AF_UNIX;
	sun.sun_path[0] = 0;
	sprintf(sun.sun_path+1, "ifstat%d", getuid());

	if (scan_interval > 0) {
		if (time_constant == 0)
			time_constant = 60;
		time_constant *= 1000;
		W = 1 - 1/exp(log(10)*(double)scan_interval/time_constant);
		if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
			perror("ifstat: socket");
			exit(-1);
		}
		if (bind(fd, (struct sockaddr *)&sun, 2+1+strlen(sun.sun_path+1)) < 0) {
			perror("ifstat: bind");
			exit(-1);
		}
		if (listen(fd, 5) < 0) {
			perror("ifstat: listen");
			exit(-1);
		}
		if (daemon(0, 0)) {
			perror("ifstat: daemon");
			exit(-1);
		}
		signal(SIGPIPE, SIG_IGN);
		signal(SIGCHLD, sigchild);
		server_loop(fd);
		exit(0);
	}

	patterns = argv;
	npatterns = argc;

	if (getenv("IFSTAT_HISTORY"))
		snprintf(hist_name, sizeof(hist_name),
			 "%s", getenv("IFSTAT_HISTORY"));
	else
		snprintf(hist_name, sizeof(hist_name),
			 "%s/.ifstat.u%d", P_tmpdir, getuid());

	if (reset_history)
		unlink(hist_name);

	if (!ignore_history || !no_update) {
		struct stat stb;

		fd = open(hist_name, O_RDWR|O_CREAT|O_NOFOLLOW, 0600);
		if (fd < 0) {
			perror("ifstat: open history file");
			exit(-1);
		}
		if ((hist_fp = fdopen(fd, "r+")) == NULL) {
			perror("ifstat: fdopen history file");
			exit(-1);
		}
		if (flock(fileno(hist_fp), LOCK_EX)) {
			perror("ifstat: flock history file");
			exit(-1);
		}
		if (fstat(fileno(hist_fp), &stb) != 0) {
			perror("ifstat: fstat history file");
			exit(-1);
		}
		if (stb.st_nlink != 1 || stb.st_uid != getuid()) {
			fprintf(stderr, "ifstat: something is so wrong with history file, that I prefer not to proceed.\n");
			exit(-1);
		}
		if (!ignore_history) {
			FILE *tfp;
			long uptime = -1;

			if ((tfp = fopen("/proc/uptime", "r")) != NULL) {
				if (fscanf(tfp, "%ld", &uptime) != 1)
					uptime = -1;
				fclose(tfp);
			}
			if (uptime >= 0 && time(NULL) >= stb.st_mtime+uptime) {
				fprintf(stderr, "ifstat: history is aged out, resetting\n");
				if (ftruncate(fileno(hist_fp), 0))
					perror("ifstat: ftruncate");
			}
		}

		load_raw_table(hist_fp);

		hist_db = kern_db;
		kern_db = NULL;
	}

	if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0 &&
	    (connect(fd, (struct sockaddr *)&sun, 2+1+strlen(sun.sun_path+1)) == 0
	     || (strcpy(sun.sun_path+1, "ifstat0"),
		 connect(fd, (struct sockaddr *)&sun, 2+1+strlen(sun.sun_path+1)) == 0))
	    && verify_forging(fd) == 0) {
		FILE *sfp = fdopen(fd, "r");

		load_raw_table(sfp);
		if (hist_db && source_mismatch) {
			fprintf(stderr, "ifstat: history is stale, ignoring it.\n");
			hist_db = NULL;
		}
		fclose(sfp);
	} else {
		if (fd >= 0)
			close(fd);
		if (hist_db && info_source[0] && strcmp(info_source, "kernel")) {
			fprintf(stderr, "ifstat: history is stale, ignoring it.\n");
			hist_db = NULL;
			info_source[0] = 0;
		}
		load_info();
		if (info_source[0] == 0)
			strcpy(info_source, "kernel");
	}

	if (!no_output) {
		if (ignore_history || hist_db == NULL)
			dump_kern_db(stdout);
		else
			dump_incr_db(stdout);
	}

	if (!no_update) {
		if (ftruncate(fileno(hist_fp), 0))
			perror("ifstat: ftruncate");
		rewind(hist_fp);

		json_output = 0;
		dump_raw_db(hist_fp, 1);
		fclose(hist_fp);
	}
	exit(0);
}