diff options
author | An-Cheng Huang <ancheng@vyatta.com> | 2007-12-19 11:25:49 -0800 |
---|---|---|
committer | An-Cheng Huang <ancheng@vyatta.com> | 2007-12-19 11:25:49 -0800 |
commit | 561ec07cb56696b05f683a325098c06422d00f86 (patch) | |
tree | b35d1727c4de7775854948b862de652a78a0de44 | |
download | vyatta-nat-561ec07cb56696b05f683a325098c06422d00f86.tar.gz vyatta-nat-561ec07cb56696b05f683a325098c06422d00f86.zip |
migrate NAT from fairfield to glendaleupstream
68 files changed, 1604 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..139f1b1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,18 @@ +*~ +.*.swp +/aclocal.m4 +/autom4te.cache +/build-stamp +/ChangeLog +/config +/config.log +/config.guess +/config.status +/config.sub +/configure +/debian/files +/debian/vyatta-nat +/INSTALL +/Makefile.in +/Makefile + @@ -0,0 +1 @@ +eng@vyatta.com @@ -0,0 +1,26 @@ +/* + * Package: vyatt-nat + * + * **** License **** + * Version: VPL 1.0 + * + * The contents of this file are subject to the Vyatta Public License + * Version 1.0 ("License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.vyatta.com/vpl + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * This code was originally developed by Vyatta, Inc. + * Portions created by Vyatta are Copyright (C) "YEAR" Vyatta, Inc. + * All Rights Reserved. + * + * Author: An-Cheng Huang + * Date: 2007 + * Description: Vyatta configuration/operational commands for NAT + * + * **** End License **** + */ diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..850d7c9 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,21 @@ +cfgdir = $(datadir)/vyatta-cfg/templates +opdir = $(datadir)/vyatta-op/templates +xsldir = $(datadir)/xsl +share_perl5dir = $(datadir)/perl5 +bin_sudo_usersdir = $(bindir)/sudo-users + +sbin_SCRIPTS = scripts/vyatta-update-nat.pl +bin_sudo_users_SCRIPTS = scripts/vyatta-show-nat.pl + +share_perl5_DATA = scripts/VyattaNatRule.pm + +cpiop = find . ! -regex '\(.*~\|.*\.bak\|.*\.swp\|.*\#.*\#\)' -print0 | \ + cpio -0pd + +install-exec-hook: + mkdir -p $(DESTDIR)$(cfgdir) + cd templates-cfg; $(cpiop) $(DESTDIR)$(cfgdir) + mkdir -p $(DESTDIR)$(opdir) + cd templates-op; $(cpiop) $(DESTDIR)$(opdir) + mkdir -p $(DESTDIR)$(xsldir) + cd xsl; $(cpiop) $(DESTDIR)$(xsldir) @@ -0,0 +1 @@ +see http://www.vyatta.com/news/ @@ -0,0 +1 @@ +This package has the Vyatta configuration and operational templates and scripts for NAT. diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..15fd8e9 --- /dev/null +++ b/configure.ac @@ -0,0 +1,29 @@ +# Process this file with autoconf to produce a configure script. +AC_PREREQ(2.59) + +m4_define([VERSION_ID], [m4_esyscmd([ + if test -f .version ; then + head -n 1 .version | tr -d \\n + else + echo -n 2.4 + fi])]) +AC_INIT([vyatta-nat], VERSION_ID, [vyatta-support@vyatta.com]) + +test -n "$VYATTA_VERSION" || VYATTA_VERSION=$PACKAGE_VERSION + +AC_CONFIG_AUX_DIR([config]) +AM_INIT_AUTOMAKE([gnu no-dist-gzip dist-bzip2 subdir-objects]) +AC_PREFIX_DEFAULT([/opt/vyatta]) + +AC_ARG_ENABLE([nostrip], + AC_HELP_STRING([--enable-nostrip], + [include -nostrip option during packaging]), + [NOSTRIP=-nostrip], [NOSTRIP=]) + +AC_CONFIG_FILES( + [Makefile]) + +AC_SUBST(NOSTRIP) + +AC_OUTPUT + diff --git a/debian/README b/debian/README new file mode 100644 index 0000000..30b3107 --- /dev/null +++ b/debian/README @@ -0,0 +1,6 @@ +The Debian Package vyatta-nat +---------------------------- + +This package has the Vyatta configuration and operational templates and scripts for NAT. + + -- An-Cheng Huang <ancheng@vyatta.com> Tue, 18 Dec 2007 11:59:49 -0700 diff --git a/debian/autogen.sh b/debian/autogen.sh new file mode 100755 index 0000000..ff125d1 --- /dev/null +++ b/debian/autogen.sh @@ -0,0 +1,37 @@ +#!/bin/sh + + +if [ -d .git ] ; then +# generate GNU/Debian format ChangeLog from git log + + rm -f ChangeLog + + if which git2cl >/dev/null ; then + git-log --pretty --numstat --summary | git2cl >> ChangeLog + else + git-log --pretty=short >> ChangeLog + fi + +# append repository reference + + url=` git repo-config --get remote.origin.url` + test "x$url" = "x" && url=`pwd` + + branch=`git-branch --no-color | sed '/^\* /!d; s/^\* //'` + test "x$branch" = "x" && branch=master + + sha=`git log --pretty=oneline --no-color -n 1 | cut -c-8` + test "x$sha" = "x" && sha=00000000 + + echo "$url#$branch-$sha" >> ChangeLog + +fi + +rm -rf config +rm -f aclocal.m4 config.guess config.statusconfig.sub configure INSTALL + +autoreconf --force --install + +rm -f config.sub config.guess +ln -s /usr/share/misc/config.sub . +ln -s /usr/share/misc/config.guess . diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..b558752 --- /dev/null +++ b/debian/changelog @@ -0,0 +1,5 @@ +vyatta-nat (0.1) unstable; urgency=low + + * Initial Release. + + -- An-Cheng Huang <ancheng@vyatta.com> Tue, 18 Dec 2007 11:59:49 -0700 diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000..7ed6ff8 --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +5 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..f1359be --- /dev/null +++ b/debian/control @@ -0,0 +1,14 @@ +Source: vyatta-nat +Section: contrib/net +Priority: extra +Maintainer: An-Cheng Huang <ancheng@vyatta.com> +Build-Depends: debhelper (>= 5), autotools-dev +Standards-Version: 3.7.2 + +Package: vyatta-nat +Architecture: all +Depends: vyatta-cfg, + vyatta-op, + iptables +Description: Vyatta configuration/operational commands for NAT + Vyatta configuration and operational templates and scripts for NAT diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..f7600be --- /dev/null +++ b/debian/copyright @@ -0,0 +1,34 @@ +This package was debianized by An-Cheng Huang <ancheng@vyatta.com> on +Tue, 18 Dec 2007 11:59:49 -0700. + +It's original content from the GIT repository <http://vyatt.com/git/vyatta-nat> + +Upstream Author: + + <eng@vyatta.com> + +Copyright: + + Copyright (C) 2007 Vyatta, Inc. + All Rights Reserved. + +License: + + The contents of this package are subject to the Vyatta Public License + Version 1.0 ("License"); you may not use this file except in + compliance with the License. You may obtain a copy of the License at + http://www.vyatta.com/vpl + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + the License for the specific language governing rights and limitations + under the License. + + This code was originally developed by Vyatta, Inc. + Portions created by Vyatta are Copyright (C) 2007 Vyatta, Inc. + +On Debian systems, the complete text of the GNU General +Public License can be found in `/usr/share/common-licenses/GPL'. + +The Debian packaging is (C) 2007, Tom Grennan <tgrennan@vyatta.com> and +is licensed under the GPL, see above. diff --git a/debian/docs b/debian/docs new file mode 100644 index 0000000..50bd824 --- /dev/null +++ b/debian/docs @@ -0,0 +1,2 @@ +NEWS +README diff --git a/debian/linda b/debian/linda new file mode 100644 index 0000000..0381d9d --- /dev/null +++ b/debian/linda @@ -0,0 +1 @@ +Tag: file-in-opt diff --git a/debian/lintian b/debian/lintian new file mode 100644 index 0000000..3bcedc4 --- /dev/null +++ b/debian/lintian @@ -0,0 +1,2 @@ +vyatta-nat: file-in-unusual-dir +vyatta-nat: dir-or-file-in-opt diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..e98fe01 --- /dev/null +++ b/debian/rules @@ -0,0 +1,102 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Sample debian/rules that uses debhelper. +# This file was originally written by Joey Hess and Craig Small. +# As a special exception, when this file is copied by dh-make into a +# dh-make output file, you may use that output file without restriction. +# This special exception was added by Craig Small in version 0.37 of dh-make. + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + + +# These are used for cross-compiling and for saving the configure script +# from having to guess our platform (since we know it already) +DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE) +DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE) +PACKAGE=vyatta-nat +PKGDIR=$(CURDIR)/debian/$(PACKAGE) + +CFLAGS = -Wall -g + +configure = ./configure +configure += --host=$(DEB_HOST_GNU_TYPE) +configure += --build=$(DEB_BUILD_GNU_TYPE) +configure += --prefix=/opt/vyatta +configure += --mandir=\$${prefix}/share/man +configure += --infodir=\$${prefix}/share/info +configure += CFLAGS="$(CFLAGS)" +configure += LDFLAGS="-Wl,-z,defs" + +ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS))) + CFLAGS += -O0 +else + CFLAGS += -O2 +endif + +configure: configure.ac Makefile.am + chmod +x debian/autogen.sh + debian/autogen.sh + +config.status: configure + dh_testdir + rm -f config.cache + $(configure) + +build: build-stamp + +build-stamp: config.status + dh_testdir + $(MAKE) + touch $@ + +clean: clean-patched + +# Clean everything up, including everything auto-generated +# at build time that needs not to be kept around in the Debian diff +clean-patched: + dh_testdir + dh_testroot + if test -f Makefile ; then $(MAKE) clean distclean ; fi + rm -f build-stamp + rm -f config.status config.sub config.guess config.log + rm -f aclocal.m4 configure Makefile.in Makefile INSTALL + rm -f etc/default/vyatta + rm -rf config + dh_clean + +install: build + dh_testdir + dh_testroot + dh_clean -k + dh_installdirs + + $(MAKE) DESTDIR=$(PKGDIR) install + + install -D --mode=0644 debian/lintian $(PKGDIR)/usr/share/lintian/overrides/$(PACKAGE) + install -D --mode=0644 debian/linda $(PKGDIR)/usr/share/linda/overrides/$(PACKAGE) + +# Build architecture-independent files here. +binary-indep: build install + dh_testdir + dh_testroot + dh_installchangelogs ChangeLog + dh_installdocs + dh_install + dh_installdebconf + dh_link + dh_strip + dh_compress + dh_fixperms + dh_installdeb + dh_gencontrol + dh_md5sums + dh_builddeb + +# Build architecture-dependent files here. +binary-arch: build install +# This is an architecture independent package +# so; we have nothing to do by default. + +binary: binary-indep binary-arch +.PHONY: build clean binary-indep binary-arch binary install diff --git a/scripts/VyattaNatRule.pm b/scripts/VyattaNatRule.pm new file mode 100644 index 0000000..5bcfac6 --- /dev/null +++ b/scripts/VyattaNatRule.pm @@ -0,0 +1,532 @@ +package VyattaNatRule; + +use strict; +use lib "/opt/vyatta/share/perl5/"; +use VyattaConfig; + +my %fields = ( + _type => undef, + _orig_type => undef, + _inbound_if => undef, + _outbound_if => undef, + _proto => undef, + _source => { + _addr => undef, + _net => undef, + _port_num => undef, + _port_name => undef, + _port_range => { + _start => undef, + _stop => undef, + }, + }, + _destination => { + _addr => undef, + _net => undef, + _port_num => undef, + _port_name => undef, + _port_range => { + _start => undef, + _stop => undef, + }, + }, + _inside_addr => { + _addr => undef, + _range => { + _start => undef, + _stop => undef, + }, + _port_num => undef, + _port_range => { + _start => undef, + _stop => undef, + }, + }, + _outside_addr => { + _addr => undef, + _range => { + _start => undef, + _stop => undef, + }, + _port_num => undef, + _port_range => { + _start => undef, + _stop => 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 VyattaConfig; + + $config->setLevel("$level"); + + $self->{_type} = $config->returnValue("type"); + $self->{_orig_type} = $config->returnOrigValue("type"); + $self->{_inbound_if} = $config->returnValue("inbound-interface"); + $self->{_outbound_if} = $config->returnValue("outbound-interface"); + $self->{_proto} = $config->returnValue("protocols"); + + $self->{_source}->{_addr} = $config->returnValue("source address"); + $self->{_source}->{_net} = $config->returnValue("source network"); + my @tmp = $config->returnValues("source port-number"); + $self->{_source}->{_port_num} = [ @tmp ]; + @tmp = $config->returnValues("source port-name"); + $self->{_source}->{_port_name} = [ @tmp ]; + $self->{_source}->{_port_range}->{_start} + = $config->returnValue("source port-range start"); + $self->{_source}->{_port_range}->{_stop} + = $config->returnValue("source port-range stop"); + + $self->{_destination}->{_addr} = $config->returnValue("destination address"); + $self->{_destination}->{_net} = $config->returnValue("destination network"); + @tmp = $config->returnValues("destination port-number"); + $self->{_destination}->{_port_num} = [ @tmp ]; + @tmp = $config->returnValues("destination port-name"); + $self->{_destination}->{_port_name} = [ @tmp ]; + $self->{_destination}->{_port_range}->{_start} + = $config->returnValue("destination port-range start"); + $self->{_destination}->{_port_range}->{_stop} + = $config->returnValue("destination port-range stop"); + + $self->{_inside_addr}->{_addr} + = $config->returnValue("inside-address address"); + $self->{_inside_addr}->{_range}->{_start} + = $config->returnValue("inside-address range start"); + $self->{_inside_addr}->{_range}->{_stop} + = $config->returnValue("inside-address range stop"); + $self->{_inside_addr}->{_port_num} + = $config->returnValue("inside-address port-number"); + $self->{_inside_addr}->{_port_range}->{_start} + = $config->returnValue("inside-address port-range start"); + $self->{_inside_addr}->{_port_range}->{_stop} + = $config->returnValue("inside-address port-range stop"); + + $self->{_outside_addr}->{_addr} + = $config->returnValue("outside-address address"); + $self->{_outside_addr}->{_range}->{_start} + = $config->returnValue("outside-address range start"); + $self->{_outside_addr}->{_range}->{_stop} + = $config->returnValue("outside-address range stop"); + $self->{_outside_addr}->{_port_num} + = $config->returnValue("outside-address port-number"); + $self->{_outside_addr}->{_port_range}->{_start} + = $config->returnValue("outside-address port-range start"); + $self->{_outside_addr}->{_port_range}->{_stop} + = $config->returnValue("outside-address port-range stop"); + + return 0; +} + +sub setupOrig { + my ( $self, $level ) = @_; + my $config = new VyattaConfig; + + $config->setLevel("$level"); + + $self->{_type} = $config->returnOrigValue("type"); + $self->{_orig_type} = $config->returnOrigValue("type"); + $self->{_inbound_if} = $config->returnOrigValue("inbound-interface"); + $self->{_outbound_if} = $config->returnOrigValue("outbound-interface"); + $self->{_proto} = $config->returnOrigValue("protocols"); + + $self->{_source}->{_addr} = $config->returnOrigValue("source address"); + $self->{_source}->{_net} = $config->returnOrigValue("source network"); + my @tmp = $config->returnOrigValues("source port-number"); + $self->{_source}->{_port_num} = [ @tmp ]; + @tmp = $config->returnOrigValues("source port-name"); + $self->{_source}->{_port_name} = [ @tmp ]; + $self->{_source}->{_port_range}->{_start} + = $config->returnOrigValue("source port-range start"); + $self->{_source}->{_port_range}->{_stop} + = $config->returnOrigValue("source port-range stop"); + + $self->{_destination}->{_addr} + = $config->returnOrigValue("destination address"); + $self->{_destination}->{_net} + = $config->returnOrigValue("destination network"); + @tmp = $config->returnOrigValues("destination port-number"); + $self->{_destination}->{_port_num} = [ @tmp ]; + @tmp = $config->returnOrigValues("destination port-name"); + $self->{_destination}->{_port_name} = [ @tmp ]; + $self->{_destination}->{_port_range}->{_start} + = $config->returnOrigValue("destination port-range start"); + $self->{_destination}->{_port_range}->{_stop} + = $config->returnOrigValue("destination port-range stop"); + + $self->{_inside_addr}->{_addr} + = $config->returnOrigValue("inside-address address"); + $self->{_inside_addr}->{_range}->{_start} + = $config->returnOrigValue("inside-address range start"); + $self->{_inside_addr}->{_range}->{_stop} + = $config->returnOrigValue("inside-address range stop"); + $self->{_inside_addr}->{_port_num} + = $config->returnOrigValue("inside-address port-number"); + $self->{_inside_addr}->{_port_range}->{_start} + = $config->returnOrigValue("inside-address port-range start"); + $self->{_inside_addr}->{_port_range}->{_stop} + = $config->returnOrigValue("inside-address port-range stop"); + + $self->{_outside_addr}->{_addr} + = $config->returnOrigValue("outside-address address"); + $self->{_outside_addr}->{_range}->{_start} + = $config->returnOrigValue("outside-address range start"); + $self->{_outside_addr}->{_range}->{_stop} + = $config->returnOrigValue("outside-address range stop"); + $self->{_outside_addr}->{_port_num} + = $config->returnOrigValue("outside-address port-number"); + $self->{_outside_addr}->{_port_range}->{_start} + = $config->returnOrigValue("outside-address port-range start"); + $self->{_outside_addr}->{_port_range}->{_stop} + = $config->returnOrigValue("outside-address port-range stop"); + + return 0; +} + +sub handle_ports { + my $num_ref = shift; + my $name_ref = shift; + my $pstart = shift; + my $pstop = shift; + my $can_use_port = shift; + my $prefix = shift; + my $proto = shift; + + my $rule_str = ""; + my ($ports, $prange) = (0, 0); + my @pnums = @{$num_ref}; + my @pnames = @{$name_ref}; + $ports = ($#pnums + 1) + ($#pnames + 1); + + if (defined($pstart) && defined($pstop)) { + if ($pstop < $pstart) { + return (undef, "invalid port range $pstart-$pstop"); + } + $ports += ($pstop - $pstart + 1); + $prange = ($pstop - $pstart - 1); + } + if (($ports > 0) && (!$can_use_port)) { + return (undef, "ports can only be specified when protocol is \"tcp\" " + . "or \"udp\" (currently \"$proto\")"); + } + if (($ports - $prange) > 15) { + return (undef, "source/destination port specification only supports " + . "up to 15 ports (port range counts as 2)"); + } + if ($ports > 1) { + $rule_str .= " -m multiport --${prefix}ports "; + my $first = 1; + if ($#pnums >= 0) { + my $pstr = join(',', @pnums); + $rule_str .= "$pstr"; + $first = 0; + } + if ($#pnames >= 0) { + if ($first == 0) { + $rule_str .= ","; + } + my $pstr = join(',', @pnames); + $rule_str .= "$pstr"; + $first = 0; + } + if (defined($pstart) && defined($pstop)) { + if ($first == 0) { + $rule_str .= ","; + } + if ($pstart == $pstop) { + $rule_str .= "$pstart"; + } else { + $rule_str .= "$pstart:$pstop"; + } + $first = 0; + } + } elsif ($ports > 0) { + $rule_str .= " --${prefix}port "; + if ($#pnums >= 0) { + $rule_str .= "$pnums[0]"; + } elsif ($#pnames >= 0) { + $rule_str .= "$pnames[0]"; + } else { + # no number, no name, range of 1 + $rule_str .= "$pstart"; + } + } + + return ($rule_str, undef); +} + +# returns (rule, error) +sub rule_str { + my ($self) = @_; + my $rule_str = ""; + my $can_use_port = 1; + + if (!defined($self->{_proto}) || + (($self->{_proto} ne "tcp") && ($self->{_proto} ne "6") + && ($self->{_proto} ne "udp") && ($self->{_proto} ne "17"))) { + $can_use_port = 0; + } + if (($self->{_type} eq "source") || ($self->{_type} eq "masquerade")) { + if ($self->{_type} eq "masquerade") { + $rule_str .= "-j MASQUERADE"; + } else { + $rule_str .= "-j SNAT"; + } + if (defined($self->{_outbound_if})) { + $rule_str .= " -o $self->{_outbound_if}"; + } else { + # "masquerade" requires outbound_if. + # also make this a requirement for "source" to prevent users from + # inadvertently NATing loopback traffic. + return (undef, "outbound-interface not specified"); + } + + if (defined($self->{_proto})) { + my $str = $self->{_proto}; + $str =~ s/^\!(.*)$/! $1/; + $rule_str .= " -p $str"; + } + + #my $to_src = " --to-source "; + my $to_src = ""; + if (defined($self->{_outside_addr}->{_addr})) { + $to_src .= "$self->{_outside_addr}->{_addr}"; + } elsif (defined($self->{_outside_addr}->{_range}->{_start}) + && defined($self->{_outside_addr}->{_range}->{_stop})) { + $to_src .= "$self->{_outside_addr}->{_range}->{_start}"; + $to_src .= "-$self->{_outside_addr}->{_range}->{_stop}"; + } + + if (($to_src ne "") && ($self->{_type} eq "masquerade")) { + return (undef, "cannot specify outside IP address with \"masquerade\""); + } + + if (defined($self->{_outside_addr}->{_port_num})) { + if (!$can_use_port) { + return (undef, "ports can only be specified when protocol is \"tcp\" " + . "or \"udp\" (currently \"$self->{_proto}\")"); + } + if ($self->{_type} ne "masquerade") { + $to_src .= ":"; + } + $to_src .= "$self->{_outside_addr}->{_port_num}"; + } elsif (defined($self->{_outside_addr}->{_port_range}->{_start}) + && defined($self->{_outside_addr}->{_port_range}->{_stop})) { + if (!$can_use_port) { + return (undef, "ports can only be specified when protocol is \"tcp\" " + . "or \"udp\" (currently \"$self->{_proto}\")"); + } + if ($self->{_type} ne "masquerade") { + $to_src .= ":"; + } + $to_src .= "$self->{_outside_addr}->{_port_range}->{_start}"; + $to_src .= "-$self->{_outside_addr}->{_port_range}->{_stop}"; + } + + if ($to_src ne "") { + if ($self->{_type} eq "masquerade") { + $rule_str .= " --to-ports $to_src"; + } else { + $rule_str .= " --to-source $to_src"; + } + } elsif ($self->{_type} ne "masquerade") { + return (undef, "outside-address not specified"); + } + } else { + # type is destination + $rule_str .= "-j DNAT"; + + if (defined($self->{_inbound_if})) { + $rule_str .= " -i $self->{_inbound_if}"; + } else { + # make this a requirement to prevent users from + # inadvertently NATing loopback traffic. + return (undef, "inbound-interface not specified"); + } + + if (defined($self->{_proto})) { + $rule_str .= " -p $self->{_proto}"; + } + + my $to_dst = " --to-destination "; + if (defined($self->{_inside_addr}->{_addr})) { + $to_dst .= "$self->{_inside_addr}->{_addr}"; + } elsif (defined($self->{_inside_addr}->{_range}->{_start}) + && defined($self->{_inside_addr}->{_range}->{_stop})) { + $to_dst .= "$self->{_inside_addr}->{_range}->{_start}"; + $to_dst .= "-$self->{_inside_addr}->{_range}->{_stop}"; + } + if (defined($self->{_inside_addr}->{_port_num})) { + if (!$can_use_port) { + return (undef, "ports can only be specified when protocol is \"tcp\" " + . "or \"udp\" (currently \"$self->{_proto}\")"); + } + $to_dst .= ":$self->{_inside_addr}->{_port_num}"; + } elsif (defined($self->{_inside_addr}->{_port_range}->{_start}) + && defined($self->{_inside_addr}->{_port_range}->{_stop})) { + if (!$can_use_port) { + return (undef, "ports can only be specified when protocol is \"tcp\" " + . "or \"udp\" (currently \"$self->{_proto}\")"); + } + $to_dst .= ":$self->{_inside_addr}->{_port_range}->{_start}"; + $to_dst .= "-$self->{_inside_addr}->{_port_range}->{_stop}"; + } + if ($to_dst ne " --to-destination ") { + $rule_str .= $to_dst; + } else { + return (undef, "inside-address not specified"); + } + } + + # source port(s) + my ($port_str, $port_err) + = handle_ports($self->{_source}->{_port_num}, + $self->{_source}->{_port_name}, + $self->{_source}->{_port_range}->{_start}, + $self->{_source}->{_port_range}->{_stop}, + $can_use_port, "s", $self->{_proto}); + return (undef, $port_err) if (!defined($port_str)); + $rule_str .= $port_str; + + # destination port(s) + ($port_str, $port_err) + = handle_ports($self->{_destination}->{_port_num}, + $self->{_destination}->{_port_name}, + $self->{_destination}->{_port_range}->{_start}, + $self->{_destination}->{_port_range}->{_stop}, + $can_use_port, "d", $self->{_proto}); + return (undef, $port_err) if (!defined($port_str)); + $rule_str .= $port_str; + + if (defined($self->{_source}->{_addr})) { + my $str = $self->{_source}->{_addr}; + $str =~ s/^\!(.*)$/! $1/; + $rule_str .= " -s $str"; + } elsif (defined($self->{_source}->{_net})) { + my $str = $self->{_source}->{_net}; + $str =~ s/^\!(.*)$/! $1/; + $rule_str .= " -s $str"; + } + + if (defined($self->{_destination}->{_addr})) { + my $str = $self->{_destination}->{_addr}; + $str =~ s/^\!(.*)$/! $1/; + $rule_str .= " -d $str"; + } elsif (defined($self->{_destination}->{_net})) { + my $str = $self->{_destination}->{_net}; + $str =~ s/^\!(.*)$/! $1/; + $rule_str .= " -d $str"; + } + + return ($rule_str, ""); +} + +sub orig_type { + my ($self) = @_; + return "source" if ($self->{_orig_type} eq "masquerade"); + return $self->{_orig_type}; +} + +sub new_type { + my ($self) = @_; + return "source" if ($self->{_type} eq "masquerade"); + return $self->{_type}; +} + +sub print_str { + my ($self) = @_; + my $str = + "type[$self->{_type}] " . + "in_if[$self->{_inbound_if}] out_if[$self->{_outbound_if}] " . + "proto[$self->{_proto}] saddr[$self->{_source}->{_addr}] ". + "snet[$self->{_source}->{_net}] spnum[@{$self->{_source}->{_port_num}}] ". + "spname[@{$self->{_source}->{_port_name}}] " . + "sprange[$self->{_source}->{_port_range}->{_start}" . + "-$self->{_source}->{_port_range}->{_stop}] " . + "daddr[$self->{_destination}->{_addr}] " . + "dnet[$self->{_destination}->{_net}] " . + "dpnum[@{$self->{_destination}->{_port_num}}] " . + "dpname[@{$self->{_destination}->{_port_name}}] " . + "dprange[$self->{_destination}->{_port_range}->{_start}-" . + "$self->{_destination}->{_port_range}->{_stop}] " . + "inaddr[$self->{_inside_addr}->{_addr}] " . + "inrange[$self->{_inside_addr}->{_range}->{_start}-" . + "$self->{_inside_addr}->{_range}->{_stop}] " . + "inp[$self->{_inside_addr}->{_port_num}] " . + "inprange[$self->{_inside_addr}->{_port_range}->{_start}-" . + "$self->{_inside_addr}->{_port_range}->{_stop}] " . + "outaddr[$self->{_outside_addr}->{_addr}] " . + "outrange[$self->{_outside_addr}->{_range}->{_start}-" . + "$self->{_outside_addr}->{_range}->{_stop}]"; + "outp[$self->{_outside_addr}->{_port_num}] " . + "outprange[$self->{_outside_addr}->{_port_range}->{_start}-" . + "$self->{_outside_addr}->{_port_range}->{_stop}] " . + + return $str; +} + +sub outputXmlElem { + my ($name, $value, $fh) = @_; + print $fh " <$name>$value</$name>\n"; +} + +sub outputXml { + my ($self, $fh) = @_; + outputXmlElem("type", $self->{_type}, $fh); + outputXmlElem("in_interface", $self->{_inbound_if}, $fh); + outputXmlElem("out_interface", $self->{_outbound_if}, $fh); + outputXmlElem("src_addr", $self->{_source}->{_addr}, $fh); + outputXmlElem("src_network", $self->{_source}->{_net}, $fh); + outputXmlElem("src_ports", join(',', @{$self->{_source}->{_port_num}}), $fh); + outputXmlElem("src_ports_apps", join(',', @{$self->{_source}->{_port_name}}), + $fh); + outputXmlElem("src_port_start", $self->{_source}->{_port_range}->{_start}, + $fh); + outputXmlElem("src_port_stop", $self->{_source}->{_port_range}->{_stop}, + $fh); + outputXmlElem("dst_addr", $self->{_destination}->{_addr}, $fh); + outputXmlElem("dst_network", $self->{_destination}->{_net}, $fh); + outputXmlElem("dst_ports", join(',', @{$self->{_destination}->{_port_num}}), + $fh); + outputXmlElem("dst_ports_apps", + join(',', @{$self->{_destination}->{_port_name}}), $fh); + outputXmlElem("dst_port_start", + $self->{_destination}->{_port_range}->{_start}, $fh); + outputXmlElem("dst_port_stop", + $self->{_destination}->{_port_range}->{_stop}, $fh); + outputXmlElem("in_addr", $self->{_inside_addr}->{_addr}, $fh); + outputXmlElem("in_addr_start", $self->{_inside_addr}->{_range}->{_start}, + $fh); + outputXmlElem("in_addr_stop", $self->{_inside_addr}->{_range}->{_stop}, + $fh); + outputXmlElem("in_port", $self->{_inside_addr}->{_port_num}, $fh); + outputXmlElem("in_port_start", + $self->{_inside_addr}->{_port_range}->{_start}, $fh); + outputXmlElem("in_port_stop", + $self->{_inside_addr}->{_port_range}->{_stop}, $fh); + outputXmlElem("out_addr", $self->{_outside_addr}->{_addr}, $fh); + outputXmlElem("out_addr_start", $self->{_outside_addr}->{_range}->{_start}, + $fh); + outputXmlElem("out_addr_stop", $self->{_outside_addr}->{_range}->{_stop}, + $fh); + outputXmlElem("out_port", $self->{_outside_addr}->{_port_num}, $fh); + outputXmlElem("out_port_start", + $self->{_outside_addr}->{_port_range}->{_start}, $fh); + outputXmlElem("out_port_stop", + $self->{_outside_addr}->{_port_range}->{_stop}, $fh); + + # no proto? ($self->{_proto}) +} + diff --git a/scripts/vyatta-show-nat.pl b/scripts/vyatta-show-nat.pl new file mode 100755 index 0000000..5ae67b8 --- /dev/null +++ b/scripts/vyatta-show-nat.pl @@ -0,0 +1,64 @@ +#!/usr/bin/perl + +use strict; +use lib "/opt/vyatta/share/perl5/"; +use VyattaConfig; +use VyattaNatRule; + +sub numerically { $a <=> $b; } + +exit 1 if ($#ARGV != 0); +my $xsl_file = $ARGV[0]; + +my %stats = ( + source => [ ], + destination => [ ], + ); +open(STATS, "iptables -t nat -L -vn |") or exit 1; +my $skey = ""; +while (<STATS>) { + if (m/^Chain PREROUTING/) { + $skey = "destination"; + } elsif (m/^Chain POSTROUTING/) { + $skey = "source"; + } elsif (m/^Chain /) { + $skey = ""; + } + + if ($skey ne "" && (m/SNAT/ || m/DNAT/ || m/MASQUERADE/)) { + m/^\s*(\d+)\s+(\d+)\s/; + push @{$stats{$skey}}, ($1, $2); + } +} +close STATS; + +open(RENDER, "| /opt/vyatta/libexec/xorp/render_xml $xsl_file") or exit 1; + +# begin +print RENDER "<opcommand name='natrules'><format type='row'>\n"; + +my $config = new VyattaConfig; +$config->setLevel("service nat rule"); +my @rules_pre = $config->listOrigNodes(); +my $rule; +my @rules = sort numerically @rules_pre; +for $rule (@rules) { + my $nrule = new VyattaNatRule; + $nrule->setupOrig("service nat rule $rule"); + my $ntype = $nrule->orig_type(); + print RENDER " <row>\n"; + print RENDER " <rule_num>$rule</rule_num>\n"; + my $pkts = shift @{$stats{$ntype}}; + my $bytes = shift @{$stats{$ntype}}; + print RENDER " <pkts>$pkts</pkts>\n"; + print RENDER " <bytes>$bytes</bytes>\n"; + $nrule->outputXml(*RENDER{IO}); + print RENDER " </row>\n"; +} + +# end +print RENDER "</format></opcommand>\n"; + +close RENDER; +exit 0; + diff --git a/scripts/vyatta-update-nat.pl b/scripts/vyatta-update-nat.pl new file mode 100755 index 0000000..19255ed --- /dev/null +++ b/scripts/vyatta-update-nat.pl @@ -0,0 +1,164 @@ +#!/usr/bin/perl + +use strict; +use lib "/opt/vyatta/share/perl5/"; +use VyattaConfig; +use VyattaNatRule; + +sub numerically { $a <=> $b; } + +sub raw_cleanup { + # remove the conntrack setup. + my @lines + = `iptables -t raw -L PREROUTING -vn --line-numbers | egrep ^[0-9]`; + foreach (@lines) { + my ($num, $ignore, $ignore, $chain, $ignore, $ignore, $in, $out, + $ignore, $ignore) = split /\s+/; + if ($chain eq "NAT_CONNTRACK") { + system("iptables -t raw -D PREROUTING $num"); + system("iptables -t raw -D OUTPUT $num"); + system("iptables -t raw -F NAT_CONNTRACK"); + system("iptables -t raw -X NAT_CONNTRACK"); + last; + } + } +} + +# for "clear nat translations" +if ($ARGV[0] eq "clearnattranslations") { + system("iptables-save -t nat | iptables-restore"); + exit 0; +} + +my $config = new VyattaConfig; +$config->setLevel("service nat rule"); +my %rules = $config->listNodeStatus(); +my $rule; +open(OUT, ">>/dev/null") or exit 1; +my %ipt_rulenum = ( + source => 1, + destination => 1, + ); +my %chain_name = ( + source => "POSTROUTING", + destination => "PREROUTING", + ); +print OUT "========= nat list =========\n"; +my @rule_keys = sort numerically keys %rules; +if ($#rule_keys < 0) { + # no rules (everything is deleted) => flush the nat table & return + print OUT "iptables -t nat -F\n"; + if (system("iptables -t nat -F")) { + exit 1; + } + + raw_cleanup(); + + exit 0; +} + +## it seems that "multiport" does not like port range (p1:p2) if nobody has +## touched the nat table yet after reboot!? +system("iptables -t nat -L -n >& /dev/null"); + +# we have some nat rule(s). make sure conntrack is enabled. +system("iptables -t raw -L NAT_CONNTRACK -n >& /dev/null"); +if ($? >> 8) { + # NAT_CONNTRACK chain does not exist yet. set up conntrack. + system("iptables -t raw -N NAT_CONNTRACK"); + # this enables conntrack for all packets. potentially we can add more rules + # to the NAT_CONNTRACK chain for finer-grained control over which packets + # are tracked. + system("iptables -t raw -A NAT_CONNTRACK -j ACCEPT"); + system("iptables -t raw -I PREROUTING 1 -j NAT_CONNTRACK"); + system("iptables -t raw -I OUTPUT 1 -j NAT_CONNTRACK"); +} + +my $all_deleted = 1; +for $rule (@rule_keys) { + print OUT "$rule: $rules{$rule}\n"; + my $nrule = new VyattaNatRule; + $nrule->setup("service nat rule $rule"); + my $otype = $nrule->orig_type(); + my $ntype = $nrule->new_type(); + if ((defined($otype) && $otype ne "source" && $otype ne "destination") + || (defined($ntype) && $ntype ne "source" && $ntype ne "destination")) { + exit 2; + } + + if ($rules{$rule} ne "deleted") { + $all_deleted = 0; + } + + my $cmd; + if ($rules{$rule} eq "static") { + # $otype and $ntype should be the same + if (!defined($ntype)) { + exit 3; + } + $ipt_rulenum{$ntype} += 1; + next; + } elsif ($rules{$rule} eq "deleted") { + # $ntype should be empty + if (!defined($otype)) { + exit 4; + } + $cmd = "iptables -t nat -D $chain_name{$otype} $ipt_rulenum{$otype}"; + print OUT "$cmd\n"; + if (system($cmd)) { + exit 1; + } + next; + } + + my ($str, $err) = $nrule->rule_str(); + if (!defined($str)) { + # rule check failed => return error + print OUT "ERROR: $err\n"; + print STDERR "ERROR: $err\n"; + exit 5; + } + + if ($rules{$rule} eq "added") { + # $otype should be empty + if (!defined($ntype)) { + exit 6; + } + $cmd = "iptables -t nat -I $chain_name{$ntype} $ipt_rulenum{$ntype} " . + "$str"; + print OUT "$cmd\n"; + if (system($cmd)) { + exit 1; + } + $ipt_rulenum{$ntype} += 1; + } elsif ($rules{$rule} eq "changed") { + # $otype and $ntype may not be the same + if (!defined($otype) || !defined($ntype)) { + exit 7; + } + $cmd = "iptables -t nat -I $chain_name{$ntype} $ipt_rulenum{$ntype} " . + "$str"; + print OUT "$cmd\n"; + if (system($cmd)) { + exit 1; + } + my $idx = $ipt_rulenum{$otype}; + if ($otype eq $ntype) { + $idx += 1; + } + $cmd = "iptables -t nat -D $chain_name{$otype} $idx"; + print OUT "$cmd\n"; + if (system($cmd)) { + exit 1; + } + $ipt_rulenum{$ntype} += 1; + } +} + +if ($all_deleted) { + raw_cleanup(); +} + +close OUT; +exit 0; + diff --git a/templates-cfg/service/nat/node.def b/templates-cfg/service/nat/node.def new file mode 100644 index 0000000..a06299a --- /dev/null +++ b/templates-cfg/service/nat/node.def @@ -0,0 +1,2 @@ +help: "NAT configuration" +end: "sudo /opt/vyatta/sbin/vyatta-update-nat.pl" diff --git a/templates-cfg/service/nat/rule/node.def b/templates-cfg/service/nat/rule/node.def new file mode 100644 index 0000000..8de4c74 --- /dev/null +++ b/templates-cfg/service/nat/rule/node.def @@ -0,0 +1,4 @@ +tag: +type: u32 +help: "Rule number for NAT" +syntax: ($(@) > 0 && $(@) < 1025) ; "rule number must be between 1 and 1024" diff --git a/templates-cfg/service/nat/rule/node.tag/destination/address/node.def b/templates-cfg/service/nat/rule/node.tag/destination/address/node.def new file mode 100644 index 0000000..21aa728 --- /dev/null +++ b/templates-cfg/service/nat/rule/node.tag/destination/address/node.def @@ -0,0 +1,3 @@ +type: txt +help: "Destination address" +syntax: exec "/opt/vyatta/sbin/vyatta-validate-type.pl ipv4_negate '$(@)'" ; "invalid destination address \"$(@)\"" diff --git a/templates-cfg/service/nat/rule/node.tag/destination/network/node.def b/templates-cfg/service/nat/rule/node.tag/destination/network/node.def new file mode 100644 index 0000000..90c0571 --- /dev/null +++ b/templates-cfg/service/nat/rule/node.tag/destination/network/node.def @@ -0,0 +1,3 @@ +type: txt +help: "Destination network" +syntax: exec "/opt/vyatta/sbin/vyatta-validate-type.pl ipv4net_negate '$(@)'" ; "invalid destination network \"$(@)\"" diff --git a/templates-cfg/service/nat/rule/node.tag/destination/node.def b/templates-cfg/service/nat/rule/node.tag/destination/node.def new file mode 100644 index 0000000..54f73b4 --- /dev/null +++ b/templates-cfg/service/nat/rule/node.tag/destination/node.def @@ -0,0 +1 @@ +help: "NAT destination parameters" diff --git a/templates-cfg/service/nat/rule/node.tag/destination/port-name/node.def b/templates-cfg/service/nat/rule/node.tag/destination/port-name/node.def new file mode 100644 index 0000000..ddd9de5 --- /dev/null +++ b/templates-cfg/service/nat/rule/node.tag/destination/port-name/node.def @@ -0,0 +1,10 @@ +multi: +type: txt +help: "Named destination port (e.g., http)" +syntax: exec "sh -c 'if grep -q '\\''^$(@)[ \t]'\\'' /etc/services; \ +then exit 0; else \ + if grep -q \ + '\\''^[^ \t]\\+[ \t]\\+[^ \t]\\+[^#]*[ \t]$(@)\\([ \t]\\|\\$\\)'\\'' \ + /etc/services; then exit 0; else exit 1; \ + fi; \ +fi' " ; "invalid port name $(@)" diff --git a/templates-cfg/service/nat/rule/node.tag/destination/port-number/node.def b/templates-cfg/service/nat/rule/node.tag/destination/port-number/node.def new file mode 100644 index 0000000..5a1c509 --- /dev/null +++ b/templates-cfg/service/nat/rule/node.tag/destination/port-number/node.def @@ -0,0 +1,4 @@ +multi: +type: u32 +help: "Numbered destination port (ex. 80)" +syntax: ($(@) > 0 && $(@) < 65536) ; "port must be between 1 and 65535" diff --git a/templates-cfg/service/nat/rule/node.tag/destination/port-range/node.def b/templates-cfg/service/nat/rule/node.tag/destination/port-range/node.def new file mode 100644 index 0000000..62f0ac8 --- /dev/null +++ b/templates-cfg/service/nat/rule/node.tag/destination/port-range/node.def @@ -0,0 +1 @@ +help: "Range of destination ports (ex. 80-110)" diff --git a/templates-cfg/service/nat/rule/node.tag/destination/port-range/start/node.def b/templates-cfg/service/nat/rule/node.tag/destination/port-range/start/node.def new file mode 100644 index 0000000..59ade24 --- /dev/null +++ b/templates-cfg/service/nat/rule/node.tag/destination/port-range/start/node.def @@ -0,0 +1,3 @@ +type: u32 +help: "Starting destination port range" +syntax: ($(@) > 0 && $(@) < 65536) ; "port must be between 1 and 65535" diff --git a/templates-cfg/service/nat/rule/node.tag/destination/port-range/stop/node.def b/templates-cfg/service/nat/rule/node.tag/destination/port-range/stop/node.def new file mode 100644 index 0000000..d745455 --- /dev/null +++ b/templates-cfg/service/nat/rule/node.tag/destination/port-range/stop/node.def @@ -0,0 +1,3 @@ +type: u32 +help: "Ending destination port range" +syntax: ($(@) > 0 && $(@) < 65536) ; "port must be between 1 and 65535" diff --git a/templates-cfg/service/nat/rule/node.tag/inbound-interface/node.def b/templates-cfg/service/nat/rule/node.tag/inbound-interface/node.def new file mode 100644 index 0000000..c87d281 --- /dev/null +++ b/templates-cfg/service/nat/rule/node.tag/inbound-interface/node.def @@ -0,0 +1,5 @@ +type: txt +help: "Inbound interface of NAT traffic" +## iptables allow any interface names. +#syntax: exec "sh -c 'if grep -q '\\''^ \\+$(@):'\\'' /proc/net/dev; \ +#then exit 0; else exit 1; fi' " ; "invalid interface $(@)" diff --git a/templates-cfg/service/nat/rule/node.tag/inside-address/address/node.def b/templates-cfg/service/nat/rule/node.tag/inside-address/address/node.def new file mode 100644 index 0000000..8ff9c72 --- /dev/null +++ b/templates-cfg/service/nat/rule/node.tag/inside-address/address/node.def @@ -0,0 +1,2 @@ +type: ipv4 +help: "Inside address to NAT" diff --git a/templates-cfg/service/nat/rule/node.tag/inside-address/node.def b/templates-cfg/service/nat/rule/node.tag/inside-address/node.def new file mode 100644 index 0000000..113c11a --- /dev/null +++ b/templates-cfg/service/nat/rule/node.tag/inside-address/node.def @@ -0,0 +1 @@ +help: "Inside NAT IP (used by destination NAT only)" diff --git a/templates-cfg/service/nat/rule/node.tag/inside-address/port-number/node.def b/templates-cfg/service/nat/rule/node.tag/inside-address/port-number/node.def new file mode 100644 index 0000000..0ff1b43 --- /dev/null +++ b/templates-cfg/service/nat/rule/node.tag/inside-address/port-number/node.def @@ -0,0 +1,3 @@ +type: u32 +help: "Inside port to NAT" +syntax: ($(@) > 0 && $(@) < 65536) ; "port must be between 1 and 65535" diff --git a/templates-cfg/service/nat/rule/node.tag/inside-address/port-range/node.def b/templates-cfg/service/nat/rule/node.tag/inside-address/port-range/node.def new file mode 100644 index 0000000..4dbd32c --- /dev/null +++ b/templates-cfg/service/nat/rule/node.tag/inside-address/port-range/node.def @@ -0,0 +1 @@ +help: "Inside port range to NAT" diff --git a/templates-cfg/service/nat/rule/node.tag/inside-address/port-range/start/node.def b/templates-cfg/service/nat/rule/node.tag/inside-address/port-range/start/node.def new file mode 100644 index 0000000..8658b46 --- /dev/null +++ b/templates-cfg/service/nat/rule/node.tag/inside-address/port-range/start/node.def @@ -0,0 +1,3 @@ +type: u32 +help: "Inside port range start" +syntax: ($(@) > 0 && $(@) < 65536) ; "port must be between 1 and 65535" diff --git a/templates-cfg/service/nat/rule/node.tag/inside-address/port-range/stop/node.def b/templates-cfg/service/nat/rule/node.tag/inside-address/port-range/stop/node.def new file mode 100644 index 0000000..182a362 --- /dev/null +++ b/templates-cfg/service/nat/rule/node.tag/inside-address/port-range/stop/node.def @@ -0,0 +1,3 @@ +type: u32 +help: "Inside port range stop" +syntax: ($(@) > 0 && $(@) < 65536) ; "port must be between 1 and 65535" diff --git a/templates-cfg/service/nat/rule/node.tag/inside-address/range/node.def b/templates-cfg/service/nat/rule/node.tag/inside-address/range/node.def new file mode 100644 index 0000000..f8ef0ea --- /dev/null +++ b/templates-cfg/service/nat/rule/node.tag/inside-address/range/node.def @@ -0,0 +1 @@ +help: "Inside address range" diff --git a/templates-cfg/service/nat/rule/node.tag/inside-address/range/start/node.def b/templates-cfg/service/nat/rule/node.tag/inside-address/range/start/node.def new file mode 100644 index 0000000..473d565 --- /dev/null +++ b/templates-cfg/service/nat/rule/node.tag/inside-address/range/start/node.def @@ -0,0 +1,2 @@ +type: ipv4 +help: "Inside address range start" diff --git a/templates-cfg/service/nat/rule/node.tag/inside-address/range/stop/node.def b/templates-cfg/service/nat/rule/node.tag/inside-address/range/stop/node.def new file mode 100644 index 0000000..4c3ebb0 --- /dev/null +++ b/templates-cfg/service/nat/rule/node.tag/inside-address/range/stop/node.def @@ -0,0 +1,2 @@ +type: ipv4 +help: "Inside address range stop" diff --git a/templates-cfg/service/nat/rule/node.tag/outbound-interface/node.def b/templates-cfg/service/nat/rule/node.tag/outbound-interface/node.def new file mode 100644 index 0000000..bf3e8a2 --- /dev/null +++ b/templates-cfg/service/nat/rule/node.tag/outbound-interface/node.def @@ -0,0 +1,5 @@ +type: txt +help: "Outbound interface for NAT traffic" +## iptables allow any interface names. +#syntax: exec "sh -c 'if grep -q '\\''^ \\+$(@):'\\'' /proc/net/dev; \ +#then exit 0; else exit 1; fi' " ; "invalid interface $(@)" diff --git a/templates-cfg/service/nat/rule/node.tag/outside-address/address/node.def b/templates-cfg/service/nat/rule/node.tag/outside-address/address/node.def new file mode 100644 index 0000000..d6ee617 --- /dev/null +++ b/templates-cfg/service/nat/rule/node.tag/outside-address/address/node.def @@ -0,0 +1,2 @@ +type: ipv4 +help: "Outside address to NAT" diff --git a/templates-cfg/service/nat/rule/node.tag/outside-address/node.def b/templates-cfg/service/nat/rule/node.tag/outside-address/node.def new file mode 100644 index 0000000..466af5c --- /dev/null +++ b/templates-cfg/service/nat/rule/node.tag/outside-address/node.def @@ -0,0 +1 @@ +help: "Outside NAT IP (used by source NAT only)" diff --git a/templates-cfg/service/nat/rule/node.tag/outside-address/port-number/node.def b/templates-cfg/service/nat/rule/node.tag/outside-address/port-number/node.def new file mode 100644 index 0000000..d30ea94 --- /dev/null +++ b/templates-cfg/service/nat/rule/node.tag/outside-address/port-number/node.def @@ -0,0 +1,3 @@ +type: u32 +help: "Outside port to NAT" +syntax: ($(@) > 0 && $(@) < 65536) ; "port must be between 1 and 65535" diff --git a/templates-cfg/service/nat/rule/node.tag/outside-address/port-range/node.def b/templates-cfg/service/nat/rule/node.tag/outside-address/port-range/node.def new file mode 100644 index 0000000..aa13b4a --- /dev/null +++ b/templates-cfg/service/nat/rule/node.tag/outside-address/port-range/node.def @@ -0,0 +1 @@ +help: "Outside port range to NAT" diff --git a/templates-cfg/service/nat/rule/node.tag/outside-address/port-range/start/node.def b/templates-cfg/service/nat/rule/node.tag/outside-address/port-range/start/node.def new file mode 100644 index 0000000..09a987a --- /dev/null +++ b/templates-cfg/service/nat/rule/node.tag/outside-address/port-range/start/node.def @@ -0,0 +1,3 @@ +type: u32 +help: "Outside port range start" +syntax: ($(@) > 0 && $(@) < 65536) ; "port must be between 1 and 65535" diff --git a/templates-cfg/service/nat/rule/node.tag/outside-address/port-range/stop/node.def b/templates-cfg/service/nat/rule/node.tag/outside-address/port-range/stop/node.def new file mode 100644 index 0000000..3ce8342 --- /dev/null +++ b/templates-cfg/service/nat/rule/node.tag/outside-address/port-range/stop/node.def @@ -0,0 +1,3 @@ +type: u32 +help: "Outside port range stop" +syntax: ($(@) > 0 && $(@) < 65536) ; "port must be between 1 and 65535" diff --git a/templates-cfg/service/nat/rule/node.tag/outside-address/range/node.def b/templates-cfg/service/nat/rule/node.tag/outside-address/range/node.def new file mode 100644 index 0000000..b28186e --- /dev/null +++ b/templates-cfg/service/nat/rule/node.tag/outside-address/range/node.def @@ -0,0 +1 @@ +help: "Outside address range" diff --git a/templates-cfg/service/nat/rule/node.tag/outside-address/range/start/node.def b/templates-cfg/service/nat/rule/node.tag/outside-address/range/start/node.def new file mode 100644 index 0000000..27395f1 --- /dev/null +++ b/templates-cfg/service/nat/rule/node.tag/outside-address/range/start/node.def @@ -0,0 +1,2 @@ +type: ipv4 +help: "Outside address range start" diff --git a/templates-cfg/service/nat/rule/node.tag/outside-address/range/stop/node.def b/templates-cfg/service/nat/rule/node.tag/outside-address/range/stop/node.def new file mode 100644 index 0000000..f441522 --- /dev/null +++ b/templates-cfg/service/nat/rule/node.tag/outside-address/range/stop/node.def @@ -0,0 +1,2 @@ +type: ipv4 +help: "Outside address range stop" diff --git a/templates-cfg/service/nat/rule/node.tag/protocols/node.def b/templates-cfg/service/nat/rule/node.tag/protocols/node.def new file mode 100644 index 0000000..75ccb86 --- /dev/null +++ b/templates-cfg/service/nat/rule/node.tag/protocols/node.def @@ -0,0 +1,3 @@ +type: txt +help: "Protocol to NAT (this can be a protocol name in /etc/protocols, a protocol number, or \"all\")" +syntax: exec "/opt/vyatta/sbin/vyatta-validate-type.pl protocol_negate '$(@)'" ; "invalid protocol \"$(@)\"" diff --git a/templates-cfg/service/nat/rule/node.tag/source/address/node.def b/templates-cfg/service/nat/rule/node.tag/source/address/node.def new file mode 100644 index 0000000..6b88193 --- /dev/null +++ b/templates-cfg/service/nat/rule/node.tag/source/address/node.def @@ -0,0 +1,3 @@ +type: txt +help: "Source address" +syntax: exec "/opt/vyatta/sbin/vyatta-validate-type.pl ipv4_negate '$(@)'" ; "invalid source address \"$(@)\"" diff --git a/templates-cfg/service/nat/rule/node.tag/source/network/node.def b/templates-cfg/service/nat/rule/node.tag/source/network/node.def new file mode 100644 index 0000000..9306c53 --- /dev/null +++ b/templates-cfg/service/nat/rule/node.tag/source/network/node.def @@ -0,0 +1,3 @@ +type: txt +help: "Inside network" +syntax: exec "/opt/vyatta/sbin/vyatta-validate-type.pl ipv4net_negate '$(@)'" ; "invalid source network \"$(@)\"" diff --git a/templates-cfg/service/nat/rule/node.tag/source/node.def b/templates-cfg/service/nat/rule/node.tag/source/node.def new file mode 100644 index 0000000..3aad309 --- /dev/null +++ b/templates-cfg/service/nat/rule/node.tag/source/node.def @@ -0,0 +1 @@ +help: "NAT source parameters" diff --git a/templates-cfg/service/nat/rule/node.tag/source/port-name/node.def b/templates-cfg/service/nat/rule/node.tag/source/port-name/node.def new file mode 100644 index 0000000..1ead23b --- /dev/null +++ b/templates-cfg/service/nat/rule/node.tag/source/port-name/node.def @@ -0,0 +1,10 @@ +multi: +type: txt +help: "Named source port (e.g., http)" +syntax: exec "sh -c 'if grep -q '\\''^$(@)[ \t]'\\'' /etc/services; \ +then exit 0; else \ + if grep -q \ + '\\''^[^ \t]\\+[ \t]\\+[^ \t]\\+[^#]*[ \t]$(@)\\([ \t]\\|\\$\\)'\\'' \ + /etc/services; then exit 0; else exit 1; \ + fi; \ +fi' " ; "invalid port name $(@)" diff --git a/templates-cfg/service/nat/rule/node.tag/source/port-number/node.def b/templates-cfg/service/nat/rule/node.tag/source/port-number/node.def new file mode 100644 index 0000000..8b8be63 --- /dev/null +++ b/templates-cfg/service/nat/rule/node.tag/source/port-number/node.def @@ -0,0 +1,4 @@ +multi: +type: u32 +help: "Numbered source port (ex. 80)" +syntax: ($(@) > 0 && $(@) < 65536) ; "port must be between 1 and 65535" diff --git a/templates-cfg/service/nat/rule/node.tag/source/port-range/node.def b/templates-cfg/service/nat/rule/node.tag/source/port-range/node.def new file mode 100644 index 0000000..b21d6e8 --- /dev/null +++ b/templates-cfg/service/nat/rule/node.tag/source/port-range/node.def @@ -0,0 +1 @@ +help: "Range of source ports (ex. 80-110)" diff --git a/templates-cfg/service/nat/rule/node.tag/source/port-range/start/node.def b/templates-cfg/service/nat/rule/node.tag/source/port-range/start/node.def new file mode 100644 index 0000000..4ad95f4 --- /dev/null +++ b/templates-cfg/service/nat/rule/node.tag/source/port-range/start/node.def @@ -0,0 +1,3 @@ +type: u32 +help: "Starting source port range" +syntax: ($(@) > 0 && $(@) < 65536) ; "port must be between 1 and 65535" diff --git a/templates-cfg/service/nat/rule/node.tag/source/port-range/stop/node.def b/templates-cfg/service/nat/rule/node.tag/source/port-range/stop/node.def new file mode 100644 index 0000000..74a308b --- /dev/null +++ b/templates-cfg/service/nat/rule/node.tag/source/port-range/stop/node.def @@ -0,0 +1,3 @@ +type: u32 +help: "Ending source port range" +syntax: ($(@) > 0 && $(@) < 65536) ; "port must be between 1 and 65535" diff --git a/templates-cfg/service/nat/rule/node.tag/type/node.def b/templates-cfg/service/nat/rule/node.tag/type/node.def new file mode 100644 index 0000000..9df10a9 --- /dev/null +++ b/templates-cfg/service/nat/rule/node.tag/type/node.def @@ -0,0 +1,4 @@ +type: txt +help: "Source, destination, or masquerade NAT" +syntax: ($(@) == "source" || $(@) == "destination" || $(@) == "masquerade") ; \ +"invalid type $(@)" diff --git a/templates-op/clear/nat/counters/node.def b/templates-op/clear/nat/counters/node.def new file mode 100644 index 0000000..39a6ed5 --- /dev/null +++ b/templates-op/clear/nat/counters/node.def @@ -0,0 +1,2 @@ +help: Clear NAT counters +run: sudo iptables -Z -t nat diff --git a/templates-op/clear/nat/node.def b/templates-op/clear/nat/node.def new file mode 100644 index 0000000..aae6adc --- /dev/null +++ b/templates-op/clear/nat/node.def @@ -0,0 +1 @@ +help: Clear Network Address Translation tables diff --git a/templates-op/clear/nat/translations/node.def b/templates-op/clear/nat/translations/node.def new file mode 100644 index 0000000..0727cbd --- /dev/null +++ b/templates-op/clear/nat/translations/node.def @@ -0,0 +1,2 @@ +help: Clear NAT translations +run: sudo ${vyatta_sbindir}/vyatta-update-nat.pl clearnattranslations diff --git a/templates-op/show/nat/node.def b/templates-op/show/nat/node.def new file mode 100644 index 0000000..20ecd4d --- /dev/null +++ b/templates-op/show/nat/node.def @@ -0,0 +1 @@ +help: Show Network Address Translation information diff --git a/templates-op/show/nat/rules/node.def b/templates-op/show/nat/rules/node.def new file mode 100644 index 0000000..772e1b0 --- /dev/null +++ b/templates-op/show/nat/rules/node.def @@ -0,0 +1,3 @@ +help: Show configured NAT rule set +run: sudo ${vyatta_bindir}/sudo-users/vyatta-show-nat.pl \ + ${vyatta_datadir}/xsl/show_nat_rules.xsl diff --git a/templates-op/show/nat/statistics/node.def b/templates-op/show/nat/statistics/node.def new file mode 100644 index 0000000..b4fe23f --- /dev/null +++ b/templates-op/show/nat/statistics/node.def @@ -0,0 +1,3 @@ +help: Show statistics for configured NAT rules +run: sudo ${vyatta_bindir}/sudo-users/vyatta-show-nat.pl \ + ${vyatta_datadir}/xsl/show_nat_statistics.xsl diff --git a/xsl/show_nat_rules.xsl b/xsl/show_nat_rules.xsl new file mode 100644 index 0000000..e9fdbc9 --- /dev/null +++ b/xsl/show_nat_rules.xsl @@ -0,0 +1,309 @@ +<?xml version="1.0"?> +<!DOCTYPE stylesheet [ +<!ENTITY newln " "> +]> + +<!-- /* + * Copyright 2006, Vyatta, Inc. + * + * GNU General Public 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + * Module: show_nat_rules.xsl + * + * Author: Mike Horn + * Date: 2006 + * + */ --> + +<!--XSL Template for formatting the "show nat rules" command--> + +<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> + +<xsl:include href="url-decode.xsl" /> + +<xsl:variable name="pad6" select="' '"/> +<xsl:variable name="pad6_len" select="string-length($pad6)"/> +<xsl:variable name="pad7" select="' '"/> +<xsl:variable name="pad7_len" select="string-length($pad7)"/> +<xsl:variable name="pad11" select="' '"/> +<xsl:variable name="pad11_len" select="string-length($pad11)"/> +<xsl:variable name="pad13" select="' '"/> +<xsl:variable name="pad13_len" select="string-length($pad13)"/> +<xsl:variable name="pad20" select="' '"/> +<xsl:variable name="pad20_len" select="string-length($pad20)"/> + + +<xsl:template match="opcommand"> +<xsl:text>&newln;</xsl:text> +<xsl:text>&newln;</xsl:text> +<xsl:text>Type Codes: SRC - source, DST - destination, MASQ - masquerade&newln;</xsl:text> +<xsl:text>&newln;</xsl:text> +<xsl:text>rule type IN OUT source destination translation</xsl:text> +<xsl:text>&newln;</xsl:text> +<xsl:text>---- ---- --------- --------- ------ ----------- -----------</xsl:text> +<xsl:text>&newln;</xsl:text> + +<xsl:for-each select="format/row"> + +<xsl:value-of select="rule_num"/> +<xsl:value-of select="substring($pad6,1,$pad6_len - string-length(rule_num))"/> + + <xsl:choose> + <xsl:when test="type='source'"> + <xsl:text>SRC </xsl:text> + </xsl:when> + + <xsl:when test="type='destination'"> + <xsl:text>DST </xsl:text> + </xsl:when> + + <xsl:when test="type='masquerade'"> + <xsl:text>MASQ </xsl:text> + </xsl:when> + </xsl:choose> + + <xsl:choose> + <xsl:when test="in_interface=''"> + <xsl:text> - </xsl:text> + </xsl:when> + + <xsl:when test="in_interface!=''"> + <xsl:value-of select="in_interface"/> + <xsl:value-of select="substring($pad11,1,$pad11_len - string-length(in_interface))"/> + </xsl:when> + </xsl:choose> + + <xsl:choose> + <xsl:when test="out_interface=''"> + <xsl:text> - </xsl:text> + </xsl:when> + + <xsl:when test="out_interface!=''"> + <xsl:value-of select="out_interface"/> + <xsl:value-of select="substring($pad11,1,$pad11_len - string-length(out_interface))"/> + </xsl:when> + </xsl:choose> + + <xsl:choose> + <xsl:when test="src_addr=''"> + <xsl:value-of select="src_network"/> + <xsl:value-of select="substring($pad20,1,$pad20_len - string-length(src_network))"/> + </xsl:when> + + <xsl:when test="src_addr!='0.0.0.0'"> + <xsl:value-of select="src_addr"/> + <xsl:value-of select="substring($pad20,1,$pad20_len - string-length(src_addr))"/> + </xsl:when> + + <xsl:when test="src_addr='0.0.0.0'"> + <xsl:value-of select="src_network"/> + <xsl:value-of select="substring($pad20,1,$pad20_len - string-length(src_network))"/> + </xsl:when> + </xsl:choose> + + <xsl:choose> + <xsl:when test="dst_addr=''"> + <xsl:value-of select="dst_network"/> + <xsl:value-of select="substring($pad20,1,$pad20_len - string-length(dst_network))"/> + </xsl:when> + + <xsl:when test="dst_addr!='0.0.0.0'"> + <xsl:value-of select="dst_addr"/> + <xsl:value-of select="substring($pad20,1,$pad20_len - string-length(dst_addr))"/> + </xsl:when> + + <xsl:when test="dst_addr='0.0.0.0'"> + <xsl:value-of select="dst_network"/> + <xsl:value-of select="substring($pad20,1,$pad20_len - string-length(dst_network))"/> + </xsl:when> + </xsl:choose> + + <xsl:if test="type='destination'"> + <xsl:choose> + <xsl:when test="in_addr=''"> + <xsl:value-of select="in_network"/> + <xsl:value-of select="substring($pad20,1,$pad20_len - string-length(in_network))"/> + </xsl:when> + + <xsl:when test="in_addr!='0.0.0.0'"> + <xsl:value-of select="in_addr"/> + <xsl:value-of select="substring($pad20,1,$pad20_len - string-length(in_addr))"/> + </xsl:when> + + <xsl:when test="in_addr='0.0.0.0'"> + <xsl:value-of select="in_network"/> + <xsl:value-of select="substring($pad20,1,$pad20_len - string-length(in_network))"/> + </xsl:when> + </xsl:choose> + </xsl:if> + + <xsl:if test="type!='destination'"> + <xsl:choose> + <xsl:when test="out_addr=''"> + <xsl:value-of select="out_network"/> + <xsl:value-of select="substring($pad20,1,$pad20_len - string-length(out_network))"/> + </xsl:when> + + <xsl:when test="out_addr!='0.0.0.0'"> + <xsl:value-of select="out_addr"/> + <xsl:value-of select="substring($pad20,1,$pad20_len - string-length(out_addr))"/> + </xsl:when> + + <xsl:when test="out_addr='0.0.0.0'"> + <xsl:value-of select="out_network"/> + <xsl:value-of select="substring($pad20,1,$pad20_len - string-length(out_network))"/> + </xsl:when> + </xsl:choose> + </xsl:if> + + <xsl:text>&newln;</xsl:text> + + + <xsl:if test="src_ports!='' or dst_ports!=''"> + <xsl:variable name="src_ports_d"> + <xsl:call-template name="decode"> + <xsl:with-param name="encoded" select="src_ports"/> + </xsl:call-template> + </xsl:variable> + + <xsl:variable name="dst_ports_d"> + <xsl:call-template name="decode"> + <xsl:with-param name="encoded" select="dst_ports"/> + </xsl:call-template> + </xsl:variable> + + <xsl:value-of select="$pad6"/> + <xsl:value-of select="$pad6"/> + <xsl:value-of select="$pad6"/> + <xsl:value-of select="$pad11"/> + <xsl:value-of select="$pad11"/> + + <xsl:choose> + <xsl:when test="$src_ports_d=''"> + <xsl:value-of select="$pad20"/> + </xsl:when> + <xsl:when test="$src_ports_d!=''"> + <xsl:value-of select="$src_ports_d"/> + <xsl:value-of select="substring($pad20,1,$pad20_len - string-length($src_ports_d))"/> + </xsl:when> + </xsl:choose> + + <xsl:choose> + <xsl:when test="$dst_ports_d!=''"> + <xsl:value-of select="$dst_ports_d"/> + <xsl:value-of select="substring($pad20,1,$pad20_len - string-length($dst_ports_d))"/> + </xsl:when> + </xsl:choose> + <xsl:text>&newln;</xsl:text> + </xsl:if> + + + <xsl:if test="src_ports_apps!='' or dst_ports_apps!=''"> + <xsl:variable name="src_ports_apps_d"> + <xsl:call-template name="decode"> + <xsl:with-param name="encoded" select="src_ports_apps"/> + </xsl:call-template> + </xsl:variable> + + <xsl:variable name="dst_ports_apps_d"> + <xsl:call-template name="decode"> + <xsl:with-param name="encoded" select="dst_ports_apps"/> + </xsl:call-template> + </xsl:variable> + + <xsl:value-of select="$pad6"/> + <xsl:value-of select="$pad6"/> + <xsl:value-of select="$pad6"/> + <xsl:value-of select="$pad11"/> + <xsl:value-of select="$pad11"/> + + <xsl:choose> + <xsl:when test="$src_ports_apps_d=''"> + <xsl:value-of select="$pad20"/> + </xsl:when> + <xsl:when test="$src_ports_apps_d!=''"> + <xsl:value-of select="$src_ports_apps_d"/> + <xsl:value-of select="substring($pad20,1,$pad20_len - string-length($src_ports_apps_d))"/> + </xsl:when> + </xsl:choose> + + <xsl:choose> + <xsl:when test="$dst_ports_apps_d!=''"> + <xsl:value-of select="$dst_ports_apps_d"/> + <xsl:value-of select="substring($pad20,1,$pad20_len - string-length($dst_ports_apps_d))"/> + </xsl:when> + </xsl:choose> + <xsl:text>&newln;</xsl:text> + </xsl:if> + + <xsl:if test="src_port_start!='' or dst_port_start!=''"> + <xsl:value-of select="$pad6"/> + <xsl:value-of select="$pad6"/> + <xsl:value-of select="$pad6"/> + <xsl:value-of select="$pad11"/> + <xsl:value-of select="$pad11"/> + + <xsl:choose> + <xsl:when test="src_port_start=''"> + <xsl:value-of select="$pad20"/> + </xsl:when> + <xsl:when test="src_port_start!=''"> + <xsl:value-of select="src_port_start"/> + <xsl:value-of select="substring($pad20,1,$pad20_len - string-length(src_port_start))"/> + </xsl:when> + </xsl:choose> + + <xsl:choose> + <xsl:when test="dst_port_start!=''"> + <xsl:value-of select="dst_port_start"/> + <xsl:value-of select="substring($pad20,1,$pad20_len - string-length(dst_port_start))"/> + </xsl:when> + </xsl:choose> + <xsl:text>&newln;</xsl:text> + </xsl:if> + + <xsl:if test="src_port_stop!='' or dst_port_stop!=''"> + <xsl:value-of select="$pad6"/> + <xsl:value-of select="$pad6"/> + <xsl:value-of select="$pad6"/> + <xsl:value-of select="$pad11"/> + <xsl:value-of select="$pad11"/> + + <xsl:choose> + <xsl:when test="src_port_stop=''"> + <xsl:value-of select="$pad20"/> + </xsl:when> + <xsl:when test="src_port_stop!=''"> + <xsl:value-of select="src_port_stop"/> + <xsl:value-of select="substring($pad20,1,$pad20_len - string-length(src_port_stop))"/> + </xsl:when> + </xsl:choose> + + <xsl:choose> + <xsl:when test="dst_port_stop!=''"> + <xsl:value-of select="dst_port_stop"/> + <xsl:value-of select="substring($pad20,1,$pad20_len - string-length(dst_port_stop))"/> + </xsl:when> + </xsl:choose> + <xsl:text>&newln;</xsl:text> + </xsl:if> + +</xsl:for-each> +</xsl:template> + +</xsl:stylesheet> + diff --git a/xsl/show_nat_statistics.xsl b/xsl/show_nat_statistics.xsl new file mode 100644 index 0000000..140f98c --- /dev/null +++ b/xsl/show_nat_statistics.xsl @@ -0,0 +1,107 @@ +<?xml version="1.0"?> +<!DOCTYPE stylesheet [ +<!ENTITY newln " "> +]> + +<!-- /* + * Copyright 2006, Vyatta, Inc. + * + * GNU General Public 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + * Module: show_nat_statistics.xsl + * + * Author: Mike Horn + * Date: 2006 + * + */ --> + +<!--XSL Template for formatting the "show nat statistics" command--> + +<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> + +<xsl:variable name="pad6" select="' '"/> +<xsl:variable name="pad6_len" select="string-length($pad6)"/> +<xsl:variable name="pad10" select="' '"/> +<xsl:variable name="pad10_len" select="string-length($pad10)"/> +<xsl:variable name="pad11" select="' '"/> +<xsl:variable name="pad11_len" select="string-length($pad11)"/> +<xsl:variable name="pad12" select="' '"/> +<xsl:variable name="pad12_len" select="string-length($pad12)"/> + +<xsl:template match="opcommand"> + +<xsl:text>&newln;</xsl:text> +<xsl:text>&newln;</xsl:text> +<xsl:text>Type Codes: SRC - source, DST - destination, MASQ - masquerade&newln;</xsl:text> +<xsl:text>&newln;</xsl:text> +<xsl:text>rule packets bytes type IN OUT</xsl:text> +<xsl:text>&newln;</xsl:text> +<xsl:text>---- ------- ----- ---- --------- ---------</xsl:text> +<xsl:text>&newln;</xsl:text> + +<xsl:for-each select="format/row"> + +<xsl:value-of select="rule_num"/> +<xsl:value-of select="substring($pad6,1,$pad6_len - string-length(rule_num))"/> + +<xsl:value-of select="pkts"/> +<xsl:value-of select="substring($pad10,1,$pad10_len - string-length(pkts))"/> + +<xsl:value-of select="bytes"/> +<xsl:value-of select="substring($pad10,1,$pad10_len - string-length(bytes))"/> + + <xsl:choose> + <xsl:when test="type='source'"> + <xsl:text>SRC </xsl:text> + </xsl:when> + + <xsl:when test="type='destination'"> + <xsl:text>DST </xsl:text> + </xsl:when> + + <xsl:when test="type='masquerade'"> + <xsl:text>MASQ </xsl:text> + </xsl:when> + </xsl:choose> + + <xsl:choose> + <xsl:when test="in_interface=''"> + <xsl:text> - </xsl:text> + </xsl:when> + + <xsl:when test="in_interface!=''"> + <xsl:value-of select="in_interface"/> + <xsl:value-of select="substring($pad11,1,$pad11_len - string-length(in_interface))"/> + </xsl:when> + </xsl:choose> + + <xsl:choose> + <xsl:when test="out_interface=''"> + <xsl:text> - </xsl:text> + </xsl:when> + + <xsl:when test="out_interface!=''"> + <xsl:value-of select="out_interface"/> + </xsl:when> + </xsl:choose> + +<xsl:text>&newln;</xsl:text> + +</xsl:for-each> +</xsl:template> + +</xsl:stylesheet> |