📄 ipv4.pm
字号:
## $Id: IPv4.pm,v 1.3.2.4 2006/06/04 13:36:56 gomor Exp $#package Net::Packet::IPv4;use strict;use warnings;require Net::Packet::Layer3;our @ISA = qw(Net::Packet::Layer3);use Carp;use Net::Packet::Env qw($Env);use Net::Packet::Utils qw(getRandom16bitsInt inetAton inetNtoa inetChecksum);use Net::Packet::Consts qw(:ipv4 :layer);our @AS = qw( id ttl src dst protocol checksum flags offset version tos length hlen options noFixLen doChecksum);__PACKAGE__->cgBuildIndices;__PACKAGE__->cgBuildAccessorsScalar(\@AS); no strict 'vars';BEGIN { my $osname = { freebsd => [ \&_fixLenBsd, undef, ], netbsd => [ \&_fixLenBsd, undef, ], cygwin => [ undef, \&_newWin32, ], MSWin32 => [ undef, \&_newWin32, ], }; *_fixLen = $osname->{$^O}->[0] || \&_fixLenOther; *new = $osname->{$^O}->[1] || \&_newOther;}sub _fixLenBsd { pack('v', shift) }sub _fixLenOther { pack('n', shift) }sub _newWin32 { shift->_newCommon(doChecksum => 1, @_) }sub _newOther { shift->_newCommon(@_) }sub _newCommon { my $self = shift->SUPER::new( version => 4, tos => 0, id => getRandom16bitsInt(), length => 0, hlen => 0, flags => 0, offset => 0, ttl => 128, protocol => NP_IPv4_PROTOCOL_TCP, checksum => 0, src => $Env->ip, dst => '127.0.0.1', options => '', noFixLen => 0, doChecksum => 0, @_, ); unless ($self->[$__raw]) { #燗utocompute header length if not user specified unless ($self->[$__hlen]) { my $hLen = NP_IPv4_HDR_LEN; $hLen += length($self->[$__options]) if $self->[$__options]; $self->[$__hlen] = $hLen / 4; } } $self;}sub pack { my $self = shift; # Thank you Stephanie Wehner my $hlenVer = ($self->[$__hlen] & 0x0f)|(($self->[$__version] << 4) & 0xf0); my $flags = $self->[$__flags]; my $offset = $self->[$__offset]; my $len = ($self->[$__noFixLen] ? _fixLenOther($self->[$__length]) : _fixLen($self->[$__length])); $self->[$__raw] = $self->SUPER::pack('CCa*nnCCna4a4', $hlenVer, $self->[$__tos], $len, $self->[$__id], $flags << 13 | $offset, $self->[$__ttl], $self->[$__protocol], $self->[$__checksum], inetAton($self->[$__src]), inetAton($self->[$__dst]), ) or return undef; my $opt; if ($self->[$__options]) { $opt = $self->SUPER::pack('a*', $self->[$__options]) or return undef; $self->[$__raw] = $self->[$__raw].$opt; } 1;}sub unpack { my $self = shift; my ($verHlen, $tos, $len, $id, $flags, $ttl, $proto, $cksum, $src, $dst, $payload) = $self->SUPER::unpack('CCnnnCCna4a4 a*', $self->[$__raw]) or return undef; $self->[$__version] = ($verHlen & 0xf0) >> 4; $self->[$__hlen] = $verHlen & 0x0f; $self->[$__tos] = $tos; $self->[$__length] = $len; $self->[$__id] = $id; $self->[$__flags] = $flags >> 13; $self->[$__offset] = $flags & 0x1FFF; $self->[$__ttl] = $ttl; $self->[$__protocol] = $proto; $self->[$__checksum] = $cksum; $self->[$__src] = inetNtoa($src); $self->[$__dst] = inetNtoa($dst); $self->[$__payload] = $payload; my ($options, $payload2) = $self->SUPER::unpack( 'a'. $self->getOptionsLength. 'a*', $self->[$__payload] ) or return undef; $self->[$__options] = $options; $self->[$__payload] = $payload2; 1;}sub getLength { my $self = shift; $self->[$__hlen] > 0 ? $self->[$__hlen] * 4 : 0;}sub getHeaderLength { NP_IPv4_HDR_LEN }sub getPayloadLength { my $self = shift; my $gLen = $self->getLength; $self->[$__length] > $gLen ? $self->[$__length] - $gLen : 0;}sub getOptionsLength { my $self = shift; my $gLen = $self->getLength; my $hLen = $self->getHeaderLength; $gLen > $hLen ? $gLen - $hLen : 0;}sub _computeTotalLength { my $self = shift; my $frame = shift; # Do not compute if user specified return if $self->[$__length]; my $total = $self->getLength; $total += $frame->l4->getLength; $total += $frame->l7->getLength if $frame->l7; $self->[$__length] = $total;}sub computeLengths { my $self = shift; my $frame = shift; $frame->l4->computeLengths($frame) or return undef; $self->_computeTotalLength($frame); 1;}sub computeChecksums { my $self = shift; return 1 unless $self->[$__doChecksum]; $self->pack; $self->[$__checksum] = inetChecksum($self->[$__raw]); 1;}sub encapsulate { my $types = { NP_IPv4_PROTOCOL_TCP() => NP_LAYER_TCP(), NP_IPv4_PROTOCOL_UDP() => NP_LAYER_UDP(), NP_IPv4_PROTOCOL_ICMPv4() => NP_LAYER_ICMPv4(), }; $types->{shift->protocol} || NP_LAYER_UNKNOWN();}sub getKey { my $self = shift; $self->is.':'.$self->[$__src].'-'.$self->[$__dst];}sub getKeyReverse { my $self = shift; $self->is.':'.$self->[$__dst].'-'.$self->[$__src];}sub print { my $self = shift; my $i = $self->is; my $l = $self->layer; sprintf "$l:+$i: version:%d id:%.4d ttl:%d [%s => %s]\n". "$l: $i: tos:0x%.2x flags:0x%.2x offset:%d\n". "$l: $i: checksum:0x%.4x protocol:0x%.2x\n". "$l: $i: size:%d length:%d optionsLength:%d payload:%d", $self->[$__version], $self->[$__id], $self->[$__ttl], $self->[$__src], $self->[$__dst], $self->[$__tos], $self->[$__flags], $self->[$__offset], $self->[$__checksum], $self->[$__protocol], $self->[$__length], $self->getLength, $self->getOptionsLength, $self->getPayloadLength, ;}## Helpers#sub _haveFlag { (shift->flags & shift()) ? 1 : 0 }sub haveFlagDf { shift->_haveFlag(NP_IPv4_DONT_FRAGMENT) }sub haveFlagMf { shift->_haveFlag(NP_IPv4_MORE_FRAGMENT) }sub haveFlagRf { shift->_haveFlag(NP_IPv4_RESERVED_FRAGMENT) }sub _isProtocol { shift->protocol == shift() }sub isProtocolTcp { shift->_isProtocol(NP_IPv4_PROTOCOL_TCP) }sub isProtocolUdp { shift->_isProtocol(NP_IPv4_PROTOCOL_UDP) }sub isProtocolIcmpv4 { shift->_isProtocol(NP_IPv4_PROTOCOL_ICMPv4) }1;__END__ =head1 NAMENet::Packet::IPv4 - Internet Protocol v4 layer 3 object=head1 SYNOPSIS use Net::Packet::IPv4; use Net::Packet::Consts qw(:ipv4); #燘uild layer to inject to network my $ip = Net::Packet::IPv4->new( flags => NP_IPv4_DONT_FRAGMENT, dst => "192.168.0.1", ); # Decode from network to create the object # Usually, you do not use this, it is used by Net::Packet::Frame my $ip2 = Net::Packet::IPv4->new(raw => $rawFromNetwork); print $ip->print, "\n";=head1 DESCRIPTIONThis modules implements the encoding and decoding of the IPv4 layer.RFC: ftp://ftp.rfc-editor.org/in-notes/rfc791.txt See also B<Net::Packet::Layer> and B<Net::Packet::Layer3> for other attributes and methods.=head1 ATTRIBUTES=over 4=item B<id>IP ID of the datagram.=item B<ttl>Time to live.=item B<src>=item B<dst>Source and destination IP addresses.=item B<protocol>Of which type the layer 4 is.=item B<checksum>IP checksum.=item B<flags>IP Flags.=item B<offset>IP fragment offset.=item B<version>IP version, here it is 4.=item B<tos>Type of service flag.=item B<length>Total length in bytes of the packet, including IP headers (that is, layer 3 + layer 4 + layer 7).=item B<hlen>Header length in number of words, including IP options.=item B<options>IP options, as a hexadecimal string.=item B<noFixLen>Since the byte ordering of B<length> attribute varies from system to system, a subroutine inside this module detects which byte order to use. Sometimes, like when you build B<Net::Packet::VLAN> layers, you may have the need to avoid this. So set it to 1 in order to avoid fixing. Default is 0 (that is to fix).=item B<doChecksum>Usually the IP checksum is done by the system. But if you inject some frames into network somewhere (well, err...), this checksum could be not computed. So, you can enable it by setting this attribute to 1. Default 0, to let the system compute it.=back=head1 METHODS=over 4=item B<new>Object constructor. You can pass attributes that will overwrite default ones. Default values:version: 4tos: 0id: getRandom16bitsInt()length: 0hlen: 0flags: 0offset: 0ttl: 128protocol: NP_IPv4_PROTOCOL_TCPchecksum: 0src: $Env->ipdst: "127.0.0.1"options: ""noFixLen: 0doChecksum: 0=item B<pack>Packs all attributes into a raw format, in order to inject to network. Returns 1 on success, undef otherwise.=item B<unpack>Unpacks raw data from network and stores attributes into the object. Returns 1 on success, undef otherwise.=item B<getHeaderLength>Returns the header length in bytes, not including IP options.=item B<getPayloadLength>Returns the length in bytes of encapsulated layers (that is, layer 4 + layer 7).=item B<getOptionsLength>Returns the length in bytes of IP options.=item B<haveFlagDf>=item B<haveFlagMf>=item B<haveFlagRf>Returns 1 if the specified flag is set in B<flags> attribute, 0 otherwise.=item B<isProtocolTcp>=item B<isProtocolUdp>=item B<isProtocolIcmpv4>Returns 1 if the specified protocol is used at layer 4, 0 otherwise.=back=head1 CONSTANTSLoad them: use Net::Packet::Consts qw(:ipv4);=over 4=item B<NP_IPv4_PROTOCOL_TCP>=item B<NP_IPv4_PROTOCOL_UDP>=item B<NP_IPv4_PROTOCOL_ICMPv4>Various protocol type constants.=item B<NP_IPv4_MORE_FRAGMENT>=item B<NP_IPv4_DONT_FRAGMENT>=item B<NP_IPv4_RESERVED_FRAGMENT>Various possible flags.=back=head1 AUTHOR Patrice E<lt>GomoRE<gt> Auffret=head1 COPYRIGHT AND LICENSECopyright (c) 2004-2006, Patrice E<lt>GomoRE<gt> Auffret You may distribute this module under the terms of the Artistic license.See LICENSE.Artistic file in the source distribution archive.=head1 RELATED MODULES L<NetPacket>, L<Net::RawIP>, L<Net::RawSock>=cut
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -