def read(io,args={})
begin
if io.size >= 14
@eth_header.read(io)
eth_proto_num = io[12,2].unpack("n")[0]
if eth_proto_num == 0x0800
ip_hlen=(io[14] & 0x0f) * 4
ip_ver=(io[14] >> 4)
if ip_ver == 4
ip_proto_num = io[23,1].unpack("C")[0]
@ip_header.read(io[14,ip_hlen])
if ip_proto_num == 0x06
tcp_len = io[16,2].unpack("n")[0] - 20
if args[:strip]
tcp_all = io[ip_hlen+14,tcp_len]
else
tcp_all = io[ip_hlen+14,0xffff]
end
tcp_hlen = ((tcp_all[12,1].unpack("C")[0]) >> 4) * 4
if tcp_hlen.to_i >= 20
@tcp_header.read(tcp_all)
@ip_header.body = @tcp_header
else
@ip_header.body = io[16,io.size-16]
end
elsif ip_proto_num == 0x11
udp_len = io[16,2].unpack("n")[0] - 20
if args[:strip]
@udp_header.read(io[ip_hlen+14,udp_len])
else
@udp_header.read(io[ip_hlen+14,0xffff])
end
@ip_header.body = @udp_header
elsif ip_proto_num == 1
@icmp_header.read(io[ip_hlen+14,0xffff])
@ip_header.body = @icmp_header
else
@ip_header.body = io[16,io.size-16]
end
else
@ip_header.read(io[14,ip_hlen])
@ip_header.body = io[16,io.size-16]
end
@eth_header.body = @ip_header
elsif eth_proto_num == 0x0806
@arp_header.read(io[14,0xffff])
@eth_header.body=@arp_header
@eth_header.body
elsif eth_proto_num == 0x86dd
@ipv6_header.read(io[14,0xffff])
@eth_header.body=@ipv6_header
else
@eth_header.body = io[14,io.size-14]
end
if (args[:fix] || args[:recalc])
ip_recalc(:ip_sum) if respond_to? :ip_header
recalc(:tcp) if respond_to? :tcp_header
recalc(:udp) if respond_to? :udp_header
end
else
@invalid_header.read(io)
end
self
rescue ::Exception => e
self.headers.pop
return_header_type = self.headers[self.headers.length-1].class.to_s
retklass = PacketFu::InvalidPacket
seekpos = 0
target_header = @invalid_header
case return_header_type.to_s
when "PacketFu::EthHeader"
retklass = PacketFu::EthPacket
seekpos = 0x0e
target_header = @eth_header
when "PacketFu::IPHeader"
retklass = PacketFu::IPPacket
seekpos = 0x0e + @ip_header.ip_hl * 4
target_header = @ip_header
when "PacketFu::TCPHeader"
retklass = PacketFu::TCPPacket
seekpos = 0x0e + @ip_header.ip_hl * 4 + @tcpheader.tcp_hlen
target_header = @tcp_header
when "PacketFu::UDPHeader"
retklass = PacketFu::UDPPacket
when "PacketFu::ARPHeader"
retklass = PacketFu::ARPPacket
when "PacketFu::ICMPHeader"
retklass = PacketFu::ICMPPacket
when "PacketFu::IPv6Header"
retklass = PacketFu::IPv6Packet
else
end
io = io[seekpos,io.length - seekpos]
target_header.body = io
p = retklass.new
p.headers = self.headers
p
raise e if $debug
end
end