Class: PacketGen::Header::TFTP
- Inherits:
-
Base
- Object
- Types::Fields
- Base
- PacketGen::Header::TFTP
- Defined in:
- lib/packetgen/header/tftp.rb
Overview
A TFTP (Trivial File Transfer Protocol, RFC 1350) header consists of:
-
a #opcode (Types::Int16Enum),
-
and a body. Its content depends on opcode.
Specialized subclasses exists to handle Read Request, Write Request, DATA, ACK and 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
Defined Under Namespace
Classes: ACK, DATA, ERROR, RRQ, WRQ
Constant Summary collapse
- OPCODES =
Known opcodes
{ 'RRQ' => 1, 'WRQ' => 2, 'DATA' => 3, 'ACK' => 4, 'Error' => 5 }.freeze
Instance Attribute Summary collapse
- #body ⇒ String
-
#opcode ⇒ Integer
16-bit operation code.
Instance Method Summary collapse
-
#added_to_packet(packet) ⇒ void
Callback called when a TFTP header is added to a packet Here, add
#tftpmethod as a shortcut to existing #tftp(rrq|wrq|data|ack|error). -
#decode!(ary) ⇒ void
Decode subsequent TFTP packets to this one.
-
#human_opcode ⇒ String
Get human readable opcode.
-
#initialize(options = {}) ⇒ TFTP
constructor
A new instance of TFTP.
- #old_read ⇒ Object
-
#read(str) ⇒ TFTP
Populate object from binary string.
Methods inherited from Base
bind, calculate_and_set_length, #header_id, inherited, #ip_header, known_headers, #ll_header
Methods included from PacketGen::Headerable
included, #method_name, #packet, #packet=, #parse?, #protocol_name
Methods inherited from Types::Fields
#[], #[]=, #bits_on, define_bit_fields_on, define_field, define_field_after, define_field_before, #fields, fields, inherited, #inspect, #offset_of, #optional?, #optional_fields, #present?, remove_bit_fields_on, remove_field, #sz, #to_h, #to_s, update_field
Constructor Details
#initialize(options = {}) ⇒ TFTP
Returns a new instance of TFTP.
68 69 70 71 72 73 74 75 76 |
# File 'lib/packetgen/header/tftp.rb', line 68 def initialize(={}) type = protocol_name.sub(/^.*::/, '') opcode = OPCODES[type] if (self.class != TFTP) && !opcode.nil? super({ opcode: opcode }.merge()) else super end end |
Instance Attribute Details
Instance Method Details
#added_to_packet(packet) ⇒ void
This method returns an undefined value.
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).
135 136 137 138 139 |
# 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!(ary) ⇒ void
This method returns an undefined value.
Decode subsequent TFTP packets to this one. Packets are modified in place in ary.
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
# 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 |
#human_opcode ⇒ String
Get human readable opcode
126 127 128 |
# File 'lib/packetgen/header/tftp.rb', line 126 def human_opcode self[:opcode].to_human end |
#old_read ⇒ Object
79 |
# File 'lib/packetgen/header/tftp.rb', line 79 alias old_read read |