diff options
author | Stig Thormodsrud <stig@io.vyatta.com> | 2009-02-02 19:50:21 -0800 |
---|---|---|
committer | Stig Thormodsrud <stig@io.vyatta.com> | 2009-02-02 19:50:21 -0800 |
commit | 299adf5bb38fa7e026ccd3604fc05ba812520700 (patch) | |
tree | 1df602c721dafae568a14b79d4af9b58e6c0e4b3 /lib/Vyatta/IpTables/IpSet.pm | |
parent | 3ea4540b14ad999386c4b359a963bf362d545ee2 (diff) | |
download | vyatta-cfg-firewall-299adf5bb38fa7e026ccd3604fc05ba812520700.tar.gz vyatta-cfg-firewall-299adf5bb38fa7e026ccd3604fc05ba812520700.zip |
Add 1st pass of firewall group support (ipset netfilter module
integration).
Diffstat (limited to 'lib/Vyatta/IpTables/IpSet.pm')
-rwxr-xr-x | lib/Vyatta/IpTables/IpSet.pm | 225 |
1 files changed, 225 insertions, 0 deletions
diff --git a/lib/Vyatta/IpTables/IpSet.pm b/lib/Vyatta/IpTables/IpSet.pm new file mode 100755 index 0000000..c8508c6 --- /dev/null +++ b/lib/Vyatta/IpTables/IpSet.pm @@ -0,0 +1,225 @@ +#!/usr/bin/perl +# +# Module: IpSet.pm +# +# **** 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) 2009 Vyatta, Inc. +# All Rights Reserved. +# +# Author: Stig Thormodsrud +# Date: January 2009 +# Description: vyatta interface to ipset +# +# **** End License **** +# + +package Vyatta::IpTables::IpSet; + +use Vyatta::Config; +use Vyatta::TypeChecker; +use Vyatta::Misc; +use NetAddr::IP; + +use strict; +use warnings; + +my %fields = ( + _name => undef, + _type => undef, + _debug => undef, +); + +my $logger = 'logger -t IpSet.pm -p local0.warn --'; + +sub new { + my ($that, $name, $type) = @_; + + my $class = ref ($that) || $that; + my $self = { + %fields, + }; + $self->{_name} = $name; + $self->{_type} = $type; + + bless $self, $class; + return $self; +} + +sub debug { + my ($self, $onoff) = @_; + + $self->{_debug} = undef; + $self->{_debug} = 1 if $onoff eq "on"; +} + +sub exists { + my ($self) = @_; + + return 0 if ! defined $self->{_name}; + my $func = (caller(0))[3]; + my $cmd = "ipset -L $self->{_name}"; + my $rc = system("sudo $cmd > /dev/null &>2"); + system("$logger [$func] [$cmd] = [$rc]") if defined $self->{_debug}; + return $rc ? 0 : 1; +} + +sub create { + my ($self) = @_; + + return "Error: undefined group name" if ! defined $self->{_name}; + return "Error: undefined group type" if ! defined $self->{_type}; + return "Error: group [$self->{_name}] already exists" if $self->exists(); + + my $ipset_param; + if ($self->{_type} eq 'address') { + $ipset_param = 'iphash'; + } elsif ($self->{_type} eq 'network') { + $ipset_param = 'nethash'; + } elsif ($self->{_type} eq 'port') { + $ipset_param = 'portmap --from 1 --to 65535'; + } else { + return "Error: invalid group type"; + } + + my $func = (caller(0))[3]; + my $cmd = "ipset -N $self->{_name} $ipset_param"; + my $rc = system("sudo $cmd"); + system("$logger [$func] [$cmd] = [$rc]") if defined $self->{_debug}; + return "Error: call to ipset failed [$rc]" if $rc; + return undef; +} + +sub references { + my ($self) = @_; + + return 0 if ! $self->exists(); + my @lines = `sudo ipset -L $self->{_name}`; + foreach my $line (@lines) { + if ($line =~ /^References:\s+(\d+)$/) { + return $1; + } + } + return 0; +} + +sub delete { + my ($self) = @_; + + return "Error: undefined group name" if ! defined $self->{_name}; + return "Error: group [$self->{_name}] doesn't exists\n" if !$self->exists(); + + my $refs = $self->references(); + return "Error: group [$self->{_name}] still in use.\n" if $refs != 0; + + my $func = (caller(0))[3]; + my $cmd = "ipset -X $self->{_name}"; + my $rc = system("sudo $cmd"); + system("$logger [$func] [$cmd] = [$rc]") if defined $self->{_debug}; + return "Error: call to ipset failed [$rc]" if $rc; + return undef; +} + +sub check_member { + my ($self, $member) = @_; + + return "Error: undefined group name" if ! defined $self->{_name}; + return "Error: undefined group type" if ! defined $self->{_type}; + + if ($self->{_type} eq 'address') { + if (!Vyatta::TypeChecker::validateType('ipv4', $member, 1)) { + return "Error: [$member] isn't valid IPv4 address\n"; + } + } elsif ($self->{_type} eq 'network') { + if (!Vyatta::TypeChecker::validateType('ipv4net', $member, 1)) { + return "Error: [$member] isn't valid IPv4 network\n"; + } + } elsif ($self->{_type} eq 'port') { + if ($member =~ /^\d/) { + my ($success, $err) = Vyatta::Misc::isValidPortNumber($member); + if (!defined $success) { + return "Error: [$member] isn't valid port number\n"; + } + } else { + my ($success, $err) = Vyatta::Misc::isValidPortName($member); + if (!defined $success) { + return "Error: [$member] isn't valid port name\n"; + } + } + } else { + return "Error: invalid set type [$self->{_type}]"; + } + return undef; +} + +sub member_exists { + my ($self, $member) = @_; + + my $func = (caller(0))[3]; + my $cmd = "ipset -T $self->{_name} $member -q"; + my $rc = system("sudo $cmd"); + system("$logger [$func] [$cmd] = [$rc]") if defined $self->{_debug}; + return $rc ? 0 : 1; +} + +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 ($self->member_exists($member)) { + return "Error: member [$member] already exists in [$self->{_name}]\n"; + } + my $func = (caller(0))[3]; + my $cmd = "ipset -A $self->{_name} $member"; + my $rc = system("sudo $cmd"); + system("$logger [$func] [$cmd] = [$rc]") if defined $self->{_debug}; + return "Error: call to ipset failed [$rc]" if $rc; + return undef; +} + +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 (!$self->member_exists($member)) { + return "Error: member [$member] doesn't exists in [$self->{_name}]\n"; + } + my $func = (caller(0))[3]; + my $cmd = "ipset -D $self->{_name} $member"; + my $rc = system("sudo $cmd"); + system("$logger [$func] [$cmd] = [$rc]") if defined $self->{_debug}; + return "Error: call to ipset failed [$rc]" if $rc; + return undef; +} + +sub rule { + my ($self, $direction) = @_; + + if (! $self->exists()) { + my $rc = $self->create(); + return (undef, $rc) if $rc; + } + + my $srcdst; + my $grp = $self->{_name}; + $srcdst = 'src' if $direction eq 'source'; + $srcdst = 'dst' if $direction eq 'destination'; + + return (undef, "Invalid direction [$direction]") if ! defined $srcdst; + return ("-m set --set $grp $srcdst ", ); +} + +1; |