]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Filters upgraded - a bit. Moved code to filter.c because it is where
authorPavel Machek <pavel@ucw.cz>
Wed, 7 Apr 1999 12:11:08 +0000 (12:11 +0000)
committerPavel Machek <pavel@ucw.cz>
Wed, 7 Apr 1999 12:11:08 +0000 (12:11 +0000)
it belongs. (f-util.c stays there for auxiliary and non-important things.)

Makefile
bird.conf
conf/cf-lex.l
conf/confbase.Y
filter/Makefile
filter/config.Y
filter/f-util.c
filter/filter.c [new file with mode: 0644]
filter/filter.h

index fb1006d35c35c5d768cb64cf09ca9d94d780a78e..a2bba642cec80d62340964e157a9500016bb52d6 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -9,7 +9,7 @@ all depend:
 
 clean:
        $(MAKE) -C $(objdir) clean
-       rm -f `find . -name "*~" -or -name "*.[oa]" -or -name "\#*\#" -or -name TAGS -or -name core -or -name depend -or -name .#*`
+       find . -name "*~" -or -name "*.[oa]" -or -name "\#*\#" -or -name TAGS -or -name core -or -name depend -or -name .#* | xargs rm -f
 
 distclean: clean
        rm -rf $(objdir)
index 1b5b53477f374971b3606bcf8dd84d2b988c3238..3d22f5a7a1a6ec4787a4fb04916c055896a2c3f2 100644 (file)
--- a/bird.conf
+++ b/bird.conf
@@ -4,42 +4,62 @@
 
 # Yet another comment
 
-router id 62.168.0.1
+router id 62.168.0.1;
 
-define xyzzy = 120+10
+define xyzzy = 120+10;
 
-function startup () int i; { printdebug; printdebug; i = 5; print( i ); i = 1234 + i; print( i ); if 0 then { puts( "You must not ever see this" ); quitbird; } print( 2 ); if 1 then puts( "jedna dve honza jde" ); quitbird; }
+function startup () 
+int i; 
+{ 
+       print "Bird filter language: selftesting...";
+       i = 4; 
+       i = 1230 + i; 
+       print "Testing arithmetics: 1234 = " i;
+       if i = 4 then { print "*** FAIL: if 0"; quitbird; } else print "test 1 passed";
+       if 1234 = i then print "test 2 passed"; else { print "*** FAIL: if 1 else"; }
+       if 1 <= 1 then print "test 3 passed"; else { print "*** FAIL: test 3"; }
+       if 1234 < 1234 then { print "*** FAIL: test 4"; quitbird; } else print "test 4 passed";
 
-filter testf int j; { j = const(4321); print( j ); }
+       
+       print "done";
+       quitbird;
+       print "*** FAIL: this is unreachable"; 
+}
 
+filter testf 
+int j; 
+{ 
+       j = const(4321); 
+       print j;
+}
 
 protocol rip MyRIP_test {
-       preference xyzzy
-       debug all
-       port 1520
-       period 5
-       garbagetime 30
-       interface "*"
+       preference xyzzy;
+       debug all;
+       port 1520;
+       period 5;
+       garbagetime 30;
+       interface "*";
 }
 
 protocol device {
-       disabled
-       interface "eth*", "ppp*"
+#      disabled;
+#      interface "eth*", "ppp*";
 }
 
 #protocol kernel {
-#      disabled
+#      disabled;
 #      learn;                  # Learn all routes from the kernel
 #      scan time 10;           # Scan kernel tables every 10 seconds
 #}
 
 protocol static {
-#      disabled
-       route 0.0.0.0/0 via 62.168.0.13
-       route 62.168.0.0/25 reject
-#      route 10.0.0.0/8 reject
-#      route 10.1.1.0:255.255.255.0 via 62.168.0.3
-#      route 10.1.2.0:255.255.255.0 via 62.168.0.3
-#      route 10.1.3.0:255.255.255.0 via 62.168.0.4
-#      route 10.2.0.0/24 via "arc0"
+#      disabled;
+       route 0.0.0.0/0 via 62.168.0.13;
+       route 62.168.0.0/25 reject;
+#      route 10.0.0.0/8 reject;
+#      route 10.1.1.0:255.255.255.0 via 62.168.0.3;
+#      route 10.1.2.0:255.255.255.0 via 62.168.0.3;
+#      route 10.1.3.0:255.255.255.0 via 62.168.0.4;
+#      route 10.2.0.0/24 via "arc0";
 }
