Module: sip-router Branch: master Commit: e085834f0ea38a52bca926c2e83cf1f0d6fc4bae URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=e085834f...
Author: Andrei Pelinescu-Onciul andrei@iptel.org Committer: Andrei Pelinescu-Onciul andrei@iptel.org Date: Fri Jun 18 22:13:01 2010 +0200
core: network addresses in ip rve comparisons
ip address comparison with rvalue expressions support now network type addresses (ip/mask). E.g.: $net = "10.0.0.0" $mask = "255.0.0.0" if (src_ip == $net+"/"+$mask) ....
---
NEWS | 3 + route.c | 201 ++++++++++++++++++++++++++++++++++++++++++++++----------------- 2 files changed, 150 insertions(+), 54 deletions(-)
diff --git a/NEWS b/NEWS index de353af..0112243 100644 --- a/NEWS +++ b/NEWS @@ -6,6 +6,9 @@ $Id$ sip-router 3.1 chages
core: + - networks addresses support in ip comparisons (src_ip, dst_ip, to_ip) + with strings or rvalue expressions. + E.g.: $ip=10.0.0.0; if (src_ip == $ip +"/8") .... - onreply_route {...} is now equivalent with onreply_route[0] {...} - global, per protocol blacklist ignore masks (via extended send_flags). See dst_blacklist_udp_imask a.s.o (dst_blacklist_*_imask). diff --git a/route.c b/route.c index b1cd14c..9a8f649 100644 --- a/route.c +++ b/route.c @@ -50,14 +50,15 @@ * unless the operator is DIFF_OP (Miklos) * 2008-12-03 fixups for rvalues in assignments (andrei) * 2009-05-04 switched IF_T to rval_expr (andrei) + * 2010-06-18 ip comparison (comp_ip()) normalizes strings to + * ip/netmask (andrei) */
-/*! - * \file - * \brief SIP-router core :: - * \ingroup core - * Module: \ref core +/** expression evaluation, route fixups and routing lists. + * @file route.c + * @ingroup core + * Module: @ref core */
#include <stdlib.h> @@ -1213,7 +1214,8 @@ inline static int comp_str(int op, str* left, int rtype, goto error; } break; - case STRING_ST: + case STRING_ST: /* strings are stored as {asciiz, len } */ + case STR_ST: right=&r->str; break; case NUMBER_ST: @@ -1517,7 +1519,19 @@ inline static int comp_ip(int op, struct ip_addr* ip, int rtype, char ** h; int ret; str tmp; + str* right; + struct net net; + union exp_op r_expop; + struct rvalue* rv; + struct rval_cache rv_cache; + avp_t* avp; + int_str val; + pv_value_t pval; + int destroy_pval;
+ right=0; /* warning fix */ + rv=0; + destroy_pval=0; ret=-1; switch(rtype){ case NET_ST: @@ -1531,66 +1545,145 @@ inline static int comp_ip(int op, struct ip_addr* ip, int rtype, default: goto error_op; } - break; - case AVP_ST: - case STRING_ST: - case RE_ST: - case RVE_ST: - case SELECT_ST: - switch(op){ - case EQUAL_OP: - case MATCH_OP: - /* 1: compare with ip2str*/ - ret=comp_string(op, ip_addr2a(ip), rtype, r, msg, ctx); - if (likely(ret==1)) break; - /* 2: resolve (name) & compare w/ all the ips */ - if (rtype==STRING_ST){ - he=resolvehost(r->str.s); - if (he==0){ - DBG("comp_ip: could not resolve %s\n", - r->str.s); - }else if (he->h_addrtype==ip->af){ - for(h=he->h_addr_list;(ret!=1)&& (*h); h++){ - ret=(memcmp(ip->u.addr, *h, ip->len)==0); - } - if (ret==1) break; - } - } - /* 3: (slow) rev dns the address - * and compare with all the aliases - * !!??!! review: remove this? */ - if (unlikely((received_dns & DO_REV_DNS) && - ((he=rev_resolvehost(ip))!=0) )){ - /* compare with primary host name */ - ret=comp_string(op, he->h_name, rtype, r, msg, ctx); - /* compare with all the aliases */ - for(h=he->h_aliases; (ret!=1) && (*h); h++){ - ret=comp_string(op, *h, rtype, r, msg, ctx); - } - }else{ - ret=0; - } - break; - case DIFF_OP: - ret=(comp_ip(EQUAL_OP, ip, rtype, r, msg, ctx) > 0) ?0:1; - break; - default: - goto error_op; - } - break; + return ret; /* exit directly */ case MYSELF_ST: /* check if it's one of our addresses*/ tmp.s=ip_addr2a(ip); tmp.len=strlen(tmp.s); ret=check_self_op(op, &tmp, 0); + return ret; + case STRING_ST: + case STR_ST: + right=&r->str; + break; + case RVE_ST: + rval_cache_init(&rv_cache); + rv=rval_expr_eval(ctx, msg, r->param); + if (unlikely (rv==0)) + return (op==DIFF_OP); /* not found or error*/ + if (unlikely(rval_get_tmp_str(ctx, msg, &tmp, rv, 0, &rv_cache) + < 0)){ + goto error; + } + right = &tmp; + break; + case AVP_ST: + /* we can still have AVP_ST due to the RVE optimisations + (if a RVE == $avp => rve wrapper removed => pure avp) */ + avp = search_avp_by_index(r->attr->type, r->attr->name, + &val, r->attr->index); + if (likely(avp && (avp->flags & AVP_VAL_STR))) right = &val.s; + else return (op == DIFF_OP); + break; + case SELECT_ST: + /* see AVP_ST comment and s/AVP_ST/SELECT_ST/ */ + ret = run_select(&tmp, r->select, msg); + if (unlikely(ret != 0)) + return (op == DIFF_OP); /* Not found or error */ + right = &tmp; + break; + case PVAR_ST: + /* see AVP_ST comment and s/AVP_ST/PVAR_ST/ */ + memset(&pval, 0, sizeof(pv_value_t)); + if (unlikely(pv_get_spec_value(msg, r->param, &pval)!=0)){ + return (op == DIFF_OP); /* error, not found => false */ + } + destroy_pval=1; + if (likely(pval.flags & PV_VAL_STR)){ + right=&pval.rs; + }else{ + pv_value_destroy(&pval); + return (op == DIFF_OP); /* not found or invalid type */ + } break; + case RE_ST: + if (unlikely(op != MATCH_OP)) + goto error_op; + /* 1: compare with ip2str*/ + ret=comp_string(op, ip_addr2a(ip), rtype, r, msg, ctx); + if (likely(ret==1)) + return ret; + /* 3: (slow) rev dns the address + * and compare with all the aliases + * !!??!! review: remove this? */ + if (unlikely((received_dns & DO_REV_DNS) && + ((he=rev_resolvehost(ip))!=0) )){ + /* compare with primary host name */ + ret=comp_string(op, he->h_name, rtype, r, msg, ctx); + /* compare with all the aliases */ + for(h=he->h_aliases; (ret!=1) && (*h); h++){ + ret=comp_string(op, *h, rtype, r, msg, ctx); + } + }else{ + ret=0; + } + return ret; default: LOG(L_CRIT, "BUG: comp_ip: invalid type for " " src_ip or dst_ip (%d)\n", rtype); ret=-1; } + /* here "right" is set to the str we compare with */ + r_expop.str=*right; + switch(op){ + case EQUAL_OP: + case MATCH_OP: + /* 0: try if ip or network (ip/mask) */ + if (mk_net_str(&net, right) == 0) { + ret=(matchnet(ip, &net)==1); + break; + } + /* 1: compare with ip2str*/ + /* + ret=comp_string(op, ip_addr2a(ip), STR_ST, &r_expop, msg, ctx); + if (likely(ret==1)) break; + */ + /* 2: resolve (name) & compare w/ all the ips */ + he=resolvehost(right->s); + if (he==0){ + DBG("comp_ip: could not resolve %s\n", r->str.s); + }else if (he->h_addrtype==ip->af){ + for(h=he->h_addr_list;(ret!=1)&& (*h); h++){ + ret=(memcmp(ip->u.addr, *h, ip->len)==0); + } + if (ret==1) break; + } + /* 3: (slow) rev dns the address + * and compare with all the aliases + * !!??!! review: remove this? */ + if (unlikely((received_dns & DO_REV_DNS) && + ((he=rev_resolvehost(ip))!=0) )){ + /* compare with primary host name */ + ret=comp_string(op, he->h_name, STR_ST, &r_expop, msg, ctx); + /* compare with all the aliases */ + for(h=he->h_aliases; (ret!=1) && (*h); h++){ + ret=comp_string(op, *h, STR_ST, &r_expop, msg, ctx); + } + }else{ + ret=0; + } + break; + case DIFF_OP: + ret=(comp_ip(EQUAL_OP, ip, STR_ST, &r_expop, msg, ctx) > 0)?0:1; + break; + default: + goto error_op; + } + if (rv){ + rval_cache_clean(&rv_cache); + rval_destroy(rv); + } + if (destroy_pval) + pv_value_destroy(&pval); return ret; error_op: - LOG(L_CRIT, "BUG: comp_ip: invalid operator %d\n", op); + LOG(L_CRIT, "BUG: comp_ip: invalid operator %d for type %d\n", op, rtype); +error: + if (unlikely(rv)){ + rval_cache_clean(&rv_cache); + rval_destroy(rv); + } + if (destroy_pval) + pv_value_destroy(&pval); return -1; }