X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=filter%2Ff-inst.c;h=e3e0d76d9dafa1fd02342540eb72a77902b10f24;hb=ff2ca10cba9c5a3be690ec1a77a068e23395ef20;hp=f13048332479a92d836e056415f5863071de975f;hpb=c0999a149c223fa9c622552a314c767e6a640bf6;p=thirdparty%2Fbird.git diff --git a/filter/f-inst.c b/filter/f-inst.c index f13048332..e3e0d76d9 100644 --- a/filter/f-inst.c +++ b/filter/f-inst.c @@ -104,7 +104,7 @@ * m4_dnl (103) [[ put it here ]] * m4_dnl ... * m4_dnl if (all arguments are constant) - * m4_dnl (108) [[ put it here ]] + * m4_dnl (108) [[ put it here ]] * m4_dnl } * m4_dnl For writing directly to constructor argument list, use FID_NEW_ARGS. * m4_dnl For computing something in constructor (103), use FID_NEW_BODY. @@ -226,6 +226,9 @@ } INST(FI_AND, 1, 1) { ARG(1,T_BOOL); + ARG_TYPE(2,T_BOOL); + RESULT_TYPE(T_BOOL); + if (v1.val.i) LINE(2,0); else @@ -233,6 +236,9 @@ } INST(FI_OR, 1, 1) { ARG(1,T_BOOL); + ARG_TYPE(2,T_BOOL); + RESULT_TYPE(T_BOOL); + if (!v1.val.i) LINE(2,0); else @@ -253,7 +259,7 @@ ARG_ANY(1); ARG(2, T_INT); - FID_MEMBER(enum ec_subtype, ecs, f1->ecs != f2->ecs, ec subtype %s, ec_subtype_str(item->ecs)); + FID_MEMBER(enum ec_subtype, ecs, f1->ecs != f2->ecs, "ec subtype %s", ec_subtype_str(item->ecs)); int check, ipv4_used; u32 key, val; @@ -308,12 +314,24 @@ case T_PATH_MASK_ITEM: pm->item[i] = vv(i).val.pmi; break; + case T_INT: pm->item[i] = (struct f_path_mask_item) { .asn = vv(i).val.i, .kind = PM_ASN, }; break; + + case T_SET: + if (vv(i).val.t->from.type != T_INT) + runtime("Only integer sets allowed in path mask"); + + pm->item[i] = (struct f_path_mask_item) { + .set = vv(i).val.t, + .kind = PM_ASN_SET, + }; + break; + default: runtime( "Error resolving path mask template: value not an integer" ); } @@ -339,6 +357,8 @@ INST(FI_LT, 2, 1) { ARG_ANY(1); ARG_ANY(2); + ARG_SAME_TYPE(1, 2); + int i = val_compare(&v1, &v2); if (i == F_CMP_ERROR) runtime( "Can't compare values of incompatible types" ); @@ -348,6 +368,8 @@ INST(FI_LTE, 2, 1) { ARG_ANY(1); ARG_ANY(2); + ARG_SAME_TYPE(1, 2); + int i = val_compare(&v1, &v2); if (i == F_CMP_ERROR) runtime( "Can't compare values of incompatible types" ); @@ -404,18 +426,7 @@ NEVER_CONSTANT; ARG_ANY(1); SYMBOL; - - if ((sym->class != (SYM_VARIABLE | v1.type)) && (v1.type != T_VOID)) - { - /* IP->Quad implicit conversion */ - if ((sym->class == (SYM_VARIABLE | T_QUAD)) && val_is_ip4(&v1)) - v1 = (struct f_val) { - .type = T_QUAD, - .val.i = ipa_to_u32(v1.val.ip), - }; - else - runtime( "Assigning to variable of incompatible type" ); - } + ARG_TYPE(1, sym->class & 0xff); fstk->vstk[curline.vbase + sym->offset] = v1; } @@ -423,6 +434,7 @@ INST(FI_VAR_GET, 0, 1) { SYMBOL; NEVER_CONSTANT; + RESULT_TYPE(sym->class & 0xff); RESULT_VAL(fstk->vstk[curline.vbase + sym->offset]); } @@ -431,10 +443,11 @@ struct f_val, val, [[ !val_same(&(f1->val), &(f2->val)) ]], - value %s, + "value %s", val_dump(&(item->val)) ); + RESULT_TYPE(val.type); RESULT_VAL(val); } @@ -455,23 +468,24 @@ val_format(&(vv(i)), &fs->buf); } - INST(FI_DIE, 0, 0) { + INST(FI_FLUSH, 0, 0) { NEVER_CONSTANT; - FID_MEMBER(enum filter_return, fret, f1->fret != f2->fret, %s, filter_return_str(item->fret)); - - if (fs->buf.start < fs->buf.pos) + if (!(fs->flags & FF_SILENT)) + /* After log_commit, the buffer is reset */ log_commit(*L_INFO, &fs->buf); + } + + INST(FI_DIE, 0, 0) { + NEVER_CONSTANT; + FID_MEMBER(enum filter_return, fret, f1->fret != f2->fret, "%s", filter_return_str(item->fret)); switch (whati->fret) { case F_QUITBIRD: die( "Filter asked me to die" ); - case F_ACCEPT: - /* Should take care about turning ACCEPT into MODIFY */ + case F_ACCEPT: /* Should take care about turning ACCEPT into MODIFY */ case F_ERROR: - case F_REJECT: /* FIXME (noncritical) Should print complete route along with reason to reject route */ + case F_REJECT: /* Maybe print complete route along with reason to reject route? */ return fret; /* We have to return now, no more processing. */ - case F_NOP: - break; default: bug( "unknown return type: Can't happen"); } @@ -505,8 +519,7 @@ ACCESS_RTE; ARG_ANY(1); STATIC_ATTR; - if (sa.f_type != v1.type) - runtime( "Attempt to set static attribute to incompatible type" ); + ARG_TYPE(1, sa.f_type); f_rta_cow(fs); { @@ -575,31 +588,32 @@ DYNAMIC_ATTR; ACCESS_RTE; ACCESS_EATTRS; + RESULT_TYPE(da.f_type); { eattr *e = ea_find(*fs->eattrs, da.ea_code); if (!e) { /* A special case: undefined as_path looks like empty as_path */ if (da.type == EAF_TYPE_AS_PATH) { - RESULT(T_PATH, ad, &null_adata); + RESULT_(T_PATH, ad, &null_adata); break; } /* The same special case for int_set */ if (da.type == EAF_TYPE_INT_SET) { - RESULT(T_CLIST, ad, &null_adata); + RESULT_(T_CLIST, ad, &null_adata); break; } /* The same special case for ec_set */ if (da.type == EAF_TYPE_EC_SET) { - RESULT(T_ECLIST, ad, &null_adata); + RESULT_(T_ECLIST, ad, &null_adata); break; } /* The same special case for lc_set */ if (da.type == EAF_TYPE_LC_SET) { - RESULT(T_LCLIST, ad, &null_adata); + RESULT_(T_LCLIST, ad, &null_adata); break; } @@ -610,31 +624,31 @@ switch (e->type & EAF_TYPE_MASK) { case EAF_TYPE_INT: - RESULT(da.f_type, i, e->u.data); + RESULT_(da.f_type, i, e->u.data); break; case EAF_TYPE_ROUTER_ID: - RESULT(T_QUAD, i, e->u.data); + RESULT_(T_QUAD, i, e->u.data); break; case EAF_TYPE_OPAQUE: - RESULT(T_ENUM_EMPTY, i, 0); + RESULT_(T_ENUM_EMPTY, i, 0); break; case EAF_TYPE_IP_ADDRESS: - RESULT(T_IP, ip, *((ip_addr *) e->u.ptr->data)); + RESULT_(T_IP, ip, *((ip_addr *) e->u.ptr->data)); break; case EAF_TYPE_AS_PATH: - RESULT(T_PATH, ad, e->u.ptr); + RESULT_(T_PATH, ad, e->u.ptr); break; case EAF_TYPE_BITFIELD: - RESULT(T_BOOL, i, !!(e->u.data & (1u << da.bit))); + RESULT_(T_BOOL, i, !!(e->u.data & (1u << da.bit))); break; case EAF_TYPE_INT_SET: - RESULT(T_CLIST, ad, e->u.ptr); + RESULT_(T_CLIST, ad, e->u.ptr); break; case EAF_TYPE_EC_SET: - RESULT(T_ECLIST, ad, e->u.ptr); + RESULT_(T_ECLIST, ad, e->u.ptr); break; case EAF_TYPE_LC_SET: - RESULT(T_LCLIST, ad, e->u.ptr); + RESULT_(T_LCLIST, ad, e->u.ptr); break; case EAF_TYPE_UNDEF: RESULT_VOID; @@ -650,6 +664,7 @@ ACCESS_EATTRS; ARG_ANY(1); DYNAMIC_ATTR; + ARG_TYPE(1, da.f_type); { struct ea_list *l = lp_alloc(fs->pool, sizeof(struct ea_list) + sizeof(eattr)); @@ -662,20 +677,7 @@ switch (da.type) { case EAF_TYPE_INT: - if (v1.type != da.f_type) - runtime( "Setting int attribute to non-int value" ); - l->attrs[0].u.data = v1.val.i; - break; - case EAF_TYPE_ROUTER_ID: - /* IP->Quad implicit conversion */ - if (val_is_ip4(&v1)) { - l->attrs[0].u.data = ipa_to_u32(v1.val.ip); - break; - } - /* T_INT for backward compatibility */ - if ((v1.type != T_QUAD) && (v1.type != T_INT)) - runtime( "Setting quad attribute to non-quad value" ); l->attrs[0].u.data = v1.val.i; break; @@ -683,9 +685,7 @@ runtime( "Setting opaque attribute is not allowed" ); break; - case EAF_TYPE_IP_ADDRESS: - if (v1.type != T_IP) - runtime( "Setting ip attribute to non-ip value" ); + case EAF_TYPE_IP_ADDRESS:; int len = sizeof(ip_addr); struct adata *ad = lp_alloc(fs->pool, sizeof(struct adata) + len); ad->length = len; @@ -694,14 +694,13 @@ break; case EAF_TYPE_AS_PATH: - if (v1.type != T_PATH) - runtime( "Setting path attribute to non-path value" ); + case EAF_TYPE_INT_SET: + case EAF_TYPE_EC_SET: + case EAF_TYPE_LC_SET: l->attrs[0].u.ptr = v1.val.ad; break; case EAF_TYPE_BITFIELD: - if (v1.type != T_BOOL) - runtime( "Setting bit in bitfield attribute to non-bool value" ); { /* First, we have to find the old value */ eattr *e = ea_find(*fs->eattrs, da.ea_code); @@ -714,24 +713,6 @@ } break; - case EAF_TYPE_INT_SET: - if (v1.type != T_CLIST) - runtime( "Setting clist attribute to non-clist value" ); - l->attrs[0].u.ptr = v1.val.ad; - break; - - case EAF_TYPE_EC_SET: - if (v1.type != T_ECLIST) - runtime( "Setting eclist attribute to non-eclist value" ); - l->attrs[0].u.ptr = v1.val.ad; - break; - - case EAF_TYPE_LC_SET: - if (v1.type != T_LCLIST) - runtime( "Setting lclist attribute to non-lclist value" ); - l->attrs[0].u.ptr = v1.val.ad; - break; - default: bug("Unknown dynamic attribute type"); } @@ -790,18 +771,76 @@ } } - INST(FI_SADR_SRC, 1, 1) { /* Get SADR src prefix */ + INST(FI_NET_SRC, 1, 1) { /* Get src prefix */ ARG(1, T_NET); - if (!net_is_sadr(v1.val.net)) - runtime( "SADR expected" ); - net_addr_ip6_sadr *net = (void *) v1.val.net; + net_addr_union *net = (void *) v1.val.net; net_addr *src = falloc(sizeof(net_addr_ip6)); - net_fill_ip6(src, net->src_prefix, net->src_pxlen); + const byte *part; + + switch(v1.val.net->type) { + case NET_FLOW4: + part = flow4_get_part(&net->flow4, FLOW_TYPE_SRC_PREFIX); + if (part) + net_fill_ip4(src, flow_read_ip4_part(part), flow_read_pxlen(part)); + else + net_fill_ip4(src, IP4_NONE, 0); + break; + + case NET_FLOW6: + part = flow6_get_part(&net->flow6, FLOW_TYPE_SRC_PREFIX); + if (part) + net_fill_ip6(src, flow_read_ip6_part(part), flow_read_pxlen(part)); + else + net_fill_ip6(src, IP6_NONE, 0); + break; + + case NET_IP6_SADR: + net_fill_ip6(src, net->ip6_sadr.src_prefix, net->ip6_sadr.src_pxlen); + break; + + default: + runtime( "Flow or SADR expected" ); + } RESULT(T_NET, net, src); } + INST(FI_NET_DST, 1, 1) { /* Get dst prefix */ + ARG(1, T_NET); + + net_addr_union *net = (void *) v1.val.net; + net_addr *dst = falloc(sizeof(net_addr_ip6)); + const byte *part; + + switch(v1.val.net->type) { + case NET_FLOW4: + part = flow4_get_part(&net->flow4, FLOW_TYPE_DST_PREFIX); + if (part) + net_fill_ip4(dst, flow_read_ip4_part(part), flow_read_pxlen(part)); + else + net_fill_ip4(dst, IP4_NONE, 0); + break; + + case NET_FLOW6: + part = flow6_get_part(&net->flow6, FLOW_TYPE_DST_PREFIX); + if (part) + net_fill_ip6(dst, flow_read_ip6_part(part), flow_read_pxlen(part)); + else + net_fill_ip6(dst, IP6_NONE, 0); + break; + + case NET_IP6_SADR: + net_fill_ip6(dst, net->ip6_sadr.dst_prefix, net->ip6_sadr.dst_pxlen); + break; + + default: + runtime( "Flow or SADR expected" ); + } + + RESULT(T_NET, net, dst); + } + INST(FI_ROA_MAXLEN, 1, 1) { /* Get ROA max prefix length */ ARG(1, T_NET); if (!net_is_roa(v1.val.net)) @@ -836,14 +875,14 @@ INST(FI_AS_PATH_FIRST, 1, 1) { /* Get first ASN from AS PATH */ ARG(1, T_PATH); - int as = 0; + u32 as = 0; as_path_get_first(v1.val.ad, &as); RESULT(T_INT, i, as); } INST(FI_AS_PATH_LAST, 1, 1) { /* Get last ASN from AS PATH */ ARG(1, T_PATH); - int as = 0; + u32 as = 0; as_path_get_last(v1.val.ad, &as); RESULT(T_INT, i, as); } @@ -884,6 +923,11 @@ NEVER_CONSTANT; SYMBOL; + FID_SAME_BODY() + if (!(f2->sym->flags & SYM_FLAG_SAME)) + return 0; + FID_INTERPRET_BODY() + /* Push the body on stack */ LINEX(sym->function); curline.emask |= FE_RETURN; @@ -909,7 +953,7 @@ INST(FI_SWITCH, 1, 0) { ARG_ANY(1); - FID_MEMBER(struct f_tree *, tree, [[!same_tree(f1->tree, f2->tree)]], tree %p, item->tree); + FID_MEMBER(struct f_tree *, tree, [[!same_tree(f1->tree, f2->tree)]], "tree %p", item->tree); const struct f_tree *t = find_tree(tree, &v1); if (!t) { @@ -942,6 +986,8 @@ INST(FI_CLIST_ADD, 2, 1) { /* (Extended) Community list add */ ARG_ANY(1); ARG_ANY(2); + RESULT_TYPE(f1->type); + if (v1.type == T_PATH) runtime("Can't add to path"); @@ -951,14 +997,14 @@ struct f_val dummy; if ((v2.type == T_PAIR) || (v2.type == T_QUAD)) - RESULT(T_CLIST, ad, [[ int_set_add(fpool, v1.val.ad, v2.val.i) ]]); + RESULT_(T_CLIST, ad, [[ int_set_add(fpool, v1.val.ad, v2.val.i) ]]); /* IP->Quad implicit conversion */ else if (val_is_ip4(&v2)) - RESULT(T_CLIST, ad, [[ int_set_add(fpool, v1.val.ad, ipa_to_u32(v2.val.ip)) ]]); + RESULT_(T_CLIST, ad, [[ int_set_add(fpool, v1.val.ad, ipa_to_u32(v2.val.ip)) ]]); else if ((v2.type == T_SET) && clist_set_type(v2.val.t, &dummy)) runtime("Can't add set"); else if (v2.type == T_CLIST) - RESULT(T_CLIST, ad, [[ int_set_union(fpool, v1.val.ad, v2.val.ad) ]]); + RESULT_(T_CLIST, ad, [[ int_set_union(fpool, v1.val.ad, v2.val.ad) ]]); else runtime("Can't add non-pair"); } @@ -969,11 +1015,11 @@ if ((v2.type == T_SET) && eclist_set_type(v2.val.t)) runtime("Can't add set"); else if (v2.type == T_ECLIST) - RESULT(T_ECLIST, ad, [[ ec_set_union(fpool, v1.val.ad, v2.val.ad) ]]); + RESULT_(T_ECLIST, ad, [[ ec_set_union(fpool, v1.val.ad, v2.val.ad) ]]); else if (v2.type != T_EC) runtime("Can't add non-ec"); else - RESULT(T_ECLIST, ad, [[ ec_set_add(fpool, v1.val.ad, v2.val.ec) ]]); + RESULT_(T_ECLIST, ad, [[ ec_set_add(fpool, v1.val.ad, v2.val.ec) ]]); } else if (v1.type == T_LCLIST) @@ -982,11 +1028,11 @@ if ((v2.type == T_SET) && lclist_set_type(v2.val.t)) runtime("Can't add set"); else if (v2.type == T_LCLIST) - RESULT(T_LCLIST, ad, [[ lc_set_union(fpool, v1.val.ad, v2.val.ad) ]]); + RESULT_(T_LCLIST, ad, [[ lc_set_union(fpool, v1.val.ad, v2.val.ad) ]]); else if (v2.type != T_LC) runtime("Can't add non-lc"); else - RESULT(T_LCLIST, ad, [[ lc_set_add(fpool, v1.val.ad, v2.val.lc) ]]); + RESULT_(T_LCLIST, ad, [[ lc_set_add(fpool, v1.val.ad, v2.val.lc) ]]); } @@ -997,6 +1043,8 @@ INST(FI_CLIST_DEL, 2, 1) { /* (Extended) Community list add or delete */ ARG_ANY(1); ARG_ANY(2); + RESULT_TYPE(f1->type); + if (v1.type == T_PATH) { const struct f_tree *set = NULL; @@ -1009,7 +1057,7 @@ else runtime("Can't delete non-integer (set)"); - RESULT(T_PATH, ad, [[ as_path_filter(fpool, v1.val.ad, set, key, 0) ]]); + RESULT_(T_PATH, ad, [[ as_path_filter(fpool, v1.val.ad, set, key, 0) ]]); } else if (v1.type == T_CLIST) @@ -1018,12 +1066,12 @@ struct f_val dummy; if ((v2.type == T_PAIR) || (v2.type == T_QUAD)) - RESULT(T_CLIST, ad, [[ int_set_del(fpool, v1.val.ad, v2.val.i) ]]); + RESULT_(T_CLIST, ad, [[ int_set_del(fpool, v1.val.ad, v2.val.i) ]]); /* IP->Quad implicit conversion */ else if (val_is_ip4(&v2)) - RESULT(T_CLIST, ad, [[ int_set_del(fpool, v1.val.ad, ipa_to_u32(v2.val.ip)) ]]); + RESULT_(T_CLIST, ad, [[ int_set_del(fpool, v1.val.ad, ipa_to_u32(v2.val.ip)) ]]); else if ((v2.type == T_SET) && clist_set_type(v2.val.t, &dummy) || (v2.type == T_CLIST)) - RESULT(T_CLIST, ad, [[ clist_filter(fpool, v1.val.ad, &v2, 0) ]]); + RESULT_(T_CLIST, ad, [[ clist_filter(fpool, v1.val.ad, &v2, 0) ]]); else runtime("Can't delete non-pair"); } @@ -1032,22 +1080,22 @@ { /* v2.val is either EC or EC-set */ if ((v2.type == T_SET) && eclist_set_type(v2.val.t) || (v2.type == T_ECLIST)) - RESULT(T_ECLIST, ad, [[ eclist_filter(fpool, v1.val.ad, &v2, 0) ]]); + RESULT_(T_ECLIST, ad, [[ eclist_filter(fpool, v1.val.ad, &v2, 0) ]]); else if (v2.type != T_EC) runtime("Can't delete non-ec"); else - RESULT(T_ECLIST, ad, [[ ec_set_del(fpool, v1.val.ad, v2.val.ec) ]]); + RESULT_(T_ECLIST, ad, [[ ec_set_del(fpool, v1.val.ad, v2.val.ec) ]]); } else if (v1.type == T_LCLIST) { /* v2.val is either LC or LC-set */ if ((v2.type == T_SET) && lclist_set_type(v2.val.t) || (v2.type == T_LCLIST)) - RESULT(T_LCLIST, ad, [[ lclist_filter(fpool, v1.val.ad, &v2, 0) ]]); + RESULT_(T_LCLIST, ad, [[ lclist_filter(fpool, v1.val.ad, &v2, 0) ]]); else if (v2.type != T_LC) runtime("Can't delete non-lc"); else - RESULT(T_LCLIST, ad, [[ lc_set_del(fpool, v1.val.ad, v2.val.lc) ]]); + RESULT_(T_LCLIST, ad, [[ lc_set_del(fpool, v1.val.ad, v2.val.lc) ]]); } else @@ -1057,12 +1105,14 @@ INST(FI_CLIST_FILTER, 2, 1) { /* (Extended) Community list add or delete */ ARG_ANY(1); ARG_ANY(2); + RESULT_TYPE(f1->type); + if (v1.type == T_PATH) { u32 key = 0; if ((v2.type == T_SET) && (v2.val.t->from.type == T_INT)) - RESULT(T_PATH, ad, [[ as_path_filter(fpool, v1.val.ad, v2.val.t, key, 1) ]]); + RESULT_(T_PATH, ad, [[ as_path_filter(fpool, v1.val.ad, v2.val.t, key, 1) ]]); else runtime("Can't filter integer"); } @@ -1073,7 +1123,7 @@ struct f_val dummy; if ((v2.type == T_SET) && clist_set_type(v2.val.t, &dummy) || (v2.type == T_CLIST)) - RESULT(T_CLIST, ad, [[ clist_filter(fpool, v1.val.ad, &v2, 1) ]]); + RESULT_(T_CLIST, ad, [[ clist_filter(fpool, v1.val.ad, &v2, 1) ]]); else runtime("Can't filter pair"); } @@ -1082,7 +1132,7 @@ { /* v2.val is either EC or EC-set */ if ((v2.type == T_SET) && eclist_set_type(v2.val.t) || (v2.type == T_ECLIST)) - RESULT(T_ECLIST, ad, [[ eclist_filter(fpool, v1.val.ad, &v2, 1) ]]); + RESULT_(T_ECLIST, ad, [[ eclist_filter(fpool, v1.val.ad, &v2, 1) ]]); else runtime("Can't filter ec"); } @@ -1091,7 +1141,7 @@ { /* v2.val is either LC or LC-set */ if ((v2.type == T_SET) && lclist_set_type(v2.val.t) || (v2.type == T_LCLIST)) - RESULT(T_LCLIST, ad, [[ lclist_filter(fpool, v1.val.ad, &v2, 1) ]]); + RESULT_(T_LCLIST, ad, [[ lclist_filter(fpool, v1.val.ad, &v2, 1) ]]); else runtime("Can't filter lc"); } @@ -1161,7 +1211,7 @@ NEVER_CONSTANT; ARG(1, T_BOOL); - FID_MEMBER(char *, s, [[strcmp(f1->s, f2->s)]], string %s, item->s); + FID_MEMBER(char *, s, [[strcmp(f1->s, f2->s)]], "string %s", item->s); ASSERT(s);