File Coverage

blib/lib/IPChains/PortFW.pm
Criterion Covered Total %
statement 20 86 23.2
branch 1 52 1.9
condition 1 9 11.1
subroutine 6 13 46.1
pod 7 8 87.5
total 35 168 20.8


line stmt bran cond sub pod time code
1             #
2             # PortFW.pm - Perl module to interface with ipmasqadm portfw command.
3             #
4             # This file is part of Fwctl.
5             #
6             # Author: Francis J. Lacoste
7             #
8             # Copyright (C) 1999,2000 iNsu Innovations Inc.
9             #
10             # This program is free software; you can redistribute it and/or modify
11             # it under the terms of the GNU General Public License as published by
12             # the Free Software Foundation; either version 2 of the License, or
13             # (at your option) any later version.
14             #
15             package IPChains::PortFW;
16              
17 1     1   5 use strict;
  1         2  
  1         31  
18              
19 1     1   5 use Carp;
  1         2  
  1         62  
20 1     1   977 use Symbol;
  1         1089  
  1         68  
21              
22 1     1   5 use vars qw( $VERSION $IPMASQADM );
  1         2  
  1         77  
23              
24             BEGIN {
25              
26 1     1   1436 ($VERSION) = '$Revision: 1.4 $' =~ /Revision: ([0-9.]+)/;
27              
28             }
29              
30             my %VALID_OPTIONS = map { $_ => 1 } qw( LocalAddr LocalPort RemAddr RemPort
31             Proto Pref
32             );
33              
34             sub new {
35 1     1 1 2 my $proto = shift;
36 1   33     8 my $class = ref $proto || $proto;
37 1         3 my %args = @_;
38 1         2 my $self = { };
39              
40             # Look for ipmasqadm
41 1         7 my ($path) = grep { -x "$_/ipmasqadm" } split /:/, "/sbin:/bin:/usr/sbin:/usr/bin:$ENV{PATH}";
  11         162  
42 1 50       11 die ( "Couldn't find ipmasqadm in PATH ($ENV{PATH})\n" ) unless $path;
43 0           $self->{ipmasqadm} = "$path/ipmasqadm";
44              
45 0           bless $self, $class;
46              
47 0           while ( my ($key,$value) = each %args ) {
48 0           $self->attribute( $key, $value );
49             }
50              
51 0           $self;
52             }
53              
54             sub attribute {
55 0     0 1   my ($self,$key,$value) = @_;
56              
57 0 0         if ( @_ == 3 ) {
58 0 0         if ( $VALID_OPTIONS{$key} ) {
59 0           $self->{$key} = $value;
60             } else {
61 0           carp "Unknown option : $key";
62             }
63             }
64              
65 0           return $self->{$key};
66             }
67              
68             sub clopts {
69 0     0 1   my ( $self ) = shift;
70              
71 0           foreach my $key ( keys %VALID_OPTIONS ) {
72 0           delete $self->{$key};
73             }
74             }
75              
76             sub run_portfw {
77 0     0 0   my ( $self, @args ) = @_;
78              
79 0           my ($r_fh,$w_fh) = (gensym,gensym);
80 0 0         pipe $r_fh, $w_fh
81             or die "can't pipe: $!\n";
82              
83 0           my $pid = fork;
84 0 0         die "can't fork: $!\n" unless defined $pid;
85              
86 0 0         if ( $pid ) {
87             # Don't need this one
88 0           close $w_fh;
89              
90             # Collect STDOUT and STDERR
91 0           my $output;
92 0           while ( my $line = <$r_fh> ) {
93 0           $output .= $line;
94             }
95              
96             # Collect exit status
97 0           waitpid $pid,0;
98              
99 0 0         die "ipmasq exit with non zero status:\n$output\n" if $?;
100              
101 0           $output;
102             } else {
103             # Don't need this one
104 0           close $r_fh;
105              
106             # Redirect STDOUT and STDERR to parent
107 0 0         open ( STDOUT, ">&" . fileno $w_fh )
108             or die "can't redirect STDOUT to proper pipe: $!\n";
109 0 0         open ( STDERR, ">&" . fileno $w_fh )
110             or die "can't redirect STDERR to proper output fd: $!\n";
111 0 0         exec( $self->{ipmasqadm}, "portfw", @args )
112             or die "can't exec ipmasqadm: $!";
113             }
114             }
115              
116             sub append {
117 0     0 1   my ( $self ) = shift;
118              
119 0           my @args = ( "-a" );
120 0 0         croak "missing protocol" unless exists $self->{Proto};
121 0 0         croak "invalid protocol" unless $self->{Proto} =~ /udp|tcp|6|17/i;
122 0 0         croak "missing local address" unless exists $self->{LocalAddr};
123 0 0         croak "missing local port" unless exists $self->{LocalPort};
124 0 0         croak "missing remote address" unless exists $self->{RemAddr};
125 0 0         croak "missing remote port" unless exists $self->{RemPort};
126 0 0         if ( exists $self->{Pref} ) {
127 0 0 0       croak "invalid preference" unless $self->{Pref} =~ /\d+/ &&
128             $self->{Pref} >= 0;
129             }
130              
131 0           push @args, "-P", lc $self->{Proto}, "-L", $self->{LocalAddr},
132             $self->{LocalPort}, "-R", $self->{RemAddr}, $self->{RemPort};
133 0 0         push @args, "-p", $self->{Pref} if exists $self->{Pref};
134              
135 0           $self->run_portfw( @args );
136             }
137              
138             sub delete {
139 0     0 1   my ( $self ) = shift;
140              
141 0           my @args = ( "-d" );
142 0 0         croak "missing protocol" unless exists $self->{Proto};
143 0 0         croak "invalid protocol" unless $self->{Proto} =~ /udp|tcp|6|17/i;
144 0 0         croak "missing local address" unless exists $self->{LocalAddr};
145 0 0         croak "missing local port" unless exists $self->{LocalPort};
146              
147 0           push @args, "-P", lc $self->{Proto}, "-L", $self->{LocalAddr},
148             $self->{LocalPort};
149 0 0         push @args, "-R", $self->{RemAddr}, $self->{RemPort}
150             if exists $self->{RemAddr};
151              
152 0           $self->run_portfw( @args );
153              
154             }
155              
156             sub flush {
157 0     0 1   $_[0]->run_portfw( "-f" );
158             }
159              
160             sub list {
161 0     0 1   my ($self, $use_dns) = @_;
162              
163 0           my @args = ( "-l" );
164 0 0 0       push @args, "-n" unless defined $use_dns && $use_dns;
165              
166 0           my $output = $self->run_portfw( @args );
167 0 0         return () unless defined $output;
168              
169             # Parse output
170 0           my @lines = split /\n/, $output;
171              
172             # Skip header line
173 0           shift @lines;
174              
175 0           my @rules = ();
176 0           foreach my $line ( @lines ) {
177 0           my ( $prot, $laddr, $raddr, $lport, $rport, $ignored, $pref ) =
178             split / +/, $line;
179 0           push @rules, $self->new( Proto => lc $prot,
180             LocalAddr => $laddr,
181             RemAddr => $raddr,
182             LocalPort => $lport,
183             RemPort => $rport,
184             );
185             }
186              
187 0           @rules;
188             }
189              
190             1;
191              
192             __END__