ipops: added dsn_int_match_ip(hostname, ipaddr)
authorDaniel-Constantin Mierla <miconda@gmail.com>
Fri, 12 Jul 2013 16:09:09 +0000 (18:09 +0200)
committerDaniel-Constantin Mierla <miconda@gmail.com>
Fri, 12 Jul 2013 16:09:09 +0000 (18:09 +0200)
- function that uses the internal resolver to match a hostname with an
  ip (similar operation like 'scr_ip=="hostname"')
- rename dns_nc_match_ip() to dns_sys_match_ip() to be more suggestive
  about what kind of resolver is used

modules/ipops/README
modules/ipops/doc/ipops_admin.xml
modules/ipops/ipops_mod.c

index 901535a..cd6118e 100644 (file)
@@ -36,7 +36,8 @@ I
               4.8. compare_pure_ips (ip1, ip2)
               4.9. is_ip_rfc1918 (ip)
               4.10. is_in_subnet (ip, subnet)
-              4.11. dns_nc_match_ip(hostname, ipaddr)
+              4.11. dns_sys_match_ip(hostname, ipaddr)
+              4.12. dns_int_match_ip(hostname, ipaddr)
 
    List of Examples
 
@@ -50,7 +51,8 @@ I
    1.8. compare_pure_ips usage
    1.9. is_ip_rfc1918 usage
    1.10. is_in_subnet usage
-   1.11. dns_nc_match_ip usage
+   1.11. dns_sys_match_ip usage
+   1.12. dns_int_match_ip usage
 
 Chapter 1. Admin Guide
 
@@ -75,7 +77,8 @@ Chapter 1. Admin Guide
         4.8. compare_pure_ips (ip1, ip2)
         4.9. is_ip_rfc1918 (ip)
         4.10. is_in_subnet (ip, subnet)
-        4.11. dns_nc_match_ip(hostname, ipaddr)
+        4.11. dns_sys_match_ip(hostname, ipaddr)
+        4.12. dns_int_match_ip(hostname, ipaddr)
 
 1. Overview
 
@@ -127,7 +130,8 @@ Chapter 1. Admin Guide
    4.8. compare_pure_ips (ip1, ip2)
    4.9. is_ip_rfc1918 (ip)
    4.10. is_in_subnet (ip, subnet)
-   4.11. dns_nc_match_ip(hostname, ipaddr)
+   4.11. dns_sys_match_ip(hostname, ipaddr)
+   4.12. dns_int_match_ip(hostname, ipaddr)
 
 4.1. is_ip (ip)
 
@@ -334,22 +338,49 @@ if (is_in_subnet("10.0.123.123", "10.0.123.1/24")) {
 }
 ...
 
-4.11. dns_nc_match_ip(hostname, ipaddr)
+4.11. dns_sys_match_ip(hostname, ipaddr)
 
    Returns TRUE if ipaddr is associated by DNS to hostname. FALSE
-   otherwise. It does not use the internal DNS cache, but directly
-   getaddrinfo(...).
+   otherwise. It does not use the internal DNS resolver, but directly
+   getaddrinfo(...). All addresses returned for the hostname are checked.
+   Note that some hosts may return different lists of IP addresses for
+   each query, if the DNS server is configured in that way (e.g., for
+   providing load balancing through DNS).
 
    Parameters:
      * ipaddr - string or pseudo-variable containing the ip address.
      * hostname - string or pseudo-variable containing the hostname. The
-       resulting IP addresses from DNS query are compared with ipaddress.
+       resulting IP addresses from DNS query are compared with ipaddr.
 
    This function can be used from ANY_ROUTE.
 
-   Example 1.11. dns_nc_match_ip usage
+   Example 1.11. dns_sys_match_ip usage
 ...
