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