2011-01-15 13:40:54 +00:00
package dns
2010-12-30 19:00:26 +00:00
2011-01-17 19:29:40 +00:00
import (
2014-02-17 10:50:29 +00:00
"bytes"
2014-09-11 19:49:20 +00:00
"crypto/rsa"
2014-04-04 18:33:50 +00:00
"encoding/hex"
2012-02-17 19:37:19 +00:00
"fmt"
2014-02-17 10:50:29 +00:00
"math/rand"
2012-10-05 07:49:31 +00:00
"net"
2014-09-11 19:49:20 +00:00
"reflect"
2012-10-05 07:49:31 +00:00
"strconv"
2011-07-23 21:43:43 +00:00
"strings"
2011-01-17 19:29:40 +00:00
"testing"
2014-02-17 10:50:29 +00:00
"testing/quick"
2011-12-15 16:37:07 +00:00
"time"
2011-01-17 19:29:40 +00:00
)
2010-12-30 19:00:26 +00:00
2011-02-21 19:33:36 +00:00
func TestDotInName ( t * testing . T ) {
buf := make ( [ ] byte , 20 )
2012-01-11 15:16:09 +00:00
PackDomainName ( "aa\\.bb.nl." , buf , 0 , nil , false )
2011-07-23 21:43:43 +00:00
// index 3 must be a real dot
if buf [ 3 ] != '.' {
2015-02-21 05:03:02 +00:00
t . Error ( "dot should be a real dot" )
2011-07-23 21:43:43 +00:00
}
2011-02-21 19:33:36 +00:00
2011-07-23 21:43:43 +00:00
if buf [ 6 ] != 2 {
2015-02-21 05:03:02 +00:00
t . Error ( "this must have the value 2" )
2011-07-23 21:43:43 +00:00
}
2011-12-09 20:12:03 +00:00
dom , _ , _ := UnpackDomainName ( buf , 0 )
2011-07-23 21:43:43 +00:00
// printing it should yield the backspace again
if dom != "aa\\.bb.nl." {
2015-02-21 05:03:02 +00:00
t . Error ( "dot should have been escaped: " , dom )
2011-07-23 21:43:43 +00:00
}
2011-02-21 17:23:39 +00:00
}
2011-12-15 16:37:07 +00:00
2014-02-15 00:37:57 +00:00
func TestDotLastInLabel ( t * testing . T ) {
sample := "aa\\..au."
buf := make ( [ ] byte , 20 )
_ , err := PackDomainName ( sample , buf , 0 , nil , false )
if err != nil {
2015-02-26 08:49:59 +00:00
t . Fatalf ( "unexpected error packing domain: %v" , err )
2014-02-15 00:37:57 +00:00
}
dom , _ , _ := UnpackDomainName ( buf , 0 )
if dom != sample {
2014-08-19 08:39:04 +00:00
t . Fatalf ( "unpacked domain `%s' doesn't match packed domain" , dom )
2014-02-15 00:37:57 +00:00
}
}
2013-09-11 07:22:20 +00:00
func TestTooLongDomainName ( t * testing . T ) {
l := "aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrsssttt."
dom := l + l + l + l + l + l + l
2015-02-26 06:14:21 +00:00
_ , err := NewRR ( dom + " IN A 127.0.0.1" )
if err == nil {
2015-02-21 05:03:02 +00:00
t . Error ( "should be too long" )
2013-09-11 07:22:20 +00:00
} else {
2015-02-26 06:14:21 +00:00
t . Logf ( "error is %v" , err )
2013-09-11 07:22:20 +00:00
}
2015-02-26 06:14:21 +00:00
_ , err = NewRR ( "..com. IN A 127.0.0.1" )
if err == nil {
2015-02-21 05:03:02 +00:00
t . Error ( "should fail" )
2013-09-11 07:22:20 +00:00
} else {
2015-02-26 06:14:21 +00:00
t . Logf ( "error is %v" , err )
2013-09-11 07:22:20 +00:00
}
}
2012-01-08 13:53:55 +00:00
func TestDomainName ( t * testing . T ) {
2012-02-15 09:28:55 +00:00
tests := [ ] string { "r\\.gieben.miek.nl." , "www\\.www.miek.nl." ,
2012-02-23 18:37:08 +00:00
"www.*.miek.nl." , "www.*.miek.nl." ,
}
2012-01-12 21:49:26 +00:00
dbuff := make ( [ ] byte , 40 )
2012-01-08 13:53:55 +00:00
2012-01-12 21:49:26 +00:00
for _ , ts := range tests {
2012-10-09 20:15:33 +00:00
if _ , err := PackDomainName ( ts , dbuff , 0 , nil , false ) ; err != nil {
2015-02-21 05:03:02 +00:00
t . Error ( "not a valid domain name" )
2012-01-12 21:49:26 +00:00
continue
}
2012-10-09 20:15:33 +00:00
n , _ , err := UnpackDomainName ( dbuff , 0 )
if err != nil {
2015-02-21 05:03:02 +00:00
t . Error ( "failed to unpack packed domain name" )
2012-01-12 21:49:26 +00:00
continue
}
if ts != n {
2015-02-26 06:14:21 +00:00
t . Errorf ( "must be equal: in: %s, out: %s" , ts , n )
2012-01-12 21:49:26 +00:00
}
}
2012-01-08 13:53:55 +00:00
}
2014-03-02 10:37:07 +00:00
func TestDomainNameAndTXTEscapes ( t * testing . T ) {
tests := [ ] byte { '.' , '(' , ')' , ';' , ' ' , '@' , '"' , '\\' , '\t' , '\r' , '\n' , 0 , 255 }
for _ , b := range tests {
rrbytes := [ ] byte {
1 , b , 0 , // owner
byte ( TypeTXT >> 8 ) , byte ( TypeTXT ) ,
byte ( ClassINET >> 8 ) , byte ( ClassINET ) ,
0 , 0 , 0 , 1 , // TTL
0 , 2 , 1 , b , // Data
}
rr1 , _ , err := UnpackRR ( rrbytes , 0 )
if err != nil {
panic ( err )
}
s := rr1 . String ( )
rr2 , err := NewRR ( s )
if err != nil {
2015-02-21 05:03:02 +00:00
t . Errorf ( "Error parsing unpacked RR's string: %v" , err )
2015-02-26 06:14:21 +00:00
t . Errorf ( " Bytes: %v" , rrbytes )
t . Errorf ( "String: %v" , s )
2014-03-02 10:37:07 +00:00
}
repacked := make ( [ ] byte , len ( rrbytes ) )
if _ , err := PackRR ( rr2 , repacked , 0 , nil , false ) ; err != nil {
2015-02-21 05:03:02 +00:00
t . Errorf ( "error packing parsed RR: %v" , err )
2015-02-26 06:14:21 +00:00
t . Errorf ( " original Bytes: %v" , rrbytes )
t . Errorf ( "unpacked Struct: %v" , rr1 )
t . Errorf ( " parsed Struct: %v" , rr2 )
2014-03-02 10:37:07 +00:00
}
if ! bytes . Equal ( repacked , rrbytes ) {
2015-02-21 05:03:02 +00:00
t . Error ( "packed bytes don't match original bytes" )
t . Errorf ( " original bytes: %v" , rrbytes )
t . Errorf ( " packed bytes: %v" , repacked )
2015-02-26 06:14:21 +00:00
t . Errorf ( "unpacked struct: %v" , rr1 )
t . Errorf ( " parsed struct: %v" , rr2 )
2014-03-02 10:37:07 +00:00
}
}
}
2014-09-10 19:56:23 +00:00
func TestTXTEscapeParsing ( t * testing . T ) {
test := [ ] [ ] string {
{ ` ";" ` , ` ";" ` } ,
{ ` \; ` , ` ";" ` } ,
{ ` "\t" ` , ` "\t" ` } ,
{ ` "\r" ` , ` "\r" ` } ,
{ ` "\ " ` , ` " " ` } ,
{ ` "\;" ` , ` ";" ` } ,
{ ` "\;\"" ` , ` ";\"" ` } ,
{ ` "\(a\)" ` , ` "(a)" ` } ,
{ ` "\(a)" ` , ` "(a)" ` } ,
{ ` "(a\)" ` , ` "(a)" ` } ,
{ ` "(a)" ` , ` "(a)" ` } ,
{ ` "\048" ` , ` "0" ` } ,
{ ` "\ ` + "\n" + ` " ` , ` "\n" ` } ,
{ ` "\ ` + "\r" + ` " ` , ` "\r" ` } ,
{ ` "\ ` + "\x11" + ` " ` , ` "\017" ` } ,
{ ` "\'" ` , ` "'" ` } ,
}
for _ , s := range test {
rr , err := NewRR ( fmt . Sprintf ( "example.com. IN TXT %v" , s [ 0 ] ) )
if err != nil {
t . Errorf ( "Could not parse %v TXT: %s" , s [ 0 ] , err )
continue
}
txt := sprintTxt ( rr . ( * TXT ) . Txt )
if txt != s [ 1 ] {
t . Errorf ( "Mismatch after parsing `%v` TXT record: `%v` != `%v`" , s [ 0 ] , txt , s [ 1 ] )
}
}
}
2014-02-17 10:50:29 +00:00
func GenerateDomain ( r * rand . Rand , size int ) [ ] byte {
dnLen := size % 70 // artificially limit size so there's less to intrepret if a failure occurs
var dn [ ] byte
done := false
for i := 0 ; i < dnLen && ! done ; {
max := dnLen - i
if max > 63 {
max = 63
}
lLen := max
if lLen != 0 {
2014-04-10 13:40:37 +00:00
lLen = int ( r . Int31 ( ) ) % max
2014-02-17 10:50:29 +00:00
}
done = lLen == 0
if done {
continue
}
l := make ( [ ] byte , lLen + 1 )
l [ 0 ] = byte ( lLen )
for j := 0 ; j < lLen ; j ++ {
2014-04-10 13:40:37 +00:00
l [ j + 1 ] = byte ( rand . Int31 ( ) )
2014-02-17 10:50:29 +00:00
}
dn = append ( dn , l ... )
i += 1 + lLen
}
return append ( dn , 0 )
}
func TestDomainQuick ( t * testing . T ) {
r := rand . New ( rand . NewSource ( 0 ) )
f := func ( l int ) bool {
db := GenerateDomain ( r , l )
ds , _ , err := UnpackDomainName ( db , 0 )
if err != nil {
panic ( err )
}
buf := make ( [ ] byte , 255 )
off , err := PackDomainName ( ds , buf , 0 , nil , false )
if err != nil {
2015-02-26 06:14:21 +00:00
t . Errorf ( "error packing domain: %v" , err )
t . Errorf ( " bytes: %v" , db )
t . Errorf ( "string: %v" , ds )
2014-02-17 10:50:29 +00:00
return false
}
if ! bytes . Equal ( db , buf [ : off ] ) {
2015-02-21 05:03:02 +00:00
t . Errorf ( "repacked domain doesn't match original:" )
t . Errorf ( "src bytes: %v" , db )
t . Errorf ( " string: %v" , ds )
t . Errorf ( "out bytes: %v" , buf [ : off ] )
2014-02-17 10:50:29 +00:00
return false
}
return true
}
if err := quick . Check ( f , nil ) ; err != nil {
t . Error ( err )
}
}
func GenerateTXT ( r * rand . Rand , size int ) [ ] byte {
rdLen := size % 300 // artificially limit size so there's less to intrepret if a failure occurs
var rd [ ] byte
for i := 0 ; i < rdLen ; {
max := rdLen - 1
if max > 255 {
max = 255
}
sLen := max
if max != 0 {
2014-04-10 13:40:37 +00:00
sLen = int ( r . Int31 ( ) ) % max
2014-02-17 10:50:29 +00:00
}
s := make ( [ ] byte , sLen + 1 )
s [ 0 ] = byte ( sLen )
for j := 0 ; j < sLen ; j ++ {
2014-04-10 13:40:37 +00:00
s [ j + 1 ] = byte ( rand . Int31 ( ) )
2014-02-17 10:50:29 +00:00
}
rd = append ( rd , s ... )
i += 1 + sLen
}
return rd
}
2015-03-04 09:33:37 +00:00
// Ok, 2 things. 1) this test breaks with the new functionality of splitting up larger txt
// chunks into 255 byte pieces. 2) I don't like the random nature of this thing, because I can't
// place the quotes where they need to be.
// So either add some code the places the quotes in just the right spots, make this non random
// or do something else.
// Disabled for now. (miek)
func testTXTRRQuick ( t * testing . T ) {
2014-02-17 10:50:29 +00:00
s := rand . NewSource ( 0 )
r := rand . New ( s )
typeAndClass := [ ] byte {
byte ( TypeTXT >> 8 ) , byte ( TypeTXT ) ,
byte ( ClassINET >> 8 ) , byte ( ClassINET ) ,
0 , 0 , 0 , 1 , // TTL
}
f := func ( l int ) bool {
owner := GenerateDomain ( r , l )
rdata := GenerateTXT ( r , l )
rrbytes := make ( [ ] byte , 0 , len ( owner ) + 2 + 2 + 4 + 2 + len ( rdata ) )
rrbytes = append ( rrbytes , owner ... )
rrbytes = append ( rrbytes , typeAndClass ... )
rrbytes = append ( rrbytes , byte ( len ( rdata ) >> 8 ) )
rrbytes = append ( rrbytes , byte ( len ( rdata ) ) )
rrbytes = append ( rrbytes , rdata ... )
rr , _ , err := UnpackRR ( rrbytes , 0 )
if err != nil {
panic ( err )
}
buf := make ( [ ] byte , len ( rrbytes ) * 3 )
off , err := PackRR ( rr , buf , 0 , nil , false )
if err != nil {
2015-02-26 06:14:21 +00:00
t . Errorf ( "pack Error: %v\nRR: %v" , err , rr )
2014-02-17 10:50:29 +00:00
return false
}
buf = buf [ : off ]
if ! bytes . Equal ( buf , rrbytes ) {
2015-02-21 05:03:02 +00:00
t . Errorf ( "packed bytes don't match original bytes" )
t . Errorf ( "src bytes: %v" , rrbytes )
2015-02-26 06:14:21 +00:00
t . Errorf ( " struct: %v" , rr )
2015-02-21 05:03:02 +00:00
t . Errorf ( "out bytes: %v" , buf )
2014-02-17 10:50:29 +00:00
return false
}
if len ( rdata ) == 0 {
// string'ing won't produce any data to parse
return true
}
rrString := rr . String ( )
rr2 , err := NewRR ( rrString )
if err != nil {
2015-02-26 06:14:21 +00:00
t . Errorf ( "error parsing own output: %v" , err )
t . Errorf ( "struct: %v" , rr )
2015-02-21 05:03:02 +00:00
t . Errorf ( "string: %v" , rrString )
2014-02-17 10:50:29 +00:00
return false
}
if rr2 . String ( ) != rrString {
2015-02-21 05:03:02 +00:00
t . Errorf ( "parsed rr.String() doesn't match original string" )
t . Errorf ( "original: %v" , rrString )
t . Errorf ( " parsed: %v" , rr2 . String ( ) )
2014-02-17 10:50:29 +00:00
return false
}
buf = make ( [ ] byte , len ( rrbytes ) * 3 )
off , err = PackRR ( rr2 , buf , 0 , nil , false )
if err != nil {
2015-02-26 06:14:21 +00:00
t . Errorf ( "error packing parsed rr: %v" , err )
t . Errorf ( "unpacked Struct: %v" , rr )
2015-02-21 05:03:02 +00:00
t . Errorf ( " string: %v" , rrString )
2015-02-26 06:14:21 +00:00
t . Errorf ( " parsed Struct: %v" , rr2 )
2014-02-17 10:50:29 +00:00
return false
}
buf = buf [ : off ]
if ! bytes . Equal ( buf , rrbytes ) {
2015-02-21 05:03:02 +00:00
t . Errorf ( "parsed packed bytes don't match original bytes" )
t . Errorf ( " source bytes: %v" , rrbytes )
2015-02-26 06:14:21 +00:00
t . Errorf ( "unpacked struct: %v" , rr )
2015-02-21 05:03:02 +00:00
t . Errorf ( " string: %v" , rrString )
2015-02-26 06:14:21 +00:00
t . Errorf ( " parsed struct: %v" , rr2 )
2015-02-21 05:03:02 +00:00
t . Errorf ( " repacked bytes: %v" , buf )
2014-02-17 10:50:29 +00:00
return false
}
return true
}
2014-03-02 10:15:26 +00:00
c := & quick . Config { MaxCountScale : 10 }
if err := quick . Check ( f , c ) ; err != nil {
2014-02-17 10:50:29 +00:00
t . Error ( err )
}
}
2012-02-15 08:04:09 +00:00
func TestParseDirectiveMisc ( t * testing . T ) {
2012-02-12 10:45:44 +00:00
tests := map [ string ] string {
2012-02-23 18:37:08 +00:00
"$ORIGIN miek.nl.\na IN NS b" : "a.miek.nl.\t3600\tIN\tNS\tb.miek.nl." ,
"$TTL 2H\nmiek.nl. IN NS b." : "miek.nl.\t7200\tIN\tNS\tb." ,
"miek.nl. 1D IN NS b." : "miek.nl.\t86400\tIN\tNS\tb." ,
` name . IN SOA a6 . nstld . com . hostmaster . nic . name . (
2012-02-15 08:04:09 +00:00
203362132 ; serial
5 m ; refresh ( 5 minutes )
5 m ; retry ( 5 minutes )
2 w ; expire ( 2 weeks )
300 ; minimum ( 5 minutes )
) ` : "name.\t3600\tIN\tSOA\ta6.nstld.com. hostmaster.nic.name. 203362132 300 300 1209600 300" ,
2012-02-23 18:37:08 +00:00
". 3600000 IN NS ONE.MY-ROOTS.NET." : ".\t3600000\tIN\tNS\tONE.MY-ROOTS.NET." ,
"ONE.MY-ROOTS.NET. 3600000 IN A 192.168.1.1" : "ONE.MY-ROOTS.NET.\t3600000\tIN\tA\t192.168.1.1" ,
}
2012-02-12 10:45:44 +00:00
for i , o := range tests {
2015-02-26 06:14:21 +00:00
rr , err := NewRR ( i )
if err != nil {
t . Error ( "failed to parse RR: " , err )
2012-02-12 10:45:44 +00:00
continue
}
if rr . String ( ) != o {
2015-02-26 06:14:21 +00:00
t . Errorf ( "`%s' should be equal to\n`%s', but is `%s'" , i , o , rr . String ( ) )
2012-02-12 10:45:44 +00:00
} else {
t . Logf ( "RR is OK: `%s'" , rr . String ( ) )
}
}
}
2013-10-13 11:25:08 +00:00
func TestNSEC ( t * testing . T ) {
2012-02-11 21:59:34 +00:00
nsectests := map [ string ] string {
2012-03-01 21:40:34 +00:00
"nl. IN NSEC3PARAM 1 0 5 30923C44C6CBBB8F" : "nl.\t3600\tIN\tNSEC3PARAM\t1 0 5 30923C44C6CBBB8F" ,
2012-02-23 18:37:08 +00:00
"p2209hipbpnm681knjnu0m1febshlv4e.nl. IN NSEC3 1 1 5 30923C44C6CBBB8F P90DG1KE8QEAN0B01613LHQDG0SOJ0TA NS SOA TXT RRSIG DNSKEY NSEC3PARAM" : "p2209hipbpnm681knjnu0m1febshlv4e.nl.\t3600\tIN\tNSEC3\t1 1 5 30923C44C6CBBB8F P90DG1KE8QEAN0B01613LHQDG0SOJ0TA NS SOA TXT RRSIG DNSKEY NSEC3PARAM" ,
2012-03-01 21:40:34 +00:00
"localhost.dnssex.nl. IN NSEC www.dnssex.nl. A RRSIG NSEC" : "localhost.dnssex.nl.\t3600\tIN\tNSEC\twww.dnssex.nl. A RRSIG NSEC" ,
"localhost.dnssex.nl. IN NSEC www.dnssex.nl. A RRSIG NSEC TYPE65534" : "localhost.dnssex.nl.\t3600\tIN\tNSEC\twww.dnssex.nl. A RRSIG NSEC TYPE65534" ,
2014-08-28 12:04:33 +00:00
"localhost.dnssex.nl. IN NSEC www.dnssex.nl. A RRSIG NSec Type65534" : "localhost.dnssex.nl.\t3600\tIN\tNSEC\twww.dnssex.nl. A RRSIG NSEC TYPE65534" ,
2012-02-23 18:37:08 +00:00
}
2012-02-11 21:59:34 +00:00
for i , o := range nsectests {
2015-02-26 06:14:21 +00:00
rr , err := NewRR ( i )
if err != nil {
t . Error ( "failed to parse RR: " , err )
2012-02-11 21:59:34 +00:00
continue
}
if rr . String ( ) != o {
2015-02-26 06:14:21 +00:00
t . Errorf ( "`%s' should be equal to\n`%s', but is `%s'" , i , o , rr . String ( ) )
2012-02-11 21:59:34 +00:00
} else {
t . Logf ( "RR is OK: `%s'" , rr . String ( ) )
}
}
}
2012-04-30 19:42:58 +00:00
func TestParseLOC ( t * testing . T ) {
2012-04-30 19:57:42 +00:00
lt := map [ string ] string {
2014-03-27 12:43:13 +00:00
"SW1A2AA.find.me.uk. LOC 51 30 12.748 N 00 07 39.611 W 0.00m 0.00m 0.00m 0.00m" : "SW1A2AA.find.me.uk.\t3600\tIN\tLOC\t51 30 12.748 N 00 07 39.611 W 0m 0.00m 0.00m 0.00m" ,
"SW1A2AA.find.me.uk. LOC 51 0 0.0 N 00 07 39.611 W 0.00m 0.00m 0.00m 0.00m" : "SW1A2AA.find.me.uk.\t3600\tIN\tLOC\t51 00 0.000 N 00 07 39.611 W 0m 0.00m 0.00m 0.00m" ,
2012-04-30 19:57:42 +00:00
}
for i , o := range lt {
2015-02-26 06:14:21 +00:00
rr , err := NewRR ( i )
if err != nil {
t . Error ( "failed to parse RR: " , err )
2012-04-30 19:57:42 +00:00
continue
}
if rr . String ( ) != o {
2015-02-26 06:14:21 +00:00
t . Errorf ( "`%s' should be equal to\n`%s', but is `%s'" , i , o , rr . String ( ) )
2012-04-30 19:57:42 +00:00
} else {
t . Logf ( "RR is OK: `%s'" , rr . String ( ) )
}
2012-04-30 19:42:58 +00:00
}
}
2013-01-16 10:48:43 +00:00
func TestParseDS ( t * testing . T ) {
dt := map [ string ] string {
2013-01-28 13:34:18 +00:00
"example.net. 3600 IN DS 40692 12 3 22261A8B0E0D799183E35E24E2AD6BB58533CBA7E3B14D659E9CA09B 2071398F" : "example.net.\t3600\tIN\tDS\t40692 12 3 22261A8B0E0D799183E35E24E2AD6BB58533CBA7E3B14D659E9CA09B2071398F" ,
2013-01-16 10:48:43 +00:00
}
for i , o := range dt {
2015-02-26 06:14:21 +00:00
rr , err := NewRR ( i )
if err != nil {
t . Error ( "failed to parse RR: " , err )
2013-01-16 10:48:43 +00:00
continue
}
if rr . String ( ) != o {
2015-02-26 06:14:21 +00:00
t . Errorf ( "`%s' should be equal to\n`%s', but is `%s'" , i , o , rr . String ( ) )
2013-01-16 10:48:43 +00:00
} else {
t . Logf ( "RR is OK: `%s'" , rr . String ( ) )
}
}
}
2012-02-12 18:06:32 +00:00
func TestQuotes ( t * testing . T ) {
tests := map [ string ] string {
2012-02-23 18:37:08 +00:00
` t.example.com. IN TXT "a bc" ` : "t.example.com.\t3600\tIN\tTXT\t\"a bc\"" ,
` t . example . com . IN TXT " a
bc "`: " t . example . com . \ t3600 \ tIN \ tTXT \ t \ "a\\n bc\"" ,
2014-01-11 08:50:10 +00:00
` t.example.com. IN TXT "" ` : "t.example.com.\t3600\tIN\tTXT\t\"\"" ,
2012-02-23 18:37:08 +00:00
` t.example.com. IN TXT "a" ` : "t.example.com.\t3600\tIN\tTXT\t\"a\"" ,
` t.example.com. IN TXT "aa" ` : "t.example.com.\t3600\tIN\tTXT\t\"aa\"" ,
` t.example.com. IN TXT "aaa" ; ` : "t.example.com.\t3600\tIN\tTXT\t\"aaa\"" ,
` t.example.com. IN TXT "abc" "DEF" ` : "t.example.com.\t3600\tIN\tTXT\t\"abc\" \"DEF\"" ,
` t.example.com. IN TXT "abc" ( "DEF" ) ` : "t.example.com.\t3600\tIN\tTXT\t\"abc\" \"DEF\"" ,
` t.example.com. IN TXT aaa ; ` : "t.example.com.\t3600\tIN\tTXT\t\"aaa \"" ,
` t.example.com. IN TXT aaa aaa; ` : "t.example.com.\t3600\tIN\tTXT\t\"aaa aaa\"" ,
` t.example.com. IN TXT aaa aaa ` : "t.example.com.\t3600\tIN\tTXT\t\"aaa aaa\"" ,
` t.example.com. IN TXT aaa ` : "t.example.com.\t3600\tIN\tTXT\t\"aaa\"" ,
"cid.urn.arpa. NAPTR 100 50 \"s\" \"z3950+I2L+I2C\" \"\" _z3950._tcp.gatech.edu." : "cid.urn.arpa.\t3600\tIN\tNAPTR\t100 50 \"s\" \"z3950+I2L+I2C\" \"\" _z3950._tcp.gatech.edu." ,
"cid.urn.arpa. NAPTR 100 50 \"s\" \"rcds+I2C\" \"\" _rcds._udp.gatech.edu." : "cid.urn.arpa.\t3600\tIN\tNAPTR\t100 50 \"s\" \"rcds+I2C\" \"\" _rcds._udp.gatech.edu." ,
"cid.urn.arpa. NAPTR 100 50 \"s\" \"http+I2L+I2C+I2R\" \"\" _http._tcp.gatech.edu." : "cid.urn.arpa.\t3600\tIN\tNAPTR\t100 50 \"s\" \"http+I2L+I2C+I2R\" \"\" _http._tcp.gatech.edu." ,
"cid.urn.arpa. NAPTR 100 10 \"\" \"\" \"/urn:cid:.+@([^\\.]+\\.)(.*)$/\\2/i\" ." : "cid.urn.arpa.\t3600\tIN\tNAPTR\t100 10 \"\" \"\" \"/urn:cid:.+@([^\\.]+\\.)(.*)$/\\2/i\" ." ,
}
2012-02-12 18:06:32 +00:00
for i , o := range tests {
2015-02-26 06:14:21 +00:00
rr , err := NewRR ( i )
if err != nil {
t . Error ( "failed to parse RR: " , err )
2012-02-12 18:06:32 +00:00
continue
}
if rr . String ( ) != o {
2015-02-26 06:14:21 +00:00
t . Errorf ( "`%s' should be equal to\n`%s', but is\n`%s'" , i , o , rr . String ( ) )
2012-02-12 18:06:32 +00:00
} else {
t . Logf ( "RR is OK: `%s'" , rr . String ( ) )
}
}
}
2014-06-15 19:39:23 +00:00
func TestParseClass ( t * testing . T ) {
tests := map [ string ] string {
"t.example.com. IN A 127.0.0.1" : "t.example.com. 3600 IN A 127.0.0.1" ,
"t.example.com. CS A 127.0.0.1" : "t.example.com. 3600 CS A 127.0.0.1" ,
"t.example.com. CH A 127.0.0.1" : "t.example.com. 3600 CH A 127.0.0.1" ,
// ClassANY can not occur in zone files
// "t.example.com. ANY A 127.0.0.1": "t.example.com. 3600 ANY A 127.0.0.1",
"t.example.com. NONE A 127.0.0.1" : "t.example.com. 3600 NONE A 127.0.0.1" ,
}
for i , o := range tests {
2015-02-26 06:14:21 +00:00
rr , err := NewRR ( i )
if err != nil {
t . Error ( "failed to parse RR: " , err )
2014-06-15 19:39:23 +00:00
continue
}
if rr . String ( ) != o {
2015-02-26 06:14:21 +00:00
t . Errorf ( "`%s' should be equal to\n`%s', but is\n`%s'" , i , o , rr . String ( ) )
2014-06-15 19:39:23 +00:00
} else {
t . Logf ( "RR is OK: `%s'" , rr . String ( ) )
}
}
}
2013-10-13 11:25:08 +00:00
func TestBrace ( t * testing . T ) {
2011-12-17 09:16:24 +00:00
tests := map [ string ] string {
2012-11-22 10:54:46 +00:00
"(miek.nl.) 3600 IN A 127.0.1.1" : "miek.nl.\t3600\tIN\tA\t127.0.1.1" ,
2011-12-17 09:16:24 +00:00
"miek.nl. (3600) IN MX (10) elektron.atoom.net." : "miek.nl.\t3600\tIN\tMX\t10 elektron.atoom.net." ,
` miek . nl . IN (
3600 A 127.0 .0 .1 ) ` : "miek.nl.\t3600\tIN\tA\t127.0.0.1" ,
2012-11-22 10:54:46 +00:00
"(miek.nl.) (A) (127.0.2.1)" : "miek.nl.\t3600\tIN\tA\t127.0.2.1" ,
"miek.nl A 127.0.3.1" : "miek.nl.\t3600\tIN\tA\t127.0.3.1" ,
2012-02-23 18:37:08 +00:00
"_ssh._tcp.local. 60 IN (PTR) stora._ssh._tcp.local." : "_ssh._tcp.local.\t60\tIN\tPTR\tstora._ssh._tcp.local." ,
"miek.nl. NS ns.miek.nl" : "miek.nl.\t3600\tIN\tNS\tns.miek.nl." ,
2011-12-17 10:28:54 +00:00
` ( miek . nl . ) (
2013-09-20 15:15:27 +00:00
( IN )
2011-12-17 10:28:54 +00:00
( AAAA )
( : : 1 ) ) ` : "miek.nl.\t3600\tIN\tAAAA\t::1" ,
2011-12-17 09:16:24 +00:00
` ( miek . nl . ) (
2013-09-20 15:15:27 +00:00
( IN )
2011-12-17 09:16:24 +00:00
( AAAA )
( : : 1 ) ) ` : "miek.nl.\t3600\tIN\tAAAA\t::1" ,
2012-11-22 10:54:46 +00:00
"miek.nl. IN AAAA ::2" : "miek.nl.\t3600\tIN\tAAAA\t::2" ,
2012-01-12 21:49:26 +00:00
` ( ( m ) ( i ) ek . ( n ) l . ) ( SOA ) ( soa . ) ( soa . ) (
2012-01-12 09:50:01 +00:00
2009032802 ; serial
21600 ; refresh ( 6 hours )
7 ( 2 ) 00 ; retry ( 2 hours )
604 ( ) 800 ; expire ( 1 week )
3600 ; minimum ( 1 hour )
) ` : "miek.nl.\t3600\tIN\tSOA\tsoa. soa. 2009032802 21600 7200 604800 3600" ,
2012-11-22 10:54:46 +00:00
"miek\\.nl. IN A 127.0.0.10" : "miek\\.nl.\t3600\tIN\tA\t127.0.0.10" ,
"miek.nl. IN A 127.0.0.11" : "miek.nl.\t3600\tIN\tA\t127.0.0.11" ,
"miek.nl. A 127.0.0.12" : "miek.nl.\t3600\tIN\tA\t127.0.0.12" ,
2011-12-17 09:16:24 +00:00
` miek . nl . 86400 IN SOA elektron . atoom . net . miekg . atoom . net . (
2009032802 ; serial
21600 ; refresh ( 6 hours )
7200 ; retry ( 2 hours )
604800 ; expire ( 1 week )
3600 ; minimum ( 1 hour )
) ` : "miek.nl.\t86400\tIN\tSOA\telektron.atoom.net. miekg.atoom.net. 2009032802 21600 7200 604800 3600" ,
2011-07-23 21:43:43 +00:00
}
2011-12-15 16:37:07 +00:00
for i , o := range tests {
2015-02-26 06:14:21 +00:00
rr , err := NewRR ( i )
if err != nil {
t . Errorf ( "failed to parse RR: %v\n\t%s" , err , i )
2011-12-18 12:42:59 +00:00
continue
2011-12-16 09:26:32 +00:00
}
2011-12-15 21:40:07 +00:00
if rr . String ( ) != o {
2015-02-26 06:14:21 +00:00
t . Errorf ( "`%s' should be equal to\n`%s', but is `%s'" , i , o , rr . String ( ) )
2011-12-15 21:40:07 +00:00
} else {
2011-12-16 09:26:32 +00:00
t . Logf ( "RR is OK: `%s'" , rr . String ( ) )
}
2011-07-23 21:43:43 +00:00
}
2011-07-15 15:41:26 +00:00
}
2011-07-18 13:19:47 +00:00
2011-07-24 15:08:33 +00:00
func TestParseFailure ( t * testing . T ) {
2011-12-15 16:37:07 +00:00
tests := [ ] string { "miek.nl. IN A 327.0.0.1" ,
"miek.nl. IN AAAA ::x" ,
"miek.nl. IN MX a0 miek.nl." ,
"miek.nl aap IN MX mx.miek.nl." ,
2014-08-28 12:11:18 +00:00
"miek.nl 200 IN mxx 10 mx.miek.nl." ,
"miek.nl. inn MX 10 mx.miek.nl." ,
2013-09-10 18:09:22 +00:00
// "miek.nl. IN CNAME ", // actually valid nowadays, zero size rdata
"miek.nl. IN CNAME .." ,
2011-12-15 16:37:07 +00:00
"miek.nl. PA MX 10 miek.nl." ,
2011-12-17 09:16:24 +00:00
"miek.nl. ) IN MX 10 miek.nl." ,
2011-12-15 16:37:07 +00:00
}
2011-07-24 15:08:33 +00:00
2011-12-15 16:37:07 +00:00
for _ , s := range tests {
2011-12-15 16:49:43 +00:00
_ , err := NewRR ( s )
2011-12-15 16:37:07 +00:00
if err == nil {
2015-02-21 05:03:02 +00:00
t . Errorf ( "should have triggered an error: \"%s\"" , s )
2011-12-15 16:37:07 +00:00
}
}
2011-07-18 13:19:47 +00:00
}
2011-07-22 20:06:07 +00:00
func TestZoneParsing ( t * testing . T ) {
2014-10-06 06:45:31 +00:00
// parse_test.db
db := `
a . example . com . IN A 127.0 .0 .1
8 db7 . _openpgpkey . example . com . IN OPENPGPKEY mQCNAzIG
$ ORIGIN a . example . com .
test IN A 127.0 .0 .1
$ ORIGIN b . example . com .
test IN CNAME test . a . example . com .
`
2011-12-18 20:01:32 +00:00
start := time . Now ( ) . UnixNano ( )
2014-10-06 06:45:31 +00:00
to := ParseZone ( strings . NewReader ( db ) , "" , "parse_test.db" )
2011-12-15 16:37:07 +00:00
var i int
2011-12-16 13:38:52 +00:00
for x := range to {
2011-12-15 16:37:07 +00:00
i ++
2014-08-14 08:18:08 +00:00
if x . Error != nil {
2015-02-26 06:14:21 +00:00
t . Error ( x . Error )
2014-08-14 08:18:08 +00:00
continue
}
2015-02-26 06:14:21 +00:00
t . Log ( x . RR )
2011-07-23 21:43:43 +00:00
}
2011-12-18 20:01:32 +00:00
delta := time . Now ( ) . UnixNano ( ) - start
2011-12-15 16:37:07 +00:00
t . Logf ( "%d RRs parsed in %.2f s (%.2f RR/s)" , i , float32 ( delta ) / 1e9 , float32 ( i ) / ( float32 ( delta ) / 1e9 ) )
2011-07-22 20:06:07 +00:00
}
2012-02-17 19:37:19 +00:00
func ExampleZone ( ) {
2012-02-23 18:37:08 +00:00
zone := ` $ ORIGIN .
2012-02-17 19:37:19 +00:00
$ TTL 3600 ; 1 hour
name IN SOA a6 . nstld . com . hostmaster . nic . name . (
203362132 ; serial
300 ; refresh ( 5 minutes )
300 ; retry ( 5 minutes )
1209600 ; expire ( 2 weeks )
300 ; minimum ( 5 minutes )
)
$ TTL 10800 ; 3 hours
2012-12-13 13:57:19 +00:00
name . 10800 IN NS name .
2012-02-27 17:48:53 +00:00
IN NS g6 . nstld . com .
7200 NS h6 . nstld . com .
3600 IN NS j6 . nstld . com .
IN 3600 NS k6 . nstld . com .
2012-02-17 19:37:19 +00:00
NS l6 . nstld . com .
NS a6 . nstld . com .
NS c6 . nstld . com .
NS d6 . nstld . com .
NS f6 . nstld . com .
NS m6 . nstld . com .
2013-09-20 15:15:27 +00:00
(
2012-12-13 13:57:19 +00:00
NS m7 . nstld . com .
)
2012-02-17 19:37:19 +00:00
$ ORIGIN name .
0 - 0 onlus NS ns7 . ehiweb . it .
NS ns8 . ehiweb . it .
0 - g MX 10 mx01 . nic
MX 10 mx02 . nic
MX 10 mx03 . nic
MX 10 mx04 . nic
$ ORIGIN 0 - g . name
moutamassey NS ns01 . yahoodomains . jp .
NS ns02 . yahoodomains . jp .
`
to := ParseZone ( strings . NewReader ( zone ) , "" , "testzone" )
for x := range to {
2015-02-26 06:14:21 +00:00
fmt . Println ( x . RR )
2012-02-17 19:37:19 +00:00
}
2012-12-13 13:57:19 +00:00
// Output:
// name. 3600 IN SOA a6.nstld.com. hostmaster.nic.name. 203362132 300 300 1209600 300
// name. 10800 IN NS name.
// name. 10800 IN NS g6.nstld.com.
// name. 7200 IN NS h6.nstld.com.
// name. 3600 IN NS j6.nstld.com.
// name. 3600 IN NS k6.nstld.com.
// name. 10800 IN NS l6.nstld.com.
// name. 10800 IN NS a6.nstld.com.
// name. 10800 IN NS c6.nstld.com.
// name. 10800 IN NS d6.nstld.com.
// name. 10800 IN NS f6.nstld.com.
// name. 10800 IN NS m6.nstld.com.
// name. 10800 IN NS m7.nstld.com.
// 0-0onlus.name. 10800 IN NS ns7.ehiweb.it.
// 0-0onlus.name. 10800 IN NS ns8.ehiweb.it.
// 0-g.name. 10800 IN MX 10 mx01.nic.name.
// 0-g.name. 10800 IN MX 10 mx02.nic.name.
// 0-g.name. 10800 IN MX 10 mx03.nic.name.
// 0-g.name. 10800 IN MX 10 mx04.nic.name.
// moutamassey.0-g.name.name. 10800 IN NS ns01.yahoodomains.jp.
// moutamassey.0-g.name.name. 10800 IN NS ns02.yahoodomains.jp.
2012-02-17 19:37:19 +00:00
}
2012-02-19 10:27:16 +00:00
func ExampleHIP ( ) {
2014-11-28 19:03:55 +00:00
h := ` www . example . com IN HIP ( 2 200100107 B1A74DF365639CC39F1D578
2012-02-19 11:28:31 +00:00
AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p
9 + LrV4e19WzK00 + CI6zBCQTdtWsuxKbWIy87UOoJTwkUs7lBu + Upr1gsNrut79ryra + bSRGQ
b1slImA8YVJyuIDsj7kwzG7jnERNqnWxZ48AWkskmdHaVDP4BcelrTI3rMXdXF5D
rvs . example . com . ) `
2012-02-23 18:37:08 +00:00
if hip , err := NewRR ( h ) ; err == nil {
2015-02-26 06:14:21 +00:00
fmt . Println ( hip . String ( ) )
2012-02-23 18:37:08 +00:00
}
2012-12-13 13:57:19 +00:00
// Output:
2014-11-28 19:03:55 +00:00
// www.example.com. 3600 IN HIP 2 200100107B1A74DF365639CC39F1D578 AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwkUs7lBu+Upr1gsNrut79ryra+bSRGQb1slImA8YVJyuIDsj7kwzG7jnERNqnWxZ48AWkskmdHaVDP4BcelrTI3rMXdXF5D rvs.example.com.
2012-02-19 10:27:16 +00:00
}
2012-02-19 17:36:59 +00:00
2014-02-22 05:28:48 +00:00
func TestHIP ( t * testing . T ) {
h := ` www . example . com . IN HIP ( 2 200100107 B1A74DF365639CC39F1D578
AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p
9 + LrV4e19WzK00 + CI6zBCQTdtWsuxKbWIy87UOoJTwkUs7lBu + Upr1gsNrut79ryra + bSRGQ
b1slImA8YVJyuIDsj7kwzG7jnERNqnWxZ48AWkskmdHaVDP4BcelrTI3rMXdXF5D
rvs1 . example . com .
rvs2 . example . com . ) `
rr , err := NewRR ( h )
if err != nil {
2015-02-26 08:49:59 +00:00
t . Fatalf ( "failed to parse RR: %v" , err )
2014-02-22 05:28:48 +00:00
}
t . Logf ( "RR: %s" , rr )
msg := new ( Msg )
msg . Answer = [ ] RR { rr , rr }
bytes , err := msg . Pack ( )
if err != nil {
2015-02-26 08:49:59 +00:00
t . Fatalf ( "failed to pack msg: %v" , err )
2014-02-22 05:28:48 +00:00
}
if err := msg . Unpack ( bytes ) ; err != nil {
2015-02-26 08:49:59 +00:00
t . Fatalf ( "failed to unpack msg: %v" , err )
2014-02-22 05:28:48 +00:00
}
if len ( msg . Answer ) != 2 {
2015-02-26 06:14:21 +00:00
t . Fatalf ( "2 answers expected: %v" , msg )
2014-02-22 05:28:48 +00:00
}
for i , rr := range msg . Answer {
rr := rr . ( * HIP )
t . Logf ( "RR: %s" , rr )
if l := len ( rr . RendezvousServers ) ; l != 2 {
2015-02-26 06:14:21 +00:00
t . Fatalf ( "2 servers expected, only %d in record %d:\n%v" , l , i , msg )
2014-02-22 05:28:48 +00:00
}
for j , s := range [ ] string { "rvs1.example.com." , "rvs2.example.com." } {
if rr . RendezvousServers [ j ] != s {
2015-02-26 06:14:21 +00:00
t . Fatalf ( "expected server %d of record %d to be %s:\n%v" , j , i , s , msg )
2014-02-22 05:28:48 +00:00
}
}
}
}
2012-02-19 17:36:59 +00:00
func ExampleSOA ( ) {
2012-02-23 18:37:08 +00:00
s := "example.com. 1000 SOA master.example.com. admin.example.com. 1 4294967294 4294967293 4294967295 100"
if soa , err := NewRR ( s ) ; err == nil {
2015-02-26 06:14:21 +00:00
fmt . Println ( soa . String ( ) )
2012-02-23 18:37:08 +00:00
}
2012-12-13 13:57:19 +00:00
// Output:
// example.com. 1000 IN SOA master.example.com. admin.example.com. 1 4294967294 4294967293 4294967295 100
2012-02-19 17:36:59 +00:00
}
2012-03-03 16:40:30 +00:00
func TestLineNumberError ( t * testing . T ) {
s := "example.com. 1000 SOA master.example.com. admin.example.com. monkey 4294967294 4294967293 4294967295 100"
if _ , err := NewRR ( s ) ; err != nil {
if err . Error ( ) != "dns: bad SOA zone parameter: \"monkey\" at line: 1:68" {
2015-02-21 05:03:02 +00:00
t . Error ( "not expecting this error: " , err )
2012-03-03 16:40:30 +00:00
}
}
}
// Test with no known RR on the line
func TestLineNumberError2 ( t * testing . T ) {
2012-11-22 10:54:46 +00:00
tests := map [ string ] string {
"example.com. 1000 SO master.example.com. admin.example.com. 1 4294967294 4294967293 4294967295 100" : "dns: expecting RR type or class, not this...: \"SO\" at line: 1:21" ,
"example.com 1000 IN TALINK a.example.com. b..example.com." : "dns: bad TALINK NextName: \"b..example.com.\" at line: 1:57" ,
"example.com 1000 IN TALINK ( a.example.com. b..example.com. )" : "dns: bad TALINK NextName: \"b..example.com.\" at line: 1:60" ,
2013-09-20 15:15:27 +00:00
` example . com 1000 IN TALINK ( a . example . com .
2012-11-22 10:54:46 +00:00
bb . . example . com . ) ` : "dns: bad TALINK NextName: \"bb..example.com.\" at line: 2:18" ,
2012-11-22 12:41:40 +00:00
// This is a bug, it should report an error on line 1, but the new is already processed.
2012-11-22 10:54:46 +00:00
` example . com 1000 IN TALINK ( a . example . com . b ... example . com .
2012-11-22 12:41:40 +00:00
) ` : "dns: bad TALINK NextName: \"b...example.com.\" at line: 2:1" }
2012-11-22 10:54:46 +00:00
2015-02-26 06:14:21 +00:00
for in , errStr := range tests {
_ , err := NewRR ( in )
if err == nil {
t . Error ( "err is nil" )
2012-11-22 10:54:46 +00:00
} else {
2015-02-26 06:14:21 +00:00
if err . Error ( ) != errStr {
t . Errorf ( "%s: error should be %s is %v" , in , errStr , err )
2012-11-22 10:54:46 +00:00
}
}
2012-03-03 16:40:30 +00:00
}
}
2012-05-15 10:24:57 +00:00
// Test if the calculations are correct
func TestRfc1982 ( t * testing . T ) {
// If the current time and the timestamp are more than 68 years apart
// it means the date has wrapped. 0 is 1970
// fall in the current 68 year span
strtests := [ ] string { "20120525134203" , "19700101000000" , "20380119031408" }
for _ , v := range strtests {
2012-09-17 06:56:27 +00:00
if x , _ := StringToTime ( v ) ; v != TimeToString ( x ) {
2015-02-21 05:03:02 +00:00
t . Errorf ( "1982 arithmetic string failure %s (%s:%d)" , v , TimeToString ( x ) , x )
2012-05-15 10:24:57 +00:00
}
}
inttests := map [ uint32 ] string { 0 : "19700101000000" ,
1 << 31 : "20380119031408" ,
1 << 32 - 1 : "21060207062815" ,
}
for i , v := range inttests {
2012-09-11 19:45:21 +00:00
if TimeToString ( i ) != v {
2015-02-21 05:03:02 +00:00
t . Errorf ( "1982 arithmetic int failure %d:%s (%s)" , i , v , TimeToString ( i ) )
2012-05-15 10:24:57 +00:00
}
}
// Future tests, these dates get parsed to a date within the current 136 year span
future := map [ string ] string { "22680119031408" : "20631123173144" ,
"19010101121212" : "20370206184028" ,
"19210101121212" : "20570206184028" ,
"19500101121212" : "20860206184028" ,
"19700101000000" : "19700101000000" ,
"19690101000000" : "21050207062816" ,
"29210101121212" : "21040522212236" ,
}
for from , to := range future {
2012-09-17 06:56:27 +00:00
x , _ := StringToTime ( from )
2012-09-11 19:45:21 +00:00
y := TimeToString ( x )
2012-05-15 10:24:57 +00:00
if y != to {
2015-02-21 05:03:02 +00:00
t . Errorf ( "1982 arithmetic future failure %s:%s (%s)" , from , to , y )
2012-05-15 10:24:57 +00:00
}
}
}
2012-05-20 13:28:27 +00:00
2012-05-20 13:31:35 +00:00
func TestEmpty ( t * testing . T ) {
2015-02-26 09:48:30 +00:00
for _ = range ParseZone ( strings . NewReader ( "" ) , "" , "" ) {
2015-02-21 05:03:02 +00:00
t . Errorf ( "should be empty" )
2012-05-20 13:31:35 +00:00
}
}
2014-08-28 12:27:09 +00:00
func TestLowercaseTokens ( t * testing . T ) {
2014-08-27 20:27:37 +00:00
var testrecords = [ ] string {
2014-08-27 20:36:28 +00:00
"example.org. 300 IN a 1.2.3.4" ,
"example.org. 300 in A 1.2.3.4" ,
"example.org. 300 in a 1.2.3.4" ,
"example.org. 300 a 1.2.3.4" ,
2014-08-27 20:38:31 +00:00
"example.org. 300 A 1.2.3.4" ,
2014-08-27 20:27:37 +00:00
"example.org. IN a 1.2.3.4" ,
"example.org. in A 1.2.3.4" ,
"example.org. in a 1.2.3.4" ,
"example.org. a 1.2.3.4" ,
2014-08-27 20:38:31 +00:00
"example.org. A 1.2.3.4" ,
"example.org. a 1.2.3.4" ,
2014-08-28 12:17:40 +00:00
"$ORIGIN example.org.\n a 1.2.3.4" ,
"$Origin example.org.\n a 1.2.3.4" ,
"$origin example.org.\n a 1.2.3.4" ,
2014-08-28 17:05:05 +00:00
"example.org. Class1 Type1 1.2.3.4" ,
2014-08-27 20:27:37 +00:00
}
for _ , testrr := range testrecords {
_ , err := NewRR ( testrr )
if err != nil {
2015-02-26 06:14:21 +00:00
t . Errorf ( "failed to parse %#v, got %v" , testrr , err )
2014-08-27 20:27:37 +00:00
}
}
}
2012-05-20 13:41:14 +00:00
func ExampleGenerate ( ) {
// From the manual: http://www.bind9.net/manual/bind/9.3.2/Bv9ARM.ch06.html#id2566761
zone := "$GENERATE 1-2 0 NS SERVER$.EXAMPLE.\n$GENERATE 1-8 $ CNAME $.0"
to := ParseZone ( strings . NewReader ( zone ) , "0.0.192.IN-ADDR.ARPA." , "" )
2012-05-20 13:28:27 +00:00
for x := range to {
if x . Error == nil {
2015-02-26 06:14:21 +00:00
fmt . Println ( x . RR . String ( ) )
2012-05-20 13:28:27 +00:00
}
}
2012-12-13 13:57:19 +00:00
// Output:
// 0.0.0.192.IN-ADDR.ARPA. 3600 IN NS SERVER1.EXAMPLE.
// 0.0.0.192.IN-ADDR.ARPA. 3600 IN NS SERVER2.EXAMPLE.
// 1.0.0.192.IN-ADDR.ARPA. 3600 IN CNAME 1.0.0.0.192.IN-ADDR.ARPA.
// 2.0.0.192.IN-ADDR.ARPA. 3600 IN CNAME 2.0.0.0.192.IN-ADDR.ARPA.
// 3.0.0.192.IN-ADDR.ARPA. 3600 IN CNAME 3.0.0.0.192.IN-ADDR.ARPA.
// 4.0.0.192.IN-ADDR.ARPA. 3600 IN CNAME 4.0.0.0.192.IN-ADDR.ARPA.
// 5.0.0.192.IN-ADDR.ARPA. 3600 IN CNAME 5.0.0.0.192.IN-ADDR.ARPA.
// 6.0.0.192.IN-ADDR.ARPA. 3600 IN CNAME 6.0.0.0.192.IN-ADDR.ARPA.
// 7.0.0.192.IN-ADDR.ARPA. 3600 IN CNAME 7.0.0.0.192.IN-ADDR.ARPA.
// 8.0.0.192.IN-ADDR.ARPA. 3600 IN CNAME 8.0.0.0.192.IN-ADDR.ARPA.
2012-05-20 13:28:27 +00:00
}
2012-10-05 07:49:31 +00:00
func TestSRVPacking ( t * testing . T ) {
msg := Msg { }
things := [ ] string { "1.2.3.4:8484" ,
"45.45.45.45:8484" ,
"84.84.84.84:8484" ,
}
for i , n := range things {
h , p , err := net . SplitHostPort ( n )
if err != nil {
continue
}
port := 8484
tmp , err := strconv . Atoi ( p )
if err == nil {
port = tmp
}
2012-12-09 18:23:25 +00:00
rr := & SRV {
2012-10-05 07:49:31 +00:00
Hdr : RR_Header { Name : "somename." ,
Rrtype : TypeSRV ,
Class : ClassINET ,
Ttl : 5 } ,
Priority : uint16 ( i ) ,
Weight : 5 ,
Port : uint16 ( port ) ,
Target : h + "." ,
}
msg . Answer = append ( msg . Answer , rr )
}
2012-10-09 20:15:33 +00:00
_ , err := msg . Pack ( )
2012-10-10 20:17:50 +00:00
if err != nil {
2015-02-26 06:14:21 +00:00
t . Fatalf ( "couldn't pack %v: %v" , msg , err )
2012-10-05 07:49:31 +00:00
}
}
2012-11-15 08:39:32 +00:00
func TestParseBackslash ( t * testing . T ) {
2015-02-26 06:14:21 +00:00
if r , err := NewRR ( "nul\\000gap.test.globnix.net. 600 IN A 192.0.2.10" ) ; err != nil {
2015-02-21 05:03:02 +00:00
t . Errorf ( "could not create RR with \\000 in it" )
2013-06-29 07:46:34 +00:00
} else {
2015-02-26 06:14:21 +00:00
t . Logf ( "parsed %s" , r . String ( ) )
2013-06-29 07:46:34 +00:00
}
2015-02-26 06:14:21 +00:00
if r , err := NewRR ( ` nul\000gap.test.globnix.net. 600 IN TXT "Hello\123" ` ) ; err != nil {
2015-02-21 05:03:02 +00:00
t . Errorf ( "could not create RR with \\000 in it" )
2012-11-15 08:39:32 +00:00
} else {
2015-02-26 06:14:21 +00:00
t . Logf ( "parsed %s" , r . String ( ) )
2012-11-15 08:39:32 +00:00
}
2015-02-26 06:14:21 +00:00
if r , err := NewRR ( ` m\ @\ iek.nl. IN 3600 A 127.0.0.1 ` ) ; err != nil {
2015-02-21 05:03:02 +00:00
t . Errorf ( "could not create RR with \\ and \\@ in it" )
2013-12-03 09:12:21 +00:00
} else {
2015-02-26 06:14:21 +00:00
t . Logf ( "parsed %s" , r . String ( ) )
2013-12-03 09:12:21 +00:00
}
2012-11-15 08:39:32 +00:00
}
2012-11-18 08:10:28 +00:00
func TestILNP ( t * testing . T ) {
tests := [ ] string {
2012-11-18 09:29:05 +00:00
"host1.example.com.\t3600\tIN\tNID\t10 0014:4fff:ff20:ee64" ,
"host1.example.com.\t3600\tIN\tNID\t20 0015:5fff:ff21:ee65" ,
"host2.example.com.\t3600\tIN\tNID\t10 0016:6fff:ff22:ee66" ,
"host1.example.com.\t3600\tIN\tL32\t10 10.1.2.0" ,
"host1.example.com.\t3600\tIN\tL32\t20 10.1.4.0" ,
"host2.example.com.\t3600\tIN\tL32\t10 10.1.8.0" ,
"host1.example.com.\t3600\tIN\tL64\t10 2001:0DB8:1140:1000" ,
"host1.example.com.\t3600\tIN\tL64\t20 2001:0DB8:2140:2000" ,
"host2.example.com.\t3600\tIN\tL64\t10 2001:0DB8:4140:4000" ,
"host1.example.com.\t3600\tIN\tLP\t10 l64-subnet1.example.com." ,
"host1.example.com.\t3600\tIN\tLP\t10 l64-subnet2.example.com." ,
"host1.example.com.\t3600\tIN\tLP\t20 l32-subnet1.example.com." ,
2012-11-18 08:10:28 +00:00
}
for _ , t1 := range tests {
2015-02-26 06:14:21 +00:00
r , err := NewRR ( t1 )
if err != nil {
t . Fatalf ( "an error occurred: %v" , err )
2012-11-18 08:10:28 +00:00
} else {
2012-11-18 09:29:05 +00:00
if t1 != r . String ( ) {
2014-08-19 08:39:04 +00:00
t . Fatalf ( "strings should be equal %s %s" , t1 , r . String ( ) )
2012-11-18 09:29:05 +00:00
}
2012-11-18 08:10:28 +00:00
}
}
}
2013-03-04 10:24:08 +00:00
2013-10-19 20:31:12 +00:00
func TestNsapGposEidNimloc ( t * testing . T ) {
2013-10-13 11:25:08 +00:00
dt := map [ string ] string {
"foo.bar.com. IN NSAP 21 47000580ffff000000321099991111222233334444" : "foo.bar.com.\t3600\tIN\tNSAP\t21 47000580ffff000000321099991111222233334444" ,
2013-10-13 12:01:33 +00:00
"host.school.de IN NSAP 17 39276f3100111100002222333344449876" : "host.school.de.\t3600\tIN\tNSAP\t17 39276f3100111100002222333344449876" ,
"444433332222111199990123000000ff. NSAP-PTR foo.bar.com." : "444433332222111199990123000000ff.\t3600\tIN\tNSAP-PTR\tfoo.bar.com." ,
2013-10-15 14:21:47 +00:00
"lillee. IN GPOS -32.6882 116.8652 10.0" : "lillee.\t3600\tIN\tGPOS\t-32.6882 116.8652 10.0" ,
"hinault. IN GPOS -22.6882 116.8652 250.0" : "hinault.\t3600\tIN\tGPOS\t-22.6882 116.8652 250.0" ,
2013-10-19 20:31:12 +00:00
"VENERA. IN NIMLOC 75234159EAC457800920" : "VENERA.\t3600\tIN\tNIMLOC\t75234159EAC457800920" ,
"VAXA. IN EID 3141592653589793" : "VAXA.\t3600\tIN\tEID\t3141592653589793" ,
2013-10-13 11:25:08 +00:00
}
for i , o := range dt {
2015-02-26 06:14:21 +00:00
rr , err := NewRR ( i )
if err != nil {
t . Error ( "failed to parse RR: " , err )
2013-10-13 11:25:08 +00:00
continue
}
if rr . String ( ) != o {
2015-02-26 06:14:21 +00:00
t . Errorf ( "`%s' should be equal to\n`%s', but is `%s'" , i , o , rr . String ( ) )
2013-10-13 11:25:08 +00:00
} else {
t . Logf ( "RR is OK: `%s'" , rr . String ( ) )
}
}
}
2013-10-13 12:23:02 +00:00
func TestPX ( t * testing . T ) {
dt := map [ string ] string {
2013-10-15 14:21:47 +00:00
"*.net2.it. IN PX 10 net2.it. PRMD-net2.ADMD-p400.C-it." : "*.net2.it.\t3600\tIN\tPX\t10 net2.it. PRMD-net2.ADMD-p400.C-it." ,
2013-10-13 12:23:02 +00:00
"ab.net2.it. IN PX 10 ab.net2.it. O-ab.PRMD-net2.ADMDb.C-it." : "ab.net2.it.\t3600\tIN\tPX\t10 ab.net2.it. O-ab.PRMD-net2.ADMDb.C-it." ,
}
for i , o := range dt {
2015-02-26 06:14:21 +00:00
rr , err := NewRR ( i )
if err != nil {
t . Error ( "failed to parse RR: " , err )
2013-10-13 12:23:02 +00:00
continue
}
if rr . String ( ) != o {
2015-02-26 06:14:21 +00:00
t . Errorf ( "`%s' should be equal to\n`%s', but is `%s'" , i , o , rr . String ( ) )
2013-10-13 12:23:02 +00:00
} else {
t . Logf ( "RR is OK: `%s'" , rr . String ( ) )
}
}
}
2013-03-04 10:24:08 +00:00
func TestComment ( t * testing . T ) {
2013-03-04 14:40:22 +00:00
// Comments we must see
comments := map [ string ] bool { "; this is comment 1" : true ,
"; this is comment 4" : true , "; this is comment 6" : true ,
"; this is comment 7" : true , "; this is comment 8" : true }
2013-03-04 10:24:08 +00:00
zone := `
2013-03-04 14:40:22 +00:00
foo . IN A 10.0 .0 .1 ; this is comment 1
2013-03-04 10:24:08 +00:00
foo . IN A (
2013-03-04 11:16:20 +00:00
10.0 .0 .2 ; this is comment2
2013-03-04 10:24:08 +00:00
)
2013-03-04 11:16:20 +00:00
; this is comment3
2013-03-04 10:24:08 +00:00
foo . IN A 10.0 .0 .3
2013-03-04 14:40:22 +00:00
foo . IN A ( 10.0 .0 .4 ) ; this is comment 4
2013-03-04 11:16:20 +00:00
foo . IN A 10.0 .0 .5
; this is comment5
foo . IN A 10.0 .0 .6
2013-03-04 14:40:22 +00:00
foo . IN DNSKEY 256 3 5 AwEAAb + 8 l ; this is comment 6
foo . IN NSEC miek . nl . TXT RRSIG NSEC ; this is comment 7
foo . IN TXT "THIS IS TEXT MAN" ; this is comment 8
2013-03-04 10:24:08 +00:00
`
for x := range ParseZone ( strings . NewReader ( zone ) , "." , "" ) {
if x . Error == nil {
2013-03-04 14:40:22 +00:00
if x . Comment != "" {
if _ , ok := comments [ x . Comment ] ; ! ok {
2015-02-21 05:03:02 +00:00
t . Errorf ( "wrong comment %s" , x . Comment )
2013-03-04 14:40:22 +00:00
}
}
2013-03-04 10:24:08 +00:00
}
}
}
2013-04-15 17:42:07 +00:00
func TestEUIxx ( t * testing . T ) {
tests := map [ string ] string {
"host.example. IN EUI48 00-00-5e-90-01-2a" : "host.example.\t3600\tIN\tEUI48\t00-00-5e-90-01-2a" ,
"host.example. IN EUI64 00-00-5e-ef-00-00-00-2a" : "host.example.\t3600\tIN\tEUI64\t00-00-5e-ef-00-00-00-2a" ,
}
for i , o := range tests {
2015-02-26 06:14:21 +00:00
r , err := NewRR ( i )
if err != nil {
2015-02-26 08:49:59 +00:00
t . Errorf ( "failed to parse %s: %v" , i , err )
2013-04-15 17:42:07 +00:00
}
if r . String ( ) != o {
2015-02-26 06:14:21 +00:00
t . Errorf ( "want %s, got %s" , o , r . String ( ) )
2013-04-15 17:42:07 +00:00
}
}
}
2013-04-30 14:42:04 +00:00
func TestUserRR ( t * testing . T ) {
tests := map [ string ] string {
2013-06-14 18:42:55 +00:00
"host.example. IN UID 1234" : "host.example.\t3600\tIN\tUID\t1234" ,
"host.example. IN GID 1234556" : "host.example.\t3600\tIN\tGID\t1234556" ,
2013-04-30 14:42:04 +00:00
"host.example. IN UINFO \"Miek Gieben\"" : "host.example.\t3600\tIN\tUINFO\t\"Miek Gieben\"" ,
}
for i , o := range tests {
2015-02-26 06:14:21 +00:00
r , err := NewRR ( i )
if err != nil {
2015-02-26 08:49:59 +00:00
t . Errorf ( "failed to parse %s: %v" , i , err )
2013-04-30 14:42:04 +00:00
}
if r . String ( ) != o {
2015-02-26 06:14:21 +00:00
t . Errorf ( "want %s, got %s" , o , r . String ( ) )
2013-04-30 14:42:04 +00:00
}
}
}
2013-06-13 18:19:40 +00:00
2013-06-29 07:46:34 +00:00
func TestTXT ( t * testing . T ) {
2013-06-13 18:19:40 +00:00
// Test single entry TXT record
rr , err := NewRR ( ` _raop._tcp.local. 60 IN TXT "single value" ` )
if err != nil {
2014-08-19 08:39:04 +00:00
t . Error ( "failed to parse single value TXT record" , err )
2013-06-13 18:19:40 +00:00
} else if rr , ok := rr . ( * TXT ) ; ! ok {
2014-08-19 08:39:04 +00:00
t . Error ( "wrong type, record should be of type TXT" )
2013-06-13 18:19:40 +00:00
} else {
if len ( rr . Txt ) != 1 {
2014-08-19 08:39:04 +00:00
t . Error ( "bad size of TXT value:" , len ( rr . Txt ) )
2013-06-13 18:19:40 +00:00
} else if rr . Txt [ 0 ] != "single value" {
2014-08-19 08:39:04 +00:00
t . Error ( "bad single value" )
2013-06-13 18:19:40 +00:00
}
if rr . String ( ) != ` _raop._tcp.local. 60 IN TXT "single value" ` {
2014-08-19 08:39:04 +00:00
t . Error ( "bad representation of TXT record:" , rr . String ( ) )
2013-06-13 18:19:40 +00:00
}
2014-01-11 05:28:47 +00:00
if rr . len ( ) != 28 + 1 + 12 {
2014-08-19 08:39:04 +00:00
t . Error ( "bad size of serialized record:" , rr . len ( ) )
2013-06-13 18:19:40 +00:00
}
}
// Test multi entries TXT record
rr , err = NewRR ( ` _raop._tcp.local. 60 IN TXT "a=1" "b=2" "c=3" "d=4" ` )
if err != nil {
2014-08-19 08:39:04 +00:00
t . Error ( "failed to parse multi-values TXT record" , err )
2013-06-13 18:19:40 +00:00
} else if rr , ok := rr . ( * TXT ) ; ! ok {
2014-08-19 08:39:04 +00:00
t . Error ( "wrong type, record should be of type TXT" )
2013-06-13 18:19:40 +00:00
} else {
if len ( rr . Txt ) != 4 {
2014-08-19 08:39:04 +00:00
t . Error ( "bad size of TXT multi-value:" , len ( rr . Txt ) )
2013-06-13 18:19:40 +00:00
} else if rr . Txt [ 0 ] != "a=1" || rr . Txt [ 1 ] != "b=2" || rr . Txt [ 2 ] != "c=3" || rr . Txt [ 3 ] != "d=4" {
2014-08-19 08:39:04 +00:00
t . Error ( "bad values in TXT records" )
2013-06-13 18:19:40 +00:00
}
if rr . String ( ) != ` _raop._tcp.local. 60 IN TXT "a=1" "b=2" "c=3" "d=4" ` {
2014-08-19 08:39:04 +00:00
t . Error ( "bad representation of TXT multi value record:" , rr . String ( ) )
2013-06-13 18:19:40 +00:00
}
2014-01-11 05:30:46 +00:00
if rr . len ( ) != 28 + 1 + 3 + 1 + 3 + 1 + 3 + 1 + 3 {
2014-08-19 08:39:04 +00:00
t . Error ( "bad size of serialized multi value record:" , rr . len ( ) )
2013-06-13 18:19:40 +00:00
}
}
2014-01-11 05:31:43 +00:00
// Test empty-string in TXT record
rr , err = NewRR ( ` _raop._tcp.local. 60 IN TXT "" ` )
if err != nil {
2014-08-19 08:39:04 +00:00
t . Error ( "failed to parse empty-string TXT record" , err )
2014-01-11 05:31:43 +00:00
} else if rr , ok := rr . ( * TXT ) ; ! ok {
2014-08-19 08:39:04 +00:00
t . Error ( "wrong type, record should be of type TXT" )
2014-01-11 05:31:43 +00:00
} else {
if len ( rr . Txt ) != 1 {
2014-08-19 08:39:04 +00:00
t . Error ( "bad size of TXT empty-string value:" , len ( rr . Txt ) )
2014-01-11 05:31:43 +00:00
} else if rr . Txt [ 0 ] != "" {
2014-08-19 08:39:04 +00:00
t . Error ( "bad value for empty-string TXT record" )
2014-01-11 05:31:43 +00:00
}
if rr . String ( ) != ` _raop._tcp.local. 60 IN TXT "" ` {
2014-08-19 08:39:04 +00:00
t . Error ( "bad representation of empty-string TXT record:" , rr . String ( ) )
2014-01-11 05:31:43 +00:00
}
if rr . len ( ) != 28 + 1 {
2014-08-19 08:39:04 +00:00
t . Error ( "bad size of serialized record:" , rr . len ( ) )
2014-01-11 05:31:43 +00:00
}
}
2015-03-04 09:33:37 +00:00
// Test TXT record with chunk larger than 255 bytes, they should be split up, by the parser
s := ""
for i := 0 ; i < 255 ; i ++ {
s += "a"
}
s += "b"
rr , err = NewRR ( ` test.local. 60 IN TXT " ` + s + ` " ` )
if err != nil {
t . Error ( "failed to parse empty-string TXT record" , err )
}
if rr . ( * TXT ) . Txt [ 1 ] != "b" {
t . Errorf ( "Txt should have two chunk, last one my be 'b', but is %s" , rr . ( * TXT ) . Txt [ 1 ] )
}
t . Log ( rr . String ( ) )
2013-06-13 18:19:40 +00:00
}
2013-12-05 07:48:13 +00:00
func TestTypeXXXX ( t * testing . T ) {
2013-12-05 09:54:46 +00:00
_ , err := NewRR ( "example.com IN TYPE1234 \\# 4 aabbccdd" )
if err != nil {
2015-02-26 06:14:21 +00:00
t . Errorf ( "failed to parse TYPE1234 RR: %v" , err )
2013-12-05 09:54:46 +00:00
}
_ , err = NewRR ( "example.com IN TYPE655341 \\# 8 aabbccddaabbccdd" )
2013-06-13 18:19:40 +00:00
if err == nil {
2015-02-21 05:03:02 +00:00
t . Errorf ( "this should not work, for TYPE655341" )
2013-06-13 18:19:40 +00:00
}
2013-12-05 09:54:46 +00:00
_ , err = NewRR ( "example.com IN TYPE1 \\# 4 0a000001" )
2013-06-13 18:19:40 +00:00
if err == nil {
2015-02-21 05:03:02 +00:00
t . Errorf ( "this should not work" )
2013-06-13 18:19:40 +00:00
}
}
2013-06-29 07:46:34 +00:00
func TestPTR ( t * testing . T ) {
2013-06-13 18:19:40 +00:00
_ , err := NewRR ( "144.2.0.192.in-addr.arpa. 900 IN PTR ilouse03146p0\\(.example.com." )
if err != nil {
2015-02-26 06:14:21 +00:00
t . Error ( "failed to parse " , err )
2013-06-13 18:19:40 +00:00
}
}
2013-06-14 06:31:22 +00:00
func TestDigit ( t * testing . T ) {
tests := map [ string ] byte {
2013-06-14 11:35:06 +00:00
"miek\\000.nl. 100 IN TXT \"A\"" : 0 ,
"miek\\001.nl. 100 IN TXT \"A\"" : 1 ,
"miek\\254.nl. 100 IN TXT \"A\"" : 254 ,
"miek\\255.nl. 100 IN TXT \"A\"" : 255 ,
"miek\\256.nl. 100 IN TXT \"A\"" : 0 ,
"miek\\257.nl. 100 IN TXT \"A\"" : 1 ,
"miek\\004.nl. 100 IN TXT \"A\"" : 4 ,
2013-06-14 06:31:22 +00:00
}
for s , i := range tests {
2015-02-26 06:14:21 +00:00
r , err := NewRR ( s )
2013-06-14 06:31:22 +00:00
buf := make ( [ ] byte , 40 )
2015-02-26 06:14:21 +00:00
if err != nil {
t . Fatalf ( "failed to parse %v" , err )
2013-06-14 06:31:22 +00:00
}
PackRR ( r , buf , 0 , nil , false )
2015-02-26 06:14:21 +00:00
t . Log ( buf )
2013-06-14 06:31:22 +00:00
if buf [ 5 ] != i {
t . Fatalf ( "5 pos must be %d, is %d" , i , buf [ 5 ] )
}
r1 , _ , _ := UnpackRR ( buf , 0 )
2013-06-14 11:35:06 +00:00
if r1 . Header ( ) . Ttl != 100 {
2014-08-19 08:39:04 +00:00
t . Fatalf ( "TTL should %d, is %d" , 100 , r1 . Header ( ) . Ttl )
2013-06-14 11:35:06 +00:00
}
2013-06-14 06:31:22 +00:00
}
}
2014-01-11 08:37:34 +00:00
func TestParseRRSIGTimestamp ( t * testing . T ) {
tests := map [ string ] bool {
` miek.nl. IN RRSIG SOA 8 2 43200 20140210031301 20140111031301 12051 miek.nl. MVZUyrYwq0iZhMFDDnVXD2BvuNiUJjSYlJAgzyAE6CF875BMvvZa+Sb0 RlSCL7WODQSQHhCx/fegHhVVF+Iz8N8kOLrmXD1+jO3Bm6Prl5UhcsPx WTBsg/kmxbp8sR1kvH4oZJtVfakG3iDerrxNaf0sQwhZzyfJQAqpC7pcBoc= ` : true ,
2014-01-11 08:50:10 +00:00
` miek.nl. IN RRSIG SOA 8 2 43200 315565800 4102477800 12051 miek.nl. MVZUyrYwq0iZhMFDDnVXD2BvuNiUJjSYlJAgzyAE6CF875BMvvZa+Sb0 RlSCL7WODQSQHhCx/fegHhVVF+Iz8N8kOLrmXD1+jO3Bm6Prl5UhcsPx WTBsg/kmxbp8sR1kvH4oZJtVfakG3iDerrxNaf0sQwhZzyfJQAqpC7pcBoc= ` : true ,
2014-01-11 08:37:34 +00:00
}
2015-02-19 09:58:33 +00:00
for r := range tests {
2015-02-26 06:14:21 +00:00
_ , err := NewRR ( r )
if err != nil {
t . Error ( err )
2014-01-11 08:37:34 +00:00
}
}
2014-01-11 08:50:10 +00:00
}
2014-01-11 16:32:08 +00:00
func TestTxtEqual ( t * testing . T ) {
rr1 := new ( TXT )
rr1 . Hdr = RR_Header { Name : "." , Rrtype : TypeTXT , Class : ClassINET , Ttl : 0 }
rr1 . Txt = [ ] string { "a\"a" , "\"" , "b" }
rr2 , _ := NewRR ( rr1 . String ( ) )
if rr1 . String ( ) != rr2 . String ( ) {
2015-02-21 05:03:02 +00:00
// This is not an error, but keep this test.
2015-02-26 06:14:21 +00:00
t . Errorf ( "these two TXT records should match:\n%s\n%s" , rr1 . String ( ) , rr2 . String ( ) )
2014-01-11 16:32:08 +00:00
}
2015-02-26 06:14:21 +00:00
t . Logf ( "%s\n%s" , rr1 . String ( ) , rr2 . String ( ) )
2014-01-11 16:32:08 +00:00
}
2014-04-04 18:33:50 +00:00
2014-03-01 07:34:44 +00:00
func TestTxtLong ( t * testing . T ) {
rr1 := new ( TXT )
rr1 . Hdr = RR_Header { Name : "." , Rrtype : TypeTXT , Class : ClassINET , Ttl : 0 }
// Make a long txt record, this breaks when sending the packet,
// but not earlier.
rr1 . Txt = [ ] string { "start-" }
for i := 0 ; i < 200 ; i ++ {
rr1 . Txt [ 0 ] += "start-"
}
str := rr1 . String ( )
if len ( str ) < len ( rr1 . Txt [ 0 ] ) {
2015-02-21 05:03:02 +00:00
t . Error ( "string conversion should work" )
2014-03-01 07:34:44 +00:00
}
}
2014-04-04 18:33:50 +00:00
2014-08-30 06:34:05 +00:00
// Basically, don't crash.
2014-04-05 07:06:49 +00:00
func TestMalformedPackets ( t * testing . T ) {
var packets = [ ] string {
2014-04-06 08:29:42 +00:00
"0021641c0000000100000000000078787878787878787878787303636f6d0000100001" ,
2014-04-05 07:06:49 +00:00
}
2014-04-04 18:33:50 +00:00
2014-04-23 20:06:17 +00:00
// com = 63 6f 6d
2014-04-05 07:06:49 +00:00
for _ , packet := range packets {
data , _ := hex . DecodeString ( packet )
2014-04-23 20:06:17 +00:00
// for _, v := range data {
2015-02-26 08:30:40 +00:00
// t.Log(v)
2014-04-23 20:06:17 +00:00
// }
2014-04-05 07:06:49 +00:00
var msg Msg
msg . Unpack ( data )
2014-04-23 20:06:17 +00:00
// println(msg.String())
2014-04-05 07:06:49 +00:00
}
2014-04-04 18:33:50 +00:00
}
2014-08-29 09:42:43 +00:00
2014-09-11 19:49:20 +00:00
type algorithm struct {
name uint8
bits int
}
2014-12-06 01:41:33 +00:00
func TestNewPrivateKey ( t * testing . T ) {
2014-11-12 10:19:20 +00:00
if testing . Short ( ) {
t . Skip ( "skipping test in short mode." )
}
2014-09-11 19:49:20 +00:00
algorithms := [ ] algorithm {
2015-02-26 09:48:30 +00:00
algorithm { ECDSAP256SHA256 , 256 } ,
algorithm { ECDSAP384SHA384 , 384 } ,
algorithm { RSASHA1 , 1024 } ,
algorithm { RSASHA256 , 2048 } ,
algorithm { DSA , 1024 } ,
2014-09-11 19:49:20 +00:00
}
for _ , algo := range algorithms {
key := new ( DNSKEY )
key . Hdr . Rrtype = TypeDNSKEY
key . Hdr . Name = "miek.nl."
key . Hdr . Class = ClassINET
key . Hdr . Ttl = 14400
key . Flags = 256
key . Protocol = 3
key . Algorithm = algo . name
privkey , err := key . Generate ( algo . bits )
if err != nil {
2015-02-26 06:14:21 +00:00
t . Fatal ( err )
2014-09-11 19:49:20 +00:00
}
newPrivKey , err := key . NewPrivateKey ( key . PrivateKeyString ( privkey ) )
if err != nil {
2015-02-21 05:03:02 +00:00
t . Error ( key . String ( ) )
t . Error ( key . PrivateKeyString ( privkey ) )
2015-02-26 06:14:21 +00:00
t . Fatal ( err )
2014-09-11 19:49:20 +00:00
}
switch newPrivKey := newPrivKey . ( type ) {
2015-01-23 21:04:29 +00:00
case * RSAPrivateKey :
( * rsa . PrivateKey ) ( newPrivKey ) . Precompute ( )
2014-09-11 19:49:20 +00:00
}
if ! reflect . DeepEqual ( privkey , newPrivKey ) {
2015-02-26 06:14:21 +00:00
t . Errorf ( "[%v] Private keys differ:\n%#v\n%#v" , AlgorithmToString [ algo . name ] , privkey , newPrivKey )
2014-09-11 19:49:20 +00:00
}
}
}
2015-01-11 09:20:04 +00:00
// special input test
func TestNewRRSpecial ( t * testing . T ) {
var (
rr RR
err error
expect string
)
rr , err = NewRR ( "; comment" )
expect = ""
if err != nil {
2015-02-26 08:49:59 +00:00
t . Errorf ( "unexpected err: %v" , err )
2015-01-11 09:20:04 +00:00
}
if rr != nil {
Implement custom verbs for fmt.Printf use
The dns package implements String() for all RR types, but sometimes you will
need more flexibility. The functions Printf, Sprintf, etc. implemented formatted I/O
for the RR type.
Printing
The verbs:
Generic part of RRs:
%N the owner name of the RR
%C the class: IN, CH, CLASS15, etc.
%D the TTL in seconds
%Y the type: MX, A, etc.
The rdata of each RR differs, we allow each field to be printed as a string.
Rdata:
%0 the first rdata field
%1 the second rdata field
%2 the third rdata field
.. ...
%9 the nineth rdata field
%R all rdata fields
The rdata fields remain a TODO, but will be implemented using
reflection.
2015-01-11 17:23:02 +00:00
t . Errorf ( "unexpected result: [%s] != [%s]" , rr , expect )
2015-01-11 09:20:04 +00:00
}
rr , err = NewRR ( "" )
expect = ""
if err != nil {
2015-02-26 08:49:59 +00:00
t . Errorf ( "unexpected err: %v" , err )
2015-01-11 09:20:04 +00:00
}
if rr != nil {
Implement custom verbs for fmt.Printf use
The dns package implements String() for all RR types, but sometimes you will
need more flexibility. The functions Printf, Sprintf, etc. implemented formatted I/O
for the RR type.
Printing
The verbs:
Generic part of RRs:
%N the owner name of the RR
%C the class: IN, CH, CLASS15, etc.
%D the TTL in seconds
%Y the type: MX, A, etc.
The rdata of each RR differs, we allow each field to be printed as a string.
Rdata:
%0 the first rdata field
%1 the second rdata field
%2 the third rdata field
.. ...
%9 the nineth rdata field
%R all rdata fields
The rdata fields remain a TODO, but will be implemented using
reflection.
2015-01-11 17:23:02 +00:00
t . Errorf ( "unexpected result: [%s] != [%s]" , rr , expect )
2015-01-11 09:20:04 +00:00
}
rr , err = NewRR ( "$ORIGIN foo." )
expect = ""
if err != nil {
2015-02-26 08:49:59 +00:00
t . Errorf ( "unexpected err: %v" , err )
2015-01-11 09:20:04 +00:00
}
if rr != nil {
Implement custom verbs for fmt.Printf use
The dns package implements String() for all RR types, but sometimes you will
need more flexibility. The functions Printf, Sprintf, etc. implemented formatted I/O
for the RR type.
Printing
The verbs:
Generic part of RRs:
%N the owner name of the RR
%C the class: IN, CH, CLASS15, etc.
%D the TTL in seconds
%Y the type: MX, A, etc.
The rdata of each RR differs, we allow each field to be printed as a string.
Rdata:
%0 the first rdata field
%1 the second rdata field
%2 the third rdata field
.. ...
%9 the nineth rdata field
%R all rdata fields
The rdata fields remain a TODO, but will be implemented using
reflection.
2015-01-11 17:23:02 +00:00
t . Errorf ( "unexpected result: [%s] != [%s]" , rr , expect )
2015-01-11 09:20:04 +00:00
}
rr , err = NewRR ( " " )
expect = ""
if err != nil {
2015-02-26 08:49:59 +00:00
t . Errorf ( "unexpected err: %v" , err )
2015-01-11 09:20:04 +00:00
}
if rr != nil {
Implement custom verbs for fmt.Printf use
The dns package implements String() for all RR types, but sometimes you will
need more flexibility. The functions Printf, Sprintf, etc. implemented formatted I/O
for the RR type.
Printing
The verbs:
Generic part of RRs:
%N the owner name of the RR
%C the class: IN, CH, CLASS15, etc.
%D the TTL in seconds
%Y the type: MX, A, etc.
The rdata of each RR differs, we allow each field to be printed as a string.
Rdata:
%0 the first rdata field
%1 the second rdata field
%2 the third rdata field
.. ...
%9 the nineth rdata field
%R all rdata fields
The rdata fields remain a TODO, but will be implemented using
reflection.
2015-01-11 17:23:02 +00:00
t . Errorf ( "unexpected result: [%s] != [%s]" , rr , expect )
2015-01-11 09:20:04 +00:00
}
rr , err = NewRR ( "\n" )
expect = ""
if err != nil {
2015-02-26 08:49:59 +00:00
t . Errorf ( "unexpected err: %v" , err )
2015-01-11 09:20:04 +00:00
}
if rr != nil {
Implement custom verbs for fmt.Printf use
The dns package implements String() for all RR types, but sometimes you will
need more flexibility. The functions Printf, Sprintf, etc. implemented formatted I/O
for the RR type.
Printing
The verbs:
Generic part of RRs:
%N the owner name of the RR
%C the class: IN, CH, CLASS15, etc.
%D the TTL in seconds
%Y the type: MX, A, etc.
The rdata of each RR differs, we allow each field to be printed as a string.
Rdata:
%0 the first rdata field
%1 the second rdata field
%2 the third rdata field
.. ...
%9 the nineth rdata field
%R all rdata fields
The rdata fields remain a TODO, but will be implemented using
reflection.
2015-01-11 17:23:02 +00:00
t . Errorf ( "unexpected result: [%s] != [%s]" , rr , expect )
2015-01-11 09:20:04 +00:00
}
rr , err = NewRR ( "foo. A 1.1.1.1\nbar. A 2.2.2.2" )
expect = "foo.\t3600\tIN\tA\t1.1.1.1"
if err != nil {
2015-02-26 08:49:59 +00:00
t . Errorf ( "unexpected err: %v" , err )
2015-01-11 09:20:04 +00:00
}
if rr == nil || rr . String ( ) != expect {
Implement custom verbs for fmt.Printf use
The dns package implements String() for all RR types, but sometimes you will
need more flexibility. The functions Printf, Sprintf, etc. implemented formatted I/O
for the RR type.
Printing
The verbs:
Generic part of RRs:
%N the owner name of the RR
%C the class: IN, CH, CLASS15, etc.
%D the TTL in seconds
%Y the type: MX, A, etc.
The rdata of each RR differs, we allow each field to be printed as a string.
Rdata:
%0 the first rdata field
%1 the second rdata field
%2 the third rdata field
.. ...
%9 the nineth rdata field
%R all rdata fields
The rdata fields remain a TODO, but will be implemented using
reflection.
2015-01-11 17:23:02 +00:00
t . Errorf ( "unexpected result: [%s] != [%s]" , rr , expect )
2015-01-11 09:20:04 +00:00
}
}
Implement custom verbs for fmt.Printf use
The dns package implements String() for all RR types, but sometimes you will
need more flexibility. The functions Printf, Sprintf, etc. implemented formatted I/O
for the RR type.
Printing
The verbs:
Generic part of RRs:
%N the owner name of the RR
%C the class: IN, CH, CLASS15, etc.
%D the TTL in seconds
%Y the type: MX, A, etc.
The rdata of each RR differs, we allow each field to be printed as a string.
Rdata:
%0 the first rdata field
%1 the second rdata field
%2 the third rdata field
.. ...
%9 the nineth rdata field
%R all rdata fields
The rdata fields remain a TODO, but will be implemented using
reflection.
2015-01-11 17:23:02 +00:00
2015-01-11 21:01:54 +00:00
func TestPrintfVerbsRdata ( t * testing . T ) {
x , _ := NewRR ( "www.miek.nl. IN MX 20 mx.miek.nl." )
if Field ( x , 1 ) != "20" {
t . Errorf ( "should be 20" )
}
if Field ( x , 2 ) != "mx.miek.nl." {
t . Errorf ( "should be mx.miek.nl." )
Implement custom verbs for fmt.Printf use
The dns package implements String() for all RR types, but sometimes you will
need more flexibility. The functions Printf, Sprintf, etc. implemented formatted I/O
for the RR type.
Printing
The verbs:
Generic part of RRs:
%N the owner name of the RR
%C the class: IN, CH, CLASS15, etc.
%D the TTL in seconds
%Y the type: MX, A, etc.
The rdata of each RR differs, we allow each field to be printed as a string.
Rdata:
%0 the first rdata field
%1 the second rdata field
%2 the third rdata field
.. ...
%9 the nineth rdata field
%R all rdata fields
The rdata fields remain a TODO, but will be implemented using
reflection.
2015-01-11 17:23:02 +00:00
}
2015-01-13 10:20:34 +00:00
2015-01-12 22:33:49 +00:00
x , _ = NewRR ( "www.miek.nl. IN A 127.0.0.1" )
2015-01-13 10:20:34 +00:00
if Field ( x , 1 ) != "127.0.0.1" {
t . Errorf ( "should be 127.0.0.1" )
}
2015-01-12 22:33:49 +00:00
x , _ = NewRR ( "www.miek.nl. IN AAAA ::1" )
2015-01-13 10:20:34 +00:00
if Field ( x , 1 ) != "::1" {
t . Errorf ( "should be ::1" )
}
x , _ = NewRR ( "www.miek.nl. IN NSEC a.miek.nl. A NS SOA MX AAAA" )
if Field ( x , 1 ) != "a.miek.nl." {
t . Errorf ( "should be a.miek.nl." )
}
if Field ( x , 2 ) != "A NS SOA MX AAAA" {
t . Errorf ( "should be A NS SOA MX AAAA" )
}
x , _ = NewRR ( "www.miek.nl. IN TXT \"first\" \"second\"" )
if Field ( x , 1 ) != "first second" {
t . Errorf ( "should be first second" )
}
2015-01-13 11:43:57 +00:00
if Field ( x , 0 ) != "" {
t . Errorf ( "should be empty" )
}
Implement custom verbs for fmt.Printf use
The dns package implements String() for all RR types, but sometimes you will
need more flexibility. The functions Printf, Sprintf, etc. implemented formatted I/O
for the RR type.
Printing
The verbs:
Generic part of RRs:
%N the owner name of the RR
%C the class: IN, CH, CLASS15, etc.
%D the TTL in seconds
%Y the type: MX, A, etc.
The rdata of each RR differs, we allow each field to be printed as a string.
Rdata:
%0 the first rdata field
%1 the second rdata field
%2 the third rdata field
.. ...
%9 the nineth rdata field
%R all rdata fields
The rdata fields remain a TODO, but will be implemented using
reflection.
2015-01-11 17:23:02 +00:00
}
2015-01-25 10:58:30 +00:00
func TestParseIPSECKEY ( t * testing . T ) {
tests := [ ] string {
"38.2.0.192.in-addr.arpa. 7200 IN IPSECKEY ( 10 1 2 192.0.2.38 AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ== )" ,
"38.2.0.192.in-addr.arpa.\t7200\tIN\tIPSECKEY\t10 1 2 192.0.2.38 AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==" ,
"38.2.0.192.in-addr.arpa. 7200 IN IPSECKEY ( 10 0 2 . AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ== )" ,
"38.2.0.192.in-addr.arpa.\t7200\tIN\tIPSECKEY\t10 0 2 . AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==" ,
"38.2.0.192.in-addr.arpa. 7200 IN IPSECKEY ( 10 1 2 192.0.2.3 AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ== )" ,
"38.2.0.192.in-addr.arpa.\t7200\tIN\tIPSECKEY\t10 1 2 192.0.2.3 AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==" ,
"38.1.0.192.in-addr.arpa. 7200 IN IPSECKEY ( 10 3 2 mygateway.example.com. AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ== )" ,
"38.1.0.192.in-addr.arpa.\t7200\tIN\tIPSECKEY\t10 3 2 mygateway.example.com. AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==" ,
"0.d.4.0.3.0.e.f.f.f.3.f.0.1.2.0 7200 IN IPSECKEY ( 10 2 2 2001:0DB8:0:8002::2000:1 AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ== )" ,
"0.d.4.0.3.0.e.f.f.f.3.f.0.1.2.0.\t7200\tIN\tIPSECKEY\t10 2 2 2001:db8:0:8002::2000:1 AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==" ,
}
for i := 0 ; i < len ( tests ) - 1 ; i ++ {
t1 := tests [ i ]
e1 := tests [ i + 1 ]
2015-02-26 06:14:21 +00:00
r , err := NewRR ( t1 )
if err != nil {
t . Errorf ( "failed to parse IPSECKEY %v" , err )
2015-01-25 10:58:30 +00:00
continue
}
if r . String ( ) != e1 {
2015-02-26 06:14:21 +00:00
t . Errorf ( "these two IPSECKEY records should match:\n%s\n%s" , r . String ( ) , e1 )
2015-01-25 10:58:30 +00:00
}
i ++
}
}