From 93022c0cc6c22b3a30ded3e109a3fe0a0dce8ca0 Mon Sep 17 00:00:00 2001 From: Kaushal M Date: Wed, 7 Mar 2012 13:06:38 +0530 Subject: mgmt/glusterd : volume set validation fixes This is the new version of the patch by Kaushik at review.gluster.com/699 The following new option types have been introduced: * GF_OPTION_TYPE_INTERNET_ADDRESS_LIST * GF_OPTION_TYPE_PRIORITY_LIST * GF_OPTION_TYPE_SIZE_LIST and option types of several options in translators have been updated to use the new types. valid_internet_address(), valid_ipv4_address() & valid_ipv6_address() functions has been updated for * wildcard matching. Previously used standalone wildcard address checking functions have been removed. Changes have been done to stripe translator to correctly set, update and use stripe-blocksize. Also minimum value for block-size has been set to 16KB. Change-Id: I2aa484ff695f6a915a8fc9a9f965cf0344f41d59 BUG: 765248 Signed-off-by: Kaushal M Reviewed-on: http://review.gluster.com/2899 Tested-by: Gluster Build System Reviewed-by: Shishir Gowda Reviewed-by: Anand Avati --- libglusterfs/src/common-utils.c | 219 +++++++++++++++------------------------- libglusterfs/src/common-utils.h | 6 +- libglusterfs/src/options.c | 183 ++++++++++++++++++++++++++++++++- libglusterfs/src/options.h | 3 + 4 files changed, 269 insertions(+), 142 deletions(-) (limited to 'libglusterfs') diff --git a/libglusterfs/src/common-utils.c b/libglusterfs/src/common-utils.c index 952af10cfd0..f26d2bdc318 100644 --- a/libglusterfs/src/common-utils.c +++ b/libglusterfs/src/common-utils.c @@ -1586,47 +1586,79 @@ get_nth_word (const char *str, int n) } /* RFC 1123 & 952 */ - -/* The functions below validate given internet addresses and - * wildcard internet address for correctness. - * All return 1 on success and 0 on failure - */ - +/* Syntax formed combining RFC 1123 & 952 * + ::= *["."] * + ::= <[*[]] + ::= [*[]] */ char valid_host_name (char *address, int length) { - int i = 0; - char ret = 0; - int flag = 0; + int i = 0; + int str_len = 0; + char ret = 1; + char *dup_addr = NULL; + char *temp_str = NULL; + char *save_ptr = NULL; - if ((length > 255) || (length == 1)) + if ((length > _POSIX_HOST_NAME_MAX) || (length == 1)) { + ret = 0; goto out; + } - if (!isalnum (address[length - 1])) + dup_addr = gf_strdup (address); + if (!dup_addr) { + ret = 0; goto out; + } + temp_str = strtok_r (dup_addr,".", &save_ptr); - for (i = 0; i < length; i++) { - if (!isalnum (address[i]) && (address[i] != '.') - && (address[i] != '-')) + /* first-name */ + if (!temp_str || + !isalnum(temp_str[0]) || + !isalnum (temp_str[strlen(temp_str)-1])) { + ret = 0; + goto out; + } + for (i = 1; i < (strlen (temp_str) - 1); i++) { + if (!isalnum (temp_str[i]) && (temp_str[i] != '-')) { + ret = 0; goto out; + } + } - if (isalpha(address[i])) - flag = 1; + /* gen-name */ + while ((temp_str = strtok_r (NULL, ".", &save_ptr))) { + str_len = strlen (temp_str); + + if (!isalpha (temp_str[0]) || + !isalnum (temp_str[str_len-1])) { + ret = 0; + goto out; + } + for (i = 1; i < str_len; i++) { + if (!isalnum (temp_str[i]) && (temp_str[i] != '-')) { + ret = 0; + goto out; + } + } } - if (flag) - ret = 1; out: + if (dup_addr) + GF_FREE (dup_addr); return ret; } +/* Matches all ipv4 address, if wildcard_acc is true '*' wildcard pattern for* + subnets is considerd as valid strings as well */ char -valid_ipv4_address (char *address, int length) +valid_ipv4_address (char *address, int length, gf_boolean_t wildcard_acc) { int octets = 0; int value = 0; char *tmp = NULL, *ptr = NULL, *prev = NULL, *endptr = NULL; - char ret = 0; + char ret = 1; + int is_wildcard = 0; tmp = gf_strdup (address); prev = tmp; @@ -1634,15 +1666,22 @@ valid_ipv4_address (char *address, int length) while (prev != NULL) { octets++; - value = strtol (prev, &endptr, 10); - if ((value > 255) || (value < 0) || - (endptr != NULL && *endptr != '\0')) - goto out; + if (wildcard_acc && !strcmp (prev, "*")) { + is_wildcard = 1; + } else { + value = strtol (prev, &endptr, 10); + if ((value > 255) || (value < 0) || + (endptr != NULL && *endptr != '\0')) { + ret = 0; + goto out; + } + } prev = strtok_r (NULL, ".", &ptr); } - if (octets == 4) - ret = 1; + if ((octets > 4) || (octets < 4 && !is_wildcard)) { + ret = 0; + } out: GF_FREE (tmp); @@ -1650,27 +1689,35 @@ out: } char -valid_ipv6_address (char *address, int length) +valid_ipv6_address (char *address, int length, gf_boolean_t wildcard_acc) { int hex_numbers = 0; int value = 0; char *tmp = NULL, *ptr = NULL, *prev = NULL, *endptr = NULL; - char ret = 0; + char ret = 1; + int is_wildcard = 0; tmp = gf_strdup (address); prev = strtok_r (tmp, ":", &ptr); while (prev != NULL) { hex_numbers++; - value = strtol (prev, &endptr, 16); - if ((value > 0xffff) || (value < 0) - || (endptr != NULL && *endptr != '\0')) - goto out; + if (wildcard_acc && !strcmp (prev, "*")) { + is_wildcard = 1; + } else { + value = strtol (prev, &endptr, 16); + if ((value > 0xffff) || (value < 0) + || (endptr != NULL && *endptr != '\0')) { + ret = 0; + goto out; + } + } prev = strtok_r (NULL, ":", &ptr); } - if (hex_numbers <= 8) - ret = 1; + if ((hex_numbers > 8) || (hex_numbers < 8 && !is_wildcard)) { + ret = 0; + } out: GF_FREE (tmp); @@ -1678,7 +1725,7 @@ out: } char -valid_internet_address (char *address) +valid_internet_address (char *address, gf_boolean_t wildcard_acc) { char ret = 0; int length = 0; @@ -1692,8 +1739,8 @@ valid_internet_address (char *address) if (length == 0) goto out; - if (valid_ipv4_address (address, length) - || valid_ipv6_address (address, length) + if (valid_ipv4_address (address, length, wildcard_acc) + || valid_ipv6_address (address, length, wildcard_acc) || valid_host_name (address, length)) ret = 1; @@ -1701,104 +1748,6 @@ out: return ret; } -char -valid_ipv4_wildcard_check (char *address) -{ - char ret = 0; - int octets = 0; - char *tmp = NULL; - char *prev = NULL; - char *endptr = NULL; - int value = 0; - int is_wildcard = 0; - - tmp = gf_strdup (address); - prev = strtok (tmp, "."); - - while (prev != NULL) { - octets++; - - if (!strcmp (prev, "*")) { - is_wildcard = 1; - } else { - value = strtol (prev, &endptr, 10); - - if ((value > 255) || (value < 0) || - (endptr != NULL && *endptr != '\0')) - goto out; - } - prev = strtok (NULL, "."); - } - - if (is_wildcard && (octets <= 4)) - ret = 1; - -out: - if (tmp) - GF_FREE (tmp); - return ret; - -} - -char -valid_ipv6_wildcard_check (char *address) -{ - char ret = 0; - int hex_numbers = 0; - int value = 0; - char *tmp = NULL; - char *prev = NULL; - char *endptr = NULL; - int is_wildcard = 0; - - tmp = gf_strdup (address); - prev = strtok (tmp, ":"); - - while (prev != NULL) { - hex_numbers++; - - if (!strcmp (prev, "*")) { - is_wildcard = 1; - } else { - value = strtol (prev, &endptr, 16); - - if ((value > 0xffff) || (value < 0) || - (endptr != NULL && *endptr != '\0')) - goto out; - } - prev = strtok (NULL, ":"); - } - - if (is_wildcard && (hex_numbers <= 8)) - ret = 1; -out: - if (tmp) - GF_FREE (tmp); - return ret; -} - -char -valid_wildcard_internet_address (char *address) -{ - char ret = 0; - - if (address == NULL) { - gf_log_callingfn (THIS->name, GF_LOG_WARNING, - "argument invalid"); - goto out; - } - - if (strlen (address) == 0) - goto out; - - if (valid_ipv4_wildcard_check (address) || - valid_ipv6_wildcard_check (address)) - ret = 1; - -out: - return ret; -} - /*Thread safe conversion function*/ char * uuid_utoa (uuid_t uuid) diff --git a/libglusterfs/src/common-utils.h b/libglusterfs/src/common-utils.h index 8c9b26f76d9..33551779974 100644 --- a/libglusterfs/src/common-utils.h +++ b/libglusterfs/src/common-utils.h @@ -465,9 +465,9 @@ void skip_word (char **str); char *get_nth_word (const char *str, int n); char valid_host_name (char *address, int length); -char valid_ipv4_address (char *address, int length); -char valid_ipv6_address (char *address, int length); -char valid_internet_address (char *address); +char valid_ipv4_address (char *address, int length, gf_boolean_t wildcard_acc); +char valid_ipv6_address (char *address, int length, gf_boolean_t wildcard_acc); +char valid_internet_address (char *address, gf_boolean_t wildcard_acc); char valid_ipv4_wildcard_check (char *address); char valid_ipv6_wildcard_check (char *address); char valid_wildcard_internet_address (char *address); diff --git a/libglusterfs/src/options.c b/libglusterfs/src/options.c index 39844461a65..6da68fd999a 100644 --- a/libglusterfs/src/options.c +++ b/libglusterfs/src/options.c @@ -464,10 +464,11 @@ xlator_option_validate_addr (xlator_t *xl, const char *key, const char *value, int ret = -1; char errstr[256]; - if (!valid_internet_address ((char *)value)) { + if (!valid_internet_address ((char *)value, _gf_false)) { snprintf (errstr, 256, - "internet address '%s' does not conform to standards.", - value); + "option %s %s: '%s' is not a valid internet-address," + " it does not conform to standards.", + key, value, value); gf_log (xl->name, GF_LOG_ERROR, "%s", errstr); if (op_errstr) *op_errstr = gf_strdup (errstr); @@ -478,6 +479,176 @@ xlator_option_validate_addr (xlator_t *xl, const char *key, const char *value, return ret; } +static int +xlator_option_validate_addr_list (xlator_t *xl, const char *key, + const char *value, volume_option_t *opt, + char **op_errstr) +{ + int ret = -1; + char *dup_val = NULL; + char *addr_tok = NULL; + char *save_ptr = NULL; + char errstr[256]; + + dup_val = gf_strdup (value); + if (!dup_val) { + ret = -1; + snprintf (errstr, 256, "internal error, out of memory."); + goto out; + } + + addr_tok = strtok_r (dup_val, ",", &save_ptr); + while (addr_tok) { + if (!valid_internet_address (addr_tok, _gf_true)) { + snprintf (errstr, 256, + "option %s %s: '%s' is not a valid " + "internet-address-list", + key, value, value); + gf_log (xl->name, GF_LOG_ERROR, "%s", errstr); + ret = -1; + goto out; + } + addr_tok = strtok_r (NULL, ",", &save_ptr); + } + ret = 0; + out: + if (op_errstr && ret) + *op_errstr = gf_strdup (errstr); + if (dup_val) + GF_FREE (dup_val); + + return ret; +} + +/*XXX: the rules to validate are as per block-size required for stripe xlator */ +static int +gf_validate_size (const char *sizestr, volume_option_t *opt) +{ + uint64_t value = 0; + int ret = 0; + + GF_ASSERT (opt); + + if (gf_string2bytesize (sizestr, &value) != 0 || + value < opt->min || + value % 512) { + ret = -1; + goto out; + } + + out: + gf_log (THIS->name, GF_LOG_DEBUG, "Returning %d", ret); + return ret; +} + +static int +gf_validate_number (const char *numstr, volume_option_t *opt) +{ + int32_t value; + return gf_string2int32 (numstr, &value); +} + +/* Parses the string to be of the form :,:... * + * takes two optional validaters key_validator and value_validator */ +static int +validate_list_elements (const char *string, volume_option_t *opt, + int (key_validator)( const char *), + int (value_validator)( const char *, volume_option_t *)) +{ + + char *dup_string = NULL; + char *str_sav = NULL; + char *substr_sav = NULL; + char *str_ptr = NULL; + char *key = NULL; + char *value = NULL; + int ret = 0; + + GF_ASSERT (string); + + dup_string = gf_strdup (string); + if (NULL == dup_string) + goto out; + + str_ptr = strtok_r (dup_string, ",", &str_sav); + while (str_ptr) { + + key = strtok_r (str_ptr, ":", &substr_sav); + if (!key || + (key_validator && key_validator(key))) { + ret = -1; + gf_log (THIS->name, GF_LOG_WARNING, + "invalid list '%s', key '%s' not valid.", + string, key); + goto out; + } + + value = strtok_r (NULL, ":", &substr_sav); + if (!value || + (value_validator && value_validator(value, opt))) { + ret = -1; + gf_log (THIS->name, GF_LOG_WARNING, + "invalid list '%s', value '%s' not valid.", + string, key); + goto out; + } + + str_ptr = strtok_r (NULL, ",", &str_sav); + substr_sav = NULL; + } + out: + if (dup_string) + GF_FREE (dup_string); + gf_log (THIS->name, GF_LOG_DEBUG, "Returning %d", ret); + return ret; +} + +static int +xlator_option_validate_priority_list (xlator_t *xl, const char *key, + const char *value, volume_option_t *opt, + char **op_errstr) +{ + int ret =0; + char errstr[1024] = {0, }; + + GF_ASSERT (value); + + ret = validate_list_elements (value, opt, NULL, &gf_validate_number); + if (ret) { + snprintf (errstr, 1024, + "option %s %s: '%s' is not a valid " + "priority-list", key, value, value); + *op_errstr = gf_strdup (errstr); + } + + return ret; +} + +static int +xlator_option_validate_size_list (xlator_t *xl, const char *key, + const char *value, volume_option_t *opt, + char **op_errstr) +{ + + int ret = 0; + char errstr[1024] = {0, }; + + GF_ASSERT (value); + + ret = gf_validate_size (value, opt); + if (ret) + ret = validate_list_elements (value, opt, NULL, &gf_validate_size); + + if (ret) { + snprintf (errstr, 1024, + "option %s %s: '%s' is not a valid " + "size-list", key, value, value); + *op_errstr = gf_strdup (errstr); + } + + return ret; + +} static int xlator_option_validate_any (xlator_t *xl, const char *key, const char *value, @@ -486,7 +657,6 @@ xlator_option_validate_any (xlator_t *xl, const char *key, const char *value, return 0; } - typedef int (xlator_option_validator_t) (xlator_t *xl, const char *key, const char *value, volume_option_t *opt, char **operrstr); @@ -510,6 +680,11 @@ xlator_option_validate (xlator_t *xl, char *key, char *value, [GF_OPTION_TYPE_TIME] = xlator_option_validate_time, [GF_OPTION_TYPE_DOUBLE] = xlator_option_validate_double, [GF_OPTION_TYPE_INTERNET_ADDRESS] = xlator_option_validate_addr, + [GF_OPTION_TYPE_INTERNET_ADDRESS_LIST] = + xlator_option_validate_addr_list, + [GF_OPTION_TYPE_PRIORITY_LIST] = + xlator_option_validate_priority_list, + [GF_OPTION_TYPE_SIZE_LIST] = xlator_option_validate_size_list, [GF_OPTION_TYPE_ANY] = xlator_option_validate_any, [GF_OPTION_TYPE_MAX] = NULL, }; diff --git a/libglusterfs/src/options.h b/libglusterfs/src/options.h index 40089ac6317..722cc3b7a5d 100644 --- a/libglusterfs/src/options.h +++ b/libglusterfs/src/options.h @@ -44,6 +44,9 @@ typedef enum { GF_OPTION_TYPE_TIME, GF_OPTION_TYPE_DOUBLE, GF_OPTION_TYPE_INTERNET_ADDRESS, + GF_OPTION_TYPE_INTERNET_ADDRESS_LIST, + GF_OPTION_TYPE_PRIORITY_LIST, + GF_OPTION_TYPE_SIZE_LIST, GF_OPTION_TYPE_MAX, } volume_option_type_t; -- cgit