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