Upgrade the bundled Racket to version 1.0.7

git-svn-id: file:///home/svn/framework3/trunk@8003 4d416f70-5f16-0410-b530-b9f4589650da
unstable
HD Moore 2009-12-28 13:26:56 +00:00
parent 5ac485eb48
commit bb84e76e40
42 changed files with 1945 additions and 179 deletions

View File

@ -24,10 +24,7 @@
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
require 'racket/l2/ethernet'
require 'racket/l2/llc'
require 'racket/l2/snap'
require 'racket/l2/vlan'
require 'racket/l2/eightotwodotthree'
Dir.glob(File.join(File.dirname(__FILE__), 'l2/*.rb')).each { |f| require f }
# vim: set ts=2 et sw=2:

View File

@ -25,8 +25,9 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# 802.3 Ethernet. Should always be followed by an LLC header
module Racket
module L2
# 802.3 Ethernet. Should always be followed by an LLC header
class EightOTwoDotThree < RacketPart
# Destination MAC address
hex_octets :dst_mac, 48
@ -43,4 +44,5 @@ class EightOTwoDotThree < RacketPart
end
end
end
end
# vim: set ts=2 et sw=2:

View File

@ -25,10 +25,11 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
module Racket
module L2
# Ethernet II (DIX v2.0)
#
# http://en.wikipedia.org/wiki/Ethernet_II_framing
module Racket
class Ethernet < RacketPart
ETHERTYPE_IPV4 = 0x0800
ETHERTYPE_ARP = 0x0806
@ -57,4 +58,5 @@ class Ethernet < RacketPart
rest :payload
end
end
end
#set ts=2 et sw=2: vim

View File

