dns

package
v1.1.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 29, 2016 License: BSD-3-Clause, Apache-2.0 Imports: 35 Imported by: 0

README

Build Status

Alternative (more granular) approach to a DNS library

Less is more.

Complete and usable DNS library. All widely used Resource Records are supported, including the DNSSEC types. It follows a lean and mean philosophy. If there is stuff you should know as a DNS programmer there isn't a convenience function for it. Server side and client side programming is supported, i.e. you can build servers and resolvers with it.

If you like this, you may also be interested in:

Goals

  • KISS;
  • Fast;
  • Small API, if its easy to code in Go, don't make a function for it.

Users

A not-so-up-to-date-list-that-may-be-actually-current:

Send pull request if you want to be listed here.

Features

  • UDP/TCP queries, IPv4 and IPv6;
  • RFC 1035 zone file parsing ($INCLUDE, $ORIGIN, $TTL and $GENERATE (for all record types) are supported;
  • Fast:
    • Reply speed around ~ 80K qps (faster hardware results in more qps);
    • Parsing RRs ~ 100K RR/s, that's 5M records in about 50 seconds;
  • Server side programming (mimicking the net/http package);
  • Client side programming;
  • DNSSEC: signing, validating and key generation for DSA, RSA and ECDSA;
  • EDNS0, NSID;
  • AXFR/IXFR;
  • TSIG, SIG(0);
  • DNS name compression;
  • Depends only on the standard library.

Have fun!

Miek Gieben - 2010-2012 - miek@miek.nl

Building

Building is done with the go tool. If you have setup your GOPATH correctly, the following should work:

go get github.com/miekg/dns
go build github.com/miekg/dns

Examples

A short "how to use the API" is at the beginning of doc.go (this also will show when you call godoc github.com/miekg/dns).

Example programs can be found in the github.com/miekg/exdns repository.

Supported RFCs

all of them

  • 103{4,5} - DNS standard
  • 1348 - NSAP record (removed the record)
  • 1982 - Serial Arithmetic
  • 1876 - LOC record
  • 1995 - IXFR
  • 1996 - DNS notify
  • 2136 - DNS Update (dynamic updates)
  • 2181 - RRset definition - there is no RRset type though, just []RR
  • 2537 - RSAMD5 DNS keys
  • 2065 - DNSSEC (updated in later RFCs)
  • 2671 - EDNS record
  • 2782 - SRV record
  • 2845 - TSIG record
  • 2915 - NAPTR record
  • 2929 - DNS IANA Considerations
  • 3110 - RSASHA1 DNS keys
  • 3225 - DO bit (DNSSEC OK)
  • 340{1,2,3} - NAPTR record
  • 3445 - Limiting the scope of (DNS)KEY
  • 3597 - Unknown RRs
  • 4025 - IPSECKEY
  • 403{3,4,5} - DNSSEC + validation functions
  • 4255 - SSHFP record
  • 4343 - Case insensitivity
  • 4408 - SPF record
  • 4509 - SHA256 Hash in DS
  • 4592 - Wildcards in the DNS
  • 4635 - HMAC SHA TSIG
  • 4701 - DHCID
  • 4892 - id.server
  • 5001 - NSID
  • 5155 - NSEC3 record
  • 5205 - HIP record
  • 5702 - SHA2 in the DNS
  • 5936 - AXFR
  • 5966 - TCP implementation recommendations
  • 6605 - ECDSA
  • 6725 - IANA Registry Update
  • 6742 - ILNP DNS
  • 6844 - CAA record
  • 6891 - EDNS0 update
  • 6895 - DNS IANA considerations
  • 6975 - Algorithm Understanding in DNSSEC
  • 7043 - EUI48/EUI64 records
  • 7314 - DNS (EDNS) EXPIRE Option
  • 7553 - URI record
  • xxxx - EDNS0 DNS Update Lease (draft)

Loosely based upon

  • ldns
  • NSD
  • Net::DNS
  • GRONG

TODO

  • privatekey.Precompute() when signing?
  • Last remaining RRs: APL, ATMA, A6, NSAP and NXT.
  • Missing in parsing: ISDN, UNSPEC, NSAP and ATMA.
  • NSEC(3) cover/match/closest enclose.
  • Replies with TC bit are not parsed to the end.

Documentation

Overview

Package dns implements a full featured interface to the Domain Name System. Server- and client-side programming is supported. The package allows complete control over what is send out to the DNS. The package API follows the less-is-more principle, by presenting a small, clean interface.

The package dns supports (asynchronous) querying/replying, incoming/outgoing zone transfers, TSIG, EDNS0, dynamic updates, notifies and DNSSEC validation/signing. Note that domain names MUST be fully qualified, before sending them, unqualified names in a message will result in a packing failure.

Resource records are native types. They are not stored in wire format. Basic usage pattern for creating a new resource record:

     r := new(dns.MX)
     r.Hdr = dns.RR_Header{Name: "miek.nl.", Rrtype: dns.TypeMX,
	Class: dns.ClassINET, Ttl: 3600}
     r.Preference = 10
     r.Mx = "mx.miek.nl."

Or directly from a string:

mx, err := dns.NewRR("miek.nl. 3600 IN MX 10 mx.miek.nl.")

Or when the default TTL (3600) and class (IN) suit you:

mx, err := dns.NewRR("miek.nl. MX 10 mx.miek.nl.")

Or even:

mx, err := dns.NewRR("$ORIGIN nl.\nmiek 1H IN MX 10 mx.miek")

In the DNS messages are exchanged, these messages contain resource records (sets). Use pattern for creating a message:

m := new(dns.Msg)
m.SetQuestion("miek.nl.", dns.TypeMX)

Or when not certain if the domain name is fully qualified:

m.SetQuestion(dns.Fqdn("miek.nl"), dns.TypeMX)

The message m is now a message with the question section set to ask the MX records for the miek.nl. zone.

The following is slightly more verbose, but more flexible:

m1 := new(dns.Msg)
m1.Id = dns.Id()
m1.RecursionDesired = true
m1.Question = make([]dns.Question, 1)
m1.Question[0] = dns.Question{"miek.nl.", dns.TypeMX, dns.ClassINET}

After creating a message it can be send. Basic use pattern for synchronous querying the DNS at a server configured on 127.0.0.1 and port 53:

c := new(dns.Client)
in, rtt, err := c.Exchange(m1, "127.0.0.1:53")

Suppressing multiple outstanding queries (with the same question, type and class) is as easy as setting:

c.SingleInflight = true

If these "advanced" features are not needed, a simple UDP query can be send, with:

in, err := dns.Exchange(m1, "127.0.0.1:53")

When this functions returns you will get dns message. A dns message consists out of four sections. The question section: in.Question, the answer section: in.Answer, the authority section: in.Ns and the additional section: in.Extra.

Each of these sections (except the Question section) contain a []RR. Basic use pattern for accessing the rdata of a TXT RR as the first RR in the Answer section:

if t, ok := in.Answer[0].(*dns.TXT); ok {
	// do something with t.Txt
}

Domain Name and TXT Character String Representations

Both domain names and TXT character strings are converted to presentation form both when unpacked and when converted to strings.

For TXT character strings, tabs, carriage returns and line feeds will be converted to \t, \r and \n respectively. Back slashes and quotations marks will be escaped. Bytes below 32 and above 127 will be converted to \DDD form.

For domain names, in addition to the above rules brackets, periods, spaces, semicolons and the at symbol are escaped.

DNSSEC

DNSSEC (DNS Security Extension) adds a layer of security to the DNS. It uses public key cryptography to sign resource records. The public keys are stored in DNSKEY records and the signatures in RRSIG records.

Requesting DNSSEC information for a zone is done by adding the DO (DNSSEC OK) bit to an request.

m := new(dns.Msg)
m.SetEdns0(4096, true)

Signature generation, signature verification and key generation are all supported.

DYNAMIC UPDATES

Dynamic updates reuses the DNS message format, but renames three of the sections. Question is Zone, Answer is Prerequisite, Authority is Update, only the Additional is not renamed. See RFC 2136 for the gory details.

You can set a rather complex set of rules for the existence of absence of certain resource records or names in a zone to specify if resource records should be added or removed. The table from RFC 2136 supplemented with the Go DNS function shows which functions exist to specify the prerequisites.

3.2.4 - Table Of Metavalues Used In Prerequisite Section

 CLASS    TYPE     RDATA    Meaning                    Function
 --------------------------------------------------------------
 ANY      ANY      empty    Name is in use             dns.NameUsed
 ANY      rrset    empty    RRset exists (value indep) dns.RRsetUsed
 NONE     ANY      empty    Name is not in use         dns.NameNotUsed
 NONE     rrset    empty    RRset does not exist       dns.RRsetNotUsed
 zone     rrset    rr       RRset exists (value dep)   dns.Used

The prerequisite section can also be left empty. If you have decided on the prerequisites you can tell what RRs should be added or deleted. The next table shows the options you have and what functions to call.

3.4.2.6 - Table Of Metavalues Used In Update Section

 CLASS    TYPE     RDATA    Meaning                     Function
 ---------------------------------------------------------------
 ANY      ANY      empty    Delete all RRsets from name dns.RemoveName
 ANY      rrset    empty    Delete an RRset             dns.RemoveRRset
 NONE     rrset    rr       Delete an RR from RRset     dns.Remove
 zone     rrset    rr       Add to an RRset             dns.Insert

TRANSACTION SIGNATURE

An TSIG or transaction signature adds a HMAC TSIG record to each message sent. The supported algorithms include: HmacMD5, HmacSHA1, HmacSHA256 and HmacSHA512.

Basic use pattern when querying with a TSIG name "axfr." (note that these key names must be fully qualified - as they are domain names) and the base64 secret "so6ZGir4GPAqINNh9U5c3A==":

c := new(dns.Client)
c.TsigSecret = map[string]string{"axfr.": "so6ZGir4GPAqINNh9U5c3A=="}
m := new(dns.Msg)
m.SetQuestion("miek.nl.", dns.TypeMX)
m.SetTsig("axfr.", dns.HmacMD5, 300, time.Now().Unix())
...
// When sending the TSIG RR is calculated and filled in before sending

When requesting an zone transfer (almost all TSIG usage is when requesting zone transfers), with TSIG, this is the basic use pattern. In this example we request an AXFR for miek.nl. with TSIG key named "axfr." and secret "so6ZGir4GPAqINNh9U5c3A==" and using the server 176.58.119.54:

t := new(dns.Transfer)
m := new(dns.Msg)
t.TsigSecret = map[string]string{"axfr.": "so6ZGir4GPAqINNh9U5c3A=="}
m.SetAxfr("miek.nl.")
m.SetTsig("axfr.", dns.HmacMD5, 300, time.Now().Unix())
c, err := t.In(m, "176.58.119.54:53")
for r := range c { ... }

You can now read the records from the transfer as they come in. Each envelope is checked with TSIG. If something is not correct an error is returned.

Basic use pattern validating and replying to a message that has TSIG set.

server := &dns.Server{Addr: ":53", Net: "udp"}
server.TsigSecret = map[string]string{"axfr.": "so6ZGir4GPAqINNh9U5c3A=="}
go server.ListenAndServe()
dns.HandleFunc(".", handleRequest)

func handleRequest(w dns.ResponseWriter, r *dns.Msg) {
	m := new(Msg)
	m.SetReply(r)
	if r.IsTsig() {
		if w.TsigStatus() == nil {
			// *Msg r has an TSIG record and it was validated
			m.SetTsig("axfr.", dns.HmacMD5, 300, time.Now().Unix())
		} else {
			// *Msg r has an TSIG records and it was not valided
		}
	}
	w.WriteMsg(m)
}

PRIVATE RRS

RFC 6895 sets aside a range of type codes for private use. This range is 65,280 - 65,534 (0xFF00 - 0xFFFE). When experimenting with new Resource Records these can be used, before requesting an official type code from IANA.

see http://miek.nl/posts/2014/Sep/21/Private%20RRs%20and%20IDN%20in%20Go%20DNS/ for more information.

EDNS0

EDNS0 is an extension mechanism for the DNS defined in RFC 2671 and updated by RFC 6891. It defines an new RR type, the OPT RR, which is then completely abused. Basic use pattern for creating an (empty) OPT RR:

o := new(dns.OPT)
o.Hdr.Name = "." // MUST be the root zone, per definition.
o.Hdr.Rrtype = dns.TypeOPT

The rdata of an OPT RR consists out of a slice of EDNS0 (RFC 6891) interfaces. Currently only a few have been standardized: EDNS0_NSID (RFC 5001) and EDNS0_SUBNET (draft-vandergaast-edns-client-subnet-02). Note that these options may be combined in an OPT RR. Basic use pattern for a server to check if (and which) options are set:

// o is a dns.OPT
for _, s := range o.Option {
	switch e := s.(type) {
	case *dns.EDNS0_NSID:
		// do stuff with e.Nsid
	case *dns.EDNS0_SUBNET:
		// access e.Family, e.Address, etc.
	}
}

SIG(0)

From RFC 2931:

SIG(0) provides protection for DNS transactions and requests ....
... protection for glue records, DNS requests, protection for message headers
on requests and responses, and protection of the overall integrity of a response.

It works like TSIG, except that SIG(0) uses public key cryptography, instead of the shared secret approach in TSIG. Supported algorithms: DSA, ECDSAP256SHA256, ECDSAP384SHA384, RSASHA1, RSASHA256 and RSASHA512.

Signing subsequent messages in multi-message sessions is not implemented.

Index

Examples

Constants

View Source
const (

	// DefaultMsgSize is the standard default for messages larger than 512 bytes.
	DefaultMsgSize = 4096
	// MinMsgSize is the minimal size of a DNS packet.
	MinMsgSize = 512
	// MaxMsgSize is the largest possible DNS packet.
	MaxMsgSize = 65535
)
View Source
const (
	RSAMD5 uint8
	DH
	DSA

	RSASHA1
	DSANSEC3SHA1
	RSASHA1NSEC3SHA1
	RSASHA256

	RSASHA512

	ECCGOST
	ECDSAP256SHA256
	ECDSAP384SHA384
	INDIRECT   uint8 = 252
	PRIVATEDNS uint8 = 253 // Private (experimental keys)
	PRIVATEOID uint8 = 254
)

DNSSEC encryption algorithm codes.

View Source
const (
	SHA1   uint8 // RFC 4034
	SHA256       // RFC 4509
	GOST94       // RFC 5933
	SHA384       // Experimental
	SHA512       // Experimental
)

DNSSEC hashing algorithm codes.

View Source
const (
	SEP    = 1
	REVOKE = 1 << 7
	ZONE   = 1 << 8
)

DNSKEY flag values.

View Source
const (
	EDNS0LLQ         = 0x1    // long lived queries: http://tools.ietf.org/html/draft-sekar-dns-llq-01
	EDNS0UL          = 0x2    // update lease draft: http://files.dns-sd.org/draft-sekar-dns-ul.txt
	EDNS0NSID        = 0x3    // nsid (RFC5001)
	EDNS0DAU         = 0x5    // DNSSEC Algorithm Understood
	EDNS0DHU         = 0x6    // DS Hash Understood
	EDNS0N3U         = 0x7    // NSEC3 Hash Understood
	EDNS0SUBNET      = 0x8    // client-subnet (RFC6891)
	EDNS0EXPIRE      = 0x9    // EDNS0 expire
	EDNS0SUBNETDRAFT = 0x50fa // Don't use! Use EDNS0SUBNET
	EDNS0LOCALSTART  = 0xFDE9 // Beginning of range reserved for local/experimental use (RFC6891)
	EDNS0LOCALEND    = 0xFFFE // End of range reserved for local/experimental use (RFC6891)

)

EDNS0 Option codes.

View Source
const (
	HmacMD5    = "hmac-md5.sig-alg.reg.int."
	HmacSHA1   = "hmac-sha1."
	HmacSHA256 = "hmac-sha256."
	HmacSHA512 = "hmac-sha512."
)

HMAC hashing codes. These are transmitted as domain names.

View Source
const (
	TypeNone       uint16 = 0
	TypeA          uint16 = 1
	TypeNS         uint16 = 2
	TypeMD         uint16 = 3
	TypeMF         uint16 = 4
	TypeCNAME      uint16 = 5
	TypeSOA        uint16 = 6
	TypeMB         uint16 = 7
	TypeMG         uint16 = 8
	TypeMR         uint16 = 9
	TypeNULL       uint16 = 10
	TypeWKS        uint16 = 11
	TypePTR        uint16 = 12
	TypeHINFO      uint16 = 13
	TypeMINFO      uint16 = 14
	TypeMX         uint16 = 15
	TypeTXT        uint16 = 16
	TypeRP         uint16 = 17
	TypeAFSDB      uint16 = 18
	TypeX25        uint16 = 19
	TypeISDN       uint16 = 20
	TypeRT         uint16 = 21
	TypeNSAPPTR    uint16 = 23
	TypeSIG        uint16 = 24
	TypeKEY        uint16 = 25
	TypePX         uint16 = 26
	TypeGPOS       uint16 = 27
	TypeAAAA       uint16 = 28
	TypeLOC        uint16 = 29
	TypeNXT        uint16 = 30
	TypeEID        uint16 = 31
	TypeNIMLOC     uint16 = 32
	TypeSRV        uint16 = 33
	TypeATMA       uint16 = 34
	TypeNAPTR      uint16 = 35
	TypeKX         uint16 = 36
	TypeCERT       uint16 = 37
	TypeDNAME      uint16 = 39
	TypeOPT        uint16 = 41 // EDNS
	TypeDS         uint16 = 43
	TypeSSHFP      uint16 = 44
	TypeIPSECKEY   uint16 = 45
	TypeRRSIG      uint16 = 46
	TypeNSEC       uint16 = 47
	TypeDNSKEY     uint16 = 48
	TypeDHCID      uint16 = 49
	TypeNSEC3      uint16 = 50
	TypeNSEC3PARAM uint16 = 51
	TypeTLSA       uint16 = 52
	TypeHIP        uint16 = 55
	TypeNINFO      uint16 = 56
	TypeRKEY       uint16 = 57
	TypeTALINK     uint16 = 58
	TypeCDS        uint16 = 59
	TypeCDNSKEY    uint16 = 60
	TypeOPENPGPKEY uint16 = 61
	TypeSPF        uint16 = 99
	TypeUINFO      uint16 = 100
	TypeUID        uint16 = 101
	TypeGID        uint16 = 102
	TypeUNSPEC     uint16 = 103
	TypeNID        uint16 = 104
	TypeL32        uint16 = 105
	TypeL64        uint16 = 106
	TypeLP         uint16 = 107
	TypeEUI48      uint16 = 108
	TypeEUI64      uint16 = 109
	TypeURI        uint16 = 256
	TypeCAA        uint16 = 257

	TypeTKEY uint16 = 249
	TypeTSIG uint16 = 250

	// valid Question.Qtype only
	TypeIXFR  uint16 = 251
	TypeAXFR  uint16 = 252
	TypeMAILB uint16 = 253
	TypeMAILA uint16 = 254
	TypeANY   uint16 = 255

	TypeTA       uint16 = 32768
	TypeDLV      uint16 = 32769
	TypeReserved uint16 = 65535

	// valid Question.Qclass
	ClassINET   = 1
	ClassCSNET  = 2
	ClassCHAOS  = 3
	ClassHESIOD = 4
	ClassNONE   = 254
	ClassANY    = 255

	// Message Response Codes.
	RcodeSuccess        = 0
	RcodeFormatError    = 1
	RcodeServerFailure  = 2
	RcodeNameError      = 3
	RcodeNotImplemented = 4
	RcodeRefused        = 5
	RcodeYXDomain       = 6
	RcodeYXRrset        = 7
	RcodeNXRrset        = 8
	RcodeNotAuth        = 9
	RcodeNotZone        = 10
	RcodeBadSig         = 16 // TSIG
	RcodeBadVers        = 16 // EDNS0
	RcodeBadKey         = 17
	RcodeBadTime        = 18
	RcodeBadMode        = 19 // TKEY
	RcodeBadName        = 20
	RcodeBadAlg         = 21
	RcodeBadTrunc       = 22 // TSIG

	// Message Opcodes. There is no 3.
	OpcodeQuery  = 0
	OpcodeIQuery = 1
	OpcodeStatus = 2
	OpcodeNotify = 4
	OpcodeUpdate = 5
)

Wire constants and supported types.

View Source
const (
	LOC_EQUATOR       = 1 << 31 // RFC 1876, Section 2.
	LOC_PRIMEMERIDIAN = 1 << 31 // RFC 1876, Section 2.

	LOC_HOURS   = 60 * 1000
	LOC_DEGREES = 60 * LOC_HOURS

	LOC_ALTITUDEBASE = 100000
)
View Source
const (
	CertPKIX = 1 + iota
	CertSPKI
	CertPGP
	CertIPIX
	CertISPKI
	CertIPGP
	CertACPKIX
	CertIACPKIX
	CertURI = 253
	CertOID = 254
)

Different Certificate Types, see RFC 4398, Section 2.1

Variables

View Source
var (
	// ErrAlg indicates an error with the (DNSSEC) algorithm.
	ErrAlg error = &Error{err: "bad algorithm"}
	// ErrAuth indicates an error in the TSIG authentication.
	ErrAuth error = &Error{err: "bad authentication"}
	// ErrBuf indicates that the buffer used it too small for the message.
	ErrBuf error = &Error{err: "buffer size too small"}
	// ErrConnEmpty indicates a connection is being uses before it is initialized.
	ErrConnEmpty error = &Error{err: "conn has no connection"}
	// ErrExtendedRcode ...
	ErrExtendedRcode error = &Error{err: "bad extended rcode"}
	// ErrFqdn indicates that a domain name does not have a closing dot.
	ErrFqdn error = &Error{err: "domain must be fully qualified"}
	// ErrId indicates there is a mismatch with the message's ID.
	ErrId error = &Error{err: "id mismatch"}
	// ErrKeyAlg indicates that the algorithm in the key is not valid.
	ErrKeyAlg    error = &Error{err: "bad key algorithm"}
	ErrKey       error = &Error{err: "bad key"}
	ErrKeySize   error = &Error{err: "bad key size"}
	ErrNoSig     error = &Error{err: "no signature found"}
	ErrPrivKey   error = &Error{err: "bad private key"}
	ErrRcode     error = &Error{err: "bad rcode"}
	ErrRdata     error = &Error{err: "bad rdata"}
	ErrRRset     error = &Error{err: "bad rrset"}
	ErrSecret    error = &Error{err: "no secrets defined"}
	ErrShortRead error = &Error{err: "short read"}
	// ErrSig indicates that a signature can not be cryptographically validated.
	ErrSig error = &Error{err: "bad signature"}
	// ErrSOA indicates that no SOA RR was seen when doing zone transfers.
	ErrSoa error = &Error{err: "no SOA"}
	// ErrTime indicates a timing error in TSIG authentication.
	ErrTime error = &Error{err: "bad time"}
)

Map of algorithm crypto hashes.

View Source
var AlgorithmToString = map[uint8]string{
	RSAMD5:           "RSAMD5",
	DH:               "DH",
	DSA:              "DSA",
	RSASHA1:          "RSASHA1",
	DSANSEC3SHA1:     "DSA-NSEC3-SHA1",
	RSASHA1NSEC3SHA1: "RSASHA1-NSEC3-SHA1",
	RSASHA256:        "RSASHA256",
	RSASHA512:        "RSASHA512",
	ECCGOST:          "ECC-GOST",
	ECDSAP256SHA256:  "ECDSAP256SHA256",
	ECDSAP384SHA384:  "ECDSAP384SHA384",
	INDIRECT:         "INDIRECT",
	PRIVATEDNS:       "PRIVATEDNS",
	PRIVATEOID:       "PRIVATEOID",
}

Map for algorithm names.

View Source
var CertTypeToString = map[uint16]string{
	CertPKIX:    "PKIX",
	CertSPKI:    "SPKI",
	CertPGP:     "PGP",
	CertIPIX:    "IPIX",
	CertISPKI:   "ISPKI",
	CertIPGP:    "IPGP",
	CertACPKIX:  "ACPKIX",
	CertIACPKIX: "IACPKIX",
	CertURI:     "URI",
	CertOID:     "OID",
}

CertTypeToString converts the Cert Type to its string representation. See RFC 4398 and RFC 6944.

View Source
var ClassToString = map[uint16]string{
	ClassINET:   "IN",
	ClassCSNET:  "CS",
	ClassCHAOS:  "CH",
	ClassHESIOD: "HS",
	ClassNONE:   "NONE",
	ClassANY:    "ANY",
}

ClassToString is a maps Classes to strings for each CLASS wire type.

View Source
var DefaultServeMux = NewServeMux()

DefaultServeMux is the default ServeMux used by Serve.

View Source
var HashToString = map[uint8]string{
	SHA1:   "SHA1",
	SHA256: "SHA256",
	GOST94: "GOST94",
	SHA384: "SHA384",
	SHA512: "SHA512",
}

Map for hash names.

View Source
var Id func() uint16 = id

Id, by default, returns a 16 bits random number to be used as a message id. The random provided should be good enough. This being a variable the function can be reassigned to a custom function. For instance, to make it return a static value:

dns.Id = func() uint16 { return 3 }
View Source
var OpcodeToString = map[int]string{
	OpcodeQuery:  "QUERY",
	OpcodeIQuery: "IQUERY",
	OpcodeStatus: "STATUS",
	OpcodeNotify: "NOTIFY",
	OpcodeUpdate: "UPDATE",
}

OpcodeToString maps Opcodes to strings.

View Source
var RcodeToString = map[int]string{
	RcodeSuccess:        "NOERROR",
	RcodeFormatError:    "FORMERR",
	RcodeServerFailure:  "SERVFAIL",
	RcodeNameError:      "NXDOMAIN",
	RcodeNotImplemented: "NOTIMPL",
	RcodeRefused:        "REFUSED",
	RcodeYXDomain:       "YXDOMAIN",
	RcodeYXRrset:        "YXRRSET",
	RcodeNXRrset:        "NXRRSET",
	RcodeNotAuth:        "NOTAUTH",
	RcodeNotZone:        "NOTZONE",
	RcodeBadSig:         "BADSIG",

	RcodeBadKey:   "BADKEY",
	RcodeBadTime:  "BADTIME",
	RcodeBadMode:  "BADMODE",
	RcodeBadName:  "BADNAME",
	RcodeBadAlg:   "BADALG",
	RcodeBadTrunc: "BADTRUNC",
}

RcodeToString maps Rcodes to strings.

View Source
var StringToAlgorithm = reverseInt8(AlgorithmToString)

Map of algorithm strings.

View Source
var StringToCertType = reverseInt16(CertTypeToString)

StringToCertType is the reverseof CertTypeToString.

View Source
var StringToClass = reverseInt16(ClassToString)

StringToClass is the reverse of ClassToString, needed for string parsing.

View Source
var StringToHash = reverseInt8(HashToString)

Map of hash strings.

View Source
var StringToOpcode = reverseInt(OpcodeToString)

Map of opcodes strings.

View Source
var StringToRcode = reverseInt(RcodeToString)

Map of rcodes strings.

View Source
var StringToType = reverseInt16(TypeToString)

StringToType is the reverse of TypeToString, needed for string parsing.

View Source
var TypeToString = map[uint16]string{
	TypeA:          "A",
	TypeAAAA:       "AAAA",
	TypeAFSDB:      "AFSDB",
	TypeANY:        "ANY",
	TypeATMA:       "ATMA",
	TypeAXFR:       "AXFR",
	TypeCAA:        "CAA",
	TypeCDNSKEY:    "CDNSKEY",
	TypeCDS:        "CDS",
	TypeCERT:       "CERT",
	TypeCNAME:      "CNAME",
	TypeDHCID:      "DHCID",
	TypeDLV:        "DLV",
	TypeDNAME:      "DNAME",
	TypeDNSKEY:     "DNSKEY",
	TypeDS:         "DS",
	TypeEID:        "EID",
	TypeEUI48:      "EUI48",
	TypeEUI64:      "EUI64",
	TypeGID:        "GID",
	TypeGPOS:       "GPOS",
	TypeHINFO:      "HINFO",
	TypeHIP:        "HIP",
	TypeIPSECKEY:   "IPSECKEY",
	TypeISDN:       "ISDN",
	TypeIXFR:       "IXFR",
	TypeKEY:        "KEY",
	TypeKX:         "KX",
	TypeL32:        "L32",
	TypeL64:        "L64",
	TypeLOC:        "LOC",
	TypeLP:         "LP",
	TypeMB:         "MB",
	TypeMD:         "MD",
	TypeMF:         "MF",
	TypeMG:         "MG",
	TypeMINFO:      "MINFO",
	TypeMR:         "MR",
	TypeMX:         "MX",
	TypeNAPTR:      "NAPTR",
	TypeNID:        "NID",
	TypeNINFO:      "NINFO",
	TypeNIMLOC:     "NIMLOC",
	TypeNS:         "NS",
	TypeNSAPPTR:    "NSAP-PTR",
	TypeNSEC3:      "NSEC3",
	TypeNSEC3PARAM: "NSEC3PARAM",
	TypeNSEC:       "NSEC",
	TypeNULL:       "NULL",
	TypeOPT:        "OPT",
	TypeOPENPGPKEY: "OPENPGPKEY",
	TypePTR:        "PTR",
	TypeRKEY:       "RKEY",
	TypeRP:         "RP",
	TypeRRSIG:      "RRSIG",
	TypeRT:         "RT",
	TypeSIG:        "SIG",
	TypeSOA:        "SOA",
	TypeSPF:        "SPF",
	TypeSRV:        "SRV",
	TypeSSHFP:      "SSHFP",
	TypeTA:         "TA",
	TypeTALINK:     "TALINK",
	TypeTKEY:       "TKEY",
	TypeTLSA:       "TLSA",
	TypeTSIG:       "TSIG",
	TypeTXT:        "TXT",
	TypePX:         "PX",
	TypeUID:        "UID",
	TypeUINFO:      "UINFO",
	TypeUNSPEC:     "UNSPEC",
	TypeURI:        "URI",
	TypeWKS:        "WKS",
	TypeX25:        "X25",
}

TypeToString is a map of strings for each RR wire type.

Functions

func ActivateAndServe

func ActivateAndServe(l net.Listener, p net.PacketConn, handler Handler) error

ActivateAndServe activates a server with a listener from systemd, l and p should not both be non-nil. If both l and p are not nil only p will be used. Invoke handler for incoming queries.

func CertificateToDANE

func CertificateToDANE(selector, matchingType uint8, cert *x509.Certificate) (string, error)

CertificateToDANE converts a certificate to a hex string as used in the TLSA record.

func CompareDomainName

func CompareDomainName(s1, s2 string) (n int)

CompareDomainName compares the names s1 and s2 and returns how many labels they have in common starting from the *right*. The comparison stops at the first inequality. The names are not downcased before the comparison.

www.miek.nl. and miek.nl. have two labels in common: miek and nl www.miek.nl. and www.bla.nl. have one label in common: nl

func CountLabel

func CountLabel(s string) (labels int)

CountLabel counts the the number of labels in the string s.

func Field

func Field(r RR, i int) string

Field returns the rdata field i as a string. Fields are indexed starting from 1. RR types that holds slice data, for instance the NSEC type bitmap will return a single string where the types are concatenated using a space. Accessing non existing fields will cause a panic.

func Fqdn

func Fqdn(s string) string

Fqdn return the fully qualified domain name from s. If s is already fully qualified, it behaves as the identity function.

func Handle

func Handle(pattern string, handler Handler)

Handle registers the handler with the given pattern in the DefaultServeMux. The documentation for ServeMux explains how patterns are matched.

func HandleFailed

func HandleFailed(w ResponseWriter, r *Msg)

HandleFailed returns a HandlerFunc that returns SERVFAIL for every request it gets.

func HandleFunc

func HandleFunc(pattern string, handler func(ResponseWriter, *Msg))

HandleFunc registers the handler function with the given pattern in the DefaultServeMux.

func HandleRemove

func HandleRemove(pattern string)

HandleRemove deregisters the handle with the given pattern in the DefaultServeMux.

func HashName

func HashName(label string, ha uint8, iter uint16, salt string) string

HashName hashes a string (label) according to RFC 5155. It returns the hashed string in uppercase.

func IsDomainName

func IsDomainName(s string) (labels int, ok bool)

IsDomainName checks if s is a valid domainname, it returns the number of labels and true, when a domain name is valid. Note that non fully qualified domain name is considered valid, in this case the last label is counted in the number of labels. When false is returned the number of labels is not defined.

func IsFqdn

func IsFqdn(s string) bool

IsFqdn checks if a domain name is fully qualified.

func IsMsg

func IsMsg(buf []byte) error

IsMsg sanity checks buf and returns an error if it isn't a valid DNS packet. The checking is performed on the binary payload.

func IsRRset added in v1.0.7

func IsRRset(rrset []RR) bool

IsRRset checks if a set of RRs is a valid RRset as defined by RFC 2181. This means the RRs need to have the same type, name, and class. Returns true if the RR set is valid, otherwise false.

func IsSubDomain

func IsSubDomain(parent, child string) bool

IsSubDomain checks if child is indeed a child of the parent. Both child and parent are *not* downcased before doing the comparison.

func ListenAndServe

func ListenAndServe(addr string, network string, handler Handler) error

ListenAndServe Starts a server on addresss and network speficied. Invoke handler for incoming queries.

func NextLabel

func NextLabel(s string, offset int) (i int, end bool)

NextLabel returns the index of the start of the next label in the string s starting at offset. The bool end is true when the end of the string has been reached. Also see PrevLabel.

func NumField

func NumField(r RR) int

NumField returns the number of rdata fields r has.

func PackDomainName

func PackDomainName(s string, msg []byte, off int, compression map[string]int, compress bool) (off1 int, err error)

PackDomainName packs a domain name s into msg[off:]. If compression is wanted compress must be true and the compression map needs to hold a mapping between domain names and offsets pointing into msg.

func PackRR

func PackRR(rr RR, msg []byte, off int, compression map[string]int, compress bool) (off1 int, err error)

PackRR packs a resource record rr into msg[off:]. See PackDomainName for documentation about the compression.

func PackStruct

func PackStruct(any interface{}, msg []byte, off int) (off1 int, err error)

PackStruct packs any structure to wire format.

func ParseZone

func ParseZone(r io.Reader, origin, file string) chan *Token

ParseZone reads a RFC 1035 style zonefile from r. It returns *Tokens on the returned channel, which consist out the parsed RR, a potential comment or an error. If there is an error the RR is nil. The string file is only used in error reporting. The string origin is used as the initial origin, as if the file would start with: $ORIGIN origin . The directives $INCLUDE, $ORIGIN, $TTL and $GENERATE are supported. The channel t is closed by ParseZone when the end of r is reached.

Basic usage pattern when reading from a string (z) containing the zone data:

for x := range dns.ParseZone(strings.NewReader(z), "", "") {
	if x.Error != nil {
		// Do something with x.RR
	}
}

Comments specified after an RR (and on the same line!) are returned too:

foo. IN A 10.0.0.1 ; this is a comment

The text "; this is comment" is returned in Token.Comment. Comments inside the RR are discarded. Comments on a line by themselves are discarded too.

func PrevLabel

func PrevLabel(s string, n int) (i int, start bool)

PrevLabel returns the index of the label when starting from the right and jumping n labels to the left. The bool start is true when the start of the string has been overshot. Also see NextLabel.

func PrivateHandle

func PrivateHandle(rtypestr string, rtype uint16, generator func() PrivateRdata)

PrivateHandle registers a private resource record type. It requires string and numeric representation of private RR type and generator function as argument.

Example
package main

import (
	"errors"
	"fmt"
	"github.com/miekg/dns"
	"log"
	"net"
)

const TypeAPAIR = 0x0F99

type APAIR struct {
	addr [2]net.IP
}

func NewAPAIR() dns.PrivateRdata { return new(APAIR) }

func (rd *APAIR) String() string { return rd.addr[0].String() + " " + rd.addr[1].String() }
func (rd *APAIR) Parse(txt []string) error {
	if len(txt) != 2 {
		return errors.New("two addresses required for APAIR")
	}
	for i, s := range txt {
		ip := net.ParseIP(s)
		if ip == nil {
			return errors.New("invalid IP in APAIR text representation")
		}
		rd.addr[i] = ip
	}
	return nil
}

func (rd *APAIR) Pack(buf []byte) (int, error) {
	b := append([]byte(rd.addr[0]), []byte(rd.addr[1])...)
	n := copy(buf, b)
	if n != len(b) {
		return n, dns.ErrBuf
	}
	return n, nil
}

func (rd *APAIR) Unpack(buf []byte) (int, error) {
	ln := net.IPv4len * 2
	if len(buf) != ln {
		return 0, errors.New("invalid length of APAIR rdata")
	}
	cp := make([]byte, ln)
	copy(cp, buf)

	rd.addr[0] = net.IP(cp[:3])
	rd.addr[1] = net.IP(cp[4:])

	return len(buf), nil
}

func (rd *APAIR) Copy(dest dns.PrivateRdata) error {
	cp := make([]byte, rd.Len())
	_, err := rd.Pack(cp)
	if err != nil {
		return err
	}

	d := dest.(*APAIR)
	d.addr[0] = net.IP(cp[:3])
	d.addr[1] = net.IP(cp[4:])
	return nil
}

func (rd *APAIR) Len() int {
	return net.IPv4len * 2
}

func main() {
	dns.PrivateHandle("APAIR", TypeAPAIR, NewAPAIR)
	defer dns.PrivateHandleRemove(TypeAPAIR)

	rr, err := dns.NewRR("miek.nl. APAIR (1.2.3.4    1.2.3.5)")
	if err != nil {
		log.Fatal("could not parse APAIR record: ", err)
	}
	fmt.Println(rr)
	
Output:

func PrivateHandleRemove

func PrivateHandleRemove(rtype uint16)

PrivateHandleRemove removes defenitions required to support private RR type.

func ReverseAddr

func ReverseAddr(addr string) (arpa string, err error)

ReverseAddr returns the in-addr.arpa. or ip6.arpa. hostname of the IP address suitable for reverse DNS (PTR) record lookups or an error if it fails to parse the IP address.

func Split

func Split(s string) []int

Split splits a name s into its label indexes. www.miek.nl. returns []int{0, 4, 9}, www.miek.nl also returns []int{0, 4, 9}. The root name (.) returns nil. Also see SplitDomainName.

func SplitDomainName

func SplitDomainName(s string) (labels []string)

SplitDomainName splits a name string into it's labels. www.miek.nl. returns []string{"www", "miek", "nl"} The root label (.) returns nil. Note that using strings.Split(s) will work in most cases, but does not handle escaped dots (\.) for instance.

func StringToTime

func StringToTime(s string) (uint32, error)

StringToTime translates the RRSIG's incep. and expir. times from string values like "20110403154150" to an 32 bit integer. It takes serial arithmetic (RFC 1982) into account.

func TLSAName

func TLSAName(name, service, network string) (string, error)

TLSAName returns the ownername of a TLSA resource record as per the rules specified in RFC 6698, Section 3.

func TimeToString

func TimeToString(t uint32) string

TimeToString translates the RRSIG's incep. and expir. times to the string representation used when printing the record. It takes serial arithmetic (RFC 1982) into account.

func TsigGenerate

func TsigGenerate(m *Msg, secret, requestMAC string, timersOnly bool) ([]byte, string, error)

TsigGenerate fills out the TSIG record attached to the message. The message should contain a "stub" TSIG RR with the algorithm, key name (owner name of the RR), time fudge (defaults to 300 seconds) and the current time The TSIG MAC is saved in that Tsig RR. When TsigGenerate is called for the first time requestMAC is set to the empty string and timersOnly is false. If something goes wrong an error is returned, otherwise it is nil.

func TsigVerify

func TsigVerify(msg []byte, secret, requestMAC string, timersOnly bool) error

TsigVerify verifies the TSIG on a message. If the signature does not validate err contains the error, otherwise it is nil.

func UnpackDomainName

func UnpackDomainName(msg []byte, off int) (string, int, error)

UnpackDomainName unpacks a domain name into a string.

func UnpackStruct

func UnpackStruct(any interface{}, msg []byte, off int) (int, error)

UnpackStruct unpacks a binary message from offset off to the interface value given.

func WriteToSessionUDP

func WriteToSessionUDP(conn *net.UDPConn, b []byte, session *SessionUDP) (int, error)

WriteToSessionUDP acts just like net.UDPConn.WritetTo(), but uses a *SessionUDP instead of a net.Addr.

Types

type A

type A struct {
	Hdr RR_Header
	A   net.IP `dns:"a"`
}

func (*A) Header

func (rr *A) Header() *RR_Header

func (*A) String

func (rr *A) String() string

type AAAA

type AAAA struct {
	Hdr  RR_Header
	AAAA net.IP `dns:"aaaa"`
}

func (*AAAA) Header

func (rr *AAAA) Header() *RR_Header

func (*AAAA) String

func (rr *AAAA) String() string

type AFSDB

type AFSDB struct {
	Hdr      RR_Header
	Subtype  uint16
	Hostname string `dns:"cdomain-name"`
}

func (*AFSDB) Header

func (rr *AFSDB) Header() *RR_Header

func (*AFSDB) String

func (rr *AFSDB) String() string

type ANY

type ANY struct {
	Hdr RR_Header
}

ANY is a wildcard record. See RFC 1035, Section 3.2.3. ANY is named "*" there.

func (*ANY) Header

func (rr *ANY) Header() *RR_Header

func (*ANY) String

func (rr *ANY) String() string

type CAA added in v1.0.7

type CAA struct {
	Hdr   RR_Header
	Flag  uint8
	Tag   string
	Value string `dns:"octet"`
}

func (*CAA) Header added in v1.0.7

func (rr *CAA) Header() *RR_Header

func (*CAA) String added in v1.0.7

func (rr *CAA) String() string

type CDNSKEY

type CDNSKEY struct {
	DNSKEY
}

type CDS

type CDS struct {
	DS
}

type CERT

type CERT struct {
	Hdr         RR_Header
	Type        uint16
	KeyTag      uint16
	Algorithm   uint8
	Certificate string `dns:"base64"`
}

The CERT resource record, see RFC 4398.

func (*CERT) Header

func (rr *CERT) Header() *RR_Header

func (*CERT) String

func (rr *CERT) String() string

type CNAME

type CNAME struct {
	Hdr    RR_Header
	Target string `dns:"cdomain-name"`
}

func (*CNAME) Header

func (rr *CNAME) Header() *RR_Header

func (*CNAME) String

func (rr *CNAME) String() string

type Class

type Class uint16

Class is a DNS class.

func (Class) String

func (c Class) String() string

String returns the string representation for the class c.

type Client

type Client struct {
	Net            string            // if "tcp" a TCP query will be initiated, otherwise an UDP one (default is "" for UDP)
	UDPSize        uint16            // minimum receive buffer for UDP messages
	DialTimeout    time.Duration     // net.DialTimeout, defaults to 2 seconds
	ReadTimeout    time.Duration     // net.Conn.SetReadTimeout value for connections, defaults to 2 seconds
	WriteTimeout   time.Duration     // net.Conn.SetWriteTimeout value for connections, defaults to 2 seconds
	TsigSecret     map[string]string // secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be fully qualified
	SingleInflight bool              // if true suppress multiple outstanding queries for the same Qname, Qtype and Qclass
	// contains filtered or unexported fields
}

A Client defines parameters for a DNS client.

func (*Client) Exchange

func (c *Client) Exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err error)

Exchange performs an synchronous query. It sends the message m to the address contained in a and waits for an reply. Basic use pattern with a *dns.Client:

c := new(dns.Client)
in, rtt, err := c.Exchange(message, "127.0.0.1:53")

Exchange does not retry a failed query, nor will it fall back to TCP in case of truncation.

type ClientConfig

type ClientConfig struct {
	Servers  []string // servers to use
	Search   []string // suffixes to append to local name
	Port     string   // what port to use
	Ndots    int      // number of dots in name to trigger absolute lookup
	Timeout  int      // seconds before giving up on packet
	Attempts int      // lost packets before giving up on server, not used in the package dns
}

ClientConfig wraps the contents of the /etc/resolv.conf file.

func ClientConfigFromFile

func ClientConfigFromFile(resolvconf string) (*ClientConfig, error)

ClientConfigFromFile parses a resolv.conf(5) like file and returns a *ClientConfig.

type Conn

type Conn struct {
	net.Conn                     // a net.Conn holding the connection
	UDPSize    uint16            // minimum receive buffer for UDP messages
	TsigSecret map[string]string // secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be fully qualified
	// contains filtered or unexported fields
}

A Conn represents a connection to a DNS server.

func Dial

func Dial(network, address string) (conn *Conn, err error)

Dial connects to the address on the named network.

func DialTimeout

func DialTimeout(network, address string, timeout time.Duration) (conn *Conn, err error)

DialTimeout acts like Dial but takes a timeout.

func (*Conn) Read

func (co *Conn) Read(p []byte) (n int, err error)

Read implements the net.Conn read method.

func (*Conn) ReadMsg

func (co *Conn) ReadMsg() (*Msg, error)

ReadMsg reads a message from the connection co. If the received message contains a TSIG record the transaction signature is verified.

func (*Conn) ReadMsgHeader added in v1.0.7

func (co *Conn) ReadMsgHeader(hdr *Header) ([]byte, error)

ReadMsgHeader reads a DNS message, parses and populates hdr (when hdr is not nil). Returns message as a byte slice to be parsed with Msg.Unpack later on. Note that error handling on the message body is not possible as only the header is parsed.

func (*Conn) Write

func (co *Conn) Write(p []byte) (n int, err error)

Write implements the net.Conn Write method.

func (*Conn) WriteMsg

func (co *Conn) WriteMsg(m *Msg) (err error)

WriteMsg sends a message throught the connection co. If the message m contains a TSIG record the transaction signature is calculated.

type DHCID

type DHCID struct {
	Hdr    RR_Header
	Digest string `dns:"base64"`
}

func (*DHCID) Header

func (rr *DHCID) Header() *RR_Header

func (*DHCID) String

func (rr *DHCID) String() string

type DLV

type DLV struct {
	DS
}

type DNAME

type DNAME struct {
	Hdr    RR_Header
	Target string `dns:"domain-name"`
}

The DNAME resource record, see RFC 2672.

func (*DNAME) Header

func (rr *DNAME) Header() *RR_Header

func (*DNAME) String

func (rr *DNAME) String() string

type DNSKEY

type DNSKEY struct {
	Hdr       RR_Header
	Flags     uint16
	Protocol  uint8
	Algorithm uint8
	PublicKey string `dns:"base64"`
}

func (*DNSKEY) Generate

func (k *DNSKEY) Generate(bits int) (crypto.PrivateKey, error)

Generate generates a DNSKEY of the given bit size. The public part is put inside the DNSKEY record. The Algorithm in the key must be set as this will define what kind of DNSKEY will be generated. The ECDSA algorithms imply a fixed keysize, in that case bits should be set to the size of the algorithm.

func (*DNSKEY) Header

func (rr *DNSKEY) Header() *RR_Header

func (*DNSKEY) KeyTag

func (k *DNSKEY) KeyTag() uint16

KeyTag calculates the keytag (or key-id) of the DNSKEY.

func (*DNSKEY) NewPrivateKey

func (k *DNSKEY) NewPrivateKey(s string) (crypto.PrivateKey, error)

NewPrivateKey returns a PrivateKey by parsing the string s. s should be in the same form of the BIND private key files.

func (*DNSKEY) PrivateKeyString

func (r *DNSKEY) PrivateKeyString(p crypto.PrivateKey) string

PrivateKeyString converts a PrivateKey to a string. This string has the same format as the private-key-file of BIND9 (Private-key-format: v1.3). It needs some info from the key (the algorithm), so its a method of the DNSKEY It supports rsa.PrivateKey, ecdsa.PrivateKey and dsa.PrivateKey

func (*DNSKEY) ReadPrivateKey

func (k *DNSKEY) ReadPrivateKey(q io.Reader, file string) (crypto.PrivateKey, error)

ReadPrivateKey reads a private key from the io.Reader q. The string file is only used in error reporting. The public key must be known, because some cryptographic algorithms embed the public inside the privatekey.

func (*DNSKEY) String

func (rr *DNSKEY) String() string

func (*DNSKEY) ToCDNSKEY

func (k *DNSKEY) ToCDNSKEY() *CDNSKEY

ToCDNSKEY converts a DNSKEY record to a CDNSKEY record.

func (*DNSKEY) ToDS

func (k *DNSKEY) ToDS(h uint8) *DS

ToDS converts a DNSKEY record to a DS record.

type DS

type DS struct {
	Hdr        RR_Header
	KeyTag     uint16
	Algorithm  uint8
	DigestType uint8
	Digest     string `dns:"hex"`
}

func (*DS) Header

func (rr *DS) Header() *RR_Header

func (*DS) String

func (rr *DS) String() string

func (*DS) ToCDS

func (d *DS) ToCDS() *CDS

ToCDS converts a DS record to a CDS record.

type DecorateReader added in v1.0.7

type DecorateReader func(Reader) Reader

DecorateReader is a decorator hook for extending or supplanting the functionality of a Reader. Implementations should never return a nil Reader.

type DecorateWriter added in v1.0.7

type DecorateWriter func(Writer) Writer

DecorateWriter is a decorator hook for extending or supplanting the functionality of a Writer. Implementations should never return a nil Writer.

Example
// instrument raw DNS message writing
wf := DecorateWriter(func(w Writer) Writer {
	return &ExampleFrameLengthWriter{w}
})

// simple UDP server
pc, err := net.ListenPacket("udp", "127.0.0.1:0")
if err != nil {
	fmt.Println(err.Error())
	return
}
server := &Server{
	PacketConn:     pc,
	DecorateWriter: wf,
}

waitLock := sync.Mutex{}
waitLock.Lock()
server.NotifyStartedFunc = waitLock.Unlock
defer server.Shutdown()

go func() {
	server.ActivateAndServe()
	pc.Close()
}()

waitLock.Lock()

HandleFunc("miek.nl.", HelloServer)

c := new(Client)
m := new(Msg)
m.SetQuestion("miek.nl.", TypeTXT)
_, _, err = c.Exchange(m, pc.LocalAddr().String())
if err != nil {
	fmt.Println("failed to exchange", err.Error())
	return
}
Output:

writing raw DNS message of length 56

type Denialer

type Denialer interface {
	// Cover will check if the (unhashed) name is being covered by this NSEC or NSEC3.
	Cover(name string) bool
	// Match will check if the ownername matches the (unhashed) name for this NSEC3 or NSEC3.
	Match(name string) bool
}

Denialer is an interface that should be implemented by types that are used to denial answers in DNSSEC.

type EDNS0

type EDNS0 interface {
	// Option returns the option code for the option.
	Option() uint16

	// String returns the string representation of the option.
	String() string
	// contains filtered or unexported methods
}

EDNS0 defines an EDNS0 Option. An OPT RR can have multiple options appended to it.

type EDNS0_DAU

type EDNS0_DAU struct {
	Code    uint16 // Always EDNS0DAU
	AlgCode []uint8
}

func (*EDNS0_DAU) Option

func (e *EDNS0_DAU) Option() uint16

func (*EDNS0_DAU) String

func (e *EDNS0_DAU) String() string

type EDNS0_DHU

type EDNS0_DHU struct {
	Code    uint16 // Always EDNS0DHU
	AlgCode []uint8
}

func (*EDNS0_DHU) Option

func (e *EDNS0_DHU) Option() uint16

func (*EDNS0_DHU) String

func (e *EDNS0_DHU) String() string

type EDNS0_EXPIRE

type EDNS0_EXPIRE struct {
	Code   uint16 // Always EDNS0EXPIRE
	Expire uint32
}

func (*EDNS0_EXPIRE) Option

func (e *EDNS0_EXPIRE) Option() uint16

func (*EDNS0_EXPIRE) String

func (e *EDNS0_EXPIRE) String() string

type EDNS0_LLQ

type EDNS0_LLQ struct {
	Code      uint16 // Always EDNS0LLQ
	Version   uint16
	Opcode    uint16
	Error     uint16
	Id        uint64
	LeaseLife uint32
}

EDNS0_LLQ stands for Long Lived Queries: http://tools.ietf.org/html/draft-sekar-dns-llq-01 Implemented for completeness, as the EDNS0 type code is assigned.

func (*EDNS0_LLQ) Option

func (e *EDNS0_LLQ) Option() uint16

func (*EDNS0_LLQ) String

func (e *EDNS0_LLQ) String() string

type EDNS0_LOCAL

type EDNS0_LOCAL struct {
	Code uint16
	Data []byte
}

The EDNS0_LOCAL option is used for local/experimental purposes. The option code is recommended to be within the range [EDNS0LOCALSTART, EDNS0LOCALEND] (RFC6891), although any unassigned code can actually be used. The content of the option is made available in Data, unaltered. Basic use pattern for creating a local option:

o := new(dns.OPT)
o.Hdr.Name = "."
o.Hdr.Rrtype = dns.TypeOPT
e := new(dns.EDNS0_LOCAL)
e.Code = dns.EDNS0LOCALSTART
e.Data = []byte{72, 82, 74}
o.Option = append(o.Option, e)

func (*EDNS0_LOCAL) Option

func (e *EDNS0_LOCAL) Option() uint16

func (*EDNS0_LOCAL) String

func (e *EDNS0_LOCAL) String() string

type EDNS0_N3U

type EDNS0_N3U struct {
	Code    uint16 // Always EDNS0N3U
	AlgCode []uint8
}

func (*EDNS0_N3U) Option

func (e *EDNS0_N3U) Option() uint16

func (*EDNS0_N3U) String

func (e *EDNS0_N3U) String() string

type EDNS0_NSID

type EDNS0_NSID struct {
	Code uint16 // Always EDNS0NSID
	Nsid string // This string needs to be hex encoded
}

The nsid EDNS0 option is used to retrieve a nameserver identifier. When sending a request Nsid must be set to the empty string The identifier is an opaque string encoded as hex. Basic use pattern for creating an nsid option:

o := new(dns.OPT)
o.Hdr.Name = "."
o.Hdr.Rrtype = dns.TypeOPT
e := new(dns.EDNS0_NSID)
e.Code = dns.EDNS0NSID
e.Nsid = "AA"
o.Option = append(o.Option, e)

func (*EDNS0_NSID) Option

func (e *EDNS0_NSID) Option() uint16

func (*EDNS0_NSID) String

func (e *EDNS0_NSID) String() string

type EDNS0_SUBNET

type EDNS0_SUBNET struct {
	Code          uint16 // Always EDNS0SUBNET
	Family        uint16 // 1 for IP, 2 for IP6
	SourceNetmask uint8
	SourceScope   uint8
	Address       net.IP
	DraftOption   bool // Set to true if using the old (0x50fa) option code
}

EDNS0_SUBNET is the subnet option that is used to give the remote nameserver an idea of where the client lives. It can then give back a different answer depending on the location or network topology. Basic use pattern for creating an subnet option:

o := new(dns.OPT)
o.Hdr.Name = "."
o.Hdr.Rrtype = dns.TypeOPT
e := new(dns.EDNS0_SUBNET)
e.Code = dns.EDNS0SUBNET
e.Family = 1	// 1 for IPv4 source address, 2 for IPv6
e.NetMask = 32	// 32 for IPV4, 128 for IPv6
e.SourceScope = 0
e.Address = net.ParseIP("127.0.0.1").To4()	// for IPv4
// e.Address = net.ParseIP("2001:7b8:32a::2")	// for IPV6
o.Option = append(o.Option, e)

Note: the spec (draft-ietf-dnsop-edns-client-subnet-00) has some insane logic for which netmask applies to the address. This code will parse all the available bits when unpacking (up to optlen). When packing it will apply SourceNetmask. If you need more advanced logic, patches welcome and good luck.

func (*EDNS0_SUBNET) Option

func (e *EDNS0_SUBNET) Option() uint16

func (*EDNS0_SUBNET) String

func (e *EDNS0_SUBNET) String() (s string)

type EDNS0_UL

type EDNS0_UL struct {
	Code  uint16 // Always EDNS0UL
	Lease uint32
}

The EDNS0_UL (Update Lease) (draft RFC) option is used to tell the server to set an expiration on an update RR. This is helpful for clients that cannot clean up after themselves. This is a draft RFC and more information can be found at http://files.dns-sd.org/draft-sekar-dns-ul.txt

o := new(dns.OPT)
o.Hdr.Name = "."
o.Hdr.Rrtype = dns.TypeOPT
e := new(dns.EDNS0_UL)
e.Code = dns.EDNS0UL
e.Lease = 120 // in seconds
o.Option = append(o.Option, e)

func (*EDNS0_UL) Option

func (e *EDNS0_UL) Option() uint16

func (*EDNS0_UL) String

func (e *EDNS0_UL) String() string

type EID

type EID struct {
	Hdr      RR_Header
	Endpoint string `dns:"hex"`
}

func (*EID) Header

func (rr *EID) Header() *RR_Header

func (*EID) String

func (rr *EID) String() string

type EUI48

type EUI48 struct {
	Hdr     RR_Header
	Address uint64 `dns:"uint48"`
}

func (*EUI48) Header

func (rr *EUI48) Header() *RR_Header

func (*EUI48) String

func (rr *EUI48) String() string

type EUI64

type EUI64 struct {
	Hdr     RR_Header
	Address uint64
}

func (*EUI64) Header

func (rr *EUI64) Header() *RR_Header

func (*EUI64) String

func (rr *EUI64) String() string

type Envelope

type Envelope struct {
	RR    []RR  // The set of RRs in the answer section of the xfr reply message.
	Error error // If something went wrong, this contains the error.
}

Envelope is used when doing a zone transfer with a remote server.

type Error

type Error struct {
	// contains filtered or unexported fields
}

Error represents a DNS error

func (*Error) Error

func (e *Error) Error() string

type GID

type GID struct {
	Hdr RR_Header
	Gid uint32
}

func (*GID) Header

func (rr *GID) Header() *RR_Header

func (*GID) String

func (rr *GID) String() string

type GPOS

type GPOS struct {
	Hdr       RR_Header
	Longitude string
	Latitude  string
	Altitude  string
}

func (*GPOS) Header

func (rr *GPOS) Header() *RR_Header

func (*GPOS) String

func (rr *GPOS) String() string

type HINFO

type HINFO struct {
	Hdr RR_Header
	Cpu string
	Os  string
}

func (*HINFO) Header

func (rr *HINFO) Header() *RR_Header

func (*HINFO) String

func (rr *HINFO) String() string

type HIP

type HIP struct {
	Hdr                RR_Header
	HitLength          uint8
	PublicKeyAlgorithm uint8
	PublicKeyLength    uint16
	Hit                string   `dns:"hex"`
	PublicKey          string   `dns:"base64"`
	RendezvousServers  []string `dns:"domain-name"`
}
Example
h := `www.example.com     IN  HIP ( 2 200100107B1A74DF365639CC39F1D578
                AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p
9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwkUs7lBu+Upr1gsNrut79ryra+bSRGQ
b1slImA8YVJyuIDsj7kwzG7jnERNqnWxZ48AWkskmdHaVDP4BcelrTI3rMXdXF5D
        rvs.example.com. )`
if hip, err := NewRR(h); err == nil {
	fmt.Println(hip.String())
}
Output:

www.example.com.	3600	IN	HIP	2 200100107B1A74DF365639CC39F1D578 AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwkUs7lBu+Upr1gsNrut79ryra+bSRGQb1slImA8YVJyuIDsj7kwzG7jnERNqnWxZ48AWkskmdHaVDP4BcelrTI3rMXdXF5D rvs.example.com.

func (*HIP) Header

func (rr *HIP) Header() *RR_Header

func (*HIP) String

func (rr *HIP) String() string

type Handler

type Handler interface {
	ServeDNS(w ResponseWriter, r *Msg)
}

Handler is implemented by any value that implements ServeDNS.

type HandlerFunc

type HandlerFunc func(ResponseWriter, *Msg)

The HandlerFunc type is an adapter to allow the use of ordinary functions as DNS handlers. If f is a function with the appropriate signature, HandlerFunc(f) is a Handler object that calls f.

func (HandlerFunc) ServeDNS

func (f HandlerFunc) ServeDNS(w ResponseWriter, r *Msg)

ServeDNS calls f(w, r).

type Header struct {
	Id                                 uint16
	Bits                               uint16
	Qdcount, Ancount, Nscount, Arcount uint16
}

Headers is the wire format for the DNS packet header.

type IPSECKEY

type IPSECKEY struct {
	Hdr        RR_Header
	Precedence uint8
	// GatewayType: 1: A record, 2: AAAA record, 3: domainname.
	// 0 is use for no type and GatewayName should be "." then.
	GatewayType uint8
	Algorithm   uint8
	// Gateway can be an A record, AAAA record or a domain name.
	GatewayA    net.IP `dns:"a"`
	GatewayAAAA net.IP `dns:"aaaa"`
	GatewayName string `dns:"domain-name"`
	PublicKey   string `dns:"base64"`
}

func (*IPSECKEY) Header

func (rr *IPSECKEY) Header() *RR_Header

func (*IPSECKEY) String

func (rr *IPSECKEY) String() string

type KEY

type KEY struct {
	DNSKEY
}

type KX

type KX struct {
	Hdr        RR_Header
	Preference uint16
	Exchanger  string `dns:"domain-name"`
}

func (*KX) Header

func (rr *KX) Header() *RR_Header

func (*KX) String

func (rr *KX) String() string

type L32

type L32 struct {
	Hdr        RR_Header
	Preference uint16
	Locator32  net.IP `dns:"a"`
}

func (*L32) Header

func (rr *L32) Header() *RR_Header

func (*L32) String

func (rr *L32) String() string

type L64

type L64 struct {
	Hdr        RR_Header
	Preference uint16
	Locator64  uint64
}

func (*L64) Header

func (rr *L64) Header() *RR_Header

func (*L64) String

func (rr *L64) String() string

type LOC

type LOC struct {
	Hdr       RR_Header
	Version   uint8
	Size      uint8
	HorizPre  uint8
	VertPre   uint8
	Latitude  uint32
	Longitude uint32
	Altitude  uint32
}

func (*LOC) Header

func (rr *LOC) Header() *RR_Header

func (*LOC) String

func (rr *LOC) String() string

type LP

type LP struct {
	Hdr        RR_Header
	Preference uint16
	Fqdn       string `dns:"domain-name"`
}

func (*LP) Header

func (rr *LP) Header() *RR_Header

func (*LP) String

func (rr *LP) String() string

type MB

type MB struct {
	Hdr RR_Header
	Mb  string `dns:"cdomain-name"`
}

func (*MB) Header

func (rr *MB) Header() *RR_Header

func (*MB) String

func (rr *MB) String() string

type MD

type MD struct {
	Hdr RR_Header
	Md  string `dns:"cdomain-name"`
}

func (*MD) Header

func (rr *MD) Header() *RR_Header

func (*MD) String

func (rr *MD) String() string

type MF

type MF struct {
	Hdr RR_Header
	Mf  string `dns:"cdomain-name"`
}

func (*MF) Header

func (rr *MF) Header() *RR_Header

func (*MF) String

func (rr *MF) String() string

type MG

type MG struct {
	Hdr RR_Header
	Mg  string `dns:"cdomain-name"`
}

func (*MG) Header

func (rr *MG) Header() *RR_Header

func (*MG) String

func (rr *MG) String() string

type MINFO

type MINFO struct {
	Hdr   RR_Header
	Rmail string `dns:"cdomain-name"`
	Email string `dns:"cdomain-name"`
}

func (*MINFO) Header

func (rr *MINFO) Header() *RR_Header

func (*MINFO) String

func (rr *MINFO) String() string

type MR

type MR struct {
	Hdr RR_Header
	Mr  string `dns:"cdomain-name"`
}

func (*MR) Header

func (rr *MR) Header() *RR_Header

func (*MR) String

func (rr *MR) String() string

type MX

type MX struct {
	Hdr        RR_Header
	Preference uint16
	Mx         string `dns:"cdomain-name"`
}
Example

Retrieve the MX records for miek.nl.

package main

import (
	"fmt"
	"github.com/miekg/dns"
)

func main() {
	config, _ := dns.ClientConfigFromFile("/etc/resolv.conf")
	c := new(dns.Client)
	m := new(dns.Msg)
	m.SetQuestion("miek.nl.", dns.TypeMX)
	m.RecursionDesired = true
	r, _, err := c.Exchange(m, config.Servers[0]+":"+config.Port)
	if err != nil {
		return
	}
	if r.Rcode != dns.RcodeSuccess {
		return
	}
	for _, a := range r.Answer {
		if mx, ok := a.(*dns.MX); ok {
			fmt.Printf("%s\n", mx.String())
		}
	}
}
Output:

func (*MX) Header

func (rr *MX) Header() *RR_Header

func (*MX) String

func (rr *MX) String() string

type Msg

type Msg struct {
	MsgHdr
	Compress bool       `json:"-"` // If true, the message will be compressed when converted to wire format. This not part of the official DNS packet format.
	Question []Question // Holds the RR(s) of the question section.
	Answer   []RR       // Holds the RR(s) of the answer section.
	Ns       []RR       // Holds the RR(s) of the authority section.
	Extra    []RR       // Holds the RR(s) of the additional section.
}

Msg contains the layout of a DNS message.

func Exchange

func Exchange(m *Msg, a string) (r *Msg, err error)

Exchange performs a synchronous UDP query. It sends the message m to the address contained in a and waits for an reply. Exchange does not retry a failed query, nor will it fall back to TCP in case of truncation. If you need to send a DNS message on an already existing connection, you can use the following:

co := &dns.Conn{Conn: c} // c is your net.Conn
co.WriteMsg(m)
in, err  := co.ReadMsg()
co.Close()

func ExchangeConn

func ExchangeConn(c net.Conn, m *Msg) (r *Msg, err error)

ExchangeConn performs a synchronous query. It sends the message m via the connection c and waits for a reply. The connection c is not closed by ExchangeConn. This function is going away, but can easily be mimicked:

co := &dns.Conn{Conn: c} // c is your net.Conn
co.WriteMsg(m)
in, _  := co.ReadMsg()
co.Close()

func (*Msg) Copy

func (dns *Msg) Copy() *Msg

Copy returns a new *Msg which is a deep-copy of dns.

func (*Msg) CopyTo

func (dns *Msg) CopyTo(r1 *Msg) *Msg

CopyTo copies the contents to the provided message using a deep-copy and returns the copy.

func (*Msg) Insert

func (u *Msg) Insert(rr []RR)

Insert creates a dynamic update packet that adds an complete RRset, see RFC 2136 section 2.5.1.

func (*Msg) IsEdns0

func (dns *Msg) IsEdns0() *OPT

IsEdns0 checks if the message has a EDNS0 (OPT) record, any EDNS0 record in the additional section will do. It returns the OPT record found or nil.

func (*Msg) IsTsig

func (dns *Msg) IsTsig() *TSIG

IsTsig checks if the message has a TSIG record as the last record in the additional section. It returns the TSIG record found or nil.

func (*Msg) Len

func (dns *Msg) Len() int

Len returns the message length when in (un)compressed wire format. If dns.Compress is true compression it is taken into account. Len() is provided to be a faster way to get the size of the resulting packet, than packing it, measuring the size and discarding the buffer.

func (*Msg) NameNotUsed

func (u *Msg) NameNotUsed(rr []RR)

NameNotUsed sets the RRs in the prereq section to "Name is in not use" RRs. RFC 2136 section 2.4.5.

func (*Msg) NameUsed

func (u *Msg) NameUsed(rr []RR)

NameUsed sets the RRs in the prereq section to "Name is in use" RRs. RFC 2136 section 2.4.4.

func (*Msg) Pack

func (dns *Msg) Pack() (msg []byte, err error)

Pack packs a Msg: it is converted to to wire format. If the dns.Compress is true the message will be in compressed wire format.

func (*Msg) PackBuffer

func (dns *Msg) PackBuffer(buf []byte) (msg []byte, err error)

PackBuffer packs a Msg, using the given buffer buf. If buf is too small a new buffer is allocated.

func (*Msg) RRsetNotUsed

func (u *Msg) RRsetNotUsed(rr []RR)

RRsetNotUsed sets the RRs in the prereq section to "RRset does not exist" RRs. RFC 2136 section 2.4.3.

func (*Msg) RRsetUsed

func (u *Msg) RRsetUsed(rr []RR)

RRsetUsed sets the RRs in the prereq section to "RRset exists (value independent -- no rdata)" RRs. RFC 2136 section 2.4.1.

func (*Msg) Remove

func (u *Msg) Remove(rr []RR)

Remove creates a dynamic update packet deletes RR from the RRSset, see RFC 2136 section 2.5.4

func (*Msg) RemoveName

func (u *Msg) RemoveName(rr []RR)

RemoveName creates a dynamic update packet that deletes all RRsets of a name, see RFC 2136 section 2.5.3

func (*Msg) RemoveRRset

func (u *Msg) RemoveRRset(rr []RR)

RemoveRRset creates a dynamic update packet that deletes an RRset, see RFC 2136 section 2.5.2.

func (*Msg) SetAxfr

func (dns *Msg) SetAxfr(z string) *Msg

SetAxfr creates message for requesting an AXFR.

func (*Msg) SetEdns0

func (dns *Msg) SetEdns0(udpsize uint16, do bool) *Msg

SetEdns0 appends a EDNS0 OPT RR to the message. TSIG should always the last RR in a message.

func (*Msg) SetIxfr

func (dns *Msg) SetIxfr(z string, serial uint32, ns, mbox string) *Msg

SetIxfr creates message for requesting an IXFR.

func (*Msg) SetNotify

func (dns *Msg) SetNotify(z string) *Msg

SetNotify creates a notify message, it sets the Question section, generates an Id and sets the Authoritative (AA) bit to true.

func (*Msg) SetQuestion

func (dns *Msg) SetQuestion(z string, t uint16) *Msg

SetQuestion creates a question message, it sets the Question section, generates an Id and sets the RecursionDesired (RD) bit to true.

func (*Msg) SetRcode

func (dns *Msg) SetRcode(request *Msg, rcode int) *Msg

SetRcode creates an error message suitable for the request.

func (*Msg) SetRcodeFormatError

func (dns *Msg) SetRcodeFormatError(request *Msg) *Msg

SetRcodeFormatError creates a message with FormError set.

func (*Msg) SetReply

func (dns *Msg) SetReply(request *Msg) *Msg

SetReply creates a reply message from a request message.

func (*Msg) SetTsig

func (dns *Msg) SetTsig(z, algo string, fudge, timesigned int64) *Msg

SetTsig appends a TSIG RR to the message. This is only a skeleton TSIG RR that is added as the last RR in the additional section. The Tsig is calculated when the message is being send.

func (*Msg) SetUpdate

func (dns *Msg) SetUpdate(z string) *Msg

SetUpdate makes the message a dynamic update message. It sets the ZONE section to: z, TypeSOA, ClassINET.

func (*Msg) String

func (dns *Msg) String() string

Convert a complete message to a string with dig-like output.

func (*Msg) Unpack

func (dns *Msg) Unpack(msg []byte) (err error)

Unpack unpacks a binary message to a Msg structure.

func (*Msg) Used

func (u *Msg) Used(rr []RR)

Used sets the RRs in the prereq section to "RRset exists (value dependent -- with rdata)" RRs. RFC 2136 section 2.4.2.

type MsgHdr

type MsgHdr struct {
	Id                 uint16
	Response           bool
	Opcode             int
	Authoritative      bool
	Truncated          bool
	RecursionDesired   bool
	RecursionAvailable bool
	Zero               bool
	AuthenticatedData  bool
	CheckingDisabled   bool
	Rcode              int
}

MsgHdr is a a manually-unpacked version of (id, bits).

func (*MsgHdr) String

func (h *MsgHdr) String() string

Convert a MsgHdr to a string, with dig-like headers:

;; opcode: QUERY, status: NOERROR, id: 48404

;; flags: qr aa rd ra;

type NAPTR

type NAPTR struct {
	Hdr         RR_Header
	Order       uint16
	Preference  uint16
	Flags       string
	Service     string
	Regexp      string
	Replacement string `dns:"domain-name"`
}

func (*NAPTR) Header

func (rr *NAPTR) Header() *RR_Header

func (*NAPTR) String

func (rr *NAPTR) String() string

type NID

type NID struct {
	Hdr        RR_Header
	Preference uint16
	NodeID     uint64
}

func (*NID) Header

func (rr *NID) Header() *RR_Header

func (*NID) String

func (rr *NID) String() string

type NIMLOC

type NIMLOC struct {
	Hdr     RR_Header
	Locator string `dns:"hex"`
}

func (*NIMLOC) Header

func (rr *NIMLOC) Header() *RR_Header

func (*NIMLOC) String

func (rr *NIMLOC) String() string

type NINFO

type NINFO struct {
	Hdr    RR_Header
	ZSData []string `dns:"txt"`
}

func (*NINFO) Header

func (rr *NINFO) Header() *RR_Header

func (*NINFO) String

func (rr *NINFO) String() string

type NS

type NS struct {
	Hdr RR_Header
	Ns  string `dns:"cdomain-name"`
}

func (*NS) Header

func (rr *NS) Header() *RR_Header

func (*NS) String

func (rr *NS) String() string

type NSAPPTR

type NSAPPTR struct {
	Hdr RR_Header
	Ptr string `dns:"domain-name"`
}

func (*NSAPPTR) Header

func (rr *NSAPPTR) Header() *RR_Header

func (*NSAPPTR) String

func (rr *NSAPPTR) String() string

type NSEC

type NSEC struct {
	Hdr        RR_Header
	NextDomain string   `dns:"domain-name"`
	TypeBitMap []uint16 `dns:"nsec"`
}

func (*NSEC) Cover

func (rr *NSEC) Cover(name string) bool

Cover implements the Denialer interface.

func (*NSEC) Header

func (rr *NSEC) Header() *RR_Header

func (*NSEC) Match

func (rr *NSEC) Match(name string) bool

Match implements the Denialer interface.

func (*NSEC) String

func (rr *NSEC) String() string

type NSEC3

type NSEC3 struct {
	Hdr        RR_Header
	Hash       uint8
	Flags      uint8
	Iterations uint16
	SaltLength uint8
	Salt       string `dns:"size-hex"`
	HashLength uint8
	NextDomain string   `dns:"size-base32"`
	TypeBitMap []uint16 `dns:"nsec"`
}

func (*NSEC3) Cover

func (rr *NSEC3) Cover(name string) bool

Cover implements the Denialer interface.

func (*NSEC3) Header

func (rr *NSEC3) Header() *RR_Header

func (*NSEC3) Match

func (rr *NSEC3) Match(name string) bool

Match implements the Denialer interface.

func (*NSEC3) String

func (rr *NSEC3) String() string

type NSEC3PARAM

type NSEC3PARAM struct {
	Hdr        RR_Header
	Hash       uint8
	Flags      uint8
	Iterations uint16
	SaltLength uint8
	Salt       string `dns:"hex"`
}

func (*NSEC3PARAM) Header

func (rr *NSEC3PARAM) Header() *RR_Header

func (*NSEC3PARAM) String

func (rr *NSEC3PARAM) String() string

type Name

type Name string

Name is a DNS domain name.

func (Name) String

func (n Name) String() string

String returns the string representation for the name n.

type OPENPGPKEY

type OPENPGPKEY struct {
	Hdr       RR_Header
	PublicKey string `dns:"base64"`
}

func (*OPENPGPKEY) Header

func (rr *OPENPGPKEY) Header() *RR_Header

func (*OPENPGPKEY) String

func (rr *OPENPGPKEY) String() string

type OPT

type OPT struct {
	Hdr    RR_Header
	Option []EDNS0 `dns:"opt"`
}

OPT is the EDNS0 RR appended to messages to convey extra (meta) information. See RFC 6891.

func (*OPT) Do

func (rr *OPT) Do() bool

Do returns the value of the DO (DNSSEC OK) bit.

func (*OPT) ExtendedRcode

func (rr *OPT) ExtendedRcode() uint8

ExtendedRcode returns the EDNS extended RCODE field (the upper 8 bits of the TTL).

func (*OPT) Header

func (rr *OPT) Header() *RR_Header

Header implements the RR interface.

func (*OPT) SetDo

func (rr *OPT) SetDo()

SetDo sets the DO (DNSSEC OK) bit.

func (*OPT) SetExtendedRcode

func (rr *OPT) SetExtendedRcode(v uint8)

SetExtendedRcode sets the EDNS extended RCODE field.

func (*OPT) SetUDPSize

func (rr *OPT) SetUDPSize(size uint16)

SetUDPSize sets the UDP buffer size.

func (*OPT) SetVersion

func (rr *OPT) SetVersion(v uint8)

SetVersion sets the version of EDNS. This is usually zero.

func (*OPT) String

func (rr *OPT) String() string

func (*OPT) UDPSize

func (rr *OPT) UDPSize() uint16

UDPSize returns the UDP buffer size.

func (*OPT) Version

func (rr *OPT) Version() uint8

Version returns the EDNS version used. Only zero is defined.

type PTR

type PTR struct {
	Hdr RR_Header
	Ptr string `dns:"cdomain-name"`
}

func (*PTR) Header

func (rr *PTR) Header() *RR_Header

func (*PTR) String

func (rr *PTR) String() string

type PX

type PX struct {
	Hdr        RR_Header
	Preference uint16
	Map822     string `dns:"domain-name"`
	Mapx400    string `dns:"domain-name"`
}

func (*PX) Header

func (rr *PX) Header() *RR_Header

func (*PX) String

func (rr *PX) String() string

type ParseError

type ParseError struct {
	// contains filtered or unexported fields
}

ParseError is a parsing error. It contains the parse error and the location in the io.Reader where the error occured.

func (*ParseError) Error

func (e *ParseError) Error() (s string)

type PrivateRR

type PrivateRR struct {
	Hdr  RR_Header
	Data PrivateRdata
}

PrivateRR represents an RR that uses a PrivateRdata user-defined type. It mocks normal RRs and implements dns.RR interface.

func (*PrivateRR) Header

func (r *PrivateRR) Header() *RR_Header

Header return the RR header of r.

func (*PrivateRR) String

func (r *PrivateRR) String() string

type PrivateRdata

type PrivateRdata interface {
	// String returns the text presentaton of the Rdata of the Private RR.
	String() string
	// Parse parses the Rdata of the private RR.
	Parse([]string) error
	// Pack is used when packing a private RR into a buffer.
	Pack([]byte) (int, error)
	// Unpack is used when unpacking a private RR from a buffer.
	// TODO(miek): diff. signature than Pack, see edns0.go for instance.
	Unpack([]byte) (int, error)
	// Copy copies the Rdata.
	Copy(PrivateRdata) error
	// Len returns the length in octets of the Rdata.
	Len() int
}

PrivateRdata is an interface used for implementing "Private Use" RR types, see RFC 6895. This allows one to experiment with new RR types, without requesting an official type code. Also see dns.PrivateHandle and dns.PrivateHandleRemove.

type Question

type Question struct {
	Name   string `dns:"cdomain-name"` // "cdomain-name" specifies encoding (and may be compressed)
	Qtype  uint16
	Qclass uint16
}

Question holds a DNS question. There can be multiple questions in the question section of a message. Usually there is just one.

func (*Question) String

func (q *Question) String() (s string)

type RFC3597

type RFC3597 struct {
	Hdr   RR_Header
	Rdata string `dns:"hex"`
}

RFC3597 represents an unknown/generic RR.

func (*RFC3597) Header

func (rr *RFC3597) Header() *RR_Header

func (*RFC3597) String

func (rr *RFC3597) String() string

func (*RFC3597) ToRFC3597

func (rr *RFC3597) ToRFC3597(r RR) error

ToRFC3597 converts a known RR to the unknown RR representation from RFC 3597.

type RKEY

type RKEY struct {
	Hdr       RR_Header
	Flags     uint16
	Protocol  uint8
	Algorithm uint8
	PublicKey string `dns:"base64"`
}

func (*RKEY) Header

func (rr *RKEY) Header() *RR_Header

func (*RKEY) String

func (rr *RKEY) String() string

type RP

type RP struct {
	Hdr  RR_Header
	Mbox string `dns:"domain-name"`
	Txt  string `dns:"domain-name"`
}

func (*RP) Header

func (rr *RP) Header() *RR_Header

func (*RP) String

func (rr *RP) String() string

type RR

type RR interface {
	// Header returns the header of an resource record. The header contains
	// everything up to the rdata.
	Header() *RR_Header
	// String returns the text representation of the resource record.
	String() string
	// contains filtered or unexported methods
}

An RR represents a resource record.

func Copy

func Copy(r RR) RR

Copy returns a new RR which is a deep-copy of r.

func Dedup added in v1.0.7

func Dedup(rrs []RR, m map[string]RR) []RR

Dedup removes identical RRs from rrs. It preserves the original ordering. The lowest TTL of any duplicates is used in the remaining one. Dedup modifies rrs. m is used to store the RRs temporay. If it is nil a new map will be allocated.

func NewRR

func NewRR(s string) (RR, error)

NewRR reads the RR contained in the string s. Only the first RR is returned. If s contains no RR, return nil with no error. The class defaults to IN and TTL defaults to 3600. The full zone file syntax like $TTL, $ORIGIN, etc. is supported. All fields of the returned RR are set, except RR.Header().Rdlength which is set to 0.

func ReadRR

func ReadRR(q io.Reader, filename string) (RR, error)

ReadRR reads the RR contained in q. See NewRR for more documentation.

func UnpackRR

func UnpackRR(msg []byte, off int) (rr RR, off1 int, err error)

UnpackRR unpacks msg[off:] into an RR.

type RRSIG

type RRSIG struct {
	Hdr         RR_Header
	TypeCovered uint16
	Algorithm   uint8
	Labels      uint8
	OrigTtl     uint32
	Expiration  uint32
	Inception   uint32
	KeyTag      uint16
	SignerName  string `dns:"domain-name"`
	Signature   string `dns:"base64"`
}

func (*RRSIG) Header

func (rr *RRSIG) Header() *RR_Header

func (*RRSIG) Sign

func (rr *RRSIG) Sign(k crypto.Signer, rrset []RR) error

Sign signs an RRSet. The signature needs to be filled in with the values: Inception, Expiration, KeyTag, SignerName and Algorithm. The rest is copied from the RRset. Sign returns true when the signing went OK, otherwise false. There is no check if RRSet is a proper (RFC 2181) RRSet. If OrigTTL is non zero, it is used as-is, otherwise the TTL of the RRset is used as the OrigTTL.

func (*RRSIG) String

func (rr *RRSIG) String() string

func (*RRSIG) ValidityPeriod

func (rr *RRSIG) ValidityPeriod(t time.Time) bool

ValidityPeriod uses RFC1982 serial arithmetic to calculate if a signature period is valid. If t is the zero time, the current time is taken other t is. Returns true if the signature is valid at the given time, otherwise returns false.

func (*RRSIG) Verify

func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error

Verify validates an RRSet with the signature and key. This is only the cryptographic test, the signature validity period must be checked separately. This function copies the rdata of some RRs (to lowercase domain names) for the validation to work.

type RR_Header

type RR_Header struct {
	Name     string `dns:"cdomain-name"`
	Rrtype   uint16
	Class    uint16
	Ttl      uint32
	Rdlength uint16 // length of data after header
}

RR_Header is the header all DNS resource records share.

func (*RR_Header) Header

func (h *RR_Header) Header() *RR_Header

Header returns itself. This is here to make RR_Header implement the RR interface.

func (*RR_Header) String

func (h *RR_Header) String() string

type RT

type RT struct {
	Hdr        RR_Header
	Preference uint16
	Host       string `dns:"cdomain-name"`
}

func (*RT) Header

func (rr *RT) Header() *RR_Header

func (*RT) String

func (rr *RT) String() string

type Reader added in v1.0.7

type Reader interface {
	// ReadTCP reads a raw message from a TCP connection. Implementations may alter
	// connection properties, for example the read-deadline.
	ReadTCP(conn *net.TCPConn, timeout time.Duration) ([]byte, error)
	// ReadUDP reads a raw message from a UDP connection. Implementations may alter
	// connection properties, for example the read-deadline.
	ReadUDP(conn *net.UDPConn, timeout time.Duration) ([]byte, *SessionUDP, error)
}

Reader reads raw DNS messages; each call to ReadTCP or ReadUDP should return an entire message.

type ResponseWriter

type ResponseWriter interface {
	// LocalAddr returns the net.Addr of the server
	LocalAddr() net.Addr
	// RemoteAddr returns the net.Addr of the client that sent the current request.
	RemoteAddr() net.Addr
	// WriteMsg writes a reply back to the client.
	WriteMsg(*Msg) error
	// Write writes a raw buffer back to the client.
	Write([]byte) (int, error)
	// Close closes the connection.
	Close() error
	// TsigStatus returns the status of the Tsig.
	TsigStatus() error
	// TsigTimersOnly sets the tsig timers only boolean.
	TsigTimersOnly(bool)
	// Hijack lets the caller take over the connection.
	// After a call to Hijack(), the DNS package will not do anything with the connection.
	Hijack()
}

A ResponseWriter interface is used by an DNS handler to construct an DNS response.

type SIG

type SIG struct {
	RRSIG
}

SIG is identical to RRSIG and nowadays only used for SIG(0), RFC2931.

func (*SIG) Sign

func (rr *SIG) Sign(k crypto.Signer, m *Msg) ([]byte, error)

Sign signs a dns.Msg. It fills the signature with the appropriate data. The SIG record should have the SignerName, KeyTag, Algorithm, Inception and Expiration set.

func (*SIG) Verify

func (rr *SIG) Verify(k *KEY, buf []byte) error

Verify validates the message buf using the key k. It's assumed that buf is a valid message from which rr was unpacked.

type SOA

type SOA struct {
	Hdr     RR_Header
	Ns      string `dns:"cdomain-name"`
	Mbox    string `dns:"cdomain-name"`
	Serial  uint32
	Refresh uint32
	Retry   uint32
	Expire  uint32
	Minttl  uint32
}
Example
s := "example.com. 1000 SOA master.example.com. admin.example.com. 1 4294967294 4294967293 4294967295 100"
if soa, err := NewRR(s); err == nil {
	fmt.Println(soa.String())
}
Output:

example.com.	1000	IN	SOA	master.example.com. admin.example.com. 1 4294967294 4294967293 4294967295 100

func (*SOA) Header

func (rr *SOA) Header() *RR_Header

func (*SOA) String

func (rr *SOA) String() string

type SPF

type SPF struct {
	Hdr RR_Header
	Txt []string `dns:"txt"`
}

func (*SPF) Header

func (rr *SPF) Header() *RR_Header

func (*SPF) String

func (rr *SPF) String() string

type SRV

type SRV struct {
	Hdr      RR_Header
	Priority uint16
	Weight   uint16
	Port     uint16
	Target   string `dns:"domain-name"`
}

func (*SRV) Header

func (rr *SRV) Header() *RR_Header

func (*SRV) String

func (rr *SRV) String() string

type SSHFP

type SSHFP struct {
	Hdr         RR_Header
	Algorithm   uint8
	Type        uint8
	FingerPrint string `dns:"hex"`
}

func (*SSHFP) Header

func (rr *SSHFP) Header() *RR_Header

func (*SSHFP) String

func (rr *SSHFP) String() string

type ServeMux

type ServeMux struct {
	// contains filtered or unexported fields
}

ServeMux is an DNS request multiplexer. It matches the zone name of each incoming request against a list of registered patterns add calls the handler for the pattern that most closely matches the zone name. ServeMux is DNSSEC aware, meaning that queries for the DS record are redirected to the parent zone (if that is also registered), otherwise the child gets the query. ServeMux is also safe for concurrent access from multiple goroutines.

func NewServeMux

func NewServeMux() *ServeMux

NewServeMux allocates and returns a new ServeMux.

func (*ServeMux) Handle

func (mux *ServeMux) Handle(pattern string, handler Handler)

Handle adds a handler to the ServeMux for pattern.

func (*ServeMux) HandleFunc

func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Msg))

