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