racket 1.0.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 (88) hide show
  1. data/README +76 -0
  2. data/examples/arp-send +24 -0
  3. data/examples/arp-send2 +30 -0
  4. data/examples/cdp +39 -0
  5. data/examples/cdp-spew +52 -0
  6. data/examples/dhcp +42 -0
  7. data/examples/dhcp-spew +48 -0
  8. data/examples/dns +38 -0
  9. data/examples/egp +30 -0
  10. data/examples/hsrp +43 -0
  11. data/examples/hsrp_takeover +69 -0
  12. data/examples/icmp-recv +34 -0
  13. data/examples/icmp-spew +50 -0
  14. data/examples/icmpv6 +84 -0
  15. data/examples/icmpv6-spew +50 -0
  16. data/examples/igmpv1 +27 -0
  17. data/examples/igmpv2 +27 -0
  18. data/examples/igrp-send +25 -0
  19. data/examples/ipv6 +35 -0
  20. data/examples/ntp +38 -0
  21. data/examples/ntp2 +42 -0
  22. data/examples/sctp +32 -0
  23. data/examples/stp-send +21 -0
  24. data/examples/synflood +147 -0
  25. data/examples/tcp +43 -0
  26. data/examples/tcp2udp +65 -0
  27. data/examples/udp +46 -0
  28. data/examples/vrrp +34 -0
  29. data/examples/vtp +28 -0
  30. data/lib/racket.rb +4 -0
  31. data/lib/racket/l2.rb +30 -0
  32. data/lib/racket/l2/eightotwodotthree.rb +48 -0
  33. data/lib/racket/l2/ethernet.rb +62 -0
  34. data/lib/racket/l2/llc.rb +50 -0
  35. data/lib/racket/l2/misc.rb +67 -0
  36. data/lib/racket/l2/snap.rb +40 -0
  37. data/lib/racket/l2/vlan.rb +61 -0
  38. data/lib/racket/l2/vtp.rb +124 -0
  39. data/lib/racket/l3.rb +30 -0
  40. data/lib/racket/l3/arp.rb +63 -0
  41. data/lib/racket/l3/cdp.rb +85 -0
  42. data/lib/racket/l3/egp.rb +53 -0
  43. data/lib/racket/l3/ipv4.rb +132 -0
  44. data/lib/racket/l3/ipv6.rb +66 -0
  45. data/lib/racket/l3/misc.rb +165 -0
  46. data/lib/racket/l3/stp.rb +81 -0
  47. data/lib/racket/l4.rb +30 -0
  48. data/lib/racket/l4/gre.rb +65 -0
  49. data/lib/racket/l4/icmp.rb +295 -0
  50. data/lib/racket/l4/icmpv6.rb +446 -0
  51. data/lib/racket/l4/igmpv1.rb +79 -0
  52. data/lib/racket/l4/igmpv2.rb +76 -0
  53. data/lib/racket/l4/igrp.rb +138 -0
  54. data/lib/racket/l4/misc.rb +35 -0
  55. data/lib/racket/l4/sctp.rb +163 -0
  56. data/lib/racket/l4/tcp.rb +152 -0
  57. data/lib/racket/l4/udp.rb +81 -0
  58. data/lib/racket/l4/vrrp.rb +95 -0
  59. data/lib/racket/l5.rb +30 -0
  60. data/lib/racket/l5/bootp.rb +106 -0
  61. data/lib/racket/l5/dns.rb +110 -0
  62. data/lib/racket/l5/hsrp.rb +73 -0
  63. data/lib/racket/l5/misc.rb +35 -0
  64. data/lib/racket/l5/ntp.rb +59 -0
  65. data/lib/racket/misc.rb +30 -0
  66. data/lib/racket/misc/lv.rb +108 -0
  67. data/lib/racket/misc/misc.rb +61 -0
  68. data/lib/racket/misc/orderedhash.rb +63 -0
  69. data/lib/racket/misc/raw.rb +35 -0
  70. data/lib/racket/misc/tlv.rb +103 -0
  71. data/lib/racket/misc/vt.rb +114 -0
  72. data/lib/racket/racket.rb +164 -0
  73. data/lib/racket/racketpart.rb +66 -0
  74. data/test/l2/ts_ethernet.rb +22 -0
  75. data/test/l2/ts_misc.rb +23 -0
  76. data/test/l2/ts_vlan.rb +15 -0
  77. data/test/l3/ts_ipv4.rb +44 -0
  78. data/test/l3/ts_ipv6.rb +26 -0
  79. data/test/l3/ts_misc.rb +31 -0
  80. data/test/l4/ts_icmp.rb +38 -0
  81. data/test/l4/ts_tcp.rb +55 -0
  82. data/test/l4/ts_udp.rb +40 -0
  83. data/test/misc/ts_lv.rb +59 -0
  84. data/test/misc/ts_orderedhash.rb +33 -0
  85. data/test/misc/ts_tlv.rb +47 -0
  86. data/test/misc/ts_vt.rb +56 -0
  87. data/test/ts_all.rb +14 -0
  88. metadata +182 -0
