| 1 | /*	$NetBSD: ipf.c,v 1.3 2018/02/04 08:19:42 mrg Exp $	*/ | 
| 2 |  | 
| 3 | /* | 
| 4 |  * Copyright (C) 2012 by Darren Reed. | 
| 5 |  * | 
| 6 |  * See the IPFILTER.LICENCE file for details on licencing. | 
| 7 |  */ | 
| 8 | #ifdef	__FreeBSD__ | 
| 9 | # ifndef __FreeBSD_cc_version | 
| 10 | #  include <osreldate.h> | 
| 11 | # else | 
| 12 | #  if __FreeBSD_cc_version < 430000 | 
| 13 | #   include <osreldate.h> | 
| 14 | #  endif | 
| 15 | # endif | 
| 16 | #endif | 
| 17 | #include "ipf.h" | 
| 18 | #include <fcntl.h> | 
| 19 | #include <ctype.h> | 
| 20 | #include <sys/ioctl.h> | 
| 21 | #include "netinet/ipl.h" | 
| 22 |  | 
| 23 | #if !defined(lint) | 
| 24 | static __attribute__((__used__)) const char sccsid[] = "@(#)ipf.c	1.23 6/5/96 (C) 1993-2000 Darren Reed" ; | 
| 25 | static __attribute__((__used__)) const char rcsid[] = "@(#)Id: ipf.c,v 1.1.1.2 2012/07/22 13:44:51 darrenr Exp $" ; | 
| 26 | #endif | 
| 27 |  | 
| 28 | #if !defined(__SVR4) && defined(__GNUC__) | 
| 29 | extern	char	*index __P((const char *, int)); | 
| 30 | #endif | 
| 31 |  | 
| 32 | extern	char	*optarg; | 
| 33 | extern	int	optind; | 
| 34 | extern	frentry_t *frtop; | 
| 35 |  | 
| 36 |  | 
| 37 | void	ipf_frsync __P((void)); | 
| 38 | void	zerostats __P((void)); | 
| 39 | int	main __P((int, char *[])); | 
| 40 |  | 
| 41 | int	opts = 0; | 
| 42 | int	outputc = 0; | 
| 43 | int	use_inet6 = 0; | 
| 44 | int	exitstatus = 0; | 
| 45 |  | 
| 46 | static	void	procfile __P((char *)); | 
| 47 | static	void	flushfilter __P((char *, int *)); | 
| 48 | static	void	set_state __P((u_int)); | 
| 49 | static	void	showstats __P((friostat_t *)); | 
| 50 | static	void	packetlogon __P((char *)); | 
| 51 | static	void	swapactive __P((void)); | 
| 52 | static	int	opendevice __P((char *, int)); | 
| 53 | static	void	closedevice __P((void)); | 
| 54 | static	char	*ipfname = IPL_NAME; | 
| 55 | static	void	usage __P((void)); | 
| 56 | static	int	showversion __P((void)); | 
| 57 | static	int	get_flags __P((void)); | 
| 58 | static	int	ipf_interceptadd __P((int, ioctlfunc_t, void *)); | 
| 59 |  | 
| 60 | static	int	fd = -1; | 
| 61 | static	ioctlfunc_t	iocfunctions[IPL_LOGSIZE] = { ioctl, ioctl, ioctl, | 
| 62 | 						      ioctl, ioctl, ioctl, | 
| 63 | 						      ioctl, ioctl }; | 
| 64 |  | 
| 65 |  | 
| 66 | static void usage() | 
| 67 | { | 
| 68 | 	fprintf(stderr, "usage: ipf [-6AdDEInoPrRsvVyzZ] %s %s %s\n" , | 
| 69 | 		"[-l block|pass|nomatch|state|nat]" , "[-cc] [-F i|o|a|s|S|u]" , | 
| 70 | 		"[-f filename] [-T <tuneopts>]" ); | 
| 71 | 	exit(1); | 
| 72 | } | 
| 73 |  | 
| 74 |  | 
| 75 | int main(argc,argv) | 
| 76 | 	int argc; | 
| 77 | 	char *argv[]; | 
| 78 | { | 
| 79 | 	int c, *filter = NULL; | 
| 80 |  | 
| 81 | 	if (argc < 2) | 
| 82 | 		usage(); | 
| 83 |  | 
| 84 | 	assigndefined(getenv("IPF_PREDEFINED" )); | 
| 85 |  | 
| 86 | 	while ((c = getopt(argc, argv, "46Ac:dDEf:F:Il:m:noPrRsT:vVyzZ" )) != -1) { | 
| 87 | 		switch (c) | 
| 88 | 		{ | 
| 89 | 		case '?' : | 
| 90 | 			usage(); | 
| 91 | 			break; | 
| 92 | 		case '4' : | 
| 93 | 			use_inet6 = -1; | 
| 94 | 			break; | 
| 95 | 		case '6' : | 
| 96 | 			use_inet6 = 1; | 
| 97 | 			break; | 
| 98 | 		case 'A' : | 
| 99 | 			opts &= ~OPT_INACTIVE; | 
| 100 | 			break; | 
| 101 | 		case 'c' : | 
| 102 | 			if (strcmp(optarg, "c" ) == 0) | 
| 103 | 				outputc = 1; | 
| 104 | 			break; | 
| 105 | 		case 'E' : | 
| 106 | 			set_state((u_int)1); | 
| 107 | 			break; | 
| 108 | 		case 'D' : | 
| 109 | 			set_state((u_int)0); | 
| 110 | 			break; | 
| 111 | 		case 'd' : | 
| 112 | 			opts ^= OPT_DEBUG; | 
| 113 | 			break; | 
| 114 | 		case 'f' : | 
| 115 | 			procfile(optarg); | 
| 116 | 			break; | 
| 117 | 		case 'F' : | 
| 118 | 			flushfilter(optarg, filter); | 
| 119 | 			break; | 
| 120 | 		case 'I' : | 
| 121 | 			opts ^= OPT_INACTIVE; | 
| 122 | 			break; | 
| 123 | 		case 'l' : | 
| 124 | 			packetlogon(optarg); | 
| 125 | 			break; | 
| 126 | 		case 'm' : | 
| 127 | 			filter = parseipfexpr(optarg, NULL); | 
| 128 | 			break; | 
| 129 | 		case 'n' : | 
| 130 | 			opts ^= OPT_DONOTHING|OPT_DONTOPEN; | 
| 131 | 			break; | 
| 132 | 		case 'o' : | 
| 133 | 			break; | 
| 134 | 		case 'P' : | 
| 135 | 			ipfname = IPAUTH_NAME; | 
| 136 | 			break; | 
| 137 | 		case 'R' : | 
| 138 | 			opts ^= OPT_NORESOLVE; | 
| 139 | 			break; | 
| 140 | 		case 'r' : | 
| 141 | 			opts ^= OPT_REMOVE; | 
| 142 | 			break; | 
| 143 | 		case 's' : | 
| 144 | 			swapactive(); | 
| 145 | 			break; | 
| 146 | 		case 'T' : | 
| 147 | 			if (opendevice(ipfname, 1) >= 0) | 
| 148 | 				ipf_dotuning(fd, optarg, ioctl); | 
| 149 | 			break; | 
| 150 | 		case 'v' : | 
| 151 | 			opts += OPT_VERBOSE; | 
| 152 | 			break; | 
| 153 | 		case 'V' : | 
| 154 | 			if (showversion()) | 
| 155 | 				exit(1); | 
| 156 | 			break; | 
| 157 | 		case 'y' : | 
| 158 | 			ipf_frsync(); | 
| 159 | 			break; | 
| 160 | 		case 'z' : | 
| 161 | 			opts ^= OPT_ZERORULEST; | 
| 162 | 			break; | 
| 163 | 		case 'Z' : | 
| 164 | 			zerostats(); | 
| 165 | 			break; | 
| 166 | 		} | 
| 167 | 	} | 
| 168 |  | 
| 169 | 	if (optind < 2) | 
| 170 | 		usage(); | 
| 171 |  | 
| 172 | 	if (fd != -1) | 
| 173 | 		(void) close(fd); | 
| 174 |  | 
| 175 | 	return(exitstatus); | 
| 176 | 	/* NOTREACHED */ | 
| 177 | } | 
| 178 |  | 
| 179 |  | 
| 180 | static int opendevice(ipfdev, check) | 
| 181 | 	char *ipfdev; | 
| 182 | 	int check; | 
| 183 | { | 
| 184 | 	if (opts & OPT_DONOTHING) | 
| 185 | 		return -2; | 
| 186 |  | 
| 187 | 	if (check && checkrev(ipfname) == -1) { | 
| 188 | 		fprintf(stderr, "User/kernel version check failed\n" ); | 
| 189 | 		return -2; | 
| 190 | 	} | 
| 191 |  | 
| 192 | 	if (!ipfdev) | 
| 193 | 		ipfdev = ipfname; | 
| 194 |  | 
| 195 | 	if (fd == -1) | 
| 196 | 		if ((fd = open(ipfdev, O_RDWR)) == -1) | 
| 197 | 			if ((fd = open(ipfdev, O_RDONLY)) == -1) | 
| 198 | 				ipferror(fd, "open device" ); | 
| 199 | 	return fd; | 
| 200 | } | 
| 201 |  | 
| 202 |  | 
| 203 | static void closedevice() | 
| 204 | { | 
| 205 | 	close(fd); | 
| 206 | 	fd = -1; | 
| 207 | } | 
| 208 |  | 
| 209 |  | 
| 210 | static	int	get_flags() | 
| 211 | { | 
| 212 | 	int i = 0; | 
| 213 |  | 
| 214 | 	if ((opendevice(ipfname, 1) != -2) && | 
| 215 | 	    (ioctl(fd, SIOCGETFF, &i) == -1)) { | 
| 216 | 		ipferror(fd, "SIOCGETFF" ); | 
| 217 | 		return 0; | 
| 218 | 	} | 
| 219 | 	return i; | 
| 220 | } | 
| 221 |  | 
| 222 |  | 
| 223 | static	void	set_state(enable) | 
| 224 | 	u_int	enable; | 
| 225 | { | 
| 226 | 	if (opendevice(ipfname, 0) != -2) { | 
| 227 | 		if (ioctl(fd, SIOCFRENB, &enable) == -1) { | 
| 228 | 			if (errno == EBUSY) { | 
| 229 | 				fprintf(stderr, | 
| 230 | 					"IP FIlter: already initialized\n" ); | 
| 231 | 			} else { | 
| 232 | 				ipferror(fd, "SIOCFRENB" ); | 
| 233 | 			} | 
| 234 | 		} | 
| 235 | 	} | 
| 236 | 	return; | 
| 237 | } | 
| 238 |  | 
| 239 |  | 
| 240 | static	void	procfile(file) | 
| 241 | 	char	*file; | 
| 242 | { | 
| 243 | 	(void) opendevice(ipfname, 1); | 
| 244 |  | 
| 245 | 	initparse(); | 
| 246 |  | 
| 247 | 	ipf_parsefile(fd, ipf_interceptadd, iocfunctions, file); | 
| 248 |  | 
| 249 | 	if (outputc) { | 
| 250 | 		printC(0); | 
| 251 | 		printC(1); | 
| 252 | 		emit(-1, -1, NULL, NULL); | 
| 253 | 	} | 
| 254 | } | 
| 255 |  | 
| 256 |  | 
| 257 | static int ipf_interceptadd(fd, ioctlfunc, ptr) | 
| 258 | 	int fd; | 
| 259 | 	ioctlfunc_t ioctlfunc; | 
| 260 | 	void *ptr; | 
| 261 | { | 
| 262 | 	if (outputc) | 
| 263 | 		printc(ptr); | 
| 264 |  | 
| 265 | 	if (ipf_addrule(fd, ioctlfunc, ptr) != 0) | 
| 266 | 		exitstatus = 1; | 
| 267 | 	return 0; | 
| 268 | } | 
| 269 |  | 
| 270 |  | 
| 271 | static void packetlogon(opt) | 
| 272 | 	char	*opt; | 
| 273 | { | 
| 274 | 	int	flag, xfd, logopt, change = 0; | 
| 275 |  | 
| 276 | 	flag = get_flags(); | 
| 277 | 	if (flag != 0) { | 
| 278 | 		if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) | 
| 279 | 			printf("log flag is currently %#x\n" , flag); | 
| 280 | 	} | 
| 281 |  | 
| 282 | 	flag &= ~(FF_LOGPASS|FF_LOGNOMATCH|FF_LOGBLOCK); | 
| 283 |  | 
| 284 | 	if (strstr(opt, "pass" )) { | 
| 285 | 		flag |= FF_LOGPASS; | 
| 286 | 		if (opts & OPT_VERBOSE) | 
| 287 | 			printf("set log flag: pass\n" ); | 
| 288 | 		change = 1; | 
| 289 | 	} | 
| 290 | 	if (strstr(opt, "nomatch" )) { | 
| 291 | 		flag |= FF_LOGNOMATCH; | 
| 292 | 		if (opts & OPT_VERBOSE) | 
| 293 | 			printf("set log flag: nomatch\n" ); | 
| 294 | 		change = 1; | 
| 295 | 	} | 
| 296 | 	if (strstr(opt, "block" ) || index(opt, 'd')) { | 
| 297 | 		flag |= FF_LOGBLOCK; | 
| 298 | 		if (opts & OPT_VERBOSE) | 
| 299 | 			printf("set log flag: block\n" ); | 
| 300 | 		change = 1; | 
| 301 | 	} | 
| 302 | 	if (strstr(opt, "none" )) { | 
| 303 | 		if (opts & OPT_VERBOSE) | 
| 304 | 			printf("disable all log flags\n" ); | 
| 305 | 		change = 1; | 
| 306 | 	} | 
| 307 |  | 
| 308 | 	if (change == 1) { | 
| 309 | 		if (opendevice(ipfname, 1) != -2 && | 
| 310 | 		    (ioctl(fd, SIOCSETFF, &flag) != 0)) | 
| 311 | 			ipferror(fd, "ioctl(SIOCSETFF)" ); | 
| 312 | 	} | 
| 313 |  | 
| 314 | 	if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) { | 
| 315 | 		flag = get_flags(); | 
| 316 | 		printf("log flags are now %#x\n" , flag); | 
| 317 | 	} | 
| 318 |  | 
| 319 | 	if (strstr(opt, "state" )) { | 
| 320 | 		if (opts & OPT_VERBOSE) | 
| 321 | 			printf("set state log flag\n" ); | 
| 322 | 		xfd = open(IPSTATE_NAME, O_RDWR); | 
| 323 | 		if (xfd >= 0) { | 
| 324 | 			logopt = 0; | 
| 325 | 			if (ioctl(xfd, SIOCGETLG, &logopt)) | 
| 326 | 				ipferror(fd, "ioctl(SIOCGETLG)" ); | 
| 327 | 			else { | 
| 328 | 				logopt = 1 - logopt; | 
| 329 | 				if (ioctl(xfd, SIOCSETLG, &logopt)) | 
| 330 | 					ipferror(xfd, "ioctl(SIOCSETLG)" ); | 
| 331 | 			} | 
| 332 | 			close(xfd); | 
| 333 | 		} | 
| 334 | 	} | 
| 335 |  | 
| 336 | 	if (strstr(opt, "nat" )) { | 
| 337 | 		if (opts & OPT_VERBOSE) | 
| 338 | 			printf("set nat log flag\n" ); | 
| 339 | 		xfd = open(IPNAT_NAME, O_RDWR); | 
| 340 | 		if (xfd >= 0) { | 
| 341 | 			logopt = 0; | 
| 342 | 			if (ioctl(xfd, SIOCGETLG, &logopt)) | 
| 343 | 				ipferror(xfd, "ioctl(SIOCGETLG)" ); | 
| 344 | 			else { | 
| 345 | 				logopt = 1 - logopt; | 
| 346 | 				if (ioctl(xfd, SIOCSETLG, &logopt)) | 
| 347 | 					ipferror(xfd, "ioctl(SIOCSETLG)" ); | 
| 348 | 			} | 
| 349 | 			close(xfd); | 
| 350 | 		} | 
| 351 | 	} | 
| 352 | } | 
| 353 |  | 
| 354 |  | 
| 355 | static void flushfilter(arg, filter) | 
| 356 | 	char *arg; | 
| 357 | 	int *filter; | 
| 358 | { | 
| 359 | 	int	fl = 0, rem; | 
| 360 |  | 
| 361 | 	if (!arg || !*arg) | 
| 362 | 		return; | 
| 363 | 	if (!strcmp(arg, "s" ) || !strcmp(arg, "S" ) || ISDIGIT(*arg)) { | 
| 364 | 		if (*arg == 'S') | 
| 365 | 			fl = 0; | 
| 366 | 		else if (*arg == 's') | 
| 367 | 			fl = 1; | 
| 368 | 		else | 
| 369 | 			fl = atoi(arg); | 
| 370 | 		rem = fl; | 
| 371 |  | 
| 372 | 		closedevice(); | 
| 373 | 		if (opendevice(IPSTATE_NAME, 1) == -2) | 
| 374 | 			exit(1); | 
| 375 |  | 
| 376 | 		if (!(opts & OPT_DONOTHING)) { | 
| 377 | 			if (use_inet6) { | 
| 378 | 				fprintf(stderr, | 
| 379 | 					"IPv6 rules are no longer seperate\n" ); | 
| 380 | 			} else if (filter != NULL) { | 
| 381 | 				ipfobj_t obj; | 
| 382 |  | 
| 383 | 				obj.ipfo_rev = IPFILTER_VERSION; | 
| 384 | 				obj.ipfo_size = filter[0] * sizeof(int); | 
| 385 | 				obj.ipfo_type = IPFOBJ_IPFEXPR; | 
| 386 | 				obj.ipfo_ptr = filter; | 
| 387 | 				if (ioctl(fd, SIOCMATCHFLUSH, &obj) == -1) { | 
| 388 | 					ipferror(fd, "ioctl(SIOCMATCHFLUSH)" ); | 
| 389 | 					fl = -1; | 
| 390 | 				} else { | 
| 391 | 					fl = obj.ipfo_retval; | 
| 392 | 				} | 
| 393 | 			} else { | 
| 394 | 				if (ioctl(fd, SIOCIPFFL, &fl) == -1) { | 
| 395 | 					ipferror(fd, "ioctl(SIOCIPFFL)" ); | 
| 396 | 					exit(1); | 
| 397 | 				} | 
| 398 | 			} | 
| 399 | 		} | 
| 400 | 		if ((opts & (OPT_DONOTHING|OPT_DEBUG)) == OPT_DEBUG) { | 
| 401 | 			printf("remove flags %s (%d)\n" , arg, rem); | 
| 402 | 		} | 
| 403 | 		if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) { | 
| 404 | 			printf("%d state entries removed\n" , fl); | 
| 405 | 		} | 
| 406 | 		closedevice(); | 
| 407 | 		return; | 
| 408 | 	} | 
| 409 |  | 
| 410 | #ifdef	SIOCIPFFA | 
| 411 | 	if (!strcmp(arg, "u" )) { | 
| 412 | 		closedevice(); | 
| 413 | 		/* | 
| 414 | 		 * Flush auth rules and packets | 
| 415 | 		 */ | 
| 416 | 		if (opendevice(IPL_AUTH, 1) == -1) | 
| 417 | 			perror("open(IPL_AUTH)" ); | 
| 418 | 		else { | 
| 419 | 			if (ioctl(fd, SIOCIPFFA, &fl) == -1) | 
| 420 | 				ipferror(fd, "ioctl(SIOCIPFFA)" ); | 
| 421 | 		} | 
| 422 | 		closedevice(); | 
| 423 | 		return; | 
| 424 | 	} | 
| 425 | #endif | 
| 426 |  | 
| 427 | 	if (strchr(arg, 'i') || strchr(arg, 'I')) | 
| 428 | 		fl = FR_INQUE; | 
| 429 | 	if (strchr(arg, 'o') || strchr(arg, 'O')) | 
| 430 | 		fl = FR_OUTQUE; | 
| 431 | 	if (strchr(arg, 'a') || strchr(arg, 'A')) | 
| 432 | 		fl = FR_OUTQUE|FR_INQUE; | 
| 433 | 	if (opts & OPT_INACTIVE) | 
| 434 | 		fl |= FR_INACTIVE; | 
| 435 | 	rem = fl; | 
| 436 |  | 
| 437 | 	if (opendevice(ipfname, 1) == -2) | 
| 438 | 		exit(1); | 
| 439 |  | 
| 440 | 	if (!(opts & OPT_DONOTHING)) { | 
| 441 | 		if (use_inet6) { | 
| 442 | 			if (ioctl(fd, SIOCIPFL6, &fl) == -1) { | 
| 443 | 				ipferror(fd, "ioctl(SIOCIPFL6)" ); | 
| 444 | 				exit(1); | 
| 445 | 			} | 
| 446 | 		} else { | 
| 447 | 			if (ioctl(fd, SIOCIPFFL, &fl) == -1) { | 
| 448 | 				ipferror(fd, "ioctl(SIOCIPFFL)" ); | 
| 449 | 				exit(1); | 
| 450 | 			} | 
| 451 | 		} | 
| 452 | 	} | 
| 453 |  | 
| 454 | 	if ((opts & (OPT_DONOTHING|OPT_DEBUG)) == OPT_DEBUG) { | 
| 455 | 		printf("remove flags %s%s (%d)\n" , (rem & FR_INQUE) ? "I"  : "" , | 
| 456 | 			(rem & FR_OUTQUE) ? "O"  : "" , rem); | 
| 457 | 	} | 
| 458 | 	if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) { | 
| 459 | 		printf("%d filter rules removed\n" , fl); | 
| 460 | 	} | 
| 461 | 	return; | 
| 462 | } | 
| 463 |  | 
| 464 |  | 
| 465 | static void swapactive() | 
| 466 | { | 
| 467 | 	int in = 2; | 
| 468 |  | 
| 469 | 	if (opendevice(ipfname, 1) != -2 && ioctl(fd, SIOCSWAPA, &in) == -1) | 
| 470 | 		ipferror(fd, "ioctl(SIOCSWAPA)" ); | 
| 471 | 	else | 
| 472 | 		printf("Set %d now inactive\n" , in); | 
| 473 | } | 
| 474 |  | 
| 475 |  | 
| 476 | void ipf_frsync() | 
| 477 | { | 
| 478 | 	int frsyn = 0; | 
| 479 |  | 
| 480 | 	if (opendevice(ipfname, 1) != -2 && ioctl(fd, SIOCFRSYN, &frsyn) == -1) | 
| 481 | 		ipferror(fd, "SIOCFRSYN" ); | 
| 482 | 	else | 
| 483 | 		printf("filter sync'd\n" ); | 
| 484 | } | 
| 485 |  | 
| 486 |  | 
| 487 | void zerostats() | 
| 488 | { | 
| 489 | 	ipfobj_t	obj; | 
| 490 | 	friostat_t	fio; | 
| 491 |  | 
| 492 | 	obj.ipfo_rev = IPFILTER_VERSION; | 
| 493 | 	obj.ipfo_type = IPFOBJ_IPFSTAT; | 
| 494 | 	obj.ipfo_size = sizeof(fio); | 
| 495 | 	obj.ipfo_ptr = &fio; | 
| 496 | 	obj.ipfo_offset = 0; | 
| 497 |  | 
| 498 | 	if (opendevice(ipfname, 1) != -2) { | 
| 499 | 		if (ioctl(fd, SIOCFRZST, &obj) == -1) { | 
| 500 | 			ipferror(fd, "ioctl(SIOCFRZST)" ); | 
| 501 | 			exit(-1); | 
| 502 | 		} | 
| 503 | 		showstats(&fio); | 
| 504 | 	} | 
| 505 |  | 
| 506 | } | 
| 507 |  | 
| 508 |  | 
| 509 | /* | 
| 510 |  * read the kernel stats for packets blocked and passed | 
| 511 |  */ | 
| 512 | static void showstats(fp) | 
| 513 | 	friostat_t	*fp; | 
| 514 | { | 
| 515 | 	printf("bad packets:\t\tin %lu\tout %lu\n" , | 
| 516 | 			fp->f_st[0].fr_bad, fp->f_st[1].fr_bad); | 
| 517 | 	printf(" input packets:\t\tblocked %lu passed %lu nomatch %lu" , | 
| 518 | 			fp->f_st[0].fr_block, fp->f_st[0].fr_pass, | 
| 519 | 			fp->f_st[0].fr_nom); | 
| 520 | 	printf(" counted %lu\n" , fp->f_st[0].fr_acct); | 
| 521 | 	printf("output packets:\t\tblocked %lu passed %lu nomatch %lu" , | 
| 522 | 			fp->f_st[1].fr_block, fp->f_st[1].fr_pass, | 
| 523 | 			fp->f_st[1].fr_nom); | 
| 524 | 	printf(" counted %lu\n" , fp->f_st[0].fr_acct); | 
| 525 | 	printf(" input packets logged:\tblocked %lu passed %lu\n" , | 
| 526 | 			fp->f_st[0].fr_bpkl, fp->f_st[0].fr_ppkl); | 
| 527 | 	printf("output packets logged:\tblocked %lu passed %lu\n" , | 
| 528 | 			fp->f_st[1].fr_bpkl, fp->f_st[1].fr_ppkl); | 
| 529 | } | 
| 530 |  | 
| 531 |  | 
| 532 | static int showversion() | 
| 533 | { | 
| 534 | 	struct friostat fio; | 
| 535 | 	ipfobj_t ipfo; | 
| 536 | 	u_32_t flags; | 
| 537 | 	char *s; | 
| 538 | 	int vfd; | 
| 539 |  | 
| 540 | 	bzero((caddr_t)&ipfo, sizeof(ipfo)); | 
| 541 | 	ipfo.ipfo_rev = IPFILTER_VERSION; | 
| 542 | 	ipfo.ipfo_size = sizeof(fio); | 
| 543 | 	ipfo.ipfo_ptr = (void *)&fio; | 
| 544 | 	ipfo.ipfo_type = IPFOBJ_IPFSTAT; | 
| 545 |  | 
| 546 | 	printf("ipf: %s (%d)\n" , IPL_VERSION, (int)sizeof(frentry_t)); | 
| 547 |  | 
| 548 | 	if ((vfd = open(ipfname, O_RDONLY)) == -1) { | 
| 549 | 		perror("open device" ); | 
| 550 | 		return 1; | 
| 551 | 	} | 
| 552 |  | 
| 553 | 	if (ioctl(vfd, SIOCGETFS, &ipfo)) { | 
| 554 | 		ipferror(vfd, "ioctl(SIOCGETFS)" ); | 
| 555 | 		close(vfd); | 
| 556 | 		return 1; | 
| 557 | 	} | 
| 558 | 	close(vfd); | 
| 559 | 	flags = get_flags(); | 
| 560 |  | 
| 561 | 	printf("Kernel: %-*.*s\n" , (int)sizeof(fio.f_version), | 
| 562 | 		(int)sizeof(fio.f_version), fio.f_version); | 
| 563 | 	printf("Running: %s\n" , (fio.f_running > 0) ? "yes"  : "no" ); | 
| 564 | 	printf("Log Flags: %#x = " , flags); | 
| 565 | 	s = "" ; | 
| 566 | 	if (flags & FF_LOGPASS) { | 
| 567 | 		printf("pass" ); | 
| 568 | 		s = ", " ; | 
| 569 | 	} | 
| 570 | 	if (flags & FF_LOGBLOCK) { | 
| 571 | 		printf("%sblock" , s); | 
| 572 | 		s = ", " ; | 
| 573 | 	} | 
| 574 | 	if (flags & FF_LOGNOMATCH) { | 
| 575 | 		printf("%snomatch" , s); | 
| 576 | 		s = ", " ; | 
| 577 | 	} | 
| 578 | 	if (flags & FF_BLOCKNONIP) { | 
| 579 | 		printf("%snonip" , s); | 
| 580 | 		s = ", " ; | 
| 581 | 	} | 
| 582 | 	if (!*s) | 
| 583 | 		printf("none set" ); | 
| 584 | 	putchar('\n'); | 
| 585 |  | 
| 586 | 	printf("Default: " ); | 
| 587 | 	if (FR_ISPASS(fio.f_defpass)) | 
| 588 | 		s = "pass" ; | 
| 589 | 	else if (FR_ISBLOCK(fio.f_defpass)) | 
| 590 | 		s = "block" ; | 
| 591 | 	else | 
| 592 | 		s = "nomatch -> block" ; | 
| 593 | 	printf("%s all, Logging: %savailable\n" , s, fio.f_logging ? ""  : "un" ); | 
| 594 | 	printf("Active list: %d\n" , fio.f_active); | 
| 595 | 	printf("Feature mask: %#x\n" , fio.f_features); | 
| 596 |  | 
| 597 | 	return 0; | 
| 598 | } | 
| 599 |  |