Diff for /embedaddon/bird/filter/filter.c between versions 1.1.1.1 and 1.1.1.2

version 1.1.1.1, 2017/08/22 12:33:54 version 1.1.1.2, 2021/03/17 19:50:23
Line 46 Line 46
 #include "conf/conf.h"  #include "conf/conf.h"
 #include "filter/filter.h"  #include "filter/filter.h"
   
 #define P(a,b) ((a<<8) | b)  
   
 #define CMP_ERROR 999  #define CMP_ERROR 999
   
 static struct adata *  static struct adata *
Line 84  pm_format(struct f_path_mask *p, buffer *buf) Line 82  pm_format(struct f_path_mask *p, buffer *buf)
       break;        break;
   
     case PM_ASN_EXPR:      case PM_ASN_EXPR:
      buffer_print(buf, "%u ", f_eval_asn((struct f_inst *) p->val));      ASSERT(0);
      break; 
     }      }
   
     p = p->next;      p = p->next;
Line 590  f_rta_cow(void) Line 587  f_rta_cow(void)
 static struct tbf rl_runtime_err = TBF_DEFAULT_LOG_LIMITS;  static struct tbf rl_runtime_err = TBF_DEFAULT_LOG_LIMITS;
   
 #define runtime(x) do { \  #define runtime(x) do { \
    log_rl(&rl_runtime_err, L_ERR "filters, line %d: %s", what->lineno, x); \    if (!(f_flags & FF_SILENT)) \
       log_rl(&rl_runtime_err, L_ERR "filters, line %d: %s", what->lineno, x); \
     res.type = T_RETURN; \      res.type = T_RETURN; \
     res.val.i = F_ERROR; \      res.val.i = F_ERROR; \
     return res; \      return res; \