HandleFunc adds a handler function to the ServeMux for pattern.

func (*ServeMux) HandleRemove

func (mux *ServeMux) HandleRemove(pattern string)

HandleRemove deregistrars the handler specific for pattern from the ServeMux.

func (*ServeMux) ServeDNS

func (mux *ServeMux) ServeDNS(w ResponseWriter, request *Msg)

ServeDNS dispatches the request to the handler whose pattern most closely matches the request message. If DefaultServeMux is used the correct thing for DS queries is done: a possible parent is sought. If no handler is found a standard SERVFAIL message is returned If the request message does not have exactly one question in the question section a SERVFAIL is returned, unlesss Unsafe is true.

type Server

type Server struct {
	// Address to listen on, ":dns" if empty.
	Addr string
	// if "tcp" it will invoke a TCP listener, otherwise an UDP one.
	Net string
	// TCP Listener to use, this is to aid in systemd's socket activation.
	Listener net.Listener
	// UDP "Listener" to use, this is to aid in systemd's socket activation.
	PacketConn net.PacketConn
	// Handler to invoke, dns.DefaultServeMux if nil.
	Handler Handler
	// Default buffer size to use to read incoming UDP messages. If not set
	// it defaults to MinMsgSize (512 B).
	UDPSize int
	// The net.Conn.SetReadTimeout value for new connections, defaults to 2 * time.Second.
	ReadTimeout time.Duration
	// The net.Conn.SetWriteTimeout value for new connections, defaults to 2 * time.Second.
	WriteTimeout time.Duration
	// TCP idle timeout for multiple queries, if nil, defaults to 8 * time.Second (RFC 5966).
	IdleTimeout func() time.Duration
	// Secret(s) for Tsig map[<zonename>]<base64 secret>.
	TsigSecret map[string]string
	// Unsafe instructs the server to disregard any sanity checks and directly hand the message to
	// the handler. It will specfically not check if the query has the QR bit not set.
	Unsafe bool
	// If NotifyStartedFunc is set it is called once the server has started listening.
	NotifyStartedFunc func()
	// DecorateReader is optional, allows customization of the process that reads raw DNS messages.
	DecorateReader DecorateReader
	// DecorateWriter is optional, allows customization of the process that writes raw DNS messages.
	DecorateWriter DecorateWriter
	// contains filtered or unexported fields
}

A Server defines parameters for running an DNS server.

func (*Server) ActivateAndServe

func (srv *Server) ActivateAndServe() error

ActivateAndServe starts a nameserver with the PacketConn or Listener configured in *Server. Its main use is to start a server from systemd.

func (*Server) ListenAndServe

func (srv *Server) ListenAndServe() error

ListenAndServe starts a nameserver on the configured address in *Server.

func (*Server) Shutdown

func (srv *Server) Shutdown() error

Shutdown gracefully shuts down a server. After a call to Shutdown, ListenAndServe and ActivateAndServe will return. All in progress queries are completed before the server is taken down. If the Shutdown is taking longer than the reading timeout an error is returned.

type SessionUDP

type SessionUDP struct {
	// contains filtered or unexported fields
}

SessionUDP holds the remote address and the associated out-of-band data.

func ReadFromSessionUDP

func ReadFromSessionUDP(conn *net.UDPConn, b []byte) (int, *SessionUDP, error)

ReadFromSessionUDP acts just like net.UDPConn.ReadFrom(), but returns a session object instead of a net.UDPAddr.

func (*SessionUDP) RemoteAddr

func (s *SessionUDP) RemoteAddr() net.Addr

RemoteAddr returns the remote network address.

type TA

type TA struct {
	Hdr        RR_Header
	KeyTag     uint16
	Algorithm  uint8
	DigestType uint8
	Digest     string `dns:"hex"`
}

func (*TA) Header

func (rr *TA) Header() *RR_Header

func (*TA) String

func (rr *TA) String() string
type TALINK struct {
	Hdr          RR_Header
	PreviousName string `dns:"domain-name"`
	NextName     string `dns:"domain-name"`
}

func (*TALINK) Header

func (rr *TALINK) Header() *RR_Header

func (*TALINK) String

func (rr *TALINK) String() string

type TKEY

type TKEY struct {
	Hdr        RR_Header
	Algorithm  string `dns:"domain-name"`
	Inception  uint32
	Expiration uint32
	Mode       uint16
	Error      uint16
	KeySize    uint16
	Key        string
	OtherLen   uint16
	OtherData  string
}

func (*TKEY) Header

func (rr *TKEY) Header() *RR_Header

func (*TKEY) String

func (rr *TKEY) String() string

type TLSA

type TLSA struct {
	Hdr          RR_Header
	Usage        uint8
	Selector     uint8
	MatchingType uint8
	Certificate  string `dns:"hex"`
}

func (*TLSA) Header

func (rr *TLSA) Header() *RR_Header

func (*TLSA) Sign

func (r *TLSA) Sign(usage, selector, matchingType int, cert *x509.Certificate) (err error)

Sign creates a TLSA record from an SSL certificate.

