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