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