diff options
author | alex <alex@builder.localdomain> | 2007-12-11 15:12:36 -0800 |
---|---|---|
committer | alex <alex@builder.localdomain> | 2007-12-11 15:12:36 -0800 |
commit | fb9450551d5757a45806a062d7457a761e6dd295 (patch) | |
tree | cda8e28bdf2c1bc23d98de6de9437b1c90c5f654 | |
parent | 1d78b0c336c8d3ae62f65983098584a6e2e613ce (diff) | |
download | vyatta-cfg-fb9450551d5757a45806a062d7457a761e6dd295.tar.gz vyatta-cfg-fb9450551d5757a45806a062d7457a761e6dd295.zip |
Bug #2509
Multivalue nodes are diffed with previous value for validation before
commit.
-rw-r--r-- | src/cli_new.c | 95 | ||||
-rw-r--r-- | src/cli_objects.c | 2 | ||||
-rw-r--r-- | src/cli_val.h | 1 | ||||
-rw-r--r-- | src/commit.c | 24 | ||||
-rw-r--r-- | templates/interfaces/ethernet/node.tag/address/node.def | 2 |
5 files changed, 116 insertions, 8 deletions
diff --git a/src/cli_new.c b/src/cli_new.c index 0f5abd9..c51be7f 100644 --- a/src/cli_new.c +++ b/src/cli_new.c @@ -56,8 +56,13 @@ static int cond_format_lens[DOMAIN_TYPE] = 6 /* MACADDR_TYPE */ }; +struct __slist_t; + +typedef struct __slist_t { + struct __slist_t *next; +} slist_t; + static int cli_val_len; -static char *cli_val_alloc; static char *cli_val_ptr; static char *exe_string; @@ -82,6 +87,8 @@ static void free_reuse_list(void); void free_path(vtw_path *path); static void free_string(char *str); static vtw_node * get_node(void); +void subtract_values(char **lhs, const char *rhs); + static void scan_ipv6(char *val, unsigned int *parts); @@ -1518,7 +1525,6 @@ int get_value(char **valpp, vtw_path *pathp) readcnt = fread(valp, 1, statbuf.st_size, in); if (readcnt != statbuf.st_size) { my_free(valp); - cli_val_alloc = 0; err = "Error reading value file in [%s]\n"; goto bad_path; } @@ -1784,6 +1790,91 @@ boolean validate_value(vtw_def *def, char *cp) return ret; } +typedef struct __value_list { + slist_t link; + const char *value; +} value_list; + +static void delete_list(slist_t *head) +{ + while (head != NULL) { + slist_t *elem = head; + head = head->next; + my_free(elem); + } +} + +void subtract_values(char **lhs, const char *rhs) +{ + size_t length = 0; + const char *line = NULL; + char *rhs_copy = NULL, *res = NULL; + slist_t *head = NULL, *ptr = NULL; + slist_t *new_head = NULL, *new_ptr = NULL; + + if (lhs == NULL || *lhs == NULL || **lhs == '\0' || rhs == NULL || *rhs == '\0') + return; + + rhs_copy = my_malloc(strlen(rhs), "subtract_values rhs_copy"); + strcpy(rhs_copy, rhs); + + head = ptr = my_malloc(sizeof(slist_t), "subtract_values list1"); + memset(head, 0, sizeof(slist_t)); + + line = strtok(rhs_copy, "\n\r"); + while (line != NULL && *line != '\0') { + value_list *elem = NULL; + + elem = (value_list *) my_malloc(sizeof(value_list), "subtract_values elem1"); + memset(elem, 0, sizeof(value_list)); + elem->value = line; + ptr->next = (slist_t *) elem; + ptr = ptr->next; + line = strtok(NULL, "\n\r"); + } + + new_head = new_ptr = my_malloc(sizeof(slist_t), "subtract_values list2"); + memset(new_head, 0, sizeof(slist_t)); + + line = strtok(*lhs, "\n\r"); + while (line != NULL && *line != '\0') { + value_list *elem = NULL; + + ptr = head; + while (ptr->next != NULL) { + elem = (value_list *) ptr->next; + if (strncmp(line, elem->value, strlen(line)) == 0) + break; + ptr = ptr->next; + } + if (ptr->next == NULL) { + elem = (value_list *) my_malloc(sizeof(value_list), "subtract_values elem2"); + memset(elem, 0, sizeof(value_list)); + elem->value = line; + new_ptr->next = elem; + new_ptr = new_ptr->next; + length += strlen(line) + 1; + } + line = strtok(NULL, "\n\r"); + } + + new_ptr = new_head->next; + res = (char *) my_malloc(length + 1, "subtract_values result"); + *res = '\0'; + while (new_ptr != NULL) { + strcat(res, ((value_list *) new_ptr)->value); + strcat(res, "\n"); + new_ptr = new_ptr->next; + } + + delete_list(head); + delete_list(new_head); + if (rhs_copy != NULL) + my_free(rhs_copy); + my_free(*lhs); + + *lhs = res; +} int cli_val_read(char *buf, int max_size) { diff --git a/src/cli_objects.c b/src/cli_objects.c index 9bb36f0..8f0f6fe 100644 --- a/src/cli_objects.c +++ b/src/cli_objects.c @@ -334,7 +334,7 @@ void init_paths(boolean for_commit) init_path(&m_path, startp); switch_path(get_f_seg_c_ptr()); m_path.print_offset = max_len; - }else + } else init_path(&m_path, mdirp); init_path(&t_path, tdirp); diff --git a/src/cli_val.h b/src/cli_val.h index 7383263..edbda41 100644 --- a/src/cli_val.h +++ b/src/cli_val.h @@ -171,6 +171,7 @@ extern void dump_tree(vtw_node *node, int lev); extern void dump_def(vtw_def *defp); extern boolean val_cmp(valstruct *left, valstruct *right, vtw_cond_e cond); extern void out_of_memory(void); +extern void subtract_values(char **lhs, const char *rhs); extern boolean validate_value(vtw_def *def, char *value); extern void internal_error(int line, char *file); diff --git a/src/commit.c b/src/commit.c index 4820094..2eedf6f 100644 --- a/src/commit.c +++ b/src/commit.c @@ -91,7 +91,7 @@ static boolean validate_dir_for_commit() def_present = TRUE; memset(&def, 0, sizeof(def)); #ifdef DEBUG1 - printf("Parsing definition\n"); + printf("Parsing definition %s\n", t_path.path); #endif if ((status = parse_def(&def, t_path.path, @@ -102,7 +102,7 @@ static boolean validate_dir_for_commit() } #ifdef DEBUG1 else - printf("No definition\n"); + printf("No definition %s\n", t_path.path); #endif pop_path(&t_path); /* for PUSH 1 */ @@ -156,11 +156,27 @@ static boolean validate_dir_for_commit() /* read it */ cp = NULL; status = get_value(&cp, &m_path); - if (status == VTWERR_OK){ + if (status == VTWERR_OK) { #ifdef DEBUG1 printf("Validating value |%s|\n" "for path %s\n", cp, m_path.path); #endif + + // multivalue has to be diff-ed with the pre-existing value. + // only the difference should be ran through the validation. + // Bug #2509 + if (def.multi) { + char *old_value = NULL; + switch_path(APATH); // temporarily switching to the active config path + status = get_value(&old_value, &m_path); + if (status == VTWERR_OK) { + subtract_values(&cp, old_value); + } + switch_path(CPATH); + if (old_value) + my_free(old_value); + } + status = validate_value(&def, cp); ret = ret && status; } @@ -232,7 +248,7 @@ static boolean validate_dir_for_commit() } if (def_present && def.tag) - pop_path(&t_path); /* for PUSH 3a */ + pop_path(&t_path); /* for PUSH 2a */ if (def_present) free_def(&def); #ifdef DEBUG diff --git a/templates/interfaces/ethernet/node.tag/address/node.def b/templates/interfaces/ethernet/node.tag/address/node.def index 9447c99..6cef105 100644 --- a/templates/interfaces/ethernet/node.tag/address/node.def +++ b/templates/interfaces/ethernet/node.tag/address/node.def @@ -2,5 +2,5 @@ multi: type: txt help: "Set IPv4 address and prefix for this interface" syntax: exec "/opt/vyatta/sbin/vyatta-interfaces.pl --valid-addr $(@) --dev $(../@)" -create: "sudo /opt/vyatta/sbin/vyatta-interfaces.pl --eth-addr-update $(@) --dev $(../@)"; "Error setting address $(@) on dev $(../@)" +update: "sudo /opt/vyatta/sbin/vyatta-interfaces.pl --eth-addr-update $(@) --dev $(../@)"; "Error setting address $(@) on dev $(../@)" delete: "sudo /opt/vyatta/sbin/vyatta-interfaces.pl --eth-addr-delete $(@) --dev $(../@)"; "Error deleting address $(@) on dev $(../@)" |