1package dns 2 3import ( 4 "bytes" 5 "encoding/hex" 6 "net" 7 "testing" 8) 9 10func TestPackUnpack(t *testing.T) { 11 out := new(Msg) 12 out.Answer = make([]RR, 1) 13 key := &DNSKEY{Flags: 257, Protocol: 3, Algorithm: RSASHA1} 14 key.Hdr = RR_Header{Name: "miek.nl.", Rrtype: TypeDNSKEY, Class: ClassINET, Ttl: 3600} 15 key.PublicKey = "AwEAAaHIwpx3w4VHKi6i1LHnTaWeHCL154Jug0Rtc9ji5qwPXpBo6A5sRv7cSsPQKPIwxLpyCrbJ4mr2L0EPOdvP6z6YfljK2ZmTbogU9aSU2fiq/4wjxbdkLyoDVgtO+JsxNN4bjr4WcWhsmk1Hg93FV9ZpkWb0Tbad8DFqNDzr//kZ" 16 17 out.Answer[0] = key 18 msg, err := out.Pack() 19 if err != nil { 20 t.Error("failed to pack msg with DNSKEY") 21 } 22 in := new(Msg) 23 if in.Unpack(msg) != nil { 24 t.Error("failed to unpack msg with DNSKEY") 25 } 26 27 sig := &RRSIG{TypeCovered: TypeDNSKEY, Algorithm: RSASHA1, Labels: 2, 28 OrigTtl: 3600, Expiration: 4000, Inception: 4000, KeyTag: 34641, SignerName: "miek.nl.", 29 Signature: "AwEAAaHIwpx3w4VHKi6i1LHnTaWeHCL154Jug0Rtc9ji5qwPXpBo6A5sRv7cSsPQKPIwxLpyCrbJ4mr2L0EPOdvP6z6YfljK2ZmTbogU9aSU2fiq/4wjxbdkLyoDVgtO+JsxNN4bjr4WcWhsmk1Hg93FV9ZpkWb0Tbad8DFqNDzr//kZ"} 30 sig.Hdr = RR_Header{Name: "miek.nl.", Rrtype: TypeRRSIG, Class: ClassINET, Ttl: 3600} 31 32 out.Answer[0] = sig 33 msg, err = out.Pack() 34 if err != nil { 35 t.Error("failed to pack msg with RRSIG") 36 } 37 38 if in.Unpack(msg) != nil { 39 t.Error("failed to unpack msg with RRSIG") 40 } 41} 42 43func TestPackUnpack2(t *testing.T) { 44 m := new(Msg) 45 m.Extra = make([]RR, 1) 46 m.Answer = make([]RR, 1) 47 dom := "miek.nl." 48 rr := new(A) 49 rr.Hdr = RR_Header{Name: dom, Rrtype: TypeA, Class: ClassINET, Ttl: 0} 50 rr.A = net.IPv4(127, 0, 0, 1) 51 52 x := new(TXT) 53 x.Hdr = RR_Header{Name: dom, Rrtype: TypeTXT, Class: ClassINET, Ttl: 0} 54 x.Txt = []string{"heelalaollo"} 55 56 m.Extra[0] = x 57 m.Answer[0] = rr 58 _, err := m.Pack() 59 if err != nil { 60 t.Error("Packing failed: ", err) 61 return 62 } 63} 64 65func TestPackUnpack3(t *testing.T) { 66 m := new(Msg) 67 m.Extra = make([]RR, 2) 68 m.Answer = make([]RR, 1) 69 dom := "miek.nl." 70 rr := new(A) 71 rr.Hdr = RR_Header{Name: dom, Rrtype: TypeA, Class: ClassINET, Ttl: 0} 72 rr.A = net.IPv4(127, 0, 0, 1) 73 74 x1 := new(TXT) 75 x1.Hdr = RR_Header{Name: dom, Rrtype: TypeTXT, Class: ClassINET, Ttl: 0} 76 x1.Txt = []string{} 77 78 x2 := new(TXT) 79 x2.Hdr = RR_Header{Name: dom, Rrtype: TypeTXT, Class: ClassINET, Ttl: 0} 80 x2.Txt = []string{"heelalaollo"} 81 82 m.Extra[0] = x1 83 m.Extra[1] = x2 84 m.Answer[0] = rr 85 b, err := m.Pack() 86 if err != nil { 87 t.Error("packing failed: ", err) 88 return 89 } 90 91 var unpackMsg Msg 92 err = unpackMsg.Unpack(b) 93 if err != nil { 94 t.Error("unpacking failed") 95 return 96 } 97} 98 99func TestBailiwick(t *testing.T) { 100 yes := map[string]string{ 101 "miek1.nl": "miek1.nl", 102 "miek.nl": "ns.miek.nl", 103 ".": "miek.nl", 104 } 105 for parent, child := range yes { 106 if !IsSubDomain(parent, child) { 107 t.Errorf("%s should be child of %s", child, parent) 108 t.Errorf("comparelabels %d", CompareDomainName(parent, child)) 109 t.Errorf("lenlabels %d %d", CountLabel(parent), CountLabel(child)) 110 } 111 } 112 no := map[string]string{ 113 "www.miek.nl": "ns.miek.nl", 114 "m\\.iek.nl": "ns.miek.nl", 115 "w\\.iek.nl": "w.iek.nl", 116 "p\\\\.iek.nl": "ns.p.iek.nl", // p\\.iek.nl , literal \ in domain name 117 "miek.nl": ".", 118 } 119 for parent, child := range no { 120 if IsSubDomain(parent, child) { 121 t.Errorf("%s should not be child of %s", child, parent) 122 t.Errorf("comparelabels %d", CompareDomainName(parent, child)) 123 t.Errorf("lenlabels %d %d", CountLabel(parent), CountLabel(child)) 124 } 125 } 126} 127 128func TestPackNAPTR(t *testing.T) { 129 for _, n := range []string{ 130 `apple.com. IN NAPTR 100 50 "se" "SIP+D2U" "" _sip._udp.apple.com.`, 131 `apple.com. IN NAPTR 90 50 "se" "SIP+D2T" "" _sip._tcp.apple.com.`, 132 `apple.com. IN NAPTR 50 50 "se" "SIPS+D2T" "" _sips._tcp.apple.com.`, 133 } { 134 rr := testRR(n) 135 msg := make([]byte, Len(rr)) 136 if off, err := PackRR(rr, msg, 0, nil, false); err != nil { 137 t.Errorf("packing failed: %v", err) 138 t.Errorf("length %d, need more than %d", Len(rr), off) 139 } 140 } 141} 142 143func TestToRFC3597(t *testing.T) { 144 a := testRR("miek.nl. IN A 10.0.1.1") 145 x := new(RFC3597) 146 x.ToRFC3597(a) 147 if x.String() != `miek.nl. 3600 CLASS1 TYPE1 \# 4 0a000101` { 148 t.Errorf("string mismatch, got: %s", x) 149 } 150 151 b := testRR("miek.nl. IN MX 10 mx.miek.nl.") 152 x.ToRFC3597(b) 153 if x.String() != `miek.nl. 3600 CLASS1 TYPE15 \# 14 000a026d78046d69656b026e6c00` { 154 t.Errorf("string mismatch, got: %s", x) 155 } 156} 157 158func TestNoRdataPack(t *testing.T) { 159 data := make([]byte, 1024) 160 for typ, fn := range TypeToRR { 161 r := fn() 162 *r.Header() = RR_Header{Name: "miek.nl.", Rrtype: typ, Class: ClassINET, Ttl: 16} 163 _, err := PackRR(r, data, 0, nil, false) 164 if err != nil { 165 t.Errorf("failed to pack RR with zero rdata: %s: %v", TypeToString[typ], err) 166 } 167 } 168} 169 170func TestNoRdataUnpack(t *testing.T) { 171 data := make([]byte, 1024) 172 for typ, fn := range TypeToRR { 173 if typ == TypeSOA || typ == TypeTSIG || typ == TypeTKEY { 174 // SOA, TSIG will not be seen (like this) in dyn. updates? 175 // TKEY requires length fields to be present for the Key and OtherData fields 176 continue 177 } 178 r := fn() 179 *r.Header() = RR_Header{Name: "miek.nl.", Rrtype: typ, Class: ClassINET, Ttl: 16} 180 off, err := PackRR(r, data, 0, nil, false) 181 if err != nil { 182 // Should always works, TestNoDataPack should have caught this 183 t.Errorf("failed to pack RR: %v", err) 184 continue 185 } 186 if _, _, err := UnpackRR(data[:off], 0); err != nil { 187 t.Errorf("failed to unpack RR with zero rdata: %s: %v", TypeToString[typ], err) 188 } 189 } 190} 191 192func TestRdataOverflow(t *testing.T) { 193 rr := new(RFC3597) 194 rr.Hdr.Name = "." 195 rr.Hdr.Class = ClassINET 196 rr.Hdr.Rrtype = 65280 197 rr.Rdata = hex.EncodeToString(make([]byte, 0xFFFF)) 198 buf := make([]byte, 0xFFFF*2) 199 if _, err := PackRR(rr, buf, 0, nil, false); err != nil { 200 t.Fatalf("maximum size rrdata pack failed: %v", err) 201 } 202 rr.Rdata += "00" 203 if _, err := PackRR(rr, buf, 0, nil, false); err != ErrRdata { 204 t.Fatalf("oversize rrdata pack didn't return ErrRdata - instead: %v", err) 205 } 206} 207 208func TestCopy(t *testing.T) { 209 rr := testRR("miek.nl. 2311 IN A 127.0.0.1") // Weird TTL to avoid catching TTL 210 rr1 := Copy(rr) 211 if rr.String() != rr1.String() { 212 t.Fatalf("Copy() failed %s != %s", rr.String(), rr1.String()) 213 } 214} 215 216func TestMsgCopy(t *testing.T) { 217 m := new(Msg) 218 m.SetQuestion("miek.nl.", TypeA) 219 rr := testRR("miek.nl. 2311 IN A 127.0.0.1") 220 m.Answer = []RR{rr} 221 rr = testRR("miek.nl. 2311 IN NS 127.0.0.1") 222 m.Ns = []RR{rr} 223 224 m1 := m.Copy() 225 if m.String() != m1.String() { 226 t.Fatalf("Msg.Copy() failed %s != %s", m.String(), m1.String()) 227 } 228 229 m1.Answer[0] = testRR("somethingelse.nl. 2311 IN A 127.0.0.1") 230 if m.String() == m1.String() { 231 t.Fatalf("Msg.Copy() failed; change to copy changed template %s", m.String()) 232 } 233 234 rr = testRR("miek.nl. 2311 IN A 127.0.0.2") 235 m1.Answer = append(m1.Answer, rr) 236 if m1.Ns[0].String() == m1.Answer[1].String() { 237 t.Fatalf("Msg.Copy() failed; append changed underlying array %s", m1.Ns[0].String()) 238 } 239} 240 241func TestMsgPackBuffer(t *testing.T) { 242 var testMessages = []string{ 243 // news.ycombinator.com.in.escapemg.com. IN A, response 244 "586285830001000000010000046e6577730b79636f6d62696e61746f7203636f6d02696e086573636170656d6703636f6d0000010001c0210006000100000e10002c036e7332c02103646e730b67726f6f7665736861726bc02d77ed50e600002a3000000e1000093a8000000e10", 245 246 // news.ycombinator.com.in.escapemg.com. IN A, question 247 "586201000001000000000000046e6577730b79636f6d62696e61746f7203636f6d02696e086573636170656d6703636f6d0000010001", 248 249 "398781020001000000000000046e6577730b79636f6d62696e61746f7203636f6d0000010001", 250 } 251 252 for i, hexData := range testMessages { 253 // we won't fail the decoding of the hex 254 input, _ := hex.DecodeString(hexData) 255 m := new(Msg) 256 if err := m.Unpack(input); err != nil { 257 t.Errorf("packet %d failed to unpack", i) 258 continue 259 } 260 } 261} 262 263// Make sure we can decode a TKEY packet from the string, modify the RR, and then pack it again. 264func TestTKEY(t *testing.T) { 265 // An example TKEY RR captured. There is no known accepted standard text format for a TKEY 266 // record so we do this from a hex string instead of from a text readable string. 267 tkeyStr := "0737362d6d732d370932322d3332633233332463303439663961662d633065612d313165372d363839362d6463333937396666656666640000f900ff0000000000d2086773732d747369670059fd01f359fe53730003000000b8a181b53081b2a0030a0100a10b06092a864882f712010202a2819d04819a60819706092a864886f71201020202006f8187308184a003020105a10302010fa2783076a003020112a26f046db29b1b1d2625da3b20b49dafef930dd1e9aad335e1c5f45dcd95e0005d67a1100f3e573d70506659dbed064553f1ab890f68f65ae10def0dad5b423b39f240ebe666f2886c5fe03819692d29182bbed87b83e1f9d16b7334ec16a3c4fc5ad4a990088e0be43f0c6957916f5fe60000" 268 tkeyBytes, err := hex.DecodeString(tkeyStr) 269 if err != nil { 270 t.Fatal("unable to decode TKEY string ", err) 271 } 272 // Decode the RR 273 rr, tkeyLen, unPackErr := UnpackRR(tkeyBytes, 0) 274 if unPackErr != nil { 275 t.Fatal("unable to decode TKEY RR", unPackErr) 276 } 277 // Make sure it's a TKEY record 278 if rr.Header().Rrtype != TypeTKEY { 279 t.Fatal("Unable to decode TKEY") 280 } 281 // Make sure we get back the same length 282 if Len(rr) != len(tkeyBytes) { 283 t.Fatalf("Lengths don't match %d != %d", Len(rr), len(tkeyBytes)) 284 } 285 // make space for it with some fudge room 286 msg := make([]byte, tkeyLen+1000) 287 offset, packErr := PackRR(rr, msg, 0, nil, false) 288 if packErr != nil { 289 t.Fatal("unable to pack TKEY RR", packErr) 290 } 291 if offset != len(tkeyBytes) { 292 t.Fatalf("mismatched TKEY RR size %d != %d", len(tkeyBytes), offset) 293 } 294 if !bytes.Equal(tkeyBytes, msg[0:offset]) { 295 t.Fatal("mismatched TKEY data after rewriting bytes") 296 } 297 298 // Now add some bytes to this and make sure we can encode OtherData properly 299 tkey := rr.(*TKEY) 300 tkey.OtherData = "abcd" 301 tkey.OtherLen = 2 302 offset, packErr = PackRR(tkey, msg, 0, nil, false) 303 if packErr != nil { 304 t.Fatal("unable to pack TKEY RR after modification", packErr) 305 } 306 if offset != len(tkeyBytes)+2 { 307 t.Fatalf("mismatched TKEY RR size %d != %d", offset, len(tkeyBytes)+2) 308 } 309 310 // Make sure we can parse our string output 311 tkey.Hdr.Class = ClassINET // https://github.com/miekg/dns/issues/577 312 _, newError := NewRR(tkey.String()) 313 if newError != nil { 314 t.Fatalf("unable to parse TKEY string: %s", newError) 315 } 316} 317