Browse code

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)
....

Andrei Pelinescu-Onciul authored on 18/06/2010 20:13:01
Showing 2 changed files
... ...
@@ -6,6 +6,9 @@ $Id$
6 6
 sip-router 3.1 chages
7 7
 
8 8
 core:
9
+  - networks addresses support in ip comparisons (src_ip, dst_ip, to_ip)
10
+    with strings or rvalue expressions.
11
+    E.g.: $ip=10.0.0.0;  if (src_ip == $ip +"/8") ....
9 12
   - onreply_route {...} is now equivalent with onreply_route[0] {...}
10 13
   - global, per protocol blacklist ignore masks (via extended send_flags).
11 14
     See dst_blacklist_udp_imask a.s.o (dst_blacklist_*_imask).
... ...
@@ -50,14 +50,15 @@
50 50
  *  		unless the operator is DIFF_OP (Miklos)
51 51
  *  2008-12-03  fixups for rvalues in assignments (andrei)
52 52
  *  2009-05-04  switched IF_T to rval_expr (andrei)
53
+ *  2010-06-18  ip comparison (comp_ip()) normalizes strings to
54
+ *              ip/netmask  (andrei)
53 55
  */
54 56
 
55 57
 
56
-/*!
57
- * \file
58
- * \brief SIP-router core :: 
59
- * \ingroup core
60
- * Module: \ref core
58
+/** expression evaluation, route fixups and routing lists.
59
+ * @file route.c
60
+ * @ingroup core
61
+ * Module: @ref core
61 62
  */
62 63
 
63 64
 #include <stdlib.h>
... ...
@@ -1213,7 +1214,8 @@ inline static int comp_str(int op, str* left, int rtype,
1213 1213
 				goto error;
1214 1214
 			}
1215 1215
 			break;
1216
-		case STRING_ST:
1216
+		case STRING_ST: /* strings are stored as {asciiz, len } */
1217
+		case STR_ST:
1217 1218
 			right=&r->str;
1218 1219
 			break;
1219 1220
 		case NUMBER_ST:
