diff options
Diffstat (limited to 'lib')
-rwxr-xr-x | lib/Vyatta/IpTables/AddressFilter.pm | 210 |
1 files changed, 210 insertions, 0 deletions
diff --git a/lib/Vyatta/IpTables/AddressFilter.pm b/lib/Vyatta/IpTables/AddressFilter.pm new file mode 100755 index 0000000..9b1e318 --- /dev/null +++ b/lib/Vyatta/IpTables/AddressFilter.pm @@ -0,0 +1,210 @@ +#!/usr/bin/perl + +# Author: An-Cheng Huang <ancheng@vyatta.com> +# Date: 2007 +# Description: IP tables address filter + +# **** 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 Vyatta, Inc. +# All Rights Reserved. +# **** End License **** + +package Vyatta::IpTables::AddressFilter; + +require Vyatta::Config; +use Vyatta::Misc; +use Vyatta::TypeChecker; + +use strict; +use warnings; + +my %_protocolswithports = ( + tcp => 1, + udp => 1, + 6 => 1, + 17 => 1, +); + +my %fields = ( + _srcdst => undef, + _range_start => undef, + _range_stop => undef, + _network => undef, + _address => undef, + _port => undef, + _protocol => undef, + _src_mac => undef, +); + +sub new { + my $that = shift; + my $class = ref ($that) || $that; + my $self = { + %fields, + }; + + bless $self, $class; + return $self; +} + +sub setup { + my ($self, $level) = @_; + my $config = new Vyatta::Config; + + $config->setLevel("$level"); + + # setup needed parent nodes + $self->{_srcdst} = $config->returnParent(".."); + $self->{_protocol} = $config->returnValue(".. protocol"); + + # setup address filter nodes + $self->{_address} = $config->returnValue("address"); + $self->{_network} = undef; + $self->{_range_start} = undef; + $self->{_range_stop} = undef; + if (defined($self->{_address})) { + if ($self->{_address} =~ /\//) { + $self->{_network} = $self->{_address}; + $self->{_address} = undef; + } elsif ($self->{_address} =~ /^([^-]+)-([^-]+)$/) { + $self->{_range_start} = $1; + $self->{_range_stop} = $2; + $self->{_address} = undef; + } + } + + $self->{_port} = $config->returnValue("port"); + $self->{_src_mac} = $config->returnValue("mac-address"); + + return 0; +} + +sub setupOrig { + my ($self, $level) = @_; + my $config = new Vyatta::Config; + + $config->setLevel("$level"); + + # setup needed parent nodes + $self->{_srcdst} = $config->returnParent(".."); + $self->{_protocol} = $config->returnOrigValue(".. protocol"); + + # setup address filter nodes + $self->{_address} = $config->returnOrigValue("address"); + $self->{_network} = undef; + $self->{_range_start} = undef; + $self->{_range_stop} = undef; + if (defined($self->{_address})) { + if ($self->{_address} =~ /\//) { + $self->{_network} = $self->{_address}; + $self->{_address} = undef; + } elsif ($self->{_address} =~ /^([^-]+)-([^-]+)$/) { + $self->{_range_start} = $1; + $self->{_range_stop} = $2; + $self->{_address} = undef; + } + } + + $self->{_port} = $config->returnOrigValue("port"); + $self->{_src_mac} = $config->returnValue("mac-address"); + + return 0; +} + +sub print { + my ($self) = @_; + + print "srcdst: $self->{_srcdst}\n" if defined $self->{_srcdst}; + print "range start: $self->{_range_start}\n" if defined $self->{_range_start}; + print "range stop: $self->{_range_stop}\n" if defined $self->{_range_stop}; + print "network: $self->{_network}\n" if defined $self->{_network}; + print "address: $self->{_address}\n" if defined $self->{_address}; + print "port: $self->{_port}\n" if defined $self->{_port}; + print "protocol: $self->{_protocol}\n" if defined $self->{_protocol}; + print "src-mac: $self->{_src_mac}\n" if defined $self->{_src_mac}; + + return 0; +} + +sub rule { + my ($self) = @_; + my $rule = ""; + my $can_use_port = 1; + + if (!defined($self->{_protocol}) + || !defined($_protocolswithports{$self->{_protocol}})) { + $can_use_port = 0; + } + + if (($self->{_srcdst} eq "source") && (defined($self->{_src_mac}))) { + # handle src mac + my $str = $self->{_src_mac}; + $str =~ s/^\!(.*)$/! $1/; + $rule .= "-m mac --mac-source $str "; + } + + # set the address filter parameters + if (defined($self->{_network})) { + my $str = $self->{_network}; + return (undef, "\"$str\" is not a valid IP subnet") + if (!VyattaTypeChecker::validateType('ipv4net_negate', $str, 1)); + $str =~ s/^\!(.*)$/! $1/; + $rule .= "--$self->{_srcdst} $str "; + } elsif (defined($self->{_address})) { + my $str = $self->{_address}; + return (undef, "\"$str\" is not a valid IP address") + if (!VyattaTypeChecker::validateType('ipv4_negate', $str, 1)); + $str =~ s/^\!(.*)$/! $1/; + $rule .= "--$self->{_srcdst} $str "; + } elsif ((defined $self->{_range_start}) && (defined $self->{_range_stop})) { + my $start = $self->{_range_start}; + my $stop = $self->{_range_stop}; + return (undef, "\"$start-$stop\" is not a valid IP range") + if (!VyattaTypeChecker::validateType('ipv4_negate', $start, 1) + || !VyattaTypeChecker::validateType('ipv4', $stop, 1)); + my $negate = ''; + if ($self->{_range_start} =~ /^!(.*)$/) { + $start = $1; + $negate = '! ' + } + if ("$self->{_srcdst}" eq "source") { + $rule .= ("-m iprange $negate--src-range $start-$self->{_range_stop} "); + } + elsif ("$self->{_srcdst}" eq "destination") { + $rule .= ("-m iprange $negate--dst-range $start-$self->{_range_stop} "); + } + } + + my ($port_str, $port_err) + = VyattaMisc::getPortRuleString($self->{_port}, $can_use_port, + ($self->{_srcdst} eq "source") ? "s" : "d", + $self->{_protocol}); + return (undef, $port_err) if (!defined($port_str)); + $rule .= $port_str; + return ($rule, undef); +} + +sub outputXmlElem { + my ($name, $value, $fh) = @_; + print $fh " <$name>$value</$name>\n"; +} + +sub outputXml { + my ($self, $prefix, $fh) = @_; + outputXmlElem("${prefix}_addr", $self->{_address}, $fh); + outputXmlElem("${prefix}_net", $self->{_network}, $fh); + outputXmlElem("${prefix}_addr_start", $self->{_range_start}, $fh); + outputXmlElem("${prefix}_addr_stop", $self->{_range_stop}, $fh); + outputXmlElem("${prefix}_port", $self->{_port}, $fh); +} + |