index b6b0df70f39ad22b711d5f614ee4bac849e40030..a9e7b54279a171e49f456fcf546d4d33a127083e 100644 (file)
@@ -103,7 +103,7 @@ WHITE [ \t]
   return SYM;
 }
 
-[={}:;,()+*/%-] {
+[={}:;,()+*/%-<>~] {
   return yytext[0];
 }
 
index 880b0df52d9ab6f56759373cb8344a4aecf20e8a..0598d56048fa3500fe06c73adc64e67a005111ce 100644 (file)
@@ -37,9 +37,10 @@ CF_DECLS
 
 %type <i> expr bool pxlen
 
-%left '='
+%nonassoc '=' '<' '>'
 %left '+' '-'
 %left '*' '/' '%'
+%left '!'
 
 CF_KEYWORDS(DEFINE, ON, OFF, YES, NO)
 
index 1e7fb6840790ca34c7cca503326335696990796a..81bd355b8742435de6710f317ac0b563cb820c58 100644 (file)
@@ -1,4 +1,4 @@
-source=f-util.c
+source=f-util.c filter.c
 root-rel=../
 dir-name=filter
 
index de178e7c6e687a0b80ad72a594720590f7ae28bd..47612ee308ad6678bc3d6efa8c21cefaa69d3b59 100644 (file)
@@ -21,11 +21,12 @@ CF_DECLS
 CF_KEYWORDS(FUNCTION, PRINTDEBUG, PRINT, CONST, PUTS, 
        ACCEPT, REJECT, ERROR, QUITBIRD,
        INT, BOOL, IP, PREFIX, PAIR, SET, STRING,
-       IF, THEN,
+       IF, THEN, ELSE,
+       TRUE, FALSE,
        FILTER
        )
 
-%type <x> term block cmds cmd function_body
+%type <x> term block cmds cmd function_body ifthen constant print_one print_list
 %type <f> filter filter_body
 %type <i> type break_command
 
@@ -127,34 +128,37 @@ block:
    }
  ;
 
+constant:
+   CONST '(' expr ')' { $$ = f_new_inst(); $$->code = 'c'; $$->arg1 = T_INT; $$->arg2 = $3; }
+ | NUM    { $$ = f_new_inst(); $$->code = 'c'; $$->arg1 = T_INT;  $$->arg2 = $1; }
+ | TRUE   { $$ = f_new_inst(); $$->code = 'c'; $$->arg1 = T_BOOL; $$->arg2 = 1;  }
+ | FALSE  { $$ = f_new_inst(); $$->code = 'c'; $$->arg1 = T_BOOL; $$->arg2 = 0;  }
+ | TEXT   { $$ = f_new_inst(); $$->code = 'c'; $$->arg1 = T_STRING; $$->arg2 = $1; } 
+ ;
+
 term:
