1 /*
2 * Copyright (c) 2016-2020, Peter Haag
3 * Copyright (c) 2004-2008, SWITCH - Teleinformatikdienste fuer Lehre und Forschung
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * * Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 * * Neither the name of the author nor the names of its contributors may be
15 * used to endorse or promote products derived from this software without
16 * specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 *
30 */
31
32 %{
33
34 #ifdef HAVE_CONFIG_H
35 #include "config.h"
36 #endif
37
38 #include <stdio.h>
39 #include <sys/types.h>
40 #include <sys/socket.h>
41 #include <netinet/in.h>
42 #include <string.h>
43 #include <stdlib.h>
44 #include <errno.h>
45 #include <ctype.h>
46
47 #ifdef HAVE_STDINT_H
48 #include <stdint.h>
49 #endif
50
51 #include "util.h"
52 #include "output_util.h"
53 #include "rbtree.h"
54 #include "filter.h"
55 #include "nfdump.h"
56 #include "nffile.h"
57 #include "nftree.h"
58 #include "ipconv.h"
59
60 #define AnyMask 0xffffffffffffffffLL
61
62 /*
63 * function prototypes
64 */
65 static void yyerror(char *msg);
66
67 static uint32_t ChainHosts(uint64_t *offsets, uint64_t *hostlist, int num_records, int type);
68
69 static uint64_t VerifyMac(char *s);
70
71 static int InitSymbols(void);
72
73 static uint32_t Get_fwd_status_id(char *status);
74
75 enum { DIR_UNSPEC = 1,
76 SOURCE, DESTINATION, SOURCE_AND_DESTINATION, SOURCE_OR_DESTINATION,
77 DIR_IN, DIR_OUT,
78 IN_SRC, IN_DST, OUT_SRC, OUT_DST,
79 ADJ_PREV, ADJ_NEXT };
80
81 enum { IS_START = 0, IS_END };
82
83 /* var defs */
84 extern int lineno;
85 extern char *yytext;
86 extern uint64_t *IPstack;
87 extern uint32_t StartNode;
88 extern uint16_t Extended;
89 extern int (*FilterEngine)(uint32_t *);
90 extern char *FilterFilename;
91
92 static uint32_t num_ip;
93
94 static struct fwd_status_def_s {
95 uint32_t id;
96 char *name;
97 } fwd_status_def_list[] = {
98 { 0, "Ukwn"}, // Unknown
99 { 1, "Forw"}, // Normal forwarding
100 { 2, "Frag"}, // Fragmented
101 { 16, "Drop"}, // Drop
102 { 17, "DaclD"}, // Drop ACL deny
103 { 18, "Daclp"}, // Drop ACL drop
104 { 19, "Noroute"}, // Unroutable
105 { 20, "Dadj"}, // Drop Adjacency
106 { 21, "Dfrag"}, // Drop Fragmentation & DF set
107 { 22, "Dbadh"}, // Drop Bad header checksum
108 { 23, "Dbadtlen"}, // Drop Bad total Length
109 { 24, "Dbadhlen"}, // Drop Bad Header Length
110 { 25, "DbadTTL"}, // Drop bad TTL
111 { 26, "Dpolicy"}, // Drop Policer
112 { 27, "Dwred"}, // Drop WRED
113 { 28, "Drpf"}, // Drop RPF
114 { 29, "Dforus"}, // Drop For us
115 { 30, "DbadOf"}, // Drop Bad output interface
116 { 31, "Dhw"}, // Drop Hardware
117 { 128, "Term"}, // Terminate
118 { 129, "Tadj"}, // Terminate Punt Adjacency
119 { 130, "TincAdj"}, // Terminate Incomplete Adjacency
120 { 131, "Tforus"}, // Terminate For us
121 { 0, NULL} // Last entry
122 };
123
124 static char **fwd_status = NULL;
125
126 char yyerror_buff[256];
127
128 #define MPLSMAX 0x00ffffff
129 %}
130
131 %union {
132 uint64_t value;
133 char *s;
134 FilterParam_t param;
135 void *list;
136 }
137
138 %token ANY IP IF MAC MPLS TOS DIR FLAGS PROTO MASK HOSTNAME NET PORT FWDSTAT IN OUT SRC DST EQ LT GT PREV NEXT
139 %token NUMBER STRING IDENT PORTNUM ICMP_TYPE ICMP_CODE ENGINE_TYPE ENGINE_ID AS PACKETS BYTES FLOWS
140 %token PPS BPS BPP DURATION NOT
141 %token IPV4 IPV6 BGPNEXTHOP ROUTER VLAN
142 %token CLIENT SERVER APP LATENCY SYSID
143 %token ASA REASON DENIED XEVENT XIP XNET XPORT INGRESS EGRESS ACL ACE XACE
144 %token NAT ADD EVENT VRF NPORT NIP
145 %token PBLOCK START END STEP SIZE
146 %type <value> expr NUMBER PORTNUM ICMP_TYPE ICMP_CODE
147 %type <s> STRING REASON
148 %type <param> dqual term comp acl inout
149 %type <list> iplist ullist
150
151 %left '+' OR
152 %left '*' AND
153 %left NEGATE
154
155 %%
156 prog: /* empty */
157 | expr {
158 StartNode = $1;
159 }
160 ;
161
162 term: ANY { /* this is an unconditionally true expression, as a filter applies in any case */
163 $$.self = NewBlock(OffsetProto, 0, 0, CMP_EQ, FUNC_NONE, NULL );
164 }
165
166 | IDENT STRING {
167 if ( !ScreenIdentString($2) ) {
168 yyerror("Illegal ident string");
169 YYABORT;
170 }
171
172 uint32_t index = AddIdent($2);
173 $$.self = NewBlock(0, 0, index, CMP_IDENT, FUNC_NONE, NULL );
174 }
175
176 | IPV4 {
177 $$.self = NewBlock(OffsetRecordFlags, (1LL << ShiftRecordFlags) & MaskRecordFlags,
178 (0LL << ShiftRecordFlags) & MaskRecordFlags, CMP_EQ, FUNC_NONE, NULL);
179 }
180
181 | IPV6 {
182 $$.self = NewBlock(OffsetRecordFlags, (1LL << ShiftRecordFlags) & MaskRecordFlags,
183 (1LL << ShiftRecordFlags) & MaskRecordFlags, CMP_EQ, FUNC_NONE, NULL);
184 }
185
186 | PROTO NUMBER {
187 int64_t proto;
188 proto = $2;
189
190 if ( proto > 255 ) {
191 yyerror("Protocol number > 255");
192 YYABORT;
193 }
194 if ( proto < 0 ) {
195 yyerror("Unknown protocol");
196 YYABORT;
197 }
198 $$.self = NewBlock(OffsetProto, MaskProto, (proto << ShiftProto) & MaskProto, CMP_EQ, FUNC_NONE, NULL);
199
200 }
201
202 | PROTO STRING {
203 int64_t proto;
204 proto = ProtoNum($2);
205
206 if ( proto > 255 ) {
207 yyerror("Protocol number > 255");
208 YYABORT;
209 }
210 if ( proto < 0 ) {
211 yyerror("Unknown protocol");
212 YYABORT;
213 }
214 $$.self = NewBlock(OffsetProto, MaskProto, (proto << ShiftProto) & MaskProto, CMP_EQ, FUNC_NONE, NULL);
215 }
216
217 | dqual PACKETS comp NUMBER {
218
219 switch ( $1.direction ) {
220 case DIR_UNSPEC:
221 case DIR_IN:
222 $$.self = NewBlock(OffsetPackets, MaskPackets, $4, $3.comp, FUNC_NONE, NULL);
223 break;
224 case DIR_OUT:
225 $$.self = NewBlock(OffsetOutPackets, MaskPackets, $4, $3.comp, FUNC_NONE, NULL);
226 break;
227 default:
228 /* should never happen */
229 yyerror("This token is not expected here!");
230 YYABORT;
231 } // End of switch
232
233 }
234
235 | dqual BYTES comp NUMBER {
236
237 switch ( $1.direction ) {
238 case DIR_UNSPEC:
239 case DIR_IN:
240 $$.self = NewBlock(OffsetBytes, MaskBytes, $4, $3.comp, FUNC_NONE, NULL);
241 break;
242 case DIR_OUT:
243 $$.self = NewBlock(OffsetOutBytes, MaskBytes, $4, $3.comp, FUNC_NONE, NULL);
244 break;
245 default:
246 yyerror("This token is not expected here!");
247 YYABORT;
248 } // End of switch
249
250 }
251
252 | FLOWS comp NUMBER {
253 $$.self = NewBlock(OffsetAggrFlows, MaskFlows, $3, $2.comp, FUNC_NONE, NULL);
254 }
255
256 | PPS comp NUMBER {
257 $$.self = NewBlock(0, AnyMask, $3, $2.comp, FUNC_PPS, NULL);
258 }
259
260 | BPS comp NUMBER {
261 $$.self = NewBlock(0, AnyMask, $3, $2.comp, FUNC_BPS, NULL);
262 }
263
264 | BPP comp NUMBER {
265 $$.self = NewBlock(0, AnyMask, $3, $2.comp, FUNC_BPP, NULL);
266 }
267
268 | DURATION comp NUMBER {
269 $$.self = NewBlock(0, AnyMask, $3, $2.comp, FUNC_DURATION, NULL);
270 }
271
272 | dqual TOS comp NUMBER {
273 if ( $4 > 255 ) {
274 yyerror("TOS must be 0..255");
275 YYABORT;
276 }
277
278 switch ( $1.direction ) {
279 case DIR_UNSPEC:
280 case SOURCE:
281 $$.self = NewBlock(OffsetTos, MaskTos, ($4 << ShiftTos) & MaskTos, $3.comp, FUNC_NONE, NULL);
282 break;
283 case DESTINATION:
284 $$.self = NewBlock(OffsetDstTos, MaskDstTos, ($4 << ShiftDstTos) & MaskDstTos, $3.comp, FUNC_NONE, NULL);
285 break;
286 case SOURCE_OR_DESTINATION:
287 $$.self = Connect_OR(
288 NewBlock(OffsetTos, MaskTos, ($4 << ShiftTos) & MaskTos, $3.comp, FUNC_NONE, NULL),
289 NewBlock(OffsetDstTos, MaskDstTos, ($4 << ShiftDstTos) & MaskDstTos, $3.comp, FUNC_NONE, NULL)
290 );
291 break;
292 case SOURCE_AND_DESTINATION:
293 $$.self = Connect_AND(
294 NewBlock(OffsetTos, MaskTos, ($4 << ShiftTos) & MaskTos, $3.comp, FUNC_NONE, NULL),
295 NewBlock(OffsetDstTos, MaskDstTos, ($4 << ShiftDstTos) & MaskDstTos, $3.comp, FUNC_NONE, NULL)
296 );
297 break;
298 default:
299 yyerror("This token is not expected here!");
300 YYABORT;
301 }
302 }
303
304 | FLAGS comp NUMBER {
305 if ( $3 > 63 ) {
306 yyerror("Flags must be 0..63");
307 YYABORT;
308 }
309 $$.self = NewBlock(OffsetFlags, MaskFlags, ($3 << ShiftFlags) & MaskFlags, $2.comp, FUNC_NONE, NULL);
310 }
311
312 | FLAGS STRING {
313 uint64_t fl = 0;
314 int cnt = 0;
315 size_t len = strlen($2);
316
317 if ( len > 7 ) {
318 yyerror("Too many flags");
319 YYABORT;
320 }
321
322 if ( strchr($2, 'F') ) { fl |= 1; cnt++; }
323 if ( strchr($2, 'S') ) { fl |= 2; cnt++; }
324 if ( strchr($2, 'R') ) { fl |= 4; cnt++; }
325 if ( strchr($2, 'P') ) { fl |= 8; cnt++; }
326 if ( strchr($2, 'A') ) { fl |= 16; cnt++; }
327 if ( strchr($2, 'U') ) { fl |= 32; cnt++; }
328 if ( strchr($2, 'X') ) { fl = 63; cnt++; }
329
330 if ( cnt != len ) {
331 yyerror("Too many flags");
332 YYABORT;
333 }
334
335 $$.self = NewBlock(OffsetFlags, (fl << ShiftFlags) & MaskFlags,
336 (fl << ShiftFlags) & MaskFlags, CMP_FLAGS, FUNC_NONE, NULL);
337 }
338
339 | dqual IP STRING {
340 int af, bytes, ret;
341
342 ret = parse_ip(&af, $3, IPstack, &bytes, ALLOW_LOOKUP, &num_ip);
343
344 if ( ret == 0 ) {
345 yyerror("Error parsing IP address.");
346 YYABORT;
347 }
348
349 // ret == -1 will never happen here, as ALLOW_LOOKUP is set
350 if ( ret == -2 ) {
351 // could not resolv host => 'not any'
352 $$.self = Invert(NewBlock(OffsetProto, 0, 0, CMP_EQ, FUNC_NONE, NULL ));
353 } else {
354 uint64_t offsets[4] = {OffsetSrcIPv6a, OffsetSrcIPv6b, OffsetDstIPv6a, OffsetDstIPv6b };
355 if ( af && (( af == PF_INET && bytes != 4 ) || ( af == PF_INET6 && bytes != 16 ))) {
356 yyerror("incomplete IP address");
357 YYABORT;
358 }
359
360 switch ( $1.direction ) {
361 case SOURCE:
362 case DESTINATION:
363 $$.self = ChainHosts(offsets, IPstack, num_ip, $1.direction);
364 break;
365 case DIR_UNSPEC:
366 case SOURCE_OR_DESTINATION: {
367 uint32_t src = ChainHosts(offsets, IPstack, num_ip, SOURCE);
368 uint32_t dst = ChainHosts(offsets, IPstack, num_ip, DESTINATION);
369 $$.self = Connect_OR(src, dst);
370 } break;
371 case SOURCE_AND_DESTINATION: {
372 uint32_t src = ChainHosts(offsets, IPstack, num_ip, SOURCE);
373 uint32_t dst = ChainHosts(offsets, IPstack, num_ip, DESTINATION);
374 $$.self = Connect_AND(src, dst);
375 } break;
376 default:
377 yyerror("This token is not expected here!");
378 YYABORT;
379
380 } // End of switch
381
382 }
383 }
384
385 | dqual IP IN '[' iplist ']' {
386
387 switch ( $1.direction ) {
388 case SOURCE:
389 $$.self = NewBlock(OffsetSrcIPv6a, MaskIPv6, 0 , CMP_IPLIST, FUNC_NONE, (void *)$5 );
390 break;
391 case DESTINATION:
392 $$.self = NewBlock(OffsetDstIPv6a, MaskIPv6, 0 , CMP_IPLIST, FUNC_NONE, (void *)$5 );
393 break;
394 case DIR_UNSPEC:
395 case SOURCE_OR_DESTINATION:
396 $$.self = Connect_OR(
397 NewBlock(OffsetSrcIPv6a, MaskIPv6, 0 , CMP_IPLIST, FUNC_NONE, (void *)$5 ),
398 NewBlock(OffsetDstIPv6a, MaskIPv6, 0 , CMP_IPLIST, FUNC_NONE, (void *)$5 )
399 );
400 break;
401 case SOURCE_AND_DESTINATION:
402 $$.self = Connect_AND(
403 NewBlock(OffsetSrcIPv6a, MaskIPv6, 0 , CMP_IPLIST, FUNC_NONE, (void *)$5 ),
404 NewBlock(OffsetDstIPv6a, MaskIPv6, 0 , CMP_IPLIST, FUNC_NONE, (void *)$5 )
405 );
406 break;
407 default:
408 yyerror("This token is not expected here!");
409 YYABORT;
410 }
411 }
412
413 | NEXT IP STRING {
414 int af, bytes, ret;
415
416 ret = parse_ip(&af, $3, IPstack, &bytes, STRICT_IP, &num_ip);
417
418 if ( ret == 0 ) {
419 yyerror("Error parsing IP address.");
420 YYABORT;
421 }
422
423 if ( ret == -1 ) {
424 yyerror("IP address required - hostname not allowed here.");
425 YYABORT;
426 }
427 // ret == -2 will never happen here, as STRICT_IP is set
428
429 if ( af && (( af == PF_INET && bytes != 4 ) || ( af == PF_INET6 && bytes != 16 ))) {
430 yyerror("incomplete IP address");
431 YYABORT;
432 }
433
434 $$.self = Connect_AND(
435 NewBlock(OffsetNexthopv6b, MaskIPv6, IPstack[1] , CMP_EQ, FUNC_NONE, NULL ),
436 NewBlock(OffsetNexthopv6a, MaskIPv6, IPstack[0] , CMP_EQ, FUNC_NONE, NULL )
437 );
438 }
439
440 | NEXT IP IN '[' iplist ']' {
441
442 $$.self = NewBlock(OffsetNexthopv6a, MaskIPv6, 0 , CMP_IPLIST, FUNC_NONE, (void *)$5 );
443
444 }
445
446 | BGPNEXTHOP IP STRING {
447 int af, bytes, ret;
448
449 ret = parse_ip(&af, $3, IPstack, &bytes, STRICT_IP, &num_ip);
450
451 if ( ret == 0 ) {
452 yyerror("Error parsing IP address.");
453 YYABORT;
454 }
455
456 if ( ret == -1 ) {
457 yyerror("IP address required - hostname not allowed here.");
458 YYABORT;
459 }
460 // ret == -2 will never happen here, as STRICT_IP is set
461
462 if ( af && (( af == PF_INET && bytes != 4 ) || ( af == PF_INET6 && bytes != 16 ))) {
463 yyerror("incomplete IP address");
464 YYABORT;
465 }
466
467 $$.self = Connect_AND(
468 NewBlock(OffsetBGPNexthopv6b, MaskIPv6, IPstack[1] , CMP_EQ, FUNC_NONE, NULL ),
469 NewBlock(OffsetBGPNexthopv6a, MaskIPv6, IPstack[0] , CMP_EQ, FUNC_NONE, NULL )
470 );
471 }
472
473 | ROUTER IP STRING {
474 int af, bytes, ret;
475
476 ret = parse_ip(&af, $3, IPstack, &bytes, STRICT_IP, &num_ip);
477
478 if ( ret == 0 ) {
479 yyerror("Error parsing IP address.");
480 YYABORT;
481 }
482
483 if ( ret == -1 ) {
484 yyerror("IP address required - hostname not allowed here.");
485 YYABORT;
486 }
487 // ret == -2 will never happen here, as STRICT_IP is set
488
489 if ( af && (( af == PF_INET && bytes != 4 ) || ( af == PF_INET6 && bytes != 16 ))) {
490 yyerror("incomplete IP address");
491 YYABORT;
492 }
493
494 $$.self = Connect_AND(
495 NewBlock(OffsetRouterv6b, MaskIPv6, IPstack[1] , CMP_EQ, FUNC_NONE, NULL ),
496 NewBlock(OffsetRouterv6a, MaskIPv6, IPstack[0] , CMP_EQ, FUNC_NONE, NULL )
497 );
498 }
499
500 | CLIENT LATENCY comp NUMBER {
501 $$.self = NewBlock(OffsetClientLatency, MaskLatency, $4, $3.comp, FUNC_NONE, NULL);
502 }
503
504 | SERVER LATENCY comp NUMBER {
505 $$.self = NewBlock(OffsetServerLatency, MaskLatency, $4, $3.comp, FUNC_NONE, NULL);
506 }
507
508 | APP LATENCY comp NUMBER {
509 $$.self = NewBlock(OffsetAppLatency, MaskLatency, $4, $3.comp, FUNC_NONE, NULL);
510 }
511
512 | SYSID NUMBER {
513 if ( $2 > 255 ) {
514 yyerror("Router SysID expected between be 1..255");
515 YYABORT;
516 }
517 $$.self = NewBlock(OffsetExporterSysID, MaskExporterSysID, ($2 << ShiftExporterSysID) & MaskExporterSysID, CMP_EQ, FUNC_NONE, NULL);
518 }
519
520 | dqual PORT comp NUMBER {
521 if ( $4 > 65535 ) {
522 yyerror("Port outside of range 0..65535");
523 YYABORT;
524 }
525
526 switch ( $1.direction ) {
527 case SOURCE:
528 $$.self = NewBlock(OffsetPort, MaskSrcPort, ($4 << ShiftSrcPort) & MaskSrcPort, $3.comp, FUNC_NONE, NULL );
529 break;
530 case DESTINATION:
531 $$.self = NewBlock(OffsetPort, MaskDstPort, ($4 << ShiftDstPort) & MaskDstPort, $3.comp, FUNC_NONE, NULL );
532 break;
533 case DIR_UNSPEC:
534 case SOURCE_OR_DESTINATION:
535 $$.self = Connect_OR(
536 NewBlock(OffsetPort, MaskSrcPort, ($4 << ShiftSrcPort) & MaskSrcPort, $3.comp, FUNC_NONE, NULL ),
537 NewBlock(OffsetPort, MaskDstPort, ($4 << ShiftDstPort) & MaskDstPort, $3.comp, FUNC_NONE, NULL )
538 );
539 break;
540 case SOURCE_AND_DESTINATION:
541 $$.self = Connect_AND(
542 NewBlock(OffsetPort, MaskSrcPort, ($4 << ShiftSrcPort) & MaskSrcPort, $3.comp, FUNC_NONE, NULL ),
543 NewBlock(OffsetPort, MaskDstPort, ($4 << ShiftDstPort) & MaskDstPort, $3.comp, FUNC_NONE, NULL )
544 );
545 break;
546 default:
547 yyerror("This token is not expected here!");
548 YYABORT;
549 } // End switch
550
551 }
552
553 | dqual PORT IN PBLOCK {
554 #ifdef NSEL
555 switch ( $1.direction ) {
556 case SOURCE:
557 $$.self = NewBlock(OffsetPort, MaskSrcPort, ShiftSrcPort, CMP_EQ, FUNC_PBLOCK, NULL );
558 break;
559 case DESTINATION:
560 $$.self = NewBlock(OffsetPort, MaskDstPort, ShiftDstPort, CMP_EQ, FUNC_PBLOCK, NULL );
561 break;
562 case DIR_UNSPEC:
563 case SOURCE_OR_DESTINATION:
564 $$.self = Connect_OR(
565 NewBlock(OffsetPort, MaskSrcPort, ShiftSrcPort, CMP_EQ, FUNC_PBLOCK, NULL ),
566 NewBlock(OffsetPort, MaskDstPort, ShiftDstPort, CMP_EQ, FUNC_PBLOCK, NULL )
567 );
568 break;
569 default:
570 yyerror("This token is not expected here!");
571 YYABORT;
572 } // End switch
573
574 #else
575 yyerror("NAT filters not available");
576 YYABORT;
577 #endif
578 }
579
580 | dqual PORT IN '[' ullist ']' {
581 struct ULongListNode *node;
582 ULongtree_t *root = NULL;
583
584 if ( $1.direction == DIR_UNSPEC || $1.direction == SOURCE_OR_DESTINATION || $1.direction == SOURCE_AND_DESTINATION ) {
585 // src and/or dst port
586 // we need a second rbtree due to different shifts for src and dst ports
587 root = malloc(sizeof(ULongtree_t));
588
589 struct ULongListNode *n;
590 if ( root == NULL) {
591 yyerror("malloc() error");
592 YYABORT;
593 }
594 RB_INIT(root);
595
596 RB_FOREACH(node, ULongtree, (ULongtree_t *)$5) {
597 if ( node->value > 65535 ) {
598 yyerror("Port outside of range 0..65535");
599 YYABORT;
600 }
601 if ((n = malloc(sizeof(struct ULongListNode))) == NULL) {
602 yyerror("malloc() error");
603 YYABORT;
604 }
605 n->value = (node->value << ShiftDstPort) & MaskDstPort;
606 node->value = (node->value << ShiftSrcPort) & MaskSrcPort;
607 RB_INSERT(ULongtree, root, n);
608 }
609 }
610
611 switch ( $1.direction ) {
612 case SOURCE:
613 RB_FOREACH(node, ULongtree, (ULongtree_t *)$5) {
614 node->value = (node->value << ShiftSrcPort) & MaskSrcPort;
615 }
616 $$.self = NewBlock(OffsetPort, MaskSrcPort, 0, CMP_ULLIST, FUNC_NONE, (void *)$5 );
617 break;
618 case DESTINATION:
619 RB_FOREACH(node, ULongtree, (ULongtree_t *)$5) {
620 node->value = (node->value << ShiftDstPort) & MaskDstPort;
621 }
622 $$.self = NewBlock(OffsetPort, MaskDstPort, 0, CMP_ULLIST, FUNC_NONE, (void *)$5 );
623 break;
624 case DIR_UNSPEC:
625 case SOURCE_OR_DESTINATION:
626 $$.self = Connect_OR(
627 NewBlock(OffsetPort, MaskSrcPort, 0, CMP_ULLIST, FUNC_NONE, (void *)$5 ),
628 NewBlock(OffsetPort, MaskDstPort, 0, CMP_ULLIST, FUNC_NONE, (void *)root )
629 );
630 break;
631 case SOURCE_AND_DESTINATION:
632 $$.self = Connect_AND(
633 NewBlock(OffsetPort, MaskSrcPort, 0, CMP_ULLIST, FUNC_NONE, (void *)$5 ),
634 NewBlock(OffsetPort, MaskDstPort, 0, CMP_ULLIST, FUNC_NONE, (void *)root )
635 );
636 break;
637 default:
638 yyerror("This token is not expected here!");
639 YYABORT;
640 } // End of switch
641
642 }
643
644 | ICMP_TYPE NUMBER {
645 if ( $2 > 255 ) {
646 yyerror("ICMP tpye of range 0..15");
647 YYABORT;
648 }
649 $$.self = Connect_AND(
650 // imply proto ICMP with a proto ICMP block
651 Connect_OR (
652 NewBlock(OffsetProto, MaskProto, ((uint64_t)IPPROTO_ICMP << ShiftProto) & MaskProto, CMP_EQ, FUNC_NONE, NULL),
653 NewBlock(OffsetProto, MaskProto, ((uint64_t)IPPROTO_ICMPV6 << ShiftProto) & MaskProto, CMP_EQ, FUNC_NONE, NULL)
654 ),
655 NewBlock(OffsetPort, MaskICMPtype, ($2 << ShiftICMPtype) & MaskICMPtype, CMP_EQ, FUNC_NONE, NULL )
656 );
657
658 }
659
660 | ICMP_CODE NUMBER {
661 if ( $2 > 255 ) {
662 yyerror("ICMP code of range 0..15");
663 YYABORT;
664 }
665 $$.self = Connect_AND(
666 // imply proto ICMP with a proto ICMP block
667 Connect_OR (
668 NewBlock(OffsetProto, MaskProto, ((uint64_t)IPPROTO_ICMP << ShiftProto) & MaskProto, CMP_EQ, FUNC_NONE, NULL),
669 NewBlock(OffsetProto, MaskProto, ((uint64_t)IPPROTO_ICMPV6 << ShiftProto) & MaskProto, CMP_EQ, FUNC_NONE, NULL)
670 ),
671 NewBlock(OffsetPort, MaskICMPcode, ($2 << ShiftICMPcode) & MaskICMPcode, CMP_EQ, FUNC_NONE, NULL )
672 );
673
674 }
675
676 | ENGINE_TYPE comp NUMBER {
677 if ( $3 > 255 ) {
678 yyerror("Engine type of range 0..255");
679 YYABORT;
680 }
681 $$.self = NewBlock(OffsetRouterID, MaskEngineType, ($3 << ShiftEngineType) & MaskEngineType, $2.comp, FUNC_NONE, NULL);
682
683 }
684
685 | ENGINE_ID comp NUMBER {
686 if ( $3 > 255 ) {
687 yyerror("Engine ID of range 0..255");
688 YYABORT;
689 }
690 $$.self = NewBlock(OffsetRouterID, MaskEngineID, ($3 << ShiftEngineID) & MaskEngineID, $2.comp, FUNC_NONE, NULL);
691
692 }
693
694 | ASA EVENT REASON {
695 #ifdef NSEL
696 if ( strncasecmp($3,"ignore", 6) == 0) {
697 $$.self = NewBlock(OffsetConnID, MaskFWevent, ( NSEL_EVENT_IGNORE << ShiftFWevent) & MaskFWevent, CMP_EQ, FUNC_NONE, NULL );
698 } else if( strncasecmp($3,"create", 6) == 0) {
699 $$.self = NewBlock(OffsetConnID, MaskFWevent, ( NSEL_EVENT_CREATE << ShiftFWevent) & MaskFWevent, CMP_EQ, FUNC_NONE, NULL );
700 } else if( strncasecmp($3,"term", 4) == 0 || strncasecmp($3,"delete", 6) == 0) {
701 $$.self = NewBlock(OffsetConnID, MaskFWevent, ( NSEL_EVENT_DELETE << ShiftFWevent) & MaskFWevent, CMP_EQ, FUNC_NONE, NULL );
702 } else if (strncasecmp($3,"deny", 4) == 0) {
703 $$.self = NewBlock(OffsetConnID, MaskFWevent, ( NSEL_EVENT_DENIED << ShiftFWevent) & MaskFWevent, CMP_EQ, FUNC_NONE, NULL );
704 } else if (strncasecmp($3,"alert", 5) == 0) {
705 $$.self = NewBlock(OffsetConnID, MaskFWevent, ( NSEL_EVENT_ALERT << ShiftFWevent) & MaskFWevent, CMP_EQ, FUNC_NONE, NULL );
706 } else if (strncasecmp($3,"update", 6) == 0) {
707 $$.self = NewBlock(OffsetConnID, MaskFWevent, ( NSEL_EVENT_UPDATE << ShiftFWevent) & MaskFWevent, CMP_EQ, FUNC_NONE, NULL );
708 } else {
709 yyerror("Unknown asa event");
710 YYABORT;
711 }
712 #else
713 yyerror("NSEL/ASA filters not available");
714 YYABORT;
715 #endif
716 }
717
718 | ASA EVENT comp NUMBER {
719 #ifdef NSEL
720 if ( $4 > 255 ) {
721 yyerror("Invalid xevent ID");
722 YYABORT;
723 }
724 $$.self = NewBlock(OffsetConnID, MaskFWevent, ( $4 << ShiftFWevent) & MaskFWevent, $3.comp, FUNC_NONE, NULL );
725 #else
726 yyerror("NSEL/ASA filters not available");
727 YYABORT;
728 #endif
729 }
730
731 | ASA EVENT DENIED inout {
732 #ifdef NSEL
733 uint64_t xevent = 0;
734 if ( $4.inout == INGRESS ) {
735 xevent = 1001;
736 } else if ( $4.inout == EGRESS ) {
737 xevent = 1002;
738 } else {
739 yyerror("Invalid inout token");
740 YYABORT;
741 }
742 $$.self = Connect_AND(
743 NewBlock(OffsetConnID, MaskFWevent, ( NSEL_EVENT_DENIED << ShiftFWevent) & MaskFWevent, CMP_EQ, FUNC_NONE, NULL ),
744 NewBlock(OffsetConnID, MaskFWXevent, ( xevent << ShiftFWXevent) & MaskFWXevent, CMP_EQ, FUNC_NONE, NULL )
745 );
746 #else
747 yyerror("NSEL/ASA filters not available");
748 YYABORT;
749 #endif
750 }
751 | ASA EVENT DENIED STRING {
752 #ifdef NSEL
753 uint64_t xevent = 0;
754 if( strncasecmp($4,"interface", 9) == 0) {
755 xevent = 1003;
756 } else if( strncasecmp($4,"nosyn", 5) == 0) {
757 xevent = 1004;
758 } else {
759 xevent = (uint64_t)strtol($4, (char **)NULL, 10);
760 if ( (xevent == 0 && errno == EINVAL) || xevent > 65535 ) {
761 yyerror("Invalid xevent ID");
762 YYABORT;
763 }
764 }
765 $$.self = Connect_AND(
766 NewBlock(OffsetConnID, MaskFWevent, ( NSEL_EVENT_DENIED << ShiftFWevent) & MaskFWevent, CMP_EQ, FUNC_NONE, NULL ),
767 NewBlock(OffsetConnID, MaskFWXevent, ( xevent << ShiftFWXevent) & MaskFWXevent, CMP_EQ, FUNC_NONE, NULL )
768 );
769 #else
770 yyerror("NSEL/ASA filters not available");
771 YYABORT;
772 #endif
773 }
774
775 | ASA XEVENT comp NUMBER {
776 #ifdef NSEL
777 if ( $4 > 65535 ) {
778 yyerror("Invalid xevent ID");
779 YYABORT;
780 }
781 $$.self = NewBlock(OffsetConnID, MaskFWXevent, ( $4 << ShiftFWXevent) & MaskFWXevent, $3.comp, FUNC_NONE, NULL );
782 #else
783 yyerror("NSEL/ASA filters not available");
784 YYABORT;
785 #endif
786 }
787
788 | dqual XIP STRING {
789 #ifdef NSEL
790 int af, bytes, ret;
791
792 ret = parse_ip(&af, $3, IPstack, &bytes, ALLOW_LOOKUP, &num_ip);
793
794 if ( ret == 0 ) {
795 yyerror("Error parsing IP address.");
796 YYABORT;
797 }
798
799 // ret == -1 will never happen here, as ALLOW_LOOKUP is set
800 if ( ret == -2 ) {
801 // could not resolv host => 'not any'
802 $$.self = Invert(NewBlock(OffsetProto, 0, 0, CMP_EQ, FUNC_NONE, NULL ));
803 } else {
804 uint64_t offsets[4] = {OffsetXLATESRCv6a, OffsetXLATESRCv6b, OffsetXLATEDSTv6a, OffsetXLATEDSTv6b };
805 if ( af && (( af == PF_INET && bytes != 4 ) || ( af == PF_INET6 && bytes != 16 ))) {
806 yyerror("incomplete IP address");
807 YYABORT;
808 }
809
810 switch ( $1.direction ) {
811 case SOURCE:
812 case DESTINATION:
813 $$.self = ChainHosts(offsets, IPstack, num_ip, $1.direction);
814 break;
815 case DIR_UNSPEC:
816 case SOURCE_OR_DESTINATION: {
817 uint32_t src = ChainHosts(offsets, IPstack, num_ip, SOURCE);
818 uint32_t dst = ChainHosts(offsets, IPstack, num_ip, DESTINATION);
819 $$.self = Connect_OR(src, dst);
820 } break;
821 case SOURCE_AND_DESTINATION: {
822 uint32_t src = ChainHosts(offsets, IPstack, num_ip, SOURCE);
823 uint32_t dst = ChainHosts(offsets, IPstack, num_ip, DESTINATION);
824 $$.self = Connect_AND(src, dst);
825 } break;
826 default:
827 yyerror("This token is not expected here!");
828 YYABORT;
829
830 } // End of switch
831
832 }
833 #else
834 yyerror("NSEL/ASA filters not available");
835 YYABORT;
836 #endif
837 }
838
839 | dqual XNET STRING '/' NUMBER {
840 #ifdef NSEL
841 int af, bytes, ret;
842 uint64_t mask[2];
843
844 ret = parse_ip(&af, $3, IPstack, &bytes, STRICT_IP, &num_ip);
845 if ( ret == 0 ) {
846 yyerror("Invalid IP address");
847 YYABORT;
848 }
849 if ( ret == -1 ) {
850 yyerror("IP address required - hostname not allowed here.");
851 YYABORT;
852 }
853 // ret == -2 will never happen here, as STRICT_IP is set
854
855
856 if ( $5 > (bytes*8) ) {
857 yyerror("Too many netbits for this IP address");
858 YYABORT;
859 }
860
861 if ( af == PF_INET ) {
862 mask[0] = 0xffffffffffffffffLL;
863 mask[1] = 0xffffffffffffffffLL << ( 32 - $5 );
864 } else { // PF_INET6
865 if ( $5 > 64 ) {
866 mask[0] = 0xffffffffffffffffLL;
867 mask[1] = 0xffffffffffffffffLL << ( 128 - $5 );
868 } else {
869 mask[0] = 0xffffffffffffffffLL << ( 64 - $5 );
870 mask[1] = 0;
871 }
872 }
873 // IP aadresses are stored in network representation
874 mask[0] = mask[0];
875 mask[1] = mask[1];
876
877 IPstack[0] &= mask[0];
878 IPstack[1] &= mask[1];
879
880 switch ( $1.direction ) {
881 case SOURCE:
882 $$.self = Connect_AND(
883 NewBlock(OffsetXLATESRCv6b, mask[1], IPstack[1] , CMP_EQ, FUNC_NONE, NULL ),
884 NewBlock(OffsetXLATESRCv6a, mask[0], IPstack[0] , CMP_EQ, FUNC_NONE, NULL )
885 );
886 break;
887 case DESTINATION:
888 $$.self = Connect_AND(
889 NewBlock(OffsetXLATEDSTv6b, mask[1], IPstack[1] , CMP_EQ, FUNC_NONE, NULL ),
890 NewBlock(OffsetXLATEDSTv6a, mask[0], IPstack[0] , CMP_EQ, FUNC_NONE, NULL )
891 );
892 break;
893 case DIR_UNSPEC:
894 case SOURCE_OR_DESTINATION:
895 $$.self = Connect_OR(
896 Connect_AND(
897 NewBlock(OffsetXLATESRCv6b, mask[1], IPstack[1] , CMP_EQ, FUNC_NONE, NULL ),
898 NewBlock(OffsetXLATESRCv6a, mask[0], IPstack[0] , CMP_EQ, FUNC_NONE, NULL )
899 ),
900 Connect_AND(
901 NewBlock(OffsetXLATEDSTv6b, mask[1], IPstack[1] , CMP_EQ, FUNC_NONE, NULL ),
902 NewBlock(OffsetXLATEDSTv6a, mask[0], IPstack[0] , CMP_EQ, FUNC_NONE, NULL )
903 )
904 );
905 break;
906 case SOURCE_AND_DESTINATION:
907 $$.self = Connect_AND(
908 Connect_AND(
909 NewBlock(OffsetXLATESRCv6b, mask[1], IPstack[1] , CMP_EQ, FUNC_NONE, NULL ),
910 NewBlock(OffsetXLATESRCv6a, mask[0], IPstack[0] , CMP_EQ, FUNC_NONE, NULL )
911 ),
912 Connect_AND(
913 NewBlock(OffsetXLATEDSTv6b, mask[1], IPstack[1] , CMP_EQ, FUNC_NONE, NULL ),
914 NewBlock(OffsetXLATEDSTv6a, mask[0], IPstack[0] , CMP_EQ, FUNC_NONE, NULL )
915 )
916 );
917 break;
918 default:
919 yyerror("This token is not expected here!");
920 YYABORT;
921 } // End of switch
922
923 #else
924 yyerror("NSEL/ASA filters not available");
925 YYABORT;
926 #endif
927 }
928
929 | dqual XPORT comp NUMBER {
930 #ifdef NSEL
931 if ( $4 > 65535 ) {
932 yyerror("Port outside of range 0..65535");
933 YYABORT;
934 }
935
936 switch ( $1.direction ) {
937 case SOURCE:
938 $$.self = NewBlock(OffsetXLATEPort, MaskXLATESRCPORT, ($4 << ShiftXLATESRCPORT) & MaskXLATESRCPORT, $3.comp, FUNC_NONE, NULL );
939 break;
940 case DESTINATION:
941 $$.self = NewBlock(OffsetXLATEPort, MaskXLATEDSTPORT, ($4 << ShiftXLATEDSTPORT) & MaskXLATEDSTPORT, $3.comp, FUNC_NONE, NULL );
942 break;
943 case DIR_UNSPEC:
944 case SOURCE_OR_DESTINATION:
945 $$.self = Connect_OR(
946 NewBlock(OffsetXLATEPort, MaskXLATESRCPORT, ($4 << ShiftXLATESRCPORT) & MaskXLATESRCPORT, $3.comp, FUNC_NONE, NULL ),
947 NewBlock(OffsetXLATEPort, MaskXLATEDSTPORT, ($4 << ShiftXLATEDSTPORT) & MaskXLATEDSTPORT, $3.comp, FUNC_NONE, NULL )
948 );
949 break;
950 case SOURCE_AND_DESTINATION:
951 $$.self = Connect_AND(
952 NewBlock(OffsetXLATEPort, MaskXLATESRCPORT, ($4 << ShiftXLATESRCPORT) & MaskXLATESRCPORT, $3.comp, FUNC_NONE, NULL ),
953 NewBlock(OffsetXLATEPort, MaskXLATEDSTPORT, ($4 << ShiftXLATEDSTPORT) & MaskXLATEDSTPORT, $3.comp, FUNC_NONE, NULL )
954 );
955 break;
956 default:
957 yyerror("This token is not expected here!");
958 YYABORT;
959 } // End switch
960 #else
961 yyerror("NSEL/ASA filters not available");
962 YYABORT;
963 #endif
964
965 }
966
967 | inout acl comp NUMBER {
968 #ifdef NSEL
969 uint64_t offset, mask, shift;
970 if ( $1.inout == INGRESS ) {
971 switch ($2.acl) {
972 case ACL:
973 offset = OffsetIngressAclId;
974 mask = MaskIngressAclId;
975 shift = ShiftIngressAclId;
976 break;
977 case ACE:
978 offset = OffsetIngressAceId;
979 mask = MaskIngressAceId;
980 shift = ShiftIngressAceId;
981 break;
982 case XACE:
983 offset = OffsetIngressGrpId;
984 mask = MaskIngressGrpId;
985 shift = ShiftIngressGrpId;
986 break;
987 default:
988 yyerror("Invalid ACL specifier");
989 YYABORT;
990 }
991 } else if ( $1.inout == EGRESS && $$.acl == ACL ) {
992 offset = OffsetEgressAclId;
993 mask = MaskEgressAclId;
994 shift = ShiftEgressAclId;
995 } else {
996 yyerror("ingress/egress syntax error");
997 YYABORT;
998 }
999 $$.self = NewBlock(offset, mask, ($4 << shift) & mask , $3.comp, FUNC_NONE, NULL );
1000
1001 #else
1002 yyerror("NSEL/ASA filters not available");
1003 YYABORT;
1004 #endif
1005 }
1006
1007 | NAT EVENT REASON {
1008 #ifdef NSEL
1009 if ( strncasecmp($3,"invalid", 7) == 0) {
1010 $$.self = NewBlock(OffsetNATevent, MasNATevent, ( NEL_EVENT_INVALID << ShiftNATevent) & MasNATevent, CMP_EQ, FUNC_NONE, NULL );
1011 } else if( strncasecmp($3,"add", 3) == 0 || strncasecmp($3,"create", 6) == 0) {
1012 $$.self = NewBlock(OffsetNATevent, MasNATevent, ( NEL_EVENT_ADD << ShiftNATevent) & MasNATevent, CMP_EQ, FUNC_NONE, NULL );
1013 } else if( strncasecmp($3,"delete", 6) == 0) {
1014 $$.self = NewBlock(OffsetNATevent, MasNATevent, ( NEL_EVENT_DELETE << ShiftNATevent) & MasNATevent, CMP_EQ, FUNC_NONE, NULL );
1015 } else {
1016 yyerror("Unknown nat event");
1017 YYABORT;
1018 }
1019 #else
1020 yyerror("NAT filters not available");
1021 YYABORT;
1022 #endif
1023 }
1024
1025 | NAT EVENT comp NUMBER {
1026 #ifdef NSEL
1027 if ( $4 > 255 ) {
1028 yyerror("Invalid event ID");
1029 YYABORT;
1030 }
1031 $$.self = NewBlock(OffsetNATevent, MasNATevent, ( $4 << ShiftNATevent) & MasNATevent, $3.comp, FUNC_NONE, NULL );
1032 #else
1033 yyerror("NAT filters not available");
1034 YYABORT;
1035 #endif
1036 }
1037
1038 | INGRESS VRF comp NUMBER {
1039 #ifdef NSEL
1040 if ( $4 > 0xFFFFFFFFLL ) {
1041 yyerror("Invalid ingress vrf ID");
1042 YYABORT;
1043 }
1044 $$.self = NewBlock(OffsetIVRFID, MaskIVRFID, ( $4 << ShiftIVRFID) & MaskIVRFID, $3.comp, FUNC_NONE, NULL );
1045 #else
1046 yyerror("NAT filters not available");
1047 YYABORT;
1048 #endif
1049 }
1050
1051 | EGRESS VRF comp NUMBER {
1052 #ifdef NSEL
1053 if ( $4 > 0xFFFFFFFFLL ) {
1054 yyerror("Invalid egress vrf ID");
1055 YYABORT;
1056 }
1057 $$.self = NewBlock(OffsetEVRFID, MaskEVRFID, ( $4 << ShiftEVRFID) & MaskEVRFID, $3.comp, FUNC_NONE, NULL );
1058 #else
1059 yyerror("NAT filters not available");
1060 YYABORT;
1061 #endif
1062 }
1063
1064 | PBLOCK START comp NUMBER {
1065 #ifdef NSEL
1066 if ( $4 > 65536 ) {
1067 yyerror("Invalid port");
1068 YYABORT;
1069 }
1070 $$.self = NewBlock(OffsetPortBlock, MaskPortBlockStart, ( $4 << ShiftPortBlockStart) & MaskPortBlockStart, $3.comp, FUNC_NONE, NULL );
1071 #else
1072 yyerror("NAT filters not available");
1073 YYABORT;
1074 #endif
1075 }
1076
1077 | PBLOCK END comp NUMBER {
1078 #ifdef NSEL
1079 if ( $4 > 65536 ) {
1080 yyerror("Invalid port");
1081 YYABORT;
1082 }
1083 $$.self = NewBlock(OffsetPortBlock, MaskPortBlockEnd, ( $4 << ShiftPortBlockEnd) & MaskPortBlockEnd, $3.comp, FUNC_NONE, NULL );
1084 #else
1085 yyerror("NAT filters not available");
1086 YYABORT;
1087 #endif
1088 }
1089
1090 | PBLOCK STEP comp NUMBER {
1091 #ifdef NSEL
1092 if ( $4 > 65536 ) {
1093 yyerror("Invalid port");
1094 YYABORT;
1095 }
1096 $$.self = NewBlock(OffsetPortBlock, MaskPortBlockStep, ( $4 << ShiftPortBlockStep) & MaskPortBlockStep, $3.comp, FUNC_NONE, NULL );
1097 #else
1098 yyerror("NAT filters not available");
1099 YYABORT;
1100 #endif
1101 }
1102
1103 | PBLOCK SIZE comp NUMBER {
1104 #ifdef NSEL
1105 if ( $4 > 65536 ) {
1106 yyerror("Invalid port");
1107 YYABORT;
1108 }
1109 $$.self = NewBlock(OffsetPortBlock, MaskPortBlockSize, ( $4 << ShiftPortBlockSize) & MaskPortBlockSize, $3.comp, FUNC_NONE, NULL );
1110 #else
1111 yyerror("NAT filters not available");
1112 YYABORT;
1113 #endif
1114 }
1115
1116 | dqual NPORT comp NUMBER {
1117 #ifdef NSEL
1118 if ( $4 > 65535 ) {
1119 yyerror("Port outside of range 0..65535");
1120 YYABORT;
1121 }
1122
1123 switch ( $1.direction ) {
1124 case SOURCE:
1125 $$.self = NewBlock(OffsetXLATEPort, MaskXLATESRCPORT, ($4 << ShiftXLATESRCPORT) & MaskXLATESRCPORT, $3.comp, FUNC_NONE, NULL );
1126 break;
1127 case DESTINATION:
1128 $$.self = NewBlock(OffsetXLATEPort, MaskXLATEDSTPORT, ($4 << ShiftXLATEDSTPORT) & MaskXLATEDSTPORT, $3.comp, FUNC_NONE, NULL );
1129 break;
1130 case DIR_UNSPEC:
1131 case SOURCE_OR_DESTINATION:
1132 $$.self = Connect_OR(
1133 NewBlock(OffsetXLATEPort, MaskXLATESRCPORT, ($4 << ShiftXLATESRCPORT) & MaskXLATESRCPORT, $3.comp, FUNC_NONE, NULL ),
1134 NewBlock(OffsetXLATEPort, MaskXLATEDSTPORT, ($4 << ShiftXLATEDSTPORT) & MaskXLATEDSTPORT, $3.comp, FUNC_NONE, NULL )
1135 );
1136 break;
1137 case SOURCE_AND_DESTINATION:
1138 $$.self = Connect_AND(
1139 NewBlock(OffsetXLATEPort, MaskXLATESRCPORT, ($4 << ShiftXLATESRCPORT) & MaskXLATESRCPORT, $3.comp, FUNC_NONE, NULL ),
1140 NewBlock(OffsetXLATEPort, MaskXLATEDSTPORT, ($4 << ShiftXLATEDSTPORT) & MaskXLATEDSTPORT, $3.comp, FUNC_NONE, NULL )
1141 );
1142 break;
1143 default:
1144 yyerror("This token is not expected here!");
1145 YYABORT;
1146 } // End switch
1147 #else
1148 yyerror("NEL/NAT filters not available");
1149 YYABORT;
1150 #endif
1151
1152 }
1153
1154 | dqual NIP STRING {
1155 #ifdef NSEL
1156 int af, bytes, ret;
1157
1158 ret = parse_ip(&af, $3, IPstack, &bytes, ALLOW_LOOKUP, &num_ip);
1159
1160 if ( ret == 0 ) {
1161 yyerror("Error parsing IP address.");
1162 YYABORT;
1163 }
1164
1165 // ret == -1 will never happen here, as ALLOW_LOOKUP is set
1166 if ( ret == -2 ) {
1167 // could not resolv host => 'not any'
1168 $$.self = Invert(NewBlock(OffsetProto, 0, 0, CMP_EQ, FUNC_NONE, NULL ));
1169 } else {
1170 uint64_t offsets[4] = {OffsetXLATESRCv6a, OffsetXLATESRCv6b, OffsetXLATEDSTv6a, OffsetXLATEDSTv6b };
1171 if ( af && (( af == PF_INET && bytes != 4 ) || ( af == PF_INET6 && bytes != 16 ))) {
1172 yyerror("incomplete IP address");
1173 YYABORT;
1174 }
1175
1176 switch ( $1.direction ) {
1177 case SOURCE:
1178 case DESTINATION:
1179 $$.self = ChainHosts(offsets, IPstack, num_ip, $1.direction);
1180 break;
1181 case DIR_UNSPEC:
1182 case SOURCE_OR_DESTINATION: {
1183 uint32_t src = ChainHosts(offsets, IPstack, num_ip, SOURCE);
1184 uint32_t dst = ChainHosts(offsets, IPstack, num_ip, DESTINATION);
1185 $$.self = Connect_OR(src, dst);
1186 } break;
1187 case SOURCE_AND_DESTINATION: {
1188 uint32_t src = ChainHosts(offsets, IPstack, num_ip, SOURCE);
1189 uint32_t dst = ChainHosts(offsets, IPstack, num_ip, DESTINATION);
1190 $$.self = Connect_AND(src, dst);
1191 } break;
1192 default:
1193 yyerror("This token is not expected here!");
1194 YYABORT;
1195
1196 } // End of switch
1197
1198 }
1199 #else
1200 yyerror("NSEL/ASA filters not available");
1201 YYABORT;
1202 #endif
1203 }
1204
1205 | dqual AS comp NUMBER {
1206 if ( $4 > 0xfFFFFFFF ) {
1207 yyerror("AS number of range");
1208 YYABORT;
1209 }
1210
1211 switch ( $1.direction ) {
1212 case SOURCE:
1213 $$.self = NewBlock(OffsetAS, MaskSrcAS, ($4 << ShiftSrcAS) & MaskSrcAS, $3.comp, FUNC_NONE, NULL );
1214 break;
1215 case DESTINATION:
1216 $$.self = NewBlock(OffsetAS, MaskDstAS, ($4 << ShiftDstAS) & MaskDstAS, $3.comp, FUNC_NONE, NULL);
1217 break;
1218 case DIR_UNSPEC:
1219 case SOURCE_OR_DESTINATION:
1220 $$.self = Connect_OR(
1221 NewBlock(OffsetAS, MaskSrcAS, ($4 << ShiftSrcAS) & MaskSrcAS, $3.comp, FUNC_NONE, NULL ),
1222 NewBlock(OffsetAS, MaskDstAS, ($4 << ShiftDstAS) & MaskDstAS, $3.comp, FUNC_NONE, NULL)
1223 );
1224 break;
1225 case SOURCE_AND_DESTINATION:
1226 $$.self = Connect_AND(
1227 NewBlock(OffsetAS, MaskSrcAS, ($4 << ShiftSrcAS) & MaskSrcAS, $3.comp, FUNC_NONE, NULL ),
1228 NewBlock(OffsetAS, MaskDstAS, ($4 << ShiftDstAS) & MaskDstAS, $3.comp, FUNC_NONE, NULL)
1229 );
1230 break;
1231 case ADJ_PREV:
1232 $$.self = NewBlock(OffsetBGPadj, MaskBGPadjPrev, ($4 << ShiftBGPadjPrev) & MaskBGPadjPrev, $3.comp, FUNC_NONE, NULL );
1233 break;
1234 case ADJ_NEXT:
1235 $$.self = NewBlock(OffsetBGPadj, MaskBGPadjNext, ($4 << ShiftBGPadjNext) & MaskBGPadjNext, $3.comp, FUNC_NONE, NULL );
1236 break;
1237 default:
1238 yyerror("This token is not expected here!");
1239 YYABORT;
1240 } // End of switch
1241
1242 }
1243
1244 | dqual AS IN '[' ullist ']' {
1245 struct ULongListNode *node;
1246 ULongtree_t *root = NULL;
1247
1248 if ( $1.direction == DIR_UNSPEC || $1.direction == SOURCE_OR_DESTINATION || $1.direction == SOURCE_AND_DESTINATION ) {
1249 // src and/or dst AS
1250 // we need a second rbtree due to different shifts for src and dst AS
1251 root = malloc(sizeof(ULongtree_t));
1252
1253 struct ULongListNode *n;
1254 if ( root == NULL) {
1255 yyerror("malloc() error");
1256 YYABORT;
1257 }
1258 RB_INIT(root);
1259
1260 RB_FOREACH(node, ULongtree, (ULongtree_t *)$5) {
1261 if ( node->value > 0xFFFFFFFFLL ) {
1262 yyerror("AS number of range");
1263 YYABORT;
1264 }
1265 if ((n = malloc(sizeof(struct ULongListNode))) == NULL) {
1266 yyerror("malloc() error");
1267 YYABORT;
1268 }
1269 n->value = (node->value << ShiftDstAS) & MaskDstAS;
1270 node->value = (node->value << ShiftSrcAS) & MaskSrcAS;
1271 RB_INSERT(ULongtree, root, n);
1272 }
1273 }
1274
1275 switch ( $1.direction ) {
1276 case SOURCE:
1277 RB_FOREACH(node, ULongtree, (ULongtree_t *)$5) {
1278 node->value = (node->value << ShiftSrcAS) & MaskSrcAS;
1279 }
1280 $$.self = NewBlock(OffsetAS, MaskSrcAS, 0, CMP_ULLIST, FUNC_NONE, (void *)$5 );
1281 break;
1282 case DESTINATION:
1283 RB_FOREACH(node, ULongtree, (ULongtree_t *)$5) {
1284 node->value = (node->value << ShiftDstAS) & MaskDstAS;
1285 }
1286 $$.self = NewBlock(OffsetAS, MaskDstAS, 0, CMP_ULLIST, FUNC_NONE, (void *)$5 );
1287 break;
1288 case DIR_UNSPEC:
1289 case SOURCE_OR_DESTINATION:
1290 $$.self = Connect_OR(
1291 NewBlock(OffsetAS, MaskSrcAS, 0, CMP_ULLIST, FUNC_NONE, (void *)$5 ),
1292 NewBlock(OffsetAS, MaskDstAS, 0, CMP_ULLIST, FUNC_NONE, (void *)root )
1293 );
1294 break;
1295 case SOURCE_AND_DESTINATION:
1296 $$.self = Connect_AND(
1297 NewBlock(OffsetAS, MaskSrcAS, 0, CMP_ULLIST, FUNC_NONE, (void *)$5 ),
1298 NewBlock(OffsetAS, MaskDstAS, 0, CMP_ULLIST, FUNC_NONE, (void *)root )
1299 );
1300 break;
1301 default:
1302 yyerror("This token is not expected here!");
1303 YYABORT;
1304 }
1305
1306 }
1307
1308 | dqual MASK NUMBER {
1309 if ( $3 > 255 ) {
1310 yyerror("Mask outside of range 0..255");
1311 YYABORT;
1312 }
1313
1314 switch ( $1.direction ) {
1315 case SOURCE:
1316 $$.self = NewBlock(OffsetMask, MaskSrcMask, ($3 << ShiftSrcMask) & MaskSrcMask, CMP_EQ, FUNC_NONE, NULL );
1317 break;
1318 case DESTINATION:
1319 $$.self = NewBlock(OffsetMask, MaskDstMask, ($3 << ShiftDstMask) & MaskDstMask, CMP_EQ, FUNC_NONE, NULL );
1320 break;
1321 case DIR_UNSPEC:
1322 case SOURCE_OR_DESTINATION:
1323 $$.self = Connect_OR(
1324 NewBlock(OffsetMask, MaskSrcMask, ($3 << ShiftSrcMask) & MaskSrcMask, CMP_EQ, FUNC_NONE, NULL ),
1325 NewBlock(OffsetMask, MaskDstMask, ($3 << ShiftDstMask) & MaskDstMask, CMP_EQ, FUNC_NONE, NULL )
1326 );
1327 break;
1328 case SOURCE_AND_DESTINATION:
1329 $$.self = Connect_AND(
1330 NewBlock(OffsetMask, MaskSrcMask, ($3 << ShiftSrcMask) & MaskSrcMask, CMP_EQ, FUNC_NONE, NULL ),
1331 NewBlock(OffsetMask, MaskDstMask, ($3 << ShiftDstMask) & MaskDstMask, CMP_EQ, FUNC_NONE, NULL )
1332 );
1333 break;
1334 default:
1335 yyerror("This token is not expected here!");
1336 YYABORT;
1337 } // End switch
1338
1339 }
1340
1341 | dqual NET STRING STRING {
1342 int af, bytes, ret;
1343 uint64_t mask[2];
1344 ret = parse_ip(&af, $3, IPstack, &bytes, STRICT_IP, &num_ip);
1345
1346 if ( ret == 0 ) {
1347 yyerror("Invalid IP address");
1348 YYABORT;
1349 }
1350
1351 if ( ret == -1 ) {
1352 yyerror("IP address required - hostname not allowed here.");
1353 YYABORT;
1354 }
1355 // ret == -2 will never happen here, as STRICT_IP is set
1356
1357 if ( af != PF_INET ) {
1358 yyerror("IP netmask syntax valid only for IPv4");
1359 YYABORT;
1360 }
1361 if ( bytes != 4 ) {
1362 yyerror("Need complete IP address");
1363 YYABORT;
1364 }
1365
1366 ret = parse_ip(&af, $4, mask, &bytes, STRICT_IP, &num_ip);
1367 if ( ret == 0 ) {
1368 yyerror("Invalid IP address");
1369 YYABORT;
1370 }
1371 if ( ret == -1 ) {
1372 yyerror("IP address required - hostname not allowed here.");
1373 YYABORT;
1374 }
1375 // ret == -2 will never happen here, as STRICT_IP is set
1376
1377 if ( af != PF_INET || bytes != 4 ) {
1378 yyerror("Invalid netmask for IPv4 address");
1379 YYABORT;
1380 }
1381
1382 IPstack[0] &= mask[0];
1383 IPstack[1] &= mask[1];
1384
1385 switch ( $1.direction ) {
1386 case SOURCE:
1387 $$.self = Connect_AND(
1388 NewBlock(OffsetSrcIPv6b, mask[1], IPstack[1] , CMP_EQ, FUNC_NONE, NULL ),
1389 NewBlock(OffsetSrcIPv6a, mask[0], IPstack[0] , CMP_EQ, FUNC_NONE, NULL )
1390 );
1391 break;
1392 case DESTINATION:
1393 $$.self = Connect_AND(
1394 NewBlock(OffsetDstIPv6b, mask[1], IPstack[1] , CMP_EQ, FUNC_NONE, NULL ),
1395 NewBlock(OffsetDstIPv6a, mask[0], IPstack[0] , CMP_EQ, FUNC_NONE, NULL )
1396 );
1397 break;
1398 case DIR_UNSPEC:
1399 case SOURCE_OR_DESTINATION:
1400 $$.self = Connect_OR(
1401 Connect_AND(
1402 NewBlock(OffsetSrcIPv6b, mask[1], IPstack[1] , CMP_EQ, FUNC_NONE, NULL ),
1403 NewBlock(OffsetSrcIPv6a, mask[0], IPstack[0] , CMP_EQ, FUNC_NONE, NULL )
1404 ),
1405 Connect_AND(
1406 NewBlock(OffsetDstIPv6b, mask[1], IPstack[1] , CMP_EQ, FUNC_NONE, NULL ),
1407 NewBlock(OffsetDstIPv6a, mask[0], IPstack[0] , CMP_EQ, FUNC_NONE, NULL )
1408 )
1409 );
1410 break;
1411 case SOURCE_AND_DESTINATION:
1412 $$.self = Connect_AND(
1413 Connect_AND(
1414 NewBlock(OffsetSrcIPv6b, mask[1], IPstack[1] , CMP_EQ, FUNC_NONE, NULL ),
1415 NewBlock(OffsetSrcIPv6a, mask[0], IPstack[0] , CMP_EQ, FUNC_NONE, NULL )
1416 ),
1417 Connect_AND(
1418 NewBlock(OffsetDstIPv6b, mask[1], IPstack[1] , CMP_EQ, FUNC_NONE, NULL ),
1419 NewBlock(OffsetDstIPv6a, mask[0], IPstack[0] , CMP_EQ, FUNC_NONE, NULL )
1420 )
1421 );
1422 break;
1423 default:
1424 /* should never happen */
1425 yyerror("This token is not expected here!");
1426 YYABORT;
1427 } // End of switch
1428
1429 }
1430
1431 | dqual NET STRING '/' NUMBER {
1432 int af, bytes, ret;
1433 uint64_t mask[2];
1434
1435 ret = parse_ip(&af, $3, IPstack, &bytes, STRICT_IP, &num_ip);
1436 if ( ret == 0 ) {
1437 yyerror("Invalid IP address");
1438 YYABORT;
1439 }
1440 if ( ret == -1 ) {
1441 yyerror("IP address required - hostname not allowed here.");
1442 YYABORT;
1443 }
1444 // ret == -2 will never happen here, as STRICT_IP is set
1445
1446
1447 if ( $5 > (bytes*8) ) {
1448 yyerror("Too many netbits for this IP address");
1449 YYABORT;
1450 }
1451
1452 if ( af == PF_INET ) {
1453 mask[0] = 0xffffffffffffffffLL;
1454 mask[1] = 0xffffffffffffffffLL << ( 32 - $5 );
1455 } else { // PF_INET6
1456 if ( $5 > 64 ) {
1457 mask[0] = 0xffffffffffffffffLL;
1458 mask[1] = 0xffffffffffffffffLL << ( 128 - $5 );
1459 } else {
1460 mask[0] = 0xffffffffffffffffLL << ( 64 - $5 );
1461 mask[1] = 0;
1462 }
1463 }
1464 // IP aadresses are stored in network representation
1465 mask[0] = mask[0];
1466 mask[1] = mask[1];
1467
1468 IPstack[0] &= mask[0];
1469 IPstack[1] &= mask[1];
1470
1471 switch ( $1.direction ) {
1472 case SOURCE:
1473 $$.self = Connect_AND(
1474 NewBlock(OffsetSrcIPv6b, mask[1], IPstack[1] , CMP_EQ, FUNC_NONE, NULL ),
1475 NewBlock(OffsetSrcIPv6a, mask[0], IPstack[0] , CMP_EQ, FUNC_NONE, NULL )
1476 );
1477 break;
1478 case DESTINATION:
1479 $$.self = Connect_AND(
1480 NewBlock(OffsetDstIPv6b, mask[1], IPstack[1] , CMP_EQ, FUNC_NONE, NULL ),
1481 NewBlock(OffsetDstIPv6a, mask[0], IPstack[0] , CMP_EQ, FUNC_NONE, NULL )
1482 );
1483 break;
1484 case DIR_UNSPEC:
1485 case SOURCE_OR_DESTINATION:
1486 $$.self = Connect_OR(
1487 Connect_AND(
1488 NewBlock(OffsetSrcIPv6b, mask[1], IPstack[1] , CMP_EQ, FUNC_NONE, NULL ),
1489 NewBlock(OffsetSrcIPv6a, mask[0], IPstack[0] , CMP_EQ, FUNC_NONE, NULL )
1490 ),
1491 Connect_AND(
1492 NewBlock(OffsetDstIPv6b, mask[1], IPstack[1] , CMP_EQ, FUNC_NONE, NULL ),
1493 NewBlock(OffsetDstIPv6a, mask[0], IPstack[0] , CMP_EQ, FUNC_NONE, NULL )
1494 )
1495 );
1496 break;
1497 case SOURCE_AND_DESTINATION:
1498 $$.self = Connect_AND(
1499 Connect_AND(
1500 NewBlock(OffsetSrcIPv6b, mask[1], IPstack[1] , CMP_EQ, FUNC_NONE, NULL ),
1501 NewBlock(OffsetSrcIPv6a, mask[0], IPstack[0] , CMP_EQ, FUNC_NONE, NULL )
1502 ),
1503 Connect_AND(
1504 NewBlock(OffsetDstIPv6b, mask[1], IPstack[1] , CMP_EQ, FUNC_NONE, NULL ),
1505 NewBlock(OffsetDstIPv6a, mask[0], IPstack[0] , CMP_EQ, FUNC_NONE, NULL )
1506 )
1507 );
1508 break;
1509 default:
1510 yyerror("This token is not expected here!");
1511 YYABORT;
1512 } // End of switch
1513
1514 }
1515
1516 | dqual IF NUMBER {
1517 if ( $3 > 0xffffffffLL ) {
1518 yyerror("Input interface number must 0..2^32");
1519 YYABORT;
1520 }
1521
1522 switch ( $1.direction ) {
1523 case DIR_UNSPEC:
1524 $$.self = Connect_OR(
1525 NewBlock(OffsetInOut, MaskInput, ($3 << ShiftInput) & MaskInput, CMP_EQ, FUNC_NONE, NULL),
1526 NewBlock(OffsetInOut, MaskOutput, ($3 << ShiftOutput) & MaskOutput, CMP_EQ, FUNC_NONE, NULL)
1527 );
1528 break;
1529 case DIR_IN:
1530 $$.self = NewBlock(OffsetInOut, MaskInput, ($3 << ShiftInput) & MaskInput, CMP_EQ, FUNC_NONE, NULL);
1531 break;
1532 case DIR_OUT:
1533 $$.self = NewBlock(OffsetInOut, MaskOutput, ($3 << ShiftOutput) & MaskOutput, CMP_EQ, FUNC_NONE, NULL);
1534 break;
1535 default:
1536 yyerror("This token is not expected here!");
1537 YYABORT;
1538 } // End of switch
1539
1540 }
1541
1542 | dqual VLAN NUMBER {
1543 if ( $3 > 65535 ) {
1544 yyerror("VLAN number of range 0..65535");
1545 YYABORT;
1546 }
1547
1548 switch ( $1.direction ) {
1549 case SOURCE:
1550 $$.self = NewBlock(OffsetVlan, MaskSrcVlan, ($3 << ShiftSrcVlan) & MaskSrcVlan, CMP_EQ, FUNC_NONE, NULL );
1551 break;
1552 case DESTINATION:
1553 $$.self = NewBlock(OffsetVlan, MaskDstVlan, ($3 << ShiftDstVlan) & MaskDstVlan, CMP_EQ, FUNC_NONE, NULL);
1554 break;
1555 case DIR_UNSPEC:
1556 case SOURCE_OR_DESTINATION:
1557 $$.self = Connect_OR(
1558 NewBlock(OffsetVlan, MaskSrcVlan, ($3 << ShiftSrcVlan) & MaskSrcVlan, CMP_EQ, FUNC_NONE, NULL ),
1559 NewBlock(OffsetVlan, MaskDstVlan, ($3 << ShiftDstVlan) & MaskDstVlan, CMP_EQ, FUNC_NONE, NULL)
1560 );
1561 break;
1562 case SOURCE_AND_DESTINATION:
1563 $$.self = Connect_AND(
1564 NewBlock(OffsetVlan, MaskSrcVlan, ($3 << ShiftSrcVlan) & MaskSrcVlan, CMP_EQ, FUNC_NONE, NULL ),
1565 NewBlock(OffsetVlan, MaskDstVlan, ($3 << ShiftDstVlan) & MaskDstVlan, CMP_EQ, FUNC_NONE, NULL)
1566 );
1567 break;
1568 default:
1569 yyerror("This token is not expected here!");
1570 YYABORT;
1571 } // End of switch
1572
1573 }
1574
1575 | dqual MAC STRING {
1576 uint64_t mac = VerifyMac($3);
1577 if ( mac == 0 ) {
1578 yyerror("Invalid MAC address format");
1579 YYABORT;
1580 }
1581 switch ( $1.direction ) {
1582 case DIR_UNSPEC: {
1583 uint32_t in, out;
1584 in = Connect_OR(
1585 NewBlock(OffsetInSrcMAC, MaskMac, mac, CMP_EQ, FUNC_NONE, NULL ),
1586 NewBlock(OffsetInDstMAC, MaskMac, mac, CMP_EQ, FUNC_NONE, NULL )
1587 );
1588 out = Connect_OR(
1589 NewBlock(OffsetOutSrcMAC, MaskMac, mac, CMP_EQ, FUNC_NONE, NULL ),
1590 NewBlock(OffsetOutDstMAC, MaskMac, mac, CMP_EQ, FUNC_NONE, NULL )
1591 );
1592 $$.self = Connect_OR(in, out);
1593 } break;
1594 case DIR_IN:
1595 $$.self = Connect_OR(
1596 NewBlock(OffsetInSrcMAC, MaskMac, mac, CMP_EQ, FUNC_NONE, NULL ),
1597 NewBlock(OffsetInDstMAC, MaskMac, mac, CMP_EQ, FUNC_NONE, NULL )
1598 );
1599 break;
1600 case DIR_OUT:
1601 $$.self = Connect_OR(
1602 NewBlock(OffsetOutSrcMAC, MaskMac, mac, CMP_EQ, FUNC_NONE, NULL ),
1603 NewBlock(OffsetOutDstMAC, MaskMac, mac, CMP_EQ, FUNC_NONE, NULL )
1604 );
1605 break;
1606 case SOURCE:
1607 $$.self = Connect_OR(
1608 NewBlock(OffsetInSrcMAC, MaskMac, mac, CMP_EQ, FUNC_NONE, NULL ),
1609 NewBlock(OffsetOutSrcMAC, MaskMac, mac, CMP_EQ, FUNC_NONE, NULL )
1610 );
1611 break;
1612 case DESTINATION:
1613 $$.self = Connect_OR(
1614 NewBlock(OffsetInDstMAC, MaskMac, mac, CMP_EQ, FUNC_NONE, NULL ),
1615 NewBlock(OffsetOutDstMAC, MaskMac, mac, CMP_EQ, FUNC_NONE, NULL )
1616 );
1617 break;
1618 case IN_SRC:
1619 $$.self = NewBlock(OffsetInSrcMAC, MaskMac, mac, CMP_EQ, FUNC_NONE, NULL );
1620 break;
1621 case IN_DST:
1622 $$.self = NewBlock(OffsetInDstMAC, MaskMac, mac, CMP_EQ, FUNC_NONE, NULL );
1623 break;
1624 case OUT_SRC:
1625 $$.self = NewBlock(OffsetOutSrcMAC, MaskMac, mac, CMP_EQ, FUNC_NONE, NULL );
1626 break;
1627 case OUT_DST:
1628 $$.self = NewBlock(OffsetOutDstMAC, MaskMac, mac, CMP_EQ, FUNC_NONE, NULL );
1629 break;
1630 break;
1631 default:
1632 yyerror("This token is not expected here!");
1633 YYABORT;
1634 } // End of switch
1635 }
1636
1637 | MPLS STRING comp NUMBER {
1638 if ( $4 > MPLSMAX ) {
1639 yyerror("MPLS value out of range");
1640 YYABORT;
1641 }
1642
1643 // search for label1 - label10
1644 if ( strncasecmp($2, "label", 5) == 0 ) {
1645 uint64_t mask;
1646 uint32_t offset, shift;
1647 char *s = &$2[5];
1648 if ( *s == '\0' ) {
1649 yyerror("Missing label number");
1650 YYABORT;
1651 }
1652 int i = (int)strtol(s, (char **)NULL, 10);
1653
1654 switch (i) {
1655 case 1:
1656 offset = OffsetMPLS12;
1657 mask = MaskMPLSlabelOdd;
1658 shift = ShiftMPLSlabelOdd;
1659 break;
1660 case 2:
1661 offset = OffsetMPLS12;
1662 mask = MaskMPLSlabelEven;
1663 shift = ShiftMPLSlabelEven;
1664 break;
1665 case 3:
1666 offset = OffsetMPLS34;
1667 mask = MaskMPLSlabelOdd;
1668 shift = ShiftMPLSlabelOdd;
1669 break;
1670 case 4:
1671 offset = OffsetMPLS34;
1672 mask = MaskMPLSlabelEven;
1673 shift = ShiftMPLSlabelEven;
1674 break;
1675 case 5:
1676 offset = OffsetMPLS56;
1677 mask = MaskMPLSlabelOdd;
1678 shift = ShiftMPLSlabelOdd;
1679 break;
1680 case 6:
1681 offset = OffsetMPLS56;
1682 mask = MaskMPLSlabelEven;
1683 shift = ShiftMPLSlabelEven;
1684 break;
1685 case 7:
1686 offset = OffsetMPLS78;
1687 mask = MaskMPLSlabelOdd;
1688 shift = ShiftMPLSlabelOdd;
1689 break;
1690 case 8:
1691 offset = OffsetMPLS78;
1692 mask = MaskMPLSlabelEven;
1693 shift = ShiftMPLSlabelEven;
1694 break;
1695 case 9:
1696 offset = OffsetMPLS910;
1697 mask = MaskMPLSlabelOdd;
1698 shift = ShiftMPLSlabelOdd;
1699 break;
1700 case 10:
1701 offset = OffsetMPLS910;
1702 mask = MaskMPLSlabelEven;
1703 shift = ShiftMPLSlabelEven;
1704 break;
1705 default:
1706 yyerror("MPLS label out of range 1..10");
1707 YYABORT;
1708 }
1709 $$.self = NewBlock(offset, mask, ($4 << shift) & mask, $3.comp, FUNC_NONE, NULL );
1710
1711 } else if ( strcasecmp($2, "eos") == 0 ) {
1712 // match End of Stack label
1713 $$.self = NewBlock(0, AnyMask, $4 << 4, $3.comp, FUNC_MPLS_EOS, NULL );
1714
1715 } else if ( strncasecmp($2, "exp", 3) == 0 ) {
1716 uint64_t mask;
1717 uint32_t offset, shift;
1718 char *s = &$2[3];
1719 if ( *s == '\0' ) {
1720 yyerror("Missing label number");
1721 YYABORT;
1722 }
1723 int i = (int)strtol(s, (char **)NULL, 10);
1724
1725 if ( $4 > 7 ) {
1726 yyerror("MPLS exp value out of range");
1727 YYABORT;
1728 }
1729
1730 switch (i) {
1731 case 1:
1732 offset = OffsetMPLS12;
1733 mask = MaskMPLSexpOdd;
1734 shift = ShiftMPLSexpOdd;
1735 break;
1736 case 2:
1737 offset = OffsetMPLS12;
1738 mask = MaskMPLSexpEven;
1739 shift = ShiftMPLSexpEven;
1740 break;
1741 case 3:
1742 offset = OffsetMPLS34;
1743 mask = MaskMPLSexpOdd;
1744 shift = ShiftMPLSexpOdd;
1745 break;
1746 case 4:
1747 offset = OffsetMPLS34;
1748 mask = MaskMPLSexpEven;
1749 shift = ShiftMPLSexpEven;
1750 break;
1751 case 5:
1752 offset = OffsetMPLS56;
1753 mask = MaskMPLSexpOdd;
1754 shift = ShiftMPLSexpOdd;
1755 break;
1756 case 6:
1757 offset = OffsetMPLS56;
1758 mask = MaskMPLSexpEven;
1759 shift = ShiftMPLSexpEven;
1760 break;
1761 case 7:
1762 offset = OffsetMPLS78;
1763 mask = MaskMPLSexpOdd;
1764 shift = ShiftMPLSexpOdd;
1765 break;
1766 case 8:
1767 offset = OffsetMPLS78;
1768 mask = MaskMPLSexpEven;
1769 shift = ShiftMPLSexpEven;
1770 break;
1771 case 9:
1772 offset = OffsetMPLS910;
1773 mask = MaskMPLSexpOdd;
1774 shift = ShiftMPLSexpOdd;
1775 break;
1776 case 10:
1777 offset = OffsetMPLS910;
1778 mask = MaskMPLSexpEven;
1779 shift = ShiftMPLSexpEven;
1780 break;
1781 default:
1782 yyerror("MPLS label out of range 1..10");
1783 YYABORT;
1784 }
1785 $$.self = NewBlock(offset, mask, $4 << shift, $3.comp, FUNC_NONE, NULL );
1786
1787 } else {
1788 yyerror("Unknown MPLS option");
1789 YYABORT;
1790 }
1791 }
1792 | MPLS ANY NUMBER {
1793 uint32_t *opt = malloc(sizeof(uint32_t));
1794 if ( $3 > MPLSMAX ) {
1795 yyerror("MPLS value out of range");
1796 YYABORT;
1797 }
1798 if ( opt == NULL) {
1799 yyerror("malloc() error");
1800 YYABORT;
1801 }
1802 *opt = $3 << 4;
1803 $$.self = NewBlock(0, AnyMask, $3 << 4, CMP_EQ, FUNC_MPLS_ANY, opt );
1804
1805 }
1806 | FWDSTAT NUMBER {
1807 if ( $2 > 255 ) {
1808 yyerror("Forwarding status of range 0..255");
1809 YYABORT;
1810 }
1811 $$.self = NewBlock(OffsetStatus, MaskStatus, ($2 << ShiftStatus) & MaskStatus, CMP_EQ, FUNC_NONE, NULL);
1812 }
1813
1814 | FWDSTAT STRING {
1815 uint64_t id = Get_fwd_status_id($2);
1816 if (id == 256 ) {
1817 yyerror("Unknown forwarding status");
1818 YYABORT;
1819 }
1820
1821 $$.self = NewBlock(OffsetStatus, MaskStatus, (id << ShiftStatus) & MaskStatus, CMP_EQ, FUNC_NONE, NULL);
1822
1823 }
1824
1825 | DIR NUMBER {
1826 if ( $2 > 2 ) {
1827 yyerror("Flow direction status of range 0, 1");
1828 YYABORT;
1829 }
1830 $$.self = NewBlock(OffsetDir, MaskDir, ($2 << ShiftDir) & MaskDir, CMP_EQ, FUNC_NONE, NULL);
1831
1832 }
1833
1834 | DIR inout {
1835 uint64_t dir = 0xFF;
1836 if ( $2.inout == INGRESS )
1837 dir = 0;
1838 else if ( $2.inout == EGRESS )
1839 dir = 1;
1840 else {
1841 yyerror("Flow direction status of range ingress, egress");
1842 YYABORT;
1843 }
1844
1845 $$.self = NewBlock(OffsetDir, MaskDir, (dir << ShiftDir) & MaskDir, CMP_EQ, FUNC_NONE, NULL);
1846
1847 }
1848
1849 /* iplist definition */
1850 iplist: STRING {
1851 int i, af, bytes, ret;
1852 struct IPListNode *node;
1853
1854 IPlist_t *root = malloc(sizeof(IPlist_t));
1855
1856 if ( root == NULL) {
1857 yyerror("malloc() error");
1858 YYABORT;
1859 }
1860 RB_INIT(root);
1861
1862 ret = parse_ip(&af, $1, IPstack, &bytes, ALLOW_LOOKUP, &num_ip);
1863
1864 if ( ret == 0 ) {
1865 yyerror("Invalid IP address");
1866 YYABORT;
1867 }
1868 // ret == -1 will never happen here, as ALLOW_LOOKUP is set
1869
1870 if ( ret != -2 ) {
1871 if ( af && (( af == PF_INET && bytes != 4 ) || ( af == PF_INET6 && bytes != 16 ))) {
1872 yyerror("incomplete IP address");
1873 YYABORT;
1874 }
1875
1876 for ( i=0; i<num_ip; i++ ) {
1877 if ((node = malloc(sizeof(struct IPListNode))) == NULL) {
1878 yyerror("malloc() error");
1879 YYABORT;
1880 }
1881 node->ip[0] = IPstack[2*i];
1882 node->ip[1] = IPstack[2*i+1];
1883 node->mask[0] = 0xffffffffffffffffLL;
1884 node->mask[1] = 0xffffffffffffffffLL;
1885 RB_INSERT(IPtree, root, node);
1886 }
1887
1888 }
1889 $$ = (void *)root;
1890
1891 }
1892
1893 iplist: STRING '/' NUMBER {
1894 int af, bytes, ret;
1895 struct IPListNode *node;
1896
1897 IPlist_t *root = malloc(sizeof(IPlist_t));
1898
1899 if ( root == NULL) {
1900 yyerror("malloc() error");
1901 YYABORT;
1902 }
1903 RB_INIT(root);
1904
1905 ret = parse_ip(&af, $1, IPstack, &bytes, STRICT_IP, &num_ip);
1906
1907 if ( ret == 0 ) {
1908 yyerror("Invalid IP address");
1909 YYABORT;
1910 }
1911 // ret == -1 will never happen here, as ALLOW_LOOKUP is set
1912
1913 if ( ret != -2 ) {
1914 if ( af && (( af == PF_INET && bytes != 4 ) || ( af == PF_INET6 && bytes != 16 ))) {
1915 yyerror("incomplete IP address");
1916 YYABORT;
1917 }
1918
1919 if ((node = malloc(sizeof(struct IPListNode))) == NULL) {
1920 yyerror("malloc() error");
1921 YYABORT;
1922 }
1923
1924 if ( af == PF_INET ) {
1925 node->mask[0] = 0xffffffffffffffffLL;
1926 node->mask[1] = 0xffffffffffffffffLL << ( 32 - $3 );
1927 } else { // PF_INET6
1928 if ( $3 > 64 ) {
1929 node->mask[0] = 0xffffffffffffffffLL;
1930 node->mask[1] = 0xffffffffffffffffLL << ( 128 - $3 );
1931 } else {
1932 node->mask[0] = 0xffffffffffffffffLL << ( 64 - $3 );
1933 node->mask[1] = 0;
1934 }
1935 }
1936
1937 node->ip[0] = IPstack[0] & node->mask[0];
1938 node->ip[1] = IPstack[1] & node->mask[1];
1939
1940 RB_INSERT(IPtree, root, node);
1941
1942 }
1943 $$ = (void *)root;
1944
1945 }
1946
1947 | iplist STRING {
1948 int i, af, bytes, ret;
1949 struct IPListNode *node;
1950
1951 ret = parse_ip(&af, $2, IPstack, &bytes, ALLOW_LOOKUP, &num_ip);
1952
1953 if ( ret == 0 ) {
1954 yyerror("Invalid IP address");
1955 YYABORT;
1956 }
1957 if ( af && (( af == PF_INET && bytes != 4 ) || ( af == PF_INET6 && bytes != 16 ))) {
1958 yyerror("incomplete IP address");
1959 YYABORT;
1960 }
1961
1962 // ret == - 2 means lookup failure
1963 if ( ret != -2 ) {
1964 for ( i=0; i<num_ip; i++ ) {
1965 if ((node = malloc(sizeof(struct IPListNode))) == NULL) {
1966 yyerror("malloc() error");
1967 YYABORT;
1968 }
1969 node->ip[0] = IPstack[2*i];
1970 node->ip[1] = IPstack[2*i+1];
1971 node->mask[0] = 0xffffffffffffffffLL;
1972 node->mask[1] = 0xffffffffffffffffLL;
1973
1974 RB_INSERT(IPtree, (IPlist_t *)$$, node);
1975 }
1976 }
1977 }
1978 | iplist ',' STRING {
1979 int i, af, bytes, ret;
1980 struct IPListNode *node;
1981
1982 ret = parse_ip(&af, $3, IPstack, &bytes, ALLOW_LOOKUP, &num_ip);
1983
1984 if ( ret == 0 ) {
1985 yyerror("Invalid IP address");
1986 YYABORT;
1987 }
1988 if ( af && (( af == PF_INET && bytes != 4 ) || ( af == PF_INET6 && bytes != 16 ))) {
1989 yyerror("incomplete IP address");
1990 YYABORT;
1991 }
1992
1993 // ret == - 2 means lookup failure
1994 if ( ret != -2 ) {
1995 for ( i=0; i<num_ip; i++ ) {
1996 if ((node = malloc(sizeof(struct IPListNode))) == NULL) {
1997 yyerror("malloc() error");
1998 YYABORT;
1999 }
2000 node->ip[0] = IPstack[2*i];
2001 node->ip[1] = IPstack[2*i+1];
2002 node->mask[0] = 0xffffffffffffffffLL;
2003 node->mask[1] = 0xffffffffffffffffLL;
2004
2005 RB_INSERT(IPtree, (IPlist_t *)$$, node);
2006 }
2007 }
2008 }
2009
2010 | iplist STRING '/' NUMBER {
2011 int af, bytes, ret;
2012 struct IPListNode *node;
2013
2014 ret = parse_ip(&af, $2, IPstack, &bytes, STRICT_IP, &num_ip);
2015
2016 if ( ret == 0 ) {
2017 yyerror("Invalid IP address");
2018 YYABORT;
2019 }
2020 if ( af && (( af == PF_INET && bytes != 4 ) || ( af == PF_INET6 && bytes != 16 ))) {
2021 yyerror("incomplete IP address");
2022 YYABORT;
2023 }
2024
2025 // ret == - 2 means lookup failure
2026 if ( ret != -2 ) {
2027 if ((node = malloc(sizeof(struct IPListNode))) == NULL) {
2028 yyerror("malloc() error");
2029 YYABORT;
2030 }
2031 if ( af == PF_INET ) {
2032 node->mask[0] = 0xffffffffffffffffLL;
2033 node->mask[1] = 0xffffffffffffffffLL << ( 32 - $4 );
2034 } else { // PF_INET6
2035 if ( $4 > 64 ) {
2036 node->mask[0] = 0xffffffffffffffffLL;
2037 node->mask[1] = 0xffffffffffffffffLL << ( 128 - $4 );
2038 } else {
2039 node->mask[0] = 0xffffffffffffffffLL << ( 64 - $4 );
2040 node->mask[1] = 0;
2041 }
2042 }
2043
2044 node->ip[0] = IPstack[0] & node->mask[0];
2045 node->ip[1] = IPstack[1] & node->mask[1];
2046
2047 RB_INSERT(IPtree, (IPlist_t *)$$, node);
2048 }
2049 }
2050
2051 ;
2052
2053 /* ULlist definition */
2054 ullist: NUMBER {
2055 struct ULongListNode *node;
2056
2057 ULongtree_t *root = malloc(sizeof(ULongtree_t));
2058
2059 if ( root == NULL) {
2060 yyerror("malloc() error");
2061 YYABORT;
2062 }
2063 RB_INIT(root);
2064
2065 if ((node = malloc(sizeof(struct ULongListNode))) == NULL) {
2066 yyerror("malloc() error");
2067 YYABORT;
2068 }
2069 node->value = $1;
2070
2071 RB_INSERT(ULongtree, root, node);
2072 $$ = (void *)root;
2073 }
2074
2075 | ullist NUMBER {
2076 struct ULongListNode *node;
2077
2078 if ((node = malloc(sizeof(struct ULongListNode))) == NULL) {
2079 yyerror("malloc() error");
2080 YYABORT;
2081 }
2082 node->value = $2;
2083 RB_INSERT(ULongtree, (ULongtree_t *)$$, node);
2084 }
2085
2086 | ullist ',' NUMBER {
2087 struct ULongListNode *node;
2088
2089 if ((node = malloc(sizeof(struct ULongListNode))) == NULL) {
2090 yyerror("malloc() error");
2091 YYABORT;
2092 }
2093 node->value = $3;
2094 RB_INSERT(ULongtree, (ULongtree_t *)$$, node);
2095 }
2096
2097 ;
2098
2099 /* comparator qualifiers */
2100 comp: { $$.comp = CMP_EQ; }
2101 | EQ { $$.comp = CMP_EQ; }
2102 | LT { $$.comp = CMP_LT; }
2103 | GT { $$.comp = CMP_GT; }
2104 ;
2105
2106 /* 'direction' qualifiers */
2107 dqual: { $$.direction = DIR_UNSPEC; }
2108 | SRC { $$.direction = SOURCE; }
2109 | DST { $$.direction = DESTINATION; }
2110 | SRC OR DST { $$.direction = SOURCE_OR_DESTINATION; }
2111 | DST OR SRC { $$.direction = SOURCE_OR_DESTINATION; }
2112 | SRC AND DST { $$.direction = SOURCE_AND_DESTINATION; }
2113 | DST AND SRC { $$.direction = SOURCE_AND_DESTINATION; }
2114 | IN { $$.direction = DIR_IN; }
2115 | OUT { $$.direction = DIR_OUT; }
2116 | IN SRC { $$.direction = IN_SRC; }
2117 | IN DST { $$.direction = IN_DST; }
2118 | OUT SRC { $$.direction = OUT_SRC; }
2119 | OUT DST { $$.direction = OUT_DST; }
2120 | PREV { $$.direction = ADJ_PREV; }
2121 | NEXT { $$.direction = ADJ_NEXT; }
2122 ;
2123
2124 inout: INGRESS { $$.inout = INGRESS; }
2125 | EGRESS { $$.inout = EGRESS; }
2126 ;
2127
2128 acl: ACL { $$.acl = ACL; }
2129 | ACE { $$.acl = ACE; }
2130 | XACE { $$.acl = XACE; }
2131 ;
2132
2133 expr: term { $$ = $1.self; }
2134 | expr OR expr { $$ = Connect_OR($1, $3); }
2135 | expr AND expr { $$ = Connect_AND($1, $3); }
2136 | NOT expr %prec NEGATE { $$ = Invert($2); }
2137 | '(' expr ')' { $$ = $2; }
2138 | '(' expr ')' '%' STRING {
2139 $$ = $2;
2140 if ( strlen($5) > 16 ) {
2141 yyerror("Error: Maximum 16 chars allowed for flowlabel");
2142 YYABORT;
2143 } else {
2144 AddLabel($2, $5);
2145 }
2146 }
2147 | '%' STRING '(' expr ')' {
2148 $$ = $4;
2149 if ( strlen($2) > 16 ) {
2150 yyerror("Error: Maximum 16 chars allowed for flowlabel");
2151 YYABORT;
2152 } else {
2153 AddLabel($4, $2);
2154 }
2155 }
2156 ;
2157
2158 %%
2159
2160 static void yyerror(char *msg) {
2161
2162 if ( FilterFilename )
2163 snprintf(yyerror_buff, 255 ,"File '%s' line %d: %s at '%s'", FilterFilename, lineno, msg, yytext);
2164 else
2165 snprintf(yyerror_buff, 255, "Line %d: %s at '%s'", lineno, msg, yytext);
2166
2167 yyerror_buff[255] = '\0';
2168 fprintf(stderr, "%s\n", yyerror_buff);
2169
2170 } /* End of yyerror */
2171
ChainHosts(uint64_t * offsets,uint64_t * hostlist,int num_records,int type)2172 static uint32_t ChainHosts(uint64_t *offsets, uint64_t *hostlist, int num_records, int type) {
2173 uint32_t offset_a, offset_b, i, j, block;
2174 if ( type == SOURCE ) {
2175 offset_a = offsets[0];
2176 offset_b = offsets[1];
2177 } else {
2178 offset_a = offsets[2];
2179 offset_b = offsets[3];
2180 }
2181
2182 i = 0;
2183 block = Connect_AND(
2184 NewBlock(offset_b, MaskIPv6, hostlist[i+1] , CMP_EQ, FUNC_NONE, NULL ),
2185 NewBlock(offset_a, MaskIPv6, hostlist[i] , CMP_EQ, FUNC_NONE, NULL )
2186 );
2187 i += 2;
2188 for ( j=1; j<num_records; j++ ) {
2189 uint32_t b = Connect_AND(
2190 NewBlock(offset_b, MaskIPv6, hostlist[i+1] , CMP_EQ, FUNC_NONE, NULL ),
2191 NewBlock(offset_a, MaskIPv6, hostlist[i] , CMP_EQ, FUNC_NONE, NULL )
2192 );
2193 block = Connect_OR(block, b);
2194 i += 2;
2195 }
2196
2197 return block;
2198
2199 } // End of ChainHosts
2200
VerifyMac(char * s)2201 uint64_t VerifyMac(char *s) {
2202 uint64_t mac;
2203 size_t slen = strlen(s);
2204 long l;
2205 char *p, *q, *r;
2206 int i;
2207
2208 if ( slen > 17 )
2209 return 0;
2210
2211 for (i=0; i<slen; i++ ) {
2212 if ( !isxdigit(s[i]) && s[i] != ':' )
2213 return 0;
2214 }
2215
2216 p = strdup(s);
2217 if ( !p ) {
2218 yyerror("malloc() error");
2219 return 0;
2220 }
2221
2222 mac = 0;
2223 i = 0; // number of MAC octets must be 6
2224 r = p;
2225 q = strchr(r, ':');
2226 while ( r && i < 6 ) {
2227 if ( q )
2228 *q = '\0';
2229 l = strtol(r, NULL, 16);
2230 if ( (i == 0 && errno == EINVAL) ) {
2231 free(p);
2232 return 0;
2233 }
2234 if ( l > 255 ) {
2235 free(p);
2236 return 0;
2237 }
2238
2239 mac = ( mac << 8 ) | (l & 0xFF );
2240 i++;
2241
2242 if ( q ) {
2243 r = ++q;
2244 q = strchr(r, ':');
2245 } else
2246 r = NULL;
2247 }
2248
2249 if ( i != 6 )
2250 return 0;
2251
2252 return mac;
2253
2254 } // End of VerifyMac
2255
InitSymbols(void)2256 static int InitSymbols(void) {
2257 int i;
2258
2259 // already initialised?
2260 if ( fwd_status )
2261 return 1;
2262
2263 // fill fwd status cache table
2264 fwd_status = ( char **)calloc(256, sizeof(char *));
2265 if ( !fwd_status ) {
2266 fprintf(stderr, "malloc(): %s line %d: %s", __FILE__, __LINE__, strerror (errno));
2267 return 0;
2268 }
2269 i=0;
2270 while ( fwd_status_def_list[i].name ) {
2271 uint32_t j = fwd_status_def_list[i].id;
2272 fwd_status[j] = fwd_status_def_list[i].name;
2273 i++;
2274 }
2275 return 1;
2276
2277 } // End of InitSymbols
2278
Get_fwd_status_id(char * status)2279 static uint32_t Get_fwd_status_id(char *status) {
2280 int i;
2281
2282 if ( !fwd_status && !InitSymbols() )
2283 yyerror("malloc() error");
2284
2285 i = 0;
2286 while ( i < 256 ) {
2287 if ( fwd_status[i] && strcasecmp(fwd_status[i], status) == 0 )
2288 return i;
2289 i++;
2290 }
2291 return 256;
2292
2293 } // End of Get_fwd_status_id
2294
2295