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