-   term '+' term {
-     $$ = f_new_inst();
-     $$->code = '+';
-     $$->arg1 = $1;
-     $$->arg2 = $3;
-   }
+   term '+' term     { $$ = f_new_inst(); $$->code = '+';  $$->arg1 = $1; $$->arg2 = $3; }
+
+ | term '=' term     { $$ = f_new_inst(); $$->code = '=='; $$->arg1 = $1; $$->arg2 = $3; }
+ | term '!' '=' term { $$ = f_new_inst(); $$->code = '!='; $$->arg1 = $1; $$->arg2 = $4; }
+ | term '<' term     { $$ = f_new_inst(); $$->code = '<';  $$->arg1 = $1; $$->arg2 = $3; }
+ | term '<' '=' term { $$ = f_new_inst(); $$->code = '<='; $$->arg1 = $1; $$->arg2 = $4; }
+ | term '>' term     { $$ = f_new_inst(); $$->code = '<';  $$->arg1 = $3; $$->arg2 = $1; }
+ | term '>' '=' term { $$ = f_new_inst(); $$->code = '<='; $$->arg1 = $4; $$->arg2 = $1; }
+
  | SYM {
      $$ = f_new_inst();
      switch ($1->class) {
        case SYM_VARIABLE | T_INT:
         $$->code = 'i';
-         $$->arg1 = &($1->aux);
+         $$->arg1 = T_INT;
+        $$->arg2 = &($1->aux);
         break;
        default:
         cf_error("Can not use this class of symbol as variable" );
      }
    }
- | CONST '(' expr ')' {
-     $$ = f_new_inst();
-     $$->code = 'c';
-     $$->arg1 = $3;
-   }
- | NUM {
-     $$ = f_new_inst();
-     $$->code = 'c';
-     $$->arg1 = $1
-   }
+ | constant { $$ = $1; }
  ;
 
 break_command:
@@ -162,46 +166,52 @@ break_command:
  | ACCEPT { $$ = F_ACCEPT }
  | REJECT { $$ = F_REJECT }
  | ERROR { $$ = F_ERROR }
+ | PRINT { $$ = F_NOP }
  ;
 
-cmd:
+ifthen:
    IF term THEN block {
      $$ = f_new_inst();
      $$->code = '?';
      $$->arg1 = $2;
      $$->arg2 = $4;
    }
+ ;
+
+print_one:
+   term { $$ = f_new_inst(); $$->code = 'p'; $$->arg1 = $1; $$->arg2 = NULL; }
+ ;
+
+print_list: /* EMPTY */ { $$ = NULL; }
+ | print_one print_list {
+     if ($1) {
+       $1->next = $2;
+       $$ = $1;
+     } else $$ = $2;
+   }
+ ;
+
+cmd:
+   ifthen { 
+     $$ = $1;
+   }
+       /* FIXME: this leads to shift/reduce conflict. */
+ | ifthen ELSE block {
+     $$ = f_new_inst();
+     $$->code = '?';
+     $$->arg1 = $1;
+     $$->arg2 = $3;
+   }
  | SYM '=' term ';' {
      $$ = f_new_inst();
      printf( "Ook, we'll set value\n" );
      if (($1->class & ~T_MASK) != SYM_VARIABLE)
        cf_error( "You may only set variables, and this is %x.\n", $1->class );
-     $$->code = '=';
+     $$->code = 's';
      $$->arg1 = $1;
      $$->arg2 = $3;
    }
- | PRINT '(' term ')' ';' {
-     $$ = f_new_inst();
-     printf( "Ook, we'll print something\n" );
-     $$->code = 'p';
-     $$->arg1 = $3;
-     $$->arg2 = NULL;
-   }
- | PUTS '(' TEXT ')' ';' {
-     $$ = f_new_inst();
-     $$->code = 'd';
-     $$->arg1 = $3;
-   }
- | PRINTDEBUG ';' {
-     $$ = f_new_inst();
-     $$->code = 'D';
-     $$->arg1 = $$->arg2 = NULL;
-   }
- | break_command ';' {
-     $$ = f_new_inst();
-     $$->code = '!';
-     (int) $$->arg1 = $1;
-   }
+ | break_command print_list ';' { $$ = f_new_inst(); $$->code = 'p,'; $$->arg1 = $2; $$->arg2 = $1; }
  ;
 
 CF_END
index 6605091e8dd87ace5eb83adb1afce62df153a291..40805f8a1447878ed4824373a522e1f44692ed8c 100644 (file)
 #include "conf/conf.h"
 #include "filter/filter.h"
 
