File Coverage

blib/lib/Net/Packet/Env.pm
Criterion Covered Total %
statement 15 17 88.2
branch n/a
condition 1 2 50.0
subroutine 6 6 100.0
pod n/a
total 22 25 88.0


line stmt bran cond sub pod time code
1             #
2             # $Id: Env.pm 2002 2015-02-15 16:50:35Z gomor $
3             #
4             package Net::Packet::Env;
5 29     29   161042 use strict;
  29         59  
  29         1096  
6 29     29   139 use warnings;
  29         40  
  29         2238  
7              
8             require Exporter;
9             require Class::Gomor::Array;
10             our @ISA = qw(Exporter Class::Gomor::Array);
11             our @EXPORT_OK = qw($Env);
12              
13 29     29   142 use Carp qw(croak);
  29         38  
  29         3950  
14             require Net::Libdnet;
15             require Net::IPv6Addr;
16              
17             our @AS = qw(
18             dev
19             ip
20             ip6
21             mac
22             subnet
23             gatewayIp
24             gatewayMac
25             desc
26             dump
27             err
28             errString
29             noFrameAutoDesc
30             noFrameAutoDump
31             noDescAutoSet
32             noDumpAutoSet
33             noFramePadding
34             noFrameComputeChecksums
35             noFrameComputeLengths
36             noObsoleteWarning
37             doFrameReturnList
38             doIPv4Checksum
39             doMemoryOptimizations
40             _dnet
41             );
42             our @AO = qw(
43             debug
44             );
45             __PACKAGE__->cgBuildIndices;
46             __PACKAGE__->cgBuildAccessorsScalar(\@AS);
47              
48 29     29   202 no strict 'vars';
  29         49  
  29         2291  
49              
50             BEGIN {
51 29     29   184 my $osname = {
52             cygwin => [ \&_getDevWin32, ],
53             MSWin32 => [ \&_getDevWin32, ],
54             };
55              
56 29   50     1002 *getDev = $osname->{$^O}->[0] || \&_getDevOther;
57             }
58              
59 29     29   12536 use Net::Packet::Utils qw(getGatewayIp);
  0            
  0            
