summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMohit Mehta <mohit.mehta@vyatta.com>2009-08-05 12:24:11 -0700
committerMohit Mehta <mohit.mehta@vyatta.com>2009-08-05 12:24:11 -0700
commit4d56db8428fd770c86d80f77511814e2aff37c5e (patch)
treefba0883a86032086a448e757fada846dd5ce4808
parent1dfc6aa94e31a5ee6c420d184ec83dfd463bf615 (diff)
downloadvyatta-nat-4d56db8428fd770c86d80f77511814e2aff37c5e.tar.gz
vyatta-nat-4d56db8428fd770c86d80f77511814e2aff37c5e.zip
* Fix Bug 1445 - Allow setting protocols tcp and udp in one rule
NAT rules can be defined with 'tcp_udp' as a valid value for protocol * Fix Bug 4780 - DNAT rule to translate port fails
-rw-r--r--lib/Vyatta/NatRule.pm91
-rwxr-xr-xscripts/vyatta-show-nat.pl18
-rw-r--r--templates-cfg/service/nat/rule/node.tag/protocol/node.def7
3 files changed, 97 insertions, 19 deletions
diff --git a/lib/Vyatta/NatRule.pm b/lib/Vyatta/NatRule.pm
index c3631ae..79ca644 100644
--- a/lib/Vyatta/NatRule.pm
+++ b/lib/Vyatta/NatRule.pm
@@ -158,6 +158,10 @@ sub get_num_ipt_rules {
if ("$self->{_log}" eq 'enable') {
$ipt_rules++;
}
+ if (defined $self->{_proto} && $self->{_proto} eq 'tcp_udp') {
+ $ipt_rules++;
+ $ipt_rules++ if $self->{_log} eq 'enable';
+ }
return $ipt_rules;
}
@@ -189,10 +193,12 @@ sub rule_str {
my $jump_target = '';
my $jump_param = '';
my $use_netmap = 0;
+ my $tcp_and_udp = 0;
if (!defined($self->{_proto}) ||
- (($self->{_proto} ne "tcp") && ($self->{_proto} ne "6")
- && ($self->{_proto} ne "udp") && ($self->{_proto} ne "17"))) {
+ (($self->{_proto} ne "tcp_udp")
+ && ($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")) {
@@ -226,7 +232,12 @@ sub rule_str {
if (defined($self->{_proto})) {
my $str = $self->{_proto};
$str =~ s/^\!(.*)$/! $1/;
- $rule_str .= " -p $str";
+ if ($str eq 'tcp_udp') {
+ $tcp_and_udp = 1;
+ $rule_str .= " -p tcp"; # we'll add the '-p udp' to 2nd rule later
+ } else {
+ $rule_str .= " -p $str";
+ }
}
my $to_src = '';
@@ -259,7 +270,7 @@ sub rule_str {
if (defined($self->{_outside_addr}->{_port})) {
if (!$can_use_port) {
return ("ports can only be specified when protocol is \"tcp\" "
- . "or \"udp\" (currently \"$self->{_proto}\")", undef);
+ . "\"udp\" or \"tcp_udp\" (currently \"$self->{_proto}\")", undef);
}
if ($use_netmap) {
return ("Cannot use ports with an IPv4net type outside-address as it " .
@@ -280,9 +291,17 @@ sub rule_str {
= Vyatta::Misc::isValidPortNumber($port);
return ($err, undef) if (!defined($success));
} else {
- ($success, $err) = Vyatta::Misc::isValidPortName($port);
+ if ($self->{_proto} eq 'tcp_udp') {
+ ($success, $err) = Vyatta::Misc::isValidPortName($port, 'tcp');
+ return ($err, undef) if !defined $success ;
+ ($success, $err) = Vyatta::Misc::isValidPortName($port, 'udp');
+ return ($err, undef) if !defined $success ;
+ $port = getservbyname($port, 'tcp');
+ } else {
+ ($success, $err) = Vyatta::Misc::isValidPortName($port, $self->{_proto});
return ($err, undef) if !defined $success ;
- $port = getservbyname($port, $self->{_proto});
+ $port = getservbyname($port, $self->{_proto});
+ }
}
$to_src .= "$port";
}
@@ -331,7 +350,14 @@ sub rule_str {
}
if (defined($self->{_proto})) {
- $rule_str .= " -p $self->{_proto}";
+ my $str = $self->{_proto};
+ $str =~ s/^\!(.*)$/! $1/;
+ if ($str eq 'tcp_udp') {
+ $tcp_and_udp = 1;
+ $rule_str .= " -p tcp"; # we'll add the '-p udp' to 2nd rule later
+ } else {
+ $rule_str .= " -p $str";
+ }
}
my $to_dst = "";
@@ -363,7 +389,7 @@ sub rule_str {
if (defined($self->{_inside_addr}->{_port})) {
if (!$can_use_port) {
return ("ports can only be specified when protocol is \"tcp\" "
- . "or \"udp\" (currently \"$self->{_proto}\")", undef);
+ . "\"udp\" or \"tcp_udp\" (currently \"$self->{_proto}\")", undef);
}
if ($use_netmap) {
return ("Cannot use ports with an IPv4net type outside-address as it "
@@ -379,10 +405,19 @@ sub rule_str {
($success, $err) = Vyatta::Misc::isValidPortNumber($port);
return ($err, undef) if (!defined($success));
} else {
- ($success, $err) = Vyatta::Misc::isValidPortName($port);
- return ($err, undef) if (!defined($success));
- $port = getservbyname($port, $self->{_proto});
+ if ($self->{_proto} eq 'tcp_udp') {
+ ($success, $err) = Vyatta::Misc::isValidPortName($port, 'tcp');
+ return ($err, undef) if !defined $success ;
+ ($success, $err) = Vyatta::Misc::isValidPortName($port, 'udp');
+ return ($err, undef) if !defined $success ;
+ $port = getservbyname($port, 'tcp');
+ } else {
+ ($success, $err) = Vyatta::Misc::isValidPortName($port, $self->{_proto});
+ return ($err, undef) if !defined $success ;
+ $port = getservbyname($port, $self->{_proto});
+ }
}
+ $to_dst = " --to-destination " if $to_dst eq "";
$to_dst .= ":$port";
}
@@ -474,17 +509,39 @@ sub rule_str {
return (undef, undef) if defined $self->{_disable};
- $rule_str .= " $src_str $dst_str";
+ my $comment = "\"NAT-$self->{_rule_number}\" ";
+ if ($tcp_and_udp == 1) {
+ $comment = "\"NAT-$self->{_rule_number} tcp_udp\" ";
+ }
+ $rule_str .= " $src_str $dst_str" . " -m comment --comment " . $comment;
if ("$self->{_log}" eq "enable") {
- my $log_rule = $rule_str;
my $rule_num = $self->{_rule_number};
my $log_prefix = get_log_prefix($rule_num, $jump_target);
- $log_rule .= " -j LOG --log-prefix \"$log_prefix\" ";
- $rule_str .= " -j $jump_target $jump_param";
- return (undef, $log_rule, $rule_str);
+ if ($tcp_and_udp == 1) {
+ my $tcp_log_rule = $rule_str;
+ $tcp_log_rule .= " -j LOG --log-prefix \"$log_prefix\" ";
+ my $udp_log_rule = $tcp_log_rule;
+ $udp_log_rule =~ s/ \-p tcp / -p udp /;
+ $rule_str .= " -j $jump_target $jump_param";
+ my $udp_rule_str = $rule_str;
+ $udp_rule_str =~ s/ \-p tcp / -p udp /;
+ return (undef, $tcp_log_rule, $rule_str, $udp_log_rule, $udp_rule_str);
+ } else {
+ my $log_rule = $rule_str;
+ $log_rule .= " -j LOG --log-prefix \"$log_prefix\" ";
+ $rule_str .= " -j $jump_target $jump_param";
+ return (undef, $log_rule, $rule_str);
+ }
} else {
$rule_str .= " -j $jump_target $jump_param";
- return (undef, $rule_str);
+ if ($tcp_and_udp == 1) {
+ # protocol is 'tcp_udp'; make another rule for protocol 'udp'
+ my $udp_rule_str = $rule_str;
+ $udp_rule_str =~ s/ \-p tcp / -p udp /;
+ return (undef, $rule_str, $udp_rule_str);
+ } else {
+ return (undef, $rule_str);
+ }
}
}
diff --git a/scripts/vyatta-show-nat.pl b/scripts/vyatta-show-nat.pl
index 574c995..0ae25af 100755
--- a/scripts/vyatta-show-nat.pl
+++ b/scripts/vyatta-show-nat.pl
@@ -21,6 +21,8 @@ my %stats = (
);
open(STATS, "sudo /sbin/iptables -t nat -L -vn |") or exit 1;
my $skey = "";
+my ($rule_tcp_pkts, $rule_tcp_bytes, $rule_pkts, $rule_bytes);
+my $tcp_done = 0;
while (<STATS>) {
if (m/^Chain PREROUTING/) {
$skey = "destination";
@@ -32,7 +34,21 @@ while (<STATS>) {
if ($skey ne "" && (m/SNAT/ || m/DNAT/ || m/MASQUERADE/ || m/RETURN/ || m/NETMAP/)) {
m/^\s*(\d+[KMG]?)\s+(\d+[KMG]?)\s/;
- push @{$stats{$skey}}, ($1, $2);
+ $rule_pkts = $1;
+ $rule_bytes = $2;
+ if (m/tcp_udp/) { # protocol is tcp_udp, 2 rules in iptables for it
+ if ($tcp_done == 0) {
+ $rule_tcp_pkts = $rule_pkts;
+ $rule_tcp_bytes = $rule_bytes;
+ $tcp_done = 1;
+ next;
+ } else {
+ $rule_pkts += $rule_tcp_pkts;
+ $rule_bytes += $rule_tcp_bytes;
+ $tcp_done = 0;
+ }
+ }
+ push @{$stats{$skey}}, ($rule_pkts, $rule_bytes);
}
}
close STATS;
diff --git a/templates-cfg/service/nat/rule/node.tag/protocol/node.def b/templates-cfg/service/nat/rule/node.tag/protocol/node.def
index fdd589a..0aff708 100644
--- a/templates-cfg/service/nat/rule/node.tag/protocol/node.def
+++ b/templates-cfg/service/nat/rule/node.tag/protocol/node.def
@@ -1,8 +1,13 @@
type: txt
help: Set protocol to NAT (this can be a protocol name in /etc/protocols, a protocol number, or "all")
-syntax:expression: exec "/opt/vyatta/sbin/vyatta-validate-type.pl protocol_negate '$VAR(@)'" ; "invalid protocol \"$VAR(@)\""
comp_help:Possible completions:
<text> An IP protocol name from /etc/protocols (e.g. "tcp" or "udp")
<0-255> An IP protocol number
+ tcp_udp Both TCP and UDP
all All IP protocols
!<protocol> All IP protocols except for the specified name or number (negation)
+syntax:expression: exec "if [ -n \"`/opt/vyatta/sbin/vyatta-validate-type.pl protocol_negate '$VAR(@)'`\" ] \
+ && [ \"$VAR(@)\" != 'tcp_udp' ]; then \
+ echo invalid protocol \"$VAR(@)\" ; \
+ exit 1 ; \
+ fi ; "