dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt#!/usr/bin/perl -w
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt#
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews# Copyright (C) 2012, 2016 Internet Systems Consortium, Inc. ("ISC")
bf8267aa453e5d2a735ed732a043b77a0b355b20Mark Andrews#
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews# This Source Code Form is subject to the terms of the Mozilla Public
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews# License, v. 2.0. If a copy of the MPL was not distributed with this
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews# file, You can obtain one at http://mozilla.org/MPL/2.0/.
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt# $Id$
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt#
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt# Ad hoc name server
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt#
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Huntuse IO::File;
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Huntuse IO::Socket;
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Huntuse Net::DNS;
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Huntuse Net::DNS::Packet;
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Huntmy $sock = IO::Socket::INET->new(LocalAddr => "10.53.0.4",
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt LocalPort => 5300, Proto => "udp") or die "$!";
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Huntmy $pidf = new IO::File "ans.pid", "w" or die "cannot open pid file: $!";
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Huntprint $pidf "$$\n" or die "cannot write pid file: $!";
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt$pidf->close or die "cannot close pid file: $!";
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Huntsub rmpid { unlink "ans.pid"; exit 1; };
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt$SIG{INT} = \&rmpid;
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt$SIG{TERM} = \&rmpid;
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Huntfor (;;) {
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt $sock->recv($buf, 512);
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt print "**** request from " , $sock->peerhost, " port ", $sock->peerport, "\n";
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt
03958ad4b9fd6b2d6f1fbf20e85d8ff2a1f9d069Mark Andrews my $packet;
03958ad4b9fd6b2d6f1fbf20e85d8ff2a1f9d069Mark Andrews
03958ad4b9fd6b2d6f1fbf20e85d8ff2a1f9d069Mark Andrews if ($Net::DNS::VERSION > 0.68) {
03958ad4b9fd6b2d6f1fbf20e85d8ff2a1f9d069Mark Andrews $packet = new Net::DNS::Packet(\$buf, 0);
03958ad4b9fd6b2d6f1fbf20e85d8ff2a1f9d069Mark Andrews $@ and die $@;
03958ad4b9fd6b2d6f1fbf20e85d8ff2a1f9d069Mark Andrews } else {
03958ad4b9fd6b2d6f1fbf20e85d8ff2a1f9d069Mark Andrews my $err;
03958ad4b9fd6b2d6f1fbf20e85d8ff2a1f9d069Mark Andrews ($packet, $err) = new Net::DNS::Packet(\$buf, 0);
03958ad4b9fd6b2d6f1fbf20e85d8ff2a1f9d069Mark Andrews $err and die $err;
03958ad4b9fd6b2d6f1fbf20e85d8ff2a1f9d069Mark Andrews }
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt print "REQUEST:\n";
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt $packet->print;
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt $packet->header->qr(1);
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt my @questions = $packet->question;
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt my $qname = $questions[0]->qname;
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt my $qtype = $questions[0]->qtype;
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt my $donotrespond = 0;
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt if ($qname eq "foo.info") {
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt $donotrespond = 1;
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt } elsif ($qname eq "cname1.example.com") {
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt # Data for the "cname + other data / 1" test
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt $packet->push("answer", new Net::DNS::RR("cname1.example.com 300 CNAME cname1.example.com"));
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt $packet->push("answer", new Net::DNS::RR("cname1.example.com 300 A 1.2.3.4"));
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt } elsif ($qname eq "cname2.example.com") {
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt # Data for the "cname + other data / 2" test: same RRs in opposite order
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt $packet->push("answer", new Net::DNS::RR("cname2.example.com 300 A 1.2.3.4"));
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt $packet->push("answer", new Net::DNS::RR("cname2.example.com 300 CNAME cname2.example.com"));
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt } elsif ($qname eq "www.example.org" || $qname eq "www.example.net" ||
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt $qname eq "badcname.example.org" ||
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt $qname eq "goodcname.example.org" ||
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt $qname eq "foo.baddname.example.org" ||
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt $qname eq "foo.gooddname.example.org") {
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt # Data for address/alias filtering.
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt $packet->header->aa(1);
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt if ($qtype eq "A") {
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt $packet->push("answer",
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt new Net::DNS::RR($qname .
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt " 300 A 192.0.2.1"));
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt } elsif ($qtype eq "AAAA") {
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt $packet->push("answer",
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt new Net::DNS::RR($qname .
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt " 300 AAAA 2001:db8:beef::1"));
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt }
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt } elsif ($qname eq "badcname.example.net" ||
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt $qname eq "goodcname.example.net") {
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt # Data for CNAME/DNAME filtering. We need to make one-level
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt # delegation to avoid automatic acceptance for subdomain aliases
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt $packet->push("authority", new Net::DNS::RR("example.net 300 NS ns.example.net"));
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt $packet->push("additional", new Net::DNS::RR("ns.example.net 300 A 10.53.0.3"));
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt } elsif ($qname =~ /^nodata\.example\.net$/i) {
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt $packet->header->aa(1);
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt } elsif ($qname =~ /^nxdomain\.example\.net$/i) {
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt $packet->header->aa(1);
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt $packet->header->rcode(NXDOMAIN);
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt } elsif ($qname =~ /sub\.example\.org/) {
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt # Data for CNAME/DNAME filtering. The final answers are
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt # expected to be accepted regardless of the filter setting.
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt $packet->push("authority", new Net::DNS::RR("sub.example.org 300 NS ns.sub.example.org"));
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt $packet->push("additional", new Net::DNS::RR("ns.sub.example.org 300 A 10.53.0.3"));
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt } else {
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt # Data for the "bogus referrals" test
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt $packet->push("authority", new Net::DNS::RR("below.www.example.com 300 NS ns.below.www.example.com"));
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt $packet->push("additional", new Net::DNS::RR("ns.below.www.example.com 300 A 10.53.0.3"));
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt }
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt if ($donotrespond == 0) {
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt $sock->send($packet->data);
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt print "RESPONSE:\n";
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt $packet->print;
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt print "\n";
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt }
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt}