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.
Attributes inherited from Base
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, bind_header, calculate_and_set_length, #header_id, inherited, #ip_header, known_headers, #ll_header, #method_name, #parse?, #protocol_name, protocol_name
Methods inherited from Types::Fields
#[], #[]=, #bits_on, define_bit_fields_on, define_field, define_field_after, define_field_before, delete_field, fields, #fields, #force_binary, inherited, #inspect, #is_optional?, #is_present?, #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
#body ⇒ String
66 |
# File 'lib/packetgen/header/tftp.rb', line 66 define_field :body, Types::String |
#opcode ⇒ Integer
16-bit operation code
62 |
# File 'lib/packetgen/header/tftp.rb', line 62 define_field :opcode, Types::Int16Enum, enum: OPCODES |
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).
133 134 135 136 |
# File 'lib/packetgen/header/tftp.rb', line 133 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 |
# 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
124 125 126 |
# File 'lib/packetgen/header/tftp.rb', line 124 def human_opcode self[:opcode].to_human end |
#old_read ⇒ Object
79 |
# File 'lib/packetgen/header/tftp.rb', line 79 alias old_read read |
#read(str) ⇒ TFTP
Populate object from binary string
84 85 86 87 88 89 90 91 92 93 94 95 |
# 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 |