diff options
author | Daniil Baturin <daniil@baturin.org> | 2013-06-02 05:53:13 -0700 |
---|---|---|
committer | Daniil Baturin <daniil@baturin.org> | 2013-06-02 05:53:13 -0700 |
commit | 83cf00e0117c4b41001a56f93cf4beae720cc6a0 (patch) | |
tree | f9be4ab75a0a7df11f1a35103987a83f218bb13a | |
parent | a64770739a28b05f6c5a033a3f2085959662b447 (diff) | |
download | ipaddrcheck-83cf00e0117c4b41001a56f93cf4beae720cc6a0.tar.gz ipaddrcheck-83cf00e0117c4b41001a56f93cf4beae720cc6a0.zip |
Add interface address validation support.
Fix IPv4 CIDR regex to support one-digit mask properly.
-rw-r--r-- | src/ipaddrcheck.c | 21 | ||||
-rw-r--r-- | src/ipaddrcheck_functions.c | 25 | ||||
-rw-r--r-- | src/ipaddrcheck_functions.h | 7 | ||||
-rw-r--r-- | tests/check_ipaddrcheck.c | 24 |
4 files changed, 72 insertions, 5 deletions
diff --git a/src/ipaddrcheck.c b/src/ipaddrcheck.c index 8b99b23..cc0a26b 100644 --- a/src/ipaddrcheck.c +++ b/src/ipaddrcheck.c @@ -47,6 +47,8 @@ #define IS_VALID_INTF_ADDR 220 #define IS_ANY_CIDR 230 #define IS_ANY_SINGLE 240 +#define ALLOW_LOOPBACK 250 +#define NO_ACTION 500 static const struct option options[] = { @@ -71,7 +73,7 @@ static const struct option options[] = { "is-ipv6-multicast", no_argument, NULL, 's' }, { "is-ipv6-link-local", no_argument, NULL, 't' }, { "is-valid-intf-address", no_argument, NULL, 'u' }, - { "legacy", no_argument, NULL, 'w' }, + { "allow-loopback", no_argument, NULL, 'C' }, { "version", no_argument, NULL, 'z' }, { "help", no_argument, NULL, '?' }, { NULL, no_argument, NULL, 0 } @@ -91,6 +93,9 @@ int main(int argc, char* argv[]) int option_index = 0; /* Number of the current option for getopt call */ int optc; /* Option character for getopt call */ + int allow_loopback = NO_LOOPBACK; /* Allow IPv4 loopback in --is-valid-intf-address */ + + /* Parse options, convert to action codes, store in array */ /* Try to allocate memory for the actions array, abort if fail */ @@ -101,7 +106,7 @@ int main(int argc, char* argv[]) return(EXIT_FAILURE); } - while( (optc = getopt_long(argc, argv, "acdefghijklmnoprstuzAB?", options, &option_index)) != -1 ) + while( (optc = getopt_long(argc, argv, "acdefghijklmnoprstuzABC?", options, &option_index)) != -1 ) { switch(optc) { @@ -169,6 +174,10 @@ int main(int argc, char* argv[]) case 'B': action = IS_ANY_SINGLE; break; + case 'C': + allow_loopback = LOOPBACK_ALLOWED; + action = NO_ACTION; + break; case '?': print_help(); return(0); @@ -273,6 +282,14 @@ int main(int argc, char* argv[]) case IS_ANY_SINGLE: result = is_any_single(address_str); break; + case IS_VALID_INTF_ADDR: + printf("allow_loopback: %d\n", allow_loopback); + result = is_valid_intf_address(address, address_str, allow_loopback); + break; + case NO_ACTION: + break; + default: + break; } printf("action: %d\n", actions[action_count]); action_count--; diff --git a/src/ipaddrcheck_functions.c b/src/ipaddrcheck_functions.c index dfcdcfb..0240914 100644 --- a/src/ipaddrcheck_functions.c +++ b/src/ipaddrcheck_functions.c @@ -48,7 +48,7 @@ int is_ipv4_cidr(char* address_str) const char *error; int erroffset; - re = pcre_compile("^((([1-9]\\d{0,2}|0)\\.){3}([1-9]\\d{0,2}|0)(\\/([1-3][0-9]|0)))$", + 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); @@ -443,3 +443,26 @@ int is_ipv6_link_local(CIDR *address) return(result); } +/* Is it an address that can belong an interface? */ +int is_valid_intf_address(CIDR *address, char* address_str, int allow_loopback) +{ + int result; + + if( (is_ipv4_broadcast(address) == RESULT_FAILURE) && + (is_ipv4_multicast(address) == RESULT_FAILURE) && + (is_ipv6_multicast(address) == RESULT_FAILURE) && + ((is_ipv4_loopback(address) == RESULT_FAILURE) || (allow_loopback == LOOPBACK_ALLOWED)) && + (cidr_equals(address, cidr_from_str(IPV6_LOOPBACK)) != 0) && + (cidr_equals(address, cidr_from_str(IPV4_UNSPECIFIED)) != 0) && + (cidr_contains(cidr_from_str(IPV4_THIS), address) != 0) && + (is_any_cidr(address_str) == RESULT_SUCCESS) ) + { + result = RESULT_SUCCESS; + } + else + { + result = RESULT_FAILURE; + } + + return(result); +} diff --git a/src/ipaddrcheck_functions.h b/src/ipaddrcheck_functions.h index 34bb18e..67cc410 100644 --- a/src/ipaddrcheck_functions.h +++ b/src/ipaddrcheck_functions.h @@ -37,11 +37,17 @@ #define IPV4_MULTICAST "224.0.0.0/4" #define IPV4_LOOPBACK "127.0.0.0/8" #define IPV4_LINKLOCAL "169.254.0.0/16" +#define IPV4_UNSPECIFIED "0.0.0.0/0" +#define IPV4_THIS "0.0.0.0/8" #define IPV4_RFC1918_A "10.0.0.0/8" #define IPV4_RFC1918_B "172.16.0.0/12" #define IPV4_RFC1918_C "192.168.0.0/16" #define IPV6_MULTICAST "ff00::/8" #define IPV6_LINKLOCAL "fe80::/64" +#define IPV6_LOOPBACK "::1/128" + +#define NO_LOOPBACK 0 +#define LOOPBACK_ALLOWED 1 int is_ipv4_cidr(char* address_str); int is_ipv4_single(char* address_str); @@ -63,3 +69,4 @@ int is_ipv6_host(CIDR *address); int is_ipv6_net(CIDR *address); int is_ipv6_multicast(CIDR *address); int is_ipv6_link_local(CIDR *address); +int is_valid_intf_address(CIDR *address, char* address_str, int allow_loopback); diff --git a/tests/check_ipaddrcheck.c b/tests/check_ipaddrcheck.c index ebf99b2..9315bec 100644 --- a/tests/check_ipaddrcheck.c +++ b/tests/check_ipaddrcheck.c @@ -43,8 +43,11 @@ END_TEST START_TEST (test_is_ipv4_cidr) { - char* good_address_str = "192.0.2.1/21"; - ck_assert_int_eq(is_ipv4_cidr(good_address_str), RESULT_SUCCESS); + char* good_address_str_1 = "192.0.2.1/8"; + ck_assert_int_eq(is_ipv4_cidr(good_address_str_1), RESULT_SUCCESS); + + char* good_address_str_2 = "192.0.2.1/21"; + ck_assert_int_eq(is_ipv4_cidr(good_address_str_2), RESULT_SUCCESS); char* address_str_no_mask = "192.0.2.1"; ck_assert_int_eq(is_ipv4_cidr(address_str_no_mask), RESULT_FAILURE); @@ -339,6 +342,22 @@ START_TEST (test_is_ipv6_link_local) } END_TEST +START_TEST (test_is_valid_intf_address) +{ + char* good_address_str_v4 = "192.0.2.5/24"; + CIDR* good_address_v4 = cidr_from_str(good_address_str_v4); + ck_assert_int_eq(is_valid_intf_address(good_address_v4, good_address_str_v4, NO_LOOPBACK), RESULT_SUCCESS); + cidr_free(good_address_v4); + + char* good_address_str_v6 = "2001:db8:a:b::14/64"; + CIDR* good_address_v6 = cidr_from_str(good_address_str_v6); + ck_assert_int_eq(is_valid_intf_address(good_address_v6, good_address_str_v6, NO_LOOPBACK), RESULT_SUCCESS); + cidr_free(good_address_v6); + + +} +END_TEST + Suite *ipaddrcheck_suite(void) { @@ -366,6 +385,7 @@ Suite *ipaddrcheck_suite(void) tcase_add_test(tc_core, test_is_ipv6_net); tcase_add_test(tc_core, test_is_ipv6_multicast); tcase_add_test(tc_core, test_is_ipv6_link_local); + tcase_add_test(tc_core, test_is_valid_intf_address); suite_add_tcase(s, tc_core); |