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