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