Annotation of embedaddon/bird/filter/filter.c, revision 1.1.1.1

1.1       misho       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>