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