summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkouak <kouak@kouak.org>2015-02-15 22:37:14 +0100
committerkouak <kouak@kouak.org>2015-02-15 22:37:14 +0100
commit9571f0e592088c49c6c16724c5124631326066fd (patch)
tree89fe54ea2a5232496e32524c4dd99f5f8ae0ee10
parent9ee62f2e55cd83110c5964c020233c0c983154a0 (diff)
downloadvyatta-nat-9571f0e592088c49c6c16724c5124631326066fd.tar.gz
vyatta-nat-9571f0e592088c49c6c16724c5124631326066fd.zip
Add initial support for NPTv6 (#387)
-rw-r--r--Makefile.am4
-rw-r--r--lib/VyOS/Nptv6Rule.pm161
-rwxr-xr-xscripts/vyos-update-nptv6.pl119
-rw-r--r--templates-cfg/nat/nptv6/node.def3
-rw-r--r--templates-cfg/nat/nptv6/rule/node.def11
-rw-r--r--templates-cfg/nat/nptv6/rule/node.tag/description/node.def3
-rw-r--r--templates-cfg/nat/nptv6/rule/node.tag/disable/node.def1
-rw-r--r--templates-cfg/nat/nptv6/rule/node.tag/inside-prefix/node.def7
-rw-r--r--templates-cfg/nat/nptv6/rule/node.tag/outside-interface/node.def30
-rw-r--r--templates-cfg/nat/nptv6/rule/node.tag/outside-prefix/node.def7
10 files changed, 346 insertions, 0 deletions
diff --git a/Makefile.am b/Makefile.am
index 2877aab..d56ca9d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,6 +1,7 @@
cfgdir = $(datadir)/vyatta-cfg/templates
opdir = $(datadir)/vyatta-op/templates
share_perl5dir = $(datadir)/perl5/Vyatta
+share_vyos_perl5dir = $(datadir)/perl5/VyOS
bin_sudo_usersdir = $(bindir)/sudo-users
curverdir = $(sysconfdir)/config-migrate/current
@@ -9,12 +10,15 @@ sbin_SCRIPTS += scripts/vyatta-update-src-nat.pl
sbin_SCRIPTS += scripts/vyatta-show-nat-statistics.pl
sbin_SCRIPTS += scripts/vyatta-show-nat-rules.pl
sbin_SCRIPTS += scripts/vyatta-clear-nat-counters.pl
+sbin_SCRIPTS += scripts/vyos-update-nptv6.pl
bin_sudo_users_SCRIPTS = scripts/vyatta-nat-translations.pl
share_perl5_DATA = lib/Vyatta/NatRuleCommon.pm
share_perl5_DATA += lib/Vyatta/DstNatRule.pm
share_perl5_DATA += lib/Vyatta/SrcNatRule.pm
+
+share_vyos_perl5_DATA = lib/VyOS/Nptv6Rule.pm
curver_DATA = cfg-version/nat@4
cpiop = find . ! -regex '\(.*~\|.*\.bak\|.*\.swp\|.*\#.*\#\)' -print0 | \
diff --git a/lib/VyOS/Nptv6Rule.pm b/lib/VyOS/Nptv6Rule.pm
new file mode 100644
index 0000000..3166325
--- /dev/null
+++ b/lib/VyOS/Nptv6Rule.pm
@@ -0,0 +1,161 @@
+#
+# VyOS::Nptv6Rule: Update SNPT/DNPT ip6tables rules
+#
+# Copyright (C) 2014 VyOS Development Group <maintainers@vyos.net>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+# USA
+
+
+package VyOS::Nptv6Rule;
+
+use strict;
+use lib "/opt/vyatta/share/perl5";
+require Vyatta::Config;
+require Vyatta::IpTables::AddressFilter;
+use Vyatta::Misc;
+use Vyatta::TypeChecker;
+
+require Exporter;
+our @ISA = qw(Exporter);
+our @EXPORT = qw(is_disabled rule_str);
+
+my %fields = (
+ _rule_number => undef,
+ _outside_if => undef,
+ _inside_pfx => undef,
+ _outside_pfx => undef,
+ _disable => 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");
+
+ $self->{_rule_number} = $config->returnParent("..");
+ $self->{_inside_if} = $config->returnValue("inside-interface");
+ $self->{_outside_if} = $config->returnValue("outside-interface");
+ $self->{_inside_pfx} = $config->returnValue("inside-prefix");
+ $self->{_outside_pfx} = $config->returnValue("outside-prefix");
+
+ $self->{_disable} = $config->exists("disable");
+
+ return 0;
+}
+
+# Make SNPT ip6tables string
+# POSTROUTING
+# ip6tables -t mangle -I VYOS_NPT_HOOK -s inside-pfx -o outside-if -j SNPT --src-pfx inside-pfx --dst-pfx outside-pfx
+sub make_snpt_string {
+ my ($self) = @_;
+ my $snpt_str = "";
+
+ # Construct ip6tables string
+ $snpt_str .= "-I VYOS_SNPT_HOOK ";
+ $snpt_str .= "-s ";
+ $snpt_str .= $self->{_inside_pfx};
+ if(defined($self->{_outside_if})) {
+ $snpt_str .= " -o ";
+ $snpt_str .= $self->{_outside_if};
+ }
+ $snpt_str .= " -j SNPT --src-pfx ";
+ $snpt_str .= $self->{_inside_pfx};
+ $snpt_str .= " --dst-pfx ";
+ $snpt_str .= $self->{_outside_pfx};
+
+ return $snpt_str;
+}
+
+# Make DNPT ip6tables string
+# PREROUTING
+# ip6tables -t mangle -I VYOS_NPT_HOOK -d outside-pfx -i outside-if -j DNPT --src-pfx outside-pfx --dst-pfx inside-pfx
+sub make_dnpt_string {
+ my ($self) = @_;
+ my $dnpt_str = "";
+
+ # Construct ip6tables string
+ $dnpt_str .= "-I VYOS_DNPT_HOOK ";
+ $dnpt_str .= "-d ";
+ $dnpt_str .= $self->{_outside_pfx};
+ if(defined($self->{_outside_if})) {
+ $dnpt_str .= " -i ";
+ $dnpt_str .= $self->{_outside_if};
+ }
+ $dnpt_str .= " -j DNPT --src-pfx ";
+ $dnpt_str .= $self->{_outside_pfx};
+ $dnpt_str .= " --dst-pfx ";
+ $dnpt_str .= $self->{_inside_pfx};
+
+ return $dnpt_str;
+}
+
+# Tests if the rule is valid, returns false if valid, returns error string if invalid
+sub is_invalid {
+ my ($self) = @_;
+
+ # Validate prefixes
+ if(!defined($self->{_inside_pfx}) || $self->{_inside_pfx} eq '') {
+ return "inside-prefix must be set";
+ }
+
+ if(!defined($self->{_outside_pfx}) || $self->{_outside_pfx} eq '') {
+ return "outside-prefix must be set";
+ }
+
+ if(!Vyatta::TypeChecker::validateType('ipv6net', $self->{_inside_pfx}, 1)) {
+ return "inside-prefix is not a valid prefix";
+ }
+
+ if(!Vyatta::TypeChecker::validateType('ipv6net', $self->{_outside_pfx}, 1)) {
+ return "outside-prefix is not a valid prefix";
+ }
+
+ return 0;
+}
+
+# Returns an array of ip6tables parameters (SNPT, DNPT)
+sub rule_str {
+ my ($self) = @_;
+ my $err;
+
+ $err = $self->is_invalid();
+ if($err ne 0) {
+ return ($err, undef, undef);
+ }
+
+ return (undef, $self->make_snpt_string(), $self->make_dnpt_string());
+}
+
+sub is_disabled {
+ my $self = shift;
+ return 1 if defined $self->{_disable};
+ return 0;
+}
+
+1;
+
diff --git a/scripts/vyos-update-nptv6.pl b/scripts/vyos-update-nptv6.pl
new file mode 100755
index 0000000..5079a66
--- /dev/null
+++ b/scripts/vyos-update-nptv6.pl
@@ -0,0 +1,119 @@
+#!/usr/bin/perl
+#
+# vyos-update-nptv6.pl: Update SNPT/DNPT ip6tables rules
+#
+# Copyright (C) 2014 VyOS Development Group <maintainers@vyos.net>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+# USA
+
+use strict;
+use lib "/opt/vyatta/share/perl5/";
+use Vyatta::Config;
+use VyOS::Nptv6Rule;
+use Vyatta::IpTables::Mgr;
+
+my $CONFIG_LEVEL = "nat nptv6";
+my $IPTABLES = "/sbin/ip6tables";
+
+sub numerically_desc { $b <=> $a; }
+
+my $config = new Vyatta::Config;
+
+my $all_deleted = 1;
+
+my $rule;
+$config->setLevel($CONFIG_LEVEL." rule");
+my %rules = $config->listNodeStatus();
+for $rule (keys %rules) {
+ if ($rules{$rule} ne "deleted") {
+ $all_deleted = 0;
+ }
+}
+
+my $debug = 0;
+if ($debug) {
+ open(OUT, ">>/tmp/nat") or exit 1;
+} else {
+ open(OUT, ">>/dev/null") or exit 1;
+}
+
+# Send rule to iptables
+sub send_iptables {
+ my @cmds = @_;
+ my $prepend = $IPTABLES . " -t mangle ";
+ my $cmd;
+
+ for $cmd (@cmds) {
+ print OUT $prepend . ' ' . $cmd . "\n";
+ if(system($prepend . ' ' . $cmd)) {
+ exit 1;
+ }
+ }
+ return 0;
+}
+
+# Clean up function
+sub raw_cleanup {
+ my @cmds = ("-F VYOS_SNPT_HOOK", "-F VYOS_DNPT_HOOK", "-A VYOS_SNPT_HOOK -j RETURN", "-A VYOS_DNPT_HOOK -j RETURN");
+ send_iptables(@cmds);
+}
+
+print OUT "========= NPTv6 list =========\n";
+my @rule_keys = sort numerically_desc keys %rules;
+
+# No rules, clean up
+if ($#rule_keys < 0) {
+ raw_cleanup();
+ exit 0;
+}
+
+my @cmds;
+# Loop through all loops, sorted numerically
+for $rule (@rule_keys) {
+ print OUT "$rule: $rules{$rule}\n";
+ my $tmp = `ip6tables -L -nv --line -t mangle`;
+ print OUT "iptables before:\n$tmp\n";
+
+ my $nrule = new VyOS::Nptv6Rule;
+ $nrule->setup($CONFIG_LEVEL." rule $rule");
+
+ if ($rules{$rule} eq "deleted" || $nrule->is_disabled()) {
+ next;
+ }
+
+ my ($err, $snpt_rule, $dnpt_rule) = $nrule->rule_str();
+ if (defined $err) {
+ # rule check failed => return error
+ print OUT "NPT configuration error in rule $rule: $err\n";
+ print STDERR "NPT configuration error in rule $rule: $err\n";
+ exit 5;
+ }
+
+ push(@cmds, $snpt_rule);
+ push(@cmds, $dnpt_rule);
+}
+
+raw_cleanup();
+send_iptables(@cmds);
+
+close OUT;
+exit 0;
+
+# Local Variables:
+# mode: perl
+# indent-tabs-mode: nil
+# perl-indent-level: 2
+# End:
diff --git a/templates-cfg/nat/nptv6/node.def b/templates-cfg/nat/nptv6/node.def
new file mode 100644
index 0000000..be59537
--- /dev/null
+++ b/templates-cfg/nat/nptv6/node.def
@@ -0,0 +1,3 @@
+help: NPTv6 settings
+
+end:expression: "sudo /opt/vyatta/sbin/vyos-update-nptv6.pl"
diff --git a/templates-cfg/nat/nptv6/rule/node.def b/templates-cfg/nat/nptv6/rule/node.def
new file mode 100644
index 0000000..c666be9
--- /dev/null
+++ b/templates-cfg/nat/nptv6/rule/node.def
@@ -0,0 +1,11 @@
+tag:
+
+type: u32
+
+help: Rule number for NAT
+
+syntax:expression: ($VAR(@) > 0 && $VAR(@) < 10000) ; \
+ "Rule number must be between 1 and 9999."
+
+val_help: u32:1-9999 ; Number for this NAT rule
+
diff --git a/templates-cfg/nat/nptv6/rule/node.tag/description/node.def b/templates-cfg/nat/nptv6/rule/node.tag/description/node.def
new file mode 100644
index 0000000..90bf88b
--- /dev/null
+++ b/templates-cfg/nat/nptv6/rule/node.tag/description/node.def
@@ -0,0 +1,3 @@
+type: txt
+
+help: Rule description
diff --git a/templates-cfg/nat/nptv6/rule/node.tag/disable/node.def b/templates-cfg/nat/nptv6/rule/node.tag/disable/node.def
new file mode 100644
index 0000000..c23fc5a
--- /dev/null
+++ b/templates-cfg/nat/nptv6/rule/node.tag/disable/node.def
@@ -0,0 +1 @@
+help: Disable NAT rule
diff --git a/templates-cfg/nat/nptv6/rule/node.tag/inside-prefix/node.def b/templates-cfg/nat/nptv6/rule/node.tag/inside-prefix/node.def
new file mode 100644
index 0000000..7af7091
--- /dev/null
+++ b/templates-cfg/nat/nptv6/rule/node.tag/inside-prefix/node.def
@@ -0,0 +1,7 @@
+type: txt
+
+help: Inside prefix to be translated
+
+val_help: ipv6net; IPv6 prefix to match
+
+syntax:expression: exec "/opt/vyatta/sbin/vyatta-validate-type ipv6_addr_param $VAR(@)"
diff --git a/templates-cfg/nat/nptv6/rule/node.tag/outside-interface/node.def b/templates-cfg/nat/nptv6/rule/node.tag/outside-interface/node.def
new file mode 100644
index 0000000..d0954ad
--- /dev/null
+++ b/templates-cfg/nat/nptv6/rule/node.tag/outside-interface/node.def
@@ -0,0 +1,30 @@
+type: txt
+
+help: Outside interface of NPTv6 traffic
+
+enumeration: existing-interfaces; echo "any"
+
+val_help: <interface> ; Interface name or "any"
+
+commit:expression: exec "
+ if [ \"any\" == \"$VAR(@)\" ] ; then
+ exit 0
+ fi
+ intf_array=($(awk '$1 ~ /:/ { print $1 }' /proc/net/dev))
+ intf_array_len=${#intf_array[*]}
+ i=0
+ while [ $i -lt $intf_array_len ]; do
+ temp=${intf_array[$i]%:*}
+ if [ \"$temp\" == \"$VAR(@)\" ] ; then
+ exit 0
+ fi
+ let i++
+ done
+ intf_group_name_array=\"eth+ bond+ br+ peth+ vtun+ tun+ wlm+ wlan+\"
+ i=0
+ for i in $intf_group_name_array; do
+ if [ \"$i\" == \"$VAR(@)\" ]; then
+ exit 0
+ fi
+ done
+ echo NPTv6 configuration warning: interface $VAR(@) does not exist on this system "
diff --git a/templates-cfg/nat/nptv6/rule/node.tag/outside-prefix/node.def b/templates-cfg/nat/nptv6/rule/node.tag/outside-prefix/node.def
new file mode 100644
index 0000000..7af7091
--- /dev/null
+++ b/templates-cfg/nat/nptv6/rule/node.tag/outside-prefix/node.def
@@ -0,0 +1,7 @@
+type: txt
+
+help: Inside prefix to be translated
+
+val_help: ipv6net; IPv6 prefix to match
+
+syntax:expression: exec "/opt/vyatta/sbin/vyatta-validate-type ipv6_addr_param $VAR(@)"