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