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