Class: PacketGen::Header::TCP

Inherits:
Base show all
Defined in:
lib/packetgen/header/tcp.rb,
lib/packetgen/header/tcp.rb,
lib/packetgen/header/tcp/option.rb,
lib/packetgen/header/tcp/options.rb

Overview

A TCP header consists of:

Create a TCP header

# standalone
tcph = PacketGen::Header::TCP.new
# in a IP packet
pkt = PacketGen.gen('IP').add('TCP')
# access to TCP header
pkt.tcp   # => PacketGen::Header::TCP

TCP attributes

tcph.sport = 4500
tcph.dport = 80
tcph.seqnum = 43
tcph.acknum = 0x45678925
tcph.wsize = 0x240
tcph.urg_pointer = 0x40
tcph.body.read 'this is a body'

Flags

TCP flags may be accesed as a 9-bit integer:

tcph.flags = 0x1002

Each flag may be accessed independently:

tcph.flag_syn?    # => Boolean
tcph.flag_rst = true

Options

#options TCP attribute is a Options. Option may added to it:

tcph.options << PacketGen::Header::TCP::MSS.new(1250)

or:

tcph.options << { opt: 'MSS', value: 1250 }

Author:

  • Sylvain Daubert

Defined Under Namespace

Classes: ECHO, ECHOREPLY, EOL, MSS, NOP, Option, Options, SACK, SACKOK, TS, WS

Constant Summary collapse

IP_PROTOCOL =

IP protocol number for TCP

6

Instance Attribute Summary collapse

Attributes inherited from Base

#packet

Instance Method Summary collapse

Methods inherited from Base

bind_header, #header_id, inherited, #ip_header, known_headers, #parse?, #protocol_name

Methods inherited from Types::Fields

#[], #[]=, define_bit_fields_on, define_field, define_field_after, define_field_before, #fields, #force_binary, inherited, #sz, #to_h, #to_s

Constructor Details

#initialize(options = {}) ⇒ TCP

