packetfu 1.1.9 → 1.1.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. data/bench/octets.rb +9 -9
  2. data/examples/100kpackets.rb +12 -12
  3. data/examples/ackscan.rb +16 -16
  4. data/examples/arp.rb +35 -35
  5. data/examples/arphood.rb +36 -36
  6. data/examples/dissect_thinger.rb +6 -6
  7. data/examples/new-simple-stats.rb +23 -23
  8. data/examples/packetfu-shell.rb +25 -25
  9. data/examples/simple-sniffer.rb +9 -9
  10. data/examples/simple-stats.rb +23 -23
  11. data/examples/slammer.rb +3 -3
  12. data/lib/packetfu.rb +127 -127
  13. data/lib/packetfu/capture.rb +169 -169
  14. data/lib/packetfu/config.rb +52 -52
  15. data/lib/packetfu/inject.rb +56 -56
  16. data/lib/packetfu/packet.rb +528 -528
  17. data/lib/packetfu/pcap.rb +579 -579
  18. data/lib/packetfu/protos/arp.rb +90 -90
  19. data/lib/packetfu/protos/arp/header.rb +158 -158
  20. data/lib/packetfu/protos/arp/mixin.rb +36 -36
  21. data/lib/packetfu/protos/eth.rb +44 -44
  22. data/lib/packetfu/protos/eth/header.rb +243 -243
  23. data/lib/packetfu/protos/eth/mixin.rb +3 -3
  24. data/lib/packetfu/protos/hsrp.rb +69 -69
  25. data/lib/packetfu/protos/hsrp/header.rb +107 -107
  26. data/lib/packetfu/protos/hsrp/mixin.rb +29 -29
  27. data/lib/packetfu/protos/icmp.rb +71 -71
  28. data/lib/packetfu/protos/icmp/header.rb +82 -82
  29. data/lib/packetfu/protos/icmp/mixin.rb +14 -14
  30. data/lib/packetfu/protos/invalid.rb +49 -49
  31. data/lib/packetfu/protos/ip.rb +69 -69
  32. data/lib/packetfu/protos/ip/header.rb +291 -291
  33. data/lib/packetfu/protos/ip/mixin.rb +40 -40
  34. data/lib/packetfu/protos/ipv6.rb +50 -50
  35. data/lib/packetfu/protos/ipv6/header.rb +188 -188
  36. data/lib/packetfu/protos/ipv6/mixin.rb +29 -29
  37. data/lib/packetfu/protos/tcp.rb +176 -176
  38. data/lib/packetfu/protos/tcp/ecn.rb +35 -35
  39. data/lib/packetfu/protos/tcp/flags.rb +74 -74
  40. data/lib/packetfu/protos/tcp/header.rb +268 -268
  41. data/lib/packetfu/protos/tcp/hlen.rb +32 -32
  42. data/lib/packetfu/protos/tcp/mixin.rb +46 -46
  43. data/lib/packetfu/protos/tcp/option.rb +321 -321
  44. data/lib/packetfu/protos/tcp/options.rb +95 -95
  45. data/lib/packetfu/protos/tcp/reserved.rb +35 -35
  46. data/lib/packetfu/protos/udp.rb +116 -116
  47. data/lib/packetfu/protos/udp/header.rb +91 -91
  48. data/lib/packetfu/protos/udp/mixin.rb +3 -3
  49. data/lib/packetfu/structfu.rb +280 -280
  50. data/lib/packetfu/utils.rb +226 -217
  51. data/lib/packetfu/version.rb +41 -41
  52. data/packetfu.gemspec +2 -1
  53. data/spec/ethpacket_spec.rb +48 -48
  54. data/spec/packet_spec.rb +57 -57
  55. data/spec/packet_subclasses_spec.rb +8 -8
  56. data/spec/packetfu_spec.rb +59 -59
  57. data/spec/structfu_spec.rb +268 -268
  58. data/spec/tcp_spec.rb +75 -75
  59. data/test/all_tests.rb +13 -13
  60. data/test/func_lldp.rb +3 -3
  61. data/test/ptest.rb +2 -2
  62. data/test/test_arp.rb +116 -116
  63. data/test/test_capture.rb +45 -45
  64. data/test/test_eth.rb +68 -68
  65. data/test/test_hsrp.rb +9 -9
  66. data/test/test_icmp.rb +52 -52
  67. data/test/test_inject.rb +18 -18
  68. data/test/test_invalid.rb +16 -16
  69. data/test/test_ip.rb +36 -36
  70. data/test/test_ip6.rb +48 -48
  71. data/test/test_octets.rb +21 -21
  72. data/test/test_packet.rb +154 -154
  73. data/test/test_pcap.rb +170 -170
  74. data/test/test_structfu.rb +97 -97
  75. data/test/test_tcp.rb +320 -320
  76. data/test/test_udp.rb +76 -76
  77. metadata +4 -3
