xref: /netbsd-src/external/mpl/bind/dist/bin/tests/system/packet.pl (revision e7ac2a8b5bd66fa2e050809de09a075c36a7014d)
1#!/usr/bin/perl
2#
3# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
4#
5# This Source Code Form is subject to the terms of the Mozilla Public
6# License, v. 2.0. If a copy of the MPL was not distributed with this
7# file, You can obtain one at http://mozilla.org/MPL/2.0/.
8#
9# See the COPYRIGHT file distributed with this work for additional
10# information regarding copyright ownership.
11
12# This is a tool for sending an arbitrary packet via UDP or TCP to an
13# arbitrary address and port.  The packet is specified in a file or on
14# the standard input, in the form of a series of bytes in hexadecimal.
15# Whitespace is ignored, as is anything following a '#' symbol.
16#
17# For example, the following input would generate normal query for
18# isc.org/NS/IN":
19#
20#     # QID:
21#     0c d8
22#     # header:
23#     01 00 00 01 00 00 00 00 00 00
24#     # qname isc.org:
25#     03 69 73 63 03 6f 72 67 00
26#     # qtype NS:
27#     00 02
28#     # qclass IN:
29#     00 01
30#
31# Note that we do not wait for a response for the server.  This is simply
32# a way of injecting arbitrary packets to test server resposnes.
33#
34# Usage: packet.pl [-a <address>] [-p <port>] [-t (udp|tcp)] [filename]
35#
36# If not specified, address defaults to 127.0.0.1, port to 53, protocol
37# to udp, and file to stdin.
38#
39# XXX: Doesn't support IPv6 yet
40
41require 5.006.001;
42
43use strict;
44use Getopt::Std;
45use IO::File;
46use IO::Socket;
47
48sub usage {
49    print ("Usage: packet.pl [-a address] [-p port] [-t (tcp|udp)] [file]\n");
50    exit 1;
51}
52
53my %options={};
54getopts("a:p:t:", \%options);
55
56my $addr = "127.0.0.1";
57$addr = $options{a} if defined $options{a};
58
59my $port = 53;
60$port = $options{p} if defined $options{p};
61
62my $proto = "udp";
63$proto = lc $options{t} if defined $options{t};
64usage if ($proto !~ /^(udp|tcp)$/);
65
66my $file = "STDIN";
67if (@ARGV >= 1) {
68    my $filename = shift @ARGV;
69    open FH, "<$filename" or die "$filename: $!";
70    $file = "FH";
71}
72
73my $input = "";
74while (defined(my $line = <$file>) ) {
75    chomp $line;
76    $line =~ s/#.*$//;
77    $input .= $line;
78}
79
80$input =~ s/\s+//g;
81my $data = pack("H*", $input);
82my $len = length $data;
83
84my $output = unpack("H*", $data);
85print ("sending: $output\n");
86
87my $sock = IO::Socket::INET->new(PeerAddr => $addr, PeerPort => $port,
88				 Proto => $proto,) or die "$!";
89
90my $bytes;
91if ($proto eq "udp") {
92    $bytes = $sock->send($data);
93} else {
94    $bytes = $sock->syswrite(pack("n", $len), 2);
95    $bytes += $sock->syswrite($data, $len);
96}
97
98print ("sent $bytes bytes to $addr:$port\n");
99$sock->close;
100close $file;
101