--------------080709010801000306020303
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit

Sven C. Koehler wrote:
> 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;
 namep.rb"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filenamep.rb"

require 'scanf'

# based on icmp.rb Copyright (C) 2000 GOTOU YUUZOU <gotoyuzo / notwork.org>
class IP < String
  def self.new(sl); s ? super(s) : super("\0" * 20); end

  def ip_v;       (self[0] >> 4) & 0x0f; end
  def ip_v);   self[0]  v << 4) | (self[0] & 0x0f); end

  def ip_hl;      self[0] & 0xf end
  def ip_hl);  self[0]  self[0] & 0xf0) | (v & 0x0f); end

  def ip_tos;     self[1]; end
  def ip_tos); self[1]  ; end

  def ip_len;     self[2..3].unpack("n")[0]; end
  def ip_len); self[2..3]].pack("n"); end

  def ip_id;      self[4..5].unpack("n")[0]; end
  def ip_id);  self[4..5]].pack("n"); end

  def ip_off;     self[6..7].unpack("n")[0]; end
  def ip_off); self[6..7]].pack("n"); end

  def ip_ttl;     self[8]; end
  def ip_ttl); self[8] end

  def ip_p;       self[9]; end
  def ip_p);   self[9] end

  def ip_sum;     self[10..11].unpack("n")[0]; end
  def ip_sum); self[10..11]].pack("n"); end

  def ip_src;     "%d.%d.%d.%d" % [self[12], self[13], self[14], self[15]]; end
  def ip_src); self[12..15]  .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); self[16..19]  .scanf("%d.%d.%d.%d").pack("c*"); end

  def body;       self[(ip_hl*4)..-1]; end
  def body);   self[(ip_hl*4)..-1]  ; end

#    def inspect; "<IP: sizesize} srcip_src} dstip_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  P.new
  ip.ip_v    
  ip.ip_hl    ## ?
  ip.ip_tos  
  ip.ip_len  
  ip.ip_id   
  ip.ip_off  
  ip.ip_ttl  55
  ip.ip_p    55
  ip.ip_sum  
  ip.ip_src  192.168.1.4"
  ip.ip_dst  192.168.1.255"

  print ip.details
end


--------------080709010801000306020303
Content-Type: text/plain;
 nameend-recv.rb"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filenameend-recv.rb"

require "socket"
require "ip"
require "readline"

begin
  rsock  ocket.open(Socket::PF_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  hread.new do
  loop do
    data, sender  sock.recvfrom(8192)
    port, host  ocket.unpack_sockaddr_in(sender)
    puts
    puts "-"*80
    puts "packet received from #{host}:#{port}:"
    puts IP.new(data).details
    $stdout.flush
  end
end

sockaddr  ocket.pack_sockaddr_in(1024, "127.0.0.1")
#dst_port, dst_host  ocket.unpack_sockaddr_in(sockaddr)
#src_port, src_host  ocket.unpack_sockaddr_in(rsock.getsockname)

ip  P.new
  ip.ip_v    
  ip.ip_hl   
  ip.ip_tos  
  ip.ip_len  
  ip.ip_id   
  ip.ip_off  
  ip.ip_ttl  55
  ip.ip_p    ocket::IPPROTO_RAW
  ip.ip_sum  
#  ip.ip_src  rc_host   <-- filled in by socket
#  ip.ip_dst  st_host

loop do
  line  eadline.readline("input> ", true)
  break unless line
  ip.body  ine
  rsock.send(ip, 0, sockaddr)
end

listener.kill
rsock.close


--------------080709010801000306020303
Content-Type: text/plain;
 nameend.rb"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filenameend.rb"

require "socket"
require "ip"
require "readline"

rsock  ocket.open(Socket::PF_INET, Socket::SOCK_RAW, Socket::IPPROTO_RAW)
sockaddr  ocket.pack_sockaddr_in(1024, "localhost")

ip  P.new
  ip.ip_v    
  ip.ip_hl   
  ip.ip_tos  
  ip.ip_len  
  ip.ip_id   
  ip.ip_off  
  ip.ip_ttl  55
  ip.ip_p    55
  ip.ip_sum  
  ip.ip_src  192.168.1.4"
  ip.ip_dst  192.168.1.255"

loop do
  line  eadline.readline("input> ", true)
  break unless line
  ip.body  ine
  rsock.send(ip, 0, sockaddr)
end

rsock.close


--------------080709010801000306020303--