@@ -1,44 +1,44 @@
1
1
  # -*- coding: binary -*-
2
2
 
3
3
  module PacketFu
4
- # This Mixin simplifies access to the IPHeaders. Mix this in with your
5
- # packet interface, and it will add methods that essentially delegate to
6
- # the 'ip_header' method (assuming that it is a IPHeader object)
7
- module IPHeaderMixin
8
- def ip_calc_id; self.ip_header.ip_calc_id ; end
9
- def ip_calc_len; self.ip_header.ip_calc_len ; end
10
- def ip_calc_sum; self.ip_header.ip_calc_sum ; end
11
- def ip_daddr; self.ip_header.ip_daddr ; end
12
- def ip_daddr=(v); self.ip_header.ip_daddr= v; end
13
- def ip_dst; self.ip_header.ip_dst ; end
14
- def ip_dst=(v); self.ip_header.ip_dst= v; end
15
- def ip_dst_readable; self.ip_header.ip_dst_readable ; end
16
- def ip_frag; self.ip_header.ip_frag ; end
17
- def ip_frag=(v); self.ip_header.ip_frag= v; end
18
- def ip_hl; self.ip_header.ip_hl ; end
19
- def ip_hl=(v); self.ip_header.ip_hl= v; end
20
- def ip_hlen; self.ip_header.ip_hlen ; end
21
- def ip_id; self.ip_header.ip_id ; end
22
- def ip_id=(v); self.ip_header.ip_id= v; end
23
- def ip_id_readable; self.ip_header.ip_id_readable ; end
24
- def ip_len; self.ip_header.ip_len ; end
25
- def ip_len=(v); self.ip_header.ip_len= v; end
26
- def ip_proto; self.ip_header.ip_proto ; end
27
- def ip_proto=(v); self.ip_header.ip_proto= v; end
28
- def ip_recalc(*args); self.ip_header.ip_recalc(*args) ; end
29
- def ip_saddr; self.ip_header.ip_saddr ; end
30
- def ip_saddr=(v); self.ip_header.ip_saddr= v; end
31
- def ip_src; self.ip_header.ip_src ; end
32
- def ip_src=(v); self.ip_header.ip_src= v; end
33
- def ip_src_readable; self.ip_header.ip_src_readable ; end
34
- def ip_sum; self.ip_header.ip_sum ; end
35
- def ip_sum=(v); self.ip_header.ip_sum= v; end
36
- def ip_sum_readable; self.ip_header.ip_sum_readable ; end
37
- def ip_tos; self.ip_header.ip_tos ; end
38
- def ip_tos=(v); self.ip_header.ip_tos= v; end
39
- def ip_ttl; self.ip_header.ip_ttl ; end
40
- def ip_ttl=(v); self.ip_header.ip_ttl= v; end
41
- def ip_v; self.ip_header.ip_v ; end
42
- def ip_v=(v); self.ip_header.ip_v= v; end
43
- end
4
+ # This Mixin simplifies access to the IPHeaders. Mix this in with your
5
+ # packet interface, and it will add methods that essentially delegate to
6
+ # the 'ip_header' method (assuming that it is a IPHeader object)
7
+ module IPHeaderMixin
8
+ def ip_calc_id; self.ip_header.ip_calc_id ; end
9
+ def ip_calc_len; self.ip_header.ip_calc_len ; end
10
+ def ip_calc_sum; self.ip_header.ip_calc_sum ; end
11
+ def ip_daddr; self.ip_header.ip_daddr ; end
12
+ def ip_daddr=(v); self.ip_header.ip_daddr= v; end
13
+ def ip_dst; self.ip_header.ip_dst ; end
14
+ def ip_dst=(v); self.ip_header.ip_dst= v; end
15
+ def ip_dst_readable; self.ip_header.ip_dst_readable ; end
16
+ def ip_frag; self.ip_header.ip_frag ; end
17
+ def ip_frag=(v); self.ip_header.ip_frag= v; end
18
+ def ip_hl; self.ip_header.ip_hl ; end
19
+ def ip_hl=(v); self.ip_header.ip_hl= v; end
20
+ def ip_hlen; self.ip_header.ip_hlen ; end
21
+ def ip_id; self.ip_header.ip_id ; end
22
+ def ip_id=(v); self.ip_header.ip_id= v; end
23
+ def ip_id_readable; self.ip_header.ip_id_readable ; end
24
+ def ip_len; self.ip_header.ip_len ; end
25
+ def ip_len=(v); self.ip_header.ip_len= v; end
26
+ def ip_proto; self.ip_header.ip_proto ; end
27
+ def ip_proto=(v); self.ip_header.ip_proto= v; end
28
+ def ip_recalc(*args); self.ip_header.ip_recalc(*args) ; end
29
+ def ip_saddr; self.ip_header.ip_saddr ; end
30
+ def ip_saddr=(v); self.ip_header.ip_saddr= v; end
31
+ def ip_src; self.ip_header.ip_src ; end
32
+ def ip_src=(v); self.ip_header.ip_src= v; end
33
+ def ip_src_readable; self.ip_header.ip_src_readable ; end
34
+ def ip_sum; self.ip_header.ip_sum ; end
35
+ def ip_sum=(v); self.ip_header.ip_sum= v; end
36
+ def ip_sum_readable; self.ip_header.ip_sum_readable ; end
37
+ def ip_tos; self.ip_header.ip_tos ; end
38
+ def ip_tos=(v); self.ip_header.ip_tos= v; end
39
+ def ip_ttl; self.ip_header.ip_ttl ; end
40
+ def ip_ttl=(v); self.ip_header.ip_ttl= v; end
41
+ def ip_v; self.ip_header.ip_v ; end
42
+ def ip_v=(v); self.ip_header.ip_v= v; end
43
+ end
44
44
  end
