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?, #ipv6_calc_len, #ipv6_calc_sum_on_addr, #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_calc_sum_on_addr, #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.



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

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
62
63
64
# 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
  if IPPacket.can_parse? str
    return true if str[23,1] == "\x11"
  elsif IPv6Packet.can_parse? str
    return true if str[20,1] == "\x11"
  end
  false
end

Instance Method Details

#peek_formatObject

Peek provides summary data on packet contents.



155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/packetfu/protos/udp.rb', line 155

def peek_format
  if self.ipv6?
    peek_data = ["6U "]
    peek_data << "%-5d" % self.to_s.size
    peek_data << "%-31s" % "#{self.ipv6_saddr}:#{self.udp_sport}"
    peek_data << "->"
    peek_data << "%31s" % "#{self.ipv6_daddr}:#{self.udp_dport}"
    peek_data.join
  else
    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
end

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



66
67
68
69
70
71
72
73
74
75
# File 'lib/packetfu/protos/udp.rb', line 66

def read(str=nil, args={})
  super
  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])
    udp_calc_sum
    @ip_header.ip_recalc unless ipv6?
  end
  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.



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
# File 'lib/packetfu/protos/udp.rb', line 103

def udp_calc_sum
  # This is /not/ delegated down to @udp_header since we need info
  # from the IP header, too.
  if @ipv6_header
    checksum = ipv6_calc_sum_on_addr
  else
    checksum = ip_calc_sum_on_addr
  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.


140
141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/packetfu/protos/udp.rb', line 140

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