-struct f_inst *startup_func = NULL;
-
-#define runtime(x) do { \
-    log( L_ERR, x ); \
-    res.type = T_RETURN; \
-    res.val.i = F_ERROR; \
-    return res; \
-  } while(0)
-
-#define ARG(x,y) \
-       x = interpret(what->y); \
-       if (x.type == T_RETURN) \
-               return x;
-
-#define ONEARG ARG(v1, arg1)
-#define TWOARGS ARG(v1, arg1) \
-               ARG(v2, arg2)
-
-static struct f_val
-interpret(struct f_inst *what)
-{
-  struct symbol *sym;
-  struct f_val v1, v2, res;
-
-  res.type = T_VOID;
-  if (!what)
-    return res;
-
-  switch(what->code) {
-  case ',':
-    TWOARGS;
-    break;
-  case '+':
-    TWOARGS;
-    if (v1.type != v2.type)
-      runtime( "Can not operate with values of incompatible types" );
-
-    switch (res.type = v1.type) {
-    case T_VOID: runtime( "Can not operate with values of type void" );
-    case T_INT: res.val.i = v1.val.i + v2.val.i; break;
-    default: runtime( "Usage of unknown type" );
-    }
-    break;
-  case '=':
-    ARG(v2, arg2);
-    sym = what->arg1;
-    switch (res.type = v2.type) {
-    case T_VOID: runtime( "Can not assign void values" );
-    case T_INT: 
-      if (sym->class != (SYM_VARIABLE | T_INT))
-       runtime( "Variable of bad type" );
-      sym->aux = v2.val.i; 
-      break;
-    }
-    break;
-  case 'c':
-    res.type = T_INT;
-    res.val.i = (int) what->arg1;
-    break;
-  case 'i':
-    res.type = T_INT;
-    res.val.i = * ((int *) what->arg1);
-    break;
-  case 'p':
-    ONEARG;
-    printf( "Printing: " );
-    switch (v1.type) {
-    case T_VOID: printf( "(void)" ); break;
-    case T_INT: printf( "%d", v1.val.i ); break;
-    default: runtime( "Print of variable of unknown type" );
-    }
-    printf( "\n" );
-    break;
-  case '?':
-    ONEARG;
-    if (v1.type != T_INT)
-      runtime( "If requires integer expression" );
-    if (v1.val.i) {
-      ARG(res,arg2);
-    }
-    break;
-  case 'D':
-    printf( "DEBUGGING PRINT\n" );
-    break;
-  case '0':
-    printf( "No operation\n" );
-    break;
-  case 'd':
-    printf( "Puts: %s\n", (char *) what->arg1 );
-    break;
-  case '!':
-    switch ((int) what->arg1) {
-    case F_QUITBIRD:
-      die( "Filter asked me to die" );
-    case F_ACCEPT:
-      /* Should take care about turning ACCEPT into MODIFY */
-    case F_ERROR:
-    case F_REJECT:
-      res.type = T_RETURN;
-      res.val.i = (int) what->arg1;
-      break;
-    default:
-      bug( "unknown return type: can not happen");
-    }
-    break;
-  default:
-    bug( "Unknown instruction %d (%c)", what->code, what->code & 0xff);
-  }
-  if (what->next)
-    return interpret(what->next);
-  return res;
-}
-
 struct f_inst *
 f_new_inst(void)
 {
@@ -145,21 +32,6 @@ f_new_inst(void)
   return ret;
 }
 
-int
-f_run(struct filter *filter, struct rte **rte, struct ea_list **tmp_attrs, struct linpool *tmp_pool)
-{
-  struct f_inst *inst;
-  struct f_val res;
-  debug( "Running filter `%s'...", filter->name );
-
-  inst = filter->root;
-  res = interpret(inst);
-  if (res.type != T_RETURN)
-    return F_ERROR;
-  debug( "done (%d)\n", res.val.i );
-  return res.val.i;
-}
-
 char *
 filter_name(struct filter *filter)
 {
@@ -170,12 +42,3 @@ filter_name(struct filter *filter)
   else
     return filter->name;
 }
