File Coverage

blib/lib/Net/Divert.pm
Criterion Covered Total %
statement 10 49 20.4
branch 1 14 7.1
condition n/a
subroutine 3 8 37.5
pod 0 3 0.0
total 14 74 18.9


line stmt bran cond sub pod time code
1             #
2             # Copyright (c) 2001, Stephanie Wehner
3             # All rights reserved.
4             #
5             # Redistribution and use in source and binary forms, with or without
6             # modification, are permitted provided that the following conditions
7             # are met:
8             #
9             # 1. Redistributions of source code must retain the above copyright
10             # notice, this list of conditions and the following disclaimer.
11             # 2. Redistributions in binary form must reproduce the above copyright
12             # notice, this list of conditions and the following disclaimer in the
13             # documentation and/or other materials provided with the distribution.
14             # 3. Neither the name of the company ITSX nor the names of its contributors
15             # may be used to endorse or promote products derived from this software
16             # without specific prior written permission.
17             #
18             # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19             # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20             # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21             # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22             # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23             # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24             # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25             # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26             # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27             # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28             # SUCH DAMAGE.
29             #
30             #
31             # Net::Divert - FreeBSD Divert sockets in perl
32             #
33             # $Id: Divert.pm,v 1.2 2001/07/13 13:40:31 atrak Exp $
34              
35             package Net::Divert;
36              
37 1     1   8983 use strict;
  1         2  
  1         51  
38 1     1   5 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
  1         2  
  1         206  
39              
40             require Exporter;
41              
42             @ISA = qw(Exporter AutoLoader);
43              
44             # Items to export into callers namespace by default. Note: do not export
45             # names by default without a very good reason. Use EXPORT_OK instead.
46             # Do not simply export all your public functions/methods/constants.
47             @EXPORT = qw(
48            
49             );
50              
51             $VERSION = '0.01';
52              
53             # variables
54             my $IP_MAXPACKET = 65535;
55              
56              
57             BEGIN {
58              
59 1     1   2 my (@mods,$mod);
60              
61 1         8 @mods = qw(POSIX IO::Socket IO::Select);
62              
63 1         2 for $mod (@mods) {
64              
65 3 50       55719 unless(eval "require $mod") {
66 0           die "Can't find required module $mod: $!\n";
67             }
68             }
69             }
70              
71             sub new
72             {
73 0     0 0   my $class = shift;
74 0           my $self = {};
75              
76 0           bless($self, $class);
77              
78             # initialize the divert object
79 0           $self->_init(@_);
80              
81 0           return($self);
82             }
83              
84             # initialize
85              
86             sub _init
87             {
88 0     0     my $self = shift;
89 0           my ($host, $port) = @_;
90            
91             # check if we're root
92 0 0         if(POSIX::getuid() != 0) {
93 0           die "Need to be root to create a divert socket.\n";
94             }
95              
96             # record host and port
97 0           $self->{HOST} = $host;
98 0           $self->{PORT} = $port;
99              
100             # set the initial fwrule tag where the packet is
101             # reinserted (see man divert)
102 0           $self->{FWTAG} = 0;
103              
104             # nothing to be written now
105 0           $self->{OUT} = -1;
106 0           $self->{DATA} = "";
107              
108             # setup the divert socket
109 0           $self->{SOCK} = IO::Socket::INET->new(LocalHost => $host,
110             LocalPort => $port,
111             Type => IO::Socket::SOCK_RAW,
112             Proto => 'divert');
113              
114             # set autoflush
115 0           $self->{SOCK}->autoflush(1);
116              
117 0           return;
118             }
119              
120             # clean up at the end
121              
122             sub DESTROY
123 0     0     {
124             # socket cleanup will be done by IO::Socket::INET
125             }
126              
127             # fetch data and call user supplied function, this is perhaps
128             # a bit overly cautious :)
129              
130             sub getPackets
131             {
132 0     0 0   my $self = shift;
133 0           my $pFunc = shift;
134 0           my ($select,$data,$fwtag,$s);
135              
136             # initialize the select object
137 0           $select = new IO::Select($self->{SOCK});
138              
139             # get packets
140 0           while(1) {
141              
142             # see if things still need to be written
143 0 0         if($self->{OUT} == -1) {
144              
145             # check if one can read
146 0           foreach $s ($select->can_read) {
147              
148 0 0         if($s == $self->{SOCK}) {
149              
150             # fetch the packet
151 0 0         $fwtag = recv($s,$data,$IP_MAXPACKET,0) or
152             die "Unable to read packet: $!\n";
153              
154             # call the user supplied function
155 0           &$pFunc($data,$fwtag);
156             }
157             }
158              
159             } else {
160              
161             # check if one can write
162 0           foreach $s ($select->can_write) {
163              
164 0 0         if($s == $self->{SOCK}) {
165            
166             # write outstanding packet
167 0 0         send($s,$self->{DATA},0,$self->{FWTAG}) or
168             die "Unable to write packet: $!\n";
169              
170             # XXX robustness
171              
172 0           $self->{OUT} = -1 ;
173             }
174             }
175             }
176              
177             }
178              
179 0           return;
180             }
181              
182             # put a packet back on track, that'll be written next
183              
184             sub putPacket
185             {
186 0     0 0   my $self = shift;
187            
188 0           $self->{DATA} = shift;
189 0           $self->{FWTAG} = shift;
190 0           $self->{OUT} = $self->{SOCK};
191              
192 0           return;
193             }
194              
195             1;
196             __END__