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