Line 634  static struct f_val Line 632  static struct f_val
 interpret(struct f_inst *what)  interpret(struct f_inst *what)
 {  {
   struct symbol *sym;    struct symbol *sym;
  struct f_val v1, v2, res, *vp;  struct f_val v1, v2, res = { .type = T_VOID }, *vp;
   unsigned u1, u2;    unsigned u1, u2;
   int i;    int i;
   u32 as;    u32 as;
   
     for ( ; what; what = what->next) {
   res.type = T_VOID;    res.type = T_VOID;
  if (!what)  switch(what->fi_code) {
    return res; 
 
  switch(what->code) { 
  case ',': 
    TWOARGS; 
    break; 
 
 /* Binary operators */  /* Binary operators */
  case '+':  case FI_ADD:
     TWOARGS_C;      TWOARGS_C;
     switch (res.type = v1.type) {      switch (res.type = v1.type) {
     case T_VOID: runtime( "Can't operate with values of type void" );      case T_VOID: runtime( "Can't operate with values of type void" );
Line 657  interpret(struct f_inst *what) Line 649  interpret(struct f_inst *what)
     default: runtime( "Usage of unknown type" );      default: runtime( "Usage of unknown type" );
     }      }
     break;      break;
  case '-':  case FI_SUBTRACT:
     TWOARGS_C;      TWOARGS_C;
     switch (res.type = v1.type) {      switch (res.type = v1.type) {
     case T_VOID: runtime( "Can't operate with values of type void" );      case T_VOID: runtime( "Can't operate with values of type void" );
Line 665  interpret(struct f_inst *what) Line 657  interpret(struct f_inst *what)
     default: runtime( "Usage of unknown type" );      default: runtime( "Usage of unknown type" );
     }      }
     break;      break;
  case '*':  case FI_MULTIPLY:
     TWOARGS_C;      TWOARGS_C;
     switch (res.type = v1.type) {      switch (res.type = v1.type) {
     case T_VOID: runtime( "Can't operate with values of type void" );      case T_VOID: runtime( "Can't operate with values of type void" );
Line 673  interpret(struct f_inst *what) Line 665  interpret(struct f_inst *what)
     default: runtime( "Usage of unknown type" );      default: runtime( "Usage of unknown type" );
     }      }
     break;      break;
  case '/':  case FI_DIVIDE:
     TWOARGS_C;      TWOARGS_C;
     switch (res.type = v1.type) {      switch (res.type = v1.type) {
     case T_VOID: runtime( "Can't operate with values of type void" );      case T_VOID: runtime( "Can't operate with values of type void" );
Line 683  interpret(struct f_inst *what) Line 675  interpret(struct f_inst *what)
     }      }
     break;      break;
   
  case '&':  case FI_AND:
  case '|':  case FI_OR:
     ARG(v1, a1.p);      ARG(v1, a1.p);
     if (v1.type != T_BOOL)      if (v1.type != T_BOOL)
       runtime( "Can't do boolean operation on non-booleans" );        runtime( "Can't do boolean operation on non-booleans" );
    if (v1.val.i == (what->code == '|')) {    if (v1.val.i == (what->fi_code == FI_OR)) {
       res.type = T_BOOL;        res.type = T_BOOL;
       res.val.i = v1.val.i;        res.val.i = v1.val.i;
       break;        break;
Line 701  interpret(struct f_inst *what) Line 693  interpret(struct f_inst *what)
     res.val.i = v2.val.i;      res.val.i = v2.val.i;
     break;      break;
   
  case P('m','p'):  case FI_PAIR_CONSTRUCT:
     TWOARGS;      TWOARGS;
     if ((v1.type != T_INT) || (v2.type != T_INT))      if ((v1.type != T_INT) || (v2.type != T_INT))
       runtime( "Can't operate with value of non-integer type in pair constructor" );        runtime( "Can't operate with value of non-integer type in pair constructor" );
Line 713  interpret(struct f_inst *what) Line 705  interpret(struct f_inst *what)
     res.type = T_PAIR;      res.type = T_PAIR;
     break;      break;
   
  case P('m','c'):  case FI_EC_CONSTRUCT:
     {      {
       TWOARGS;        TWOARGS;
   
Line 761  interpret(struct f_inst *what) Line 753  interpret(struct f_inst *what)
       break;        break;
     }      }
   
  case P('m','l'):  case FI_LC_CONSTRUCT:
     {      {
       TWOARGS;        TWOARGS;
   
Line 779  interpret(struct f_inst *what) Line 771  interpret(struct f_inst *what)
       break;        break;
     }      }
   
     case FI_PATHMASK_CONSTRUCT:
       {
         struct f_path_mask *tt = what->a1.p, *vbegin, **vv = &vbegin;
   
         while (tt) {
           *vv = lp_alloc(f_pool, sizeof(struct f_path_mask));
           if (tt->kind == PM_ASN_EXPR) {
             struct f_val res = interpret((struct f_inst *) tt->val);
             (*vv)->kind = PM_ASN;
             if (res.type != T_INT) {
               runtime( "Error resolving path mask template: value not an integer" );
               return (struct f_val) { .type = T_VOID };
             }
   
             (*vv)->val = res.val.i;
           } else {
             **vv = *tt;
           }
           tt = tt->next;
           vv = &((*vv)->next);
         }
   
         res = (struct f_val) { .type = T_PATH_MASK, .val.path_mask = vbegin };
         break;
       }
   
 /* Relational operators */  /* Relational operators */
   
 #define COMPARE(x) \  #define COMPARE(x) \
Line 797  interpret(struct f_inst *what) Line 815  interpret(struct f_inst *what)
     res.val.i = (x); \      res.val.i = (x); \
     break;      break;
   
  case P('!','='): SAME(!i);  case FI_NEQ: SAME(!i);
  case P('=','='): SAME(i);  case FI_EQ: SAME(i);
  case '<': COMPARE(i==-1);  case FI_LT: COMPARE(i==-1);
  case P('<','='): COMPARE(i!=1);  case FI_LTE: COMPARE(i!=1);
   
  case '!':  case FI_NOT:
     ONEARG;      ONEARG;
     if (v1.type != T_BOOL)      if (v1.type != T_BOOL)
       runtime( "Not applied to non-boolean" );        runtime( "Not applied to non-boolean" );
Line 810  interpret(struct f_inst *what) Line 828  interpret(struct f_inst *what)
     res.val.i = !res.val.i;      res.val.i = !res.val.i;
     break;      break;
   
  case '~':  case FI_MATCH:
     TWOARGS;      TWOARGS;
     res.type = T_BOOL;      res.type = T_BOOL;
     res.val.i = val_in_range(v1, v2);      res.val.i = val_in_range(v1, v2);
Line 819  interpret(struct f_inst *what) Line 837  interpret(struct f_inst *what)
     res.val.i = !!res.val.i;      res.val.i = !!res.val.i;
     break;      break;
   
  case P('!','~'):  case FI_NOT_MATCH:
     TWOARGS;      TWOARGS;
     res.type = T_BOOL;      res.type = T_BOOL;
     res.val.i = val_in_range(v1, v2);      res.val.i = val_in_range(v1, v2);
Line 828  interpret(struct f_inst *what) Line 846  interpret(struct f_inst *what)
     res.val.i = !res.val.i;      res.val.i = !res.val.i;
     break;      break;
   
  case P('d','e'):  case FI_DEFINED:
     ONEARG;      ONEARG;
     res.type = T_BOOL;      res.type = T_BOOL;
     res.val.i = (v1.type != T_VOID);      res.val.i = (v1.type != T_VOID);
     break;      break;
   
   /* Set to indirect value, a1 = variable, a2 = value */    /* Set to indirect value, a1 = variable, a2 = value */
  case 's':  case FI_SET:
     ARG(v2, a2.p);      ARG(v2, a2.p);
     sym = what->a1.p;      sym = what->a1.p;
     vp = sym->def;      vp = sym->def;
Line 854  interpret(struct f_inst *what) Line 872  interpret(struct f_inst *what)
     break;      break;
   
     /* some constants have value in a2, some in *a1.p, strange. */      /* some constants have value in a2, some in *a1.p, strange. */
  case 'c':       /* integer (or simple type) constant, string, set, or prefix_set */  case FI_CONSTANT:       /* integer (or simple type) constant, string, set, or prefix_set */
     res.type = what->aux;      res.type = what->aux;
   
     if (res.type == T_PREFIX_SET)      if (res.type == T_PREFIX_SET)
Line 866  interpret(struct f_inst *what) Line 884  interpret(struct f_inst *what)
     else      else
       res.val.i = what->a2.i;        res.val.i = what->a2.i;
     break;      break;
  case 'V':  case FI_VARIABLE:
  case 'C':  case FI_CONSTANT_INDIRECT:
     res = * ((struct f_val *) what->a1.p);      res = * ((struct f_val *) what->a1.p);
     break;      break;
  case 'p':  case FI_PRINT:
     ONEARG;      ONEARG;
     val_format(v1, &f_buf);      val_format(v1, &f_buf);
     break;      break;
  case '?':       /* ? has really strange error value, so we can implement if ... else nicely :-) */  case FI_CONDITION:       /* ? has really strange error value, so we can implement if ... else nicely :-) */
     ONEARG;      ONEARG;
     if (v1.type != T_BOOL)      if (v1.type != T_BOOL)
       runtime( "If requires boolean expression" );        runtime( "If requires boolean expression" );
Line 884  interpret(struct f_inst *what) Line 902  interpret(struct f_inst *what)
     } else res.val.i = 1;      } else res.val.i = 1;
     res.type = T_BOOL;      res.type = T_BOOL;
     break;      break;
  case '0':  case FI_NOP:
     debug( "No operation\n" );      debug( "No operation\n" );
     break;      break;
  case P('p',','):  case FI_PRINT_AND_DIE:
     ONEARG;      ONEARG;
    if (what->a2.i == F_NOP || (what->a2.i != F_NONL && what->a1.p))    if ((what->a2.i == F_NOP || (what->a2.i != F_NONL && what->a1.p)) &&
         !(f_flags & FF_SILENT))
       log_commit(*L_INFO, &f_buf);        log_commit(*L_INFO, &f_buf);
   
     switch (what->a2.i) {      switch (what->a2.i) {
Line 909  interpret(struct f_inst *what) Line 928  interpret(struct f_inst *what)
       bug( "unknown return type: Can't happen");        bug( "unknown return type: Can't happen");
     }      }
     break;      break;
  case 'a':       /* rta access */  case FI_RTA_GET:       /* rta access */
     {      {
       ACCESS_RTE;        ACCESS_RTE;
       struct rta *rta = (*f_rte)->attrs;        struct rta *rta = (*f_rte)->attrs;
Line 934  interpret(struct f_inst *what) Line 953  interpret(struct f_inst *what)
       }        }
     }      }
     break;      break;
  case P('a','S'):  case FI_RTA_SET:
     ACCESS_RTE;      ACCESS_RTE;
     ONEARG;      ONEARG;
     if (what->aux != v1.type)      if (what->aux != v1.type)
Line 981  interpret(struct f_inst *what) Line 1000  interpret(struct f_inst *what)
         rta->hostentry = NULL;          rta->hostentry = NULL;
         break;          break;
   
         case SA_IFNAME:
           {
             struct iface *ifa = if_find_by_name(v1.val.s);
             if (!ifa)
               runtime( "Invalid iface name" );
   
             rta->dest = RTD_DEVICE;
             rta->gw = IPA_NONE;
             rta->iface = ifa;
             rta->nexthops = NULL;
             rta->hostentry = NULL;
           }
           break;
   
       default:        default:
         bug("Invalid static attribute access (%x)", res.type);          bug("Invalid static attribute access (%x)", res.type);
       }        }
     }      }
     break;      break;
  case P('e','a'):       /* Access to extended attributes */  case FI_EA_GET:       /* Access to extended attributes */
     ACCESS_RTE;      ACCESS_RTE;
     {      {
       eattr *e = NULL;        eattr *e = NULL;
Line 1072  interpret(struct f_inst *what) Line 1105  interpret(struct f_inst *what)
       }        }
     }      }
     break;      break;
  case P('e','S'):  case FI_EA_SET:
     ACCESS_RTE;      ACCESS_RTE;
     ONEARG;      ONEARG;
     {      {
Line 1088  interpret(struct f_inst *what) Line 1121  interpret(struct f_inst *what)
   
       switch (what->aux & EAF_TYPE_MASK) {        switch (what->aux & EAF_TYPE_MASK) {
       case EAF_TYPE_INT:        case EAF_TYPE_INT:
        if (v1.type != T_INT)        // Enums are also ints, so allow them in.
         if (v1.type != T_INT && (v1.type < T_ENUM_LO || v1.type > T_ENUM_HI))
           runtime( "Setting int attribute to non-int value" );            runtime( "Setting int attribute to non-int value" );
         l->attrs[0].u.data = v1.val.i;          l->attrs[0].u.data = v1.val.i;
         break;          break;
Line 1177  interpret(struct f_inst *what) Line 1211  interpret(struct f_inst *what)
       }        }
     }      }
     break;      break;
  case 'P':  case FI_PREF_GET:
     ACCESS_RTE;      ACCESS_RTE;
     res.type = T_INT;      res.type = T_INT;
     res.val.i = (*f_rte)->pref;      res.val.i = (*f_rte)->pref;
     break;      break;
  case P('P','S'):  case FI_PREF_SET:
     ACCESS_RTE;      ACCESS_RTE;
     ONEARG;      ONEARG;
     if (v1.type != T_INT)      if (v1.type != T_INT)
