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 }