What is the best way to test IPv6 DNS

James Housley jim@thehousleys.net
Tue, 26 Sep 2000 23:09:58 -0400


This is a multi-part message in MIME format.
--------------8D1E1E780BDCCC68510FBD52
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Jonathan Guthrie wrote:
> 
> I've nearly finished my initial IPv6 setup.  In fact, just about the only
> thing left is the Forward and Reverse-DNS.  The forward seems to work okay
> (at least www.ipv6.brokersys.com resolves to the correct address and a
> browser that goes there loads Debian's default web content, which is
> what's there) but I'm kind of puzzled about how to test the reverse DNS.
> 
> With IPv4, I'd use nslookup, but I can't seem to make nslookup do anything
> useful with IPv6 addresses.  Can someone give me a hint?
Attached is a simple perl script that will help.  The top of the file
documents it.

Jim
-- 
In God we Trust -- all others must submit an X.509 certificate.
    -- Charles Forsythe <forsythe@alum.mit.edu>
--------------8D1E1E780BDCCC68510FBD52
Content-Type: text/plain; charset=us-ascii;
 name="ip6int"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="ip6int"

#!/usr/bin/perl -w
#
#       Convert valid IPv6 address to ip6.int PTR value.  Convert valid
#       IPv4 address to in-addr.arpa PTR value.  Anything not valid is
#       simply printed as is.  Handles :: notation and embedded IPv4
#       addresses.  If the address is followed by /n, the PTR is
#       truncated to n bits.
#
#      If n is negative, the host part of the address is printed instead.
#      This is useful for generating zone files.
#
#       Examples:
#               nslookup -type=any `ip6_int 3ffe::203.34.97.6` looks up
# 6.0.1.6.2.2.b.c.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.e.f.f.3.ip6.int
#               nslookup -type=any `ip6_int fe80::b432:e6ff/10` looks up
# 2.e.f.ip6.int
#               nslookup -type=any `ip6_int ::127.0.0.1` looks up
# 1.0.0.0.0.0.f.7.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.int
#               nslookup -type=any `ip6_int 127.0.0.1` looks up
# 1.0.0.127.in-addr.arpa
#               nslookup -type=any `ip6_int 127.0.0.1/8` looks up
# 127.in-addr.arpa
#
#       Copyright 1997 Keith Owens <kaos@ocs.com.au>.  GPL.
#      Negative /n added by Magnus Ahltorp <map@stacken.kth.se> 1998-06-06.
#

require 5;
use strict;
use integer;

my $v6;

if ($#ARGV >= 0 &&
    ($v6 = ($ARGV[0] =~ m;^([0-9a-fA-f:]+)(?::(\d+\.\d+\.\d+\.\d+))?(?:/(-)?(\d+))?$;))
     || $ARGV[0] =~ m;^(\d+\.\d+\.\d+\.\d+)(?:/(-)?(\d+))?$;) {
	my $valid = 1;
	if ($v6) {
		my (@chunk) = split(/:/, $1, 99);
		my $negative = defined($3);
		my $mask = $4;
		if ($2) {
			my (@v4) = split(/\./, $2);
			$valid = ($v4[0] <= 255 && $v4[1] <= 255 &&
				  $v4[2] <= 255 && $v4[3] <= 255);
			if ($valid) {
				push(@chunk, sprintf("%x%02x", $v4[0], $v4[1]));
				push(@chunk, sprintf("%x%02x", $v4[2], $v4[3]));
			}
		}
		my $pattern = "";
		if ($valid) {
			foreach (@chunk) {
				$pattern .= /^$/ ? 'b' : 'c';
			}
			if ($pattern =~ /^bbc+$/) {
				@chunk = (0, 0, @chunk[2..$#chunk]);
				@chunk = (0, @chunk) while ($#chunk < 7);
			}
			elsif ($pattern =~ /^c+bb$/) {
				@chunk = (@chunk[0..$#chunk-2], 0, 0);
				push(@chunk, 0) while ($#chunk < 7);
			}
			elsif ($pattern =~ /^c+bc+$/) {
				my @left;
				push(@left, shift(@chunk)) while ($chunk[0] ne "");
				shift(@chunk);
				push(@left, 0);
				push(@left, 0) while (($#left + $#chunk) < 6);
				@chunk = (@left, @chunk);
			}
			$valid = $#chunk == 7;
		}
		my $ip6int = "ip6.int";
		my $i;
		if ($valid) {
			foreach (@chunk) {
				$i = hex($_);
				if ($i > 65535) {
					$valid = 0;
				}
				else {
					$ip6int = sprintf("%x.%x.%x.%x.",
							  ($i) & 0xf,
							  ($i >> 4) & 0xf,
							  ($i >> 8) & 0xf,
							  ($i >> 12) & 0xf)
						  . $ip6int;
				}
			}
		}
		if ($valid && defined($mask)) {
			$valid = ($mask =~ /^\d+$/ && $mask <= 128);
			if ($valid) {
				if ($negative) {
					$ip6int = substr($ip6int, 0, int((128-$mask+3)/4)*2-1);
				} else {
					$ip6int = substr($ip6int, int((128-$mask)/4)*2);
			}
				if ($mask &= 3) {
					if ($negative) {
						$i = hex(substr($ip6int, -1, 1));
						$i &= (15 >> $mask);
						substr($ip6int, -1, 1) = sprintf("%x", $i);
					} else {
						$i = hex(substr($ip6int, 0, 1));
						$i >>= (4-$mask);
						substr($ip6int, 0, 1) = sprintf("%x", $i);
					}
				}
			}
		}
		$ARGV[0] = $ip6int if ($valid);
	}
	else {
		# v4
		my (@v4) = split(/\./, $1);
		my $negative = defined($2);
		my $mask = $3;
		$valid = ($v4[0] <= 255 && $v4[1] <= 255 &&
			  $v4[2] <= 255 && $v4[3] <= 255);
		my $v4 = hex(sprintf("%02X%02X%02X%02X", @v4));
		if ($valid && defined($mask)) {
			$valid = ($mask =~ /^\d+$/ && $mask <= 32);
			if ($valid) {
				if ($negative) {
					no integer;	# unsigned shift please
					$v4 = $v4 & ((~0) >> $mask);
					use integer;	# back to normal
				} else {
					$v4 = $v4 & ((~0) << (32-$mask));
				}
				$v4[0] = ($v4 >> 24) & 255;
				$v4[1] = ($v4 >> 16) & 255;
				$v4[2] = ($v4 >> 8) & 255;
				$v4[3] = $v4 & 255;
			}
		}
		else {
			$mask = 32;
		}
		if ($valid) {
			if ($negative) {
				my $i = 4 - int((32-$mask+7) / 8);
				shift(@v4) while ($i--);
				$ARGV[0] = join('.', reverse(@v4));
			} else {
				my $i = 4 - int(($mask+7) / 8);
				pop(@v4) while ($i--);
				$ARGV[0] = join('.', reverse(@v4));
				$ARGV[0] .= '.' if ($ARGV[0] ne "");
				$ARGV[0] .= 'in-addr.arpa';
			}
		}
	}
}
print "@ARGV\n";

--------------8D1E1E780BDCCC68510FBD52--