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