* gcc-interface/decl.c (warn_on_field_placement): Issue the warning
[official-gcc.git] / libgo / go / net / dnsclient_unix_test.go
blobc66d2d196b214e6eae578cf076667e3c21b8b3a1
1 // Copyright 2013 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
7 package net
9 import (
10 "context"
11 "fmt"
12 "internal/testenv"
13 "io/ioutil"
14 "os"
15 "path"
16 "reflect"
17 "strings"
18 "sync"
19 "testing"
20 "time"
23 // Test address from 192.0.2.0/24 block, reserved by RFC 5737 for documentation.
24 const TestAddr uint32 = 0xc0000201
26 var dnsTransportFallbackTests = []struct {
27 server string
28 name string
29 qtype uint16
30 timeout int
31 rcode int
33 // Querying "com." with qtype=255 usually makes an answer
34 // which requires more than 512 bytes.
35 {"8.8.8.8:53", "com.", dnsTypeALL, 2, dnsRcodeSuccess},
36 {"8.8.4.4:53", "com.", dnsTypeALL, 4, dnsRcodeSuccess},
39 func TestDNSTransportFallback(t *testing.T) {
40 testenv.MustHaveExternalNetwork(t)
42 for _, tt := range dnsTransportFallbackTests {
43 ctx, cancel := context.WithCancel(context.Background())
44 defer cancel()
45 msg, err := exchange(ctx, tt.server, tt.name, tt.qtype, time.Second)
46 if err != nil {
47 t.Error(err)
48 continue
50 switch msg.rcode {
51 case tt.rcode, dnsRcodeServerFailure:
52 default:
53 t.Errorf("got %v from %v; want %v", msg.rcode, tt.server, tt.rcode)
54 continue
59 // See RFC 6761 for further information about the reserved, pseudo
60 // domain names.
61 var specialDomainNameTests = []struct {
62 name string
63 qtype uint16
64 rcode int
66 // Name resolution APIs and libraries should not recognize the
67 // followings as special.
68 {"1.0.168.192.in-addr.arpa.", dnsTypePTR, dnsRcodeNameError},
69 {"test.", dnsTypeALL, dnsRcodeNameError},
70 {"example.com.", dnsTypeALL, dnsRcodeSuccess},
72 // Name resolution APIs and libraries should recognize the
73 // followings as special and should not send any queries.
74 // Though, we test those names here for verifying negative
75 // answers at DNS query-response interaction level.
76 {"localhost.", dnsTypeALL, dnsRcodeNameError},
77 {"invalid.", dnsTypeALL, dnsRcodeNameError},
80 func TestSpecialDomainName(t *testing.T) {
81 testenv.MustHaveExternalNetwork(t)
83 server := "8.8.8.8:53"
84 for _, tt := range specialDomainNameTests {
85 ctx, cancel := context.WithCancel(context.Background())
86 defer cancel()
87 msg, err := exchange(ctx, server, tt.name, tt.qtype, 3*time.Second)
88 if err != nil {
89 t.Error(err)
90 continue
92 switch msg.rcode {
93 case tt.rcode, dnsRcodeServerFailure:
94 default:
95 t.Errorf("got %v from %v; want %v", msg.rcode, server, tt.rcode)
96 continue
101 // Issue 13705: don't try to resolve onion addresses, etc
102 func TestAvoidDNSName(t *testing.T) {
103 tests := []struct {
104 name string
105 avoid bool
107 {"foo.com", false},
108 {"foo.com.", false},
110 {"foo.onion.", true},
111 {"foo.onion", true},
112 {"foo.ONION", true},
113 {"foo.ONION.", true},
115 // But do resolve *.local address; Issue 16739
116 {"foo.local.", false},
117 {"foo.local", false},
118 {"foo.LOCAL", false},
119 {"foo.LOCAL.", false},
121 {"", true}, // will be rejected earlier too
123 // Without stuff before onion/local, they're fine to
124 // use DNS. With a search path,
125 // "onion.vegegtables.com" can use DNS. Without a
126 // search path (or with a trailing dot), the queries
127 // are just kinda useless, but don't reveal anything
128 // private.
129 {"local", false},
130 {"onion", false},
131 {"local.", false},
132 {"onion.", false},
134 for _, tt := range tests {
135 got := avoidDNS(tt.name)
136 if got != tt.avoid {
137 t.Errorf("avoidDNS(%q) = %v; want %v", tt.name, got, tt.avoid)
142 // Issue 13705: don't try to resolve onion addresses, etc
143 func TestLookupTorOnion(t *testing.T) {
144 addrs, err := goLookupIP(context.Background(), "foo.onion")
145 if len(addrs) > 0 {
146 t.Errorf("unexpected addresses: %v", addrs)
148 if err != nil {
149 t.Fatalf("lookup = %v; want nil", err)
153 type resolvConfTest struct {
154 dir string
155 path string
156 *resolverConfig
159 func newResolvConfTest() (*resolvConfTest, error) {
160 dir, err := ioutil.TempDir("", "go-resolvconftest")
161 if err != nil {
162 return nil, err
164 conf := &resolvConfTest{
165 dir: dir,
166 path: path.Join(dir, "resolv.conf"),
167 resolverConfig: &resolvConf,
169 conf.initOnce.Do(conf.init)
170 return conf, nil
173 func (conf *resolvConfTest) writeAndUpdate(lines []string) error {
174 f, err := os.OpenFile(conf.path, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0600)
175 if err != nil {
176 return err
178 if _, err := f.WriteString(strings.Join(lines, "\n")); err != nil {
179 f.Close()
180 return err
182 f.Close()
183 if err := conf.forceUpdate(conf.path, time.Now().Add(time.Hour)); err != nil {
184 return err
186 return nil
189 func (conf *resolvConfTest) forceUpdate(name string, lastChecked time.Time) error {
190 dnsConf := dnsReadConfig(name)
191 conf.mu.Lock()
192 conf.dnsConfig = dnsConf
193 conf.mu.Unlock()
194 for i := 0; i < 5; i++ {
195 if conf.tryAcquireSema() {
196 conf.lastChecked = lastChecked
197 conf.releaseSema()
198 return nil
201 return fmt.Errorf("tryAcquireSema for %s failed", name)
204 func (conf *resolvConfTest) servers() []string {
205 conf.mu.RLock()
206 servers := conf.dnsConfig.servers
207 conf.mu.RUnlock()
208 return servers
211 func (conf *resolvConfTest) teardown() error {
212 err := conf.forceUpdate("/etc/resolv.conf", time.Time{})
213 os.RemoveAll(conf.dir)
214 return err
217 var updateResolvConfTests = []struct {
218 name string // query name
219 lines []string // resolver configuration lines
220 servers []string // expected name servers
223 name: "golang.org",
224 lines: []string{"nameserver 8.8.8.8"},
225 servers: []string{"8.8.8.8:53"},
228 name: "",
229 lines: nil, // an empty resolv.conf should use defaultNS as name servers
230 servers: defaultNS,
233 name: "www.example.com",
234 lines: []string{"nameserver 8.8.4.4"},
235 servers: []string{"8.8.4.4:53"},
239 func TestUpdateResolvConf(t *testing.T) {
240 testenv.MustHaveExternalNetwork(t)
242 conf, err := newResolvConfTest()
243 if err != nil {
244 t.Fatal(err)
246 defer conf.teardown()
248 for i, tt := range updateResolvConfTests {
249 if err := conf.writeAndUpdate(tt.lines); err != nil {
250 t.Error(err)
251 continue
253 if tt.name != "" {
254 var wg sync.WaitGroup
255 const N = 10
256 wg.Add(N)
257 for j := 0; j < N; j++ {
258 go func(name string) {
259 defer wg.Done()
260 ips, err := goLookupIP(context.Background(), name)
261 if err != nil {
262 t.Error(err)
263 return
265 if len(ips) == 0 {
266 t.Errorf("no records for %s", name)
267 return
269 }(tt.name)
271 wg.Wait()
273 servers := conf.servers()
274 if !reflect.DeepEqual(servers, tt.servers) {
275 t.Errorf("#%d: got %v; want %v", i, servers, tt.servers)
276 continue
281 var goLookupIPWithResolverConfigTests = []struct {
282 name string
283 lines []string // resolver configuration lines
284 error
285 a, aaaa bool // whether response contains A, AAAA-record
287 // no records, transport timeout
289 "jgahvsekduiv9bw4b3qhn4ykdfgj0493iohkrjfhdvhjiu4j",
290 []string{
291 "options timeout:1 attempts:1",
292 "nameserver 255.255.255.255", // please forgive us for abuse of limited broadcast address
294 &DNSError{Name: "jgahvsekduiv9bw4b3qhn4ykdfgj0493iohkrjfhdvhjiu4j", Server: "255.255.255.255:53", IsTimeout: true},
295 false, false,
298 // no records, non-existent domain
300 "jgahvsekduiv9bw4b3qhn4ykdfgj0493iohkrjfhdvhjiu4j",
301 []string{
302 "options timeout:3 attempts:1",
303 "nameserver 8.8.8.8",
305 &DNSError{Name: "jgahvsekduiv9bw4b3qhn4ykdfgj0493iohkrjfhdvhjiu4j", Server: "8.8.8.8:53", IsTimeout: false},
306 false, false,
309 // a few A records, no AAAA records
311 "ipv4.google.com.",
312 []string{
313 "nameserver 8.8.8.8",
314 "nameserver 2001:4860:4860::8888",
316 nil,
317 true, false,
320 "ipv4.google.com",
321 []string{
322 "domain golang.org",
323 "nameserver 2001:4860:4860::8888",
324 "nameserver 8.8.8.8",
326 nil,
327 true, false,
330 "ipv4.google.com",
331 []string{
332 "search x.golang.org y.golang.org",
333 "nameserver 2001:4860:4860::8888",
334 "nameserver 8.8.8.8",
336 nil,
337 true, false,
340 // no A records, a few AAAA records
342 "ipv6.google.com.",
343 []string{
344 "nameserver 2001:4860:4860::8888",
345 "nameserver 8.8.8.8",
347 nil,
348 false, true,
351 "ipv6.google.com",
352 []string{
353 "domain golang.org",
354 "nameserver 8.8.8.8",
355 "nameserver 2001:4860:4860::8888",
357 nil,
358 false, true,
361 "ipv6.google.com",
362 []string{
363 "search x.golang.org y.golang.org",
364 "nameserver 8.8.8.8",
365 "nameserver 2001:4860:4860::8888",
367 nil,
368 false, true,
371 // both A and AAAA records
373 "hostname.as112.net", // see RFC 7534
374 []string{
375 "domain golang.org",
376 "nameserver 2001:4860:4860::8888",
377 "nameserver 8.8.8.8",
379 nil,
380 true, true,
383 "hostname.as112.net", // see RFC 7534
384 []string{
385 "search x.golang.org y.golang.org",
386 "nameserver 2001:4860:4860::8888",
387 "nameserver 8.8.8.8",
389 nil,
390 true, true,
394 func TestGoLookupIPWithResolverConfig(t *testing.T) {
395 testenv.MustHaveExternalNetwork(t)
397 conf, err := newResolvConfTest()
398 if err != nil {
399 t.Fatal(err)
401 defer conf.teardown()
403 for _, tt := range goLookupIPWithResolverConfigTests {
404 if err := conf.writeAndUpdate(tt.lines); err != nil {
405 t.Error(err)
406 continue
408 addrs, err := goLookupIP(context.Background(), tt.name)
409 if err != nil {
410 // This test uses external network connectivity.
411 // We need to take care with errors on both
412 // DNS message exchange layer and DNS
413 // transport layer because goLookupIP may fail
414 // when the IP connectivity on node under test
415 // gets lost during its run.
416 if err, ok := err.(*DNSError); !ok || tt.error != nil && (err.Name != tt.error.(*DNSError).Name || err.Server != tt.error.(*DNSError).Server || err.IsTimeout != tt.error.(*DNSError).IsTimeout) {
417 t.Errorf("got %v; want %v", err, tt.error)
419 continue
421 if len(addrs) == 0 {
422 t.Errorf("no records for %s", tt.name)
424 if !tt.a && !tt.aaaa && len(addrs) > 0 {
425 t.Errorf("unexpected %v for %s", addrs, tt.name)
427 for _, addr := range addrs {
428 if !tt.a && addr.IP.To4() != nil {
429 t.Errorf("got %v; must not be IPv4 address", addr)
431 if !tt.aaaa && addr.IP.To16() != nil && addr.IP.To4() == nil {
432 t.Errorf("got %v; must not be IPv6 address", addr)
438 // Test that goLookupIPOrder falls back to the host file when no DNS servers are available.
439 func TestGoLookupIPOrderFallbackToFile(t *testing.T) {
440 testenv.MustHaveExternalNetwork(t)
442 // Add a config that simulates no dns servers being available.
443 conf, err := newResolvConfTest()
444 if err != nil {
445 t.Fatal(err)
447 if err := conf.writeAndUpdate([]string{}); err != nil {
448 t.Fatal(err)
450 // Redirect host file lookups.
451 defer func(orig string) { testHookHostsPath = orig }(testHookHostsPath)
452 testHookHostsPath = "testdata/hosts"
454 for _, order := range []hostLookupOrder{hostLookupFilesDNS, hostLookupDNSFiles} {
455 name := fmt.Sprintf("order %v", order)
457 // First ensure that we get an error when contacting a non-existent host.
458 _, _, err := goLookupIPCNAMEOrder(context.Background(), "notarealhost", order)
459 if err == nil {
460 t.Errorf("%s: expected error while looking up name not in hosts file", name)
461 continue
464 // Now check that we get an address when the name appears in the hosts file.
465 addrs, _, err := goLookupIPCNAMEOrder(context.Background(), "thor", order) // entry is in "testdata/hosts"
466 if err != nil {
467 t.Errorf("%s: expected to successfully lookup host entry", name)
468 continue
470 if len(addrs) != 1 {
471 t.Errorf("%s: expected exactly one result, but got %v", name, addrs)
472 continue
474 if got, want := addrs[0].String(), "127.1.1.1"; got != want {
475 t.Errorf("%s: address doesn't match expectation. got %v, want %v", name, got, want)
478 defer conf.teardown()
481 // Issue 12712.
482 // When using search domains, return the error encountered
483 // querying the original name instead of an error encountered
484 // querying a generated name.
485 func TestErrorForOriginalNameWhenSearching(t *testing.T) {
486 const fqdn = "doesnotexist.domain"
488 origTestHookDNSDialer := testHookDNSDialer
489 defer func() { testHookDNSDialer = origTestHookDNSDialer }()
491 conf, err := newResolvConfTest()
492 if err != nil {
493 t.Fatal(err)
495 defer conf.teardown()
497 if err := conf.writeAndUpdate([]string{"search servfail"}); err != nil {
498 t.Fatal(err)
501 d := &fakeDNSDialer{}
502 testHookDNSDialer = func() dnsDialer { return d }
504 d.rh = func(s string, q *dnsMsg, _ time.Time) (*dnsMsg, error) {
505 r := &dnsMsg{
506 dnsMsgHdr: dnsMsgHdr{
507 id: q.id,
511 switch q.question[0].Name {
512 case fqdn + ".servfail.":
513 r.rcode = dnsRcodeServerFailure
514 default:
515 r.rcode = dnsRcodeNameError
518 return r, nil
521 _, err = goLookupIP(context.Background(), fqdn)
522 if err == nil {
523 t.Fatal("expected an error")
526 want := &DNSError{Name: fqdn, Err: errNoSuchHost.Error()}
527 if err, ok := err.(*DNSError); !ok || err.Name != want.Name || err.Err != want.Err {
528 t.Errorf("got %v; want %v", err, want)
532 // Issue 15434. If a name server gives a lame referral, continue to the next.
533 func TestIgnoreLameReferrals(t *testing.T) {
534 origTestHookDNSDialer := testHookDNSDialer
535 defer func() { testHookDNSDialer = origTestHookDNSDialer }()
537 conf, err := newResolvConfTest()
538 if err != nil {
539 t.Fatal(err)
541 defer conf.teardown()
543 if err := conf.writeAndUpdate([]string{"nameserver 192.0.2.1", // the one that will give a lame referral
544 "nameserver 192.0.2.2"}); err != nil {
545 t.Fatal(err)
548 d := &fakeDNSDialer{}
549 testHookDNSDialer = func() dnsDialer { return d }
551 d.rh = func(s string, q *dnsMsg, _ time.Time) (*dnsMsg, error) {
552 t.Log(s, q)
553 r := &dnsMsg{
554 dnsMsgHdr: dnsMsgHdr{
555 id: q.id,
556 response: true,
558 question: q.question,
561 if s == "192.0.2.2:53" {
562 r.recursion_available = true
563 if q.question[0].Qtype == dnsTypeA {
564 r.answer = []dnsRR{
565 &dnsRR_A{
566 Hdr: dnsRR_Header{
567 Name: q.question[0].Name,
568 Rrtype: dnsTypeA,
569 Class: dnsClassINET,
570 Rdlength: 4,
572 A: TestAddr,
578 return r, nil
581 addrs, err := goLookupIP(context.Background(), "www.golang.org")
582 if err != nil {
583 t.Fatal(err)
586 if got := len(addrs); got != 1 {
587 t.Fatalf("got %d addresses, want 1", got)
590 if got, want := addrs[0].String(), "192.0.2.1"; got != want {
591 t.Fatalf("got address %v, want %v", got, want)
595 func BenchmarkGoLookupIP(b *testing.B) {
596 testHookUninstaller.Do(uninstallTestHooks)
597 ctx := context.Background()
599 for i := 0; i < b.N; i++ {
600 goLookupIP(ctx, "www.example.com")
604 func BenchmarkGoLookupIPNoSuchHost(b *testing.B) {
605 testHookUninstaller.Do(uninstallTestHooks)
606 ctx := context.Background()
608 for i := 0; i < b.N; i++ {
609 goLookupIP(ctx, "some.nonexistent")
613 func BenchmarkGoLookupIPWithBrokenNameServer(b *testing.B) {
614 testHookUninstaller.Do(uninstallTestHooks)
616 conf, err := newResolvConfTest()
617 if err != nil {
618 b.Fatal(err)
620 defer conf.teardown()
622 lines := []string{
623 "nameserver 203.0.113.254", // use TEST-NET-3 block, see RFC 5737
624 "nameserver 8.8.8.8",
626 if err := conf.writeAndUpdate(lines); err != nil {
627 b.Fatal(err)
629 ctx := context.Background()
631 for i := 0; i < b.N; i++ {
632 goLookupIP(ctx, "www.example.com")
636 type fakeDNSDialer struct {
637 // reply handler
638 rh func(s string, q *dnsMsg, t time.Time) (*dnsMsg, error)
641 func (f *fakeDNSDialer) dialDNS(_ context.Context, n, s string) (dnsConn, error) {
642 return &fakeDNSConn{f.rh, s, time.Time{}}, nil
645 type fakeDNSConn struct {
646 rh func(s string, q *dnsMsg, t time.Time) (*dnsMsg, error)
647 s string
648 t time.Time
651 func (f *fakeDNSConn) Close() error {
652 return nil
655 func (f *fakeDNSConn) SetDeadline(t time.Time) error {
656 f.t = t
657 return nil
660 func (f *fakeDNSConn) dnsRoundTrip(q *dnsMsg) (*dnsMsg, error) {
661 return f.rh(f.s, q, f.t)
664 // UDP round-tripper algorithm should ignore invalid DNS responses (issue 13281).
665 func TestIgnoreDNSForgeries(t *testing.T) {
666 c, s := Pipe()
667 go func() {
668 b := make([]byte, 512)
669 n, err := s.Read(b)
670 if err != nil {
671 t.Error(err)
672 return
675 msg := &dnsMsg{}
676 if !msg.Unpack(b[:n]) {
677 t.Error("invalid DNS query")
678 return
681 s.Write([]byte("garbage DNS response packet"))
683 msg.response = true
684 msg.id++ // make invalid ID
685 b, ok := msg.Pack()
686 if !ok {
687 t.Error("failed to pack DNS response")
688 return
690 s.Write(b)
692 msg.id-- // restore original ID
693 msg.answer = []dnsRR{
694 &dnsRR_A{
695 Hdr: dnsRR_Header{
696 Name: "www.example.com.",
697 Rrtype: dnsTypeA,
698 Class: dnsClassINET,
699 Rdlength: 4,
701 A: TestAddr,
705 b, ok = msg.Pack()
706 if !ok {
707 t.Error("failed to pack DNS response")
708 return
710 s.Write(b)
713 msg := &dnsMsg{
714 dnsMsgHdr: dnsMsgHdr{
715 id: 42,
717 question: []dnsQuestion{
719 Name: "www.example.com.",
720 Qtype: dnsTypeA,
721 Qclass: dnsClassINET,
726 resp, err := dnsRoundTripUDP(c, msg)
727 if err != nil {
728 t.Fatalf("dnsRoundTripUDP failed: %v", err)
731 if got := resp.answer[0].(*dnsRR_A).A; got != TestAddr {
732 t.Errorf("got address %v, want %v", got, TestAddr)
736 // Issue 16865. If a name server times out, continue to the next.
737 func TestRetryTimeout(t *testing.T) {
738 origTestHookDNSDialer := testHookDNSDialer
739 defer func() { testHookDNSDialer = origTestHookDNSDialer }()
741 conf, err := newResolvConfTest()
742 if err != nil {
743 t.Fatal(err)
745 defer conf.teardown()
747 testConf := []string{
748 "nameserver 192.0.2.1", // the one that will timeout
749 "nameserver 192.0.2.2",
751 if err := conf.writeAndUpdate(testConf); err != nil {
752 t.Fatal(err)
755 d := &fakeDNSDialer{}
756 testHookDNSDialer = func() dnsDialer { return d }
758 var deadline0 time.Time
760 d.rh = func(s string, q *dnsMsg, deadline time.Time) (*dnsMsg, error) {
761 t.Log(s, q, deadline)
763 if deadline.IsZero() {
764 t.Error("zero deadline")
767 if s == "192.0.2.1:53" {
768 deadline0 = deadline
769 time.Sleep(10 * time.Millisecond)
770 return nil, errTimeout
773 if deadline == deadline0 {
774 t.Error("deadline didn't change")
777 return mockTXTResponse(q), nil
780 _, err = LookupTXT("www.golang.org")
781 if err != nil {
782 t.Fatal(err)
785 if deadline0.IsZero() {
786 t.Error("deadline0 still zero", deadline0)
790 func TestRotate(t *testing.T) {
791 // without rotation, always uses the first server
792 testRotate(t, false, []string{"192.0.2.1", "192.0.2.2"}, []string{"192.0.2.1:53", "192.0.2.1:53", "192.0.2.1:53"})
794 // with rotation, rotates through back to first
795 testRotate(t, true, []string{"192.0.2.1", "192.0.2.2"}, []string{"192.0.2.1:53", "192.0.2.2:53", "192.0.2.1:53"})
798 func testRotate(t *testing.T, rotate bool, nameservers, wantServers []string) {
799 origTestHookDNSDialer := testHookDNSDialer
800 defer func() { testHookDNSDialer = origTestHookDNSDialer }()
802 conf, err := newResolvConfTest()
803 if err != nil {
804 t.Fatal(err)
806 defer conf.teardown()
808 var confLines []string
809 for _, ns := range nameservers {
810 confLines = append(confLines, "nameserver "+ns)
812 if rotate {
813 confLines = append(confLines, "options rotate")
816 if err := conf.writeAndUpdate(confLines); err != nil {
817 t.Fatal(err)
820 d := &fakeDNSDialer{}
821 testHookDNSDialer = func() dnsDialer { return d }
823 var usedServers []string
824 d.rh = func(s string, q *dnsMsg, _ time.Time) (*dnsMsg, error) {
825 usedServers = append(usedServers, s)
826 return mockTXTResponse(q), nil
829 // len(nameservers) + 1 to allow rotation to get back to start
830 for i := 0; i < len(nameservers)+1; i++ {
831 if _, err := LookupTXT("www.golang.org"); err != nil {
832 t.Fatal(err)
836 if !reflect.DeepEqual(usedServers, wantServers) {
837 t.Errorf("rotate=%t got used servers:\n%v\nwant:\n%v", rotate, usedServers, wantServers)
841 func mockTXTResponse(q *dnsMsg) *dnsMsg {
842 r := &dnsMsg{
843 dnsMsgHdr: dnsMsgHdr{
844 id: q.id,
845 response: true,
846 recursion_available: true,
848 question: q.question,
849 answer: []dnsRR{
850 &dnsRR_TXT{
851 Hdr: dnsRR_Header{
852 Name: q.question[0].Name,
853 Rrtype: dnsTypeTXT,
854 Class: dnsClassINET,
856 Txt: "ok",
861 return r