-
-void
-filters_postconfig(void)
-{
-  printf( "Launching startup function..." );
-  if (startup_func)
-    interpret(startup_func);
-  printf( "done\n" );
-} 
diff --git a/filter/filter.c b/filter/filter.c
new file mode 100644 (file)
index 0000000..eb40d3c
--- /dev/null
@@ -0,0 +1,212 @@
+/*
+ *     Filters: utility functions
+ *
+ *     Copyright 1998 Pavel Machek <pavel@ucw.cz>
+ *
+ *     Can be freely distributed and used under the terms of the GNU GPL.
+ */
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/signal.h>
+#include <setjmp.h>
+
+#include "nest/bird.h"
+#include "lib/lists.h"
+#include "lib/resource.h"
+#include "lib/socket.h"
+#include "nest/route.h"
+#include "nest/protocol.h"
+#include "nest/iface.h"
+#include "conf/conf.h"
+#include "filter/filter.h"
+
+struct f_inst *startup_func = NULL;
+
+#define runtime(x) do { \
+    log( L_ERR x ); \
+    res.type = T_RETURN; \
+    res.val.i = F_ERROR; \
+    return res; \
+  } while(0)
+
+#define ARG(x,y) \
+       x = interpret(what->y); \
+       if (x.type == T_RETURN) \
+               return x;
+
+#define ONEARG ARG(v1, arg1)
+#define TWOARGS ARG(v1, arg1) \
+               ARG(v2, arg2)
+#define TWOARGS_C TWOARGS \
+                  if (v1.type != v2.type) \
+                   runtime( "Can not operate with values of incompatible types" );
+
+static struct f_val
+interpret(struct f_inst *what)
+{
+  struct symbol *sym;
+  struct f_val v1, v2, res;
+
+  res.type = T_VOID;
+  if (!what)
+    return res;
+
+  switch(what->code) {
+  case ',':
+    TWOARGS;
+    break;
+
+/* Binary operators */
+  case '+':
+    TWOARGS_C;
+    switch (res.type = v1.type) {
+    case T_VOID: runtime( "Can not operate with values of type void" );
+    case T_INT: res.val.i = v1.val.i + v2.val.i; break;
+    default: runtime( "Usage of unknown type" );
+    }
+    break;
+  case '/':
+    TWOARGS_C;
+    switch (res.type = v1.type) {
+    case T_VOID: runtime( "Can not operate with values of type void" );
+    case T_INT: res.val.i = v1.val.i / v2.val.i; break;
+    case T_IP: if (v2.type != T_INT)
+                 runtime( "Operator / is <ip>/<int>" );
+               break;
+    default: runtime( "Usage of unknown type" );
+    }
+    break;
+
+/* Relational operators */
+  case '!=':
+  case '==':
+    TWOARGS_C;
+    res.type = T_BOOL;
+    switch (v1.type) {
+    case T_VOID: runtime( "Can not operate with values of type void" );
+    case T_INT: res.val.i = (v1.val.i == v2.val.i); break;
+    default: runtime( "Usage of unknown type" );
+    }
+    if (what->code == '!=')
+      res.val.i = !(res.val.i);
+    break;
+  case '<':
+    TWOARGS_C;
+    res.type = T_BOOL;
+    switch (v1.type) {
+    case T_VOID: runtime( "Can not operate with values of type void" );
+    case T_INT: res.val.i = (v1.val.i < v2.val.i); break;
+    default: runtime( "Usage of unknown type" );
+    }
+    break;
+  case '<=':
+    TWOARGS_C;
+    res.type = T_BOOL;
+    switch (v1.type) {
+    case T_VOID: runtime( "Can not operate with values of type void" );
+    case T_INT: res.val.i = (v1.val.i <= v2.val.i); break;
+    default: runtime( "Usage of unknown type" );
+    }
+    break;
+
+/* Set */
+  case 's':
+    ARG(v2, arg2);
+    sym = what->arg1;
+    switch (res.type = v2.type) {
+    case T_VOID: runtime( "Can not assign void values" );
+    case T_INT: 
+      if (sym->class != (SYM_VARIABLE | T_INT))
+       runtime( "Variable of bad type" );
+      sym->aux = v2.val.i; 
+      break;
+    }
+    break;
+
+  case 'c':
+    res.type = (int) what->arg1;
+    res.val.i = (int) what->arg2;
+    break;
+  case 'i':
+    res.type = (int) what->arg1;
+    res.val.i = * ((int *) what->arg2);
+    break;
+  case 'p':
+    ONEARG;
+    switch (v1.type) {
+    case T_VOID: printf( "(void)" ); break;
+    case T_INT: printf( "%d ", v1.val.i ); break;
+    case T_STRING: printf( "%s", v1.val.i ); break;
+    default: runtime( "Print of variable of unknown type" );
+    }
+    break;
+  case '?':    /* ? has really strange error value, so we can implement if ... else nicely :-) */
+    ONEARG;
+    if (v1.type != T_BOOL)
+      runtime( "If requires bool expression" );
+    if (v1.val.i) {
+      ARG(res,arg2);
+      res.val.i = 0;
+    } else res.val.i = 1;
+    res.type = T_BOOL;
+    break;
+  case '0':
+    printf( "No operation\n" );
+    break;
+  case 'p,':
+    ONEARG;
+    printf( "\n" );
+
+    switch ((int) what->arg2) {
+    case F_QUITBIRD:
+      die( "Filter asked me to die" );
+    case F_ACCEPT:
+      /* Should take care about turning ACCEPT into MODIFY */
+    case F_ERROR:
+    case F_REJECT:
+      res.type = T_RETURN;
+      res.val.i = (int) what->arg1;
+      break;
+    case F_NOP:
+      break;
+    default:
+      bug( "unknown return type: can not happen");
+    }
+    break;
+  default:
+    bug( "Unknown instruction %d (%c)", what->code, what->code & 0xff);
+  }
+  if (what->next)
+    return interpret(what->next);
+  return res;
+}
+
+int
+f_run(struct filter *filter, struct rte **rte, struct ea_list **tmp_attrs, struct linpool *tmp_pool)
+{
+  struct f_inst *inst;
+  struct f_val res;
+  debug( "Running filter `%s'...", filter->name );
+
+  inst = filter->root;
+  res = interpret(inst);
+  if (res.type != T_RETURN)
+    return F_ERROR;
+  debug( "done (%d)\n", res.val.i );
+  return res.val.i;
+}
+
+
+void
+filters_postconfig(void)
+{
+  struct f_val res;
+  printf( "Launching startup function...\n" );
+  if (startup_func)
+    res = interpret(startup_func);
+  if (res.type = F_ERROR)
+    die( "Startup function resulted in error." );
+  printf( "done\n" );
+} 
index d8ee7efa7d304e979e8e17e3bdaec4f2d34677fd..129434254a06454233dcd65561efd36a536a84ef 100644 (file)
@@ -10,6 +10,7 @@
 #define _BIRD_FILT_H_
 
 #include "lib/resource.h"
+#include "lib/ip.h"
 
 struct f_inst {                /* Instruction */
   struct f_inst *next; /* Structure is 16 bytes, anyway */
@@ -17,10 +18,17 @@ struct f_inst {             /* Instruction */
   void *arg1, *arg2;
 };
 
+struct prefix {
+  ip_addr ip;
+  int len;
+};
+
 struct f_val {
   int type;
   union {
     int i;
+    struct prefix *px;
+    char *s;
   } val;
 };
 
@@ -35,6 +43,8 @@ struct f_inst *f_new_inst(void);
 int f_run(struct filter *filter, struct rte **rte, struct ea_list **tmp_attrs, struct linpool *tmp_pool);
 char *filter_name(struct filter *filter);
 
+
+#define F_NOP 0
 #define F_ACCEPT 1     /* Need to preserve ordering: accepts < rejects! */
 #define F_MODIFY 2     /* FIXME: Introduce modification flags instead? */
 #define F_REJECT 3