@@ -6,62 +6,62 @@ require 'packetfu/protos/ipv6/header'
6
6
  require 'packetfu/protos/ipv6/mixin'
7
7
 
8
8
  module PacketFu
9
- # IPv6Packet is used to construct IPv6 Packets. They contain an EthHeader and an IPv6Header, and in
10
- # the distant, unknowable future, will take interesting IPv6ish payloads.
11
- #
12
- # This mostly complete, but not very useful. It's intended primarily as an example protocol.
13
- #
14
- # == Parameters
15
- #
16
- # :eth
17
- # A pre-generated EthHeader object.
18
- # :ip
19
- # A pre-generated IPHeader object.
20
- # :flavor
21
- # TODO: Sets the "flavor" of the IPv6 packet. No idea what this will look like, haven't done much IPv6 fingerprinting.
22
- # :config
23
- # A hash of return address details, often the output of Utils.whoami?
24
- class IPv6Packet < Packet
9
+ # IPv6Packet is used to construct IPv6 Packets. They contain an EthHeader and an IPv6Header, and in
10
+ # the distant, unknowable future, will take interesting IPv6ish payloads.
11
+ #
12
+ # This mostly complete, but not very useful. It's intended primarily as an example protocol.
13
+ #
14
+ # == Parameters
15
+ #
16
+ # :eth
17
+ # A pre-generated EthHeader object.
18
+ # :ip
19
+ # A pre-generated IPHeader object.
20
+ # :flavor
21
+ # TODO: Sets the "flavor" of the IPv6 packet. No idea what this will look like, haven't done much IPv6 fingerprinting.
22
+ # :config
23
+ # A hash of return address details, often the output of Utils.whoami?
24
+ class IPv6Packet < Packet
25
25
  include ::PacketFu::EthHeaderMixin