@@ -0,0 +1,114 @@
1
+ # $Id: vt.rb 14 2008-03-02 05:42:30Z warchild $
2
+ #
3
+ # Copyright (c) 2008, Jon Hart
4
+ # All rights reserved.
5
+ #
6
+ # Redistribution and use in source and binary forms, with or without
7
+ # modification, are permitted provided that the following conditions are met:
8
+ # * Redistributions of source code must retain the above copyright
9
+ # notice, this list of conditions and the following disclaimer.
10
+ # * Redistributions in binary form must reproduce the above copyright
11
+ # notice, this list of conditions and the following disclaimer in the
12
+ # documentation and/or other materials provided with the distribution.
13
+ # * Neither the name of the <organization> nor the
14
+ # names of its contributors may be used to endorse or promote products
15
+ # derived from this software without specific prior written permission.
16
+ #
17
+ # THIS SOFTWARE IS PROVIDED BY Jon Hart ``AS IS'' AND ANY
18
+ # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ # DISCLAIMED. IN NO EVENT SHALL Jon Hart BE LIABLE FOR ANY
21
+ # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ #
28
+ module Racket
29
+ module Misc
30
+ # Simple class to represent a datastructure that is made up of a
31
+ # null terminted string followed by an arbitrary number of
32
+ # arbitrarily sized values, followed by a "rest" field.
33
+ class VT
34
+ # the value for this VT object
35
+ attr_accessor :value
36
+ # the array of types for this VT object
37
+ attr_accessor :types
38
+ # everything else
39
+ attr_accessor :rest
40
+
41
+ # Create a new VT which consists of a null terminated string
42
+ # followed by some number of arbitrarily sized values, as
43
+ # specified by +args+
44
+ def initialize(*args)
45
+ @lengths = args
46
+ @types = []
47
+ @value = ""
48
+ end
49
+
50
+ # Given +data+, return the value and an array
51
+ # of the types as dictated by this instance
52
+ def decode(data)
53
+ null = data.index(0x00)
54
+ value = data.unpack("a#{null}")[0]
55
+ data = data.slice(null+1, data.length)
56
+
57
+ n = 0
58
+ types = []
59
+ @lengths.each do |l|
60
+ types[n] = data.unpack("#{punpack_string(l)}")[0]
61
+ data = data.slice(l, data.length)
62
+ n += 1
63
+ end
64
+
65
+ [value, types, data]
66
+ end
67
+
68
+ # Given +data+, set the +value+ and +types+ array
69
+ # accordingly
70
+ def decode!(data)
71
+ @value, @types, @rest = self.decode(data)
72
+ end
73
+
74
+ # Return a string suitable for use elsewhere
75
+ def encode
76
+ s = "#{@value}\000"
77
+
78
+ n = 0
79
+ @lengths.each do |l|
80
+ s << [@types[n]].pack("#{punpack_string(l)}")
81
+ n += 1
82
+ end
83
+ s
84
+ end
85
+
86
+ def to_s
87
+ encode
88
+ end
89
+
90
+ def to_str
91
+ encode
92
+ end
93
+
94
+ private
95
+ # XXX: make this handle arbitrarily sized fields
96
+ def punpack_string(size)
97
+ s = ""
98
+ case size
99
+ when 1
100
+ s << "C"
101
+ when 2
102
+ s << "n"
103
+ when 4
104
+ s << "N"
105
+ else
106
+ raise ArgumentError, "Size #{s} not supported"
107
+ end
108
+ s
109
+ end
110
+
111
+ end
112
+ end
113
+ end
114
+ # vim: set ts=2 et sw=2:
@@ -0,0 +1,164 @@
1
+ # $Id: racket.rb 14 2008-03-02 05:42:30Z warchild $
2
+ #
3
+ # Copyright (c) 2008, Jon Hart
4
+ # All rights reserved.
5
+ #
6
+ # Redistribution and use in source and binary forms, with or without
7
+ # modification, are permitted provided that the following conditions are met:
8
+ # * Redistributions of source code must retain the above copyright
9
+ # notice, this list of conditions and the following disclaimer.
10
+ # * Redistributions in binary form must reproduce the above copyright
11
+ # notice, this list of conditions and the following disclaimer in the
12
+ # documentation and/or other materials provided with the distribution.
13
+ # * Neither the name of the <organization> nor the
14
+ # names of its contributors may be used to endorse or promote products
15
+ # derived from this software without specific prior written permission.
16
+ #
17
+ # THIS SOFTWARE IS PROVIDED BY Jon Hart ``AS IS'' AND ANY
18
+ # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ # DISCLAIMED. IN NO EVENT SHALL Jon Hart BE LIABLE FOR ANY
21
+ # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ #
28
+
29
+ require 'socket'
30
+ require 'racket/racketpart'
31
+ require 'racket/misc'
32
+ require 'racket/l2'
33
+ require 'racket/l3'
34
+ require 'racket/l4'
35
+ require 'racket/l5'
36
+
37
+ module Racket
38
+ class Racket
39
+
40
+ attr_accessor :iface, :mtu, :timeout
41
+ attr_accessor :layers, :payload
42
+
43
+ @@loaded_pcaprub = false
44
+ begin
45
+ require 'pcaprub'
46
+ @@loaded_pcaprub = true
47
+ rescue ::LoadError
48
+ end
49
+
50
+
51
+ def initialize(payload="")
52
+ @layers = []
53
+ @mtu = 1500
54
+ @timeout = 10
55
+ @payload = payload
56
+ 1.upto(7) do |l|
57
+ self.class.send(:define_method, "layer#{l}", lambda { @layers[l] })
58
+ self.class.send(:define_method, "l#{l}", lambda { @layers[l] })
59
+ self.class.send(:define_method, "layer#{l}=", lambda { |x| @layers[l] = x; })
60
+ self.class.send(:define_method, "l#{l}=", lambda { |x| @layers[l] = x; })
61
+ end
62
+ end
63
+
64
+ # Assemble all the pieces of this Racket as a string, ready for sending.
65
+ def pack
66
+ last_payload = ""
67
+ orig_payload = ""
68
+ @layers.compact.reverse.each do |l|
69
+ # save the original payload
70
+ orig_payload = l.payload
71
+ # tack on the last payload in
72
+ # case fix needs it...
73
+ l.payload += last_payload
74
+ if (l.autofix?)
75
+ l.fix!
76
+ end
77
+
78
+ if (l.payload == orig_payload + last_payload)
79
+ # payload was not modified by fix, so reset it to what
80
+ # it used to be
81
+ l.payload = orig_payload
82
+ else
83
+ # payload was modified by fix. chop off what we added.
84
+ # XXX: this assumes that what we added is still at the end.
85
+ # XXX: this is not always true
86
+ l.payload = l.payload.slice(0, l.payload.length - last_payload.length)
87
+ end
88
+
89
+ # save this layer for the next guy
90
+ last_payload += l
91
+
92
+ end
93
+
94
+ payload = ""
95
+ @layers.compact.each do |l|
96
+ payload += l
97
+ end
98
+ payload
99
+ end
100
+
101
+ # return a pretty interpretation of this packet
102
+ def pretty
103
+ s = ""
104
+ @layers.compact.each do |l|
105
+ s << "#{l.class}: "
106
+ s << l.pretty
107
+ s << "\n"
108
+ end
109
+ s
110
+ end
111
+
112
+
113
+ # Attempt to figure out which of send2 or send3 needs to be called.
114
+ def sendpacket
115
+ if (@layers[2])
116
+ send2
117
+ else
118
+ send3
119
+ end
120
+ end
121
+
122
+ # Write raw layer2 frames
123
+ def send2
124
+ if(not @@loaded_pcaprub)
125
+ raise RuntimeError, "Could not initialize the pcaprub library (You need pcaprub from SVN (http://rubyforge.org/projects/pcaprub/))"
126
+ end
127
+ begin
128
+
129
+ p = Pcap::open_live(@iface, @mtu, false, @timeout)
130
+ rescue Exception => e
131
+ puts "Pcap: can't open device '#{@iface}' (#{e})"
132
+ return
133
+ end
134
+
135
+ begin
136
+ b = p.inject(pack)
137
+ #p.pcap_close
138
+ return b
139
+ rescue Exception => e
140
+ puts "Pcap: error while sending packet on '#{@iface}' (#{e})"
141
+ end
142
+ end
143
+
144
+ # Write raw layer3 frames
145
+ def send3
146
+ begin
147
+ s = Socket.open(Socket::PF_INET, Socket::SOCK_RAW, Socket::IPPROTO_RAW)
148
+
149
+ if (Socket.const_defined?('SOL_IP'))
150
+ s.setsockopt(Socket::SOL_IP, Socket::IP_HDRINCL, true)
151
+ else
152
+ # BSD
153
+ s.setsockopt(Socket::IPPROTO_IP, Socket::IP_HDRINCL, true)
154
+ end
155
+ rescue Errno::EPERM
156
+ raise ArgumentError, "Must run #{$0} as root."
157
+ end
158
+
159
+ return s.send(pack, 0, Socket.pack_sockaddr_in(1024, @layers[3].dst_ip))
160
+ end
161
+ end
162
+ end
163
+
164
+ # vim: set ts=2 et sw=2:
@@ -0,0 +1,66 @@
1
+ # $Id: racketpart.rb 14 2008-03-02 05:42:30Z warchild $
2
+ #
3
+ # Copyright (c) 2008, Jon Hart
4
+ # All rights reserved.
5
+ #
6
+ # Redistribution and use in source and binary forms, with or without
7
+ # modification, are permitted provided that the following conditions are met:
8
+ # * Redistributions of source code must retain the above copyright
9
+ # notice, this list of conditions and the following disclaimer.
10
+ # * Redistributions in binary form must reproduce the above copyright
11
+ # notice, this list of conditions and the following disclaimer in the
12
+ # documentation and/or other materials provided with the distribution.
13
+ # * Neither the name of the <organization> nor the
14
+ # names of its contributors may be used to endorse or promote products
15
+ # derived from this software without specific prior written permission.
16
+ #
17
+ # THIS SOFTWARE IS PROVIDED BY Jon Hart ``AS IS'' AND ANY
18
+ # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ # DISCLAIMED. IN NO EVENT SHALL Jon Hart BE LIABLE FOR ANY
21
+ # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ #
28
+ require 'rubygems'
29
+ require 'bit-struct'
30
+
31
+ module Racket
32
+ # Every Racket object is made up of numerous sub-parts, namely layers of the OSI stack.
33
+ class RacketPart < BitStruct
34
+
35
+ # Boolean indicating whether or not this instance should be
36
+ # automatically "fixed" prior to be packed and sent.
37
+ attr_accessor :autofix
38
+
39
+ # Should this instance be automatically fixed
40
+ # prior to being packed and sent?
41
+ def autofix?
42
+ @autofix
43
+ end
44
+
45
+ def initialize(*args)
46
+ @autofix = true
47
+ super(*args)
48
+ end
49
+
50
+
51
+ # Print out all of the fields and all of their values
52
+ def pretty
53
+ s = ""
54
+ self.fields.each do |f|
55
+ unless (f.name == "payload")
56
+ s += "#{f.name}=#{self.send(f.name)} "
57
+ end
58
+ end
59
+ s.gsub(/ $/, '')
60
+ end
61
+
62
+ def fix!
63
+ end
64
+ end
65
+ end
66
+ # vim: set ts=2 et sw=2:
@@ -0,0 +1,22 @@
1
+ # $Id: ts_ethernet.rb 129 2009-11-29 01:37:06Z jhart $
2
+
3
+ $:.unshift File.join(File.dirname(__FILE__), "../..", "lib")
4
+
5
+ require 'test/unit'
6
+ require 'racket'
7
+
8
+ class TestEthernet < Test::Unit::TestCase
9
+ def test_init
10
+ assert_nothing_raised() { Racket::L2::Ethernet.new }
11
+ assert_nothing_raised() { Racket::L2::Ethernet.new(Racket::Misc.randstring(30)) }
12
+ end
13
+
14
+ def test_attrs
15
+ binary = "\x00\x00\x24\xc1\x8c\x09\x00\x30\x1b\xa0\x63\x16\x08\x00\x45\x10\x00\x3c\x2f\xdf\x40\x00\x40\x06\x89\x17\xc0\xa8\x00\x64\xc0\xa8\x00\x01\x99\xb7\x00\x35\x29\x39\x28\x66\x00\x00\x00\x00\xa0\x02\x16\xd0\xbc\x04\x00\x00\x02\x04\x05\xb4\x04\x02\x08\x0a\x00\x31\x07\xb9\x00\x00\x00\x00\x01\x03\x03\x07"
16
+ e = Racket::L2::Ethernet.new(binary)
17
+ assert_equal(e.src_mac, "00:30:1b:a0:63:16")
18
+ assert_equal(e.dst_mac, "00:00:24:c1:8c:09")
19
+ assert_equal(e.ethertype, 2048)
20
+ end
21
+ end
22
+ # vim: set ts=2 et sw=2:
@@ -0,0 +1,23 @@
1
+ # $Id: ts_misc.rb 142 2009-12-13 01:53:14Z jhart $
2
+
3
+ $:.unshift File.join(File.dirname(__FILE__), "../..", "lib")
4
+
5
+ require 'test/unit'
6
+ require 'racket'
7
+
8
+ class TestL2Misc < Test::Unit::TestCase
9
+ def test_convert
10
+ (0..rand(1024)).each {
11
+ len = rand(512)+1
12
+ mac = Racket::L2::Misc.randommac(len)
13
+ assert_equal(mac.length, (len*2) + (len-1))
14
+ long = Racket::L2::Misc.mac2long(mac)
15
+ assert_equal(mac, Racket::L2::Misc.long2mac(long, len))
16
+ assert_equal(long, Racket::L2::Misc.mac2long(mac))
17
+ mac = "00:11:22:33:44:55"
18
+ string = Racket::L2::Misc.mac2string(mac)
19
+ assert_equal(mac, Racket::L2::Misc.string2mac(string))
20
+ }
21
+ end
22
+ end
23
+ # vim: set ts=2 et sw=2:
@@ -0,0 +1,15 @@
1
+ # $Id: ts_vlan.rb 129 2009-11-29 01:37:06Z jhart $
2
+
3
+ $:.unshift File.join(File.dirname(__FILE__), "../..", "lib")
4
+
5
+ require 'test/unit'
6
+ require 'racket'
7
+
8
+ class TestVLAN < Test::Unit::TestCase
9
+ def test_init
10
+ assert_nothing_raised() { Racket::L2::VLAN.new }
11
+ assert_nothing_raised() { Racket::L2::VLAN.new(Racket::Misc.randstring(30)) }
12
+ end
13
+
14
+ end
15
+ # vim: set ts=2 et sw=2:
@@ -0,0 +1,44 @@
1
+ # $Id: ts_ipv4.rb 129 2009-11-29 01:37:06Z jhart $
2
+
3
+ $:.unshift File.join(File.dirname(__FILE__), "../..", "lib")
4
+
5
+ require 'test/unit'
6
+ require 'racket'
7
+
8
+ class TestIPv4 < Test::Unit::TestCase
9
+ def test_init
10
+ assert_nothing_raised() { Racket::L3::IPv4.new }
11
+ assert_nothing_raised() { Racket::L3::IPv4.new(Racket::Misc.randstring(30)) }
12
+ end
13
+
14
+ def test_attrs
15
+ binary = "\x45\x10\x00\x3c\x2f\xdf\x40\x00\x40\x06\x89\x17\xc0\xa8\x00\x64\xc0\xa8\x00\x01\x99\xb7\x00\x35\x29\x39\x28\x66\x00\x00\x00\x00\xa0\x02\x16\xd0\xbc\x04\x00\x00\x02\x04\x05\xb4\x04\x02\x08\x0a\x00\x31\x07\xb9\x00\x00\x00\x00\x01\x03\x03\x07"
16
+ i = Racket::L3::IPv4.new(binary)
17
+ assert_equal(i.version, 4)
18
+ assert_equal(i.hlen, 5)
19
+ assert_equal(i.tos, 16)
20
+ assert_equal(i.len, 60)
21
+ assert_equal(i.id, 12255)
22
+ assert_equal(i.flags, 2)
23
+ assert_equal(i.foffset, 0)
24
+ assert_equal(i.ttl, 64)
25
+ assert_equal(i.protocol, 6)
26
+ assert_equal(i.checksum, 35095)
27
+ assert_equal(i.src_ip, "192.168.0.100")
28
+ assert_equal(i.dst_ip, "192.168.0.1")
29
+
30
+ i.src_ip = "1.2.3.4"
31
+ i.fix!
32
+ assert_equal(i.checksum, 17950)
33
+ end
34
+
35
+ def test_convert
36
+ (0..512).each {
37
+ long = rand(2**32)
38
+ ipv4 = Racket::L3::Misc.long2ipv4(long)
39
+ assert_equal(long, Racket::L3::Misc.ipv42long(ipv4))
40
+ assert_equal(ipv4, Racket::L3::Misc.long2ipv4(long))
41
+ }
42
+ end
43
+ end
44
+ # vim: set ts=2 et sw=2: