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