1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
|
#!/usr/bin/perl
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
#
# SPDX-License-Identifier: MPL-2.0
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, you can obtain one at https://mozilla.org/MPL/2.0/.
#
# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
# This is a tool for sending an arbitrary packet via UDP or TCP to an
# arbitrary address and port. The packet is specified in a file or on
# the standard input, in the form of a series of bytes in hexadecimal.
# Whitespace is ignored, as is anything following a '#' symbol.
#
# For example, the following input would generate normal query for
# isc.org/NS/IN":
#
# # QID:
# 0c d8
# # header:
# 01 00 00 01 00 00 00 00 00 00
# # qname isc.org:
# 03 69 73 63 03 6f 72 67 00
# # qtype NS:
# 00 02
# # qclass IN:
# 00 01
#
# Note that we do not wait for a response for the server. This is simply
# a way of injecting arbitrary packets to test server resposnes.
#
# Usage: packet.pl [-a <address>] [-d] [-p <port>] [-t (udp|tcp)] [-r <repeats>] [filename]
#
# Options:
# -a <address>: specify address (XXX: no IPv6 support yet)
# -p <port>: specify port
# -t <protocol>: specify UDP or TCP
# -r <num>: send packet <num> times
# -d: dump response packets
#
# If not specified, address defaults to 127.0.0.1, port to 53, protocol
# to udp, and file to stdin.
require 5.006.001;
use strict;
use Getopt::Std;
use IO::File;
use IO::Socket;
sub usage {
print ("Usage: packet.pl [-a address] [-d] [-p port] [-t (tcp|udp)] [-r <repeats>] [file]\n");
exit 1;
}
my $sock;
my $proto;
sub dumppacket {
use Net::DNS;
use Net::DNS::Packet;
my $rin;
my $rout;
$rin = '';
vec($rin, fileno($sock), 1) = 1;
select($rout = $rin, undef, undef, 1);
if (vec($rout, fileno($sock), 1)) {
my $buf;
if ($proto eq "udp") {
$sock->recv($buf, 512);
} else {
my $n = $sock->sysread($buf, 2);
return unless $n == 2;
my $len = unpack("n", $buf);
$n = $sock->sysread($buf, $len);
return unless $n == $len;
}
my $response;
if ($Net::DNS::VERSION > 0.68) {
$response = new Net::DNS::Packet(\$buf, 0);
$@ and die $@;
} else {
my $err;
($response, $err) = new Net::DNS::Packet(\$buf, 0);
$err and die $err;
}
$response->print;
}
}
my %options={};
getopts("a:dp:t:r:", \%options);
my $addr = "127.0.0.1";
$addr = $options{a} if defined $options{a};
my $port = 53;
$port = $options{p} if defined $options{p};
$proto = "udp";
$proto = lc $options{t} if defined $options{t};
usage if ($proto !~ /^(udp|tcp)$/);
my $repeats = 1;
$repeats = $options{r} if defined $options{r};
my $file = "STDIN";
if (@ARGV >= 1) {
my $filename = shift @ARGV;
open FH, "<$filename" or die "$filename: $!";
$file = "FH";
}
my $input = "";
while (defined(my $line = <$file>) ) {
chomp $line;
$line =~ s/#.*$//;
$input .= $line;
}
$input =~ s/\s+//g;
my $data = pack("H*", $input);
my $len = length $data;
my $output = unpack("H*", $data);
print ("sending $repeats time(s): $output\n");
$sock = IO::Socket::INET->new(PeerAddr => $addr, PeerPort => $port,
Blocking => 0,
Proto => $proto,) or die "$!";
STDOUT->autoflush(1);
my $bytes = 0;
while ($repeats > 0) {
if ($proto eq "udp") {
$bytes += $sock->send($data);
} else {
$bytes += $sock->syswrite(pack("n", $len), 2);
$bytes += $sock->syswrite($data, $len);
}
$repeats = $repeats - 1;
if ($repeats % 1000 == 0) {
print ".";
}
}
$sock->shutdown(SHUT_WR);
if (defined $options{d}) {
dumppacket;
}
$sock->close;
close $file;
print ("\nsent $bytes bytes to $addr:$port\n");
|