1 %{
2 // Copyright (c) 2001,2002 RIPE NCC
3 //
4 // All Rights Reserved
5 //
6 // Permission to use, copy, modify, and distribute this software and its
7 // documentation for any purpose and without fee is hereby granted,
8 // provided that the above copyright notice appear in all copies and that
9 // both that copyright notice and this permission notice appear in
10 // supporting documentation, and that the name of the author not be
11 // used in advertising or publicity pertaining to distribution of the
12 // software without specific, written prior permission.
13 //
14 // THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
15 // ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
16 // AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
17 // DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
18 // AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19 // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 //
21 // $Id$
22 //
23 // Copyright (c) 1994 by the University of Southern California
24 // All rights reserved.
25 //
26 // Permission is hereby granted, free of charge, to any person obtaining a copy
27 // of this software and associated documentation files (the "Software"), to deal
28 // in the Software without restriction, including without limitation the rights
29 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
30 // copies of the Software, and to permit persons to whom the Software is
31 // furnished to do so, subject to the following conditions:
32 //
33 // The above copyright notice and this permission notice shall be included in
34 // all copies or substantial portions of the Software.
35 //
36 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
37 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
38 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
39 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
40 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
41 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
42 // THE SOFTWARE.
43 //
44 // Questions concerning this software should be directed to
45 // irrtoolset@cs.usc.edu.
46 //
47 // Author(s): Cengiz Alaettinoglu <cengiz@ISI.EDU>
48 // Katie Petrusha <katie@ripe.net>
49
50 #include "config.h"
51 #include "time.h"
52 #include "schema.hh"
53 #include "object.hh"
54 #include "regexp.hh"
55 #include "rptype.hh"
56
57 #ifdef ENABLE_DEBUG
58 #define YYDEBUG 1
59 #endif // ENABLE_DEBUG
60 #if YYDEBUG != 0
61 // stdio is needed for yydebug
62 #include <cstdio>
63 #endif
64
65 extern "C" {
66 #ifdef HAVE_REGEX_H
67 #include <regex.h>
68 #else
69 #include <gnu/regex.h>
70 #endif
71 }
72
73 extern void handle_error(const char *, ...);
74 extern void handle_object_error(const char *, ...);
75 extern void handle_warning(const char *, ...);
76 extern int yylex();
77 char *token_name(int token_id);
78 void rpslerror(const char *s, ...);
79 Attr *changeCurrentAttr(Attr *b);
80 void handleArgumentTypeError(char *attr, const char *method, int position,
81 const RPType *correctType,
82 bool isOperator = false);
83 const AttrMethod *searchMethod(const AttrRPAttr *rp_attr, const char *method, ItemList *args);
84
85 /* argument to yyparse result of parsing should be stored here */
86 #define yyschema schema
87 #define enable_yy_parser_debugging enable_rpsl_parser_debugging
88
89 extern Object *current_object;
90
91 %}
92
93 %name-prefix "rpsl"
94 %output "rpsl.y.cc"
95
96 %expect 1
97
98 %union {
99 long long int i;
100 double real;
101 char *string;
102 void *ptr;
103 time_t time;
104 Item *item;
105 ItemList *list;
106 regexp *re;
107 SymID sid;
108 IPAddr *ip;
109 Prefix *prfx;
110 PrefixRange *prfxrng;
111 IPv6Addr *ipv6;
112 IPv6Prefix *prfxv6;
113 IPv6PrefixRange *prfxv6rng;
114 AddressFamily *afi;
115 RPType *typenode;
116 MPPrefix *mpprefix;
117 Tunnel *tunnel;
118
119 Filter *filter;
120 FilterMS *moreSpecOp;
121 PolicyPeering *peering;
122 PolicyPeering *mp_peering;
123 PolicyActionList *actionList;
124 PolicyAction *actionNode;
125 PolicyFactor *policyFactor;
126 PolicyTerm *policyTerm;
127 PolicyExpr *policyExpr;
128 List<PolicyPeeringAction> *peeringActionList;
129
130 Attr *attr;
131 AttrAttr *rpslattr;
132 AttrMethod *method;
133 const AttrRPAttr *rp_attr;
134 const AttrProtocol *protocol;
135 AttrProtocolOption *protocol_option;
136 List<AttrProtocolOption> *protocol_option_list;
137
138 AttrPeerOption *peer_option;
139 List<AttrPeerOption> *peer_option_list;
140
141 List<RPTypeNode> *typelist;
142 List<AttrMethod> *methodlist;
143 List<WordNode> *wordlist;
144
145 List<AttrMntRoutes::MntPrfxPair> *listMntPrfxPair;
146 AttrMntRoutes::MntPrfxPair *mntPrfxPair;
147 }
148
149 %token KEYW_TRUE
150 %token KEYW_FALSE
151 %token KEYW_ACTION
152 %token KEYW_ACCEPT
153 %token KEYW_ANNOUNCE
154 %token KEYW_FROM
155 %token KEYW_TO
156 %token KEYW_AT
157 %token KEYW_ANY
158 %token KEYW_REFINE
159 %token KEYW_EXCEPT
160 %token KEYW_STATIC
161 %token KEYW_NETWORKS
162 %token KEYW_MASKLEN
163 %token KEYW_UNION
164 %token KEYW_RANGE
165 %token KEYW_LIST
166 %token KEYW_OF
167 %token KEYW_OPERATOR
168 %token KEYW_SYNTAX
169 %token KEYW_SPECIAL
170 %token KEYW_REGEXP
171 %token KEYW_OPTIONAL
172 %token KEYW_MANDATORY
173 %token KEYW_INTERNAL
174 %token KEYW_SINGLEVALUED
175 %token KEYW_MULTIVALUED
176 %token KEYW_LOOKUP
177 %token KEYW_KEY
178 %token KEYW_DELETED
179 %token KEYW_OBSOLETE
180 %token KEYW_PEERAS
181 %token KEYW_PROTOCOL
182 %token KEYW_INTO
183 %token KEYW_ATOMIC
184 %token KEYW_INBOUND
185 %token KEYW_OUTBOUND
186 %token KEYW_UPON
187 %token KEYW_HAVE_COMPONENTS
188 %token KEYW_EXCLUDE
189 %token KEYW_AFI
190 %token KEYW_TUNNEL
191
192 %token TKN_ERROR
193 %token TKN_UNKNOWN_CLASS
194 %token TKN_EOA /* end of attribute */
195 %token TKN_EOO /* end of object */
196 %token TKN_FREETEXT
197 %token <i> TKN_INT
198 %token <real> TKN_REAL
199 %token <string> TKN_STRING
200 %token <time> TKN_TIMESTAMP
201 %token <string> TKN_BLOB
202 %token <ip> TKN_IPV4
203 %token <prfx> TKN_PRFXV4
204 %token <prfxrng> TKN_PRFXV4RNG
205 %token <ipv6> TKN_IPV6
206 %token <prfxv6> TKN_PRFXV6
207 %token <prfxv6rng> TKN_PRFXV6RNG
208 %token <i> TKN_ASNO
209 %token <sid> TKN_ASNAME
210 %token <sid> TKN_RSNAME
211 %token <sid> TKN_RTRSNAME
212 %token <sid> TKN_PRNGNAME
213 %token <sid> TKN_FLTRNAME
214 %token <i> TKN_BOOLEAN
215 %token <string> TKN_WORD
216 %token <rp_attr> TKN_RP_ATTR
217 %token <sid> TKN_DNS
218 %token <string> TKN_EMAIL
219 %token TKN_3DOTS
220 %token <afi> TKN_AFI
221
222 %token <attr> ATTR_GENERIC
223 %token <attr> ATTR_BLOBS
224 %token <attr> ATTR_REGEXP
225 %token <attr> ATTR_IMPORT
226 %token <attr> ATTR_MP_IMPORT
227 %token <attr> ATTR_EXPORT
228 %token <attr> ATTR_MP_EXPORT
229 %token <attr> ATTR_DEFAULT
230 %token <attr> ATTR_MP_DEFAULT
231 %token <attr> ATTR_FREETEXT
232 %token <attr> ATTR_CHANGED
233 %token <attr> ATTR_IFADDR
234 %token <attr> ATTR_INTERFACE
235 %token <attr> ATTR_PEER
236 %token <attr> ATTR_MP_PEER
237 %token <attr> ATTR_INJECT
238 %token <attr> ATTR_V6_INJECT
239 %token <attr> ATTR_COMPONENTS
240 %token <attr> ATTR_V6_COMPONENTS
241 %token <attr> ATTR_AGGR_MTD
242 %token <attr> ATTR_AGGR_BNDRY
243 %token <attr> ATTR_RS_MEMBERS
244 %token <attr> ATTR_RS_MP_MEMBERS
245 %token <attr> ATTR_RTR_MP_MEMBERS
246 %token <attr> ATTR_RP_ATTR
247 %token <attr> ATTR_TYPEDEF
248 %token <attr> ATTR_PROTOCOL
249 %token <attr> ATTR_FILTER
250 %token <attr> ATTR_V6_FILTER
251 %token <attr> ATTR_MP_FILTER
252 %token <attr> ATTR_MP_PEVAL
253 %token <attr> ATTR_PEERING
254 %token <attr> ATTR_MP_PEERING
255 %token <attr> ATTR_ATTR
256 %token <attr> ATTR_MNT_ROUTES
257 %token <attr> ATTR_MNT_ROUTES6
258 %token <attr> ATTR_MNT_ROUTES_MP
259
260 %left OP_OR
261 %left OP_AND
262 %right OP_NOT
263 %nonassoc<moreSpecOp> OP_MS
264 %nonassoc<string> TKN_OPERATOR
265
266 %type<list> generic_list
267 %type<list> rs_members_list
268 %type<list> opt_rs_members_list
269
270 %type<list> rs_mp_members_list
271 %type<list> opt_rs_mp_members_list
272
273 %type<list> afi_list
274 %type<list> opt_afi_list
275
276 %type<list> blobs_list
277 %type<list> generic_non_empty_list
278 %type<item> list_item
279 %type<item> list_item_0
280 %type<item> rs_member
281 %type<item> rs_mp_member
282 %type<item> afi
283
284 %type<string> tkn_word
285 %type<string> tkn_word_from_keyw
286
287 %type<attr> attribute
288 %type<attr> generic_attribute
289 %type<attr> blobs_attribute
290 %type<attr> regexp_attribute
291 %type<attr> changed_attribute
292 %type<attr> ifaddr_attribute
293 %type<attr> interface_attribute
294 %type<attr> peer_attribute
295 %type<attr> mp_peer_attribute
296 %type<attr> components_attribute
297 %type<attr> v6_components_attribute
298 %type<attr> inject_attribute
299 %type<attr> v6_inject_attribute
300 %type<attr> aggr_mtd_attribute
301 %type<attr> aggr_bndry_attribute
302
303 %type<attr> import_attribute
304 %type<attr> mp_import_attribute
305 %type<attr> export_attribute
306 %type<attr> mp_export_attribute
307 %type<attr> default_attribute
308 %type<attr> mp_default_attribute
309 %type<attr> typedef_attribute
310 %type<attr> rpattr_attribute
311 %type<attr> rs_members_attribute
312 %type<attr> rs_mp_members_attribute
313 %type<attr> protocol_attribute
314 %type<attr> filter_attribute
315 %type<attr> v6_filter_attribute
316 %type<attr> mp_filter_attribute
317 %type<attr> mp_peval_attribute
318 %type<attr> peering_attribute
319 %type<attr> mp_peering_attribute
320 %type<attr> attr_attribute
321 %type<attr> freetext_attribute
322 %type<attr> mnt_routes_attribute
323 %type<attr> mnt_routes6_attribute
324 %type<attr> mnt_routes_mp_attribute
325
326 %type<filter> filter
327 %type<filter> opt_default_filter
328 %type<filter> filter_term
329 %type<filter> filter_factor
330 %type<filter> filter_operand
331 %type<filter> filter_prefix
332 %type<filter> filter_prefix_operand
333 %type<filter> opt_filter_prefix_list
334 %type<filter> filter_prefix_list
335 %type<prfxrng> filter_prefix_list_prefix
336 %type<filter> filter_rp_attribute
337
338 %type<filter> mp_filter
339 %type<filter> opt_default_mp_filter
340 %type<filter> mp_filter_term
341 %type<filter> mp_filter_factor
342 %type<filter> mp_filter_operand
343 %type<filter> mp_filter_prefix
344 %type<filter> mp_filter_prefix_operand
345 %type<filter> opt_mp_filter_prefix_list
346 %type<filter> mp_filter_prefix_list
347 %type<mpprefix> mp_filter_prefix_list_prefix
348 %type<filter> mp_peval
349
350 %type<filter> v6_filter
351 %type<filter> v6_filter_term
352 %type<filter> v6_filter_factor
353 %type<filter> v6_filter_operand
354 %type<filter> v6_filter_prefix
355 %type<filter> v6_filter_prefix_operand
356 %type<filter> opt_v6_filter_prefix_list
357 %type<filter> v6_filter_prefix_list
358 %type<mpprefix> v6_filter_prefix_list_prefix
359
360 %type<filter> opt_v6_inject_expr
361 %type<filter> v6_inject_expr
362 %type<filter> v6_inject_expr_term
363 %type<filter> v6_inject_expr_factor
364 %type<filter> v6_inject_expr_operand
365
366 %type<filter> opt_as_expr
367 %type<filter> as_expr
368 %type<filter> as_expr_term
369 %type<filter> as_expr_factor
370 %type<filter> as_expr_operand
371
372 %type<filter> opt_router_expr
373 %type<filter> opt_router_expr_with_at
374 %type<filter> router_expr
375 %type<filter> router_expr_term
376 %type<filter> router_expr_factor
377 %type<filter> router_expr_operand
378
379 %type<filter> opt_mp_router_expr
380 %type<filter> opt_mp_router_expr_with_at
381 %type<filter> mp_router_expr
382 %type<filter> mp_router_expr_term
383 %type<filter> mp_router_expr_factor
384 %type<filter> mp_router_expr_operand
385
386 %type<filter> opt_inject_expr
387 %type<filter> inject_expr
388 %type<filter> inject_expr_term
389 %type<filter> inject_expr_factor
390 %type<filter> inject_expr_operand
391
392 %type<re> filter_aspath
393 %type<re> filter_aspath_term
394 %type<re> filter_aspath_closure
395 %type<re> filter_aspath_factor
396 %type<re> filter_aspath_no
397 %type<re> filter_aspath_range
398
399 %type<actionList> action
400 %type<actionList> opt_action
401 %type<actionNode> single_action
402
403 %type<peering> peering
404 %type<peering> mp_peering
405
406 %type<peeringActionList> import_peering_action_list
407 %type<peeringActionList> export_peering_action_list
408 %type<policyFactor> import_factor
409 %type<policyTerm> import_factor_list
410 %type<policyTerm> import_term
411 %type<policyExpr> import_expr
412 %type<policyFactor> export_factor
413 %type<policyTerm> export_factor_list
414 %type<policyTerm> export_term
415 %type<policyExpr> export_expr
416
417 %type<peeringActionList> mp_import_peering_action_list
418 %type<peeringActionList> mp_export_peering_action_list
419 %type<policyFactor> mp_import_factor
420 %type<policyTerm> mp_import_factor_list
421 %type<policyTerm> mp_import_term
422 %type<policyExpr> mp_import_expr
423 %type<policyFactor> mp_export_factor
424 %type<policyTerm> mp_export_factor_list
425 %type<policyTerm> mp_export_term
426 %type<policyExpr> mp_export_expr
427
428 %type<protocol> opt_protocol_from
429 %type<protocol> opt_protocol_into
430
431 %type<wordlist> enum_list
432 %type<typenode> typedef_type
433 %type<typelist> typedef_type_list
434
435 %type<method> method
436 %type<methodlist> methods
437
438 %type<protocol_option> protocol_option
439 %type<protocol_option_list> protocol_options
440
441 %type<peer_option> peer_option
442 %type<peer_option_list> peer_options
443 %type<peer_option_list> opt_peer_options
444 %type<ip> peer_id
445 %type<mpprefix> mp_peer_id
446 %type<mpprefix> interface_address
447 %type<tunnel> opt_tunnel_spec
448
449 %type<rpslattr> opt_attr_options
450 %type<rpslattr> attr_options
451 %type<rpslattr> attr_option
452
453 %type<listMntPrfxPair> mnt_routes_list
454 %type<mntPrfxPair> mnt_routes_list_item
455 %type<listMntPrfxPair> mnt_routes6_list
456 %type<mntPrfxPair> mnt_routes6_list_item
457 %type<listMntPrfxPair> mnt_routes_mp_list
458 %type<mntPrfxPair> mnt_routes_mp_list_item
459
460 %%
461 object: attribute_list TKN_EOO {
462 YYACCEPT;
463 }
464 | TKN_UNKNOWN_CLASS TKN_EOO {
465 YYACCEPT;
466 }
467 | error TKN_EOO {
468 handle_object_error("Error: syntax error\n");
469 YYABORT;
470 }
471 | attribute_list { // end of file
472 YYACCEPT;
473 }
474 | TKN_UNKNOWN_CLASS { // end of file
475 YYACCEPT;
476 }
477 | error { // end of file
478 handle_object_error("Error: syntax error\n");
479 YYABORT;
480 }
481 | { // end of file
482 YYABORT;
483 }
484 ;
485
486 attribute_list: attribute {
487 (*current_object) += $1;
488 }
489 | attribute_list attribute {
490 (*current_object) += $2;
491 }
492 ;
493
494 attribute: generic_attribute
495 | blobs_attribute
496 | regexp_attribute
497 | changed_attribute
498 | import_attribute
499 | mp_import_attribute
500 | export_attribute
501 | mp_export_attribute
502 | default_attribute
503 | mp_default_attribute
504 | peer_attribute
505 | mp_peer_attribute
506 | ifaddr_attribute
507 | interface_attribute
508 | components_attribute
509 | v6_components_attribute
510 | inject_attribute
511 | v6_inject_attribute
512 | aggr_mtd_attribute
513 | aggr_bndry_attribute
514 | typedef_attribute
515 | protocol_attribute
516 | rpattr_attribute
517 | rs_members_attribute
518 | rs_mp_members_attribute
519 | filter_attribute
520 | v6_filter_attribute
521 | mp_filter_attribute
522 | mp_peval_attribute
523 | peering_attribute
524 | mp_peering_attribute
525 | attr_attribute
526 | freetext_attribute
527 | mnt_routes_attribute
528 | mnt_routes6_attribute
529 | mnt_routes_mp_attribute
530 | TKN_ERROR TKN_EOA { // the current line started w/ non-attribute
531 $$ = changeCurrentAttr(new Attr);
532 handle_error("Error: syntax error\n");
533 }
534 | error TKN_EOA {
535 $$ = changeCurrentAttr(new Attr);
536 handle_error("Error: syntax error\n");
537 yyerrok;
538 }
539 ;
540
541 //**** Generic Attributes ************************************************
542
543 changed_attribute: ATTR_CHANGED TKN_EMAIL TKN_INT TKN_EOA {
544 free($2);
545 $$ = $1;
546 }
547 | ATTR_CHANGED error TKN_EOA {
548 handle_error("Error: \"changed: <email> <YYYYMMDD>\" expected\n");
549 yyerrok;
550 }
551 ;
552
553 freetext_attribute: ATTR_FREETEXT TKN_EOA {
554 char *start = strchr($1->object->contents + $1->offset, ':') + 1;
555 int len = $1->object->contents + $1->offset + $1->len - start;
556 ItemFREETEXT *ft = new ItemFREETEXT(start, len);
557 ItemList *il = new ItemList;
558 il->append(ft);
559
560 $$ = changeCurrentAttr(new AttrGeneric($1->type, il));
561 }
562 ;
563
564 regexp_attribute: ATTR_REGEXP TKN_EOA {
565 char *start = strchr($1->object->contents + $1->offset, ':') + 1;
566 int len = $1->object->contents + $1->offset + $1->len - start;
567
568 while (isspace(*start)) {
569 start++;
570 len --;
571 }
572
573 char *comment = strrchr(start, '#');
574 if (comment && comment < start+len)
575 len = comment - start;
576
577 while (isspace(*(start+len-1)))
578 len --;
579
580 Buffer b(len+1);
581 b.append(start, len);
582 b.append("", 1);
583
584 regmatch_t *matches = (regmatch_t *) malloc(sizeof(regmatch_t)
585 * ($1->type->reIndex + 1));
586 int code = regexec($1->type->reComp, b.contents,
587 $1->type->reIndex + 1, matches, 0);
588
589 if (code) {
590 handle_error("Error: argument to %s should match %s.\n",
591 $1->type->name(), $1->type->re);
592 $$ = changeCurrentAttr(new AttrGeneric($1->type, NULL));
593 } else {
594 Buffer *buf = new Buffer(matches[$1->type->reIndex].rm_eo
595 - matches[$1->type->reIndex].rm_so);
596 buf->append(b.contents + matches[$1->type->reIndex].rm_so,buf->capacity);
597
598 ItemBUFFER *item = new ItemBUFFER(buf);
599 ItemList *il = new ItemList;
600 il->append(item);
601
602 $$ = changeCurrentAttr(new AttrGeneric($1->type, il));
603 }
604 }
605 ;
606
607 generic_attribute: ATTR_GENERIC generic_list TKN_EOA {
608 if (!$1->type->subsyntax()->validate($2)) {
609 handle_error("Error: argument to %s should be %s.\n",
610 $1->type->name(), $1->type->subsyntax()->name());
611 delete $2;
612 $$ = changeCurrentAttr(new AttrGeneric($1->type, NULL));
613 } else
614 $$ = changeCurrentAttr(new AttrGeneric($1->type, $2));
615 }
616 | ATTR_GENERIC error TKN_EOA {
617 $$ = $1;
618 handle_error("Error: argument to %s should be %s.\n",
619 $1->type->name(), $1->type->subsyntax()->name());
620 yyerrok;
621 }
622 ;
623
624 generic_list: /* empty list */ {
625 $$ = new ItemList;
626 }
627 | generic_non_empty_list
628 ;
629
630 generic_non_empty_list: list_item {
631 $$ = new ItemList;
632 $$->append($1);
633 }
634 | generic_non_empty_list ',' list_item {
635 $$ = $1;
636 $$->append($3);
637 }
638 ;
639
640 blobs_attribute: ATTR_BLOBS blobs_list TKN_EOA {
641 $$ = changeCurrentAttr(new AttrGeneric($1->type, $2));
642 }
643 | ATTR_BLOBS error TKN_EOA {
644 $$ = $1;
645 handle_error("Error: argument to %s should be blob sequence.\n",
646 $1->type->name());
647 yyerrok;
648 }
649 ;
650
651 blobs_list: list_item {
652 $$ = new ItemList;
653 $$->append($1);
654 }
655 | blobs_list list_item {
656 $$ = $1;
657 $$->append($2);
658 }
659 ;
660
661 list_item: list_item_0 {
662 $$ = $1;
663 }
664 | list_item_0 '-' list_item_0 {
665 $$ = new ItemRange($1, $3);
666 }
667 ;
668
669 list_item_0: TKN_ASNO {
670 $$ = new ItemASNO($1);
671 }
672 | TKN_INT {
673 $$ = new ItemINT($1);
674 }
675 | TKN_REAL {
676 $$ = new ItemREAL($1);
677 }
678 | TKN_STRING {
679 $$ = new ItemSTRING($1);
680 }
681 | TKN_TIMESTAMP {
682 $$ = new ItemTimeStamp($1);
683 }
684 | TKN_IPV4 {
685 $$ = new ItemIPV4($1);
686 }
687 | TKN_PRFXV4 {
688 $$ = new ItemPRFXV4($1);
689 }
690 | TKN_PRFXV4RNG {
691 $$ = new ItemPRFXV4Range($1);
692 }
693 | TKN_IPV6 {
694 $$ = new ItemIPV6($1);
695 }
696 | TKN_PRFXV6 {
697 $$ = new ItemPRFXV6($1);
698 }
699 | TKN_PRFXV6RNG {
700 $$ = new ItemPRFXV6Range($1);
701 }
702 | TKN_IPV4 ':' TKN_INT {
703 $$ = new ItemConnection($1, $3);
704 }
705 | TKN_DNS ':' TKN_INT {
706 $$ = new ItemConnection($1, $3);
707 }
708 | TKN_ASNAME {
709 $$ = new ItemASNAME($1);
710 }
711 | TKN_RSNAME {
712 $$ = new ItemRSNAME($1);
713 }
714 | TKN_RTRSNAME {
715 $$ = new ItemRTRSNAME($1);
716 }
717 | TKN_PRNGNAME {
718 $$ = new ItemPRNGNAME($1);
719 }
720 | TKN_FLTRNAME {
721 $$ = new ItemFLTRNAME($1);
722 }
723 | TKN_BOOLEAN {
724 $$ = new ItemBOOLEAN($1);
725 }
726 | TKN_WORD {
727 $$ = new ItemWORD($1);
728 }
729 | tkn_word_from_keyw {
730 $$ = new ItemWORD($1);
731 }
732 | TKN_DNS {
733 $$ = new ItemDNS($1);
734 }
735 | TKN_EMAIL {
736 $$ = new ItemEMAIL($1);
737 }
738 | TKN_BLOB {
739 $$ = new ItemBLOB($1);
740 }
741 | '{' generic_list '}' {
742 $$ = $2;
743 }
744 | '(' filter ')' {
745 $$ = new ItemFilter($2);
746 }
747 ;
748
749 tkn_word: TKN_WORD {
750 $$ = $1;
751 }
752 | TKN_ASNO {
753 char buffer[64];
754 asnum_string(buffer, $1);
755 $$ = strdup(buffer);
756 }
757 | TKN_ASNAME {
758 $$ = strdup($1);
759 }
760 | TKN_RSNAME {
761 $$ = strdup($1);
762 }
763 | TKN_RTRSNAME {
764 $$ = strdup($1);
765 }
766 | TKN_PRNGNAME {
767 $$ = strdup($1);
768 }
769 | TKN_FLTRNAME {
770 $$ = strdup($1);
771 }
772 | TKN_BOOLEAN {
773 if ($1)
774 $$ = strdup("true");
775 else
776 $$ = strdup("false");
777 }
778 | tkn_word_from_keyw
779 ;
780
781 tkn_word_from_keyw: KEYW_TRUE {
782 $$ = strdup("true");
783 }
784 | KEYW_FALSE {
785 $$ = strdup("false");
786 }
787 | KEYW_ACTION {
788 $$ = strdup("action");
789 }
790 | KEYW_ACCEPT {
791 $$ = strdup("accept");
792 }
793 | KEYW_ANNOUNCE {
794 $$ = strdup("announce");
795 }
796 | KEYW_FROM {
797 $$ = strdup("from");
798 }
799 | KEYW_TO {
800 $$ = strdup("to");
801 }
802 | KEYW_AT {
803 $$ = strdup("at");
804 }
805 | KEYW_ANY {
806 $$ = strdup("any");
807 }
808 | KEYW_REFINE {
809 $$ = strdup("refine");
810 }
811 | KEYW_EXCEPT {
812 $$ = strdup("except");
813 }
814 | KEYW_STATIC {
815 $$ = strdup("static");
816 }
817 | KEYW_NETWORKS {
818 $$ = strdup("networks");
819 }
820 | KEYW_MASKLEN {
821 $$ = strdup("masklen");
822 }
823 | KEYW_UNION {
824 $$ = strdup("union");
825 }
826 | KEYW_RANGE {
827 $$ = strdup("range");
828 }
829 | KEYW_LIST {
830 $$ = strdup("list");
831 }
832 | KEYW_OF {
833 $$ = strdup("of");
834 }
835 | KEYW_OPERATOR {
836 $$ = strdup("operator");
837 }
838 | KEYW_SYNTAX {
839 $$ = strdup("syntax");
840 }
841 | KEYW_SPECIAL {
842 $$ = strdup("special");
843 }
844 | KEYW_REGEXP {
845 $$ = strdup("regexp");
846 }
847 | KEYW_OPTIONAL {
848 $$ = strdup("optional");
849 }
850 | KEYW_MANDATORY {
851 $$ = strdup("mandatory");
852 }
853 | KEYW_INTERNAL {
854 $$ = strdup("internal");
855 }
856 | KEYW_DELETED {
857 $$ = strdup("deleted");
858 }
859 | KEYW_SINGLEVALUED {
860 $$ = strdup("singlevalued");
861 }
862 | KEYW_MULTIVALUED {
863 $$ = strdup("multivalued");
864 }
865 | KEYW_LOOKUP {
866 $$ = strdup("lookup");
867 }
868 | KEYW_KEY {
869 $$ = strdup("key");
870 }
871 | KEYW_OBSOLETE {
872 $$ = strdup("obsolete");
873 }
874 | KEYW_PEERAS {
875 $$ = strdup("peeras");
876 }
877 | KEYW_PROTOCOL {
878 $$ = strdup("protocol");
879 }
880 | KEYW_INTO {
881 $$ = strdup("into");
882 }
883 | KEYW_ATOMIC {
884 $$ = strdup("atomic");
885 }
886 | KEYW_INBOUND {
887 $$ = strdup("inbound");
888 }
889 | KEYW_OUTBOUND {
890 $$ = strdup("outbound");
891 }
892 ;
893
894 //**** aut-num class ******************************************************
895
896 //// as_expr ////////////////////////////////////////////////////////////
897
898 opt_as_expr: {
899 $$ = new FilterASNAME(symbols.symID("AS-ANY"));
900 }
901 | as_expr
902 ;
903
904 as_expr: as_expr OP_OR as_expr_term {
905 $$ = new FilterOR($1, $3);
906 }
907 | as_expr_term
908 ;
909
910 as_expr_term: as_expr_term OP_AND as_expr_factor {
911 $$ = new FilterAND($1, $3);
912 }
913 | as_expr_term KEYW_EXCEPT as_expr_factor {
914 $$ = new FilterEXCEPT($1, $3);
915 }
916 | as_expr_term OP_AND OP_NOT as_expr_factor {
917 $$ = new FilterEXCEPT($1, $4);
918 }
919 | as_expr_factor
920 ;
921
922 as_expr_factor: '(' as_expr ')' {
923 $$ = $2;
924 }
925 | as_expr_operand
926 ;
927
928 as_expr_operand: TKN_ASNO {
929 $$ = new FilterASNO($1);
930 }
931 | TKN_ASNAME {
932 $$ = new FilterASNAME($1);
933 }
934 ;
935
936 //// router_expr ///////////////////////////////////////////////////////////
937
938 opt_router_expr: {
939 $$ = new FilterANY;
940 }
941 | router_expr {
942 $$ = $1;
943 }
944 ;
945
946 opt_router_expr_with_at: {
947 $$ = new FilterANY;
948 }
949 | KEYW_AT router_expr {
950 $$ = $2;
951 }
952 ;
953
954 router_expr: router_expr OP_OR router_expr_term {
955 $$ = new FilterOR($1, $3);
956 }
957 | router_expr_term
958 ;
959
960 router_expr_term: router_expr_term OP_AND router_expr_factor {
961 $$ = new FilterAND($1, $3);
962 }
963 | router_expr_term KEYW_EXCEPT router_expr_factor {
964 $$ = new FilterEXCEPT($1, $3);
965 }
966 | router_expr_term OP_AND OP_NOT router_expr_factor {
967 $$ = new FilterEXCEPT($1, $4);
968 }
969
970 | router_expr_factor
971 ;
972
973 router_expr_factor: '(' router_expr ')' {
974 $$ = $2;
975 }
976 | router_expr_operand
977 ;
978
979 router_expr_operand: TKN_IPV4 {
980 $$ = new FilterRouter($1);
981 }
982 | TKN_DNS {
983 $$ = new FilterRouterName($1);
984 }
985 | TKN_RTRSNAME {
986 $$ = new FilterRTRSNAME($1);
987 }
988 ;
989
990 //// peering ////////////////////////////////////////////////////////////
991
992 peering: as_expr opt_router_expr opt_router_expr_with_at {
993 $$ = new PolicyPeering($1, $2, $3);
994 }
995 | TKN_PRNGNAME {
996 $$ = new PolicyPeering($1);
997 }
998 ;
999
1000 //// action /////////////////////////////////////////////////////////////
1001
1002 opt_action: {
1003 $$ = new PolicyActionList;
1004 }
1005 | KEYW_ACTION action {
1006 $$ = $2;
1007 }
1008 ;
1009
1010 action: single_action {
1011 $$ = new PolicyActionList;
1012 if ($1)
1013 $$->append($1);
1014 }
1015 | action single_action {
1016 $$ = $1;
1017 if ($2)
1018 $$->append($2);
1019 }
1020 ;
1021
1022 single_action: TKN_RP_ATTR '.' TKN_WORD '(' generic_list ')' ';' {
1023 const AttrMethod *mtd = searchMethod($1, $3, $5);
1024 if (mtd)
1025 $$ = new PolicyAction($1, mtd, $5);
1026 else {
1027 delete $5;
1028 $$ = NULL;
1029 }
1030 free($3);
1031 }
1032 | TKN_RP_ATTR TKN_OPERATOR list_item ';' {
1033 ItemList *plist = new ItemList;
1034 plist->append($3);
1035
1036 const AttrMethod *mtd = searchMethod($1, $2, plist);
1037 if (mtd)
1038 $$ = new PolicyAction($1, mtd, plist);
1039 else {
1040 delete plist;
1041 $$ = NULL;
1042 }
1043 free($2);
1044 }
1045 | TKN_RP_ATTR '(' generic_list ')' ';' {
1046 const AttrMethod *mtd = searchMethod($1, "()", $3);
1047 if (mtd)
1048 $$ = new PolicyAction($1, mtd, $3);
1049 else {
1050 delete $3;
1051 $$ = NULL;
1052 }
1053 }
1054 | TKN_RP_ATTR '[' generic_list ']' ';' {
1055 const AttrMethod *mtd = searchMethod($1, "[]", $3);
1056 if (mtd)
1057 $$ = new PolicyAction($1, mtd, $3);
1058 else {
1059 delete $3;
1060 $$ = NULL;
1061 }
1062 }
1063 | ';' {
1064 $$ = NULL;
1065 }
1066 ;
1067
1068 //// filter /////////////////////////////////////////////////////////////
1069 //// default afi = ipv4.unicast
1070
1071 filter: filter OP_OR filter_term {
1072 $$ = new FilterOR($1, $3);
1073 }
1074 | filter filter_term %prec OP_OR {
1075 $$ = new FilterOR($1, $2);
1076 }
1077 | filter_term
1078 ;
1079
1080 filter_term : filter_term OP_AND filter_factor {
1081 $$ = new FilterAND($1, $3);
1082 }
1083 | filter_factor
1084 ;
1085
1086 filter_factor : OP_NOT filter_factor {
1087 $$ = new FilterNOT($2);
1088 }
1089 | '(' filter ')' {
1090 $$ = $2;
1091 }
1092 | filter_operand
1093 ;
1094
1095 filter_operand: KEYW_ANY {
1096 $$ = new FilterANY;
1097 }
1098 | '<' filter_aspath '>' {
1099 $$ = new FilterASPath($2);
1100 }
1101 | filter_rp_attribute {
1102 if ($1)
1103 $$ = $1;
1104 else
1105 $$ = new FilterNOT(new FilterANY);
1106 }
1107 | TKN_FLTRNAME {
1108 $$ = new FilterFLTRNAME($1);
1109 }
1110 | filter_prefix
1111 ;
1112
1113 filter_prefix: filter_prefix_operand OP_MS {
1114 $2->f1 = $1;
1115 $$ = $2;
1116 }
1117 | filter_prefix_operand
1118 ;
1119
1120 filter_prefix_operand: TKN_ASNO {
1121 $$ = new FilterASNO($1);
1122 }
1123 | KEYW_PEERAS {
1124 $$ = new FilterPeerAS;
1125 }
1126 | TKN_ASNAME {
1127 $$ = new FilterASNAME($1);
1128 }
1129 | TKN_RSNAME {
1130 $$ = new FilterRSNAME($1);
1131 }
1132 | '{' opt_filter_prefix_list '}' {
1133 $$ = $2;
1134 }
1135 ;
1136
1137 opt_filter_prefix_list: {
1138 $$ = new FilterPRFXList;
1139 }
1140 | filter_prefix_list {
1141 $$ = $1;
1142 }
1143 ;
1144
1145 filter_prefix_list: filter_prefix_list_prefix {
1146 ((FilterPRFXList *) ($$ = new FilterPRFXList))->add_high(*$1);
1147 delete $1;
1148 }
1149 | filter_prefix_list ',' filter_prefix_list_prefix {
1150 $$ = $1;
1151 ((FilterPRFXList *) ($$))->add_high(*$3);
1152 delete $3;
1153 }
1154 ;
1155
1156 filter_prefix_list_prefix: TKN_PRFXV4 {
1157 $$ = $1;
1158 }
1159 | TKN_PRFXV4RNG {
1160 $$ = $1;
1161 }
1162 ;
1163
1164 filter_aspath: filter_aspath '|' filter_aspath_term {
1165 $$ = new regexp_or($1, $3);
1166 }
1167 | filter_aspath_term
1168 ;
1169
1170 filter_aspath_term: filter_aspath_term filter_aspath_closure {
1171 $$ = new regexp_cat($1, $2);
1172 }
1173 | filter_aspath_closure
1174 ;
1175
1176 filter_aspath_closure: filter_aspath_closure '*' {
1177 $$ = new regexp_star($1);
1178 }
1179 | filter_aspath_closure '?' {
1180 $$ = new regexp_question($1);
1181 }
1182 | filter_aspath_closure '+' {
1183 $$ = new regexp_plus($1);
1184 }
1185 | filter_aspath_no '~' '+' {
1186 $$ = new regexp_tildaplus($1);
1187 }
1188 | filter_aspath_no '~' '*' {
1189 $$ = new regexp_tildastar($1);
1190 }
1191 | filter_aspath_factor
1192 ;
1193
1194 filter_aspath_factor: '^' {
1195 $$ = new regexp_bol;
1196 }
1197 | '$' {
1198 $$ = new regexp_eol;
1199 }
1200 | '(' filter_aspath ')' {
1201 $$ = $2;
1202 }
1203 | filter_aspath_no
1204 ;
1205
1206 filter_aspath_no: TKN_ASNO {
1207 $$ = new regexp_symbol($1);
1208 }
1209 | KEYW_PEERAS {
1210 $$ = new regexp_symbol(symbols.symID("PEERAS"));
1211 }
1212 | TKN_ASNAME {
1213 $$ = new regexp_symbol($1);
1214 }
1215 | '.' {
1216 $$ = new regexp_symbol(regexp_symbol::MIN_AS, regexp_symbol::MAX_AS);
1217 }
1218 | '[' filter_aspath_range ']' {
1219 $$ = $2;
1220 }
1221 | '[' '^' filter_aspath_range ']' {
1222 $$ = $3;
1223 ((regexp_symbol *) $$)->complement();
1224 }
1225 ;
1226
1227 filter_aspath_range: {
1228 $$ = new regexp_symbol;
1229 }
1230 | filter_aspath_range TKN_ASNO {
1231 ((regexp_symbol *) ($$ = $1))->add($2);
1232 }
1233 | filter_aspath_range KEYW_PEERAS {
1234 ((regexp_symbol *) ($$ = $1))->add(symbols.symID("PEERAS"));
1235 }
1236 | filter_aspath_range '.' {
1237 ((regexp_symbol *) ($$ = $1))->add(regexp_symbol::MIN_AS, regexp_symbol::MAX_AS);
1238 }
1239 | filter_aspath_range TKN_ASNO '-' TKN_ASNO {
1240 ((regexp_symbol *) ($$ = $1))->add($2, $4);
1241 }
1242 | filter_aspath_range TKN_ASNAME {
1243 ((regexp_symbol *) ($$ = $1))->add($2);
1244 }
1245 ;
1246
1247 filter_rp_attribute: TKN_RP_ATTR '.' TKN_WORD '(' generic_list ')' {
1248 const AttrMethod *mtd = searchMethod($1, $3, $5);
1249 if (mtd)
1250 $$ = new FilterRPAttribute($1, mtd, $5);
1251 else {
1252 delete $5;
1253 $$ = NULL;
1254 }
1255 free($3);
1256 }
1257 | TKN_RP_ATTR TKN_OPERATOR list_item {
1258 ItemList *plist = new ItemList;
1259 plist->append($3);
1260
1261 const AttrMethod *mtd = searchMethod($1, $2, plist);
1262 if (mtd)
1263 $$ = new FilterRPAttribute($1, mtd, plist);
1264 else {
1265 delete plist;
1266 $$ = NULL;
1267 }
1268 free($2);
1269 }
1270 | TKN_RP_ATTR '(' generic_list ')' {
1271 const AttrMethod *mtd = searchMethod($1, "()", $3);
1272 if (mtd)
1273 $$ = new FilterRPAttribute($1, mtd, $3);
1274 else {
1275 delete $3;
1276 $$ = NULL;
1277 }
1278 }
1279 | TKN_RP_ATTR '[' generic_list ']' {
1280 const AttrMethod *mtd = searchMethod($1, "[]", $3);
1281 if (mtd)
1282 $$ = new FilterRPAttribute($1, mtd, $3);
1283 else {
1284 delete $3;
1285 $$ = NULL;
1286 }
1287 }
1288 ;
1289
1290 //// peering action pair ////////////////////////////////////////////////
1291
1292 import_peering_action_list: KEYW_FROM peering opt_action {
1293 $$ = new List<PolicyPeeringAction>;
1294 $$->append(new PolicyPeeringAction($2, $3));
1295 }
1296 | import_peering_action_list KEYW_FROM peering opt_action {
1297 $$ = $1;
1298 $$->append(new PolicyPeeringAction($3, $4));
1299 }
1300 ;
1301
1302 export_peering_action_list: KEYW_TO peering opt_action {
1303 $$ = new List<PolicyPeeringAction>;
1304 $$->append(new PolicyPeeringAction($2, $3));
1305 }
1306 | export_peering_action_list KEYW_TO peering opt_action {
1307 $$ = $1;
1308 $$->append(new PolicyPeeringAction($3, $4));
1309 }
1310 ;
1311
1312 //// import/export factor ///////////////////////////////////////////////
1313
1314 import_factor: import_peering_action_list KEYW_ACCEPT filter {
1315 ItemList *afi_list = new ItemList;
1316 afi_list->append(new ItemAFI("ipv4.unicast"));
1317 $$ = new PolicyFactor($1, new FilterAFI (afi_list, $3));
1318 }
1319 ;
1320
1321 import_factor_list: import_factor ';' {
1322 $$ = new PolicyTerm;
1323 $$->append($1);
1324 }
1325 | import_factor_list import_factor ';' {
1326 $$ = $1;
1327 $$->append($2);
1328 }
1329 ;
1330
1331 export_factor: export_peering_action_list KEYW_ANNOUNCE filter {
1332 ItemList *afi_list = new ItemList;
1333 afi_list->append(new ItemAFI("ipv4.unicast"));
1334 $$ = new PolicyFactor($1, new FilterAFI (afi_list, $3));
1335 }
1336 ;
1337
1338 export_factor_list: export_factor ';' {
1339 $$ = new PolicyTerm;
1340 $$->append($1);
1341 }
1342 | export_factor_list export_factor ';' {
1343 $$ = $1;
1344 $$->append($2);
1345 }
1346 ;
1347
1348 //// import/export term /////////////////////////////////////////////////
1349
1350 import_term: import_factor ';' {
1351 PolicyTerm *term = new PolicyTerm;
1352 term->append($1);
1353 $$ = term;
1354 }
1355 | '{' import_factor_list '}' {
1356 $$ = $2;
1357 }
1358 ;
1359
1360 export_term: export_factor ';' {
1361 PolicyTerm *term = new PolicyTerm;
1362 term->append($1);
1363 $$ = term;
1364 }
1365 | '{' export_factor_list '}' {
1366 $$ = $2;
1367 }
1368 ;
1369
1370 //// import/export expr /////////////////////////////////////////////////
1371
1372 import_expr: import_term {
1373 $$ = $1;
1374 }
1375 | import_term KEYW_REFINE import_expr {
1376 $$ = new PolicyRefine($1, $3);
1377 }
1378 | import_term KEYW_EXCEPT import_expr {
1379 $$ = new PolicyExcept($1, $3);
1380 }
1381 ;
1382
1383 export_expr: export_term {
1384 $$ = $1;
1385 }
1386 | export_term KEYW_REFINE export_expr {
1387 $$ = new PolicyRefine($1, $3);
1388 }
1389 | export_term KEYW_EXCEPT export_expr {
1390 $$ = new PolicyExcept($1, $3);
1391 }
1392 ;
1393
1394 //// protocol ///////////////////////////////////////////////////////////
1395
1396 opt_protocol_from: {
1397 $$ = schema.searchProtocol("BGP4");
1398 }
1399 | KEYW_PROTOCOL tkn_word {
1400 $$ = schema.searchProtocol($2);
1401 if (!$$) {
1402 handle_warning("Warning: unknown protocol %s, BGP4 assumed.\n", $2);
1403 $$ = schema.searchProtocol("BGP4");
1404 }
1405 free($2);
1406 }
1407 ;
1408
1409 opt_protocol_into: {
1410 $$ = schema.searchProtocol("BGP4");
1411 }
1412 | KEYW_INTO tkn_word {
1413 $$ = schema.searchProtocol($2);
1414 if (!$$) {
1415 handle_warning("Warning: unknown protocol %s, BGP4 assumed.\n", $2);
1416 $$ = schema.searchProtocol("BGP4");
1417 }
1418 free($2);;
1419 }
1420 ;
1421 //**** mp-import/mp-export attributes TBD *************************************
1422
1423 mp_import_attribute: ATTR_MP_IMPORT
1424 opt_protocol_from opt_protocol_into
1425 mp_import_expr TKN_EOA {
1426 $$ = changeCurrentAttr(new AttrImport($2, $3, $4));
1427 }
1428 | ATTR_MP_IMPORT opt_protocol_from opt_protocol_into opt_afi_list mp_import_factor TKN_EOA {
1429 PolicyTerm *term = new PolicyTerm;
1430 $5->filter = new FilterAFI($4, $5->filter);
1431 term->append($5);
1432 $$ = changeCurrentAttr(new AttrImport($2, $3, term));
1433 }
1434 | ATTR_MP_IMPORT opt_protocol_from opt_protocol_into KEYW_AFI afi_list error TKN_EOA {
1435 $$ = $1;
1436 handle_error ("Error: in peering/filter specification\n");
1437 yyerrok;
1438 }
1439 | ATTR_MP_IMPORT error TKN_EOA {
1440 $$ = $1;
1441 handle_error("Error: wrong mp-import.\n");
1442 yyerrok;
1443 }
1444 ;
1445
1446 mp_export_attribute: ATTR_MP_EXPORT
1447 opt_protocol_from opt_protocol_into
1448 mp_export_expr TKN_EOA {
1449 $$ = changeCurrentAttr(new AttrExport($2, $3, $4));
1450 }
1451 | ATTR_MP_EXPORT opt_protocol_from opt_protocol_into opt_afi_list mp_export_factor TKN_EOA {
1452 PolicyTerm *term = new PolicyTerm;
1453 $5->filter = new FilterAFI($4, $5->filter);
1454 term->append($5);
1455 $$ = changeCurrentAttr(new AttrExport($2, $3, term));
1456 }
1457 | ATTR_MP_EXPORT opt_protocol_from opt_protocol_into KEYW_AFI afi_list error TKN_EOA {
1458 $$ = $1;
1459 handle_error ("Error: in peering/filter specification\n");
1460 yyerrok;
1461 }
1462 | ATTR_MP_EXPORT error TKN_EOA {
1463 $$ = $1;
1464 handle_error("Error: wrong mp-export.\n");
1465 yyerrok;
1466 }
1467 ;
1468 ///////// mp-import/mp-export expr TBD //////////////
1469
1470 mp_import_expr: mp_import_term {
1471 $$ = $1;
1472 }
1473 | mp_import_term KEYW_REFINE mp_import_expr {
1474 $$ = new PolicyRefine($1, $3);
1475 }
1476 | mp_import_term KEYW_EXCEPT mp_import_expr {
1477 $$ = new PolicyExcept($1, $3);
1478 }
1479 ;
1480
1481 mp_export_expr: mp_export_term {
1482 $$ = $1;
1483 }
1484 | mp_export_term KEYW_REFINE mp_export_expr {
1485 $$ = new PolicyRefine($1, $3);
1486 }
1487 | mp_export_term KEYW_EXCEPT mp_export_expr {
1488 $$ = new PolicyExcept($1, $3);
1489 }
1490 ;
1491
1492 /////// mp-import/mp-export term TBD //////////////////
1493
1494 mp_import_term: opt_afi_list mp_import_factor ';' {
1495 PolicyTerm *term = new PolicyTerm;
1496 $2->filter = new FilterAFI($1, $2->filter);
1497 term->append($2);
1498 $$ = term;
1499 }
1500 | opt_afi_list '{' mp_import_factor_list '}' {
1501 for (PolicyFactor *pf = $3->head(); pf; pf = $3->next(pf)) {
1502 pf->filter = new FilterAFI($1, pf->filter);
1503 }
1504 $$ = $3;
1505 }
1506 ;
1507
1508 mp_export_term: opt_afi_list mp_export_factor ';' {
1509 PolicyTerm *term = new PolicyTerm;
1510 $2->filter = new FilterAFI($1, $2->filter);
1511 term->append($2);
1512 $$ = term;
1513 }
1514 | opt_afi_list '{' mp_export_factor_list '}' {
1515 for (PolicyFactor *pf = $3->head(); pf; pf = $3->next(pf)) {
1516 pf->filter = new FilterAFI($1, pf->filter);
1517 }
1518 $$ = $3;
1519 }
1520 ;
1521
1522 //// mp-import/mp-export factor TBD ///////////////////////////////////////////////
1523
1524 mp_import_factor: mp_import_peering_action_list KEYW_ACCEPT mp_filter {
1525 $$ = new PolicyFactor($1, $3);
1526 }
1527 ;
1528
1529 mp_import_factor_list: mp_import_factor ';' {
1530 $$ = new PolicyTerm;
1531 $$->append($1);
1532 }
1533 | mp_import_factor_list mp_import_factor ';' {
1534 $$ = $1;
1535 $$->append($2);
1536 }
1537 ;
1538
1539 mp_export_factor: mp_export_peering_action_list KEYW_ANNOUNCE mp_filter {
1540 $$ = new PolicyFactor($1, $3);
1541 }
1542 ;
1543
1544 mp_export_factor_list: mp_export_factor ';' {
1545 $$ = new PolicyTerm;
1546 $$->append($1);
1547 }
1548 | mp_export_factor_list mp_export_factor ';' {
1549 $$ = $1;
1550 $$->append($2);
1551 }
1552 ;
1553
1554 //// mp-import-mp-export peering action pair TBD ///////////////////////////
1555
1556 mp_import_peering_action_list: KEYW_FROM mp_peering opt_action {
1557 $$ = new List<PolicyPeeringAction>;
1558 $$->append(new PolicyPeeringAction($2, $3));
1559 }
1560 | mp_import_peering_action_list KEYW_FROM mp_peering opt_action {
1561 $$ = $1;
1562 $$->append(new PolicyPeeringAction($3, $4));
1563 }
1564 ;
1565
1566 mp_export_peering_action_list: KEYW_TO mp_peering opt_action {
1567 $$ = new List<PolicyPeeringAction>;
1568 $$->append(new PolicyPeeringAction($2, $3));
1569 }
1570 | mp_export_peering_action_list KEYW_TO mp_peering opt_action {
1571 $$ = $1;
1572 $$->append(new PolicyPeeringAction($3, $4));
1573 }
1574 ;
1575
1576 //// mp-filter //////////////////////
1577
1578 mp_filter: mp_filter OP_OR mp_filter_term {
1579 $$ = new FilterOR($1, $3);
1580 }
1581 | mp_filter mp_filter_term %prec OP_OR {
1582 $$ = new FilterOR($1, $2);
1583 }
1584 | mp_filter_term
1585 ;
1586
1587 mp_filter_term : mp_filter_term OP_AND mp_filter_factor {
1588 $$ = new FilterAND($1, $3);
1589 }
1590 | mp_filter_factor
1591 ;
1592
1593 mp_filter_factor : OP_NOT mp_filter_factor {
1594 $$ = new FilterNOT($2);
1595 }
1596 | '(' mp_filter ')' {
1597 $$ = $2;
1598 }
1599 | mp_filter_operand
1600 ;
1601
1602 mp_filter_operand: KEYW_ANY {
1603 $$ = new FilterANY;
1604 }
1605 | '<' filter_aspath '>' {
1606 $$ = new FilterASPath($2);
1607 }
1608 | filter_rp_attribute {
1609 if ($1)
1610 $$ = $1;
1611 else
1612 $$ = new FilterNOT(new FilterANY);
1613 }
1614 | TKN_FLTRNAME {
1615 $$ = new FilterFLTRNAME($1);
1616 }
1617 | mp_filter_prefix
1618 ;
1619
1620 mp_filter_prefix: mp_filter_prefix_operand OP_MS {
1621 $2->f1 = $1;
1622 $$ = $2;
1623 }
1624 | mp_filter_prefix_operand
1625 ;
1626
1627 mp_filter_prefix_operand: TKN_ASNO {
1628 $$ = new FilterASNO($1);
1629 }
1630 | KEYW_PEERAS {
1631 $$ = new FilterPeerAS;
1632 }
1633 | TKN_ASNAME {
1634 $$ = new FilterASNAME($1);
1635 }
1636 | TKN_RSNAME {
1637 $$ = new FilterRSNAME($1);
1638 }
1639 | '{' opt_mp_filter_prefix_list '}' {
1640 $$ = $2;
1641 }
1642 ;
1643
1644 opt_mp_filter_prefix_list: {
1645 $$ = new FilterMPPRFXList;
1646 }
1647 | mp_filter_prefix_list
1648 ;
1649
1650 mp_filter_prefix_list: mp_filter_prefix_list_prefix {
1651
1652 ((FilterMPPRFXList *) ($$ = new FilterMPPRFXList))->push_back(*$1);
1653 }
1654 | mp_filter_prefix_list ',' mp_filter_prefix_list_prefix {
1655 $$ = $1;
1656 ((FilterMPPRFXList *) ($$))->push_back(*$3);
1657 }
1658 ;
1659
1660 mp_filter_prefix_list_prefix: TKN_PRFXV6 {
1661 $$ = new MPPrefix($1);
1662 }
1663 | TKN_PRFXV6RNG {
1664 $$ = new MPPrefix($1);
1665 }
1666 | TKN_PRFXV4 {
1667 $$ = new MPPrefix($1);
1668 }
1669 | TKN_PRFXV4RNG {
1670 $$ = new MPPrefix($1);
1671 }
1672 ;
1673
1674 //// mp-peering TBD /////////////////////
1675
1676 mp_peering: as_expr opt_mp_router_expr opt_mp_router_expr_with_at {
1677 $$ = new PolicyPeering($1, $2, $3);
1678 // need to check here that afi in opt_mp_router_expr == afi in opt_mp_router_expr_with_at ?
1679
1680 }
1681 | TKN_PRNGNAME {
1682 $$ = new PolicyPeering($1);
1683 }
1684 ;
1685
1686 //// opt_mp_router_expr/with_at ///////////
1687
1688 opt_mp_router_expr: {
1689 $$ = new FilterANY;
1690 }
1691 | mp_router_expr {
1692 $$ = $1;
1693 }
1694 ;
1695
1696 opt_mp_router_expr_with_at: {
1697 $$ = new FilterANY;
1698 }
1699 | KEYW_AT mp_router_expr {
1700 $$ = $2;
1701 }
1702 ;
1703
1704 mp_router_expr: mp_router_expr OP_OR mp_router_expr_term {
1705 $$ = new FilterOR($1, $3);
1706 }
1707 | mp_router_expr_term
1708 ;
1709
1710 mp_router_expr_term: mp_router_expr_term OP_AND mp_router_expr_factor {
1711 $$ = new FilterAND($1, $3);
1712 }
1713 | mp_router_expr_term KEYW_EXCEPT mp_router_expr_factor {
1714 $$ = new FilterEXCEPT($1, $3);
1715 }
1716 | mp_router_expr_term OP_AND OP_NOT mp_router_expr_factor {
1717 $$ = new FilterEXCEPT($1, $4);
1718 }
1719 | mp_router_expr_factor
1720 ;
1721
1722 mp_router_expr_factor: '(' mp_router_expr ')' {
1723 $$ = $2;
1724 }
1725 | mp_router_expr_operand
1726 ;
1727
1728 mp_router_expr_operand: TKN_IPV4 {
1729 $$ = new FilterRouter($1);
1730 }
1731 | TKN_IPV6 {
1732 $$ = new FilterRouter($1);
1733 }
1734 | TKN_DNS {
1735 $$ = new FilterRouterName($1);
1736 }
1737 | TKN_RTRSNAME {
1738 $$ = new FilterRTRSNAME($1);
1739 }
1740 ;
1741
1742 //**** import/export attributes *******************************************
1743
1744 import_attribute: ATTR_IMPORT
1745 opt_protocol_from opt_protocol_into
1746 import_expr TKN_EOA {
1747 $$ = changeCurrentAttr(new AttrImport($2, $3, $4));
1748 }
1749 | ATTR_IMPORT opt_protocol_from opt_protocol_into import_factor TKN_EOA {
1750 PolicyTerm *term = new PolicyTerm;
1751 term->append($4);
1752
1753 $$ = changeCurrentAttr(new AttrImport($2, $3, term));
1754 }
1755 | ATTR_IMPORT error TKN_EOA {
1756 $$ = $1;
1757 handle_error("Error: from <peering> expected.\n");
1758 yyerrok;
1759 }
1760 ;
1761
1762 export_attribute: ATTR_EXPORT
1763 opt_protocol_from opt_protocol_into
1764 export_expr TKN_EOA {
1765 $$ = changeCurrentAttr(new AttrExport($2, $3, $4));
1766 }
1767 | ATTR_EXPORT opt_protocol_from opt_protocol_into export_factor TKN_EOA {
1768 PolicyTerm *term = new PolicyTerm;
1769 term->append($4);
1770
1771 $$ = changeCurrentAttr(new AttrExport($2, $3, term));
1772 }
1773 | ATTR_EXPORT error TKN_EOA {
1774 $$ = $1;
1775 handle_error("Error: to <peering> expected.\n");
1776 yyerrok;
1777 }
1778 ;
1779
1780 opt_default_filter: {
1781 $$ = new FilterANY;
1782 }
1783 | KEYW_NETWORKS filter {
1784 $$ = $2;
1785 }
1786 ;
1787
1788 // **** default attribute
1789
1790 default_attribute: ATTR_DEFAULT KEYW_TO peering
1791 opt_action
1792 opt_default_filter TKN_EOA {
1793 $$ = changeCurrentAttr(new AttrDefault($3, $4, $5));
1794 }
1795 | ATTR_DEFAULT KEYW_TO peering error TKN_EOA {
1796 if ($3)
1797 delete $3;
1798 handle_error("Error: badly formed filter/action or keyword NETWORKS/ACTION missing.\n");
1799 yyerrok;
1800 }
1801 | ATTR_DEFAULT error TKN_EOA {
1802 handle_error("Error: TO <peer> missing.\n");
1803 yyerrok;
1804 }
1805 ;
1806
1807 // **** mp-default attribute TBD *******************///
1808
1809 mp_default_attribute: ATTR_MP_DEFAULT opt_afi_list
1810 KEYW_TO mp_peering
1811 opt_action
1812 opt_default_mp_filter TKN_EOA {
1813 $$ = changeCurrentAttr(new AttrDefault($2, $4, $5, $6));
1814 }
1815 | ATTR_MP_DEFAULT opt_afi_list KEYW_TO mp_peering error TKN_EOA {
1816 if ($4)
1817 delete $4;
1818 handle_error("Error: badly formed filter/action or keyword NETWORKS/ACTION missing.\n");
1819 yyerrok;
1820 }
1821 | ATTR_MP_DEFAULT error TKN_EOA {
1822 handle_error("Error: TO <peer> missing. in mp-default\n");
1823 yyerrok;
1824 }
1825 ;
1826
1827 opt_default_mp_filter: {
1828 $$ = new FilterANY;
1829 }
1830 | KEYW_NETWORKS mp_filter {
1831 $$ = $2;
1832 }
1833 ;
1834
1835 /// filter specification //////////////////////////
1836
1837 filter_attribute: ATTR_FILTER filter TKN_EOA {
1838 // check that "mp-filter:" is not present
1839 if (current_object->hasAttr("mp-filter")) {
1840 handle_error("Error: mp-filter and filter attributes can't be used together\n");
1841 yyerrok;
1842 } else {
1843 //$$ = changeCurrentAttr(new AttrFilter($2));
1844 $$ = changeCurrentAttr(new AttrFilter(new FilterAFI(new ItemAFI(new AddressFamily("ipv4.unicast")), $2)));
1845 }
1846 }
1847 | ATTR_FILTER error TKN_EOA {
1848 $$ = $1;
1849 handle_error("Error: badly formed filter.\n");
1850 yyerrok;
1851 }
1852 ;
1853
1854 // for peval
1855
1856 mp_peval_attribute: ATTR_MP_PEVAL mp_peval TKN_EOA {
1857 $$ = changeCurrentAttr(new AttrMPPeval($2));
1858 }
1859 | ATTR_MP_PEVAL error TKN_EOA {
1860 $$ = $1;
1861 handle_error("Error: badly formed filter in mp-peval.\n");
1862 yyerrok;
1863 }
1864 ;
1865
1866 mp_peval: KEYW_AFI afi_list mp_filter {
1867 $$ = new FilterAFI((ItemList *) $2, $3);
1868 }
1869 ;
1870
1871 /// mp-filter attribute ///
1872
1873 mp_filter_attribute: ATTR_MP_FILTER mp_filter TKN_EOA {
1874 // check that "filter:" is not present
1875 if (current_object->hasAttr("filter")) {
1876 handle_error("Error: mp-filter and filter attributes can't be used together\n");
1877 yyerrok;
1878 } else {
1879 $$ = changeCurrentAttr(new AttrFilter($2));
1880 }
1881 }
1882 | ATTR_MP_FILTER error TKN_EOA {
1883 $$ = $1;
1884 handle_error("Error: badly formed filter in mp-filter.\n");
1885 yyerrok;
1886 }
1887 ;
1888
1889 //** peering attribute *****//
1890
1891 peering_attribute: ATTR_PEERING peering TKN_EOA {
1892 $$ = changeCurrentAttr(new AttrPeering($2));
1893 }
1894 | ATTR_PEERING error TKN_EOA {
1895 $$ = $1;
1896 handle_error("Error: badly formed filter.\n");
1897 yyerrok;
1898 }
1899 ;
1900
1901 //** mp-peering attribute TBD *****//
1902
1903 mp_peering_attribute: ATTR_MP_PEERING mp_peering TKN_EOA {
1904 $$ = changeCurrentAttr(new AttrPeering($2));
1905 }
1906 | ATTR_MP_PEERING error TKN_EOA {
1907 $$ = $1;
1908 handle_error("Error: badly formed peering.\n");
1909 yyerrok;
1910 }
1911 ;
1912
1913 //**** inet-rtr class *****************************************************
1914
1915 ////// ifaddr attribute ///////////////////////////////////////////////////
1916
1917 ifaddr_attribute: ATTR_IFADDR TKN_IPV4 KEYW_MASKLEN TKN_INT opt_action TKN_EOA {
1918 $$ = changeCurrentAttr(new AttrIfAddr(new MPPrefix((PrefixRange *) $2), $4, $5, NULL));
1919 }
1920 | ATTR_IFADDR TKN_IPV4 KEYW_MASKLEN TKN_INT error TKN_EOA {
1921 delete $2;
1922 $$ = $1;
1923 handle_error("Error: in action specification.\n");
1924 yyerrok;
1925 }
1926 | ATTR_IFADDR TKN_IPV4 KEYW_MASKLEN error TKN_EOA {
1927 delete $2;
1928 $$ = $1;
1929 handle_error("Error: integer mask length expected.\n");
1930 yyerrok;
1931 }
1932 | ATTR_IFADDR TKN_IPV4 error TKN_EOA {
1933 delete $2;
1934 $$ = $1;
1935 handle_error("Error: MASKLEN <length> expected.\n");
1936 yyerrok;
1937 }
1938 | ATTR_IFADDR error TKN_EOA {
1939 $$ = $1;
1940 handle_error("Error: <ip_address> MASKLEN <length> [<action>] expected.\n");
1941 yyerrok;
1942 }
1943 ;
1944
1945 ////// interface attribute TBD ///////////////////////////////////////////
1946
1947 interface_address: TKN_IPV4 {
1948 $$ = new MPPrefix($1);
1949 }
1950 | TKN_IPV6 {
1951 $$ = new MPPrefix($1);
1952 }
1953 ;
1954
1955 opt_tunnel_spec: {
1956 $$ = NULL;
1957 }
1958 | KEYW_TUNNEL interface_address ',' TKN_WORD {
1959 $$ = new Tunnel($2, new ItemWORD($4));
1960 if (! (schema.searchTypedef("encapsulation"))->validate(new ItemWORD($4))) {
1961 delete $$;
1962 handle_error("Error: wrong encapsulation specified.\n");
1963 yyerrok;
1964 }
1965 }
1966 ;
1967
1968 interface_attribute: ATTR_INTERFACE interface_address KEYW_MASKLEN TKN_INT
1969 opt_action
1970 opt_tunnel_spec TKN_EOA {
1971 $$ = changeCurrentAttr(new AttrIfAddr($2, $4, $5, $6));
1972 if ($6) {
1973 if (($2->ipv4 && $6->remote_ip->ipv6) || ($2->ipv6 && $6->remote_ip->ipv4)) {
1974 handle_error("Error: address family mismatch in local/remote tunnel endpoint\n");
1975 yyerrok;
1976 }
1977 }
1978 }
1979 | ATTR_INTERFACE interface_address KEYW_MASKLEN TKN_INT opt_action error TKN_EOA {
1980 $$ = $1;
1981 handle_error("Error: error in tunnel specification.\n");
1982 yyerrok;
1983 }
1984 | ATTR_INTERFACE interface_address KEYW_MASKLEN error TKN_EOA {
1985 $$ = $1;
1986 handle_error("Error: integer mask length expected.\n");
1987 yyerrok;
1988 }
1989 | ATTR_INTERFACE interface_address error TKN_EOA {
1990 $$ = $1;
1991 handle_error("Error: MASKLEN <length> expected.\n");
1992 yyerrok;
1993 }
1994 | ATTR_INTERFACE error TKN_EOA {
1995 $$ = $1;
1996 handle_error("Error: <ip_address> MASKLEN <length> [<action>] [<tunnel>] expected.\n");
1997 yyerrok;
1998 }
1999 ;
2000
2001 //// peer attribute /////////////////////////////////////////////////////
2002
2003 opt_peer_options: {
2004 $$ = new List<AttrPeerOption>;
2005 }
2006 | peer_options {
2007 $$ = $1;
2008 }
2009 ;
2010
2011 peer_options: peer_option {
2012 $$ = new List<AttrPeerOption>;
2013 $$->append($1);
2014 }
2015 | peer_options ',' peer_option {
2016 $$ = $1;
2017 $$->append($3);
2018 }
2019 ;
2020
2021 peer_option: tkn_word '(' generic_list ')' {
2022 $$ = new AttrPeerOption($1, $3);
2023 }
2024 ;
2025
2026 peer_id: TKN_IPV4
2027 | TKN_DNS {
2028 $$ = new IPAddr;
2029 }
2030 | TKN_RTRSNAME {
2031 $$ = new IPAddr;
2032 }
2033 | TKN_PRNGNAME {
2034 $$ = new IPAddr;
2035 }
2036 ;
2037
2038 peer_attribute: ATTR_PEER tkn_word peer_id opt_peer_options TKN_EOA {
2039 const AttrProtocol *protocol = schema.searchProtocol($2);
2040 int position;
2041 const RPType *correctType;
2042 bool error = false;
2043
2044 if (!protocol) {
2045 handle_error("Error: unknown protocol %s.\n", $2);
2046 error = true;
2047 } else {
2048 ((AttrProtocol *) protocol)->startMandatoryCheck();
2049 for (AttrPeerOption *opt = $4->head(); opt; opt = $4->next(opt)) {
2050 const AttrProtocolOption *decl = protocol->searchOption(opt->option);
2051 if (!decl) {
2052 handle_error("Error: protocol %s does not have option %s.\n",
2053 $2, opt->option);
2054 error = true;
2055 } else {
2056 for (; decl; decl = protocol->searchNextOption(decl))
2057 if (decl->option->validateArgs(opt->args, position, correctType))
2058 break;
2059 if (! decl) {
2060 if (! (!strcasecmp(protocol->name, "BGP4")
2061 && !strcasecmp(opt->option, "asno")
2062 && opt->args->isSingleton()
2063 && typeid(*opt->args->head()) == typeid(ItemWORD)
2064 && !strcasecmp(((ItemWORD *) opt->args->head())->word,
2065 "peeras"))) {
2066 handleArgumentTypeError($2, opt->option, position,
2067 correctType);
2068 error = true;
2069 }
2070 }
2071 }
2072 }
2073 }
2074
2075 if (! error) {
2076 const AttrProtocolOption *missing =
2077 ((AttrProtocol *) protocol)->missingMandatoryOption();
2078 if (missing) {
2079 handle_error("Error: mandatory option %s of protocol %s is missing.\n",
2080 missing->option->name, $2);
2081 error = true;
2082 }
2083 }
2084
2085 if (!error)
2086 //$$ = changeCurrentAttr(new AttrPeer(protocol, $3, $4));
2087 $$ = changeCurrentAttr(new AttrPeer(protocol, new MPPrefix((PrefixRange *) $3), $4));
2088 else {
2089 free($2);
2090 delete $3;
2091 delete $4;
2092 }
2093 }
2094 | ATTR_PEER tkn_word TKN_IPV4 error TKN_EOA {
2095 $$ = $1;
2096 free($2);
2097 delete $3;
2098 handle_error("Error: in peer option.\n");
2099 yyerrok;
2100 }
2101 | ATTR_PEER tkn_word error TKN_EOA {
2102 $$ = $1;
2103 free($2);
2104 handle_error("Error: missing peer ip_address.\n");
2105 yyerrok;
2106 }
2107 | ATTR_PEER error TKN_EOA {
2108 $$ = $1;
2109 handle_error("Error: missing protocol name.\n");
2110 yyerrok;
2111 }
2112 ;
2113
2114 // mp-peer attribute TBD *****************//
2115
2116 mp_peer_attribute: ATTR_MP_PEER TKN_WORD mp_peer_id opt_peer_options TKN_EOA {
2117 const AttrProtocol *protocol = schema.searchProtocol($2);
2118 int position;
2119 const RPType *correctType;
2120 bool error = false;
2121
2122 if (!protocol) {
2123 handle_error("Error: unknown protocol %s.\n", $2);
2124 error = true;
2125 } else {
2126 ((AttrProtocol *) protocol)->startMandatoryCheck();
2127 for (AttrPeerOption *opt = $4->head(); opt; opt = $4->next(opt)) {
2128 const AttrProtocolOption *decl = protocol->searchOption(opt->option);
2129 if (!decl) {
2130 handle_error("Error: protocol %s does not have option %s.\n",
2131 $2, opt->option);
2132 error = true;
2133 } else {
2134 for (; decl; decl = protocol->searchNextOption(decl))
2135 if (decl->option->validateArgs(opt->args, position, correctType))
2136 break;
2137 if (! decl) {
2138 if (! (!strcasecmp(protocol->name, "BGP4")
2139 && !strcasecmp(opt->option, "asno")
2140 && opt->args->isSingleton()
2141 && typeid(*opt->args->head()) == typeid(ItemWORD)
2142 && !strcasecmp(((ItemWORD *) opt->args->head())->word,
2143 "peeras"))) {
2144 handleArgumentTypeError($2, opt->option, position,
2145 correctType);
2146 error = true;
2147 }
2148 }
2149 }
2150 }
2151 }
2152
2153 if (! error) {
2154 const AttrProtocolOption *missing =
2155 ((AttrProtocol *) protocol)->missingMandatoryOption();
2156 if (missing) {
2157 handle_error("Error: mandatory option %s of protocol %s is missing.\n",
2158 missing->option->name, $2);
2159 error = true;
2160 }
2161 }
2162
2163 if (!error) {
2164 $$ = changeCurrentAttr(new AttrPeer(protocol, $3, $4));
2165 }
2166 else {
2167 free($2);
2168 delete $3;
2169 delete $4;
2170 }
2171
2172 }
2173 | ATTR_MP_PEER TKN_WORD mp_peer_id error TKN_EOA {
2174 $$ = $1;
2175 free($2);
2176 delete $3;
2177 handle_error("Error: in peer option.\n");
2178 yyerrok;
2179 }
2180 | ATTR_MP_PEER TKN_WORD error TKN_EOA {
2181 $$ = $1;
2182 free($2);
2183 handle_error("Error: missing peer ip_address.\n");
2184 yyerrok;
2185 }
2186 | ATTR_MP_PEER error TKN_EOA {
2187 $$ = $1;
2188 handle_error("Error: missing protocol name.\n");
2189 yyerrok;
2190 }
2191 ;
2192
2193 mp_peer_id: TKN_IPV4 {
2194 $$ = new MPPrefix($1);
2195 }
2196 | TKN_IPV6 {
2197 $$ = new MPPrefix($1);
2198 }
2199 | TKN_DNS {
2200 $$ = new MPPrefix;
2201 }
2202 | TKN_RTRSNAME {
2203 // $$ = new IPAddr;
2204 $$ = new MPPrefix;
2205 }
2206 | TKN_PRNGNAME {
2207 // $$ = new IPAddr;
2208 $$ = new MPPrefix;
2209 }
2210 ;
2211
2212
2213 //**** route6 class *******************************************************
2214
2215
2216 //// v6_filter v6 only filter in route6 object //////////////////////////////////////////////////////////
2217
2218 v6_filter_attribute: ATTR_V6_FILTER v6_filter TKN_EOA {
2219 $$ = changeCurrentAttr(new AttrFilter($2));
2220 }
2221 | ATTR_V6_FILTER error TKN_EOA {
2222 $$ = $1;
2223 handle_error("Error: badly formed filter.\n");
2224 yyerrok;
2225 }
2226 ;
2227
2228 v6_filter: v6_filter OP_OR v6_filter_term {
2229 $$ = new FilterOR($1, $3);
2230 }
2231 | v6_filter v6_filter_term %prec OP_OR {
2232 $$ = new FilterOR($1, $2);
2233 }
2234 | v6_filter_term
2235 ;
2236
2237 v6_filter_term : v6_filter_term OP_AND v6_filter_factor {
2238 $$ = new FilterAND($1, $3);
2239 }
2240 | v6_filter_factor
2241 ;
2242
2243 v6_filter_factor : OP_NOT v6_filter_factor {
2244 $$ = new FilterNOT($2);
2245 }
2246 | '(' v6_filter ')' {
2247 $$ = $2;
2248 }
2249 | v6_filter_operand
2250 ;
2251
2252 v6_filter_operand: KEYW_ANY {
2253 $$ = new FilterANY;
2254 }
2255 | '<' filter_aspath '>' {
2256 $$ = new FilterASPath($2);
2257 }
2258 | filter_rp_attribute {
2259 if ($1)
2260 $$ = $1;
2261 else
2262 $$ = new FilterNOT(new FilterANY);
2263 }
2264 | TKN_FLTRNAME {
2265 $$ = new FilterFLTRNAME($1);
2266 }
2267 | v6_filter_prefix
2268 ;
2269
2270 v6_filter_prefix: v6_filter_prefix_operand OP_MS {
2271 $2->f1 = $1;
2272 $$ = $2;
2273 }
2274 | v6_filter_prefix_operand
2275 ;
2276
2277 v6_filter_prefix_operand: TKN_ASNO {
2278 $$ = new FilterASNO($1);
2279 }
2280 | KEYW_PEERAS {
2281 $$ = new FilterPeerAS;
2282 }
2283 | TKN_ASNAME {
2284 $$ = new FilterASNAME($1);
2285 }
2286 | TKN_RSNAME {
2287 $$ = new FilterRSNAME($1);
2288 }
2289 | '{' opt_v6_filter_prefix_list '}' {
2290 $$ = $2;
2291 }
2292 ;
2293
2294 opt_v6_filter_prefix_list: {
2295 $$ = new FilterMPPRFXList;
2296 }
2297 | v6_filter_prefix_list
2298 ;
2299
2300 v6_filter_prefix_list: v6_filter_prefix_list_prefix {
2301
2302 ((FilterMPPRFXList *) ($$ = new FilterMPPRFXList))->push_back(*$1);
2303 }
2304 | v6_filter_prefix_list ',' v6_filter_prefix_list_prefix {
2305 $$ = $1;
2306 ((FilterMPPRFXList *) ($$))->push_back(*$3);
2307 }
2308 ;
2309
2310
2311 v6_filter_prefix_list_prefix: TKN_PRFXV6 {
2312 $$ = new MPPrefix($1);
2313 }
2314 | TKN_PRFXV6RNG {
2315 $$ = new MPPrefix($1);
2316 }
2317 ;
2318
2319 //// v6-components attribute ///////////////////////////////////////////////
2320
2321 v6_components_attribute: ATTR_V6_COMPONENTS opt_atomic v6_components_list TKN_EOA {
2322 $$ = $1;
2323 }
2324 | ATTR_V6_COMPONENTS error TKN_EOA {
2325 $$ = $1;
2326 handle_error("Error: [ATOMIC] [[<filter>] [PROTOCOL <protocol> <filter>] ...] expected.\n");
2327 yyerrok;
2328 }
2329 ;
2330
2331 v6_components_list: {
2332 }
2333 | v6_filter {
2334 delete $1;
2335 }
2336 | v6_components_list KEYW_PROTOCOL TKN_WORD v6_filter {
2337 free($3);
2338 delete $4;
2339 }
2340 ;
2341
2342
2343
2344
2345 //// v6-inject attribute ///////////////////////////////////////////////////
2346
2347 v6_inject_attribute: ATTR_V6_INJECT opt_mp_router_expr_with_at opt_action opt_v6_inject_expr TKN_EOA {
2348 $$ = $1;
2349 delete $2;
2350 delete $3;
2351 delete $4;
2352
2353 }
2354 | ATTR_V6_INJECT error TKN_EOA {
2355 $$ = $1;
2356 handle_error("Error: [at <router-exp>] [action <action>] [upon <condition>] expected.\n");
2357 yyerrok;
2358 }
2359 ;
2360
2361 opt_v6_inject_expr: {
2362 $$ = new FilterANY;
2363 }
2364 | KEYW_UPON v6_inject_expr {
2365 $$ = $2;
2366 }
2367 ;
2368
2369 v6_inject_expr: v6_inject_expr OP_OR v6_inject_expr_term {
2370 $$ = new FilterOR($1, $3);
2371 }
2372 | v6_inject_expr_term {
2373 }
2374 ;
2375
2376 v6_inject_expr_term: v6_inject_expr_term OP_AND v6_inject_expr_factor {
2377 $$ = new FilterAND($1, $3);
2378 }
2379 | v6_inject_expr_factor
2380 ;
2381
2382 v6_inject_expr_factor: '(' v6_inject_expr ')' {
2383 $$ = $2;
2384 }
2385 | v6_inject_expr_operand
2386 ;
2387
2388 v6_inject_expr_operand: KEYW_STATIC {
2389 $$ = new FilterANY;
2390 }
2391 | KEYW_HAVE_COMPONENTS '{' opt_v6_filter_prefix_list '}' {
2392 $$ = new FilterV6HAVE_COMPONENTS((FilterMPPRFXList *) $3);
2393 }
2394 | KEYW_EXCLUDE '{' opt_v6_filter_prefix_list '}' {
2395 $$ = new FilterV6EXCLUDE((FilterMPPRFXList *) $3);
2396 }
2397 ;
2398
2399 //**** route class ********************************************************
2400
2401 aggr_bndry_attribute: ATTR_AGGR_BNDRY as_expr TKN_EOA {
2402 $$ = $1;
2403 delete $2;
2404 }
2405 | ATTR_AGGR_BNDRY error TKN_EOA {
2406 $$ = $1;
2407 handle_error("Error: <as-expression> expected.\n");
2408 yyerrok;
2409 }
2410 ;
2411
2412 aggr_mtd_attribute: ATTR_AGGR_MTD KEYW_INBOUND TKN_EOA {
2413 $$ = $1;
2414 }
2415 | ATTR_AGGR_MTD KEYW_OUTBOUND opt_as_expr TKN_EOA {
2416 delete $3;
2417 }
2418 | ATTR_AGGR_MTD KEYW_OUTBOUND error TKN_EOA {
2419 $$ = $1;
2420 handle_error("Error: OUTBOUND <as-expression> expected.\n");
2421 yyerrok;
2422 }
2423 | ATTR_AGGR_MTD KEYW_INBOUND error TKN_EOA {
2424 $$ = $1;
2425 handle_error("Error: INBOUND can not be followed by anything.\n");
2426 yyerrok;
2427 }
2428 | ATTR_AGGR_MTD error TKN_EOA {
2429 $$ = $1;
2430 handle_error("Error: keyword INBOUND or OUTBOUND expected.\n");
2431 yyerrok;
2432 }
2433 ;
2434
2435 //// inject attribute ///////////////////////////////////////////////////
2436
2437 opt_inject_expr: {
2438 $$ = new FilterANY;
2439 }
2440 | KEYW_UPON inject_expr {
2441 $$ = $2;
2442 }
2443 ;
2444
2445 inject_expr: inject_expr OP_OR inject_expr_term {
2446 $$ = new FilterOR($1, $3);
2447 }
2448 | inject_expr_term
2449 ;
2450
2451 inject_expr_term: inject_expr_term OP_AND inject_expr_factor {
2452 $$ = new FilterAND($1, $3);
2453 }
2454 | inject_expr_factor
2455 ;
2456
2457 inject_expr_factor: '(' inject_expr ')' {
2458 $$ = $2;
2459 }
2460 | inject_expr_operand
2461 ;
2462
2463 inject_expr_operand: KEYW_STATIC {
2464 $$ = new FilterANY;
2465 }
2466 | KEYW_HAVE_COMPONENTS '{' opt_filter_prefix_list '}' {
2467 $$ = new FilterHAVE_COMPONENTS((FilterPRFXList *) $3);
2468 }
2469 | KEYW_EXCLUDE '{' opt_filter_prefix_list '}' {
2470 $$ = new FilterEXCLUDE((FilterPRFXList *) $3);
2471 }
2472 ;
2473
2474 inject_attribute: ATTR_INJECT opt_router_expr_with_at opt_action opt_inject_expr TKN_EOA {
2475 $$ = $1;
2476 delete $2;
2477 delete $3;
2478 delete $4;
2479 }
2480 | ATTR_INJECT error TKN_EOA {
2481 $$ = $1;
2482 handle_error("Error: [at <router-exp>] [action <action>] [upon <condition>] expected.\n");
2483 yyerrok;
2484 }
2485 ;
2486
2487 //// components attribute ///////////////////////////////////////////////
2488
2489 opt_atomic:
2490 | KEYW_ATOMIC
2491 ;
2492
2493 components_list: {
2494 }
2495 | filter {
2496 delete $1;
2497 }
2498 | components_list KEYW_PROTOCOL tkn_word filter {
2499 free($3);
2500 delete $4;
2501 }
2502 ;
2503
2504 components_attribute: ATTR_COMPONENTS opt_atomic components_list TKN_EOA {
2505 $$ = $1;
2506 }
2507 | ATTR_COMPONENTS error TKN_EOA {
2508 $$ = $1;
2509 handle_error("Error: [ATOMIC] [[<filter>] [PROTOCOL <protocol> <filter>] ...] expected.\n");
2510 yyerrok;
2511 }
2512 ;
2513
2514 //**** route-set **********************************************************
2515
2516 opt_rs_members_list: /* empty list */ {
2517 $$ = new ItemList;
2518 }
2519 | rs_members_list {
2520 $$ = $1;
2521 }
2522 ;
2523
2524 rs_members_list: rs_member {
2525 $$ = new ItemList;
2526 $$->append($1);
2527 }
2528 | rs_members_list ',' rs_member {
2529 $$ = $1;
2530 $$->append($3);
2531 }
2532 ;
2533
2534 rs_member: TKN_ASNO {
2535 $$ = new ItemASNO($1);
2536 }
2537 | TKN_ASNO OP_MS {
2538 $$ = new ItemMSItem(new ItemASNO($1), $2->code, $2->n, $2->m);
2539 delete $2;
2540 }
2541 | TKN_ASNAME {
2542 $$ = new ItemASNAME($1);
2543 }
2544 | TKN_ASNAME OP_MS {
2545 $$ = new ItemMSItem(new ItemASNAME($1), $2->code, $2->n, $2->m);
2546 delete $2;
2547 }
2548 | TKN_RSNAME {
2549 $$ = new ItemRSNAME($1);
2550 }
2551 | TKN_RSNAME OP_MS {
2552 $$ = new ItemMSItem(new ItemRSNAME($1), $2->code, $2->n, $2->m);
2553 delete $2;
2554 }
2555 | TKN_PRFXV4 {
2556 $$ = new ItemPRFXV4($1);
2557 }
2558 | TKN_PRFXV4RNG {
2559 $$ = new ItemPRFXV4Range($1);
2560 }
2561 ;
2562
2563 rs_members_attribute: ATTR_RS_MEMBERS opt_rs_members_list TKN_EOA {
2564 $$ = changeCurrentAttr(new AttrGeneric($1->type, $2));
2565 }
2566 | ATTR_RS_MEMBERS error TKN_EOA {
2567 $$ = $1;
2568 handle_error("Error: invalid member\n");
2569 yyerrok;
2570 }
2571 ;
2572
2573 //* mp-members attribute of route-set object TBD */
2574
2575 opt_rs_mp_members_list: /* empty list */ {
2576 $$ = new ItemList;
2577 }
2578 | rs_mp_members_list {
2579 $$ = $1;
2580 }
2581 ;
2582
2583 rs_mp_members_list: rs_mp_member {
2584 $$ = new ItemList;
2585 $$->append($1);
2586 }
2587 | rs_mp_members_list ',' rs_mp_member {
2588 $$ = $1;
2589 $$->append($3);
2590 }
2591 ;
2592
2593 rs_mp_member: TKN_ASNO {
2594 $$ = new ItemASNO($1);
2595 }
2596 | TKN_ASNO OP_MS {
2597 $$ = new ItemMSItem(new ItemASNO($1), $2->code, $2->n, $2->m);
2598 delete $2;
2599 }
2600 | TKN_ASNAME {
2601 $$ = new ItemASNAME($1);
2602 }
2603 | TKN_ASNAME OP_MS {
2604 $$ = new ItemMSItem(new ItemASNAME($1), $2->code, $2->n, $2->m);
2605 delete $2;
2606 }
2607 | TKN_RSNAME {
2608 $$ = new ItemRSNAME($1);
2609 }
2610 | TKN_RSNAME OP_MS {
2611 $$ = new ItemMSItem(new ItemRSNAME($1), $2->code, $2->n, $2->m);
2612 delete $2;
2613 }
2614 | TKN_PRFXV4 {
2615 $$ = new ItemPRFXV4($1);
2616 }
2617 | TKN_PRFXV4RNG {
2618 $$ = new ItemPRFXV4Range($1);
2619 }
2620 | TKN_PRFXV6 {
2621 $$ = new ItemPRFXV6($1);
2622 }
2623 | TKN_PRFXV6RNG {
2624 $$ = new ItemPRFXV6Range($1);
2625 }
2626 ;
2627
2628 rs_mp_members_attribute: ATTR_RS_MP_MEMBERS opt_rs_mp_members_list TKN_EOA {
2629 $$ = changeCurrentAttr(new AttrGeneric($1->type, $2));
2630 }
2631 | ATTR_RS_MP_MEMBERS error TKN_EOA {
2632 $$ = $1;
2633 handle_error("Error: invalid member\n");
2634 yyerrok;
2635 }
2636 ;
2637
2638 //**** dictionary *********************************************************
2639
2640 rpattr_attribute: ATTR_RP_ATTR TKN_WORD methods TKN_EOA {
2641 $$ = changeCurrentAttr(new AttrRPAttr($2, $3));
2642 }
2643 | ATTR_RP_ATTR TKN_RP_ATTR methods TKN_EOA {
2644 $$ = changeCurrentAttr(new AttrRPAttr($2->name, $3));
2645 }
2646 | ATTR_RP_ATTR error TKN_EOA {
2647 $$ = $1;
2648 handle_error("Error: invalid rp-attribute specification\n");
2649 yyerrok;
2650 }
2651 ;
2652
2653 methods: method {
2654 $$ = new List<AttrMethod>;
2655 if ($1)
2656 $$->append($1);
2657 }
2658 | methods method {
2659 $$ = $1;
2660 if ($2)
2661 $$->append($2);
2662 }
2663 ;
2664
2665 method: TKN_WORD '(' ')' {
2666 $$ = new AttrMethod($1, new List<RPTypeNode>, false);
2667 }
2668 | TKN_WORD '(' typedef_type_list ')' {
2669 $$ = new AttrMethod($1, $3, false);
2670 }
2671 | TKN_WORD '(' typedef_type_list ',' TKN_3DOTS ')' {
2672 $$ = new AttrMethod($1, $3, true);
2673 }
2674 | KEYW_OPERATOR TKN_OPERATOR '(' typedef_type_list ')' {
2675 char buffer[16];
2676 strcpy(buffer, "operator");
2677 strcat(buffer, $2);
2678 $$ = new AttrMethod(strdup(buffer), $4, false, true);
2679 free($2);
2680 }
2681 | KEYW_OPERATOR TKN_OPERATOR '(' typedef_type_list ',' TKN_3DOTS ')' {
2682 char buffer[16];
2683 strcpy(buffer, "operator");
2684 strcat(buffer, $2);
2685 $$ = new AttrMethod(strdup(buffer), $4, true, true);
2686 free($2);
2687 }
2688 | TKN_WORD error ')' {
2689 free($1);
2690 $$ = NULL;
2691 handle_error("Error: invalid method specification for %s\n", $1);
2692 }
2693 | KEYW_OPERATOR TKN_OPERATOR error ')' {
2694 $$ = NULL;
2695 handle_error("Error: invalid operator specification for %s\n", $2);
2696 free($2);
2697 }
2698 | KEYW_OPERATOR error ')' {
2699 $$ = NULL;
2700 handle_error("Error: invalid operator\n");
2701 }
2702 | error ')' {
2703 $$ = NULL;
2704 handle_error("Error: method specification expected\n");
2705 }
2706 ;
2707
2708 //// typedef attribute /////////////////////////////////////////////////
2709
2710 typedef_attribute: ATTR_TYPEDEF TKN_WORD typedef_type TKN_EOA {
2711 $$ = changeCurrentAttr(new AttrTypedef($2, $3));
2712 }
2713 | ATTR_TYPEDEF error TKN_EOA {
2714 $$ = $1;
2715 handle_error("Error: invalid typedef specification\n");
2716 yyerrok;
2717 }
2718 ;
2719
2720 typedef_type_list: typedef_type {
2721 $$ = new List<RPTypeNode>;
2722 if ($1)
2723 $$->append(new RPTypeNode($1));
2724 }
2725 | typedef_type_list ',' typedef_type {
2726 $$ = $1;
2727 if ($3)
2728 $$->append(new RPTypeNode($3));
2729 }
2730 ;
2731
2732 typedef_type: KEYW_UNION typedef_type_list {
2733 $$ = RPType::newRPType("union", $2);
2734 if (!$$) {
2735 handle_error("Error: empty union specification\n");
2736 delete $2;
2737 }
2738 }
2739 | KEYW_RANGE KEYW_OF typedef_type {
2740 if ($3)
2741 $$ = new RPTypeRange($3);
2742 else {
2743 $$ = NULL;
2744 }
2745 }
2746 | TKN_WORD {
2747 $$ = RPType::newRPType($1);
2748 if (!$$) {
2749 handle_error("Error: invalid type %s\n", $1);
2750 }
2751 free($1);
2752 }
2753 | TKN_WORD '[' TKN_INT ',' TKN_INT ']' {
2754 $$ = RPType::newRPType($1, $3, $5);
2755 if (!$$) {
2756 handle_error("Error: invalid type %s[%d,%d]\n", $1, $3, $5);
2757 }
2758 free($1);
2759 }
2760 | TKN_WORD '[' TKN_REAL ',' TKN_REAL ']' {
2761 $$ = RPType::newRPType($1, $3, $5);
2762 if (!$$) {
2763 handle_error("Error: invalid type %s[%f,%f]\n", $1, $3, $5);
2764 }
2765 free($1);
2766 }
2767 | TKN_WORD '[' enum_list ']' {
2768 $$ = RPType::newRPType($1, $3);
2769 if (!$$) {
2770 handle_error("Error: invalid type %s, enum expected\n", $1);
2771 delete $3;
2772 }
2773 free($1);
2774 }
2775 | KEYW_LIST '[' TKN_INT ':' TKN_INT ']' KEYW_OF typedef_type {
2776 if ($8)
2777 if ($3 < $5)
2778 $$ = new RPTypeList($8, $3, $5);
2779 else
2780 $$ = new RPTypeList($8, $5, $3);
2781 else {
2782 $$ = NULL;
2783 delete $8;
2784 }
2785 }
2786 | KEYW_LIST KEYW_OF typedef_type {
2787 if ($3)
2788 $$ = new RPTypeList($3);
2789 else {
2790 $$ = NULL;
2791 }
2792 }
2793 | KEYW_LIST error KEYW_OF typedef_type {
2794 $$ = NULL;
2795 delete $4;
2796 handle_error("Error: invalid list size\n");
2797 }
2798 ;
2799
2800 enum_list: tkn_word {
2801 $$ = new List<WordNode>;
2802 $$->append(new WordNode($1));
2803 }
2804 | enum_list ',' tkn_word {
2805 $$ = $1;
2806 $$->append(new WordNode($3));
2807 }
2808 ;
2809
2810 //// protocol attribute /////////////////////////////////////////////////
2811
2812 protocol_attribute: ATTR_PROTOCOL tkn_word protocol_options TKN_EOA {
2813 $$ = changeCurrentAttr(new AttrProtocol($2, $3));
2814 }
2815 | ATTR_PROTOCOL tkn_word error TKN_EOA {
2816 $$ = $1;
2817 handle_error("Error: invalid protocol option\n");
2818 yyerrok;
2819 }
2820 | ATTR_PROTOCOL error TKN_EOA {
2821 $$ = $1;
2822 handle_error("Error: invalid protocol name\n");
2823 yyerrok;
2824 }
2825 ;
2826
2827 protocol_options: {
2828 $$ = new List<AttrProtocolOption>;
2829 }
2830 | protocol_options protocol_option {
2831 $$ = $1;
2832 $$->append($2);
2833 }
2834 ;
2835
2836 protocol_option: KEYW_MANDATORY method {
2837 $$ = new AttrProtocolOption(false, $2);
2838 }
2839 | KEYW_OPTIONAL method {
2840 $$ = new AttrProtocolOption(true, $2);
2841 }
2842 ;
2843
2844 //**** schema class *******************************************************
2845
2846 opt_attr_options: {
2847 $$ = new AttrAttr(ATTR_GENERIC, RPType::newRPType("free_text"));
2848 }
2849 | attr_options {
2850 $$ = new AttrAttr(ATTR_GENERIC, RPType::newRPType("free_text"));
2851 *$$ |= *$1;
2852 delete $1;
2853 }
2854 ;
2855
2856 attr_options: attr_option {
2857 $$ = $1;
2858 }
2859 | attr_options ',' attr_option {
2860 $$ = $1;
2861 *$$ |= *$3;
2862 delete $3;
2863 }
2864 | error ',' attr_option {
2865 $$ = $3;
2866 handle_error("Error: in attr option specification.\n");
2867 }
2868 ;
2869
2870 attr_option: KEYW_SYNTAX '(' typedef_type ')' {
2871 $$ = new AttrAttr(ATTR_GENERIC, $3);
2872 }
2873 | KEYW_SYNTAX '(' KEYW_SPECIAL ',' tkn_word ')' {
2874 int syntax = schema.searchAttrSyntax($5);
2875 if (syntax < 0) {
2876 handle_error("Error: no known syntax rule for %s.\n", $5);
2877 $$ = new AttrAttr;
2878 } else
2879 $$ = new AttrAttr(syntax, NULL);
2880 free($5);
2881 }
2882 | KEYW_SYNTAX '(' KEYW_REGEXP ',' TKN_STRING ')' {
2883 regex_t *re = (regex_t *) malloc(sizeof(regex_t));
2884 int code = regcomp(re, $5, REG_EXTENDED | REG_ICASE);
2885
2886 if (code) {
2887 handle_error("Error: could not compile regexp %s.\n", $5);
2888 free(re);
2889 free($5);
2890 $$ = new AttrAttr;
2891 } else
2892 $$ = new AttrAttr(ATTR_REGEXP, $5, re);
2893 }
2894 | KEYW_SYNTAX '(' KEYW_REGEXP ',' TKN_STRING ',' TKN_INT ')' {
2895 regex_t *re = (regex_t *) malloc(sizeof(regex_t));
2896 int code = regcomp(re, $5, REG_EXTENDED | REG_ICASE);
2897
2898 if (code) {
2899 handle_error("Error: could not compile regexp %s.\n", $5);
2900 free(re);
2901 free($5);
2902 $$ = new AttrAttr;
2903 } else
2904 $$ = new AttrAttr(ATTR_REGEXP, $5, re, $7);
2905 }
2906 | KEYW_OPTIONAL {
2907 $$ = new AttrAttr(AttrAttr::OPTIONAL);
2908 }
2909 | KEYW_MANDATORY {
2910 $$ = new AttrAttr;
2911 }
2912 | KEYW_DELETED {
2913 $$ = new AttrAttr(AttrAttr::DELETED);
2914 }
2915 | KEYW_SINGLEVALUED {
2916 $$ = new AttrAttr;
2917 }
2918 | KEYW_MULTIVALUED {
2919 $$ = new AttrAttr(AttrAttr::MULTIVALUED);
2920 }
2921 | KEYW_LOOKUP {
2922 $$ = new AttrAttr(AttrAttr::LOOKUP);
2923 }
2924 | KEYW_KEY {
2925 $$ = new AttrAttr(AttrAttr::KEY);
2926 }
2927 | KEYW_OBSOLETE {
2928 $$ = new AttrAttr(AttrAttr::OBSOLETE);
2929 }
2930 | KEYW_INTERNAL {
2931 $$ = new AttrAttr(AttrAttr::INTERNAL);
2932 }
2933 ;
2934
2935 attr_attribute: ATTR_ATTR tkn_word opt_attr_options TKN_EOA {
2936 $3->setName($2);
2937 $$ = changeCurrentAttr($3);
2938 }
2939 | ATTR_ATTR tkn_word error TKN_EOA {
2940 $$ = $1;
2941 free($2);
2942 handle_error("Error: in attr option specification.\n");
2943 yyerrok;
2944 }
2945 | ATTR_ATTR error TKN_EOA {
2946 $$ = $1;
2947 handle_error("Error: attr name expected.\n");
2948 yyerrok;
2949 }
2950 ;
2951
2952 //**** rps-auth stuff *****************************************************
2953 // mnt-routes in route, inetnum
2954
2955 mnt_routes_attribute: ATTR_MNT_ROUTES mnt_routes_list TKN_EOA {
2956 $$ = changeCurrentAttr(new AttrMntRoutes($2));
2957 }
2958 ;
2959
2960 mnt_routes_list: mnt_routes_list_item {
2961 $$ = new List<AttrMntRoutes::MntPrfxPair>;
2962 $$->append($1);
2963 }
2964 | mnt_routes_list ',' mnt_routes_list_item {
2965 $$ = $1;
2966 $$->append($3);
2967 }
2968 ;
2969
2970 mnt_routes_list_item: tkn_word {
2971 $$ = new AttrMntRoutes::MntPrfxPair($1, NULL);
2972 }
2973 | tkn_word KEYW_ANY {
2974 $$ = new AttrMntRoutes::MntPrfxPair($1, NULL);
2975 }
2976 | tkn_word '{' opt_filter_prefix_list '}' {
2977 $$ = new AttrMntRoutes::MntPrfxPair($1, (FilterMPPRFXList *) $3);
2978 }
2979 ;
2980
2981 //** mnt-routes in route6, inet6num
2982
2983 mnt_routes6_attribute: ATTR_MNT_ROUTES6 mnt_routes6_list TKN_EOA {
2984 $$ = changeCurrentAttr(new AttrMntRoutes($2));
2985 }
2986 ;
2987 mnt_routes6_list: mnt_routes6_list_item {
2988 $$ = new List<AttrMntRoutes::MntPrfxPair>;
2989 $$->append($1);
2990 }
2991 | mnt_routes6_list ',' mnt_routes6_list_item {
2992 $$ = $1;
2993 $$->append($3);
2994 }
2995 ;
2996
2997 mnt_routes6_list_item: tkn_word {
2998 $$ = new AttrMntRoutes::MntPrfxPair($1, NULL);
2999 }
3000 | tkn_word KEYW_ANY {
3001 $$ = new AttrMntRoutes::MntPrfxPair($1, NULL);
3002 }
3003 | tkn_word '{' opt_v6_filter_prefix_list '}' {
3004 $$ = new AttrMntRoutes::MntPrfxPair($1, (FilterMPPRFXList *) $3);
3005 }
3006 ;
3007
3008 // mnt-routes attribute in aut-num (multiprotocol)
3009
3010 mnt_routes_mp_attribute: ATTR_MNT_ROUTES_MP mnt_routes_mp_list TKN_EOA {
3011 $$ = changeCurrentAttr(new AttrMntRoutes($2));
3012 }
3013 ;
3014 mnt_routes_mp_list: mnt_routes_mp_list_item {
3015 $$ = new List<AttrMntRoutes::MntPrfxPair>;
3016 $$->append($1);
3017 }
3018 | mnt_routes_mp_list ',' mnt_routes_mp_list_item {
3019 $$ = $1;
3020 $$->append($3);
3021 }
3022 ;
3023
3024 mnt_routes_mp_list_item: tkn_word {
3025 $$ = new AttrMntRoutes::MntPrfxPair($1, NULL);
3026 }
3027 | tkn_word KEYW_ANY {
3028 $$ = new AttrMntRoutes::MntPrfxPair($1, NULL);
3029 }
3030 | tkn_word '{' opt_mp_filter_prefix_list '}' {
3031 $$ = new AttrMntRoutes::MntPrfxPair($1, (FilterMPPRFXList *) $3);
3032 }
3033 ;
3034
3035 // **** afi stuff ************************************************************
3036 /* any == ipv4.unicast. ipv4.multicast, ipv6.unicast, ipv6.multicast
3037 any.unicast == ipv4.unicast, ipv6.unicast
3038 any.multicast == ipv4.multicast, ipv6.multicast
3039 ipv4 == ipv4.unicast, ipv4.multicast
3040 ipv6 == ipv6.unicast, ipv6.multicast
3041 */
3042
3043 opt_afi_list: KEYW_AFI afi_list {
3044 $$ = $2;
3045 }
3046 | {
3047 $$ = new ItemList;
3048 $$->append(new ItemAFI("any"));
3049 $$ = $$->expand();
3050 }
3051 ;
3052
3053 afi_list: afi {
3054 $$ = new ItemList;
3055 $$->append($1);
3056 $$ = $$->expand();
3057 }
3058 | afi_list ',' afi {
3059 $$ = $1;
3060 $$->append($3);
3061 $$ = $$->expand();
3062 }
3063 ;
3064
3065 afi: TKN_AFI {
3066 $$ = new ItemAFI($1);
3067 }
3068 | KEYW_ANY {
3069 // workaround for clashing 'any'
3070 $$ = new ItemAFI("any");
3071 }
3072 ;
3073
3074 %%
3075
3076 void enable_yy_parser_debugging() {
3077 #if YYDEBUG != 0
3078 yydebug = 1;
3079 #endif
3080 }
3081
handleArgumentTypeError(char * attr,const char * method,int position,const RPType * correctType,bool isOperator)3082 void handleArgumentTypeError(char *attr, const char *method, int position,
3083 const RPType *correctType,
3084 bool isOperator) {
3085 if (isOperator)
3086 if (position)
3087 handle_error("Error: argument %d to %s.operator%s should be %s.\n",
3088 position, attr, method, ((RPType *) correctType)->name());
3089 else
3090 handle_error("Error: wrong number of arguments to %s.operator%s.\n",
3091 attr, method);
3092 else
3093 if (position)
3094 handle_error("Error: argument %d to %s.%s should be %s.\n",
3095 position, attr, method, ((RPType *) correctType)->name());
3096 else
3097 handle_error("Error: wrong number of arguments to %s.%s.\n",
3098 attr, method);
3099 }
3100
searchMethod(const AttrRPAttr * rp_attr,const char * method,ItemList * args)3101 const AttrMethod *searchMethod(const AttrRPAttr *rp_attr, const char *method, ItemList *args) {
3102 const AttrMethod *mtd = rp_attr->searchMethod(method);
3103 int position;
3104 const RPType *correctType;
3105
3106 if (!mtd) {
3107 handle_error("Error: rp-attribute %s does not have %s defined.\n",
3108 rp_attr->name, method);
3109 return NULL;
3110 }
3111
3112 for (; mtd; mtd = rp_attr->searchNextMethod(mtd))
3113 if (mtd->validateArgs(args, position, correctType))
3114 return mtd;
3115
3116 handleArgumentTypeError(rp_attr->name, method, position, correctType);
3117
3118 return NULL;
3119 }
3120