## modules/rpsl/filter.y

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

## FUNCTIONS

This source file includes following functions.

1. yyparse
2. filtererror
3. yyerror
4. syntax_error
5. yywrap
6. min
7. yy_input
8. main

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

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