Call {Base#initialize), then handle specific options to set u16 by part:

  • :data_offset

  • :hlen

  • :reserved

  • :flags

Parameters:

  • options (Hash) (defaults to: {})

Options Hash (options):

  • :sport (Integer)
  • :dport (Integer)
  • :seqnum (Integer)
  • :acknum (Integer)
  • :data_offset (Integer)
  • :reserved (Integer)
  • :flags (Integer)
  • :window (Integer)
  • :checksum (Integer)
  • :urg_pointer (Integer)
  • :body (String)


131
132
133
134
# File 'lib/packetgen/header/tcp.rb', line 131

def initialize(options={})
  opts = { data_offset: 5 }.merge!(options)
  super(opts)
end

Instance Attribute Details

#acknumInteger Also known as: acknowledgement_number

32-bit TCP acknowledgement number

Returns:

  • (Integer)


79
# File 'lib/packetgen/header/tcp.rb', line 79

define_field :acknum, Types::Int32

#bodyTypes::String, Header::Base



101
# File 'lib/packetgen/header/tcp.rb', line 101

define_field :body, Types::String

#checksumInteger

16-bit TCP checksum

Returns:

  • (Integer)


90
# File 'lib/packetgen/header/tcp.rb', line 90

define_field :checksum, Types::Int16

#data_offsetInteger Also known as: hlen

Returns 4-bit data offset from #u16.

Returns:

  • (Integer)

    4-bit data offset from #u16



142
# File 'lib/packetgen/header/tcp.rb', line 142

define_bit_fields_on :u16, :data_offset, 4, :reserved, 3, :flags, 9

#dportInteger Also known as: destination_port

16-bit TCP destination port

Returns:

  • (Integer)


71
# File 'lib/packetgen/header/tcp.rb', line 71

define_field :dport, Types::Int16

#flag_ackBoolean

Returns 1-bit ACK flag.

Returns:

  • (Boolean)

    1-bit ACK flag



164
165
# File 'lib/packetgen/header/tcp.rb', line 164

define_bit_fields_on :u16, :_, 7, :flag_ns, :flag_cwr, :flag_ece, :flag_urg,
:flag_ack, :flag_psh, :flag_rst, :flag_syn, :flag_fin

#flag_cwrBoolean

Returns 1-bit CWR flag.

Returns:

  • (Boolean)

    1-bit CWR flag



164
165
# File 'lib/packetgen/header/tcp.rb', line 164

define_bit_fields_on :u16, :_, 7, :flag_ns, :flag_cwr, :flag_ece, :flag_urg,
:flag_ack, :flag_psh, :flag_rst, :flag_syn, :flag_fin

#flag_eceBoolean

Returns 1-bit ECE flag.

Returns:

  • (Boolean)

    1-bit ECE flag



164
165
# File 'lib/packetgen/header/tcp.rb', line 164

define_bit_fields_on :u16, :_, 7, :flag_ns, :flag_cwr, :flag_ece, :flag_urg,
:flag_ack, :flag_psh, :flag_rst, :flag_syn, :flag_fin

#flag_finBoolean

Returns 1-bit FIN flag.

Returns:

  • (Boolean)

    1-bit FIN flag



164
165
# File 'lib/packetgen/header/tcp.rb', line 164

define_bit_fields_on :u16, :_, 7, :flag_ns, :flag_cwr, :flag_ece, :flag_urg,
:flag_ack, :flag_psh, :flag_rst, :flag_syn, :flag_fin

#flag_nsBoolean

Returns 1-bit NS flag.

Returns:

  • (Boolean)

    1-bit NS flag



164
165
# File 'lib/packetgen/header/tcp.rb', line 164

define_bit_fields_on :u16, :_, 7, :flag_ns, :flag_cwr, :flag_ece, :flag_urg,
:flag_ack, :flag_psh, :flag_rst, :flag_syn, :flag_fin

#flag_pshBoolean

Returns 1-bit PSH flag.

Returns:

  • (Boolean)

    1-bit PSH flag



164
165
# File 'lib/packetgen/header/tcp.rb', line 164

define_bit_fields_on :u16, :_, 7, :flag_ns, :flag_cwr, :flag_ece, :flag_urg,
:flag_ack, :flag_psh, :flag_rst, :flag_syn, :flag_fin

#flag_rstBoolean

Returns 1-bit RST flag.

Returns:

  • (Boolean)

    1-bit RST flag



164
165
# File 'lib/packetgen/header/tcp.rb', line 164

define_bit_fields_on :u16, :_, 7, :flag_ns, :flag_cwr, :flag_ece, :flag_urg,
:flag_ack, :flag_psh, :flag_rst, :flag_syn, :flag_fin

#flag_synBoolean

Returns 1-bit SYN flag.

Returns:

  • (Boolean)

    1-bit SYN flag



164
165
# File 'lib/packetgen/header/tcp.rb', line 164

define_bit_fields_on :u16, :_, 7, :flag_ns, :flag_cwr, :flag_ece, :flag_urg,
:flag_ack, :flag_psh, :flag_rst, :flag_syn, :flag_fin

#flag_urgBoolean

Returns 1-bit URG flag.

Returns:

  • (Boolean)

    1-bit URG flag



164
165
# File 'lib/packetgen/header/tcp.rb', line 164

define_bit_fields_on :u16, :_, 7, :flag_ns, :flag_cwr, :flag_ece, :flag_urg,
:flag_ack, :flag_psh, :flag_rst, :flag_syn, :flag_fin

#flagsInteger

Returns 9-bit flags from #u16.

Returns:

  • (Integer)

    9-bit flags from #u16



142
# File 'lib/packetgen/header/tcp.rb', line 142

define_bit_fields_on :u16, :data_offset, 4, :reserved, 3, :flags, 9

#optionsOptions

TCP options

Returns:



98
# File 'lib/packetgen/header/tcp.rb', line 98

define_field :options, TCP::Options

#reservedInteger

Returns 3-bit reserved from #u16.

Returns:

  • (Integer)

    3-bit reserved from #u16



142
# File 'lib/packetgen/header/tcp.rb', line 142

define_bit_fields_on :u16, :data_offset, 4, :reserved, 3, :flags, 9

#seqnumInteger Also known as: sequence_number

32-bit TCP sequence number

Returns:

  • (Integer)


75
# File 'lib/packetgen/header/tcp.rb', line 75

define_field :seqnum, Types::Int32, default: -> { rand(2**32) }

#sportInteger Also known as: source_port

16-bit TCP source port

Returns:

  • (Integer)


67
# File 'lib/packetgen/header/tcp.rb', line 67

define_field :sport, Types::Int16

#u16Integer

Returns 16-bit word used by flags and bit fields.

Returns:

  • (Integer)

    16-bit word used by flags and bit fields



82
# File 'lib/packetgen/header/tcp.rb', line 82

define_field :u16, Types::Int16

#urg_pointerInteger

16-bit TCP urgent data pointer

Returns:

  • (Integer)


94
# File 'lib/packetgen/header/tcp.rb', line 94

define_field :urg_pointer, Types::Int16

#windowInteger Also known as: wsize

16-bit TCP window size

Returns:

  • (Integer)


86
# File 'lib/packetgen/header/tcp.rb', line 86

define_field :window, Types::Int16

Instance Method Details

#calc_checksumInteger

Compute checksum and set checksum field

Returns:

  • (Integer)


187
188
189
190
191
192
193
194
195
196
197
198
199
200
# File 'lib/packetgen/header/tcp.rb', line 187

def calc_checksum
  sum = ip_header(self).pseudo_header_checksum
  sum += IP_PROTOCOL
  sum += self.sz
  str = self.to_s
  str << "\x00" if str.length % 2 == 1
  sum += str.unpack('n*').reduce(:+)

  while sum > 0xffff do
    sum = (sum & 0xffff) + (sum >> 16)
  end
  sum = ~sum & 0xffff
  self[:checksum].value = (sum == 0) ? 0xffff : sum
end

#calc_lengthInteger

Compute header length and set data_offset field

Returns:

  • (Integer)


204
205
206
# File 'lib/packetgen/header/tcp.rb', line 204

def calc_length
  self[:data_offset] = 5 + self[:options].sz / 4
end

#inspectString

Returns:

  • (String)


212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
# File 'lib/packetgen/header/tcp.rb', line 212

def inspect
  str = Inspect.dashed_line(self.class, 2)
  shift = Inspect.shift_level(2)
  to_h.each do |attr, value|
    next if attr == :body
    str << Inspect.inspect_attribute(attr, value, 2)
    if attr == :u16
      doff = Inspect.int_dec_hex(data_offset, 1)
      str << shift + Inspect::INSPECT_FMT_ATTR % ['', 'data_offset', doff]
      str << shift + Inspect::INSPECT_FMT_ATTR % ['', 'reserved', reserved]
      flags = ''
      %w(ns cwr ece urg ack psh rst syn fin).each do |fl|
        flags << (send("flag_#{fl}?") ? fl[0].upcase : '.')
      end
      str << shift + Inspect::INSPECT_FMT_ATTR % ['', 'flags', flags]
    end
  end
  str
end

#read(str) ⇒ self

Read a TCP header from a string

Parameters:

  • str (String)

    binary string

Returns:

  • (self)


169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# File 'lib/packetgen/header/tcp.rb', line 169

def read(str)
  return self if str.nil?
  force_binary str
  self[:sport].read str[0, 2]
  self[:dport].read str[2, 2]
  self[:seqnum].read str[4, 4]
  self[:acknum].read str[8, 4]
  self[:u16].read str[12, 2]
  self[:window].read str[14, 2]
  self[:checksum].read str[16, 2]
  self[:urg_pointer].read str[18, 2]
  self[:options].read str[20, (self.data_offset - 5) * 4] if self.data_offset > 5
  self[:body].read str[self.data_offset * 4..-1]
  self
end