func (*TLSA) String

func (rr *TLSA) String() string

func (*TLSA) Verify

func (r *TLSA) Verify(cert *x509.Certificate) error

Verify verifies a TLSA record against an SSL certificate. If it is OK a nil error is returned.

type TSIG

type TSIG struct {
	Hdr        RR_Header
	Algorithm  string `dns:"domain-name"`
	TimeSigned uint64 `dns:"uint48"`
	Fudge      uint16
	MACSize    uint16
	MAC        string `dns:"size-hex"`
	OrigId     uint16
	Error      uint16
	OtherLen   uint16
	OtherData  string `dns:"size-hex"`
}

TSIG is the RR the holds the transaction signature of a message. See RFC 2845 and RFC 4635.

func (*TSIG) Header

func (rr *TSIG) Header() *RR_Header

func (*TSIG) String

func (rr *TSIG) String() string

type TXT

type TXT struct {
	Hdr RR_Header
	Txt []string `dns:"txt"`
}

func (*TXT) Header

func (rr *TXT) Header() *RR_Header

func (*TXT) String

func (rr *TXT) String() string

type Token

type Token struct {
	// The scanned resource record when error is not nil.
	RR
	// When an error occured, this has the error specifics.
	Error *ParseError
	// A potential comment positioned after the RR and on the same line.
	Comment string
}

Token holds the token that are returned when a zone file is parsed.

type Transfer

type Transfer struct {
	*Conn
	DialTimeout  time.Duration     // net.DialTimeout, defaults to 2 seconds
	ReadTimeout  time.Duration     // net.Conn.SetReadTimeout value for connections, defaults to 2 seconds
	WriteTimeout time.Duration     // net.Conn.SetWriteTimeout value for connections, defaults to 2 seconds
	TsigSecret   map[string]string // Secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be fully qualified
	// contains filtered or unexported fields
}

A Transfer defines parameters that are used during a zone transfer.

func (*Transfer) In

func (t *Transfer) In(q *Msg, a string) (env chan *Envelope, err error)

In performs an incoming transfer with the server in a.

func (*Transfer) Out

func (t *Transfer) Out(w ResponseWriter, q *Msg, ch chan *Envelope) error

Out performs an outgoing transfer with the client connecting in w. Basic use pattern:

ch := make(chan *dns.Envelope)
tr := new(dns.Transfer)
tr.Out(w, r, ch)
c <- &dns.Envelope{RR: []dns.RR{soa, rr1, rr2, rr3, soa}}
close(ch)
w.Hijack()
// w.Close() // Client closes connection

The server is responsible for sending the correct sequence of RRs through the channel ch.

