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