@ -25,8 +25,9 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Logical Link Control (http://en.wikipedia.org/wiki/Logical_Link_Control)
module Racket
module L2
# Logical Link Control (http://en.wikipedia.org/wiki/Logical_Link_Control)
class LLC < RacketPart
LLC_IBM_SNA = 0x04
LLC_IP = 0x06
@ -45,4 +46,5 @@ class LLC < RacketPart
rest :payload
end
end
end
# vim: set ts=2 et sw=2:

67
lib/racket/l2/misc.rb Normal file
View File

@ -0,0 +1,67 @@
# $Id: misc.rb 142 2009-12-13 01:53:14Z jhart $
#
# Copyright (c) 2008, Jon Hart
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the <organization> nor the
# names of its contributors may be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY Jon Hart ``AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL Jon Hart BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
module Racket
module L2
# Miscelaneous L2 helper methods
module Misc
# given a string representing a MAC address, return the
# human readable form
def Misc.string2mac(string)
string.unpack("C*").map { |i| i.to_s(16).ljust(2,"0") }.join(":")
end
# given a MAC address, return the string representation
def Misc.mac2string(mac)
mac.split(":").map { |i| i.hex.chr }.join
end
# given a MAC address, return the long representation
def Misc.mac2long(addr)
long = 0
addr.split(':').map { |s| s.to_i(16) }.each do |o|
long = (long << 8) ^ o
end
long
end
# given a long representing a MAC address
# print it out in human readable form of a given length,
# defaulting to 6 (ethernet)
def Misc.long2mac(long, len=6)
long.to_s(16).rjust(len*2, '0').unpack("a2"*len).join(":")
end
# Return a random MAC, defaults to 6 bytes (ethernet)
def Misc.randommac(len=6)
long2mac(rand(2**(8*len)), len)
end
end
end
end
# vim: set ts=2 et sw=2:

View File

@ -25,8 +25,9 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Subnetwork Access Protocl (http://en.wikipedia.org/wiki/Subnetwork_Access_Protocol)
module Racket
module L2
# Subnetwork Access Protocl (http://en.wikipedia.org/wiki/Subnetwork_Access_Protocol)
class SNAP < RacketPart
# Organizational code
unsigned :org, 24, { :default => 0x00000c }
@ -35,4 +36,5 @@ class SNAP < RacketPart
rest :payload
end
end
end
# vim: set ts=2 et sw=2:

View File

@ -25,8 +25,9 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# IEEE 802.1Q VLAN tag (http://en.wikipedia.org/wiki/IEEE_802.1Q)
module Racket
module L2
# IEEE 802.1Q VLAN tag (http://en.wikipedia.org/wiki/IEEE_802.1Q)
class VLAN < RacketPart
ETHERTYPE_IPV4 = 0x0800
ETHERTYPE_ARP = 0x0806
@ -45,7 +46,9 @@ class VLAN < RacketPart
ETHERTYPE_ATAOE = 0x88A2
ETHERTYPE_8021AE = 0x88E5
# Frame priority level
unsigned :priority, 3
# Canonical format indicator
unsigned :cfi, 1
# VLAN ID
unsigned :id, 12
@ -54,4 +57,5 @@ class VLAN < RacketPart
rest :payload
end
end
end
# vim: set ts=2 et sw=2:

124
lib/racket/l2/vtp.rb Normal file
View File

@ -0,0 +1,124 @@
# $Id: vtp.rb 127 2009-11-29 01:30:46Z jhart $
#
# Copyright (c) 2008, Jon Hart
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the <organization> nor the
# names of its contributors may be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY Jon Hart ``AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL Jon Hart BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
module Racket
module L2
# VLAN Trunking Protocol (VTP)
# http://en.wikipedia.org/wiki/VLAN_Trunking_Protocol
# http://www.cisco.com/en/US/tech/tk389/tk689/technologies_tech_note09186a0080094c52.shtml
# This is just a base class from which all VTP messages inherit and should never be used directly
class VTPGeneric < RacketPart
# VTP version (1-3)
unsigned :version, 8
# Message code (summary advertisement, subset advertisement, advertisement request, VTP join)
unsigned :code, 8
# Sometimes used, sometimes not, depends on the type
unsigned :reserved, 8
# Length of the management domain
unsigned :domain_length, 8
# management domain name, zero padded to 32 bytes
text :domain, 256
# Adjust +domain_length+ and +domain+ accordingly prior to sending
def fix!
self.domain_length = self.domain.length
self.domain = self.domain.ljust(32, "\x00")
end
end
# A raw VTP message
class VTPRaw < VTPGeneric
rest :payload
end
class VTPSubsetAdvertisement < VTPGeneric
# Configuration revision
unsigned :revision, 32
# all of the vlan info fields
rest :payload
def add_vlan_info(status, type, id, mtu, index, name)
name_length = name.length
# zero pad name to a multiple of 4 bytes
name = name.length % 4 == 0 ? name : name.ljust(name.length + (4 - (name.length % 4)), "\x00")
length = 12 + name.length
@vlan_info << [length, status, type, name_length, id, mtu, index, name]
end
def fix!
@vlan_info.each do |v|
self.payload += v.pack("CCCCnnNa*")
end
super
end
def initialize(*args)
@vlan_info = []
super(*args)
self.code = 2
end
end
class VTPSummaryAdvertisement < VTPGeneric
# Configuration revision number
unsigned :revision, 32
# Updater identity (IP)
octets :updater, 32
# update timestamp
unsigned :timestamp, 96
# MD5 digest of VTP password
text :md5, 128
rest :payload
def initialize(*args)
super(*args)
self.code = 1
end
end
class VTPAdvertisementRequest < VTPGeneric
# This is used in cases in which there are several subset advertisements. If the first (n) subset advertisement has been received and the subsequent one (n+1) has not been received, the Catalyst only requests advertisements from the (n+1)th one.
unsigned :start, 32
rest :payload
def initialize(*args)
super(*args)
self.code = 3
end
end
class VTPJoin < VTPGeneric
def initialize(*args)
super(*args)
self.code = 4
end
end
end
end
# vim: set ts=2 et sw=2:

View File

@ -24,11 +24,7 @@
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
require 'racket/l3/ipv4'
require 'racket/l3/ipv6'
require 'racket/l3/arp'
require 'racket/l3/stp'
require 'racket/l3/cdp'
require 'racket/l3/misc'
Dir.glob(File.join(File.dirname(__FILE__), 'l3/*.rb')).each { |f| require f }
# vim: set ts=2 et sw=2:

View File

@ -25,10 +25,10 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Address Resolution Protocol: ARP
#
# RFC826 (http://www.faqs.org/rfcs/rfc826.html)
module Racket
module L3
# Address Resolution Protocol: ARP
# RFC826 (http://www.faqs.org/rfcs/rfc826.html)
class ARP < RacketPart
ARPOP_REQUEST = 0x0001
ARPOP_REPLY = 0x0002
@ -59,4 +59,5 @@ class ARP < RacketPart
rest :payload
end
end
end
# vim: set ts=2 et sw=2:

View File

@ -25,54 +25,61 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
module Racket
module L3
# CDP -- Cisco Discovery Protocol
# http://www.cisco.biz/univercd/cc/td/doc/product/lan/trsrb/frames.htm#xtocid12
module Racket
class CDP < RacketPart
# CDP Version (generally 1)
unsigned :version, 8, { :default => 1 }
# Time-to-live of the data in this message
unsigned :ttl, 8
# Checksum
unsigned :csum, 16
unsigned :checksum, 16
# Payload of this CDP message. Generally untouched.
rest :payload
def initialize(*args)
super(*args)
end
# Add a new field to this CDP message.
def add_field(type, value)# {{{
t = TLV.new(2,2)
def add_field(type, value)
t = Racket::Misc::TLV.new(2,2)
t.type = type
t.value = value
t.length = 4 + value.length
self.payload += t.encode
end# }}}
end
# Check the checksum for this IP datagram
def checksum?# {{{
self.csum == compute_checksum
end# }}}
def checksum?
self.checksum == compute_checksum
end
# Compute and set the checksum for this IP datagram
def checksum!# {{{
self.csum = compute_checksum
end# }}}
def checksum!
self.checksum = compute_checksum
end
# Fix this CDP message up for sending.
def fix!# {{{
def fix!
self.checksum!
end# }}}
end
private
# Compute the checksum for this IP datagram
def compute_checksum# {{{
def compute_checksum
pseudo = []
pseudo << ((self.version << 8) | self.ttl)
pseudo << 0
pseudo << self.payload
L3::Misc.checksum(pseudo.pack("nna*"))
end# }}}
end
end
end
end
# vim: set ts=2 et sw=2:

53
lib/racket/l3/egp.rb Normal file
View File

@ -0,0 +1,53 @@
# $Id: egp.rb 127 2009-11-29 01:30:46Z jhart $
#
# Copyright (c) 2008, Jon Hart
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the <organization> nor the
# names of its contributors may be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY Jon Hart ``AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL Jon Hart BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
module Racket
module L3
# Exterior Gateway protocol (EGP)
# http://tools.ietf.org/html/rfc904
# XXX: TODO, add support for tacking on the various message types
class EGP < RacketPart
# EGP version
unsigned :version, 8
# Message type
unsigned :type, 8
# Message code (subtype)
unsigned :code, 8
# Message dependent status information
unsigned :status, 8
# Checksum
unsigned :checksum, 16
# assigned number identifying the particular autonomous system
unsigned :asn, 16
# Sequence number
unsigned :sequence, 16
# Payload
rest :payload
end
end
end
# vim: set ts=2 et sw=2:

View File

@ -25,10 +25,11 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
module Racket
module L3
# Internet Protcol Version 4 (IPV4)
#
# RFC791 (http://www.ietf.org/rfc/rfc791.txt)
module Racket
class IPv4 < RacketPart
# Version (defaults to 4)
unsigned :version, 4, { :default => 4 }
@ -49,10 +50,12 @@ class IPv4 < RacketPart
# Protocol
unsigned :protocol, 8
# Checksum
unsigned :csum, 16, "Checksum"
# Source IP address
unsigned :checksum, 16, "Checksum"
# Source IP address, passed as four octets separated by periods
# (192.168.1.2)
octets :src_ip, 32
# Destination IP address
# Destination IP address, passed as four octets separated by periods
# (192.168.1.2)
octets :dst_ip, 32
# Payload
rest :payload
@ -66,7 +69,7 @@ class IPv4 < RacketPart
# All rejiggering will happen when the call to fix!
# happens automagically
def add_option(number, value)
t = TLV.new(1,1)
t = Misc::TLV.new(1,1)
t.type = number
t.value = value
t.length = value.length + 2
@ -75,12 +78,12 @@ class IPv4 < RacketPart
# Check the checksum for this IP datagram
def checksum?
self.csum == compute_checksum
self.checksum == compute_checksum
end
# Compute and set the checksum for this IP datagram
def checksum!
self.csum = compute_checksum
self.checksum = compute_checksum
end
# Perform all the niceties necessary prior to sending
@ -125,4 +128,5 @@ private
end
end
end
end
# vim: set ts=2 et sw=2:

View File

@ -1,8 +1,8 @@
# $Id: ipv6.rb 14 2008-03-02 05:42:30Z warchild $
#
# Copyright (c) 2008, Jon Hart
# Copyright (c) 2008, Jon Hart
# All rights reserved.
#
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# * Redistributions of source code must retain the above copyright
@ -13,7 +13,7 @@
# * Neither the name of the <organization> nor the
# names of its contributors may be used to endorse or promote products
# derived from this software without specific prior written permission.
#
#
# THIS SOFTWARE IS PROVIDED BY Jon Hart ``AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
@ -25,10 +25,10 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
module Racket
module L3
# Internet Protocol Version 6 (IPV6)
# RFC2460
# XXX: not tested, incomplete.
module Racket
class IPv6 < RacketPart
# IP Version (defaults to 6)
unsigned :version, 4, { :default => 6 }
@ -41,14 +41,26 @@ class IPv6 < RacketPart
# Next header type
unsigned :nhead, 8
# Hop limit
unsigned :ttl, 8
# Source IP address
unsigned :ttl, 8, { :default => 200 }
# Source IP address. Must be passed as an integer
unsigned :src_ip, 128
# Destination IP address
# Destination IP address. Must be passed as an integer
unsigned :dst_ip, 128
# Payload
rest :payload
def initialize(*args)
@headers = []
super
@autofix = true
end
# Adjust plen to match the payload
def fix!
self.plen = self.payload.length
end
end
end
end
# vim: set ts=2 et sw=2:

View File

@ -25,8 +25,10 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
require 'ipaddr'
module Racket
module L3
# Miscelaneous L3 helper methods
module Misc
# given an IPv4 address packed as an integer
# return the friendly "dotted quad"
@ -39,37 +41,123 @@ module L3
quad.join(".")
end
def Misc.long2ipv6(long)
def Misc.randomipv4
Misc.long2ipv4(rand(2**32))
end
# Compute link local address for a given mac address
# From Daniele Bellucci
def Misc.linklocaladdr(mac)
mac = mac.split(":")
mac[0] = (mac[0].to_i(16) ^ (1 << 1)).to_s(16)
["fe80", "", mac[0,2].join, mac[2,2].join("ff:fe"), mac[4,2].join].join(":")
end
# Given a long, convert it to an IPv6 address,
# optionally compressing the address returned
def Misc.long2ipv6(long, compress=true)
ipv6 = []
ipv6[0] = long >> 112
ipv6[1] = (long >> 96) & (0xFFFF)
ipv6[2] = (long >> 80) & (0xFFFF)
ipv6[3] = (long >> 64) & (0xFFFF)
ipv6[4] = (long >> 48) & (0xFFFF)
ipv6[5] = (long >> 32) & (0xFFFF)
ipv6[6] = (long >> 16) & (0xFFFF)
ipv6[7] = long & (0xFFFF)
ipv6 = ipv6.map { |o| o.to_s(16) }.join(":")
compress ? Misc.compressipv6(ipv6) : ipv6
end
# Compress an IPv6 address
# Inspired by Daniele Bellucci and jacked from ipaddr
def Misc.compressipv6(ipv6)
ipv6.gsub!(/\b0{1,3}([\da-f]+)\b/i, '\1')
loop do
break if ipv6.sub!(/\A0:0:0:0:0:0:0:0\Z/, '::')
break if ipv6.sub!(/\b0:0:0:0:0:0:0\b/, ':')
break if ipv6.sub!(/\b0:0:0:0:0:0\b/, ':')
break if ipv6.sub!(/\b0:0:0:0:0\b/, ':')
break if ipv6.sub!(/\b0:0:0:0\b/, ':')
break if ipv6.sub!(/\b0:0:0\b/, ':')
break if ipv6.sub!(/\b0:0\b/, ':')
break
end
ipv6.sub!(/:{3,}/, '::')
if /\A::(ffff:)?([\da-f]{1,4}):([\da-f]{1,4})\Z/i =~ ipv6
ipv6 = sprintf('::%s%d.%d.%d.%d', $1, $2.hex / 256, $2.hex % 256, $3.hex / 256, $3.hex % 256)
end
ipv6
end
def Misc.randomipv6
Misc.long2ipv6(rand(2**128))
end
# given a string representing an IPv6
# address, return the integer representation
def Misc.ipv62long(ip)
IPAddr.new(ip).to_i
end
# In addition to the regular multicast addresses, each unicast address
# has a special multicast address called its solicited-node address. This
# address is created through a special mapping from the devices unicast
# address. Solicited-node addresses are used by the IPv6 Neighbor
# Discovery (ND) protocol to provide more efficient address resolution
# than the ARP technique used in IPv4.
# From Daniele Bellucci
def Misc.soll_mcast_addr6(addr)
h = addr.split(':')[-2, 2]
m = []
m << 'ff'
m << (h[0].to_i(16) & 0xff).to_s(16)
m << ((h[1].to_i(16) & (0xff << 8)) >> 8).to_s(16)
m << (h[1].to_i(16) & 0xff).to_s(16)
'ff02::1:' + [m[0,2].join, m[2,2].join].join(':')
end
#
def Misc.soll_mcast_mac(addr)
h = addr.split(':')[-2, 2]
m = []
m << 'ff'
m << (h[0].to_i(16) & 0xff).to_s(16)
m << ((h[1].to_i(16) & (0xff << 8)) >> 8).to_s(16)
m << (h[1].to_i(16) & 0xff).to_s(16)
'33:33:' + m.join(':')
end
# given a "dotted quad" representing an IPv4
# address, return the integer representation
def Misc.ipv42long(ip)
quad = ip.split(/\./)
quad.collect! {|s| s.to_i}
# XXX: replace this with an inject
quad[3] + (256 * quad[2]) + ((256**2) * quad[1]) + ((256**3) * quad[0])
IPAddr.new(ip).to_i
end
# Calculate the checksum. 16 bit one's complement of the one's
# complement sum of all 16 bit words
def Misc.checksum(data)
num_shorts = data.length / 2
csum = 0
checksum = 0
count = data.length
data.unpack("S#{num_shorts}").each { |x|
csum += x
checksum += x
count -= 2
}
if (count == 1)
csum += data[data.length - 1]
checksum += data[data.length - 1]
end
csum = (csum >> 16) + (csum & 0xffff)
csum = ~((csum >> 16) + csum) & 0xffff
([csum].pack("S*")).unpack("n*")[0]
checksum = (checksum >> 16) + (checksum & 0xffff)
checksum = ~((checksum >> 16) + checksum) & 0xffff
([checksum].pack("S*")).unpack("n*")[0]
end
end
end

View File

@ -25,10 +25,11 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
module Racket
module L3
# Spanning Tree Protocol
#
# http://en.wikipedia.org/wiki/Spanning_tree_protocol
module Racket
class STP < RacketPart
# Protocol identifier
unsigned :protocol, 16, { :default => 0 }
@ -76,4 +77,5 @@ class STP < RacketPart
rest :payload
end
end
end
# vim: set ts=2 et sw=2:

View File

@ -24,13 +24,7 @@
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
require 'racket/l4/igmpv1'
require 'racket/l4/igmpv2'
require 'racket/l4/igrp'
require 'racket/l4/gre'
require 'racket/l4/icmp'
require 'racket/l4/tcp'
require 'racket/l4/udp'
Dir.glob(File.join(File.dirname(__FILE__), 'l4/*.rb')).each { |f| require f }
# vim: set ts=2 et sw=2:

View File

@ -25,8 +25,9 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# XXX: currently broken. all of the "optional" fields must be made dynamic
module Racket
module L4
# XXX: currently broken. all of the "optional" fields must be made dynamic
class GRE < RacketPart
# Is a checksum present?
unsigned :checksum_present, 1
@ -60,4 +61,5 @@ class GRE < RacketPart
rest :payload
end
end
end
# vim: set ts=2 et sw=2:

View File

@ -25,11 +25,14 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
module Racket
module L4
# Internet Control Message Protcol.
#
# RFC792 (http://www.faqs.org/rfcs/rfc792.html)
module Racket
class ICMP < RacketPart
#
# Generic ICMP class from which all ICMP variants spawn. This should never be used directly.
class ICMPGeneric < RacketPart
ICMP_TYPE_ECHO_REPLY = 0
ICMP_TYPE_DESTINATION_UNREACHABLE = 3
ICMP_TYPE_SOURCE_QUENCH = 4
@ -51,22 +54,23 @@ class ICMP < RacketPart
# Code
unsigned :code, 8
# Checksum
unsigned :csum, 16
# ID
unsigned :id, 16
# Sequence number
unsigned :seq, 16
# Payload
rest :payload
unsigned :checksum, 16
rest :message
# check the checksum for this ICMP packet
def checksum?
self.csum == compute_checksum
self.checksum == compute_checksum
end
def initialize(*args)
super(*args)
@autofix = false
end
# compute and set the checksum for this ICMP packet
def checksum!
self.csum = compute_checksum
self.checksum = compute_checksum
end
# 'fix' this ICMP packet up for sending.
@ -78,9 +82,214 @@ class ICMP < RacketPart
private
def compute_checksum
# pseudo header used for checksum calculation as per RFC 768
pseudo = [ self.type, self.code, 0, self.id, self.seq, self.payload ]
L3::Misc.checksum(pseudo.pack("CCnnna*"))
pseudo = [ self.type, self.code, 0, self.message ]
L3::Misc.checksum(pseudo.pack("CCna*"))
end
end
# Send raw ICMP packets of your own design
class ICMP < ICMPGeneric
rest :payload
end
# ICMP Echo. Generic class that ICMPEchoRequest and ICMPEchoReply inherit
class ICMPEcho < ICMPGeneric
# ID for tracking requests/replies
unsigned :id, 16
# sequence number for tracking request/replies
unsigned :sequence, 16
rest :payload
def initialize(*args)
super(*args)
self.type = 8
self.code = 0
end
end
# ICMP Echo Request
class ICMPEchoRequest < ICMPEcho
rest :payload
def initialize(*args)
super(*args)
self.type = 8
self.code = 0
end
end
# ICMP Echo Reply
class ICMPEchoReply < ICMPEcho
rest :payload
def initialize(*args)
super(*args)
self.type = 0
self.code = 0
end
end
# ICMP Destination Unreachable Message
class ICMPDestinationUnreachable < ICMPGeneric
ICMP_CODE_NETWORK_UNREACHABLE = 0
ICMP_CODE_HOST_UNREACHABLE = 1
ICMP_CODE_PROTOCOL_UNREACHABLE = 2
ICMP_CODE_PORT_UNREACHABLE = 3
ICMP_CODE_FRAG_NEEDED_DF_SET = 4
ICMP_CODE_SOURCE_ROUTE_FAILED = 5
# This is never used according to the RFC
unsigned :unused, 32
# Internet header + 64 bits of original datagram
rest :payload
def initialize(*args)
super(*args)
self.type = 3
end
end
# ICMP Time Exceeded Message
class ICMPTimeExceeded < ICMPGeneric
ICMP_CODE_TTL_EXCEEDED_IN_TRANSIT = 0
ICMP_CODE_FRAG_REASSEMBLY_TIME_EXCEEDED = 1
# This is never used according to the RFC
unsigned :unused, 32
# Internet header + 64 bits of original datagram
rest :payload
def initialize(*args)
super(*args)
self.type = 11
end
end
# ICMP Parameter Problem Message
class ICMPParameterProblem < ICMPGeneric
# pointer to the octet where the error was detected
unsigned :pointer, 8
# This is never used according to the RFC
unsigned :unused, 24
# Internet header + 64 bits of original datagram
rest :payload
def initialize(*args)
super(*args)
self.type = 12
self.code = 0
end
end
# ICMP Source Quench Message
class ICMPSourceQuench < ICMPGeneric
# This is never used according to the RFC
unsigned :unused, 32
# Internet header + 64 bits of original datagram
rest :payload
def initialize(*args)
super(*args)
self.type = 4
self.code = 0
end
end
# ICMP Redirect Message
class ICMPRedirect < ICMPGeneric
ICMP_CODE_REDIRECT_NETWORK = 0
ICMP_CODE_REDIRECT_HOST = 1
ICMP_CODE_REDIRECT_TOS_NETWORK = 2
ICMP_CODE_REDIRECT_TOS_HOST = 3
# Gateway internet address
octets :gateway_ip, 32
# Internet header + 64 bits of original datagram
rest :payload
def initialize(*args)
super(*args)
self.type = 5
self.code = 0
end
end
# Generic ICMP Timestamp Message from which ICMPTimestampRequest and
# ICMPTimestampReply inherit
class ICMPTimestamp < ICMPGeneric
# an identifier to add in matching timestamp and replies
unsigned :id, 16
# a sequence number to aid in matching timestamp and replies
unsigned :sequence, 16
# time the sender last touched the message before sending it in number of milliseconds since midnight UT
unsigned :originate_timestamp, 32
# time the echoer first touched it on receipt in number of milliseconds since midnight UT
unsigned :receive_timestamp, 32
# time the echoers last touched the message on sending it in number of milliseconds since midnight UT
unsigned :transmit_timestamp, 32
# probably never used ...
rest :payload
def initialize(*args)
super(*args)
end
end
# ICMP Timestamp Request Message
class ICMPTimestampRequest < ICMPTimestamp
# probably never used ...
rest :payload
def initialize(*args)
super(*args)
self.type = 13
self.code = 0
end
end
# ICMP Timestamp Reply Message
class ICMPTimestampReply < ICMPTimestamp
# probably never used ...
rest :payload
def initialize(*args)
super(*args)
self.type = 14
self.code = 0
end
end
# ICMP Information Request Message
class ICMPInformationRequest < ICMPGeneric
# an identifier to add in matching timestamp and replies
unsigned :id, 16
# a sequence number to aid in matching timestamp and replies
unsigned :sequence, 16
# probably never used ...
rest :payload
def initialize(*args)
super(*args)
self.type = 15
self.code = 0
end
end
# ICMP Information Reply Message
class ICMPInformationReply < ICMPGeneric
# an identifier to add in matching timestamp and replies
unsigned :id, 16
# a sequence number to aid in matching timestamp and replies
unsigned :sequence, 16
# probably never used ...
rest :payload
def initialize(*args)
super(*args)
self.type = 16
self.code = 0
end
end
end
end
# vim: set ts=2 et sw=2:

446
lib/racket/l4/icmpv6.rb Normal file
View File

@ -0,0 +1,446 @@
# $Id: icmpv6.rb 157 2009-12-14 15:27:32Z jhart $
#
# Copyright (c) 2008, Jon Hart
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the <organization> nor the
# names of its contributors may be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY Jon Hart ``AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL Jon Hart BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
module Racket
module L4
# Internet Control Message Protcol, v6
#
# http://en.wikipedia.org/wiki/ICMPv6
#
# Generic ICMP class from which all ICMP variants spawn. This should never be used directly.
class ICMPv6Generic < RacketPart
ICMPv6_TYPE_ECHO_REPLY = 129
ICMPv6_TYPE_DESTINATION_UNREACHABLE = 1
ICMPv6_TYPE_PACKET_TOO_BIG = 2
ICMPv6_TYPE_ECHO_REQUEST = 128
ICMPv6_TYPE_TIME_EXCEEDED = 3
ICMPv6_TYPE_PARAMETER_PROBLEM = 4
ICMPv6_TYPE_MLD_QUERY = 130
ICMPv6_TYPE_MLD_REPORT = 131
ICMPv6_TYPE_MLD_DONE = 132
ICMPv6_TYPE_ROUTER_SOLICITATION = 133
ICMPv6_TYPE_ROUTER_ADVERTISEMENT = 134
ICMPv6_TYPE_NEIGHBOR_SOLICITATION = 135
ICMPv6_TYPE_NEIGHBOR_ADVERTISEMENT = 136
ICMPv6_TYPE_REDIRECT = 137
ICMPv6_TYPE_INFORMATION_REQUEST = 139
ICMPv6_TYPE_INFORMATION_REPLY = 140
# Type
unsigned :type, 8
# Code
unsigned :code, 8
# Checksum
unsigned :checksum, 16
rest :message
# check the checksum for this ICMP packet
def checksum?
self.checksum == compute_checksum
end
def initialize(*args)
super(*args)
@autofix = false
end
# Add an ICMPv6 option. RFC claims that the value should be padded (with what?)
# to land on a 64-bit boundary, however that doesn't always appear to be the case. so, yeah,
# try to pad on your own or pick strings that are multiples of 8 characters
def add_option(type, value)
t = Misc::TLV.new(1,1)
t.type = type
t.length = (value.length + 2) / 8
just = value.length + 2 + (8 - ((value.length + 2) % 8))
t.value = (value.length + 2) % 8 == 0 ? value : value.ljust(just, "\x00")
self.payload = t.encode + self.payload
end
# ignorantly assume the first parts of the payload contain ICMPv6 options
# and find a return an array of Racket::Misc::TLV representing the options
def get_options
p = self.payload
options = []
until ((o = Misc::TLV.new(1,1,8,true).decode(p)).nil?)
options << o[0..2]
p = o[3]
end
options
end
# compute and set the checksum for this ICMP packet
def checksum!(src_ip, dst_ip)
self.checksum = compute_checksum(src_ip, dst_ip)
end
# 'fix' this ICMP packet up for sending.
# (really, just set the checksum)
def fix!(src_ip, dst_ip)
self.checksum!(src_ip, dst_ip)
end
# get the source link layer address of this message, if found
def slla
addr = nil
self.get_options.each do |o|
type, length, value, rest = o.flatten
if (type == 1)
addr = L2::Misc.string2mac(value)
end
end
addr
end
# set the source link layer address of this message.
# expects +addr+ in de:ad:ba:dc:af:e0 form
def slla=(addr)
self.add_option(1, L2::Misc.mac2string(addr))
end
# get the target link layer address of this message, if found
def tlla
addr = nil
self.get_options.each do |o|
type, length, value, rest = o.flatten
if (type == 2)
addr = L2::Misc.string2mac(value)
end
end
addr
end
# set the target link layer address of this message
# expects +addr+ in de:ad:ba:dc:af:e0 form
def tlla=(addr)
self.add_option(2, L2::Misc.mac2string(addr))
end
private
def compute_checksum(src_ip, dst_ip)
s1 = src_ip >> 96
s2 = (src_ip >> 64) & 0xFFFFFFFF
s3 = (src_ip >> 32) & 0xFFFFFFFF
s4 = src_ip & 0xFFFFFFFF
d1 = dst_ip >> 96
d2 = (dst_ip >> 64) & 0xFFFFFFFF
d3 = (dst_ip >> 32) & 0xFFFFFFFF
d4 = dst_ip & 0xFFFFFFFF
# pseudo header used for checksum calculation as per RFC 768
pseudo = [ s1, s2, s3, s4, d1, d2, d3, d4, self.length, 58, self.type, self.code, 0, self.message ]
L3::Misc.checksum(pseudo.pack("NNNNNNNNNNCCna*"))
end
end
# Send raw ICMP packets of your own design
class ICMPv6 < ICMPv6Generic
rest :payload
end
# Generic ICMPv6 echo, used by ICMPv6EchoRequest and ICMPv6EchoReply
class ICMPv6Echo < ICMPv6Generic
# identifier to aid in matching echo requests/replies
unsigned :id, 16
# sequence number to aid in matching requests/replies
unsigned :sequence, 16
rest :payload
def initialize(*args)
super(*args)
end
end
# ICMPv6Echo Request
class ICMPv6EchoRequest < ICMPv6Echo
rest :payload
def initialize(*args)
super(*args)
self.type = ICMPv6_TYPE_ECHO_REQUEST
self.code = 0
end
end
# ICMPv6Echo Reply
class ICMPv6EchoReply < ICMPv6Echo
rest :payload
def initialize(*args)
super(*args)
self.type = ICMPv6_TYPE_ECHO_REPLY
self.code = 0
end
end
# ICMP Destination Unreachable Message
class ICMPv6DestinationUnreachable < ICMPv6Generic
ICMPv6_CODE_NO_ROUTE = 0
ICMPv6_CODE_ADMIN_PROHIBITED = 1
ICMPv6_CODE_BEYOND_SCOPE = 2
ICMPv6_CODE_ADDRESS_UNREACHABLE = 3
ICMPv6_CODE_PORT_UNREACHABLE = 4
ICMPv6_CODE_FAILED_POLICY = 4
ICMPv6_CODE_REJECT_ROUTE = 5
# This is never used according to the RFC
unsigned :unused, 32
# Internet header + 64 bits of original datagram
rest :payload
def initialize(*args)
super(*args)
self.type = ICMPv6_TYPE_DESTINATION_UNREACHABLE
end
end
class ICMPv6PacketTooBig < ICMPv6Generic
# The Maximum Transmission Unit of the next-hop link
unsigned :mtu, 32
rest :payload
def initialize(*args)
super(*args)
self.type = ICMPv6_TYPE_PACKET_TOO_BIG
end
end
# ICMP Time Exceeded Message
class ICMPv6TimeExceeded < ICMPv6Generic
ICMPv6_CODE_TTL_EXCEEDED_IN_TRANSIT = 0
ICMPv6_CODE_FRAG_REASSEMBLY_TIME_EXCEEDED = 1
# This is never used according to the RFC
unsigned :unused, 32
# As much of the original ICMPv6 packet without busting MTU
rest :payload
def initialize(*args)
super(*args)
self.type = ICMPv6_TYPE_TIME_EXCEEDED
end
end
# ICMPv6 Parameter Problem Message
class ICMPv6ParameterProblem < ICMPv6Generic
ICMPv6_CODE_ERRONEOUS_HEADER = 0
ICMPv6_CODE_UNRECOGNIZED_NEXT_HEADER = 1
ICMPv6_CODE_UNRECOGNIZED_OPTION = 2
# pointer to the octet where the error was detected
unsigned :pointer, 32
# As much of the original ICMPv6 packet without busting MTU
rest :payload
def initialize(*args)
super(*args)
self.type = ICMPv6_TYPE_PARAMETER_PROBLEM
end
end
# ICMPv6 Multicast Listener Discovery (MLD)
# http://www.faqs.org/rfcs/rfc2710.html
class ICMPv6MulticastListener < ICMPv6Generic
# maximum response delay
unsigned :delay, 16
# should be zero. never used.
unsigned :reserved, 16
# multicast address
unsigned :address, 128
rest :payload
def initialize(*args)
super(*args)
end
end
class ICMPv6MulticastListenerQuery < ICMPv6MulticastListener
rest :payload
def initialize(*args)
super(*args)
self.type = ICMPv6_TYPE_MLD_QUERY
end
end
class ICMPv6MulticastListenerReport < ICMPv6MulticastListener
rest :payload
def initialize(*args)
super(*args)
self.type = ICMPv6_TYPE_MLD_REPORT
end
end
class ICMPv6MulticastListenerDone < ICMPv6MulticastListener
rest :payload
def initialize(*args)
super(*args)
self.type = ICMPv6_TYPE_MLD_DONE
end
end
# http://tools.ietf.org/html/rfc4861
class ICMPv6RouterSolicitation < ICMPv6Generic
# should be 0, never used.
unsigned :reserved, 32
rest :payload
def initialize(*args)
super(*args)
self.type = ICMPv6_TYPE_ROUTER_SOLICITATION
end
end
# http://tools.ietf.org/html/rfc4861
class ICMPv6RouterAdvertisement < ICMPv6Generic
# default value that should be placed in the hop count field of the IP header
# for outgoing IP packets
unsigned :hop_limit, 8
# boolean, managed address configuration?
unsigned :managed_config, 1
# boolean, other configuration?
unsigned :other_config, 1
# set to 0, never used.
unsigned :reserved, 6
# lifetime associated with the default router in seconds
unsigned :lifetime, 16
# time in milliseconds that a node assumes a neighbor is reachable after having received a reachability confirmation
unsigned :reachable_time, 32
# time in milliseconds between retransmitted neighbor solicitation messages
unsigned :retrans_time, 32
rest :payload
def initialize(*args)
super(*args)
self.type = ICMPv6_TYPE_ROUTER_ADVERTISEMENT
end
end
# http://tools.ietf.org/html/rfc4861
class ICMPv6NeighborSolicitation < ICMPv6Generic
# set to 0, never used.
unsigned :reserved, 32
# target address of the solicitation
unsigned :address, 128
rest :payload
def initialize(*args)
super(*args)
self.type = ICMPv6_TYPE_NEIGHBOR_SOLICITATION
end
end
# http://tools.ietf.org/html/rfc4861
class ICMPv6NeighborAdvertisement < ICMPv6Generic
# normally this would be router (1), solicited (1), override(1) and reserved (2), however
# a bit-struct byte boundary bug bites us here
unsigned :bigbustedfield, 32
# for solicited adverts, the target address field in the solicitation that prompted this.
# for unsolicited adverts, the address whose link-layer address has changed
unsigned :address, 128
rest :payload
# set solicited flag
def solicited=(f)
self.bigbustedfield = (f << 30) ^ self.bigbustedfield
end
# set router flag
def router=(f)
self.bigbustedfield = (f << 31) ^ self.bigbustedfield
end
# set override flag
def override=(f)
self.bigbustedfield = (f << 29) ^ self.bigbustedfield
end
def initialize(*args)
super(*args)
self.type = ICMPv6_TYPE_NEIGHBOR_ADVERTISEMENT
end
end
# http://tools.ietf.org/html/rfc4861
class ICMPv6Redirect < ICMPv6Generic
# unused, should be 0
unsigned :reserved, 32
# the IP address that is a better first hop to use for the ICMP destination address
unsigned :src_ip, 128
# the IP address of the destination that is redirected to the target
unsigned :dst_ip, 128
rest :payload
def initialize(*args)
super(*args)
self.type = ICMPv6_TYPE_REDIRECT
end
end
# Generic class that IPv6NodeInformationRequest and Reply inherit from
# http://tools.ietf.org/html/rfc4620
class ICMPv6NodeInformation < ICMPv6Generic
# type of information requested in a query or supplied in a reply
unsigned :qtype, 16
# qtype-specific flags that may be defined for certain qtypes and their replies
unsigned :flags, 16
# opaque field to help avoid spoofing and/or to aid in matching replies with queries
text :nonce, 64
rest :payload
def initialize(*args)
super(*args)
end
end
# http://tools.ietf.org/html/rfc4620
class ICMPv6NodeInformationRequest < ICMPv6NodeInformation
ICMPv6_CODE_INFORMATION_REQUEST_IPv6 = 0
ICMPv6_CODE_INFORMATION_REQUEST_NAME = 1
ICMPv6_CODE_INFORMATION_REQUEST_IPv4 = 2
def initialize(*args)
super(*args)
self.type = ICMPv6_TYPE_INFORMATION_REQUEST
end
end
# http://tools.ietf.org/html/rfc4620
class ICMPv6NodeInformationReply < ICMPv6NodeInformation
ICMPv6_CODE_INFORMATION_REPLY_SUCCESS = 0
ICMPv6_CODE_INFORMATION_REPLY_REFUSE = 1
ICMPv6_CODE_INFORMATION_REPLY_UNKNOWN = 2
def initialize(*args)
super(*args)
self.type = ICMPv6_TYPE_INFORMATION_REPLY
end
end
end
end
# vim: set ts=2 et sw=2:

View File

@ -25,20 +25,21 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
module Racket
module L4
# Internet Group Management Protocol, Version 1
#
# RFC1112 (http://www.faqs.org/rfcs/rfc1112.html)
#
module Racket
class IGMPv1 < RacketPart
# Version (defaults to 1)
unsigned :version, 4
unsigned :version, 4, { :default => 1 }
# Type
unsigned :type, 4
# Unused
unsigned :unused, 8
# Checksum
unsigned :csum, 16
unsigned :checksum, 16
# Group Address
octets :gaddr, 32
# Payload
@ -46,12 +47,12 @@ class IGMPv1 < RacketPart
# Check the checksum for this IGMP message
def checksum?
self.csum == 0 || (self.csum == compute_checksum)
self.checksum == 0 || (self.checksum == compute_checksum)
end
# Compute and set the checkum for this IGMP message
def checksum!
self.csum = compute_checksum
self.checksum = compute_checksum
end
# Do whatever 'fixing' is neccessary in preparation
@ -74,4 +75,5 @@ private
end
end
end
end
# vim: set ts=2 et sw=2:

View File

@ -25,17 +25,18 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
module Racket
module L4
# Internet Group Management Protocol, Version 2: IGMPv2
#
# RFC2236 (http://www.faqs.org/rfcs/rfc2236.html)
module Racket
class IGMPv2 < RacketPart
# Type
unsigned :type, 8
# Max Response Time
unsigned :time, 8
# Checksum
unsigned :csum, 16
unsigned :checksum, 16
# Group Address
octets :gaddr, 32
# Payload
@ -43,12 +44,12 @@ class IGMPv2 < RacketPart
# Is the checksum of this IGMPv2 message correct
def checksum?
self.csum == 0 || (self.csum == compute_checksum)
self.checksum == 0 || (self.checksum == compute_checksum)
end
# Set the checksum of this IGMPv2 message
def checksum!
self.csum = compute_checksum
self.checksum = compute_checksum
end
# Do whatever 'fixing' is neccessary in preparation
@ -71,4 +72,5 @@ private
end
end
end
end
# vim: set ts=2 et sw=2:

View File

@ -25,6 +25,8 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
module Racket
module L4
# Internet Gateway Routing Protocol: IGRP
#
# http://www.cisco.com/warp/public/103/5.html
@ -37,7 +39,6 @@
# uchar reliability; /* percent packets successfully tx/rx */
# uchar load; /* percent of channel occupied */
# uchar hopcount; /* hop count */
module Racket
class IGRP < RacketPart
IGRP_UPDATE = 1
IGRP_REQUEST = 2
@ -132,5 +133,6 @@ private
end
end
end
end
# vim: set ts=2 et sw=2:

35
lib/racket/l4/misc.rb Normal file
View File

@ -0,0 +1,35 @@
# $Id: misc.rb 169 2009-12-18 16:12:34Z jhart $
#
# Copyright (c) 2008, Jon Hart
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the <organization> nor the
# names of its contributors may be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY Jon Hart ``AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL Jon Hart BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
#module Racket
#module L4
# # Miscelaneous L3 helper methods
# module Misc
# end
#end
#end
# vim: set ts=2 et sw=2:

160
lib/racket/l4/sctp.rb Normal file
View File

@ -0,0 +1,160 @@
# $Id: sctp.rb 162 2009-12-18 05:12:18Z jhart $
#
# Copyright (c) 2008, Jon Hart
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the <organization> nor the
# names of its contributors may be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY Jon Hart ``AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL Jon Hart BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
module Racket
module L4
# Stream Control Transmission Protocol
# http://tools.ietf.org/html/rfc4960
class SCTP < RacketPart
# Source port
unsigned :src_port, 16
# Destination port
unsigned :dst_port, 16
# Verification tag
unsigned :verification, 32
# Checksum
unsigned :checksum, 32
rest :payload
# Add a new SCTP chunk (see http://tools.ietf.org/html/rfc4960)
def add_chunk(type, flags, length, data)
@chunks << [ type, flags, length, data ]
end
def checksum?
self.checksum == compute_checksum
end
def checksum!
self.checksum = compute_checksum
end
# (really, just set the checksum)
def fix!
self.payload = ""
@chunks.each do |c|
self.payload += c.pack("CCna*")
end
self.checksum!
end
def initialize(*args)
@chunks = []
super
end
private
def compute_checksum
crc_c = [
0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4,
0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB,
0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B,
0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24,
0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B,
0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384,
0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54,
0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B,
0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A,
0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35,
0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5,
0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA,
0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45,
0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A,
0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A,
0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595,
0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48,
0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957,
0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687,
0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198,
0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927,
0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38,
0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8,
0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7,
0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096,
0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789,
0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859,
0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46,
0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9,
0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6,
0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36,
0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829,
0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C,
0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93,
0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043,
0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C,
0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3,
0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC,
0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C,
0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033,
0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652,
0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D,
0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D,
0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982,
0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D,
0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622,
0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2,
0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED,
0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530,
0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F,
0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF,
0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0,
0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F,
0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540,
0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90,
0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F,
0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE,
0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1,
0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321,
0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E,
0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81,
0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E,
0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E,
0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351
]
crc32 = ~0
header = [ self.src_port, self.dst_port, self.verification, 0 ].pack("CCnn")
(0..header.length-1).each do |b|
crc32 = (crc32 >> 8) ^ crc_c[(crc32^header[b]) & 0xFF]
end
result = ~crc32
byte0 = result & 0xff
byte1 = (result >> 8) & 0xff
byte2 = (result >> 16) & 0xff
byte3 = (result >> 24) & 0xff
crc32 = ((byte0 << 24) |
(byte1 << 16) |
(byte2 << 8) |
byte3)
end
end
end
end
# vim: set ts=2 et sw=2:

View File

@ -25,10 +25,11 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
module Racket
module L4
# Transmission Control Protocol: TCP
#
# RFC793 (http://www.faqs.org/rfcs/rfc793.html)
module Racket
class TCP < RacketPart
# Source port
unsigned :src_port, 16
@ -61,7 +62,7 @@ class TCP < RacketPart
# Window size
unsigned :window, 16
# Checksum
unsigned :csum, 16
unsigned :checksum, 16
# Urgent pointer
unsigned :urg, 16
# Payload
@ -71,7 +72,7 @@ class TCP < RacketPart
# All rejiggering will happen when the call to fix!
# happens automagically.
def add_option(number, value)
t = TLV.new(1,1)
t = Racket::Misc::TLV.new(1,1)
t.type = number
t.value = value
t.length = value.length + 2
@ -80,12 +81,12 @@ class TCP < RacketPart
# Check the checksum for this TCP packet
def checksum?(ip_src, ip_dst)
self.csum == compute_checksum(ip_src, ip_dst)
self.checksum == compute_checksum(ip_src, ip_dst)
end
# Compute and set the checksum for this TCP packet
def checksum!(ip_src, ip_dst)
self.csum = compute_checksum(ip_src, ip_dst)
self.checksum = compute_checksum(ip_src, ip_dst)
end
# Fix this packet up for proper sending. Sets the length
@ -104,10 +105,7 @@ class TCP < RacketPart
self.payload = newpayload + self.payload + next_payload
self.offset = self.class.bit_length/32 + newpayload.length/4
self.checksum!(ip_src, ip_dst)
end
def payload_data
self.payload[(self.offset * 4)-20, self.payload.length-((self.offset * 4)-20)] || ''
self.payload = newpayload
end
def initialize(*args)
@ -139,4 +137,5 @@ private
end
end
end
end
# vim: set ts=2 et sw=2:

View File

@ -25,10 +25,11 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
module Racket
module L4
# User Datagram Protocol: UDP
#
# RFC768 (http://www.faqs.org/rfcs/rfc768.html)
module Racket
class UDP < RacketPart
# Source Port
unsigned :src_port, 16
@ -37,20 +38,20 @@ class UDP < RacketPart
# Datagram Length
unsigned :len, 16
# Checksum
unsigned :csum, 16
unsigned :checksum, 16
# Payload
rest :payload
# Check the checksum for this UDP datagram
def checksum?(src_ip, dst_ip)
self.csum == 0 || (self.csum == compute_checksum(src_ip, dst_ip))
self.checksum == 0 || (self.checksum == compute_checksum(src_ip, dst_ip))
end
# Compute and set the checksum for this UDP datagram
def checksum!(src_ip, dst_ip)
# set the checksum to 0 for usage in the pseudo header...
self.csum = 0
self.csum = compute_checksum(src_ip, dst_ip)
self.checksum = 0
self.checksum = compute_checksum(src_ip, dst_ip)
end
# Fix this packet up for proper sending. Sets the length
@ -74,6 +75,7 @@ private
L3::Misc.checksum((pseudo << header).flatten.pack("NNnnnnnna*"))
end
end
end
end
# vim: set ts=2 et sw=2:

95
lib/racket/l4/vrrp.rb Normal file
View File

@ -0,0 +1,95 @@
# $Id: vrrp.rb 127 2009-11-29 01:30:46Z jhart $
#
# Copyright (c) 2008, Jon Hart
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the <organization> nor the
# names of its contributors may be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY Jon Hart ``AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL Jon Hart BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
module Racket
module L4
# Virtual Router Redundancy Protocol (VRRP)
# http://tools.ietf.org/html/rfc2338
# http://tools.ietf.org/html/rfc3768
class VRRP < RacketPart
# Version
unsigned :version, 4
# VRRP packet type
unsigned :type, 4
# Virtual Router Identifier (VRID)
unsigned :id, 8
# the sending VRRP router's priority for the virtual router.
# Higher values equal higher priority.
unsigned :priority, 8
# Total number of IPs contained in this VRRP message
unsigned :num_ips, 8
# Authentication type (0, 1, 2)
unsigned :auth_type, 8
# Advertisement interval
unsigned :interval, 8
# Checksum
unsigned :checksum, 16
rest :payload
# Add a new IP to this message
def add_ip(ip)
@ips << L3::Misc.ipv42long(ip)
end
# Add authentication data
def add_auth(authdata)
@authdata = authdata[0,8].ljust(32, "\x00")
end
# Validate the checksum
def checksum?
self.checksum == compute_checksum
end
# compute and set the checksum
def checksum!
self.checksum = compute_checksum
end
# (really, just set the checksum)
def fix!
self.payload = [@ips, @authdata].flatten.pack("N#{@ips.size}a*")
self.num_ips = @ips.size
self.checksum!
end
def initialize(*args)
@ips = []
@authdata = ""
super
end
private
def compute_checksum
# pseudo header used for checksum calculation as per RFC 768
pseudo = [ ((self.version << 4) | self.type), self.id, self.priority, self.num_ips, self.auth_type, self.interval, 0, self.payload ]
L3::Misc.checksum(pseudo.pack("CCCCCCna*"))
end
end
end
end
# vim: set ts=2 et sw=2:

View File

@ -24,11 +24,7 @@
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
require 'racket/l5/bootp'
require 'racket/l5/ntp'
require 'racket/l5/dns'
require 'racket/l5/hsrp'
require 'racket/l5/raw'
Dir.glob(File.join(File.dirname(__FILE__), 'l5/*.rb')).each { |f| require f }
# vim: set ts=2 et sw=2:

View File

@ -25,10 +25,11 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
module Racket
module L5
# Bootstrap Protocol -- BOOTP
#
# RFC951 (http://www.faqs.org/rfcs/rfc951.html)
module Racket
class BOOTP < RacketPart
BOOTP_REQUEST = 1
BOOTP_REPLY = 2
@ -65,7 +66,7 @@ class BOOTP < RacketPart
rest :payload
def add_option(number, value)
o = TLV.new(1,1)
o = Misc::TLV.new(1,1)
o.type = number
o.value = value
o.length = value.length
@ -99,6 +100,7 @@ class BOOTP < RacketPart
@autofix = false
end
end
end
end
# vim: set ts=2 et sw=2:

View File

@ -25,8 +25,9 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Domain Name System
module Racket
module L5
# Domain Name System
class DNS < RacketPart
# Transaction ID
unsigned :tx_id, 16
@ -91,9 +92,9 @@ class DNS < RacketPart
private
def add_record(name, type, klass)
q = VT.new(2,2)
q = Misc::VT.new(2,2)
name.split(/\./).each do |p|
lv = LV.new(1)
lv = Misc::LV.new(1)
lv.values << p
lv.lengths << p.length
q.value << lv.encode
@ -103,6 +104,7 @@ private
q
end
end
end
end
# vim: set ts=2 et sw=2:

View File

@ -25,10 +25,11 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
module Racket
module L5
# Hot Standby Router Protocol: HSRP
#
# RFC2281 (http://www.faqs.org/rfcs/rfc2281.html)
module Racket
class HSRP < RacketPart
HSRP_HELLO = 0
HSRP_COUP = 1
@ -58,6 +59,7 @@ class HSRP < RacketPart
unsigned :priority, 8
# Standby group
unsigned :group, 8
# reserved, never used, should be 0
unsigned :reserved, 8
# Clear-text, 8-character reused password. Defaults to 'cisco'
text :password, 64, { :default => 'cisco' }
@ -67,4 +69,5 @@ class HSRP < RacketPart
rest :payload
end
end
end
# vim: set ts=2 et sw=2:

35
lib/racket/l5/misc.rb Normal file
View File

@ -0,0 +1,35 @@
# $Id: misc.rb 167 2009-12-18 05:26:57Z jhart $
#
# Copyright (c) 2008, Jon Hart
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the <organization> nor the
# names of its contributors may be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY Jon Hart ``AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL Jon Hart BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
module Racket
module L5
# Miscelaneous L3 helper methods
module Misc
end
end
end
# vim: set ts=2 et sw=2:

View File

@ -26,6 +26,8 @@
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
module Racket
module L5
# Network time protocol
class NTP < RacketPart
# Leap Indicator
unsigned :leap, 2
@ -52,5 +54,6 @@ class NTP < RacketPart
rest :payload
end
end
end
# vim: set ts=2 et sw=2:

View File

@ -1,4 +1,4 @@
# $Id: misc.rb 14 2008-03-02 05:42:30Z warchild $
# $Id: misc.rb 125 2009-11-29 01:15:58Z jhart $
#
# Copyright (c) 2008, Jon Hart
# All rights reserved.
@ -24,46 +24,7 @@
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
module Racket
module Misc
# Return a number that is at most size bits long
def Misc.randbits(size)
bits = 0
srand Time.now.usec
0.upto(size-1) {
bits <<= 1
bits |= rand(2)
}
bits
end
# Return a byte that is at most size bytes long
def Misc.randbytes(size)
bytes = 0
0.upto(size-1) {
bytes <<= 8
bytes |= randbits(8)
}
bytes
end
Dir.glob(File.join(File.dirname(__FILE__), 'misc/*.rb')).each { |f| require f }
# Return a string that is at most size characters long
def Misc.randstring(size)
s = ""
0.upto(size-1) {
s += sprintf("%c", randbytes(1))
}
s
end
# given a long representing a MAC address
# print it out in human readable form
def Misc.macaddr(long)
long.to_s(16).rjust(12, '0').unpack("a2a2a2a2a2a2").join(":")
end
end
end
# vim: set ts=2 et sw=2:

108
lib/racket/misc/lv.rb Normal file
View File

@ -0,0 +1,108 @@
# $Id: lv.rb 14 2008-03-02 05:42:30Z warchild $
#
# Copyright (c) 2008, Jon Hart
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the <organization> nor the
# names of its contributors may be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY Jon Hart ``AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL Jon Hart BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
module Racket
module Misc
# Simple class to represent data structures that
# consist of an arbitrary number of length value pairs.
class LV
# An array containing the values parsed from this LV
attr_accessor :values
# The lengths of the values parsed from this LV
attr_accessor :lengths
# everything else
attr_accessor :rest
# Create a new LV object whose L sizes are specified in +args+
def initialize(*args)
@sizes = args
@values = []
@lengths = []
end
def decode(data)
n = 0
values = []
lengths = []
@sizes.each do |s|
# XXX: raise an error here if there is not enough data to
# unpack this next LV
lengths[n] = data.unpack("#{punpack_string(s)}")[0]
data = data.slice(s, data.length)
values[n] = data.unpack("a#{lengths[n]}")[0]
data = data.slice(lengths[n], data.length)
n += 1
end
# data now contains "rest"
[lengths, values, data]
end
def decode!(data)
@lengths, @values, @rest = self.decode(data)
end
def encode
n = 0
s = ""
@lengths.each do |l|
s << [l].pack("#{punpack_string(@sizes[n])}")
s << [@values[n]].pack("a#{l}")
n += 1
end
s
end
def to_s
encode
end
def to_str
encode
end
private
def punpack_string(size)
s = ""
case size
when 1
s << "C"
when 2
s << "n"
when 4
s << "N"
else
raise ArgumentError, "Size #{s} not supported"
end
s
end
end
end
end
# vim: set ts=2 et sw=2:

61
lib/racket/misc/misc.rb Normal file
View File

@ -0,0 +1,61 @@
# $Id: misc.rb 14 2008-03-02 05:42:30Z warchild $
#
# Copyright (c) 2008, Jon Hart
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the <organization> nor the
# names of its contributors may be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY Jon Hart ``AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL Jon Hart BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
module Racket
module Misc
# Return a number that is at most size bits long
def Misc.randbits(size)
bits = 0
srand Time.now.usec
0.upto(size-1) {
bits <<= 1
bits |= rand(2)
}
bits
end
# Return a byte that is at most size bytes long
def Misc.randbytes(size)
bytes = 0
0.upto(size-1) {
bytes <<= 8
bytes |= randbits(8)
}
bytes
end
# Return a string that is at most size characters long
def Misc.randstring(size)
s = ""
0.upto(size-1) {
s += sprintf("%c", randbytes(1))
}
s
end
end
end
# vim: set ts=2 et sw=2:

View File

@ -0,0 +1,63 @@
# $Id: orderedhash.rb 14 2008-03-02 05:42:30Z warchild $
#
# Copyright (c) 2008, Jon Hart
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the <organization> nor the
# names of its contributors may be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY Jon Hart ``AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL Jon Hart BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
module Racket
module Misc
# Simple ordered hash.
#
# XXX: todo -- add a method for moving/shifting
# members around
class OrderedHash < Hash
def initialize
@keys = []
end
def []=(key, val)
@keys << key unless (self[key])
super
end
def delete(key)
@keys.delete(key)
super
end
def each
@keys.each { |k| yield k, self[k] }
end
def each_key
@keys.each { |k| yield k }
end
def each_value
@keys.each { |k| yield self[k] }
end
end
end
end
# vim: set ts=2 et sw=2:

103
lib/racket/misc/tlv.rb Normal file
View File

@ -0,0 +1,103 @@
# $Id: tlv.rb 14 2008-03-02 05:42:30Z warchild $
#
# Copyright (c) 2008, Jon Hart
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the <organization> nor the
# names of its contributors may be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY Jon Hart ``AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL Jon Hart BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
module Racket
module Misc
# Simple class for your average type, length, value datastructure.
# Everything after the TLV is stuff into +rest+
class TLV
attr_accessor :type, :length, :value, :rest, :lbytes, :tlinclude
# Create a new TLV which requires +ts+ bytes for the type field
# and +ls+ bytes for the length field, where (optionally) the value
# in +length+ is a multiple of +lbytes+ and (optionally) whether or not
# the length field indicates the total length of the TLV of just that of
# the value
def initialize(ts, ls, lbytes=1, tlinclude=false)
@ts = ts
@ls = ls
@lbytes = lbytes
@tlinclude = tlinclude
end
# Given +data+, return the type, length, value and rest
# values as dictated by this instance.
def decode(data)
s = "#{punpack_string(@ts)}#{punpack_string(@ls)}"
type, length, tmp = data.unpack("#{s}a*")
if (type.nil? or length.nil?)
nil
else
elength = (length * lbytes) - (@tlinclude ? (@ls + @ts) : 0)
value, rest = tmp.unpack("a#{elength}a*")
if (value.empty? and length > 0)
nil
else
[type, length, value, rest]
end
end
end
def decode!(data)
@type, @length, @value, @rest = self.decode(data)
end
# Return a string suitable for use elswhere.
def encode
s = "#{punpack_string(@ts)}#{punpack_string(@ls)}"
[@type, @length, @value].pack("#{s}a*")
end
def to_s
encode
end
def to_str
encode
end
private
# XXX: make this handle arbitrarily sized fields
def punpack_string(size)
s = ""
case size
when 1
s << "C"
when 2
s << "n"
when 4
s << "N"
else
raise ArgumentError, "Size #{s} is not a supported conversion size"
end
s
end
end
end
end
# vim: set ts=2 et sw=2:

114
lib/racket/misc/vt.rb Normal file
View File

@ -0,0 +1,114 @@
# $Id: vt.rb 14 2008-03-02 05:42:30Z warchild $
#
# Copyright (c) 2008, Jon Hart
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the <organization> nor the
# names of its contributors may be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY Jon Hart ``AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL Jon Hart BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
module Racket
module Misc
# Simple class to represent a datastructure that is made up of a
# null terminted string followed by an arbitrary number of
# arbitrarily sized values, followed by a "rest" field.
class VT
# the value for this VT object
attr_accessor :value
# the array of types for this VT object
attr_accessor :types
# everything else
attr_accessor :rest
# Create a new VT which consists of a null terminated string
# followed by some number of arbitrarily sized values, as
# specified by +args+
def initialize(*args)
@lengths = args
@types = []
@value = ""
end
# Given +data+, return the value and an array
# of the types as dictated by this instance
def decode(data)
null = data.index(0x00)
value = data.unpack("a#{null}")[0]
data = data.slice(null+1, data.length)
n = 0
types = []
@lengths.each do |l|
types[n] = data.unpack("#{punpack_string(l)}")[0]
data = data.slice(l, data.length)
n += 1
end
[value, types, data]
end
# Given +data+, set the +value+ and +types+ array
# accordingly
def decode!(data)
@value, @types, @rest = self.decode(data)
end
# Return a string suitable for use elsewhere
def encode
s = "#{@value}\000"
n = 0
@lengths.each do |l|
s << [@types[n]].pack("#{punpack_string(l)}")
n += 1
end
s
end
def to_s
encode
end
def to_str
encode
end
private
# XXX: make this handle arbitrarily sized fields
def punpack_string(size)
s = ""
case size
when 1
s << "C"
when 2
s << "n"
when 4
s << "N"
else
raise ArgumentError, "Size #{s} not supported"
end
s
end
end
end
end
# vim: set ts=2 et sw=2:

View File

@ -27,18 +27,13 @@
#
require 'socket'
require 'racket/racketpart'
require 'racket/tlv'
require 'racket/lv'
require 'racket/vt'
require 'racket/misc'
require 'racket/l2'
require 'racket/l3'
require 'racket/l4'
require 'racket/l5'
module Racket
class Racket
@ -47,11 +42,12 @@ class Racket
@@loaded_pcaprub = false
begin
require 'pcaprub'
@@loaded_pcaprub = true
require 'pcaprub'
@@loaded_pcaprub = true
rescue ::LoadError
end
def initialize(payload="")
@layers = []
@mtu = 1500
@ -102,6 +98,7 @@ class Racket
payload
end
# return a pretty interpretation of this packet
def pretty
s = ""
@layers.compact.each do |l|
@ -125,10 +122,10 @@ class Racket
# Write raw layer2 frames
def send2
if(not @@loaded_pcaprub)
raise RuntimeError, "Could not initialize the pcaprub library"
end
raise RuntimeError, "Could not initialize the pcaprub library (You need pcaprub from SVN (http://rubyforge.org/projects/pcaprub/))"
end
begin
p = Pcap::open_live(@iface, @mtu, false, @timeout)
rescue Exception => e
puts "Pcap: can't open device '#{@iface}' (#{e})"
@ -137,7 +134,7 @@ class Racket
begin
b = p.inject(pack)
p.close
#p.pcap_close
return b
rescue Exception => e
puts "Pcap: error while sending packet on '#{@iface}' (#{e})"
@ -148,16 +145,20 @@ class Racket
def send3
begin
s = Socket.open(Socket::PF_INET, Socket::SOCK_RAW, Socket::IPPROTO_RAW)
#s.setsockopt(Socket::SOL_IP, Socket::IP_HDRINCL, true)
if (Socket.const_defined?('SOL_IP'))
s.setsockopt(Socket::SOL_IP, Socket::IP_HDRINCL, true)
else
# BSD
s.setsockopt(Socket::IPPROTO_IP, Socket::IP_HDRINCL, true)
end
rescue Errno::EPERM
$stderr.puts "Must run #{$0} as root."
exit!
raise ArgumentError, "Must run #{$0} as root."
end
return s.send(pack, 0, Socket.pack_sockaddr_in(1024, @layers[3].dst_ip))
end
end
end
# vim: set ts=2 et sw=2:

View File

@ -25,9 +25,11 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
require 'rubygems'
require 'bit-struct'
module Racket
# Every Racket object is made up of numerous sub-parts, namely layers of the OSI stack.
class RacketPart < BitStruct
# Boolean indicating whether or not this instance should be
@ -42,9 +44,10 @@ class RacketPart < BitStruct
def initialize(*args)
@autofix = true
super
super(*args)
end
# Print out all of the fields and all of their values
def pretty
s = ""