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