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