Documentation ¶
Overview ¶
Package dns implements a full featured interface to the DNS. The package allows complete control over what is send out to the DNS.
Resource records are native types. They are not stored in wire format. Basic usage pattern for creating a new resource record:
r := new(RR_TXT) r.Hdr = RR_Header{Name: "a.miek.nl", Rrtype: TypeTXT, Class: ClassINET, Ttl: 3600} r.TXT = "This is the content of the TXT record"
The package dns supports (async) querying/replying, incoming/outgoing Axfr/Ixfr, TSIG, EDNS0, dynamic updates, notifies and DNSSEC validation/signing.
In the DNS messages are exchanged. Use pattern for creating one:
m := new(Msg) m.SetQuestion("miek.nl.", dns.TypeMX) // Set the desired options. m.MsgHdr.RecursionDesired = true
Basic use pattern for synchronize querying of the DNS:
c := dns.NewClient() in := c.Exchange(m, "127.0.0.1:53")
Index ¶
- Constants
- Variables
- func Handle(pattern string, handler Handler)
- func HandleFunc(pattern string, handler func(ResponseWriter, *Msg))
- func HandleQuery(d *Conn, i *Msg)
- func HandleQueryFunc(pattern string, handler func(RequestWriter, *Msg))
- func Id() uint16
- func InitQueryChannels()
- func ListenAndQuery(c chan *Request, handler QueryHandler)
- func ListenAndServe(addr string, network string, handler Handler) os.Error
- func QueryAndServeTCP(f func(*Conn, *Msg)) os.Error
- func QueryAndServeUDP(f func(*Conn, *Msg)) os.Error
- func Refused(w ResponseWriter, r *Msg)
- func ServeTCP(l *net.TCPListener, handler Handler) os.Error
- func ServeUDP(l *net.UDPConn, handler Handler) os.Error
- func TsigVerify(msg []byte, secret, requestMAC string, timersOnly bool) (bool, os.Error)
- type Client
- type ClientConfig
- type Error
- type Handler
- type HandlerFunc
- type HandlerQueryFunc
- type Header
- type Msg
- func (dns *Msg) IsAxfr() (ok bool)
- func (dns *Msg) IsIxfr() (ok bool)
- func (dns *Msg) IsNotify() (ok bool)
- func (dns *Msg) IsTsig() (ok bool)
- func (dns *Msg) IsUpdate() (ok bool)
- func (dns *Msg) Pack() (msg []byte, ok bool)
- func (dns *Msg) SetAxfr(z string)
- func (dns *Msg) SetIxfr(z string, serial uint32)
- func (dns *Msg) SetNotify(z string)
- func (dns *Msg) SetQuestion(z string, t uint16)
- func (dns *Msg) SetReply(request *Msg)
- func (dns *Msg) SetTsig(z, algo string, fudge uint16, timesigned uint64)
- func (dns *Msg) String() string
- func (dns *Msg) Unpack(msg []byte) bool
- type MsgHdr
- type Option
- type PrivateKey
- type Query
- type QueryHandler
- type QueryMux
- type Question
- type RR
- type RR_A
- type RR_AAAA
- type RR_CERT
- type RR_CNAME
- type RR_DHCID
- type RR_DLV
- type RR_DNAME
- type RR_DNSKEY
- func (r *RR_DNSKEY) Generate(bits int) (PrivateKey, os.Error)
- func (rr *RR_DNSKEY) Header() *RR_Header
- func (k *RR_DNSKEY) KeyTag() uint16
- func (r *RR_DNSKEY) PrivateKeyString(p PrivateKey) (s string)
- func (k *RR_DNSKEY) ReadPrivateKey(q io.Reader) (PrivateKey, os.Error)
- func (rr *RR_DNSKEY) String() string
- func (k *RR_DNSKEY) ToDS(h int) *RR_DS
- type RR_DS
- type RR_HINFO
- type RR_Header
- type RR_KX
- type RR_LOC
- type RR_MB
- type RR_MG
- type RR_MINFO
- type RR_MR
- type RR_MX
- type RR_NAPTR
- type RR_NS
- type RR_NSEC
- type RR_NSEC3
- type RR_NSEC3PARAM
- type RR_OPT
- func (rr *RR_OPT) Do() bool
- func (rr *RR_OPT) Header() *RR_Header
- func (rr *RR_OPT) Nsid() string
- func (rr *RR_OPT) SetDo()
- func (rr *RR_OPT) SetNsid(hexnsid string)
- func (rr *RR_OPT) SetUDPSize(size uint16)
- func (rr *RR_OPT) SetVersion(v uint8)
- func (rr *RR_OPT) String() string
- func (rr *RR_OPT) UDPSize() uint16
- func (rr *RR_OPT) Version() uint8
- type RR_PTR
- type RR_RFC3597
- type RR_RRSIG
- type RR_SOA
- type RR_SPF
- type RR_SRV
- type RR_SSHFP
- type RR_TA
- type RR_TALINK
- type RR_TKEY
- type RR_TSIG
- type RR_TXT
- type RR_URI
- type RRset
- type Request
- type RequestWriter
- type ResponseWriter
- type ServeMux
- type Server
Constants ¶
const ( Year68 = 2 << (32 - 1) // For RFC1982 (Serial Arithmetic) calculations in 32 bits. DefaultMsgSize = 4096 // A standard default for larger than 512 packets. MaxMsgSize = 65536 // Largest possible DNS packet. DefaultTTL = 3600 // Default Ttl. )
const ( AlgRSAMD5 = 1 AlgDH = 2 AlgDSA = 3 AlgECC = 4 AlgRSASHA1 = 5 AlgRSASHA256 = 8 AlgRSASHA512 = 10 AlgECCGOST = 12 )
DNSSEC encryption algorithm codes.
const ( HashSHA1 HashSHA256 HashGOST94 )
DNSSEC hashing codes.
const ( KSK = 1 ZSK = 1 << 8 REVOKE = 1 << 7 )
DNSKEY flags values.
const ( OptionCodeLLQ // not used OptionCodeUL // not used OptionCodeNSID // NSID, RFC5001 )
EDNS0 Option codes.
const ( HmacMD5 = "hmac-md5.sig-alg.reg.int." HmacSHA1 = "hmac-sha1." HmacSHA256 = "hmac-sha256." )
HMAC hashing codes. These are transmitted as domain names.
const ( // valid RR_Header.Rrtype and Question.qtype TypeA = 1 TypeNS = 2 TypeMD = 3 TypeMF = 4 TypeCNAME = 5 TypeSOA = 6 TypeMB = 7 TypeMG = 8 TypeMR = 9 TypeNULL = 10 TypeWKS = 11 TypePTR = 12 TypeHINFO = 13 TypeMINFO = 14 TypeMX = 15 TypeTXT = 16 TypeAAAA = 28 TypeLOC = 29 TypeSRV = 33 TypeNAPTR = 35 TypeKX = 36 TypeCERT = 37 TypeDNAME = 39 // EDNS TypeOPT = 41 TypeSIG = 24 TypeKEY = 25 TypeNXT = 30 TypeDS = 43 TypeSSHFP = 44 TypeIPSECKEY = 45 // No type implemented TypeRRSIG = 46 TypeNSEC = 47 TypeDNSKEY = 48 TypeDHCID = 49 TypeNSEC3 = 50 TypeNSEC3PARAM = 51 TypeTALINK = 58 TypeSPF = 99 TypeTKEY = 249 TypeTSIG = 250 // valid Question.Qtype only TypeIXFR = 251 TypeAXFR = 252 TypeMAILB = 253 TypeMAILA = 254 TypeALL = 255 // newly defined types TypeURI = 256 TypeTA = 32768 TypeDLV = 32769 // valid Question.Qclass ClassINET = 1 ClassCSNET = 2 ClassCHAOS = 3 ClassHESIOD = 4 ClassNONE = 254 ClassANY = 255 // Msg.rcode 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 RcodeBadKey = 17 RcodeBadTime = 18 RcodeBadMode = 19 // TKEY RcodeBadName = 20 RcodeBadAlg = 21 RcodeBadTrunc = 22 // TSIG // Opcode OpcodeQuery = 0 OpcodeIQuery = 1 OpcodeStatus = 2 // There is no 3 OpcodeNotify = 4 OpcodeUpdate = 5 )
Wire constants and supported types.
Variables ¶
var ( ErrUnpack os.Error = &Error{Error: "unpacking failed"} ErrPack os.Error = &Error{Error: "packing failed"} ErrId os.Error = &Error{Error: "id mismatch"} ErrShortRead os.Error = &Error{Error: "short read"} ErrConn os.Error = &Error{Error: "conn holds both UDP and TCP connection"} ErrConnEmpy os.Error = &Error{Error: "conn has no connection"} ErrServ os.Error = &Error{Error: "no servers could be reached"} ErrKey os.Error = &Error{Error: "bad key"} ErrPrivKey os.Error = &Error{Error: "bad private key"} ErrKeySize os.Error = &Error{Error: "bad key size"} ErrAlg os.Error = &Error{Error: "bad algorithm"} ErrTime os.Error = &Error{Error: "bad time"} ErrNoSig os.Error = &Error{Error: "no signature found"} ErrSig os.Error = &Error{Error: "bad signature"} ErrSigGen os.Error = &Error{Error: "bad signature generation"} ErrAuth os.Error = &Error{Error: "bad authentication"} ErrXfrSoa os.Error = &Error{Error: "no SOA seen"} ErrHandle os.Error = &Error{Error: "handle is nil"} ErrChan os.Error = &Error{Error: "channel is nil"} )
var ( // Request an async query by sending to this channel. QueryRequest chan *Query // Listen for replies to previously sent queries on this channel. QueryReply chan *Query )
These channels are global so that all parts of the application can send queries (or even pick them up).
var Class_str = map[uint16]string{
ClassINET: "IN",
ClassCSNET: "CS",
ClassCHAOS: "CH",
ClassHESIOD: "HS",
ClassANY: "ANY",
}
Map of strings for each CLASS wire type.
var DefaultQueryChan = newQueryChan()
var DefaultQueryMux = NewQueryMux()
DefaultQueryMux is the default QueryMux used by Query.
var DefaultReplyChan = newQueryChanSlice()
Default channel to use for the resolver
var DefaultServeMux = NewServeMux()
DefaultServeMux is the default ServeMux used by Serve.
var Rr_str = map[uint16]string{
TypeCNAME: "CNAME",
TypeHINFO: "HINFO",
TypeMB: "MB",
TypeMG: "MG",
TypeMINFO: "MINFO",
TypeMR: "MR",
TypeMX: "MX",
TypeNS: "NS",
TypePTR: "PTR",
TypeSOA: "SOA",
TypeTXT: "TXT",
TypeSRV: "SRV",
TypeNAPTR: "NAPTR",
TypeKX: "KX",
TypeCERT: "CERT",
TypeDNAME: "DNAME",
TypeA: "A",
TypeAAAA: "AAAA",
TypeLOC: "LOC",
TypeOPT: "OPT",
TypeDS: "DS",
TypeDHCID: "DHCID",
TypeIPSECKEY: "IPSECKEY",
TypeSSHFP: "SSHFP",
TypeRRSIG: "RRSIG",
TypeNSEC: "NSEC",
TypeDNSKEY: "DNSKEY",
TypeNSEC3: "NSEC3",
TypeNSEC3PARAM: "NSEC3PARAM",
TypeTALINK: "TALINK",
TypeSPF: "SPF",
TypeTKEY: "TKEY",
TypeTSIG: "TSIG",
TypeAXFR: "AXFR",
TypeIXFR: "IXFR",
TypeALL: "ANY",
TypeURI: "URI",
TypeTA: "TA",
TypeDLV: "DLV",
}
Map of strings for each RR wire type.
var Str_rr = reverse(Rr_str)
Reverse of Rr_str (needed for string parsing).
Functions ¶
func Handle ¶
Handle register the handler the given pattern in the DefaultServeMux. The documentation for ServeMux explains how patters are matched.
func HandleFunc ¶
func HandleFunc(pattern string, handler func(ResponseWriter, *Msg))
func HandleQuery ¶
func HandleQuery(d *Conn, i *Msg)
HandleQuery can be used as a default query handler. It fires of the querie, wait for a response and sends the response back on the QueryReply channel. HandleQuery closes d.
func HandleQueryFunc ¶
func HandleQueryFunc(pattern string, handler func(RequestWriter, *Msg))
func Id ¶
func Id() uint16
Return a 16 bits random number to be used as a message id. The random provided should be good enough.
func InitQueryChannels ¶
func InitQueryChannels()
Initialize the QueryRequest and QueryReply channels. This is only required when async. queries are wanted.
func ListenAndQuery ¶
func ListenAndQuery(c chan *Request, handler QueryHandler)
func QueryAndServeTCP ¶
QueryAndServeTCP listens for incoming requests on channel in and then calls f. The function f is executed in a seperate goroutine and performs the actual TCP query and should return the result on the QueryReply channel.
func QueryAndServeUDP ¶
QueryAndServeUDP listens for incoming requests on channel in and then calls f. The function f is executed in a seperate goroutine and performs the actual UDP query and should return the result on the QueryReply channel.
func Refused ¶
func Refused(w ResponseWriter, r *Msg)
func ServeTCP ¶
func ServeTCP(l *net.TCPListener, handler Handler) os.Error
Serve accepts incoming DNS request on the TCP listener l, creating a new service thread for each. The service threads read requests and then call handler to reply to them. Handler is typically nil, in which case the DefaultServeMux is used.
Types ¶
type Client ¶
type Client struct { Net string // if "tcp" a TCP query will be initiated, otherwise an UDP one Addr string // address to call Attempts int // number of attempts Retry bool // retry with TCP ChannelQuery chan *Request // read DNS request from this channel ChannelReply chan []*Msg // read DNS request from this channel ReadTimeout int64 // the net.Conn.SetReadTimeout value for new connections WriteTimeout int64 // the net.Conn.SetWriteTimeout value for new connections TsigSecret map[string]string // secret(s) for Tsig map[<zonename>]<base64 secret> }
TODO add: LocalAddr
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 }
Wrap the contents of the /etc/resolv.conf.
func ClientConfigFromFile ¶
func ClientConfigFromFile(conf string) (*ClientConfig, os.Error)
See resolv.conf(5) on a Linux machine. Parse a /etc/resolv.conf like file and return a filled out ClientConfig. Note that all nameservers will have the port number appendend (:53)
type Handler ¶
type Handler interface {
ServeDNS(w ResponseWriter, r *Msg)
}
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)
ServerDNS calls f(w, reg)
type HandlerQueryFunc ¶
type HandlerQueryFunc func(RequestWriter, *Msg)
The HandlerQueryFunc type is an adapter to allow the use of ordinary functions as DNS query handlers. If f is a function with the appropriate signature, HandlerQueryFunc(f) is a QueryHandler object that calls f.
func (HandlerQueryFunc) QueryDNS ¶
func (f HandlerQueryFunc) QueryDNS(w RequestWriter, r *Msg)
QueryDNS calls f(w, reg)
type Msg ¶
The layout of a DNS message.
func SimpleQuery ¶
SimpleQuery performs a query and waits for the reply before returning.
func TsigGenerate ¶
Add a Tsig to an message. // Must return the mac
func (*Msg) SetQuestion ¶
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 }
A manually-unpacked version of (id, bits). This is in its own struct for easy printing.
type PrivateKey ¶
type PrivateKey interface{}
Empty interface that is used as a wrapper around all possible private key implementations from the crypto package.
type Query ¶
type Query struct { // The query message which is to be send. Query *Msg // Any reply message that came back from the wire. Reply *Msg // It is only required to fill out Conn.RemoteAddr. // Optionally you may set Conn.Tsig if TSIG is required. // The rest of the structure is filled by the Query functions. Conn *Conn // If there are any errors there Err is not nil Err os.Error }
Query is used to communicate with the Query* functions.
func (*Query) ListenAndQuery ¶
type QueryHandler ¶
type QueryHandler interface {
QueryDNS(w RequestWriter, q *Msg)
}
type QueryMux ¶
type QueryMux struct {
// contains filtered or unexported fields
}
QueryMux 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.
func (*QueryMux) Handle ¶
func (mux *QueryMux) Handle(pattern string, handler QueryHandler)
func (*QueryMux) HandleQueryFunc ¶
func (mux *QueryMux) HandleQueryFunc(pattern string, handler func(RequestWriter, *Msg))
func (*QueryMux) QueryDNS ¶
func (mux *QueryMux) QueryDNS(w RequestWriter, r *Msg)
type Question ¶
type Question struct { Name string "domain-name" // "domain-name" specifies encoding Qtype uint16 Qclass uint16 }
DNS queries.
type RR_CERT ¶
type RR_CERT struct { Hdr RR_Header Type uint16 KeyTag uint16 Algorithm uint8 Certificate string "base64" }
See RFC 4398.
type RR_DLV ¶
type RR_DNSKEY ¶
type RR_DNSKEY struct { Hdr RR_Header Flags uint16 Protocol uint8 Algorithm uint8 PublicKey string "base64" }
func (*RR_DNSKEY) Generate ¶
func (r *RR_DNSKEY) Generate(bits int) (PrivateKey, os.Error)
Generate a key 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.
func (*RR_DNSKEY) PrivateKeyString ¶
func (r *RR_DNSKEY) PrivateKeyString(p PrivateKey) (s string)
Convert 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 (hashing, keytag), so its a method of the RR_DNSKEY.
func (*RR_DNSKEY) ReadPrivateKey ¶
Read a private key (file) string and create a public key. Return the private key.
type RR_DS ¶
type RR_Header ¶
type RR_Header struct { Name string "domain-name" Rrtype uint16 Class uint16 Ttl uint32 Rdlength uint16 // length of data after header }
DNS resource records. There are many types of messages, but they all share the same header.
type RR_LOC ¶
type RR_NAPTR ¶
type RR_NSEC3 ¶
type RR_NSEC3 struct { Hdr RR_Header Hash uint8 Flags uint8 Iterations uint16 SaltLength uint8 Salt string "size-hex" HashLength uint8 NextDomain string "size-base32" TypeBitMap []uint16 "NSEC" }
type RR_NSEC3PARAM ¶
type RR_NSEC3PARAM struct { Hdr RR_Header Hash uint8 Flags uint8 Iterations uint16 SaltLength uint8 Salt string "hex" }
func (*RR_NSEC3PARAM) Header ¶
func (rr *RR_NSEC3PARAM) Header() *RR_Header
func (*RR_NSEC3PARAM) String ¶
func (rr *RR_NSEC3PARAM) String() string
type RR_OPT ¶
Adding an EDNS0 record to a message is done as follows:
opt := new(RR_OPT) opt.Hdr = dns.RR_Header{Name: "", Rrtype: TypeOPT} opt.SetVersion(0) // set version to zero opt.SetDo() // set the DO bit opt.SetUDPSize(4096) // set the message size m.Extra = make([]RR, 1) m.Extra[0] = opt // add OPT RR to the message
type RR_RFC3597 ¶
Unknown RR representation
func (*RR_RFC3597) Header ¶
func (rr *RR_RFC3597) Header() *RR_Header
func (*RR_RFC3597) String ¶
func (rr *RR_RFC3597) String() string
type RR_RRSIG ¶
type RR_RRSIG struct { Hdr RR_Header TypeCovered uint16 Algorithm uint8 Labels uint8 OrigTtl uint32 Expiration uint32 Inception uint32 KeyTag uint16 SignerName string "domain-name" Signature string "base64" }
DNSSEC types
func (*RR_RRSIG) Sign ¶
func (s *RR_RRSIG) Sign(k PrivateKey, rrset RRset) bool
Sign 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. Returns true when the signing went OK. The Signature data in the RRSIG is filled by this method. There is no check if RRSet is a proper (RFC 2181) RRSet.
func (*RR_RRSIG) ValidityPeriod ¶
Use RFC1982 to calculate if a signature period is valid.
type RR_SOA ¶
type RR_SRV ¶
type RR_TA ¶
type RR_TKEY ¶
type RR_TSIG ¶
type RequestWriter ¶
type RequestWriter interface { WriteMessages([]*Msg) Write(*Msg) Send(*Msg) os.Error Receive() (*Msg, os.Error) }
A RequestWriter interface is used by an DNS query handler to construct an DNS request.
type ResponseWriter ¶
type ResponseWriter interface { // RemoteAddr returns the address of the client that sent the current request RemoteAddr() string Write([]byte) (int, os.Error) }
A ResponseWriter interface is used by an DNS handler to construct an DNS response.
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.
func (*ServeMux) HandleFunc ¶
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Msg))
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.
type Server ¶
type Server struct { Addr string // address to listen on, ":dns" if empty Net string // if "tcp" it will invoke a TCP listener, otherwise an UDP one Handler Handler // handler to invoke, dns.DefaultServeMux if nil ReadTimeout int64 // the net.Conn.SetReadTimeout value for new connections WriteTimeout int64 // the net.Conn.SetWriteTimeout value for new connections }
A Server defines parameters for running an DNS server.