26
26
  include ::PacketFu::IPv6HeaderMixin
27
27
 
28
- attr_accessor :eth_header, :ipv6_header
28
+ attr_accessor :eth_header, :ipv6_header
29
29
 
30
- def self.can_parse?(str)
31
- return false unless EthPacket.can_parse? str
32
- return false unless str.size >= 54
33
- return false unless str[12,2] == "\x86\xdd"
34
- true
35
- end
30
+ def self.can_parse?(str)
31
+ return false unless EthPacket.can_parse? str
32
+ return false unless str.size >= 54
33
+ return false unless str[12,2] == "\x86\xdd"
34
+ true
35
+ end
36
36
 
37
- def read(str=nil,args={})
38
- raise "Cannot parse `#{str}'" unless self.class.can_parse?(str)
39
- @eth_header.read(str)
40
- super(args)
41
- self
42
- end
37
+ def read(str=nil,args={})
38
+ raise "Cannot parse `#{str}'" unless self.class.can_parse?(str)
39
+ @eth_header.read(str)
40
+ super(args)
41
+ self
42
+ end
43
43
 
44
- def initialize(args={})
45
- @eth_header = (args[:eth] || EthHeader.new)
46
- @ipv6_header = (args[:ipv6] || IPv6Header.new)
47
- @eth_header.eth_proto = 0x86dd
48
- @eth_header.body=@ipv6_header
49
- @headers = [@eth_header, @ipv6_header]
50
- super
51
- end
44
+ def initialize(args={})
45
+ @eth_header = (args[:eth] || EthHeader.new)
46
+ @ipv6_header = (args[:ipv6] || IPv6Header.new)
47
+ @eth_header.eth_proto = 0x86dd
48
+ @eth_header.body=@ipv6_header
49
+ @headers = [@eth_header, @ipv6_header]
50
+ super
51
+ end
52
52
 
53
- # Peek provides summary data on packet contents.
54
- def peek(args={})
55
- peek_data = ["6 "]
56
- peek_data << "%-5d" % self.to_s.size
57
- peek_data << "%-31s" % self.ipv6_saddr
58
- peek_data << "-> "
59
- peek_data << "%-31s" % self.ipv6_daddr
60
- peek_data << " N:"
61
- peek_data << self.ipv6_next.to_s(16)
62
- peek_data.join
63
- end
53
+ # Peek provides summary data on packet contents.
54
+ def peek(args={})
55
+ peek_data = ["6 "]
56
+ peek_data << "%-5d" % self.to_s.size
57
+ peek_data << "%-31s" % self.ipv6_saddr
58
+ peek_data << "-> "
59
+ peek_data << "%-31s" % self.ipv6_daddr
60
+ peek_data << " N:"
61
+ peek_data << self.ipv6_next.to_s(16)
62
+ peek_data.join
63
+ end
64
64
 
65
- end
66
-
65
+ end
66
+
67
67
  end
@@ -1,191 +1,191 @@
1
1
  # -*- coding: binary -*-
2
2
  module PacketFu
