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