1// Copyright 2017 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.
4
5package dnsmessage_test
6
7import (
8	"fmt"
9	"net"
10	"strings"
11
12	"golang.org/x/net/dns/dnsmessage"
13)
14
15func mustNewName(name string) dnsmessage.Name {
16	n, err := dnsmessage.NewName(name)
17	if err != nil {
18		panic(err)
19	}
20	return n
21}
22
23func ExampleParser() {
24	msg := dnsmessage.Message{
25		Header: dnsmessage.Header{Response: true, Authoritative: true},
26		Questions: []dnsmessage.Question{
27			{
28				Name:  mustNewName("foo.bar.example.com."),
29				Type:  dnsmessage.TypeA,
30				Class: dnsmessage.ClassINET,
31			},
32			{
33				Name:  mustNewName("bar.example.com."),
34				Type:  dnsmessage.TypeA,
35				Class: dnsmessage.ClassINET,
36			},
37		},
38		Answers: []dnsmessage.Resource{
39			{
40				Header: dnsmessage.ResourceHeader{
41					Name:  mustNewName("foo.bar.example.com."),
42					Type:  dnsmessage.TypeA,
43					Class: dnsmessage.ClassINET,
44				},
45				Body: &dnsmessage.AResource{A: [4]byte{127, 0, 0, 1}},
46			},
47			{
48				Header: dnsmessage.ResourceHeader{
49					Name:  mustNewName("bar.example.com."),
50					Type:  dnsmessage.TypeA,
51					Class: dnsmessage.ClassINET,
52				},
53				Body: &dnsmessage.AResource{A: [4]byte{127, 0, 0, 2}},
54			},
55		},
56	}
57
58	buf, err := msg.Pack()
59	if err != nil {
60		panic(err)
61	}
62
63	wantName := "bar.example.com."
64
65	var p dnsmessage.Parser
66	if _, err := p.Start(buf); err != nil {
67		panic(err)
68	}
69
70	for {
71		q, err := p.Question()
72		if err == dnsmessage.ErrSectionDone {
73			break
74		}
75		if err != nil {
76			panic(err)
77		}
78
79		if q.Name.String() != wantName {
80			continue
81		}
82
83		fmt.Println("Found question for name", wantName)
84		if err := p.SkipAllQuestions(); err != nil {
85			panic(err)
86		}
87		break
88	}
89
90	var gotIPs []net.IP
91	for {
92		h, err := p.AnswerHeader()
93		if err == dnsmessage.ErrSectionDone {
94			break
95		}
96		if err != nil {
97			panic(err)
98		}
99
100		if (h.Type != dnsmessage.TypeA && h.Type != dnsmessage.TypeAAAA) || h.Class != dnsmessage.ClassINET {
101			continue
102		}
103
104		if !strings.EqualFold(h.Name.String(), wantName) {
105			if err := p.SkipAnswer(); err != nil {
106				panic(err)
107			}
108			continue
109		}
110
111		switch h.Type {
112		case dnsmessage.TypeA:
113			r, err := p.AResource()
114			if err != nil {
115				panic(err)
116			}
117			gotIPs = append(gotIPs, r.A[:])
118		case dnsmessage.TypeAAAA:
119			r, err := p.AAAAResource()
120			if err != nil {
121				panic(err)
122			}
123			gotIPs = append(gotIPs, r.AAAA[:])
124		}
125	}
126
127	fmt.Printf("Found A/AAAA records for name %s: %v\n", wantName, gotIPs)
128
129	// Output:
130	// Found question for name bar.example.com.
131	// Found A/AAAA records for name bar.example.com.: [127.0.0.2]
132}
133