Line 1192  interpret(struct f_inst *what) Line 1226  interpret(struct f_inst *what)
     f_rte_cow();      f_rte_cow();
     (*f_rte)->pref = v1.val.i;      (*f_rte)->pref = v1.val.i;
     break;      break;
  case 'L':       /* Get length of */  case FI_LENGTH:       /* Get length of */
     ONEARG;      ONEARG;
     res.type = T_INT;      res.type = T_INT;
     switch(v1.type) {      switch(v1.type) {
Line 1204  interpret(struct f_inst *what) Line 1238  interpret(struct f_inst *what)
     default: runtime( "Prefix, path, clist or eclist expected" );      default: runtime( "Prefix, path, clist or eclist expected" );
     }      }
     break;      break;
  case P('c','p'):       /* Convert prefix to ... */  case FI_IP:       /* Convert prefix to ... */
     ONEARG;      ONEARG;
     if (v1.type != T_PREFIX)      if (v1.type != T_PREFIX)
       runtime( "Prefix expected" );        runtime( "Prefix expected" );
Line 1215  interpret(struct f_inst *what) Line 1249  interpret(struct f_inst *what)
     default: bug( "Unknown prefix to conversion" );      default: bug( "Unknown prefix to conversion" );
     }      }
     break;      break;
  case P('a','f'):       /* Get first ASN from AS PATH */  case FI_AS_PATH_FIRST:       /* Get first ASN from AS PATH */
     ONEARG;      ONEARG;
     if (v1.type != T_PATH)      if (v1.type != T_PATH)
       runtime( "AS path expected" );        runtime( "AS path expected" );