3
- # AddrIpv6 handles addressing for IPv6Header
4
- #
5
- # ==== Header Definition
6
- #
7
- # Int32 :a1
8
- # Int32 :a2
9
- # Int32 :a3
10
- # Int32 :a4
11
- class AddrIpv6 < Struct.new(:a1, :a2, :a3, :a4)
12
-
13
- include StructFu
14
-
15
- def initialize(args={})
16
- super(
17
- Int32.new(args[:a1]),
18
- Int32.new(args[:a2]),
19
- Int32.new(args[:a3]),
20
- Int32.new(args[:a4]))
21
- end
22
-
23
- # Returns the address in string format.
24
- def to_s
25
- self.to_a.map {|x| x.to_s}.join
26
- end
27
-
28
- # Returns the address as a fairly ginormous integer.
29
- def to_i
30
- (a1.to_i << 96) + (a2.to_i << 64) + (a3.to_i << 32) + a4.to_i
31
- end
32
-
33
- # Returns the address as a colon-delimited hex string.
34
- def to_x
35
- IPAddr.new(self.to_i, Socket::AF_INET6).to_s
36
- end
37
-
38
- # Reads in a string and casts it as an IPv6 address
39
- def read(str)
40
- force_binary(str)
41
- return self if str.nil?
42
- self[:a1].read str[0,4]
43
- self[:a2].read str[4,4]
44
- self[:a3].read str[8,4]
45
- self[:a4].read str[12,4]
46
- self
47
- end
48
-
49
- # Reads in a colon-delimited hex string and casts it as an IPv6 address.
50
- def read_x(str)
51
- addr = IPAddr.new(str).to_i
52
- self[:a1]=Int32.new(addr >> 96)
53
- self[:a2]=Int32.new((addr & 0x00000000ffffffff0000000000000000) >> 64)
54
- self[:a3]=Int32.new((addr & 0x0000000000000000ffffffff00000000) >> 32)
55
- self[:a4]=Int32.new(addr & 0x000000000000000000000000ffffffff)
56
- self
57
- end
58
-
59
- end
60
-
61
- # IPv6Header is complete IPv6 struct, used in IPv6Packet.
62
- #
63
- # ==== Header Definition
64
- #
65
- # Fixnum (4 bits) :ipv6_v Default: 6 # Versiom
66
- # Fixnum (8 bits) :ipv6_class Defualt: 0 # Class
67
- # Fixnum (20 bits) :ipv6_label Defualt: 0 # Label
68
- # Int16 :ipv6_len Default: calc # Payload length
69
- # Int8 :ipv6_next # Next Header
70
- # Int8 :ipv6_hop Default: 0xff # Hop limit
71
- # AddrIpv6 :ipv6_src
72
- # AddrIpv6 :ipv6_dst
73
- # String :body
74
- class IPv6Header < Struct.new(:ipv6_v, :ipv6_class, :ipv6_label,
75
- :ipv6_len, :ipv6_next, :ipv6_hop,
76
- :ipv6_src, :ipv6_dst, :body)
77
- include StructFu
78
-
79
- def initialize(args={})
80
- super(
81
- (args[:ipv6_v] || 6),
82
- (args[:ipv6_class] || 0),
83
- (args[:ipv6_label] || 0),
84
- Int16.new(args[:ipv6_len]),
85
- Int8.new(args[:ipv6_next]),
86
- Int8.new(args[:ipv6_hop] || 0xff),
87
- AddrIpv6.new.read(args[:ipv6_src] || ("\x00" * 16)),
88
- AddrIpv6.new.read(args[:ipv6_dst] || ("\x00" * 16)),
89
- StructFu::String.new.read(args[:body])
90
- )
91
- end
92
-
93
- # Returns the object in string form.
94
- def to_s
95
- bytes_v_class_label = [(self.ipv6_v << 28) +
96
- (self.ipv6_class << 20) +
97
- self.ipv6_label].pack("N")
98
- bytes_v_class_label + (self.to_a[3,6].map {|x| x.to_s}.join)
99
- end
100
-
101
- # Reads a string to populate the object.
102
- def read(str)
103
- force_binary(str)
104
- return self if str.nil?
105
- self[:ipv6_v] = str[0,1].unpack("C").first >> 4
106
- self[:ipv6_class] = (str[0,2].unpack("n").first & 0x0ff0) >> 4
107
- self[:ipv6_label] = str[0,4].unpack("N").first & 0x000fffff
108
- self[:ipv6_len].read(str[4,2])
109
- self[:ipv6_next].read(str[6,1])
110
- self[:ipv6_hop].read(str[7,1])
111
- self[:ipv6_src].read(str[8,16])
112
- self[:ipv6_dst].read(str[24,16])
113
- self[:body].read(str[40,str.size]) if str.size > 40
114
- self
115
- end
116
-
117
- # Setter for the version (usually, 6).
118
- def ipv6_v=(i); self[:ip_v] = i.to_i; end
119
- # Getter for the version (usually, 6).
120
- def ipv6_v; self[:ipv6_v].to_i; end
121
- # Setter for the traffic class.
122
- def ipv6_class=(i); self[:ip_class] = i.to_i; end
123
- # Getter for the traffic class.
124
- def ipv6_class; self[:ipv6_class].to_i; end
125
- # Setter for the flow label.
126
- def ipv6_label=(i); self[:ip_label] = i.to_i; end
127
- # Getter for the flow label.
128
- def ipv6_label; self[:ipv6_label].to_i; end
129
- # Setter for the payload length.
130
- def ipv6_len=(i); typecast i; end
131
- # Getter for the payload length.
132
- def ipv6_len; self[:ipv6_len].to_i; end
133
- # Setter for the next protocol header.
134
- def ipv6_next=(i); typecast i; end
135
- # Getter for the next protocol header.
136
- def ipv6_next; self[:ipv6_next].to_i; end
137
- # Setter for the hop limit.
138
- def ipv6_hop=(i); typecast i; end
139
- # Getter for the hop limit.
140
- def ipv6_hop; self[:ipv6_hop].to_i; end
141
- # Setter for the source address.
142
- def ipv6_src=(i); typecast i; end
143
- # Getter for the source address.
144
- def ipv6_src; self[:ipv6_src].to_i; end
145
- # Setter for the destination address.
146
- def ipv6_dst=(i); typecast i; end
147
- # Getter for the destination address.
148
- def ipv6_dst; self[:ipv6_dst].to_i; end
149
-
150
- # Calculates the payload length.
151
- def ipv6_calc_len
152
- self[:ipv6_len] = body.to_s.length
153
- end
154
-
155
- # Recalculates the calculatable fields for this object.
156
- def ipv6_recalc(arg=:all)
157
- case arg
158
- when :ipv6_len
159
- ipv6_calc_len
160
- when :all
161
- ipv6_recalc(:len)
162
- end
163
- end
164
-
165
- # Get the source address in a more readable form.
166
- def ipv6_saddr
167
- self[:ipv6_src].to_x
168
- end
169
-
170
- # Set the source address in a more readable form.
171
- def ipv6_saddr=(str)
172
- self[:ipv6_src].read_x(str)
173
- end
174
-
175
- # Get the destination address in a more readable form.
176
- def ipv6_daddr
177
- self[:ipv6_dst].to_x
178
- end
179
-
180
- # Set the destination address in a more readable form.
181
- def ipv6_daddr=(str)
182
- self[:ipv6_dst].read_x(str)
183
- end
184
-
185
- # Readability aliases
186
-
187
- alias :ipv6_src_readable :ipv6_saddr
188
- alias :ipv6_dst_readable :ipv6_daddr
189
-
190
- end # class IPv6Header
3
+ # AddrIpv6 handles addressing for IPv6Header
4
+ #
5
+ # ==== Header Definition
6
+ #
7
+ # Int32 :a1
8
+ # Int32 :a2
9
+ # Int32 :a3
10
+ # Int32 :a4
11
+ class AddrIpv6 < Struct.new(:a1, :a2, :a3, :a4)
12
+
13
+ include StructFu
14
+
15
+ def initialize(args={})
16
+ super(
17
+ Int32.new(args[:a1]),
18
+ Int32.new(args[:a2]),
19
+ Int32.new(args[:a3]),
20
+ Int32.new(args[:a4]))
21
+ end
22
+
23
+ # Returns the address in string format.
24
+ def to_s
25
+ self.to_a.map {|x| x.to_s}.join
26
+ end
27
+
28
+ # Returns the address as a fairly ginormous integer.
29
+ def to_i
30
+ (a1.to_i << 96) + (a2.to_i << 64) + (a3.to_i << 32) + a4.to_i
31
+ end
32
+
33
+ # Returns the address as a colon-delimited hex string.
34
+ def to_x
35
+ IPAddr.new(self.to_i, Socket::AF_INET6).to_s
36
+ end
37
+
38
+ # Reads in a string and casts it as an IPv6 address
39
+ def read(str)
40
+ force_binary(str)
41
+ return self if str.nil?
42
+ self[:a1].read str[0,4]
43
+ self[:a2].read str[4,4]
44
+ self[:a3].read str[8,4]
45
+ self[:a4].read str[12,4]
46
+ self
47
+ end
48
+
49
+ # Reads in a colon-delimited hex string and casts it as an IPv6 address.
50
+ def read_x(str)
51
+ addr = IPAddr.new(str).to_i
52
+ self[:a1]=Int32.new(addr >> 96)
53
+ self[:a2]=Int32.new((addr & 0x00000000ffffffff0000000000000000) >> 64)
54
+ self[:a3]=Int32.new((addr & 0x0000000000000000ffffffff00000000) >> 32)
55
+ self[:a4]=Int32.new(addr & 0x000000000000000000000000ffffffff)
56
+ self
57
+ end
58
+
59
+ end
60
+
61
+ # IPv6Header is complete IPv6 struct, used in IPv6Packet.
62
+ #
63
+ # ==== Header Definition
64
+ #
65
+ # Fixnum (4 bits) :ipv6_v Default: 6 # Versiom
66
+ # Fixnum (8 bits) :ipv6_class Defualt: 0 # Class
67
+ # Fixnum (20 bits) :ipv6_label Defualt: 0 # Label
68
+ # Int16 :ipv6_len Default: calc # Payload length
69
+ # Int8 :ipv6_next # Next Header
70
+ # Int8 :ipv6_hop Default: 0xff # Hop limit
71
+ # AddrIpv6 :ipv6_src
72
+ # AddrIpv6 :ipv6_dst
73
+ # String :body
74
+ class IPv6Header < Struct.new(:ipv6_v, :ipv6_class, :ipv6_label,
75
+ :ipv6_len, :ipv6_next, :ipv6_hop,
76
+ :ipv6_src, :ipv6_dst, :body)
77
+ include StructFu
78
+
79
+ def initialize(args={})
80
+ super(
81
+ (args[:ipv6_v] || 6),
82
+ (args[:ipv6_class] || 0),
83
+ (args[:ipv6_label] || 0),
84
+ Int16.new(args[:ipv6_len]),
85
+ Int8.new(args[:ipv6_next]),
86
+ Int8.new(args[:ipv6_hop] || 0xff),
87
+ AddrIpv6.new.read(args[:ipv6_src] || ("\x00" * 16)),
88
+ AddrIpv6.new.read(args[:ipv6_dst] || ("\x00" * 16)),
89
+ StructFu::String.new.read(args[:body])
90
+ )
91
+ end
92
+
93
+ # Returns the object in string form.
94
+ def to_s
95
+ bytes_v_class_label = [(self.ipv6_v << 28) +
96
+ (self.ipv6_class << 20) +
97
+ self.ipv6_label].pack("N")
98
+ bytes_v_class_label + (self.to_a[3,6].map {|x| x.to_s}.join)
99
+ end
100
+
101
+ # Reads a string to populate the object.
102
+ def read(str)
103
+ force_binary(str)
104
+ return self if str.nil?
105
+ self[:ipv6_v] = str[0,1].unpack("C").first >> 4
106
+ self[:ipv6_class] = (str[0,2].unpack("n").first & 0x0ff0) >> 4
107
+ self[:ipv6_label] = str[0,4].unpack("N").first & 0x000fffff
108
+ self[:ipv6_len].read(str[4,2])
109
+ self[:ipv6_next].read(str[6,1])
110
+ self[:ipv6_hop].read(str[7,1])
111
+ self[:ipv6_src].read(str[8,16])
112
+ self[:ipv6_dst].read(str[24,16])
113
+ self[:body].read(str[40,str.size]) if str.size > 40
114
+ self
115
+ end
116
+
117
+ # Setter for the version (usually, 6).
118
+ def ipv6_v=(i); self[:ip_v] = i.to_i; end
119
+ # Getter for the version (usually, 6).
120
+ def ipv6_v; self[:ipv6_v].to_i; end
121
+ # Setter for the traffic class.
122
+ def ipv6_class=(i); self[:ip_class] = i.to_i; end
123
+ # Getter for the traffic class.
124
+ def ipv6_class; self[:ipv6_class].to_i; end
125
+ # Setter for the flow label.
126
+ def ipv6_label=(i); self[:ip_label] = i.to_i; end
127
+ # Getter for the flow label.
128
+ def ipv6_label; self[:ipv6_label].to_i; end
129
+ # Setter for the payload length.
130
+ def ipv6_len=(i); typecast i; end
131
+ # Getter for the payload length.
132
+ def ipv6_len; self[:ipv6_len].to_i; end
133
+ # Setter for the next protocol header.
134
+ def ipv6_next=(i); typecast i; end
135
+ # Getter for the next protocol header.
136
+ def ipv6_next; self[:ipv6_next].to_i; end
137
+ # Setter for the hop limit.
138
+ def ipv6_hop=(i); typecast i; end
139
+ # Getter for the hop limit.
140
+ def ipv6_hop; self[:ipv6_hop].to_i; end
141
+ # Setter for the source address.
142
+ def ipv6_src=(i); typecast i; end
143
+ # Getter for the source address.
144
+ def ipv6_src; self[:ipv6_src].to_i; end
145
+ # Setter for the destination address.
146
+ def ipv6_dst=(i); typecast i; end
147
+ # Getter for the destination address.
148
+ def ipv6_dst; self[:ipv6_dst].to_i; end
149
+
150
+ # Calculates the payload length.
151
+ def ipv6_calc_len
152
+ self[:ipv6_len] = body.to_s.length
153
+ end
154
+
155
+ # Recalculates the calculatable fields for this object.
156
+ def ipv6_recalc(arg=:all)
157
+ case arg
158
+ when :ipv6_len
159
+ ipv6_calc_len
160
+ when :all
161
+ ipv6_recalc(:len)
162
+ end
163
+ end
164
+
165
+ # Get the source address in a more readable form.
166
+ def ipv6_saddr
167
+ self[:ipv6_src].to_x
168
+ end
169
+
170
+ # Set the source address in a more readable form.
171
+ def ipv6_saddr=(str)
172
+ self[:ipv6_src].read_x(str)
173
+ end
174
+
175
+ # Get the destination address in a more readable form.
176
+ def ipv6_daddr
177
+ self[:ipv6_dst].to_x
178
+ end
179
+
180
+ # Set the destination address in a more readable form.
181
+ def ipv6_daddr=(str)
182
+ self[:ipv6_dst].read_x(str)
183
+ end
184
+
185
+ # Readability aliases
186
+
187
+ alias :ipv6_src_readable :ipv6_saddr
188
+ alias :ipv6_dst_readable :ipv6_daddr
189
+
190
+ end # class IPv6Header
191
191
  end