-if (!dns_nc_match_ip("myhost.com", "1.2.3.4")) {
+if (!dns_sys_match_ip("myhost.com", "1.2.3.4")) {
+    xdbg("ip address not associated with hostname\n");
+}
+...
+
+4.12. dns_int_match_ip(hostname, ipaddr)
+
+   Returns TRUE if ipaddr is associated by DNS to hostname. FALSE
+   otherwise. It uses internal DNS resolver. At this moment, the function
+   might not check all the IP addresses as returned by dns_sys_match_ip(),
+   because the internal resolver targets to discover the first address to
+   be used for relaying SIP traffic. Thus is better to use
+   dns_sys_match_ip() if the host you want to check has many IP addresses,
+   in different address famililies (IPv4/6).
+
+   Parameters:
+     * ipaddr - string or pseudo-variable containing the ip address.
+     * hostname - string or pseudo-variable containing the hostname. The
+       resulting IP addresses from DNS query are compared with ipaddr.
+
+   This function can be used from ANY_ROUTE.
+
+   Example 1.12. dns_int_match_ip usage
+...
+if (!dns_int_match_ip("myhost.com", "1.2.3.4")) {
     xdbg("ip address not associated with hostname\n");
 }
 ...
index afb03d8..9f3528d 100644 (file)
@@ -529,14 +529,17 @@ if (is_in_subnet("10.0.123.123", "10.0.123.1/24")) {
 
     </section>
 
-    <section id="ipops.f.dns_nc_match_ip">
+    <section id="ipops.f.dns_sys_match_ip">
       <title>
-        <function moreinfo="none">dns_nc_match_ip(hostname, ipaddr)</function>
+        <function moreinfo="none">dns_sys_match_ip(hostname, ipaddr)</function>
       </title>
 
       <para>
                  Returns TRUE if ipaddr is associated by DNS to hostname. FALSE otherwise. It
-                 does not use the internal DNS cache, but directly getaddrinfo(...).
+                 does not use the internal DNS resolver, but directly getaddrinfo(...). All
+                 addresses returned for the hostname are checked. Note that some hosts may
+                 return different lists of IP addresses for each query, if the DNS server
+                 is configured in that way (e.g., for providing load balancing through DNS).
       </para>
 
       <para>Parameters:</para>
@@ -550,7 +553,7 @@ if (is_in_subnet("10.0.123.123", "10.0.123.1/24")) {
         <listitem>
           <para>
                          <emphasis>hostname</emphasis> - string or pseudo-variable containing the hostname.
-                         The resulting IP addresses from DNS query are compared with ipaddress.
+                         The resulting IP addresses from DNS query are compared with ipaddr.
           </para>
         </listitem>
       </itemizedlist>
@@ -561,11 +564,60 @@ if (is_in_subnet("10.0.123.123", "10.0.123.1/24")) {
 
       <example>
         <title>
-          <function>dns_nc_match_ip</function> usage
+          <function>dns_sys_match_ip</function> usage
         </title>
         <programlisting format="linespecific">
 ...
-if (!dns_nc_match_ip("myhost.com", "1.2.3.4")) {
+if (!dns_sys_match_ip("myhost.com", "1.2.3.4")) {
+    xdbg("ip address not associated with hostname\n");
+}
+...
+        </programlisting>
+      </example>
+
+    </section>
+
+    <section id="ipops.f.dns_int_match_ip">
+      <title>
+        <function moreinfo="none">dns_int_match_ip(hostname, ipaddr)</function>
+      </title>
+
+      <para>
+                 Returns TRUE if ipaddr is associated by DNS to hostname. FALSE otherwise. It
+                 uses internal DNS resolver. At this moment, the function might not check all
+                 the IP addresses as returned by dns_sys_match_ip(), because the internal
+                 resolver targets to discover the first address to be used for relaying
+                 SIP traffic. Thus is better to use dns_sys_match_ip() if the host you want
+                 to check has many IP addresses, in different address famililies (IPv4/6).
+      </para>
+
+      <para>Parameters:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>
+            <emphasis>ipaddr</emphasis> - string or pseudo-variable containing the ip address.
+          </para>
+        </listitem>
+        <listitem>
+          <para>
+                         <emphasis>hostname</emphasis> - string or pseudo-variable containing the hostname.
+                         The resulting IP addresses from DNS query are compared with ipaddr.
+          </para>
+        </listitem>
+      </itemizedlist>
+
+      <para>
+        This function can be used from ANY_ROUTE.
+      </para>
+
+      <example>
+        <title>
+          <function>dns_int_match_ip</function> usage
+        </title>
+        <programlisting format="linespecific">
+...
+if (!dns_int_match_ip("myhost.com", "1.2.3.4")) {
     xdbg("ip address not associated with hostname\n");
 }
 ...
index d21546c..dc58fc8 100644 (file)
@@ -87,7 +87,8 @@ static int w_compare_ips(struct sip_msg*, char*, char*);
 static int w_compare_pure_ips(struct sip_msg*, char*, char*);
 static int w_is_ip_rfc1918(struct sip_msg*, char*);
 static int w_ip_is_in_subnet(struct sip_msg*, char*, char*);
-static int w_dns_nc_match_ip(sip_msg_t*, char*, char*);
+static int w_dns_sys_match_ip(sip_msg_t*, char*, char*);
+static int w_dns_int_match_ip(sip_msg_t*, char*, char*);
 
 
 /*
@@ -115,7 +116,9 @@ static cmd_export_t cmds[] =
   REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE },
   { "is_in_subnet", (cmd_function)w_ip_is_in_subnet, 2, fixup_spve_spve, 0,
   REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE },
-  { "dns_nc_match_ip", (cmd_function)w_dns_nc_match_ip, 2, fixup_spve_spve, 0,
+  { "dns_sys_match_ip", (cmd_function)w_dns_sys_match_ip, 2, fixup_spve_spve, 0,
+  ANY_ROUTE },
+  { "dns_int_match_ip", (cmd_function)w_dns_int_match_ip, 2, fixup_spve_spve, 0,
   ANY_ROUTE },
   { "bind_ipops", (cmd_function)bind_ipops, 0, 0, 0, 0},
   { 0, 0, 0, 0, 0, 0 }
@@ -617,7 +620,7 @@ static inline ip_addr_t *strtoipX(str *ips)
        }
 }
 
-static int w_dns_nc_match_ip(sip_msg_t *msg, char *hnp, char *ipp)
+static int w_dns_sys_match_ip(sip_msg_t *msg, char *hnp, char *ipp)
 {
        struct addrinfo hints, *res, *p;
        int status;
@@ -653,7 +656,7 @@ static int w_dns_nc_match_ip(sip_msg_t *msg, char *hnp, char *ipp)
        if ((status = getaddrinfo(hns.s, NULL, &hints, &res)) != 0)
        {
         LM_ERR("getaddrinfo: %s\n", gai_strerror(status));
-        return -2;
+        return -4;
     }
 
        for(p = res;p != NULL; p = p->ai_next)
@@ -680,3 +683,52 @@ static int w_dns_nc_match_ip(sip_msg_t *msg, char *hnp, char *ipp)
 
        return -1;
 }
+
+static int w_dns_int_match_ip(sip_msg_t *msg, char *hnp, char *ipp)
+{
+       ip_addr_t *ipa;
+       str hns;
+       str ips;
+       struct hostent* he;
+       char ** h;
+       int ret;
+
+       if (fixup_get_svalue(msg, (gparam_p)hnp, &hns))
+       {
+               LM_ERR("cannot evaluate hostname parameter\n");
+               return -2;
+       }
+
+       if (fixup_get_svalue(msg, (gparam_p)ipp, &ips))
+       {
+               LM_ERR("cannot evaluate ip address parameter\n");
+               return -2;
+       }
+
+       ipa = strtoipX(&ips);
+       if(ipa==NULL)
+       {
+               LM_ERR("invalid ip address: %.*s\n", ips.len, ips.s);
+               return -3;
+       }
+
+       he=resolvehost(hns.s);
+       if (he==0) {
+               DBG("could not resolve %s\n", hns.s);
+               return -4;
+       }
+       ret = 0;
+       if (he->h_addrtype==ipa->af)
+       {
+               for(h=he->h_addr_list; (*h); h++)
+               {
+                       if(memcmp(ipa->u.addr, *h, ipa->len)==0)
+                       {
+                               /* match */
+                               return 1;
+                       }
+               }
+       }
+       /* no match */
+       return -1;
+}