[sr-dev] git:master: core: network addresses in ip rve comparisons

Andrei Pelinescu-Onciul andrei at iptel.org
Fri Jun 18 22:34:55 CEST 2010


Module: sip-router
Branch: master
Commit: e085834f0ea38a52bca926c2e83cf1f0d6fc4bae
URL:    http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=e085834f0ea38a52bca926c2e83cf1f0d6fc4bae

Author: Andrei Pelinescu-Onciul <andrei at iptel.org>
Committer: Andrei Pelinescu-Onciul <andrei at 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;
 }
 




More information about the sr-dev mailing list