ipops: Added function is_ip_rfc1918(ip) for detecting private IPv4 according to RFC...
authorIñaki Baz Castillo <ibc@aliax.net>
Mon, 1 Aug 2011 10:21:44 +0000 (12:21 +0200)
committerIñaki Baz Castillo <ibc@aliax.net>
Mon, 1 Aug 2011 10:22:55 +0000 (12:22 +0200)
modules/ipops/README
modules/ipops/compile_rfc1918_parser.rl.sh [new file with mode: 0755]
modules/ipops/doc/ipops_admin.xml
modules/ipops/ipops_mod.c
modules/ipops/rfc1918_parser.c [new file with mode: 0644]
modules/ipops/rfc1918_parser.h [new file with mode: 0644]
modules/ipops/rfc1918_parser.rl [new file with mode: 0644]

index 1447a45..c389aa6 100644 (file)
@@ -34,6 +34,7 @@ Iñaki Baz Castillo
               4.6. ip_type (ip)
               4.7. compare_ips (ip1, ip2)
               4.8. compare_pure_ips (ip1, ip2)
+              4.9. is_ip_rfc1918 (ip)
 
    List of Examples
 
@@ -45,6 +46,7 @@ Iñaki Baz Castillo
    1.6. ip_type usage
    1.7. compare_ips usage
    1.8. compare_pure_ips usage
+   1.9. is_ip_rfc1918 usage
 
 Chapter 1. Admin Guide
 
@@ -67,6 +69,7 @@ Chapter 1. Admin Guide
         4.6. ip_type (ip)
         4.7. compare_ips (ip1, ip2)
         4.8. compare_pure_ips (ip1, ip2)
+        4.9. is_ip_rfc1918 (ip)
 
 1. Overview
 
@@ -113,6 +116,7 @@ Chapter 1. Admin Guide
    4.6. ip_type (ip)
    4.7. compare_ips (ip1, ip2)
    4.8. compare_pure_ips (ip1, ip2)
+   4.9. is_ip_rfc1918 (ip)
 
 4.1.  is_ip (ip)
 
@@ -277,3 +281,21 @@ if (compare_pure_ips($si, "1080::8:800:200C:417A")) {
   xlog("L_INFO", "both are the same IP\n");
 }
 ...
