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