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