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