1 /* $FreeBSD$ */ 2 3 /* 4 * Copyright (C) 2012 by Darren Reed. 5 * 6 * See the IPFILTER.LICENCE file for details on licencing. 7 */ 8 #if !defined(lint) 9 static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed"; 10 static const char rcsid[] = "@(#)$Id$"; 11 #endif 12 13 #include "ipf.h" 14 15 16 typedef struct { 17 int c; 18 int e; 19 int n; 20 int p; 21 int s; 22 } mc_t; 23 24 25 static char *portcmp[] = { "*", "==", "!=", "<", ">", "<=", ">=", "**", "***" }; 26 static int count = 0; 27 28 int intcmp(const void *, const void *); 29 static void indent(FILE *, int); 30 static void printeq(FILE *, char *, int, int, int); 31 static void printipeq(FILE *, char *, int, int, int); 32 static void addrule(FILE *, frentry_t *); 33 static void printhooks(FILE *, int, int, frgroup_t *); 34 static void emitheader(frgroup_t *, u_int, u_int); 35 static void emitGroup(int, int, void *, frentry_t *, char *, 36 u_int, u_int); 37 static void emittail(void); 38 static void printCgroup(int, frentry_t *, mc_t *, char *); 39 40 #define FRC_IFN 0 41 #define FRC_V 1 42 #define FRC_P 2 43 #define FRC_FL 3 44 #define FRC_TOS 4 45 #define FRC_TTL 5 46 #define FRC_SRC 6 47 #define FRC_DST 7 48 #define FRC_TCP 8 49 #define FRC_SP 9 50 #define FRC_DP 10 51 #define FRC_OPT 11 52 #define FRC_SEC 12 53 #define FRC_ATH 13 54 #define FRC_ICT 14 55 #define FRC_ICC 15 56 #define FRC_MAX 16 57 58 59 static FILE *cfile = NULL; 60 61 /* 62 * This is called once per filter rule being loaded to emit data structures 63 * required. 64 */ 65 void 66 printc(frentry_t *fr) 67 { 68 u_long *ulp; 69 char *and; 70 FILE *fp; 71 int i; 72 73 if (fr->fr_family == 6) 74 return; 75 if ((fr->fr_type != FR_T_IPF) && (fr->fr_type != FR_T_NONE)) 76 return; 77 if ((fr->fr_type == FR_T_IPF) && 78 ((fr->fr_datype != FRI_NORMAL) || (fr->fr_satype != FRI_NORMAL))) 79 return; 80 81 if (cfile == NULL) 82 cfile = fopen("ip_rules.c", "w"); 83 if (cfile == NULL) 84 return; 85 fp = cfile; 86 if (count == 0) { 87 fprintf(fp, "/*\n"); 88 fprintf(fp, "* Copyright (C) 2012 by Darren Reed.\n"); 89 fprintf(fp, "*\n"); 90 fprintf(fp, "* Redistribution and use in source and binary forms are permitted\n"); 91 fprintf(fp, "* provided that this notice is preserved and due credit is given\n"); 92 fprintf(fp, "* to the original author and the contributors.\n"); 93 fprintf(fp, "*/\n\n"); 94 95 fprintf(fp, "#include <sys/param.h>\n"); 96 fprintf(fp, "#include <sys/types.h>\n"); 97 fprintf(fp, "#include <sys/time.h>\n"); 98 fprintf(fp, "#include <sys/socket.h>\n"); 99 fprintf(fp, "#if (__FreeBSD_version >= 40000)\n"); 100 fprintf(fp, "# if defined(_KERNEL)\n"); 101 fprintf(fp, "# include <sys/libkern.h>\n"); 102 fprintf(fp, "# else\n"); 103 fprintf(fp, "# include <sys/unistd.h>\n"); 104 fprintf(fp, "# endif\n"); 105 fprintf(fp, "#endif\n"); 106 fprintf(fp, "#if (__NetBSD_Version__ >= 399000000)\n"); 107 fprintf(fp, "#else\n"); 108 fprintf(fp, "# if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__sgi)\n"); 109 fprintf(fp, "# include <sys/systm.h>\n"); 110 fprintf(fp, "# endif\n"); 111 fprintf(fp, "#endif\n"); 112 fprintf(fp, "#include <sys/errno.h>\n"); 113 fprintf(fp, "#include <sys/param.h>\n"); 114 fprintf(fp, 115 "#if !defined(__SVR4) && !defined(__svr4__) && !defined(__hpux)\n"); 116 fprintf(fp, "# include <sys/mbuf.h>\n"); 117 fprintf(fp, "#endif\n"); 118 fprintf(fp, 119 "#if defined(__FreeBSD__) && (__FreeBSD_version > 220000)\n"); 120 fprintf(fp, "# include <sys/sockio.h>\n"); 121 fprintf(fp, "#else\n"); 122 fprintf(fp, "# include <sys/ioctl.h>\n"); 123 fprintf(fp, "#endif /* FreeBSD */\n"); 124 fprintf(fp, "#include <net/if.h>\n"); 125 fprintf(fp, "#include <netinet/in.h>\n"); 126 fprintf(fp, "#include <netinet/in_systm.h>\n"); 127 fprintf(fp, "#include <netinet/ip.h>\n"); 128 fprintf(fp, "#include <netinet/tcp.h>\n"); 129 fprintf(fp, "#include \"netinet/ip_compat.h\"\n"); 130 fprintf(fp, "#include \"netinet/ip_fil.h\"\n\n"); 131 fprintf(fp, "#include \"netinet/ip_rules.h\"\n\n"); 132 fprintf(fp, "#ifndef _KERNEL\n"); 133 fprintf(fp, "# include <string.h>\n"); 134 fprintf(fp, "#endif /* _KERNEL */\n"); 135 fprintf(fp, "\n"); 136 fprintf(fp, "#ifdef IPFILTER_COMPILED\n"); 137 fprintf(fp, "\n"); 138 fprintf(fp, "extern ipf_main_softc_t ipfmain;\n"); 139 fprintf(fp, "\n"); 140 } 141 142 addrule(fp, fr); 143 fr->fr_type |= FR_T_BUILTIN; 144 and = ""; 145 fr->fr_ref = 1; 146 i = sizeof(*fr); 147 if (i & -(1 - sizeof(*ulp))) 148 i += sizeof(u_long); 149 for (i /= sizeof(u_long), ulp = (u_long *)fr; i > 0; i--) { 150 fprintf(fp, "%s%#lx", and, *ulp++); 151 and = ", "; 152 } 153 fprintf(fp, "\n};\n"); 154 fr->fr_type &= ~FR_T_BUILTIN; 155 156 count++; 157 158 fflush(fp); 159 } 160 161 162 static frgroup_t *groups = NULL; 163 164 165 static void 166 addrule(FILE *fp, frentry_t *fr) 167 { 168 frentry_t *f, **fpp; 169 frgroup_t *g; 170 u_long *ulp; 171 char *ghead; 172 char *gname; 173 char *and; 174 int i; 175 176 f = (frentry_t *)malloc(sizeof(*f)); 177 bcopy((char *)fr, (char *)f, sizeof(*fr)); 178 if (fr->fr_ipf) { 179 f->fr_ipf = (fripf_t *)malloc(sizeof(*f->fr_ipf)); 180 bcopy((char *)fr->fr_ipf, (char *)f->fr_ipf, 181 sizeof(*fr->fr_ipf)); 182 } 183 184 f->fr_next = NULL; 185 gname = FR_NAME(fr, fr_group); 186 187 for (g = groups; g != NULL; g = g->fg_next) 188 if ((strncmp(g->fg_name, gname, FR_GROUPLEN) == 0) && 189 (g->fg_flags == (f->fr_flags & FR_INOUT))) 190 break; 191 192 if (g == NULL) { 193 g = (frgroup_t *)calloc(1, sizeof(*g)); 194 g->fg_next = groups; 195 groups = g; 196 g->fg_head = f; 197 strncpy(g->fg_name, gname, FR_GROUPLEN); 198 g->fg_ref = 0; 199 g->fg_flags = f->fr_flags & FR_INOUT; 200 } 201 202 for (fpp = &g->fg_start; *fpp != NULL; ) 203 fpp = &((*fpp)->fr_next); 204 *fpp = f; 205 206 if (fr->fr_dsize > 0) { 207 fprintf(fp, "\ 208 static u_long ipf%s_rule_data_%s_%u[] = {\n", 209 f->fr_flags & FR_INQUE ? "in" : "out", 210 g->fg_name, g->fg_ref); 211 and = ""; 212 i = fr->fr_dsize; 213 ulp = fr->fr_data; 214 for (i /= sizeof(u_long); i > 0; i--) { 215 fprintf(fp, "%s%#lx", and, *ulp++); 216 and = ", "; 217 } 218 fprintf(fp, "\n};\n"); 219 } 220 221 fprintf(fp, "\nstatic u_long %s_rule_%s_%d[] = {\n", 222 f->fr_flags & FR_INQUE ? "in" : "out", g->fg_name, g->fg_ref); 223 224 g->fg_ref++; 225 226 if (f->fr_grhead != -1) { 227 ghead = FR_NAME(f, fr_grhead); 228 for (g = groups; g != NULL; g = g->fg_next) 229 if ((strncmp(g->fg_name, ghead, FR_GROUPLEN) == 0) && 230 g->fg_flags == (f->fr_flags & FR_INOUT)) 231 break; 232 if (g == NULL) { 233 g = (frgroup_t *)calloc(1, sizeof(*g)); 234 g->fg_next = groups; 235 groups = g; 236 g->fg_head = f; 237 strncpy(g->fg_name, ghead, FR_GROUPLEN); 238 g->fg_ref = 0; 239 g->fg_flags = f->fr_flags & FR_INOUT; 240 } 241 } 242 } 243 244 245 int 246 intcmp(const void *c1, const void *c2) 247 { 248 const mc_t *i1 = (const mc_t *)c1, *i2 = (const mc_t *)c2; 249 250 if (i1->n == i2->n) { 251 return (i1->c - i2->c); 252 } 253 return (i2->n - i1->n); 254 } 255 256 257 static void 258 indent(FILE *fp, int in) 259 { 260 for (; in; in--) 261 fputc('\t', fp); 262 } 263 264 static void 265 printeq(FILE *fp, char *var, int m, int max, int v) 266 { 267 if (m == max) 268 fprintf(fp, "%s == %#x) {\n", var, v); 269 else 270 fprintf(fp, "(%s & %#x) == %#x) {\n", var, m, v); 271 } 272 273 /* 274 * Parameters: var - IP# being compared 275 * fl - 0 for positive match, 1 for negative match 276 * m - netmask 277 * v - required address 278 */ 279 static void 280 printipeq(FILE *fp, char *var, int fl, int m, int v) 281 { 282 if (m == 0xffffffff) 283 fprintf(fp, "%s ", var); 284 else 285 fprintf(fp, "(%s & %#x) ", var, m); 286 fprintf(fp, "%c", fl ? '!' : '='); 287 fprintf(fp, "= %#x) {\n", v); 288 } 289 290 291 void 292 emit(int num, int dir, void *v, frentry_t *fr) 293 { 294 u_int incnt, outcnt; 295 frgroup_t *g; 296 frentry_t *f; 297 298 for (g = groups; g != NULL; g = g->fg_next) { 299 if (dir == 0 || dir == -1) { 300 if ((g->fg_flags & FR_INQUE) == 0) 301 continue; 302 for (incnt = 0, f = g->fg_start; f != NULL; 303 f = f->fr_next) 304 incnt++; 305 emitGroup(num, dir, v, fr, g->fg_name, incnt, 0); 306 } 307 if (dir == 1 || dir == -1) { 308 if ((g->fg_flags & FR_OUTQUE) == 0) 309 continue; 310 for (outcnt = 0, f = g->fg_start; f != NULL; 311 f = f->fr_next) 312 outcnt++; 313 emitGroup(num, dir, v, fr, g->fg_name, 0, outcnt); 314 } 315 } 316 317 if (num == -1 && dir == -1) { 318 for (g = groups; g != NULL; g = g->fg_next) { 319 if ((g->fg_flags & FR_INQUE) != 0) { 320 for (incnt = 0, f = g->fg_start; f != NULL; 321 f = f->fr_next) 322 incnt++; 323 if (incnt > 0) 324 emitheader(g, incnt, 0); 325 } 326 if ((g->fg_flags & FR_OUTQUE) != 0) { 327 for (outcnt = 0, f = g->fg_start; f != NULL; 328 f = f->fr_next) 329 outcnt++; 330 if (outcnt > 0) 331 emitheader(g, 0, outcnt); 332 } 333 } 334 emittail(); 335 fprintf(cfile, "#endif /* IPFILTER_COMPILED */\n"); 336 } 337 338 } 339 340 341 static void 342 emitheader(frgroup_t *grp, u_int incount, u_int outcount) 343 { 344 static FILE *fph = NULL; 345 frgroup_t *g; 346 347 if (fph == NULL) { 348 fph = fopen("ip_rules.h", "w"); 349 if (fph == NULL) 350 return; 351 352 fprintf(fph, "extern int ipfrule_add(void));\n"); 353 fprintf(fph, "extern int ipfrule_remove(void));\n"); 354 } 355 356 printhooks(cfile, incount, outcount, grp); 357 358 if (incount) { 359 fprintf(fph, "\n\ 360 extern frentry_t *ipfrule_match_in_%s(fr_info_t *, u_32_t *));\n\ 361 extern frentry_t *ipf_rules_in_%s[%d];\n", 362 grp->fg_name, grp->fg_name, incount); 363 364 for (g = groups; g != grp; g = g->fg_next) 365 if ((strncmp(g->fg_name, grp->fg_name, 366 FR_GROUPLEN) == 0) && 367 g->fg_flags == grp->fg_flags) 368 break; 369 if (g == grp) { 370 fprintf(fph, "\n\ 371 extern int ipfrule_add_in_%s(void));\n\ 372 extern int ipfrule_remove_in_%s(void));\n", grp->fg_name, grp->fg_name); 373 } 374 } 375 if (outcount) { 376 fprintf(fph, "\n\ 377 extern frentry_t *ipfrule_match_out_%s(fr_info_t *, u_32_t *));\n\ 378 extern frentry_t *ipf_rules_out_%s[%d];\n", 379 grp->fg_name, grp->fg_name, outcount); 380 381 for (g = groups; g != grp; g = g->fg_next) 382 if ((strncmp(g->fg_name, grp->fg_name, 383 FR_GROUPLEN) == 0) && 384 g->fg_flags == grp->fg_flags) 385 break; 386 if (g == grp) { 387 fprintf(fph, "\n\ 388 extern int ipfrule_add_out_%s(void));\n\ 389 extern int ipfrule_remove_out_%s(void));\n", 390 grp->fg_name, grp->fg_name); 391 } 392 } 393 } 394 395 static void 396 emittail(void) 397 { 398 frgroup_t *g; 399 400 fprintf(cfile, "\n\ 401 int ipfrule_add()\n\ 402 {\n\ 403 int err;\n\ 404 \n"); 405 for (g = groups; g != NULL; g = g->fg_next) 406 fprintf(cfile, "\ 407 err = ipfrule_add_%s_%s();\n\ 408 if (err != 0)\n\ 409 return (err);\n", 410 (g->fg_flags & FR_INQUE) ? "in" : "out", g->fg_name); 411 fprintf(cfile, "\ 412 return (0);\n"); 413 fprintf(cfile, "}\n\ 414 \n"); 415 416 fprintf(cfile, "\n\ 417 int ipfrule_remove()\n\ 418 {\n\ 419 int err;\n\ 420 \n"); 421 for (g = groups; g != NULL; g = g->fg_next) 422 fprintf(cfile, "\ 423 err = ipfrule_remove_%s_%s();\n\ 424 if (err != 0)\n\ 425 return (err);\n", 426 (g->fg_flags & FR_INQUE) ? "in" : "out", g->fg_name); 427 fprintf(cfile, "\ 428 return (0);\n"); 429 fprintf(cfile, "}\n"); 430 } 431 432 433 static void 434 emitGroup(int num, int dir, void *v, frentry_t *fr, char *group, 435 u_int incount, u_int outcount) 436 { 437 static FILE *fp = NULL; 438 static int header[2] = { 0, 0 }; 439 static char egroup[FR_GROUPLEN] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 440 static int openfunc = 0; 441 static mc_t *n = NULL; 442 static int sin = 0; 443 frentry_t *f; 444 frgroup_t *g; 445 fripf_t *ipf; 446 int i, in, j; 447 mc_t *m = v; 448 449 if (fp == NULL) 450 fp = cfile; 451 if (fp == NULL) 452 return; 453 if (strncmp(egroup, group, FR_GROUPLEN)) { 454 for (sin--; sin > 0; sin--) { 455 indent(fp, sin); 456 fprintf(fp, "}\n"); 457 } 458 if (openfunc == 1) { 459 fprintf(fp, "\treturn (fr);\n}\n"); 460 openfunc = 0; 461 if (n != NULL) { 462 free(n); 463 n = NULL; 464 } 465 } 466 sin = 0; 467 header[0] = 0; 468 header[1] = 0; 469 strncpy(egroup, group, FR_GROUPLEN); 470 } else if (openfunc == 1 && num < 0) { 471 if (n != NULL) { 472 free(n); 473 n = NULL; 474 } 475 for (sin--; sin > 0; sin--) { 476 indent(fp, sin); 477 fprintf(fp, "}\n"); 478 } 479 if (openfunc == 1) { 480 fprintf(fp, "\treturn (fr);\n}\n"); 481 openfunc = 0; 482 } 483 } 484 485 if (dir == -1) 486 return; 487 488 for (g = groups; g != NULL; g = g->fg_next) { 489 if (dir == 0 && (g->fg_flags & FR_INQUE) == 0) 490 continue; 491 else if (dir == 1 && (g->fg_flags & FR_OUTQUE) == 0) 492 continue; 493 if (strncmp(g->fg_name, group, FR_GROUPLEN) != 0) 494 continue; 495 break; 496 } 497 498 /* 499 * Output the array of pointers to rules for this group. 500 */ 501 if (g != NULL && num == -2 && dir == 0 && header[0] == 0 && 502 incount != 0) { 503 fprintf(fp, "\nfrentry_t *ipf_rules_in_%s[%d] = {", 504 group, incount); 505 for (f = g->fg_start, i = 0; f != NULL; f = f->fr_next) { 506 if ((f->fr_flags & FR_INQUE) == 0) 507 continue; 508 if ((i & 1) == 0) { 509 fprintf(fp, "\n\t"); 510 } 511 fprintf(fp, "(frentry_t *)&in_rule_%s_%d", 512 FR_NAME(f, fr_group), i); 513 if (i + 1 < incount) 514 fprintf(fp, ", "); 515 i++; 516 } 517 fprintf(fp, "\n};\n"); 518 } 519 520 if (g != NULL && num == -2 && dir == 1 && header[0] == 0 && 521 outcount != 0) { 522 fprintf(fp, "\nfrentry_t *ipf_rules_out_%s[%d] = {", 523 group, outcount); 524 for (f = g->fg_start, i = 0; f != NULL; f = f->fr_next) { 525 if ((f->fr_flags & FR_OUTQUE) == 0) 526 continue; 527 if ((i & 1) == 0) { 528 fprintf(fp, "\n\t"); 529 } 530 fprintf(fp, "(frentry_t *)&out_rule_%s_%d", 531 FR_NAME(f, fr_group), i); 532 if (i + 1 < outcount) 533 fprintf(fp, ", "); 534 i++; 535 } 536 fprintf(fp, "\n};\n"); 537 fp = NULL; 538 } 539 540 if (num < 0) 541 return; 542 543 in = 0; 544 ipf = fr->fr_ipf; 545 546 /* 547 * If the function header has not been printed then print it now. 548 */ 549 if (g != NULL && header[dir] == 0) { 550 int pdst = 0, psrc = 0; 551 552 openfunc = 1; 553 fprintf(fp, "\nfrentry_t *ipfrule_match_%s_%s(fin, passp)\n", 554 (dir == 0) ? "in" : "out", group); 555 fprintf(fp, "fr_info_t *fin;\n"); 556 fprintf(fp, "u_32_t *passp;\n"); 557 fprintf(fp, "{\n"); 558 fprintf(fp, "\tfrentry_t *fr = NULL;\n"); 559 560 /* 561 * Print out any variables that need to be declared. 562 */ 563 for (f = g->fg_start, i = 0; f != NULL; f = f->fr_next) { 564 if (incount + outcount > m[FRC_SRC].e + 1) 565 psrc = 1; 566 if (incount + outcount > m[FRC_DST].e + 1) 567 pdst = 1; 568 } 569 if (psrc == 1) 570 fprintf(fp, "\tu_32_t src = ntohl(%s);\n", 571 "fin->fin_fi.fi_saddr"); 572 if (pdst == 1) 573 fprintf(fp, "\tu_32_t dst = ntohl(%s);\n", 574 "fin->fin_fi.fi_daddr"); 575 } 576 577 for (i = 0; i < FRC_MAX; i++) { 578 switch(m[i].c) 579 { 580 case FRC_IFN : 581 if (fr->fr_ifnames[0] != -1) 582 m[i].s = 1; 583 break; 584 case FRC_V : 585 if (ipf != NULL && ipf->fri_mip.fi_v != 0) 586 m[i].s = 1; 587 break; 588 case FRC_FL : 589 if (ipf != NULL && ipf->fri_mip.fi_flx != 0) 590 m[i].s = 1; 591 break; 592 case FRC_P : 593 if (ipf != NULL && ipf->fri_mip.fi_p != 0) 594 m[i].s = 1; 595 break; 596 case FRC_TTL : 597 if (ipf != NULL && ipf->fri_mip.fi_ttl != 0) 598 m[i].s = 1; 599 break; 600 case FRC_TOS : 601 if (ipf != NULL && ipf->fri_mip.fi_tos != 0) 602 m[i].s = 1; 603 break; 604 case FRC_TCP : 605 if (ipf == NULL) 606 break; 607 if ((ipf->fri_ip.fi_p == IPPROTO_TCP) && 608 fr->fr_tcpfm != 0) 609 m[i].s = 1; 610 break; 611 case FRC_SP : 612 if (ipf == NULL) 613 break; 614 if (fr->fr_scmp == FR_INRANGE) 615 m[i].s = 1; 616 else if (fr->fr_scmp == FR_OUTRANGE) 617 m[i].s = 1; 618 else if (fr->fr_scmp != 0) 619 m[i].s = 1; 620 break; 621 case FRC_DP : 622 if (ipf == NULL) 623 break; 624 if (fr->fr_dcmp == FR_INRANGE) 625 m[i].s = 1; 626 else if (fr->fr_dcmp == FR_OUTRANGE) 627 m[i].s = 1; 628 else if (fr->fr_dcmp != 0) 629 m[i].s = 1; 630 break; 631 case FRC_SRC : 632 if (ipf == NULL) 633 break; 634 if (fr->fr_satype == FRI_LOOKUP) { 635 ; 636 } else if ((fr->fr_smask != 0) || 637 (fr->fr_flags & FR_NOTSRCIP) != 0) 638 m[i].s = 1; 639 break; 640 case FRC_DST : 641 if (ipf == NULL) 642 break; 643 if (fr->fr_datype == FRI_LOOKUP) { 644 ; 645 } else if ((fr->fr_dmask != 0) || 646 (fr->fr_flags & FR_NOTDSTIP) != 0) 647 m[i].s = 1; 648 break; 649 case FRC_OPT : 650 if (ipf == NULL) 651 break; 652 if (fr->fr_optmask != 0) 653 m[i].s = 1; 654 break; 655 case FRC_SEC : 656 if (ipf == NULL) 657 break; 658 if (fr->fr_secmask != 0) 659 m[i].s = 1; 660 break; 661 case FRC_ATH : 662 if (ipf == NULL) 663 break; 664 if (fr->fr_authmask != 0) 665 m[i].s = 1; 666 break; 667 case FRC_ICT : 668 if (ipf == NULL) 669 break; 670 if ((fr->fr_icmpm & 0xff00) != 0) 671 m[i].s = 1; 672 break; 673 case FRC_ICC : 674 if (ipf == NULL) 675 break; 676 if ((fr->fr_icmpm & 0xff) != 0) 677 m[i].s = 1; 678 break; 679 } 680 } 681 682 if (!header[dir]) { 683 fprintf(fp, "\n"); 684 header[dir] = 1; 685 sin = 0; 686 } 687 688 qsort(m, FRC_MAX, sizeof(mc_t), intcmp); 689 690 if (n) { 691 /* 692 * Calculate the indentation interval upto the last common 693 * common comparison being made. 694 */ 695 for (i = 0, in = 1; i < FRC_MAX; i++) { 696 if (n[i].c != m[i].c) 697 break; 698 if (n[i].s != m[i].s) 699 break; 700 if (n[i].s) { 701 if (n[i].n && (n[i].n > n[i].e)) { 702 m[i].p++; 703 in += m[i].p; 704 break; 705 } 706 if (n[i].e > 0) { 707 in++; 708 } else 709 break; 710 } 711 } 712 if (sin != in) { 713 for (j = sin - 1; j >= in; j--) { 714 indent(fp, j); 715 fprintf(fp, "}\n"); 716 } 717 } 718 } else { 719 in = 1; 720 i = 0; 721 } 722 723 /* 724 * print out C code that implements a filter rule. 725 */ 726 for (; i < FRC_MAX; i++) { 727 switch(m[i].c) 728 { 729 case FRC_IFN : 730 if (m[i].s) { 731 indent(fp, in); 732 fprintf(fp, "if (fin->fin_ifp == "); 733 fprintf(fp, "ipf_rules_%s_%s[%d]->fr_ifa) {\n", 734 dir ? "out" : "in", group, num); 735 in++; 736 } 737 break; 738 case FRC_V : 739 if (m[i].s) { 740 indent(fp, in); 741 fprintf(fp, "if (fin->fin_v == %d) {\n", 742 ipf->fri_ip.fi_v); 743 in++; 744 } 745 break; 746 case FRC_FL : 747 if (m[i].s) { 748 indent(fp, in); 749 fprintf(fp, "if ("); 750 printeq(fp, "fin->fin_flx", 751 ipf->fri_mip.fi_flx, 0xf, 752 ipf->fri_ip.fi_flx); 753 in++; 754 } 755 break; 756 case FRC_P : 757 if (m[i].s) { 758 indent(fp, in); 759 fprintf(fp, "if (fin->fin_p == %d) {\n", 760 ipf->fri_ip.fi_p); 761 in++; 762 } 763 break; 764 case FRC_TTL : 765 if (m[i].s) { 766 indent(fp, in); 767 fprintf(fp, "if ("); 768 printeq(fp, "fin->fin_ttl", 769 ipf->fri_mip.fi_ttl, 0xff, 770 ipf->fri_ip.fi_ttl); 771 in++; 772 } 773 break; 774 case FRC_TOS : 775 if (m[i].s) { 776 indent(fp, in); 777 fprintf(fp, "if (fin->fin_tos"); 778 printeq(fp, "fin->fin_tos", 779 ipf->fri_mip.fi_tos, 0xff, 780 ipf->fri_ip.fi_tos); 781 in++; 782 } 783 break; 784 case FRC_TCP : 785 if (m[i].s) { 786 indent(fp, in); 787 fprintf(fp, "if ("); 788 printeq(fp, "fin->fin_tcpf", fr->fr_tcpfm, 789 0xff, fr->fr_tcpf); 790 in++; 791 } 792 break; 793 case FRC_SP : 794 if (!m[i].s) 795 break; 796 if (fr->fr_scmp == FR_INRANGE) { 797 indent(fp, in); 798 fprintf(fp, "if ((fin->fin_data[0] > %d) && ", 799 fr->fr_sport); 800 fprintf(fp, "(fin->fin_data[0] < %d)", 801 fr->fr_stop); 802 fprintf(fp, ") {\n"); 803 in++; 804 } else if (fr->fr_scmp == FR_OUTRANGE) { 805 indent(fp, in); 806 fprintf(fp, "if ((fin->fin_data[0] < %d) || ", 807 fr->fr_sport); 808 fprintf(fp, "(fin->fin_data[0] > %d)", 809 fr->fr_stop); 810 fprintf(fp, ") {\n"); 811 in++; 812 } else if (fr->fr_scmp) { 813 indent(fp, in); 814 fprintf(fp, "if (fin->fin_data[0] %s %d)", 815 portcmp[fr->fr_scmp], fr->fr_sport); 816 fprintf(fp, " {\n"); 817 in++; 818 } 819 break; 820 case FRC_DP : 821 if (!m[i].s) 822 break; 823 if (fr->fr_dcmp == FR_INRANGE) { 824 indent(fp, in); 825 fprintf(fp, "if ((fin->fin_data[1] > %d) && ", 826 fr->fr_dport); 827 fprintf(fp, "(fin->fin_data[1] < %d)", 828 fr->fr_dtop); 829 fprintf(fp, ") {\n"); 830 in++; 831 } else if (fr->fr_dcmp == FR_OUTRANGE) { 832 indent(fp, in); 833 fprintf(fp, "if ((fin->fin_data[1] < %d) || ", 834 fr->fr_dport); 835 fprintf(fp, "(fin->fin_data[1] > %d)", 836 fr->fr_dtop); 837 fprintf(fp, ") {\n"); 838 in++; 839 } else if (fr->fr_dcmp) { 840 indent(fp, in); 841 fprintf(fp, "if (fin->fin_data[1] %s %d)", 842 portcmp[fr->fr_dcmp], fr->fr_dport); 843 fprintf(fp, " {\n"); 844 in++; 845 } 846 break; 847 case FRC_SRC : 848 if (!m[i].s) 849 break; 850 if (fr->fr_satype == FRI_LOOKUP) { 851 ; 852 } else if ((fr->fr_smask != 0) || 853 (fr->fr_flags & FR_NOTSRCIP) != 0) { 854 indent(fp, in); 855 fprintf(fp, "if ("); 856 printipeq(fp, "src", 857 fr->fr_flags & FR_NOTSRCIP, 858 fr->fr_smask, fr->fr_saddr); 859 in++; 860 } 861 break; 862 case FRC_DST : 863 if (!m[i].s) 864 break; 865 if (fr->fr_datype == FRI_LOOKUP) { 866 ; 867 } else if ((fr->fr_dmask != 0) || 868 (fr->fr_flags & FR_NOTDSTIP) != 0) { 869 indent(fp, in); 870 fprintf(fp, "if ("); 871 printipeq(fp, "dst", 872 fr->fr_flags & FR_NOTDSTIP, 873 fr->fr_dmask, fr->fr_daddr); 874 in++; 875 } 876 break; 877 case FRC_OPT : 878 if (m[i].s) { 879 indent(fp, in); 880 fprintf(fp, "if ("); 881 printeq(fp, "fin->fin_fi.fi_optmsk", 882 fr->fr_optmask, 0xffffffff, 883 fr->fr_optbits); 884 in++; 885 } 886 break; 887 case FRC_SEC : 888 if (m[i].s) { 889 indent(fp, in); 890 fprintf(fp, "if ("); 891 printeq(fp, "fin->fin_fi.fi_secmsk", 892 fr->fr_secmask, 0xffff, 893 fr->fr_secbits); 894 in++; 895 } 896 break; 897 case FRC_ATH : 898 if (m[i].s) { 899 indent(fp, in); 900 fprintf(fp, "if ("); 901 printeq(fp, "fin->fin_fi.fi_authmsk", 902 fr->fr_authmask, 0xffff, 903 fr->fr_authbits); 904 in++; 905 } 906 break; 907 case FRC_ICT : 908 if (m[i].s) { 909 indent(fp, in); 910 fprintf(fp, "if ("); 911 printeq(fp, "fin->fin_data[0]", 912 fr->fr_icmpm & 0xff00, 0xffff, 913 fr->fr_icmp & 0xff00); 914 in++; 915 } 916 break; 917 case FRC_ICC : 918 if (m[i].s) { 919 indent(fp, in); 920 fprintf(fp, "if ("); 921 printeq(fp, "fin->fin_data[0]", 922 fr->fr_icmpm & 0xff, 0xffff, 923 fr->fr_icmp & 0xff); 924 in++; 925 } 926 break; 927 } 928 929 } 930 931 indent(fp, in); 932 if (fr->fr_flags & FR_QUICK) { 933 fprintf(fp, "return ((frentry_t *)&%s_rule_%s_%d);\n", 934 fr->fr_flags & FR_INQUE ? "in" : "out", 935 FR_NAME(fr, fr_group), num); 936 } else { 937 fprintf(fp, "fr = (frentry_t *)&%s_rule_%s_%d;\n", 938 fr->fr_flags & FR_INQUE ? "in" : "out", 939 FR_NAME(fr, fr_group), num); 940 } 941 if (n == NULL) 942 n = (mc_t *)malloc(sizeof(*n) * FRC_MAX); 943 bcopy((char *)m, (char *)n, sizeof(*n) * FRC_MAX); 944 sin = in; 945 } 946 947 948 void 949 printC(int dir) 950 { 951 static mc_t *m = NULL; 952 frgroup_t *g; 953 954 if (m == NULL) 955 m = (mc_t *)calloc(FRC_MAX, sizeof(*m)); 956 957 for (g = groups; g != NULL; g = g->fg_next) { 958 if ((dir == 0) && ((g->fg_flags & FR_INQUE) != 0)) 959 printCgroup(dir, g->fg_start, m, g->fg_name); 960 if ((dir == 1) && ((g->fg_flags & FR_OUTQUE) != 0)) 961 printCgroup(dir, g->fg_start, m, g->fg_name); 962 } 963 964 emit(-1, dir, m, NULL); 965 } 966 967 968 /* 969 * Now print out code to implement all of the rules. 970 */ 971 static void 972 printCgroup(int dir, frentry_t *top, mc_t *m, char *group) 973 { 974 frentry_t *fr, *fr1; 975 int i, n, rn; 976 u_int count; 977 978 for (count = 0, fr1 = top; fr1 != NULL; fr1 = fr1->fr_next) { 979 if ((dir == 0) && ((fr1->fr_flags & FR_INQUE) != 0)) 980 count++; 981 else if ((dir == 1) && ((fr1->fr_flags & FR_OUTQUE) != 0)) 982 count++; 983 } 984 985 if (dir == 0) 986 emitGroup(-2, dir, m, fr1, group, count, 0); 987 else if (dir == 1) 988 emitGroup(-2, dir, m, fr1, group, 0, count); 989 990 /* 991 * Before printing each rule, check to see how many of its fields are 992 * matched by subsequent rules. 993 */ 994 for (fr1 = top, rn = 0; fr1 != NULL; fr1 = fr1->fr_next, rn++) { 995 if (!dir && !(fr1->fr_flags & FR_INQUE)) 996 continue; 997 if (dir && !(fr1->fr_flags & FR_OUTQUE)) 998 continue; 999 n = 0xfffffff; 1000 1001 for (i = 0; i < FRC_MAX; i++) 1002 m[i].e = 0; 1003 qsort(m, FRC_MAX, sizeof(mc_t), intcmp); 1004 1005 for (i = 0; i < FRC_MAX; i++) { 1006 m[i].c = i; 1007 m[i].e = 0; 1008 m[i].n = 0; 1009 m[i].s = 0; 1010 } 1011 1012 for (fr = fr1->fr_next; fr; fr = fr->fr_next) { 1013 if (!dir && !(fr->fr_flags & FR_INQUE)) 1014 continue; 1015 if (dir && !(fr->fr_flags & FR_OUTQUE)) 1016 continue; 1017 1018 if ((n & 0x0001) && 1019 !strcmp(fr1->fr_names + fr1->fr_ifnames[0], 1020 fr->fr_names + fr->fr_ifnames[0])) { 1021 m[FRC_IFN].e++; 1022 m[FRC_IFN].n++; 1023 } else 1024 n &= ~0x0001; 1025 1026 if ((n & 0x0002) && (fr1->fr_family == fr->fr_family)) { 1027 m[FRC_V].e++; 1028 m[FRC_V].n++; 1029 } else 1030 n &= ~0x0002; 1031 1032 if ((n & 0x0004) && 1033 (fr->fr_type == fr1->fr_type) && 1034 (fr->fr_type == FR_T_IPF) && 1035 (fr1->fr_mip.fi_flx == fr->fr_mip.fi_flx) && 1036 (fr1->fr_ip.fi_flx == fr->fr_ip.fi_flx)) { 1037 m[FRC_FL].e++; 1038 m[FRC_FL].n++; 1039 } else 1040 n &= ~0x0004; 1041 1042 if ((n & 0x0008) && 1043 (fr->fr_type == fr1->fr_type) && 1044 (fr->fr_type == FR_T_IPF) && 1045 (fr1->fr_proto == fr->fr_proto)) { 1046 m[FRC_P].e++; 1047 m[FRC_P].n++; 1048 } else 1049 n &= ~0x0008; 1050 1051 if ((n & 0x0010) && 1052 (fr->fr_type == fr1->fr_type) && 1053 (fr->fr_type == FR_T_IPF) && 1054 (fr1->fr_ttl == fr->fr_ttl)) { 1055 m[FRC_TTL].e++; 1056 m[FRC_TTL].n++; 1057 } else 1058 n &= ~0x0010; 1059 1060 if ((n & 0x0020) && 1061 (fr->fr_type == fr1->fr_type) && 1062 (fr->fr_type == FR_T_IPF) && 1063 (fr1->fr_tos == fr->fr_tos)) { 1064 m[FRC_TOS].e++; 1065 m[FRC_TOS].n++; 1066 } else 1067 n &= ~0x0020; 1068 1069 if ((n & 0x0040) && 1070 (fr->fr_type == fr1->fr_type) && 1071 (fr->fr_type == FR_T_IPF) && 1072 ((fr1->fr_tcpfm == fr->fr_tcpfm) && 1073 (fr1->fr_tcpf == fr->fr_tcpf))) { 1074 m[FRC_TCP].e++; 1075 m[FRC_TCP].n++; 1076 } else 1077 n &= ~0x0040; 1078 1079 if ((n & 0x0080) && 1080 (fr->fr_type == fr1->fr_type) && 1081 (fr->fr_type == FR_T_IPF) && 1082 ((fr1->fr_scmp == fr->fr_scmp) && 1083 (fr1->fr_stop == fr->fr_stop) && 1084 (fr1->fr_sport == fr->fr_sport))) { 1085 m[FRC_SP].e++; 1086 m[FRC_SP].n++; 1087 } else 1088 n &= ~0x0080; 1089 1090 if ((n & 0x0100) && 1091 (fr->fr_type == fr1->fr_type) && 1092 (fr->fr_type == FR_T_IPF) && 1093 ((fr1->fr_dcmp == fr->fr_dcmp) && 1094 (fr1->fr_dtop == fr->fr_dtop) && 1095 (fr1->fr_dport == fr->fr_dport))) { 1096 m[FRC_DP].e++; 1097 m[FRC_DP].n++; 1098 } else 1099 n &= ~0x0100; 1100 1101 if ((n & 0x0200) && 1102 (fr->fr_type == fr1->fr_type) && 1103 (fr->fr_type == FR_T_IPF) && 1104 ((fr1->fr_satype == FRI_LOOKUP) && 1105 (fr->fr_satype == FRI_LOOKUP) && 1106 (fr1->fr_srcnum == fr->fr_srcnum))) { 1107 m[FRC_SRC].e++; 1108 m[FRC_SRC].n++; 1109 } else if ((n & 0x0200) && 1110 (fr->fr_type == fr1->fr_type) && 1111 (fr->fr_type == FR_T_IPF) && 1112 (((fr1->fr_flags & FR_NOTSRCIP) == 1113 (fr->fr_flags & FR_NOTSRCIP)))) { 1114 if ((fr1->fr_smask == fr->fr_smask) && 1115 (fr1->fr_saddr == fr->fr_saddr)) 1116 m[FRC_SRC].e++; 1117 else 1118 n &= ~0x0200; 1119 if (fr1->fr_smask && 1120 (fr1->fr_saddr & fr1->fr_smask) == 1121 (fr->fr_saddr & fr1->fr_smask)) { 1122 m[FRC_SRC].n++; 1123 n |= 0x0200; 1124 } 1125 } else { 1126 n &= ~0x0200; 1127 } 1128 1129 if ((n & 0x0400) && 1130 (fr->fr_type == fr1->fr_type) && 1131 (fr->fr_type == FR_T_IPF) && 1132 ((fr1->fr_datype == FRI_LOOKUP) && 1133 (fr->fr_datype == FRI_LOOKUP) && 1134 (fr1->fr_dstnum == fr->fr_dstnum))) { 1135 m[FRC_DST].e++; 1136 m[FRC_DST].n++; 1137 } else if ((n & 0x0400) && 1138 (fr->fr_type == fr1->fr_type) && 1139 (fr->fr_type == FR_T_IPF) && 1140 (((fr1->fr_flags & FR_NOTDSTIP) == 1141 (fr->fr_flags & FR_NOTDSTIP)))) { 1142 if ((fr1->fr_dmask == fr->fr_dmask) && 1143 (fr1->fr_daddr == fr->fr_daddr)) 1144 m[FRC_DST].e++; 1145 else 1146 n &= ~0x0400; 1147 if (fr1->fr_dmask && 1148 (fr1->fr_daddr & fr1->fr_dmask) == 1149 (fr->fr_daddr & fr1->fr_dmask)) { 1150 m[FRC_DST].n++; 1151 n |= 0x0400; 1152 } 1153 } else { 1154 n &= ~0x0400; 1155 } 1156 1157 if ((n & 0x0800) && 1158 (fr->fr_type == fr1->fr_type) && 1159 (fr->fr_type == FR_T_IPF) && 1160 (fr1->fr_optmask == fr->fr_optmask) && 1161 (fr1->fr_optbits == fr->fr_optbits)) { 1162 m[FRC_OPT].e++; 1163 m[FRC_OPT].n++; 1164 } else 1165 n &= ~0x0800; 1166 1167 if ((n & 0x1000) && 1168 (fr->fr_type == fr1->fr_type) && 1169 (fr->fr_type == FR_T_IPF) && 1170 (fr1->fr_secmask == fr->fr_secmask) && 1171 (fr1->fr_secbits == fr->fr_secbits)) { 1172 m[FRC_SEC].e++; 1173 m[FRC_SEC].n++; 1174 } else 1175 n &= ~0x1000; 1176 1177 if ((n & 0x10000) && 1178 (fr->fr_type == fr1->fr_type) && 1179 (fr->fr_type == FR_T_IPF) && 1180 (fr1->fr_authmask == fr->fr_authmask) && 1181 (fr1->fr_authbits == fr->fr_authbits)) { 1182 m[FRC_ATH].e++; 1183 m[FRC_ATH].n++; 1184 } else 1185 n &= ~0x10000; 1186 1187 if ((n & 0x20000) && 1188 (fr->fr_type == fr1->fr_type) && 1189 (fr->fr_type == FR_T_IPF) && 1190 ((fr1->fr_icmpm & 0xff00) == 1191 (fr->fr_icmpm & 0xff00)) && 1192 ((fr1->fr_icmp & 0xff00) == 1193 (fr->fr_icmp & 0xff00))) { 1194 m[FRC_ICT].e++; 1195 m[FRC_ICT].n++; 1196 } else 1197 n &= ~0x20000; 1198 1199 if ((n & 0x40000) && 1200 (fr->fr_type == fr1->fr_type) && 1201 (fr->fr_type == FR_T_IPF) && 1202 ((fr1->fr_icmpm & 0xff) == (fr->fr_icmpm & 0xff)) && 1203 ((fr1->fr_icmp & 0xff) == (fr->fr_icmp & 0xff))) { 1204 m[FRC_ICC].e++; 1205 m[FRC_ICC].n++; 1206 } else 1207 n &= ~0x40000; 1208 } 1209 /*msort(m);*/ 1210 1211 if (dir == 0) 1212 emitGroup(rn, dir, m, fr1, group, count, 0); 1213 else if (dir == 1) 1214 emitGroup(rn, dir, m, fr1, group, 0, count); 1215 } 1216 } 1217 1218 static void 1219 printhooks(FILE *fp, int in, int out, frgroup_t *grp) 1220 { 1221 frentry_t *fr; 1222 char *group; 1223 int dogrp, i; 1224 char *instr; 1225 1226 group = grp->fg_name; 1227 dogrp = 0; 1228 1229 if (in && out) { 1230 fprintf(stderr, 1231 "printhooks called with both in and out set\n"); 1232 exit(1); 1233 } 1234 1235 if (in) { 1236 instr = "in"; 1237 } else if (out) { 1238 instr = "out"; 1239 } else { 1240 instr = "???"; 1241 } 1242 fprintf(fp, "static frentry_t ipfrule_%s_%s;\n", instr, group); 1243 1244 fprintf(fp, "\ 1245 \n\ 1246 int ipfrule_add_%s_%s()\n", instr, group); 1247 fprintf(fp, "\ 1248 {\n\ 1249 int i, j, err = 0, max;\n\ 1250 frentry_t *fp;\n"); 1251 1252 if (dogrp) 1253 fprintf(fp, "\ 1254 frgroup_t *fg;\n"); 1255 1256 fprintf(fp, "\n"); 1257 1258 for (i = 0, fr = grp->fg_start; fr != NULL; i++, fr = fr->fr_next) 1259 if (fr->fr_dsize > 0) { 1260 fprintf(fp, "\ 1261 ipf_rules_%s_%s[%d]->fr_data = &ipf%s_rule_data_%s_%u;\n", 1262 instr, grp->fg_name, i, 1263 instr, grp->fg_name, i); 1264 } 1265 fprintf(fp, "\ 1266 max = sizeof(ipf_rules_%s_%s)/sizeof(frentry_t *);\n\ 1267 for (i = 0; i < max; i++) {\n\ 1268 fp = ipf_rules_%s_%s[i];\n\ 1269 fp->fr_next = NULL;\n", instr, group, instr, group); 1270 1271 fprintf(fp, "\ 1272 for (j = i + 1; j < max; j++)\n\ 1273 if (strncmp(fp->fr_names + fp->fr_group,\n\ 1274 ipf_rules_%s_%s[j]->fr_names +\n\ 1275 ipf_rules_%s_%s[j]->fr_group,\n\ 1276 FR_GROUPLEN) == 0) {\n\ 1277 if (ipf_rules_%s_%s[j] != NULL)\n\ 1278 ipf_rules_%s_%s[j]->fr_pnext =\n\ 1279 &fp->fr_next;\n\ 1280 fp->fr_pnext = &ipf_rules_%s_%s[j];\n\ 1281 fp->fr_next = ipf_rules_%s_%s[j];\n\ 1282 break;\n\ 1283 }\n", instr, group, instr, group, instr, group, 1284 instr, group, instr, group, instr, group); 1285 if (dogrp) 1286 fprintf(fp, "\ 1287 \n\ 1288 if (fp->fr_grhead != -1) {\n\ 1289 fg = fr_addgroup(fp->fr_names + fp->fr_grhead,\n\ 1290 fp, FR_INQUE, IPL_LOGIPF, 0);\n\ 1291 if (fg != NULL)\n\ 1292 fp->fr_grp = &fg->fg_start;\n\ 1293 }\n"); 1294 fprintf(fp, "\ 1295 }\n\ 1296 \n\ 1297 fp = &ipfrule_%s_%s;\n", instr, group); 1298 fprintf(fp, "\ 1299 bzero((char *)fp, sizeof(*fp));\n\ 1300 fp->fr_type = FR_T_CALLFUNC_BUILTIN;\n\ 1301 fp->fr_flags = FR_%sQUE|FR_NOMATCH;\n\ 1302 fp->fr_data = (void *)ipf_rules_%s_%s[0];\n", 1303 (in != 0) ? "IN" : "OUT", instr, group); 1304 fprintf(fp, "\ 1305 fp->fr_dsize = sizeof(ipf_rules_%s_%s[0]);\n", 1306 instr, group); 1307 1308 fprintf(fp, "\ 1309 fp->fr_family = AF_INET;\n\ 1310 fp->fr_func = (ipfunc_t)ipfrule_match_%s_%s;\n\ 1311 err = frrequest(&ipfmain, IPL_LOGIPF, SIOCADDFR, (caddr_t)fp,\n\ 1312 ipfmain.ipf_active, 0);\n", 1313 instr, group); 1314 fprintf(fp, "\treturn (err);\n}\n"); 1315 1316 fprintf(fp, "\n\n\ 1317 int ipfrule_remove_%s_%s()\n", instr, group); 1318 fprintf(fp, "\ 1319 {\n\ 1320 int err = 0, i;\n\ 1321 frentry_t *fp;\n\ 1322 \n\ 1323 /*\n\ 1324 * Try to remove the %sbound rule.\n", instr); 1325 1326 fprintf(fp, "\ 1327 */\n\ 1328 if (ipfrule_%s_%s.fr_ref > 0) {\n", instr, group); 1329 1330 fprintf(fp, "\ 1331 err = EBUSY;\n\ 1332 } else {\n"); 1333 1334 fprintf(fp, "\ 1335 i = sizeof(ipf_rules_%s_%s)/sizeof(frentry_t *) - 1;\n\ 1336 for (; i >= 0; i--) {\n\ 1337 fp = ipf_rules_%s_%s[i];\n\ 1338 if (fp->fr_ref > 1) {\n\ 1339 err = EBUSY;\n\ 1340 break;\n\ 1341 }\n\ 1342 }\n\ 1343 }\n\ 1344 if (err == 0)\n\ 1345 err = frrequest(&ipfmain, IPL_LOGIPF, SIOCDELFR,\n\ 1346 (caddr_t)&ipfrule_%s_%s,\n\ 1347 ipfmain.ipf_active, 0);\n", 1348 instr, group, instr, group, instr, group); 1349 fprintf(fp, "\ 1350 if (err)\n\ 1351 return (err);\n\ 1352 \n\n"); 1353 1354 fprintf(fp, "\treturn (err);\n}\n"); 1355 } 1356