Class: PacketFu::UDPPacket

Inherits:
Packet
  • Object
show all
Includes:
EthHeaderMixin, IPHeaderMixin, IPv6HeaderMixin, UDPHeaderMixin
Defined in:
lib/packetfu/protos/udp.rb

Overview

UDPPacket is used to construct UDP Packets. They contain an EthHeader, an IPHeader, and a UDPHeader.

Example

udp_pkt = PacketFu::UDPPacket.new
udp_pkt.udp_src=rand(0xffff-1024) + 1024
udp_pkt.udp_dst=53
udp_pkt.ip_saddr="1.2.3.4"
udp_pkt.ip_daddr="10.20.30.40"
udp_pkt.recalc
udp_pkt.to_f('/tmp/udp.pcap')

udp6_pkt = PacketFu::UDPPacket.new(:on_ipv6 => true)
udp6_pkt.udp_src=rand(0xffff-1024) + 1024
udp6_pkt.udp_dst=53
udp6_pkt.ip6_saddr="4::1"
udp6_pkt.ip6_daddr="12:3::4567"
udp6_pkt.recalc
udp6_pkt.to_f('/tmp/udp.pcap')

Parameters

:eth
  A pre-generated EthHeader object.
:ip
  A pre-generated IPHeader object.
:flavor
  TODO: Sets the "flavor" of the UDP packet. UDP packets don't tend have a lot of
  flavor, but their underlying ip headers do.
:config
 A hash of return address details, often the output of Utils.whoami?

Instance Attribute Summary collapse

Attributes inherited from Packet

#flavor, #headers, #iface, #inspect_style

Class Method Summary collapse

Instance Method Summary collapse

Methods included from UDPHeaderMixin

#udp_calc_len, #udp_dport, #udp_dport=, #udp_dst, #udp_dst=, #udp_len, #udp_len=, #udp_sport, #udp_sport=, #udp_src, #udp_src=, #udp_sum, #udp_sum=, #udp_sum_readable

Methods included from IPv6HeaderMixin

#ipv6_calc_len, #ipv6_class, #ipv6_class=, #ipv6_daddr, #ipv6_daddr=, #ipv6_dst, #ipv6_dst=, #ipv6_dst_readable, #ipv6_hop, #ipv6_hop=, #ipv6_label, #ipv6_label=, #ipv6_len, #ipv6_len=, #ipv6_next, #ipv6_next=, #ipv6_recalc, #ipv6_saddr, #ipv6_saddr=, #ipv6_src, #ipv6_src=, #ipv6_src_readable, #ipv6_v, #ipv6_v=

Methods included from IPHeaderMixin

#ip_calc_id, #ip_calc_len, #ip_calc_sum, #ip_daddr, #ip_daddr=, #ip_dst, #ip_dst=, #ip_dst_readable, #ip_frag, #ip_frag=, #ip_hl, #ip_hl=, #ip_hlen, #ip_id, #ip_id=, #ip_id_readable, #ip_len, #ip_len=, #ip_proto, #ip_proto=, #ip_recalc, #ip_saddr, #ip_saddr=, #ip_src, #ip_src=, #ip_src_readable, #ip_sum, #ip_sum=, #ip_sum_readable, #ip_tos, #ip_tos=, #ip_ttl, #ip_ttl=, #ip_v, #ip_v=

Methods included from EthHeaderMixin

#eth_daddr, #eth_daddr=, #eth_dst, #eth_dst=, #eth_dst_readable, #eth_proto, #eth_proto=, #eth_proto_readable, #eth_saddr, #eth_saddr=, #eth_src, #eth_src=, #eth_src_readable

Methods inherited from Packet

#==, #clone, #dissect, #dissection_table, force_binary, #handle_is_identity, #hexify, inherited, #inspect, #inspect_hex, #kind_of?, #layer, layer, layer_symbol, #layer_symbol, #method_missing, #orig_kind_of?, parse, #payload, #payload=, #peek, #proto, #recalc, #respond_to?, #size, #to_f, #to_pcap, #to_s, #to_w, #write

Constructor Details

#initialize(args = {}) ⇒ UDPPacket

Returns a new instance of UDPPacket.


74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/packetfu/protos/udp.rb', line 74

def initialize(args={})
  if args[:on_ipv6] or args[:ipv6]
    @eth_header = EthHeader.new(args.merge(:eth_proto => 0x86dd)).read(args[:eth])
    @ipv6_header = IPv6Header.new(args).read(args[:ipv6])
    @ipv6_header.ipv6_next=0x11
  else
    @eth_header = EthHeader.new(args).read(args[:eth])
    @ip_header = IPHeader.new(args).read(args[:ip])
    @ip_header.ip_proto=0x11
  end
  @udp_header = UDPHeader.new(args).read(args[:udp])
  if args[:on_ipv6] or args[:ipv6]
    @ipv6_header.body = @udp_header
    @eth_header.body = @ipv6_header
    @headers = [@eth_header, @ipv6_header, @udp_header]
  else
    @ip_header.body = @udp_header
    @eth_header.body = @ip_header
    @headers = [@eth_header, @ip_header, @udp_header]
  end
  super
  udp_calc_sum
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class PacketFu::Packet

