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