1*00b67f09SDavid van Moolenbroek#!/usr/bin/perl 2*00b67f09SDavid van Moolenbroek# 3*00b67f09SDavid van Moolenbroek# Copyright (C) 2011, 2012 Internet Systems Consortium, Inc. ("ISC") 4*00b67f09SDavid van Moolenbroek# 5*00b67f09SDavid van Moolenbroek# Permission to use, copy, modify, and/or distribute this software for any 6*00b67f09SDavid van Moolenbroek# purpose with or without fee is hereby granted, provided that the above 7*00b67f09SDavid van Moolenbroek# copyright notice and this permission notice appear in all copies. 8*00b67f09SDavid van Moolenbroek# 9*00b67f09SDavid van Moolenbroek# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10*00b67f09SDavid van Moolenbroek# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11*00b67f09SDavid van Moolenbroek# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12*00b67f09SDavid van Moolenbroek# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13*00b67f09SDavid van Moolenbroek# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14*00b67f09SDavid van Moolenbroek# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15*00b67f09SDavid van Moolenbroek# PERFORMANCE OF THIS SOFTWARE. 16*00b67f09SDavid van Moolenbroek 17*00b67f09SDavid van Moolenbroek# Id: packet.pl,v 1.2 2011/04/15 01:02:08 each Exp 18*00b67f09SDavid van Moolenbroek 19*00b67f09SDavid van Moolenbroek# This is a tool for sending an arbitrary packet via UDP or TCP to an 20*00b67f09SDavid van Moolenbroek# arbitrary address and port. The packet is specified in a file or on 21*00b67f09SDavid van Moolenbroek# the standard input, in the form of a series of bytes in hexidecimal. 22*00b67f09SDavid van Moolenbroek# Whitespace is ignored, as is anything following a '#' symbol. 23*00b67f09SDavid van Moolenbroek# 24*00b67f09SDavid van Moolenbroek# For example, the following input would generate normal query for 25*00b67f09SDavid van Moolenbroek# isc.org/NS/IN": 26*00b67f09SDavid van Moolenbroek# 27*00b67f09SDavid van Moolenbroek# # QID: 28*00b67f09SDavid van Moolenbroek# 0c d8 29*00b67f09SDavid van Moolenbroek# # header: 30*00b67f09SDavid van Moolenbroek# 01 00 00 01 00 00 00 00 00 00 31*00b67f09SDavid van Moolenbroek# # qname isc.org: 32*00b67f09SDavid van Moolenbroek# 03 69 73 63 03 6f 72 67 00 33*00b67f09SDavid van Moolenbroek# # qtype NS: 34*00b67f09SDavid van Moolenbroek# 00 02 35*00b67f09SDavid van Moolenbroek# # qclass IN: 36*00b67f09SDavid van Moolenbroek# 00 01 37*00b67f09SDavid van Moolenbroek# 38*00b67f09SDavid van Moolenbroek# Note that we do not wait for a response for the server. This is simply 39*00b67f09SDavid van Moolenbroek# a way of injecting arbitrary packets to test server resposnes. 40*00b67f09SDavid van Moolenbroek# 41*00b67f09SDavid van Moolenbroek# Usage: packet.pl [-a <address>] [-p <port>] [-t (udp|tcp)] [filename] 42*00b67f09SDavid van Moolenbroek# 43*00b67f09SDavid van Moolenbroek# If not specified, address defaults to 127.0.0.1, port to 53, protocol 44*00b67f09SDavid van Moolenbroek# to udp, and file to stdin. 45*00b67f09SDavid van Moolenbroek# 46*00b67f09SDavid van Moolenbroek# XXX: Doesn't support IPv6 yet 47*00b67f09SDavid van Moolenbroek 48*00b67f09SDavid van Moolenbroekrequire 5.006.001; 49*00b67f09SDavid van Moolenbroek 50*00b67f09SDavid van Moolenbroekuse strict; 51*00b67f09SDavid van Moolenbroekuse Getopt::Std; 52*00b67f09SDavid van Moolenbroekuse IO::File; 53*00b67f09SDavid van Moolenbroekuse IO::Socket; 54*00b67f09SDavid van Moolenbroek 55*00b67f09SDavid van Moolenbroeksub usage { 56*00b67f09SDavid van Moolenbroek print ("Usage: packet.pl [-a address] [-p port] [-t (tcp|udp)] [file]\n"); 57*00b67f09SDavid van Moolenbroek exit 1; 58*00b67f09SDavid van Moolenbroek} 59*00b67f09SDavid van Moolenbroek 60*00b67f09SDavid van Moolenbroekmy %options={}; 61*00b67f09SDavid van Moolenbroekgetopts("a:p:t:", \%options); 62*00b67f09SDavid van Moolenbroek 63*00b67f09SDavid van Moolenbroekmy $addr = "127.0.0.1"; 64*00b67f09SDavid van Moolenbroek$addr = $options{a} if defined $options{a}; 65*00b67f09SDavid van Moolenbroek 66*00b67f09SDavid van Moolenbroekmy $port = 53; 67*00b67f09SDavid van Moolenbroek$port = $options{p} if defined $options{p}; 68*00b67f09SDavid van Moolenbroek 69*00b67f09SDavid van Moolenbroekmy $proto = "udp"; 70*00b67f09SDavid van Moolenbroek$proto = lc $options{t} if defined $options{t}; 71*00b67f09SDavid van Moolenbroekusage if ($proto !~ /^(udp|tcp)$/); 72*00b67f09SDavid van Moolenbroek 73*00b67f09SDavid van Moolenbroekmy $file = "STDIN"; 74*00b67f09SDavid van Moolenbroekif (@ARGV >= 1) { 75*00b67f09SDavid van Moolenbroek my $filename = shift @ARGV; 76*00b67f09SDavid van Moolenbroek open FH, "<$filename" or die "$filename: $!"; 77*00b67f09SDavid van Moolenbroek $file = "FH"; 78*00b67f09SDavid van Moolenbroek} 79*00b67f09SDavid van Moolenbroek 80*00b67f09SDavid van Moolenbroekmy $input = ""; 81*00b67f09SDavid van Moolenbroekwhile (defined(my $line = <$file>) ) { 82*00b67f09SDavid van Moolenbroek chomp $line; 83*00b67f09SDavid van Moolenbroek $line =~ s/#.*$//; 84*00b67f09SDavid van Moolenbroek $input .= $line; 85*00b67f09SDavid van Moolenbroek} 86*00b67f09SDavid van Moolenbroek 87*00b67f09SDavid van Moolenbroek$input =~ s/\s+//g; 88*00b67f09SDavid van Moolenbroekmy $data = pack("H*", $input); 89*00b67f09SDavid van Moolenbroekmy $len = length $data; 90*00b67f09SDavid van Moolenbroek 91*00b67f09SDavid van Moolenbroekmy $output = unpack("H*", $data); 92*00b67f09SDavid van Moolenbroekprint ("sending: $output\n"); 93*00b67f09SDavid van Moolenbroek 94*00b67f09SDavid van Moolenbroekmy $sock = IO::Socket::INET->new(PeerAddr => $addr, PeerPort => $port, 95*00b67f09SDavid van Moolenbroek Proto => $proto,) or die "$!"; 96*00b67f09SDavid van Moolenbroek 97*00b67f09SDavid van Moolenbroekmy $bytes; 98*00b67f09SDavid van Moolenbroekif ($proto eq "udp") { 99*00b67f09SDavid van Moolenbroek $bytes = $sock->send($data); 100*00b67f09SDavid van Moolenbroek} else { 101*00b67f09SDavid van Moolenbroek $bytes = $sock->syswrite(pack("n", $len), 2); 102*00b67f09SDavid van Moolenbroek $bytes += $sock->syswrite($data, $len); 103*00b67f09SDavid van Moolenbroek} 104*00b67f09SDavid van Moolenbroek 105*00b67f09SDavid van Moolenbroekprint ("sent $bytes bytes to $addr:$port\n"); 106*00b67f09SDavid van Moolenbroek$sock->close; 107*00b67f09SDavid van Moolenbroekclose $file; 108