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