File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / bird / filter / filter.c
Revision 1.1: download - view: text, annotated - select for diffs - revision graph
Tue Aug 22 12:33:54 2017 UTC (6 years, 10 months ago) by misho
CVS tags: MAIN, HEAD
Initial revision

    1: /*
    2:  *	Filters: utility functions
    3:  *
    4:  *	Copyright 1998 Pavel Machek <pavel@ucw.cz>
    5:  *
    6:  *	Can be freely distributed and used under the terms of the GNU GPL.
    7:  *
    8:  */
    9: 
   10: /**
   11:  * DOC: Filters
   12:  *
   13:  * You can find sources of the filter language in |filter/|
   14:  * directory. File |filter/config.Y| contains filter grammar and basically translates
   15:  * the source from user into a tree of &f_inst structures. These trees are
   16:  * later interpreted using code in |filter/filter.c|.
   17:  *
   18:  * A filter is represented by a tree of &f_inst structures, one structure per
   19:  * "instruction". Each &f_inst contains @code, @aux value which is
   20:  * usually the data type this instruction operates on and two generic
   21:  * arguments (@a1, @a2). Some instructions contain pointer(s) to other
   22:  * instructions in their (@a1, @a2) fields.
   23:  *
   24:  * Filters use a &f_val structure for their data. Each &f_val
   25:  * contains type and value (types are constants prefixed with %T_). Few
   26:  * of the types are special; %T_RETURN can be or-ed with a type to indicate
   27:  * that return from a function or from the whole filter should be
   28:  * forced. Important thing about &f_val's is that they may be copied
   29:  * with a simple |=|. That's fine for all currently defined types: strings
   30:  * are read-only (and therefore okay), paths are copied for each
   31:  * operation (okay too).
   32:  */
   33: 
   34: #undef LOCAL_DEBUG
   35: 
   36: #include "nest/bird.h"
   37: #include "lib/lists.h"
   38: #include "lib/resource.h"
   39: #include "lib/socket.h"
   40: #include "lib/string.h"
   41: #include "lib/unaligned.h"
   42: #include "nest/route.h"
   43: #include "nest/protocol.h"
   44: #include "nest/iface.h"
   45: #include "nest/attrs.h"
   46: #include "conf/conf.h"
   47: #include "filter/filter.h"
   48: 
   49: #define P(a,b) ((a<<8) | b)
   50: 
   51: #define CMP_ERROR 999
   52: 
   53: static struct adata *
   54: adata_empty(struct linpool *pool, int l)
   55: {
   56:   struct adata *res = lp_alloc(pool, sizeof(struct adata) + l);
   57:   res->length = l;
   58:   return res;
   59: }
   60: 
   61: static void
   62: pm_format(struct f_path_mask *p, buffer *buf)
   63: {
   64:   buffer_puts(buf, "[= ");
   65: 
   66:   while (p)
   67:   {
   68:     switch(p->kind)
   69:     {
   70:     case PM_ASN:
   71:       buffer_print(buf, "%u ", p->val);
   72:       break;
   73: 
   74:     case PM_QUESTION:
   75:       buffer_puts(buf, "? ");
   76:       break;
   77: 
   78:     case PM_ASTERISK:
   79:       buffer_puts(buf, "* ");
   80:       break;
   81: 
   82:     case PM_ASN_RANGE:
   83:       buffer_print(buf, "%u..%u ", p->val, p->val2);
   84:       break;
   85: 
   86:     case PM_ASN_EXPR:
   87:       buffer_print(buf, "%u ", f_eval_asn((struct f_inst *) p->val));
   88:       break;
   89:     }
   90: 
   91:     p = p->next;
   92:   }
   93: 
   94:   buffer_puts(buf, "=]");
   95: }
   96: 
   97: static inline int
   98: uint_cmp(uint i1, uint i2)
   99: {
  100:   return (int)(i1 > i2) - (int)(i1 < i2);
  101: }
  102: 
  103: static inline int
  104: u64_cmp(u64 i1, u64 i2)
  105: {
  106:   return (int)(i1 > i2) - (int)(i1 < i2);
  107: }
  108: 
  109: static inline int
  110: lcomm_cmp(lcomm v1, lcomm v2)
  111: {
  112:   if (v1.asn != v2.asn)
  113:     return (v1.asn > v2.asn) ? 1 : -1;
  114:   if (v1.ldp1 != v2.ldp1)
  115:     return (v1.ldp1 > v2.ldp1) ? 1 : -1;
  116:   if (v1.ldp2 != v2.ldp2)
  117:     return (v1.ldp2 > v2.ldp2) ? 1 : -1;
  118:   return 0;
  119: }
  120: 
  121: /**
  122:  * val_compare - compare two values
  123:  * @v1: first value
  124:  * @v2: second value
  125:  *
  126:  * Compares two values and returns -1, 0, 1 on <, =, > or CMP_ERROR on
  127:  * error. Tree module relies on this giving consistent results so
  128:  * that it can be used for building balanced trees.
  129:  */
  130: int
  131: val_compare(struct f_val v1, struct f_val v2)
  132: {
  133:   int rc;
  134: 
  135:   if (v1.type != v2.type) {
  136:     if (v1.type == T_VOID)	/* Hack for else */
  137:       return -1;
  138:     if (v2.type == T_VOID)
  139:       return 1;
  140: 
  141: #ifndef IPV6
  142:     /* IP->Quad implicit conversion */
  143:     if ((v1.type == T_QUAD) && (v2.type == T_IP))
  144:       return uint_cmp(v1.val.i, ipa_to_u32(v2.val.px.ip));
  145:     if ((v1.type == T_IP) && (v2.type == T_QUAD))
  146:       return uint_cmp(ipa_to_u32(v1.val.px.ip), v2.val.i);
  147: #endif
  148: 
  149:     debug( "Types do not match in val_compare\n" );
  150:     return CMP_ERROR;
  151:   }
  152: 
  153:   switch (v1.type) {
  154:   case T_VOID:
  155:     return 0;
  156:   case T_ENUM:
  157:   case T_INT:
  158:   case T_BOOL:
  159:   case T_PAIR:
  160:   case T_QUAD:
  161:     return uint_cmp(v1.val.i, v2.val.i);
  162:   case T_EC:
  163:     return u64_cmp(v1.val.ec, v2.val.ec);
  164:   case T_LC:
  165:     return lcomm_cmp(v1.val.lc, v2.val.lc);
  166:   case T_IP:
  167:     return ipa_compare(v1.val.px.ip, v2.val.px.ip);
  168:   case T_PREFIX:
  169:     if (rc = ipa_compare(v1.val.px.ip, v2.val.px.ip))
  170:       return rc;
  171:     return uint_cmp(v1.val.px.len, v2.val.px.len);
  172:   case T_STRING:
  173:     return strcmp(v1.val.s, v2.val.s);
  174:   default:
  175:     return CMP_ERROR;
  176:   }
  177: }
  178: 
  179: static int
  180: pm_same(struct f_path_mask *m1, struct f_path_mask *m2)
  181: {
  182:   while (m1 && m2)
  183:   {
  184:     if (m1->kind != m2->kind)
  185:       return 0;
  186: 
  187:     if (m1->kind == PM_ASN_EXPR)
  188:     {
  189:       if (!i_same((struct f_inst *) m1->val, (struct f_inst *) m2->val))
  190: 	return 0;
  191:     }
  192:     else
  193:     {
  194:       if ((m1->val != m2->val) || (m1->val2 != m2->val2))
  195: 	return 0;
  196:     }
  197: 
  198:     m1 = m1->next;
  199:     m2 = m2->next;
  200:   }
  201: 
  202:   return !m1 && !m2;
  203: }
  204: 
  205: /**
  206:  * val_same - compare two values
  207:  * @v1: first value
  208:  * @v2: second value
  209:  *
  210:  * Compares two values and returns 1 if they are same and 0 if not.
  211:  * Comparison of values of different types is valid and returns 0.
  212:  */
  213: int
  214: val_same(struct f_val v1, struct f_val v2)
  215: {
  216:   int rc;
  217: 
  218:   rc = val_compare(v1, v2);
  219:   if (rc != CMP_ERROR)
  220:     return !rc;
  221: 
  222:   if (v1.type != v2.type)
  223:     return 0;
  224: 
  225:   switch (v1.type) {
  226:   case T_PATH_MASK:
  227:     return pm_same(v1.val.path_mask, v2.val.path_mask);
  228:   case T_PATH:
  229:   case T_CLIST:
  230:   case T_ECLIST:
  231:   case T_LCLIST:
  232:     return adata_same(v1.val.ad, v2.val.ad);
  233:   case T_SET:
  234:     return same_tree(v1.val.t, v2.val.t);
  235:   case T_PREFIX_SET:
  236:     return trie_same(v1.val.ti, v2.val.ti);
  237:   default:
  238:     bug("Invalid type in val_same(): %x", v1.type);
  239:   }
  240: }
  241: 
  242: void
  243: fprefix_get_bounds(struct f_prefix *px, int *l, int *h)
  244: {
  245:   *l = *h = px->len & LEN_MASK;
  246: 
  247:   if (px->len & LEN_MINUS)
  248:     *l = 0;
  249: 
  250:   else if (px->len & LEN_PLUS)
  251:     *h = MAX_PREFIX_LENGTH;
  252: 
  253:   else if (px->len & LEN_RANGE)
  254:     {
  255:       *l = 0xff & (px->len >> 16);
  256:       *h = 0xff & (px->len >> 8);
  257:     }
  258: }
  259: 
  260: static int
  261: clist_set_type(struct f_tree *set, struct f_val *v)
  262: {
  263:  switch (set->from.type) {
  264:   case T_PAIR:
  265:     v->type = T_PAIR;
  266:     return 1;
  267:   case T_QUAD:
  268: #ifndef IPV6
  269:   case T_IP:
  270: #endif
  271:     v->type = T_QUAD;
  272:     return 1;
  273:     break;
  274:   default:
  275:     v->type = T_VOID;
  276:     return 0;
  277:   }
  278: }
  279: 
  280: static inline int
  281: eclist_set_type(struct f_tree *set)
  282: { return set->from.type == T_EC; }
  283: 
  284: static inline int
  285: lclist_set_type(struct f_tree *set)
  286: { return set->from.type == T_LC; }
  287: 
  288: static int
  289: clist_match_set(struct adata *clist, struct f_tree *set)
  290: {
  291:   if (!clist)
  292:     return 0;
  293: 
  294:   struct f_val v;
  295:   if (!clist_set_type(set, &v))
  296:     return CMP_ERROR;
  297: 
  298:   u32 *l = (u32 *) clist->data;
  299:   u32 *end = l + clist->length/4;
  300: 
  301:   while (l < end) {
  302:     v.val.i = *l++;
  303:     if (find_tree(set, v))
  304:       return 1;
  305:   }
  306:   return 0;
  307: }
  308: 
  309: static int
  310: eclist_match_set(struct adata *list, struct f_tree *set)
  311: {
  312:   if (!list)
  313:     return 0;
  314: 
  315:   if (!eclist_set_type(set))
  316:     return CMP_ERROR;
  317: 
  318:   struct f_val v;
  319:   u32 *l = int_set_get_data(list);
  320:   int len = int_set_get_size(list);
  321:   int i;
  322: 
  323:   v.type = T_EC;
  324:   for (i = 0; i < len; i += 2) {
  325:     v.val.ec = ec_get(l, i);
  326:     if (find_tree(set, v))
  327:       return 1;
  328:   }
  329: 
  330:   return 0;
  331: }
  332: 
  333: static int
  334: lclist_match_set(struct adata *list, struct f_tree *set)
  335: {
  336:   if (!list)
  337:     return 0;
  338: 
  339:   if (!lclist_set_type(set))
  340:     return CMP_ERROR;
  341: 
  342:   struct f_val v;
  343:   u32 *l = int_set_get_data(list);
  344:   int len = int_set_get_size(list);
  345:   int i;
  346: 
  347:   v.type = T_LC;
  348:   for (i = 0; i < len; i += 3) {
  349:     v.val.lc = lc_get(l, i);
  350:     if (find_tree(set, v))
  351:       return 1;
  352:   }
  353: 
  354:   return 0;
  355: }
  356: 
  357: static struct adata *
  358: clist_filter(struct linpool *pool, struct adata *list, struct f_val set, int pos)
  359: {
  360:   if (!list)
  361:     return NULL;
  362: 
  363:   int tree = (set.type == T_SET);	/* 1 -> set is T_SET, 0 -> set is T_CLIST */
  364:   struct f_val v;
  365:   if (tree)
  366:     clist_set_type(set.val.t, &v);
  367:   else
  368:     v.type = T_PAIR;
  369: 
  370:   int len = int_set_get_size(list);
  371:   u32 *l = int_set_get_data(list);
  372:   u32 tmp[len];
  373:   u32 *k = tmp;
  374:   u32 *end = l + len;
  375: 
  376:   while (l < end) {
  377:     v.val.i = *l++;
  378:     /* pos && member(val, set) || !pos && !member(val, set),  member() depends on tree */
  379:     if ((tree ? !!find_tree(set.val.t, v) : int_set_contains(set.val.ad, v.val.i)) == pos)
  380:       *k++ = v.val.i;
  381:   }
  382: 
  383:   uint nl = (k - tmp) * sizeof(u32);
  384:   if (nl == list->length)
  385:     return list;
  386: 
  387:   struct adata *res = adata_empty(pool, nl);
  388:   memcpy(res->data, tmp, nl);
  389:   return res;
  390: }
  391: 
  392: static struct adata *
  393: eclist_filter(struct linpool *pool, struct adata *list, struct f_val set, int pos)
  394: {
  395:   if (!list)
  396:     return NULL;
  397: 
  398:   int tree = (set.type == T_SET);	/* 1 -> set is T_SET, 0 -> set is T_CLIST */
  399:   struct f_val v;
  400: 
  401:   int len = int_set_get_size(list);
  402:   u32 *l = int_set_get_data(list);
  403:   u32 tmp[len];
  404:   u32 *k = tmp;
  405:   int i;
  406: 
  407:   v.type = T_EC;
  408:   for (i = 0; i < len; i += 2) {
  409:     v.val.ec = ec_get(l, i);
  410:     /* pos && member(val, set) || !pos && !member(val, set),  member() depends on tree */
  411:     if ((tree ? !!find_tree(set.val.t, v) : ec_set_contains(set.val.ad, v.val.ec)) == pos) {
  412:       *k++ = l[i];
  413:       *k++ = l[i+1];
  414:     }
  415:   }
  416: 
  417:   uint nl = (k - tmp) * sizeof(u32);
  418:   if (nl == list->length)
  419:     return list;
  420: 
  421:   struct adata *res = adata_empty(pool, nl);
  422:   memcpy(res->data, tmp, nl);
  423:   return res;
  424: }
  425: 
  426: static struct adata *
  427: lclist_filter(struct linpool *pool, struct adata *list, struct f_val set, int pos)
  428: {
  429:   if (!list)
  430:     return NULL;
  431: 
  432:   int tree = (set.type == T_SET);	/* 1 -> set is T_SET, 0 -> set is T_CLIST */
  433:   struct f_val v;
  434: 
  435:   int len = int_set_get_size(list);
  436:   u32 *l = int_set_get_data(list);
  437:   u32 tmp[len];
  438:   u32 *k = tmp;
  439:   int i;
  440: 
  441:   v.type = T_LC;
  442:   for (i = 0; i < len; i += 3) {
  443:     v.val.lc = lc_get(l, i);
  444:     /* pos && member(val, set) || !pos && !member(val, set),  member() depends on tree */
  445:     if ((tree ? !!find_tree(set.val.t, v) : lc_set_contains(set.val.ad, v.val.lc)) == pos)
  446:       k = lc_copy(k, l+i);
  447:   }
  448: 
  449:   uint nl = (k - tmp) * sizeof(u32);
  450:   if (nl == list->length)
  451:     return list;
  452: 
  453:   struct adata *res = adata_empty(pool, nl);
  454:   memcpy(res->data, tmp, nl);
  455:   return res;
  456: }
  457: 
  458: /**
  459:  * val_in_range - implement |~| operator
  460:  * @v1: element
  461:  * @v2: set
  462:  *
  463:  * Checks if @v1 is element (|~| operator) of @v2.
  464:  */
  465: static int
  466: val_in_range(struct f_val v1, struct f_val v2)
  467: {
  468:   if ((v1.type == T_PATH) && (v2.type == T_PATH_MASK))
  469:     return as_path_match(v1.val.ad, v2.val.path_mask);
  470: 
  471:   if ((v1.type == T_INT) && (v2.type == T_PATH))
  472:     return as_path_contains(v2.val.ad, v1.val.i, 1);
  473: 
  474:   if (((v1.type == T_PAIR) || (v1.type == T_QUAD)) && (v2.type == T_CLIST))
  475:     return int_set_contains(v2.val.ad, v1.val.i);
  476: #ifndef IPV6
  477:   /* IP->Quad implicit conversion */
  478:   if ((v1.type == T_IP) && (v2.type == T_CLIST))
  479:     return int_set_contains(v2.val.ad, ipa_to_u32(v1.val.px.ip));
  480: #endif
  481: 
  482:   if ((v1.type == T_EC) && (v2.type == T_ECLIST))
  483:     return ec_set_contains(v2.val.ad, v1.val.ec);
  484: 
  485:   if ((v1.type == T_LC) && (v2.type == T_LCLIST))
  486:     return lc_set_contains(v2.val.ad, v1.val.lc);
  487: 
  488:   if ((v1.type == T_STRING) && (v2.type == T_STRING))
  489:     return patmatch(v2.val.s, v1.val.s);
  490: 
  491:   if ((v1.type == T_IP) && (v2.type == T_PREFIX))
  492:     return ipa_in_net(v1.val.px.ip, v2.val.px.ip, v2.val.px.len);
  493: 
  494:   if ((v1.type == T_PREFIX) && (v2.type == T_PREFIX))
  495:     return net_in_net(v1.val.px.ip, v1.val.px.len, v2.val.px.ip, v2.val.px.len);
  496: 
  497:   if ((v1.type == T_PREFIX) && (v2.type == T_PREFIX_SET))
  498:     return trie_match_fprefix(v2.val.ti, &v1.val.px);
  499: 
  500:   if (v2.type != T_SET)
  501:     return CMP_ERROR;
  502: 
  503:   /* With integrated Quad<->IP implicit conversion */
  504:   if ((v1.type == v2.val.t->from.type) ||
  505:       ((IP_VERSION == 4) && (v1.type == T_QUAD) && (v2.val.t->from.type == T_IP)))
  506:     return !!find_tree(v2.val.t, v1);
  507: 
  508:   if (v1.type == T_CLIST)
  509:     return clist_match_set(v1.val.ad, v2.val.t);
  510: 
  511:   if (v1.type == T_ECLIST)
  512:     return eclist_match_set(v1.val.ad, v2.val.t);
  513: 
  514:   if (v1.type == T_LCLIST)
  515:     return lclist_match_set(v1.val.ad, v2.val.t);
  516: 
  517:   if (v1.type == T_PATH)
  518:     return as_path_match_set(v1.val.ad, v2.val.t);
  519: 
  520:   return CMP_ERROR;
  521: }
  522: 
  523: /*
  524:  * val_format - format filter value
  525:  */
  526: void
  527: val_format(struct f_val v, buffer *buf)
  528: {
  529:   char buf2[1024];
  530:   switch (v.type)
  531:   {
  532:   case T_VOID:	buffer_puts(buf, "(void)"); return;
  533:   case T_BOOL:	buffer_puts(buf, v.val.i ? "TRUE" : "FALSE"); return;
  534:   case T_INT:	buffer_print(buf, "%u", v.val.i); return;
  535:   case T_STRING: buffer_print(buf, "%s", v.val.s); return;
  536:   case T_IP:	buffer_print(buf, "%I", v.val.px.ip); return;
  537:   case T_PREFIX: buffer_print(buf, "%I/%d", v.val.px.ip, v.val.px.len); return;
  538:   case T_PAIR:	buffer_print(buf, "(%u,%u)", v.val.i >> 16, v.val.i & 0xffff); return;
  539:   case T_QUAD:	buffer_print(buf, "%R", v.val.i); return;
  540:   case T_EC:	ec_format(buf2, v.val.ec); buffer_print(buf, "%s", buf2); return;
  541:   case T_LC:	lc_format(buf2, v.val.lc); buffer_print(buf, "%s", buf2); return;
  542:   case T_PREFIX_SET: trie_format(v.val.ti, buf); return;
  543:   case T_SET:	tree_format(v.val.t, buf); return;
  544:   case T_ENUM:	buffer_print(buf, "(enum %x)%u", v.type, v.val.i); return;
  545:   case T_PATH:	as_path_format(v.val.ad, buf2, 1000); buffer_print(buf, "(path %s)", buf2); return;
  546:   case T_CLIST:	int_set_format(v.val.ad, 1, -1, buf2, 1000); buffer_print(buf, "(clist %s)", buf2); return;
  547:   case T_ECLIST: ec_set_format(v.val.ad, -1, buf2, 1000); buffer_print(buf, "(eclist %s)", buf2); return;
  548:   case T_LCLIST: lc_set_format(v.val.ad, -1, buf2, 1000); buffer_print(buf, "(lclist %s)", buf2); return;
  549:   case T_PATH_MASK: pm_format(v.val.path_mask, buf); return;
  550:   default:	buffer_print(buf, "[unknown type %x]", v.type); return;
  551:   }
  552: }
  553: 
  554: static struct rte **f_rte;
  555: static struct rta *f_old_rta;
  556: static struct ea_list **f_tmp_attrs;
  557: static struct linpool *f_pool;
  558: static struct buffer f_buf;
  559: static int f_flags;
  560: 
  561: static inline void f_rte_cow(void)
  562: {
  563:   *f_rte = rte_cow(*f_rte);
  564: }
  565: 
  566: /*
  567:  * rta_cow - prepare rta for modification by filter
  568:  */
  569: static void
  570: f_rta_cow(void)
  571: {
  572:   if (!rta_is_cached((*f_rte)->attrs))
  573:     return;
  574: 
  575:   /* Prepare to modify rte */
  576:   f_rte_cow();
  577: 
  578:   /* Store old rta to free it later, it stores reference from rte_cow() */
  579:   f_old_rta = (*f_rte)->attrs;
  580: 
  581:   /*
  582:    * Get shallow copy of rta. Fields eattrs and nexthops of rta are shared
  583:    * with f_old_rta (they will be copied when the cached rta will be obtained
  584:    * at the end of f_run()), also the lock of hostentry is inherited (we
  585:    * suppose hostentry is not changed by filters).
  586:    */
  587:   (*f_rte)->attrs = rta_do_cow((*f_rte)->attrs, f_pool);
  588: }
  589: 
  590: static struct tbf rl_runtime_err = TBF_DEFAULT_LOG_LIMITS;
  591: 
  592: #define runtime(x) do { \
  593:     log_rl(&rl_runtime_err, L_ERR "filters, line %d: %s", what->lineno, x); \
  594:     res.type = T_RETURN; \
  595:     res.val.i = F_ERROR; \
  596:     return res; \
  597:   } while(0)
  598: 
  599: #define ARG(x,y) \
  600: 	x = interpret(what->y); \
  601: 	if (x.type & T_RETURN) \
  602: 		return x;
  603: 
  604: #define ONEARG ARG(v1, a1.p)
  605: #define TWOARGS ARG(v1, a1.p) \
  606: 		ARG(v2, a2.p)
  607: #define TWOARGS_C TWOARGS \
  608:                   if (v1.type != v2.type) \
  609: 		    runtime( "Can't operate with values of incompatible types" );
  610: #define ACCESS_RTE \
  611:   do { if (!f_rte) runtime("No route to access"); } while (0)
  612: 
  613: #define BITFIELD_MASK(what) \
  614:   (1u << (what->a2.i >> 24))
  615: 
  616: /**
  617:  * interpret
  618:  * @what: filter to interpret
  619:  *
  620:  * Interpret given tree of filter instructions. This is core function
  621:  * of filter system and does all the hard work.
  622:  *
  623:  * Each instruction has 4 fields: code (which is instruction code),
  624:  * aux (which is extension to instruction code, typically type),
  625:  * arg1 and arg2 - arguments. Depending on instruction, arguments
  626:  * are either integers, or pointers to instruction trees. Common
  627:  * instructions like +, that have two expressions as arguments use
  628:  * TWOARGS macro to get both of them evaluated.
  629:  *
  630:  * &f_val structures are copied around, so there are no problems with
  631:  * memory managment.
  632:  */
  633: static struct f_val
  634: interpret(struct f_inst *what)
  635: {
  636:   struct symbol *sym;
  637:   struct f_val v1, v2, res, *vp;
  638:   unsigned u1, u2;
  639:   int i;
  640:   u32 as;
  641: 
  642:   res.type = T_VOID;
  643:   if (!what)
  644:     return res;
  645: 
  646:   switch(what->code) {
  647:   case ',':
  648:     TWOARGS;
  649:     break;
  650: 
  651: /* Binary operators */
  652:   case '+':
  653:     TWOARGS_C;
  654:     switch (res.type = v1.type) {
  655:     case T_VOID: runtime( "Can't operate with values of type void" );
  656:     case T_INT: res.val.i = v1.val.i + v2.val.i; break;
  657:     default: runtime( "Usage of unknown type" );
  658:     }
  659:     break;
  660:   case '-':
  661:     TWOARGS_C;
  662:     switch (res.type = v1.type) {
  663:     case T_VOID: runtime( "Can't operate with values of type void" );
  664:     case T_INT: res.val.i = v1.val.i - v2.val.i; break;
  665:     default: runtime( "Usage of unknown type" );
  666:     }
  667:     break;
  668:   case '*':
  669:     TWOARGS_C;
  670:     switch (res.type = v1.type) {
  671:     case T_VOID: runtime( "Can't operate with values of type void" );
  672:     case T_INT: res.val.i = v1.val.i * v2.val.i; break;
  673:     default: runtime( "Usage of unknown type" );
  674:     }
  675:     break;
  676:   case '/':
  677:     TWOARGS_C;
  678:     switch (res.type = v1.type) {
  679:     case T_VOID: runtime( "Can't operate with values of type void" );
  680:     case T_INT: if (v2.val.i == 0) runtime( "Mother told me not to divide by 0" );
  681:       	        res.val.i = v1.val.i / v2.val.i; break;
  682:     default: runtime( "Usage of unknown type" );
  683:     }
  684:     break;
  685: 
  686:   case '&':
  687:   case '|':
  688:     ARG(v1, a1.p);
  689:     if (v1.type != T_BOOL)
  690:       runtime( "Can't do boolean operation on non-booleans" );
  691:     if (v1.val.i == (what->code == '|')) {
  692:       res.type = T_BOOL;
  693:       res.val.i = v1.val.i;
  694:       break;
  695:     }
  696: 
  697:     ARG(v2, a2.p);
  698:     if (v2.type != T_BOOL)
  699:       runtime( "Can't do boolean operation on non-booleans" );
  700:     res.type = T_BOOL;
  701:     res.val.i = v2.val.i;
  702:     break;
  703: 
  704:   case P('m','p'):
  705:     TWOARGS;
  706:     if ((v1.type != T_INT) || (v2.type != T_INT))
  707:       runtime( "Can't operate with value of non-integer type in pair constructor" );
  708:     u1 = v1.val.i;
  709:     u2 = v2.val.i;
  710:     if ((u1 > 0xFFFF) || (u2 > 0xFFFF))
  711:       runtime( "Can't operate with value out of bounds in pair constructor" );
  712:     res.val.i = (u1 << 16) | u2;
  713:     res.type = T_PAIR;
  714:     break;
  715: 
  716:   case P('m','c'):
  717:     {
  718:       TWOARGS;
  719: 
  720:       int check, ipv4_used;
  721:       u32 key, val;
  722: 
  723:       if (v1.type == T_INT) {
  724: 	ipv4_used = 0; key = v1.val.i;
  725:       }
  726:       else if (v1.type == T_QUAD) {
  727: 	ipv4_used = 1; key = v1.val.i;
  728:       }
  729: #ifndef IPV6
  730:       /* IP->Quad implicit conversion */
  731:       else if (v1.type == T_IP) {
  732: 	ipv4_used = 1; key = ipa_to_u32(v1.val.px.ip);
  733:       }
  734: #endif
  735:       else
  736: 	runtime("Can't operate with key of non-integer/IPv4 type in EC constructor");
  737: 
  738:       if (v2.type != T_INT)
  739: 	runtime("Can't operate with value of non-integer type in EC constructor");
  740:       val = v2.val.i;
  741: 
  742:       /* XXXX */
  743:       res.type = T_EC;
  744: 
  745:       if (what->aux == EC_GENERIC) {
  746: 	check = 0; res.val.ec = ec_generic(key, val);
  747:       }
  748:       else if (ipv4_used) {
  749: 	check = 1; res.val.ec = ec_ip4(what->aux, key, val);
  750:       }
  751:       else if (key < 0x10000) {
  752: 	check = 0; res.val.ec = ec_as2(what->aux, key, val);
  753:       }
  754:       else {
  755: 	check = 1; res.val.ec = ec_as4(what->aux, key, val);
  756:       }
  757: 
  758:       if (check && (val > 0xFFFF))
  759: 	runtime("Can't operate with value out of bounds in EC constructor");
  760: 
  761:       break;
  762:     }
  763: 
  764:   case P('m','l'):
  765:     {
  766:       TWOARGS;
  767: 
  768:       /* Third argument hack */
  769:       struct f_val v3 = interpret(INST3(what).p);
  770:       if (v3.type & T_RETURN)
  771: 	return v3;
  772: 
  773:       if ((v1.type != T_INT) || (v2.type != T_INT) || (v3.type != T_INT))
  774: 	runtime( "Can't operate with value of non-integer type in LC constructor" );
  775: 
  776:       res.type = T_LC;
  777:       res.val.lc = (lcomm) { v1.val.i, v2.val.i, v3.val.i };
  778: 
  779:       break;
  780:     }
  781: 
  782: /* Relational operators */
  783: 
  784: #define COMPARE(x) \
  785:     TWOARGS; \
  786:     i = val_compare(v1, v2); \
  787:     if (i==CMP_ERROR) \
  788:       runtime( "Can't compare values of incompatible types" ); \
  789:     res.type = T_BOOL; \
  790:     res.val.i = (x); \
  791:     break;
  792: 
  793: #define SAME(x) \
  794:     TWOARGS; \
  795:     i = val_same(v1, v2); \
  796:     res.type = T_BOOL; \
  797:     res.val.i = (x); \
  798:     break;
  799: 
  800:   case P('!','='): SAME(!i);
  801:   case P('=','='): SAME(i);
  802:   case '<': COMPARE(i==-1);
  803:   case P('<','='): COMPARE(i!=1);
  804: 
  805:   case '!':
  806:     ONEARG;
  807:     if (v1.type != T_BOOL)
  808:       runtime( "Not applied to non-boolean" );
  809:     res = v1;
  810:     res.val.i = !res.val.i;
  811:     break;
  812: 
  813:   case '~':
  814:     TWOARGS;
  815:     res.type = T_BOOL;
  816:     res.val.i = val_in_range(v1, v2);
  817:     if (res.val.i == CMP_ERROR)
  818:       runtime( "~ applied on unknown type pair" );
  819:     res.val.i = !!res.val.i;
  820:     break;
  821: 
  822:   case P('!','~'):
  823:     TWOARGS;
  824:     res.type = T_BOOL;
  825:     res.val.i = val_in_range(v1, v2);
  826:     if (res.val.i == CMP_ERROR)
  827:       runtime( "!~ applied on unknown type pair" );
  828:     res.val.i = !res.val.i;
  829:     break;
  830: 
  831:   case P('d','e'):
  832:     ONEARG;
  833:     res.type = T_BOOL;
  834:     res.val.i = (v1.type != T_VOID);
  835:     break;
  836: 
  837:   /* Set to indirect value, a1 = variable, a2 = value */
  838:   case 's':
  839:     ARG(v2, a2.p);
  840:     sym = what->a1.p;
  841:     vp = sym->def;
  842:     if ((sym->class != (SYM_VARIABLE | v2.type)) && (v2.type != T_VOID)) {
  843: #ifndef IPV6
  844:       /* IP->Quad implicit conversion */
  845:       if ((sym->class == (SYM_VARIABLE | T_QUAD)) && (v2.type == T_IP)) {
  846: 	vp->type = T_QUAD;
  847: 	vp->val.i = ipa_to_u32(v2.val.px.ip);
  848: 	break;
  849:       }
  850: #endif
  851:       runtime( "Assigning to variable of incompatible type" );
  852:     }
  853:     *vp = v2;
  854:     break;
  855: 
  856:     /* some constants have value in a2, some in *a1.p, strange. */
  857:   case 'c':	/* integer (or simple type) constant, string, set, or prefix_set */
  858:     res.type = what->aux;
  859: 
  860:     if (res.type == T_PREFIX_SET)
  861:       res.val.ti = what->a2.p;
  862:     else if (res.type == T_SET)
  863:       res.val.t = what->a2.p;
  864:     else if (res.type == T_STRING)
  865:       res.val.s = what->a2.p;
  866:     else
  867:       res.val.i = what->a2.i;
  868:     break;
  869:   case 'V':
  870:   case 'C':
  871:     res = * ((struct f_val *) what->a1.p);
  872:     break;
  873:   case 'p':
  874:     ONEARG;
  875:     val_format(v1, &f_buf);
  876:     break;
  877:   case '?':	/* ? has really strange error value, so we can implement if ... else nicely :-) */
  878:     ONEARG;
  879:     if (v1.type != T_BOOL)
  880:       runtime( "If requires boolean expression" );
  881:     if (v1.val.i) {
  882:       ARG(res,a2.p);
  883:       res.val.i = 0;
  884:     } else res.val.i = 1;
  885:     res.type = T_BOOL;
  886:     break;
  887:   case '0':
  888:     debug( "No operation\n" );
  889:     break;
  890:   case P('p',','):
  891:     ONEARG;
  892:     if (what->a2.i == F_NOP || (what->a2.i != F_NONL && what->a1.p))
  893:       log_commit(*L_INFO, &f_buf);
  894: 
  895:     switch (what->a2.i) {
  896:     case F_QUITBIRD:
  897:       die( "Filter asked me to die" );
  898:     case F_ACCEPT:
  899:       /* Should take care about turning ACCEPT into MODIFY */
  900:     case F_ERROR:
  901:     case F_REJECT:	/* FIXME (noncritical) Should print complete route along with reason to reject route */
  902:       res.type = T_RETURN;
  903:       res.val.i = what->a2.i;
  904:       return res;	/* We have to return now, no more processing. */
  905:     case F_NONL:
  906:     case F_NOP:
  907:       break;
  908:     default:
  909:       bug( "unknown return type: Can't happen");
  910:     }
  911:     break;
  912:   case 'a':	/* rta access */
  913:     {
  914:       ACCESS_RTE;
  915:       struct rta *rta = (*f_rte)->attrs;
  916:       res.type = what->aux;
  917: 
  918:       switch (what->a2.i)
  919:       {
  920:       case SA_FROM:	res.val.px.ip = rta->from; break;
  921:       case SA_GW:	res.val.px.ip = rta->gw; break;
  922:       case SA_NET:	res.val.px.ip = (*f_rte)->net->n.prefix;
  923: 			res.val.px.len = (*f_rte)->net->n.pxlen; break;
  924:       case SA_PROTO:	res.val.s = rta->src->proto->name; break;
  925:       case SA_SOURCE:	res.val.i = rta->source; break;
  926:       case SA_SCOPE:	res.val.i = rta->scope; break;
  927:       case SA_CAST:	res.val.i = rta->cast; break;
  928:       case SA_DEST:	res.val.i = rta->dest; break;
  929:       case SA_IFNAME:	res.val.s = rta->iface ? rta->iface->name : ""; break;
  930:       case SA_IFINDEX:	res.val.i = rta->iface ? rta->iface->index : 0; break;
  931: 
  932:       default:
  933: 	bug("Invalid static attribute access (%x)", res.type);
  934:       }
  935:     }
  936:     break;
  937:   case P('a','S'):
  938:     ACCESS_RTE;
  939:     ONEARG;
  940:     if (what->aux != v1.type)
  941:       runtime( "Attempt to set static attribute to incompatible type" );
  942: 
  943:     f_rta_cow();
  944:     {
  945:       struct rta *rta = (*f_rte)->attrs;
  946: 
  947:       switch (what->a2.i)
  948:       {
  949:       case SA_FROM:
  950: 	rta->from = v1.val.px.ip;
  951: 	break;
  952: 
  953:       case SA_GW:
  954: 	{
  955: 	  ip_addr ip = v1.val.px.ip;
  956: 	  neighbor *n = neigh_find(rta->src->proto, &ip, 0);
  957: 	  if (!n || (n->scope == SCOPE_HOST))
  958: 	    runtime( "Invalid gw address" );
  959: 
  960: 	  rta->dest = RTD_ROUTER;
  961: 	  rta->gw = ip;
  962: 	  rta->iface = n->iface;
  963: 	  rta->nexthops = NULL;
  964: 	  rta->hostentry = NULL;
  965: 	}
  966: 	break;
  967: 
  968:       case SA_SCOPE:
  969: 	rta->scope = v1.val.i;
  970: 	break;
  971: 
  972:       case SA_DEST:
  973: 	i = v1.val.i;
  974: 	if ((i != RTD_BLACKHOLE) && (i != RTD_UNREACHABLE) && (i != RTD_PROHIBIT))
  975: 	  runtime( "Destination can be changed only to blackhole, unreachable or prohibit" );
  976: 
  977: 	rta->dest = i;
  978: 	rta->gw = IPA_NONE;
  979: 	rta->iface = NULL;
  980: 	rta->nexthops = NULL;
  981: 	rta->hostentry = NULL;
  982: 	break;
  983: 
  984:       default:
  985: 	bug("Invalid static attribute access (%x)", res.type);
  986:       }
  987:     }
  988:     break;
  989:   case P('e','a'):	/* Access to extended attributes */
  990:     ACCESS_RTE;
  991:     {
  992:       eattr *e = NULL;
  993:       u16 code = what->a2.i;
  994: 
  995:       if (!(f_flags & FF_FORCE_TMPATTR))
  996: 	e = ea_find((*f_rte)->attrs->eattrs, code);
  997:       if (!e)
  998: 	e = ea_find((*f_tmp_attrs), code);
  999:       if ((!e) && (f_flags & FF_FORCE_TMPATTR))
 1000: 	e = ea_find((*f_rte)->attrs->eattrs, code);
 1001: 
 1002:       if (!e) {
 1003: 	/* A special case: undefined int_set looks like empty int_set */
 1004: 	if ((what->aux & EAF_TYPE_MASK) == EAF_TYPE_INT_SET) {
 1005: 	  res.type = T_CLIST;
 1006: 	  res.val.ad = adata_empty(f_pool, 0);
 1007: 	  break;
 1008: 	}
 1009: 
 1010: 	/* The same special case for ec_set */
 1011: 	if ((what->aux & EAF_TYPE_MASK) == EAF_TYPE_EC_SET) {
 1012: 	  res.type = T_ECLIST;
 1013: 	  res.val.ad = adata_empty(f_pool, 0);
 1014: 	  break;
 1015: 	}
 1016: 
 1017: 	/* The same special case for lc_set */
 1018: 	if ((what->aux & EAF_TYPE_MASK) == EAF_TYPE_LC_SET) {
 1019: 	  res.type = T_LCLIST;
 1020: 	  res.val.ad = adata_empty(f_pool, 0);
 1021: 	  break;
 1022: 	}
 1023: 
 1024: 	/* Undefined value */
 1025: 	res.type = T_VOID;
 1026: 	break;
 1027:       }
 1028: 
 1029:       switch (what->aux & EAF_TYPE_MASK) {
 1030:       case EAF_TYPE_INT:
 1031: 	res.type = T_INT;
 1032: 	res.val.i = e->u.data;
 1033: 	break;
 1034:       case EAF_TYPE_ROUTER_ID:
 1035: 	res.type = T_QUAD;
 1036: 	res.val.i = e->u.data;
 1037: 	break;
 1038:       case EAF_TYPE_OPAQUE:
 1039: 	res.type = T_ENUM_EMPTY;
 1040: 	res.val.i = 0;
 1041: 	break;
 1042:       case EAF_TYPE_IP_ADDRESS:
 1043: 	res.type = T_IP;
 1044: 	struct adata * ad = e->u.ptr;
 1045: 	res.val.px.ip = * (ip_addr *) ad->data;
 1046: 	break;
 1047:       case EAF_TYPE_AS_PATH:
 1048:         res.type = T_PATH;
 1049: 	res.val.ad = e->u.ptr;
 1050: 	break;
 1051:       case EAF_TYPE_BITFIELD:
 1052: 	res.type = T_BOOL;
 1053: 	res.val.i = !!(e->u.data & BITFIELD_MASK(what));
 1054: 	break;
 1055:       case EAF_TYPE_INT_SET:
 1056: 	res.type = T_CLIST;
 1057: 	res.val.ad = e->u.ptr;
 1058: 	break;
 1059:       case EAF_TYPE_EC_SET:
 1060: 	res.type = T_ECLIST;
 1061: 	res.val.ad = e->u.ptr;
 1062: 	break;
 1063:       case EAF_TYPE_LC_SET:
 1064: 	res.type = T_LCLIST;
 1065: 	res.val.ad = e->u.ptr;
 1066: 	break;
 1067:       case EAF_TYPE_UNDEF:
 1068: 	res.type = T_VOID;
 1069: 	break;
 1070:       default:
 1071: 	bug("Unknown type in e,a");
 1072:       }
 1073:     }
 1074:     break;
 1075:   case P('e','S'):
 1076:     ACCESS_RTE;
 1077:     ONEARG;
 1078:     {
 1079:       struct ea_list *l = lp_alloc(f_pool, sizeof(struct ea_list) + sizeof(eattr));
 1080:       u16 code = what->a2.i;
 1081: 
 1082:       l->next = NULL;
 1083:       l->flags = EALF_SORTED;
 1084:       l->count = 1;
 1085:       l->attrs[0].id = code;
 1086:       l->attrs[0].flags = 0;
 1087:       l->attrs[0].type = what->aux | EAF_ORIGINATED;
 1088: 
 1089:       switch (what->aux & EAF_TYPE_MASK) {
 1090:       case EAF_TYPE_INT:
 1091: 	if (v1.type != T_INT)
 1092: 	  runtime( "Setting int attribute to non-int value" );
 1093: 	l->attrs[0].u.data = v1.val.i;
 1094: 	break;
 1095: 
 1096:       case EAF_TYPE_ROUTER_ID:
 1097: #ifndef IPV6
 1098: 	/* IP->Quad implicit conversion */
 1099: 	if (v1.type == T_IP) {
 1100: 	  l->attrs[0].u.data = ipa_to_u32(v1.val.px.ip);
 1101: 	  break;
 1102: 	}
 1103: #endif
 1104: 	/* T_INT for backward compatibility */
 1105: 	if ((v1.type != T_QUAD) && (v1.type != T_INT))
 1106: 	  runtime( "Setting quad attribute to non-quad value" );
 1107: 	l->attrs[0].u.data = v1.val.i;
 1108: 	break;
 1109: 
 1110:       case EAF_TYPE_OPAQUE:
 1111: 	runtime( "Setting opaque attribute is not allowed" );
 1112: 	break;
 1113:       case EAF_TYPE_IP_ADDRESS:
 1114: 	if (v1.type != T_IP)
 1115: 	  runtime( "Setting ip attribute to non-ip value" );
 1116: 	int len = sizeof(ip_addr);
 1117: 	struct adata *ad = lp_alloc(f_pool, sizeof(struct adata) + len);
 1118: 	ad->length = len;
 1119: 	(* (ip_addr *) ad->data) = v1.val.px.ip;
 1120: 	l->attrs[0].u.ptr = ad;
 1121: 	break;
 1122:       case EAF_TYPE_AS_PATH:
 1123: 	if (v1.type != T_PATH)
 1124: 	  runtime( "Setting path attribute to non-path value" );
 1125: 	l->attrs[0].u.ptr = v1.val.ad;
 1126: 	break;
 1127:       case EAF_TYPE_BITFIELD:
 1128: 	if (v1.type != T_BOOL)
 1129: 	  runtime( "Setting bit in bitfield attribute to non-bool value" );
 1130: 	{
 1131: 	  /* First, we have to find the old value */
 1132: 	  eattr *e = NULL;
 1133: 	  if (!(f_flags & FF_FORCE_TMPATTR))
 1134: 	    e = ea_find((*f_rte)->attrs->eattrs, code);
 1135: 	  if (!e)
 1136: 	    e = ea_find((*f_tmp_attrs), code);
 1137: 	  if ((!e) && (f_flags & FF_FORCE_TMPATTR))
 1138: 	    e = ea_find((*f_rte)->attrs->eattrs, code);
 1139: 	  u32 data = e ? e->u.data : 0;
 1140: 
 1141: 	  if (v1.val.i)
 1142: 	    l->attrs[0].u.data = data | BITFIELD_MASK(what);
 1143: 	  else
 1144: 	    l->attrs[0].u.data = data & ~BITFIELD_MASK(what);;
 1145: 	}
 1146: 	break;
 1147:       case EAF_TYPE_INT_SET:
 1148: 	if (v1.type != T_CLIST)
 1149: 	  runtime( "Setting clist attribute to non-clist value" );
 1150: 	l->attrs[0].u.ptr = v1.val.ad;
 1151: 	break;
 1152:       case EAF_TYPE_EC_SET:
 1153: 	if (v1.type != T_ECLIST)
 1154: 	  runtime( "Setting eclist attribute to non-eclist value" );
 1155: 	l->attrs[0].u.ptr = v1.val.ad;
 1156: 	break;
 1157:       case EAF_TYPE_LC_SET:
 1158: 	if (v1.type != T_LCLIST)
 1159: 	  runtime( "Setting lclist attribute to non-lclist value" );
 1160: 	l->attrs[0].u.ptr = v1.val.ad;
 1161: 	break;
 1162:       case EAF_TYPE_UNDEF:
 1163: 	if (v1.type != T_VOID)
 1164: 	  runtime( "Setting void attribute to non-void value" );
 1165: 	l->attrs[0].u.data = 0;
 1166: 	break;
 1167:       default: bug("Unknown type in e,S");
 1168:       }
 1169: 
 1170:       if (!(what->aux & EAF_TEMP) && (!(f_flags & FF_FORCE_TMPATTR))) {
 1171: 	f_rta_cow();
 1172: 	l->next = (*f_rte)->attrs->eattrs;
 1173: 	(*f_rte)->attrs->eattrs = l;
 1174:       } else {
 1175: 	l->next = (*f_tmp_attrs);
 1176: 	(*f_tmp_attrs) = l;
 1177:       }
 1178:     }
 1179:     break;
 1180:   case 'P':
 1181:     ACCESS_RTE;
 1182:     res.type = T_INT;
 1183:     res.val.i = (*f_rte)->pref;
 1184:     break;
 1185:   case P('P','S'):
 1186:     ACCESS_RTE;
 1187:     ONEARG;
 1188:     if (v1.type != T_INT)
 1189:       runtime( "Can't set preference to non-integer" );
 1190:     if (v1.val.i > 0xFFFF)
 1191:       runtime( "Setting preference value out of bounds" );
 1192:     f_rte_cow();
 1193:     (*f_rte)->pref = v1.val.i;
 1194:     break;
 1195:   case 'L':	/* Get length of */
 1196:     ONEARG;
 1197:     res.type = T_INT;
 1198:     switch(v1.type) {
 1199:     case T_PREFIX: res.val.i = v1.val.px.len; break;
 1200:     case T_PATH:   res.val.i = as_path_getlen(v1.val.ad); break;
 1201:     case T_CLIST:  res.val.i = int_set_get_size(v1.val.ad); break;
 1202:     case T_ECLIST: res.val.i = ec_set_get_size(v1.val.ad); break;
 1203:     case T_LCLIST: res.val.i = lc_set_get_size(v1.val.ad); break;
 1204:     default: runtime( "Prefix, path, clist or eclist expected" );
 1205:     }
 1206:     break;
 1207:   case P('c','p'):	/* Convert prefix to ... */
 1208:     ONEARG;
 1209:     if (v1.type != T_PREFIX)
 1210:       runtime( "Prefix expected" );
 1211:     res.type = what->aux;
 1212:     switch(res.type) {
 1213:       /*    case T_INT:	res.val.i = v1.val.px.len; break; Not needed any more */
 1214:     case T_IP: res.val.px.ip = v1.val.px.ip; break;
 1215:     default: bug( "Unknown prefix to conversion" );
 1216:     }
 1217:     break;
 1218:   case P('a','f'):	/* Get first ASN from AS PATH */
 1219:     ONEARG;
 1220:     if (v1.type != T_PATH)
 1221:       runtime( "AS path expected" );
 1222: 
 1223:     as = 0;
 1224:     as_path_get_first(v1.val.ad, &as);
 1225:     res.type = T_INT;
 1226:     res.val.i = as;
 1227:     break;
 1228:   case P('a','l'):	/* Get last ASN from AS PATH */
 1229:     ONEARG;
 1230:     if (v1.type != T_PATH)
 1231:       runtime( "AS path expected" );
 1232: 
 1233:     as = 0;
 1234:     as_path_get_last(v1.val.ad, &as);
 1235:     res.type = T_INT;
 1236:     res.val.i = as;
 1237:     break;
 1238:   case P('a','L'):	/* Get last ASN from non-aggregated part of AS PATH */
 1239:     ONEARG;
 1240:     if (v1.type != T_PATH)
 1241:       runtime( "AS path expected" );
 1242: 
 1243:     res.type = T_INT;
 1244:     res.val.i = as_path_get_last_nonaggregated(v1.val.ad);
 1245:     break;
 1246:   case 'r':
 1247:     ONEARG;
 1248:     res = v1;
 1249:     res.type |= T_RETURN;
 1250:     return res;
 1251:   case P('c','a'): /* CALL: this is special: if T_RETURN and returning some value, mask it out  */
 1252:     ONEARG;
 1253:     res = interpret(what->a2.p);
 1254:     if (res.type == T_RETURN)
 1255:       return res;
 1256:     res.type &= ~T_RETURN;
 1257:     break;
 1258:   case P('c','v'):	/* Clear local variables */
 1259:     for (sym = what->a1.p; sym != NULL; sym = sym->aux2)
 1260:       ((struct f_val *) sym->def)->type = T_VOID;
 1261:     break;
 1262:   case P('S','W'):
 1263:     ONEARG;
 1264:     {
 1265:       struct f_tree *t = find_tree(what->a2.p, v1);
 1266:       if (!t) {
 1267: 	v1.type = T_VOID;
 1268: 	t = find_tree(what->a2.p, v1);
 1269: 	if (!t) {
 1270: 	  debug( "No else statement?\n");
 1271: 	  break;
 1272: 	}
 1273:       }
 1274:       /* It is actually possible to have t->data NULL */
 1275: 
 1276:       res = interpret(t->data);
 1277:       if (res.type & T_RETURN)
 1278: 	return res;
 1279:     }
 1280:     break;
 1281:   case P('i','M'): /* IP.MASK(val) */
 1282:     TWOARGS;
 1283:     if (v2.type != T_INT)
 1284:       runtime( "Integer expected");
 1285:     if (v1.type != T_IP)
 1286:       runtime( "You can mask only IP addresses" );
 1287:     {
 1288:       ip_addr mask = ipa_mkmask(v2.val.i);
 1289:       res.type = T_IP;
 1290:       res.val.px.ip = ipa_and(mask, v1.val.px.ip);
 1291:     }
 1292:     break;
 1293: 
 1294:   case 'E':	/* Create empty attribute */
 1295:     res.type = what->aux;
 1296:     res.val.ad = adata_empty(f_pool, 0);
 1297:     break;
 1298:   case P('A','p'):	/* Path prepend */
 1299:     TWOARGS;
 1300:     if (v1.type != T_PATH)
 1301:       runtime("Can't prepend to non-path");
 1302:     if (v2.type != T_INT)
 1303:       runtime("Can't prepend non-integer");
 1304: 
 1305:     res.type = T_PATH;
 1306:     res.val.ad = as_path_prepend(f_pool, v1.val.ad, v2.val.i);
 1307:     break;
 1308: 
 1309:   case P('C','a'):	/* (Extended) Community list add or delete */
 1310:     TWOARGS;
 1311:     if (v1.type == T_PATH)
 1312:     {
 1313:       struct f_tree *set = NULL;
 1314:       u32 key = 0;
 1315:       int pos;
 1316: 
 1317:       if (v2.type == T_INT)
 1318: 	key = v2.val.i;
 1319:       else if ((v2.type == T_SET) && (v2.val.t->from.type == T_INT))
 1320: 	set = v2.val.t;
 1321:       else
 1322: 	runtime("Can't delete non-integer (set)");
 1323: 
 1324:       switch (what->aux)
 1325:       {
 1326:       case 'a':	runtime("Can't add to path");
 1327:       case 'd':	pos = 0; break;
 1328:       case 'f':	pos = 1; break;
 1329:       default:	bug("unknown Ca operation");
 1330:       }
 1331: 
 1332:       if (pos && !set)
 1333: 	runtime("Can't filter integer");
 1334: 
 1335:       res.type = T_PATH;
 1336:       res.val.ad = as_path_filter(f_pool, v1.val.ad, set, key, pos);
 1337:     }
 1338:     else if (v1.type == T_CLIST)
 1339:     {
 1340:       /* Community (or cluster) list */
 1341:       struct f_val dummy;
 1342:       int arg_set = 0;
 1343:       uint n = 0;
 1344: 
 1345:       if ((v2.type == T_PAIR) || (v2.type == T_QUAD))
 1346: 	n = v2.val.i;
 1347: #ifndef IPV6
 1348:       /* IP->Quad implicit conversion */
 1349:       else if (v2.type == T_IP)
 1350: 	n = ipa_to_u32(v2.val.px.ip);
 1351: #endif
 1352:       else if ((v2.type == T_SET) && clist_set_type(v2.val.t, &dummy))
 1353: 	arg_set = 1;
 1354:       else if (v2.type == T_CLIST)
 1355: 	arg_set = 2;
 1356:       else
 1357: 	runtime("Can't add/delete non-pair");
 1358: 
 1359:       res.type = T_CLIST;
 1360:       switch (what->aux)
 1361:       {
 1362:       case 'a':
 1363: 	if (arg_set == 1)
 1364: 	  runtime("Can't add set");
 1365: 	else if (!arg_set)
 1366: 	  res.val.ad = int_set_add(f_pool, v1.val.ad, n);
 1367: 	else
 1368: 	  res.val.ad = int_set_union(f_pool, v1.val.ad, v2.val.ad);
 1369: 	break;
 1370: 
 1371:       case 'd':
 1372: 	if (!arg_set)
 1373: 	  res.val.ad = int_set_del(f_pool, v1.val.ad, n);
 1374: 	else
 1375: 	  res.val.ad = clist_filter(f_pool, v1.val.ad, v2, 0);
 1376: 	break;
 1377: 
 1378:       case 'f':
 1379: 	if (!arg_set)
 1380: 	  runtime("Can't filter pair");
 1381: 	res.val.ad = clist_filter(f_pool, v1.val.ad, v2, 1);
 1382: 	break;
 1383: 
 1384:       default:
 1385: 	bug("unknown Ca operation");
 1386:       }
 1387:     }
 1388:     else if (v1.type == T_ECLIST)
 1389:     {
 1390:       /* Extended community list */
 1391:       int arg_set = 0;
 1392: 
 1393:       /* v2.val is either EC or EC-set */
 1394:       if ((v2.type == T_SET) && eclist_set_type(v2.val.t))
 1395: 	arg_set = 1;
 1396:       else if (v2.type == T_ECLIST)
 1397: 	arg_set = 2;
 1398:       else if (v2.type != T_EC)
 1399: 	runtime("Can't add/delete non-ec");
 1400: 
 1401:       res.type = T_ECLIST;
 1402:       switch (what->aux)
 1403:       {
 1404:       case 'a':
 1405: 	if (arg_set == 1)
 1406: 	  runtime("Can't add set");
 1407: 	else if (!arg_set)
 1408: 	  res.val.ad = ec_set_add(f_pool, v1.val.ad, v2.val.ec);
 1409: 	else
 1410: 	  res.val.ad = ec_set_union(f_pool, v1.val.ad, v2.val.ad);
 1411: 	break;
 1412: 
 1413:       case 'd':
 1414: 	if (!arg_set)
 1415: 	  res.val.ad = ec_set_del(f_pool, v1.val.ad, v2.val.ec);
 1416: 	else
 1417: 	  res.val.ad = eclist_filter(f_pool, v1.val.ad, v2, 0);
 1418: 	break;
 1419: 
 1420:       case 'f':
 1421: 	if (!arg_set)
 1422: 	  runtime("Can't filter ec");
 1423: 	res.val.ad = eclist_filter(f_pool, v1.val.ad, v2, 1);
 1424: 	break;
 1425: 
 1426:       default:
 1427: 	bug("unknown Ca operation");
 1428:       }
 1429:     }
 1430:     else if (v1.type == T_LCLIST)
 1431:     {
 1432:       /* Large community list */
 1433:       int arg_set = 0;
 1434: 
 1435:       /* v2.val is either LC or LC-set */
 1436:       if ((v2.type == T_SET) && lclist_set_type(v2.val.t))
 1437: 	arg_set = 1;
 1438:       else if (v2.type == T_LCLIST)
 1439: 	arg_set = 2;
 1440:       else if (v2.type != T_LC)
 1441: 	runtime("Can't add/delete non-lc");
 1442: 
 1443:       res.type = T_LCLIST;
 1444:       switch (what->aux)
 1445:       {
 1446:       case 'a':
 1447: 	if (arg_set == 1)
 1448: 	  runtime("Can't add set");
 1449: 	else if (!arg_set)
 1450: 	  res.val.ad = lc_set_add(f_pool, v1.val.ad, v2.val.lc);
 1451: 	else
 1452: 	  res.val.ad = lc_set_union(f_pool, v1.val.ad, v2.val.ad);
 1453: 	break;
 1454: 
 1455:       case 'd':
 1456: 	if (!arg_set)
 1457: 	  res.val.ad = lc_set_del(f_pool, v1.val.ad, v2.val.lc);
 1458: 	else
 1459: 	  res.val.ad = lclist_filter(f_pool, v1.val.ad, v2, 0);
 1460: 	break;
 1461: 
 1462:       case 'f':
 1463: 	if (!arg_set)
 1464: 	  runtime("Can't filter lc");
 1465: 	res.val.ad = lclist_filter(f_pool, v1.val.ad, v2, 1);
 1466: 	break;
 1467: 
 1468:       default:
 1469: 	bug("unknown Ca operation");
 1470:       }
 1471:     }
 1472:     else
 1473:       runtime("Can't add/delete to non-[e|l]clist");
 1474: 
 1475:     break;
 1476: 
 1477:   case P('R','C'):	/* ROA Check */
 1478:     if (what->arg1)
 1479:     {
 1480:       TWOARGS;
 1481:       if ((v1.type != T_PREFIX) || (v2.type != T_INT))
 1482: 	runtime("Invalid argument to roa_check()");
 1483: 
 1484:       as = v2.val.i;
 1485:     }
 1486:     else
 1487:     {
 1488:       ACCESS_RTE;
 1489:       v1.val.px.ip = (*f_rte)->net->n.prefix;
 1490:       v1.val.px.len = (*f_rte)->net->n.pxlen;
 1491: 
 1492:       /* We ignore temporary attributes, probably not a problem here */
 1493:       /* 0x02 is a value of BA_AS_PATH, we don't want to include BGP headers */
 1494:       eattr *e = ea_find((*f_rte)->attrs->eattrs, EA_CODE(EAP_BGP, 0x02));
 1495: 
 1496:       if (!e || e->type != EAF_TYPE_AS_PATH)
 1497: 	runtime("Missing AS_PATH attribute");
 1498: 
 1499:       as_path_get_last(e->u.ptr, &as);
 1500:     }
 1501: 
 1502:     struct roa_table_config *rtc = ((struct f_inst_roa_check *) what)->rtc;
 1503:     if (!rtc->table)
 1504:       runtime("Missing ROA table");
 1505: 
 1506:     res.type = T_ENUM_ROA;
 1507:     res.val.i = roa_check(rtc->table, v1.val.px.ip, v1.val.px.len, as);
 1508:     break;
 1509: 
 1510:   default:
 1511:     bug( "Unknown instruction %d (%c)", what->code, what->code & 0xff);
 1512:   }
 1513:   if (what->next)
 1514:     return interpret(what->next);
 1515:   return res;
 1516: }
 1517: 
 1518: #undef ARG
 1519: #define ARG(x,y) \
 1520: 	if (!i_same(f1->y, f2->y)) \
 1521: 		return 0;
 1522: 
 1523: #define ONEARG ARG(v1, a1.p)
 1524: #define TWOARGS ARG(v1, a1.p) \
 1525: 		ARG(v2, a2.p)
 1526: 
 1527: #define A2_SAME if (f1->a2.i != f2->a2.i) return 0;
 1528: 
 1529: /*
 1530:  * i_same - function that does real comparing of instruction trees, you should call filter_same from outside
 1531:  */
 1532: int
 1533: i_same(struct f_inst *f1, struct f_inst *f2)
 1534: {
 1535:   if ((!!f1) != (!!f2))
 1536:     return 0;
 1537:   if (!f1)
 1538:     return 1;
 1539:   if (f1->aux != f2->aux)
 1540:     return 0;
 1541:   if (f1->code != f2->code)
 1542:     return 0;
 1543:   if (f1 == f2)		/* It looks strange, but it is possible with call rewriting trickery */
 1544:     return 1;
 1545: 
 1546:   switch(f1->code) {
 1547:   case ',': /* fall through */
 1548:   case '+':
 1549:   case '-':
 1550:   case '*':
 1551:   case '/':
 1552:   case '|':
 1553:   case '&':
 1554:   case P('m','p'):
 1555:   case P('m','c'):
 1556:   case P('!','='):
 1557:   case P('=','='):
 1558:   case '<':
 1559:   case P('<','='): TWOARGS; break;
 1560: 
 1561:   case '!': ONEARG; break;
 1562:   case '~': TWOARGS; break;
 1563:   case P('d','e'): ONEARG; break;
 1564: 
 1565:   case P('m','l'):
 1566:     TWOARGS;
 1567:     if (!i_same(INST3(f1).p, INST3(f2).p))
 1568:       return 0;
 1569:     break;
 1570: 
 1571:   case 's':
 1572:     ARG(v2, a2.p);
 1573:     {
 1574:       struct symbol *s1, *s2;
 1575:       s1 = f1->a1.p;
 1576:       s2 = f2->a1.p;
 1577:       if (strcmp(s1->name, s2->name))
 1578: 	return 0;
 1579:       if (s1->class != s2->class)
 1580: 	return 0;
 1581:     }
 1582:     break;
 1583: 
 1584:   case 'c':
 1585:     switch (f1->aux) {
 1586: 
 1587:     case T_PREFIX_SET:
 1588:       if (!trie_same(f1->a2.p, f2->a2.p))
 1589: 	return 0;
 1590:       break;
 1591: 
 1592:     case T_SET:
 1593:       if (!same_tree(f1->a2.p, f2->a2.p))
 1594: 	return 0;
 1595:       break;
 1596: 
 1597:     case T_STRING:
 1598:       if (strcmp(f1->a2.p, f2->a2.p))
 1599: 	return 0;
 1600:       break;
 1601: 
 1602:     default:
 1603:       A2_SAME;
 1604:     }
 1605:     break;
 1606: 
 1607:   case 'C':
 1608:     if (!val_same(* (struct f_val *) f1->a1.p, * (struct f_val *) f2->a1.p))
 1609:       return 0;
 1610:     break;
 1611: 
 1612:   case 'V':
 1613:     if (strcmp((char *) f1->a2.p, (char *) f2->a2.p))
 1614:       return 0;
 1615:     break;
 1616:   case 'p': case 'L': ONEARG; break;
 1617:   case '?': TWOARGS; break;
 1618:   case '0': case 'E': break;
 1619:   case P('p',','): ONEARG; A2_SAME; break;
 1620:   case 'P':
 1621:   case 'a': A2_SAME; break;
 1622:   case P('e','a'): A2_SAME; break;
 1623:   case P('P','S'):
 1624:   case P('a','S'):
 1625:   case P('e','S'): ONEARG; A2_SAME; break;
 1626: 
 1627:   case 'r': ONEARG; break;
 1628:   case P('c','p'): ONEARG; break;
 1629:   case P('c','a'): /* Call rewriting trickery to avoid exponential behaviour */
 1630:              ONEARG;
 1631: 	     if (!i_same(f1->a2.p, f2->a2.p))
 1632: 	       return 0;
 1633: 	     f2->a2.p = f1->a2.p;
 1634: 	     break;
 1635:   case P('c','v'): break; /* internal instruction */
 1636:   case P('S','W'): ONEARG; if (!same_tree(f1->a2.p, f2->a2.p)) return 0; break;
 1637:   case P('i','M'): TWOARGS; break;
 1638:   case P('A','p'): TWOARGS; break;
 1639:   case P('C','a'): TWOARGS; break;
 1640:   case P('a','f'):
 1641:   case P('a','l'):
 1642:   case P('a','L'): ONEARG; break;
 1643:   case P('R','C'):
 1644:     TWOARGS;
 1645:     /* Does not really make sense - ROA check resuls may change anyway */
 1646:     if (strcmp(((struct f_inst_roa_check *) f1)->rtc->name,
 1647: 	       ((struct f_inst_roa_check *) f2)->rtc->name))
 1648:       return 0;
 1649:     break;
 1650:   default:
 1651:     bug( "Unknown instruction %d in same (%c)", f1->code, f1->code & 0xff);
 1652:   }
 1653:   return i_same(f1->next, f2->next);
 1654: }
 1655: 
 1656: /**
 1657:  * f_run - run a filter for a route
 1658:  * @filter: filter to run
 1659:  * @rte: route being filtered, may be modified
 1660:  * @tmp_attrs: temporary attributes, prepared by caller or generated by f_run()
 1661:  * @tmp_pool: all filter allocations go from this pool
 1662:  * @flags: flags
 1663:  *
 1664:  * If filter needs to modify the route, there are several
 1665:  * posibilities. @rte might be read-only (with REF_COW flag), in that
 1666:  * case rw copy is obtained by rte_cow() and @rte is replaced. If
 1667:  * @rte is originally rw, it may be directly modified (and it is never
 1668:  * copied).
 1669:  *
 1670:  * The returned rte may reuse the (possibly cached, cloned) rta, or
 1671:  * (if rta was modificied) contains a modified uncached rta, which
 1672:  * uses parts allocated from @tmp_pool and parts shared from original
 1673:  * rta. There is one exception - if @rte is rw but contains a cached
 1674:  * rta and that is modified, rta in returned rte is also cached.
 1675:  *
 1676:  * Ownership of cached rtas is consistent with rte, i.e.
 1677:  * if a new rte is returned, it has its own clone of cached rta
 1678:  * (and cached rta of read-only source rte is intact), if rte is
 1679:  * modified in place, old cached rta is possibly freed.
 1680:  */
 1681: int
 1682: f_run(struct filter *filter, struct rte **rte, struct ea_list **tmp_attrs, struct linpool *tmp_pool, int flags)
 1683: {
 1684:   if (filter == FILTER_ACCEPT)
 1685:     return F_ACCEPT;
 1686: 
 1687:   if (filter == FILTER_REJECT)
 1688:     return F_REJECT;
 1689: 
 1690:   int rte_cow = ((*rte)->flags & REF_COW);
 1691:   DBG( "Running filter `%s'...", filter->name );
 1692: 
 1693:   f_rte = rte;
 1694:   f_old_rta = NULL;
 1695:   f_tmp_attrs = tmp_attrs;
 1696:   f_pool = tmp_pool;
 1697:   f_flags = flags;
 1698: 
 1699:   LOG_BUFFER_INIT(f_buf);
 1700: 
 1701:   struct f_val res = interpret(filter->root);
 1702: 
 1703:   if (f_old_rta) {
 1704:     /*
 1705:      * Cached rta was modified and f_rte contains now an uncached one,
 1706:      * sharing some part with the cached one. The cached rta should
 1707:      * be freed (if rte was originally COW, f_old_rta is a clone
 1708:      * obtained during rte_cow()).
 1709:      *
 1710:      * This also implements the exception mentioned in f_run()
 1711:      * description. The reason for this is that rta reuses parts of
 1712:      * f_old_rta, and these may be freed during rta_free(f_old_rta).
 1713:      * This is not the problem if rte was COW, because original rte
 1714:      * also holds the same rta.
 1715:      */
 1716:     if (!rte_cow)
 1717:       (*f_rte)->attrs = rta_lookup((*f_rte)->attrs);
 1718: 
 1719:     rta_free(f_old_rta);
 1720:   }
 1721: 
 1722: 
 1723:   if (res.type != T_RETURN) {
 1724:     log_rl(&rl_runtime_err, L_ERR "Filter %s did not return accept nor reject. Make up your mind", filter->name);
 1725:     return F_ERROR;
 1726:   }
 1727:   DBG( "done (%u)\n", res.val.i );
 1728:   return res.val.i;
 1729: }
 1730: 
 1731: /* TODO: perhaps we could integrate f_eval(), f_eval_rte() and f_run() */
 1732: 
 1733: struct f_val
 1734: f_eval_rte(struct f_inst *expr, struct rte **rte, struct linpool *tmp_pool)
 1735: {
 1736:   struct ea_list *tmp_attrs = NULL;
 1737: 
 1738:   f_rte = rte;
 1739:   f_old_rta = NULL;
 1740:   f_tmp_attrs = &tmp_attrs;
 1741:   f_pool = tmp_pool;
 1742:   f_flags = 0;
 1743: 
 1744:   LOG_BUFFER_INIT(f_buf);
 1745: 
 1746:   /* Note that in this function we assume that rte->attrs is private / uncached */
 1747:   struct f_val res = interpret(expr);
 1748: 
 1749:   /* Hack to include EAF_TEMP attributes to the main list */
 1750:   (*rte)->attrs->eattrs = ea_append(tmp_attrs, (*rte)->attrs->eattrs);
 1751: 
 1752:   return res;
 1753: }
 1754: 
 1755: struct f_val
 1756: f_eval(struct f_inst *expr, struct linpool *tmp_pool)
 1757: {
 1758:   f_flags = 0;
 1759:   f_tmp_attrs = NULL;
 1760:   f_rte = NULL;
 1761:   f_pool = tmp_pool;
 1762: 
 1763:   LOG_BUFFER_INIT(f_buf);
 1764: 
 1765:   return interpret(expr);
 1766: }
 1767: 
 1768: uint
 1769: f_eval_int(struct f_inst *expr)
 1770: {
 1771:   /* Called independently in parse-time to eval expressions */
 1772:   struct f_val res = f_eval(expr, cfg_mem);
 1773: 
 1774:   if (res.type != T_INT)
 1775:     cf_error("Integer expression expected");
 1776: 
 1777:   return res.val.i;
 1778: }
 1779: 
 1780: u32
 1781: f_eval_asn(struct f_inst *expr)
 1782: {
 1783:   /* Called as a part of another interpret call, therefore no log_reset() */
 1784:   struct f_val res = interpret(expr);
 1785:   return (res.type == T_INT) ? res.val.i : 0;
 1786: }
 1787: 
 1788: /**
 1789:  * filter_same - compare two filters
 1790:  * @new: first filter to be compared
 1791:  * @old: second filter to be compared, notice that this filter is
 1792:  * damaged while comparing.
 1793:  *
 1794:  * Returns 1 in case filters are same, otherwise 0. If there are
 1795:  * underlying bugs, it will rather say 0 on same filters than say
 1796:  * 1 on different.
 1797:  */
 1798: int
 1799: filter_same(struct filter *new, struct filter *old)
 1800: {
 1801:   if (old == new)	/* Handle FILTER_ACCEPT and FILTER_REJECT */
 1802:     return 1;
 1803:   if (old == FILTER_ACCEPT || old == FILTER_REJECT ||
 1804:       new == FILTER_ACCEPT || new == FILTER_REJECT)
 1805:     return 0;
 1806:   return i_same(new->root, old->root);
 1807: }

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