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