#!/usr/bin/perl -w # # delay-net.pl: insert arbitrary packet delay # (c) Copyright 2005, Daniel Berrange, based on: # # countertrace, a traceroute faker # (c) Copyright 2002 Michael C. Toren # # Released under the terms of the GNU General Public Liense, version 2. # Alternate licensing may be available if you have a specific need; # please send mail to mct@toren.net with details describing you unique # situation. # # Updates are available from http://michael.toren.net/code/countertrace/ use strict; use warnings; use IPTables::IPv4::IPQueue qw(:constants); use Digest::MD5 qw(md5_base64); use Time::HiRes qw(gettimeofday); my @queue; my $delay = shift @ARGV; $delay = 250 unless defined $delay; my $debug = shift @ARGV; $debug = 0 unless defined $debug; my $id = 0; my %seen; $delay = $delay / 1000; print "Delay by $delay seconds\n"; $| = 1; my $ipq = new IPTables::IPv4::IPQueue (copy_mode => IPQ_COPY_PACKET, copy_range => 2000) or die "Could not initialize IPQ: ", IPTables::IPv4::IPQueue->errstr, "\n"; &process(); exit 0; sub process { while (1) { print "Tick ", time, "\n" if $debug > 1; # process oustanding queued packets my $now1 = gettimeofday; @queue = grep { if ($now1 + 0.003 >= $_->{time}) { print "Deliver: ", $_->{msg}->packet_id, "\n"; $ipq->set_verdict($_->{msg}->packet_id, NF_ACCEPT); 0; } else { 1; } } @queue; # set the timeout for when the next packet is due to go off, or 60 seconds my ($nap) = (sort { $a->{time} <=> $b->{time} } @queue, { time => $now1 + 60 }); $nap = $nap->{time} - gettimeofday; # Get next message off the queue, timing out after $nap u-seconds my $msg = $ipq->get_message($nap * 1_000_000); unless (defined $msg) { die "ipq: [", IPTables::IPv4::IPQueue->errstr, "]\n" unless (IPTables::IPv4::IPQueue->errstr =~ /^timeout/i); next; } unless ($msg->data_len) { print "Ignoring zero-length ipq message\n" if $debug; next; } my $pid = $msg->packet_id; print "In: ", md5_base64($msg->payload), "\n"; # process the received message my $now = gettimeofday; # Figure out when it needs to go back out... my $alarm = $now + $delay; # Queue if for the future print "Queue: ", $msg->packet_id, "\n"; push @queue, { time => $delay + $now, msg => $msg }; } }