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