瀏覽代碼

ipops: Added function is_ip_rfc1918(ip) for detecting private IPv4 according to RFC 1918.

Iñaki Baz Castillo 14 年之前
父節點
當前提交
aa940ed3b5

+ 22 - 0
modules/ipops/README

@@ -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");
+}
+...

+ 21 - 0
modules/ipops/compile_rfc1918_parser.rl.sh

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

+ 39 - 0
modules/ipops/doc/ipops_admin.xml

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

+ 27 - 1
modules/ipops/ipops_mod.c

@@ -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;
+}

+ 399 - 0
modules/ipops/rfc1918_parser.c

@@ -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;
+}
+

+ 16 - 0
modules/ipops/rfc1918_parser.h

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

+ 43 - 0
modules/ipops/rfc1918_parser.rl

@@ -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;
+}
+