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