+
+4.9.  is_ip_rfc1918 (ip)
+
+   Returns TRUE if the argument is a private IPv4 according to RFC 1918.
+   FALSE otherwise.
+
+   Parameters:
+     * ip - String or pseudo-variable containing the IP to evaluate.
+
+   This function can be used from REQUEST_ROUTE, FAILURE_ROUTE,
+   ONREPLY_ROUTE, BRANCH_ROUTE and LOCAL_ROUTE.
+
+   Example 1.9.  is_ip_rfc1918 usage
+...
+if (is_ip_rfc1918("10.0.123.123")) {
+  xlog("L_INFO", "it's a private IPv4\n");
+}
+...
diff --git a/modules/ipops/compile_rfc1918_parser.rl.sh b/modules/ipops/compile_rfc1918_parser.rl.sh
new file mode 100755 (executable)
index 0000000..be2a750
--- /dev/null
@@ -0,0 +1,21 @@
+#!/bin/bash
+
+
+which ragel >/dev/null
+if [ $? -ne 0 ] ; then
+  echo "ERROR. Ragel not installed, cannot compile the Ragel grammar." >&2
+  exit 1
+else
+  ragel -v
+  echo
+fi
+
+
+set -e
+
+RAGEL_FILE=rfc1918_parser
+echo ">>> Compiling Ragel grammar $RAGEL_FILE.rl ..."
+ragel -G2 -C $RAGEL_FILE.rl
+echo
+echo "<<< OK: $RAGEL_FILE.c generated"
+echo
index 98fa39f..222f41f 100644 (file)
@@ -440,6 +440,45 @@ if (compare_pure_ips($si, "1080::8:800:200C:417A")) {
 
     </section>
 
+    <section>
+      <title>
+        <function moreinfo="none">is_ip_rfc1918 (ip)</function>
+      </title>
+
+      <para>
+        Returns TRUE if the argument is a private IPv4 according to RFC 1918. FALSE otherwise.
+      </para>
+
+      <para>Parameters:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>
+            <emphasis>ip</emphasis> - String or pseudo-variable containing the IP to evaluate.
+          </para>
+        </listitem>
+      </itemizedlist>
+
+      <para>
+        This function can be used from REQUEST_ROUTE, FAILURE_ROUTE, ONREPLY_ROUTE, BRANCH_ROUTE and LOCAL_ROUTE.
+      </para>
+
+      <example>
+        <title>
+          <function>is_ip_rfc1918</function> usage
+        </title>
+        <programlisting format="linespecific">
+...
+if (is_ip_rfc1918("10.0.123.123")) {
+  xlog("L_INFO", "it's a private IPv4\n");
+}
+...
+        </programlisting>
+      </example>
+
+    </section>
+
   </section>
  
 </chapter>
index 19fe95a..0f36dd5 100644 (file)
@@ -21,6 +21,7 @@
  *
  * History:
  * -------
+ *  2011-07-29: Added a function to detect RFC1918 private IPv4 addresses (ibc)
  *  2011-04-27: Initial version (ibc)
  */
 /*!
@@ -46,7 +47,7 @@
 #include "../../mod_fix.h"
 #include "../../pvar.h"
 #include "ip_parser.h"
-
+#include "rfc1918_parser.h"
 
 MODULE_VERSION
 
@@ -78,6 +79,7 @@ static int w_is_ipv6_reference(struct sip_msg*, char*);
 static int w_ip_type(struct sip_msg*, char*);
 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*);
 
 
 /*
@@ -101,6 +103,8 @@ static cmd_export_t cmds[] =
   REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE },
   { "compare_pure_ips", (cmd_function)w_compare_pure_ips, 2, fixup_spve_spve, 0,
   REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE },
+  { "is_ip_rfc1918", (cmd_function)w_is_ip_rfc1918, 1, fixup_spve_null, 0,
+  REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE },
   { 0, 0, 0, 0, 0, 0 }
 };
 
@@ -435,3 +439,25 @@ static int w_compare_pure_ips(struct sip_msg* _msg, char* _s1, char* _s2)
     return -1;
 }
 
+
+/*! \brief Return true if the given argument (string or pv) is a valid RFC 1918 IPv4 (private address). */
+static int w_is_ip_rfc1918(struct sip_msg* _msg, char* _s)
+{
+  str string;
+  
+  if (_s == NULL) {
+    LM_ERR("bad parameter\n");
+    return -2;
+  }
+  
+  if (fixup_get_svalue(_msg, (gparam_p)_s, &string))
+  {
+    LM_ERR("cannot print the format for string\n");
+    return -3;
+  }
+  
+  if (rfc1918_parser_execute(string.s, string.len) == 1)
+    return 1;
+  else
+    return -1;
+}
diff --git a/modules/ipops/rfc1918_parser.c b/modules/ipops/rfc1918_parser.c
new file mode 100644 (file)
index 0000000..f39fff0
--- /dev/null
@@ -0,0 +1,399 @@
+
+#line 1 "rfc1918_parser.rl"
+#include "rfc1918_parser.h"
+
+
+/** Ragel machine **/
+
+#line 21 "rfc1918_parser.rl"
+
+
+
+/** Data **/
+
+#line 15 "rfc1918_parser.c"
+static const int rfc1918_parser_start = 1;
+static const int rfc1918_parser_first_final = 28;
+static const int rfc1918_parser_error = 0;
+
+static const int rfc1918_parser_en_main = 1;
+
+
+#line 26 "rfc1918_parser.rl"
+
+
+/** exec **/
+unsigned int rfc1918_parser_execute(const char *str, size_t len)
+{
+  int cs = 0;
+  const char *p, *pe;
+  unsigned int is_ip_rfc1918 = 0;
+
+  p = str;
+  pe = str+len;
+
+  
+#line 37 "rfc1918_parser.c"
+       {
+       cs = rfc1918_parser_start;
+       }
+
+#line 39 "rfc1918_parser.rl"
+  
+#line 44 "rfc1918_parser.c"
+       {
+       if ( p == pe )
+               goto _test_eof;
+       switch ( cs )
+       {
+case 1:
+       if ( (*p) == 49 )
+               goto st2;
+       goto st0;
+st0:
+cs = 0;
+       goto _out;
+st2:
+       if ( ++p == pe )
+               goto _test_eof2;
+case 2:
+       switch( (*p) ) {
+               case 48: goto st3;
+               case 55: goto st17;
+               case 57: goto st23;
+       }
+       goto st0;
+st3:
+       if ( ++p == pe )
+               goto _test_eof3;
+case 3:
+       if ( (*p) == 46 )
+               goto st4;
+       goto st0;
+st4:
+       if ( ++p == pe )
+               goto _test_eof4;
+case 4:
+       switch( (*p) ) {
+               case 48: goto st5;
+               case 49: goto st13;
+               case 50: goto st15;
+       }
+       if ( 51 <= (*p) && (*p) <= 57 )
+               goto st14;
+       goto st0;
+st5:
+       if ( ++p == pe )
+               goto _test_eof5;
+case 5:
+       if ( (*p) == 46 )
+               goto st6;
+       goto st0;
+st6:
+       if ( ++p == pe )
+               goto _test_eof6;
+case 6:
+       switch( (*p) ) {
+               case 48: goto st7;
+               case 49: goto st9;
+               case 50: goto st11;
+       }
+       if ( 51 <= (*p) && (*p) <= 57 )
+               goto st10;
+       goto st0;
+st7:
+       if ( ++p == pe )
+               goto _test_eof7;
+case 7:
+       if ( (*p) == 46 )
+               goto st8;
+       goto st0;
+st8:
+       if ( ++p == pe )
+               goto _test_eof8;
+case 8:
+       switch( (*p) ) {
+               case 48: goto tr16;
+               case 49: goto tr17;
+               case 50: goto tr18;
+       }
+       if ( 51 <= (*p) && (*p) <= 57 )
+               goto tr19;
+       goto st0;
+tr16:
+#line 8 "rfc1918_parser.rl"
+       {
+    is_ip_rfc1918 = 1;
+  }
+       goto st28;
+st28:
+       if ( ++p == pe )
+               goto _test_eof28;
+case 28:
+#line 134 "rfc1918_parser.c"
+       goto st0;
+tr17:
+#line 8 "rfc1918_parser.rl"
+       {
+    is_ip_rfc1918 = 1;
+  }
+       goto st29;
+st29:
+       if ( ++p == pe )
+               goto _test_eof29;
+case 29:
+#line 146 "rfc1918_parser.c"
+       if ( 48 <= (*p) && (*p) <= 57 )
+               goto tr19;
+       goto st0;
+tr19:
+#line 8 "rfc1918_parser.rl"
+       {
+    is_ip_rfc1918 = 1;
+  }
+       goto st30;
+st30:
+       if ( ++p == pe )
+               goto _test_eof30;
+case 30:
+#line 160 "rfc1918_parser.c"
+       if ( 48 <= (*p) && (*p) <= 57 )
+               goto tr16;
+       goto st0;
+tr18:
+#line 8 "rfc1918_parser.rl"
+       {
+    is_ip_rfc1918 = 1;
+  }
+       goto st31;
+st31:
+       if ( ++p == pe )
+               goto _test_eof31;
+case 31:
+#line 174 "rfc1918_parser.c"
+       if ( (*p) == 53 )
+               goto tr31;
+       if ( (*p) > 52 ) {
+               if ( 54 <= (*p) && (*p) <= 57 )
+                       goto tr16;
+       } else if ( (*p) >= 48 )
+               goto tr19;
+       goto st0;
+tr31:
+#line 8 "rfc1918_parser.rl"
+       {
+    is_ip_rfc1918 = 1;
+  }
+       goto st32;
+st32:
+       if ( ++p == pe )
+               goto _test_eof32;
+case 32:
+#line 193 "rfc1918_parser.c"
+       if ( 48 <= (*p) && (*p) <= 53 )
+               goto tr16;
+       goto st0;
+st9:
+       if ( ++p == pe )
+               goto _test_eof9;
+case 9:
+       if ( (*p) == 46 )
+               goto st8;
+       if ( 48 <= (*p) && (*p) <= 57 )
+               goto st10;
+       goto st0;
+st10:
+       if ( ++p == pe )
+               goto _test_eof10;
+case 10:
+       if ( (*p) == 46 )
+               goto st8;
+       if ( 48 <= (*p) && (*p) <= 57 )
+               goto st7;
+       goto st0;
+st11:
+       if ( ++p == pe )
+               goto _test_eof11;
+case 11:
+       switch( (*p) ) {
+               case 46: goto st8;
+               case 53: goto st12;
+       }
+       if ( (*p) > 52 ) {
+               if ( 54 <= (*p) && (*p) <= 57 )
+                       goto st7;
+       } else if ( (*p) >= 48 )
+               goto st10;
+       goto st0;
+st12:
+       if ( ++p == pe )
+               goto _test_eof12;
+case 12:
+       if ( (*p) == 46 )
+               goto st8;
+       if ( 48 <= (*p) && (*p) <= 53 )
+               goto st7;
+       goto st0;
+st13:
+       if ( ++p == pe )
+               goto _test_eof13;
+case 13:
+       if ( (*p) == 46 )
+               goto st6;
+       if ( 48 <= (*p) && (*p) <= 57 )
+               goto st14;
+       goto st0;
+st14:
+       if ( ++p == pe )
+               goto _test_eof14;
+case 14:
+       if ( (*p) == 46 )
+               goto st6;
+       if ( 48 <= (*p) && (*p) <= 57 )
+               goto st5;
+       goto st0;
+st15:
+       if ( ++p == pe )
+               goto _test_eof15;
+case 15:
+       switch( (*p) ) {
+               case 46: goto st6;
+               case 53: goto st16;
+       }
+       if ( (*p) > 52 ) {
+               if ( 54 <= (*p) && (*p) <= 57 )
+                       goto st5;
+       } else if ( (*p) >= 48 )
+               goto st14;
+       goto st0;
+st16:
+       if ( ++p == pe )
+               goto _test_eof16;
+case 16:
+       if ( (*p) == 46 )
+               goto st6;
+       if ( 48 <= (*p) && (*p) <= 53 )
+               goto st5;
+       goto st0;
+st17:
+       if ( ++p == pe )
+               goto _test_eof17;
+case 17:
+       if ( (*p) == 50 )
+               goto st18;
+       goto st0;
+st18:
+       if ( ++p == pe )
+               goto _test_eof18;
+case 18:
+       if ( (*p) == 46 )
+               goto st19;
+       goto st0;
+st19:
+       if ( ++p == pe )
+               goto _test_eof19;
+case 19:
+       switch( (*p) ) {
+               case 49: goto st20;
+               case 50: goto st21;
+               case 51: goto st22;
+       }
+       goto st0;
+st20:
+       if ( ++p == pe )
+               goto _test_eof20;
+case 20:
+       if ( 54 <= (*p) && (*p) <= 57 )
+               goto st5;
+       goto st0;
+st21:
+       if ( ++p == pe )
+               goto _test_eof21;
+case 21:
+       if ( 48 <= (*p) && (*p) <= 57 )
+               goto st5;
+       goto st0;
+st22:
+       if ( ++p == pe )
+               goto _test_eof22;
+case 22:
+       if ( 48 <= (*p) && (*p) <= 49 )
+               goto st5;
+       goto st0;
+st23:
+       if ( ++p == pe )
+               goto _test_eof23;
+case 23:
+       if ( (*p) == 50 )
+               goto st24;
+       goto st0;
+st24:
+       if ( ++p == pe )
+               goto _test_eof24;
+case 24:
+       if ( (*p) == 46 )
+               goto st25;
+       goto st0;
+st25:
+       if ( ++p == pe )
+               goto _test_eof25;
+case 25:
+       if ( (*p) == 49 )
+               goto st26;
+       goto st0;
+st26:
+       if ( ++p == pe )
+               goto _test_eof26;
+case 26:
+       if ( (*p) == 54 )
+               goto st27;
+       goto st0;
+st27:
+       if ( ++p == pe )
+               goto _test_eof27;
+case 27:
+       if ( (*p) == 56 )
+               goto st5;
+       goto st0;
+       }
+       _test_eof2: cs = 2; goto _test_eof; 
+       _test_eof3: cs = 3; goto _test_eof; 
+       _test_eof4: cs = 4; goto _test_eof; 
+       _test_eof5: cs = 5; goto _test_eof; 
+       _test_eof6: cs = 6; goto _test_eof; 
+       _test_eof7: cs = 7; goto _test_eof; 
+       _test_eof8: cs = 8; goto _test_eof; 
+       _test_eof28: cs = 28; goto _test_eof; 
+       _test_eof29: cs = 29; goto _test_eof; 
+       _test_eof30: cs = 30; goto _test_eof; 
+       _test_eof31: cs = 31; goto _test_eof; 
+       _test_eof32: cs = 32; goto _test_eof; 
+       _test_eof9: cs = 9; goto _test_eof; 
+       _test_eof10: cs = 10; goto _test_eof; 
+       _test_eof11: cs = 11; goto _test_eof; 
+       _test_eof12: cs = 12; goto _test_eof; 
+       _test_eof13: cs = 13; goto _test_eof; 
+       _test_eof14: cs = 14; goto _test_eof; 
+       _test_eof15: cs = 15; goto _test_eof; 
+       _test_eof16: cs = 16; goto _test_eof; 
+       _test_eof17: cs = 17; goto _test_eof; 
+       _test_eof18: cs = 18; goto _test_eof; 
+       _test_eof19: cs = 19; goto _test_eof; 
+       _test_eof20: cs = 20; goto _test_eof; 
+       _test_eof21: cs = 21; goto _test_eof; 
+       _test_eof22: cs = 22; goto _test_eof; 
+       _test_eof23: cs = 23; goto _test_eof; 
+       _test_eof24: cs = 24; goto _test_eof; 
+       _test_eof25: cs = 25; goto _test_eof; 
+       _test_eof26: cs = 26; goto _test_eof; 
+       _test_eof27: cs = 27; goto _test_eof; 
+
+       _test_eof: {}
+       _out: {}
+       }
+
+#line 40 "rfc1918_parser.rl"
+
+  return is_ip_rfc1918;
+}
+
diff --git a/modules/ipops/rfc1918_parser.h b/modules/ipops/rfc1918_parser.h
new file mode 100644 (file)
index 0000000..e9ef634
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * Warning: This file is auto generated from a ragel syntax (rfc1918_parser.rl),
+ * do not change it!
+ */   
+
+#ifndef rfc1918_parser_h
+#define rfc1918_parser_h
+
+
+#include <sys/types.h>
+
+
+unsigned int rfc1918_parser_execute(const char *str, size_t len);
+
+
+#endif
diff --git a/modules/ipops/rfc1918_parser.rl b/modules/ipops/rfc1918_parser.rl
new file mode 100644 (file)
index 0000000..cd2903a
--- /dev/null
@@ -0,0 +1,43 @@
+#include "rfc1918_parser.h"
+
+
+/** Ragel machine **/
+%%{
+  machine rfc1918_parser;
+
+  action is_rfc1918 {
+    is_ip_rfc1918 = 1;
+  }
+
+  DIGIT                = "0".."9";
+  dec_octet            = DIGIT | ( 0x31..0x39 DIGIT ) | ( "1" DIGIT{2} ) |
+                         ( "2" 0x30..0x34 DIGIT ) | ( "25" 0x30..0x35 );
+
+  RFC1918_address      = ( "10." dec_octet "." dec_octet "." dec_octet ) |
+                         ( "172." ( ( "1" "6".."9" ) | ( "2" DIGIT ) | ( "3" "0".."1" ) ) "." dec_octet "." dec_octet ) |
+                         ( "192.168." dec_octet "." dec_octet );
+
+   main                := RFC1918_address @is_rfc1918;
+}%%
+
+
+/** Data **/
+%% write data;
+
+
+/** exec **/
+unsigned int rfc1918_parser_execute(const char *str, size_t len)
+{
+  int cs = 0;
+  const char *p, *pe;
+  unsigned int is_ip_rfc1918 = 0;
+
+  p = str;
+  pe = str+len;
+
+  %% write init;
+  %% write exec;
+
+  return is_ip_rfc1918;
+}
+