summaryrefslogtreecommitdiff
path: root/src/ipaddrcheck_functions.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ipaddrcheck_functions.c')
-rw-r--r--src/ipaddrcheck_functions.c208
1 files changed, 113 insertions, 95 deletions
diff --git a/src/ipaddrcheck_functions.c b/src/ipaddrcheck_functions.c
index d98ceda..269981f 100644
--- a/src/ipaddrcheck_functions.c
+++ b/src/ipaddrcheck_functions.c
@@ -20,6 +20,9 @@
*
*/
+#include <netinet/in.h>
+#include <assert.h>
+
#include "ipaddrcheck_functions.h"
/*
@@ -36,134 +39,59 @@
* the format was.
*/
-
-/* Does it contain double colons? This is not allowed in IPv6 addresses */
-int duplicate_double_colons(char* address_str) {
+int regex_matches(const char* regex, const char* str)
+{
int offsets[1];
pcre *re;
int rc;
const char *error;
int erroffset;
- re = pcre_compile(".*(::).*\\1", 0, &error, &erroffset, NULL);
- rc = pcre_exec(re, NULL, address_str, strlen(address_str), 0, 0, offsets, 1);
+ re = pcre_compile(regex, 0, &error, &erroffset, NULL);
+ assert(re != NULL);
+
+ rc = pcre_exec(re, NULL, str, strlen(str), 0, 0, offsets, 1);
if( rc >= 0)
{
- return(1);
+ return RESULT_SUCCESS;
}
else
{
- return(0);
+ return RESULT_FAILURE;
}
}
+
+/* Does it contain double colons? This is not allowed in IPv6 addresses */
+int duplicate_double_colons(char* address_str) {
+ return regex_matches(".*(::).*\\1", address_str);
+}
+
/* Does it look like IPv4 CIDR (e.g. 192.0.2.1/24)? */
int is_ipv4_cidr(char* address_str)
{
- int result;
-
- int offsets[1];
- pcre *re;
- int rc;
- const char *error;
- int erroffset;
-
- re = pcre_compile("^((([1-9]\\d{0,2}|0)\\.){3}([1-9]\\d{0,2}|0)\\/([1-9]\\d*|0))$",
- 0, &error, &erroffset, NULL);
- rc = pcre_exec(re, NULL, address_str, strlen(address_str), 0, 0, offsets, 1);
-
- if( rc < 0 )
- {
- result = RESULT_FAILURE;
- }
- else
- {
- result = RESULT_SUCCESS;
- }
-
- return(result);
+ return regex_matches("^((([1-9]\\d{0,2}|0)\\.){3}([1-9]\\d{0,2}|0)\\/([1-9]\\d*|0))$",
+ address_str);
}
/* Is it a single dotted decimal address? */
int is_ipv4_single(char* address_str)
{
- int result;
-
- int offsets[1];
- pcre *re;
- int rc;
- const char *error;
- int erroffset;
-
- re = pcre_compile("^((([1-9]\\d{0,2}|0)\\.){3}([1-9]\\d{0,2}|0))$",
- 0, &error, &erroffset, NULL);
- rc = pcre_exec(re, NULL, address_str, strlen(address_str), 0, 0, offsets, 1);
-
- if( rc < 0 )
- {
- result = RESULT_FAILURE;
- }
- else
- {
- result = RESULT_SUCCESS;
- }
-
- return(result);
+ return regex_matches("^((([1-9]\\d{0,2}|0)\\.){3}([1-9]\\d{0,2}|0))$",
+ address_str);
}
/* Is it an IPv6 address with prefix length? */
int is_ipv6_cidr(char* address_str)
{
- int result;
-
- int offsets[1];
- pcre *re;
- int rc;
- const char *error;
- int erroffset;
-
- re = pcre_compile("^((([0-9a-fA-F\\:])+)(\\/\\d{1,3}))$",
- 0, &error, &erroffset, NULL);
- rc = pcre_exec(re, NULL, address_str, strlen(address_str), 0, 0, offsets, 1);
-
- if( rc < 0 )
- {
- result = RESULT_FAILURE;
- }
- else
- {
- result = RESULT_SUCCESS;
- }
-
- return(result);
+ return regex_matches("^((([0-9a-fA-F\\:])+)(\\/\\d{1,3}))$", address_str);
}
/* Is it a single IPv6 address? */
int is_ipv6_single(char* address_str)
{
- int result;
-
- int offsets[1];
- pcre *re;
- int rc;
- const char *error;
- int erroffset;
-
- re = pcre_compile("^(([0-9a-fA-F\\:])+)$",
- 0, &error, &erroffset, NULL);
- rc = pcre_exec(re, NULL, address_str, strlen(address_str), 0, 0, offsets, 1);
-
- if( rc < 0 )
- {
- result = RESULT_FAILURE;
- }
- else
- {
- result = RESULT_SUCCESS;
- }
-
- return(result);
+ return regex_matches("^(([0-9a-fA-F\\:])+)$", address_str);
}
/* Is it a CIDR-formatted IPv4 or IPv6 address? */
@@ -527,3 +455,93 @@ int is_any_net(CIDR *address)
}
+int is_ipv4_range(char* range_str, int verbose)
+{
+ int result = RESULT_SUCCESS;
+
+ int regex_check_res = regex_matches("^([0-9\\.]+\\-[0-9\\.]+)$", range_str);
+
+ if( !regex_check_res )
+ {
+ if( verbose )
+ {
+ fprintf(stderr, "Malformed range %s: must be a pair of hyphen-separated IPv4 addresses\n", range_str);
+ }
+ result = RESULT_FAILURE;
+ }
+ else
+ {
+ /* Extract sub-components from the range string. */
+
+ /* Alocate memory for the components.
+ We know that an IPv4 address is always 15 characters or less, plus a null byte. */
+ char left[16];
+ char right[16];
+
+ /* Split the string at the hyphen.
+ If the regex check succeeded, we know the hyphen is there. */
+ char* ptr = left;
+ int length = strlen(range_str);
+ int pos = 0;
+ int index = 0;
+ while(pos < length)
+ {
+ if( range_str[pos] == '-' )
+ {
+ ptr[index] = '\0';
+ ptr = right;
+ index = 0;
+ }
+ else
+ {
+ ptr[index] = range_str[pos];
+ index++;
+ }
+
+ pos++;
+ }
+ ptr[index] = '\0';
+
+ if( !is_ipv4_single(left) )
+ {
+ if( verbose )
+ {
+ fprintf(stderr, "Malformed range %s: %s is not a valid IPv4 address\n", range_str, left);
+ }
+ result = RESULT_FAILURE;
+ }
+ else if( !is_ipv4_single(right) )
+ {
+ if( verbose )
+ {
+ fprintf(stderr, "Malformed range %s: %s is not a valid IPv4 address\n", range_str, right);
+ }
+ result = RESULT_FAILURE;
+ }
+ else
+ {
+ CIDR* left_addr = cidr_from_str(left);
+ CIDR* right_addr = cidr_from_str(right);
+ struct in_addr* left_in_addr = cidr_to_inaddr(left_addr, NULL);
+ struct in_addr* right_in_addr = cidr_to_inaddr(right_addr, NULL);
+
+ if( left_in_addr->s_addr < right_in_addr->s_addr )
+ {
+ result = RESULT_SUCCESS;
+ }
+ else
+ {
+ if( verbose )
+ {
+ fprintf(stderr, "Malformed IPv4 range %s: its first address is greater than the last\n", range_str);
+ }
+ result = RESULT_FAILURE;
+ }
+
+ cidr_free(left_addr);
+ cidr_free(right_addr);
+ }
+ }
+
+ return(result);
+}