## modules/rpsl/components.y

/* [<][>][^][v][top][bottom][index][help] */

## DEFINITIONS

This source file includes following functions.

1. yyparse
2. componentserror
3. yyerror
4. syntax_error
5. yywrap
6. yy_input
7. main

       1 %{
       2 /*
       3   filename: components.y
       4
       5   description:
       6     Defines the grammar for an RPSL component attribute.  It was mostly
       7     stolen from the IRRToolSet, simplified by removing ability to parse
       8     things defined by a dictionary (we use XML for extensibility rather
       9     than a dictionary).
      10
      11   notes:
      12     Defines tokens for the associated lexer, components.l.
      13 */
      14 %}
      15
      16 %union {
      17     char *sval;
      18 }
      19
      20 %token OP_OR OP_AND OP_NOT OP_MS OP_EQUAL OP_APPEND OP_COMPARE
      21 %token KEYW_ANY KEYW_PEERAS
      22 %token ASPATH_POSTFIX
      23 %token TKN_FLTRNAME TKN_ASNO TKN_RSNAME TKN_ASNAME TKN_PRFXV4 TKN_PRFXV4RNG
      24 %token KEYW_ATOMIC
      25 %token KEYW_PROTOCOL TKN_PROTOCOL
      26 %token KEYW_IGP_COST KEYW_SELF KEYW_PREPEND KEYW_APPEND
      27 %token KEYW_DELETE KEYW_CONTAINS
      28 %token KEYW_INTERNET KEYW_NO_EXPORT KEYW_NO_ADVERTISE
      29 %token TKN_PREF TKN_MED TKN_DPA TKN_ASPATH TKN_COMMUNITY
      30 %token TKN_NEXT_HOP TKN_COST TKN_COMM_NO TKN_IPV4
      31
      32 %token <sval> TKN_INT
      33
      34 %{
      35 #include <stdio.h>
      36 #include <stdarg.h>
      37 #include <stdlib.h>
      38
      39 int yyerror(const char *s);
      40
      41 /* defines for unit testing */
      42 #ifdef UNIT_TEST
      43 int main();
      44 #endif /* UNIT_TEST */
      45 %}
      46
      47 %%
         /* [<][>][^][v][top][bottom][index][help] */
      48
      49 components: opt_atomic components_list
      50 ;
      51
      52 opt_atomic:
      53 | KEYW_ATOMIC
      54 ;
      55
      56 components_list:
      57 | filter
      58 | components_list KEYW_PROTOCOL TKN_PROTOCOL filter
      59 ;
      60
      61 filter: filter OP_OR filter_term
      62 | filter filter_term %prec OP_OR
      63 | filter_term
      64 ;
      65
      66 filter_term : filter_term OP_AND filter_factor
      67 | filter_factor
      68 ;
      69
      70 filter_factor :  OP_NOT filter_factor
      71 | '(' filter ')'
      72 | filter_operand
      73 ;
      74
      75 filter_operand: KEYW_ANY
      76 | '<' filter_aspath '>'
      77 | rp_attribute
      78 | TKN_FLTRNAME
      79 | filter_prefix
      80 ;
      81
      82 filter_prefix: filter_prefix_operand OP_MS
      83 |  filter_prefix_operand
      84 ;
      85
      86 filter_prefix_operand: TKN_ASNO
      87 | KEYW_PEERAS
      88 | TKN_ASNAME
      89 | TKN_RSNAME
      90 | '{' opt_filter_prefix_list '}'
      91 ;
      92
      93 opt_filter_prefix_list:
      94 | filter_prefix_list
      95 ;
      96
      97 filter_prefix_list: filter_prefix_list_prefix
      98 | filter_prefix_list ',' filter_prefix_list_prefix
      99 ;
     100
     101 filter_prefix_list_prefix: TKN_PRFXV4
     102 | TKN_PRFXV4RNG
     103 ;
     104
     105 filter_aspath: filter_aspath '|' filter_aspath_term
     106 | filter_aspath_term
     107 ;
     108
     109 filter_aspath_term: filter_aspath_term filter_aspath_closure
     110 | filter_aspath_closure
     111 ;
     112
     113 filter_aspath_closure: filter_aspath_closure '*'
     114 | filter_aspath_closure '?'
     115 | filter_aspath_closure '+'
     116 | filter_aspath_closure ASPATH_POSTFIX
     117 | filter_aspath_factor
     118 ;
     119
     120 filter_aspath_factor: '^'
     121 | '$'
     122 | '(' filter_aspath ')'
     123 | filter_aspath_no
     124 ;
     125
     126 filter_aspath_no: TKN_ASNO
     127 | KEYW_PEERAS
     128 | TKN_ASNAME
     129 | '.'
     130 | '[' filter_aspath_range ']'
     131 | '[' '^' filter_aspath_range ']'
     132 ;
     133
     134 filter_aspath_range:
     135 | filter_aspath_range TKN_ASNO
     136 | filter_aspath_range KEYW_PEERAS
     137 | filter_aspath_range '.'
     138 | filter_aspath_range TKN_ASNO '-' TKN_ASNO
     139 | filter_aspath_range TKN_ASNAME
     140 ;
     141
     142 rp_attribute: pref
     143 | med
     144 | dpa
     145 | aspath
     146 | community
     147 | next_hop
     148 | cost
     149 ;
     150
     151 pref: TKN_PREF OP_EQUAL TKN_INT {
     152       long int val;
     153       char *s, *p;
     154       p = $3;
     155       val = strtol(p, &s, 10);
     156       if ((val < 0) || (val > 65535)) {
     157           syntax_error("pref value \"%s\" is not between 0 and 65535", p);
     158       }
     159 }
     160 ;
     161
     162 med: TKN_MED OP_EQUAL TKN_INT {
     163       long int val;
     164       char *s, *p;
     165       p = $3;
     166       val = strtol(p, &s, 10);
     167       if ((val < 0) || (val > 65535)) {
     168           syntax_error("med value \"%s\" is not between 0 and 65535", p);
     169       }
     170 }
     171 | TKN_MED OP_EQUAL KEYW_IGP_COST
     172 ;
     173
     174 dpa: TKN_DPA OP_EQUAL TKN_INT {
     175       long int val;
     176       char *s, *p;
     177       p = $3;
     178       val = strtol(p, &s, 10);
     179       if ((val < 0) || (val > 65535)) {
     180           syntax_error("dpa value \"%s\" is not between 0 and 65535", p);
     181       }
     182 }
     183 ;
     184
     185 aspath: TKN_ASPATH '.' KEYW_PREPEND '(' asno_list ')'
     186 ;
     187
     188 asno_list: TKN_ASNO
     189 | asno_list ',' TKN_ASNO
     190 ;
     191
     192 community: TKN_COMMUNITY OP_EQUAL community_list
     193 | TKN_COMMUNITY OP_APPEND community_list
     194 | TKN_COMMUNITY '.' KEYW_APPEND '(' community_elm_list ')'
     195 | TKN_COMMUNITY '.' KEYW_DELETE '(' community_elm_list ')'
     196 | TKN_COMMUNITY '.' KEYW_CONTAINS '(' community_elm_list ')'
     197 | TKN_COMMUNITY '(' community_elm_list ')'
     198 | TKN_COMMUNITY OP_COMPARE community_list
     199 ;
     200
     201 community_list: '{' community_elm_list '}'
     202 ;
     203
     204 community_elm_list: community_elm
     205 | community_elm_list ',' community_elm
     206 ;
     207
     208 community_elm: KEYW_INTERNET
     209 | KEYW_NO_EXPORT
     210 | KEYW_NO_ADVERTISE
     211 | TKN_INT {
     212       unsigned long int val;
     213       char *s, *p;
     214       p = $1;
     215       val = strtoul(p, &s, 10);
     216       if ((val < 1) || (val > 4294967295UL) || (*s != '\0')) {
     217           syntax_error("community element \"%s\" is not between 1 and 4294967295",
     218                        p);
     219       }
     220 }
     221 | TKN_COMM_NO
     222 ;
     223
     224 next_hop: TKN_NEXT_HOP OP_EQUAL TKN_IPV4
     225 | TKN_NEXT_HOP OP_EQUAL KEYW_SELF
     226 ;
     227
     228 cost: TKN_COST OP_EQUAL TKN_INT {
     229       long int val;
     230       char *s, *p;
     231       p = $3;
     232       val = strtol(p, &s, 10);
     233       if ((val < 0) || (val > 65535)) {
     234           syntax_error("cost value \"%s\" is not between 0 and 65535", p);
     235       }
     236 }
     237 ;
     238
     239 %%
     240
     241 /* define a unit test that simply returns "yes" or "no" for filter input */
     242 #ifndef UNIT_TEST
     243
     244 #undef componentserror
     245 #undef yyerror
     246
     247 int
     248 componentserror (const char *s)
         /* [<][>][^][v][top][bottom][index][help] */
     249 {
     250     yyerror(s);
     251     return 0;
     252 }
     253 #else /* UNIT_TEST */
     254
     255 int parse_error_count;
     256
     257 /* parse error */
     258 void
     259 yyerror(const char *s)
         /* [<][>][^][v][top][bottom][index][help] */
     260 {
     261     fputs(s, stderr);
     262     putc('\n', stderr);
     263     parse_error_count++;
     264 }
     265
     266 /* syntax error */
     267 void
     268 syntax_error(const char *fmt, ...)
         /* [<][>][^][v][top][bottom][index][help] */
     269 {
     270     va_list args;
     271     char buf[1024];
     272
     273     va_start(args, fmt);
     274     vsnprintf(buf, sizeof(buf), fmt, args);
     275     va_end(args);
     276     yyerror(buf);
     277 }
     278
     279 int
     280 yywrap()
         /* [<][>][^][v][top][bottom][index][help] */
     281 {
     282     return 1;
     283 }
     284
     285 /* taken from _lex & yacc_ p.157, by Levine, Mason, & Brown (corrected) */
     286 char *myinputptr;
     287 char *myinputlim;
     288
     289 #undef min
     290 #define min(a, b)  (((a) < (b)) ? (a) : (b))
     291
     292 void
     293 yy_input(char *buf, int *result, int max_size)
         /* [<][>][^][v][top][bottom][index][help] */
     294 {
     295     int n = min(max_size, myinputlim - myinputptr);
     296
     297     if (n > 0) {
     298         memcpy(buf, myinputptr, n);
     299         myinputptr += n;
     300     }
     301     *result = n;
     302 }
     303
     304 /* program entry point */
     305 int
     306 main()
         /* [<][>][^][v][top][bottom][index][help] */
     307 {
     308     char buf[4096];
     309
     310     setbuf(stdout, NULL);
     311     for (;;) {
     312         printf("filter> ");
     313         if (gets(buf) == NULL) {
     314             printf("\n");
     315             return(0);
     316         }
     317         parse_error_count = 0;
     318         myinputptr = buf;
     319         myinputlim = buf + strlen(buf);
     320         filterparse();
     321         printf("%d parse errors\n", parse_error_count);
     322     }
     323 }
     324 #endif /* UNIT_TEST */

/* [<][>][^][v][top][bottom][index][help] */