| Net-Write documentation | Contained in the Net-Write distribution. |
Net::Write::Layer - base class and constants
use Net::Write::Layer qw(:constants);
This is the base class for Net::Write::Layer2, Net::Write::Layer3 and Net::Write::Layer4 modules.
It just provides those layers with inheritable attributes, methods and constants.
Network interface to use.
Target IPv4 or IPv6 address.
Transport layer protocol to use (TCP, UDP, ...).
Adresse family to use (NW_AF_INET, NW_AF_INET6).
Object constructor.
Open the descriptor, when you are ready to send.
Send the raw data passed as a parameter. Returns undef on failure, true otherwise.
Close the descriptor.
Address family constants, for use with family attribute.
Transport layer protocol constants, for use with protocol attribute.
Mostly used internally.
Patrice <GomoR> Auffret
Copyright (c) 2006-2009, Patrice <GomoR> Auffret
You may distribute this module under the terms of the Artistic license. See LICENSE.Artistic file in the source distribution archive.
| Net-Write documentation | Contained in the Net-Write distribution. |
# # $Id: Layer.pm 1636 2009-06-10 18:38:24Z gomor $ # package Net::Write::Layer; use strict; use warnings; require Exporter; require Class::Gomor::Array; our @ISA = qw(Exporter Class::Gomor::Array); our @AS = qw( dev dst protocol family _io _sockaddr ); __PACKAGE__->cgBuildIndices; __PACKAGE__->cgBuildAccessorsScalar(\@AS); sub _setIpProtoIpConstant { my $val = 0; if (defined(&IPPROTO_IP)) { $val = &IPPROTO_IP; } elsif ($^O eq 'darwin' || $^O eq 'linux' || $^O eq 'freebsd' || $^O eq 'openbsd' || $^O eq 'netbsd' || $^O eq 'aix') { $val = 0; } eval "use constant NW_IPPROTO_IP => $val;"; } sub _setIpProtoIpv6Constant { my $val = 0; if (defined(&IPPROTO_IPv6)) { $val = &IPPROTO_IPv6; } elsif ($^O eq 'linux' || $^O eq 'freebsd') { $val = 41; } eval "use constant NW_IPPROTO_IPv6 => $val;"; } sub _setIpProtoRawConstant { my $val = 255; if (defined(&IPPROTO_RAW)) { $val = &IPPROTO_RAW; } elsif ($^O eq 'darwin' || $^O eq 'linux' || $^O eq 'freebsd' || $^O eq 'openbsd' || $^O eq 'netbsd' || $^O eq 'aix') { $val = 255; } eval "use constant NW_IPPROTO_RAW => $val;"; } sub _setIpHdrInclConstant { my $val = 2; if (defined(&IP_HDRINCL)) { $val = &IP_HDRINCL; } elsif ($^O eq 'darwin' || $^O eq 'freebsd' || $^O eq 'openbsd' || $^O eq 'netbsd' || $^O eq 'linux' || $^O eq 'aix' || $^O eq 'cygwin') { $val = 2; } elsif ($^O eq 'hpux') { $val = 0x1002; } eval "use constant NW_IP_HDRINCL => $val;"; } sub _setAfinet6Constant { require Socket6; require Socket; my $val = 0; if (defined(&Socket6::AF_INET6)) { $val = &Socket6::AF_INET6; } elsif (defined(&Socket::AF_INET6)) { $val = &Socket::AF_INET6; } eval "use constant NW_AF_INET6 => $val;"; } BEGIN { my $osname = { cygwin => \&_checkWin32, MSWin32 => \&_checkWin32, }; *_check = $osname->{$^O} || \&_checkOther; _setIpProtoIpConstant(); _setIpProtoIpv6Constant(); _setIpProtoRawConstant(); _setIpHdrInclConstant(); _setAfinet6Constant(); } no strict 'vars'; use Socket; use Socket6 qw(getaddrinfo); use IO::Socket; use Net::Pcap; use Carp; use constant NW_AF_INET => AF_INET(); use constant NW_AF_UNSPEC => AF_UNSPEC(); use constant NW_IPPROTO_ICMPv4 => 1; use constant NW_IPPROTO_TCP => 6; use constant NW_IPPROTO_UDP => 17; use constant NW_IPPROTO_ICMPv6 => 58; our %EXPORT_TAGS = ( constants => [qw( NW_AF_INET NW_AF_INET6 NW_AF_UNSPEC NW_IPPROTO_IP NW_IPPROTO_IPv6 NW_IPPROTO_ICMPv4 NW_IPPROTO_TCP NW_IPPROTO_UDP NW_IPPROTO_ICMPv6 NW_IP_HDRINCL NW_IPPROTO_RAW )], ); our @EXPORT_OK = ( @{$EXPORT_TAGS{constants}}, ); sub _checkWin32 { } sub _checkOther { croak("Must be EUID 0 (or equivalent) to open a device for writing.\n") if $>; } sub new { _check(); shift->SUPER::new(@_) } sub open { my $self = shift; my ($hdrincl) = @_; my @res = getaddrinfo($self->[$__dst], 0, $self->[$__family], SOCK_STREAM) or croak("@{[(caller(0))[3]]}: getaddrinfo: $!\n"); my ($family, $saddr) = @res[0, 3] if @res >= 5; $self->[$___sockaddr] = $saddr; socket(my $s, $family, SOCK_RAW, $self->[$__protocol]) or croak("@{[(caller(0))[3]]}: socket: $!\n"); my $fd = fileno($s) or croak("@{[(caller(0))[3]]}: fileno: $!\n"); if ($hdrincl) { $self->_setIpHdrincl($s, $self->[$__family]) or croak("@{[(caller(0))[3]]}: setsockopt: $!\n"); } my $io = IO::Socket->new; $io->fdopen($fd, 'w') or croak("@{[(caller(0))[3]]}: fdopen: $!\n"); $self->[$___io] = $io; 1; } sub send { my $self = shift; my ($raw) = @_; while (1) { my $ret = CORE::send($self->_io, $raw, 0, $self->_sockaddr); unless ($ret) { if ($!{ENOBUFS}) { $self->cgDebugPrint(2, "ENOBUFS returned, sleeping for 1 second"); sleep 1; next; } elsif ($!{EHOSTDOWN}) { $self->cgDebugPrint(2, "host is down"); last; } carp("@{[(caller(0))[3]]}: $!\n"); return undef; } last; } 1; } sub close { shift->_io->close } 1; __END__