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