summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
authorStig Thormodsrud <stig@vyatta.com>2008-08-02 19:13:03 -0700
committerStig Thormodsrud <stig@vyatta.com>2008-08-02 19:13:03 -0700
commitb4453ca528607b6bf9871c17c23048465de3768c (patch)
treef9ab2dd92b31cef86d8ccda95c996c26d284cf54 /scripts
parentddc06ae69abd438b07afa679f5f3af4d9a8199d9 (diff)
downloadvyatta-nat-b4453ca528607b6bf9871c17c23048465de3768c.tar.gz
vyatta-nat-b4453ca528607b6bf9871c17c23048465de3768c.zip
Fix 522: Feature Request: add "show nat translations" command to list active NAT translations.
Diffstat (limited to 'scripts')
-rwxr-xr-xscripts/vyatta-nat-translations.pl254
1 files changed, 254 insertions, 0 deletions
diff --git a/scripts/vyatta-nat-translations.pl b/scripts/vyatta-nat-translations.pl
new file mode 100755
index 0000000..e5e9e64
--- /dev/null
+++ b/scripts/vyatta-nat-translations.pl
@@ -0,0 +1,254 @@
+#!/usr/bin/perl
+#
+# Module: vyatta-nat-translate.pl
+#
+# **** 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) 2007 Vyatta, Inc.
+# All Rights Reserved.
+#
+# Author: Stig Thormodsrud
+# Date: July 2008
+# Description: Script to display nat translations
+#
+# **** End License ****
+#
+
+use Getopt::Long;
+use XML::Simple;
+use Data::Dumper;
+use POSIX;
+
+use warnings;
+use strict;
+
+my $dump = 0;
+my ($xml_file, $verbose, $proto, $stats, $ipaddr, $pipe);
+my $mode='both';
+my $verbose_format = "%-20s %-18s %-20s %-18s\n";
+my $format = "%-20s %-20s %-4s %-4s %-8s";
+
+
+sub add_xml_root {
+ my $xml = shift;
+
+ $xml = '<data>' . $xml . '</data>';
+ return $xml;
+}
+
+sub read_xml_file {
+ my $file = shift;
+
+ local($/, *FD); # slurp mode
+ open FD, "<", $file or die "Couldn't open $file\n";
+ my $xml = <FD>;
+ close FD;
+ $xml = add_xml_root($xml);
+ return $xml;
+}
+
+sub print_xml {
+ my $data = shift;
+ print Dumper($data);
+}
+
+sub nat_print_xml {
+ my ($data, $mode) = @_;
+
+ my $flow = 0;
+
+ my %flowh;
+ while (1) {
+ my $meta = 0;
+ last if ! defined $data->{flow}[$flow];
+ my $flow_ref = $data->{flow}[$flow];
+ my $flow_type = $flow_ref->{type};
+ my (%src, %dst, %sport, %dport, %proto);
+ my (%packets, %bytes);
+ my $timeout = undef;
+ my $uses = undef;
+ while (1) {
+ my $meta_ref = $flow_ref->{meta}[$meta];
+ last if ! defined $meta_ref;
+ my $dir = $meta_ref->{direction};
+ if ($dir eq 'original' or $dir eq 'reply') {
+ my $l3_ref = $meta_ref->{layer3}[0];
+ my $l4_ref = $meta_ref->{layer4}[0];
+ my $count_ref = $meta_ref->{counters}[0];
+ if (defined $l3_ref) {
+ $src{$dir} = $l3_ref->{src}[0];
+ $dst{$dir} = $l3_ref->{dst}[0];
+ if (defined $l4_ref) {
+ $sport{$dir} = $l4_ref->{sport}[0];
+ $dport{$dir} = $l4_ref->{dport}[0];
+ $proto{$dir} = $l4_ref->{protoname};
+ }
+ }
+ if (defined $stats and defined $count_ref) {
+ $packets{$dir} = $count_ref->{packets}[0];
+ $bytes{$dir} = $count_ref->{bytes}[0];
+ }
+ } elsif ($dir eq 'independent') {
+ $timeout = $meta_ref->{timeout}[0];
+ $uses = $meta_ref->{'use'}[0];
+ }
+ $meta++;
+ }
+ my ($proto, $in_src, $in_dst, $out_src, $out_dst);
+ $proto = $proto{original};
+ $in_src = "$src{original}";
+ $in_src .= ":$sport{original}" if defined $sport{original};
+ $in_dst = "$dst{original}";
+ $in_dst .= ":$dport{original}" if defined $dport{original};
+ $out_src = "$dst{reply}";
+ $out_src .= ":$dport{reply}" if defined $dport{reply};
+ $out_dst = "$src{reply}";
+ $out_dst .= ":$sport{reply}" if defined $sport{reply};
+ if (defined $verbose) {
+ printf($verbose_format, $in_src, $in_dst, $out_src, $out_dst);
+ }
+ if (defined $mode) {
+ my ($from, $to);
+ if ($mode eq 'snat') {
+ $from = "$src{original}";
+ $to = "$dst{reply}";
+ if (defined $sport{original} and defined $dport{reply}) {
+ if ($sport{original} ne $dport{reply}) {
+ $from .= ":$sport{original}";
+ $to .= ":$dport{reply}";
+ }
+ }
+ } else {
+ $from = "$dst{original}";
+ $to = "$src{reply}";
+ if (defined $dport{original} and defined $sport{reply}) {
+ if ($dport{original} ne $sport{reply}) {
+ $from .= ":$dport{original}";
+ $to .= ":$sport{reply}";
+ }
+ }
+ }
+ if (defined $verbose) {
+ print " $proto: $mode: $from ==> $to";
+ } else {
+ my $timeout2 = "";
+ if (defined $timeout) {
+ $timeout2 = $timeout;
+ }
+ printf($format, $from, $to, $mode, $proto, $timeout2);
+ print " $flow_type" if defined $flow_type;
+ print "\n";
+ }
+ }
+ if (defined $verbose) {
+ print " timeout: $timeout" if defined $timeout;
+ print " use: $uses " if defined $uses;
+ print " type: $flow_type" if defined $flow_type;
+ print "\n";
+ }
+ if (defined $stats) {
+ foreach my $dir ('original', 'reply') {
+ if (defined $packets{$dir}) {
+ printf(" %-8s: packets %s, bytes %s\n",
+ $dir, $packets{$dir}, $bytes{$dir});
+ }
+ }
+ }
+ $flow++;
+ }
+ return $flow;
+}
+
+
+#
+# main
+#
+GetOptions("verbose" => \$verbose,
+ "proto=s" => \$proto,
+ "file=s" => \$xml_file,
+ "stats" => \$stats,
+ "mode=s" => \$mode,
+ "ipaddr=s" => \$ipaddr,
+ "pipe" => \$pipe,
+);
+
+my $conntrack = '/usr/sbin/conntrack';
+if (! -f $conntrack) {
+ die "Package [conntrack] not installed";
+}
+
+my $xs = XML::Simple->new(ForceArray => 1, KeepRoot => 0);
+my ($xml, $data);
+
+if (defined $xml_file) {
+ $xml = read_xml_file($xml_file);
+ $data = $xs->XMLin($xml);
+ if ($dump) {
+ print_xml($data);
+ exit;
+ }
+ if (defined $verbose) {
+ printf($verbose_format, 'Inside src', 'Inside dst',
+ 'Outside src', 'Outside dst');
+ } else {
+ printf($format, 'Pre-NAT', 'Post-NAT', 'Type', 'Prot', 'Timeout');
+ print "\n";
+ }
+ nat_print_xml($data, 'snat');
+
+} elsif (defined $pipe) {
+ # flush stdout after every write
+ $| = 1;
+ printf($format, 'Pre-NAT', 'Post-NAT', 'Type', 'Prot', 'Timeout');
+ print " Type\n";
+ while ($xml = <STDIN>) {
+ $xml = add_xml_root($xml);
+ $data = $xs->XMLin($xml);
+ nat_print_xml($data, $mode);
+ }
+} else {
+
+ if (defined $proto) {
+ $proto = "-p $proto"
+ } else {
+ $proto = "";
+ }
+ if (defined $verbose) {
+ printf($verbose_format, 'Inside src', 'Inside dst',
+ 'Outside src', 'Outside dst');
+ } else {
+ printf($format, 'Pre-NAT', 'Post-NAT', 'Type', 'Prot', 'Timeout');
+ print "\n";
+ }
+ if ($mode eq 'both' or $mode eq 'snat') {
+ my $ipopt = "";
+ if (defined $ipaddr) {
+ $ipopt = "--orig-src $ipaddr";
+ }
+ $xml = `sudo $conntrack -L -n $ipopt -o xml $proto`;
+ my $snat_xml = add_xml_root($xml);
+ $data = $xs->XMLin($snat_xml);
+ nat_print_xml($data, 'snat');
+ }
+ if ($mode eq 'both' or $mode eq 'dnat') {
+ my $ipopt = "";
+ if (defined $ipaddr) {
+ $ipopt = "--orig-dst $ipaddr";
+ }
+ $xml = `sudo $conntrack -L -g $ipopt -o xml $proto`;
+ my $dnat_xml = add_xml_root($xml);
+ $data = $xs->XMLin($dnat_xml);
+ nat_print_xml($data, 'dnat');
+ }
+}
+
+# end of file