Add PROTO and PORTS columns to netmap

This commit is contained in:
Tom Eastep 2011-09-05 12:33:42 -07:00
parent ee8a8978b2
commit 77ca62835f
2 changed files with 181 additions and 1 deletions

View File

@ -151,6 +151,7 @@ our %EXPORT_TAGS = (
clearrule clearrule
port_count port_count
do_proto do_proto
do_iproto
do_mac do_mac
do_imac do_imac
verify_mark verify_mark
@ -3125,6 +3126,181 @@ sub do_mac( $ ) {
"-m mac ${invert}--mac-source $mac "; "-m mac ${invert}--mac-source $mac ";
} }
sub do_iproto( $$$ )
{
my ($proto, $ports, $sports ) = @_;
my @output = ();
my $restricted = 1;
$proto = '' if $proto eq '-';
$ports = '' if $ports eq '-';
$sports = '' if $sports eq '-';
if ( $proto ne '' ) {
my $synonly = ( $proto =~ s/:syn$//i );
my $invert = ( $proto =~ s/^!// ? '! ' : '' );
my $protonum = resolve_proto $proto;
if ( defined $protonum ) {
#
# Protocol is numeric and <= 255 or is defined in /etc/protocols or NSS equivalent
#
fatal_error "'!0' not allowed in the PROTO column" if $invert && ! $protonum;
my $pname = proto_name( $proto = $protonum );
#
# $proto now contains the protocol number and $pname contains the canonical name of the protocol
#
unless ( $synonly ) {
@output = ( p => "${invert}${proto}" );
} else {
fatal_error '":syn" is only allowed with tcp' unless $proto == TCP && ! $invert;
@output = ( p => "$proto --syn" );
}
fatal_error "SOURCE/DEST PORT(S) not allowed with PROTO !$pname" if $invert && ($ports ne '' || $sports ne '');
PROTO:
{
if ( $proto == TCP || $proto == UDP || $proto == SCTP || $proto == DCCP || $proto == UDPLITE ) {
my $multiport = 0;
if ( $ports ne '' ) {
$invert = $ports =~ s/^!// ? '! ' : '';
if ( $ports =~ tr/,/,/ > 0 || $sports =~ tr/,/,/ > 0 || $proto == UDPLITE ) {
fatal_error "Port lists require Multiport support in your kernel/iptables" unless have_capability( 'MULTIPORT' );
fatal_error "Multiple ports not supported with SCTP" if $proto == SCTP;
if ( port_count ( $ports ) > 15 ) {
if ( $restricted ) {
fatal_error "A port list in this file may only have up to 15 ports";
} elsif ( $invert ) {
fatal_error "An inverted port list may only have up to 15 ports";
}
}
$ports = validate_port_list $pname , $ports;
push @output, multiport => "${invert}--dports ${ports}";
$multiport = 1;
} else {
fatal_error "Missing DEST PORT" unless supplied $ports;
$ports = validate_portpair $pname , $ports;
push @output, dport => "${invert}${ports}";
}
} else {
$multiport = ( ( $sports =~ tr/,/,/ ) > 0 || $proto == UDPLITE );
}
if ( $sports ne '' ) {
$invert = $sports =~ s/^!// ? '! ' : '';
if ( $multiport ) {
if ( port_count( $sports ) > 15 ) {
if ( $restricted ) {
fatal_error "A port list in this file may only have up to 15 ports";
} elsif ( $invert ) {
fatal_error "An inverted port list may only have up to 15 ports";
}
}
$sports = validate_port_list $pname , $sports;
push @output, multiport => "${invert}--sports ${sports}";
} else {
fatal_error "Missing SOURCE PORT" unless supplied $sports;
$sports = validate_portpair $pname , $sports;
push @output, sport => "${invert}${sports}";
}
}
last PROTO; }
if ( $proto == ICMP ) {
fatal_error "ICMP not permitted in an IPv6 configuration" if $family == F_IPV6; #User specified proto 1 rather than 'icmp'
if ( $ports ne '' ) {
$invert = $ports =~ s/^!// ? '! ' : '';
my $types;
if ( $ports =~ /,/ ) {
fatal_error "An inverted ICMP list may only contain a single type" if $invert;
$types = '';
for my $type ( split_list( $ports, 'ICMP type list' ) ) {
$types = $types ? join( ',', $types, validate_icmp( $type ) ) : $type;
}
} else {
$types = validate_icmp $ports;
}
push @output, 'icmp-type' => "${invert}${types}";
}
fatal_error 'SOURCE PORT(S) not permitted with ICMP' if $sports ne '';
last PROTO; }
if ( $proto == IPv6_ICMP ) {
fatal_error "IPv6_ICMP not permitted in an IPv4 configuration" if $family == F_IPV4;
if ( $ports ne '' ) {
$invert = $ports =~ s/^!// ? '! ' : '';
my $types;
if ( $ports =~ /,/ ) {
fatal_error "An inverted ICMP list may only contain a single type" if $invert;
$types = '';
for my $type ( list_split( $ports, 'ICMP type list' ) ) {
$types = $types ? join( ',', $types, validate_icmp6( $type ) ) : $type;
}
} else {
$types = validate_icmp6 $ports;
}
push @output, 'icmpv6-type' => "${invert}${types}";
}
fatal_error 'SOURCE PORT(S) not permitted with IPv6-ICMP' if $sports ne '';
last PROTO; }
fatal_error "SOURCE/DEST PORT(S) not allowed with PROTO $pname" if $ports ne '' || $sports ne '';
} # PROTO
} else {
fatal_error '":syn" is only allowed with tcp' if $synonly;
if ( $proto =~ /^(ipp2p(:(tcp|udp|all))?)$/i ) {
my $p = $2 ? lc $3 : 'tcp';
require_capability( 'IPP2P_MATCH' , "PROTO = $proto" , 's' );
$proto = '-p ' . proto_name($p) . ' ';
my $options = '';
if ( $ports ne 'ipp2p' ) {
$options .= " --$_" for split /,/, $ports;
}
$options = have_capability( 'OLD_IPP2P_MATCH' ) ? ' --ipp2p' : ' --edk --kazaa --gnu --dc' unless $options;
push @output, ipp2p => "${proto}${options}";
} else {
fatal_error "Invalid/Unknown protocol ($proto)"
}
}
} else {
#
# No protocol
#
fatal_error "SOURCE/DEST PORT(S) not allowed without PROTO" if $ports ne '' || $sports ne '';
}
@output;
}
sub do_imac( $ ) { sub do_imac( $ ) {
my $mac = $_[0]; my $mac = $_[0];

View File

@ -407,7 +407,7 @@ sub setup_netmap() {
while ( read_a_line ) { while ( read_a_line ) {
my ( $type, $net1, $interfacelist, $net2, $net3 ) = split_line 4, 5, 'netmap file'; my ( $type, $net1, $interfacelist, $net2, $net3, $proto, $dport, $sport ) = split_line 4, 8, 'netmap file';
validate_net $net1, 0; validate_net $net1, 0;
validate_net $net2, 0; validate_net $net2, 0;
@ -420,6 +420,8 @@ sub setup_netmap() {
fatal_error "Unknown interface ($interface)" unless my $interfaceref = known_interface( $interface ); fatal_error "Unknown interface ($interface)" unless my $interfaceref = known_interface( $interface );
my @rule = do_iproto( $proto, $sport, $dport );
unless ( $type =~ /:/ ) { unless ( $type =~ /:/ ) {
my @rulein; my @rulein;
my @ruleout; my @ruleout;
@ -465,6 +467,7 @@ sub setup_netmap() {
targetopts => "--to-dest $net2", targetopts => "--to-dest $net2",
imatch_source_net( $net3 ) , imatch_source_net( $net3 ) ,
imatch_dest_net( $net1 ) , imatch_dest_net( $net1 ) ,
@rule ,
@match ); @match );
} else { } else {
add_ijump( ensure_chain( $table, $chain ) , add_ijump( ensure_chain( $table, $chain ) ,
@ -472,6 +475,7 @@ sub setup_netmap() {
targetopts => "--to-source $net2", targetopts => "--to-source $net2",
imatch_dest_net( $net3 ) , imatch_dest_net( $net3 ) ,
imatch_source_net( $net1 ) , imatch_source_net( $net1 ) ,
@rule ,
@match ); @match );
} }
} else { } else {