--------------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; name p.rb" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename p.rb" require 'scanf' # based on icmp.rb Copyright (C) 2000 GOTOU YUUZOU <gotoyuzo / notwork.org> class IP < String def self.new(s l); 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: 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 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; name end-recv.rb" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename end-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; name end.rb" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename end.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--