Skip to content

Instantly share code, notes, and snippets.

@zunda
Created December 7, 2011 07:15
Show Gist options
  • Save zunda/1441829 to your computer and use it in GitHub Desktop.
Save zunda/1441829 to your computer and use it in GitHub Desktop.
A script to create byte sequence of an arp packet. This can not emit packet onto the network.
#!/usr/bin/env ruby
# asks for IP address of a MAC address
#
# Copyright (c) 2011 zunda <zunda at freeshell.org>
#
# Permission is granted for use, copying, modification,
# distribution, and distribution of modified versions of this
# work as long as the above copyright notice is included.
#
# ARP message over Ethenet ARP packet
# http://en.wikipedia.org/wiki/Address_Resolution_Protocol
class ARPMessage
attr_accessor :htype # Hardware type
attr_accessor :ptype # Protocol type
attr_accessor :hlen # Hardware address length
attr_accessor :plen # Protocol address length
attr_accessor :oper # Operation
attr_accessor :sha # Sender hardware address
attr_accessor :spa # Sender protocol address
attr_accessor :tha # Target hardware address
attr_accessor :tpa # Target protocol address
# http://www.javvin.com/protocolARP.html
OperCode = {
:ARP_request => 1,
:ARP_response => 2,
:RARP_response => 3,
:RARP_response => 4,
:Dynamic_RARP_response => 5,
:Dynamic_RARP_response => 6,
:Dynamic_RARP_error => 7,
:InARP_request => 8,
:InARP_response => 9,
}
def initialize(htype = 1, ptype = 0x0800, hlen = 6, plen = 4)
@htype = htype # 1:Ethernet
@ptype = ptype # 0x0800:IPv4
@hlen = hlen # 6:Ethernet
@plen = plen # 4:IPv4
end
def msg
raise 'oper must be set' unless @oper
result = [@htype, @ptype, @hlen, @plen, @oper].pack('n2C2n')
result += @sha.bytes.to_a.pack("C#{@hlen}")
result += (@spa || "\x00"*@plen).bytes.to_a.pack("C#{@plen}")
result += (@tha || "\x00"*@hlen).bytes.to_a.pack("C#{@hlen}")
result += (@tpa || "\x00"*@plen).bytes.to_a.pack("C#{@plen}")
return result
end
def ARPMessage.parse(message)
result = ARPMessage.new
result.htype, result.ptype, result.hlen, result.plen, result.oper = message.slice!(0,8).unpack('n2C2n')
result.sha = message.slice!(0,result.hlen)
result.spa = message.slice!(0,result.plen)
result.tha = message.slice!(0,result.hlen)
result.tpa = message.slice!(0,result.plen)
return result
end
end
if __FILE__ == $0
require 'test/unit'
class TestARPMessage < Test::Unit::TestCase
def setup
@oper = ARPMessage::OperCode[:ARP_request]
@sha = "\x00\x00\x00\x12\x34\x56"
@spa = "\xc0\xa8\x01\x01"
@tpa = "\xc0\xa8\x01\x40"
@packet = ARPMessage.new
@packet.oper = @oper
@packet.sha = @sha
@packet.spa = @spa
@packet.tpa = @tpa
end
def test_creation
assert_equal("\x00\x01\x08\x00\x06\x04\x00\x01\x00\x00\x00\x12\x34\x56\xc0\xa8\x01\x01\x00\x00\x00\x00\x00\x00\xc0\xa8\x01\x40", @packet.msg)
end
def test_parse
packet = ARPMessage.parse(@packet.msg)
assert_equal(1, packet.htype, 'htype')
assert_equal(@oper, packet.oper, 'oper')
assert_equal(@sha, packet.sha, 'sha')
assert_equal(@spa, packet.spa, 'spa')
assert_equal("\x00"*6, packet.tha, 'tha')
assert_equal(@tpa, packet.tpa, 'tpa')
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment