1package dns_test
2
3import (
4	"errors"
5	"fmt"
6	"log"
7	"net"
8
9	"github.com/miekg/dns"
10)
11
12// Retrieve the MX records for miek.nl.
13func ExampleMX() {
14	config, _ := dns.ClientConfigFromFile("/etc/resolv.conf")
15	c := new(dns.Client)
16	m := new(dns.Msg)
17	m.SetQuestion("miek.nl.", dns.TypeMX)
18	m.RecursionDesired = true
19	r, _, err := c.Exchange(m, config.Servers[0]+":"+config.Port)
20	if err != nil {
21		return
22	}
23	if r.Rcode != dns.RcodeSuccess {
24		return
25	}
26	for _, a := range r.Answer {
27		if mx, ok := a.(*dns.MX); ok {
28			fmt.Printf("%s\n", mx.String())
29		}
30	}
31}
32
33// Retrieve the DNSKEY records of a zone and convert them
34// to DS records for SHA1, SHA256 and SHA384.
35func ExampleDS() {
36	config, _ := dns.ClientConfigFromFile("/etc/resolv.conf")
37	c := new(dns.Client)
38	m := new(dns.Msg)
39	zone := "miek.nl"
40	m.SetQuestion(dns.Fqdn(zone), dns.TypeDNSKEY)
41	m.SetEdns0(4096, true)
42	r, _, err := c.Exchange(m, config.Servers[0]+":"+config.Port)
43	if err != nil {
44		return
45	}
46	if r.Rcode != dns.RcodeSuccess {
47		return
48	}
49	for _, k := range r.Answer {
50		if key, ok := k.(*dns.DNSKEY); ok {
51			for _, alg := range []uint8{dns.SHA1, dns.SHA256, dns.SHA384} {
52				fmt.Printf("%s; %d\n", key.ToDS(alg).String(), key.Flags)
53			}
54		}
55	}
56}
57
58const TypeAPAIR = 0x0F99
59
60type APAIR struct {
61	addr [2]net.IP
62}
63
64func NewAPAIR() dns.PrivateRdata { return new(APAIR) }
65
66func (rd *APAIR) String() string { return rd.addr[0].String() + " " + rd.addr[1].String() }
67func (rd *APAIR) Parse(txt []string) error {
68	if len(txt) != 2 {
69		return errors.New("two addresses required for APAIR")
70	}
71	for i, s := range txt {
72		ip := net.ParseIP(s)
73		if ip == nil {
74			return errors.New("invalid IP in APAIR text representation")
75		}
76		rd.addr[i] = ip
77	}
78	return nil
79}
80
81func (rd *APAIR) Pack(buf []byte) (int, error) {
82	b := append([]byte(rd.addr[0]), []byte(rd.addr[1])...)
83	n := copy(buf, b)
84	if n != len(b) {
85		return n, dns.ErrBuf
86	}
87	return n, nil
88}
89
90func (rd *APAIR) Unpack(buf []byte) (int, error) {
91	ln := net.IPv4len * 2
92	if len(buf) != ln {
93		return 0, errors.New("invalid length of APAIR rdata")
94	}
95	cp := make([]byte, ln)
96	copy(cp, buf) // clone bytes to use them in IPs
97
98	rd.addr[0] = net.IP(cp[:3])
99	rd.addr[1] = net.IP(cp[4:])
100
101	return len(buf), nil
102}
103
104func (rd *APAIR) Copy(dest dns.PrivateRdata) error {
105	cp := make([]byte, rd.Len())
106	_, err := rd.Pack(cp)
107	if err != nil {
108		return err
109	}
110
111	d := dest.(*APAIR)
112	d.addr[0] = net.IP(cp[:3])
113	d.addr[1] = net.IP(cp[4:])
114	return nil
115}
116
117func (rd *APAIR) Len() int {
118	return net.IPv4len * 2
119}
120
121func ExamplePrivateHandle() {
122	dns.PrivateHandle("APAIR", TypeAPAIR, NewAPAIR)
123	defer dns.PrivateHandleRemove(TypeAPAIR)
124
125	rr, err := dns.NewRR("miek.nl. APAIR (1.2.3.4    1.2.3.5)")
126	if err != nil {
127		log.Fatal("could not parse APAIR record: ", err)
128	}
129	fmt.Println(rr)
130	// Output: miek.nl.	3600	IN	APAIR	1.2.3.4 1.2.3.5
131
132	m := new(dns.Msg)
133	m.Id = 12345
134	m.SetQuestion("miek.nl.", TypeAPAIR)
135	m.Answer = append(m.Answer, rr)
136
137	fmt.Println(m)
138	// ;; opcode: QUERY, status: NOERROR, id: 12345
139	// ;; flags: rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
140	//
141	// ;; QUESTION SECTION:
142	// ;miek.nl.	IN	 APAIR
143	//
144	// ;; ANSWER SECTION:
145	// miek.nl.	3600	IN	APAIR	1.2.3.4 1.2.3.5
146}
147