diff --git a/config b/config
index 4f046aa..eab5c72 100755
--- a/config
+++ b/config
@@ -7,8 +7,8 @@ fi
ngx_addon_name=ngx_http_set_misc_module
HTTP_AUX_FILTER_MODULES="$HTTP_AUX_FILTER_MODULES ngx_http_set_misc_module"
-NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/src/ngx_http_set_base32.c $ngx_addon_dir/src/ngx_http_set_default_value.c $ngx_addon_dir/src/ngx_http_set_hashed_upstream.c $ngx_addon_dir/src/ngx_http_set_quote_sql.c $ngx_addon_dir/src/ngx_http_set_quote_json.c $ngx_addon_dir/src/ngx_http_set_unescape_uri.c $ngx_addon_dir/src/ngx_http_set_misc_module.c $ngx_addon_dir/src/ngx_http_set_escape_uri.c $ngx_addon_dir/src/ngx_http_set_hash.c $ngx_addon_dir/src/ngx_http_set_local_today.c $ngx_addon_dir/src/ngx_http_set_hex.c $ngx_addon_dir/src/ngx_http_set_base64.c $ngx_addon_dir/src/ngx_http_set_random.c $ngx_addon_dir/src/ngx_http_set_secure_random.c $ngx_addon_dir/src/ngx_http_set_rotate.c"
-NGX_ADDON_DEPS="$NGX_ADDON_DEPS $ngx_addon_dir/src/ddebug.h $ngx_addon_dir/src/ngx_http_set_default_value.h $ngx_addon_dir/src/ngx_http_set_hashed_upstream.h $ngx_addon_dir/src/ngx_http_set_quote_sql.h $ngx_addon_dir/src/ngx_http_set_quote_json.h $ngx_addon_dir/src/ngx_http_set_unescape_uri.h $ngx_addon_dir/src/ngx_http_set_escape_uri.h $ngx_addon_dir/src/ngx_http_set_hash.h $ngx_addon_dir/src/ngx_http_set_local_today.h $ngx_addon_dir/src/ngx_http_set_hex.h $ngx_addon_dir/src/ngx_http_set_base64.h $ngx_addon_dir/src/ngx_http_set_random.h $ngx_addon_dir/src/ngx_http_set_rotate.h $ngx_addon_dir/src/ngx_http_set_secure_random.h $ngx_addon_dir/src/ngx_http_set_misc_module.h"
+NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/src/ngx_http_set_base32.c $ngx_addon_dir/src/ngx_http_set_default_value.c $ngx_addon_dir/src/ngx_http_set_hashed_upstream.c $ngx_addon_dir/src/ngx_http_set_quote_sql.c $ngx_addon_dir/src/ngx_http_set_quote_json.c $ngx_addon_dir/src/ngx_http_set_unescape_uri.c $ngx_addon_dir/src/ngx_http_set_misc_module.c $ngx_addon_dir/src/ngx_http_set_escape_uri.c $ngx_addon_dir/src/ngx_http_set_hash.c $ngx_addon_dir/src/ngx_http_set_local_today.c $ngx_addon_dir/src/ngx_http_set_hex.c $ngx_addon_dir/src/ngx_http_set_ip_matches.c $ngx_addon_dir/src/ngx_http_set_base64.c $ngx_addon_dir/src/ngx_http_set_random.c $ngx_addon_dir/src/ngx_http_set_secure_random.c $ngx_addon_dir/src/ngx_http_set_rotate.c"
+NGX_ADDON_DEPS="$NGX_ADDON_DEPS $ngx_addon_dir/src/ddebug.h $ngx_addon_dir/src/ngx_http_set_default_value.h $ngx_addon_dir/src/ngx_http_set_hashed_upstream.h $ngx_addon_dir/src/ngx_http_set_quote_sql.h $ngx_addon_dir/src/ngx_http_set_quote_json.h $ngx_addon_dir/src/ngx_http_set_unescape_uri.h $ngx_addon_dir/src/ngx_http_set_escape_uri.h $ngx_addon_dir/src/ngx_http_set_hash.h $ngx_addon_dir/src/ngx_http_set_local_today.h $ngx_addon_dir/src/ngx_http_set_hex.h $ngx_addon_dir/src/ngx_http_set_ip_matches.h $ngx_addon_dir/src/ngx_http_set_base64.h $ngx_addon_dir/src/ngx_http_set_random.h $ngx_addon_dir/src/ngx_http_set_rotate.h $ngx_addon_dir/src/ngx_http_set_secure_random.h $ngx_addon_dir/src/ngx_http_set_misc_module.h"
if [ $USE_OPENSSL = YES ]; then
NGX_ADDON_DEPS="$NGX_ADDON_DEPS $ngx_addon_dir/src/ngx_http_set_hmac.h"
diff --git a/doc/HttpSetMiscModule.wiki b/doc/HttpSetMiscModule.wiki
index 59a5f76..70c30d9 100644
--- a/doc/HttpSetMiscModule.wiki
+++ b/doc/HttpSetMiscModule.wiki
@@ -715,6 +715,31 @@ Please note that we're using [[HttpEchoModule]]'s [[HttpEchoModule#echo|echo dir
This directive requires the OpenSSL library enabled in your Nignx build (usually by passing the --with-http_ssl_module
option to the ./configure
script).
+== set_ip_matches ==
+'''syntax:''' ''set_ip_matches $dst ''
+
+'''default:''' ''no''
+
+'''context:''' ''location, location if''
+
+'''phase:''' ''rewrite''
+
+Sets $dst
to either 1
or 0
, dependent on whether or not the IP address (either IPv4 or IPv6) as defined in ip
matches the network defined in network
. The network can be specified as a single IP address or using CIDR notation.
+
+For instance,
+
+
+ location /test {
+ set_ip_matches $r1 10.0.0.0/8 10.0.2.101;
+ set_ip_matches $r2 10.0.0.0/24 10.0.2.101;
+ echo "r1=$r1, r2=$r2";
+ }
+
+
+then request GET /test
will output r1=1, r2=0
.
+
+This directive looks a lot like the "allow" directive, but it executes in the "rewrite" phase and allows for custom handling of matches and mismatches.
+
== set_random ==
'''syntax:''' ''set_random $res ''
diff --git a/src/ngx_http_set_ip_matches.c b/src/ngx_http_set_ip_matches.c
new file mode 100644
index 0000000..d667dd7
--- /dev/null
+++ b/src/ngx_http_set_ip_matches.c
@@ -0,0 +1,85 @@
+#ifndef DDEBUG
+#define DDEBUG 0
+#endif
+#include "ddebug.h"
+
+#include
+
+#include "ngx_http_set_ip_matches.h"
+
+ngx_int_t
+ngx_http_set_misc_set_ip_matches(ngx_http_request_t *r, ngx_str_t *res,
+ ngx_http_variable_value_t *v)
+{
+ ngx_http_variable_value_t *network_var, *ip_var;
+ ngx_str_t network_str, ip_str;
+ ngx_cidr_t network, ip;
+ size_t len;
+ u_char *ip_addr, *ip_mask, *network_addr, *network_mask, result;
+ u_int i;
+
+ network_var = v;
+ ip_var = v+1;
+
+ network_str.len = network_var->len;
+ network_str.data = network_var->data;
+
+ ip_str.len = ip_var->len;
+ ip_str.data = ip_var->data;
+
+ if (ngx_ptocidr(&network_str, &network) == NGX_ERROR) {
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "network: invalid address or cidr");
+ return NGX_ERROR;
+ }
+
+ if (ngx_ptocidr(&ip_str, &ip) == NGX_ERROR) {
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "ip: invalid address");
+ return NGX_ERROR;
+ }
+
+ if (network.family != ip.family) {
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "IPv4 and IPv6 cannot be mixed");
+ return NGX_ERROR;
+ }
+
+ switch (ip.family) {
+ case AF_INET:
+ len = 4;
+ ip_addr = (u_char *) &ip.u.in.addr;
+ ip_mask = (u_char *) &ip.u.in.mask;
+ network_addr = (u_char *) &network.u.in.addr;
+ network_mask = (u_char *) &network.u.in.mask;
+ break;
+ case AF_INET6:
+ len = 16;
+ ip_addr = ip.u.in6.addr.__in6_u.__u6_addr8;
+ ip_mask = ip.u.in6.mask.__in6_u.__u6_addr8;
+ network_addr = network.u.in6.addr.__in6_u.__u6_addr8;
+ network_mask = network.u.in6.mask.__in6_u.__u6_addr8;
+ break;
+ default:
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "invalid address family");
+ return NGX_ERROR;
+ }
+
+ for (i=0;iconnection->log, 0, "ip: cidr notation not allowed");
+ return NGX_ERROR;
+ }
+ }
+
+ result = 0;
+ for (i=0;ilen = 1;
+ res->data = ngx_palloc(r->pool, res->len);
+ if (res->data == NULL) {
+ return NGX_ERROR;
+ }
+ res->data[0] = result==0 ? '1' : '0';
+
+ return NGX_OK;
+ }
diff --git a/src/ngx_http_set_ip_matches.h b/src/ngx_http_set_ip_matches.h
new file mode 100644
index 0000000..987f19a
--- /dev/null
+++ b/src/ngx_http_set_ip_matches.h
@@ -0,0 +1,11 @@
+#ifndef NGX_HTTP_SET_IP_MATCHES
+#define NGX_HTTP_SET_IP_MATCHES
+
+#include
+#include
+#include
+
+ngx_int_t ngx_http_set_misc_set_ip_matches(ngx_http_request_t *r,
+ ngx_str_t *res, ngx_http_variable_value_t *v);
+
+#endif /* NGX_HTTP_SET_IP_MATCHES */
diff --git a/src/ngx_http_set_misc_module.c b/src/ngx_http_set_misc_module.c
index c57aac7..c01018b 100755
--- a/src/ngx_http_set_misc_module.c
+++ b/src/ngx_http_set_misc_module.c
@@ -16,6 +16,7 @@
#include "ngx_http_set_hash.h"
#include "ngx_http_set_hex.h"
#include "ngx_http_set_base64.h"
+#include "ngx_http_set_ip_matches.h"
#if NGX_OPENSSL
#include "ngx_http_set_hmac.h"
#endif
@@ -62,6 +63,13 @@ static ndk_set_var_t ngx_http_set_misc_set_encode_hex_filter = {
NULL
};
+static ndk_set_var_t ngx_http_set_misc_set_ip_matches_filter = {
+ NDK_SET_VAR_MULTI_VALUE,
+ (void *) ngx_http_set_misc_set_ip_matches,
+ 2,
+ NULL
+};
+
#if NGX_OPENSSL
static ndk_set_var_t ngx_http_set_misc_set_hmac_sha1_filter = {
@@ -315,6 +323,15 @@ static ngx_command_t ngx_http_set_misc_commands[] = {
0,
NULL
},
+ {
+ ngx_string ("set_ip_matches"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF
+ |NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE3,
+ ndk_set_var_multi_value,
+ 0,
+ 0,
+ &ngx_http_set_misc_set_ip_matches_filter
+ },
{
ngx_string("set_hashed_upstream"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF
diff --git a/t/ip_matches.t b/t/ip_matches.t
new file mode 100644
index 0000000..9e4e87b
--- /dev/null
+++ b/t/ip_matches.t
@@ -0,0 +1,116 @@
+# vi:filetype=
+
+use lib 'lib';
+use Test::Nginx::Socket;
+
+#repeat_each(3);
+
+plan tests => repeat_each() * 2 * blocks();
+
+no_long_string();
+
+run_tests();
+
+#no_diff();
+
+__DATA__
+
+=== TEST 1: IPv4 address matches IPv4 CIDR
+--- config
+ location /bar {
+ set_ip_matches $ip_matches 10.0.0.0/8 10.1.0.101;
+ echo $ip_matches;
+ }
+--- request
+ GET /bar
+--- response_body
+1
+
+
+
+=== TEST 2: IPv4 address does not match IPv4 CIDR
+--- config
+ location /bar {
+ set_ip_matches $ip_matches 10.0.0.0/24 10.1.0.101;
+ echo $ip_matches;
+ }
+--- request
+ GET /bar
+--- response_body
+0
+
+
+=== TEST 3: IPv4 address matches IPv4 address
+--- config
+ location /bar {
+ set_ip_matches $ip_matches 10.1.0.101 10.1.0.101;
+ echo $ip_matches;
+ }
+--- request
+ GET /bar
+--- response_body
+1
+
+
+
+=== TEST 4: IPv4 address does not match IPv4 address
+--- config
+ location /bar {
+ set_ip_matches $ip_matches 10.1.0.102 10.1.0.101 ;
+ echo $ip_matches;
+ }
+--- request
+ GET /bar
+--- response_body
+0
+
+
+
+=== TEST 5: IPv6 address matches IPv6 CIDR
+--- config
+ location /bar {
+ set_ip_matches $ip_matches 3ffe::/16 3ffe:1900:4545:3:200:f8ff::67cf;
+ echo $ip_matches;
+ }
+--- request
+ GET /bar
+--- response_body
+1
+
+
+
+=== TEST 6: IPv6 address does not match IPv6 CIDR
+--- config
+ location /bar {
+ set_ip_matches $ip_matches 3fff::/16 3ffe:1900:4545:3:200:f8ff::67cf;
+ echo $ip_matches;
+ }
+--- request
+ GET /bar
+--- response_body
+0
+
+
+=== TEST 7: IPv6 address matches IPv6 address
+--- config
+ location /bar {
+ set_ip_matches $ip_matches 3ffe:1900:4545:3:200:f8ff::67cf 3ffe:1900:4545:3:200:f8ff::67cf;
+ echo $ip_matches;
+ }
+--- request
+ GET /bar
+--- response_body
+1
+
+
+=== TEST 7: IPv6 address does not match IPv6 address
+--- config
+ location /bar {
+ set_ip_matches $ip_matches 3ffe:1900:4545:3:200:f8ff::67d0 3ffe:1900:4545:3:200:f8ff::67cf;
+ echo $ip_matches;
+ }
+--- request
+ GET /bar
+--- response_body
+0
+