... ...
@@ -1517,7 +1519,19 @@ inline static int comp_ip(int op, struct ip_addr* ip, int rtype,
1517 1517
 	char ** h;
1518 1518
 	int ret;
1519 1519
 	str tmp;
1520
+	str* right;
1521
+	struct net net;
1522
+	union exp_op r_expop;
1523
+	struct rvalue* rv;
1524
+	struct rval_cache rv_cache;
1525
+	avp_t* avp;
1526
+	int_str val;
1527
+	pv_value_t pval;
1528
+	int destroy_pval;
1520 1529
 
1530
+	right=0; /* warning fix */
1531
+	rv=0;
1532
+	destroy_pval=0;
1521 1533
 	ret=-1;
1522 1534
 	switch(rtype){
1523 1535
 		case NET_ST:
... ...
@@ -1531,66 +1545,145 @@ inline static int comp_ip(int op, struct ip_addr* ip, int rtype,
1531 1531
 				default:
1532 1532
 					goto error_op;
1533 1533
 			}
1534
-			break;
1535
-		case AVP_ST:
1536
-		case STRING_ST:
1537
-		case RE_ST:
1538
-		case RVE_ST:
1539
-		case SELECT_ST:
1540
-			switch(op){
1541
-				case EQUAL_OP:
1542
-				case MATCH_OP:
1543
-					/* 1: compare with ip2str*/
1544
-					ret=comp_string(op, ip_addr2a(ip), rtype, r, msg, ctx);
1545
-					if (likely(ret==1)) break;
1546
-					/* 2: resolve (name) & compare w/ all the ips */
1547
-					if (rtype==STRING_ST){
1548
-						he=resolvehost(r->str.s);
1549
-						if (he==0){
1550
-							DBG("comp_ip: could not resolve %s\n",
1551
-							    r->str.s);
1552
-						}else if (he->h_addrtype==ip->af){
1553
-							for(h=he->h_addr_list;(ret!=1)&& (*h); h++){
1554
-								ret=(memcmp(ip->u.addr, *h, ip->len)==0);
1555
-							}
1556
-							if (ret==1) break;
1557
-						}
1558
-					}
1559
-					/* 3: (slow) rev dns the address
1560
-					* and compare with all the aliases
1561
-					* !!??!! review: remove this? */
1562
-					if (unlikely((received_dns & DO_REV_DNS) && 
1563
-							((he=rev_resolvehost(ip))!=0) )){
1564
-						/*  compare with primary host name */
1565
-						ret=comp_string(op, he->h_name, rtype, r, msg, ctx);
1566
-						/* compare with all the aliases */
1567
-						for(h=he->h_aliases; (ret!=1) && (*h); h++){
1568
-							ret=comp_string(op, *h, rtype, r, msg, ctx);
1569
-						}
1570
-					}else{
1571
-						ret=0;
1572
-					}
1573
-					break;
1574
-				case DIFF_OP:
1575
-					ret=(comp_ip(EQUAL_OP, ip, rtype, r, msg, ctx) > 0) ?0:1;
1576
-					break;
1577
-				default:
1578
-					goto error_op;
1579
-			}
1580
-			break;
1534
+			return ret; /* exit directly */
1581 1535
 		case MYSELF_ST: /* check if it's one of our addresses*/
1582 1536
 			tmp.s=ip_addr2a(ip);
1583 1537
 			tmp.len=strlen(tmp.s);
1584 1538
 			ret=check_self_op(op, &tmp, 0);
1539
+			return ret;
1540
+		case STRING_ST:
1541
+		case STR_ST:
1542
+			right=&r->str;
1543
+			break;
1544
+		case RVE_ST:
1545
+			rval_cache_init(&rv_cache);
1546
+			rv=rval_expr_eval(ctx, msg, r->param);
1547
+			if (unlikely (rv==0))
1548
+				return (op==DIFF_OP); /* not found or error*/
1549
+			if (unlikely(rval_get_tmp_str(ctx, msg, &tmp, rv, 0, &rv_cache)
1550
+							< 0)){
1551
+				goto error;
1552
+			}
1553
+			right = &tmp;
1554
+			break;
1555
+		case AVP_ST:
1556
+			/* we can still have AVP_ST due to the RVE optimisations
1557
+			   (if a RVE == $avp => rve wrapper removed => pure avp) */
1558
+			avp = search_avp_by_index(r->attr->type, r->attr->name,
1559
+										&val, r->attr->index);
1560
+			if (likely(avp && (avp->flags & AVP_VAL_STR))) right = &val.s;
1561
+			else return (op == DIFF_OP);
1562
+			break;
1563
+		case SELECT_ST:
1564
+			/* see AVP_ST comment and s/AVP_ST/SELECT_ST/ */
1565
+			ret = run_select(&tmp, r->select, msg);
1566
+			if (unlikely(ret != 0))
1567
+				return (op == DIFF_OP); /* Not found or error */
1568
+			right = &tmp;
1569
+			break;
1570
+		case PVAR_ST:
1571
+			/* see AVP_ST comment and s/AVP_ST/PVAR_ST/ */
1572
+			memset(&pval, 0, sizeof(pv_value_t));
1573
+			if (unlikely(pv_get_spec_value(msg, r->param, &pval)!=0)){
1574
+				return (op == DIFF_OP); /* error, not found => false */
1575
+			}
1576
+			destroy_pval=1;
1577
+			if (likely(pval.flags & PV_VAL_STR)){
1578
+				right=&pval.rs;
1579
+			}else{
1580
+				pv_value_destroy(&pval);
1581
+				return (op == DIFF_OP); /* not found or invalid type */
1582
+			}
1585 1583
 			break;
1584
+		case RE_ST:
1585
+			if (unlikely(op != MATCH_OP))
1586
+				goto error_op;
1587
+			/* 1: compare with ip2str*/
1588
+			ret=comp_string(op, ip_addr2a(ip), rtype, r, msg, ctx);
1589
+			if (likely(ret==1))
1590
+				return ret;
1591
+			/* 3: (slow) rev dns the address
1592
+			* and compare with all the aliases
1593
+			* !!??!! review: remove this? */
1594
+			if (unlikely((received_dns & DO_REV_DNS) &&
1595
+				((he=rev_resolvehost(ip))!=0) )){
1596
+				/*  compare with primary host name */
1597
+				ret=comp_string(op, he->h_name, rtype, r, msg, ctx);
1598
+				/* compare with all the aliases */
1599
+				for(h=he->h_aliases; (ret!=1) && (*h); h++){
1600
+					ret=comp_string(op, *h, rtype, r, msg, ctx);
1601
+				}
1602
+			}else{
1603
+				ret=0;
1604
+			}
1605
+			return ret;
1586 1606
 		default:
1587 1607
 			LOG(L_CRIT, "BUG: comp_ip: invalid type for "
1588 1608
 						" src_ip or dst_ip (%d)\n", rtype);
1589 1609
 			ret=-1;
1590 1610
 	}
1611
+	/* here "right" is set to the str we compare with */
1612
+	r_expop.str=*right;
1613
+	switch(op){
1614
+		case EQUAL_OP:
1615
+		case MATCH_OP:
1616
+			/* 0: try if ip or network (ip/mask) */
1617
+			if (mk_net_str(&net, right) == 0) {
1618
+				ret=(matchnet(ip, &net)==1);
1619
+				break;
1620
+			}
1621
+			/* 1: compare with ip2str*/
1622
+			/*
1623
+			 ret=comp_string(op, ip_addr2a(ip), STR_ST, &r_expop, msg, ctx);
1624
+			 if (likely(ret==1)) break;
1625
+			*/
1626
+			/* 2: resolve (name) & compare w/ all the ips */
1627
+			he=resolvehost(right->s);
1628
+			if (he==0){
1629
+				DBG("comp_ip: could not resolve %s\n", r->str.s);
1630
+			}else if (he->h_addrtype==ip->af){
1631
+				for(h=he->h_addr_list;(ret!=1)&& (*h); h++){
1632
+					ret=(memcmp(ip->u.addr, *h, ip->len)==0);
1633
+				}
1634
+				if (ret==1) break;
1635
+			}
1636
+			/* 3: (slow) rev dns the address
1637
+			 * and compare with all the aliases
1638
+			 * !!??!! review: remove this? */
1639
+			if (unlikely((received_dns & DO_REV_DNS) &&
1640
+							((he=rev_resolvehost(ip))!=0) )){
1641
+				/*  compare with primary host name */
1642
+				ret=comp_string(op, he->h_name, STR_ST, &r_expop, msg, ctx);
1643
+				/* compare with all the aliases */
1644
+				for(h=he->h_aliases; (ret!=1) && (*h); h++){
1645
+					ret=comp_string(op, *h, STR_ST, &r_expop, msg, ctx);
1646
+				}
1647
+			}else{
1648
+				ret=0;
1649
+			}
1650
+			break;
1651
+		case DIFF_OP:
1652
+			ret=(comp_ip(EQUAL_OP, ip, STR_ST, &r_expop, msg, ctx) > 0)?0:1;
1653
+		break;
1654
+		default:
1655
+			goto error_op;
1656
+	}
1657
+	if (rv){
1658
+		rval_cache_clean(&rv_cache);
1659
+		rval_destroy(rv);
1660
+	}
1661
+	if (destroy_pval)
1662
+		pv_value_destroy(&pval);
1591 1663
 	return ret;
1592 1664
 error_op:
1593
-	LOG(L_CRIT, "BUG: comp_ip: invalid operator %d\n", op);
1665
+	LOG(L_CRIT, "BUG: comp_ip: invalid operator %d for type %d\n", op, rtype);
1666
+error:
1667
+	if (unlikely(rv)){
1668
+		rval_cache_clean(&rv_cache);
1669
+		rval_destroy(rv);
1670
+	}
1671
+	if (destroy_pval)
1672
+		pv_value_destroy(&pval);
1594 1673
 	return -1;
1595 1674
 }
1596 1675