Line 1225  interpret(struct f_inst *what) Line 1259  interpret(struct f_inst *what)
     res.type = T_INT;      res.type = T_INT;
     res.val.i = as;      res.val.i = as;
     break;      break;
  case P('a','l'):       /* Get last ASN from AS PATH */  case FI_AS_PATH_LAST:       /* Get last ASN from AS PATH */
     ONEARG;      ONEARG;
     if (v1.type != T_PATH)      if (v1.type != T_PATH)
       runtime( "AS path expected" );        runtime( "AS path expected" );
Line 1235  interpret(struct f_inst *what) Line 1269  interpret(struct f_inst *what)
     res.type = T_INT;      res.type = T_INT;
     res.val.i = as;      res.val.i = as;
     break;      break;
  case P('a','L'):       /* Get last ASN from non-aggregated part of AS PATH */  case FI_AS_PATH_LAST_NAG:       /* Get last ASN from non-aggregated part of AS PATH */
     ONEARG;      ONEARG;
     if (v1.type != T_PATH)      if (v1.type != T_PATH)
       runtime( "AS path expected" );        runtime( "AS path expected" );
Line 1243  interpret(struct f_inst *what) Line 1277  interpret(struct f_inst *what)
     res.type = T_INT;      res.type = T_INT;
     res.val.i = as_path_get_last_nonaggregated(v1.val.ad);      res.val.i = as_path_get_last_nonaggregated(v1.val.ad);
     break;      break;
  case 'r':  case FI_RETURN:
     ONEARG;      ONEARG;
     res = v1;      res = v1;
     res.type |= T_RETURN;      res.type |= T_RETURN;
     return res;      return res;
  case P('c','a'): /* CALL: this is special: if T_RETURN and returning some value, mask it out  */  case FI_CALL: /* CALL: this is special: if T_RETURN and returning some value, mask it out  */
     ONEARG;      ONEARG;
     res = interpret(what->a2.p);      res = interpret(what->a2.p);
     if (res.type == T_RETURN)      if (res.type == T_RETURN)
       return res;        return res;
     res.type &= ~T_RETURN;      res.type &= ~T_RETURN;
     break;      break;
  case P('c','v'):       /* Clear local variables */  case FI_CLEAR_LOCAL_VARS:       /* Clear local variables */
     for (sym = what->a1.p; sym != NULL; sym = sym->aux2)      for (sym = what->a1.p; sym != NULL; sym = sym->aux2)
       ((struct f_val *) sym->def)->type = T_VOID;        ((struct f_val *) sym->def)->type = T_VOID;
     break;      break;
  case P('S','W'):  case FI_SWITCH:
     ONEARG;      ONEARG;
     {      {
       struct f_tree *t = find_tree(what->a2.p, v1);        struct f_tree *t = find_tree(what->a2.p, v1);
Line 1278  interpret(struct f_inst *what) Line 1312  interpret(struct f_inst *what)
         return res;          return res;
     }      }
     break;      break;
  case P('i','M'): /* IP.MASK(val) */  case FI_IP_MASK: /* IP.MASK(val) */
     TWOARGS;      TWOARGS;
     if (v2.type != T_INT)      if (v2.type != T_INT)
       runtime( "Integer expected");        runtime( "Integer expected");
