packetfu 1.1.9 → 1.1.10

Sign up to get free protection for your applications and to get access to all the features.
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