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