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