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