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