racket 1.0.10

Sign up to get free protection for your applications and to get access to all the features.
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,446 @@
1
+ # $Id: icmpv6.rb 172 2010-03-16 07:07:04Z jhart $
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 L4
30
+ # Internet Control Message Protcol, v6
31
+ #
32
+ # http://en.wikipedia.org/wiki/ICMPv6
33
+ #
34
+ # Generic ICMP class from which all ICMP variants spawn. This should never be used directly.
35
+ class ICMPv6Generic < RacketPart
36
+ ICMPv6_TYPE_ECHO_REPLY = 129
37
+ ICMPv6_TYPE_DESTINATION_UNREACHABLE = 1
38
+ ICMPv6_TYPE_PACKET_TOO_BIG = 2
39
+ ICMPv6_TYPE_ECHO_REQUEST = 128
40
+ ICMPv6_TYPE_TIME_EXCEEDED = 3
41
+ ICMPv6_TYPE_PARAMETER_PROBLEM = 4
42
+ ICMPv6_TYPE_MLD_QUERY = 130
43
+ ICMPv6_TYPE_MLD_REPORT = 131
44
+ ICMPv6_TYPE_MLD_DONE = 132
45
+ ICMPv6_TYPE_ROUTER_SOLICITATION = 133
46
+ ICMPv6_TYPE_ROUTER_ADVERTISEMENT = 134
47
+ ICMPv6_TYPE_NEIGHBOR_SOLICITATION = 135
48
+ ICMPv6_TYPE_NEIGHBOR_ADVERTISEMENT = 136
49
+ ICMPv6_TYPE_REDIRECT = 137
50
+ ICMPv6_TYPE_INFORMATION_REQUEST = 139
51
+ ICMPv6_TYPE_INFORMATION_REPLY = 140
52
+
53
+ # Type
54
+ unsigned :type, 8
55
+ # Code
56
+ unsigned :code, 8
57
+ # Checksum
58
+ unsigned :checksum, 16
59
+ rest :message
60
+
61
+ # check the checksum for this ICMP packet
62
+ def checksum?
63
+ self.checksum == compute_checksum
64
+ end
65
+
66
+ def initialize(*args)
67
+ super(*args)
68
+ @autofix = false
69
+ end
70
+
71
+ # Add an ICMPv6 option. RFC claims that the value should be padded (with what?)
72
+ # to land on a 64-bit boundary, however that doesn't always appear to be the case. so, yeah,
73
+ # try to pad on your own or pick strings that are multiples of 8 characters
74
+ def add_option(type, value)
75
+ t = Racket::Misc::TLV.new(1,1)
76
+ t.type = type
77
+ t.length = (value.length + 2) / 8
78
+ just = value.length + 2 + (8 - ((value.length + 2) % 8))
79
+ t.value = (value.length + 2) % 8 == 0 ? value : value.ljust(just, "\x00")
80
+ self.payload = t.encode + self.payload
81
+ end
82
+
83
+ # ignorantly assume the first parts of the payload contain ICMPv6 options
84
+ # and find a return an array of Racket::Misc::TLV representing the options
85
+ def get_options
86
+ p = self.payload
87
+ options = []
88
+ until ((o = Racket::Misc::TLV.new(1,1,8,true).decode(p)).nil?)
89
+ options << o[0..2]
90
+ p = o[3]
91
+ end
92
+ options
93
+ end
94
+
95
+ # compute and set the checksum for this ICMP packet
96
+ def checksum!(src_ip, dst_ip)
97
+ self.checksum = compute_checksum(src_ip, dst_ip)
98
+ end
99
+
100
+ # 'fix' this ICMP packet up for sending.
101
+ # (really, just set the checksum)
102
+ def fix!(src_ip, dst_ip)
103
+ self.checksum!(src_ip, dst_ip)
104
+ end
105
+
106
+ # get the source link layer address of this message, if found
107
+ def slla
108
+ addr = nil
109
+ self.get_options.each do |o|
110
+ type, length, value, rest = o.flatten
111
+ if (type == 1)
112
+ addr = L2::Misc.string2mac(value)
113
+ end
114
+ end
115
+ addr
116
+ end
117
+
118
+ # set the source link layer address of this message.
119
+ # expects +addr+ in de:ad:ba:dc:af:e0 form
120
+ def slla=(addr)
121
+ self.add_option(1, L2::Misc.mac2string(addr))
122
+ end
123
+
124
+ # get the target link layer address of this message, if found
125
+ def tlla
126
+ addr = nil
127
+ self.get_options.each do |o|
128
+ type, length, value, rest = o.flatten
129
+ if (type == 2)
130
+ addr = L2::Misc.string2mac(value)
131
+ end
132
+ end
133
+ addr
134
+ end
135
+
136
+ # set the target link layer address of this message
137
+ # expects +addr+ in de:ad:ba:dc:af:e0 form
138
+ def tlla=(addr)
139
+ self.add_option(2, L2::Misc.mac2string(addr))
140
+ end
141
+
142
+ private
143
+ def compute_checksum(src_ip, dst_ip)
144
+ s1 = src_ip >> 96
145
+ s2 = (src_ip >> 64) & 0xFFFFFFFF
146
+ s3 = (src_ip >> 32) & 0xFFFFFFFF
147
+ s4 = src_ip & 0xFFFFFFFF
148
+
149
+ d1 = dst_ip >> 96
150
+ d2 = (dst_ip >> 64) & 0xFFFFFFFF
151
+ d3 = (dst_ip >> 32) & 0xFFFFFFFF
152
+ d4 = dst_ip & 0xFFFFFFFF
153
+
154
+ # pseudo header used for checksum calculation as per RFC 768
155
+ pseudo = [ s1, s2, s3, s4, d1, d2, d3, d4, self.length, 58, self.type, self.code, 0, self.message ]
156
+ L3::Misc.checksum(pseudo.pack("NNNNNNNNNNCCna*"))
157
+ end
158
+ end
159
+ # Send raw ICMP packets of your own design
160
+ class ICMPv6 < ICMPv6Generic
161
+ rest :payload
162
+ end
163
+
164
+ # Generic ICMPv6 echo, used by ICMPv6EchoRequest and ICMPv6EchoReply
165
+ class ICMPv6Echo < ICMPv6Generic
166
+ # identifier to aid in matching echo requests/replies
167
+ unsigned :id, 16
168
+ # sequence number to aid in matching requests/replies
169
+ unsigned :sequence, 16
170
+ rest :payload
171
+
172
+ def initialize(*args)
173
+ super(*args)
174
+ end
175
+
176
+ end
177
+
178
+ # ICMPv6Echo Request
179
+ class ICMPv6EchoRequest < ICMPv6Echo
180
+ rest :payload
181
+
182
+ def initialize(*args)
183
+ super(*args)
184
+ self.type = ICMPv6_TYPE_ECHO_REQUEST
185
+ self.code = 0
186
+ end
187
+
188
+ end
189
+
190
+ # ICMPv6Echo Reply
191
+ class ICMPv6EchoReply < ICMPv6Echo
192
+ rest :payload
193
+
194
+ def initialize(*args)
195
+ super(*args)
196
+ self.type = ICMPv6_TYPE_ECHO_REPLY
197
+ self.code = 0
198
+ end
199
+ end
200
+
201
+ # ICMP Destination Unreachable Message
202
+ class ICMPv6DestinationUnreachable < ICMPv6Generic
203
+ ICMPv6_CODE_NO_ROUTE = 0
204
+ ICMPv6_CODE_ADMIN_PROHIBITED = 1
205
+ ICMPv6_CODE_BEYOND_SCOPE = 2
206
+ ICMPv6_CODE_ADDRESS_UNREACHABLE = 3
207
+ ICMPv6_CODE_PORT_UNREACHABLE = 4
208
+ ICMPv6_CODE_FAILED_POLICY = 4
209
+ ICMPv6_CODE_REJECT_ROUTE = 5
210
+ # This is never used according to the RFC
211
+ unsigned :unused, 32
212
+ # Internet header + 64 bits of original datagram
213
+ rest :payload
214
+
215
+ def initialize(*args)
216
+ super(*args)
217
+ self.type = ICMPv6_TYPE_DESTINATION_UNREACHABLE
218
+ end
219
+ end
220
+
221
+ class ICMPv6PacketTooBig < ICMPv6Generic
222
+ # The Maximum Transmission Unit of the next-hop link
223
+ unsigned :mtu, 32
224
+ rest :payload
225
+
226
+ def initialize(*args)
227
+ super(*args)
228
+ self.type = ICMPv6_TYPE_PACKET_TOO_BIG
229
+ end
230
+
231
+ end
232
+
233
+ # ICMP Time Exceeded Message
234
+ class ICMPv6TimeExceeded < ICMPv6Generic
235
+ ICMPv6_CODE_TTL_EXCEEDED_IN_TRANSIT = 0
236
+ ICMPv6_CODE_FRAG_REASSEMBLY_TIME_EXCEEDED = 1
237
+ # This is never used according to the RFC
238
+ unsigned :unused, 32
239
+ # As much of the original ICMPv6 packet without busting MTU
240
+ rest :payload
241
+
242
+ def initialize(*args)
243
+ super(*args)
244
+ self.type = ICMPv6_TYPE_TIME_EXCEEDED
245
+ end
246
+ end
247
+
248
+ # ICMPv6 Parameter Problem Message
249
+ class ICMPv6ParameterProblem < ICMPv6Generic
250
+ ICMPv6_CODE_ERRONEOUS_HEADER = 0
251
+ ICMPv6_CODE_UNRECOGNIZED_NEXT_HEADER = 1
252
+ ICMPv6_CODE_UNRECOGNIZED_OPTION = 2
253
+ # pointer to the octet where the error was detected
254
+ unsigned :pointer, 32
255
+ # As much of the original ICMPv6 packet without busting MTU
256
+ rest :payload
257
+
258
+ def initialize(*args)
259
+ super(*args)
260
+ self.type = ICMPv6_TYPE_PARAMETER_PROBLEM
261
+ end
262
+ end
263
+
264
+ # ICMPv6 Multicast Listener Discovery (MLD)
265
+ # http://www.faqs.org/rfcs/rfc2710.html
266
+ class ICMPv6MulticastListener < ICMPv6Generic
267
+ # maximum response delay
268
+ unsigned :delay, 16
269
+ # should be zero. never used.
270
+ unsigned :reserved, 16
271
+ # multicast address
272
+ unsigned :address, 128
273
+ rest :payload
274
+
275
+ def initialize(*args)
276
+ super(*args)
277
+ end
278
+ end
279
+
280
+ class ICMPv6MulticastListenerQuery < ICMPv6MulticastListener
281
+ rest :payload
282
+
283
+ def initialize(*args)
284
+ super(*args)
285
+ self.type = ICMPv6_TYPE_MLD_QUERY
286
+ end
287
+ end
288
+
289
+ class ICMPv6MulticastListenerReport < ICMPv6MulticastListener
290
+ rest :payload
291
+
292
+ def initialize(*args)
293
+ super(*args)
294
+ self.type = ICMPv6_TYPE_MLD_REPORT
295
+ end
296
+ end
297
+
298
+ class ICMPv6MulticastListenerDone < ICMPv6MulticastListener
299
+ rest :payload
300
+
301
+ def initialize(*args)
302
+ super(*args)
303
+ self.type = ICMPv6_TYPE_MLD_DONE
304
+ end
305
+ end
306
+
307
+ # http://tools.ietf.org/html/rfc4861
308
+ class ICMPv6RouterSolicitation < ICMPv6Generic
309
+ # should be 0, never used.
310
+ unsigned :reserved, 32
311
+ rest :payload
312
+
313
+ def initialize(*args)
314
+ super(*args)
315
+ self.type = ICMPv6_TYPE_ROUTER_SOLICITATION
316
+ end
317
+ end
318
+
319
+ # http://tools.ietf.org/html/rfc4861
320
+ class ICMPv6RouterAdvertisement < ICMPv6Generic
321
+ # default value that should be placed in the hop count field of the IP header
322
+ # for outgoing IP packets
323
+ unsigned :hop_limit, 8
324
+ # boolean, managed address configuration?
325
+ unsigned :managed_config, 1
326
+ # boolean, other configuration?
327
+ unsigned :other_config, 1
328
+ # set to 0, never used.
329
+ unsigned :reserved, 6
330
+ # lifetime associated with the default router in seconds
331
+ unsigned :lifetime, 16
332
+ # time in milliseconds that a node assumes a neighbor is reachable after having received a reachability confirmation
333
+ unsigned :reachable_time, 32
334
+ # time in milliseconds between retransmitted neighbor solicitation messages
335
+ unsigned :retrans_time, 32
336
+ rest :payload
337
+
338
+ def initialize(*args)
339
+ super(*args)
340
+ self.type = ICMPv6_TYPE_ROUTER_ADVERTISEMENT
341
+ end
342
+ end
343
+
344
+ # http://tools.ietf.org/html/rfc4861
345
+ class ICMPv6NeighborSolicitation < ICMPv6Generic
346
+ # set to 0, never used.
347
+ unsigned :reserved, 32
348
+ # target address of the solicitation
349
+ unsigned :address, 128
350
+ rest :payload
351
+
352
+ def initialize(*args)
353
+ super(*args)
354
+ self.type = ICMPv6_TYPE_NEIGHBOR_SOLICITATION
355
+ end
356
+ end
357
+
358
+ # http://tools.ietf.org/html/rfc4861
359
+ class ICMPv6NeighborAdvertisement < ICMPv6Generic
360
+ # normally this would be router (1), solicited (1), override(1) and reserved (2), however
361
+ # a bit-struct byte boundary bug bites us here
362
+ unsigned :bigbustedfield, 32
363
+ # for solicited adverts, the target address field in the solicitation that prompted this.
364
+ # for unsolicited adverts, the address whose link-layer address has changed
365
+ unsigned :address, 128
366
+ rest :payload
367
+
368
+ # set solicited flag
369
+ def solicited=(f)
370
+ self.bigbustedfield = (f << 30) ^ self.bigbustedfield
371
+ end
372
+
373
+ # set router flag
374
+ def router=(f)
375
+ self.bigbustedfield = (f << 31) ^ self.bigbustedfield
376
+ end
377
+
378
+ # set override flag
379
+ def override=(f)
380
+ self.bigbustedfield = (f << 29) ^ self.bigbustedfield
381
+ end
382
+
383
+ def initialize(*args)
384
+ super(*args)
385
+ self.type = ICMPv6_TYPE_NEIGHBOR_ADVERTISEMENT
386
+ end
387
+ end
388
+
389
+ # http://tools.ietf.org/html/rfc4861
390
+ class ICMPv6Redirect < ICMPv6Generic
391
+ # unused, should be 0
392
+ unsigned :reserved, 32
393
+ # the IP address that is a better first hop to use for the ICMP destination address
394
+ unsigned :src_ip, 128
395
+ # the IP address of the destination that is redirected to the target
396
+ unsigned :dst_ip, 128
397
+ rest :payload
398
+
399
+ def initialize(*args)
400
+ super(*args)
401
+ self.type = ICMPv6_TYPE_REDIRECT
402
+ end
403
+ end
404
+
405
+ # Generic class that IPv6NodeInformationRequest and Reply inherit from
406
+ # http://tools.ietf.org/html/rfc4620
407
+ class ICMPv6NodeInformation < ICMPv6Generic
408
+ # type of information requested in a query or supplied in a reply
409
+ unsigned :qtype, 16
410
+ # qtype-specific flags that may be defined for certain qtypes and their replies
411
+ unsigned :flags, 16
412
+ # opaque field to help avoid spoofing and/or to aid in matching replies with queries
413
+ text :nonce, 64
414
+ rest :payload
415
+
416
+ def initialize(*args)
417
+ super(*args)
418
+ end
419
+ end
420
+
421
+ # http://tools.ietf.org/html/rfc4620
422
+ class ICMPv6NodeInformationRequest < ICMPv6NodeInformation
423
+ ICMPv6_CODE_INFORMATION_REQUEST_IPv6 = 0
424
+ ICMPv6_CODE_INFORMATION_REQUEST_NAME = 1
425
+ ICMPv6_CODE_INFORMATION_REQUEST_IPv4 = 2
426
+
427
+ def initialize(*args)
428
+ super(*args)
429
+ self.type = ICMPv6_TYPE_INFORMATION_REQUEST
430
+ end
431
+ end
432
+
433
+ # http://tools.ietf.org/html/rfc4620
434
+ class ICMPv6NodeInformationReply < ICMPv6NodeInformation
435
+ ICMPv6_CODE_INFORMATION_REPLY_SUCCESS = 0
436
+ ICMPv6_CODE_INFORMATION_REPLY_REFUSE = 1
437
+ ICMPv6_CODE_INFORMATION_REPLY_UNKNOWN = 2
438
+
439
+ def initialize(*args)
440
+ super(*args)
441
+ self.type = ICMPv6_TYPE_INFORMATION_REPLY
442
+ end
443
+ end
444
+ end
445
+ end
446
+ # vim: set ts=2 et sw=2:
@@ -0,0 +1,79 @@
1
+ # $Id: igmpv1.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 L4
30
+ # Internet Group Management Protocol, Version 1
31
+ #
32
+ # RFC1112 (http://www.faqs.org/rfcs/rfc1112.html)
33
+ #
34
+ class IGMPv1 < RacketPart
35
+ # Version (defaults to 1)
36
+ unsigned :version, 4, { :default => 1 }
37
+ # Type
38
+ unsigned :type, 4
39
+ # Unused
40
+ unsigned :unused, 8
41
+ # Checksum
42
+ unsigned :checksum, 16
43
+ # Group Address
44
+ octets :gaddr, 32
45
+ # Payload
46
+ rest :payload
47
+
48
+ # Check the checksum for this IGMP message
49
+ def checksum?
50
+ self.checksum == 0 || (self.checksum == compute_checksum)
51
+ end
52
+
53
+ # Compute and set the checkum for this IGMP message
54
+ def checksum!
55
+ self.checksum = compute_checksum
56
+ end
57
+
58
+ # Do whatever 'fixing' is neccessary in preparation
59
+ # for being sent
60
+ def fix!
61
+ self.checksum!
62
+ end
63
+
64
+ private
65
+ def compute_checksum
66
+ # The checksum is the 16-bit one's complement of the one's complement sum
67
+ # of the 8-octet IGMP message. For computing the checksum, the checksum
68
+ # field is zeroed.
69
+ tmp = []
70
+ tmp << ((((self.version << 4) | self.type) << 8) | self.unused)
71
+ tmp << 0
72
+ tmp << L3::Misc.ipv42long(self.gaddr)
73
+ tmp << self.payload
74
+ L3::Misc.checksum(tmp.pack("nnNa*"))
75
+ end
76
+ end
77
+ end
78
+ end
79
+ # vim: set ts=2 et sw=2: