1145519Sdarrenr/*	$FreeBSD$	*/
2145510Sdarrenr
3145510Sdarrenr/*
4170268Sdarrenr * Copyright (C) 2001-2006 by Darren Reed.
5145510Sdarrenr *
6145510Sdarrenr * See the IPFILTER.LICENCE file for details on licencing.
7145510Sdarrenr */
8145510Sdarrenr#ifdef	__FreeBSD__
9145510Sdarrenr# ifndef __FreeBSD_cc_version
10145510Sdarrenr#  include <osreldate.h>
11145510Sdarrenr# else
12145510Sdarrenr#  if __FreeBSD_cc_version < 430000
13145510Sdarrenr#   include <osreldate.h>
14145510Sdarrenr#  endif
15145510Sdarrenr# endif
16145510Sdarrenr#endif
17145510Sdarrenr#include "ipf.h"
18145510Sdarrenr#include <fcntl.h>
19145510Sdarrenr#include <sys/ioctl.h>
20145510Sdarrenr#include "netinet/ipl.h"
21145510Sdarrenr
22145510Sdarrenr#if !defined(lint)
23145510Sdarrenrstatic const char sccsid[] = "@(#)ipf.c	1.23 6/5/96 (C) 1993-2000 Darren Reed";
24170268Sdarrenrstatic const char rcsid[] = "@(#)$Id: ipf.c,v 1.35.2.8 2007/05/10 06:12:01 darrenr Exp $";
25145510Sdarrenr#endif
26145510Sdarrenr
27145510Sdarrenr#if !defined(__SVR4) && defined(__GNUC__)
28145510Sdarrenrextern	char	*index __P((const char *, int));
29145510Sdarrenr#endif
30145510Sdarrenr
31145510Sdarrenrextern	char	*optarg;
32145510Sdarrenrextern	int	optind;
33145510Sdarrenrextern	frentry_t *frtop;
34145510Sdarrenr
35145510Sdarrenr
36145510Sdarrenrvoid	ipf_frsync __P((void));
37145510Sdarrenrvoid	zerostats __P((void));
38145510Sdarrenrint	main __P((int, char *[]));
39145510Sdarrenr
40145510Sdarrenrint	opts = 0;
41145510Sdarrenrint	outputc = 0;
42145510Sdarrenrint	use_inet6 = 0;
43145510Sdarrenr
44145510Sdarrenrstatic	void	procfile __P((char *, char *)), flushfilter __P((char *));
45145510Sdarrenrstatic	void	set_state __P((u_int)), showstats __P((friostat_t *));
46145510Sdarrenrstatic	void	packetlogon __P((char *)), swapactive __P((void));
47145510Sdarrenrstatic	int	opendevice __P((char *, int));
48145510Sdarrenrstatic	void	closedevice __P((void));
49145510Sdarrenrstatic	char	*ipfname = IPL_NAME;
50145510Sdarrenrstatic	void	usage __P((void));
51145510Sdarrenrstatic	int	showversion __P((void));
52145510Sdarrenrstatic	int	get_flags __P((void));
53145510Sdarrenrstatic	void	ipf_interceptadd __P((int, ioctlfunc_t, void *));
54145510Sdarrenr
55145510Sdarrenrstatic	int	fd = -1;
56145510Sdarrenrstatic	ioctlfunc_t	iocfunctions[IPL_LOGSIZE] = { ioctl, ioctl, ioctl,
57145510Sdarrenr						      ioctl, ioctl, ioctl,
58145510Sdarrenr						      ioctl, ioctl };
59145510Sdarrenr
60145510Sdarrenr
61145510Sdarrenrstatic void usage()
62145510Sdarrenr{
63145510Sdarrenr	fprintf(stderr, "usage: ipf [-6AdDEInoPrRsvVyzZ] %s %s %s\n",
64145510Sdarrenr		"[-l block|pass|nomatch|state|nat]", "[-cc] [-F i|o|a|s|S|u]",
65145510Sdarrenr		"[-f filename] [-T <tuneopts>]");
66145510Sdarrenr	exit(1);
67145510Sdarrenr}
68145510Sdarrenr
69145510Sdarrenr
70145510Sdarrenrint main(argc,argv)
71145510Sdarrenrint argc;
72145510Sdarrenrchar *argv[];
73145510Sdarrenr{
74145510Sdarrenr	int c;
75145510Sdarrenr
76145510Sdarrenr	if (argc < 2)
77145510Sdarrenr		usage();
78145510Sdarrenr
79145510Sdarrenr	while ((c = getopt(argc, argv, "6Ac:dDEf:F:Il:noPrRsT:vVyzZ")) != -1) {
80145510Sdarrenr		switch (c)
81145510Sdarrenr		{
82145510Sdarrenr		case '?' :
83145510Sdarrenr			usage();
84145510Sdarrenr			break;
85145510Sdarrenr#ifdef	USE_INET6
86145510Sdarrenr		case '6' :
87145510Sdarrenr			use_inet6 = 1;
88145510Sdarrenr			break;
89145510Sdarrenr#endif
90145510Sdarrenr		case 'A' :
91145510Sdarrenr			opts &= ~OPT_INACTIVE;
92145510Sdarrenr			break;
93145510Sdarrenr		case 'c' :
94145510Sdarrenr			if (strcmp(optarg, "c") == 0)
95145510Sdarrenr				outputc = 1;
96145510Sdarrenr			break;
97145510Sdarrenr		case 'E' :
98145510Sdarrenr			set_state((u_int)1);
99145510Sdarrenr			break;
100145510Sdarrenr		case 'D' :
101145510Sdarrenr			set_state((u_int)0);
102145510Sdarrenr			break;
103145510Sdarrenr		case 'd' :
104145510Sdarrenr			opts ^= OPT_DEBUG;
105145510Sdarrenr			break;
106145510Sdarrenr		case 'f' :
107145510Sdarrenr			procfile(argv[0], optarg);
108145510Sdarrenr			break;
109145510Sdarrenr		case 'F' :
110145510Sdarrenr			flushfilter(optarg);
111145510Sdarrenr			break;
112145510Sdarrenr		case 'I' :
113145510Sdarrenr			opts ^= OPT_INACTIVE;
114145510Sdarrenr			break;
115145510Sdarrenr		case 'l' :
116145510Sdarrenr			packetlogon(optarg);
117145510Sdarrenr			break;
118145510Sdarrenr		case 'n' :
119145510Sdarrenr			opts ^= OPT_DONOTHING;
120145510Sdarrenr			break;
121145510Sdarrenr		case 'o' :
122145510Sdarrenr			break;
123145510Sdarrenr		case 'P' :
124145510Sdarrenr			ipfname = IPAUTH_NAME;
125145510Sdarrenr			break;
126145510Sdarrenr		case 'R' :
127145510Sdarrenr			opts ^= OPT_NORESOLVE;
128145510Sdarrenr			break;
129145510Sdarrenr		case 'r' :
130145510Sdarrenr			opts ^= OPT_REMOVE;
131145510Sdarrenr			break;
132145510Sdarrenr		case 's' :
133145510Sdarrenr			swapactive();
134145510Sdarrenr			break;
135145510Sdarrenr		case 'T' :
136145510Sdarrenr			if (opendevice(ipfname, 1) >= 0)
137145510Sdarrenr				ipf_dotuning(fd, optarg, ioctl);
138145510Sdarrenr			break;
139145510Sdarrenr		case 'v' :
140145510Sdarrenr			opts += OPT_VERBOSE;
141145510Sdarrenr			break;
142145510Sdarrenr		case 'V' :
143145510Sdarrenr			if (showversion())
144145510Sdarrenr				exit(1);
145145510Sdarrenr			break;
146145510Sdarrenr		case 'y' :
147145510Sdarrenr			ipf_frsync();
148145510Sdarrenr			break;
149145510Sdarrenr		case 'z' :
150145510Sdarrenr			opts ^= OPT_ZERORULEST;
151145510Sdarrenr			break;
152145510Sdarrenr		case 'Z' :
153145510Sdarrenr			zerostats();
154145510Sdarrenr			break;
155145510Sdarrenr		}
156145510Sdarrenr	}
157145510Sdarrenr
158145510Sdarrenr	if (optind < 2)
159145510Sdarrenr		usage();
160145510Sdarrenr
161145510Sdarrenr	if (fd != -1)
162145510Sdarrenr		(void) close(fd);
163145510Sdarrenr
164145510Sdarrenr	return(0);
165145510Sdarrenr	/* NOTREACHED */
166145510Sdarrenr}
167145510Sdarrenr
168145510Sdarrenr
169145510Sdarrenrstatic int opendevice(ipfdev, check)
170145510Sdarrenrchar *ipfdev;
171145510Sdarrenrint check;
172145510Sdarrenr{
173145510Sdarrenr	if (opts & OPT_DONOTHING)
174145510Sdarrenr		return -2;
175145510Sdarrenr
176145510Sdarrenr	if (check && checkrev(ipfname) == -1) {
177145510Sdarrenr		fprintf(stderr, "User/kernel version check failed\n");
178145510Sdarrenr		return -2;
179145510Sdarrenr	}
180145510Sdarrenr
181145510Sdarrenr	if (!ipfdev)
182145510Sdarrenr		ipfdev = ipfname;
183145510Sdarrenr
184145510Sdarrenr	if (fd == -1)
185145510Sdarrenr		if ((fd = open(ipfdev, O_RDWR)) == -1)
186145510Sdarrenr			if ((fd = open(ipfdev, O_RDONLY)) == -1)
187145510Sdarrenr				perror("open device");
188145510Sdarrenr	return fd;
189145510Sdarrenr}
190145510Sdarrenr
191145510Sdarrenr
192145510Sdarrenrstatic void closedevice()
193145510Sdarrenr{
194145510Sdarrenr	close(fd);
195145510Sdarrenr	fd = -1;
196145510Sdarrenr}
197145510Sdarrenr
198145510Sdarrenr
199145510Sdarrenrstatic	int	get_flags()
200145510Sdarrenr{
201161357Sguido	int i = 0;
202145510Sdarrenr
203145510Sdarrenr	if ((opendevice(ipfname, 1) != -2) &&
204145510Sdarrenr	    (ioctl(fd, SIOCGETFF, &i) == -1)) {
205145510Sdarrenr		perror("SIOCGETFF");
206145510Sdarrenr		return 0;
207145510Sdarrenr	}
208145510Sdarrenr	return i;
209145510Sdarrenr}
210145510Sdarrenr
211145510Sdarrenr
212145510Sdarrenrstatic	void	set_state(enable)
213145510Sdarrenru_int	enable;
214145510Sdarrenr{
215145510Sdarrenr	if (opendevice(ipfname, 0) != -2)
216145510Sdarrenr		if (ioctl(fd, SIOCFRENB, &enable) == -1) {
217145510Sdarrenr			if (errno == EBUSY)
218145510Sdarrenr				fprintf(stderr,
219145510Sdarrenr					"IP FIlter: already initialized\n");
220145510Sdarrenr			else
221145510Sdarrenr				perror("SIOCFRENB");
222145510Sdarrenr		}
223145510Sdarrenr	return;
224145510Sdarrenr}
225145510Sdarrenr
226145510Sdarrenr
227145510Sdarrenrstatic	void	procfile(name, file)
228145510Sdarrenrchar	*name, *file;
229145510Sdarrenr{
230145510Sdarrenr	(void) opendevice(ipfname, 1);
231145510Sdarrenr
232145510Sdarrenr	initparse();
233145510Sdarrenr
234145510Sdarrenr	ipf_parsefile(fd, ipf_interceptadd, iocfunctions, file);
235145510Sdarrenr
236145510Sdarrenr	if (outputc) {
237145510Sdarrenr		printC(0);
238145510Sdarrenr		printC(1);
239145510Sdarrenr		emit(-1, -1, NULL, NULL);
240145510Sdarrenr	}
241145510Sdarrenr}
242145510Sdarrenr
243145510Sdarrenr
244145510Sdarrenrstatic void ipf_interceptadd(fd, ioctlfunc, ptr)
245145510Sdarrenrint fd;
246145510Sdarrenrioctlfunc_t ioctlfunc;
247145510Sdarrenrvoid *ptr;
248145510Sdarrenr{
249145510Sdarrenr	if (outputc)
250145510Sdarrenr		printc(ptr);
251145510Sdarrenr
252145510Sdarrenr	ipf_addrule(fd, ioctlfunc, ptr);
253145510Sdarrenr}
254145510Sdarrenr
255145510Sdarrenr
256145510Sdarrenrstatic void packetlogon(opt)
257145510Sdarrenrchar	*opt;
258145510Sdarrenr{
259145510Sdarrenr	int	flag, xfd, logopt, change = 0;
260145510Sdarrenr
261145510Sdarrenr	flag = get_flags();
262145510Sdarrenr	if (flag != 0) {
263145510Sdarrenr		if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE)
264145510Sdarrenr			printf("log flag is currently %#x\n", flag);
265145510Sdarrenr	}
266145510Sdarrenr
267145510Sdarrenr	flag &= ~(FF_LOGPASS|FF_LOGNOMATCH|FF_LOGBLOCK);
268145510Sdarrenr
269145510Sdarrenr	if (strstr(opt, "pass")) {
270145510Sdarrenr		flag |= FF_LOGPASS;
271145510Sdarrenr		if (opts & OPT_VERBOSE)
272145510Sdarrenr			printf("set log flag: pass\n");
273145510Sdarrenr		change = 1;
274145510Sdarrenr	}
275145510Sdarrenr	if (strstr(opt, "nomatch")) {
276145510Sdarrenr		flag |= FF_LOGNOMATCH;
277145510Sdarrenr		if (opts & OPT_VERBOSE)
278145510Sdarrenr			printf("set log flag: nomatch\n");
279145510Sdarrenr		change = 1;
280145510Sdarrenr	}
281145510Sdarrenr	if (strstr(opt, "block") || index(opt, 'd')) {
282145510Sdarrenr		flag |= FF_LOGBLOCK;
283145510Sdarrenr		if (opts & OPT_VERBOSE)
284145510Sdarrenr			printf("set log flag: block\n");
285145510Sdarrenr		change = 1;
286145510Sdarrenr	}
287145510Sdarrenr	if (strstr(opt, "none")) {
288145510Sdarrenr		if (opts & OPT_VERBOSE)
289145510Sdarrenr			printf("disable all log flags\n");
290145510Sdarrenr		change = 1;
291145510Sdarrenr	}
292145510Sdarrenr
293145510Sdarrenr	if (change == 1) {
294145510Sdarrenr		if (opendevice(ipfname, 1) != -2 &&
295145510Sdarrenr		    (ioctl(fd, SIOCSETFF, &flag) != 0))
296145510Sdarrenr			perror("ioctl(SIOCSETFF)");
297145510Sdarrenr	}
298145510Sdarrenr
299145510Sdarrenr	if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) {
300145510Sdarrenr		flag = get_flags();
301145510Sdarrenr		printf("log flags are now %#x\n", flag);
302145510Sdarrenr	}
303145510Sdarrenr
304145510Sdarrenr	if (strstr(opt, "state")) {
305145510Sdarrenr		if (opts & OPT_VERBOSE)
306145510Sdarrenr			printf("set state log flag\n");
307145510Sdarrenr		xfd = open(IPSTATE_NAME, O_RDWR);
308145510Sdarrenr		if (xfd >= 0) {
309145510Sdarrenr			logopt = 0;
310145510Sdarrenr			if (ioctl(xfd, SIOCGETLG, &logopt))
311145510Sdarrenr				perror("ioctl(SIOCGETLG)");
312145510Sdarrenr			else {
313145510Sdarrenr				logopt = 1 - logopt;
314145510Sdarrenr				if (ioctl(xfd, SIOCSETLG, &logopt))
315145510Sdarrenr					perror("ioctl(SIOCSETLG)");
316145510Sdarrenr			}
317145510Sdarrenr			close(xfd);
318145510Sdarrenr		}
319145510Sdarrenr	}
320145510Sdarrenr
321145510Sdarrenr	if (strstr(opt, "nat")) {
322145510Sdarrenr		if (opts & OPT_VERBOSE)
323145510Sdarrenr			printf("set nat log flag\n");
324145510Sdarrenr		xfd = open(IPNAT_NAME, O_RDWR);
325145510Sdarrenr		if (xfd >= 0) {
326145510Sdarrenr			logopt = 0;
327145510Sdarrenr			if (ioctl(xfd, SIOCGETLG, &logopt))
328145510Sdarrenr				perror("ioctl(SIOCGETLG)");
329145510Sdarrenr			else {
330145510Sdarrenr				logopt = 1 - logopt;
331145510Sdarrenr				if (ioctl(xfd, SIOCSETLG, &logopt))
332145510Sdarrenr					perror("ioctl(SIOCSETLG)");
333145510Sdarrenr			}
334145510Sdarrenr			close(xfd);
335145510Sdarrenr		}
336145510Sdarrenr	}
337145510Sdarrenr}
338145510Sdarrenr
339145510Sdarrenr
340145510Sdarrenrstatic	void	flushfilter(arg)
341145510Sdarrenrchar	*arg;
342145510Sdarrenr{
343145510Sdarrenr	int	fl = 0, rem;
344145510Sdarrenr
345145510Sdarrenr	if (!arg || !*arg)
346145510Sdarrenr		return;
347170268Sdarrenr	if (!strcmp(arg, "s") || !strcmp(arg, "S") || ISDIGIT(*arg)) {
348145510Sdarrenr		if (*arg == 'S')
349145510Sdarrenr			fl = 0;
350170268Sdarrenr		else if (*arg == 's')
351170268Sdarrenr			fl = 1;
352145510Sdarrenr		else
353170268Sdarrenr			fl = atoi(arg);
354145510Sdarrenr		rem = fl;
355145510Sdarrenr
356145510Sdarrenr		closedevice();
357145510Sdarrenr		if (opendevice(IPSTATE_NAME, 1) == -2)
358145510Sdarrenr			exit(1);
359145510Sdarrenr
360145510Sdarrenr		if (!(opts & OPT_DONOTHING)) {
361145510Sdarrenr			if (use_inet6) {
362145510Sdarrenr				if (ioctl(fd, SIOCIPFL6, &fl) == -1) {
363145510Sdarrenr					perror("ioctl(SIOCIPFL6)");
364145510Sdarrenr					exit(1);
365145510Sdarrenr				}
366145510Sdarrenr			} else {
367145510Sdarrenr				if (ioctl(fd, SIOCIPFFL, &fl) == -1) {
368145510Sdarrenr					perror("ioctl(SIOCIPFFL)");
369145510Sdarrenr					exit(1);
370145510Sdarrenr				}
371145510Sdarrenr			}
372145510Sdarrenr		}
373145510Sdarrenr		if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) {
374145510Sdarrenr			printf("remove flags %s (%d)\n", arg, rem);
375170268Sdarrenr			printf("removed %d entries\n", fl);
376145510Sdarrenr		}
377145510Sdarrenr		closedevice();
378145510Sdarrenr		return;
379145510Sdarrenr	}
380145510Sdarrenr
381145510Sdarrenr#ifdef	SIOCIPFFA
382145510Sdarrenr	if (!strcmp(arg, "u")) {
383145510Sdarrenr		closedevice();
384145510Sdarrenr		/*
385145510Sdarrenr		 * Flush auth rules and packets
386145510Sdarrenr		 */
387145510Sdarrenr		if (opendevice(IPL_AUTH, 1) == -1)
388145510Sdarrenr			perror("open(IPL_AUTH)");
389145510Sdarrenr		else {
390145510Sdarrenr			if (ioctl(fd, SIOCIPFFA, &fl) == -1)
391145510Sdarrenr				perror("ioctl(SIOCIPFFA)");
392145510Sdarrenr		}
393145510Sdarrenr		closedevice();
394145510Sdarrenr		return;
395145510Sdarrenr	}
396145510Sdarrenr#endif
397145510Sdarrenr
398145510Sdarrenr	if (strchr(arg, 'i') || strchr(arg, 'I'))
399145510Sdarrenr		fl = FR_INQUE;
400145510Sdarrenr	if (strchr(arg, 'o') || strchr(arg, 'O'))
401145510Sdarrenr		fl = FR_OUTQUE;
402145510Sdarrenr	if (strchr(arg, 'a') || strchr(arg, 'A'))
403145510Sdarrenr		fl = FR_OUTQUE|FR_INQUE;
404145510Sdarrenr	if (opts & OPT_INACTIVE)
405145510Sdarrenr		fl |= FR_INACTIVE;
406145510Sdarrenr	rem = fl;
407145510Sdarrenr
408145510Sdarrenr	if (opendevice(ipfname, 1) == -2)
409145510Sdarrenr		exit(1);
410145510Sdarrenr
411145510Sdarrenr	if (!(opts & OPT_DONOTHING)) {
412145510Sdarrenr		if (use_inet6) {
413145510Sdarrenr			if (ioctl(fd, SIOCIPFL6, &fl) == -1) {
414145510Sdarrenr				perror("ioctl(SIOCIPFL6)");
415145510Sdarrenr				exit(1);
416145510Sdarrenr			}
417145510Sdarrenr		} else {
418145510Sdarrenr			if (ioctl(fd, SIOCIPFFL, &fl) == -1) {
419145510Sdarrenr				perror("ioctl(SIOCIPFFL)");
420145510Sdarrenr				exit(1);
421145510Sdarrenr			}
422145510Sdarrenr		}
423145510Sdarrenr	}
424145510Sdarrenr
425145510Sdarrenr	if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) {
426145510Sdarrenr		printf("remove flags %s%s (%d)\n", (rem & FR_INQUE) ? "I" : "",
427145510Sdarrenr			(rem & FR_OUTQUE) ? "O" : "", rem);
428145510Sdarrenr		printf("removed %d filter rules\n", fl);
429145510Sdarrenr	}
430145510Sdarrenr	return;
431145510Sdarrenr}
432145510Sdarrenr
433145510Sdarrenr
434145510Sdarrenrstatic void swapactive()
435145510Sdarrenr{
436145510Sdarrenr	int in = 2;
437145510Sdarrenr
438145510Sdarrenr	if (opendevice(ipfname, 1) != -2 && ioctl(fd, SIOCSWAPA, &in) == -1)
439145510Sdarrenr		perror("ioctl(SIOCSWAPA)");
440145510Sdarrenr	else
441145510Sdarrenr		printf("Set %d now inactive\n", in);
442145510Sdarrenr}
443145510Sdarrenr
444145510Sdarrenr
445145510Sdarrenrvoid ipf_frsync()
446145510Sdarrenr{
447145510Sdarrenr	int frsyn = 0;
448145510Sdarrenr
449145510Sdarrenr	if (opendevice(ipfname, 1) != -2 && ioctl(fd, SIOCFRSYN, &frsyn) == -1)
450145510Sdarrenr		perror("SIOCFRSYN");
451145510Sdarrenr	else
452145510Sdarrenr		printf("filter sync'd\n");
453145510Sdarrenr}
454145510Sdarrenr
455145510Sdarrenr
456145510Sdarrenrvoid zerostats()
457145510Sdarrenr{
458157836Sdarrenr	ipfobj_t	obj;
459145510Sdarrenr	friostat_t	fio;
460145510Sdarrenr
461157836Sdarrenr	obj.ipfo_rev = IPFILTER_VERSION;
462157836Sdarrenr	obj.ipfo_type = IPFOBJ_IPFSTAT;
463157836Sdarrenr	obj.ipfo_size = sizeof(fio);
464157836Sdarrenr	obj.ipfo_ptr = &fio;
465157836Sdarrenr	obj.ipfo_offset = 0;
466157836Sdarrenr
467145510Sdarrenr	if (opendevice(ipfname, 1) != -2) {
468157836Sdarrenr		if (ioctl(fd, SIOCFRZST, &obj) == -1) {
469145510Sdarrenr			perror("ioctl(SIOCFRZST)");
470145510Sdarrenr			exit(-1);
471145510Sdarrenr		}
472157836Sdarrenr		showstats(&fio);
473145510Sdarrenr	}
474145510Sdarrenr
475145510Sdarrenr}
476145510Sdarrenr
477145510Sdarrenr
478145510Sdarrenr/*
479145510Sdarrenr * read the kernel stats for packets blocked and passed
480145510Sdarrenr */
481145510Sdarrenrstatic void showstats(fp)
482145510Sdarrenrfriostat_t	*fp;
483145510Sdarrenr{
484145510Sdarrenr	printf("bad packets:\t\tin %lu\tout %lu\n",
485145510Sdarrenr			fp->f_st[0].fr_bad, fp->f_st[1].fr_bad);
486145510Sdarrenr	printf(" input packets:\t\tblocked %lu passed %lu nomatch %lu",
487145510Sdarrenr			fp->f_st[0].fr_block, fp->f_st[0].fr_pass,
488145510Sdarrenr			fp->f_st[0].fr_nom);
489145510Sdarrenr	printf(" counted %lu\n", fp->f_st[0].fr_acct);
490145510Sdarrenr	printf("output packets:\t\tblocked %lu passed %lu nomatch %lu",
491145510Sdarrenr			fp->f_st[1].fr_block, fp->f_st[1].fr_pass,
492145510Sdarrenr			fp->f_st[1].fr_nom);
493145510Sdarrenr	printf(" counted %lu\n", fp->f_st[0].fr_acct);
494145510Sdarrenr	printf(" input packets logged:\tblocked %lu passed %lu\n",
495145510Sdarrenr			fp->f_st[0].fr_bpkl, fp->f_st[0].fr_ppkl);
496145510Sdarrenr	printf("output packets logged:\tblocked %lu passed %lu\n",
497145510Sdarrenr			fp->f_st[1].fr_bpkl, fp->f_st[1].fr_ppkl);
498145510Sdarrenr	printf(" packets logged:\tinput %lu-%lu output %lu-%lu\n",
499145510Sdarrenr			fp->f_st[0].fr_pkl, fp->f_st[0].fr_skip,
500145510Sdarrenr			fp->f_st[1].fr_pkl, fp->f_st[1].fr_skip);
501145510Sdarrenr}
502145510Sdarrenr
503145510Sdarrenr
504145510Sdarrenrstatic int showversion()
505145510Sdarrenr{
506145510Sdarrenr	struct friostat fio;
507145510Sdarrenr	ipfobj_t ipfo;
508145510Sdarrenr	u_32_t flags;
509145510Sdarrenr	char *s;
510145510Sdarrenr	int vfd;
511145510Sdarrenr
512145510Sdarrenr	bzero((caddr_t)&ipfo, sizeof(ipfo));
513145510Sdarrenr	ipfo.ipfo_rev = IPFILTER_VERSION;
514145510Sdarrenr	ipfo.ipfo_size = sizeof(fio);
515145510Sdarrenr	ipfo.ipfo_ptr = (void *)&fio;
516145510Sdarrenr	ipfo.ipfo_type = IPFOBJ_IPFSTAT;
517145510Sdarrenr
518145510Sdarrenr	printf("ipf: %s (%d)\n", IPL_VERSION, (int)sizeof(frentry_t));
519145510Sdarrenr
520145510Sdarrenr	if ((vfd = open(ipfname, O_RDONLY)) == -1) {
521145510Sdarrenr		perror("open device");
522145510Sdarrenr		return 1;
523145510Sdarrenr	}
524145510Sdarrenr
525145510Sdarrenr	if (ioctl(vfd, SIOCGETFS, &ipfo)) {
526145510Sdarrenr		perror("ioctl(SIOCGETFS)");
527145510Sdarrenr		close(vfd);
528145510Sdarrenr		return 1;
529145510Sdarrenr	}
530145510Sdarrenr	close(vfd);
531145510Sdarrenr	flags = get_flags();
532145510Sdarrenr
533145510Sdarrenr	printf("Kernel: %-*.*s\n", (int)sizeof(fio.f_version),
534145510Sdarrenr		(int)sizeof(fio.f_version), fio.f_version);
535145510Sdarrenr	printf("Running: %s\n", (fio.f_running > 0) ? "yes" : "no");
536145510Sdarrenr	printf("Log Flags: %#x = ", flags);
537145510Sdarrenr	s = "";
538145510Sdarrenr	if (flags & FF_LOGPASS) {
539145510Sdarrenr		printf("pass");
540145510Sdarrenr		s = ", ";
541145510Sdarrenr	}
542145510Sdarrenr	if (flags & FF_LOGBLOCK) {
543145510Sdarrenr		printf("%sblock", s);
544145510Sdarrenr		s = ", ";
545145510Sdarrenr	}
546145510Sdarrenr	if (flags & FF_LOGNOMATCH) {
547145510Sdarrenr		printf("%snomatch", s);
548145510Sdarrenr		s = ", ";
549145510Sdarrenr	}
550145510Sdarrenr	if (flags & FF_BLOCKNONIP) {
551145510Sdarrenr		printf("%snonip", s);
552145510Sdarrenr		s = ", ";
553145510Sdarrenr	}
554145510Sdarrenr	if (!*s)
555145510Sdarrenr		printf("none set");
556145510Sdarrenr	putchar('\n');
557145510Sdarrenr
558145510Sdarrenr	printf("Default: ");
559145510Sdarrenr	if (FR_ISPASS(fio.f_defpass))
560145510Sdarrenr		s = "pass";
561145510Sdarrenr	else if (FR_ISBLOCK(fio.f_defpass))
562145510Sdarrenr		s = "block";
563145510Sdarrenr	else
564145510Sdarrenr		s = "nomatch -> block";
565145510Sdarrenr	printf("%s all, Logging: %savailable\n", s, fio.f_logging ? "" : "un");
566145510Sdarrenr	printf("Active list: %d\n", fio.f_active);
567145510Sdarrenr	printf("Feature mask: %#x\n", fio.f_features);
568145510Sdarrenr
569145510Sdarrenr	return 0;
570145510Sdarrenr}
571