...

Source file src/github.com/miekg/dns/types.go

Documentation: github.com/miekg/dns

     1  package dns
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"net"
     7  	"strconv"
     8  	"strings"
     9  	"time"
    10  )
    11  
    12  type (
    13  	// Type is a DNS type.
    14  	Type uint16
    15  	// Class is a DNS class.
    16  	Class uint16
    17  	// Name is a DNS domain name.
    18  	Name string
    19  )
    20  
    21  // Packet formats
    22  
    23  // Wire constants and supported types.
    24  const (
    25  	// valid RR_Header.Rrtype and Question.qtype
    26  
    27  	TypeNone       uint16 = 0
    28  	TypeA          uint16 = 1
    29  	TypeNS         uint16 = 2
    30  	TypeMD         uint16 = 3
    31  	TypeMF         uint16 = 4
    32  	TypeCNAME      uint16 = 5
    33  	TypeSOA        uint16 = 6
    34  	TypeMB         uint16 = 7
    35  	TypeMG         uint16 = 8
    36  	TypeMR         uint16 = 9
    37  	TypeNULL       uint16 = 10
    38  	TypePTR        uint16 = 12
    39  	TypeHINFO      uint16 = 13
    40  	TypeMINFO      uint16 = 14
    41  	TypeMX         uint16 = 15
    42  	TypeTXT        uint16 = 16
    43  	TypeRP         uint16 = 17
    44  	TypeAFSDB      uint16 = 18
    45  	TypeX25        uint16 = 19
    46  	TypeISDN       uint16 = 20
    47  	TypeRT         uint16 = 21
    48  	TypeNSAPPTR    uint16 = 23
    49  	TypeSIG        uint16 = 24
    50  	TypeKEY        uint16 = 25
    51  	TypePX         uint16 = 26
    52  	TypeGPOS       uint16 = 27
    53  	TypeAAAA       uint16 = 28
    54  	TypeLOC        uint16 = 29
    55  	TypeNXT        uint16 = 30
    56  	TypeEID        uint16 = 31
    57  	TypeNIMLOC     uint16 = 32
    58  	TypeSRV        uint16 = 33
    59  	TypeATMA       uint16 = 34
    60  	TypeNAPTR      uint16 = 35
    61  	TypeKX         uint16 = 36
    62  	TypeCERT       uint16 = 37
    63  	TypeDNAME      uint16 = 39
    64  	TypeOPT        uint16 = 41 // EDNS
    65  	TypeAPL        uint16 = 42
    66  	TypeDS         uint16 = 43
    67  	TypeSSHFP      uint16 = 44
    68  	TypeIPSECKEY   uint16 = 45
    69  	TypeRRSIG      uint16 = 46
    70  	TypeNSEC       uint16 = 47
    71  	TypeDNSKEY     uint16 = 48
    72  	TypeDHCID      uint16 = 49
    73  	TypeNSEC3      uint16 = 50
    74  	TypeNSEC3PARAM uint16 = 51
    75  	TypeTLSA       uint16 = 52
    76  	TypeSMIMEA     uint16 = 53
    77  	TypeHIP        uint16 = 55
    78  	TypeNINFO      uint16 = 56
    79  	TypeRKEY       uint16 = 57
    80  	TypeTALINK     uint16 = 58
    81  	TypeCDS        uint16 = 59
    82  	TypeCDNSKEY    uint16 = 60
    83  	TypeOPENPGPKEY uint16 = 61
    84  	TypeCSYNC      uint16 = 62
    85  	TypeZONEMD     uint16 = 63
    86  	TypeSVCB       uint16 = 64
    87  	TypeHTTPS      uint16 = 65
    88  	TypeSPF        uint16 = 99
    89  	TypeUINFO      uint16 = 100
    90  	TypeUID        uint16 = 101
    91  	TypeGID        uint16 = 102
    92  	TypeUNSPEC     uint16 = 103
    93  	TypeNID        uint16 = 104
    94  	TypeL32        uint16 = 105
    95  	TypeL64        uint16 = 106
    96  	TypeLP         uint16 = 107
    97  	TypeEUI48      uint16 = 108
    98  	TypeEUI64      uint16 = 109
    99  	TypeURI        uint16 = 256
   100  	TypeCAA        uint16 = 257
   101  	TypeAVC        uint16 = 258
   102  	TypeAMTRELAY   uint16 = 260
   103  
   104  	TypeTKEY uint16 = 249
   105  	TypeTSIG uint16 = 250
   106  
   107  	// valid Question.Qtype only
   108  	TypeIXFR  uint16 = 251
   109  	TypeAXFR  uint16 = 252
   110  	TypeMAILB uint16 = 253
   111  	TypeMAILA uint16 = 254
   112  	TypeANY   uint16 = 255
   113  
   114  	TypeTA       uint16 = 32768
   115  	TypeDLV      uint16 = 32769
   116  	TypeReserved uint16 = 65535
   117  
   118  	// valid Question.Qclass
   119  	ClassINET   = 1
   120  	ClassCSNET  = 2
   121  	ClassCHAOS  = 3
   122  	ClassHESIOD = 4
   123  	ClassNONE   = 254
   124  	ClassANY    = 255
   125  
   126  	// Message Response Codes, see https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml
   127  	RcodeSuccess        = 0  // NoError   - No Error                          [DNS]
   128  	RcodeFormatError    = 1  // FormErr   - Format Error                      [DNS]
   129  	RcodeServerFailure  = 2  // ServFail  - Server Failure                    [DNS]
   130  	RcodeNameError      = 3  // NXDomain  - Non-Existent Domain               [DNS]
   131  	RcodeNotImplemented = 4  // NotImp    - Not Implemented                   [DNS]
   132  	RcodeRefused        = 5  // Refused   - Query Refused                     [DNS]
   133  	RcodeYXDomain       = 6  // YXDomain  - Name Exists when it should not    [DNS Update]
   134  	RcodeYXRrset        = 7  // YXRRSet   - RR Set Exists when it should not  [DNS Update]
   135  	RcodeNXRrset        = 8  // NXRRSet   - RR Set that should exist does not [DNS Update]
   136  	RcodeNotAuth        = 9  // NotAuth   - Server Not Authoritative for zone [DNS Update]
   137  	RcodeNotZone        = 10 // NotZone   - Name not contained in zone        [DNS Update/TSIG]
   138  	RcodeBadSig         = 16 // BADSIG    - TSIG Signature Failure            [TSIG]
   139  	RcodeBadVers        = 16 // BADVERS   - Bad OPT Version                   [EDNS0]
   140  	RcodeBadKey         = 17 // BADKEY    - Key not recognized                [TSIG]
   141  	RcodeBadTime        = 18 // BADTIME   - Signature out of time window      [TSIG]
   142  	RcodeBadMode        = 19 // BADMODE   - Bad TKEY Mode                     [TKEY]
   143  	RcodeBadName        = 20 // BADNAME   - Duplicate key name                [TKEY]
   144  	RcodeBadAlg         = 21 // BADALG    - Algorithm not supported           [TKEY]
   145  	RcodeBadTrunc       = 22 // BADTRUNC  - Bad Truncation                    [TSIG]
   146  	RcodeBadCookie      = 23 // BADCOOKIE - Bad/missing Server Cookie         [DNS Cookies]
   147  
   148  	// Message Opcodes. There is no 3.
   149  	OpcodeQuery  = 0
   150  	OpcodeIQuery = 1
   151  	OpcodeStatus = 2
   152  	OpcodeNotify = 4
   153  	OpcodeUpdate = 5
   154  )
   155  
   156  // Used in ZONEMD https://tools.ietf.org/html/rfc8976
   157  const (
   158  	ZoneMDSchemeSimple = 1
   159  
   160  	ZoneMDHashAlgSHA384 = 1
   161  	ZoneMDHashAlgSHA512 = 2
   162  )
   163  
   164  // Used in IPSEC https://datatracker.ietf.org/doc/html/rfc4025#section-2.3
   165  const (
   166  	IPSECGatewayNone uint8 = iota
   167  	IPSECGatewayIPv4
   168  	IPSECGatewayIPv6
   169  	IPSECGatewayHost
   170  )
   171  
   172  // Used in AMTRELAY https://datatracker.ietf.org/doc/html/rfc8777#section-4.2.3
   173  const (
   174  	AMTRELAYNone = IPSECGatewayNone
   175  	AMTRELAYIPv4 = IPSECGatewayIPv4
   176  	AMTRELAYIPv6 = IPSECGatewayIPv6
   177  	AMTRELAYHost = IPSECGatewayHost
   178  )
   179  
   180  // Header is the wire format for the DNS packet header.
   181  type Header struct {
   182  	Id                                 uint16
   183  	Bits                               uint16
   184  	Qdcount, Ancount, Nscount, Arcount uint16
   185  }
   186  
   187  const (
   188  	headerSize = 12
   189  
   190  	// Header.Bits
   191  	_QR = 1 << 15 // query/response (response=1)
   192  	_AA = 1 << 10 // authoritative
   193  	_TC = 1 << 9  // truncated
   194  	_RD = 1 << 8  // recursion desired
   195  	_RA = 1 << 7  // recursion available
   196  	_Z  = 1 << 6  // Z
   197  	_AD = 1 << 5  // authenticated data
   198  	_CD = 1 << 4  // checking disabled
   199  )
   200  
   201  // Various constants used in the LOC RR. See RFC 1876.
   202  const (
   203  	LOC_EQUATOR       = 1 << 31 // RFC 1876, Section 2.
   204  	LOC_PRIMEMERIDIAN = 1 << 31 // RFC 1876, Section 2.
   205  	LOC_HOURS         = 60 * 1000
   206  	LOC_DEGREES       = 60 * LOC_HOURS
   207  	LOC_ALTITUDEBASE  = 100000
   208  )
   209  
   210  // Different Certificate Types, see RFC 4398, Section 2.1
   211  const (
   212  	CertPKIX = 1 + iota
   213  	CertSPKI
   214  	CertPGP
   215  	CertIPIX
   216  	CertISPKI
   217  	CertIPGP
   218  	CertACPKIX
   219  	CertIACPKIX
   220  	CertURI = 253
   221  	CertOID = 254
   222  )
   223  
   224  // CertTypeToString converts the Cert Type to its string representation.
   225  // See RFC 4398 and RFC 6944.
   226  var CertTypeToString = map[uint16]string{
   227  	CertPKIX:    "PKIX",
   228  	CertSPKI:    "SPKI",
   229  	CertPGP:     "PGP",
   230  	CertIPIX:    "IPIX",
   231  	CertISPKI:   "ISPKI",
   232  	CertIPGP:    "IPGP",
   233  	CertACPKIX:  "ACPKIX",
   234  	CertIACPKIX: "IACPKIX",
   235  	CertURI:     "URI",
   236  	CertOID:     "OID",
   237  }
   238  
   239  // Prefix for IPv4 encoded as IPv6 address
   240  const ipv4InIPv6Prefix = "::ffff:"
   241  
   242  //go:generate go run types_generate.go
   243  
   244  // Question holds a DNS question. Usually there is just one. While the
   245  // original DNS RFCs allow multiple questions in the question section of a
   246  // message, in practice it never works. Because most DNS servers see multiple
   247  // questions as an error, it is recommended to only have one question per
   248  // message.
   249  type Question struct {
   250  	Name   string `dns:"cdomain-name"` // "cdomain-name" specifies encoding (and may be compressed)
   251  	Qtype  uint16
   252  	Qclass uint16
   253  }
   254  
   255  func (q *Question) len(off int, compression map[string]struct{}) int {
   256  	l := domainNameLen(q.Name, off, compression, true)
   257  	l += 2 + 2
   258  	return l
   259  }
   260  
   261  func (q *Question) String() (s string) {
   262  	// prefix with ; (as in dig)
   263  	s = ";" + sprintName(q.Name) + "\t"
   264  	s += Class(q.Qclass).String() + "\t"
   265  	s += " " + Type(q.Qtype).String()
   266  	return s
   267  }
   268  
   269  // ANY is a wild card record. See RFC 1035, Section 3.2.3. ANY
   270  // is named "*" there.
   271  type ANY struct {
   272  	Hdr RR_Header
   273  	// Does not have any rdata
   274  }
   275  
   276  func (rr *ANY) String() string { return rr.Hdr.String() }
   277  
   278  func (*ANY) parse(c *zlexer, origin string) *ParseError {
   279  	return &ParseError{err: "ANY records do not have a presentation format"}
   280  }
   281  
   282  // NULL RR. See RFC 1035.
   283  type NULL struct {
   284  	Hdr  RR_Header
   285  	Data string `dns:"any"`
   286  }
   287  
   288  func (rr *NULL) String() string {
   289  	// There is no presentation format; prefix string with a comment.
   290  	return ";" + rr.Hdr.String() + rr.Data
   291  }
   292  
   293  func (*NULL) parse(c *zlexer, origin string) *ParseError {
   294  	return &ParseError{err: "NULL records do not have a presentation format"}
   295  }
   296  
   297  // CNAME RR. See RFC 1034.
   298  type CNAME struct {
   299  	Hdr    RR_Header
   300  	Target string `dns:"cdomain-name"`
   301  }
   302  
   303  func (rr *CNAME) String() string { return rr.Hdr.String() + sprintName(rr.Target) }
   304  
   305  // HINFO RR. See RFC 1034.
   306  type HINFO struct {
   307  	Hdr RR_Header
   308  	Cpu string
   309  	Os  string
   310  }
   311  
   312  func (rr *HINFO) String() string {
   313  	return rr.Hdr.String() + sprintTxt([]string{rr.Cpu, rr.Os})
   314  }
   315  
   316  // MB RR. See RFC 1035.
   317  type MB struct {
   318  	Hdr RR_Header
   319  	Mb  string `dns:"cdomain-name"`
   320  }
   321  
   322  func (rr *MB) String() string { return rr.Hdr.String() + sprintName(rr.Mb) }
   323  
   324  // MG RR. See RFC 1035.
   325  type MG struct {
   326  	Hdr RR_Header
   327  	Mg  string `dns:"cdomain-name"`
   328  }
   329  
   330  func (rr *MG) String() string { return rr.Hdr.String() + sprintName(rr.Mg) }
   331  
   332  // MINFO RR. See RFC 1035.
   333  type MINFO struct {
   334  	Hdr   RR_Header
   335  	Rmail string `dns:"cdomain-name"`
   336  	Email string `dns:"cdomain-name"`
   337  }
   338  
   339  func (rr *MINFO) String() string {
   340  	return rr.Hdr.String() + sprintName(rr.Rmail) + " " + sprintName(rr.Email)
   341  }
   342  
   343  // MR RR. See RFC 1035.
   344  type MR struct {
   345  	Hdr RR_Header
   346  	Mr  string `dns:"cdomain-name"`
   347  }
   348  
   349  func (rr *MR) String() string {
   350  	return rr.Hdr.String() + sprintName(rr.Mr)
   351  }
   352  
   353  // MF RR. See RFC 1035.
   354  type MF struct {
   355  	Hdr RR_Header
   356  	Mf  string `dns:"cdomain-name"`
   357  }
   358  
   359  func (rr *MF) String() string {
   360  	return rr.Hdr.String() + sprintName(rr.Mf)
   361  }
   362  
   363  // MD RR. See RFC 1035.
   364  type MD struct {
   365  	Hdr RR_Header
   366  	Md  string `dns:"cdomain-name"`
   367  }
   368  
   369  func (rr *MD) String() string {
   370  	return rr.Hdr.String() + sprintName(rr.Md)
   371  }
   372  
   373  // MX RR. See RFC 1035.
   374  type MX struct {
   375  	Hdr        RR_Header
   376  	Preference uint16
   377  	Mx         string `dns:"cdomain-name"`
   378  }
   379  
   380  func (rr *MX) String() string {
   381  	return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) + " " + sprintName(rr.Mx)
   382  }
   383  
   384  // AFSDB RR. See RFC 1183.
   385  type AFSDB struct {
   386  	Hdr      RR_Header
   387  	Subtype  uint16
   388  	Hostname string `dns:"domain-name"`
   389  }
   390  
   391  func (rr *AFSDB) String() string {
   392  	return rr.Hdr.String() + strconv.Itoa(int(rr.Subtype)) + " " + sprintName(rr.Hostname)
   393  }
   394  
   395  // X25 RR. See RFC 1183, Section 3.1.
   396  type X25 struct {
   397  	Hdr         RR_Header
   398  	PSDNAddress string
   399  }
   400  
   401  func (rr *X25) String() string {
   402  	return rr.Hdr.String() + rr.PSDNAddress
   403  }
   404  
   405  // RT RR. See RFC 1183, Section 3.3.
   406  type RT struct {
   407  	Hdr        RR_Header
   408  	Preference uint16
   409  	Host       string `dns:"domain-name"` // RFC 3597 prohibits compressing records not defined in RFC 1035.
   410  }
   411  
   412  func (rr *RT) String() string {
   413  	return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) + " " + sprintName(rr.Host)
   414  }
   415  
   416  // NS RR. See RFC 1035.
   417  type NS struct {
   418  	Hdr RR_Header
   419  	Ns  string `dns:"cdomain-name"`
   420  }
   421  
   422  func (rr *NS) String() string {
   423  	return rr.Hdr.String() + sprintName(rr.Ns)
   424  }
   425  
   426  // PTR RR. See RFC 1035.
   427  type PTR struct {
   428  	Hdr RR_Header
   429  	Ptr string `dns:"cdomain-name"`
   430  }
   431  
   432  func (rr *PTR) String() string {
   433  	return rr.Hdr.String() + sprintName(rr.Ptr)
   434  }
   435  
   436  // RP RR. See RFC 1138, Section 2.2.
   437  type RP struct {
   438  	Hdr  RR_Header
   439  	Mbox string `dns:"domain-name"`
   440  	Txt  string `dns:"domain-name"`
   441  }
   442  
   443  func (rr *RP) String() string {
   444  	return rr.Hdr.String() + sprintName(rr.Mbox) + " " + sprintName(rr.Txt)
   445  }
   446  
   447  // SOA RR. See RFC 1035.
   448  type SOA struct {
   449  	Hdr     RR_Header
   450  	Ns      string `dns:"cdomain-name"`
   451  	Mbox    string `dns:"cdomain-name"`
   452  	Serial  uint32
   453  	Refresh uint32
   454  	Retry   uint32
   455  	Expire  uint32
   456  	Minttl  uint32
   457  }
   458  
   459  func (rr *SOA) String() string {
   460  	return rr.Hdr.String() + sprintName(rr.Ns) + " " + sprintName(rr.Mbox) +
   461  		" " + strconv.FormatInt(int64(rr.Serial), 10) +
   462  		" " + strconv.FormatInt(int64(rr.Refresh), 10) +
   463  		" " + strconv.FormatInt(int64(rr.Retry), 10) +
   464  		" " + strconv.FormatInt(int64(rr.Expire), 10) +
   465  		" " + strconv.FormatInt(int64(rr.Minttl), 10)
   466  }
   467  
   468  // TXT RR. See RFC 1035.
   469  type TXT struct {
   470  	Hdr RR_Header
   471  	Txt []string `dns:"txt"`
   472  }
   473  
   474  func (rr *TXT) String() string { return rr.Hdr.String() + sprintTxt(rr.Txt) }
   475  
   476  func sprintName(s string) string {
   477  	var dst strings.Builder
   478  
   479  	for i := 0; i < len(s); {
   480  		if s[i] == '.' {
   481  			if dst.Len() != 0 {
   482  				dst.WriteByte('.')
   483  			}
   484  			i++
   485  			continue
   486  		}
   487  
   488  		b, n := nextByte(s, i)
   489  		if n == 0 {
   490  			// Drop "dangling" incomplete escapes.
   491  			if dst.Len() == 0 {
   492  				return s[:i]
   493  			}
   494  			break
   495  		}
   496  		if isDomainNameLabelSpecial(b) {
   497  			if dst.Len() == 0 {
   498  				dst.Grow(len(s) * 2)
   499  				dst.WriteString(s[:i])
   500  			}
   501  			dst.WriteByte('\\')
   502  			dst.WriteByte(b)
   503  		} else if b < ' ' || b > '~' { // unprintable, use \DDD
   504  			if dst.Len() == 0 {
   505  				dst.Grow(len(s) * 2)
   506  				dst.WriteString(s[:i])
   507  			}
   508  			dst.WriteString(escapeByte(b))
   509  		} else {
   510  			if dst.Len() != 0 {
   511  				dst.WriteByte(b)
   512  			}
   513  		}
   514  		i += n
   515  	}
   516  	if dst.Len() == 0 {
   517  		return s
   518  	}
   519  	return dst.String()
   520  }
   521  
   522  func sprintTxtOctet(s string) string {
   523  	var dst strings.Builder
   524  	dst.Grow(2 + len(s))
   525  	dst.WriteByte('"')
   526  	for i := 0; i < len(s); {
   527  		if i+1 < len(s) && s[i] == '\\' && s[i+1] == '.' {
   528  			dst.WriteString(s[i : i+2])
   529  			i += 2
   530  			continue
   531  		}
   532  
   533  		b, n := nextByte(s, i)
   534  		if n == 0 {
   535  			i++ // dangling back slash
   536  		} else {
   537  			writeTXTStringByte(&dst, b)
   538  		}
   539  		i += n
   540  	}
   541  	dst.WriteByte('"')
   542  	return dst.String()
   543  }
   544  
   545  func sprintTxt(txt []string) string {
   546  	var out strings.Builder
   547  	for i, s := range txt {
   548  		out.Grow(3 + len(s))
   549  		if i > 0 {
   550  			out.WriteString(` "`)
   551  		} else {
   552  			out.WriteByte('"')
   553  		}
   554  		for j := 0; j < len(s); {
   555  			b, n := nextByte(s, j)
   556  			if n == 0 {
   557  				break
   558  			}
   559  			writeTXTStringByte(&out, b)
   560  			j += n
   561  		}
   562  		out.WriteByte('"')
   563  	}
   564  	return out.String()
   565  }
   566  
   567  func writeTXTStringByte(s *strings.Builder, b byte) {
   568  	switch {
   569  	case b == '"' || b == '\\':
   570  		s.WriteByte('\\')
   571  		s.WriteByte(b)
   572  	case b < ' ' || b > '~':
   573  		s.WriteString(escapeByte(b))
   574  	default:
   575  		s.WriteByte(b)
   576  	}
   577  }
   578  
   579  const (
   580  	escapedByteSmall = "" +
   581  		`\000\001\002\003\004\005\006\007\008\009` +
   582  		`\010\011\012\013\014\015\016\017\018\019` +
   583  		`\020\021\022\023\024\025\026\027\028\029` +
   584  		`\030\031`
   585  	escapedByteLarge = `\127\128\129` +
   586  		`\130\131\132\133\134\135\136\137\138\139` +
   587  		`\140\141\142\143\144\145\146\147\148\149` +
   588  		`\150\151\152\153\154\155\156\157\158\159` +
   589  		`\160\161\162\163\164\165\166\167\168\169` +
   590  		`\170\171\172\173\174\175\176\177\178\179` +
   591  		`\180\181\182\183\184\185\186\187\188\189` +
   592  		`\190\191\192\193\194\195\196\197\198\199` +
   593  		`\200\201\202\203\204\205\206\207\208\209` +
   594  		`\210\211\212\213\214\215\216\217\218\219` +
   595  		`\220\221\222\223\224\225\226\227\228\229` +
   596  		`\230\231\232\233\234\235\236\237\238\239` +
   597  		`\240\241\242\243\244\245\246\247\248\249` +
   598  		`\250\251\252\253\254\255`
   599  )
   600  
   601  // escapeByte returns the \DDD escaping of b which must
   602  // satisfy b < ' ' || b > '~'.
   603  func escapeByte(b byte) string {
   604  	if b < ' ' {
   605  		return escapedByteSmall[b*4 : b*4+4]
   606  	}
   607  
   608  	b -= '~' + 1
   609  	// The cast here is needed as b*4 may overflow byte.
   610  	return escapedByteLarge[int(b)*4 : int(b)*4+4]
   611  }
   612  
   613  // isDomainNameLabelSpecial returns true if
   614  // a domain name label byte should be prefixed
   615  // with an escaping backslash.
   616  func isDomainNameLabelSpecial(b byte) bool {
   617  	switch b {
   618  	case '.', ' ', '\'', '@', ';', '(', ')', '"', '\\':
   619  		return true
   620  	}
   621  	return false
   622  }
   623  
   624  func nextByte(s string, offset int) (byte, int) {
   625  	if offset >= len(s) {
   626  		return 0, 0
   627  	}
   628  	if s[offset] != '\\' {
   629  		// not an escape sequence
   630  		return s[offset], 1
   631  	}
   632  	switch len(s) - offset {
   633  	case 1: // dangling escape
   634  		return 0, 0
   635  	case 2, 3: // too short to be \ddd
   636  	default: // maybe \ddd
   637  		if isDDD(s[offset+1:]) {
   638  			return dddToByte(s[offset+1:]), 4
   639  		}
   640  	}
   641  	// not \ddd, just an RFC 1035 "quoted" character
   642  	return s[offset+1], 2
   643  }
   644  
   645  // SPF RR. See RFC 4408, Section 3.1.1.
   646  type SPF struct {
   647  	Hdr RR_Header
   648  	Txt []string `dns:"txt"`
   649  }
   650  
   651  func (rr *SPF) String() string { return rr.Hdr.String() + sprintTxt(rr.Txt) }
   652  
   653  // AVC RR. See https://www.iana.org/assignments/dns-parameters/AVC/avc-completed-template.
   654  type AVC struct {
   655  	Hdr RR_Header
   656  	Txt []string `dns:"txt"`
   657  }
   658  
   659  func (rr *AVC) String() string { return rr.Hdr.String() + sprintTxt(rr.Txt) }
   660  
   661  // SRV RR. See RFC 2782.
   662  type SRV struct {
   663  	Hdr      RR_Header
   664  	Priority uint16
   665  	Weight   uint16
   666  	Port     uint16
   667  	Target   string `dns:"domain-name"`
   668  }
   669  
   670  func (rr *SRV) String() string {
   671  	return rr.Hdr.String() +
   672  		strconv.Itoa(int(rr.Priority)) + " " +
   673  		strconv.Itoa(int(rr.Weight)) + " " +
   674  		strconv.Itoa(int(rr.Port)) + " " + sprintName(rr.Target)
   675  }
   676  
   677  // NAPTR RR. See RFC 2915.
   678  type NAPTR struct {
   679  	Hdr         RR_Header
   680  	Order       uint16
   681  	Preference  uint16
   682  	Flags       string
   683  	Service     string
   684  	Regexp      string
   685  	Replacement string `dns:"domain-name"`
   686  }
   687  
   688  func (rr *NAPTR) String() string {
   689  	return rr.Hdr.String() +
   690  		strconv.Itoa(int(rr.Order)) + " " +
   691  		strconv.Itoa(int(rr.Preference)) + " " +
   692  		"\"" + rr.Flags + "\" " +
   693  		"\"" + rr.Service + "\" " +
   694  		"\"" + rr.Regexp + "\" " +
   695  		rr.Replacement
   696  }
   697  
   698  // CERT RR. See RFC 4398.
   699  type CERT struct {
   700  	Hdr         RR_Header
   701  	Type        uint16
   702  	KeyTag      uint16
   703  	Algorithm   uint8
   704  	Certificate string `dns:"base64"`
   705  }
   706  
   707  func (rr *CERT) String() string {
   708  	var (
   709  		ok                  bool
   710  		certtype, algorithm string
   711  	)
   712  	if certtype, ok = CertTypeToString[rr.Type]; !ok {
   713  		certtype = strconv.Itoa(int(rr.Type))
   714  	}
   715  	if algorithm, ok = AlgorithmToString[rr.Algorithm]; !ok {
   716  		algorithm = strconv.Itoa(int(rr.Algorithm))
   717  	}
   718  	return rr.Hdr.String() + certtype +
   719  		" " + strconv.Itoa(int(rr.KeyTag)) +
   720  		" " + algorithm +
   721  		" " + rr.Certificate
   722  }
   723  
   724  // DNAME RR. See RFC 2672.
   725  type DNAME struct {
   726  	Hdr    RR_Header
   727  	Target string `dns:"domain-name"`
   728  }
   729  
   730  func (rr *DNAME) String() string {
   731  	return rr.Hdr.String() + sprintName(rr.Target)
   732  }
   733  
   734  // A RR. See RFC 1035.
   735  type A struct {
   736  	Hdr RR_Header
   737  	A   net.IP `dns:"a"`
   738  }
   739  
   740  func (rr *A) String() string {
   741  	if rr.A == nil {
   742  		return rr.Hdr.String()
   743  	}
   744  	return rr.Hdr.String() + rr.A.String()
   745  }
   746  
   747  // AAAA RR. See RFC 3596.
   748  type AAAA struct {
   749  	Hdr  RR_Header
   750  	AAAA net.IP `dns:"aaaa"`
   751  }
   752  
   753  func (rr *AAAA) String() string {
   754  	if rr.AAAA == nil {
   755  		return rr.Hdr.String()
   756  	}
   757  
   758  	if rr.AAAA.To4() != nil {
   759  		return rr.Hdr.String() + ipv4InIPv6Prefix + rr.AAAA.String()
   760  	}
   761  
   762  	return rr.Hdr.String() + rr.AAAA.String()
   763  }
   764  
   765  // PX RR. See RFC 2163.
   766  type PX struct {
   767  	Hdr        RR_Header
   768  	Preference uint16
   769  	Map822     string `dns:"domain-name"`
   770  	Mapx400    string `dns:"domain-name"`
   771  }
   772  
   773  func (rr *PX) String() string {
   774  	return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) + " " + sprintName(rr.Map822) + " " + sprintName(rr.Mapx400)
   775  }
   776  
   777  // GPOS RR. See RFC 1712.
   778  type GPOS struct {
   779  	Hdr       RR_Header
   780  	Longitude string
   781  	Latitude  string
   782  	Altitude  string
   783  }
   784  
   785  func (rr *GPOS) String() string {
   786  	return rr.Hdr.String() + rr.Longitude + " " + rr.Latitude + " " + rr.Altitude
   787  }
   788  
   789  // LOC RR. See RFC RFC 1876.
   790  type LOC struct {
   791  	Hdr       RR_Header
   792  	Version   uint8
   793  	Size      uint8
   794  	HorizPre  uint8
   795  	VertPre   uint8
   796  	Latitude  uint32
   797  	Longitude uint32
   798  	Altitude  uint32
   799  }
   800  
   801  // cmToM takes a cm value expressed in RFC 1876 SIZE mantissa/exponent
   802  // format and returns a string in m (two decimals for the cm).
   803  func cmToM(x uint8) string {
   804  	m := x & 0xf0 >> 4
   805  	e := x & 0x0f
   806  
   807  	if e < 2 {
   808  		if e == 1 {
   809  			m *= 10
   810  		}
   811  
   812  		return fmt.Sprintf("0.%02d", m)
   813  	}
   814  
   815  	s := fmt.Sprintf("%d", m)
   816  	for e > 2 {
   817  		s += "0"
   818  		e--
   819  	}
   820  	return s
   821  }
   822  
   823  func (rr *LOC) String() string {
   824  	s := rr.Hdr.String()
   825  
   826  	lat := rr.Latitude
   827  	ns := "N"
   828  	if lat > LOC_EQUATOR {
   829  		lat = lat - LOC_EQUATOR
   830  	} else {
   831  		ns = "S"
   832  		lat = LOC_EQUATOR - lat
   833  	}
   834  	h := lat / LOC_DEGREES
   835  	lat = lat % LOC_DEGREES
   836  	m := lat / LOC_HOURS
   837  	lat = lat % LOC_HOURS
   838  	s += fmt.Sprintf("%02d %02d %0.3f %s ", h, m, float64(lat)/1000, ns)
   839  
   840  	lon := rr.Longitude
   841  	ew := "E"
   842  	if lon > LOC_PRIMEMERIDIAN {
   843  		lon = lon - LOC_PRIMEMERIDIAN
   844  	} else {
   845  		ew = "W"
   846  		lon = LOC_PRIMEMERIDIAN - lon
   847  	}
   848  	h = lon / LOC_DEGREES
   849  	lon = lon % LOC_DEGREES
   850  	m = lon / LOC_HOURS
   851  	lon = lon % LOC_HOURS
   852  	s += fmt.Sprintf("%02d %02d %0.3f %s ", h, m, float64(lon)/1000, ew)
   853  
   854  	var alt = float64(rr.Altitude) / 100
   855  	alt -= LOC_ALTITUDEBASE
   856  	if rr.Altitude%100 != 0 {
   857  		s += fmt.Sprintf("%.2fm ", alt)
   858  	} else {
   859  		s += fmt.Sprintf("%.0fm ", alt)
   860  	}
   861  
   862  	s += cmToM(rr.Size) + "m "
   863  	s += cmToM(rr.HorizPre) + "m "
   864  	s += cmToM(rr.VertPre) + "m"
   865  	return s
   866  }
   867  
   868  // SIG RR. See RFC 2535. The SIG RR is identical to RRSIG and nowadays only used for SIG(0), See RFC 2931.
   869  type SIG struct {
   870  	RRSIG
   871  }
   872  
   873  // RRSIG RR. See RFC 4034 and RFC 3755.
   874  type RRSIG struct {
   875  	Hdr         RR_Header
   876  	TypeCovered uint16
   877  	Algorithm   uint8
   878  	Labels      uint8
   879  	OrigTtl     uint32
   880  	Expiration  uint32
   881  	Inception   uint32
   882  	KeyTag      uint16
   883  	SignerName  string `dns:"domain-name"`
   884  	Signature   string `dns:"base64"`
   885  }
   886  
   887  func (rr *RRSIG) String() string {
   888  	s := rr.Hdr.String()
   889  	s += Type(rr.TypeCovered).String()
   890  	s += " " + strconv.Itoa(int(rr.Algorithm)) +
   891  		" " + strconv.Itoa(int(rr.Labels)) +
   892  		" " + strconv.FormatInt(int64(rr.OrigTtl), 10) +
   893  		" " + TimeToString(rr.Expiration) +
   894  		" " + TimeToString(rr.Inception) +
   895  		" " + strconv.Itoa(int(rr.KeyTag)) +
   896  		" " + sprintName(rr.SignerName) +
   897  		" " + rr.Signature
   898  	return s
   899  }
   900  
   901  // NSEC RR. See RFC 4034 and RFC 3755.
   902  type NSEC struct {
   903  	Hdr        RR_Header
   904  	NextDomain string   `dns:"domain-name"`
   905  	TypeBitMap []uint16 `dns:"nsec"`
   906  }
   907  
   908  func (rr *NSEC) String() string {
   909  	s := rr.Hdr.String() + sprintName(rr.NextDomain)
   910  	for _, t := range rr.TypeBitMap {
   911  		s += " " + Type(t).String()
   912  	}
   913  	return s
   914  }
   915  
   916  func (rr *NSEC) len(off int, compression map[string]struct{}) int {
   917  	l := rr.Hdr.len(off, compression)
   918  	l += domainNameLen(rr.NextDomain, off+l, compression, false)
   919  	l += typeBitMapLen(rr.TypeBitMap)
   920  	return l
   921  }
   922  
   923  // DLV RR. See RFC 4431.
   924  type DLV struct{ DS }
   925  
   926  // CDS RR. See RFC 7344.
   927  type CDS struct{ DS }
   928  
   929  // DS RR. See RFC 4034 and RFC 3658.
   930  type DS struct {
   931  	Hdr        RR_Header
   932  	KeyTag     uint16
   933  	Algorithm  uint8
   934  	DigestType uint8
   935  	Digest     string `dns:"hex"`
   936  }
   937  
   938  func (rr *DS) String() string {
   939  	return rr.Hdr.String() + strconv.Itoa(int(rr.KeyTag)) +
   940  		" " + strconv.Itoa(int(rr.Algorithm)) +
   941  		" " + strconv.Itoa(int(rr.DigestType)) +
   942  		" " + strings.ToUpper(rr.Digest)
   943  }
   944  
   945  // KX RR. See RFC 2230.
   946  type KX struct {
   947  	Hdr        RR_Header
   948  	Preference uint16
   949  	Exchanger  string `dns:"domain-name"`
   950  }
   951  
   952  func (rr *KX) String() string {
   953  	return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) +
   954  		" " + sprintName(rr.Exchanger)
   955  }
   956  
   957  // TA RR. See http://www.watson.org/~weiler/INI1999-19.pdf.
   958  type TA struct {
   959  	Hdr        RR_Header
   960  	KeyTag     uint16
   961  	Algorithm  uint8
   962  	DigestType uint8
   963  	Digest     string `dns:"hex"`
   964  }
   965  
   966  func (rr *TA) String() string {
   967  	return rr.Hdr.String() + strconv.Itoa(int(rr.KeyTag)) +
   968  		" " + strconv.Itoa(int(rr.Algorithm)) +
   969  		" " + strconv.Itoa(int(rr.DigestType)) +
   970  		" " + strings.ToUpper(rr.Digest)
   971  }
   972  
   973  // TALINK RR. See https://www.iana.org/assignments/dns-parameters/TALINK/talink-completed-template.
   974  type TALINK struct {
   975  	Hdr          RR_Header
   976  	PreviousName string `dns:"domain-name"`
   977  	NextName     string `dns:"domain-name"`
   978  }
   979  
   980  func (rr *TALINK) String() string {
   981  	return rr.Hdr.String() +
   982  		sprintName(rr.PreviousName) + " " + sprintName(rr.NextName)
   983  }
   984  
   985  // SSHFP RR. See RFC RFC 4255.
   986  type SSHFP struct {
   987  	Hdr         RR_Header
   988  	Algorithm   uint8
   989  	Type        uint8
   990  	FingerPrint string `dns:"hex"`
   991  }
   992  
   993  func (rr *SSHFP) String() string {
   994  	return rr.Hdr.String() + strconv.Itoa(int(rr.Algorithm)) +
   995  		" " + strconv.Itoa(int(rr.Type)) +
   996  		" " + strings.ToUpper(rr.FingerPrint)
   997  }
   998  
   999  // KEY RR. See RFC RFC 2535.
  1000  type KEY struct {
  1001  	DNSKEY
  1002  }
  1003  
  1004  // CDNSKEY RR. See RFC 7344.
  1005  type CDNSKEY struct {
  1006  	DNSKEY
  1007  }
  1008  
  1009  // DNSKEY RR. See RFC 4034 and RFC 3755.
  1010  type DNSKEY struct {
  1011  	Hdr       RR_Header
  1012  	Flags     uint16
  1013  	Protocol  uint8
  1014  	Algorithm uint8
  1015  	PublicKey string `dns:"base64"`
  1016  }
  1017  
  1018  func (rr *DNSKEY) String() string {
  1019  	return rr.Hdr.String() + strconv.Itoa(int(rr.Flags)) +
  1020  		" " + strconv.Itoa(int(rr.Protocol)) +
  1021  		" " + strconv.Itoa(int(rr.Algorithm)) +
  1022  		" " + rr.PublicKey
  1023  }
  1024  
  1025  // IPSECKEY RR. See RFC 4025.
  1026  type IPSECKEY struct {
  1027  	Hdr         RR_Header
  1028  	Precedence  uint8
  1029  	GatewayType uint8
  1030  	Algorithm   uint8
  1031  	GatewayAddr net.IP `dns:"-"` // packing/unpacking/parsing/etc handled together with GatewayHost
  1032  	GatewayHost string `dns:"ipsechost"`
  1033  	PublicKey   string `dns:"base64"`
  1034  }
  1035  
  1036  func (rr *IPSECKEY) String() string {
  1037  	var gateway string
  1038  	switch rr.GatewayType {
  1039  	case IPSECGatewayIPv4, IPSECGatewayIPv6:
  1040  		gateway = rr.GatewayAddr.String()
  1041  	case IPSECGatewayHost:
  1042  		gateway = rr.GatewayHost
  1043  	case IPSECGatewayNone:
  1044  		fallthrough
  1045  	default:
  1046  		gateway = "."
  1047  	}
  1048  
  1049  	return rr.Hdr.String() + strconv.Itoa(int(rr.Precedence)) +
  1050  		" " + strconv.Itoa(int(rr.GatewayType)) +
  1051  		" " + strconv.Itoa(int(rr.Algorithm)) +
  1052  		" " + gateway +
  1053  		" " + rr.PublicKey
  1054  }
  1055  
  1056  // AMTRELAY RR. See RFC 8777.
  1057  type AMTRELAY struct {
  1058  	Hdr         RR_Header
  1059  	Precedence  uint8
  1060  	GatewayType uint8  // discovery is packed in here at bit 0x80
  1061  	GatewayAddr net.IP `dns:"-"` // packing/unpacking/parsing/etc handled together with GatewayHost
  1062  	GatewayHost string `dns:"amtrelayhost"`
  1063  }
  1064  
  1065  func (rr *AMTRELAY) String() string {
  1066  	var gateway string
  1067  	switch rr.GatewayType & 0x7f {
  1068  	case AMTRELAYIPv4, AMTRELAYIPv6:
  1069  		gateway = rr.GatewayAddr.String()
  1070  	case AMTRELAYHost:
  1071  		gateway = rr.GatewayHost
  1072  	case AMTRELAYNone:
  1073  		fallthrough
  1074  	default:
  1075  		gateway = "."
  1076  	}
  1077  	boolS := "0"
  1078  	if rr.GatewayType&0x80 == 0x80 {
  1079  		boolS = "1"
  1080  	}
  1081  
  1082  	return rr.Hdr.String() + strconv.Itoa(int(rr.Precedence)) +
  1083  		" " + boolS +
  1084  		" " + strconv.Itoa(int(rr.GatewayType&0x7f)) +
  1085  		" " + gateway
  1086  }
  1087  
  1088  // RKEY RR. See https://www.iana.org/assignments/dns-parameters/RKEY/rkey-completed-template.
  1089  type RKEY struct {
  1090  	Hdr       RR_Header
  1091  	Flags     uint16
  1092  	Protocol  uint8
  1093  	Algorithm uint8
  1094  	PublicKey string `dns:"base64"`
  1095  }
  1096  
  1097  func (rr *RKEY) String() string {
  1098  	return rr.Hdr.String() + strconv.Itoa(int(rr.Flags)) +
  1099  		" " + strconv.Itoa(int(rr.Protocol)) +
  1100  		" " + strconv.Itoa(int(rr.Algorithm)) +
  1101  		" " + rr.PublicKey
  1102  }
  1103  
  1104  // NSAPPTR RR. See RFC 1348.
  1105  type NSAPPTR struct {
  1106  	Hdr RR_Header
  1107  	Ptr string `dns:"domain-name"`
  1108  }
  1109  
  1110  func (rr *NSAPPTR) String() string { return rr.Hdr.String() + sprintName(rr.Ptr) }
  1111  
  1112  // NSEC3 RR. See RFC 5155.
  1113  type NSEC3 struct {
  1114  	Hdr        RR_Header
  1115  	Hash       uint8
  1116  	Flags      uint8
  1117  	Iterations uint16
  1118  	SaltLength uint8
  1119  	Salt       string `dns:"size-hex:SaltLength"`
  1120  	HashLength uint8
  1121  	NextDomain string   `dns:"size-base32:HashLength"`
  1122  	TypeBitMap []uint16 `dns:"nsec"`
  1123  }
  1124  
  1125  func (rr *NSEC3) String() string {
  1126  	s := rr.Hdr.String()
  1127  	s += strconv.Itoa(int(rr.Hash)) +
  1128  		" " + strconv.Itoa(int(rr.Flags)) +
  1129  		" " + strconv.Itoa(int(rr.Iterations)) +
  1130  		" " + saltToString(rr.Salt) +
  1131  		" " + rr.NextDomain
  1132  	for _, t := range rr.TypeBitMap {
  1133  		s += " " + Type(t).String()
  1134  	}
  1135  	return s
  1136  }
  1137  
  1138  func (rr *NSEC3) len(off int, compression map[string]struct{}) int {
  1139  	l := rr.Hdr.len(off, compression)
  1140  	l += 6 + len(rr.Salt)/2 + 1 + len(rr.NextDomain) + 1
  1141  	l += typeBitMapLen(rr.TypeBitMap)
  1142  	return l
  1143  }
  1144  
  1145  // NSEC3PARAM RR. See RFC 5155.
  1146  type NSEC3PARAM struct {
  1147  	Hdr        RR_Header
  1148  	Hash       uint8
  1149  	Flags      uint8
  1150  	Iterations uint16
  1151  	SaltLength uint8
  1152  	Salt       string `dns:"size-hex:SaltLength"`
  1153  }
  1154  
  1155  func (rr *NSEC3PARAM) String() string {
  1156  	s := rr.Hdr.String()
  1157  	s += strconv.Itoa(int(rr.Hash)) +
  1158  		" " + strconv.Itoa(int(rr.Flags)) +
  1159  		" " + strconv.Itoa(int(rr.Iterations)) +
  1160  		" " + saltToString(rr.Salt)
  1161  	return s
  1162  }
  1163  
  1164  // TKEY RR. See RFC 2930.
  1165  type TKEY struct {
  1166  	Hdr        RR_Header
  1167  	Algorithm  string `dns:"domain-name"`
  1168  	Inception  uint32
  1169  	Expiration uint32
  1170  	Mode       uint16
  1171  	Error      uint16
  1172  	KeySize    uint16
  1173  	Key        string `dns:"size-hex:KeySize"`
  1174  	OtherLen   uint16
  1175  	OtherData  string `dns:"size-hex:OtherLen"`
  1176  }
  1177  
  1178  // TKEY has no official presentation format, but this will suffice.
  1179  func (rr *TKEY) String() string {
  1180  	s := ";" + rr.Hdr.String() +
  1181  		" " + rr.Algorithm +
  1182  		" " + TimeToString(rr.Inception) +
  1183  		" " + TimeToString(rr.Expiration) +
  1184  		" " + strconv.Itoa(int(rr.Mode)) +
  1185  		" " + strconv.Itoa(int(rr.Error)) +
  1186  		" " + strconv.Itoa(int(rr.KeySize)) +
  1187  		" " + rr.Key +
  1188  		" " + strconv.Itoa(int(rr.OtherLen)) +
  1189  		" " + rr.OtherData
  1190  	return s
  1191  }
  1192  
  1193  // RFC3597 represents an unknown/generic RR. See RFC 3597.
  1194  type RFC3597 struct {
  1195  	Hdr   RR_Header
  1196  	Rdata string `dns:"hex"`
  1197  }
  1198  
  1199  func (rr *RFC3597) String() string {
  1200  	// Let's call it a hack
  1201  	s := rfc3597Header(rr.Hdr)
  1202  
  1203  	s += "\\# " + strconv.Itoa(len(rr.Rdata)/2) + " " + rr.Rdata
  1204  	return s
  1205  }
  1206  
  1207  func rfc3597Header(h RR_Header) string {
  1208  	var s string
  1209  
  1210  	s += sprintName(h.Name) + "\t"
  1211  	s += strconv.FormatInt(int64(h.Ttl), 10) + "\t"
  1212  	s += "CLASS" + strconv.Itoa(int(h.Class)) + "\t"
  1213  	s += "TYPE" + strconv.Itoa(int(h.Rrtype)) + "\t"
  1214  	return s
  1215  }
  1216  
  1217  // URI RR. See RFC 7553.
  1218  type URI struct {
  1219  	Hdr      RR_Header
  1220  	Priority uint16
  1221  	Weight   uint16
  1222  	Target   string `dns:"octet"`
  1223  }
  1224  
  1225  // rr.Target to be parsed as a sequence of character encoded octets according to RFC 3986
  1226  func (rr *URI) String() string {
  1227  	return rr.Hdr.String() + strconv.Itoa(int(rr.Priority)) +
  1228  		" " + strconv.Itoa(int(rr.Weight)) + " " + sprintTxtOctet(rr.Target)
  1229  }
  1230  
  1231  // DHCID RR. See RFC 4701.
  1232  type DHCID struct {
  1233  	Hdr    RR_Header
  1234  	Digest string `dns:"base64"`
  1235  }
  1236  
  1237  func (rr *DHCID) String() string { return rr.Hdr.String() + rr.Digest }
  1238  
  1239  // TLSA RR. See RFC 6698.
  1240  type TLSA struct {
  1241  	Hdr          RR_Header
  1242  	Usage        uint8
  1243  	Selector     uint8
  1244  	MatchingType uint8
  1245  	Certificate  string `dns:"hex"`
  1246  }
  1247  
  1248  func (rr *TLSA) String() string {
  1249  	return rr.Hdr.String() +
  1250  		strconv.Itoa(int(rr.Usage)) +
  1251  		" " + strconv.Itoa(int(rr.Selector)) +
  1252  		" " + strconv.Itoa(int(rr.MatchingType)) +
  1253  		" " + rr.Certificate
  1254  }
  1255  
  1256  // SMIMEA RR. See RFC 8162.
  1257  type SMIMEA struct {
  1258  	Hdr          RR_Header
  1259  	Usage        uint8
  1260  	Selector     uint8
  1261  	MatchingType uint8
  1262  	Certificate  string `dns:"hex"`
  1263  }
  1264  
  1265  func (rr *SMIMEA) String() string {
  1266  	s := rr.Hdr.String() +
  1267  		strconv.Itoa(int(rr.Usage)) +
  1268  		" " + strconv.Itoa(int(rr.Selector)) +
  1269  		" " + strconv.Itoa(int(rr.MatchingType))
  1270  
  1271  	// Every Nth char needs a space on this output. If we output
  1272  	// this as one giant line, we can't read it can in because in some cases
  1273  	// the cert length overflows scan.maxTok (2048).
  1274  	sx := splitN(rr.Certificate, 1024) // conservative value here
  1275  	s += " " + strings.Join(sx, " ")
  1276  	return s
  1277  }
  1278  
  1279  // HIP RR. See RFC 8005.
  1280  type HIP struct {
  1281  	Hdr                RR_Header
  1282  	HitLength          uint8
  1283  	PublicKeyAlgorithm uint8
  1284  	PublicKeyLength    uint16
  1285  	Hit                string   `dns:"size-hex:HitLength"`
  1286  	PublicKey          string   `dns:"size-base64:PublicKeyLength"`
  1287  	RendezvousServers  []string `dns:"domain-name"`
  1288  }
  1289  
  1290  func (rr *HIP) String() string {
  1291  	s := rr.Hdr.String() +
  1292  		strconv.Itoa(int(rr.PublicKeyAlgorithm)) +
  1293  		" " + rr.Hit +
  1294  		" " + rr.PublicKey
  1295  	for _, d := range rr.RendezvousServers {
  1296  		s += " " + sprintName(d)
  1297  	}
  1298  	return s
  1299  }
  1300  
  1301  // NINFO RR. See https://www.iana.org/assignments/dns-parameters/NINFO/ninfo-completed-template.
  1302  type NINFO struct {
  1303  	Hdr    RR_Header
  1304  	ZSData []string `dns:"txt"`
  1305  }
  1306  
  1307  func (rr *NINFO) String() string { return rr.Hdr.String() + sprintTxt(rr.ZSData) }
  1308  
  1309  // NID RR. See RFC RFC 6742.
  1310  type NID struct {
  1311  	Hdr        RR_Header
  1312  	Preference uint16
  1313  	NodeID     uint64
  1314  }
  1315  
  1316  func (rr *NID) String() string {
  1317  	s := rr.Hdr.String() + strconv.Itoa(int(rr.Preference))
  1318  	node := fmt.Sprintf("%0.16x", rr.NodeID)
  1319  	s += " " + node[0:4] + ":" + node[4:8] + ":" + node[8:12] + ":" + node[12:16]
  1320  	return s
  1321  }
  1322  
  1323  // L32 RR, See RFC 6742.
  1324  type L32 struct {
  1325  	Hdr        RR_Header
  1326  	Preference uint16
  1327  	Locator32  net.IP `dns:"a"`
  1328  }
  1329  
  1330  func (rr *L32) String() string {
  1331  	if rr.Locator32 == nil {
  1332  		return rr.Hdr.String() + strconv.Itoa(int(rr.Preference))
  1333  	}
  1334  	return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) +
  1335  		" " + rr.Locator32.String()
  1336  }
  1337  
  1338  // L64 RR, See RFC 6742.
  1339  type L64 struct {
  1340  	Hdr        RR_Header
  1341  	Preference uint16
  1342  	Locator64  uint64
  1343  }
  1344  
  1345  func (rr *L64) String() string {
  1346  	s := rr.Hdr.String() + strconv.Itoa(int(rr.Preference))
  1347  	node := fmt.Sprintf("%0.16X", rr.Locator64)
  1348  	s += " " + node[0:4] + ":" + node[4:8] + ":" + node[8:12] + ":" + node[12:16]
  1349  	return s
  1350  }
  1351  
  1352  // LP RR. See RFC 6742.
  1353  type LP struct {
  1354  	Hdr        RR_Header
  1355  	Preference uint16
  1356  	Fqdn       string `dns:"domain-name"`
  1357  }
  1358  
  1359  func (rr *LP) String() string {
  1360  	return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) + " " + sprintName(rr.Fqdn)
  1361  }
  1362  
  1363  // EUI48 RR. See RFC 7043.
  1364  type EUI48 struct {
  1365  	Hdr     RR_Header
  1366  	Address uint64 `dns:"uint48"`
  1367  }
  1368  
  1369  func (rr *EUI48) String() string { return rr.Hdr.String() + euiToString(rr.Address, 48) }
  1370  
  1371  // EUI64 RR. See RFC 7043.
  1372  type EUI64 struct {
  1373  	Hdr     RR_Header
  1374  	Address uint64
  1375  }
  1376  
  1377  func (rr *EUI64) String() string { return rr.Hdr.String() + euiToString(rr.Address, 64) }
  1378  
  1379  // CAA RR. See RFC 6844.
  1380  type CAA struct {
  1381  	Hdr   RR_Header
  1382  	Flag  uint8
  1383  	Tag   string
  1384  	Value string `dns:"octet"`
  1385  }
  1386  
  1387  // rr.Value Is the character-string encoding of the value field as specified in RFC 1035, Section 5.1.
  1388  func (rr *CAA) String() string {
  1389  	return rr.Hdr.String() + strconv.Itoa(int(rr.Flag)) + " " + rr.Tag + " " + sprintTxtOctet(rr.Value)
  1390  }
  1391  
  1392  // UID RR. Deprecated, IANA-Reserved.
  1393  type UID struct {
  1394  	Hdr RR_Header
  1395  	Uid uint32
  1396  }
  1397  
  1398  func (rr *UID) String() string { return rr.Hdr.String() + strconv.FormatInt(int64(rr.Uid), 10) }
  1399  
  1400  // GID RR. Deprecated, IANA-Reserved.
  1401  type GID struct {
  1402  	Hdr RR_Header
  1403  	Gid uint32
  1404  }
  1405  
  1406  func (rr *GID) String() string { return rr.Hdr.String() + strconv.FormatInt(int64(rr.Gid), 10) }
  1407  
  1408  // UINFO RR. Deprecated, IANA-Reserved.
  1409  type UINFO struct {
  1410  	Hdr   RR_Header
  1411  	Uinfo string
  1412  }
  1413  
  1414  func (rr *UINFO) String() string { return rr.Hdr.String() + sprintTxt([]string{rr.Uinfo}) }
  1415  
  1416  // EID RR. See http://ana-3.lcs.mit.edu/~jnc/nimrod/dns.txt.
  1417  type EID struct {
  1418  	Hdr      RR_Header
  1419  	Endpoint string `dns:"hex"`
  1420  }
  1421  
  1422  func (rr *EID) String() string { return rr.Hdr.String() + strings.ToUpper(rr.Endpoint) }
  1423  
  1424  // NIMLOC RR. See http://ana-3.lcs.mit.edu/~jnc/nimrod/dns.txt.
  1425  type NIMLOC struct {
  1426  	Hdr     RR_Header
  1427  	Locator string `dns:"hex"`
  1428  }
  1429  
  1430  func (rr *NIMLOC) String() string { return rr.Hdr.String() + strings.ToUpper(rr.Locator) }
  1431  
  1432  // OPENPGPKEY RR. See RFC 7929.
  1433  type OPENPGPKEY struct {
  1434  	Hdr       RR_Header
  1435  	PublicKey string `dns:"base64"`
  1436  }
  1437  
  1438  func (rr *OPENPGPKEY) String() string { return rr.Hdr.String() + rr.PublicKey }
  1439  
  1440  // CSYNC RR. See RFC 7477.
  1441  type CSYNC struct {
  1442  	Hdr        RR_Header
  1443  	Serial     uint32
  1444  	Flags      uint16
  1445  	TypeBitMap []uint16 `dns:"nsec"`
  1446  }
  1447  
  1448  func (rr *CSYNC) String() string {
  1449  	s := rr.Hdr.String() + strconv.FormatInt(int64(rr.Serial), 10) + " " + strconv.Itoa(int(rr.Flags))
  1450  
  1451  	for _, t := range rr.TypeBitMap {
  1452  		s += " " + Type(t).String()
  1453  	}
  1454  	return s
  1455  }
  1456  
  1457  func (rr *CSYNC) len(off int, compression map[string]struct{}) int {
  1458  	l := rr.Hdr.len(off, compression)
  1459  	l += 4 + 2
  1460  	l += typeBitMapLen(rr.TypeBitMap)
  1461  	return l
  1462  }
  1463  
  1464  // ZONEMD RR, from draft-ietf-dnsop-dns-zone-digest
  1465  type ZONEMD struct {
  1466  	Hdr    RR_Header
  1467  	Serial uint32
  1468  	Scheme uint8
  1469  	Hash   uint8
  1470  	Digest string `dns:"hex"`
  1471  }
  1472  
  1473  func (rr *ZONEMD) String() string {
  1474  	return rr.Hdr.String() +
  1475  		strconv.Itoa(int(rr.Serial)) +
  1476  		" " + strconv.Itoa(int(rr.Scheme)) +
  1477  		" " + strconv.Itoa(int(rr.Hash)) +
  1478  		" " + rr.Digest
  1479  }
  1480  
  1481  // APL RR. See RFC 3123.
  1482  type APL struct {
  1483  	Hdr      RR_Header
  1484  	Prefixes []APLPrefix `dns:"apl"`
  1485  }
  1486  
  1487  // APLPrefix is an address prefix hold by an APL record.
  1488  type APLPrefix struct {
  1489  	Negation bool
  1490  	Network  net.IPNet
  1491  }
  1492  
  1493  // String returns presentation form of the APL record.
  1494  func (rr *APL) String() string {
  1495  	var sb strings.Builder
  1496  	sb.WriteString(rr.Hdr.String())
  1497  	for i, p := range rr.Prefixes {
  1498  		if i > 0 {
  1499  			sb.WriteByte(' ')
  1500  		}
  1501  		sb.WriteString(p.str())
  1502  	}
  1503  	return sb.String()
  1504  }
  1505  
  1506  // str returns presentation form of the APL prefix.
  1507  func (a *APLPrefix) str() string {
  1508  	var sb strings.Builder
  1509  	if a.Negation {
  1510  		sb.WriteByte('!')
  1511  	}
  1512  
  1513  	switch len(a.Network.IP) {
  1514  	case net.IPv4len:
  1515  		sb.WriteByte('1')
  1516  	case net.IPv6len:
  1517  		sb.WriteByte('2')
  1518  	}
  1519  
  1520  	sb.WriteByte(':')
  1521  
  1522  	switch len(a.Network.IP) {
  1523  	case net.IPv4len:
  1524  		sb.WriteString(a.Network.IP.String())
  1525  	case net.IPv6len:
  1526  		// add prefix for IPv4-mapped IPv6
  1527  		if v4 := a.Network.IP.To4(); v4 != nil {
  1528  			sb.WriteString(ipv4InIPv6Prefix)
  1529  		}
  1530  		sb.WriteString(a.Network.IP.String())
  1531  	}
  1532  
  1533  	sb.WriteByte('/')
  1534  
  1535  	prefix, _ := a.Network.Mask.Size()
  1536  	sb.WriteString(strconv.Itoa(prefix))
  1537  
  1538  	return sb.String()
  1539  }
  1540  
  1541  // equals reports whether two APL prefixes are identical.
  1542  func (a *APLPrefix) equals(b *APLPrefix) bool {
  1543  	return a.Negation == b.Negation &&
  1544  		a.Network.IP.Equal(b.Network.IP) &&
  1545  		bytes.Equal(a.Network.Mask, b.Network.Mask)
  1546  }
  1547  
  1548  // copy returns a copy of the APL prefix.
  1549  func (a *APLPrefix) copy() APLPrefix {
  1550  	return APLPrefix{
  1551  		Negation: a.Negation,
  1552  		Network:  copyNet(a.Network),
  1553  	}
  1554  }
  1555  
  1556  // len returns size of the prefix in wire format.
  1557  func (a *APLPrefix) len() int {
  1558  	// 4-byte header and the network address prefix (see Section 4 of RFC 3123)
  1559  	prefix, _ := a.Network.Mask.Size()
  1560  	return 4 + (prefix+7)/8
  1561  }
  1562  
  1563  // TimeToString translates the RRSIG's incep. and expir. times to the
  1564  // string representation used when printing the record.
  1565  // It takes serial arithmetic (RFC 1982) into account.
  1566  func TimeToString(t uint32) string {
  1567  	mod := (int64(t)-time.Now().Unix())/year68 - 1
  1568  	if mod < 0 {
  1569  		mod = 0
  1570  	}
  1571  	ti := time.Unix(int64(t)-mod*year68, 0).UTC()
  1572  	return ti.Format("20060102150405")
  1573  }
  1574  
  1575  // StringToTime translates the RRSIG's incep. and expir. times from
  1576  // string values like "20110403154150" to an 32 bit integer.
  1577  // It takes serial arithmetic (RFC 1982) into account.
  1578  func StringToTime(s string) (uint32, error) {
  1579  	t, err := time.Parse("20060102150405", s)
  1580  	if err != nil {
  1581  		return 0, err
  1582  	}
  1583  	mod := t.Unix()/year68 - 1
  1584  	if mod < 0 {
  1585  		mod = 0
  1586  	}
  1587  	return uint32(t.Unix() - mod*year68), nil
  1588  }
  1589  
  1590  // saltToString converts a NSECX salt to uppercase and returns "-" when it is empty.
  1591  func saltToString(s string) string {
  1592  	if s == "" {
  1593  		return "-"
  1594  	}
  1595  	return strings.ToUpper(s)
  1596  }
  1597  
  1598  func euiToString(eui uint64, bits int) (hex string) {
  1599  	switch bits {
  1600  	case 64:
  1601  		hex = fmt.Sprintf("%16.16x", eui)
  1602  		hex = hex[0:2] + "-" + hex[2:4] + "-" + hex[4:6] + "-" + hex[6:8] +
  1603  			"-" + hex[8:10] + "-" + hex[10:12] + "-" + hex[12:14] + "-" + hex[14:16]
  1604  	case 48:
  1605  		hex = fmt.Sprintf("%12.12x", eui)
  1606  		hex = hex[0:2] + "-" + hex[2:4] + "-" + hex[4:6] + "-" + hex[6:8] +
  1607  			"-" + hex[8:10] + "-" + hex[10:12]
  1608  	}
  1609  	return
  1610  }
  1611  
  1612  // cloneSlice returns a shallow copy of s.
  1613  func cloneSlice[E any, S ~[]E](s S) S {
  1614  	if s == nil {
  1615  		return nil
  1616  	}
  1617  	return append(S(nil), s...)
  1618  }
  1619  
  1620  // copyNet returns a copy of a subnet.
  1621  func copyNet(n net.IPNet) net.IPNet {
  1622  	return net.IPNet{
  1623  		IP:   cloneSlice(n.IP),
  1624  		Mask: cloneSlice(n.Mask),
  1625  	}
  1626  }
  1627  
  1628  // SplitN splits a string into N sized string chunks.
  1629  // This might become an exported function once.
  1630  func splitN(s string, n int) []string {
  1631  	if len(s) < n {
  1632  		return []string{s}
  1633  	}
  1634  	sx := []string{}
  1635  	p, i := 0, n
  1636  	for {
  1637  		if i <= len(s) {
  1638  			sx = append(sx, s[p:i])
  1639  		} else {
  1640  			sx = append(sx, s[p:])
  1641  			break
  1642  
  1643  		}
  1644  		p, i = p+n, i+n
  1645  	}
  1646  
  1647  	return sx
  1648  }
  1649  

View as plain text