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