From 038dcd982d442d894c467bf0d91cdaf421e87185 Mon Sep 17 00:00:00 2001 From: Daniil Baturin Date: Mon, 27 May 2013 02:37:44 -0700 Subject: Again, multiple enhancements. * IPv6 feature set nearly complete. * Test suite expanded to cover all but a few functions. * Source files renamed according to the new project name, .h is now .h, implementations are moved to .c * Something else. --- src/Makefile.am | 2 +- src/ipaddrcheck.c | 307 ++++++++++++++++++++++++++++++++++++ src/ipaddrcheck_functions.c | 369 ++++++++++++++++++++++++++++++++++++++++++++ src/ipaddrcheck_functions.h | 40 +++++ src/iptest.c | 277 --------------------------------- src/iptest.h | 310 ------------------------------------- 6 files changed, 717 insertions(+), 588 deletions(-) create mode 100644 src/ipaddrcheck.c create mode 100644 src/ipaddrcheck_functions.c create mode 100644 src/ipaddrcheck_functions.h delete mode 100644 src/iptest.c delete mode 100644 src/iptest.h (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index f30438f..6612d3e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,7 +1,7 @@ AM_CFLAGS = --pedantic -Wall -Werror -std=c99 -O2 AM_LDFLAGS = -ipaddrcheck_SOURCES = iptest.c iptest.h +ipaddrcheck_SOURCES = ipaddrcheck.c ipaddrcheck_functions.c ipaddrcheck_LDFLAGS = -lcidr -lpcre bin_PROGRAMS = ipaddrcheck diff --git a/src/ipaddrcheck.c b/src/ipaddrcheck.c new file mode 100644 index 0000000..929da6b --- /dev/null +++ b/src/ipaddrcheck.c @@ -0,0 +1,307 @@ +/* + * iptest.c: iptest IPv4/IPv6 validator + * + * Maintainer: Daniil Baturin + * + * Copyright (C) 2013 SO3Group + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include +#include "config.h" +#include "ipaddrcheck_functions.h" + +/* Option codes */ +#define IS_VALID 10 +#define IS_IPV4 20 +#define IS_IPV4_CIDR 30 +#define IS_IPV4_SINGLE 40 +#define IS_IPV4_HOST 50 +#define IS_IPV4_NET 60 +#define IS_IPV4_BROADCAST 70 +#define IS_IPV4_UNICAST 80 +#define IS_IPV4_MULTICAST 90 +#define IS_IPV4_RFC1918 100 +#define IS_IPV4_LOOPBACK 110 +#define IS_IPV4_LINKLOCAL 120 +#define IS_IPV6 130 +#define IS_IPV6_CIDR 140 +#define IS_IPV6_SINGLE 150 +#define IS_IPV6_HOST 160 +#define IS_IPV6_NET 170 +#define IS_IPV6_UNICAST 180 +#define IS_IPV6_MULTICAST 190 +#define IS_IPV6_LINKLOCAL 200 +#define HAS_MASK 210 +#define IS_VALID_INTF_ADDR 220 + +static const struct option options[] = +{ + { "is-valid", no_argument, NULL, 'a' }, + { "has-mask", no_argument, NULL, 'b' }, + { "is-ipv4", no_argument, NULL, 'c' }, + { "is-ipv4-cidr", no_argument, NULL, 'd' }, + { "is-ipv4-single", no_argument, NULL, 'e' }, + { "is-ipv4-host", no_argument, NULL, 'f' }, + { "is-ipv4-net", no_argument, NULL, 'g' }, + { "is-ipv4-broadcast", no_argument, NULL, 'h' }, + { "is-ipv4-multicast", no_argument, NULL, 'i' }, + { "is-ipv4-loopback", no_argument, NULL, 'j' }, + { "is-ipv4-link-local", no_argument, NULL, 'k' }, + { "is-ipv4-rfc1918", no_argument, NULL, 'l' }, + { "is-ipv6", no_argument, NULL, 'm' }, + { "is-ipv6-cidr", no_argument, NULL, 'n' }, + { "is-ipv6-single", no_argument, NULL, 'o' }, + { "is-ipv6-host", no_argument, NULL, 'p' }, + { "is-ipv6-net", no_argument, NULL, 'r' }, + { "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' }, + { "version", no_argument, NULL, 'z' }, + { NULL, no_argument, NULL, 0 } +}; + +/* Auxillary functions */ +static void print_help(void); +static void print_version(void); + +int main(int argc, char* argv[]) +{ + char *address_str = ""; /* IP address string obtained from arguments */ + int action = 0; /* Action associated with given check option */ + int* actions; /* Array of all given actions */ + int action_count = 0; /* Actions array size */ + + int option_index = 0; /* Number of the current option for getopt call */ + int optc; /* Option character for getopt call */ + + /* Parse options, convert to action codes, store in array */ + + /* Try to allocate memory for the actions array, abort if fail */ + actions = (int*)calloc(argc, sizeof(int)); + if( errno == ENOMEM ) + { + fprintf(stderr, "Error: could not allocate memory!\n"); + return(EXIT_FAILURE); + } + + while( (optc = getopt_long(argc, argv, "abcdefghijklmnoprstuz?", options, &option_index)) != -1 ) + { + switch(optc) + { + case 'a': + action = IS_VALID; + break; + case 'b': + action = HAS_MASK; + break; + case 'c': + action = IS_IPV4; + break; + case 'd': + action = IS_IPV4_CIDR; + break; + case 'e': + action = IS_IPV4_SINGLE; + break; + case 'f': + action = IS_IPV4_HOST; + break; + case 'g': + action = IS_IPV4_NET; + case 'h': + action = IS_IPV4_BROADCAST; + break; + case 'i': + action = IS_IPV4_MULTICAST; + break; + case 'j': + action = IS_IPV4_LOOPBACK; + break; + case 'k': + action = IS_IPV4_LINKLOCAL; + break; + case 'l': + action = IS_IPV4_RFC1918; + break; + case 'm': + action = IS_IPV6; + break; + case 'n': + action = IS_IPV6_CIDR; + break; + case 'o': + action = IS_IPV6_SINGLE; + break; + case 'p': + action = IS_IPV6_HOST; + break; + case 'r': + action = IS_IPV6_NET; + break; + case 's': + action = IS_IPV6_MULTICAST; + break; + case 't': + action = IS_IPV6_LINKLOCAL; + break; + case 'u': + action = IS_VALID_INTF_ADDR; + break; + case '?': + print_help(); + return(0); + case 'z': + print_version(); + return(0); + default: + fprintf(stderr, "Error: invalid option\n"); + break; + } + + action_count = optind-2; + actions[action_count] = action; + } + + /* Get non-option arguments */ + if( (argc - optind) == 1 ) + { + address_str = argv[optind]; + } + else + { + fprintf(stderr, "Error: wrong number of arguments, one argument required!\n"); + print_help(); + return(EXIT_FAILURE); + } + + CIDR *address; + address = cidr_from_str(address_str); + int result = RESULT_SUCCESS; + + /* Check if the address is valid at all, + if not there is no point in going further */ + if( is_valid_address(address) != RESULT_SUCCESS ) + { + return(EXIT_FAILURE); + } + + printf("action_count: %d\n", action_count); + while( (action_count >= 0) && (result == RESULT_SUCCESS) ) + { + switch(actions[action_count]) + { + case IS_VALID: + result = is_valid_address(address); + break; + case HAS_MASK: + result = has_mask(address_str); + break; + case IS_IPV4: + result = is_ipv4(address); + break; + case IS_IPV4_CIDR: + result = is_ipv4_cidr(address_str); + break; + case IS_IPV4_SINGLE: + result = is_ipv4_single(address_str); + break; + case IS_IPV4_HOST: + result = is_ipv4_host(address); + break; + case IS_IPV4_NET: + /* XXX: Should we fail this check for single addresses? */ + result = is_ipv4_net(address); + break; + case IS_IPV4_BROADCAST: + result = is_ipv4_broadcast(address); + break; + case IS_IPV4_MULTICAST: + result = is_ipv4_multicast(address); + break; + case IS_IPV4_LOOPBACK: + result = is_ipv4_loopback(address); + break; + case IS_IPV4_LINKLOCAL: + result = is_ipv4_link_local(address); + break; + case IS_IPV4_RFC1918: + result = is_ipv4_rfc1918(address); + break; + case IS_IPV6: + result = is_ipv6(address); + break; + case IS_IPV6_CIDR: + break; + case IS_IPV6_SINGLE: + break; + case IS_IPV6_HOST: + result = is_ipv6_host(address); + break; + case IS_IPV6_NET: + result = is_ipv6_net(address); + break; + case IS_IPV6_MULTICAST: + result = is_ipv6_multicast(address); + break; + case IS_IPV6_LINKLOCAL: + result = is_ipv6_link_local(address); + break; + } + printf("action: %d\n", actions[action_count]); + action_count--; + } + + /* Clean up */ + free(actions); + cidr_free(address); + + if( result == RESULT_SUCCESS ) + { + return(EXIT_SUCCESS); + } + else + { + return(EXIT_FAILURE); + } +} + +/* + * Print help, no other side effects + */ +void print_help(void) +{ + static const char *message = \ +"--is-valid STR Check if STR is a valid IPv4 or IPv6 address\n\ + or subnet\n\ +--is-ipv4 STR Check if STR is a valid IPv4 address with mask\n"; + + printf("%s", message); +} + +/* + * Print version information, no other side effects + */ +void print_version(void) +{ + printf("%s %s\n", PACKAGE_NAME, PACKAGE_VERSION); + printf("Copyright (C) SO3Group 2013.\n\ +License GPLv2+: GNU GPL version 2 or later \n\ +This is free software: you are free to change and redistribute it.\n\ +There is NO WARRANTY, to the extent permitted by law.\n"); +} + + diff --git a/src/ipaddrcheck_functions.c b/src/ipaddrcheck_functions.c new file mode 100644 index 0000000..1006383 --- /dev/null +++ b/src/ipaddrcheck_functions.c @@ -0,0 +1,369 @@ +/* + * ipaddrcheck_functions.c: functions for iptest IPv4/IPv6 validator + * + * Maintainer: Daniil Baturin + * + * Copyright (C) 2013 SO3Group + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + * + */ + +#include "ipaddrcheck_functions.h" + +/* + * Address string functions + * + * Note that they perform format check only + * and must not be used to deermine if it's + * a valid address, only what type of address + * format it is. + * + * The only reason they exist is that libcidr + * is very liberal on its input format and + * doesn't provide any information on what + * the format was. + */ + +/* Does it have mask? */ +int has_mask(char* address_str) +{ + int result; + char *hasslash = strchr(address_str, '/'); + + if( hasslash != NULL ) + { + result = RESULT_SUCCESS; + } + else + { + result = RESULT_FAILURE; + } + + return(result); +} + +/* 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("^\\d{1,3}.\\d{1,3}.\\d{1,3}.\\d{1,3}/\\d{1,2}$", + 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); +} + +/* 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("^\\d{1,3}.\\d{1,3}.\\d{1,3}.\\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); +} + +/* + * Address checking functions that rely on libcidr + */ + +/* Does it look like a valid address of any protocol? */ +int is_valid_address(CIDR *address) +{ + int result; + + if( cidr_get_proto(address) != INVALID_PROTO ) + { + result = RESULT_SUCCESS; + } + else + { + result = RESULT_FAILURE; + } + + return(result); +} + +/* Is it a correct IPv4 host or subnet address + with or without net mask */ +int is_ipv4(CIDR *address) +{ + int result; + + if( cidr_get_proto(address) == CIDR_IPV4 ) + { + result = RESULT_SUCCESS; + } + else + { + result = RESULT_FAILURE; + } + + return(result); +} + +/* Is it a correct IPv4 host (i.e. not network) address? */ +int is_ipv4_host(CIDR *address) +{ + int result; + + if( (cidr_get_proto(address) == CIDR_IPV4) && + ((cidr_equals(address, cidr_addr_network(address)) < 0) || + (cidr_get_pflen(address) == 32)) ) + { + result = RESULT_SUCCESS; + } + else + { + result = RESULT_FAILURE; + } + + return(result); +} + +/* Is it a correct IPv4 network address? */ +int is_ipv4_net(CIDR *address) +{ + int result; + + if( (cidr_get_proto(address) == CIDR_IPV4) && + (cidr_equals(address, cidr_addr_network(address)) == 0) ) + { + result = RESULT_SUCCESS; + } + else + { + result = RESULT_FAILURE; + } + + return(result); +} + +/* Is it an IPv4 broadcast address? */ +int is_ipv4_broadcast(CIDR *address) +{ + int result; + + if( cidr_equals(address, cidr_addr_broadcast(address)) == 0 ) + { + result = RESULT_SUCCESS; + } + else + { + result = RESULT_FAILURE; + } + + return(result); +} + +/* Is it an IPv4 multicast address? */ +int is_ipv4_multicast(CIDR *address) +{ + int result; + + if( (cidr_get_proto(address) == CIDR_IPV4) && + (cidr_contains(cidr_from_str(IPV4_MULTICAST), address) == 0) ) + { + result = RESULT_SUCCESS; + } + else + { + result = RESULT_FAILURE; + } + + return(result); +} + +/* Is it an IPv4 loopback address? */ +int is_ipv4_loopback(CIDR *address) +{ + int result; + + if( (cidr_get_proto(address) == CIDR_IPV4) && + (cidr_contains(cidr_from_str(IPV4_LOOPBACK), address) == 0) ) + { + result = RESULT_SUCCESS; + } + else + { + result = RESULT_FAILURE; + } + + return(result); +} + +/* Is it an IPv4 link-local address? */ +int is_ipv4_link_local(CIDR *address) +{ + int result; + + if( (cidr_get_proto(address) == CIDR_IPV4) && + (cidr_contains(cidr_from_str(IPV4_LINKLOCAL), address) == 0) ) + { + result = RESULT_SUCCESS; + } + else + { + result = RESULT_FAILURE; + } + + return(result); +} + +/* Is it an IPv4 RFC1918 address? */ +int is_ipv4_rfc1918(CIDR *address) +{ + int result; + + if( (cidr_get_proto(address) == CIDR_IPV4) && + ( (cidr_contains(cidr_from_str(IPV4_RFC1918_A), address) == 0) || + (cidr_contains(cidr_from_str(IPV4_RFC1918_B), address) == 0) || + (cidr_contains(cidr_from_str(IPV4_RFC1918_C), address) == 0) ) ) + { + result = RESULT_SUCCESS; + } + else + { + result = RESULT_FAILURE; + } + + return(result); +} + +/* is it a correct IPv6 host or subnet address, + with or withour mask */ +int is_ipv6(CIDR *address) +{ + int result; + + if( cidr_get_proto(address) == CIDR_IPV6 ) + { + result = RESULT_SUCCESS; + } + else + { + result = RESULT_FAILURE; + } + + return(result); +} + +/* Is it a correct IPv6 host address? */ +int is_ipv6_host(CIDR *address) +{ + int result; + + if( (cidr_get_proto(address) == CIDR_IPV6) && + ((cidr_equals(address, cidr_addr_network(address)) < 0) || + (cidr_get_pflen(address) == 128)) ) + { + result = RESULT_SUCCESS; + } + else + { + result = RESULT_FAILURE; + } + + return(result); +} + +/* Is it a correct IPv6 network address? */ +int is_ipv6_net(CIDR *address) +{ + int result; + + if( (cidr_get_proto(address) == CIDR_IPV6) && + (cidr_equals(address, cidr_addr_network(address)) == 0) ) + { + result = RESULT_SUCCESS; + } + else + { + result = RESULT_FAILURE; + } + + return(result); +} + +/* Is it an IPv6 multicast address? */ +int is_ipv6_multicast(CIDR *address) +{ + int result; + + if( (cidr_get_proto(address) == CIDR_IPV6) && + (cidr_contains(cidr_from_str(IPV6_MULTICAST), address) == 0) ) + { + result = RESULT_SUCCESS; + } + else + { + result = RESULT_FAILURE; + } + + return(result); +} + +/* Is it an IPv6 link-local address? */ +int is_ipv6_link_local(CIDR *address) +{ + int result; + + if( (cidr_get_proto(address) == CIDR_IPV6) && + (cidr_contains(cidr_from_str(IPV6_LINKLOCAL), address) == 0) ) + { + result = RESULT_SUCCESS; + } + else + { + result = RESULT_FAILURE; + } + + return(result); +} + diff --git a/src/ipaddrcheck_functions.h b/src/ipaddrcheck_functions.h new file mode 100644 index 0000000..756a8f3 --- /dev/null +++ b/src/ipaddrcheck_functions.h @@ -0,0 +1,40 @@ +#include +#include +#include +#include +#include +#include + +#define INVALID_PROTO -1 + +#define RESULT_SUCCESS 1 +#define RESULT_FAILURE 0 + +#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_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" + +int has_mask(char* address_str); +int is_ipv4_cidr(char* address_str); +int is_ipv4_single(char* address_str); +int is_valid_address(CIDR *address); +int is_ipv4(CIDR *address); +int is_ipv4_host(CIDR *address); +int is_ipv4_net(CIDR *address); +int is_ipv4_broadcast(CIDR *address); +int is_ipv4_multicast(CIDR *address); +int is_ipv4_loopback(CIDR *address); +int is_ipv4_link_local(CIDR *address); +int is_ipv4_rfc1918(CIDR *address); +int is_ipv6(CIDR *address); +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); + + diff --git a/src/iptest.c b/src/iptest.c deleted file mode 100644 index c618b20..0000000 --- a/src/iptest.c +++ /dev/null @@ -1,277 +0,0 @@ -/* - * iptest.c: iptest IPv4/IPv6 validator - * - * Maintainer: Daniil Baturin - * - * Copyright (C) 2013 SO3Group - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - -#include -#include "config.h" -#include "iptest.h" - -static const struct option options[] = -{ - { "is-valid", no_argument, NULL, 'a' }, - { "has-mask", no_argument, NULL, 'b' }, - { "is-ipv4", no_argument, NULL, 'c' }, - { "is-ipv4-cidr", no_argument, NULL, 'd' }, - { "is-ipv4-single", no_argument, NULL, 'e' }, - { "is-ipv4-host", no_argument, NULL, 'f' }, - { "is-ipv4-net", no_argument, NULL, 'g' }, - { "is-ipv4-broadcast", no_argument, NULL, 'h' }, - { "is-ipv4-multicast", no_argument, NULL, 'i' }, - { "is-ipv4-loopback", no_argument, NULL, 'j' }, - { "is-ipv4-link-local", no_argument, NULL, 'k' }, - { "is-ipv4-rfc1918", no_argument, NULL, 'l' }, - { "is-ipv6", no_argument, NULL, 'm' }, - { "is-ipv6-cidr", no_argument, NULL, 'n' }, - { "is-ipv6-single", no_argument, NULL, 'o' }, - { "is-ipv6-host", no_argument, NULL, 'p' }, - { "is-ipv6-net", no_argument, NULL, 'r' }, - { "is-ipv6-multicast", no_argument, NULL, 's' }, - { "is-ipv6-link-local", no_argument, NULL, 't' }, - { "is-valid-intf-address", no_argument, NULL, 'u' }, - { "version", no_argument, NULL, 'z' }, - { NULL, no_argument, NULL, 0 } -}; - -/* Auxillary functions */ -static void print_help(void); -static void print_version(void); - -int main(int argc, char* argv[]) -{ - char *address_str = ""; /* IP address string obtained from arguments */ - int action = 0; /* Action associated with given check option */ - int* actions; /* Array of all given actions */ - int action_count = 0; /* Actions array size */ - - int option_index = 0; /* Number of the current option for getopt call */ - int optc; /* Option character for getopt call */ - - /* Parse options, convert to action codes, store in array */ - - /* Try to allocate memory for the actions array, abort if fail */ - actions = (int*)calloc(argc, sizeof(int)); - if( errno == ENOMEM ) - { - fprintf(stderr, "Error: could not allocate memory!\n"); - return(EXIT_FAILURE); - } - - while( (optc = getopt_long(argc, argv, "abcdv?", options, &option_index)) != -1 ) - { - switch(optc) - { - case 'a': - action = IS_VALID; - break; - case 'b': - action = HAS_MASK; - break; - case 'c': - action = IS_IPV4; - break; - case 'd': - action = IS_IPV4_CIDR; - break; - case 'e': - action = IS_IPV4_SINGLE; - break; - case 'f': - action = IS_IPV4_HOST; - break; - case 'g': - action = IS_IPV4_NET; - case 'h': - action = IS_IPV4_BROADCAST; - break; - case 'i': - action = IS_IPV4_MULTICAST; - break; - case 'j': - action = IS_IPV4_LOOPBACK; - break; - case 'k': - action = IS_IPV4_LINKLOCAL; - break; - case 'l': - action = IS_IPV4_RFC1918; - break; - case 'm': - action = IS_IPV6; - break; - case 'n': - action = IS_IPV6_CIDR; - break; - case 'o': - action = IS_IPV6_SINGLE; - break; - case 'p': - action = IS_IPV6_HOST; - break; - case 'r': - action = IS_IPV6_NET; - break; - case 's': - action = IS_IPV6_MULTICAST; - break; - case 't': - action = IS_IPV6_LINKLOCAL; - break; - case 'u': - action = IS_VALID_INTF_ADDR; - break; - case '?': - print_help(); - return(0); - case 'z': - print_version(); - return(0); - default: - fprintf(stderr, "Error: invalid option\n"); - break; - } - - action_count = optind-2; - actions[action_count] = action; - } - - /* Get non-option arguments */ - if( (argc - optind) == 1 ) - { - address_str = argv[optind]; - printf("%s\n", address_str); - } - else - { - fprintf(stderr, "Error: wrong number of arguments, one argument required!\n"); - print_help(); - return(EXIT_FAILURE); - } - - CIDR *address; - address = cidr_from_str(address_str); - int result = RESULT_SUCCESS; - - /* Check if the address is valid at all, - if not there is no point in going further */ - if( is_valid_address(address) != RESULT_SUCCESS ) - { - return(EXIT_FAILURE); - } - - printf("action_count: %d\n", action_count); - while( (action_count >= 0) && (result == RESULT_SUCCESS) ) - { - switch(actions[action_count]) - { - case IS_VALID: - result = is_valid_address(address); - break; - case HAS_MASK: - result = has_mask(address_str); - break; - case IS_IPV4: - result = is_ipv4(address); - break; - case IS_IPV4_CIDR: - result = is_ipv4_cidr(address_str); - break; - case IS_IPV4_SINGLE: - if( !(is_ipv4(address) && has_mask(address_str)) ) - { - result = RESULT_FAILURE; - } - /* No need to change it in case of success */ - break; - case IS_IPV4_HOST: - result = is_ipv4_host(address); - break; - case IS_IPV4_NET: - /* XXX: Should we fail this check for single addresses? */ - result = is_ipv4_net(address); - break; - case IS_IPV4_BROADCAST: - result = is_ipv4_broadcast(address); - break; - case IS_IPV4_MULTICAST: - result = is_ipv4_multicast(address); - break; - case IS_IPV4_LOOPBACK: - result = is_ipv4_loopback(address); - break; - case IS_IPV4_LINKLOCAL: - result = is_ipv4_link_local(address); - break; - case IS_IPV4_RFC1918: - result = is_ipv4_rfc1918(address); - break; - case IS_IPV6: - result = is_ipv6(address); - break; - case IS_IPV6_HOST: - result = is_ipv6_host(address); - break; - case IS_IPV6_NET: - result = is_ipv6_net(address); - break; - } - printf("action: %d\n", actions[action_count]); - action_count--; - } - - /* Clean up */ - free(actions); - cidr_free(address); - - if( result == RESULT_SUCCESS ) - { - return(EXIT_SUCCESS); - } - else - { - return(EXIT_FAILURE); - } -} - -/* - * Print help, no other side effects - */ -void print_help(void) -{ - static const char *message = \ -"--is-valid STR Check if STR is a valid IPv4 or IPv6 address\n\ - or subnet\n\ ---is-ipv4 STR Check if STR is a valid IPv4 address with mask\n"; - - printf("%s", message); -} - -/* - * Print version information, no other side effects - */ -void print_version(void) -{ - printf("%s %s\n", PACKAGE_NAME, PACKAGE_VERSION); - printf("Copyright (C) SO3Group 2013.\n\ -License GPLv2+: GNU GPL version 2 or later \n\ -This is free software: you are free to change and redistribute it.\n\ -There is NO WARRANTY, to the extent permitted by law.\n"); -} - - diff --git a/src/iptest.h b/src/iptest.h deleted file mode 100644 index f025911..0000000 --- a/src/iptest.h +++ /dev/null @@ -1,310 +0,0 @@ -/* - * ipaddrcheck.h: macros and functions for iptest IPv4/IPv6 validator - * - * Maintainer: Daniil Baturin - * - * Copyright (C) 2013 SO3Group - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * - * - */ - - -#include -#include -#include -#include -#include -#include - -#define INVALID_PROTO -1 - -/* Option codes */ -#define IS_VALID 10 -#define IS_IPV4 20 -#define IS_IPV4_CIDR 30 -#define IS_IPV4_SINGLE 40 -#define IS_IPV4_HOST 50 -#define IS_IPV4_NET 60 -#define IS_IPV4_BROADCAST 70 -#define IS_IPV4_UNICAST 80 -#define IS_IPV4_MULTICAST 90 -#define IS_IPV4_RFC1918 100 -#define IS_IPV4_LOOPBACK 110 -#define IS_IPV4_LINKLOCAL 120 -#define IS_IPV6 130 -#define IS_IPV6_CIDR 140 -#define IS_IPV6_SINGLE 150 -#define IS_IPV6_HOST 160 -#define IS_IPV6_NET 170 -#define IS_IPV6_UNICAST 180 -#define IS_IPV6_MULTICAST 190 -#define IS_IPV6_LINKLOCAL 200 -#define HAS_MASK 210 -#define IS_VALID_INTF_ADDR 220 - -#define RESULT_SUCCESS 1 -#define RESULT_FAILURE 0 - -#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_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" - -/* - * Address string functions - * - * Note that they perform format check only - * and must not be used to deermine if it's - * a valid address, only what type of address - * format it is. - * - * The only reason they exist is that libcidr - * is very liberal on its input format and - * doesn't provide any information on what - * the format was. - */ - -/* Does it have mask? */ -int has_mask(char* address_str) -{ - int result; - char *hasslash = strchr(address_str, '/'); - - if( hasslash != NULL ) - { - result = RESULT_SUCCESS; - } - else - { - result = RESULT_FAILURE; - } - - return(result); -} - -/* 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("^\\d{1,3}.\\d{1,3}.\\d{1,3}.\\d{1,3}/\\d{1,2}$", - 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); -} - - -/* - * Address checking functions that rely on libcidr - */ - -/* Does it look like a valid address of any protocol? */ -int is_valid_address(CIDR *address) -{ - int result; - - if( cidr_get_proto(address) != INVALID_PROTO ) - { - result = RESULT_SUCCESS; - } - else - { - result = RESULT_FAILURE; - } - - return(result); -} - -/* Is it a correct IPv4 host or subnet address - with or without net mask */ -int is_ipv4(CIDR *address) -{ - int result; - - if( cidr_get_proto(address) == CIDR_IPV4 ) - { - result = RESULT_SUCCESS; - } - else - { - result = RESULT_FAILURE; - } - - return(result); -} - -/* Is it a correct IPv4 host (i.e. not network) address? */ -int is_ipv4_host(CIDR *address) -{ - int result; - - if( (cidr_get_proto(address) == CIDR_IPV4) && - ((cidr_equals(address, cidr_addr_network(address)) < 0) || - (cidr_get_pflen(address) == 32)) ) - { - result = RESULT_SUCCESS; - } - else - { - result = RESULT_FAILURE; - } - - return(result); -} - -/* Is it a correct IPv4 network address? */ -int is_ipv4_net(CIDR *address) -{ - int result; - - if( (cidr_get_proto(address) == CIDR_IPV4) && - (cidr_equals(address, cidr_addr_network(address)) == 0) ) - { - result = RESULT_SUCCESS; - } - else - { - result = RESULT_FAILURE; - } - - return(result); -} - -/* Is it an IPv4 broadcast address? */ -int is_ipv4_broadcast(CIDR *address) -{ - int result; - - if( cidr_equals(address, cidr_addr_broadcast(address)) == 0 ) - { - result = RESULT_SUCCESS; - } - else - { - result = RESULT_FAILURE; - } - - return(result); -} - -/* Is it an IPv4 multicast address? */ -int is_ipv4_multicast(CIDR *address) -{ - int result; - - if( (cidr_get_proto(address) == CIDR_IPV4) && - (cidr_contains(cidr_from_str(IPV4_MULTICAST), address) == 0) ) - { - result = RESULT_SUCCESS; - } - else - { - result = RESULT_FAILURE; - } - - return(result); -} - -/* Is it an IPv4 loopback address? */ -int is_ipv4_loopback(CIDR *address) -{ - int result; - - if( (cidr_get_proto(address) == CIDR_IPV4) && - (cidr_contains(cidr_from_str(IPV4_LOOPBACK), address) == 0) ) - { - result = RESULT_SUCCESS; - } - else - { - result = RESULT_FAILURE; - } - - return(result); -} - -/* Is it an IPv4 link-local address? */ -int is_ipv4_link_local(CIDR *address) -{ - int result; - - if( (cidr_get_proto(address) == CIDR_IPV4) && - (cidr_contains(cidr_from_str(IPV4_LINKLOCAL), address) == 0) ) - { - result = RESULT_SUCCESS; - } - else - { - result = RESULT_FAILURE; - } - - return(result); -} - -/* Is it an IPv4 RFC1918 address? */ -int is_ipv4_rfc1918(CIDR *address) -{ - int result; - - if( (cidr_get_proto(address) == CIDR_IPV4) && - ( (cidr_contains(cidr_from_str(IPV4_RFC1918_A), address) == 0) || - (cidr_contains(cidr_from_str(IPV4_RFC1918_B), address) == 0) || - (cidr_contains(cidr_from_str(IPV4_RFC1918_C), address) == 0) ) ) - { - result = RESULT_SUCCESS; - } - else - { - result = RESULT_FAILURE; - } - - return(result); -} - -/* is it a correct IPv6 host or subnet address, - with or withour mask */ -int is_ipv6(CIDR *address) -{ - return RESULT_FAILURE; -} - -int is_ipv6_host(CIDR *address) -{ - return RESULT_FAILURE; -} - -int is_ipv6_net(CIDR *address) -{ - return RESULT_FAILURE; -} -- cgit v1.2.3