packetfu 1.1.8 → 1.1.9

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