--------------080709010801000306020303
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit
Hello!
I have captured the TCP/IP traffic of an application with tcpdump -w, and
now I would like to read in the file to replay the traffic, can you
advise any tools/libraries to do this? (preferably Ruby ones.) I work on
a Linux box, the dump contains both TCP and UDP packets. I want to use
Ruby here because I need to adjust some data of the dump when replaying.
I guess tcpdump -w writes raw packets, so you will need to send out the
same data as raw packets.
Here are some files to do that. Start with send.rb. Take out the
readline code. Add code to read each packet data as a string, and call
IP.new on it to get a packet, and then call send with the packet. The IP
methods will help with manipulating the packet data (in particular, you
can treat the whole packet as a string). The send-recv.rb file is nice
for debugging. Of course, all have to be run as root.
BTW, these three files are ruby prototypes for a library I am working on
to generate C code (and ruby wrappers) for doing similar things with raw
IP packets and packet options, esp. DSRC wireless options. I'll make it
available in a few weeks, probably.
--------------080709010801000306020303
Content-Type: text/plain;
name="ip.rb"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="ip.rb"
require 'scanf'
# based on icmp.rb Copyright (C) 2000 GOTOU YUUZOU <
[email protected]>
class IP < String
def self.new(s=nil); s ? super(s) : super("\0" * 20); end
def ip_v; (self[0] >> 4) & 0x0f; end
def ip_v=(v); self[0] = (v << 4) | (self[0] & 0x0f); end
def ip_hl; self[0] & 0xf end
def ip_hl=(v); self[0] = (self[0] & 0xf0) | (v & 0x0f); end
def ip_tos; self[1]; end
def ip_tos=(v); self[1] = v; end
def ip_len; self[2..3].unpack("n")[0]; end
def ip_len=(v); self[2..3]=[v].pack("n"); end
def ip_id; self[4..5].unpack("n")[0]; end
def ip_id=(v); self[4..5]=[v].pack("n"); end
def ip_off; self[6..7].unpack("n")[0]; end
def ip_off=(v); self[6..7]=[v].pack("n"); end
def ip_ttl; self[8]; end
def ip_ttl=(v); self[8]=v; end
def ip_p; self[9]; end
def ip_p=(v); self[9]=v; end
def ip_sum; self[10..11].unpack("n")[0]; end
def ip_sum=(v); self[10..11]=[v].pack("n"); end
def ip_src; "%d.%d.%d.%d" % [self[12], self[13], self[14], self[15]]; end
def ip_src=(s); self[12..15] = s.scanf("%d.%d.%d.%d").pack("c*"); end
def ip_dst; "%d.%d.%d.%d" % [self[16], self[17], self[18], self[19]]; end
def ip_dst=(s); self[16..19] = s.scanf("%d.%d.%d.%d").pack("c*"); end
def body; self[(ip_hl*4)..-1]; end
def body=(s); self[(ip_hl*4)..-1] = s; end
# def inspect; "<IP: size=#{size} src=#{ip_src} dst=#{ip_dst}>"; end
IP_FIELDS = [
["Version", :ip_v ],
["Header length", :ip_hl ],
["TOS", :ip_tos ],
["Length", :ip_len ],
["ID", :ip_id ],
["Frag offset", :ip_off ],
["TTL", :ip_ttl ],
["Protocol", :ip_p ],
["Checksum", :ip_sum ],
["Source addr", :ip_src ],
["Dest addr", :ip_dst ]
]
def details
IP_FIELDS.map do |name, meth|
sprintf("%20s = %s\n", name, send(meth))
end <<
sprintf("%20s = %s\n", "Body", body.inspect)
end
end
if __FILE__ == $0
ip = IP.new
ip.ip_v = 4
ip.ip_hl = 5 ## ?
ip.ip_tos = 0
ip.ip_len = 0
ip.ip_id = 0
ip.ip_off = 0
ip.ip_ttl = 255
ip.ip_p = 255
ip.ip_sum = 0
ip.ip_src = "192.168.1.4"
ip.ip_dst = "192.168.1.255"
print ip.details
end
--------------080709010801000306020303
Content-Type: text/plain;
name="send-recv.rb"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="send-recv.rb"
require "socket"
require "ip"
require "readline"
begin
rsock = Socket.open(Socket:

F_INET, Socket::SOCK_RAW, Socket::IPPROTO_RAW)
rescue Errno::EPERM => e
raise e, "You must be root to run this program."
end
rsock.setsockopt(Socket::SOL_SOCKET, Socket::SO_BROADCAST, true)
listener = Thread.new do
loop do
data, sender = rsock.recvfrom(8192)
port, host = Socket.unpack_sockaddr_in(sender)
puts
puts "-"*80
puts "packet received from #{host}:#{port}:"
puts IP.new(data).details
$stdout.flush
end
end
sockaddr = Socket.pack_sockaddr_in(1024, "127.0.0.1")
#dst_port, dst_host = Socket.unpack_sockaddr_in(sockaddr)
#src_port, src_host = Socket.unpack_sockaddr_in(rsock.getsockname)
ip = IP.new
ip.ip_v = 4
ip.ip_hl = 5
ip.ip_tos = 0
ip.ip_len = 0
ip.ip_id = 0
ip.ip_off = 0
ip.ip_ttl = 255
ip.ip_p = Socket::IPPROTO_RAW
ip.ip_sum = 0
# ip.ip_src = src_host <-- filled in by socket
# ip.ip_dst = dst_host
loop do
line = Readline.readline("input> ", true)
break unless line
ip.body = line
rsock.send(ip, 0, sockaddr)
end
listener.kill
rsock.close
--------------080709010801000306020303
Content-Type: text/plain;
name="send.rb"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="send.rb"
require "socket"
require "ip"
require "readline"
rsock = Socket.open(Socket:

F_INET, Socket::SOCK_RAW, Socket::IPPROTO_RAW)
sockaddr = Socket.pack_sockaddr_in(1024, "localhost")
ip = IP.new
ip.ip_v = 4
ip.ip_hl = 5
ip.ip_tos = 0
ip.ip_len = 0
ip.ip_id = 0
ip.ip_off = 0
ip.ip_ttl = 255
ip.ip_p = 255
ip.ip_sum = 0
ip.ip_src = "192.168.1.4"
ip.ip_dst = "192.168.1.255"
loop do
line = Readline.readline("input> ", true)
break unless line
ip.body = line
rsock.send(ip, 0, sockaddr)
end
rsock.close
--------------080709010801000306020303--