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