func (*Transfer) ReadMsg

func (t *Transfer) ReadMsg() (*Msg, error)

ReadMsg reads a message from the transfer connection t.

func (*Transfer) WriteMsg

func (t *Transfer) WriteMsg(m *Msg) (err error)

WriteMsg writes a message through the transfer connection t.

type Type

type Type uint16

Type is a DNS type.

func (Type) String

func (t Type) String() string

String returns the string representation for the type t.

type UID

type UID struct {
	Hdr RR_Header
	Uid uint32
}

func (*UID) Header

func (rr *UID) Header() *RR_Header

func (*UID) String

func (rr *UID) String() string

type UINFO

type UINFO struct {
	Hdr   RR_Header
	Uinfo string
}

func (*UINFO) Header

func (rr *UINFO) Header() *RR_Header

func (*UINFO) String

func (rr *UINFO) String() string

type URI

type URI struct {
	Hdr      RR_Header
	Priority uint16
	Weight   uint16
	Target   string `dns:"octet"`
}

func (*URI) Header

func (rr *URI) Header() *RR_Header

func (*URI) String

func (rr *URI) String() string

type WKS

type WKS struct {
	Hdr      RR_Header
	Address  net.IP `dns:"a"`
	Protocol uint8
	BitMap   []uint16 `dns:"wks"`
}

func (*WKS) Header

func (rr *WKS) Header() *RR_Header

func (*WKS) String

func (rr *WKS) String() (s string)

type Writer added in v1.0.7

type Writer interface {
	io.Writer
}

Writer writes raw DNS messages; each call to Write should send an entire message.

type X25

type X25 struct {
	Hdr         RR_Header
	PSDNAddress string
}

func (*X25) Header

func (rr *X25) Header() *RR_Header

func (*X25) String

func (rr *X25) String() string

Directories

Path Synopsis
Package idn implements encoding from and to punycode as speficied by RFC 3492.
Package idn implements encoding from and to punycode as speficied by RFC 3492.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL