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