Module: sip-router
Branch: master
Commit: e085834f0ea38a52bca926c2e83cf1f0d6fc4bae
URL:
http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=e085834…
Author: Andrei Pelinescu-Onciul <andrei(a)iptel.org>
Committer: Andrei Pelinescu-Onciul <andrei(a)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;
}