dns/types.go

569 lines
11 KiB
Go
Raw Normal View History

2010-08-04 07:57:59 +10:00
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Extended and bugfixes by Miek Gieben
// Package dns implements a full featured interface to the DNS.
// Supported RFCs and features include:
// * 1034/1035
// * 2671 - EDNS
// * 4033/4034/4035 - DNSSEC + validation functions
// * 1982 - Serial Arithmetic
// * IP6 support
// The package allows full control over what is send out to the DNS.
//
// Basic usage pattern for creating new Resource Record:
//
// r := new(RR_TXT)
// r.TXT = "This is the content of the TXT record"
// r.Hdr = RR_Header{Name: "a.miek.nl", Rrtype: TypeTXT, Class: ClassINET, Ttl: 3600}
2010-08-04 07:57:59 +10:00
//
package dns
import (
"net"
"strconv"
"strings"
2010-08-04 07:57:59 +10:00
)
// Packet formats
// Wire constants.
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
TypeSRV = 33
// EDNS
TypeOPT = 41
// Old DNSSEC
TypeSIG = 24
TypeKEY = 25
TypeNXT = 30
2010-08-04 07:57:59 +10:00
// DNSSEC
TypeDS = 43
TypeRRSIG = 46
TypeNSEC = 47
TypeDNSKEY = 48
TypeNSEC3 = 50
TypeNSEC3PARAM = 51
// valid Question.qtype only
TypeAXFR = 252
TypeMAILB = 253
TypeMAILA = 254
TypeALL = 255
// valid Question.qclass
ClassINET = 1
ClassCSNET = 2
ClassCHAOS = 3
ClassHESIOD = 4
ClassANY = 255
// Msg.rcode
RcodeSuccess = 0
RcodeFormatError = 1
RcodeServerFailure = 2
RcodeNameError = 3
RcodeNotImplemented = 4
RcodeRefused = 5
)
// The wire format for the DNS packet header.
type Header struct {
Id uint16
Bits uint16
Qdcount, Ancount, Nscount, Arcount uint16
}
const (
// Header.Bits
_QR = 1 << 15 // query/response (response=1)
_AA = 1 << 10 // authoritative
_TC = 1 << 9 // truncated
_RD = 1 << 8 // recursion desired
_RA = 1 << 7 // recursion available
_Z = 1 << 6 // Z
_AD = 1 << 5 // authticated data
_CD = 1 << 4 // checking disabled
2010-08-04 07:57:59 +10:00
)
// DNSSEC encryption algorithm codes.
2010-08-04 07:57:59 +10:00
const (
// DNSSEC algorithms
AlgRSAMD5 = 1
AlgDH = 2
AlgDSA = 3
AlgECC = 4
AlgRSASHA1 = 5
AlgRSASHA256 = 8
AlgRSASHA512 = 10
AlgECCGOST = 12
)
// DNSSEC hashing codes.
const (
HashSHA1 = iota
HashSHA256
HashGOST94
)
2010-08-04 07:57:59 +10:00
// DNS queries.
type Question struct {
Name string "domain-name" // "domain-name" specifies encoding; see packers below
Qtype uint16
Qclass uint16
}
func (q *Question) String() string {
// prefix with ; (as in dig)
s := ";" + q.Name + "\t"
s = s + class_str[q.Qclass] + "\t"
s = s + rr_str[q.Qtype]
return s
}
// DNS responses (resource records).
// There are many types of messages,
// but they all share the same header.
type RR_Header struct {
Name string "domain-name"
Rrtype uint16
Class uint16
Ttl uint32
Rdlength uint16 // length of data after header
}
func (h *RR_Header) Header() *RR_Header {
return h
}
func (h *RR_Header) String() string {
var s string
2010-12-23 21:02:01 +11:00
if h.Rrtype == TypeOPT {
2010-12-23 21:02:01 +11:00
s = ";"
// and maybe other things
2010-12-23 21:02:01 +11:00
}
if len(h.Name) == 0 {
s += ".\t"
} else {
s += h.Name + "\t"
}
s = s + strconv.Itoa(int(h.Ttl)) + "\t"
s = s + class_str[h.Class] + "\t"
s = s + rr_str[h.Rrtype] + "\t"
2010-08-04 07:57:59 +10:00
return s
}
type RR interface {
Header() *RR_Header
String() string
}
type RR_CNAME struct {
Hdr RR_Header
Cname string "domain-name"
}
func (rr *RR_CNAME) Header() *RR_Header {
return &rr.Hdr
}
func (rr *RR_CNAME) String() string {
return rr.Hdr.String() + rr.Cname
}
type RR_HINFO struct {
Hdr RR_Header
Cpu string
Os string
}
func (rr *RR_HINFO) Header() *RR_Header {
return &rr.Hdr
}
func (rr *RR_HINFO) String() string {
return rr.Hdr.String() + rr.Cpu + " " + rr.Os
}
type RR_MB struct {
Hdr RR_Header
Mb string "domain-name"
}
func (rr *RR_MB) Header() *RR_Header {
return &rr.Hdr
}
func (rr *RR_MB) String() string {
return rr.Hdr.String() + rr.Mb
}
type RR_MG struct {
Hdr RR_Header
Mg string "domain-name"
}
func (rr *RR_MG) Header() *RR_Header {
return &rr.Hdr
}
func (rr *RR_MG) String() string {
return rr.Hdr.String() + rr.Mg
}
type RR_MINFO struct {
Hdr RR_Header
Rmail string "domain-name"
Email string "domain-name"
}
func (rr *RR_MINFO) Header() *RR_Header {
return &rr.Hdr
}
func (rr *RR_MINFO) String() string {
return rr.Hdr.String() + rr.Rmail + " " + rr.Email
}
type RR_MR struct {
Hdr RR_Header
Mr string "domain-name"
}
func (rr *RR_MR) Header() *RR_Header {
return &rr.Hdr
}
func (rr *RR_MR) String() string {
return rr.Hdr.String() + rr.Mr
}
type RR_MX struct {
Hdr RR_Header
Pref uint16
Mx string "domain-name"
}
func (rr *RR_MX) Header() *RR_Header {
return &rr.Hdr
}
func (rr *RR_MX) String() string {
return rr.Hdr.String() + strconv.Itoa(int(rr.Pref)) + " " + rr.Mx
}
type RR_NS struct {
Hdr RR_Header
Ns string "domain-name"
}
func (rr *RR_NS) Header() *RR_Header {
return &rr.Hdr
}
func (rr *RR_NS) String() string {
return rr.Hdr.String() + rr.Ns
}
type RR_PTR struct {
Hdr RR_Header
Ptr string "domain-name"
}
func (rr *RR_PTR) Header() *RR_Header {
return &rr.Hdr
}
func (rr *RR_PTR) String() string {
return rr.Hdr.String() + rr.Ptr
}
type RR_SOA struct {
Hdr RR_Header
Ns string "domain-name"
Mbox string "domain-name"
Serial uint32
Refresh uint32
Retry uint32
Expire uint32
Minttl uint32
}
func (rr *RR_SOA) Header() *RR_Header {
return &rr.Hdr
}
func (rr *RR_SOA) String() string {
return rr.Hdr.String() + rr.Ns + " " + rr.Mbox +
" " + strconv.Itoa(int(rr.Serial)) +
" " + strconv.Itoa(int(rr.Refresh)) +
" " + strconv.Itoa(int(rr.Retry)) +
" " + strconv.Itoa(int(rr.Expire)) +
" " + strconv.Itoa(int(rr.Minttl))
}
type RR_TXT struct {
Hdr RR_Header
Txt string // not domain name
}
func (rr *RR_TXT) Header() *RR_Header {
return &rr.Hdr
}
func (rr *RR_TXT) String() string {
return rr.Hdr.String() + "\"" + rr.Txt + "\""
}
type RR_SRV struct {
Hdr RR_Header
Priority uint16
Weight uint16
Port uint16
Target string "domain-name"
}
func (rr *RR_SRV) Header() *RR_Header {
return &rr.Hdr
}
func (rr *RR_SRV) String() string {
return rr.Hdr.String() +
strconv.Itoa(int(rr.Priority)) + " " +
strconv.Itoa(int(rr.Weight)) + " " +
strconv.Itoa(int(rr.Port)) + " " + rr.Target
}
type RR_A struct {
Hdr RR_Header
A net.IP "A"
2010-08-04 07:57:59 +10:00
}
func (rr *RR_A) Header() *RR_Header {
return &rr.Hdr
}
func (rr *RR_A) String() string {
return rr.Hdr.String() + rr.A.String()
}
type RR_AAAA struct {
Hdr RR_Header
AAAA net.IP "AAAA"
2010-08-04 07:57:59 +10:00
}
func (rr *RR_AAAA) Header() *RR_Header {
return &rr.Hdr
}
func (rr *RR_AAAA) String() string {
return rr.Hdr.String() + rr.AAAA.String()
}
// DNSSEC types
type RR_RRSIG struct {
2010-12-23 21:02:01 +11:00
Hdr RR_Header
TypeCovered uint16
Algorithm uint8
Labels uint8
OrigTtl uint32
Expiration uint32
Inception uint32
KeyTag uint16
SignerName string "domain-name"
Signature string "base64"
2010-08-04 07:57:59 +10:00
}
func (rr *RR_RRSIG) Header() *RR_Header {
return &rr.Hdr
}
2010-08-04 07:57:59 +10:00
func (rr *RR_RRSIG) String() string {
2010-12-21 08:20:13 +11:00
return rr.Hdr.String() +
" " + rr_str[rr.TypeCovered] +
" " + strconv.Itoa(int(rr.Algorithm)) +
" " + strconv.Itoa(int(rr.Labels)) +
" " + strconv.Itoa(int(rr.OrigTtl)) +
" " + timeToDate(rr.Expiration) +
" " + timeToDate(rr.Inception) +
2010-12-21 08:20:13 +11:00
" " + strconv.Itoa(int(rr.KeyTag)) +
" " + rr.SignerName +
" " + rr.Signature
2010-08-04 07:57:59 +10:00
}
type RR_NSEC struct {
Hdr RR_Header
NextDomain string "domain-name"
TypeBitMap []int "NSEC"
2010-08-04 07:57:59 +10:00
}
func (rr *RR_NSEC) Header() *RR_Header {
return &rr.Hdr
}
func (rr *RR_NSEC) String() string {
return rr.Hdr.String() + "NSEC BLAH"
2010-08-04 07:57:59 +10:00
}
type RR_DS struct {
Hdr RR_Header
KeyTag uint16
Algorithm uint8
DigestType uint8
Digest string "hex"
}
func (rr *RR_DS) Header() *RR_Header {
return &rr.Hdr
}
func (rr *RR_DS) String() string {
return rr.Hdr.String() +
" " + strconv.Itoa(int(rr.KeyTag)) +
" " + strconv.Itoa(int(rr.Algorithm)) +
2010-08-04 07:57:59 +10:00
" " + strconv.Itoa(int(rr.DigestType)) +
" " + strings.ToUpper(rr.Digest)
2010-08-04 07:57:59 +10:00
}
type RR_DNSKEY struct {
Hdr RR_Header
Flags uint16
Protocol uint8
Algorithm uint8
PubKey string "base64"
}
func (rr *RR_DNSKEY) Header() *RR_Header {
return &rr.Hdr
}
func (rr *RR_DNSKEY) String() string {
return rr.Hdr.String() +
" " + strconv.Itoa(int(rr.Flags)) +
" " + strconv.Itoa(int(rr.Protocol)) +
2010-12-21 08:20:13 +11:00
" " + strconv.Itoa(int(rr.Algorithm)) +
2010-08-04 07:57:59 +10:00
" " + rr.PubKey // encoding/base64
}
type RR_NSEC3 struct {
Hdr RR_Header
Hash uint8
Flags uint8
Iterations uint16
SaltLength uint8
Salt string "hex"
HashLength uint8
NextDomain string "domain-name"
TypeBitMap []int "NSEC3" // &{TypeSOA,TypeDS,etc}
2010-08-04 07:57:59 +10:00
}
func (rr *RR_NSEC3) Header() *RR_Header {
return &rr.Hdr
// Salt with strings.ToUpper()
2010-08-04 07:57:59 +10:00
}
func (rr *RR_NSEC3) String() string {
return rr.Hdr.String() + "BLAH"
2010-08-04 07:57:59 +10:00
}
type RR_NSEC3PARAM struct {
Hdr RR_Header
Hash uint8
Flags uint8
Iterations uint16
SaltLength uint8
Salt string "hex"
2010-08-04 07:57:59 +10:00
}
func (rr *RR_NSEC3PARAM) Header() *RR_Header {
return &rr.Hdr
}
func (rr *RR_NSEC3PARAM) String() string {
return rr.Hdr.String() + "BLAH"
// Salt with strings.ToUpper()
2010-08-04 07:57:59 +10:00
}
// Map of constructors for each RR wire type.
var rr_mk = map[int]func() RR{
TypeCNAME: func() RR { return new(RR_CNAME) },
TypeHINFO: func() RR { return new(RR_HINFO) },
TypeMB: func() RR { return new(RR_MB) },
TypeMG: func() RR { return new(RR_MG) },
TypeMINFO: func() RR { return new(RR_MINFO) },
TypeMR: func() RR { return new(RR_MR) },
TypeMX: func() RR { return new(RR_MX) },
TypeNS: func() RR { return new(RR_NS) },
TypePTR: func() RR { return new(RR_PTR) },
TypeSOA: func() RR { return new(RR_SOA) },
TypeTXT: func() RR { return new(RR_TXT) },
TypeSRV: func() RR { return new(RR_SRV) },
TypeA: func() RR { return new(RR_A) },
TypeAAAA: func() RR { return new(RR_AAAA) },
TypeOPT: func() RR { return new(RR_OPT) },
2010-08-04 07:57:59 +10:00
TypeDS: func() RR { return new(RR_DS) },
TypeRRSIG: func() RR { return new(RR_RRSIG) },
TypeNSEC: func() RR { return new(RR_NSEC) },
TypeDNSKEY: func() RR { return new(RR_DNSKEY) },
TypeNSEC3: func() RR { return new(RR_NSEC3) },
TypeNSEC3PARAM: func() RR { return new(RR_NSEC3PARAM) },
}
// Map of strings for each RR wire type.
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",
TypeA: "A",
TypeAAAA: "AAAA",
2010-12-23 21:02:01 +11:00
TypeOPT: "OPT",
2010-08-04 07:57:59 +10:00
TypeDS: "DS",
TypeRRSIG: "RRSIG",
TypeNSEC: "NSEC",
TypeDNSKEY: "DNSKEY",
TypeNSEC3: "NSEC3",
TypeNSEC3PARAM: "NSEC3PARAM",
}
// Map for algorithm names.
2010-08-04 07:57:59 +10:00
var alg_str = map[uint8]string{
AlgRSAMD5: "RSAMD5",
AlgDH: "DH",
AlgDSA: "DSA",
AlgRSASHA1: "RSASHA1",
AlgRSASHA256: "RSASHA256",
AlgRSASHA512: "RSASHA512",
AlgECCGOST: "ECC-GOST",
}