xref: /freebsd/sbin/ipf/ipf/ipfcomp.c (revision f7cee4fa)
141edb306SCy Schubert 
241edb306SCy Schubert /*
341edb306SCy Schubert  * Copyright (C) 2012 by Darren Reed.
441edb306SCy Schubert  *
541edb306SCy Schubert  * See the IPFILTER.LICENCE file for details on licencing.
641edb306SCy Schubert  */
741edb306SCy Schubert 
841edb306SCy Schubert #include "ipf.h"
941edb306SCy Schubert 
1041edb306SCy Schubert 
1141edb306SCy Schubert typedef struct {
1241edb306SCy Schubert 	int c;
1341edb306SCy Schubert 	int e;
1441edb306SCy Schubert 	int n;
1541edb306SCy Schubert 	int p;
1641edb306SCy Schubert 	int s;
1741edb306SCy Schubert } mc_t;
1841edb306SCy Schubert 
1941edb306SCy Schubert 
2041edb306SCy Schubert static char *portcmp[] = { "*", "==", "!=", "<", ">", "<=", ">=", "**", "***" };
2141edb306SCy Schubert static int count = 0;
2241edb306SCy Schubert 
2341edb306SCy Schubert int intcmp(const void *, const void *);
2441edb306SCy Schubert static void indent(FILE *, int);
2541edb306SCy Schubert static void printeq(FILE *, char *, int, int, int);
2641edb306SCy Schubert static void printipeq(FILE *, char *, int, int, int);
2741edb306SCy Schubert static void addrule(FILE *, frentry_t *);
2841edb306SCy Schubert static void printhooks(FILE *, int, int, frgroup_t *);
2941edb306SCy Schubert static void emitheader(frgroup_t *, u_int, u_int);
3041edb306SCy Schubert static void emitGroup(int, int, void *, frentry_t *, char *,
3141edb306SCy Schubert 			   u_int, u_int);
3241edb306SCy Schubert static void emittail(void);
3341edb306SCy Schubert static void printCgroup(int, frentry_t *, mc_t *, char *);
3441edb306SCy Schubert 
3541edb306SCy Schubert #define	FRC_IFN	0
3641edb306SCy Schubert #define	FRC_V	1
3741edb306SCy Schubert #define	FRC_P	2
3841edb306SCy Schubert #define	FRC_FL	3
3941edb306SCy Schubert #define	FRC_TOS	4
4041edb306SCy Schubert #define	FRC_TTL	5
4141edb306SCy Schubert #define	FRC_SRC	6
4241edb306SCy Schubert #define	FRC_DST	7
4341edb306SCy Schubert #define	FRC_TCP	8
4441edb306SCy Schubert #define	FRC_SP	9
4541edb306SCy Schubert #define	FRC_DP	10
4641edb306SCy Schubert #define	FRC_OPT	11
4741edb306SCy Schubert #define	FRC_SEC	12
4841edb306SCy Schubert #define	FRC_ATH	13
4941edb306SCy Schubert #define	FRC_ICT	14
5041edb306SCy Schubert #define	FRC_ICC	15
5141edb306SCy Schubert #define	FRC_MAX	16
5241edb306SCy Schubert 
5341edb306SCy Schubert 
5441edb306SCy Schubert static	FILE	*cfile = NULL;
5541edb306SCy Schubert 
5641edb306SCy Schubert /*
5741edb306SCy Schubert  * This is called once per filter rule being loaded to emit data structures
5841edb306SCy Schubert  * required.
5941edb306SCy Schubert  */
60a3522837SCy Schubert void
printc(frentry_t * fr)61a3522837SCy Schubert printc(frentry_t *fr)
6241edb306SCy Schubert {
6341edb306SCy Schubert 	u_long *ulp;
6441edb306SCy Schubert 	char *and;
6541edb306SCy Schubert 	FILE *fp;
6641edb306SCy Schubert 	int i;
6741edb306SCy Schubert 
6841edb306SCy Schubert 	if (fr->fr_family == 6)
6941edb306SCy Schubert 		return;
7041edb306SCy Schubert 	if ((fr->fr_type != FR_T_IPF) && (fr->fr_type != FR_T_NONE))
7141edb306SCy Schubert 		return;
7241edb306SCy Schubert 	if ((fr->fr_type == FR_T_IPF) &&
7341edb306SCy Schubert 	    ((fr->fr_datype != FRI_NORMAL) || (fr->fr_satype != FRI_NORMAL)))
7441edb306SCy Schubert 		return;
7541edb306SCy Schubert 
7641edb306SCy Schubert 	if (cfile == NULL)
7741edb306SCy Schubert 		cfile = fopen("ip_rules.c", "w");
7841edb306SCy Schubert 	if (cfile == NULL)
7941edb306SCy Schubert 		return;
8041edb306SCy Schubert 	fp = cfile;
8141edb306SCy Schubert 	if (count == 0) {
8241edb306SCy Schubert 		fprintf(fp, "/*\n");
8341edb306SCy Schubert  		fprintf(fp, "* Copyright (C) 2012 by Darren Reed.\n");
8441edb306SCy Schubert  		fprintf(fp, "*\n");
8541edb306SCy Schubert  		fprintf(fp, "* Redistribution and use in source and binary forms are permitted\n");
8641edb306SCy Schubert  		fprintf(fp, "* provided that this notice is preserved and due credit is given\n");
8741edb306SCy Schubert  		fprintf(fp, "* to the original author and the contributors.\n");
8841edb306SCy Schubert  		fprintf(fp, "*/\n\n");
8941edb306SCy Schubert 
9041edb306SCy Schubert 		fprintf(fp, "#include <sys/param.h>\n");
9141edb306SCy Schubert 		fprintf(fp, "#include <sys/types.h>\n");
9241edb306SCy Schubert 		fprintf(fp, "#include <sys/time.h>\n");
9341edb306SCy Schubert 		fprintf(fp, "#include <sys/socket.h>\n");
9441edb306SCy Schubert 		fprintf(fp, "#if (__FreeBSD_version >= 40000)\n");
9541edb306SCy Schubert 		fprintf(fp, "# if defined(_KERNEL)\n");
9641edb306SCy Schubert 		fprintf(fp, "#  include <sys/libkern.h>\n");
9741edb306SCy Schubert 		fprintf(fp, "# else\n");
9841edb306SCy Schubert 		fprintf(fp, "#  include <sys/unistd.h>\n");
9941edb306SCy Schubert 		fprintf(fp, "# endif\n");
10041edb306SCy Schubert 		fprintf(fp, "#endif\n");
10141edb306SCy Schubert 		fprintf(fp, "#if (__NetBSD_Version__ >= 399000000)\n");
10241edb306SCy Schubert 		fprintf(fp, "#else\n");
10341edb306SCy Schubert 		fprintf(fp, "# if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__sgi)\n");
10441edb306SCy Schubert 		fprintf(fp, "#  include <sys/systm.h>\n");
10541edb306SCy Schubert 		fprintf(fp, "# endif\n");
10641edb306SCy Schubert 		fprintf(fp, "#endif\n");
10741edb306SCy Schubert 		fprintf(fp, "#include <sys/errno.h>\n");
10841edb306SCy Schubert 		fprintf(fp, "#include <sys/param.h>\n");
10941edb306SCy Schubert 		fprintf(fp,
11041edb306SCy Schubert "#if !defined(__SVR4) && !defined(__svr4__) && !defined(__hpux)\n");
11141edb306SCy Schubert 		fprintf(fp, "# include <sys/mbuf.h>\n");
11241edb306SCy Schubert 		fprintf(fp, "#endif\n");
11341edb306SCy Schubert 		fprintf(fp,
11441edb306SCy Schubert "#if defined(__FreeBSD__) && (__FreeBSD_version > 220000)\n");
11541edb306SCy Schubert 		fprintf(fp, "# include <sys/sockio.h>\n");
11641edb306SCy Schubert 		fprintf(fp, "#else\n");
11741edb306SCy Schubert 		fprintf(fp, "# include <sys/ioctl.h>\n");
11841edb306SCy Schubert 		fprintf(fp, "#endif /* FreeBSD */\n");
11941edb306SCy Schubert 		fprintf(fp, "#include <net/if.h>\n");
12041edb306SCy Schubert 		fprintf(fp, "#include <netinet/in.h>\n");
12141edb306SCy Schubert 		fprintf(fp, "#include <netinet/in_systm.h>\n");
12241edb306SCy Schubert 		fprintf(fp, "#include <netinet/ip.h>\n");
12341edb306SCy Schubert 		fprintf(fp, "#include <netinet/tcp.h>\n");
12441edb306SCy Schubert 		fprintf(fp, "#include \"netinet/ip_compat.h\"\n");
12541edb306SCy Schubert 		fprintf(fp, "#include \"netinet/ip_fil.h\"\n\n");
12641edb306SCy Schubert 		fprintf(fp, "#include \"netinet/ip_rules.h\"\n\n");
12741edb306SCy Schubert 		fprintf(fp, "#ifndef _KERNEL\n");
12841edb306SCy Schubert 		fprintf(fp, "# include <string.h>\n");
12941edb306SCy Schubert 		fprintf(fp, "#endif /* _KERNEL */\n");
13041edb306SCy Schubert 		fprintf(fp, "\n");
13141edb306SCy Schubert 		fprintf(fp, "#ifdef IPFILTER_COMPILED\n");
13241edb306SCy Schubert 		fprintf(fp, "\n");
13341edb306SCy Schubert 		fprintf(fp, "extern ipf_main_softc_t ipfmain;\n");
13441edb306SCy Schubert 		fprintf(fp, "\n");
13541edb306SCy Schubert 	}
13641edb306SCy Schubert 
13741edb306SCy Schubert 	addrule(fp, fr);
13841edb306SCy Schubert 	fr->fr_type |= FR_T_BUILTIN;
13941edb306SCy Schubert 	and = "";
14041edb306SCy Schubert 	fr->fr_ref = 1;
14141edb306SCy Schubert 	i = sizeof(*fr);
14241edb306SCy Schubert 	if (i & -(1 - sizeof(*ulp)))
14341edb306SCy Schubert 		i += sizeof(u_long);
14441edb306SCy Schubert 	for (i /= sizeof(u_long), ulp = (u_long *)fr; i > 0; i--) {
14541edb306SCy Schubert 		fprintf(fp, "%s%#lx", and, *ulp++);
14641edb306SCy Schubert 		and = ", ";
14741edb306SCy Schubert 	}
14841edb306SCy Schubert 	fprintf(fp, "\n};\n");
14941edb306SCy Schubert 	fr->fr_type &= ~FR_T_BUILTIN;
15041edb306SCy Schubert 
15141edb306SCy Schubert 	count++;
15241edb306SCy Schubert 
15341edb306SCy Schubert 	fflush(fp);
15441edb306SCy Schubert }
15541edb306SCy Schubert 
15641edb306SCy Schubert 
15741edb306SCy Schubert static frgroup_t *groups = NULL;
15841edb306SCy Schubert 
15941edb306SCy Schubert 
160a3522837SCy Schubert static void
addrule(FILE * fp,frentry_t * fr)161a3522837SCy Schubert addrule(FILE *fp, frentry_t *fr)
16241edb306SCy Schubert {
16341edb306SCy Schubert 	frentry_t *f, **fpp;
16441edb306SCy Schubert 	frgroup_t *g;
16541edb306SCy Schubert 	u_long *ulp;
16641edb306SCy Schubert 	char *ghead;
16741edb306SCy Schubert 	char *gname;
16841edb306SCy Schubert 	char *and;
16941edb306SCy Schubert 	int i;
17041edb306SCy Schubert 
17141edb306SCy Schubert 	f = (frentry_t *)malloc(sizeof(*f));
17241edb306SCy Schubert 	bcopy((char *)fr, (char *)f, sizeof(*fr));
17341edb306SCy Schubert 	if (fr->fr_ipf) {
17441edb306SCy Schubert 		f->fr_ipf = (fripf_t *)malloc(sizeof(*f->fr_ipf));
17541edb306SCy Schubert 		bcopy((char *)fr->fr_ipf, (char *)f->fr_ipf,
17641edb306SCy Schubert 		      sizeof(*fr->fr_ipf));
17741edb306SCy Schubert 	}
17841edb306SCy Schubert 
17941edb306SCy Schubert 	f->fr_next = NULL;
18041edb306SCy Schubert 	gname = FR_NAME(fr, fr_group);
18141edb306SCy Schubert 
18241edb306SCy Schubert 	for (g = groups; g != NULL; g = g->fg_next)
18341edb306SCy Schubert 		if ((strncmp(g->fg_name, gname, FR_GROUPLEN) == 0) &&
18441edb306SCy Schubert 		    (g->fg_flags == (f->fr_flags & FR_INOUT)))
18541edb306SCy Schubert 			break;
18641edb306SCy Schubert 
18741edb306SCy Schubert 	if (g == NULL) {
18841edb306SCy Schubert 		g = (frgroup_t *)calloc(1, sizeof(*g));
18941edb306SCy Schubert 		g->fg_next = groups;
19041edb306SCy Schubert 		groups = g;
19141edb306SCy Schubert 		g->fg_head = f;
19241edb306SCy Schubert 		strncpy(g->fg_name, gname, FR_GROUPLEN);
19341edb306SCy Schubert 		g->fg_ref = 0;
19441edb306SCy Schubert 		g->fg_flags = f->fr_flags & FR_INOUT;
19541edb306SCy Schubert 	}
19641edb306SCy Schubert 
19741edb306SCy Schubert 	for (fpp = &g->fg_start; *fpp != NULL; )
19841edb306SCy Schubert 		fpp = &((*fpp)->fr_next);
19941edb306SCy Schubert 	*fpp = f;
20041edb306SCy Schubert 
20141edb306SCy Schubert 	if (fr->fr_dsize > 0) {
20241edb306SCy Schubert 		fprintf(fp, "\
20341edb306SCy Schubert static u_long ipf%s_rule_data_%s_%u[] = {\n",
20441edb306SCy Schubert 			f->fr_flags & FR_INQUE ? "in" : "out",
20541edb306SCy Schubert 			g->fg_name, g->fg_ref);
20641edb306SCy Schubert 		and = "";
20741edb306SCy Schubert 		i = fr->fr_dsize;
20841edb306SCy Schubert 		ulp = fr->fr_data;
20941edb306SCy Schubert 		for (i /= sizeof(u_long); i > 0; i--) {
21041edb306SCy Schubert 			fprintf(fp, "%s%#lx", and, *ulp++);
21141edb306SCy Schubert 			and = ", ";
21241edb306SCy Schubert 		}
21341edb306SCy Schubert 		fprintf(fp, "\n};\n");
21441edb306SCy Schubert 	}
21541edb306SCy Schubert 
21641edb306SCy Schubert 	fprintf(fp, "\nstatic u_long %s_rule_%s_%d[] = {\n",
21741edb306SCy Schubert 		f->fr_flags & FR_INQUE ? "in" : "out", g->fg_name, g->fg_ref);
21841edb306SCy Schubert 
21941edb306SCy Schubert 	g->fg_ref++;
22041edb306SCy Schubert 
22141edb306SCy Schubert 	if (f->fr_grhead != -1) {
22241edb306SCy Schubert 		ghead = FR_NAME(f, fr_grhead);
22341edb306SCy Schubert 		for (g = groups; g != NULL; g = g->fg_next)
22441edb306SCy Schubert 			if ((strncmp(g->fg_name, ghead, FR_GROUPLEN) == 0) &&
22541edb306SCy Schubert 			    g->fg_flags == (f->fr_flags & FR_INOUT))
22641edb306SCy Schubert 				break;
22741edb306SCy Schubert 		if (g == NULL) {
22841edb306SCy Schubert 			g = (frgroup_t *)calloc(1, sizeof(*g));
22941edb306SCy Schubert 			g->fg_next = groups;
23041edb306SCy Schubert 			groups = g;
23141edb306SCy Schubert 			g->fg_head = f;
23241edb306SCy Schubert 			strncpy(g->fg_name, ghead, FR_GROUPLEN);
23341edb306SCy Schubert 			g->fg_ref = 0;
23441edb306SCy Schubert 			g->fg_flags = f->fr_flags & FR_INOUT;
23541edb306SCy Schubert 		}
23641edb306SCy Schubert 	}
23741edb306SCy Schubert }
23841edb306SCy Schubert 
23941edb306SCy Schubert 
240a3522837SCy Schubert int
intcmp(const void * c1,const void * c2)241a3522837SCy Schubert intcmp(const void *c1, const void *c2)
24241edb306SCy Schubert {
24341edb306SCy Schubert 	const mc_t *i1 = (const mc_t *)c1, *i2 = (const mc_t *)c2;
24441edb306SCy Schubert 
24541edb306SCy Schubert 	if (i1->n == i2->n) {
2462582ae57SCy Schubert 		return (i1->c - i2->c);
24741edb306SCy Schubert 	}
2482582ae57SCy Schubert 	return (i2->n - i1->n);
24941edb306SCy Schubert }
25041edb306SCy Schubert 
25141edb306SCy Schubert 
252a3522837SCy Schubert static void
indent(FILE * fp,int in)253a3522837SCy Schubert indent(FILE *fp, int in)
25441edb306SCy Schubert {
25541edb306SCy Schubert 	for (; in; in--)
25641edb306SCy Schubert 		fputc('\t', fp);
25741edb306SCy Schubert }
25841edb306SCy Schubert 
259a3522837SCy Schubert static void
printeq(FILE * fp,char * var,int m,int max,int v)260a3522837SCy Schubert printeq(FILE *fp, char *var, int m, int max, int v)
26141edb306SCy Schubert {
26241edb306SCy Schubert 	if (m == max)
26341edb306SCy Schubert 		fprintf(fp, "%s == %#x) {\n", var, v);
26441edb306SCy Schubert 	else
26541edb306SCy Schubert 		fprintf(fp, "(%s & %#x) == %#x) {\n", var, m, v);
26641edb306SCy Schubert }
26741edb306SCy Schubert 
26841edb306SCy Schubert /*
26941edb306SCy Schubert  * Parameters: var - IP# being compared
27041edb306SCy Schubert  *             fl - 0 for positive match, 1 for negative match
27141edb306SCy Schubert  *             m - netmask
27241edb306SCy Schubert  *             v - required address
27341edb306SCy Schubert  */
274a3522837SCy Schubert static void
printipeq(FILE * fp,char * var,int fl,int m,int v)275a3522837SCy Schubert printipeq(FILE *fp, char *var, int fl, int m, int v)
27641edb306SCy Schubert {
27741edb306SCy Schubert 	if (m == 0xffffffff)
27841edb306SCy Schubert 		fprintf(fp, "%s ", var);
27941edb306SCy Schubert 	else
28041edb306SCy Schubert 		fprintf(fp, "(%s & %#x) ", var, m);
28141edb306SCy Schubert 	fprintf(fp, "%c", fl ? '!' : '=');
28241edb306SCy Schubert 	fprintf(fp, "= %#x) {\n", v);
28341edb306SCy Schubert }
28441edb306SCy Schubert 
28541edb306SCy Schubert 
286a3522837SCy Schubert void
emit(int num,int dir,void * v,frentry_t * fr)287a3522837SCy Schubert emit(int num, int dir, void *v, frentry_t *fr)
28841edb306SCy Schubert {
28941edb306SCy Schubert 	u_int incnt, outcnt;
29041edb306SCy Schubert 	frgroup_t *g;
29141edb306SCy Schubert 	frentry_t *f;
29241edb306SCy Schubert 
29341edb306SCy Schubert 	for (g = groups; g != NULL; g = g->fg_next) {
29441edb306SCy Schubert 		if (dir == 0 || dir == -1) {
29541edb306SCy Schubert 			if ((g->fg_flags & FR_INQUE) == 0)
29641edb306SCy Schubert 				continue;
29741edb306SCy Schubert 			for (incnt = 0, f = g->fg_start; f != NULL;
29841edb306SCy Schubert 			     f = f->fr_next)
29941edb306SCy Schubert 				incnt++;
30041edb306SCy Schubert 			emitGroup(num, dir, v, fr, g->fg_name, incnt, 0);
30141edb306SCy Schubert 		}
30241edb306SCy Schubert 		if (dir == 1 || dir == -1) {
30341edb306SCy Schubert 			if ((g->fg_flags & FR_OUTQUE) == 0)
30441edb306SCy Schubert 				continue;
30541edb306SCy Schubert 			for (outcnt = 0, f = g->fg_start; f != NULL;
30641edb306SCy Schubert 			     f = f->fr_next)
30741edb306SCy Schubert 				outcnt++;
30841edb306SCy Schubert 			emitGroup(num, dir, v, fr, g->fg_name, 0, outcnt);
30941edb306SCy Schubert 		}
31041edb306SCy Schubert 	}
31141edb306SCy Schubert 
31241edb306SCy Schubert 	if (num == -1 && dir == -1) {
31341edb306SCy Schubert 		for (g = groups; g != NULL; g = g->fg_next) {
31441edb306SCy Schubert 			if ((g->fg_flags & FR_INQUE) != 0) {
31541edb306SCy Schubert 				for (incnt = 0, f = g->fg_start; f != NULL;
31641edb306SCy Schubert 				     f = f->fr_next)
31741edb306SCy Schubert 					incnt++;
31841edb306SCy Schubert 				if (incnt > 0)
31941edb306SCy Schubert 					emitheader(g, incnt, 0);
32041edb306SCy Schubert 			}
32141edb306SCy Schubert 			if ((g->fg_flags & FR_OUTQUE) != 0) {
32241edb306SCy Schubert 				for (outcnt = 0, f = g->fg_start; f != NULL;
32341edb306SCy Schubert 				     f = f->fr_next)
32441edb306SCy Schubert 					outcnt++;
32541edb306SCy Schubert 				if (outcnt > 0)
32641edb306SCy Schubert 					emitheader(g, 0, outcnt);
32741edb306SCy Schubert 			}
32841edb306SCy Schubert 		}
32941edb306SCy Schubert 		emittail();
33041edb306SCy Schubert 		fprintf(cfile, "#endif /* IPFILTER_COMPILED */\n");
33141edb306SCy Schubert 	}
33241edb306SCy Schubert 
33341edb306SCy Schubert }
33441edb306SCy Schubert 
33541edb306SCy Schubert 
336a3522837SCy Schubert static void
emitheader(frgroup_t * grp,u_int incount,u_int outcount)337a3522837SCy Schubert emitheader(frgroup_t *grp, u_int incount, u_int outcount)
33841edb306SCy Schubert {
33941edb306SCy Schubert 	static FILE *fph = NULL;
34041edb306SCy Schubert 	frgroup_t *g;
34141edb306SCy Schubert 
34241edb306SCy Schubert 	if (fph == NULL) {
34341edb306SCy Schubert 		fph = fopen("ip_rules.h", "w");
34441edb306SCy Schubert 		if (fph == NULL)
34541edb306SCy Schubert 			return;
34641edb306SCy Schubert 
34741edb306SCy Schubert 		fprintf(fph, "extern int ipfrule_add(void));\n");
34841edb306SCy Schubert 		fprintf(fph, "extern int ipfrule_remove(void));\n");
34941edb306SCy Schubert 	}
35041edb306SCy Schubert 
35141edb306SCy Schubert 	printhooks(cfile, incount, outcount, grp);
35241edb306SCy Schubert 
35341edb306SCy Schubert 	if (incount) {
35441edb306SCy Schubert 		fprintf(fph, "\n\
35541edb306SCy Schubert extern frentry_t *ipfrule_match_in_%s(fr_info_t *, u_32_t *));\n\
35641edb306SCy Schubert extern frentry_t *ipf_rules_in_%s[%d];\n",
35741edb306SCy Schubert 			grp->fg_name, grp->fg_name, incount);
35841edb306SCy Schubert 
35941edb306SCy Schubert 		for (g = groups; g != grp; g = g->fg_next)
36041edb306SCy Schubert 			if ((strncmp(g->fg_name, grp->fg_name,
36141edb306SCy Schubert 				     FR_GROUPLEN) == 0) &&
36241edb306SCy Schubert 			    g->fg_flags == grp->fg_flags)
36341edb306SCy Schubert 				break;
36441edb306SCy Schubert 		if (g == grp) {
36541edb306SCy Schubert 			fprintf(fph, "\n\
36641edb306SCy Schubert extern int ipfrule_add_in_%s(void));\n\
36741edb306SCy Schubert extern int ipfrule_remove_in_%s(void));\n", grp->fg_name, grp->fg_name);
36841edb306SCy Schubert 		}
36941edb306SCy Schubert 	}
37041edb306SCy Schubert 	if (outcount) {
37141edb306SCy Schubert 		fprintf(fph, "\n\
37241edb306SCy Schubert extern frentry_t *ipfrule_match_out_%s(fr_info_t *, u_32_t *));\n\
37341edb306SCy Schubert extern frentry_t *ipf_rules_out_%s[%d];\n",
37441edb306SCy Schubert 			grp->fg_name, grp->fg_name, outcount);
37541edb306SCy Schubert 
37641edb306SCy Schubert 		for (g = groups; g != grp; g = g->fg_next)
37741edb306SCy Schubert 			if ((strncmp(g->fg_name, grp->fg_name,
37841edb306SCy Schubert 				     FR_GROUPLEN) == 0) &&
37941edb306SCy Schubert 			    g->fg_flags == grp->fg_flags)
38041edb306SCy Schubert 				break;
38141edb306SCy Schubert 		if (g == grp) {
38241edb306SCy Schubert 			fprintf(fph, "\n\
38341edb306SCy Schubert extern int ipfrule_add_out_%s(void));\n\
38441edb306SCy Schubert extern int ipfrule_remove_out_%s(void));\n",
38541edb306SCy Schubert 				grp->fg_name, grp->fg_name);
38641edb306SCy Schubert 		}
38741edb306SCy Schubert 	}
38841edb306SCy Schubert }
38941edb306SCy Schubert 
390a3522837SCy Schubert static void
emittail(void)391a3522837SCy Schubert emittail(void)
39241edb306SCy Schubert {
39341edb306SCy Schubert 	frgroup_t *g;
39441edb306SCy Schubert 
39541edb306SCy Schubert 	fprintf(cfile, "\n\
39641edb306SCy Schubert int ipfrule_add()\n\
39741edb306SCy Schubert {\n\
39841edb306SCy Schubert 	int err;\n\
39941edb306SCy Schubert \n");
40041edb306SCy Schubert 	for (g = groups; g != NULL; g = g->fg_next)
40141edb306SCy Schubert 		fprintf(cfile, "\
40241edb306SCy Schubert 	err = ipfrule_add_%s_%s();\n\
40341edb306SCy Schubert 	if (err != 0)\n\
4042582ae57SCy Schubert 		return (err);\n",
40541edb306SCy Schubert 			(g->fg_flags & FR_INQUE) ? "in" : "out", g->fg_name);
40641edb306SCy Schubert 	fprintf(cfile, "\
4072582ae57SCy Schubert 	return (0);\n");
40841edb306SCy Schubert 	fprintf(cfile, "}\n\
40941edb306SCy Schubert \n");
41041edb306SCy Schubert 
41141edb306SCy Schubert 	fprintf(cfile, "\n\
41241edb306SCy Schubert int ipfrule_remove()\n\
41341edb306SCy Schubert {\n\
41441edb306SCy Schubert 	int err;\n\
41541edb306SCy Schubert \n");
41641edb306SCy Schubert 	for (g = groups; g != NULL; g = g->fg_next)
41741edb306SCy Schubert 		fprintf(cfile, "\
41841edb306SCy Schubert 	err = ipfrule_remove_%s_%s();\n\
41941edb306SCy Schubert 	if (err != 0)\n\
4202582ae57SCy Schubert 		return (err);\n",
42141edb306SCy Schubert 			(g->fg_flags & FR_INQUE) ? "in" : "out", g->fg_name);
42241edb306SCy Schubert 	fprintf(cfile, "\
4232582ae57SCy Schubert 	return (0);\n");
42441edb306SCy Schubert 	fprintf(cfile, "}\n");
42541edb306SCy Schubert }
42641edb306SCy Schubert 
42741edb306SCy Schubert 
428a3522837SCy Schubert static void
emitGroup(int num,int dir,void * v,frentry_t * fr,char * group,u_int incount,u_int outcount)429a3522837SCy Schubert emitGroup(int num, int dir, void *v, frentry_t *fr, char *group,
430a3522837SCy Schubert 	u_int incount, u_int outcount)
43141edb306SCy Schubert {
43241edb306SCy Schubert 	static FILE *fp = NULL;
43341edb306SCy Schubert 	static int header[2] = { 0, 0 };
43441edb306SCy Schubert 	static char egroup[FR_GROUPLEN] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
43541edb306SCy Schubert 	static int openfunc = 0;
43641edb306SCy Schubert 	static mc_t *n = NULL;
43741edb306SCy Schubert 	static int sin = 0;
43841edb306SCy Schubert 	frentry_t *f;
43941edb306SCy Schubert 	frgroup_t *g;
44041edb306SCy Schubert 	fripf_t *ipf;
44141edb306SCy Schubert 	int i, in, j;
44241edb306SCy Schubert 	mc_t *m = v;
44341edb306SCy Schubert 
44441edb306SCy Schubert 	if (fp == NULL)
44541edb306SCy Schubert 		fp = cfile;
44641edb306SCy Schubert 	if (fp == NULL)
44741edb306SCy Schubert 		return;
44841edb306SCy Schubert 	if (strncmp(egroup, group, FR_GROUPLEN)) {
44941edb306SCy Schubert 		for (sin--; sin > 0; sin--) {
45041edb306SCy Schubert 			indent(fp, sin);
45141edb306SCy Schubert 			fprintf(fp, "}\n");
45241edb306SCy Schubert 		}
45341edb306SCy Schubert 		if (openfunc == 1) {
4542582ae57SCy Schubert 			fprintf(fp, "\treturn (fr);\n}\n");
45541edb306SCy Schubert 			openfunc = 0;
45641edb306SCy Schubert 			if (n != NULL) {
45741edb306SCy Schubert 				free(n);
45841edb306SCy Schubert 				n = NULL;
45941edb306SCy Schubert 			}
46041edb306SCy Schubert 		}
46141edb306SCy Schubert 		sin = 0;
46241edb306SCy Schubert 		header[0] = 0;
46341edb306SCy Schubert 		header[1] = 0;
46441edb306SCy Schubert 		strncpy(egroup, group, FR_GROUPLEN);
46541edb306SCy Schubert 	} else if (openfunc == 1 && num < 0) {
46641edb306SCy Schubert 		if (n != NULL) {
46741edb306SCy Schubert 			free(n);
46841edb306SCy Schubert 			n = NULL;
46941edb306SCy Schubert 		}
47041edb306SCy Schubert 		for (sin--; sin > 0; sin--) {
47141edb306SCy Schubert 			indent(fp, sin);
47241edb306SCy Schubert 			fprintf(fp, "}\n");
47341edb306SCy Schubert 		}
47441edb306SCy Schubert 		if (openfunc == 1) {
4752582ae57SCy Schubert 			fprintf(fp, "\treturn (fr);\n}\n");
47641edb306SCy Schubert 			openfunc = 0;
47741edb306SCy Schubert 		}
47841edb306SCy Schubert 	}
47941edb306SCy Schubert 
48041edb306SCy Schubert 	if (dir == -1)
48141edb306SCy Schubert 		return;
48241edb306SCy Schubert 
48341edb306SCy Schubert 	for (g = groups; g != NULL; g = g->fg_next) {
48441edb306SCy Schubert 		if (dir == 0 && (g->fg_flags & FR_INQUE) == 0)
48541edb306SCy Schubert 			continue;
48641edb306SCy Schubert 		else if (dir == 1 && (g->fg_flags & FR_OUTQUE) == 0)
48741edb306SCy Schubert 			continue;
48841edb306SCy Schubert 		if (strncmp(g->fg_name, group, FR_GROUPLEN) != 0)
48941edb306SCy Schubert 			continue;
49041edb306SCy Schubert 		break;
49141edb306SCy Schubert 	}
49241edb306SCy Schubert 
49341edb306SCy Schubert 	/*
49441edb306SCy Schubert 	 * Output the array of pointers to rules for this group.
49541edb306SCy Schubert 	 */
49641edb306SCy Schubert 	if (g != NULL && num == -2 && dir == 0 && header[0] == 0 &&
49741edb306SCy Schubert 	    incount != 0) {
49841edb306SCy Schubert 		fprintf(fp, "\nfrentry_t *ipf_rules_in_%s[%d] = {",
49941edb306SCy Schubert 			group, incount);
50041edb306SCy Schubert 		for (f = g->fg_start, i = 0; f != NULL; f = f->fr_next) {
50141edb306SCy Schubert 			if ((f->fr_flags & FR_INQUE) == 0)
50241edb306SCy Schubert 				continue;
50341edb306SCy Schubert 			if ((i & 1) == 0) {
50441edb306SCy Schubert 				fprintf(fp, "\n\t");
50541edb306SCy Schubert 			}
50641edb306SCy Schubert 			fprintf(fp, "(frentry_t *)&in_rule_%s_%d",
50741edb306SCy Schubert 				FR_NAME(f, fr_group), i);
50841edb306SCy Schubert 			if (i + 1 < incount)
50941edb306SCy Schubert 				fprintf(fp, ", ");
51041edb306SCy Schubert 			i++;
51141edb306SCy Schubert 		}
51241edb306SCy Schubert 		fprintf(fp, "\n};\n");
51341edb306SCy Schubert 	}
51441edb306SCy Schubert 
51541edb306SCy Schubert 	if (g != NULL && num == -2 && dir == 1 && header[0] == 0 &&
51641edb306SCy Schubert 	    outcount != 0) {
51741edb306SCy Schubert 		fprintf(fp, "\nfrentry_t *ipf_rules_out_%s[%d] = {",
51841edb306SCy Schubert 			group, outcount);
51941edb306SCy Schubert 		for (f = g->fg_start, i = 0; f != NULL; f = f->fr_next) {
52041edb306SCy Schubert 			if ((f->fr_flags & FR_OUTQUE) == 0)
52141edb306SCy Schubert 				continue;
52241edb306SCy Schubert 			if ((i & 1) == 0) {
52341edb306SCy Schubert 				fprintf(fp, "\n\t");
52441edb306SCy Schubert 			}
52541edb306SCy Schubert 			fprintf(fp, "(frentry_t *)&out_rule_%s_%d",
52641edb306SCy Schubert 				FR_NAME(f, fr_group), i);
52741edb306SCy Schubert 			if (i + 1 < outcount)
52841edb306SCy Schubert 				fprintf(fp, ", ");
52941edb306SCy Schubert 			i++;
53041edb306SCy Schubert 		}
53141edb306SCy Schubert 		fprintf(fp, "\n};\n");
53241edb306SCy Schubert 		fp = NULL;
53341edb306SCy Schubert 	}
53441edb306SCy Schubert 
53541edb306SCy Schubert 	if (num < 0)
53641edb306SCy Schubert 		return;
53741edb306SCy Schubert 
53841edb306SCy Schubert 	in = 0;
53941edb306SCy Schubert 	ipf = fr->fr_ipf;
54041edb306SCy Schubert 
54141edb306SCy Schubert 	/*
54241edb306SCy Schubert 	 * If the function header has not been printed then print it now.
54341edb306SCy Schubert 	 */
54441edb306SCy Schubert 	if (g != NULL && header[dir] == 0) {
54541edb306SCy Schubert 		int pdst = 0, psrc = 0;
54641edb306SCy Schubert 
54741edb306SCy Schubert 		openfunc = 1;
54841edb306SCy Schubert 		fprintf(fp, "\nfrentry_t *ipfrule_match_%s_%s(fin, passp)\n",
54941edb306SCy Schubert 			(dir == 0) ? "in" : "out", group);
55041edb306SCy Schubert 		fprintf(fp, "fr_info_t *fin;\n");
55141edb306SCy Schubert 		fprintf(fp, "u_32_t *passp;\n");
55241edb306SCy Schubert 		fprintf(fp, "{\n");
55341edb306SCy Schubert 		fprintf(fp, "\tfrentry_t *fr = NULL;\n");
55441edb306SCy Schubert 
55541edb306SCy Schubert 		/*
55641edb306SCy Schubert 		 * Print out any variables that need to be declared.
55741edb306SCy Schubert 		 */
55841edb306SCy Schubert 		for (f = g->fg_start, i = 0; f != NULL; f = f->fr_next) {
55941edb306SCy Schubert 			if (incount + outcount > m[FRC_SRC].e + 1)
56041edb306SCy Schubert 				psrc = 1;
56141edb306SCy Schubert 			if (incount + outcount > m[FRC_DST].e + 1)
56241edb306SCy Schubert 				pdst = 1;
56341edb306SCy Schubert 		}
56441edb306SCy Schubert 		if (psrc == 1)
56541edb306SCy Schubert 			fprintf(fp, "\tu_32_t src = ntohl(%s);\n",
56641edb306SCy Schubert 				"fin->fin_fi.fi_saddr");
56741edb306SCy Schubert 		if (pdst == 1)
56841edb306SCy Schubert 			fprintf(fp, "\tu_32_t dst = ntohl(%s);\n",
56941edb306SCy Schubert 				"fin->fin_fi.fi_daddr");
57041edb306SCy Schubert 	}
57141edb306SCy Schubert 
57241edb306SCy Schubert 	for (i = 0; i < FRC_MAX; i++) {
57341edb306SCy Schubert 		switch(m[i].c)
57441edb306SCy Schubert 		{
57541edb306SCy Schubert 		case FRC_IFN :
57641edb306SCy Schubert 			if (fr->fr_ifnames[0] != -1)
57741edb306SCy Schubert 				m[i].s = 1;
57841edb306SCy Schubert 			break;
57941edb306SCy Schubert 		case FRC_V :
58041edb306SCy Schubert 			if (ipf != NULL && ipf->fri_mip.fi_v != 0)
58141edb306SCy Schubert 				m[i].s = 1;
58241edb306SCy Schubert 			break;
58341edb306SCy Schubert 		case FRC_FL :
58441edb306SCy Schubert 			if (ipf != NULL && ipf->fri_mip.fi_flx != 0)
58541edb306SCy Schubert 				m[i].s = 1;
58641edb306SCy Schubert 			break;
58741edb306SCy Schubert 		case FRC_P :
58841edb306SCy Schubert 			if (ipf != NULL && ipf->fri_mip.fi_p != 0)
58941edb306SCy Schubert 				m[i].s = 1;
59041edb306SCy Schubert 			break;
59141edb306SCy Schubert 		case FRC_TTL :
59241edb306SCy Schubert 			if (ipf != NULL && ipf->fri_mip.fi_ttl != 0)
59341edb306SCy Schubert 				m[i].s = 1;
59441edb306SCy Schubert 			break;
59541edb306SCy Schubert 		case FRC_TOS :
59641edb306SCy Schubert 			if (ipf != NULL && ipf->fri_mip.fi_tos != 0)
59741edb306SCy Schubert 				m[i].s = 1;
59841edb306SCy Schubert 			break;
59941edb306SCy Schubert 		case FRC_TCP :
60041edb306SCy Schubert 			if (ipf == NULL)
60141edb306SCy Schubert 				break;
60241edb306SCy Schubert 			if ((ipf->fri_ip.fi_p == IPPROTO_TCP) &&
60341edb306SCy Schubert 			    fr->fr_tcpfm != 0)
60441edb306SCy Schubert 				m[i].s = 1;
60541edb306SCy Schubert 			break;
60641edb306SCy Schubert 		case FRC_SP :
60741edb306SCy Schubert 			if (ipf == NULL)
60841edb306SCy Schubert 				break;
60941edb306SCy Schubert 			if (fr->fr_scmp == FR_INRANGE)
61041edb306SCy Schubert 				m[i].s = 1;
61141edb306SCy Schubert 			else if (fr->fr_scmp == FR_OUTRANGE)
61241edb306SCy Schubert 				m[i].s = 1;
61341edb306SCy Schubert 			else if (fr->fr_scmp != 0)
61441edb306SCy Schubert 				m[i].s = 1;
61541edb306SCy Schubert 			break;
61641edb306SCy Schubert 		case FRC_DP :
61741edb306SCy Schubert 			if (ipf == NULL)
61841edb306SCy Schubert 				break;
61941edb306SCy Schubert 			if (fr->fr_dcmp == FR_INRANGE)
62041edb306SCy Schubert 				m[i].s = 1;
62141edb306SCy Schubert 			else if (fr->fr_dcmp == FR_OUTRANGE)
62241edb306SCy Schubert 				m[i].s = 1;
62341edb306SCy Schubert 			else if (fr->fr_dcmp != 0)
62441edb306SCy Schubert 				m[i].s = 1;
62541edb306SCy Schubert 			break;
62641edb306SCy Schubert 		case FRC_SRC :
62741edb306SCy Schubert 			if (ipf == NULL)
62841edb306SCy Schubert 				break;
62941edb306SCy Schubert 			if (fr->fr_satype == FRI_LOOKUP) {
63041edb306SCy Schubert 				;
63141edb306SCy Schubert 			} else if ((fr->fr_smask != 0) ||
63241edb306SCy Schubert 				   (fr->fr_flags & FR_NOTSRCIP) != 0)
63341edb306SCy Schubert 				m[i].s = 1;
63441edb306SCy Schubert 			break;
63541edb306SCy Schubert 		case FRC_DST :
63641edb306SCy Schubert 			if (ipf == NULL)
63741edb306SCy Schubert 				break;
63841edb306SCy Schubert 			if (fr->fr_datype == FRI_LOOKUP) {
63941edb306SCy Schubert 				;
64041edb306SCy Schubert 			} else if ((fr->fr_dmask != 0) ||
64141edb306SCy Schubert 				   (fr->fr_flags & FR_NOTDSTIP) != 0)
64241edb306SCy Schubert 				m[i].s = 1;
64341edb306SCy Schubert 			break;
64441edb306SCy Schubert 		case FRC_OPT :
64541edb306SCy Schubert 			if (ipf == NULL)
64641edb306SCy Schubert 				break;
64741edb306SCy Schubert 			if (fr->fr_optmask != 0)
64841edb306SCy Schubert 				m[i].s = 1;
64941edb306SCy Schubert 			break;
65041edb306SCy Schubert 		case FRC_SEC :
65141edb306SCy Schubert 			if (ipf == NULL)
65241edb306SCy Schubert 				break;
65341edb306SCy Schubert 			if (fr->fr_secmask != 0)
65441edb306SCy Schubert 				m[i].s = 1;
65541edb306SCy Schubert 			break;
65641edb306SCy Schubert 		case FRC_ATH :
65741edb306SCy Schubert 			if (ipf == NULL)
65841edb306SCy Schubert 				break;
65941edb306SCy Schubert 			if (fr->fr_authmask != 0)
66041edb306SCy Schubert 				m[i].s = 1;
66141edb306SCy Schubert 			break;
66241edb306SCy Schubert 		case FRC_ICT :
66341edb306SCy Schubert 			if (ipf == NULL)
66441edb306SCy Schubert 				break;
66541edb306SCy Schubert 			if ((fr->fr_icmpm & 0xff00) != 0)
66641edb306SCy Schubert 				m[i].s = 1;
66741edb306SCy Schubert 			break;
66841edb306SCy Schubert 		case FRC_ICC :
66941edb306SCy Schubert 			if (ipf == NULL)
67041edb306SCy Schubert 				break;
67141edb306SCy Schubert 			if ((fr->fr_icmpm & 0xff) != 0)
67241edb306SCy Schubert 				m[i].s = 1;
67341edb306SCy Schubert 			break;
67441edb306SCy Schubert 		}
67541edb306SCy Schubert 	}
67641edb306SCy Schubert 
67741edb306SCy Schubert 	if (!header[dir]) {
67841edb306SCy Schubert 		fprintf(fp, "\n");
67941edb306SCy Schubert 		header[dir] = 1;
68041edb306SCy Schubert 		sin = 0;
68141edb306SCy Schubert 	}
68241edb306SCy Schubert 
68341edb306SCy Schubert 	qsort(m, FRC_MAX, sizeof(mc_t), intcmp);
68441edb306SCy Schubert 
68541edb306SCy Schubert 	if (n) {
68641edb306SCy Schubert 		/*
68741edb306SCy Schubert 		 * Calculate the indentation interval upto the last common
688f7cee4faSElyes Haouas 		 * comparison being made.
68941edb306SCy Schubert 		 */
69041edb306SCy Schubert 		for (i = 0, in = 1; i < FRC_MAX; i++) {
69141edb306SCy Schubert 			if (n[i].c != m[i].c)
69241edb306SCy Schubert 				break;
69341edb306SCy Schubert 			if (n[i].s != m[i].s)
69441edb306SCy Schubert 				break;
69541edb306SCy Schubert 			if (n[i].s) {
69641edb306SCy Schubert 				if (n[i].n && (n[i].n > n[i].e)) {
69741edb306SCy Schubert 					m[i].p++;
69841edb306SCy Schubert 					in += m[i].p;
69941edb306SCy Schubert 					break;
70041edb306SCy Schubert 				}
70141edb306SCy Schubert 				if (n[i].e > 0) {
70241edb306SCy Schubert 					in++;
70341edb306SCy Schubert 				} else
70441edb306SCy Schubert 					break;
70541edb306SCy Schubert 			}
70641edb306SCy Schubert 		}
70741edb306SCy Schubert 		if (sin != in) {
70841edb306SCy Schubert 			for (j = sin - 1; j >= in; j--) {
70941edb306SCy Schubert 				indent(fp, j);
71041edb306SCy Schubert 				fprintf(fp, "}\n");
71141edb306SCy Schubert 			}
71241edb306SCy Schubert 		}
71341edb306SCy Schubert 	} else {
71441edb306SCy Schubert 		in = 1;
71541edb306SCy Schubert 		i = 0;
71641edb306SCy Schubert 	}
71741edb306SCy Schubert 
71841edb306SCy Schubert 	/*
71941edb306SCy Schubert 	 * print out C code that implements a filter rule.
72041edb306SCy Schubert 	 */
72141edb306SCy Schubert 	for (; i < FRC_MAX; i++) {
72241edb306SCy Schubert 		switch(m[i].c)
72341edb306SCy Schubert 		{
72441edb306SCy Schubert 		case FRC_IFN :
72541edb306SCy Schubert 			if (m[i].s) {
72641edb306SCy Schubert 				indent(fp, in);
72741edb306SCy Schubert 				fprintf(fp, "if (fin->fin_ifp == ");
72841edb306SCy Schubert 				fprintf(fp, "ipf_rules_%s_%s[%d]->fr_ifa) {\n",
72941edb306SCy Schubert 					dir ? "out" : "in", group, num);
73041edb306SCy Schubert 				in++;
73141edb306SCy Schubert 			}
73241edb306SCy Schubert 			break;
73341edb306SCy Schubert 		case FRC_V :
73441edb306SCy Schubert 			if (m[i].s) {
73541edb306SCy Schubert 				indent(fp, in);
73641edb306SCy Schubert 				fprintf(fp, "if (fin->fin_v == %d) {\n",
73741edb306SCy Schubert 					ipf->fri_ip.fi_v);
73841edb306SCy Schubert 				in++;
73941edb306SCy Schubert 			}
74041edb306SCy Schubert 			break;
74141edb306SCy Schubert 		case FRC_FL :
74241edb306SCy Schubert 			if (m[i].s) {
74341edb306SCy Schubert 				indent(fp, in);
74441edb306SCy Schubert 				fprintf(fp, "if (");
74541edb306SCy Schubert 				printeq(fp, "fin->fin_flx",
74641edb306SCy Schubert 				        ipf->fri_mip.fi_flx, 0xf,
74741edb306SCy Schubert 					ipf->fri_ip.fi_flx);
74841edb306SCy Schubert 				in++;
74941edb306SCy Schubert 			}
75041edb306SCy Schubert 			break;
75141edb306SCy Schubert 		case FRC_P :
75241edb306SCy Schubert 			if (m[i].s) {
75341edb306SCy Schubert 				indent(fp, in);
75441edb306SCy Schubert 				fprintf(fp, "if (fin->fin_p == %d) {\n",
75541edb306SCy Schubert 					ipf->fri_ip.fi_p);
75641edb306SCy Schubert 				in++;
75741edb306SCy Schubert 			}
75841edb306SCy Schubert 			break;
75941edb306SCy Schubert 		case FRC_TTL :
76041edb306SCy Schubert 			if (m[i].s) {
76141edb306SCy Schubert 				indent(fp, in);
76241edb306SCy Schubert 				fprintf(fp, "if (");
76341edb306SCy Schubert 				printeq(fp, "fin->fin_ttl",
76441edb306SCy Schubert 					ipf->fri_mip.fi_ttl, 0xff,
76541edb306SCy Schubert 					ipf->fri_ip.fi_ttl);
76641edb306SCy Schubert 				in++;
76741edb306SCy Schubert 			}
76841edb306SCy Schubert 			break;
76941edb306SCy Schubert 		case FRC_TOS :
77041edb306SCy Schubert 			if (m[i].s) {
77141edb306SCy Schubert 				indent(fp, in);
77241edb306SCy Schubert 				fprintf(fp, "if (fin->fin_tos");
77341edb306SCy Schubert 				printeq(fp, "fin->fin_tos",
77441edb306SCy Schubert 					ipf->fri_mip.fi_tos, 0xff,
77541edb306SCy Schubert 					ipf->fri_ip.fi_tos);
77641edb306SCy Schubert 				in++;
77741edb306SCy Schubert 			}
77841edb306SCy Schubert 			break;
77941edb306SCy Schubert 		case FRC_TCP :
78041edb306SCy Schubert 			if (m[i].s) {
78141edb306SCy Schubert 				indent(fp, in);
78241edb306SCy Schubert 				fprintf(fp, "if (");
78341edb306SCy Schubert 				printeq(fp, "fin->fin_tcpf", fr->fr_tcpfm,
78441edb306SCy Schubert 					0xff, fr->fr_tcpf);
78541edb306SCy Schubert 				in++;
78641edb306SCy Schubert 			}
78741edb306SCy Schubert 			break;
78841edb306SCy Schubert 		case FRC_SP :
78941edb306SCy Schubert 			if (!m[i].s)
79041edb306SCy Schubert 				break;
79141edb306SCy Schubert 			if (fr->fr_scmp == FR_INRANGE) {
79241edb306SCy Schubert 				indent(fp, in);
79341edb306SCy Schubert 				fprintf(fp, "if ((fin->fin_data[0] > %d) && ",
79441edb306SCy Schubert 					fr->fr_sport);
79541edb306SCy Schubert 				fprintf(fp, "(fin->fin_data[0] < %d)",
79641edb306SCy Schubert 					fr->fr_stop);
79741edb306SCy Schubert 				fprintf(fp, ") {\n");
79841edb306SCy Schubert 				in++;
79941edb306SCy Schubert 			} else if (fr->fr_scmp == FR_OUTRANGE) {
80041edb306SCy Schubert 				indent(fp, in);
80141edb306SCy Schubert 				fprintf(fp, "if ((fin->fin_data[0] < %d) || ",
80241edb306SCy Schubert 					fr->fr_sport);
80341edb306SCy Schubert 				fprintf(fp, "(fin->fin_data[0] > %d)",
80441edb306SCy Schubert 					fr->fr_stop);
80541edb306SCy Schubert 				fprintf(fp, ") {\n");
80641edb306SCy Schubert 				in++;
80741edb306SCy Schubert 			} else if (fr->fr_scmp) {
80841edb306SCy Schubert 				indent(fp, in);
80941edb306SCy Schubert 				fprintf(fp, "if (fin->fin_data[0] %s %d)",
81041edb306SCy Schubert 					portcmp[fr->fr_scmp], fr->fr_sport);
81141edb306SCy Schubert 				fprintf(fp, " {\n");
81241edb306SCy Schubert 				in++;
81341edb306SCy Schubert 			}
81441edb306SCy Schubert 			break;
81541edb306SCy Schubert 		case FRC_DP :
81641edb306SCy Schubert 			if (!m[i].s)
81741edb306SCy Schubert 				break;
81841edb306SCy Schubert 			if (fr->fr_dcmp == FR_INRANGE) {
81941edb306SCy Schubert 				indent(fp, in);
82041edb306SCy Schubert 				fprintf(fp, "if ((fin->fin_data[1] > %d) && ",
82141edb306SCy Schubert 					fr->fr_dport);
82241edb306SCy Schubert 				fprintf(fp, "(fin->fin_data[1] < %d)",
82341edb306SCy Schubert 					fr->fr_dtop);
82441edb306SCy Schubert 				fprintf(fp, ") {\n");
82541edb306SCy Schubert 				in++;
82641edb306SCy Schubert 			} else if (fr->fr_dcmp == FR_OUTRANGE) {
82741edb306SCy Schubert 				indent(fp, in);
82841edb306SCy Schubert 				fprintf(fp, "if ((fin->fin_data[1] < %d) || ",
82941edb306SCy Schubert 					fr->fr_dport);
83041edb306SCy Schubert 				fprintf(fp, "(fin->fin_data[1] > %d)",
83141edb306SCy Schubert 					fr->fr_dtop);
83241edb306SCy Schubert 				fprintf(fp, ") {\n");
83341edb306SCy Schubert 				in++;
83441edb306SCy Schubert 			} else if (fr->fr_dcmp) {
83541edb306SCy Schubert 				indent(fp, in);
83641edb306SCy Schubert 				fprintf(fp, "if (fin->fin_data[1] %s %d)",
83741edb306SCy Schubert 					portcmp[fr->fr_dcmp], fr->fr_dport);
83841edb306SCy Schubert 				fprintf(fp, " {\n");
83941edb306SCy Schubert 				in++;
84041edb306SCy Schubert 			}
84141edb306SCy Schubert 			break;
84241edb306SCy Schubert 		case FRC_SRC :
84341edb306SCy Schubert 			if (!m[i].s)
84441edb306SCy Schubert 				break;
84541edb306SCy Schubert 			if (fr->fr_satype == FRI_LOOKUP) {
84641edb306SCy Schubert 				;
84741edb306SCy Schubert 			} else if ((fr->fr_smask != 0) ||
84841edb306SCy Schubert 				   (fr->fr_flags & FR_NOTSRCIP) != 0) {
84941edb306SCy Schubert 				indent(fp, in);
85041edb306SCy Schubert 				fprintf(fp, "if (");
85141edb306SCy Schubert 				printipeq(fp, "src",
85241edb306SCy Schubert 					  fr->fr_flags & FR_NOTSRCIP,
85341edb306SCy Schubert 					  fr->fr_smask, fr->fr_saddr);
85441edb306SCy Schubert 				in++;
85541edb306SCy Schubert 			}
85641edb306SCy Schubert 			break;
85741edb306SCy Schubert 		case FRC_DST :
85841edb306SCy Schubert 			if (!m[i].s)
85941edb306SCy Schubert 				break;
86041edb306SCy Schubert 			if (fr->fr_datype == FRI_LOOKUP) {
86141edb306SCy Schubert 				;
86241edb306SCy Schubert 			} else if ((fr->fr_dmask != 0) ||
86341edb306SCy Schubert 				   (fr->fr_flags & FR_NOTDSTIP) != 0) {
86441edb306SCy Schubert 				indent(fp, in);
86541edb306SCy Schubert 				fprintf(fp, "if (");
86641edb306SCy Schubert 				printipeq(fp, "dst",
86741edb306SCy Schubert 					  fr->fr_flags & FR_NOTDSTIP,
86841edb306SCy Schubert 					  fr->fr_dmask, fr->fr_daddr);
86941edb306SCy Schubert 				in++;
87041edb306SCy Schubert 			}
87141edb306SCy Schubert 			break;
87241edb306SCy Schubert 		case FRC_OPT :
87341edb306SCy Schubert 			if (m[i].s) {
87441edb306SCy Schubert 				indent(fp, in);
87541edb306SCy Schubert 				fprintf(fp, "if (");
87641edb306SCy Schubert 				printeq(fp, "fin->fin_fi.fi_optmsk",
87741edb306SCy Schubert 					fr->fr_optmask, 0xffffffff,
87841edb306SCy Schubert 				        fr->fr_optbits);
87941edb306SCy Schubert 				in++;
88041edb306SCy Schubert 			}
88141edb306SCy Schubert 			break;
88241edb306SCy Schubert 		case FRC_SEC :
88341edb306SCy Schubert 			if (m[i].s) {
88441edb306SCy Schubert 				indent(fp, in);
88541edb306SCy Schubert 				fprintf(fp, "if (");
88641edb306SCy Schubert 				printeq(fp, "fin->fin_fi.fi_secmsk",
88741edb306SCy Schubert 					fr->fr_secmask, 0xffff,
88841edb306SCy Schubert 					fr->fr_secbits);
88941edb306SCy Schubert 				in++;
89041edb306SCy Schubert 			}
89141edb306SCy Schubert 			break;
89241edb306SCy Schubert 		case FRC_ATH :
89341edb306SCy Schubert 			if (m[i].s) {
89441edb306SCy Schubert 				indent(fp, in);
89541edb306SCy Schubert 				fprintf(fp, "if (");
89641edb306SCy Schubert 				printeq(fp, "fin->fin_fi.fi_authmsk",
89741edb306SCy Schubert 					fr->fr_authmask, 0xffff,
89841edb306SCy Schubert 					fr->fr_authbits);
89941edb306SCy Schubert 				in++;
90041edb306SCy Schubert 			}
90141edb306SCy Schubert 			break;
90241edb306SCy Schubert 		case FRC_ICT :
90341edb306SCy Schubert 			if (m[i].s) {
90441edb306SCy Schubert 				indent(fp, in);
90541edb306SCy Schubert 				fprintf(fp, "if (");
90641edb306SCy Schubert 				printeq(fp, "fin->fin_data[0]",
90741edb306SCy Schubert 					fr->fr_icmpm & 0xff00, 0xffff,
90841edb306SCy Schubert 					fr->fr_icmp & 0xff00);
90941edb306SCy Schubert 				in++;
91041edb306SCy Schubert 			}
91141edb306SCy Schubert 			break;
91241edb306SCy Schubert 		case FRC_ICC :
91341edb306SCy Schubert 			if (m[i].s) {
91441edb306SCy Schubert 				indent(fp, in);
91541edb306SCy Schubert 				fprintf(fp, "if (");
91641edb306SCy Schubert 				printeq(fp, "fin->fin_data[0]",
91741edb306SCy Schubert 					fr->fr_icmpm & 0xff, 0xffff,
91841edb306SCy Schubert 					fr->fr_icmp & 0xff);
91941edb306SCy Schubert 				in++;
92041edb306SCy Schubert 			}
92141edb306SCy Schubert 			break;
92241edb306SCy Schubert 		}
92341edb306SCy Schubert 
92441edb306SCy Schubert 	}
92541edb306SCy Schubert 
92641edb306SCy Schubert 	indent(fp, in);
92741edb306SCy Schubert 	if (fr->fr_flags & FR_QUICK) {
9282582ae57SCy Schubert 		fprintf(fp, "return ((frentry_t *)&%s_rule_%s_%d);\n",
92941edb306SCy Schubert 			fr->fr_flags & FR_INQUE ? "in" : "out",
93041edb306SCy Schubert 			FR_NAME(fr, fr_group), num);
93141edb306SCy Schubert 	} else {
93241edb306SCy Schubert 		fprintf(fp, "fr = (frentry_t *)&%s_rule_%s_%d;\n",
93341edb306SCy Schubert 			fr->fr_flags & FR_INQUE ? "in" : "out",
93441edb306SCy Schubert 			FR_NAME(fr, fr_group), num);
93541edb306SCy Schubert 	}
93641edb306SCy Schubert 	if (n == NULL)
93741edb306SCy Schubert 		n = (mc_t *)malloc(sizeof(*n) * FRC_MAX);
93841edb306SCy Schubert 	bcopy((char *)m, (char *)n, sizeof(*n) * FRC_MAX);
93941edb306SCy Schubert 	sin = in;
94041edb306SCy Schubert }
94141edb306SCy Schubert 
94241edb306SCy Schubert 
943a3522837SCy Schubert void
printC(int dir)944a3522837SCy Schubert printC(int dir)
94541edb306SCy Schubert {
94641edb306SCy Schubert 	static mc_t *m = NULL;
94741edb306SCy Schubert 	frgroup_t *g;
94841edb306SCy Schubert 
94941edb306SCy Schubert 	if (m == NULL)
95041edb306SCy Schubert 		m = (mc_t *)calloc(FRC_MAX, sizeof(*m));
95141edb306SCy Schubert 
95241edb306SCy Schubert 	for (g = groups; g != NULL; g = g->fg_next) {
95341edb306SCy Schubert 		if ((dir == 0) && ((g->fg_flags & FR_INQUE) != 0))
95441edb306SCy Schubert 			printCgroup(dir, g->fg_start, m, g->fg_name);
95541edb306SCy Schubert 		if ((dir == 1) && ((g->fg_flags & FR_OUTQUE) != 0))
95641edb306SCy Schubert 			printCgroup(dir, g->fg_start, m, g->fg_name);
95741edb306SCy Schubert 	}
95841edb306SCy Schubert 
95941edb306SCy Schubert 	emit(-1, dir, m, NULL);
96041edb306SCy Schubert }
96141edb306SCy Schubert 
96241edb306SCy Schubert 
96341edb306SCy Schubert /*
96441edb306SCy Schubert  * Now print out code to implement all of the rules.
96541edb306SCy Schubert  */
966a3522837SCy Schubert static void
printCgroup(int dir,frentry_t * top,mc_t * m,char * group)967a3522837SCy Schubert printCgroup(int dir, frentry_t *top, mc_t *m, char *group)
96841edb306SCy Schubert {
96941edb306SCy Schubert 	frentry_t *fr, *fr1;
97041edb306SCy Schubert 	int i, n, rn;
97141edb306SCy Schubert 	u_int count;
97241edb306SCy Schubert 
97341edb306SCy Schubert 	for (count = 0, fr1 = top; fr1 != NULL; fr1 = fr1->fr_next) {
97441edb306SCy Schubert 		if ((dir == 0) && ((fr1->fr_flags & FR_INQUE) != 0))
97541edb306SCy Schubert 			count++;
97641edb306SCy Schubert 		else if ((dir == 1) && ((fr1->fr_flags & FR_OUTQUE) != 0))
97741edb306SCy Schubert 			count++;
97841edb306SCy Schubert 	}
97941edb306SCy Schubert 
98041edb306SCy Schubert 	if (dir == 0)
98141edb306SCy Schubert 		emitGroup(-2, dir, m, fr1, group, count, 0);
98241edb306SCy Schubert 	else if (dir == 1)
98341edb306SCy Schubert 		emitGroup(-2, dir, m, fr1, group, 0, count);
98441edb306SCy Schubert 
98541edb306SCy Schubert 	/*
98641edb306SCy Schubert 	 * Before printing each rule, check to see how many of its fields are
98741edb306SCy Schubert 	 * matched by subsequent rules.
98841edb306SCy Schubert 	 */
98941edb306SCy Schubert 	for (fr1 = top, rn = 0; fr1 != NULL; fr1 = fr1->fr_next, rn++) {
99041edb306SCy Schubert 		if (!dir && !(fr1->fr_flags & FR_INQUE))
99141edb306SCy Schubert 			continue;
99241edb306SCy Schubert 		if (dir && !(fr1->fr_flags & FR_OUTQUE))
99341edb306SCy Schubert 			continue;
99441edb306SCy Schubert 		n = 0xfffffff;
99541edb306SCy Schubert 
99641edb306SCy Schubert 		for (i = 0; i < FRC_MAX; i++)
99741edb306SCy Schubert 			m[i].e = 0;
99841edb306SCy Schubert 		qsort(m, FRC_MAX, sizeof(mc_t), intcmp);
99941edb306SCy Schubert 
100041edb306SCy Schubert 		for (i = 0; i < FRC_MAX; i++) {
100141edb306SCy Schubert 			m[i].c = i;
100241edb306SCy Schubert 			m[i].e = 0;
100341edb306SCy Schubert 			m[i].n = 0;
100441edb306SCy Schubert 			m[i].s = 0;
100541edb306SCy Schubert 		}
100641edb306SCy Schubert 
100741edb306SCy Schubert 		for (fr = fr1->fr_next; fr; fr = fr->fr_next) {
100841edb306SCy Schubert 			if (!dir && !(fr->fr_flags & FR_INQUE))
100941edb306SCy Schubert 				continue;
101041edb306SCy Schubert 			if (dir && !(fr->fr_flags & FR_OUTQUE))
101141edb306SCy Schubert 				continue;
101241edb306SCy Schubert 
101341edb306SCy Schubert 			if ((n & 0x0001) &&
101441edb306SCy Schubert 			    !strcmp(fr1->fr_names + fr1->fr_ifnames[0],
101541edb306SCy Schubert 				    fr->fr_names + fr->fr_ifnames[0])) {
101641edb306SCy Schubert 				m[FRC_IFN].e++;
101741edb306SCy Schubert 				m[FRC_IFN].n++;
101841edb306SCy Schubert 			} else
101941edb306SCy Schubert 				n &= ~0x0001;
102041edb306SCy Schubert 
102141edb306SCy Schubert 			if ((n & 0x0002) && (fr1->fr_family == fr->fr_family)) {
102241edb306SCy Schubert 				m[FRC_V].e++;
102341edb306SCy Schubert 				m[FRC_V].n++;
102441edb306SCy Schubert 			} else
102541edb306SCy Schubert 				n &= ~0x0002;
102641edb306SCy Schubert 
102741edb306SCy Schubert 			if ((n & 0x0004) &&
102841edb306SCy Schubert 			    (fr->fr_type == fr1->fr_type) &&
102941edb306SCy Schubert 			    (fr->fr_type == FR_T_IPF) &&
103041edb306SCy Schubert 			    (fr1->fr_mip.fi_flx == fr->fr_mip.fi_flx) &&
103141edb306SCy Schubert 			    (fr1->fr_ip.fi_flx == fr->fr_ip.fi_flx)) {
103241edb306SCy Schubert 				m[FRC_FL].e++;
103341edb306SCy Schubert 				m[FRC_FL].n++;
103441edb306SCy Schubert 			} else
103541edb306SCy Schubert 				n &= ~0x0004;
103641edb306SCy Schubert 
103741edb306SCy Schubert 			if ((n & 0x0008) &&
103841edb306SCy Schubert 			    (fr->fr_type == fr1->fr_type) &&
103941edb306SCy Schubert 			    (fr->fr_type == FR_T_IPF) &&
104041edb306SCy Schubert 			    (fr1->fr_proto == fr->fr_proto)) {
104141edb306SCy Schubert 				m[FRC_P].e++;
104241edb306SCy Schubert 				m[FRC_P].n++;
104341edb306SCy Schubert 			} else
104441edb306SCy Schubert 				n &= ~0x0008;
104541edb306SCy Schubert 
104641edb306SCy Schubert 			if ((n & 0x0010) &&
104741edb306SCy Schubert 			    (fr->fr_type == fr1->fr_type) &&
104841edb306SCy Schubert 			    (fr->fr_type == FR_T_IPF) &&
104941edb306SCy Schubert 			    (fr1->fr_ttl == fr->fr_ttl)) {
105041edb306SCy Schubert 				m[FRC_TTL].e++;
105141edb306SCy Schubert 				m[FRC_TTL].n++;
105241edb306SCy Schubert 			} else
105341edb306SCy Schubert 				n &= ~0x0010;
105441edb306SCy Schubert 
105541edb306SCy Schubert 			if ((n & 0x0020) &&
105641edb306SCy Schubert 			    (fr->fr_type == fr1->fr_type) &&
105741edb306SCy Schubert 			    (fr->fr_type == FR_T_IPF) &&
105841edb306SCy Schubert 			    (fr1->fr_tos == fr->fr_tos)) {
105941edb306SCy Schubert 				m[FRC_TOS].e++;
106041edb306SCy Schubert 				m[FRC_TOS].n++;
106141edb306SCy Schubert 			} else
106241edb306SCy Schubert 				n &= ~0x0020;
106341edb306SCy Schubert 
106441edb306SCy Schubert 			if ((n & 0x0040) &&
106541edb306SCy Schubert 			    (fr->fr_type == fr1->fr_type) &&
106641edb306SCy Schubert 			    (fr->fr_type == FR_T_IPF) &&
106741edb306SCy Schubert 			    ((fr1->fr_tcpfm == fr->fr_tcpfm) &&
106841edb306SCy Schubert 			    (fr1->fr_tcpf == fr->fr_tcpf))) {
106941edb306SCy Schubert 				m[FRC_TCP].e++;
107041edb306SCy Schubert 				m[FRC_TCP].n++;
107141edb306SCy Schubert 			} else
107241edb306SCy Schubert 				n &= ~0x0040;
107341edb306SCy Schubert 
107441edb306SCy Schubert 			if ((n & 0x0080) &&
107541edb306SCy Schubert 			    (fr->fr_type == fr1->fr_type) &&
107641edb306SCy Schubert 			    (fr->fr_type == FR_T_IPF) &&
107741edb306SCy Schubert 			    ((fr1->fr_scmp == fr->fr_scmp) &&
107841edb306SCy Schubert 			     (fr1->fr_stop == fr->fr_stop) &&
107941edb306SCy Schubert 			     (fr1->fr_sport == fr->fr_sport))) {
108041edb306SCy Schubert 				m[FRC_SP].e++;
108141edb306SCy Schubert 				m[FRC_SP].n++;
108241edb306SCy Schubert 			} else
108341edb306SCy Schubert 				n &= ~0x0080;
108441edb306SCy Schubert 
108541edb306SCy Schubert 			if ((n & 0x0100) &&
108641edb306SCy Schubert 			    (fr->fr_type == fr1->fr_type) &&
108741edb306SCy Schubert 			    (fr->fr_type == FR_T_IPF) &&
108841edb306SCy Schubert 			    ((fr1->fr_dcmp == fr->fr_dcmp) &&
108941edb306SCy Schubert 			     (fr1->fr_dtop == fr->fr_dtop) &&
109041edb306SCy Schubert 			     (fr1->fr_dport == fr->fr_dport))) {
109141edb306SCy Schubert 				m[FRC_DP].e++;
109241edb306SCy Schubert 				m[FRC_DP].n++;
109341edb306SCy Schubert 			} else
109441edb306SCy Schubert 				n &= ~0x0100;
109541edb306SCy Schubert 
109641edb306SCy Schubert 			if ((n & 0x0200) &&
109741edb306SCy Schubert 			    (fr->fr_type == fr1->fr_type) &&
109841edb306SCy Schubert 			    (fr->fr_type == FR_T_IPF) &&
109941edb306SCy Schubert 			    ((fr1->fr_satype == FRI_LOOKUP) &&
110041edb306SCy Schubert 			    (fr->fr_satype == FRI_LOOKUP) &&
110141edb306SCy Schubert 			    (fr1->fr_srcnum == fr->fr_srcnum))) {
110241edb306SCy Schubert 				m[FRC_SRC].e++;
110341edb306SCy Schubert 				m[FRC_SRC].n++;
110441edb306SCy Schubert 			} else if ((n & 0x0200) &&
110541edb306SCy Schubert 				   (fr->fr_type == fr1->fr_type) &&
110641edb306SCy Schubert 				   (fr->fr_type == FR_T_IPF) &&
110741edb306SCy Schubert 				   (((fr1->fr_flags & FR_NOTSRCIP) ==
110841edb306SCy Schubert 				    (fr->fr_flags & FR_NOTSRCIP)))) {
110941edb306SCy Schubert 					if ((fr1->fr_smask == fr->fr_smask) &&
111041edb306SCy Schubert 					    (fr1->fr_saddr == fr->fr_saddr))
111141edb306SCy Schubert 						m[FRC_SRC].e++;
111241edb306SCy Schubert 					else
111341edb306SCy Schubert 						n &= ~0x0200;
111441edb306SCy Schubert 					if (fr1->fr_smask &&
111541edb306SCy Schubert 					    (fr1->fr_saddr & fr1->fr_smask) ==
111641edb306SCy Schubert 					    (fr->fr_saddr & fr1->fr_smask)) {
111741edb306SCy Schubert 						m[FRC_SRC].n++;
111841edb306SCy Schubert 						n |= 0x0200;
111941edb306SCy Schubert 					}
112041edb306SCy Schubert 			} else {
112141edb306SCy Schubert 				n &= ~0x0200;
112241edb306SCy Schubert 			}
112341edb306SCy Schubert 
112441edb306SCy Schubert 			if ((n & 0x0400) &&
112541edb306SCy Schubert 			    (fr->fr_type == fr1->fr_type) &&
112641edb306SCy Schubert 			    (fr->fr_type == FR_T_IPF) &&
112741edb306SCy Schubert 			    ((fr1->fr_datype == FRI_LOOKUP) &&
112841edb306SCy Schubert 			    (fr->fr_datype == FRI_LOOKUP) &&
112941edb306SCy Schubert 			    (fr1->fr_dstnum == fr->fr_dstnum))) {
113041edb306SCy Schubert 				m[FRC_DST].e++;
113141edb306SCy Schubert 				m[FRC_DST].n++;
113241edb306SCy Schubert 			} else if ((n & 0x0400) &&
113341edb306SCy Schubert 				   (fr->fr_type == fr1->fr_type) &&
113441edb306SCy Schubert 				   (fr->fr_type == FR_T_IPF) &&
113541edb306SCy Schubert 				   (((fr1->fr_flags & FR_NOTDSTIP) ==
113641edb306SCy Schubert 				    (fr->fr_flags & FR_NOTDSTIP)))) {
113741edb306SCy Schubert 					if ((fr1->fr_dmask == fr->fr_dmask) &&
113841edb306SCy Schubert 					    (fr1->fr_daddr == fr->fr_daddr))
113941edb306SCy Schubert 						m[FRC_DST].e++;
114041edb306SCy Schubert 					else
114141edb306SCy Schubert 						n &= ~0x0400;
114241edb306SCy Schubert 					if (fr1->fr_dmask &&
114341edb306SCy Schubert 					    (fr1->fr_daddr & fr1->fr_dmask) ==
114441edb306SCy Schubert 					    (fr->fr_daddr & fr1->fr_dmask)) {
114541edb306SCy Schubert 						m[FRC_DST].n++;
114641edb306SCy Schubert 						n |= 0x0400;
114741edb306SCy Schubert 					}
114841edb306SCy Schubert 			} else {
114941edb306SCy Schubert 				n &= ~0x0400;
115041edb306SCy Schubert 			}
115141edb306SCy Schubert 
115241edb306SCy Schubert 			if ((n & 0x0800) &&
115341edb306SCy Schubert 			    (fr->fr_type == fr1->fr_type) &&
115441edb306SCy Schubert 			    (fr->fr_type == FR_T_IPF) &&
115541edb306SCy Schubert 			    (fr1->fr_optmask == fr->fr_optmask) &&
115641edb306SCy Schubert 			    (fr1->fr_optbits == fr->fr_optbits)) {
115741edb306SCy Schubert 				m[FRC_OPT].e++;
115841edb306SCy Schubert 				m[FRC_OPT].n++;
115941edb306SCy Schubert 			} else
116041edb306SCy Schubert 				n &= ~0x0800;
116141edb306SCy Schubert 
116241edb306SCy Schubert 			if ((n & 0x1000) &&
116341edb306SCy Schubert 			    (fr->fr_type == fr1->fr_type) &&
116441edb306SCy Schubert 			    (fr->fr_type == FR_T_IPF) &&
116541edb306SCy Schubert 			    (fr1->fr_secmask == fr->fr_secmask) &&
116641edb306SCy Schubert 			    (fr1->fr_secbits == fr->fr_secbits)) {
116741edb306SCy Schubert 				m[FRC_SEC].e++;
116841edb306SCy Schubert 				m[FRC_SEC].n++;
116941edb306SCy Schubert 			} else
117041edb306SCy Schubert 				n &= ~0x1000;
117141edb306SCy Schubert 
117241edb306SCy Schubert 			if ((n & 0x10000) &&
117341edb306SCy Schubert 			    (fr->fr_type == fr1->fr_type) &&
117441edb306SCy Schubert 			    (fr->fr_type == FR_T_IPF) &&
117541edb306SCy Schubert 			    (fr1->fr_authmask == fr->fr_authmask) &&
117641edb306SCy Schubert 			    (fr1->fr_authbits == fr->fr_authbits)) {
117741edb306SCy Schubert 				m[FRC_ATH].e++;
117841edb306SCy Schubert 				m[FRC_ATH].n++;
117941edb306SCy Schubert 			} else
118041edb306SCy Schubert 				n &= ~0x10000;
118141edb306SCy Schubert 
118241edb306SCy Schubert 			if ((n & 0x20000) &&
118341edb306SCy Schubert 			    (fr->fr_type == fr1->fr_type) &&
118441edb306SCy Schubert 			    (fr->fr_type == FR_T_IPF) &&
118541edb306SCy Schubert 			    ((fr1->fr_icmpm & 0xff00) ==
118641edb306SCy Schubert 			     (fr->fr_icmpm & 0xff00)) &&
118741edb306SCy Schubert 			    ((fr1->fr_icmp & 0xff00) ==
118841edb306SCy Schubert 			     (fr->fr_icmp & 0xff00))) {
118941edb306SCy Schubert 				m[FRC_ICT].e++;
119041edb306SCy Schubert 				m[FRC_ICT].n++;
119141edb306SCy Schubert 			} else
119241edb306SCy Schubert 				n &= ~0x20000;
119341edb306SCy Schubert 
119441edb306SCy Schubert 			if ((n & 0x40000) &&
119541edb306SCy Schubert 			    (fr->fr_type == fr1->fr_type) &&
119641edb306SCy Schubert 			    (fr->fr_type == FR_T_IPF) &&
119741edb306SCy Schubert 			    ((fr1->fr_icmpm & 0xff) == (fr->fr_icmpm & 0xff)) &&
119841edb306SCy Schubert 			    ((fr1->fr_icmp & 0xff) == (fr->fr_icmp & 0xff))) {
119941edb306SCy Schubert 				m[FRC_ICC].e++;
120041edb306SCy Schubert 				m[FRC_ICC].n++;
120141edb306SCy Schubert 			} else
120241edb306SCy Schubert 				n &= ~0x40000;
120341edb306SCy Schubert 		}
120441edb306SCy Schubert 		/*msort(m);*/
120541edb306SCy Schubert 
120641edb306SCy Schubert 		if (dir == 0)
120741edb306SCy Schubert 			emitGroup(rn, dir, m, fr1, group, count, 0);
120841edb306SCy Schubert 		else if (dir == 1)
120941edb306SCy Schubert 			emitGroup(rn, dir, m, fr1, group, 0, count);
121041edb306SCy Schubert 	}
121141edb306SCy Schubert }
121241edb306SCy Schubert 
1213a3522837SCy Schubert static void
printhooks(FILE * fp,int in,int out,frgroup_t * grp)1214a3522837SCy Schubert printhooks(FILE *fp, int in, int out, frgroup_t *grp)
121541edb306SCy Schubert {
121641edb306SCy Schubert 	frentry_t *fr;
121741edb306SCy Schubert 	char *group;
121841edb306SCy Schubert 	int dogrp, i;
121941edb306SCy Schubert 	char *instr;
122041edb306SCy Schubert 
122141edb306SCy Schubert 	group = grp->fg_name;
122241edb306SCy Schubert 	dogrp = 0;
122341edb306SCy Schubert 
122441edb306SCy Schubert 	if (in && out) {
122541edb306SCy Schubert 		fprintf(stderr,
122641edb306SCy Schubert 			"printhooks called with both in and out set\n");
122741edb306SCy Schubert 		exit(1);
122841edb306SCy Schubert 	}
122941edb306SCy Schubert 
123041edb306SCy Schubert 	if (in) {
123141edb306SCy Schubert 		instr = "in";
123241edb306SCy Schubert 	} else if (out) {
123341edb306SCy Schubert 		instr = "out";
123441edb306SCy Schubert 	} else {
123541edb306SCy Schubert 		instr = "???";
123641edb306SCy Schubert 	}
123741edb306SCy Schubert 	fprintf(fp, "static frentry_t ipfrule_%s_%s;\n", instr, group);
123841edb306SCy Schubert 
123941edb306SCy Schubert 	fprintf(fp, "\
124041edb306SCy Schubert \n\
124141edb306SCy Schubert int ipfrule_add_%s_%s()\n", instr, group);
124241edb306SCy Schubert 	fprintf(fp, "\
124341edb306SCy Schubert {\n\
124441edb306SCy Schubert 	int i, j, err = 0, max;\n\
124541edb306SCy Schubert 	frentry_t *fp;\n");
124641edb306SCy Schubert 
124741edb306SCy Schubert 	if (dogrp)
124841edb306SCy Schubert 		fprintf(fp, "\
124941edb306SCy Schubert 	frgroup_t *fg;\n");
125041edb306SCy Schubert 
125141edb306SCy Schubert 	fprintf(fp, "\n");
125241edb306SCy Schubert 
125341edb306SCy Schubert 	for (i = 0, fr = grp->fg_start; fr != NULL; i++, fr = fr->fr_next)
125441edb306SCy Schubert 		if (fr->fr_dsize > 0) {
125541edb306SCy Schubert 			fprintf(fp, "\
125641edb306SCy Schubert 	ipf_rules_%s_%s[%d]->fr_data = &ipf%s_rule_data_%s_%u;\n",
125741edb306SCy Schubert 				instr, grp->fg_name, i,
125841edb306SCy Schubert 				instr, grp->fg_name, i);
125941edb306SCy Schubert 		}
126041edb306SCy Schubert 	fprintf(fp, "\
126141edb306SCy Schubert 	max = sizeof(ipf_rules_%s_%s)/sizeof(frentry_t *);\n\
126241edb306SCy Schubert 	for (i = 0; i < max; i++) {\n\
126341edb306SCy Schubert 		fp = ipf_rules_%s_%s[i];\n\
126441edb306SCy Schubert 		fp->fr_next = NULL;\n", instr, group, instr, group);
126541edb306SCy Schubert 
126641edb306SCy Schubert 	fprintf(fp, "\
126741edb306SCy Schubert 		for (j = i + 1; j < max; j++)\n\
126841edb306SCy Schubert 			if (strncmp(fp->fr_names + fp->fr_group,\n\
126941edb306SCy Schubert 				    ipf_rules_%s_%s[j]->fr_names +\n\
127041edb306SCy Schubert 				    ipf_rules_%s_%s[j]->fr_group,\n\
127141edb306SCy Schubert 				    FR_GROUPLEN) == 0) {\n\
127241edb306SCy Schubert 				if (ipf_rules_%s_%s[j] != NULL)\n\
127341edb306SCy Schubert 					ipf_rules_%s_%s[j]->fr_pnext =\n\
127441edb306SCy Schubert 					    &fp->fr_next;\n\
127541edb306SCy Schubert 				fp->fr_pnext = &ipf_rules_%s_%s[j];\n\
127641edb306SCy Schubert 				fp->fr_next = ipf_rules_%s_%s[j];\n\
127741edb306SCy Schubert 				break;\n\
127841edb306SCy Schubert 			}\n", instr, group, instr, group, instr, group,
127941edb306SCy Schubert 			      instr, group, instr, group, instr, group);
128041edb306SCy Schubert 	if (dogrp)
128141edb306SCy Schubert 		fprintf(fp, "\
128241edb306SCy Schubert \n\
128341edb306SCy Schubert 		if (fp->fr_grhead != -1) {\n\
128441edb306SCy Schubert 			fg = fr_addgroup(fp->fr_names + fp->fr_grhead,\n\
128541edb306SCy Schubert 					 fp, FR_INQUE, IPL_LOGIPF, 0);\n\
128641edb306SCy Schubert 			if (fg != NULL)\n\
128741edb306SCy Schubert 				fp->fr_grp = &fg->fg_start;\n\
128841edb306SCy Schubert 		}\n");
128941edb306SCy Schubert 	fprintf(fp, "\
129041edb306SCy Schubert 	}\n\
129141edb306SCy Schubert \n\
129241edb306SCy Schubert 	fp = &ipfrule_%s_%s;\n", instr, group);
129341edb306SCy Schubert 		fprintf(fp, "\
129441edb306SCy Schubert 	bzero((char *)fp, sizeof(*fp));\n\
129541edb306SCy Schubert 	fp->fr_type = FR_T_CALLFUNC_BUILTIN;\n\
129641edb306SCy Schubert 	fp->fr_flags = FR_%sQUE|FR_NOMATCH;\n\
129741edb306SCy Schubert 	fp->fr_data = (void *)ipf_rules_%s_%s[0];\n",
129841edb306SCy Schubert 		(in != 0) ? "IN" : "OUT", instr, group);
129941edb306SCy Schubert 	fprintf(fp, "\
130041edb306SCy Schubert 	fp->fr_dsize = sizeof(ipf_rules_%s_%s[0]);\n",
130141edb306SCy Schubert 		instr, group);
130241edb306SCy Schubert 
130341edb306SCy Schubert 	fprintf(fp, "\
130441edb306SCy Schubert 	fp->fr_family = AF_INET;\n\
130541edb306SCy Schubert 	fp->fr_func = (ipfunc_t)ipfrule_match_%s_%s;\n\
130641edb306SCy Schubert 	err = frrequest(&ipfmain, IPL_LOGIPF, SIOCADDFR, (caddr_t)fp,\n\
130741edb306SCy Schubert 			ipfmain.ipf_active, 0);\n",
130841edb306SCy Schubert 			instr, group);
13092582ae57SCy Schubert 	fprintf(fp, "\treturn (err);\n}\n");
131041edb306SCy Schubert 
131141edb306SCy Schubert 	fprintf(fp, "\n\n\
131241edb306SCy Schubert int ipfrule_remove_%s_%s()\n", instr, group);
131341edb306SCy Schubert 	fprintf(fp, "\
131441edb306SCy Schubert {\n\
131541edb306SCy Schubert 	int err = 0, i;\n\
131641edb306SCy Schubert 	frentry_t *fp;\n\
131741edb306SCy Schubert \n\
131841edb306SCy Schubert 	/*\n\
131941edb306SCy Schubert 	 * Try to remove the %sbound rule.\n", instr);
132041edb306SCy Schubert 
132141edb306SCy Schubert 	fprintf(fp, "\
132241edb306SCy Schubert 	 */\n\
132341edb306SCy Schubert 	if (ipfrule_%s_%s.fr_ref > 0) {\n", instr, group);
132441edb306SCy Schubert 
132541edb306SCy Schubert 	fprintf(fp, "\
132641edb306SCy Schubert 		err = EBUSY;\n\
132741edb306SCy Schubert 	} else {\n");
132841edb306SCy Schubert 
132941edb306SCy Schubert 	fprintf(fp, "\
133041edb306SCy Schubert 		i = sizeof(ipf_rules_%s_%s)/sizeof(frentry_t *) - 1;\n\
133141edb306SCy Schubert 		for (; i >= 0; i--) {\n\
133241edb306SCy Schubert 			fp = ipf_rules_%s_%s[i];\n\
133341edb306SCy Schubert 			if (fp->fr_ref > 1) {\n\
133441edb306SCy Schubert 				err = EBUSY;\n\
133541edb306SCy Schubert 				break;\n\
133641edb306SCy Schubert 			}\n\
133741edb306SCy Schubert 		}\n\
133841edb306SCy Schubert 	}\n\
133941edb306SCy Schubert 	if (err == 0)\n\
134041edb306SCy Schubert 		err = frrequest(&ipfmain, IPL_LOGIPF, SIOCDELFR,\n\
134141edb306SCy Schubert 				(caddr_t)&ipfrule_%s_%s,\n\
134241edb306SCy Schubert 				ipfmain.ipf_active, 0);\n",
134341edb306SCy Schubert 		instr, group, instr, group, instr, group);
134441edb306SCy Schubert 	fprintf(fp, "\
134541edb306SCy Schubert 	if (err)\n\
13462582ae57SCy Schubert 		return (err);\n\
134741edb306SCy Schubert \n\n");
134841edb306SCy Schubert 
13492582ae57SCy Schubert 	fprintf(fp, "\treturn (err);\n}\n");
135041edb306SCy Schubert }
1351