1 /*
2 * Copyright (c) 2001 Mark Fullmer and The Ohio State University
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $Id: ftfil.c,v 1.20 2004/01/05 17:55:23 maf Exp $
27 */
28
29 #include "ftinclude.h"
30 #include "ftlib.h"
31
32 #include "radix.h"
33
34 #include <sys/time.h>
35 #include <sys/types.h>
36 #include <sys/uio.h>
37 #include <sys/socket.h>
38 #include <sys/resource.h>
39 #include <netinet/in.h>
40 #include <arpa/inet.h>
41 #include <sys/stat.h>
42 #include <ctype.h>
43 #include <syslog.h>
44 #include <dirent.h>
45 #include <limits.h>
46 #include <unistd.h>
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <time.h>
50 #include <fcntl.h>
51 #include <zlib.h>
52
53 #if !HAVE_STRSEP
54 char *strsep (char **, const char *);
55 #endif
56
57 #define PARSE_PRIMITIVE_TYPE_INIT(A)\
58 if (!(A = malloc (sizeof *A))) {\
59 fterr_warn("malloc()");\
60 return -1;\
61 }\
62 bzero(A, sizeof *A);\
63 A->init = 1;\
64 A->default_mode = FT_FIL_MODE_DENY;\
65 lp->cur_primitive->lookup = A;\
66
67 #define RADIX_TRIE_INIT\
68 if (!rn_init_called) {\
69 max_keylen = sizeof(struct radix_sockaddr_in);\
70 rn_init();\
71 rn_init_called = 1;\
72 }\
73
74 extern int max_keylen;
75 extern uint32_t mask_lookup[];
76 static int rn_init_called;
77 static struct radix_node_head *rhead;
78
79
80 enum ftfil_op { FT_FIL_OP_UNSET, FT_FIL_OP_LT, FT_FIL_OP_GT,
81 FT_FIL_OP_EQ, FT_FIL_OP_NE, FT_FIL_OP_GE,
82 FT_FIL_OP_LE };
83
84 enum ftfil_parse_state { PARSE_STATE_UNSET, PARSE_STATE_PRIMITIVE,
85 PARSE_STATE_DEFINITION };
86
87
88 enum ftfil_def_match { FT_FIL_DEFINITION_MATCH_UNSET,
89 FT_FIL_DEFINITION_MATCH_SRC_AS,
90 FT_FIL_DEFINITION_MATCH_DST_AS,
91 FT_FIL_DEFINITION_MATCH_IP_SRC_ADDR,
92 FT_FIL_DEFINITION_MATCH_IP_DST_ADDR,
93 FT_FIL_DEFINITION_MATCH_IP_EXPORTER_ADDR,
94 FT_FIL_DEFINITION_MATCH_IP_NEXT_HOP_ADDR,
95 FT_FIL_DEFINITION_MATCH_IP_SC_ADDR,
96 FT_FIL_DEFINITION_MATCH_IP_PROTOCOL,
97 FT_FIL_DEFINITION_MATCH_IP_SRC_PREFIX_LEN,
98 FT_FIL_DEFINITION_MATCH_IP_DST_PREFIX_LEN,
99 FT_FIL_DEFINITION_MATCH_IP_TOS,
100 FT_FIL_DEFINITION_MATCH_IP_MARKED_TOS,
101 FT_FIL_DEFINITION_MATCH_IP_TCP_FLAGS,
102 FT_FIL_DEFINITION_MATCH_IP_SRC_PORT,
103 FT_FIL_DEFINITION_MATCH_IP_DST_PORT,
104 FT_FIL_DEFINITION_MATCH_INPUT_IF,
105 FT_FIL_DEFINITION_MATCH_OUTPUT_IF,
106 FT_FIL_DEFINITION_MATCH_START_TIME,
107 FT_FIL_DEFINITION_MATCH_END_TIME,
108 FT_FIL_DEFINITION_MATCH_FLOWS,
109 FT_FIL_DEFINITION_MATCH_OCTETS,
110 FT_FIL_DEFINITION_MATCH_PACKETS,
111 FT_FIL_DEFINITION_MATCH_XTRA_PACKETS,
112 FT_FIL_DEFINITION_MATCH_DURATION,
113 FT_FIL_DEFINITION_MATCH_ENGINE_ID,
114 FT_FIL_DEFINITION_MATCH_ENGINE_TYPE,
115 FT_FIL_DEFINITION_MATCH_SRC_TAG,
116 FT_FIL_DEFINITION_MATCH_DST_TAG,
117 FT_FIL_DEFINITION_MATCH_PPS,
118 FT_FIL_DEFINITION_MATCH_BPS,
119 FT_FIL_DEFINITION_MATCH_RANDOM_SAMPLE };
120
121 char *op_name_lookup[] = {"Unset", "lt", "gt", "eq", "ne", "ge", "le"};
122 char *mode_name_lookup[] = {"Unset", "permit", "deny"};
123
124
125 struct line_parser {
126 enum ftfil_parse_state state;
127 enum ftfil_primitive_type type;
128 enum ftfil_mode mode;
129 struct ftfil_primitive *cur_primitive;
130 struct ftfil_def *cur_def;
131 struct ftfil_match *cur_def_match;
132 struct ftsym *sym_ip_prot;
133 struct ftsym *sym_ip_tcp_port;
134 #ifdef FT_PATH_SYM_ASN
135 struct ftsym *sym_asn;
136 #endif
137 struct ftsym *sym_tag;
138 struct ftsym *sym_cur;
139 int lineno;
140 char *buf, *word;
141 const char *fname;
142
143 };
144
145 struct ftfil_lookup_ip_address {
146 struct ftchash *ftch;
147 enum ftfil_mode default_mode; /* FT_FIL_MODE_PERMIT/DENY */
148 int init; /* initialized? */
149 };
150
151 struct ftfil_lookup_ip_mask {
152 FT_STAILQ_HEAD(filipmhead, ftfil_lookup_ip_mask_rec) list;
153 enum ftfil_mode default_mode; /* FT_FIL_MODE_PERMIT/DENY */
154 int init; /* initialized? */
155 };
156
157 struct ftfil_lookup_ip_mask_rec {
158 FT_STAILQ_ENTRY(ftfil_lookup_ip_mask_rec) chain;
159 uint32_t ip, mask;
160 int mode; /* FT_FIL_MODE_PERMIT/DENY */
161 };
162
163 struct ftfil_lookup_ip_prefix_rec {
164 struct radix_node rt_nodes[2]; /* radix tree glue */
165 struct radix_sockaddr_in addr;
166 uint8_t masklen;
167 int mode; /* FT_FIL_MODE_PERMIT/DENY */
168 };
169
170 struct ftfil_lookup_ip_prefix {
171 struct radix_node_head *rhead;
172 enum ftfil_mode default_mode; /* FT_FIL_MODE_PERMIT/DENY */
173 int init; /* initialized? */
174 };
175
176 struct ftfil_lookup_as {
177 uint8_t mode[65536];
178 enum ftfil_mode default_mode; /* FT_FIL_MODE_PERMIT/DENY */
179 int init; /* initialized? */
180 };
181
182 struct ftfil_lookup_ip_prot {
183 uint8_t mode[256];
184 enum ftfil_mode default_mode; /* FT_FIL_MODE_PERMIT/DENY */
185 int init; /* initialized? */
186 };
187
188 struct ftfil_lookup_ip_port {
189 uint8_t mode[65536];
190 enum ftfil_mode default_mode; /* FT_FIL_MODE_PERMIT/DENY */
191 int init; /* initialized? */
192 };
193
194 struct ftfil_lookup_ip_tos {
195 uint8_t mask;
196 uint8_t mode[256];
197 enum ftfil_mode default_mode; /* FT_FIL_MODE_PERMIT/DENY */
198 int init; /* initialized? */
199 };
200
201 struct ftfil_lookup_ip_tcp_flags {
202 uint8_t mask;
203 uint8_t mode[256];
204 enum ftfil_mode default_mode; /* FT_FIL_MODE_PERMIT/DENY */
205 int init; /* initialized? */
206 };
207
208 struct ftfil_lookup_if_index {
209 uint8_t mode[65536];
210 enum ftfil_mode default_mode; /* FT_FIL_MODE_PERMIT/DENY */
211 int init; /* initialized? */
212 };
213
214 struct ftfil_lookup_engine {
215 uint8_t mode[256];
216 enum ftfil_mode default_mode; /* FT_FIL_MODE_PERMIT/DENY */
217 int init; /* initialized? */
218 };
219
220 struct ftfil_lookup_ip_prefix_len {
221 uint8_t mode[33];
222 enum ftfil_mode default_mode; /* FT_FIL_MODE_PERMIT/DENY */
223 int init; /* initialized? */
224 };
225
226 struct ftfil_lookup_counter_rec {
227 FT_STAILQ_ENTRY(ftfil_lookup_counter_rec) chain;
228 uint32_t val;
229 enum ftfil_op op; /* FT_FIL_OP */
230 int mode;
231 };
232
233 struct ftfil_lookup_counter {
234 FT_STAILQ_HEAD(fillchead, ftfil_lookup_counter_rec) list;
235 enum ftfil_mode default_mode; /* FT_FIL_MODE_PERMIT/DENY */
236 int init; /* initialized? */
237 };
238
239 struct ftfil_lookup_double_rec {
240 FT_STAILQ_ENTRY(ftfil_lookup_double_rec) chain;
241 double val;
242 enum ftfil_op op; /* FT_FIL_OP */
243 int mode;
244 };
245
246 struct ftfil_lookup_double {
247 FT_STAILQ_HEAD(filldhead, ftfil_lookup_double_rec) list;
248 enum ftfil_mode default_mode; /* FT_FIL_MODE_PERMIT/DENY */
249 int init; /* initialized? */
250 };
251
252 struct ftfil_lookup_tag {
253 struct ftchash *ftch;
254 enum ftfil_mode default_mode; /* FT_FIL_MODE_PERMIT/DENY */
255 int init; /* initialized? */
256 };
257
258 struct ftfil_lookup_tag_mask_rec {
259 FT_STAILQ_ENTRY(ftfil_lookup_tag_mask_rec) chain;
260 uint32_t tag, mask;
261 int mode; /* FT_FIL_MODE_PERMIT/DENY */
262 };
263
264 struct ftfil_lookup_tag_mask {
265 FT_STAILQ_HEAD(filtmhead, ftfil_lookup_tag_mask_rec) list;
266 enum ftfil_mode default_mode; /* FT_FIL_MODE_PERMIT/DENY */
267 int init; /* initialized? */
268 };
269
270 struct ftfil_lookup_time_rec {
271 FT_STAILQ_ENTRY(ftfil_lookup_time_rec) chain;
272 int hour, min, sec;
273 enum ftfil_op op; /* FT_FIL_OP */
274 int mode;
275 };
276
277 struct ftfil_lookup_time {
278 FT_STAILQ_HEAD(filltmehead, ftfil_lookup_time_rec) list;
279 enum ftfil_mode default_mode; /* FT_FIL_MODE_PERMIT/DENY */
280 int init; /* initialized? */
281 };
282
283 struct ftfil_lookup_rate {
284 int rate;
285 enum ftfil_mode mode; /* FT_FIL_MODE_PERMIT/DENY */
286 enum ftfil_mode default_mode; /* FT_FIL_MODE_PERMIT/DENY */
287 int init; /* initialized? */
288 };
289
290 struct ftfil_match_item_cache {
291 FT_SLIST_ENTRY(ftfil_match_item_cache) chain;
292 uint32_t time; /* cache time -- only valid for flow == curflow+1 */
293 void *flow; /* address of flow evaluating -- used to invalidate cache */
294 enum ftfil_mode mode; /* result FT_FIL_MODE_* */
295 void *lookup; /* data for evaluator */
296 int (*eval)(void *lookup, void *rec, struct fts3rec_offsets *fo);
297 };
298
299 static int walk_free(struct radix_node *rn, struct walkarg *UNUSED);
300
301 static int ftfil_load_lookup(struct line_parser *lp, char *s, int size,
302 uint8_t *list, int mode);
303
304 static int parse_definition(struct line_parser *lp,
305 struct ftfil *ftfil);
306 static int parse_definition_match(struct line_parser *lp,
307 struct ftfil *ftfil);
308 static int parse_definition_or(struct line_parser *lp,
309 struct ftfil *ftfil);
310 static int parse_definition_invert(struct line_parser *lp,
311 struct ftfil *ftfil);
312
313 static int parse_primitive(struct line_parser *lp, struct ftfil *ftfil);
314 static int parse_primitive_type(struct line_parser *lp, struct ftfil *ftfil);
315 static int parse_primitive_deny(struct line_parser *lp, struct ftfil *ftfil);
316 static int parse_primitive_permit(struct line_parser *lp, struct ftfil *ftfil);
317 static int parse2_primitive_permitdeny(struct line_parser *lp,
318 struct ftfil *ftfil, int flag);
319 static int parse_primitive_default(struct line_parser *lp,
320 struct ftfil *ftfil);
321 static int parse_primitive_mask(struct line_parser *lp, struct ftfil *ftfil);
322
323 static int parse_primitive_type_asn(struct line_parser *lp,
324 struct ftfil *ftfil);
325 static int parse_primitive_type_ip_prot(struct line_parser *lp,
326 struct ftfil *ftfil);
327 static int parse_primitive_type_ip_port(struct line_parser *lp,
328 struct ftfil *ftfil);
329 static int parse_primitive_type_ip_prefix_len(struct line_parser *lp,
330 struct ftfil *ftfil);
331 static int parse_primitive_type_if_index(struct line_parser *lp,
332 struct ftfil *ftfil);
333 static int parse_primitive_type_ip_tos(struct line_parser *lp,
334 struct ftfil *ftfil);
335 static int parse_primitive_type_ip_tcp_flags(struct line_parser *lp,
336 struct ftfil *ftfil);
337 static int parse_primitive_type_engine(struct line_parser *lp,
338 struct ftfil *ftfil);
339 static int parse_primitive_type_ip_address(struct line_parser *lp,
340 struct ftfil *ftfil);
341 int parse_primitive_type_ip_mask(struct line_parser *lp,
342 struct ftfil *ftfil);
343 int parse_primitive_type_ip_prefix(struct line_parser *lp,
344 struct ftfil *ftfil);
345 static int parse_primitive_type_tag(struct line_parser *lp,
346 struct ftfil *ftfil);
347 static int parse_primitive_type_tag_mask(struct line_parser *lp,
348 struct ftfil *ftfil);
349 static int parse_primitive_type_counter(struct line_parser *lp,
350 struct ftfil *ftfil);
351 static int parse_primitive_type_time_date(struct line_parser *lp,
352 struct ftfil *ftfil);
353 static int parse_primitive_type_time(struct line_parser *lp,
354 struct ftfil *ftfil);
355 static int parse_primitive_type_double(struct line_parser *lp,
356 struct ftfil *ftfil);
357 static int parse_primitive_type_rate(struct line_parser *lp,
358 struct ftfil *ftfil);
359
360 static int eval_match_src_as(struct ftfil_lookup_as *lookup, char *rec,
361 struct fts3rec_offsets *fo);
362 static int eval_match_dst_as(struct ftfil_lookup_as *lookup, char *rec,
363 struct fts3rec_offsets *fo);
364 static int eval_match_engine_type(struct ftfil_lookup_engine *lookup,
365 char *rec, struct fts3rec_offsets *fo);
366 static int eval_match_engine_id(struct ftfil_lookup_engine *lookup,
367 char *rec, struct fts3rec_offsets *fo);
368 static int eval_match_dst_if_index(struct ftfil_lookup_if_index *lookup,
369 char *rec, struct fts3rec_offsets *fo);
370 static int eval_match_src_if_index(struct ftfil_lookup_if_index *lookup,
371 char *rec, struct fts3rec_offsets *fo);
372 static int eval_match_ip_dst_port(struct ftfil_lookup_ip_port *lookup,
373 char *rec, struct fts3rec_offsets *fo);
374 static int eval_match_ip_src_port(struct ftfil_lookup_ip_port *lookup,
375 char *rec, struct fts3rec_offsets *fo);
376 static int eval_match_ip_tcp_flags(struct ftfil_lookup_ip_tcp_flags *lookup,
377 char *rec, struct fts3rec_offsets *fo);
378 static int eval_match_ip_marked_tos(struct ftfil_lookup_ip_tos *lookup,
379 char *rec, struct fts3rec_offsets *fo);
380 static int eval_match_ip_tos(struct ftfil_lookup_ip_tos *lookup,
381 char *rec, struct fts3rec_offsets *fo);
382 static int eval_match_ip_dst_prefix_len(struct ftfil_lookup_ip_prefix_len
383 *lookup, char *rec, struct fts3rec_offsets *fo);
384 static int eval_match_ip_src_prefix_len(struct ftfil_lookup_ip_prefix_len
385 *lookup, char *rec, struct fts3rec_offsets *fo);
386 static int eval_match_ip_prot(struct ftfil_lookup_ip_prot *lookup, char *rec,
387 struct fts3rec_offsets *fo);
388 static int eval_match_flows(struct ftfil_lookup_counter *lookup, char *rec,
389 struct fts3rec_offsets *fo);
390 static int eval_match_octets(struct ftfil_lookup_counter *lookup, char *rec,
391 struct fts3rec_offsets *fo);
392 static int eval_match_packets(struct ftfil_lookup_counter *lookup, char *rec,
393 struct fts3rec_offsets *fo);
394 static int eval_match_xtra_packets(struct ftfil_lookup_counter *lookup,
395 char *rec, struct fts3rec_offsets *fo);
396 static int eval_match_duration(struct ftfil_lookup_counter *lookup, char *rec,
397 struct fts3rec_offsets *fo);
398
399 static int eval_match_start_time_date(struct ftfil_lookup_counter *lookup,
400 char *rec, struct fts3rec_offsets *fo);
401 static int eval_match_end_time_date(struct ftfil_lookup_counter *lookup,
402 char *rec, struct fts3rec_offsets *fo);
403
404 static int eval_match_start_time(struct ftfil_lookup_time *lookup,
405 char *rec, struct fts3rec_offsets *fo);
406 static int eval_match_end_time(struct ftfil_lookup_time *lookup,
407 char *rec, struct fts3rec_offsets *fo);
408
409 static int eval_match_src_tag_l(struct ftfil_lookup_tag_mask *lookup,
410 char *rec, struct fts3rec_offsets *fo);
411 static int eval_match_src_tag_h(struct ftfil_lookup_tag *lookup,
412 char *rec, struct fts3rec_offsets *fo);
413 static int eval_match_dst_tag_l(struct ftfil_lookup_tag_mask *lookup,
414 char *rec, struct fts3rec_offsets *fo);
415 static int eval_match_dst_tag_h(struct ftfil_lookup_tag *lookup,
416 char *rec, struct fts3rec_offsets *fo);
417
418 static int eval_match_ip_sc_addr_l(struct ftfil_lookup_ip_mask *lookup,
419 char *rec, struct fts3rec_offsets *fo);
420 static int eval_match_ip_sc_addr_h(struct ftfil_lookup_ip_address *lookup,
421 char *rec, struct fts3rec_offsets *fo);
422 static int eval_match_ip_sc_addr_r(struct ftfil_lookup_ip_prefix *lookup,
423 char *rec, struct fts3rec_offsets *fo);
424
425 static int eval_match_ip_nexthop_addr_l(struct ftfil_lookup_ip_mask *lookup,
426 char *rec, struct fts3rec_offsets *fo);
427 static int eval_match_ip_nexthop_addr_h(struct ftfil_lookup_ip_address *lookup,
428 char *rec, struct fts3rec_offsets *fo);
429 static int eval_match_ip_nexthop_addr_r(struct ftfil_lookup_ip_prefix *lookup,
430 char *rec, struct fts3rec_offsets *fo);
431
432 static int eval_match_ip_src_addr_l(struct ftfil_lookup_ip_mask *lookup,
433 char *rec, struct fts3rec_offsets *fo);
434 static int eval_match_ip_src_addr_h(struct ftfil_lookup_ip_address *lookup,
435 char *rec, struct fts3rec_offsets *fo);
436 static int eval_match_ip_src_addr_r(struct ftfil_lookup_ip_prefix *lookup,
437 char *rec, struct fts3rec_offsets *fo);
438
439 static int eval_match_ip_dst_addr_l(struct ftfil_lookup_ip_mask *lookup,
440 char *rec, struct fts3rec_offsets *fo);
441 static int eval_match_ip_dst_addr_h(struct ftfil_lookup_ip_address *lookup,
442 char *rec, struct fts3rec_offsets *fo);
443 static int eval_match_ip_dst_addr_r(struct ftfil_lookup_ip_prefix *lookup,
444 char *rec, struct fts3rec_offsets *fo);
445
446 static int eval_match_ip_exporter_addr_l(struct ftfil_lookup_ip_mask *lookup,
447 char *rec, struct fts3rec_offsets *fo);
448 static int eval_match_ip_exporter_addr_h(struct ftfil_lookup_ip_address *lookup,
449 char *rec, struct fts3rec_offsets *fo);
450 static int eval_match_ip_exporter_addr_r(struct ftfil_lookup_ip_prefix *lookup,
451 char *rec, struct fts3rec_offsets *fo);
452
453 static int eval_match_pps(struct ftfil_lookup_double *lookup,
454 char *rec, struct fts3rec_offsets *fo);
455 static int eval_match_bps(struct ftfil_lookup_double *lookup,
456 char *rec, struct fts3rec_offsets *fo);
457
458 static int eval_match_random_sample(struct ftfil_lookup_rate *lookup,
459 char *rec, struct fts3rec_offsets *fo);
460
461 static int resolve_primitives(struct ftfil *ftfil);
462
463 #define NEXT_WORD(A,B)\
464 for (;;) {\
465 B = strsep(A, " \t");\
466 if ((B && *B != 0) || (!B))\
467 break;\
468 }\
469
470 struct jump {
471 char *name;
472 enum ftfil_parse_state state;
473 int (*func)(struct line_parser *lp, struct ftfil *ftfil);
474 };
475
476 static struct jump pjump[] = {
477 {"filter-primitive", 0, parse_primitive},
478 {"type", PARSE_STATE_PRIMITIVE, parse_primitive_type},
479 {"permit", PARSE_STATE_PRIMITIVE, parse_primitive_permit},
480 {"deny", PARSE_STATE_PRIMITIVE, parse_primitive_deny},
481 {"default", PARSE_STATE_PRIMITIVE, parse_primitive_default},
482 {"mask", PARSE_STATE_PRIMITIVE, parse_primitive_mask},
483 {"filter-definition", 0, parse_definition},
484 {"match", PARSE_STATE_DEFINITION, parse_definition_match},
485 {"or", PARSE_STATE_DEFINITION, parse_definition_or},
486 {"invert", PARSE_STATE_DEFINITION, parse_definition_invert},
487 {0, 0, 0},
488 };
489 /*
490 * data structures:
491 *
492 * Each primitive is stored in a linked list of struct ftfil_primitive. The
493 * head is ftfil.primitives. Each primitive has a lookup entry which
494 * points to a struct ftfil_lookup_* based on the enum ftfil_primitive_type
495 * stored as type. Some lookup entries allocate further storage (ie
496 * a hash, radix tree, or linked list for the linear lookups).
497 *
498 * Each definition is stored in a linked list of struct ftfil_def.
499 * The head is ftfil.defs. Each definition has a list of
500 * ftfil_match matches. The matches have a list of ftfil_match_items.
501 * For a match to be satisfied each each item in the match must evaluate
502 * true (AND). For a definition to be satisfied (permitted) one of the
503 * entries in the match list must be satisfied (OR).
504 *
505 * Each primitive (enum ftfil_primitive_type) has an associated
506 * parse_primitive_type_xxx().
507 *
508 * Each match type (enum ftfil_def_match) has an associated
509 * eval_match_xxx().
510 *
511 * ftfil_eval() walks the matches and the match items for the definition
512 * passed to it looking for a match. If every match item in a match
513 * evaluated to permit (enum ftfil_mode) a permit is returned, else
514 * a deny.
515 *
516 * The current evaluator code does not cache results. For example
517 *
518 * match src-ip-addr test1
519 * match ip-protocol test2
520 * or
521 * match src-ip-addr test1
522 * match ip-port test3
523 *
524 * If the first two matches fail the result from "match src-ip-addr test1"
525 * will need to be calculated a second time. In practice this doesn't
526 * seem to be a problem -- the performance impact is minimal for real
527 * world definitions. Adding a cache would most likely reduce performance
528 * for most cases due to overhead of the cache test/update code.
529 *
530 * Also note that in the above example if the first two matches pass
531 * the the next two will not be evaluated at all - short circuit.
532 */
533
534 /*
535 *************************************************************************
536 eval_*
537 *************************************************************************
538 */
539
540 /*
541 * function: eval_match_src_as
542 *
543 * Evalute src_as
544 *
545 * returns: FT_FIL_MODE_PERMIT
546 * FT_FIL_MODE_DENY
547 */
eval_match_src_as(struct ftfil_lookup_as * lookup,char * rec,struct fts3rec_offsets * fo)548 static int eval_match_src_as(struct ftfil_lookup_as *lookup, char *rec,
549 struct fts3rec_offsets *fo)
550 {
551 uint16_t *src_as;
552 int val;
553
554 src_as = ((uint16_t*)(rec+fo->src_as));
555
556 val = lookup->mode[*src_as];
557
558 if (val == FT_FIL_MODE_PERMIT)
559 return FT_FIL_MODE_PERMIT;
560 else if (val == FT_FIL_MODE_DENY)
561 return FT_FIL_MODE_DENY;
562 else
563 return lookup->default_mode;
564
565 } /* eval_match_src_as */
566
567 /*
568 * function: eval_match_dst_as
569 *
570 * Evalute dst_as
571 *
572 * returns: FT_FIL_MODE_PERMIT
573 * FT_FIL_MODE_DENY
574 */
eval_match_dst_as(struct ftfil_lookup_as * lookup,char * rec,struct fts3rec_offsets * fo)575 static int eval_match_dst_as(struct ftfil_lookup_as *lookup, char *rec,
576 struct fts3rec_offsets *fo)
577 {
578 uint16_t *dst_as;
579 int val;
580
581 dst_as = ((uint16_t*)(rec+fo->dst_as));
582
583 val = lookup->mode[*dst_as];
584
585 if (val == FT_FIL_MODE_PERMIT)
586 return FT_FIL_MODE_PERMIT;
587 else if (val == FT_FIL_MODE_DENY)
588 return FT_FIL_MODE_DENY;
589 else
590 return lookup->default_mode;
591
592 } /* eval_match_dst_as */
593
594
595 /*
596 * function: eval_match_ip_prot
597 *
598 * Evalute ip_prot
599 *
600 * returns: FT_FIL_MODE_PERMIT
601 * FT_FIL_MODE_DENY
602 */
eval_match_ip_prot(struct ftfil_lookup_ip_prot * lookup,char * rec,struct fts3rec_offsets * fo)603 static int eval_match_ip_prot(struct ftfil_lookup_ip_prot *lookup, char *rec,
604 struct fts3rec_offsets *fo)
605 {
606 uint8_t *ip_prot;
607 int val;
608
609 ip_prot = ((uint8_t*)(rec+fo->prot));
610
611 val = lookup->mode[*ip_prot];
612
613 if (val == FT_FIL_MODE_PERMIT)
614 return FT_FIL_MODE_PERMIT;
615 else if (val == FT_FIL_MODE_DENY)
616 return FT_FIL_MODE_DENY;
617 else
618 return lookup->default_mode;
619
620 } /* eval_match_ip_prot */
621
622
623 /*
624 * function: eval_match_ip_src_prefix_len
625 *
626 * Evalute ip_src_prefix_len
627 *
628 * returns: FT_FIL_MODE_PERMIT
629 * FT_FIL_MODE_DENY
630 */
eval_match_ip_src_prefix_len(struct ftfil_lookup_ip_prefix_len * lookup,char * rec,struct fts3rec_offsets * fo)631 static int eval_match_ip_src_prefix_len(struct ftfil_lookup_ip_prefix_len *lookup,
632 char *rec, struct fts3rec_offsets *fo)
633 {
634 uint8_t *src_mask;
635 int val;
636
637 src_mask = ((uint8_t*)(rec+fo->src_mask));
638
639 val = lookup->mode[*src_mask];
640
641 if (val == FT_FIL_MODE_PERMIT)
642 return FT_FIL_MODE_PERMIT;
643 else if (val == FT_FIL_MODE_DENY)
644 return FT_FIL_MODE_DENY;
645 else
646 return lookup->default_mode;
647
648 } /* eval_match_ip_src_prefix_len */
649
650
651 /*
652 * function: eval_match_ip_dst_prefix_len
653 *
654 * Evalute ip_dst_prefix_len
655 *
656 * returns: FT_FIL_MODE_PERMIT
657 * FT_FIL_MODE_DENY
658 */
eval_match_ip_dst_prefix_len(struct ftfil_lookup_ip_prefix_len * lookup,char * rec,struct fts3rec_offsets * fo)659 static int eval_match_ip_dst_prefix_len(struct ftfil_lookup_ip_prefix_len *lookup,
660 char *rec, struct fts3rec_offsets *fo)
661 {
662 uint8_t *dst_mask;
663 int val;
664
665 dst_mask = ((uint8_t*)(rec+fo->dst_mask));
666
667 val = lookup->mode[*dst_mask];
668
669 if (val == FT_FIL_MODE_PERMIT)
670 return FT_FIL_MODE_PERMIT;
671 else if (val == FT_FIL_MODE_DENY)
672 return FT_FIL_MODE_DENY;
673 else
674 return lookup->default_mode;
675
676 } /* eval_match_ip_dst_prefix_len */
677
678
679 /*
680 * function: eval_match_ip_tos
681 *
682 * Evalute ip_tos
683 *
684 * returns: FT_FIL_MODE_PERMIT
685 * FT_FIL_MODE_DENY
686 */
eval_match_ip_tos(struct ftfil_lookup_ip_tos * lookup,char * rec,struct fts3rec_offsets * fo)687 static int eval_match_ip_tos(struct ftfil_lookup_ip_tos *lookup,
688 char *rec, struct fts3rec_offsets *fo)
689 {
690 uint8_t tos;
691 int val;
692
693 tos = *((uint8_t*)(rec+fo->tos));
694 tos &= lookup->mask;
695
696 val = lookup->mode[tos];
697
698 if (val == FT_FIL_MODE_PERMIT)
699 return FT_FIL_MODE_PERMIT;
700 else if (val == FT_FIL_MODE_DENY)
701 return FT_FIL_MODE_DENY;
702 else
703 return lookup->default_mode;
704
705 } /* eval_match_ip_tos */
706
707 /*
708 * function: eval_match_marked_ip_tos
709 *
710 * Evalute marked_ip_tos
711 *
712 * returns: FT_FIL_MODE_PERMIT
713 * FT_FIL_MODE_DENY
714 */
eval_match_ip_marked_tos(struct ftfil_lookup_ip_tos * lookup,char * rec,struct fts3rec_offsets * fo)715 static int eval_match_ip_marked_tos(struct ftfil_lookup_ip_tos *lookup,
716 char *rec, struct fts3rec_offsets *fo)
717 {
718 uint8_t marked_tos;
719 int val;
720
721 marked_tos = *((uint8_t*)(rec+fo->marked_tos));
722 marked_tos &= lookup->mask;
723
724 val = lookup->mode[marked_tos];
725
726 if (val == FT_FIL_MODE_PERMIT)
727 return FT_FIL_MODE_PERMIT;
728 else if (val == FT_FIL_MODE_DENY)
729 return FT_FIL_MODE_DENY;
730 else
731 return lookup->default_mode;
732
733 } /* eval_match_ip_marked_tos */
734
735
736 /*
737 * function: eval_match_ip_tcp_flags
738 *
739 * Evalute ip_tcp_flags
740 *
741 * returns: FT_FIL_MODE_PERMIT
742 * FT_FIL_MODE_DENY
743 */
eval_match_ip_tcp_flags(struct ftfil_lookup_ip_tcp_flags * lookup,char * rec,struct fts3rec_offsets * fo)744 static int eval_match_ip_tcp_flags(struct ftfil_lookup_ip_tcp_flags *lookup,
745 char *rec, struct fts3rec_offsets *fo)
746 {
747 uint8_t tcp_flags;
748 int val;
749
750 tcp_flags = *((uint8_t*)(rec+fo->tcp_flags));
751 tcp_flags &= lookup->mask;
752
753 val = lookup->mode[tcp_flags];
754
755 if (val == FT_FIL_MODE_PERMIT)
756 return FT_FIL_MODE_PERMIT;
757 else if (val == FT_FIL_MODE_DENY)
758 return FT_FIL_MODE_DENY;
759 else
760 return lookup->default_mode;
761
762 } /* eval_match_ip_tcp_flags */
763
764
765 /*
766 * function: eval_match_ip_src_port
767 *
768 * Evalute ip_src_port
769 *
770 * returns: FT_FIL_MODE_PERMIT
771 * FT_FIL_MODE_DENY
772 */
eval_match_ip_src_port(struct ftfil_lookup_ip_port * lookup,char * rec,struct fts3rec_offsets * fo)773 static int eval_match_ip_src_port(struct ftfil_lookup_ip_port *lookup,
774 char *rec, struct fts3rec_offsets *fo)
775 {
776 uint16_t *src_port;
777 int val;
778
779 src_port = ((uint16_t*)(rec+fo->srcport));
780
781 val = lookup->mode[*src_port];
782
783 if (val == FT_FIL_MODE_PERMIT)
784 return FT_FIL_MODE_PERMIT;
785 else if (val == FT_FIL_MODE_DENY)
786 return FT_FIL_MODE_DENY;
787 else
788 return lookup->default_mode;
789
790 } /* eval_match_ip_src_port */
791
792 /*
793 * function: eval_match_ip_dst_port
794 *
795 * Evalute ip_dst_port
796 *
797 * returns: FT_FIL_MODE_PERMIT
798 * FT_FIL_MODE_DENY
799 */
eval_match_ip_dst_port(struct ftfil_lookup_ip_port * lookup,char * rec,struct fts3rec_offsets * fo)800 static int eval_match_ip_dst_port(struct ftfil_lookup_ip_port *lookup,
801 char *rec, struct fts3rec_offsets *fo)
802 {
803 uint16_t *dst_port;
804 int val;
805
806 dst_port = ((uint16_t*)(rec+fo->dstport));
807
808 val = lookup->mode[*dst_port];
809
810 if (val == FT_FIL_MODE_PERMIT)
811 return FT_FIL_MODE_PERMIT;
812 else if (val == FT_FIL_MODE_DENY)
813 return FT_FIL_MODE_DENY;
814 else
815 return lookup->default_mode;
816
817 } /* eval_match_ip_dst_port */
818
819
820 /*
821 * function: eval_match_src_if_index
822 *
823 * Evalute src_if_index
824 *
825 * returns: FT_FIL_MODE_PERMIT
826 * FT_FIL_MODE_DENY
827 */
eval_match_src_if_index(struct ftfil_lookup_if_index * lookup,char * rec,struct fts3rec_offsets * fo)828 static int eval_match_src_if_index(struct ftfil_lookup_if_index *lookup,
829 char *rec, struct fts3rec_offsets *fo)
830 {
831 uint16_t *src_if_index;
832 int val;
833
834 src_if_index = ((uint16_t*)(rec+fo->input));
835
836 val = lookup->mode[*src_if_index];
837
838 if (val == FT_FIL_MODE_PERMIT)
839 return FT_FIL_MODE_PERMIT;
840 else if (val == FT_FIL_MODE_DENY)
841 return FT_FIL_MODE_DENY;
842 else
843 return lookup->default_mode;
844
845 } /* eval_match_src_if_index */
846
847 /*
848 * function: eval_match_dst_if_index
849 *
850 * Evalute dst_if_index
851 *
852 * returns: FT_FIL_MODE_PERMIT
853 * FT_FIL_MODE_DENY
854 */
eval_match_dst_if_index(struct ftfil_lookup_if_index * lookup,char * rec,struct fts3rec_offsets * fo)855 static int eval_match_dst_if_index(struct ftfil_lookup_if_index *lookup,
856 char *rec, struct fts3rec_offsets *fo)
857 {
858 uint16_t *dst_if_index;
859 int val;
860
861 dst_if_index = ((uint16_t*)(rec+fo->output));
862
863 val = lookup->mode[*dst_if_index];
864
865 if (val == FT_FIL_MODE_PERMIT)
866 return FT_FIL_MODE_PERMIT;
867 else if (val == FT_FIL_MODE_DENY)
868 return FT_FIL_MODE_DENY;
869 else
870 return lookup->default_mode;
871
872 } /* eval_match_dst_if_index */
873
874
875 /*
876 * function: eval_match_engine_id
877 *
878 * Evalute engine_id
879 *
880 * returns: FT_FIL_MODE_PERMIT
881 * FT_FIL_MODE_DENY
882 */
eval_match_engine_id(struct ftfil_lookup_engine * lookup,char * rec,struct fts3rec_offsets * fo)883 static int eval_match_engine_id(struct ftfil_lookup_engine *lookup,
884 char *rec, struct fts3rec_offsets *fo)
885 {
886 uint8_t *engine_id;
887 int val;
888
889 engine_id = ((uint8_t*)(rec+fo->engine_id));
890
891 val = lookup->mode[*engine_id];
892
893 if (val == FT_FIL_MODE_PERMIT)
894 return FT_FIL_MODE_PERMIT;
895 else if (val == FT_FIL_MODE_DENY)
896 return FT_FIL_MODE_DENY;
897 else
898 return lookup->default_mode;
899
900 } /* eval_match_engine_id */
901
902
903 /*
904 * function: eval_match_engine_type
905 *
906 * Evalute engine_type
907 *
908 * returns: FT_FIL_MODE_PERMIT
909 * FT_FIL_MODE_DENY
910 */
eval_match_engine_type(struct ftfil_lookup_engine * lookup,char * rec,struct fts3rec_offsets * fo)911 static int eval_match_engine_type(struct ftfil_lookup_engine *lookup,
912 char *rec, struct fts3rec_offsets *fo)
913 {
914 uint8_t *engine_type;
915 int val;
916
917 engine_type = ((uint8_t*)(rec+fo->engine_type));
918
919 val = lookup->mode[*engine_type];
920
921 if (val == FT_FIL_MODE_PERMIT)
922 return FT_FIL_MODE_PERMIT;
923 else if (val == FT_FIL_MODE_DENY)
924 return FT_FIL_MODE_DENY;
925 else
926 return lookup->default_mode;
927
928 } /* eval_match_engine_type */
929
930 /*
931 * function: eval_match_flows
932 *
933 * Evalute flows
934 *
935 * returns: FT_FIL_MODE_PERMIT
936 * FT_FIL_MODE_DENY
937 */
eval_match_flows(struct ftfil_lookup_counter * lookup,char * rec,struct fts3rec_offsets * fo)938 static int eval_match_flows(struct ftfil_lookup_counter *lookup, char *rec,
939 struct fts3rec_offsets *fo)
940 {
941 struct ftfil_lookup_counter_rec *ftflcr;
942 uint32_t *flows;
943 int t, match;
944
945 flows = ((uint32_t*)(rec+fo->dFlows));
946
947 match = 0;
948
949 FT_STAILQ_FOREACH(ftflcr, &lookup->list, chain) {
950
951 switch (ftflcr->op) {
952
953 case FT_FIL_OP_LT:
954 t = (*flows < ftflcr->val);
955 break;
956 case FT_FIL_OP_GT:
957 t = (*flows > ftflcr->val);
958 break;
959 case FT_FIL_OP_EQ:
960 t = (*flows == ftflcr->val);
961 break;
962 case FT_FIL_OP_NE:
963 t = (*flows != ftflcr->val);
964 break;
965 case FT_FIL_OP_GE:
966 t = (*flows >= ftflcr->val);
967 break;
968 case FT_FIL_OP_LE:
969 t = (*flows <= ftflcr->val);
970 break;
971 default:
972 fterr_warnx("eval_match_flows: internal error");
973 return -1;
974 break;
975
976 } /* switch */
977
978 /* did this line match? */
979 if (t) {
980 match = 1;
981 break;
982 }
983
984 } /* ftflcr */
985
986 /* if there was a match, then return that mode */
987 if (match)
988 return ftflcr->mode;
989
990 /* else return the default */
991 return lookup->default_mode;
992
993 } /* eval_match_flows */
994
995 /*
996 * function: eval_match_octets
997 *
998 * Evalute octets
999 *
1000 * returns: FT_FIL_MODE_PERMIT
1001 * FT_FIL_MODE_DENY
1002 */
eval_match_octets(struct ftfil_lookup_counter * lookup,char * rec,struct fts3rec_offsets * fo)1003 static int eval_match_octets(struct ftfil_lookup_counter *lookup, char *rec,
1004 struct fts3rec_offsets *fo)
1005 {
1006 struct ftfil_lookup_counter_rec *ftflcr;
1007 uint32_t *octets;
1008 int t, match;
1009
1010 octets = ((uint32_t*)(rec+fo->dOctets));
1011
1012 match = 0;
1013
1014 FT_STAILQ_FOREACH(ftflcr, &lookup->list, chain) {
1015
1016 switch (ftflcr->op) {
1017
1018 case FT_FIL_OP_LT:
1019 t = (*octets < ftflcr->val);
1020 break;
1021 case FT_FIL_OP_GT:
1022 t = (*octets > ftflcr->val);
1023 break;
1024 case FT_FIL_OP_EQ:
1025 t = (*octets == ftflcr->val);
1026 break;
1027 case FT_FIL_OP_NE:
1028 t = (*octets != ftflcr->val);
1029 break;
1030 case FT_FIL_OP_GE:
1031 t = (*octets >= ftflcr->val);
1032 break;
1033 case FT_FIL_OP_LE:
1034 t = (*octets <= ftflcr->val);
1035 break;
1036 default:
1037 fterr_warnx("eval_match_octets: internal error");
1038 return -1;
1039 break;
1040
1041 } /* switch */
1042
1043 /* did this line match? */
1044 if (t) {
1045 match = 1;
1046 break;
1047 }
1048
1049 } /* ftflcr */
1050
1051 /* if there was a match, then return that mode */
1052 if (match)
1053 return ftflcr->mode;
1054
1055 /* else return the default */
1056 return lookup->default_mode;
1057
1058 } /* eval_match_octets */
1059
1060 /*
1061 * function: eval_match_packets
1062 *
1063 * Evalute packets
1064 *
1065 * returns: FT_FIL_MODE_PERMIT
1066 * FT_FIL_MODE_DENY
1067 */
eval_match_packets(struct ftfil_lookup_counter * lookup,char * rec,struct fts3rec_offsets * fo)1068 static int eval_match_packets(struct ftfil_lookup_counter *lookup, char *rec,
1069 struct fts3rec_offsets *fo)
1070 {
1071 struct ftfil_lookup_counter_rec *ftflcr;
1072 uint32_t *packets;
1073 int t, match;
1074
1075 packets = ((uint32_t*)(rec+fo->dPkts));
1076
1077 match = 0;
1078
1079 FT_STAILQ_FOREACH(ftflcr, &lookup->list, chain) {
1080
1081 switch (ftflcr->op) {
1082
1083 case FT_FIL_OP_LT:
1084 t = (*packets < ftflcr->val);
1085 break;
1086 case FT_FIL_OP_GT:
1087 t = (*packets > ftflcr->val);
1088 break;
1089 case FT_FIL_OP_EQ:
1090 t = (*packets == ftflcr->val);
1091 break;
1092 case FT_FIL_OP_NE:
1093 t = (*packets != ftflcr->val);
1094 break;
1095 case FT_FIL_OP_GE:
1096 t = (*packets >= ftflcr->val);
1097 break;
1098 case FT_FIL_OP_LE:
1099 t = (*packets <= ftflcr->val);
1100 break;
1101 default:
1102 fterr_warnx("eval_match_packets: internal error");
1103 return -1;
1104 break;
1105
1106 } /* switch */
1107
1108 /* did this line match? */
1109 if (t) {
1110 match = 1;
1111 break;
1112 }
1113
1114 } /* ftflcr */
1115
1116 /* if there was a match, then return that mode */
1117 if (match)
1118 return ftflcr->mode;
1119
1120 /* else return the default */
1121 return lookup->default_mode;
1122
1123 } /* eval_match_packets */
1124
1125 /*
1126 * function: eval_match_xtra_packets
1127 *
1128 * Evalute xtra_packets
1129 *
1130 * returns: FT_FIL_MODE_PERMIT
1131 * FT_FIL_MODE_DENY
1132 */
eval_match_xtra_packets(struct ftfil_lookup_counter * lookup,char * rec,struct fts3rec_offsets * fo)1133 static int eval_match_xtra_packets(struct ftfil_lookup_counter *lookup,
1134 char *rec, struct fts3rec_offsets *fo)
1135 {
1136 struct ftfil_lookup_counter_rec *ftflcr;
1137 uint32_t *xtra_packets;
1138 int t, match;
1139
1140 xtra_packets = ((uint32_t*)(rec+fo->extra_pkts));
1141
1142 match = 0;
1143
1144 FT_STAILQ_FOREACH(ftflcr, &lookup->list, chain) {
1145
1146 switch (ftflcr->op) {
1147
1148 case FT_FIL_OP_LT:
1149 t = (*xtra_packets < ftflcr->val);
1150 break;
1151 case FT_FIL_OP_GT:
1152 t = (*xtra_packets > ftflcr->val);
1153 break;
1154 case FT_FIL_OP_EQ:
1155 t = (*xtra_packets == ftflcr->val);
1156 break;
1157 case FT_FIL_OP_NE:
1158 t = (*xtra_packets != ftflcr->val);
1159 break;
1160 case FT_FIL_OP_GE:
1161 t = (*xtra_packets >= ftflcr->val);
1162 break;
1163 case FT_FIL_OP_LE:
1164 t = (*xtra_packets <= ftflcr->val);
1165 break;
1166 default:
1167 fterr_warnx("eval_match_xtra_packets: internal error");
1168 return -1;
1169 break;
1170
1171 } /* switch */
1172
1173 /* did this line match? */
1174 if (t) {
1175 match = 1;
1176 break;
1177 }
1178
1179 } /* ftflcr */
1180
1181 /* if there was a match, then return that mode */
1182 if (match)
1183 return ftflcr->mode;
1184
1185 /* else return the default */
1186 return lookup->default_mode;
1187
1188 } /* eval_match_xtra_packets */
1189
1190 /*
1191 * function: eval_match_duration
1192 *
1193 * Evalute duration
1194 *
1195 * returns: FT_FIL_MODE_PERMIT
1196 * FT_FIL_MODE_DENY
1197 */
eval_match_duration(struct ftfil_lookup_counter * lookup,char * rec,struct fts3rec_offsets * fo)1198 static int eval_match_duration(struct ftfil_lookup_counter *lookup, char *rec,
1199 struct fts3rec_offsets *fo)
1200 {
1201 struct ftfil_lookup_counter_rec *ftflcr;
1202 uint32_t duration, *first, *last;
1203 int t, match;
1204
1205 first = ((uint32_t*)(rec+fo->First));
1206 last = ((uint32_t*)(rec+fo->Last));
1207 duration = *last - *first;
1208
1209 match = 0;
1210
1211 FT_STAILQ_FOREACH(ftflcr, &lookup->list, chain) {
1212
1213 switch (ftflcr->op) {
1214
1215 case FT_FIL_OP_LT:
1216 t = (duration < ftflcr->val);
1217 break;
1218 case FT_FIL_OP_GT:
1219 t = (duration > ftflcr->val);
1220 break;
1221 case FT_FIL_OP_EQ:
1222 t = (duration == ftflcr->val);
1223 break;
1224 case FT_FIL_OP_NE:
1225 t = (duration != ftflcr->val);
1226 break;
1227 case FT_FIL_OP_GE:
1228 t = (duration >= ftflcr->val);
1229 break;
1230 case FT_FIL_OP_LE:
1231 t = (duration <= ftflcr->val);
1232 break;
1233 default:
1234 fterr_warnx("eval_match_duration: internal error");
1235 return -1;
1236 break;
1237
1238 } /* switch */
1239
1240 /* did this line match? */
1241 if (t) {
1242 match = 1;
1243 break;
1244 }
1245
1246 } /* ftflcr */
1247
1248 /* if there was a match, then return that mode */
1249 if (match)
1250 return ftflcr->mode;
1251
1252 /* else return the default */
1253 return lookup->default_mode;
1254
1255 } /* eval_match_duration */
1256
1257 /*
1258 * function: eval_match_start_time_date
1259 *
1260 * Evalute start_time_date
1261 *
1262 * returns: FT_FIL_MODE_PERMIT
1263 * FT_FIL_MODE_DENY
1264 */
eval_match_start_time_date(struct ftfil_lookup_counter * lookup,char * rec,struct fts3rec_offsets * fo)1265 static int eval_match_start_time_date(struct ftfil_lookup_counter *lookup,
1266 char *rec, struct fts3rec_offsets *fo)
1267 {
1268 struct ftfil_lookup_counter_rec *ftflcr;
1269 struct fttime ftt;
1270 uint32_t *sysUpTime, *unix_secs, *unix_nsecs, *First;
1271 int t, match;
1272
1273 sysUpTime = ((uint32_t*)(rec+fo->sysUpTime));
1274 unix_secs = ((uint32_t*)(rec+fo->unix_secs));
1275 unix_nsecs = ((uint32_t*)(rec+fo->unix_nsecs));
1276 First = ((uint32_t*)(rec+fo->First));
1277
1278 ftt = ftltime(*sysUpTime, *unix_secs, *unix_nsecs, *First);
1279
1280 match = 0;
1281
1282 FT_STAILQ_FOREACH(ftflcr, &lookup->list, chain) {
1283
1284 switch (ftflcr->op) {
1285
1286 case FT_FIL_OP_LT:
1287 t = (ftt.secs < ftflcr->val);
1288 break;
1289 case FT_FIL_OP_GT:
1290 t = (ftt.secs > ftflcr->val);
1291 break;
1292 case FT_FIL_OP_EQ:
1293 t = (ftt.secs == ftflcr->val);
1294 break;
1295 case FT_FIL_OP_NE:
1296 t = (ftt.secs != ftflcr->val);
1297 break;
1298 case FT_FIL_OP_GE:
1299 t = (ftt.secs >= ftflcr->val);
1300 break;
1301 case FT_FIL_OP_LE:
1302 t = (ftt.secs <= ftflcr->val);
1303 break;
1304 default:
1305 fterr_warnx("eval_match_start_time_date: internal error");
1306 return -1;
1307 break;
1308
1309 } /* switch */
1310
1311 /* did this line match? */
1312 if (t) {
1313 match = 1;
1314 break;
1315 }
1316
1317 } /* ftflcr */
1318
1319 /* if there was a match, then return that mode */
1320 if (match)
1321 return ftflcr->mode;
1322
1323 /* else return the default */
1324 return lookup->default_mode;
1325
1326 } /* eval_match_start_time_date */
1327
1328 /*
1329 * function: eval_match_end_time_date
1330 *
1331 * Evalute end_time_date
1332 *
1333 * returns: FT_FIL_MODE_PERMIT
1334 * FT_FIL_MODE_DENY
1335 */
eval_match_end_time_date(struct ftfil_lookup_counter * lookup,char * rec,struct fts3rec_offsets * fo)1336 static int eval_match_end_time_date(struct ftfil_lookup_counter *lookup,
1337 char *rec, struct fts3rec_offsets *fo)
1338 {
1339 struct ftfil_lookup_counter_rec *ftflcr;
1340 struct fttime ftt;
1341 uint32_t *sysUpTime, *unix_secs, *unix_nsecs, *Last;
1342 int t, match;
1343
1344 sysUpTime = ((uint32_t*)(rec+fo->sysUpTime));
1345 unix_secs = ((uint32_t*)(rec+fo->unix_secs));
1346 unix_nsecs = ((uint32_t*)(rec+fo->unix_nsecs));
1347 Last = ((uint32_t*)(rec+fo->Last));
1348
1349 ftt = ftltime(*sysUpTime, *unix_secs, *unix_nsecs, *Last);
1350
1351 match = 0;
1352
1353 FT_STAILQ_FOREACH(ftflcr, &lookup->list, chain) {
1354
1355 switch (ftflcr->op) {
1356
1357 case FT_FIL_OP_LT:
1358 t = (ftt.secs < ftflcr->val);
1359 break;
1360 case FT_FIL_OP_GT:
1361 t = (ftt.secs > ftflcr->val);
1362 break;
1363 case FT_FIL_OP_EQ:
1364 t = (ftt.secs == ftflcr->val);
1365 break;
1366 case FT_FIL_OP_NE:
1367 t = (ftt.secs != ftflcr->val);
1368 break;
1369 case FT_FIL_OP_GE:
1370 t = (ftt.secs >= ftflcr->val);
1371 break;
1372 case FT_FIL_OP_LE:
1373 t = (ftt.secs <= ftflcr->val);
1374 break;
1375 default:
1376 fterr_warnx("eval_match_end_time_date: internal error");
1377 return -1;
1378 break;
1379
1380 } /* switch */
1381
1382 /* did this line match? */
1383 if (t) {
1384 match = 1;
1385 break;
1386 }
1387
1388 } /* ftflcr */
1389
1390 /* if there was a match, then return that mode */
1391 if (match)
1392 return ftflcr->mode;
1393
1394 /* else return the default */
1395 return lookup->default_mode;
1396
1397 } /* eval_match_end_time_date */
1398
1399 /*
1400 * function: eval_match_start_time
1401 *
1402 * Evalute start_time
1403 *
1404 * returns: FT_FIL_MODE_PERMIT
1405 * FT_FIL_MODE_DENY
1406 */
eval_match_start_time(struct ftfil_lookup_time * lookup,char * rec,struct fts3rec_offsets * fo)1407 static int eval_match_start_time(struct ftfil_lookup_time *lookup,
1408 char *rec, struct fts3rec_offsets *fo)
1409 {
1410 time_t t1, t2;
1411 struct tm *tm;
1412 struct ftfil_lookup_time_rec *ftfltmer;
1413 struct fttime ftt;
1414 uint32_t *sysUpTime, *unix_secs, *unix_nsecs, *First;
1415 int t, match;
1416
1417 sysUpTime = ((uint32_t*)(rec+fo->sysUpTime));
1418 unix_secs = ((uint32_t*)(rec+fo->unix_secs));
1419 unix_nsecs = ((uint32_t*)(rec+fo->unix_nsecs));
1420 First = ((uint32_t*)(rec+fo->First));
1421
1422 ftt = ftltime(*sysUpTime, *unix_secs, *unix_nsecs, *First);
1423
1424 t1 = ftt.secs;
1425
1426 /* tm is now "today" for the flow */
1427 tm = localtime(&t1);
1428 tm->tm_hour = 0;
1429 tm->tm_min = 0;
1430 tm->tm_sec = 0;
1431
1432 match = 0;
1433
1434 FT_STAILQ_FOREACH(ftfltmer, &lookup->list, chain) {
1435
1436 /*
1437 * find where the hh:mm:ss for this filter falls relative to day start,
1438 * store as t2
1439 */
1440 tm->tm_hour = ftfltmer->hour;
1441 tm->tm_min = ftfltmer->min;
1442 tm->tm_sec = ftfltmer->sec;
1443 t2 = mktime(tm);
1444
1445 switch (ftfltmer->op) {
1446
1447 case FT_FIL_OP_LT:
1448 t = (t1 < t2);
1449 break;
1450 case FT_FIL_OP_GT:
1451 t = (t1 > t2);
1452 break;
1453 case FT_FIL_OP_EQ:
1454 t = (t1 == t2);
1455 break;
1456 case FT_FIL_OP_NE:
1457 t = (t1 != t2);
1458 break;
1459 case FT_FIL_OP_GE:
1460 t = (t1 >= t2);
1461 break;
1462 case FT_FIL_OP_LE:
1463 t = (t1 <= t2);
1464 break;
1465 default:
1466 fterr_warnx("eval_match_start_time: internal error");
1467 return -1;
1468 break;
1469
1470 } /* switch */
1471
1472 /* did this line match? */
1473 if (t) {
1474 match = 1;
1475 break;
1476 }
1477
1478 } /* ftfltmer */
1479
1480 /* if there was a match, then return that mode */
1481 if (match)
1482 return ftfltmer->mode;
1483
1484 /* else return the default */
1485 return lookup->default_mode;
1486
1487 } /* eval_match_start_time */
1488
1489 /*
1490 * function: eval_match_end_time
1491 *
1492 * Evalute end_time
1493 *
1494 * returns: FT_FIL_MODE_PERMIT
1495 * FT_FIL_MODE_DENY
1496 */
eval_match_end_time(struct ftfil_lookup_time * lookup,char * rec,struct fts3rec_offsets * fo)1497 static int eval_match_end_time(struct ftfil_lookup_time *lookup,
1498 char *rec, struct fts3rec_offsets *fo)
1499 {
1500 time_t t1, t2;
1501 struct tm *tm;
1502 struct ftfil_lookup_time_rec *ftfltmer;
1503 struct fttime ftt;
1504 uint32_t *sysUpTime, *unix_secs, *unix_nsecs, *Last;
1505 int t, match;
1506
1507 sysUpTime = ((uint32_t*)(rec+fo->sysUpTime));
1508 unix_secs = ((uint32_t*)(rec+fo->unix_secs));
1509 unix_nsecs = ((uint32_t*)(rec+fo->unix_nsecs));
1510 Last = ((uint32_t*)(rec+fo->Last));
1511
1512 ftt = ftltime(*sysUpTime, *unix_secs, *unix_nsecs, *Last);
1513
1514 t1 = ftt.secs;
1515
1516 /* tm is now "today" for the flow */
1517 tm = localtime(&t1);
1518 tm->tm_hour = 0;
1519 tm->tm_min = 0;
1520 tm->tm_sec = 0;
1521
1522 match = 0;
1523
1524 FT_STAILQ_FOREACH(ftfltmer, &lookup->list, chain) {
1525
1526 /*
1527 * find where the hh:mm:ss for this filter falls relative to day start,
1528 * store as t2
1529 */
1530 tm->tm_hour = ftfltmer->hour;
1531 tm->tm_min = ftfltmer->min;
1532 tm->tm_sec = ftfltmer->sec;
1533 t2 = mktime(tm);
1534
1535 switch (ftfltmer->op) {
1536
1537 case FT_FIL_OP_LT:
1538 t = (t1 < t2);
1539 break;
1540 case FT_FIL_OP_GT:
1541 t = (t1 > t2);
1542 break;
1543 case FT_FIL_OP_EQ:
1544 t = (t1 == t2);
1545 break;
1546 case FT_FIL_OP_NE:
1547 t = (t1 != t2);
1548 break;
1549 case FT_FIL_OP_GE:
1550 t = (t1 >= t2);
1551 break;
1552 case FT_FIL_OP_LE:
1553 t = (t1 <= t2);
1554 break;
1555 default:
1556 fterr_warnx("eval_match_end_time: internal error");
1557 return -1;
1558 break;
1559
1560 } /* switch */
1561
1562 /* did this line match? */
1563 if (t) {
1564 match = 1;
1565 break;
1566 }
1567
1568 } /* ftfltmer */
1569
1570 /* if there was a match, then return that mode */
1571 if (match)
1572 return ftfltmer->mode;
1573
1574 /* else return the default */
1575 return lookup->default_mode;
1576
1577 } /* eval_match_end_time */
1578
1579 /*
1580 * function: eval_match_src_tag_l
1581 *
1582 * Evalute src_tag as list
1583 *
1584 * returns: FT_FIL_MODE_PERMIT
1585 * FT_FIL_MODE_DENY
1586 */
eval_match_src_tag_l(struct ftfil_lookup_tag_mask * lookup,char * rec,struct fts3rec_offsets * fo)1587 static int eval_match_src_tag_l(struct ftfil_lookup_tag_mask *lookup,
1588 char *rec, struct fts3rec_offsets *fo)
1589 {
1590 struct ftfil_lookup_tag_mask_rec *ftfltmr;
1591 uint32_t *src_tag;
1592 int match;
1593
1594 src_tag = ((uint32_t*)(rec+fo->src_tag));
1595
1596 match = 0;
1597
1598 FT_STAILQ_FOREACH(ftfltmr, &lookup->list, chain) {
1599
1600 /* match? */
1601 if ((*src_tag & ftfltmr->mask) == ftfltmr->tag) {
1602 match = 1;
1603 break;
1604 }
1605
1606 } /* ftfltmr */
1607
1608 /* if there was a match, then return that mode */
1609 if (match)
1610 return ftfltmr->mode;
1611
1612 /* else return the default */
1613 return lookup->default_mode;
1614
1615 } /* eval_match_src_tag_l */
1616
1617 /*
1618 * function: eval_match_src_tag_h
1619 *
1620 * Evalute src_tag as hash
1621 *
1622 * returns: FT_FIL_MODE_PERMIT
1623 * FT_FIL_MODE_DENY
1624 */
eval_match_src_tag_h(struct ftfil_lookup_tag * lookup,char * rec,struct fts3rec_offsets * fo)1625 static int eval_match_src_tag_h(struct ftfil_lookup_tag *lookup,
1626 char *rec, struct fts3rec_offsets *fo)
1627 {
1628 struct ftchash_rec_fil_c32 *ftch_recfc32p;
1629 uint32_t *src_tag, hash;
1630 int match;
1631
1632 src_tag = ((uint32_t*)(rec+fo->src_tag));
1633
1634 match = 0;
1635
1636 hash = (*src_tag>>16) ^ (*src_tag & 0xFFFF);
1637 hash = ((hash >>8) ^ (hash & 0x0FFF));
1638
1639 if ((ftch_recfc32p = ftchash_lookup(lookup->ftch, src_tag, hash)))
1640 match = 1;
1641
1642 /* if there was a match, then return that mode */
1643 if (match)
1644 return ftch_recfc32p->mode;
1645
1646 /* else return the default */
1647 return lookup->default_mode;
1648
1649 } /* eval_match_src_tag_h */
1650
1651 /*
1652 * function: eval_match_dst_tag_h
1653 *
1654 * Evalute dst_tag as hash
1655 *
1656 * returns: FT_FIL_MODE_PERMIT
1657 * FT_FIL_MODE_DENY
1658 */
eval_match_dst_tag_h(struct ftfil_lookup_tag * lookup,char * rec,struct fts3rec_offsets * fo)1659 static int eval_match_dst_tag_h(struct ftfil_lookup_tag *lookup,
1660 char *rec, struct fts3rec_offsets *fo)
1661 {
1662 struct ftchash_rec_fil_c32 *ftch_recfc32p;
1663 uint32_t *dst_tag, hash;
1664 int match;
1665
1666 dst_tag = ((uint32_t*)(rec+fo->dst_tag));
1667
1668 match = 0;
1669
1670 hash = (*dst_tag>>16) ^ (*dst_tag & 0xFFFF);
1671 hash = ((hash >>8) ^ (hash & 0x0FFF));
1672
1673 if ((ftch_recfc32p = ftchash_lookup(lookup->ftch, dst_tag, hash)))
1674 match = 1;
1675
1676 /* if there was a match, then return that mode */
1677 if (match)
1678 return ftch_recfc32p->mode;
1679
1680 /* else return the default */
1681 return lookup->default_mode;
1682
1683 } /* eval_match_dst_tag_h */
1684
1685 /*
1686 * function: eval_match_dst_tag_l
1687 *
1688 * Evalute dst_tag as list
1689 *
1690 * returns: FT_FIL_MODE_PERMIT
1691 * FT_FIL_MODE_DENY
1692 */
eval_match_dst_tag_l(struct ftfil_lookup_tag_mask * lookup,char * rec,struct fts3rec_offsets * fo)1693 static int eval_match_dst_tag_l(struct ftfil_lookup_tag_mask *lookup,
1694 char *rec, struct fts3rec_offsets *fo)
1695 {
1696 struct ftfil_lookup_tag_mask_rec *ftfltmr;
1697 uint32_t *dst_tag;
1698 int match;
1699
1700 dst_tag = ((uint32_t*)(rec+fo->dst_tag));
1701
1702 match = 0;
1703
1704 FT_STAILQ_FOREACH(ftfltmr, &lookup->list, chain) {
1705
1706 /* match? */
1707 if ((*dst_tag & ftfltmr->mask) == ftfltmr->tag) {
1708 match = 1;
1709 break;
1710 }
1711
1712 } /* ftfltmr */
1713
1714 /* if there was a match, then return that mode */
1715 if (match)
1716 return ftfltmr->mode;
1717
1718 /* else return the default */
1719 return lookup->default_mode;
1720
1721 } /* eval_match_dst_tag_l */
1722
1723 /*
1724 * function: eval_match_nexthop_l
1725 *
1726 * Evalute nexthop as list
1727 *
1728 * returns: FT_FIL_MODE_PERMIT
1729 * FT_FIL_MODE_DENY
1730 */
eval_match_ip_nexthop_addr_l(struct ftfil_lookup_ip_mask * lookup,char * rec,struct fts3rec_offsets * fo)1731 static int eval_match_ip_nexthop_addr_l(struct ftfil_lookup_ip_mask *lookup,
1732 char *rec, struct fts3rec_offsets *fo)
1733 {
1734 struct ftfil_lookup_ip_mask_rec *ftflipmr;
1735 uint32_t *nexthop;
1736 int match;
1737
1738 nexthop = ((uint32_t*)(rec+fo->nexthop));
1739
1740 match = 0;
1741
1742 FT_STAILQ_FOREACH(ftflipmr, &lookup->list, chain) {
1743
1744 /* match? */
1745 if ((*nexthop & ftflipmr->mask) == ftflipmr->ip) {
1746 match = 1;
1747 break;
1748 }
1749
1750 } /* ftflipmr */
1751
1752 /* if there was a match, then return that mode */
1753 if (match)
1754 return ftflipmr->mode;
1755
1756 /* else return the default */
1757 return lookup->default_mode;
1758
1759 } /* eval_match_ip_nexthop_addr_l */
1760
1761 /*
1762 * function: eval_match_ip_nexthop_addr_h
1763 *
1764 * Evalute nexthop as hash
1765 *
1766 * returns: FT_FIL_MODE_PERMIT
1767 * FT_FIL_MODE_DENY
1768 */
eval_match_ip_nexthop_addr_h(struct ftfil_lookup_ip_address * lookup,char * rec,struct fts3rec_offsets * fo)1769 static int eval_match_ip_nexthop_addr_h(struct ftfil_lookup_ip_address *lookup,
1770 char *rec, struct fts3rec_offsets *fo)
1771 {
1772 struct ftchash_rec_fil_c32 *ftch_recfc32p;
1773 uint32_t *nexthop, hash;
1774 int match;
1775
1776 nexthop = ((uint32_t*)(rec+fo->nexthop));
1777
1778 match = 0;
1779
1780 hash = (*nexthop>>16) ^ (*nexthop & 0xFFFF);
1781 hash = ((hash >>8) ^ (hash & 0x0FFF));
1782
1783 if ((ftch_recfc32p = ftchash_lookup(lookup->ftch, nexthop, hash)))
1784 match = 1;
1785
1786 /* if there was a match, then return that mode */
1787 if (match)
1788 return ftch_recfc32p->mode;
1789
1790 /* else return the default */
1791 return lookup->default_mode;
1792
1793 } /* eval_match_ip_nexthop_addr_h */
1794
1795 /*
1796 * function: eval_match_ip_nexthop_addr_r
1797 *
1798 * Evalute nexthop as hash
1799 *
1800 * returns: FT_FIL_MODE_PERMIT
1801 * FT_FIL_MODE_DENY
1802 */
eval_match_ip_nexthop_addr_r(struct ftfil_lookup_ip_prefix * lookup,char * rec,struct fts3rec_offsets * fo)1803 static int eval_match_ip_nexthop_addr_r(struct ftfil_lookup_ip_prefix *lookup,
1804 char *rec, struct fts3rec_offsets *fo)
1805 {
1806 struct ftfil_lookup_ip_prefix_rec *ftflipprr;
1807 struct radix_node_head *rhead;
1808 struct radix_sockaddr_in sock1;
1809 int match;
1810
1811 sock1.sin_addr.s_addr = *((uint32_t*)(rec+fo->nexthop));
1812 sock1.sin_len = sizeof sock1;
1813 sock1.sin_family = AF_INET;
1814
1815 match = 0;
1816
1817 rhead = lookup->rhead;
1818
1819 if ((ftflipprr = (struct ftfil_lookup_ip_prefix_rec*)rhead->rnh_matchaddr(
1820 &sock1, rhead)))
1821 match = 1;
1822
1823 /* if there was a match, then return that mode */
1824 if (match)
1825 return ftflipprr->mode;
1826
1827 /* else return the default */
1828 return lookup->default_mode;
1829
1830 } /* eval_match_ip_nexthop_addr_r */
1831
1832 /*
1833 * function: eval_match_ip_sc_addr_l
1834 *
1835 * Evalute sc as list
1836 *
1837 * returns: FT_FIL_MODE_PERMIT
1838 * FT_FIL_MODE_DENY
1839 */
eval_match_ip_sc_addr_l(struct ftfil_lookup_ip_mask * lookup,char * rec,struct fts3rec_offsets * fo)1840 static int eval_match_ip_sc_addr_l(struct ftfil_lookup_ip_mask *lookup,
1841 char *rec, struct fts3rec_offsets *fo)
1842 {
1843 struct ftfil_lookup_ip_mask_rec *ftflipmr;
1844 uint32_t *sc;
1845 int match;
1846
1847 sc = ((uint32_t*)(rec+fo->router_sc));
1848
1849 match = 0;
1850
1851 FT_STAILQ_FOREACH(ftflipmr, &lookup->list, chain) {
1852
1853 /* match? */
1854 if ((*sc & ftflipmr->mask) == ftflipmr->ip) {
1855 match = 1;
1856 break;
1857 }
1858
1859 } /* ftflipmr */
1860
1861 /* if there was a match, then return that mode */
1862 if (match)
1863 return ftflipmr->mode;
1864
1865 /* else return the default */
1866 return lookup->default_mode;
1867
1868 } /* eval_match_ip_sc_addr_l */
1869
1870 /*
1871 * function: eval_match_ip_sc_addr_h
1872 *
1873 * Evalute sc as hash
1874 *
1875 * returns: FT_FIL_MODE_PERMIT
1876 * FT_FIL_MODE_DENY
1877 */
eval_match_ip_sc_addr_h(struct ftfil_lookup_ip_address * lookup,char * rec,struct fts3rec_offsets * fo)1878 static int eval_match_ip_sc_addr_h(struct ftfil_lookup_ip_address *lookup,
1879 char *rec, struct fts3rec_offsets *fo)
1880 {
1881 struct ftchash_rec_fil_c32 *ftch_recfc32p;
1882 uint32_t *sc, hash;
1883 int match;
1884
1885 sc = ((uint32_t*)(rec+fo->router_sc));
1886
1887 match = 0;
1888
1889 hash = (*sc>>16) ^ (*sc & 0xFFFF);
1890 hash = ((hash >>8) ^ (hash & 0x0FFF));
1891
1892 if ((ftch_recfc32p = ftchash_lookup(lookup->ftch, sc, hash)))
1893 match = 1;
1894
1895 /* if there was a match, then return that mode */
1896 if (match)
1897 return ftch_recfc32p->mode;
1898
1899 /* else return the default */
1900 return lookup->default_mode;
1901
1902 } /* eval_match_ip_sc_addr_h */
1903
1904 /*
1905 * function: eval_match_ip_sc_addr_r
1906 *
1907 * Evalute sc as hash
1908 *
1909 * returns: FT_FIL_MODE_PERMIT
1910 * FT_FIL_MODE_DENY
1911 */
eval_match_ip_sc_addr_r(struct ftfil_lookup_ip_prefix * lookup,char * rec,struct fts3rec_offsets * fo)1912 static int eval_match_ip_sc_addr_r(struct ftfil_lookup_ip_prefix *lookup,
1913 char *rec, struct fts3rec_offsets *fo)
1914 {
1915 struct ftfil_lookup_ip_prefix_rec *ftflipprr;
1916 struct radix_node_head *rhead;
1917 struct radix_sockaddr_in sock1;
1918 int match;
1919
1920 sock1.sin_addr.s_addr = *((uint32_t*)(rec+fo->router_sc));
1921 sock1.sin_len = sizeof sock1;
1922 sock1.sin_family = AF_INET;
1923
1924 match = 0;
1925
1926 rhead = lookup->rhead;
1927
1928 if ((ftflipprr = (struct ftfil_lookup_ip_prefix_rec*)rhead->rnh_matchaddr(
1929 &sock1, rhead)))
1930 match = 1;
1931
1932 /* if there was a match, then return that mode */
1933 if (match)
1934 return ftflipprr->mode;
1935
1936 /* else return the default */
1937 return lookup->default_mode;
1938
1939 } /* eval_match_ip_sc_addr_r */
1940
1941 /*
1942 * function: eval_match_ip_src_addr_l
1943 *
1944 * Evalute ip_src_addr as list
1945 *
1946 * returns: FT_FIL_MODE_PERMIT
1947 * FT_FIL_MODE_DENY
1948 */
eval_match_ip_src_addr_l(struct ftfil_lookup_ip_mask * lookup,char * rec,struct fts3rec_offsets * fo)1949 static int eval_match_ip_src_addr_l(struct ftfil_lookup_ip_mask *lookup,
1950 char *rec, struct fts3rec_offsets *fo)
1951 {
1952 struct ftfil_lookup_ip_mask_rec *ftflipmr;
1953 uint32_t *ip_src_addr;
1954 int match;
1955
1956 ip_src_addr = ((uint32_t*)(rec+fo->srcaddr));
1957
1958 match = 0;
1959
1960 FT_STAILQ_FOREACH(ftflipmr, &lookup->list, chain) {
1961
1962 /* match? */
1963 if ((*ip_src_addr & ftflipmr->mask) == ftflipmr->ip) {
1964 match = 1;
1965 break;
1966 }
1967
1968 } /* ftflipmr */
1969
1970 /* if there was a match, then return that mode */
1971 if (match)
1972 return ftflipmr->mode;
1973
1974 /* else return the default */
1975 return lookup->default_mode;
1976
1977 } /* eval_match_ip_src_addr_l */
1978
1979 /*
1980 * function: eval_match_ip_src_addr_h
1981 *
1982 * Evalute ip_src_addr as hash
1983 *
1984 * returns: FT_FIL_MODE_PERMIT
1985 * FT_FIL_MODE_DENY
1986 */
eval_match_ip_src_addr_h(struct ftfil_lookup_ip_address * lookup,char * rec,struct fts3rec_offsets * fo)1987 static int eval_match_ip_src_addr_h(struct ftfil_lookup_ip_address *lookup,
1988 char *rec, struct fts3rec_offsets *fo)
1989 {
1990 struct ftchash_rec_fil_c32 *ftch_recfc32p;
1991 uint32_t *ip_src_addr, hash;
1992 int match;
1993
1994 ip_src_addr = ((uint32_t*)(rec+fo->srcaddr));
1995
1996 match = 0;
1997
1998 hash = (*ip_src_addr>>16) ^ (*ip_src_addr & 0xFFFF);
1999 hash = ((hash >>8) ^ (hash & 0x0FFF));
2000
2001 if ((ftch_recfc32p = ftchash_lookup(lookup->ftch, ip_src_addr, hash)))
2002 match = 1;
2003
2004 /* if there was a match, then return that mode */
2005 if (match)
2006 return ftch_recfc32p->mode;
2007
2008 /* else return the default */
2009 return lookup->default_mode;
2010
2011 } /* eval_match_ip_src_addr_h */
2012
2013 /*
2014 * function: eval_match_ip_src_addr_r
2015 *
2016 * Evalute ip_src_addr as hash
2017 *
2018 * returns: FT_FIL_MODE_PERMIT
2019 * FT_FIL_MODE_DENY
2020 */
eval_match_ip_src_addr_r(struct ftfil_lookup_ip_prefix * lookup,char * rec,struct fts3rec_offsets * fo)2021 static int eval_match_ip_src_addr_r(struct ftfil_lookup_ip_prefix *lookup,
2022 char *rec, struct fts3rec_offsets *fo)
2023 {
2024 struct ftfil_lookup_ip_prefix_rec *ftflipprr;
2025 struct radix_node_head *rhead;
2026 struct radix_sockaddr_in sock1;
2027 int match;
2028
2029 sock1.sin_addr.s_addr = *((uint32_t*)(rec+fo->srcaddr));
2030 sock1.sin_len = sizeof sock1;
2031 sock1.sin_family = AF_INET;
2032
2033 match = 0;
2034
2035 rhead = lookup->rhead;
2036
2037 if ((ftflipprr = (struct ftfil_lookup_ip_prefix_rec*)rhead->rnh_matchaddr(
2038 &sock1, rhead)))
2039 match = 1;
2040
2041 /* if there was a match, then return that mode */
2042 if (match)
2043 return ftflipprr->mode;
2044
2045 /* else return the default */
2046 return lookup->default_mode;
2047
2048 } /* eval_match_ip_src_addr_r */
2049
2050 /*
2051 * function: eval_match_ip_dst_addr_l
2052 *
2053 * Evalute ip_dst_addr as list
2054 *
2055 * returns: FT_FIL_MODE_PERMIT
2056 * FT_FIL_MODE_DENY
2057 */
eval_match_ip_dst_addr_l(struct ftfil_lookup_ip_mask * lookup,char * rec,struct fts3rec_offsets * fo)2058 static int eval_match_ip_dst_addr_l(struct ftfil_lookup_ip_mask *lookup,
2059 char *rec, struct fts3rec_offsets *fo)
2060 {
2061 struct ftfil_lookup_ip_mask_rec *ftflipmr;
2062 uint32_t *ip_dst_addr;
2063 int match;
2064
2065 ip_dst_addr = ((uint32_t*)(rec+fo->dstaddr));
2066
2067 match = 0;
2068
2069 FT_STAILQ_FOREACH(ftflipmr, &lookup->list, chain) {
2070
2071 /* match? */
2072 if ((*ip_dst_addr & ftflipmr->mask) == ftflipmr->ip) {
2073 match = 1;
2074 break;
2075 }
2076
2077 } /* ftflipmr */
2078
2079 /* if there was a match, then return that mode */
2080 if (match)
2081 return ftflipmr->mode;
2082
2083 /* else return the default */
2084 return lookup->default_mode;
2085
2086 } /* eval_match_ip_dst_addr_l */
2087
2088 /*
2089 * function: eval_match_ip_dst_addr_h
2090 *
2091 * Evalute ip_dst_addr as hash
2092 *
2093 * returns: FT_FIL_MODE_PERMIT
2094 * FT_FIL_MODE_DENY
2095 */
eval_match_ip_dst_addr_h(struct ftfil_lookup_ip_address * lookup,char * rec,struct fts3rec_offsets * fo)2096 static int eval_match_ip_dst_addr_h(struct ftfil_lookup_ip_address *lookup,
2097 char *rec, struct fts3rec_offsets *fo)
2098 {
2099 struct ftchash_rec_fil_c32 *ftch_recfc32p;
2100 uint32_t *ip_dst_addr, hash;
2101 int match;
2102
2103 ip_dst_addr = ((uint32_t*)(rec+fo->dstaddr));
2104
2105 match = 0;
2106
2107 hash = (*ip_dst_addr>>16) ^ (*ip_dst_addr & 0xFFFF);
2108 hash = ((hash >>8) ^ (hash & 0x0FFF));
2109
2110 if ((ftch_recfc32p = ftchash_lookup(lookup->ftch, ip_dst_addr, hash)))
2111 match = 1;
2112
2113 /* if there was a match, then return that mode */
2114 if (match)
2115 return ftch_recfc32p->mode;
2116
2117 /* else return the default */
2118 return lookup->default_mode;
2119
2120 } /* eval_match_ip_dst_addr_h */
2121
2122 /*
2123 * function: eval_match_ip_dst_addr_r
2124 *
2125 * Evalute ip_dst_addr as hash
2126 *
2127 * returns: FT_FIL_MODE_PERMIT
2128 * FT_FIL_MODE_DENY
2129 */
eval_match_ip_dst_addr_r(struct ftfil_lookup_ip_prefix * lookup,char * rec,struct fts3rec_offsets * fo)2130 static int eval_match_ip_dst_addr_r(struct ftfil_lookup_ip_prefix *lookup,
2131 char *rec, struct fts3rec_offsets *fo)
2132 {
2133 struct ftfil_lookup_ip_prefix_rec *ftflipprr;
2134 struct radix_node_head *rhead;
2135 struct radix_sockaddr_in sock1;
2136 int match;
2137
2138 sock1.sin_addr.s_addr = *((uint32_t*)(rec+fo->dstaddr));
2139 sock1.sin_len = sizeof sock1;
2140 sock1.sin_family = AF_INET;
2141
2142 match = 0;
2143
2144 rhead = lookup->rhead;
2145
2146 if ((ftflipprr = (struct ftfil_lookup_ip_prefix_rec*)rhead->rnh_matchaddr(
2147 &sock1, rhead)))
2148 match = 1;
2149
2150 /* if there was a match, then return that mode */
2151 if (match)
2152 return ftflipprr->mode;
2153
2154 /* else return the default */
2155 return lookup->default_mode;
2156
2157 } /* eval_match_ip_dst_addr_r */
2158
2159 /*
2160 * function: eval_match_ip_exporter_addr_l
2161 *
2162 * Evalute ip_exporter_addr as list
2163 *
2164 * returns: FT_FIL_MODE_PERMIT
2165 * FT_FIL_MODE_DENY
2166 */
eval_match_ip_exporter_addr_l(struct ftfil_lookup_ip_mask * lookup,char * rec,struct fts3rec_offsets * fo)2167 static int eval_match_ip_exporter_addr_l(struct ftfil_lookup_ip_mask *lookup,
2168 char *rec, struct fts3rec_offsets *fo)
2169 {
2170 struct ftfil_lookup_ip_mask_rec *ftflipmr;
2171 uint32_t *ip_exporter_addr;
2172 int match;
2173
2174 ip_exporter_addr = ((uint32_t*)(rec+fo->exaddr));
2175
2176 match = 0;
2177
2178 FT_STAILQ_FOREACH(ftflipmr, &lookup->list, chain) {
2179
2180 /* match? */
2181 if ((*ip_exporter_addr & ftflipmr->mask) == ftflipmr->ip) {
2182 match = 1;
2183 break;
2184 }
2185
2186 } /* ftflipmr */
2187
2188 /* if there was a match, then return that mode */
2189 if (match)
2190 return ftflipmr->mode;
2191
2192 /* else return the default */
2193 return lookup->default_mode;
2194
2195 } /* eval_match_ip_exporter_addr_l */
2196
2197 /*
2198 * function: eval_match_ip_exporter_addr_h
2199 *
2200 * Evalute ip_exporter_addr as hash
2201 *
2202 * returns: FT_FIL_MODE_PERMIT
2203 * FT_FIL_MODE_DENY
2204 */
eval_match_ip_exporter_addr_h(struct ftfil_lookup_ip_address * lookup,char * rec,struct fts3rec_offsets * fo)2205 static int eval_match_ip_exporter_addr_h(struct ftfil_lookup_ip_address *lookup,
2206 char *rec, struct fts3rec_offsets *fo)
2207 {
2208 struct ftchash_rec_fil_c32 *ftch_recfc32p;
2209 uint32_t *ip_exporter_addr, hash;
2210 int match;
2211
2212 ip_exporter_addr = ((uint32_t*)(rec+fo->exaddr));
2213
2214 match = 0;
2215
2216 hash = (*ip_exporter_addr>>16) ^ (*ip_exporter_addr & 0xFFFF);
2217 hash = ((hash >>8) ^ (hash & 0x0FFF));
2218
2219 if ((ftch_recfc32p = ftchash_lookup(lookup->ftch, ip_exporter_addr, hash)))
2220 match = 1;
2221
2222 /* if there was a match, then return that mode */
2223 if (match)
2224 return ftch_recfc32p->mode;
2225
2226 /* else return the default */
2227 return lookup->default_mode;
2228
2229 } /* eval_match_ip_exporter_addr_h */
2230
2231 /*
2232 * function: eval_match_ip_exporter_addr_r
2233 *
2234 * Evalute ip_exporter_addr as hash
2235 *
2236 * returns: FT_FIL_MODE_PERMIT
2237 * FT_FIL_MODE_DENY
2238 */
eval_match_ip_exporter_addr_r(struct ftfil_lookup_ip_prefix * lookup,char * rec,struct fts3rec_offsets * fo)2239 static int eval_match_ip_exporter_addr_r(struct ftfil_lookup_ip_prefix *lookup,
2240 char *rec, struct fts3rec_offsets *fo)
2241 {
2242 struct ftfil_lookup_ip_prefix_rec *ftflipprr;
2243 struct radix_node_head *rhead;
2244 struct radix_sockaddr_in sock1;
2245 int match;
2246
2247 sock1.sin_addr.s_addr = *((uint32_t*)(rec+fo->exaddr));
2248 sock1.sin_len = sizeof sock1;
2249 sock1.sin_family = AF_INET;
2250
2251 match = 0;
2252
2253 rhead = lookup->rhead;
2254
2255 if ((ftflipprr = (struct ftfil_lookup_ip_prefix_rec*)rhead->rnh_matchaddr(
2256 &sock1, rhead)))
2257 match = 1;
2258
2259 /* if there was a match, then return that mode */
2260 if (match)
2261 return ftflipprr->mode;
2262
2263 /* else return the default */
2264 return lookup->default_mode;
2265
2266 } /* eval_match_ip_exporter_addr_r */
2267
2268 /*
2269 * function: eval_match_bps
2270 *
2271 * Evalute Bits Per Second
2272 *
2273 * returns: FT_FIL_MODE_PERMIT
2274 * FT_FIL_MODE_DENY
2275 */
eval_match_bps(struct ftfil_lookup_double * lookup,char * rec,struct fts3rec_offsets * fo)2276 static int eval_match_bps(struct ftfil_lookup_double *lookup, char *rec,
2277 struct fts3rec_offsets *fo)
2278 {
2279 struct ftfil_lookup_double_rec *ftfldr;
2280 double bps;
2281 uint32_t dOctets, Last, First, duration;
2282 int t, match;
2283
2284 dOctets = *((uint32_t*)(rec+fo->dOctets));
2285 Last = *((uint32_t*)(rec+fo->Last));
2286 First = *((uint32_t*)(rec+fo->First));
2287 duration = Last - First;
2288
2289 if (duration)
2290 bps = (double)dOctets*8 / ((double)duration / 1000.0);
2291 else
2292 bps = 0;
2293
2294 match = 0;
2295
2296 FT_STAILQ_FOREACH(ftfldr, &lookup->list, chain) {
2297
2298 switch (ftfldr->op) {
2299
2300 case FT_FIL_OP_LT:
2301 t = (bps < ftfldr->val);
2302 break;
2303 case FT_FIL_OP_GT:
2304 t = (bps > ftfldr->val);
2305 break;
2306 case FT_FIL_OP_EQ:
2307 t = (bps == ftfldr->val);
2308 break;
2309 case FT_FIL_OP_NE:
2310 t = (bps != ftfldr->val);
2311 break;
2312 case FT_FIL_OP_GE:
2313 t = (bps >= ftfldr->val);
2314 break;
2315 case FT_FIL_OP_LE:
2316 t = (bps <= ftfldr->val);
2317 break;
2318 default:
2319 fterr_warnx("eval_match_flows: internal error");
2320 return -1;
2321 break;
2322
2323 } /* switch */
2324
2325 /* did this line match? */
2326 if (t) {
2327 match = 1;
2328 break;
2329 }
2330
2331 } /* ftflcr */
2332
2333 /* if there was a match, then return that mode */
2334 if (match)
2335 return ftfldr->mode;
2336
2337 /* else return the default */
2338 return lookup->default_mode;
2339
2340 } /* eval_match_bps */
2341
2342 /*
2343 * function: eval_match_pps
2344 *
2345 * Evalute Packets Per Second
2346 *
2347 * returns: FT_FIL_MODE_PERMIT
2348 * FT_FIL_MODE_DENY
2349 */
eval_match_pps(struct ftfil_lookup_double * lookup,char * rec,struct fts3rec_offsets * fo)2350 static int eval_match_pps(struct ftfil_lookup_double *lookup, char *rec,
2351 struct fts3rec_offsets *fo)
2352 {
2353 struct ftfil_lookup_double_rec *ftfldr;
2354 double pps;
2355 uint32_t dPkts, Last, First, duration;
2356 int t, match;
2357
2358 dPkts = *((uint32_t*)(rec+fo->dPkts));
2359 Last = *((uint32_t*)(rec+fo->Last));
2360 First = *((uint32_t*)(rec+fo->First));
2361 duration = Last - First;
2362
2363 if (duration)
2364 pps = (double)dPkts / ((double)duration / 1000.0);
2365 else
2366 pps = 0;
2367
2368 match = 0;
2369
2370 FT_STAILQ_FOREACH(ftfldr, &lookup->list, chain) {
2371
2372 switch (ftfldr->op) {
2373
2374 case FT_FIL_OP_LT:
2375 t = (pps < ftfldr->val);
2376 break;
2377 case FT_FIL_OP_GT:
2378 t = (pps > ftfldr->val);
2379 break;
2380 case FT_FIL_OP_EQ:
2381 t = (pps == ftfldr->val);
2382 break;
2383 case FT_FIL_OP_NE:
2384 t = (pps != ftfldr->val);
2385 break;
2386 case FT_FIL_OP_GE:
2387 t = (pps >= ftfldr->val);
2388 break;
2389 case FT_FIL_OP_LE:
2390 t = (pps <= ftfldr->val);
2391 break;
2392 default:
2393 fterr_warnx("eval_match_flows: internal error");
2394 return -1;
2395 break;
2396
2397 } /* switch */
2398
2399 /* did this line match? */
2400 if (t) {
2401 match = 1;
2402 break;
2403 }
2404
2405 } /* ftflcr */
2406
2407 /* if there was a match, then return that mode */
2408 if (match)
2409 return ftfldr->mode;
2410
2411 /* else return the default */
2412 return lookup->default_mode;
2413
2414 } /* eval_match_pps */
2415
2416 /*
2417 * function: eval_match_random_sample
2418 *
2419 * Evalute random_sample
2420 *
2421 * returns: FT_FIL_MODE_PERMIT
2422 * FT_FIL_MODE_DENY
2423 */
eval_match_random_sample(struct ftfil_lookup_rate * lookup,char * rec,struct fts3rec_offsets * fo)2424 static int eval_match_random_sample(struct ftfil_lookup_rate *lookup, char *rec,
2425 struct fts3rec_offsets *fo)
2426 {
2427 int val;
2428
2429 /* val is a random number from 0..lookup->rate-1 */
2430 val = rand() % lookup->rate;
2431
2432 /* pick 0 as the "pass" value -- could have picked any number in the range */
2433 if (!val)
2434 return (lookup->mode == FT_FIL_MODE_PERMIT) ? FT_FIL_MODE_PERMIT :
2435 FT_FIL_MODE_DENY;
2436 else
2437 return (lookup->mode == FT_FIL_MODE_PERMIT) ? FT_FIL_MODE_DENY :
2438 FT_FIL_MODE_PERMIT;
2439
2440 } /* eval_match_random_sample */
2441
2442 /*
2443 *************************************************************************
2444 public ftfil_*
2445 *************************************************************************
2446 */
2447
2448 /*
2449 * function: ftfil_load
2450 *
2451 * Process fname into ftfil.
2452 *
2453 * returns: 0 ok
2454 * <0 fail
2455 */
ftfil_load(struct ftfil * ftfil,struct ftvar * ftvar,const char * fname)2456 int ftfil_load(struct ftfil *ftfil, struct ftvar *ftvar, const char *fname)
2457 {
2458 struct stat sb;
2459 struct jump *jmp;
2460 struct line_parser lp;
2461 int fd, ret, found;
2462 char *buf, *buf2, *c;
2463 char sbuf[FT_LP_MAXLINE];
2464
2465 ret = -1;
2466 buf = (char*)0L;
2467 bzero(&lp, sizeof lp);
2468 bzero(ftfil, sizeof *ftfil);
2469
2470 FT_SLIST_INIT(&ftfil->defs);
2471 FT_SLIST_INIT(&ftfil->primitives);
2472
2473 lp.sym_ip_prot = ftsym_new(FT_PATH_SYM_IP_PROT);
2474 lp.sym_ip_tcp_port = ftsym_new(FT_PATH_SYM_TCP_PORT);
2475 #ifdef FT_PATH_SYM_ASN
2476 lp.sym_asn = ftsym_new(FT_PATH_SYM_ASN);
2477 #endif
2478 lp.sym_tag = ftsym_new(FT_PATH_SYM_TAG);
2479
2480 lp.fname = fname;
2481
2482 if ((fd = open(fname, O_RDONLY, 0)) < 0) {
2483 fterr_warn("open(%s)", fname);
2484 goto load_fil_out;
2485 }
2486
2487 if (fstat(fd, &sb) < 0) {
2488 fterr_warn("stat(%s)", fname);
2489 goto load_fil_out;
2490 }
2491
2492 /* allocate storage for file */
2493 if (!(buf = malloc(sb.st_size+1))) {
2494 fterr_warn("malloc()");
2495 goto load_fil_out;
2496 }
2497
2498 /* read in file */
2499 if (read(fd, buf, sb.st_size) != sb.st_size) {
2500 fterr_warnx("read(%s): short", fname);
2501 goto load_fil_out;
2502 }
2503
2504 /* null terminate file */
2505 buf[sb.st_size] = 0;
2506
2507 buf2 = buf;
2508
2509 for (;;) {
2510
2511 /* rip a line */
2512 for (;;) {
2513 c = strsep(&buf2, "\n");
2514 ++lp.lineno;
2515 if ((c && *c != 0) || (!c))
2516 break;
2517 }
2518
2519 /* no more lines */
2520 if (!c) {
2521 goto load_fil_done;
2522 }
2523
2524 /* do variable substitutions first */
2525 if (ftvar) {
2526 if (ftvar_evalstr(ftvar, c, sbuf, sizeof(sbuf)) < 0) {
2527 fterr_warnx("ftvar_evalstr(): failed");
2528 goto load_fil_done;
2529 }
2530 } else {
2531 strncpy(sbuf, c, sizeof(sbuf));
2532 sbuf[sizeof(sbuf)-1] = 0;
2533 }
2534
2535 lp.buf = sbuf;
2536
2537 /* first word */
2538 NEXT_WORD(&lp.buf, c);
2539
2540 /* whitespace only line */
2541 if (!c) {
2542 continue;
2543 }
2544
2545 /* comment line */
2546 if (c && *c == '#')
2547 continue;
2548
2549 for (jmp = pjump; jmp->name; ++jmp) {
2550
2551 found = 0;
2552
2553 if (((!jmp->state) || (jmp->state & lp.state))
2554 && (!strcasecmp(c, jmp->name))) {
2555
2556 found = 1;
2557
2558 if (jmp->func(&lp, ftfil))
2559 goto load_fil_out;
2560
2561 NEXT_WORD(&lp.buf, c);
2562
2563 if (c) {
2564 fterr_warnx("%s line %d: Unexpected \"%s\".", lp.fname, lp.lineno, c);
2565 goto load_fil_out;;
2566 }
2567
2568 break;
2569
2570 }
2571
2572 } /* test each word */
2573
2574 if (!found) {
2575 fterr_warnx("%s line %d: Unexpected \"%s\".", lp.fname, lp.lineno, c);
2576 goto load_fil_out;
2577 }
2578
2579 } /* more lines */
2580
2581 load_fil_done:
2582
2583 if (resolve_primitives(ftfil)) {
2584 fterr_warnx("resolve_primitives(): failed");
2585 goto load_fil_out;
2586 }
2587
2588 ret = 0;
2589
2590 load_fil_out:
2591
2592 if (fd != -1)
2593 close(fd);
2594
2595 if (buf)
2596 free(buf);
2597
2598 if (ret == -1)
2599 ftfil_free(ftfil);
2600
2601 if (lp.sym_ip_prot)
2602 ftsym_free(lp.sym_ip_prot);
2603
2604 if (lp.sym_ip_tcp_port)
2605 ftsym_free(lp.sym_ip_tcp_port);
2606
2607 #ifdef FT_PATH_SYM_ASN
2608 if (lp.sym_asn)
2609 ftsym_free(lp.sym_asn);
2610 #endif
2611
2612 if (lp.sym_tag)
2613 ftsym_free(lp.sym_tag);
2614
2615 return ret;
2616
2617 } /* ftfil_load */
2618
ftfil_free(struct ftfil * ftfil)2619 void ftfil_free(struct ftfil *ftfil)
2620 {
2621 struct ftfil_primitive *ftfp;
2622 struct ftfil_lookup_ip_address *ftflipa;
2623 struct ftfil_lookup_ip_prefix *ftflippr;
2624 struct ftfil_lookup_ip_mask *ftflipm;
2625 struct ftfil_lookup_counter *ftflc;
2626 struct ftfil_lookup_counter_rec *ftflcr;
2627 struct ftfil_lookup_tag *ftflt;
2628 struct ftfil_lookup_tag_mask *ftfltm;
2629 struct ftfil_lookup_tag_mask_rec *ftfltmr;
2630 struct ftfil_lookup_ip_mask_rec *ftflipmr;
2631 struct ftfil_def *ftfd;
2632 struct ftfil_match *ftm;
2633 struct ftfil_match_item *ftmi;
2634 struct ftfil_lookup_time *ftfltme;
2635 struct ftfil_lookup_time_rec *ftfltmer;
2636 struct ftfil_lookup_double *ftfld;
2637 struct ftfil_lookup_double_rec *ftfldr;
2638
2639 /*
2640 * walk the primitive list, free each entry
2641 */
2642
2643 while (!FT_SLIST_EMPTY(&ftfil->primitives)) {
2644
2645 ftfp = FT_SLIST_FIRST(&ftfil->primitives);
2646
2647 switch (ftfp->type) {
2648
2649 case FT_FIL_PRIMITIVE_TYPE_IP_PREFIX:
2650 ftflippr = ftfp->lookup;
2651 if (ftflippr->init) {
2652 rhead = ftflippr->rhead;
2653 rhead->rnh_walktree(rhead, walk_free, 0);
2654 }
2655 break;
2656
2657 case FT_FIL_PRIMITIVE_TYPE_IP_ADDRESS:
2658 ftflipa = ftfp->lookup;
2659 if (ftflipa->init)
2660 ftchash_free(ftflipa->ftch);
2661 break;
2662
2663 case FT_FIL_PRIMITIVE_TYPE_IP_MASK:
2664 ftflipm = ftfp->lookup;
2665 while (!FT_STAILQ_EMPTY(&ftflipm->list)) {
2666 ftflipmr = FT_STAILQ_FIRST(&ftflipm->list);
2667 FT_STAILQ_REMOVE_HEAD(&ftflipm->list, chain);
2668 free(ftflipmr);
2669 }
2670 break;
2671
2672 case FT_FIL_PRIMITIVE_TYPE_COUNTER:
2673 case FT_FIL_PRIMITIVE_TYPE_TIME_DATE:
2674 ftflc = ftfp->lookup;
2675 while (!FT_STAILQ_EMPTY(&ftflc->list)) {
2676 ftflcr = FT_STAILQ_FIRST(&ftflc->list);
2677 FT_STAILQ_REMOVE_HEAD(&ftflc->list, chain);
2678 free(ftflcr);
2679 }
2680 break;
2681
2682 case FT_FIL_PRIMITIVE_TYPE_TAG:
2683 ftflt = ftfp->lookup;
2684 if (ftflt->init)
2685 ftchash_free(ftflt->ftch);
2686 break;
2687
2688 case FT_FIL_PRIMITIVE_TYPE_TAG_MASK:
2689 ftfltm = ftfp->lookup;
2690 while (!FT_STAILQ_EMPTY(&ftfltm->list)) {
2691 ftfltmr = FT_STAILQ_FIRST(&ftfltm->list);
2692 FT_STAILQ_REMOVE_HEAD(&ftfltm->list, chain);
2693 free(ftfltmr);
2694 }
2695 break;
2696
2697 case FT_FIL_PRIMITIVE_TYPE_TIME:
2698 ftfltme = ftfp->lookup;
2699 while (!FT_STAILQ_EMPTY(&ftfltme->list)) {
2700 ftfltmer = FT_STAILQ_FIRST(&ftfltme->list);
2701 FT_STAILQ_REMOVE_HEAD(&ftfltme->list, chain);
2702 free(ftfltmer);
2703 }
2704 break;
2705
2706 case FT_FIL_PRIMITIVE_TYPE_DOUBLE:
2707 ftfld = ftfp->lookup;
2708 while (!FT_STAILQ_EMPTY(&ftfld->list)) {
2709 ftfldr = FT_STAILQ_FIRST(&ftfld->list);
2710 FT_STAILQ_REMOVE_HEAD(&ftfld->list, chain);
2711 free(ftfldr);
2712 }
2713 break;
2714
2715 case FT_FIL_PRIMITIVE_TYPE_UNSET:
2716 case FT_FIL_PRIMITIVE_TYPE_AS:
2717 case FT_FIL_PRIMITIVE_TYPE_IP_PROTOCOL:
2718 case FT_FIL_PRIMITIVE_TYPE_IP_PORT:
2719 case FT_FIL_PRIMITIVE_TYPE_IP_PREFIX_LEN:
2720 case FT_FIL_PRIMITIVE_TYPE_IP_TOS:
2721 case FT_FIL_PRIMITIVE_TYPE_IP_TCP_FLAGS:
2722 case FT_FIL_PRIMITIVE_TYPE_IF_INDEX:
2723 case FT_FIL_PRIMITIVE_TYPE_ENGINE:
2724 case FT_FIL_PRIMITIVE_TYPE_RATE:
2725 /* no work */
2726 break;
2727
2728 } /* ftfp->type */
2729
2730 FT_SLIST_REMOVE_HEAD(&ftfil->primitives, chain);
2731
2732 if (ftfp->name)
2733 free(ftfp->name);
2734 free(ftfp->lookup);
2735 free(ftfp);
2736
2737 } /* !ftfil->primitives list empty */
2738
2739 /*
2740 * walk the definitions list, free each entry
2741 */
2742
2743 while (!FT_SLIST_EMPTY(&ftfil->defs)) {
2744
2745 ftfd = FT_SLIST_FIRST(&ftfil->defs);
2746
2747 while (!FT_STAILQ_EMPTY(&ftfd->matches)) {
2748
2749 ftm = FT_STAILQ_FIRST(&ftfd->matches);
2750
2751 while (!FT_STAILQ_EMPTY(&ftm->items)) {
2752
2753 ftmi = FT_STAILQ_FIRST(&ftm->items);
2754
2755 if (ftmi->tmp_primitive)
2756 free(ftmi->tmp_primitive);
2757
2758 if (ftmi->tmp_type)
2759 free(ftmi->tmp_type);
2760
2761 FT_STAILQ_REMOVE_HEAD(&ftm->items, chain);
2762 free(ftmi);
2763
2764 } /* !ftm->items list empty */
2765
2766 FT_STAILQ_REMOVE_HEAD(&ftfd->matches, chain);
2767 free(ftm);
2768
2769 } /* !ftfd->matches list empty */
2770
2771 FT_SLIST_REMOVE_HEAD(&ftfil->defs, chain);
2772
2773 if (ftfd->name)
2774 free(ftfd->name);
2775 free(ftfd);
2776
2777 } /* !ftfil->defs list empty */
2778
2779 } /* ftfil_free */
2780
ftfil_def_find(struct ftfil * ftfil,const char * name)2781 struct ftfil_def *ftfil_def_find(struct ftfil *ftfil, const char *name)
2782 {
2783 struct ftfil_def *ftfd;
2784 int found;
2785
2786 found = 0;
2787
2788 FT_SLIST_FOREACH(ftfd, &ftfil->defs, chain) {
2789
2790 if (!strcasecmp(name, ftfd->name))
2791 return ftfd;
2792
2793 } /* ftfd */
2794
2795 return (struct ftfil_def*)0L;
2796
2797 } /* ftfil_def_find */
2798
2799 /*
2800 * function: ftfil_def_eval
2801 *
2802 * Evaluate a flow with a filter definition
2803 *
2804 * returns: FT_FIL_MODE_PERMIT or FT_FIL_MODE_DENY
2805 * <0 fail
2806 */
ftfil_def_eval(struct ftfil_def * active_def,char * rec,struct fts3rec_offsets * fo)2807 int ftfil_def_eval(struct ftfil_def *active_def,
2808 char *rec, struct fts3rec_offsets *fo)
2809 {
2810 struct ftfil_match_item *ftmi;
2811 struct ftfil_match *ftm;
2812 int done;
2813
2814 /* for each match (OR path) */
2815 FT_STAILQ_FOREACH(ftm, &active_def->matches, chain) {
2816
2817 done = 1;
2818
2819 /* for each matchi (AND path) */
2820 FT_STAILQ_FOREACH(ftmi, &ftm->items, chain) {
2821
2822 if (ftmi->eval(ftmi->lookup, rec, fo) == FT_FIL_MODE_DENY) {
2823 done = 0;
2824 break;
2825 }
2826
2827 } /* matchi */
2828
2829 if (done)
2830 return active_def->invert ? FT_FIL_MODE_DENY : FT_FIL_MODE_PERMIT;
2831
2832 } /* match */
2833
2834 return active_def->invert ? FT_FIL_MODE_PERMIT : FT_FIL_MODE_DENY;
2835
2836 } /* ftfil_def_eval */
2837
2838 /*
2839 * function: ftfil_test_xfields
2840 *
2841 * Check if fields in current flow are valid for a filter -- ie
2842 * the filter does not reference a field not contained in the flow.
2843 *
2844 * returns: 0 okay
2845 * 1 fail
2846 */
ftfil_def_test_xfields(struct ftfil_def * active_def,uint64_t test)2847 int ftfil_def_test_xfields(struct ftfil_def *active_def, uint64_t test)
2848 {
2849
2850 if ((active_def->xfields & test) != active_def->xfields)
2851 return 1;
2852 else
2853 return 0;
2854
2855 } /* ftfil_def_test_xfields */
2856
2857 /*
2858 *************************************************************************
2859 parse_definition_*
2860 *************************************************************************
2861 */
2862
2863 /*
2864 * function: parse_definition
2865 *
2866 * process the 'filter-definition' line. Each primitive has a unique name
2867 * which is added to the ftfil->definitions linked list. The current
2868 * definition is updated in lp. Filter definitions reference filter
2869 * primitives
2870 *
2871 * returns: 0 ok
2872 * <0 fail
2873 */
parse_definition(struct line_parser * lp,struct ftfil * ftfil)2874 int parse_definition(struct line_parser *lp, struct ftfil *ftfil)
2875 {
2876 char *c;
2877 struct ftfil_def *ftfd;
2878
2879 NEXT_WORD(&lp->buf, c);
2880
2881 if (!c) {
2882 fterr_warnx("%s line %d: Expecting name.", lp->fname, lp->lineno);
2883 return -1;
2884 }
2885
2886 /* check if it exists */
2887 FT_SLIST_FOREACH(ftfd, &ftfil->defs, chain) {
2888
2889 if (!strcasecmp(c, ftfd->name)) {
2890 fterr_warnx("%s line %d: Name (%s) previously defined.", lp->fname,
2891 lp->lineno, c);
2892 return -1;
2893 }
2894
2895 }
2896
2897 /* no, add a new entry to the list */
2898 if (!(ftfd = (struct ftfil_def*)malloc(sizeof
2899 (struct ftfil_def)))) {
2900 fterr_warn("malloc()");
2901 return -1;
2902 }
2903
2904 bzero(ftfd, sizeof *ftfd);
2905 FT_STAILQ_INIT(&ftfd->matches);
2906
2907 if (!(ftfd->name = (char*)malloc(strlen(c)+1))) {
2908 fterr_warn("malloc()");
2909 free(ftfd);
2910 return -1;
2911 }
2912
2913 strcpy(ftfd->name, c);
2914
2915 FT_SLIST_INSERT_HEAD(&ftfil->defs, ftfd, chain);
2916
2917 lp->state = PARSE_STATE_DEFINITION;
2918 lp->cur_def = ftfd;
2919 lp->cur_def_match = (void*)0L;
2920
2921 return 0;
2922
2923 } /* parse_definition */
2924
2925 /*
2926 * function: parse_definition_match
2927 *
2928 * process the definition match lines
2929 *
2930 * _must_ call resolve_primitives when done with all lines and before
2931 * destroying the file parser buffer.
2932 *
2933 * returns: 0 ok
2934 * <0 fail
2935 */
parse_definition_match(struct line_parser * lp,struct ftfil * ftfil)2936 static int parse_definition_match(struct line_parser *lp, struct ftfil *ftfil)
2937 {
2938 struct ftfil_match_item *ftmi;
2939 struct ftfil_match *ftm;
2940 char *c;
2941
2942 if (!lp->cur_def) {
2943 fterr_warnx("%s line %d: Not in filter-definition mode.", lp->fname,
2944 lp->lineno);
2945 return -1;
2946 }
2947
2948 NEXT_WORD(&lp->buf, c);
2949
2950 if (!c) {
2951 fterr_warnx("%s line %d: Expecting match type.", lp->fname,
2952 lp->lineno);
2953 return -1;
2954 }
2955
2956 NEXT_WORD(&lp->buf, lp->word);
2957
2958 if (!lp->word) {
2959 fterr_warnx("%s line %d: Expecting match primitive.", lp->fname,
2960 lp->lineno);
2961 return -1;
2962 }
2963
2964 /*
2965 * if cur_match is not set, allocate a new match. This is either the
2966 * first match line or a match after an or statement (OR path)
2967 */
2968
2969 if (!lp->cur_def_match) {
2970
2971 if (!(ftm = (struct ftfil_match*)malloc(sizeof *ftm))) {
2972 fterr_warn("malloc()");
2973 return -1;
2974 }
2975
2976 bzero(ftm, sizeof *ftm);
2977 FT_STAILQ_INIT(&ftm->items);
2978
2979 lp->cur_def_match = ftm;
2980
2981 FT_STAILQ_INSERT_TAIL(&lp->cur_def->matches, ftm, chain);
2982
2983 }
2984
2985 /* add this match line to the current items list (AND path) */
2986 if (!(ftmi = (struct ftfil_match_item*)malloc(sizeof *ftmi))) {
2987 fterr_warn("malloc()");
2988 if (!lp->cur_def_match)
2989 free(ftm);
2990 /* the potential ftm allocation will get cleaned up in ftfil_free() */
2991 return -1;
2992 }
2993
2994 bzero(ftmi, sizeof *ftmi);
2995
2996 if (!(ftmi->tmp_type = malloc(strlen(c)+1))) {
2997 if (!lp->cur_def_match)
2998 free(ftm);
2999 free(ftmi);
3000 fterr_warn("malloc()");
3001 return -1;
3002 }
3003 strcpy(ftmi->tmp_type, c);
3004
3005 if (!(ftmi->tmp_primitive = malloc(strlen(lp->word)+1))) {
3006 if (!lp->cur_def_match)
3007 free(ftm);
3008 free(ftmi->tmp_type);
3009 free(ftmi);
3010 fterr_warn("malloc()");
3011 return -1;
3012 }
3013 strcpy(ftmi->tmp_primitive, lp->word);
3014
3015 FT_STAILQ_INSERT_TAIL(&lp->cur_def_match->items, ftmi, chain);
3016
3017 return 0;
3018
3019 } /* parse_definition_match */
3020
3021 /*
3022 * function: parse_definition_invert
3023 *
3024 * process the definition invert
3025 *
3026 * returns: 0 ok
3027 * <0 fail
3028 */
parse_definition_invert(struct line_parser * lp,struct ftfil * ftfil)3029 static int parse_definition_invert(struct line_parser *lp, struct ftfil *ftfil)
3030 {
3031
3032 if (!lp->cur_def) {
3033 fterr_warnx("%s line %d: Not in filter-definition mode.", lp->fname,
3034 lp->lineno);
3035 return -1;
3036 }
3037
3038 lp->cur_def->invert = 1;
3039
3040 return 0;
3041
3042 } /* parse_definition_invert */
3043
3044 /*
3045 * function: resolve_primitives
3046 *
3047 * resolve the dangling pointers to primitives in definitions --
3048 * allows definitions to be defined before primitives.
3049 *
3050 * _must_ be called after work done by parse_definition_match
3051 *
3052 * returns: 0 ok
3053 * <0 fail
3054 */
resolve_primitives(struct ftfil * ftfil)3055 static int resolve_primitives(struct ftfil *ftfil)
3056 {
3057 struct ftfil_match_item *ftmi;
3058 struct ftfil_match *ftm;
3059 struct ftfil_primitive *ftfp;
3060 struct ftfil_def *ftfd;
3061 int type, found, valid;
3062 void *eval;
3063
3064 /* foreach definition */
3065 FT_SLIST_FOREACH(ftfd, &ftfil->defs, chain) {
3066
3067 /* foreach match line in the definition */
3068 FT_STAILQ_FOREACH(ftm, &ftfd->matches, chain) {
3069
3070 /* for each match item in the match line */
3071 FT_STAILQ_FOREACH(ftmi, &ftm->items, chain) {
3072
3073 /* Find the primitive */
3074 found = 0;
3075 FT_SLIST_FOREACH(ftfp, &ftfil->primitives, chain) {
3076
3077 if (!strcasecmp(ftmi->tmp_primitive, ftfp->name)) {
3078 found = 1;
3079 break;
3080 } /* if */
3081
3082 } /* ftfp */
3083
3084 if (!found) {
3085 fterr_warnx(
3086 "Unable to resolve primitive \"%s\" in filter-definition \"%s\".",
3087 ftmi->tmp_primitive, ftfd->name);
3088 return -1;
3089 }
3090
3091 /*
3092 * primitive found, set it and make rest of checks
3093 */
3094
3095 /* match on what? */
3096 if (!strcasecmp(ftmi->tmp_type, "src-as")) {
3097 type = FT_FIL_DEFINITION_MATCH_SRC_AS;
3098 eval = eval_match_src_as;
3099 ftfd->xfields |= FT_XFIELD_SRC_AS;
3100 } else if (!strcasecmp(ftmi->tmp_type, "source-as")) {
3101 type = FT_FIL_DEFINITION_MATCH_SRC_AS;
3102 eval = eval_match_src_as;
3103 ftfd->xfields |= FT_XFIELD_SRC_AS;
3104 } else if (!strcasecmp(ftmi->tmp_type, "dst-as")) {
3105 type = FT_FIL_DEFINITION_MATCH_DST_AS;
3106 eval = eval_match_dst_as;
3107 ftfd->xfields |= FT_XFIELD_DST_AS;
3108 } else if (!strcasecmp(ftmi->tmp_type, "destination-as")) {
3109 type = FT_FIL_DEFINITION_MATCH_DST_AS;
3110 eval = eval_match_dst_as;
3111 ftfd->xfields |= FT_XFIELD_DST_AS;
3112 } else if (!strcasecmp(ftmi->tmp_type, "ip-protocol")) {
3113 type = FT_FIL_DEFINITION_MATCH_IP_PROTOCOL;
3114 eval = eval_match_ip_prot;
3115 ftfd->xfields |= FT_XFIELD_PROT;
3116 } else if (!strcasecmp(ftmi->tmp_type, "src-ip-addr-prefix-len")) {
3117 type = FT_FIL_DEFINITION_MATCH_IP_SRC_PREFIX_LEN;
3118 eval = eval_match_ip_src_prefix_len;
3119 ftfd->xfields |= FT_XFIELD_SRC_MASK;
3120 } else if (!strcasecmp(ftmi->tmp_type, "ip-source-address-prefix-len")) {
3121 type = FT_FIL_DEFINITION_MATCH_IP_SRC_PREFIX_LEN;
3122 eval = eval_match_ip_src_prefix_len;
3123 ftfd->xfields |= FT_XFIELD_SRC_MASK;
3124 } else if (!strcasecmp(ftmi->tmp_type, "dst-ip-addr-prefix-len")) {
3125 type = FT_FIL_DEFINITION_MATCH_IP_DST_PREFIX_LEN;
3126 eval = eval_match_ip_dst_prefix_len;
3127 ftfd->xfields |= FT_XFIELD_DST_MASK;
3128 } else if (!strcasecmp(ftmi->tmp_type, "ip-destination-address-prefix-len")) {
3129 type = FT_FIL_DEFINITION_MATCH_IP_DST_PREFIX_LEN;
3130 eval = eval_match_ip_dst_prefix_len;
3131 ftfd->xfields |= FT_XFIELD_DST_MASK;
3132 } else if (!strcasecmp(ftmi->tmp_type, "ip-tos")) {
3133 type = FT_FIL_DEFINITION_MATCH_IP_TOS;
3134 eval = eval_match_ip_tos;
3135 ftfd->xfields |= FT_XFIELD_TOS;
3136 } else if (!strcasecmp(ftmi->tmp_type, "ip-marked-tos")) {
3137 type = FT_FIL_DEFINITION_MATCH_IP_MARKED_TOS;
3138 eval = eval_match_ip_marked_tos;
3139 ftfd->xfields |= FT_XFIELD_MARKED_TOS;
3140 } else if (!strcasecmp(ftmi->tmp_type, "ip-tcp-flags")) {
3141 type = FT_FIL_DEFINITION_MATCH_IP_TCP_FLAGS;
3142 eval = eval_match_ip_tcp_flags;
3143 ftfd->xfields |= FT_XFIELD_TCP_FLAGS;
3144 } else if (!strcasecmp(ftmi->tmp_type, "src-ip-port")) {
3145 type = FT_FIL_DEFINITION_MATCH_IP_SRC_PORT;
3146 eval = eval_match_ip_src_port;
3147 ftfd->xfields |= FT_XFIELD_SRCPORT;
3148 } else if (!strcasecmp(ftmi->tmp_type, "ip-source-port")) {
3149 type = FT_FIL_DEFINITION_MATCH_IP_SRC_PORT;
3150 eval = eval_match_ip_src_port;
3151 ftfd->xfields |= FT_XFIELD_SRCPORT;
3152 } else if (!strcasecmp(ftmi->tmp_type, "dst-ip-port")) {
3153 type = FT_FIL_DEFINITION_MATCH_IP_DST_PORT;
3154 eval = eval_match_ip_dst_port;
3155 ftfd->xfields |= FT_XFIELD_DSTPORT;
3156 } else if (!strcasecmp(ftmi->tmp_type, "ip-destination-port")) {
3157 type = FT_FIL_DEFINITION_MATCH_IP_DST_PORT;
3158 eval = eval_match_ip_dst_port;
3159 ftfd->xfields |= FT_XFIELD_DSTPORT;
3160 } else if (!strcasecmp(ftmi->tmp_type, "src-ifindex")) {
3161 type = FT_FIL_DEFINITION_MATCH_INPUT_IF;
3162 eval = eval_match_src_if_index;
3163 ftfd->xfields |= FT_XFIELD_INPUT;
3164 } else if (!strcasecmp(ftmi->tmp_type, "input-interface")) {
3165 type = FT_FIL_DEFINITION_MATCH_INPUT_IF;
3166 eval = eval_match_src_if_index;
3167 ftfd->xfields |= FT_XFIELD_INPUT;
3168 } else if (!strcasecmp(ftmi->tmp_type, "dst-ifindex")) {
3169 type = FT_FIL_DEFINITION_MATCH_OUTPUT_IF;
3170 eval = eval_match_dst_if_index;
3171 ftfd->xfields |= FT_XFIELD_OUTPUT;
3172 } else if (!strcasecmp(ftmi->tmp_type, "output-interface")) {
3173 type = FT_FIL_DEFINITION_MATCH_OUTPUT_IF;
3174 eval = eval_match_dst_if_index;
3175 ftfd->xfields |= FT_XFIELD_OUTPUT;
3176 } else if (!strcasecmp(ftmi->tmp_type, "engine-id")) {
3177 type = FT_FIL_DEFINITION_MATCH_ENGINE_ID;
3178 eval = eval_match_engine_id;
3179 ftfd->xfields |= FT_XFIELD_ENGINE_ID;
3180 } else if (!strcasecmp(ftmi->tmp_type, "engine-type")) {
3181 type = FT_FIL_DEFINITION_MATCH_ENGINE_TYPE;
3182 eval = eval_match_engine_type;
3183 ftfd->xfields |= FT_XFIELD_ENGINE_TYPE;
3184 } else if (!strcasecmp(ftmi->tmp_type, "flows")) {
3185 type = FT_FIL_DEFINITION_MATCH_FLOWS;
3186 eval = eval_match_flows;
3187 ftfd->xfields |= FT_XFIELD_DFLOWS;
3188 } else if (!strcasecmp(ftmi->tmp_type, "octets")) {
3189 type = FT_FIL_DEFINITION_MATCH_OCTETS;
3190 eval = eval_match_octets;
3191 ftfd->xfields |= FT_XFIELD_DOCTETS;
3192 } else if (!strcasecmp(ftmi->tmp_type, "packets")) {
3193 type = FT_FIL_DEFINITION_MATCH_PACKETS;
3194 eval = eval_match_packets;
3195 ftfd->xfields |= FT_XFIELD_DPKTS;
3196 } else if (!strcasecmp(ftmi->tmp_type, "extra-packets")) {
3197 type = FT_FIL_DEFINITION_MATCH_XTRA_PACKETS;
3198 eval = eval_match_xtra_packets;
3199 ftfd->xfields |= FT_XFIELD_EXTRA_PKTS;
3200 } else if (!strcasecmp(ftmi->tmp_type, "duration")) {
3201 type = FT_FIL_DEFINITION_MATCH_DURATION;
3202 eval = eval_match_duration;
3203 ftfd->xfields |= (FT_XFIELD_FIRST|FT_XFIELD_LAST);
3204 } else if (!strcasecmp(ftmi->tmp_type, "start-time")) {
3205 type = FT_FIL_DEFINITION_MATCH_START_TIME;
3206 if (ftfp->type == FT_FIL_PRIMITIVE_TYPE_TIME_DATE)
3207 eval = eval_match_start_time_date;
3208 else if (ftfp->type == FT_FIL_PRIMITIVE_TYPE_TIME)
3209 eval = eval_match_start_time;
3210 ftfd->xfields |= (FT_XFIELD_FIRST|FT_XFIELD_UNIX_SECS|
3211 FT_XFIELD_UNIX_NSECS|FT_XFIELD_SYSUPTIME);
3212 } else if (!strcasecmp(ftmi->tmp_type, "end-time")) {
3213 type = FT_FIL_DEFINITION_MATCH_END_TIME;
3214 if (ftfp->type == FT_FIL_PRIMITIVE_TYPE_TIME_DATE)
3215 eval = eval_match_end_time_date;
3216 else if (ftfp->type == FT_FIL_PRIMITIVE_TYPE_TIME)
3217 eval = eval_match_end_time;
3218 ftfd->xfields |= (FT_XFIELD_LAST|FT_XFIELD_UNIX_SECS|
3219 FT_XFIELD_UNIX_NSECS|FT_XFIELD_SYSUPTIME);
3220 } else if (!strcasecmp(ftmi->tmp_type, "src-tag")) {
3221 type = FT_FIL_DEFINITION_MATCH_SRC_TAG;
3222 ftfd->xfields |= FT_XFIELD_SRC_TAG;
3223 if (ftfp->type == FT_FIL_PRIMITIVE_TYPE_TAG_MASK)
3224 eval = eval_match_src_tag_l;
3225 else if (ftfp->type == FT_FIL_PRIMITIVE_TYPE_TAG)
3226 eval = eval_match_src_tag_h;
3227 } else if (!strcasecmp(ftmi->tmp_type, "source-tag")) {
3228 type = FT_FIL_DEFINITION_MATCH_SRC_TAG;
3229 ftfd->xfields |= FT_XFIELD_SRC_TAG;
3230 if (ftfp->type == FT_FIL_PRIMITIVE_TYPE_TAG_MASK)
3231 eval = eval_match_src_tag_l;
3232 else if (ftfp->type == FT_FIL_PRIMITIVE_TYPE_TAG)
3233 eval = eval_match_src_tag_h;
3234 } else if (!strcasecmp(ftmi->tmp_type, "dst-tag")) {
3235 type = FT_FIL_DEFINITION_MATCH_SRC_TAG;
3236 ftfd->xfields |= FT_XFIELD_DST_TAG;
3237 if (ftfp->type == FT_FIL_PRIMITIVE_TYPE_TAG_MASK)
3238 eval = eval_match_dst_tag_l;
3239 else if (ftfp->type == FT_FIL_PRIMITIVE_TYPE_TAG)
3240 eval = eval_match_dst_tag_h;
3241 } else if (!strcasecmp(ftmi->tmp_type, "destination-tag")) {
3242 type = FT_FIL_DEFINITION_MATCH_SRC_TAG;
3243 ftfd->xfields |= FT_XFIELD_DST_TAG;
3244 if (ftfp->type == FT_FIL_PRIMITIVE_TYPE_TAG_MASK)
3245 eval = eval_match_dst_tag_l;
3246 else if (ftfp->type == FT_FIL_PRIMITIVE_TYPE_TAG)
3247 eval = eval_match_dst_tag_h;
3248 } else if (!strcasecmp(ftmi->tmp_type, "nexthop-ip-addr")) {
3249 type = FT_FIL_DEFINITION_MATCH_IP_NEXT_HOP_ADDR;
3250 ftfd->xfields |= FT_XFIELD_NEXTHOP;
3251 if (ftfp->type == FT_FIL_PRIMITIVE_TYPE_IP_MASK)
3252 eval = eval_match_ip_nexthop_addr_l;
3253 else if (ftfp->type == FT_FIL_PRIMITIVE_TYPE_IP_ADDRESS)
3254 eval = eval_match_ip_nexthop_addr_h;
3255 else if (ftfp->type == FT_FIL_PRIMITIVE_TYPE_IP_PREFIX)
3256 eval = eval_match_ip_nexthop_addr_r;
3257 } else if (!strcasecmp(ftmi->tmp_type, "ip-nexthop-address")) {
3258 type = FT_FIL_DEFINITION_MATCH_IP_NEXT_HOP_ADDR;
3259 ftfd->xfields |= FT_XFIELD_NEXTHOP;
3260 if (ftfp->type == FT_FIL_PRIMITIVE_TYPE_IP_MASK)
3261 eval = eval_match_ip_nexthop_addr_l;
3262 else if (ftfp->type == FT_FIL_PRIMITIVE_TYPE_IP_ADDRESS)
3263 eval = eval_match_ip_nexthop_addr_h;
3264 else if (ftfp->type == FT_FIL_PRIMITIVE_TYPE_IP_PREFIX)
3265 eval = eval_match_ip_nexthop_addr_r;
3266 } else if (!strcasecmp(ftmi->tmp_type, "shortcut-ip-addr")) {
3267 type = FT_FIL_DEFINITION_MATCH_IP_SC_ADDR;
3268 ftfd->xfields |= FT_XFIELD_ROUTER_SC;
3269 if (ftfp->type == FT_FIL_PRIMITIVE_TYPE_IP_MASK)
3270 eval = eval_match_ip_sc_addr_l;
3271 else if (ftfp->type == FT_FIL_PRIMITIVE_TYPE_IP_ADDRESS)
3272 eval = eval_match_ip_sc_addr_h;
3273 else if (ftfp->type == FT_FIL_PRIMITIVE_TYPE_IP_PREFIX)
3274 eval = eval_match_ip_sc_addr_r;
3275 } else if (!strcasecmp(ftmi->tmp_type, "ip-shortcut-address")) {
3276 type = FT_FIL_DEFINITION_MATCH_IP_SC_ADDR;
3277 ftfd->xfields |= FT_XFIELD_ROUTER_SC;
3278 if (ftfp->type == FT_FIL_PRIMITIVE_TYPE_IP_MASK)
3279 eval = eval_match_ip_sc_addr_l;
3280 else if (ftfp->type == FT_FIL_PRIMITIVE_TYPE_IP_ADDRESS)
3281 eval = eval_match_ip_sc_addr_h;
3282 else if (ftfp->type == FT_FIL_PRIMITIVE_TYPE_IP_PREFIX)
3283 eval = eval_match_ip_sc_addr_r;
3284 } else if (!strcasecmp(ftmi->tmp_type, "src-ip-addr")) {
3285 type = FT_FIL_DEFINITION_MATCH_IP_SRC_ADDR;
3286 ftfd->xfields |= FT_XFIELD_SRCADDR;
3287 if (ftfp->type == FT_FIL_PRIMITIVE_TYPE_IP_MASK)
3288 eval = eval_match_ip_src_addr_l;
3289 else if (ftfp->type == FT_FIL_PRIMITIVE_TYPE_IP_ADDRESS)
3290 eval = eval_match_ip_src_addr_h;
3291 else if (ftfp->type == FT_FIL_PRIMITIVE_TYPE_IP_PREFIX)
3292 eval = eval_match_ip_src_addr_r;
3293 } else if (!strcasecmp(ftmi->tmp_type, "ip-source-address")) {
3294 type = FT_FIL_DEFINITION_MATCH_IP_SRC_ADDR;
3295 ftfd->xfields |= FT_XFIELD_SRCADDR;
3296 if (ftfp->type == FT_FIL_PRIMITIVE_TYPE_IP_MASK)
3297 eval = eval_match_ip_src_addr_l;
3298 else if (ftfp->type == FT_FIL_PRIMITIVE_TYPE_IP_ADDRESS)
3299 eval = eval_match_ip_src_addr_h;
3300 else if (ftfp->type == FT_FIL_PRIMITIVE_TYPE_IP_PREFIX)
3301 eval = eval_match_ip_src_addr_r;
3302 } else if (!strcasecmp(ftmi->tmp_type, "dst-ip-addr")) {
3303 type = FT_FIL_DEFINITION_MATCH_IP_DST_ADDR;
3304 ftfd->xfields |= FT_XFIELD_DSTADDR;
3305 if (ftfp->type == FT_FIL_PRIMITIVE_TYPE_IP_MASK)
3306 eval = eval_match_ip_dst_addr_l;
3307 else if (ftfp->type == FT_FIL_PRIMITIVE_TYPE_IP_ADDRESS)
3308 eval = eval_match_ip_dst_addr_h;
3309 else if (ftfp->type == FT_FIL_PRIMITIVE_TYPE_IP_PREFIX)
3310 eval = eval_match_ip_dst_addr_r;
3311 } else if (!strcasecmp(ftmi->tmp_type, "ip-destination-address")) {
3312 type = FT_FIL_DEFINITION_MATCH_IP_DST_ADDR;
3313 ftfd->xfields |= FT_XFIELD_DSTADDR;
3314 if (ftfp->type == FT_FIL_PRIMITIVE_TYPE_IP_MASK)
3315 eval = eval_match_ip_dst_addr_l;
3316 else if (ftfp->type == FT_FIL_PRIMITIVE_TYPE_IP_ADDRESS)
3317 eval = eval_match_ip_dst_addr_h;
3318 else if (ftfp->type == FT_FIL_PRIMITIVE_TYPE_IP_PREFIX)
3319 eval = eval_match_ip_dst_addr_r;
3320 } else if (!strcasecmp(ftmi->tmp_type, "exporter-ip-addr")) {
3321 type = FT_FIL_DEFINITION_MATCH_IP_EXPORTER_ADDR;
3322 ftfd->xfields |= FT_XFIELD_EXADDR;
3323 if (ftfp->type == FT_FIL_PRIMITIVE_TYPE_IP_MASK)
3324 eval = eval_match_ip_exporter_addr_l;
3325 else if (ftfp->type == FT_FIL_PRIMITIVE_TYPE_IP_ADDRESS)
3326 eval = eval_match_ip_exporter_addr_h;
3327 else if (ftfp->type == FT_FIL_PRIMITIVE_TYPE_IP_PREFIX)
3328 eval = eval_match_ip_exporter_addr_r;
3329 } else if (!strcasecmp(ftmi->tmp_type, "ip-exporter-address")) {
3330 type = FT_FIL_DEFINITION_MATCH_IP_EXPORTER_ADDR;
3331 ftfd->xfields |= FT_XFIELD_EXADDR;
3332 if (ftfp->type == FT_FIL_PRIMITIVE_TYPE_IP_MASK)
3333 eval = eval_match_ip_exporter_addr_l;
3334 else if (ftfp->type == FT_FIL_PRIMITIVE_TYPE_IP_ADDRESS)
3335 eval = eval_match_ip_exporter_addr_h;
3336 else if (ftfp->type == FT_FIL_PRIMITIVE_TYPE_IP_PREFIX)
3337 eval = eval_match_ip_exporter_addr_r;
3338 } else if (!strcasecmp(ftmi->tmp_type, "bps")) {
3339 type = FT_FIL_DEFINITION_MATCH_BPS;
3340 eval = eval_match_bps;
3341 ftfd->xfields |= FT_XFIELD_DOCTETS|FT_XFIELD_LAST|FT_XFIELD_FIRST;
3342 } else if (!strcasecmp(ftmi->tmp_type, "pps")) {
3343 type = FT_FIL_DEFINITION_MATCH_PPS;
3344 eval = eval_match_pps;
3345 ftfd->xfields |= FT_XFIELD_DPKTS|FT_XFIELD_LAST|FT_XFIELD_FIRST;
3346 } else if (!strcasecmp(ftmi->tmp_type, "random-sample")) {
3347 type = FT_FIL_DEFINITION_MATCH_RANDOM_SAMPLE;
3348 eval = eval_match_random_sample;
3349 } else {
3350 fterr_warnx(
3351 "Unknown match criteria \"%s\" in filter-definition \"%s\".",
3352 ftmi->tmp_type, ftfd->name);
3353 return -1;
3354 }
3355
3356 /*
3357 * the match type must be valid for the primitive
3358 */
3359
3360 valid = 0;
3361
3362 switch (ftfp->type) {
3363
3364 case FT_FIL_PRIMITIVE_TYPE_AS:
3365 if ((type == FT_FIL_DEFINITION_MATCH_SRC_AS) ||
3366 (type == FT_FIL_DEFINITION_MATCH_DST_AS))
3367 valid = 1;
3368 break;
3369
3370 case FT_FIL_PRIMITIVE_TYPE_IP_PROTOCOL:
3371 if (type == FT_FIL_DEFINITION_MATCH_IP_PROTOCOL)
3372 valid = 1;
3373 break;
3374
3375 case FT_FIL_PRIMITIVE_TYPE_IP_MASK:
3376 if ((type == FT_FIL_DEFINITION_MATCH_IP_NEXT_HOP_ADDR) ||
3377 (type == FT_FIL_DEFINITION_MATCH_IP_SRC_ADDR) ||
3378 (type == FT_FIL_DEFINITION_MATCH_IP_DST_ADDR) ||
3379 (type == FT_FIL_DEFINITION_MATCH_IP_EXPORTER_ADDR) ||
3380 (type == FT_FIL_DEFINITION_MATCH_IP_SC_ADDR))
3381 valid = 1;
3382 break;
3383
3384 case FT_FIL_PRIMITIVE_TYPE_IP_ADDRESS:
3385 if ((type == FT_FIL_DEFINITION_MATCH_IP_NEXT_HOP_ADDR) ||
3386 (type == FT_FIL_DEFINITION_MATCH_IP_SRC_ADDR) ||
3387 (type == FT_FIL_DEFINITION_MATCH_IP_DST_ADDR) ||
3388 (type == FT_FIL_DEFINITION_MATCH_IP_EXPORTER_ADDR) ||
3389 (type == FT_FIL_DEFINITION_MATCH_IP_SC_ADDR))
3390 valid = 1;
3391 break;
3392
3393 case FT_FIL_PRIMITIVE_TYPE_IP_PREFIX:
3394 if ((type == FT_FIL_DEFINITION_MATCH_IP_NEXT_HOP_ADDR) ||
3395 (type == FT_FIL_DEFINITION_MATCH_IP_SRC_ADDR) ||
3396 (type == FT_FIL_DEFINITION_MATCH_IP_DST_ADDR) ||
3397 (type == FT_FIL_DEFINITION_MATCH_IP_EXPORTER_ADDR) ||
3398 (type == FT_FIL_DEFINITION_MATCH_IP_SC_ADDR))
3399 valid = 1;
3400 break;
3401
3402
3403 case FT_FIL_PRIMITIVE_TYPE_IP_PORT:
3404 if ((type == FT_FIL_DEFINITION_MATCH_IP_SRC_PORT) ||
3405 (type == FT_FIL_DEFINITION_MATCH_IP_DST_PORT))
3406 valid = 1;
3407 break;
3408
3409 case FT_FIL_PRIMITIVE_TYPE_IP_PREFIX_LEN:
3410 if ((type == FT_FIL_DEFINITION_MATCH_IP_SRC_PREFIX_LEN) ||
3411 (type == FT_FIL_DEFINITION_MATCH_IP_DST_PREFIX_LEN))
3412 valid = 1;
3413 break;
3414
3415 case FT_FIL_PRIMITIVE_TYPE_IP_TOS:
3416 if ((type == FT_FIL_DEFINITION_MATCH_IP_TOS) ||
3417 (type == FT_FIL_DEFINITION_MATCH_IP_MARKED_TOS))
3418 valid = 1;
3419 break;
3420
3421 case FT_FIL_PRIMITIVE_TYPE_IP_TCP_FLAGS:
3422 if (type == FT_FIL_DEFINITION_MATCH_IP_TCP_FLAGS)
3423 valid = 1;
3424 break;
3425
3426 case FT_FIL_PRIMITIVE_TYPE_IF_INDEX:
3427 if ((type == FT_FIL_DEFINITION_MATCH_INPUT_IF) ||
3428 (type == FT_FIL_DEFINITION_MATCH_OUTPUT_IF))
3429 valid = 1;
3430 break;
3431
3432 case FT_FIL_PRIMITIVE_TYPE_COUNTER:
3433 if ((type == FT_FIL_DEFINITION_MATCH_FLOWS) ||
3434 (type == FT_FIL_DEFINITION_MATCH_OCTETS) ||
3435 (type == FT_FIL_DEFINITION_MATCH_PACKETS) ||
3436 (type == FT_FIL_DEFINITION_MATCH_XTRA_PACKETS) ||
3437 (type == FT_FIL_DEFINITION_MATCH_START_TIME) ||
3438 (type == FT_FIL_DEFINITION_MATCH_DURATION))
3439 valid = 1;
3440 break;
3441
3442 case FT_FIL_PRIMITIVE_TYPE_TIME:
3443 case FT_FIL_PRIMITIVE_TYPE_TIME_DATE:
3444 if ((type == FT_FIL_DEFINITION_MATCH_START_TIME) ||
3445 (type == FT_FIL_DEFINITION_MATCH_END_TIME))
3446 valid = 1;
3447 break;
3448
3449 case FT_FIL_PRIMITIVE_TYPE_ENGINE:
3450 if ((type == FT_FIL_DEFINITION_MATCH_ENGINE_ID) ||
3451 (type == FT_FIL_DEFINITION_MATCH_ENGINE_TYPE))
3452 valid = 1;
3453 break;
3454
3455 case FT_FIL_PRIMITIVE_TYPE_TAG_MASK:
3456 if ((type == FT_FIL_DEFINITION_MATCH_SRC_TAG) ||
3457 (type == FT_FIL_DEFINITION_MATCH_DST_TAG))
3458 valid = 1;
3459 break;
3460
3461 case FT_FIL_PRIMITIVE_TYPE_TAG:
3462 if ((type == FT_FIL_DEFINITION_MATCH_SRC_TAG) ||
3463 (type == FT_FIL_DEFINITION_MATCH_DST_TAG))
3464 valid = 1;
3465 break;
3466
3467 case FT_FIL_PRIMITIVE_TYPE_DOUBLE:
3468 if ((type == FT_FIL_DEFINITION_MATCH_PPS) ||
3469 (type == FT_FIL_DEFINITION_MATCH_BPS))
3470 valid = 1;
3471 break;
3472
3473 case FT_FIL_PRIMITIVE_TYPE_RATE:
3474 if (type == FT_FIL_DEFINITION_MATCH_RANDOM_SAMPLE)
3475 valid = 1;
3476
3477 default:
3478 break;
3479
3480 } /* switch */
3481
3482 /* make sure primitive is valid for match type */
3483 if (!valid) {
3484 fterr_warnx(
3485 "Primitive \"%s\" incompatible with match in filter-definition \"%s\".",
3486 ftmi->tmp_type, ftfd->name);
3487 return -1;
3488 }
3489
3490 ftmi->lookup = ftfp->lookup;
3491 ftmi->eval = eval;
3492
3493 } /* ftmi */
3494
3495 } /* ftm */
3496
3497 } /* ftfd */
3498
3499 return 0;
3500
3501 } /* resolve_primitives */
3502
3503 /*
3504 * function: parse_definition_or
3505 *
3506 * process the definition or lines
3507 *
3508 * returns: 0 ok
3509 * <0 fail
3510 */
parse_definition_or(struct line_parser * lp,struct ftfil * ftfil)3511 static int parse_definition_or(struct line_parser *lp, struct ftfil *ftfil)
3512 {
3513 lp->cur_def_match = (struct ftfil_match*)0L;
3514 return 0;
3515 } /* parse_definition_or */
3516
3517 /*
3518 *************************************************************************
3519 parse_primitive_*
3520 *************************************************************************
3521 */
3522
3523 /*
3524 * function: parse_primitive_type_asn
3525 *
3526 * process the asn primitive
3527 *
3528 * returns: 0 ok
3529 * <0 fail
3530 */
parse_primitive_type_asn(struct line_parser * lp,struct ftfil * ftfil)3531 int parse_primitive_type_asn(struct line_parser *lp, struct ftfil *ftfil)
3532 {
3533 struct ftfil_lookup_as *ftfla;
3534
3535 /* enable symbol lookups */
3536 lp->sym_cur = lp->sym_tag;
3537
3538 ftfla = (struct ftfil_lookup_as*)lp->cur_primitive->lookup;
3539
3540 if (ftfil_load_lookup(lp, lp->word, 65536, ftfla->mode, lp->mode)) {
3541 fterr_warnx("load_lookup(): failed");
3542 return -1;
3543 }
3544
3545 return 0;
3546
3547 } /* parse_primitive_type_asn */
3548
3549 /*
3550 * function: parse_primitive_type_ip_prot
3551 *
3552 * process the ip_prot primitive
3553 *
3554 * returns: 0 ok
3555 * <0 fail
3556 */
parse_primitive_type_ip_prot(struct line_parser * lp,struct ftfil * ftfil)3557 int parse_primitive_type_ip_prot(struct line_parser *lp,
3558 struct ftfil *ftfil)
3559 {
3560 struct ftfil_lookup_ip_prot *ftflipp;
3561
3562 /* enable symbol lookups */
3563 lp->sym_cur = lp->sym_ip_prot;
3564
3565 ftflipp = (struct ftfil_lookup_ip_prot*)lp->cur_primitive->lookup;
3566
3567 if (ftfil_load_lookup(lp, lp->word, 256, ftflipp->mode, lp->mode)) {
3568 fterr_warnx("load_lookup(): failed");
3569 return -1;
3570 }
3571
3572 return 0;
3573
3574 } /* parse_primitive_type_ip_prot */
3575
3576 /*
3577 * function: parse_primitive_type_ip_port
3578 *
3579 * process the ip_port primitive
3580 *
3581 * returns: 0 ok
3582 * <0 fail
3583 */
parse_primitive_type_ip_port(struct line_parser * lp,struct ftfil * ftfil)3584 int parse_primitive_type_ip_port(struct line_parser *lp,
3585 struct ftfil *ftfil)
3586 {
3587 struct ftfil_lookup_ip_port *ftflippo;
3588
3589 /* enable symbol lookups */
3590 lp->sym_cur = lp->sym_ip_tcp_port;
3591
3592 ftflippo = (struct ftfil_lookup_ip_port*)lp->cur_primitive->lookup;
3593
3594 if (ftfil_load_lookup(lp, lp->word, 65536, ftflippo->mode, lp->mode)) {
3595 fterr_warnx("load_lookup(): failed");
3596 return -1;
3597 }
3598
3599 return 0;
3600
3601 } /* parse_primitive_type_ip_port */
3602
3603 /*
3604 * function: parse_primitive_type_ip_prefix_len
3605 *
3606 * process the ip_prefix_len primitive
3607 *
3608 * returns: 0 ok
3609 * <0 fail
3610 */
parse_primitive_type_ip_prefix_len(struct line_parser * lp,struct ftfil * ftfil)3611 int parse_primitive_type_ip_prefix_len(struct line_parser *lp,
3612 struct ftfil *ftfil)
3613 {
3614 struct ftfil_lookup_ip_prefix_len *ftflipl;
3615
3616 /* disable symbol lookups */
3617 lp->sym_cur = (struct ftsym*)0L;
3618
3619 ftflipl = (struct ftfil_lookup_ip_prefix_len*)lp->cur_primitive->lookup;
3620
3621 if (ftfil_load_lookup(lp, lp->word, 33, ftflipl->mode, lp->mode)) {
3622 fterr_warnx("load_lookup(): failed");
3623 return -1;
3624 }
3625
3626 return 0;
3627
3628 } /* parse_primitive_type_ip_prefix_len */
3629
3630 /*
3631 * function: parse_primitive_type_ip_tos
3632 *
3633 * process the ip_tos primitive
3634 *
3635 * returns: 0 ok
3636 * <0 fail
3637 */
parse_primitive_type_ip_tos(struct line_parser * lp,struct ftfil * ftfil)3638 int parse_primitive_type_ip_tos(struct line_parser *lp,
3639 struct ftfil *ftfil)
3640 {
3641 struct ftfil_lookup_ip_tos *ftflipt;
3642
3643 /* disable symbol lookups */
3644 lp->sym_cur = (struct ftsym*)0L;
3645
3646 ftflipt = (struct ftfil_lookup_ip_tos*)lp->cur_primitive->lookup;
3647
3648 if (ftfil_load_lookup(lp, lp->word, 256, ftflipt->mode, lp->mode)) {
3649 fterr_warnx("load_lookup(): failed");
3650 return -1;
3651 }
3652
3653 return 0;
3654
3655 } /* parse_primitive_type_ip_tos */
3656
3657 /*
3658 * function: parse_primitive_type_ip_tcp_flags
3659 *
3660 * process the ip_tcp_flags primitive
3661 *
3662 * returns: 0 ok
3663 * <0 fail
3664 */
parse_primitive_type_ip_tcp_flags(struct line_parser * lp,struct ftfil * ftfil)3665 int parse_primitive_type_ip_tcp_flags(struct line_parser *lp,
3666 struct ftfil *ftfil)
3667 {
3668 struct ftfil_lookup_ip_tcp_flags *ftfliptcp;
3669
3670 /* disable symbol lookups */
3671 lp->sym_cur = (struct ftsym*)0L;
3672
3673 ftfliptcp = (struct ftfil_lookup_ip_tcp_flags*)lp->cur_primitive->lookup;
3674
3675 if (ftfil_load_lookup(lp, lp->word, 256, ftfliptcp->mode, lp->mode)) {
3676 fterr_warnx("load_lookup(): failed");
3677 return -1;
3678 }
3679
3680 return 0;
3681
3682 } /* parse_primitive_type_ip_tcp_flags */
3683
3684 /*
3685 * function: parse_primitive_type_if_index
3686 *
3687 * process the if_index primitive
3688 *
3689 * returns: 0 ok
3690 * <0 fail
3691 */
parse_primitive_type_if_index(struct line_parser * lp,struct ftfil * ftfil)3692 int parse_primitive_type_if_index(struct line_parser *lp,
3693 struct ftfil *ftfil)
3694 {
3695 struct ftfil_lookup_if_index *ftflif;
3696
3697 /* disable symbol lookups */
3698 lp->sym_cur = (struct ftsym*)0L;
3699
3700 ftflif = (struct ftfil_lookup_if_index*)lp->cur_primitive->lookup;
3701
3702 if (ftfil_load_lookup(lp, lp->word, 65536, ftflif->mode, lp->mode)) {
3703 fterr_warnx("load_lookup(): failed");
3704 return -1;
3705 }
3706
3707 return 0;
3708
3709 } /* parse_primitive_type_if_index */
3710
3711 /*
3712 * function: parse_primitive_type_engine
3713 *
3714 * process the engine primitive
3715 *
3716 * returns: 0 ok
3717 * <0 fail
3718 */
parse_primitive_type_engine(struct line_parser * lp,struct ftfil * ftfil)3719 int parse_primitive_type_engine(struct line_parser *lp,
3720 struct ftfil *ftfil)
3721 {
3722 struct ftfil_lookup_engine *ftfle;
3723
3724 /* disable symbol lookups */
3725 lp->sym_cur = (struct ftsym*)0L;
3726
3727 ftfle = (struct ftfil_lookup_engine*)lp->cur_primitive->lookup;
3728
3729 if (ftfil_load_lookup(lp, lp->word, 65536, ftfle->mode, lp->mode)) {
3730 fterr_warnx("load_lookup(): failed");
3731 return -1;
3732 }
3733
3734 return 0;
3735
3736 } /* parse_primitive_type_engine */
3737
3738 /*
3739 * function: parse_primitive_type_ip_address
3740 *
3741 * process the ip-address primitive
3742 *
3743 * returns: 0 ok
3744 * <0 fail
3745 */
parse_primitive_type_ip_address(struct line_parser * lp,struct ftfil * ftfil)3746 int parse_primitive_type_ip_address(struct line_parser *lp,
3747 struct ftfil *ftfil)
3748 {
3749 struct ftfil_lookup_ip_address *ftflipa;
3750 struct ftchash_rec_fil_c32 ftch_recfc32, *ftch_recfc32p;
3751 uint32_t hash;
3752 char fmt_buf[32];
3753
3754 ftflipa = (struct ftfil_lookup_ip_address*)lp->cur_primitive->lookup;
3755
3756 bzero(&ftch_recfc32, sizeof ftch_recfc32);
3757
3758 ftch_recfc32.c32 = scan_ip(lp->word);
3759
3760 hash = (ftch_recfc32.c32>>16) ^ (ftch_recfc32.c32 & 0xFFFF);
3761 hash = ((hash >>8) ^ (hash & 0x0FFF));
3762
3763 if ((ftch_recfc32p = ftchash_lookup(ftflipa->ftch, &ftch_recfc32.c32,
3764 hash))) {
3765 fmt_ipv4(fmt_buf, ftch_recfc32p->c32, FMT_JUST_LEFT);
3766 fterr_warnx("%s line %d: entry %s previously set as %s.", lp->fname,
3767 lp->lineno, fmt_buf, mode_name_lookup[ftch_recfc32p->mode]);
3768 }
3769
3770 if (!(ftch_recfc32p = ftchash_update(ftflipa->ftch, &ftch_recfc32, hash))) {
3771 fterr_warnx("ftch_update(): failed");
3772 return -1;
3773 }
3774
3775 ftch_recfc32p->mode = lp->mode;
3776
3777 return 0;
3778
3779 } /* parse_primitive_type_ip_address */
3780
3781 /*
3782 * function: parse_primitive_type_tag
3783 *
3784 * process the tag primitive
3785 *
3786 * returns: 0 ok
3787 * <0 fail
3788 */
parse_primitive_type_tag(struct line_parser * lp,struct ftfil * ftfil)3789 int parse_primitive_type_tag(struct line_parser *lp,
3790 struct ftfil *ftfil)
3791 {
3792 struct ftfil_lookup_tag *ftflt;
3793 struct ftchash_rec_fil_c32 ftch_recfc32, *ftch_recfc32p;
3794 uint32_t hash, val;
3795
3796 ftflt = (struct ftfil_lookup_tag*)lp->cur_primitive->lookup;
3797
3798 bzero(&ftch_recfc32, sizeof ftch_recfc32);
3799
3800 if (isalpha((int)lp->word[0])) {
3801 if (lp->sym_tag && ftsym_findbyname(lp->sym_tag, lp->word, &val))
3802 ftch_recfc32.c32 = val;
3803 else {
3804 fterr_warnx("%s line %d: symbol lookup for \"%s\" failed.", lp->fname,
3805 lp->lineno, lp->word);
3806 return -1;
3807 }
3808 } else
3809 ftch_recfc32.c32 = strtoul(lp->word, (char**)0L, 0);
3810
3811 hash = (ftch_recfc32.c32>>16) ^ (ftch_recfc32.c32 & 0xFFFF);
3812 hash = ((hash >>8) ^ (hash & 0x0FFF));
3813
3814 if ((ftch_recfc32p = ftchash_lookup(ftflt->ftch, &ftch_recfc32.c32, hash)))
3815 fterr_warnx("%s line %d: entry 0x%lX previously set as %s.", lp->fname,
3816 lp->lineno, ftch_recfc32.c32, mode_name_lookup[ftch_recfc32p->mode]);
3817
3818 if (!(ftch_recfc32p = ftchash_update(ftflt->ftch, &ftch_recfc32, hash))) {
3819 fterr_warnx("ftch_update(): failed");
3820 return -1;
3821 }
3822
3823 ftch_recfc32p->mode = lp->mode;
3824
3825 return 0;
3826
3827 } /* parse_primitive_type_tag */
3828
3829 /*
3830 * function: parse_primitive_type_ip_mask
3831 *
3832 * process the ip-mask primitive
3833 *
3834 * returns: 0 ok
3835 * <0 fail
3836 */
parse_primitive_type_ip_mask(struct line_parser * lp,struct ftfil * ftfil)3837 int parse_primitive_type_ip_mask(struct line_parser *lp,
3838 struct ftfil *ftfil)
3839 {
3840 struct ftfil_lookup_ip_mask *ftflipm;
3841 struct ftfil_lookup_ip_mask_rec *ftflipmr, *ftflipmr2;
3842 char fmt_buf1[32], fmt_buf2[32];
3843 char *ip;
3844
3845 ip = lp->word;
3846
3847 NEXT_WORD(&lp->buf, lp->word);
3848
3849 if (!lp->word) {
3850 fterr_warnx("%s line %d: Expecting mask.", lp->fname, lp->lineno);
3851 return -1;
3852 }
3853
3854 ftflipm = (struct ftfil_lookup_ip_mask*)lp->cur_primitive->lookup;
3855
3856 if (!(ftflipmr = (struct ftfil_lookup_ip_mask_rec*)
3857 malloc(sizeof *ftflipmr))) {
3858 fterr_warn("malloc()");
3859 return -1;
3860 }
3861
3862 bzero(ftflipmr, sizeof *ftflipmr);
3863
3864 ftflipmr->ip = scan_ip(ip);
3865 ftflipmr->mask = scan_ip(lp->word);
3866 ftflipmr->mode = lp->mode;
3867
3868 FT_STAILQ_FOREACH(ftflipmr2, &ftflipm->list, chain) {
3869
3870 if ((ftflipmr2->ip == ftflipmr->ip) &&
3871 (ftflipmr2->mask == ftflipmr->mask)) {
3872
3873 fmt_ipv4(fmt_buf1, ftflipmr2->ip, FMT_JUST_LEFT);
3874 fmt_ipv4(fmt_buf2, ftflipmr2->mask, FMT_JUST_LEFT);
3875
3876 fterr_warnx("%s line %d: entry %s %s previously set as %s.", lp->fname,
3877 lp->lineno, fmt_buf1, fmt_buf2, mode_name_lookup[ftflipmr2->mode]);
3878
3879 }
3880 }
3881
3882 FT_STAILQ_INSERT_TAIL(&ftflipm->list, ftflipmr, chain);
3883
3884 return 0;
3885
3886 } /* parse_primitive_type_ip_mask */
3887
3888 /*
3889 * function: parse_primitive_type_tag_mask
3890 *
3891 * process the tag-mask primitive
3892 *
3893 * returns: 0 ok
3894 * <0 fail
3895 */
parse_primitive_type_tag_mask(struct line_parser * lp,struct ftfil * ftfil)3896 int parse_primitive_type_tag_mask(struct line_parser *lp,
3897 struct ftfil *ftfil)
3898 {
3899 struct ftfil_lookup_tag_mask *ftfltm;
3900 struct ftfil_lookup_tag_mask_rec *ftfltmr, *ftfltmr2;
3901 uint32_t val, tval;
3902 char *tag;
3903
3904 tag = lp->word;
3905
3906 NEXT_WORD(&lp->buf, lp->word);
3907
3908 if (!lp->word) {
3909 fterr_warnx("%s line %d: Expecting mask.", lp->fname, lp->lineno);
3910 return -1;
3911 }
3912
3913 ftfltm = (struct ftfil_lookup_tag_mask*)lp->cur_primitive->lookup;
3914
3915 if (isalpha((int)tag[0])) {
3916 if (lp->sym_tag && ftsym_findbyname(lp->sym_tag, tag, &val))
3917 tval = val;
3918 else {
3919 fterr_warnx("%s line %d: symbol lookup for \"%s\" failed.", lp->fname,
3920 lp->lineno, tag);
3921 return -1;
3922 }
3923 } else
3924 tval = strtoul(tag, (char**)0L, 0);
3925
3926 if (!(ftfltmr = (struct ftfil_lookup_tag_mask_rec*)
3927 malloc(sizeof *ftfltmr))) {
3928 fterr_warn("malloc()");
3929 return -1;
3930 }
3931
3932 bzero(ftfltmr, sizeof *ftfltmr);
3933
3934 ftfltmr->tag = tval;
3935 ftfltmr->mask = strtoul(lp->word, (char**)0L, 0);
3936 ftfltmr->mode = lp->mode;
3937
3938 FT_STAILQ_FOREACH(ftfltmr2, &ftfltm->list, chain) {
3939
3940 if ((ftfltmr2->tag == ftfltmr->tag) &&
3941 (ftfltmr2->mask == ftfltmr->mask)) {
3942
3943 fterr_warnx("%s line %d: entry 0x%lX 0x%lX previously set as %s.",
3944 lp->fname, lp->lineno, ftfltmr2->tag, ftfltmr2->mask,
3945 mode_name_lookup[ftfltmr2->mode]);
3946
3947 }
3948 }
3949
3950 FT_STAILQ_INSERT_TAIL(&ftfltm->list, ftfltmr, chain);
3951
3952 return 0;
3953
3954 } /* parse_primitive_type_tag_mask */
3955
3956 /*
3957 * function: parse_primitive_type_ip_prefix
3958 *
3959 * process the ip-prefix primitive
3960 *
3961 * returns: 0 ok
3962 * <0 fail
3963 */
parse_primitive_type_ip_prefix(struct line_parser * lp,struct ftfil * ftfil)3964 int parse_primitive_type_ip_prefix(struct line_parser *lp,
3965 struct ftfil *ftfil)
3966 {
3967 struct ftfil_lookup_ip_prefix *ftflippr;
3968 struct ftfil_lookup_ip_prefix_rec *ftflipprr, *ftflipprr2;
3969 struct ip_prefix ipp;
3970 struct radix_sockaddr_in sock1, sock2;
3971 char fmt_buf[32];
3972
3973 ftflippr = (struct ftfil_lookup_ip_prefix*)lp->cur_primitive->lookup;
3974
3975 if (!(ftflipprr = (struct ftfil_lookup_ip_prefix_rec*)
3976 malloc(sizeof *ftflipprr))) {
3977 fterr_warn("malloc()");
3978 return -1;
3979 }
3980
3981 bzero (ftflipprr, sizeof *ftflipprr);
3982
3983 ipp = scan_ip_prefix(lp->word);
3984
3985 ftflipprr->rt_nodes->rn_key = (caddr_t)&ftflipprr->addr;
3986 ftflipprr->addr.sin_addr.s_addr = ipp.addr;
3987 ftflipprr->addr.sin_len = sizeof (struct radix_sockaddr_in);
3988 ftflipprr->addr.sin_family = AF_INET;
3989 ftflipprr->masklen = ipp.len;
3990 ftflipprr->mode = lp->mode;
3991
3992 bzero(&sock1, sizeof sock1);
3993 bzero(&sock2, sizeof sock2);
3994
3995 sock1.sin_addr.s_addr = ipp.addr;
3996 sock1.sin_family = AF_INET;
3997 sock1.sin_len = sizeof sock1;
3998
3999 sock2.sin_addr.s_addr = (!ipp.len) ? 0 : mask_lookup[ipp.len];
4000 sock2.sin_family = AF_INET;
4001 sock2.sin_len = sizeof sock2;
4002
4003 ftflipprr2 = (struct ftfil_lookup_ip_prefix_rec*)
4004 ftflippr->rhead->rnh_lookup(&sock1, &sock2, ftflippr->rhead);
4005
4006 if (ftflipprr2 && (ftflipprr2->addr.sin_addr.s_addr == ipp.addr) &&
4007 (ftflipprr2->masklen == ipp.len)) {
4008
4009 fmt_ipv4prefix(fmt_buf, ftflipprr2->addr.sin_addr.s_addr,
4010 ftflipprr2->masklen, FMT_JUST_LEFT);
4011
4012 fterr_warnx("%s line %d: entry %s previously set as %s.", lp->fname,
4013 lp->lineno, fmt_buf, mode_name_lookup[ftflipprr2->mode]);
4014
4015 /* can't add this again */
4016 free(ftflipprr);
4017 return 0;
4018
4019 }
4020
4021 if (!ftflippr->rhead->rnh_addaddr(&ftflipprr->addr, &sock2, ftflippr->rhead,
4022 ftflipprr->rt_nodes)) {
4023 free(ftflipprr);
4024 fterr_warnx("rnh_addaddr(): failed for %s", lp->word);
4025 return -1;
4026 }
4027
4028 return 0;
4029
4030 } /* parse_primitive_type_ip_prefix */
4031
4032 /*
4033 * function: parse_primitive_type_counter
4034 *
4035 * process the counter primitive
4036 *
4037 * returns: 0 ok
4038 * <0 fail
4039 */
parse_primitive_type_counter(struct line_parser * lp,struct ftfil * ftfil)4040 int parse_primitive_type_counter(struct line_parser *lp,
4041 struct ftfil *ftfil)
4042 {
4043 struct ftfil_lookup_counter *ftflc;
4044 struct ftfil_lookup_counter_rec *ftflcr, *ftflcr2;
4045 char *c;
4046 enum ftfil_op op;
4047
4048 c = lp->word;
4049
4050 NEXT_WORD(&lp->buf, lp->word);
4051
4052 if (!lp->word) {
4053 fterr_warnx("%s line %d: Expecting counter.", lp->fname, lp->lineno);
4054 return -1;
4055 }
4056
4057 if (!strcasecmp(c, "lt"))
4058 op = FT_FIL_OP_LT;
4059 else if (!strcasecmp(c, "gt"))
4060 op = FT_FIL_OP_GT;
4061 else if (!strcasecmp(c, "eq"))
4062 op = FT_FIL_OP_EQ;
4063 else if (!strcasecmp(c, "ne"))
4064 op = FT_FIL_OP_NE;
4065 else if (!strcasecmp(c, "le"))
4066 op = FT_FIL_OP_LE;
4067 else if (!strcasecmp(c, "ge"))
4068 op = FT_FIL_OP_GE;
4069 else {
4070 fterr_warnx("%s line %d: Expecting one of {lt,gt,eq,ne,le,ge}",
4071 lp->fname, lp->lineno);
4072 return -1;
4073 }
4074
4075 ftflc = (struct ftfil_lookup_counter*)lp->cur_primitive->lookup;
4076
4077 if (!(ftflcr = (struct ftfil_lookup_counter_rec*) malloc(sizeof *ftflcr))) {
4078 fterr_warn("malloc()");
4079 return -1;
4080 }
4081
4082 bzero(ftflcr, sizeof *ftflcr);
4083
4084 ftflcr->val = strtoul(lp->word, (char**)0L, 0);
4085 ftflcr->op = op;
4086 ftflcr->mode = lp->mode;
4087
4088 FT_STAILQ_FOREACH(ftflcr2, &ftflc->list, chain) {
4089
4090 if ((ftflcr2->val == ftflcr->val) &&
4091 (ftflcr2->op == ftflcr->op)) {
4092
4093 fterr_warnx("%s line %d: entry %s %lu previously set as %s.",
4094 lp->fname, lp->lineno, op_name_lookup[ftflcr2->op], ftflcr2->val,
4095 mode_name_lookup[ftflcr2->mode]);
4096
4097 }
4098 }
4099
4100
4101 FT_STAILQ_INSERT_TAIL(&ftflc->list, ftflcr, chain);
4102
4103 return 0;
4104
4105 } /* parse_primitive_type_counter */
4106
4107 /*
4108 * function: parse_primitive_type_time_date
4109 *
4110 * process the time/date primitive
4111 *
4112 * returns: 0 ok
4113 * <0 fail
4114 */
parse_primitive_type_time_date(struct line_parser * lp,struct ftfil * ftfil)4115 int parse_primitive_type_time_date(struct line_parser *lp,
4116 struct ftfil *ftfil)
4117 {
4118 struct ftfil_lookup_counter *ftflc;
4119 struct ftfil_lookup_counter_rec *ftflcr, *ftflcr2;
4120 time_t t;
4121 enum ftfil_op op;
4122
4123 if (!lp->buf) {
4124 fterr_warnx("%s line %d: Expecting time/date.", lp->fname, lp->lineno);
4125 return -1;
4126 }
4127
4128 if ((t = get_date(lp->buf, (time_t*)0L)) == -1) {
4129 fterr_warnx("%s line %d: Cannot parse time/date.", lp->fname, lp->lineno);
4130 return -1;
4131 }
4132
4133 /* eat the line */
4134 for (; *(lp->buf); ++lp->buf);
4135
4136 if (!strcasecmp(lp->word, "lt"))
4137 op = FT_FIL_OP_LT;
4138 else if (!strcasecmp(lp->word, "gt"))
4139 op = FT_FIL_OP_GT;
4140 else if (!strcasecmp(lp->word, "eq"))
4141 op = FT_FIL_OP_EQ;
4142 else if (!strcasecmp(lp->word, "ne"))
4143 op = FT_FIL_OP_NE;
4144 else if (!strcasecmp(lp->word, "le"))
4145 op = FT_FIL_OP_LE;
4146 else if (!strcasecmp(lp->word, "ge"))
4147 op = FT_FIL_OP_GE;
4148 else {
4149 fterr_warnx("%s line %d: Expecting one of {lt,gt,eq,ne,le,ge}",
4150 lp->fname, lp->lineno);
4151 return -1;
4152 }
4153
4154 ftflc = (struct ftfil_lookup_counter*)lp->cur_primitive->lookup;
4155
4156 if (!(ftflcr = (struct ftfil_lookup_counter_rec*) malloc(sizeof *ftflcr))) {
4157 fterr_warn("malloc()");
4158 return -1;
4159 }
4160
4161 bzero(ftflcr, sizeof *ftflcr);
4162
4163 ftflcr->val = t;
4164 ftflcr->op = op;
4165 ftflcr->mode = lp->mode;
4166
4167 FT_STAILQ_FOREACH(ftflcr2, &ftflc->list, chain) {
4168
4169 if ((ftflcr2->val == ftflcr->val) &&
4170 (ftflcr2->op == ftflcr->op)) {
4171
4172 fterr_warnx("%s line %d: entry %s %lu previously set as %s.",
4173 lp->fname, lp->lineno, op_name_lookup[ftflcr2->op], ftflcr2->val,
4174 mode_name_lookup[ftflcr2->mode]);
4175
4176 }
4177 }
4178
4179 FT_STAILQ_INSERT_TAIL(&ftflc->list, ftflcr, chain);
4180
4181 return 0;
4182
4183 } /* parse_primitive_type_time_date */
4184
4185 /*
4186 * function: parse_primitive_type_time
4187 *
4188 * process the time primitive
4189 *
4190 * returns: 0 ok
4191 * <0 fail
4192 */
parse_primitive_type_time(struct line_parser * lp,struct ftfil * ftfil)4193 int parse_primitive_type_time(struct line_parser *lp,
4194 struct ftfil *ftfil)
4195 {
4196 struct ftfil_lookup_time *ftfltme;
4197 struct ftfil_lookup_time_rec *ftfltmer, *ftfltmer2;
4198 enum ftfil_op op;
4199 char *c, *cop;
4200 int hour, min, sec;
4201
4202 if (!lp->word) {
4203 fterr_warnx("%s line %d: Expecting time op.", lp->fname, lp->lineno);
4204 return -1;
4205 }
4206
4207 cop = lp->word;
4208
4209 NEXT_WORD(&lp->buf, lp->word);
4210
4211 if (!lp->word) {
4212 fterr_warnx("%s line %d: Expecting time value.", lp->fname, lp->lineno);
4213 return -1;
4214 }
4215
4216 /* parse out time */
4217 hour = min = sec = 0;
4218
4219 if (!(c = strsep(&lp->word, ":")))
4220 goto done;
4221
4222 hour = atoi(c);
4223
4224 if (!(c = strsep(&lp->word, ":")))
4225 goto done;
4226
4227 min = atoi(c);
4228
4229 if (!(c = strsep(&lp->word, ":")))
4230 goto done;
4231
4232 sec = atoi(c);
4233
4234 if (lp->word) {
4235 fterr_warnx("%s line %d: Unexpected text: %s", lp->fname, lp->lineno,
4236 lp->word);
4237 return -1;
4238 }
4239
4240 done:
4241
4242 if (!strcasecmp(cop, "lt"))
4243 op = FT_FIL_OP_LT;
4244 else if (!strcasecmp(cop, "gt"))
4245 op = FT_FIL_OP_GT;
4246 else if (!strcasecmp(cop, "eq"))
4247 op = FT_FIL_OP_EQ;
4248 else if (!strcasecmp(cop, "ne"))
4249 op = FT_FIL_OP_NE;
4250 else if (!strcasecmp(cop, "le"))
4251 op = FT_FIL_OP_LE;
4252 else if (!strcasecmp(cop, "ge"))
4253 op = FT_FIL_OP_GE;
4254 else {
4255 fterr_warnx("%s line %d: Expecting one of {lt,gt,eq,ne,le,ge}",
4256 lp->fname, lp->lineno);
4257 return -1;
4258 }
4259
4260 ftfltme = (struct ftfil_lookup_time*)lp->cur_primitive->lookup;
4261
4262 if (!(ftfltmer = (struct ftfil_lookup_time_rec*) malloc(sizeof *ftfltmer))) {
4263 fterr_warn("malloc()");
4264 return -1;
4265 }
4266
4267 bzero(ftfltmer, sizeof *ftfltmer);
4268
4269 ftfltmer->hour = hour;
4270 ftfltmer->min = min;
4271 ftfltmer->sec = sec;
4272 ftfltmer->op = op;
4273 ftfltmer->mode = lp->mode;
4274
4275 FT_STAILQ_FOREACH(ftfltmer2, &ftfltme->list, chain) {
4276
4277 if ((ftfltmer2->hour == ftfltmer->hour) &&
4278 (ftfltmer2->min == ftfltmer->min) &&
4279 (ftfltmer2->sec == ftfltmer->sec) &&
4280 (ftfltmer2->op == ftfltmer->op)) {
4281
4282 fterr_warnx("%s line %d: entry %d:%d:%d %lu previously set as %s.",
4283 lp->fname, lp->lineno, op_name_lookup[ftfltmer2->op], ftfltmer2->hour,
4284 ftfltmer2->min, ftfltmer2->sec, mode_name_lookup[ftfltmer2->mode]);
4285
4286 }
4287 }
4288
4289 FT_STAILQ_INSERT_TAIL(&ftfltme->list, ftfltmer, chain);
4290
4291 return 0;
4292
4293 } /* parse_primitive_type_time */
4294
4295 /*
4296 * function: parse_primitive_type_double
4297 *
4298 * process the double primitive
4299 *
4300 * returns: 0 ok
4301 * <0 fail
4302 */
parse_primitive_type_double(struct line_parser * lp,struct ftfil * ftfil)4303 int parse_primitive_type_double(struct line_parser *lp,
4304 struct ftfil *ftfil)
4305 {
4306 struct ftfil_lookup_double *ftfld;
4307 struct ftfil_lookup_double_rec *ftfldr, *ftfldr2;
4308 char *c;
4309 enum ftfil_op op;
4310
4311 c = lp->word;
4312
4313 NEXT_WORD(&lp->buf, lp->word);
4314
4315 if (!lp->word) {
4316 fterr_warnx("%s line %d: Expecting counter.", lp->fname, lp->lineno);
4317 return -1;
4318 }
4319
4320 if (!strcasecmp(c, "lt"))
4321 op = FT_FIL_OP_LT;
4322 else if (!strcasecmp(c, "gt"))
4323 op = FT_FIL_OP_GT;
4324 else if (!strcasecmp(c, "eq"))
4325 op = FT_FIL_OP_EQ;
4326 else if (!strcasecmp(c, "ne"))
4327 op = FT_FIL_OP_NE;
4328 else if (!strcasecmp(c, "le"))
4329 op = FT_FIL_OP_LE;
4330 else if (!strcasecmp(c, "ge"))
4331 op = FT_FIL_OP_GE;
4332 else {
4333 fterr_warnx("%s line %d: Expecting one of {lt,gt,eq,ne,le,ge}",
4334 lp->fname, lp->lineno);
4335 return -1;
4336 }
4337
4338 ftfld = (struct ftfil_lookup_double*)lp->cur_primitive->lookup;
4339
4340 if (!(ftfldr = (struct ftfil_lookup_double_rec*) malloc(sizeof *ftfldr))) {
4341 fterr_warn("malloc()");
4342 return -1;
4343 }
4344
4345 bzero(ftfldr, sizeof *ftfldr);
4346
4347 ftfldr->val = strtod(lp->word, (char**)0L);
4348 ftfldr->op = op;
4349 ftfldr->mode = lp->mode;
4350
4351 FT_STAILQ_FOREACH(ftfldr2, &ftfld->list, chain) {
4352
4353 if ((ftfldr2->val == ftfldr->val) &&
4354 (ftfldr2->op == ftfldr->op)) {
4355
4356 fterr_warnx("%s line %d: entry %s %f previously set as %s.",
4357 lp->fname, lp->lineno, op_name_lookup[ftfldr2->op], ftfldr2->val,
4358 mode_name_lookup[ftfldr2->mode]);
4359
4360 }
4361 }
4362
4363
4364 FT_STAILQ_INSERT_TAIL(&ftfld->list, ftfldr, chain);
4365
4366 return 0;
4367
4368 } /* parse_primitive_type_double */
4369
4370 /*
4371 * function: parse_primitive_type_rate
4372 *
4373 * process the rate primitive
4374 *
4375 * returns: 0 ok
4376 * <0 fail
4377 */
parse_primitive_type_rate(struct line_parser * lp,struct ftfil * ftfil)4378 int parse_primitive_type_rate(struct line_parser *lp,
4379 struct ftfil *ftfil)
4380 {
4381 struct ftfil_lookup_rate *ftflr;
4382
4383 /* disable symbol lookups */
4384 lp->sym_cur = (struct ftsym*)0L;
4385
4386 ftflr = (struct ftfil_lookup_rate*)lp->cur_primitive->lookup;
4387
4388 if (ftflr->rate)
4389 fterr_warnx("%s line %d: Rate previously set.", lp->fname, lp->lineno);
4390
4391 ftflr->rate = atoi(lp->word);
4392
4393 if (!ftflr->rate)
4394 fterr_errx(1, "%s line %d: Rate can not be 0.", lp->fname, lp->lineno);
4395 ftflr->mode = lp->mode;
4396
4397 return 0;
4398
4399 } /* parse_primitive_type_rate */
4400
4401 /*
4402 * function: parse_primitive
4403 *
4404 * process the 'filter-primitive' line. Each primitive has a unique name
4405 * which is added to the ftfil->primitives linked list. The current
4406 * primitive definition is updated in lp. Primitives by themself do nothing,
4407 * they must be invoked by a definition.
4408 *
4409 * returns: 0 ok
4410 * <0 fail
4411 */
parse_primitive(struct line_parser * lp,struct ftfil * ftfil)4412 int parse_primitive(struct line_parser *lp, struct ftfil *ftfil)
4413 {
4414 char *c;
4415 struct ftfil_primitive *ftfp;
4416
4417 NEXT_WORD(&lp->buf, c);
4418
4419 if (!c) {
4420 fterr_warnx("%s line %d: Expecting name.", lp->fname, lp->lineno);
4421 return -1;
4422 }
4423
4424 /* check if it exists */
4425 FT_SLIST_FOREACH(ftfp, &ftfil->primitives, chain) {
4426
4427 if (!strcasecmp(c, ftfp->name)) {
4428 fterr_warnx("%s line %d: Name (%s) previously defined.", lp->fname,
4429 lp->lineno, c);
4430 return -1;
4431 }
4432
4433 }
4434
4435 /* no, add a new entry to the list */
4436 if (!(ftfp = (struct ftfil_primitive*)malloc(sizeof
4437 (struct ftfil_primitive)))) {
4438 fterr_warn("malloc()");
4439 return -1;
4440 }
4441
4442 bzero(ftfp, sizeof *ftfp);
4443
4444 if (!(ftfp->name = (char*)malloc(strlen(c)+1))) {
4445 fterr_warn("malloc()");
4446 free(ftfp);
4447 return -1;
4448 }
4449
4450 strcpy(ftfp->name, c);
4451
4452 FT_SLIST_INSERT_HEAD(&ftfil->primitives, ftfp, chain);
4453
4454 lp->state = PARSE_STATE_PRIMITIVE;
4455 lp->cur_primitive = ftfp;
4456
4457 return 0;
4458
4459 } /* parse_primitive */
4460
4461 /*
4462 * function: parse_primitive_type
4463 *
4464 * process the 'type' line. When the type is set the initial storage
4465 * is allocated.
4466 *
4467 * returns: 0 ok
4468 * <0 fail
4469 */
parse_primitive_type(struct line_parser * lp,struct ftfil * ftfil)4470 int parse_primitive_type(struct line_parser *lp, struct ftfil *ftfil)
4471 {
4472 struct ftfil_lookup_ip_address *ftflipa;
4473 struct ftfil_lookup_ip_prefix *ftflippr;
4474 struct ftfil_lookup_ip_mask *ftflipm;
4475 struct ftfil_lookup_as *ftfla;
4476 struct ftfil_lookup_ip_prefix_len *ftflipl;
4477 struct ftfil_lookup_ip_prot *ftflipp;
4478 struct ftfil_lookup_ip_tos *ftflipt;
4479 struct ftfil_lookup_ip_tcp_flags *ftfliptcp;
4480 struct ftfil_lookup_if_index *ftflif;
4481 struct ftfil_lookup_engine *ftfle;
4482 struct ftfil_lookup_ip_port *ftflippo;
4483 struct ftfil_lookup_counter *ftflc;
4484 struct ftfil_lookup_tag *ftflt;
4485 struct ftfil_lookup_tag_mask *ftfltm;
4486 struct ftfil_lookup_counter *ftfltme;
4487 struct ftfil_lookup_double *ftfld;
4488 struct ftfil_lookup_rate *ftflr;
4489
4490 if (!lp->cur_primitive) {
4491 fterr_warnx("%s line %d: Must set name first.", lp->fname, lp->lineno);
4492 return -1;
4493 }
4494
4495 NEXT_WORD(&lp->buf, lp->word);
4496
4497 if (!lp->word) {
4498 fterr_warnx("%s line %d: Expecting type.", lp->fname, lp->lineno);
4499 return -1;
4500 }
4501
4502 if (lp->cur_primitive->type) {
4503 fterr_warnx("%s line %d: Type previously defined.", lp->fname, lp->lineno);
4504 return -1;
4505 }
4506
4507 if (!strcasecmp(lp->word, "as")) {
4508
4509 lp->cur_primitive->type = FT_FIL_PRIMITIVE_TYPE_AS;
4510 PARSE_PRIMITIVE_TYPE_INIT(ftfla);
4511
4512 } else if (!strcasecmp(lp->word, "ip-address-prefix")) {
4513
4514 lp->cur_primitive->type = FT_FIL_PRIMITIVE_TYPE_IP_PREFIX;
4515 PARSE_PRIMITIVE_TYPE_INIT(ftflippr);
4516
4517 RADIX_TRIE_INIT;
4518
4519 if (rn_inithead((void**)&ftflippr->rhead, 32) < 0) {
4520 fterr_warnx("rn_inithead(): failed");
4521 return -1;
4522 }
4523
4524 } else if (!strcasecmp(lp->word, "ip-address")) {
4525
4526 lp->cur_primitive->type = FT_FIL_PRIMITIVE_TYPE_IP_ADDRESS;
4527 PARSE_PRIMITIVE_TYPE_INIT(ftflipa);
4528
4529 if (!(ftflipa->ftch = ftchash_new(4096,
4530 sizeof (struct ftchash_rec_fil_c32), 4, 12))) {
4531 fterr_warnx("ftchash_new(): failed");
4532 return -1;
4533 }
4534
4535 } else if (!strcasecmp(lp->word, "ip-address-mask")) {
4536
4537 lp->cur_primitive->type = FT_FIL_PRIMITIVE_TYPE_IP_MASK;
4538 PARSE_PRIMITIVE_TYPE_INIT(ftflipm);
4539 FT_STAILQ_INIT(&ftflipm->list);
4540
4541 } else if (!strcasecmp(lp->word, "ip-protocol")) {
4542
4543 lp->cur_primitive->type = FT_FIL_PRIMITIVE_TYPE_IP_PROTOCOL;
4544 PARSE_PRIMITIVE_TYPE_INIT(ftflipp);
4545
4546 } else if (!strcasecmp(lp->word, "ip-port")) {
4547
4548 lp->cur_primitive->type = FT_FIL_PRIMITIVE_TYPE_IP_PORT;
4549 PARSE_PRIMITIVE_TYPE_INIT(ftflippo);
4550
4551 } else if (!strcasecmp(lp->word, "ip-address-prefix-len")) {
4552
4553 lp->cur_primitive->type = FT_FIL_PRIMITIVE_TYPE_IP_PREFIX_LEN;
4554 PARSE_PRIMITIVE_TYPE_INIT(ftflipl);
4555
4556 } else if (!strcasecmp(lp->word, "ip-tos")) {
4557
4558 lp->cur_primitive->type = FT_FIL_PRIMITIVE_TYPE_IP_TOS;
4559 PARSE_PRIMITIVE_TYPE_INIT(ftflipt);
4560
4561 ftflipt->mask = 0xFF;
4562
4563 } else if (!strcasecmp(lp->word, "ip-tcp-flags")) {
4564
4565 lp->cur_primitive->type = FT_FIL_PRIMITIVE_TYPE_IP_TCP_FLAGS;
4566 PARSE_PRIMITIVE_TYPE_INIT(ftfliptcp);
4567
4568 ftfliptcp->mask = 0xFF;
4569
4570 } else if (!strcasecmp(lp->word, "ifindex")) {
4571
4572 lp->cur_primitive->type = FT_FIL_PRIMITIVE_TYPE_IF_INDEX;
4573 PARSE_PRIMITIVE_TYPE_INIT(ftflif);
4574
4575 } else if (!strcasecmp(lp->word, "counter")) {
4576
4577 lp->cur_primitive->type = FT_FIL_PRIMITIVE_TYPE_COUNTER;
4578 PARSE_PRIMITIVE_TYPE_INIT(ftflc);
4579
4580 FT_STAILQ_INIT(&ftflc->list);
4581
4582 } else if (!strcasecmp(lp->word, "time-date")) {
4583
4584 lp->cur_primitive->type = FT_FIL_PRIMITIVE_TYPE_TIME_DATE;
4585 PARSE_PRIMITIVE_TYPE_INIT(ftflc);
4586
4587 FT_STAILQ_INIT(&ftflc->list);
4588
4589 } else if (!strcasecmp(lp->word, "engine")) {
4590
4591 lp->cur_primitive->type = FT_FIL_PRIMITIVE_TYPE_ENGINE;
4592 PARSE_PRIMITIVE_TYPE_INIT(ftfle);
4593
4594 } else if (!strcasecmp(lp->word, "tag")) {
4595
4596 lp->cur_primitive->type = FT_FIL_PRIMITIVE_TYPE_TAG;
4597 PARSE_PRIMITIVE_TYPE_INIT(ftflt);
4598
4599 if (!(ftflt->ftch = ftchash_new(4096,
4600 sizeof (struct ftchash_rec_fil_c32), 4, 12))) {
4601 fterr_warnx("ftchash_new(): failed");
4602 return -1;
4603 }
4604
4605 } else if (!strcasecmp(lp->word, "tag-mask")) {
4606
4607 lp->cur_primitive->type = FT_FIL_PRIMITIVE_TYPE_TAG_MASK;
4608 PARSE_PRIMITIVE_TYPE_INIT(ftfltm);
4609
4610 FT_STAILQ_INIT(&ftfltm->list);
4611
4612 } else if (!strcasecmp(lp->word, "time")) {
4613
4614 lp->cur_primitive->type = FT_FIL_PRIMITIVE_TYPE_TIME;
4615 PARSE_PRIMITIVE_TYPE_INIT(ftfltme);
4616
4617 FT_STAILQ_INIT(&ftfltme->list);
4618
4619 } else if (!strcasecmp(lp->word, "double")) {
4620
4621 lp->cur_primitive->type = FT_FIL_PRIMITIVE_TYPE_DOUBLE;
4622 PARSE_PRIMITIVE_TYPE_INIT(ftfld);
4623
4624 FT_STAILQ_INIT(&ftfld->list);
4625
4626 } else if (!strcasecmp(lp->word, "rate")) {
4627
4628 lp->cur_primitive->type = FT_FIL_PRIMITIVE_TYPE_RATE;
4629 PARSE_PRIMITIVE_TYPE_INIT(ftflr);
4630
4631 /* initialize random number generator */
4632 srand(getpid() ^ time((time_t*)0L));
4633
4634 } else {
4635
4636 fterr_warnx("%s line %d: Unrecognized type.", lp->fname, lp->lineno);
4637 return -1;
4638
4639 }
4640
4641 return 0;
4642
4643 } /* parse_primitive_type */
4644
parse_primitive_permit(struct line_parser * lp,struct ftfil * ftfil)4645 int parse_primitive_permit(struct line_parser *lp, struct ftfil *ftfil)
4646 {
4647 return parse2_primitive_permitdeny(lp, ftfil, FT_FIL_MODE_PERMIT);
4648 }
4649
parse_primitive_deny(struct line_parser * lp,struct ftfil * ftfil)4650 int parse_primitive_deny(struct line_parser *lp, struct ftfil *ftfil)
4651 {
4652 return parse2_primitive_permitdeny(lp, ftfil, FT_FIL_MODE_DENY);
4653 }
4654
parse_primitive_default(struct line_parser * lp,struct ftfil * ftfil)4655 static int parse_primitive_default(struct line_parser *lp, struct ftfil *ftfil)
4656 {
4657 struct ftfil_lookup_ip_address *ftflipa;
4658 struct ftfil_lookup_ip_prefix *ftflippr;
4659 struct ftfil_lookup_ip_mask *ftflipm;
4660 struct ftfil_lookup_as *ftfla;
4661 struct ftfil_lookup_ip_prefix_len *ftflipl;
4662 struct ftfil_lookup_ip_prot *ftflipp;
4663 struct ftfil_lookup_ip_tos *ftflipt;
4664 struct ftfil_lookup_ip_tcp_flags *ftfliptcp;
4665 struct ftfil_lookup_if_index *ftflif;
4666 struct ftfil_lookup_engine *ftfle;
4667 struct ftfil_lookup_ip_port *ftflippo;
4668 struct ftfil_lookup_counter *ftflc;
4669 struct ftfil_lookup_tag *ftflt;
4670 struct ftfil_lookup_tag_mask *ftfltm;
4671 struct ftfil_lookup_counter *ftfltme;
4672 struct ftfil_lookup_counter *ftfld;
4673
4674 int flag;
4675
4676 NEXT_WORD(&lp->buf, lp->word);
4677
4678 if (!lp->word) {
4679 fterr_warnx("%s line %d: Expecting permit or deny.", lp->fname,
4680 lp->lineno);
4681 return -1;
4682 }
4683
4684 if (!strcasecmp(lp->word, "permit"))
4685 flag = FT_FIL_MODE_PERMIT;
4686 else if (!strcasecmp(lp->word, "deny"))
4687 flag = FT_FIL_MODE_DENY;
4688 else {
4689 fterr_warnx("%s line %d: Expecting permit or deny.", lp->fname,
4690 lp->lineno);
4691 return -1;
4692 }
4693
4694 switch (lp->cur_primitive->type) {
4695
4696 case FT_FIL_PRIMITIVE_TYPE_IP_ADDRESS:
4697 ftflipa = lp->cur_primitive->lookup;
4698 ftflipa->default_mode = flag;
4699 break;
4700
4701 case FT_FIL_PRIMITIVE_TYPE_IP_PREFIX:
4702 ftflippr = lp->cur_primitive->lookup;
4703 ftflippr->default_mode = flag;
4704 break;
4705
4706 case FT_FIL_PRIMITIVE_TYPE_IP_MASK:
4707 ftflipm = lp->cur_primitive->lookup;
4708 ftflipm->default_mode = flag;
4709 break;
4710
4711 case FT_FIL_PRIMITIVE_TYPE_AS:
4712 ftfla = lp->cur_primitive->lookup;
4713 ftfla->default_mode = flag;
4714 break;
4715
4716 case FT_FIL_PRIMITIVE_TYPE_IP_PROTOCOL:
4717 ftflipp = lp->cur_primitive->lookup;
4718 ftflipp->default_mode = flag;
4719 break;
4720
4721 case FT_FIL_PRIMITIVE_TYPE_IP_PREFIX_LEN:
4722 ftflipl = lp->cur_primitive->lookup;
4723 ftflipl->default_mode = flag;
4724 break;
4725
4726 case FT_FIL_PRIMITIVE_TYPE_IP_TOS:
4727 ftflipt = lp->cur_primitive->lookup;
4728 ftflipt->default_mode = flag;
4729 break;
4730
4731 case FT_FIL_PRIMITIVE_TYPE_IP_TCP_FLAGS:
4732 ftfliptcp = lp->cur_primitive->lookup;
4733 ftfliptcp->default_mode = flag;
4734 break;
4735
4736 case FT_FIL_PRIMITIVE_TYPE_IF_INDEX:
4737 ftflif = lp->cur_primitive->lookup;
4738 ftflif->default_mode = flag;
4739 break;
4740
4741 case FT_FIL_PRIMITIVE_TYPE_IP_PORT:
4742 ftflippo = lp->cur_primitive->lookup;
4743 ftflippo->default_mode = flag;
4744 break;
4745
4746 case FT_FIL_PRIMITIVE_TYPE_ENGINE:
4747 ftfle = lp->cur_primitive->lookup;
4748 ftfle->default_mode = flag;
4749 break;
4750
4751 case FT_FIL_PRIMITIVE_TYPE_TAG:
4752 ftflt = lp->cur_primitive->lookup;
4753 ftflt->default_mode = flag;
4754 break;
4755
4756 case FT_FIL_PRIMITIVE_TYPE_TAG_MASK:
4757 ftfltm = lp->cur_primitive->lookup;
4758 ftfltm->default_mode = flag;
4759 break;
4760
4761 case FT_FIL_PRIMITIVE_TYPE_COUNTER:
4762 ftflc = lp->cur_primitive->lookup;
4763 ftflc->default_mode = flag;
4764 break;
4765
4766 case FT_FIL_PRIMITIVE_TYPE_TIME_DATE:
4767 ftflc = lp->cur_primitive->lookup;
4768 ftflc->default_mode = flag;
4769 break;
4770
4771 case FT_FIL_PRIMITIVE_TYPE_TIME:
4772 ftfltme = lp->cur_primitive->lookup;
4773 ftfltme->default_mode = flag;
4774 break;
4775
4776 case FT_FIL_PRIMITIVE_TYPE_DOUBLE:
4777 ftfld = lp->cur_primitive->lookup;
4778 ftfld->default_mode = flag;
4779 break;
4780
4781 case FT_FIL_PRIMITIVE_TYPE_RATE:
4782 fterr_warnx("%s line %d: No default mode for rate.", lp->fname,
4783 lp->lineno);
4784 break;
4785
4786 default:
4787 fterr_errx(1, "parse_primitive_default(): internal error");
4788 break;
4789
4790 } /* switch */
4791
4792 return 0;
4793
4794 } /* parse_primitive_default */
4795
4796
4797 /*
4798 * function: parse2_primitive_permitdeny
4799 *
4800 * process the permit and deny lines
4801 *
4802 * returns: 0 ok
4803 * <0 fail
4804 */
parse2_primitive_permitdeny(struct line_parser * lp,struct ftfil * ftfil,int mode)4805 int parse2_primitive_permitdeny(struct line_parser *lp, struct ftfil *ftfil,
4806 int mode)
4807 {
4808 int ret;
4809
4810 ret = -1;
4811
4812 if (!lp->cur_primitive) {
4813 fterr_warnx("%s line %d: Must set type first.", lp->fname, lp->lineno);
4814 return -1;
4815 }
4816
4817 lp->mode = mode;
4818
4819 NEXT_WORD(&lp->buf, lp->word);
4820
4821 if (!lp->word) {
4822 fterr_warnx("%s line %d: Expecting permit/deny data.", lp->fname,
4823 lp->lineno);
4824 return -1;
4825 }
4826
4827 switch (lp->cur_primitive->type) {
4828
4829 case FT_FIL_PRIMITIVE_TYPE_AS:
4830 ret = parse_primitive_type_asn(lp, ftfil);
4831 break;
4832
4833 case FT_FIL_PRIMITIVE_TYPE_IP_PREFIX:
4834 ret = parse_primitive_type_ip_prefix(lp, ftfil);
4835 break;
4836
4837 case FT_FIL_PRIMITIVE_TYPE_IP_ADDRESS:
4838 ret = parse_primitive_type_ip_address(lp, ftfil);
4839 break;
4840
4841 case FT_FIL_PRIMITIVE_TYPE_IP_MASK:
4842 ret = parse_primitive_type_ip_mask(lp, ftfil);
4843 break;
4844
4845 case FT_FIL_PRIMITIVE_TYPE_IP_PROTOCOL:
4846 ret = parse_primitive_type_ip_prot(lp, ftfil);
4847 break;
4848
4849 case FT_FIL_PRIMITIVE_TYPE_IP_PORT:
4850 ret = parse_primitive_type_ip_port(lp, ftfil);
4851 break;
4852
4853 case FT_FIL_PRIMITIVE_TYPE_IP_PREFIX_LEN:
4854 ret = parse_primitive_type_ip_prefix_len(lp, ftfil);
4855 break;
4856
4857 case FT_FIL_PRIMITIVE_TYPE_IP_TOS:
4858 ret = parse_primitive_type_ip_tos(lp, ftfil);
4859 break;
4860
4861 case FT_FIL_PRIMITIVE_TYPE_IP_TCP_FLAGS:
4862 ret = parse_primitive_type_ip_tcp_flags(lp, ftfil);
4863 break;
4864
4865 case FT_FIL_PRIMITIVE_TYPE_IF_INDEX:
4866 ret = parse_primitive_type_if_index(lp, ftfil);
4867 break;
4868
4869 case FT_FIL_PRIMITIVE_TYPE_COUNTER:
4870 ret = parse_primitive_type_counter(lp, ftfil);
4871 break;
4872
4873 case FT_FIL_PRIMITIVE_TYPE_TIME_DATE:
4874 ret = parse_primitive_type_time_date(lp, ftfil);
4875 break;
4876
4877 case FT_FIL_PRIMITIVE_TYPE_ENGINE:
4878 ret = parse_primitive_type_engine(lp, ftfil);
4879 break;
4880
4881 case FT_FIL_PRIMITIVE_TYPE_TAG:
4882 ret = parse_primitive_type_tag(lp, ftfil);
4883 break;
4884
4885 case FT_FIL_PRIMITIVE_TYPE_TAG_MASK:
4886 ret = parse_primitive_type_tag_mask(lp, ftfil);
4887 break;
4888
4889 case FT_FIL_PRIMITIVE_TYPE_TIME:
4890 ret = parse_primitive_type_time(lp, ftfil);
4891 break;
4892
4893 case FT_FIL_PRIMITIVE_TYPE_DOUBLE:
4894 ret = parse_primitive_type_double(lp, ftfil);
4895 break;
4896
4897 case FT_FIL_PRIMITIVE_TYPE_RATE:
4898 ret = parse_primitive_type_rate(lp, ftfil);
4899 break;
4900
4901 default:
4902 fterr_errx(1, "parse_primitive_permitdeny(): internal error");
4903 break;
4904
4905 } /* switch */
4906
4907 return ret;
4908
4909 } /* parse_primitive_permitdeny */
4910
4911 /*
4912 * function: parse_primitive_mask
4913 *
4914 * process the 'mask' line.
4915 *
4916 * returns: 0 ok
4917 * <0 fail
4918 */
parse_primitive_mask(struct line_parser * lp,struct ftfil * ftfil)4919 int parse_primitive_mask(struct line_parser *lp, struct ftfil *ftfil)
4920 {
4921
4922 struct ftfil_lookup_ip_tos *ftflipt;
4923 struct ftfil_lookup_ip_tcp_flags *ftfliptcp;
4924
4925
4926 if (!lp->cur_primitive) {
4927 fterr_warnx("%s line %d: Must set name first.", lp->fname, lp->lineno);
4928 return -1;
4929 }
4930
4931 NEXT_WORD(&lp->buf, lp->word);
4932
4933 if (!lp->word) {
4934 fterr_warnx("%s line %d: Expecting mask value.", lp->fname, lp->lineno);
4935 return -1;
4936 }
4937
4938 switch (lp->cur_primitive->type) {
4939
4940 case FT_FIL_PRIMITIVE_TYPE_IP_TOS:
4941 ftflipt = lp->cur_primitive->lookup;
4942 ftflipt->mask = strtoul(lp->word, (char**)0L, 0);
4943 break;
4944
4945 case FT_FIL_PRIMITIVE_TYPE_IP_TCP_FLAGS:
4946 ftfliptcp = lp->cur_primitive->lookup;
4947 ftfliptcp->mask = strtoul(lp->word, (char**)0L, 0);
4948 break;
4949
4950 default:
4951 fterr_warnx("%s line %d: Mask not supported for primitive.", lp->fname,
4952 lp->lineno);
4953 return -1;
4954
4955 } /* switch */
4956
4957 return 0;
4958
4959 } /* parse_primitive_mask */
4960
4961 /*
4962 *************************************************************************
4963 internal support
4964 *************************************************************************
4965 */
4966
4967 /*
4968 * function: ftfil_load_lookup
4969 *
4970 * loads a list of , seperated numbers into an array
4971 * ! will invert the list
4972 * - can be used as a range operator
4973 *
4974 * example
4975 * 1,5-10 == 1,5,6,7,8,9,10
4976 * !1 == all numbers in the range except for 1
4977 *
4978 * Only ranges that have been specified will be initialized.
4979 *
4980 * The array will either be unset, or set
4981 * to FT_FL_MODE_PERMIT or FT_FL_MODE_DENY
4982 */
ftfil_load_lookup(struct line_parser * lp,char * s,int size,uint8_t * list,int mode)4983 static int ftfil_load_lookup(struct line_parser *lp, char *s, int size,
4984 uint8_t *list, int mode)
4985 {
4986 char *p, *q, *r, c;
4987 int j, flag;
4988 unsigned i, i2;
4989 int permit,deny;
4990 uint32_t val;
4991
4992 if (mode == FT_FIL_MODE_DENY) {
4993 permit = FT_FIL_MODE_DENY;
4994 deny = FT_FIL_MODE_PERMIT;
4995 } else if (mode == FT_FIL_MODE_PERMIT) {
4996 permit = FT_FIL_MODE_PERMIT;
4997 deny = FT_FIL_MODE_DENY;
4998 } else {
4999 fterr_errx(1, "ftfil_load_lookup(): internal error mode not set");
5000 }
5001
5002 p = s;
5003
5004 while ((*p == ' ') || (*p == '\t')) ++p;
5005 if (*p == '!') {
5006 flag = deny;
5007 ++p;
5008 } else {
5009 flag = permit;
5010 }
5011
5012 while (*p) {
5013
5014 /* skip white space */
5015 for (q = p; *q && (*q == ' ' || *q == '\t'); ++q);
5016
5017 /* skip to the end of the word */
5018 for (r = q; *r && (*r != ',' && *r != '-'); ++r);
5019
5020 /* save the character */
5021 c = *r;
5022
5023 /* q is the null terminated word now */
5024 *r = 0;
5025
5026 /* looks like a symbol? then try a lookup */
5027 if (isalpha((int)*q)) {
5028 if (lp->sym_cur && ftsym_findbyname(lp->sym_cur, q, &val))
5029 i = val;
5030 else {
5031 fterr_warnx("%s line %d: symbol lookup for \"%s\" failed.", lp->fname,
5032 lp->lineno, q);
5033 return -1;
5034 }
5035 } else
5036 i = (unsigned)strtoul(q, (char**)0L, 0);
5037
5038 if (i >= size) {
5039 fterr_warnx("%s line %d: Value out of range.", lp->fname, lp->lineno);
5040 return -1;
5041 }
5042
5043 if (list[i] != FT_FIL_MODE_UNSET)
5044 fterr_warnx("%s line %d: index %u previously set as %s.", lp->fname,
5045 lp->lineno, i, mode_name_lookup[list[i]]);
5046
5047 list[i] = flag;
5048
5049 /* if the next char was a null terminator, then done */
5050 if (!c)
5051 break;
5052
5053 /* skip to next word */
5054 p = r+1;
5055
5056 if (c == '-') {
5057
5058 /* skip white space */
5059 for (q = p; *q && (*q == ' ' || *q == '\t'); ++q);
5060
5061 /* skip to the end of the word */
5062 for (r = q; *r && (*r != ',' && *r != '-'); ++r);
5063
5064 /* save the character */
5065 c = *r;
5066
5067 /* q is the null terminated word now */
5068 *r = 0;
5069
5070 /* looks like a symbol? then try a lookup */
5071 if (isalpha((int)*q)) {
5072 if (lp->sym_cur && ftsym_findbyname(lp->sym_cur, q, &val))
5073 i2 = val;
5074 else {
5075 fterr_warnx("%s line %d: symbol lookup for \"%s\" failed.", lp->fname,
5076 lp->lineno, q);
5077 return -1;
5078 }
5079 } else
5080 i2 = (unsigned)strtoul(q, (char**)0L, 0);
5081
5082 if (i2 >= size) {
5083 fterr_warnx("%s line %d: Value out of range.", lp->fname, lp->lineno);
5084 return -1;
5085 }
5086
5087 for (j = i; j <= i2; ++j) {
5088
5089 if ((j != i) && (list[j] != FT_FIL_MODE_UNSET))
5090 fterr_warnx("%s line %d: index %u previously set as %s.", lp->fname,
5091 lp->lineno, j, mode_name_lookup[list[j]]);
5092
5093 list[j] = flag;
5094
5095 }
5096
5097 /* skip to next word */
5098 p = r+1;
5099
5100 /* if the next char was a null terminator, then done */
5101 if (!c)
5102 break;
5103
5104 }
5105
5106 } /* *p */
5107
5108 return 0;
5109
5110 } /* ftfil_load_lookup */
5111
walk_free(struct radix_node * rn,struct walkarg * UNUSED)5112 static int walk_free(struct radix_node *rn, struct walkarg *UNUSED)
5113 {
5114 struct ftfil_lookup_ip_prefix_rec *r;
5115 struct radix_sockaddr_in sock1, sock2;
5116
5117 r = (struct ftfil_lookup_ip_prefix_rec*)rn;
5118 bzero(&sock1, sizeof sock1);
5119 bzero(&sock2, sizeof sock2);
5120
5121 sock1.sin_addr.s_addr = r->addr.sin_addr.s_addr;
5122 sock1.sin_len = sizeof sock1;
5123 sock1.sin_family = AF_INET;
5124
5125 sock2.sin_addr.s_addr = (!r->masklen) ? 0: mask_lookup[r->masklen];
5126 sock2.sin_len = sizeof sock2;
5127 sock2.sin_family = AF_INET;
5128
5129 if (r != (struct ftfil_lookup_ip_prefix_rec*)rhead->rnh_deladdr(&sock1,
5130 &sock2, rhead))
5131 fterr_errx(1, "rn_deladdr(): failed.");
5132 else
5133 free(r);
5134
5135 return 0;
5136 } /* walk_free */
5137