diff options
-rwxr-xr-x | lib/Vyatta/IpTables/IpSet.pm | 100 | ||||
-rwxr-xr-x | scripts/firewall/vyatta-ipset.pl | 3 | ||||
-rw-r--r-- | templates/firewall/group/address-group/node.tag/address/node.def | 10 | ||||
-rw-r--r-- | templates/firewall/group/network-group/node.tag/network/node.def | 7 | ||||
-rw-r--r-- | templates/firewall/group/port-group/node.tag/port/node.def | 9 |
5 files changed, 108 insertions, 21 deletions
diff --git a/lib/Vyatta/IpTables/IpSet.pm b/lib/Vyatta/IpTables/IpSet.pm index 5689f0a..ec03430 100755 --- a/lib/Vyatta/IpTables/IpSet.pm +++ b/lib/Vyatta/IpTables/IpSet.pm @@ -72,13 +72,14 @@ sub debug { sub exists { my ($self) = @_; - return 1 if defined $self->{_exists}; + return 1 if defined $self->{_exists}; return 0 if ! defined $self->{_name}; my $func = (caller(0))[3]; my $cmd = "ipset -L $self->{_name}"; my $rc = system("$cmd > /dev/null &>2"); system("$logger [$func] [$cmd] = [$rc]") if defined $self->{_debug}; $self->{_exists} = 1 if $rc eq 0; + $self->get_type() if ! defined $self->{_type}; return $rc ? 0 : 1; } @@ -112,7 +113,7 @@ sub get_members { if (! defined $self->{_type}) { return @members if ! $self->exists(); } - my @lines = `ipset -L $self->{_name} -n`; + my @lines = `ipset -L $self->{_name} -n -s`; foreach my $line (@lines) { push @members, $line if $line =~ /^\d/; } @@ -171,22 +172,42 @@ sub delete { return; # undef } +sub check_member_address { + my $member = shift; + + if (!Vyatta::TypeChecker::validateType('ipv4', $member, 1)) { + return "Error: [$member] isn't valid IPv4 address\n"; + } + if ($member eq '0.0.0.0') { + return "Error: zero IP address not valid in address-group\n"; + } + return; +} + sub check_member { my ($self, $member) = @_; return "Error: undefined group name" if ! defined $self->{_name}; return "Error: undefined group type" if ! defined $self->{_type}; + # We can't call $self->member_exists() here since this is a + # syntax check and the group may not have been created yet + # if there hasn't been a commit yet on this group. Move the + # exists check to $self->add_member(). + if ($self->{_type} eq 'address') { - if (!Vyatta::TypeChecker::validateType('ipv4', $member, 1)) { - return "Error: [$member] isn't valid IPv4 address\n"; - } - if ($member eq '0.0.0.0') { - return "Error: zero IP address not valid in address-group\n"; + if ($member =~ /^([\d\.]+)-([\d\.]+)$/) { + foreach my $address ($1, $2) { + my $rc = check_member_address($address); + return $rc if defined $rc; + } + } else { + my $rc = check_member_address($member); + return $rc if defined $rc; } } elsif ($self->{_type} eq 'network') { if (!Vyatta::TypeChecker::validateType('ipv4net', $member, 1)) { - return "Error: [$member] isn't valid IPv4 network\n"; + return "Error: [$member] isn't a valid IPv4 network\n"; } if ($member =~ /([\d.]+)\/(\d+)/) { my ($net, $mask) = ($1, $2); @@ -198,15 +219,20 @@ sub check_member { return "Error: Invalid network group [$member]\n"; } } elsif ($self->{_type} eq 'port') { - if ($member =~ /^\d/) { + if ($member =~ /^(\d+)-(\d+)$/) { + my ($success, $err) = Vyatta::Misc::isValidPortRange($member, '-'); + if (!defined $success) { + return "Error: [$member] isn't a valid port range\n"; + } + } elsif ($member =~ /^\d/) { my ($success, $err) = Vyatta::Misc::isValidPortNumber($member); if (!defined $success) { - return "Error: [$member] isn't valid port number\n"; + return "Error: [$member] isn't a valid port number\n"; } } else { my ($success, $err) = Vyatta::Misc::isValidPortName($member); if (!defined $success) { - return "Error: [$member] isn't valid port name\n"; + return "Error: [$member] isn't a valid port name\n"; } } } else { @@ -225,12 +251,37 @@ sub member_exists { return $rc ? 0 : 1; } +sub add_member_range { + my ($self, $start, $stop) = @_; + + if ($self->{_type} eq 'port') { + foreach my $member ($start .. $stop) { + my $rc = $self->add_member($member); + return $rc if defined $rc; + } + } elsif ($self->{_type} eq 'address') { + # $start_ip++ won't work if it doesn't know the + # prefix, so we'll make a big range. + my $start_ip = new NetAddr::IP("$start/16"); + my $stop_ip = new NetAddr::IP($stop); + for (; $start_ip <= $stop_ip; $start_ip++) { + my $rc = $self->add_member($start_ip->addr()); + return $rc if defined $rc; + } + } + return; +} + sub add_member { my ($self, $member) = @_; return "Error: undefined group name" if ! defined $self->{_name}; return "Error: group [$self->{_name}] doesn't exists\n" if !$self->exists(); + if ($member =~ /^([^-]+)-([^-]+)$/) { + return $self->add_member_range($1, $2); + } + if ($self->member_exists($member)) { return "Error: member [$member] already exists in [$self->{_name}]\n"; } @@ -242,12 +293,35 @@ sub add_member { return; # undef } +sub delete_member_range { + my ($self, $start, $stop) = @_; + + if ($self->{_type} eq 'port') { + foreach my $member ($start .. $stop) { + my $rc = $self->delete_member($member); + return $rc if defined $rc; + } + } elsif ($self->{_type} eq 'address') { + my $start_ip = new NetAddr::IP("$start/8"); + my $stop_ip = new NetAddr::IP($stop); + for (; $start_ip <= $stop_ip; $start_ip++) { + my $rc = $self->delete_member($start_ip->addr()); + return $rc if defined $rc; + } + } + return; +} + sub delete_member { my ($self, $member) = @_; return "Error: undefined group name" if ! defined $self->{_name}; return "Error: group [$self->{_name}] doesn't exists\n" if !$self->exists(); + if ($member =~ /^([^-]+)-([^-]+)$/) { + return $self->delete_member_range($1, $2); + } + if (!$self->member_exists($member)) { return "Error: member [$member] doesn't exists in [$self->{_name}]\n"; } @@ -272,8 +346,8 @@ sub get_description { sub get_firewall_references { my ($self) = @_; - return if ! $self->exists(); my @fw_refs = (); + return @fw_refs if ! $self->exists(); my $config = new Vyatta::Config; foreach my $tree ('name', 'modify') { my $path = "firewall $tree "; @@ -285,7 +359,7 @@ sub get_firewall_references { my @rules = $config->listOrigNodes(); foreach my $rule (@rules) { foreach my $dir ('source', 'destination') { - my $rule_path .= "$name_path $rule $dir group"; + my $rule_path = "$name_path $rule $dir group"; $config->setLevel($rule_path); my $group_type = "$self->{_type}-group"; my $value = $config->returnOrigValue($group_type); diff --git a/scripts/firewall/vyatta-ipset.pl b/scripts/firewall/vyatta-ipset.pl index 7d6b783..57b8ce1 100755 --- a/scripts/firewall/vyatta-ipset.pl +++ b/scripts/firewall/vyatta-ipset.pl @@ -105,12 +105,13 @@ sub ipset_show_members { my @fw_refs = $group->get_firewall_references(); push @fw_refs, 'none' if scalar(@fw_refs) == 0; + my $padding = ' ' x 13; print "Name : $set_name\n"; print "Type : $type\n"; print "Description: $desc\n" if defined $desc; print "References : ", join(', ', @fw_refs), "\n"; print "Members :\n"; - print @members; + print $padding, join($padding, @members); return; } diff --git a/templates/firewall/group/address-group/node.tag/address/node.def b/templates/firewall/group/address-group/node.tag/address/node.def index bcaa497..4fc5336 100644 --- a/templates/firewall/group/address-group/node.tag/address/node.def +++ b/templates/firewall/group/address-group/node.tag/address/node.def @@ -1,5 +1,5 @@ multi: -type: ipv4 +type: txt help: Set a address-group member syntax:expression: exec "sudo /opt/vyatta/sbin/vyatta-ipset.pl \ @@ -10,8 +10,12 @@ syntax:expression: exec "sudo /opt/vyatta/sbin/vyatta-ipset.pl \ create: sudo /opt/vyatta/sbin/vyatta-ipset.pl --action=add-member \ --set-name=$VAR(../@) \ - --member="$VAR(@) " + --member="$VAR(@)" delete: sudo /opt/vyatta/sbin/vyatta-ipset.pl --action=delete-member \ --set-name=$VAR(../@) \ - --member="$VAR(@) " + --member="$VAR(@)" + +comp_help: Possible completions: + <x.x.x.x> IPv4 address to match + <x.x.x.x>-<x.x.x.x> IPv4 range to match (e.g. 10.0.0.1-10.0.0.200) diff --git a/templates/firewall/group/network-group/node.tag/network/node.def b/templates/firewall/group/network-group/node.tag/network/node.def index cd3a6a6..ad43311 100644 --- a/templates/firewall/group/network-group/node.tag/network/node.def +++ b/templates/firewall/group/network-group/node.tag/network/node.def @@ -13,8 +13,11 @@ syntax:expression: exec " \ create: sudo /opt/vyatta/sbin/vyatta-ipset.pl --action=add-member \ --set-name=$VAR(../@) \ - --member="$VAR(@) " + --member="$VAR(@)" delete: sudo /opt/vyatta/sbin/vyatta-ipset.pl --action=delete-member \ --set-name=$VAR(../@) \ - --member="$VAR(@) " + --member="$VAR(@)" + +comp_help: Possible completions: + <x.x.x.x/x> IPv4 Subnet to match diff --git a/templates/firewall/group/port-group/node.tag/port/node.def b/templates/firewall/group/port-group/node.tag/port/node.def index 92bce9c..0f0981b 100644 --- a/templates/firewall/group/port-group/node.tag/port/node.def +++ b/templates/firewall/group/port-group/node.tag/port/node.def @@ -10,8 +10,13 @@ syntax:expression: exec "sudo /opt/vyatta/sbin/vyatta-ipset.pl \ create: sudo /opt/vyatta/sbin/vyatta-ipset.pl --action=add-member \ --set-name=$VAR(../@) \ - --member="$VAR(@) " + --member="$VAR(@)" delete: sudo /opt/vyatta/sbin/vyatta-ipset.pl --action=delete-member \ --set-name=$VAR(../@) \ - --member="$VAR(@) " + --member="$VAR(@)" + +comp_help: Possible completions: + <port name> Named port (any name in /etc/services, e.g., http) + <1-65535> Numbered port + <start>-<end> Numbered port range (e.g. 1001-1050) |