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 <[email protected]>
Committer: Andrei Pelinescu-Onciul <[email protected]>
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;
 }
 


_______________________________________________
sr-dev mailing list
[email protected]
http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-dev

Reply via email to