Line 1291  interpret(struct f_inst *what) Line 1325  interpret(struct f_inst *what)
     }      }
     break;      break;
   
  case 'E':       /* Create empty attribute */  case FI_EMPTY:       /* Create empty attribute */
     res.type = what->aux;      res.type = what->aux;
     res.val.ad = adata_empty(f_pool, 0);      res.val.ad = adata_empty(f_pool, 0);
     break;      break;
  case P('A','p'):       /* Path prepend */  case FI_PATH_PREPEND:       /* Path prepend */
     TWOARGS;      TWOARGS;
     if (v1.type != T_PATH)      if (v1.type != T_PATH)
       runtime("Can't prepend to non-path");        runtime("Can't prepend to non-path");
Line 1306  interpret(struct f_inst *what) Line 1340  interpret(struct f_inst *what)
     res.val.ad = as_path_prepend(f_pool, v1.val.ad, v2.val.i);      res.val.ad = as_path_prepend(f_pool, v1.val.ad, v2.val.i);
     break;      break;
   
  case P('C','a'):       /* (Extended) Community list add or delete */  case FI_CLIST_ADD_DEL:       /* (Extended) Community list add or delete */
     TWOARGS;      TWOARGS;
     if (v1.type == T_PATH)      if (v1.type == T_PATH)
     {      {
Line 1474  interpret(struct f_inst *what) Line 1508  interpret(struct f_inst *what)
   
     break;      break;
   
  case P('R','C'):       /* ROA Check */  case FI_ROA_CHECK:       /* ROA Check */
     if (what->arg1)      if (what->arg1)
     {      {
       TWOARGS;        TWOARGS;
Line 1493  interpret(struct f_inst *what) Line 1527  interpret(struct f_inst *what)
       /* 0x02 is a value of BA_AS_PATH, we don't want to include BGP headers */        /* 0x02 is a value of BA_AS_PATH, we don't want to include BGP headers */
       eattr *e = ea_find((*f_rte)->attrs->eattrs, EA_CODE(EAP_BGP, 0x02));        eattr *e = ea_find((*f_rte)->attrs->eattrs, EA_CODE(EAP_BGP, 0x02));
   
      if (!e || e->type != EAF_TYPE_AS_PATH)      if (!e || ((e->type & EAF_TYPE_MASK) != EAF_TYPE_AS_PATH))
         runtime("Missing AS_PATH attribute");          runtime("Missing AS_PATH attribute");
   
       as_path_get_last(e->u.ptr, &as);        as_path_get_last(e->u.ptr, &as);
Line 1508  interpret(struct f_inst *what) Line 1542  interpret(struct f_inst *what)
     break;      break;
   
   default:    default:
    bug( "Unknown instruction %d (%c)", what->code, what->code & 0xff);    bug( "Unknown instruction %d (%c)", what->fi_code, what->fi_code & 0xff);
  }  }}
  if (what->next) 
    return interpret(what->next); 
   return res;    return res;
 }  }
   
