diff options
-rw-r--r-- | Makefile.am | 4 | ||||
-rw-r--r-- | debian/changelog | 62 | ||||
-rwxr-xr-x | etc/bash_completion.d/20vyatta-cfg | 22 | ||||
-rwxr-xr-x | lib/Vyatta/Config.pm | 23 | ||||
-rwxr-xr-x | lib/Vyatta/ConfigLoad.pm | 96 | ||||
-rwxr-xr-x | lib/Vyatta/ConfigOutput.pm | 26 | ||||
-rwxr-xr-x | scripts/enumeration/existing-interfaces | 4 | ||||
-rw-r--r-- | scripts/update-priority.pl | 11 | ||||
-rw-r--r-- | scripts/vyatta-activate-config.pl | 76 | ||||
-rwxr-xr-x | scripts/vyatta-cfg-cmd-wrapper | 4 | ||||
-rw-r--r-- | scripts/vyatta-comment-config.pl | 76 | ||||
-rwxr-xr-x | scripts/vyatta-config-gen-sets.pl | 3 | ||||
-rwxr-xr-x | scripts/vyatta-config-loader.pl | 40 | ||||
-rwxr-xr-x | scripts/vyatta-load-config.pl | 44 | ||||
-rw-r--r-- | src/cli_def.l | 4 | ||||
-rw-r--r-- | src/cli_new.c | 88 | ||||
-rw-r--r-- | src/cli_val.h | 4 | ||||
-rw-r--r-- | src/common/unionfs.c | 4 | ||||
-rw-r--r-- | src/delete.c | 4 | ||||
-rw-r--r-- | src/set.c | 33 |
20 files changed, 500 insertions, 128 deletions
diff --git a/Makefile.am b/Makefile.am index efe1a92..a1a8f8a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -4,6 +4,7 @@ initddir = /etc/init.d defaultdir = /etc/default etc_shell_leveldir = $(sysconfdir)/shell/level dhcphookdir = /etc/dhcp3/dhclient-exit-hooks.d +enumdir = $(datadir)/enumeration AM_CFLAGS = -I src -Wall -I /usr/include/glib-2.0 -I /usr/lib/glib-2.0/include AM_YFLAGS = -d --name-prefix=yy_`basename $* .y`_ @@ -54,6 +55,7 @@ sbin_SCRIPTS += scripts/vyatta-output-config.pl sbin_SCRIPTS += scripts/vyatta-save-config.pl sbin_SCRIPTS += scripts/vyatta-load-config.pl sbin_SCRIPTS += scripts/vyatta-activate-config.pl +sbin_SCRIPTS += scripts/vyatta-comment-config.pl sbin_SCRIPTS += scripts/vyatta-cfg-notify sbin_SCRIPTS += scripts/vyatta-irqaffin sbin_SCRIPTS += scripts/vyatta-auto-irqaffin.pl @@ -70,6 +72,8 @@ share_perl5_DATA += lib/Vyatta/ConfigLoad.pm share_perl5_DATA += lib/Vyatta/Keepalived.pm share_perl5_DATA += lib/Vyatta/Zone.pm +enum_SCRIPTS = scripts/enumeration/existing-interfaces + default_DATA = etc/default/vyatta-cfg cpiop = find . ! -regex '\(.*~\|.*\.bak\|.*\.swp\|.*\#.*\#\)' -print0 | \ diff --git a/debian/changelog b/debian/changelog index 22f9812..4fcd160 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,65 @@ +vyatta-cfg (0.16.44) unstable; urgency=low + + * fix for disable nodes loading (bug 5610). Additional checks added on + configuration of disable nodes. requires vyatta-config-migrate + package as well. + + -- Michael Larson <slioch@slioch.vyatta.com> Fri, 21 May 2010 10:21:32 -0700 + +vyatta-cfg (0.16.43) unstable; urgency=low + + * fixed error message on multinode limit exceeded--refer to parent + node name, not value. + * fixed seg violation on commit due to extended multiple types support + in valstruct. + + -- Michael Larson <slioch@slioch.vyatta.com> Thu, 20 May 2010 15:41:25 -0700 + +vyatta-cfg (0.16.42) unstable; urgency=low + + * fix for bug 5618. needed to extend valstruct to maintain multiple + types rather than using first type found in node.val file. also + simplified type check. + + -- Michael Larson <slioch@slioch.vyatta.com> Thu, 20 May 2010 13:36:53 -0700 + +vyatta-cfg (0.16.41) unstable; urgency=low + + * trap for illegal characters in comment field being set by user and + provide feedback. + * modified tag limit == 1. Now when set this node will only allow a + single instance. todo update the parsing structure to support a + signed value to support embedded tag node + + -- Michael Larson <slioch@slioch.vyatta.com> Wed, 19 May 2010 14:56:31 -0700 + +vyatta-cfg (0.16.40) unstable; urgency=low + + [ Arthur Xiong ] + * 1) skip comment and empty lines in priority file; + + [ Michael Larson ] + * added additional warning message if the user tries to deactivate a + node that has already been deactivated. + * initial checkin of comment feature for cli. + + [ An-Cheng Huang ] + * POC implementation of unified enumeration mechanism + + -- An-Cheng Huang <ancheng@vyatta.com> Fri, 14 May 2010 17:41:16 -0700 + +vyatta-cfg (0.16.39) unstable; urgency=low + + * additional fix + + -- An-Cheng Huang <ancheng@vyatta.com> Thu, 06 May 2010 17:32:40 -0700 + +vyatta-cfg (0.16.38) unstable; urgency=low + + * fix parsing error in node.def--seen with boolean default values. + + -- Michael Larson <slioch@slioch.vyatta.com> Thu, 06 May 2010 16:04:45 -0700 + vyatta-cfg (0.16.37) unstable; urgency=low [ Arthur ] diff --git a/etc/bash_completion.d/20vyatta-cfg b/etc/bash_completion.d/20vyatta-cfg index e17fd36..03f0bb2 100755 --- a/etc/bash_completion.d/20vyatta-cfg +++ b/etc/bash_completion.d/20vyatta-cfg @@ -431,6 +431,17 @@ loadkey() eval "${vyatta_sbindir}/vyatta-load-user-key.pl $@" } +comment() +{ + if [ "$#" -eq "0" ]; then + return 0 + fi + args=("$@") + #now need to replace last element + args[${#args[*]}-1]="\"${args[${#args[*]}-1]i}\""; + eval "${vyatta_sbindir}/vyatta-comment-config.pl ${args[*]}" +} + activate() { #create or remove activate file @@ -632,6 +643,7 @@ vyatta_parse_tmpl () # $1: tmpl vyatta_cfg_help="" vyatta_cfg_type="" + vyatta_cfg_enum='' vyatta_cfg_tag=0 vyatta_cfg_multi=0 vyatta_cfg_allowed=() @@ -648,11 +660,18 @@ vyatta_parse_tmpl () s/^tag:.*/vyatta_cfg_tag=1/p s/^multi:.*/vyatta_cfg_multi=1/p s/^type:[ ]\+\([^ ;]\+\)\(;.*\)\?/vyatta_cfg_type=\1/p + s/^enumeration:[ ]\+\([^ ]\+\)/vyatta_cfg_enum=\1/p ' $1` vyatta_cfg_help=$(vyatta_parse_tmpl_comp_fields $1 "help") local acmd=$(vyatta_parse_tmpl_comp_fields $1 "allowed") + if [ -n "$vyatta_cfg_enum" ]; then + local enum_script="/opt/vyatta/share/enumeration/$vyatta_cfg_enum" + if [ -f "$enum_script" ] && [ -e "$enum_script" ]; then + acmd="$enum_script" + fi + fi vyatta_cfg_comp_help=$(vyatta_parse_tmpl_comp_fields $1 "comp_help") if (( ${#vyatta_cfg_allowed[@]} == 0 )); then @@ -942,6 +961,7 @@ vyatta_config_complete () if (( ${#COMP_WORDS[@]} < 2 )); then declare -a hitems=( "activate" \ + "comment" \ "commit" \ "copy" \ "deactivate" \ @@ -959,6 +979,7 @@ vyatta_config_complete () "show" ) declare -a hstrs=( \ "Enable this portion of the configuration" \ + "Add comment to this configuration element" \ "Commit the current set of changes" \ "Copy a configuration element" \ "Inactivate this portion of the configuration" \ @@ -1310,6 +1331,7 @@ complete -F vyatta_loadsave_complete save complete -F vyatta_loadsave_complete load complete -F vyatta_loadsave_complete merge complete -F vyatta_loadkey_complete loadkey +complete -F vyatta_config_complete comment complete -F vyatta_config_complete activate complete -F vyatta_config_complete deactivate complete -F vyatta_config_complete copy diff --git a/lib/Vyatta/Config.pm b/lib/Vyatta/Config.pm index 82d835f..e4d74bb 100755 --- a/lib/Vyatta/Config.pm +++ b/lib/Vyatta/Config.pm @@ -329,6 +329,27 @@ sub returnValue { return $tmp; } +## returnComment("node") +# returns the value of "node" or undef if the node doesn't exist . +# node is relative +sub returnComment { + my ( $self, $node ) = @_; + my $tmp = undef; + + $node =~ s/\//%2F/g; + $node =~ s/\s+/\//g; + + return unless + open my $file, '<', + "$self->{_new_config_dir_base}/$node/.comment"; + + read $file, $tmp, 16384; + close $file; + + $tmp =~ s/\n$//; + return $tmp; +} + ## returnOrigPlusComValue("node") # returns the value of "node" or undef if the node doesn't exist . # node is relative @@ -808,6 +829,8 @@ sub parseTmplAll { } } elsif (/^help:\s+(\S.*)$/) { $ret{help} = $1; + } elsif (/^enumeration:\s+(\S+)$/) { + $ret{enum} = $1; } } close($tmpl); diff --git a/lib/Vyatta/ConfigLoad.pm b/lib/Vyatta/ConfigLoad.pm index 28e932e..183e598 100755 --- a/lib/Vyatta/ConfigLoad.pm +++ b/lib/Vyatta/ConfigLoad.pm @@ -30,6 +30,9 @@ use Vyatta::Config; my @all_nodes = (); my @all_naked_nodes = (); +my @disable_list = (); + + sub match_regex { my ($pattern, $str) = @_; $pattern =~ s/^(.*)$/\^$1\$/; @@ -58,6 +61,8 @@ sub applySingleQuote { return @return; } +my @comment_list = (); + sub enumerate_branch { my $cur_node = shift; my @cur_path = @_; @@ -72,31 +77,42 @@ sub enumerate_branch { } my $terminal = 0; if (!defined($cur_node->{'children'})) { - $terminal = 1; + $terminal = 1; } else { - foreach (@{$cur_node->{'children'}}) { - if (defined($_->{'name'})) { - enumerate_branch($_, @cur_path); - $terminal = 0; + my $comment; + foreach (@{$cur_node->{'children'}}) { + if (defined($_->{'comment'})) { + $comment = $_->{'comment'}; + } + + if (defined($_->{'name'})) { + if (defined $comment) { + push @comment_list, join(" ", (@cur_path, $_->{'name'}, "\"" . $comment . "\"")); + $comment = undef; + } + else { + #need to check for existance of .comment file here. + push @comment_list, join(" ", (@cur_path, $_->{'name'}, "\"\"")); + } + enumerate_branch($_, @cur_path); + $terminal = 0; + } + } - } } + + if (defined($cur_node->{'disable'})) { + push @disable_list, join(" ",@cur_path); + } + if ($terminal) { my $val = $cur_node->{'value'}; if (defined($val)) { push @cur_path, $val; } - if (defined $cur_node->{'disable'}) { - push @all_naked_nodes, [ '!', @cur_path ]; - my @qpath = applySingleQuote(@cur_path); - unshift(@qpath,'!'); - push @all_nodes, [\@qpath, 0]; - } - else { - push @all_naked_nodes, [ @cur_path ]; - my @qpath = applySingleQuote(@cur_path); - push @all_nodes, [\@qpath, 0]; - } + push @all_naked_nodes, [ @cur_path ]; + my @qpath = applySingleQuote(@cur_path); + push @all_nodes, [\@qpath, 0]; } } @@ -111,6 +127,8 @@ sub getStartupConfigStatements { if (!defined($load_cfg)) { return (); } + + my $comments = shift; my $xcp = new XorpConfigParser(); $xcp->parse($load_cfg); @@ -120,7 +138,20 @@ sub getStartupConfigStatements { } enumerate_branch($root, ( )); - return @all_nodes; + if (defined $comments && $comments eq 'true') { + #add comment commands to all nodes + foreach my $c (@comment_list) { + if ($c !~ /\"\"$/) { + my @pth = split(" ",'comment ' . $c); + push @all_nodes, [\@pth, 1]; + } + } + } + my %conf = ( + 'set' => \@all_nodes, + 'deactivate' => \@disable_list, + ); + return %conf; } my %node_order = (); @@ -221,7 +252,6 @@ sub getSortedMultiValues { my $active_cfg = undef; my $new_cfg_ref = undef; - my @delete_list = (); # find specified node's values in active config that have been deleted from @@ -278,7 +308,6 @@ sub findDeletedNodes { } my @set_list = (); -my @disable_list = (); # find specified node's values in active config that are set # (added or changed). @@ -326,9 +355,9 @@ sub findSetNodes { my %active_hash = map { $_ => 1 } @active_nodes; my $nref = $active_cfg->parseTmplAll(join ' ', @active_path); if (defined($nref->{type}) and !defined($nref->{tag})) { - # we are at a leaf node. - findSetValues($new_ref, \@active_path); - return; + # we are at a leaf node. + findSetValues($new_ref, \@active_path); + return; } foreach (sort keys %{$new_ref}) { if (scalar(keys %{$new_ref->{$_}}) == 0) { @@ -336,28 +365,16 @@ sub findSetNodes { # check if we need to add this node. if (!defined($active_hash{$_})) { my @plist = applySingleQuote(@active_path, $_); - if ($active_path[0] eq '!') { - my @tmp = @plist[1..$#plist]; - push @disable_list, [\@tmp, 0]; - push @set_list, [\@tmp, 0]; - } - else { - push @set_list, [\@plist, 0]; - } + push @set_list, [\@plist, 0]; } else { # node already present. do nothing. } next; } - if ($active_path[0] eq '!') { - my @plist = applySingleQuote(@active_path, $_); - my @tmp = @plist[1..$#plist]; - push @disable_list, [\@tmp, 0]; - } + # we recur regardless of whether it's in active. all changes will be + # handled when we reach leaf nodes (above). findSetNodes($new_ref->{$_}, [ @active_path, $_ ]); } - # we recur regardless of whether it's in active. all changes will be - # handled when we reach leaf nodes (above). } # compare the current active config with the specified hierarchy and return @@ -368,7 +385,7 @@ sub getConfigDiff { $active_cfg = new Vyatta::Config; $new_cfg_ref = shift; @set_list = (); - @disable_list = (); +# @disable_list = (); @delete_list = (); findDeletedNodes($new_cfg_ref, [ ]); findSetNodes($new_cfg_ref, [ ]); @@ -392,6 +409,7 @@ sub getConfigDiff { 'delete' => \@new_delete_list, 'set' => \@set_list, 'deactivate' => \@disable_list, + 'comment' => \@comment_list, ); return %diff; } diff --git a/lib/Vyatta/ConfigOutput.pm b/lib/Vyatta/ConfigOutput.pm index caa9356..99a0da8 100755 --- a/lib/Vyatta/ConfigOutput.pm +++ b/lib/Vyatta/ConfigOutput.pm @@ -82,6 +82,7 @@ sub displayValues { my $HIDE_PASSWORD = '****************'; $config->setLevel(join ' ', @cur_path); + if ($is_multi) { my @ovals = $config->returnOrigValues(''); my @nvals = $config->returnValues(''); @@ -201,6 +202,11 @@ sub displayDeletedOrigChildren { if (!defined $is_tag) { my $path = join(' ',( @cur_path, $child )); + my $comment = $config->returnComment($path); + if (defined $comment) { + print "$prefix /* $comment */\n"; + } + my ($state, $n) = $config->getDeactivated($path); if (defined $state) { $dis = '! '; @@ -211,6 +217,7 @@ sub displayDeletedOrigChildren { } $config->setLevel(join ' ', (@cur_path, $child)); + my @cnames = sort $config->listOrigNodesNoDef(); if ($cnames[0] eq 'node.val') { @@ -227,8 +234,14 @@ sub displayDeletedOrigChildren { next; } - #need separate check here my $path = join(' ',( @cur_path, $child, $cname )); + + my $comment = $config->returnComment($path); + if (defined $comment) { + print "$prefix /* $comment */\n"; + } + + #need separate check here my ($state, $n) = $config->getDeactivated($path); if (defined $state) { $dis = '! '; @@ -288,6 +301,11 @@ sub displayChildren { if (!defined($is_tag)) { my $path = join(' ',( @cur_path, $child )); + my $comment = $config->returnComment($path); + if (defined $comment) { + print "$prefix /* $comment */\n"; + } + my ($state, $n) = $config->getDeactivated($path); if (defined $state) { $dis = '! '; @@ -325,6 +343,11 @@ sub displayChildren { } my $path = join(' ',( @cur_path, $child, $cname )); + my $comment = $config->returnComment($path); + if (defined $comment) { + print "$prefix /* $comment */\n"; + } + my ($state, $n) = $config->getDeactivated($path); if (defined $state) { $dis = '! '; @@ -388,6 +411,7 @@ sub outputNewConfig { $config = new Vyatta::Config; $config->setLevel(join ' ', @_); my %rnodes = $config->listNodeStatus(undef,'true'); + if (scalar(keys %rnodes) > 0) { my @rn = keys %rnodes; diff --git a/scripts/enumeration/existing-interfaces b/scripts/enumeration/existing-interfaces new file mode 100755 index 0000000..1defc22 --- /dev/null +++ b/scripts/enumeration/existing-interfaces @@ -0,0 +1,4 @@ +#!/bin/bash + +ls /sys/class/net 2>/dev/null + diff --git a/scripts/update-priority.pl b/scripts/update-priority.pl index 84b4933..feb1e7f 100644 --- a/scripts/update-priority.pl +++ b/scripts/update-priority.pl @@ -38,7 +38,7 @@ my $prefix = $ARGV[1]; open my $pf, '<', $priority_file or die "$priority_file can't be opened"; while (<$pf>) { chomp; - next if /^#.*/; + next if /^#.*/ or /^$/; die "Syntax Error \"$_\"" unless /^(\d+)\s+(\S+)(|\s+|\s+#.*)$/; $priority = $1; $path = $2; @@ -55,11 +55,12 @@ while (<$pf>) { open my $nf, '<', $node_def or die "$node_def can't be opened"; open my $nfn, '>', "$node_def.new" or die "$node_def.new can't be opened"; while (<$nf>) { - print $nfn $_ if /^(tag|multi):/; - print $nfn $priority_line; - print $nfn $_ unless /^priority:\s(\d+)/ or /^(tag|multi):/; - last if $. == 1; + last unless /^#.*/ or /^$/; + print $nfn $_; } + print $nfn $_ if /^(tag|multi):/; + print $nfn $priority_line if $priority != 0; + print $nfn $_ unless /^priority:\s(\d+)/ or /^(tag|multi):/; while (<$nf>) { print $nfn $_ unless /^priority:\s(\d+)/; } diff --git a/scripts/vyatta-activate-config.pl b/scripts/vyatta-activate-config.pl index 20f704d..3eca90f 100644 --- a/scripts/vyatta-activate-config.pl +++ b/scripts/vyatta-activate-config.pl @@ -27,15 +27,40 @@ use lib "/opt/vyatta/share/perl5"; sub wanted { return unless ( $_ eq '.disable' ); - print("Cannot set nested deactivated nodes\n"); + print("Cannot deactivate nested elements\n"); exit 1; } +sub check_parents { + my @p = @_; + my $l_dir = "$ENV{VYATTA_TEMP_CONFIG_DIR}/"; + my $a_dir = "$ENV{VYATTA_ACTIVE_CONFIGURATION_DIR}/"; + foreach my $sw (@p) { + $l_dir .= "/$sw"; + $a_dir .= "/$sw"; + + if (-e "$l_dir/.disable") { + return 1; + } + if (-e "$a_dir/.disable") { + return 1; + } + } + return 0; +} + sub usage() { print "Usage: $0 <path>\n"; exit 0; } +my $action = $ARGV[0]; + +if (!defined $ARGV[1] || $ARGV[1] eq '') { + print("Cannot activate/deactivate configuration root\n"); + exit 1; +} + #adjust for leaf node my $i = 0; my @path = @ARGV[1..$#ARGV]; @@ -53,7 +78,6 @@ if (! -e $full_path) { my $leaf = "$ENV{VYATTA_TEMP_CONFIG_DIR}/$path/node.val"; if (-e $leaf) { #prevent setting on leaf or multi, check for node.val -# $full_path = "$ENV{VYATTA_TEMP_CONFIG_DIR}/$path"; printf("Cannot activate/deactivate end node\n"); exit 1; } @@ -63,45 +87,53 @@ if (! -e $full_path) { } } +####################################################### +#now check for nesting of the activate/deactivate nodes +####################################################### +if ($action eq 'deactivate') { + my $active_dir = "$ENV{VYATTA_ACTIVE_CONFIGURATION_DIR}/$path"; + my $local_dir = $full_path; + if (-e $active_dir) { #checks active children + find( \&wanted, $active_dir ); + } + if (-e $local_dir) { #checks locally commit children + find( \&wanted, $local_dir ); + } + #final check that walks up tree and checks + if (check_parents(@path)) { #checks active and locally committed parents + print("Cannot deactivate nested elements\n"); + exit 1; + } +} -if ($ARGV[0] eq 'activate') { +####################################################### +#now apply the magic +####################################################### +if ($action eq 'activate') { $full_path .= "/.disable"; if (-e $full_path) { `rm -f $full_path`; } else { - printf("This element is not deactivated.\n"); + printf("This element has not been deactivated\n"); exit 1; } } -elsif ($ARGV[0] eq 'deactivate') { +elsif ($action eq 'deactivate') { #first let's check and ensure that there is not another child .disable node... #also needs to be enforced when committing my $active_dir = "$ENV{VYATTA_ACTIVE_CONFIGURATION_DIR}/$path"; my $local_dir = $full_path; - if (-e $active_dir) { - find( \&wanted, $active_dir ); - } - if (-e $local_dir) { - find( \&wanted, $local_dir ); + if (-e "$active_dir/.disable" || -e "$local_dir/.disable") { + printf("This element has already been deactivated\n"); + exit 1; } `touch $full_path/.disable`; } -elsif ($ARGV[0] eq 'complete') { - #provide match... - printf("complete\n"); -} else { - printf("incoming arg: " . $ARGV[0] . "\n"); + printf("bad argument: " . $action . "\n"); usage(); } -#if this is activate -# make sure no activate subnodes -# create .disable file in node -#else -# ensure .disable file exists -# remove node - print "Done\n"; exit 0; diff --git a/scripts/vyatta-cfg-cmd-wrapper b/scripts/vyatta-cfg-cmd-wrapper index 3b2f040..4941e37 100755 --- a/scripts/vyatta-cfg-cmd-wrapper +++ b/scripts/vyatta-cfg-cmd-wrapper @@ -220,6 +220,10 @@ case "$1" in /opt/vyatta/sbin/vyatta-activate-config.pl activate "${@:2}" RET_STATUS=$? ;; + comment) + /opt/vyatta/sbin/vyatta-comment-config.pl "${@:2}" + RET_STATUS=$? + ;; commit) # debug file /tmp/bar should be deleted before release /opt/vyatta/sbin/my_commit -a >> /tmp/bar diff --git a/scripts/vyatta-comment-config.pl b/scripts/vyatta-comment-config.pl new file mode 100644 index 0000000..ab3191e --- /dev/null +++ b/scripts/vyatta-comment-config.pl @@ -0,0 +1,76 @@ +#!/usr/bin/perl + +# Author: Michael Larson <mike@vyatta.com> +# Date: 2010 +# Description: Perl script for adding comments to portions of the configuration + +# **** License **** +# 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. +# +# This code was originally developed by Vyatta, Inc. +# Portions created by Vyatta are Copyright (C) 2006, 2007, 2008, 2009, 2010 Vyatta, Inc. +# All Rights Reserved. +# **** End License **** + +use strict; +use warnings; +use File::Find; +use lib "/opt/vyatta/share/perl5"; + + +sub usage() { + print "Usage: $0 <path>\n"; + exit 0; +} + +if ($#ARGV == 0) { + exit 0; +} + +#adjust for leaf node +my $i = 0; +my @path = @ARGV[0..$#ARGV-1]; +foreach my $elem (@path) { + $elem =~ s/\//%2F/g; + $elem =~ s/\s+/\//g; + $path[$i++] = $elem; +} +my $path = join '/', @path; + +my $full_path = "$ENV{VYATTA_TEMP_CONFIG_DIR}/$path"; + +if (! -e $full_path) { + $path = join '/', @path[0..$#path-1]; + my $leaf = "$ENV{VYATTA_TEMP_CONFIG_DIR}/$path/node.val"; + if (-e $leaf) { + $full_path = "$ENV{VYATTA_TEMP_CONFIG_DIR}/$path"; + } + else { + `echo \"Path is not valid\n\"`; + exit 0; + } +} + +#scan for illegal characters here: '/*', '*/' +if ($ARGV[$#ARGV] =~ /\/\*|\*\//) { + print "illegal characters found in comment\n"; + exit 1; +} + + +if ($ARGV[$#ARGV] eq '') { + `rm -f $full_path/.comment`; +} +else { + `echo \"$ARGV[$#ARGV]\" > $full_path/.comment`; +} + +print "Done\n"; +exit 0; diff --git a/scripts/vyatta-config-gen-sets.pl b/scripts/vyatta-config-gen-sets.pl index e364dfa..7cf4feb 100755 --- a/scripts/vyatta-config-gen-sets.pl +++ b/scripts/vyatta-config-gen-sets.pl @@ -32,7 +32,8 @@ my $conf_file = '/opt/vyatta/etc/config/config.boot'; $conf_file = $ARGV[0] if defined $ARGV[0]; # get a list of all config statement in the startup config file -my @all_nodes = Vyatta::ConfigLoad::getStartupConfigStatements($conf_file); +my %cfg_hier = Vyatta::ConfigLoad::getStartupConfigStatements($conf_file); +my @all_nodes = @{ $cfg_hier{'set'} }; if (scalar(@all_nodes) == 0) { # no config statements exit 1; diff --git a/scripts/vyatta-config-loader.pl b/scripts/vyatta-config-loader.pl index 7a3df2b..0aae55b 100755 --- a/scripts/vyatta-config-loader.pl +++ b/scripts/vyatta-config-loader.pl @@ -46,7 +46,9 @@ sub restore_fds { } # get a list of all config statement in the startup config file -my @all_nodes = Vyatta::ConfigLoad::getStartupConfigStatements($ARGV[0]); +my %cfg_hier = Vyatta::ConfigLoad::getStartupConfigStatements($ARGV[0],'true'); +my @all_nodes = @{ $cfg_hier{'set'} }; +my @deactivate_nodes = @{ $cfg_hier{'deactivate'} }; if (scalar(@all_nodes) == 0) { # no config statements restore_fds(); @@ -72,11 +74,30 @@ foreach (@all_nodes) { my ($path_ref, $rank) = @$_; my @pr = @$path_ref; - if (@pr[0] eq '!') { - @pr = @pr[1..$#pr]; - my $deactivate_cmd = "$CWRAPPER deactivate " . (join ' ', @pr) . " 1>/dev/null"; - system("$deactivate_cmd"); - #ignore these errors due to nesting warnings. + if (@pr[0] =~ /^comment$/) { + my $ct = 0; + my $rel_path; + foreach my $rp (@pr[1..$#pr]) { + $ct++; + my $tmp_path = $rel_path . "/" . $rp; + my $node_path = "/opt/vyatta/share/vyatta-cfg/templates/" . $tmp_path . "/node.def"; + if ($rp eq '"') { + last; + } + elsif ($rp eq '""') { + last; + } + elsif (!-e $node_path) { + #pop this element + delete @pr[$ct]; + last; + } + $rel_path = $tmp_path; + } + + my $comment_cmd = "$CWRAPPER " . join(" ",@pr) ; + `$comment_cmd`; + next; } my $cmd = "$CWRAPPER set " . (join ' ', @pr); @@ -90,6 +111,13 @@ foreach (@all_nodes) { # continue after set failure (or should we abort?) } } + +# Now deactivate these nodes +for (@deactivate_nodes) { + my $cmd = "$CWRAPPER deactivate " . $_ . " 1>/dev/null"; + system("$cmd"); +} + $ret = system("$commit_cmd"); if ($ret >> 8) { print OLDOUT "Commit failed at boot\n"; diff --git a/scripts/vyatta-load-config.pl b/scripts/vyatta-load-config.pl index ab5a47e..296dc0d 100755 --- a/scripts/vyatta-load-config.pl +++ b/scripts/vyatta-load-config.pl @@ -191,6 +191,7 @@ if ( scalar( keys %cfg_hier ) == 0 ) { my %cfg_diff = Vyatta::ConfigLoad::getConfigDiff( \%cfg_hier ); my @set_list = @{ $cfg_diff{'set'} }; my @deactivate_list = @{ $cfg_diff{'deactivate'} }; +my @comment_list = @{ $cfg_diff{'comment'} }; if ($merge_mode eq 'false') { my @delete_list = @{ $cfg_diff{'delete'} }; @@ -219,10 +220,45 @@ foreach (@set_list) { } foreach (@deactivate_list) { - my ( $cmd_ref, $rank ) = @{$_}; - my @cmd = ( "$sbindir/vyatta-activate-config.pl deactivate", @{$cmd_ref} ); - my $cmd_str = join ' ', @cmd; - system("$cmd_str 1>/dev/null"); + #need to remove .disable nodes recursively in tree through activate command + my $cmd = "$sbindir/vyatta-activate-config.pl deactivate $_"; + system("$cmd 1>/dev/null"); + #ignore error on complaint re: nested nodes +} + +foreach (@comment_list) { + my ( $cmd_ref ) = $_; + #apply comment if it doesn't have an empty element at the array and a .comment file exists and this is not a merge + if ($merge_mode eq 'false' && $cmd_ref =~ /\"\"$/) { + my @cmd_array = split(" ",$cmd_ref); + pop(@cmd_array); + my $rel_path = join '/', @cmd_array; + my $path = "/opt/vyatta/config/active/" . $rel_path . "/.comment"; + if (-e $path) { + my @cmd = ( "$sbindir/vyatta-comment-config.pl ", $cmd_ref ); + my $cmd_str = join ' ', @cmd; + system("$cmd_str 1>/dev/null"); + } + else { + #not found, maybe a leaf? + pop(@cmd_array); + $rel_path = join '/', @cmd_array; + my $leaf = "/opt/vyatta/config/active/" . $rel_path . "/node.val"; + if (-e $leaf) { + $path = "/opt/vyatta/config/active/" . $rel_path . "/.comment"; + if (-e $path) { + my @cmd = ( "$sbindir/vyatta-comment-config.pl ", $cmd_ref ); + my $cmd_str = join ' ', @cmd; + system("$cmd_str 1>/dev/null"); + } + } + } + } + else { + my @cmd = ( "$sbindir/vyatta-comment-config.pl ", $cmd_ref ); + my $cmd_str = join ' ', @cmd; + system("$cmd_str 1>/dev/null"); + } #ignore error on complaint re: nested nodes } diff --git a/src/cli_def.l b/src/cli_def.l index 804d142..a7de87d 100644 --- a/src/cli_def.l +++ b/src/cli_def.l @@ -257,7 +257,7 @@ RE_TYPE_NAME (txt|u32|ipv4|ipv4net|ipv6|ipv6net|bool|macaddr) /* values */ RE_VAL_U32 [0-9]+ RE_VAL_BOOL (true|false) -RE_VAL_TEXT [a-zA-Z]+ +RE_VAL_PRIORITY (PARENT) /* operators */ RE_OP_COND (==|!=|<|>|<=|>=|in) @@ -445,7 +445,7 @@ RE_ACT_FIELD (help|syntax|commit|delete|update|activate|create|begin|end|comp_he return VAR; } -<INITIAL,expression>{RE_VAL_TEXT} { return return_value(TEXT_TYPE); } +<INITIAL,expression>{RE_VAL_PRIORITY} { return return_value(PRIORITY_TYPE); } <INITIAL,expression>{RE_VAL_U32} { return return_value(INT_TYPE); } <INITIAL,expression>{RE_IPV4} { return return_value(IPV4_TYPE); } <INITIAL,expression>{RE_IPV4NET} { return return_value(IPV4NET_TYPE); } diff --git a/src/cli_new.c b/src/cli_new.c index f6a22ea..c4d1b86 100644 --- a/src/cli_new.c +++ b/src/cli_new.c @@ -206,23 +206,23 @@ void add_val(valstruct *first, valstruct *second) { assert (first->free_me && second->free_me); assert(second->cnt == 0); - if (first->val_type != second->val_type) { - printf("Different types\n\n"); - } else { - if (first->cnt%MULTI_ALLOC == 0) { - /* convert into multivalue */ - first->vals = my_realloc(first->vals, (first->cnt + MULTI_ALLOC) * - sizeof(char *), "add_value"); - if (first->cnt == 0) { /* single value - convert */ - first->vals[0] = first->val; - first->cnt = 1; - first->val = NULL; - } + if (first->cnt%MULTI_ALLOC == 0) { + /* convert into multivalue */ + first->vals = my_realloc(first->vals, (first->cnt + MULTI_ALLOC) * + sizeof(char *), "add_value 1"); + first->val_types = my_realloc(first->val_types,(first->cnt + MULTI_ALLOC) * + sizeof(vtw_type_e), "add_value 2"); + if (first->cnt == 0) { /* single value - convert */ + first->vals[0] = first->val; + first->val_types[0] = first->val_type; + first->cnt = 1; + first->val = NULL; } - second->free_me = FALSE; /* we took its string */ - first->vals[first->cnt] = second->val; - ++first->cnt; } + second->free_me = FALSE; /* we took its string */ + first->vals[first->cnt] = second->val; + first->val_types[first->cnt] = second->val_type; + ++first->cnt; } /***************************************************** append - append node to the tail of list @@ -697,7 +697,7 @@ valstruct str2val(char *cp) /**************************************************** STATIC FUNCTIONS ****************************************************/ -int char2val_notext(vtw_def *def, int my_type, char *value, valstruct **valp, char *buf); +int char2val_notext(vtw_def *def, int my_type, int my_type2, char *value, valstruct **valp, char *buf); int char2val_text(vtw_def *def, char *value, valstruct **valp); /************************************************** @@ -731,18 +731,9 @@ int char2val(vtw_def *def, char *value, valstruct *valp) //currently fails to handle mixed text + non-text case... char buf1[2048]; - if (char2val_notext(def,my_type,value,&valp,buf1) != 0) { - if (my_type2 != ERROR_TYPE) { - char buf2[2048]; - if (char2val_notext(def,my_type2,value,&valp,buf2) != 0) { - fprintf(out_stream,"%s%s",buf1,buf2); - return -1; - } - } - else { - fprintf(out_stream,"%s",buf1); - return -1; //only single definition - } + if (char2val_notext(def,my_type,my_type2,value,&valp,buf1) != 0) { + fprintf(out_stream,"%s",buf1); + return -1; //only single definition } return 0; } @@ -753,13 +744,22 @@ int char2val(vtw_def *def, char *value, valstruct *valp) //non-text type processing block -int char2val_notext(vtw_def *def, int my_type, char *value, valstruct **valpp, char *err_buf) +int char2val_notext(vtw_def *def, int my_type, int my_type2, char *value, valstruct **valpp, char *err_buf) { valstruct *valp = *valpp; int token; boolean first = TRUE; cli_val_len = strlen(value); cli_val_ptr = value; + + char type_buf[256]; + if (my_type2 != ERROR_TYPE) { + sprintf(type_buf,"%s or %s",type_to_name(my_type),type_to_name(my_type2)); + } + else { + sprintf(type_buf,"%s",type_to_name(my_type)); + } + while(1) { token = yy_cli_val_lex(); @@ -774,19 +774,20 @@ int char2val_notext(vtw_def *def, int my_type, char *value, valstruct **valpp, c print_msg("Wrong type of value in %s, " "need %s\n", m_path.path_buf + m_path.print_offset, - type_to_name(my_type)); + type_buf); token = yy_cli_val_lex(); sprintf(err_buf, "\"%s\" is not a valid value of type \"%s\"\n", - value, type_to_name(my_type)); + value, type_buf); } return -1; } return 0; } - if (my_type != get_cli_value_ptr()->val_type) { + if (my_type != get_cli_value_ptr()->val_type && + (my_type2 != ERROR_TYPE && my_type2 != get_cli_value_ptr()->val_type)) { if (def->def_type_help){ set_at_string(value); (void)expand_string(def->def_type_help); @@ -795,12 +796,12 @@ int char2val_notext(vtw_def *def, int my_type, char *value, valstruct **valpp, c print_msg("Wrong type of value in %s, " "need %s\n", m_path.path_buf + m_path.print_offset, - type_to_name(my_type)); + type_buf); token = yy_cli_val_lex(); sprintf(err_buf, "\"%s\" is not a valid value of type \"%s\"\n", - value, type_to_name(my_type)); + value, type_buf); } my_free(get_cli_value_ptr()->val); if (first) { @@ -870,6 +871,7 @@ int char2val_text(vtw_def *def, char *value, valstruct **valpp) cnt = (linecnt + MULTI_ALLOC - 1) / MULTI_ALLOC; cnt *= MULTI_ALLOC; valp->vals = my_malloc(cnt * sizeof(char *), "char2val 2"); + valp->val_types = my_malloc(cnt * sizeof(vtw_type_e), "char2val 3"); for(cp = value, cnt = 0; cnt < linecnt; ++cnt) { endp = strchr(cp, '\n'); if (endp) @@ -914,8 +916,6 @@ boolean val_cmp(const valstruct *left, const valstruct *right, vtw_cond_e cond) else rstop = 1; - DPRINT("val_cmp: type=%d count=(%d,%d) val=(%s,%s)\n", - val_type, lstop, rstop, left->val, right->val); for(lcur = 0; lcur < lstop; ++lcur) { if (!lcur && !left->cnt) lval = left->val; @@ -947,6 +947,11 @@ boolean val_cmp(const valstruct *left, const valstruct *right, vtw_cond_e cond) (void) sscanf(lval, format, left_parts, left_parts+1, left_parts+2, left_parts+3, left_parts+4, left_parts+5); + + if ((rcur || right->cnt) + && right->val_types[rcur] != NULL) { + format = cond_formats[right->val_types[rcur]]; + } (void) sscanf(rval, format, right_parts, right_parts+1, right_parts+2, right_parts+3, right_parts+4, right_parts+5); @@ -971,16 +976,21 @@ boolean val_cmp(const valstruct *left, const valstruct *right, vtw_cond_e cond) res = 0; } done_comp: - if(res > 0) res = 1; - else if(res < 0) res = -1; + if (res > 0) + res = 1; + else if (res < 0) + res = -1; + ret = ((res == cond1[cond]) || (res == cond2[cond])); + if (ret && cond == IN_COND) { set_in_cond_tik(rcur); /* for delete */ /* one success is enough for right cycle in case of IN_COND, continue left cycle */ break; } + if (!ret && cond != IN_COND) /* one failure is enough in cases other than IN_COND - go out */ @@ -1675,6 +1685,8 @@ void free_val(valstruct *val) my_free(val->vals[cnt]); if(val->vals) my_free(val->vals); + if(val->val_types) + my_free(val->val_types); } /***************************************************** free_string - dealloc string diff --git a/src/cli_val.h b/src/cli_val.h index e6182e7..00ed103 100644 --- a/src/cli_val.h +++ b/src/cli_val.h @@ -30,7 +30,8 @@ typedef enum { MACADDR_TYPE, DOMAIN_TYPE, /*end of addr types */ TEXT_TYPE, - BOOL_TYPE + BOOL_TYPE, + PRIORITY_TYPE }vtw_type_e; typedef enum { @@ -65,6 +66,7 @@ typedef struct { char *val; int cnt; /* >0 means multivalue */ char **vals; /* We might union with val */ + vtw_type_e *val_types; /* used with vals and multitypes */ boolean free_me; }valstruct; diff --git a/src/common/unionfs.c b/src/common/unionfs.c index 151c6ce..2f7cd70 100644 --- a/src/common/unionfs.c +++ b/src/common/unionfs.c @@ -227,10 +227,10 @@ retrieve_data(char* rel_data_path, GNode *node, char* root, NODE_OPERATION op) //either multi or tag--shouldn't have made a difference, but arkady was confused. vn->_config._multi = (def.tag | def.multi); - if (def.def_tag > 0) { + if (def.def_tag != 0) { vn->_config._limit = def.def_tag; } - else if (def.def_multi > 0) { + else if (def.def_multi != 0) { vn->_config._limit = def.def_multi; } else { diff --git a/src/delete.c b/src/delete.c index f432934..4f38f54 100644 --- a/src/delete.c +++ b/src/delete.c @@ -322,8 +322,8 @@ int main(int argc, char **argv) bye("Corrupted old value ---- \n%s\n-----\n", cp); res = val_cmp(&new_value, &old_value, IN_COND); if (!res) { - fprintf(out_stream, "%s is not a configured value\n", new_value.val); - bye("Not in multivalue"); + fprintf(out_stream, "%s is not a configured value, %s\n", new_value.val,old_value.val); + bye("Not in multivalue"); } touch(); if (old_value.cnt) { @@ -93,7 +93,10 @@ boolean set_validate(vtw_def *defp, char *valp, boolean empty_val) } //apply limit count here, needs to be defined as a tag,multi and have a value set - if ((defp->tag || defp->multi) && (defp->def_tag > 0 || defp->def_multi > 0)) { + + //NOTE: changed behavior for def_tag==1. Needs signed 32 support in parser where -1 + //represents embedded tag node... TODO + if ((defp->tag || defp->multi) && (defp->def_tag != 0 || defp->def_multi != 0)) { //get count of siblings char path[2048]; @@ -124,7 +127,7 @@ boolean set_validate(vtw_def *defp, char *valp, boolean empty_val) } closedir(dirp); - if (defp->tag && file_count == 1 && defp->def_tag == 1) { + if (defp->tag && file_count == 1 && defp->def_tag < 0) { //this is the special case, where the previous value should be deleted here... char command[8192]; //let unionfs handle the diff @@ -133,14 +136,34 @@ boolean set_validate(vtw_def *defp, char *valp, boolean empty_val) } if (defp->tag) { - if (defp->def_tag > 1 && file_count >= defp->def_tag) { - fprintf(out_stream,"Number of values exceeded for %s, allowed: %d, actual: %d\n",val,defp->def_tag,file_count); + if (defp->def_tag > 0 && file_count >= defp->def_tag) { + char *p = rindex(path,'/'); + char tmp[2048]; + if (p != NULL) { + int off = p - path; + strncpy(tmp,path + off + 1, strlen(path) - off - 1); + tmp[strlen(path) - off - 1] = '\0'; + fprintf(out_stream,"Number of values exceeded for '%s', allowed: %d, actual: %d\n",tmp,defp->def_tag,file_count); + } + else { + fprintf(out_stream,"Number of values exceeded, allowed: %d, actual: %d\n",defp->def_tag,file_count); + } return FALSE; } } else { if (defp->def_multi > 1 && file_count >= defp->def_multi) { - fprintf(out_stream,"Number of values exceeded for %s, allowed: %d, actual: %d\n",val,defp->def_multi,file_count); + char *p = rindex(path,'/'); + char tmp[2048]; + if (p != NULL) { + int off = p - path; + strncpy(tmp,path + off + 1, strlen(path) - off - 1); + tmp[strlen(path) - off - 1] = '\0'; + fprintf(out_stream,"Number of values exceeded for '%s', allowed: %d, actual: %d\n",tmp,defp->def_tag,file_count); + } + else { + fprintf(out_stream,"Number of values exceeded, allowed: %d, actual: %d\n",defp->def_tag,file_count); + } return FALSE; } } |