60              
61             our $Env = __PACKAGE__->new;
62              
63             sub new {
64             my $self = shift->SUPER::new(
65             debug => 0,
66             noFrameAutoDesc => 0,
67             noFrameAutoDump => 0,
68             noDescAutoSet => 0,
69             noDumpAutoSet => 0,
70             noFramePadding => 0,
71             noFrameComputeChecksums => 0,
72             noFrameComputeLengths => 0,
73             noObsoleteWarning => 0,
74             doFrameReturnList => 0,
75             doIPv4Checksum => 0,
76             doMemoryOptimizations => 0,
77             err => 0,
78             errString => '',
79             @_,
80             );
81              
82             $self->[$__dev]
83             ? do { $self->[$__dev] = $self->getDevInfoFor($self->[$__dev]) }
84             : do { $self->[$__dev] = $self->getDevInfo };
85              
86             $self->[$__mac] = $self->getMac unless $self->[$__mac];
87             $self->[$__subnet] = $self->getSubnet unless $self->[$__subnet];
88             $self->[$__ip] = $self->getIp unless $self->[$__ip];
89             $self->[$__ip6] = $self->getIp6 unless $self->[$__ip6];
90             $self->[$__gatewayIp] = getGatewayIp() unless $self->[$__gatewayIp];
91              
92             if (! $self->noObsoleteWarning) {
93             print STDERR "*** Net::Packet is obsolete, you will receive no ".
94             "support.\n*** Now use Net::Frame::* modules.\n";
95             }
96              
97             $self;
98             }
99              
100             sub getDevInfo {
101             my $self = shift;
102             # By default, we take outgoing device to Internet
103             $self->[$___dnet] = Net::Libdnet::intf_get_dst(shift() || '1.1.1.1');
104             $self->getDev;
105             }
106              
107             sub getDevInfoFor {
108             my $self = shift;
109             $self->[$___dnet] = Net::Libdnet::intf_get(shift());
110             $self->getDev;
111             }
112              
113             sub updateDevInfo {
114             my $self = shift;
115             my ($ip) = @_;
116             $self->getDevInfo($ip);
117             $self->[$__dev] = $self->getDev;
118             $self->[$__ip] = $self->getIp;
119             $self->[$__ip6] = $self->getIp6;
120             $self->[$__mac] = $self->getMac;
121             $self->[$__subnet] = $self->getSubnet;
122             $self->[$__gatewayIp] = getGatewayIp($ip);
123             }
124              
125             # Thanx to Maddingue
126             sub _toDotQuad {
127             my ($i) = @_;
128             ($i >> 24 & 255).'.'.($i >> 16 & 255).'.'.($i >> 8 & 255).'.'.($i & 255);
129             }
130              
131             sub _getDevWin32 {
132             my $self = shift;
133              
134             croak("@{[(caller(0))[3]]}: unable to find a suitable device\n")
135             unless $self->[$___dnet]->{name};
136              
137             # Get dnet interface name and its subnet
138             my $dnet = $self->[$___dnet]->{name};
139             my $subnet = Net::Libdnet::addr_net($self->[$___dnet]->{addr});
140             croak("@{[(caller(0))[3]]}: Net::Libdnet::addr_net() error\n")
141             unless $subnet;
142              
143             require Net::Pcap;
144             my %dev;
145             my $err;
146             Net::Pcap::findalldevs(\%dev, \$err);
147             croak("@{[(caller(0))[3]]}: Net::Pcap::findalldevs() error: $err\n")
148             if $err;
149              
150             # Search for corresponding WinPcap interface, via subnet value.
151             # I can't use IP address or MAC address, they are not available
152             # through Net::Pcap (as of version 0.15_01).
153             for my $d (keys %dev) {
154             my $net;
155             my $mask;
156             if (Net::Pcap::lookupnet($d, \$net, \$mask, \$err) < 0) {
157             croak("@{[(caller(0))[3]]}: Net::Pcap::lookupnet(): $d: $err\n")
158             }
159             $net = _toDotQuad($net);
160             if ($net eq $subnet) {
161             #print STDERR "[$dnet] => [$d]\n";
162             return $d;
163             }
164             }
165             undef;
166             }
167              
168             sub _getDevOther {
169             shift->[$___dnet]->{name} || (($^O eq 'linux') ? 'lo' : 'lo0');
170             }
171              
172             sub getSubnet {
173             Net::Libdnet::addr_net(shift->[$___dnet]->{addr}) || '127.0.0.0';
174             }
175              
176             sub getMac { shift->[$___dnet]->{link_addr} || 'ff:ff:ff:ff:ff:ff' }
177              
178             sub getIp {
179             my $ip = shift->[$___dnet]->{addr} || '127.0.0.1';
180             $ip =~ s/\/\d+$//;
181             $ip;
182             }
183              
184             sub _getIp6 {
185             my $self = shift;
186             # XXX: No IP6 under Windows for now
187             return '::1' if $^O =~ m/MSWin32|cygwin/i;
188             my $dev = $self->[$__dev];
189             my $mac = $self->[$__mac];
190             my $buf = `/sbin/ifconfig $dev 2> /dev/null`;
191             $buf =~ s/$dev//;
192             $buf =~ s/$mac//i;
193             my ($ip6) = ($buf =~ /((?:[a-f0-9]{1,4}(?::|%|\/){1,2})+)/i); # XXX: better
194             if ($ip6) {
195             $ip6 =~ s/%|\///g;
196             $ip6 = lc($ip6);
197             }
198             ($ip6 && Net::IPv6Addr::ipv6_chkip($ip6) && $ip6) || '::1';
199             }
200              
201             sub getIp6 {
202             my $self = shift;
203             $self->_getIp6($self->[$__dev]);
204             }
205              
206             sub debug {
207             my $self = shift;
208             @_ ? do { $self->[$__debug] = $Class::Gomor::Debug = shift }
209             : $self->[$__debug];
210             }
211              
212             1;
213              
214             =head1 NAME
215              
216             Net::Packet::Env - environment object used for frame capture/injection
217              
218             =head1 SYNOPSIS
219              
220             use Net::Packet::Env qw($Env);
221              
222             # Get default values from system
223             my $env = Net::Packet::Env->new;
224              
225             # Get values from a specific device
226             my $env2 = Net::Packet::Env->new(dev => 'vmnet1');
227              
228             print "dev: ", $env->dev, "\n";
229             print "mac: ", $env->mac, "\n";
230             print "ip : ", $env->ip, "\n" if $env->ip;
231             print "ip6: ", $env->ip6, "\n" if $env->ip6;
232              
233             =head1 DESCRIPTION
234              
235             Basically, this module is used to tell where to inject a frame, and B default behaviour regarding auto creation of B and B objects.
236              
237             =head1 ATTRIBUTES
238              
239             =over 4
240              
241             =item B
242              
243             The device on which frames will be injected.
244              
245             =item B
246              
247             The IPv4 address of B. It will be used by default for all created frames.
248              
249             =item B
250              
251             The IPv6 address of B. It will be used by default for all created frames.
252              
253             =item B
254              
255             The MAC address of B. It will be used by default for all created frames.
256              
257             =item B
258              
259             The subnet address of B. It will be set automatically.
260              
261             =item B
262              
263             The gateway IP address of B. It is set automatically under all platforms.
264              
265             =item B
266              
267             The gateway MAC address of B. It will not be set automatically. Due to the implementation of ARP lookup within B, we can't do it within this module. It is done within B under Windows, to automatically build the layer 2 header.
268              
269             =item B
270              
271             The B object used to inject frames to network.
272              
273             =item B
274              
275             The B object used to receive frames from network.
276              
277             =item B
278              
279             This attribute controls B behaviour regarding B autocreation. If set to 0, when a B is created for the first time, a B object will be created if none has been set in B attribute for default B<$Env> object. Setting it to 1 avoids this behaviour.
280              
281             =item B
282              
283             Same as above, but for B object.
284              
285             =item B
286              
287             This attribute controls B behaviour regarding global B<$Env> autosetting behaviour. If set to 0, when a B is created for the first time, the created B object will have a pointer to it stored in B attribute of B<$Env> default object. Setting it to 1 avoids this behaviour.
288              
289             =item B
290              
291             Same as above, but for B object.
292              
293             =item B
294              
295             By default, when a B object is created from analyzing a raw string (either by taking from B object or from user), padding is achieved to complete the size of 60 bytes. Set this attribute to 1 if you do not want this behaviour.
296              
297             =item B
298              
299             By default, when a B object is created from analyzing a raw string (either by taking from B object or from user), only the first found frame is returned. If you set it to true, an arrayref of B objects will be returned. For example, if you put an IPv6 frame within IPv4, or you get one from network, you will need to use this attribute.
300              
301             =item B
302              
303             =item B
304              
305             By default, when a B object is packed, all layers checksums and lengths are computed (if respective layers implement that). If you want to do it yourself, set this to true. See B for the exception.
306            
307             =item B
308              
309             Do not print the warning about obsolescence of this software.
310              
311             =item B
312              
313             This parameter exists to improve performances of the framework. When you send an IPv4 frame at layer 3 (using a B object), under Unix systems, you MUST not compute IPv4 checksum. The kernel does it. Because this is the more general case (sending IPv4 at layer 3), this parameter is set to false by default. Note: under Windows, because B is a wrapper around B, this parameter will be set to true on B object creation.
314              
315             So, even if you let the framework compute checksums, IPv4 checksum will not be computed. If you want to send IPv4 frames at layer 2, you will need to also set this parameter to true.
316              
317             =item B
318              
319             By default, no memory optimizations are made to improve speed. You can enable those optimizations (mostly done in B) in order to gain ~ 10% in memory, at the cost of ~ 10% in speed.
320              
321             =item B
322              
323             The environment debug directive. Set it to a number greater than 0 to increase the level of debug messages. Up to 3, default 0.
324              
325             =back
326              
327             =head1 METHODS
328              
329             =over 4
330              
331             =item B
332              
333             Object constructor. You can pass attributes that will overwrite default ones. Default values:
334              
335             debug: 0
336              
337             noFrameAutoDesc: 0
338              
339             noFrameAutoDump: 0
340              
341             noDescAutoSet: 0
342              
343             noDumpAutoSet: 0
344              
345             noObsoleteWarning: 0
346              
347             dev: if not user provided, default interface is used, by calling B method. If user provided, all B, B and B attributes will be used for that B.
348              
349             ip: if not user provided, default interface IP is used, by calling B method. If user provided, it is overwritten by the user.
350              
351             ip6: if not user provided, default interface IPv6 is used, by calling B method. If user provided, it is overwritten by the user.
352              
353             mac: if not user provided, default interface MAC is used, by calling B method. If user provided, it is overwritten by the user.
354              
355             =item B [ (scalar) ]
356              
357             By default, network device to use is the one used by default gateway. If you provide an IP address as a parameter, the interface used will be the one which have direct access to this IP address.
358              
359             =item B (scalar)
360              
361             Will set internal attributes for network interface passed as a parameter. Those internal attributes are used to get IP, IPv6 and MAC attributes.
362              
363             =item B (scalar)
364              
365             This is a helper method. You pass an IP address as a parameter, and all attributes for elected network interface will be updated (B, B, B, B, B, B).
366              
367             =item B
368              
369             Returns network interface, by looking at internal attribute.
370              
371             =item B
372              
373             Returns MAC address, by looking at internal attribute.
374              
375             =item B
376              
377             Returns subnet address, by looking at internal attribute.
378              
379             =item B
380              
381             Returns IP address, by looking at internal attribute.
382              
383             =item B
384              
385             Returns IPv6 address, by looking at internal attribute.
386              
387             =back
388              
389             =head1 AUTHOR
390              
391             Patrice EGomoRE Auffret
392              
393             =head1 COPYRIGHT AND LICENSE
394            
395             Copyright (c) 2004-2015, Patrice EGomoRE Auffret
396            
397             You may distribute this module under the terms of the Artistic license.
398             See LICENSE.Artistic file in the source distribution archive.
399            
400             =head1 RELATED MODULES
401            
402             L, L, L
403            
404             =cut