Line 1538  i_same(struct f_inst *f1, struct f_inst *f2) Line 1570  i_same(struct f_inst *f1, struct f_inst *f2)
     return 1;      return 1;
   if (f1->aux != f2->aux)    if (f1->aux != f2->aux)
     return 0;      return 0;
  if (f1->code != f2->code)  if (f1->fi_code != f2->fi_code)
     return 0;      return 0;
   if (f1 == f2)         /* It looks strange, but it is possible with call rewriting trickery */    if (f1 == f2)         /* It looks strange, but it is possible with call rewriting trickery */
     return 1;      return 1;
   
  switch(f1->code) {  switch(f1->fi_code) {
  case ',': /* fall through */  case FI_ADD: /* fall through */
  case '+':  case FI_SUBTRACT:
  case '-':  case FI_MULTIPLY:
  case '*':  case FI_DIVIDE:
  case '/':  case FI_OR:
  case '|':  case FI_AND:
  case '&':  case FI_PAIR_CONSTRUCT:
  case P('m','p'):  case FI_EC_CONSTRUCT:
  case P('m','c'):  case FI_NEQ:
  case P('!','='):  case FI_EQ:
  case P('=','='):  case FI_LT:
  case '<':  case FI_LTE: TWOARGS; break;
  case P('<','='): TWOARGS; break; 
   
  case '!': ONEARG; break;  case FI_PATHMASK_CONSTRUCT: if (!pm_same(f1->a1.p, f2->a1.p)) return 0; break;
  case '~': TWOARGS; break; 
  case P('d','e'): ONEARG; break; 
   
  case P('m','l'):  case FI_NOT: ONEARG; break;
   case FI_NOT_MATCH:
   case FI_MATCH: TWOARGS; break;
   case FI_DEFINED: ONEARG; break;
 
   case FI_LC_CONSTRUCT:
     TWOARGS;      TWOARGS;
     if (!i_same(INST3(f1).p, INST3(f2).p))      if (!i_same(INST3(f1).p, INST3(f2).p))
       return 0;        return 0;
     break;      break;
   
  case 's':  case FI_SET:
     ARG(v2, a2.p);      ARG(v2, a2.p);
     {      {
       struct symbol *s1, *s2;        struct symbol *s1, *s2;
Line 1581  i_same(struct f_inst *f1, struct f_inst *f2) Line 1615  i_same(struct f_inst *f1, struct f_inst *f2)
     }      }
     break;      break;
   
  case 'c':  case FI_CONSTANT:
     switch (f1->aux) {      switch (f1->aux) {
   
     case T_PREFIX_SET:      case T_PREFIX_SET:
Line 1604  i_same(struct f_inst *f1, struct f_inst *f2) Line 1638  i_same(struct f_inst *f1, struct f_inst *f2)
     }      }
     break;      break;
   
  case 'C':  case FI_CONSTANT_INDIRECT:
     if (!val_same(* (struct f_val *) f1->a1.p, * (struct f_val *) f2->a1.p))      if (!val_same(* (struct f_val *) f1->a1.p, * (struct f_val *) f2->a1.p))
       return 0;        return 0;
     break;      break;
   
  case 'V':  case FI_VARIABLE:
     if (strcmp((char *) f1->a2.p, (char *) f2->a2.p))      if (strcmp((char *) f1->a2.p, (char *) f2->a2.p))
       return 0;        return 0;
     break;      break;
  case 'p': case 'L': ONEARG; break;  case FI_PRINT: case FI_LENGTH: ONEARG; break;
  case '?': TWOARGS; break;  case FI_CONDITION: TWOARGS; break;
  case '0': case 'E': break;  case FI_NOP: case FI_EMPTY: break;
  case P('p',','): ONEARG; A2_SAME; break;  case FI_PRINT_AND_DIE: ONEARG; A2_SAME; break;
  case 'P':  case FI_PREF_GET:
  case 'a': A2_SAME; break;  case FI_RTA_GET: A2_SAME; break;
  case P('e','a'): A2_SAME; break;  case FI_EA_GET: A2_SAME; break;
  case P('P','S'):  case FI_PREF_SET:
  case P('a','S'):  case FI_RTA_SET:
  case P('e','S'): ONEARG; A2_SAME; break;  case FI_EA_SET: ONEARG; A2_SAME; break;
   
  case 'r': ONEARG; break;  case FI_RETURN: ONEARG; break;
  case P('c','p'): ONEARG; break;  case FI_IP: ONEARG; break;
  case P('c','a'): /* Call rewriting trickery to avoid exponential behaviour */  case FI_CALL: /* Call rewriting trickery to avoid exponential behaviour */
              ONEARG;               ONEARG;
              if (!i_same(f1->a2.p, f2->a2.p))               if (!i_same(f1->a2.p, f2->a2.p))
                return 0;                 return 0;
              f2->a2.p = f1->a2.p;               f2->a2.p = f1->a2.p;
              break;               break;
  case P('c','v'): break; /* internal instruction */  case FI_CLEAR_LOCAL_VARS: break; /* internal instruction */
  case P('S','W'): ONEARG; if (!same_tree(f1->a2.p, f2->a2.p)) return 0; break;  case FI_SWITCH: ONEARG; if (!same_tree(f1->a2.p, f2->a2.p)) return 0; break;
  case P('i','M'): TWOARGS; break;  case FI_IP_MASK: TWOARGS; break;
  case P('A','p'): TWOARGS; break;  case FI_PATH_PREPEND: TWOARGS; break;
  case P('C','a'): TWOARGS; break;  case FI_CLIST_ADD_DEL: TWOARGS; break;
  case P('a','f'):  case FI_AS_PATH_FIRST:
  case P('a','l'):  case FI_AS_PATH_LAST:
  case P('a','L'): ONEARG; break;  case FI_AS_PATH_LAST_NAG: ONEARG; break;
  case P('R','C'):  case FI_ROA_CHECK:
     TWOARGS;      TWOARGS;
     /* Does not really make sense - ROA check resuls may change anyway */      /* Does not really make sense - ROA check resuls may change anyway */
     if (strcmp(((struct f_inst_roa_check *) f1)->rtc->name,      if (strcmp(((struct f_inst_roa_check *) f1)->rtc->name,
Line 1648  i_same(struct f_inst *f1, struct f_inst *f2) Line 1682  i_same(struct f_inst *f1, struct f_inst *f2)
       return 0;        return 0;
     break;      break;
   default:    default:
    bug( "Unknown instruction %d in same (%c)", f1->code, f1->code & 0xff);    bug( "Unknown instruction %d in same (%c)", f1->fi_code, f1->fi_code & 0xff);
   }    }
   return i_same(f1->next, f2->next);    return i_same(f1->next, f2->next);
 }  }
Line 1721  f_run(struct filter *filter, struct rte **rte, struct  Line 1755  f_run(struct filter *filter, struct rte **rte, struct 
   
   
   if (res.type != T_RETURN) {    if (res.type != T_RETURN) {
    log_rl(&rl_runtime_err, L_ERR "Filter %s did not return accept nor reject. Make up your mind", filter->name);    if (!(f_flags & FF_SILENT))
       log_rl(&rl_runtime_err, L_ERR "Filter %s did not return accept nor reject. Make up your mind", filter->name);
     return F_ERROR;      return F_ERROR;
   }    }
   DBG( "done (%u)\n", res.val.i );    DBG( "done (%u)\n", res.val.i );
Line 1775  f_eval_int(struct f_inst *expr) Line 1810  f_eval_int(struct f_inst *expr)
     cf_error("Integer expression expected");      cf_error("Integer expression expected");
   
   return res.val.i;    return res.val.i;
 }  
   
 u32  
 f_eval_asn(struct f_inst *expr)  
 {  
   /* Called as a part of another interpret call, therefore no log_reset() */  
   struct f_val res = interpret(expr);  
   return (res.type == T_INT) ? res.val.i : 0;  
 }  }
   
 /**  /**

Removed from v.1.1.1.1  
changed lines
  Added in v.1.1.1.2


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>