summaryrefslogtreecommitdiff
path: root/scripts/vyatta-clear-nat-counters.pl
blob: 06e67aeee0031aad87a2fdc7a7f7656c3acfadb1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#!/usr/bin/perl
#
# Module: vyatta-clear-nat-counters.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) 2006-2009 Vyatta, Inc.
# All Rights Reserved.
#
# Author: Mohit Mehta
# Date: February 2010
# Description: Script to clear nat counters
#
# **** End License ****
#

use Getopt::Long;
use POSIX;
use warnings;
use strict;
use lib "/opt/vyatta/share/perl5";
use Vyatta::Config;

# NAT type mapping from config node to iptables chain
my $src_chain = "POSTROUTING";
my $dst_chain = "PREROUTING";
my $chain = undef;

# NAT CLI levels
my $src_level = "nat source rule";
my $dst_level = "nat destination rule";
my $level = undef;

my $iptables = "sudo /sbin/iptables";

sub numerically { $a <=> $b; }

sub get_nat_rules {
  my $config = new Vyatta::Config;
  $config->setLevel($level);
  my @rules = sort numerically $config->listOrigNodes();
  return @rules;
}

sub print_nat_rules {
  my @rules = get_nat_rules();
  my $rule_string = join(" ",@rules);
  print $rule_string;
  return;
}

sub clear_rule {
  my $clirule = shift;
  my $error = undef;

  if ($clirule eq 'all') {
    # clear counters for all rules in NAT table
    $error = system("$iptables -Z -t nat &>/dev/null");
    return "error clearing NAT rule counters" if $error;
  } else {
    # clear counters for a specific NAT rule
    my @rules = get_nat_rules();

    # validate that it's a legit CLI rule
    if (!((scalar(grep(/^$clirule$/, @rules)) > 0))) {
      return "Invalid NAT rule number \"$clirule\"";
    }

    my $config = new Vyatta::Config;
    $config->setLevel($level);

    # make sure rule is enabled
    my $is_rule_disabled = $config->existsOrig("$clirule disable");
    return "NAT rule $clirule is disabled" if defined $is_rule_disabled;

    # find corresponding rulenum in the underlying NAT table
    my $iptables_rule = undef;
    my $cmd = "$iptables -L $chain -t nat -nv " .
              "--line-numbers | grep '/\* .*NAT-$clirule' | awk {'print \$1'}";
    $iptables_rule = `$cmd`;
    return "couldn't find an underlying iptables rule" if ! defined $iptables_rule;
    chomp $iptables_rule;
    # Rules with "log" statement and "tcp_udp" rules take more than one line
    my @numbers = split(/\n/, $iptables_rule);

    # clear the counters for that rule
    for my $number (@numbers) {
        $cmd = "$iptables -t nat -Z $chain $number";
        $error = system($cmd);
        return "error clearing counters for NAT rule $clirule" if $error;
    }
  }
  return;
}

#
# main
#

my ($action, $clirulenum, $type);

GetOptions( "action=s"  => \$action,
            "clirule=s" => \$clirulenum,
            "type=s"    => \$type
          );

die "undefined action" if ! defined $action;
die "undefined rule number" if ! defined $clirulenum;
die "undefined NAT type" if ! defined $type;

if ($type eq 'source') {
    $level = $src_level;
    $chain = $src_chain;
} elsif ($type eq 'destination') {
    $level = $dst_level;
    $chain = $dst_chain;
} else {
    die "unknown NAT type";
}

my ($error, $warning);

($error, $warning) = clear_rule($clirulenum) if $action eq 'clear-counters';

($error, $warning) = print_nat_rules() if $action eq 'print-nat-rules';

if (defined $warning) {
    print "$warning\n";
}

if (defined $error) {
    print "$error\n";
    exit 1;
}

exit 0;

# end of file