Instance Attribute Details

#eth_headerObject

Returns the value of attribute eth_header


53
54
55
# File 'lib/packetfu/protos/udp.rb', line 53

def eth_header
  @eth_header
end

#ip_headerObject

Returns the value of attribute ip_header


53
54
55
# File 'lib/packetfu/protos/udp.rb', line 53

def ip_header
  @ip_header
end

#ipv6_headerObject

Returns the value of attribute ipv6_header


53
54
55
# File 'lib/packetfu/protos/udp.rb', line 53

def ipv6_header
  @ipv6_header
end

#udp_headerObject

Returns the value of attribute udp_header


53
54
55
# File 'lib/packetfu/protos/udp.rb', line 53

def udp_header
  @udp_header
end

Class Method Details

.can_parse?(str) ⇒ Boolean

Returns:

  • (Boolean)

55
56
57
58
59
60
61
# File 'lib/packetfu/protos/udp.rb', line 55

def self.can_parse?(str)
  return false unless str.size >= 28
  return false unless EthPacket.can_parse? str
  return false unless IPPacket.can_parse? str
  return false unless str[23,1] == "\x11"
  return true
end

Instance Method Details

#ipv6?Boolean

Is that packet an UDP on IPv6 packet ?

Returns:

  • (Boolean)

171
172
173
# File 'lib/packetfu/protos/udp.rb', line 171

def ipv6?
  @ipv6_header
end

#peek_formatObject

Peek provides summary data on packet contents.


159
160
161
162
163
164
165
166
167
168
# File 'lib/packetfu/protos/udp.rb', line 159

def peek_format
  peek_data = ["U  "]
  peek_data << "%-5d" % self.to_s.size
  peek_data << "%-21s" % "#{self.ip_saddr}:#{self.udp_sport}"
  peek_data << "->"
  peek_data << "%21s" % "#{self.ip_daddr}:#{self.udp_dport}"
  peek_data << "%23s" % "I:"
  peek_data << "%04x" % self.ip_id
  peek_data.join
end

#read(str = nil, args = {}) ⇒ Object


63
64
65
66
67
68
69
70
71
72
# File 'lib/packetfu/protos/udp.rb', line 63

def read(str=nil, args={})
  raise "Cannot parse `#{str}'" unless self.class.can_parse?(str)
  @eth_header.read(str)
  if args[:strip]
    udp_body_len = self.ip_len - self.ip_hlen - 8
    @udp_header.body.read(@udp_header.body.to_s[0,udp_body_len])
  end
  super(args)
  self
end

#udp_calc_sumObject

udp_calc_sum() computes the UDP checksum, and is called upon intialization. It usually should be called just prior to dropping packets to a file or on the wire.


100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/packetfu/protos/udp.rb', line 100

def udp_calc_sum
  # This is /not/ delegated down to @udp_header since we need info
  # from the IP header, too.
  checksum = 0
  if @ipv6_header
    [ipv6_src, ipv6_dst].each do |iaddr|
      8.times do |i|
        checksum += (iaddr >> (i * 16)) & 0xffff
      end
    end
  else
    checksum += (ip_src.to_i >> 16)
    checksum += (ip_src.to_i & 0xffff)
    checksum += (ip_dst.to_i >> 16)
    checksum += (ip_dst.to_i & 0xffff)
  end
  checksum += 0x11
  checksum += udp_len.to_i
  checksum += udp_src.to_i
  checksum += udp_dst.to_i
  checksum += udp_len.to_i
  if udp_len.to_i >= 8
    # For IP trailers. This isn't very reliable. :/
    real_udp_payload = payload.to_s[0,(udp_len.to_i-8)] 
  else
    # I'm not going to mess with this right now.
    real_udp_payload = payload 
  end
  chk_payload = (real_udp_payload.size % 2 == 0 ? real_udp_payload : real_udp_payload + "\x00")
  chk_payload.unpack("n*").each {|x| checksum = checksum+x}
  checksum = checksum % 0xffff
  checksum = 0xffff - checksum
  checksum == 0 ? 0xffff : checksum
  @udp_header.udp_sum = checksum
end

#udp_recalc(args = :all) ⇒ Object

udp_recalc() recalculates various fields of the UDP packet. Valid arguments are:

:all
  Recomputes all calculated fields.
:udp_sum
  Recomputes the UDP checksum.
:udp_len
  Recomputes the UDP length.

144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/packetfu/protos/udp.rb', line 144

def udp_recalc(args=:all)
  case args
  when :udp_len
    @udp_header.udp_recalc
  when :udp_sum
    udp_calc_sum
  when :all
    @udp_header.udp_recalc
    udp_calc_sum
  else
    raise ArgumentError, "No such field `#{arg}'"
  end
end