4 * Copyright (C) 1993-2001 by Darren Reed.
6 * See the IPFILTER.LICENCE file for details on licencing.
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 $";
25 static char *portcmp[] = { "*", "==", "!=", "<", ">", "<=", ">=", "**", "***" };
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 *,
37 static void emittail __P((void));
38 static void printCgroup __P((int, frentry_t *, mc_t *, char *));
59 static FILE *cfile = NULL;
62 * This is called once per filter rule being loaded to emit data structures
76 if ((fr->fr_type != FR_T_IPF) && (fr->fr_type != FR_T_NONE))
78 if ((fr->fr_type == FR_T_IPF) &&
79 ((fr->fr_datype != FRI_NORMAL) || (fr->fr_satype != FRI_NORMAL)))
84 cfile = fopen("ip_rules.c", "w");
90 fprintf(fp, "* Copyright (C) 1993-2000 by Darren Reed.\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");
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");
106 "#if !defined(__SVR4) && !defined(__svr4__) && !defined(__hpux)\n");
107 fprintf(fp, "# include <sys/mbuf.h>\n");
108 fprintf(fp, "#endif\n");
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");
127 fprintf(fp, "#ifdef IPFILTER_COMPILED\n");
131 fr->fr_type |= FR_T_BUILTIN;
135 if (i & -(1 - sizeof(*ulp)))
137 for (i /= sizeof(u_long), ulp = (u_long *)fr; i > 0; i--) {
138 fprintf(fp, "%s%#lx", and, *ulp++);
141 fprintf(fp, "\n};\n");
142 fr->fr_type &= ~FR_T_BUILTIN;
150 static frgroup_t *groups = NULL;
153 static void addrule(fp, fr)
163 f = (frentry_t *)malloc(sizeof(*f));
164 bcopy((char *)fr, (char *)f, sizeof(*fr));
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));
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)))
178 g = (frgroup_t *)calloc(1, sizeof(*g));
182 bcopy(f->fr_group, g->fg_name, FR_GROUPLEN);
184 g->fg_flags = f->fr_flags & FR_INOUT;
187 for (fpp = &g->fg_start; *fpp != NULL; )
188 fpp = &((*fpp)->fr_next);
191 if (fr->fr_dsize > 0) {
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);
199 for (i /= sizeof(u_long); i > 0; i--) {
200 fprintf(fp, "%s%#lx", and, *ulp++);
203 fprintf(fp, "\n};\n");
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);
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))
218 g = (frgroup_t *)calloc(1, sizeof(*g));
222 bcopy(f->fr_grhead, g->fg_name, FR_GROUPLEN);
224 g->fg_flags = f->fr_flags & FR_INOUT;
233 const mc_t *i1 = (const mc_t *)c1, *i2 = (const mc_t *)c2;
235 if (i1->n == i2->n) {
236 return i1->c - i2->c;
238 return i2->n - i1->n;
242 static void indent(fp, in)
250 static void printeq(fp, var, m, max, v)
256 fprintf(fp, "%s == %#x) {\n", var, v);
258 fprintf(fp, "(%s & %#x) == %#x) {\n", var, m, v);
262 * Parameters: var - IP# being compared
263 * fl - 0 for positive match, 1 for negative match
265 * v - required address
267 static void printipeq(fp, var, fl, m, v)
273 fprintf(fp, "%s ", var);
275 fprintf(fp, "(%s & %#x) ", var, m);
276 fprintf(fp, "%c", fl ? '!' : '=');
277 fprintf(fp, "= %#x) {\n", v);
281 void emit(num, dir, v, fr)
290 for (g = groups; g != NULL; g = g->fg_next) {
291 if (dir == 0 || dir == -1) {
292 if ((g->fg_flags & FR_INQUE) == 0)
294 for (incnt = 0, f = g->fg_start; f != NULL;
297 emitGroup(num, dir, v, fr, g->fg_name, incnt, 0);
299 if (dir == 1 || dir == -1) {
300 if ((g->fg_flags & FR_OUTQUE) == 0)
302 for (outcnt = 0, f = g->fg_start; f != NULL;
305 emitGroup(num, dir, v, fr, g->fg_name, 0, outcnt);
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;
316 emitheader(g, incnt, 0);
318 if ((g->fg_flags & FR_OUTQUE) != 0) {
319 for (outcnt = 0, f = g->fg_start; f != NULL;
323 emitheader(g, 0, outcnt);
327 fprintf(cfile, "#endif /* IPFILTER_COMPILED */\n");
333 static void emitheader(grp, incount, outcount)
335 u_int incount, outcount;
337 static FILE *fph = NULL;
341 fph = fopen("ip_rules.h", "w");
345 fprintf(fph, "extern int ipfrule_add __P((void));\n");
346 fprintf(fph, "extern int ipfrule_remove __P((void));\n");
349 printhooks(cfile, incount, outcount, grp);
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);
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)
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);
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);
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)
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);
388 static void emittail()
397 for (g = groups; g != NULL; g = g->fg_next)
399 err = ipfrule_add_%s_%s();\n\
402 (g->fg_flags & FR_INQUE) ? "in" : "out", g->fg_name);
409 int ipfrule_remove()\n\
413 for (g = groups; g != NULL; g = g->fg_next)
415 err = ipfrule_remove_%s_%s();\n\
418 (g->fg_flags & FR_INQUE) ? "in" : "out", g->fg_name);
421 fprintf(cfile, "}\n");
425 static void emitGroup(num, dir, v, fr, group, incount, outcount)
430 u_int incount, outcount;
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;
448 if (strncmp(egroup, group, FR_GROUPLEN)) {
449 for (sin--; sin > 0; sin--) {
454 fprintf(fp, "\treturn fr;\n}\n");
464 strncpy(egroup, group, FR_GROUPLEN);
465 } else if (openfunc == 1 && num < 0) {
470 for (sin--; sin > 0; sin--) {
475 fprintf(fp, "\treturn fr;\n}\n");
483 for (g = groups; g != NULL; g = g->fg_next) {
484 if (dir == 0 && (g->fg_flags & FR_INQUE) == 0)
486 else if (dir == 1 && (g->fg_flags & FR_OUTQUE) == 0)
488 if (strncmp(g->fg_name, group, FR_GROUPLEN) != 0)
494 * Output the array of pointers to rules for this group.
496 if (num == -2 && dir == 0 && header[0] == 0 && incount != 0) {
497 fprintf(fp, "\nfrentry_t *ipf_rules_in_%s[%d] = {",
499 for (f = g->fg_start, i = 0; f != NULL; f = f->fr_next) {
500 if ((f->fr_flags & FR_INQUE) == 0)
506 "(frentry_t *)&in_rule_%s_%d",
512 fprintf(fp, "\n};\n");
515 if (num == -2 && dir == 1 && header[1] == 0 && outcount != 0) {
516 fprintf(fp, "\nfrentry_t *ipf_rules_out_%s[%d] = {",
518 for (f = g->fg_start, i = 0; f != NULL; f = f->fr_next) {
519 if ((f->fr_flags & FR_OUTQUE) == 0)
525 "(frentry_t *)&out_rule_%s_%d",
527 if (i + 1 < outcount)
531 fprintf(fp, "\n};\n");
542 * If the function header has not been printed then print it now.
544 if (header[dir] == 0) {
545 int pdst = 0, psrc = 0;
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");
553 fprintf(fp, "\tfrentry_t *fr = NULL;\n");
556 * Print out any variables that need to be declared.
558 for (f = g->fg_start, i = 0; f != NULL; f = f->fr_next) {
559 if (incount + outcount > m[FRC_SRC].e + 1)
561 if (incount + outcount > m[FRC_DST].e + 1)
565 fprintf(fp, "\tu_32_t src = ntohl(%s);\n",
566 "fin->fin_fi.fi_saddr");
568 fprintf(fp, "\tu_32_t dst = ntohl(%s);\n",
569 "fin->fin_fi.fi_daddr");
572 for (i = 0; i < FRC_MAX; i++) {
580 if (ipf != NULL && ipf->fri_mip.fi_v != 0)
584 if (ipf != NULL && ipf->fri_mip.fi_flx != 0)
588 if (ipf != NULL && ipf->fri_mip.fi_p != 0)
592 if (ipf != NULL && ipf->fri_mip.fi_ttl != 0)
596 if (ipf != NULL && ipf->fri_mip.fi_tos != 0)
602 if ((ipf->fri_ip.fi_p == IPPROTO_TCP) &&
609 if (fr->fr_scmp == FR_INRANGE)
611 else if (fr->fr_scmp == FR_OUTRANGE)
613 else if (fr->fr_scmp != 0)
619 if (fr->fr_dcmp == FR_INRANGE)
621 else if (fr->fr_dcmp == FR_OUTRANGE)
623 else if (fr->fr_dcmp != 0)
629 if (fr->fr_satype == FRI_LOOKUP) {
631 } else if ((fr->fr_smask != 0) ||
632 (fr->fr_flags & FR_NOTSRCIP) != 0)
638 if (fr->fr_datype == FRI_LOOKUP) {
640 } else if ((fr->fr_dmask != 0) ||
641 (fr->fr_flags & FR_NOTDSTIP) != 0)
647 if (fr->fr_optmask != 0)
653 if (fr->fr_secmask != 0)
659 if (fr->fr_authmask != 0)
665 if ((fr->fr_icmpm & 0xff00) != 0)
671 if ((fr->fr_icmpm & 0xff) != 0)
683 qsort(m, FRC_MAX, sizeof(mc_t), intcmp);
687 * Calculate the indentation interval upto the last common
688 * common comparison being made.
690 for (i = 0, in = 1; i < FRC_MAX; i++) {
691 if (n[i].c != m[i].c)
693 if (n[i].s != m[i].s)
696 if (n[i].n && (n[i].n > n[i].e)) {
708 for (j = sin - 1; j >= in; j--) {
719 * print out C code that implements a filter rule.
721 for (; i < FRC_MAX; i++) {
727 fprintf(fp, "if (fin->fin_ifp == ");
728 fprintf(fp, "ipf_rules_%s_%s[%d]->fr_ifa) {\n",
729 dir ? "out" : "in", group, num);
736 fprintf(fp, "if (fin->fin_v == %d) {\n",
745 printeq(fp, "fin->fin_flx",
746 ipf->fri_mip.fi_flx, 0xf,
754 fprintf(fp, "if (fin->fin_p == %d) {\n",
763 printeq(fp, "fin->fin_ttl",
764 ipf->fri_mip.fi_ttl, 0xff,
772 fprintf(fp, "if (fin->fin_tos");
773 printeq(fp, "fin->fin_tos",
774 ipf->fri_mip.fi_tos, 0xff,
783 printeq(fp, "fin->fin_tcpf", fr->fr_tcpfm,
791 if (fr->fr_scmp == FR_INRANGE) {
793 fprintf(fp, "if ((fin->fin_data[0] > %d) && ",
795 fprintf(fp, "(fin->fin_data[0] < %d)",
797 fprintf(fp, ") {\n");
799 } else if (fr->fr_scmp == FR_OUTRANGE) {
801 fprintf(fp, "if ((fin->fin_data[0] < %d) || ",
803 fprintf(fp, "(fin->fin_data[0] > %d)",
805 fprintf(fp, ") {\n");
807 } else if (fr->fr_scmp) {
809 fprintf(fp, "if (fin->fin_data[0] %s %d)",
810 portcmp[fr->fr_scmp], fr->fr_sport);
818 if (fr->fr_dcmp == FR_INRANGE) {
820 fprintf(fp, "if ((fin->fin_data[1] > %d) && ",
822 fprintf(fp, "(fin->fin_data[1] < %d)",
824 fprintf(fp, ") {\n");
826 } else if (fr->fr_dcmp == FR_OUTRANGE) {
828 fprintf(fp, "if ((fin->fin_data[1] < %d) || ",
830 fprintf(fp, "(fin->fin_data[1] > %d)",
832 fprintf(fp, ") {\n");
834 } else if (fr->fr_dcmp) {
836 fprintf(fp, "if (fin->fin_data[1] %s %d)",
837 portcmp[fr->fr_dcmp], fr->fr_dport);
845 if (fr->fr_satype == FRI_LOOKUP) {
847 } else if ((fr->fr_smask != 0) ||
848 (fr->fr_flags & FR_NOTSRCIP) != 0) {
852 fr->fr_flags & FR_NOTSRCIP,
853 fr->fr_smask, fr->fr_saddr);
860 if (fr->fr_datype == FRI_LOOKUP) {
862 } else if ((fr->fr_dmask != 0) ||
863 (fr->fr_flags & FR_NOTDSTIP) != 0) {
867 fr->fr_flags & FR_NOTDSTIP,
868 fr->fr_dmask, fr->fr_daddr);
876 printeq(fp, "fin->fin_fi.fi_optmsk",
877 fr->fr_optmask, 0xffffffff,
886 printeq(fp, "fin->fin_fi.fi_secmsk",
887 fr->fr_secmask, 0xffff,
896 printeq(fp, "fin->fin_fi.fi_authmsk",
897 fr->fr_authmask, 0xffff,
906 printeq(fp, "fin->fin_data[0]",
907 fr->fr_icmpm & 0xff00, 0xffff,
908 fr->fr_icmp & 0xff00);
916 printeq(fp, "fin->fin_data[0]",
917 fr->fr_icmpm & 0xff, 0xffff,
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",
932 fprintf(fp, "fr = (frentry_t *)&%s_rule_%s_%d;\n",
933 fr->fr_flags & FR_INQUE ? "in" : "out",
937 n = (mc_t *)malloc(sizeof(*n) * FRC_MAX);
938 bcopy((char *)m, (char *)n, sizeof(*n) * FRC_MAX);
946 static mc_t *m = NULL;
950 m = (mc_t *)calloc(1, sizeof(*m) * FRC_MAX);
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);
959 emit(-1, dir, m, NULL);
964 * Now print out code to implement all of the rules.
966 static void printCgroup(dir, top, m, group)
976 for (count = 0, fr1 = top; fr1 != NULL; fr1 = fr1->fr_next) {
977 if ((dir == 0) && ((fr1->fr_flags & FR_INQUE) != 0))
979 else if ((dir == 1) && ((fr1->fr_flags & FR_OUTQUE) != 0))
984 emitGroup(-2, dir, m, fr1, group, count, 0);
986 emitGroup(-2, dir, m, fr1, group, 0, count);
989 * Before printing each rule, check to see how many of its fields are
990 * matched by subsequent rules.
992 for (fr1 = top, rn = 0; fr1 != NULL; fr1 = fr1->fr_next, rn++) {
993 if (!dir && !(fr1->fr_flags & FR_INQUE))
995 if (dir && !(fr1->fr_flags & FR_OUTQUE))
999 for (i = 0; i < FRC_MAX; i++)
1001 qsort(m, FRC_MAX, sizeof(mc_t), intcmp);
1003 for (i = 0; i < FRC_MAX; i++) {
1010 for (fr = fr1->fr_next; fr; fr = fr->fr_next) {
1011 if (!dir && !(fr->fr_flags & FR_INQUE))
1013 if (dir && !(fr->fr_flags & FR_OUTQUE))
1017 !strcmp(fr1->fr_ifname, fr->fr_ifname)) {
1023 if ((n & 0x0002) && (fr1->fr_v == fr->fr_v)) {
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)) {
1040 (fr->fr_type == fr1->fr_type) &&
1041 (fr->fr_type == FR_T_IPF) &&
1042 (fr1->fr_proto == fr->fr_proto)) {
1049 (fr->fr_type == fr1->fr_type) &&
1050 (fr->fr_type == FR_T_IPF) &&
1051 (fr1->fr_ttl == fr->fr_ttl)) {
1058 (fr->fr_type == fr1->fr_type) &&
1059 (fr->fr_type == FR_T_IPF) &&
1060 (fr1->fr_tos == fr->fr_tos)) {
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))) {
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))) {
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))) {
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))) {
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))
1116 if (fr1->fr_smask &&
1117 (fr1->fr_saddr & fr1->fr_smask) ==
1118 (fr->fr_saddr & fr1->fr_smask)) {
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))) {
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))
1144 if (fr1->fr_dmask &&
1145 (fr1->fr_daddr & fr1->fr_dmask) ==
1146 (fr->fr_daddr & fr1->fr_dmask)) {
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)) {
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)) {
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)) {
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))) {
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))) {
1209 emitGroup(rn, dir, m, fr1, group, count, 0);
1211 emitGroup(rn, dir, m, fr1, group, 0, count);
1215 static void printhooks(fp, in, out, grp)
1226 group = grp->fg_name;
1227 dogrp = *group ? 1 : 0;
1231 "printhooks called with both in and out set\n");
1242 fprintf(fp, "static frentry_t ipfrule_%s_%s;\n", instr, group);
1246 int ipfrule_add_%s_%s()\n", instr, group);
1249 int i, j, err = 0, max;\n\
1258 for (i = 0, fr = grp->fg_start; fr != NULL; i++, fr = fr->fr_next)
1259 if (fr->fr_dsize > 0) {
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);
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);
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\
1278 }\n", instr, group, instr, group);
1282 if (fp->fr_grhead != 0) {\n\
1283 fg = fr_addgroup(fp->fr_grhead, fp, FR_INQUE,\n\
1286 fp->fr_grp = &fg->fg_start;\n\
1291 fp = &ipfrule_%s_%s;\n", instr, group);
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);
1299 fp->fr_dsize = sizeof(ipf_rules_%s_%s[0]);\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",
1307 fprintf(fp, "\treturn err;\n}\n");
1310 int ipfrule_remove_%s_%s()\n", instr, group);
1317 * Try to remove the %sbound rule.\n", instr);
1321 if (ipfrule_%s_%s.fr_ref > 0) {\n", instr, group);
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\
1338 err = frrequest(IPL_LOGIPF, SIOCDELFR,\n\
1339 (caddr_t)&ipfrule_%s_%s, fr_active, 0);\n",
1340 instr, group, instr, group, instr, group);
1346 fprintf(fp, "\treturn err;\n}\n");