class PacketGen::Header::TFTP
A TFTP
(Trivial File Transfer Protocol, {tools.ietf.org/html/rfc1350 RFC 1350}) header consists of:
-
a {#opcode} ({Types::Int16Enum}),
-
and a body. Its content depends on opcode.
Specialized subclasses exists to handle {TFTP::RRQ Read Request}, {TFTP::WRQ Write Request}, {TFTP::DATA DATA}, {TFTP::ACK ACK} and {TFTP::ERROR ERROR} packets.
Create a TFTP
header¶ ↑
# standalone tftp = PacketGen::Header::TFTP.new # in a packet pkt = PacketGen.gen('IP').add('UDP').add('TFTP') # access to TFTP header pkt.tftp # => PacketGen::Header::TFTP
TFTP
attributes¶ ↑
tftp.opcode = 'RRQ' tftp.opcode = 1 tftp.body.read 'this is a body'
TFTP
parsing¶ ↑
When parsing, only first packet (read or write request) should be decoded as TFTP
packet, as others uses custom UDP
ports.
So, to decode subsequent TFTP
packets, a method {#decode!} is provided for this purpose. This method takes a single array argument. This array should contain all subsequent TFTP
packets (others packet types may also be included in this array: they won't be modified). #decode!
will modify array in-place by replacing UDP
packets by TFTP
ones (if decoded as TFTP
packets):
# packets is an array of packets: TFTP::RRQ, UDP (should be TFTP::DATA), UDP (not a TFTP packet) and UDP (TFTP::ACK) packets.map { |pkt| pkt.headers.last.class.to_s }.join(',') # => TFTP::RRQ,UDP,UDP,UDP # Here, decoding TFTP packets packets[0].tftp.decode!(packets[1..-1]) packets.map { |pkt| pkt.headers.last.class.to_s }.join(',') # => TFTP::RRQ,TFTP::DATA,UDP,TFTP::ACK
@author Sylvain Daubert @since 2.3.0
Constants
- OPCODES
Known opcodes
Public Class Methods
PacketGen::Header::Base::new
# File lib/packetgen/header/tftp.rb, line 68 def initialize(options={}) type = protocol_name.sub(/^.*::/, '') opcode = OPCODES[type] if (self.class != TFTP) && !opcode.nil? super({ opcode: opcode }.merge(options)) else super end end
Public Instance Methods
Callback called when a TFTP
header is added to a packet Here, add #tftp
method as a shortcut to existing +#tftp(rrq|wrq|data|ack|error)+. @param [Packet] packet @return [void]
# File lib/packetgen/header/tftp.rb, line 135 def added_to_packet(packet) return if packet.respond_to? :tftp packet.instance_eval("def tftp(arg=nil); header(#{self.class}, arg); end") end
Decode subsequent TFTP
packets to this one. Packets are modified in place in ary
. @param [Array<Packet>] ary @return [void]
# File lib/packetgen/header/tftp.rb, line 101 def decode!(ary) client_tid = packet.udp.sport server_tid = nil ary.each do |pkt| if server_tid.nil? next unless pkt.is?('UDP') && (pkt.udp.dport == client_tid) server_tid = pkt.udp.sport else next unless pkt.is?('UDP') tids = [server_tid, client_tid] ports = [pkt.udp.sport, pkt.udp.dport] next unless (tids - ports).empty? end tftp = Packet.parse(pkt.body, first_header: 'TFTP') udp_dport = pkt.udp.dport pkt.encapsulate tftp # need to fix it as #encapsulate force it to 69 pkt.udp.dport = udp_dport end end
Get human readable opcode @return [String]
# File lib/packetgen/header/tftp.rb, line 126 def human_opcode self[:opcode].to_human end
Populate object from binary string @param [String] str @return [TFTP]
PacketGen::Headerable#read
# File lib/packetgen/header/tftp.rb, line 84 def read(str) if self.instance_of? TFTP super if OPCODES.value? opcode TFTP.const_get(human_opcode).new.read str else self end else old_read str end end