Add AVC record (#480)
See https://www.iana.org/assignments/dns-parameters/AVC/avc-completed-template for the template, a new record that is (again) a mirror of the TXT record. For lack of a better name, name the rdata Txt - as we do in SPF and TXT.
This commit is contained in:
parent
89d392d274
commit
767422ac12
|
@ -1509,3 +1509,21 @@ func TestParseURI(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestParseAVC(t *testing.T) {
|
||||||
|
avcs := map[string]string{
|
||||||
|
`example.org. IN AVC "app-name:WOLFGANG|app-class:OAM|business=yes"`: `example.org. 3600 IN AVC "app-name:WOLFGANG|app-class:OAM|business=yes"`,
|
||||||
|
}
|
||||||
|
for avc, o := range avcs {
|
||||||
|
rr, err := NewRR(avc)
|
||||||
|
if err != nil {
|
||||||
|
t.Error("failed to parse RR: ", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if rr.String() != o {
|
||||||
|
t.Errorf("`%s' should be equal to\n`%s', but is `%s'", avc, o, rr.String())
|
||||||
|
} else {
|
||||||
|
t.Logf("RR is OK: `%s'", rr.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
13
scan_rr.go
13
scan_rr.go
|
@ -1807,6 +1807,18 @@ func setSPF(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
|
||||||
return rr, nil, c1
|
return rr, nil, c1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setAVC(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
|
||||||
|
rr := new(AVC)
|
||||||
|
rr.Hdr = h
|
||||||
|
|
||||||
|
s, e, c1 := endingToTxtSlice(c, "bad AVC Txt", f)
|
||||||
|
if e != nil {
|
||||||
|
return nil, e, ""
|
||||||
|
}
|
||||||
|
rr.Txt = s
|
||||||
|
return rr, nil, c1
|
||||||
|
}
|
||||||
|
|
||||||
func setTXT(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
|
func setTXT(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
|
||||||
rr := new(TXT)
|
rr := new(TXT)
|
||||||
rr.Hdr = h
|
rr.Hdr = h
|
||||||
|
@ -2158,6 +2170,7 @@ var typeToparserFunc = map[uint16]parserFunc{
|
||||||
TypeSMIMEA: {setSMIMEA, true},
|
TypeSMIMEA: {setSMIMEA, true},
|
||||||
TypeSOA: {setSOA, false},
|
TypeSOA: {setSOA, false},
|
||||||
TypeSPF: {setSPF, true},
|
TypeSPF: {setSPF, true},
|
||||||
|
TypeAVC: {setAVC, true},
|
||||||
TypeSRV: {setSRV, false},
|
TypeSRV: {setSRV, false},
|
||||||
TypeSSHFP: {setSSHFP, true},
|
TypeSSHFP: {setSSHFP, true},
|
||||||
TypeTALINK: {setTALINK, false},
|
TypeTALINK: {setTALINK, false},
|
||||||
|
|
8
types.go
8
types.go
|
@ -91,6 +91,7 @@ const (
|
||||||
TypeEUI64 uint16 = 109
|
TypeEUI64 uint16 = 109
|
||||||
TypeURI uint16 = 256
|
TypeURI uint16 = 256
|
||||||
TypeCAA uint16 = 257
|
TypeCAA uint16 = 257
|
||||||
|
TypeAVC uint16 = 258
|
||||||
|
|
||||||
TypeTKEY uint16 = 249
|
TypeTKEY uint16 = 249
|
||||||
TypeTSIG uint16 = 250
|
TypeTSIG uint16 = 250
|
||||||
|
@ -530,6 +531,13 @@ type SPF struct {
|
||||||
|
|
||||||
func (rr *SPF) String() string { return rr.Hdr.String() + sprintTxt(rr.Txt) }
|
func (rr *SPF) String() string { return rr.Hdr.String() + sprintTxt(rr.Txt) }
|
||||||
|
|
||||||
|
type AVC struct {
|
||||||
|
Hdr RR_Header
|
||||||
|
Txt []string `dns:"txt"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rr *AVC) String() string { return rr.Hdr.String() + sprintTxt(rr.Txt) }
|
||||||
|
|
||||||
type SRV struct {
|
type SRV struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Priority uint16
|
Priority uint16
|
||||||
|
|
146
zcompress.go
146
zcompress.go
|
@ -5,99 +5,95 @@ package dns
|
||||||
|
|
||||||
func compressionLenHelperType(c map[string]int, r RR) {
|
func compressionLenHelperType(c map[string]int, r RR) {
|
||||||
switch x := r.(type) {
|
switch x := r.(type) {
|
||||||
case *KX:
|
|
||||||
compressionLenHelper(c, x.Exchanger)
|
|
||||||
case *MX:
|
|
||||||
compressionLenHelper(c, x.Mx)
|
|
||||||
case *NSEC:
|
|
||||||
compressionLenHelper(c, x.NextDomain)
|
|
||||||
case *DNAME:
|
|
||||||
compressionLenHelper(c, x.Target)
|
|
||||||
case *HIP:
|
|
||||||
for i := range x.RendezvousServers {
|
|
||||||
compressionLenHelper(c, x.RendezvousServers[i])
|
|
||||||
}
|
|
||||||
case *CNAME:
|
|
||||||
compressionLenHelper(c, x.Target)
|
|
||||||
case *MR:
|
|
||||||
compressionLenHelper(c, x.Mr)
|
|
||||||
case *PX:
|
|
||||||
compressionLenHelper(c, x.Map822)
|
|
||||||
compressionLenHelper(c, x.Mapx400)
|
|
||||||
case *SIG:
|
|
||||||
compressionLenHelper(c, x.SignerName)
|
|
||||||
case *SRV:
|
|
||||||
compressionLenHelper(c, x.Target)
|
|
||||||
case *TALINK:
|
|
||||||
compressionLenHelper(c, x.PreviousName)
|
|
||||||
compressionLenHelper(c, x.NextName)
|
|
||||||
case *LP:
|
|
||||||
compressionLenHelper(c, x.Fqdn)
|
|
||||||
case *NAPTR:
|
|
||||||
compressionLenHelper(c, x.Replacement)
|
|
||||||
case *NS:
|
|
||||||
compressionLenHelper(c, x.Ns)
|
|
||||||
case *RP:
|
|
||||||
compressionLenHelper(c, x.Mbox)
|
|
||||||
compressionLenHelper(c, x.Txt)
|
|
||||||
case *RRSIG:
|
|
||||||
compressionLenHelper(c, x.SignerName)
|
|
||||||
case *TKEY:
|
|
||||||
compressionLenHelper(c, x.Algorithm)
|
|
||||||
case *TSIG:
|
|
||||||
compressionLenHelper(c, x.Algorithm)
|
|
||||||
case *AFSDB:
|
|
||||||
compressionLenHelper(c, x.Hostname)
|
|
||||||
case *MF:
|
|
||||||
compressionLenHelper(c, x.Mf)
|
|
||||||
case *RT:
|
|
||||||
compressionLenHelper(c, x.Host)
|
|
||||||
case *MINFO:
|
|
||||||
compressionLenHelper(c, x.Rmail)
|
|
||||||
compressionLenHelper(c, x.Email)
|
|
||||||
case *PTR:
|
case *PTR:
|
||||||
compressionLenHelper(c, x.Ptr)
|
compressionLenHelper(c, x.Ptr)
|
||||||
case *SOA:
|
case *SOA:
|
||||||
compressionLenHelper(c, x.Ns)
|
compressionLenHelper(c, x.Ns)
|
||||||
compressionLenHelper(c, x.Mbox)
|
compressionLenHelper(c, x.Mbox)
|
||||||
case *MD:
|
case *AFSDB:
|
||||||
compressionLenHelper(c, x.Md)
|
compressionLenHelper(c, x.Hostname)
|
||||||
case *NSAPPTR:
|
case *HIP:
|
||||||
compressionLenHelper(c, x.Ptr)
|
for i := range x.RendezvousServers {
|
||||||
case *MG:
|
compressionLenHelper(c, x.RendezvousServers[i])
|
||||||
compressionLenHelper(c, x.Mg)
|
}
|
||||||
|
case *LP:
|
||||||
|
compressionLenHelper(c, x.Fqdn)
|
||||||
|
case *CNAME:
|
||||||
|
compressionLenHelper(c, x.Target)
|
||||||
case *MB:
|
case *MB:
|
||||||
compressionLenHelper(c, x.Mb)
|
compressionLenHelper(c, x.Mb)
|
||||||
|
case *RP:
|
||||||
|
compressionLenHelper(c, x.Mbox)
|
||||||
|
compressionLenHelper(c, x.Txt)
|
||||||
|
case *RRSIG:
|
||||||
|
compressionLenHelper(c, x.SignerName)
|
||||||
|
case *MF:
|
||||||
|
compressionLenHelper(c, x.Mf)
|
||||||
|
case *MINFO:
|
||||||
|
compressionLenHelper(c, x.Rmail)
|
||||||
|
compressionLenHelper(c, x.Email)
|
||||||
|
case *SIG:
|
||||||
|
compressionLenHelper(c, x.SignerName)
|
||||||
|
case *SRV:
|
||||||
|
compressionLenHelper(c, x.Target)
|
||||||
|
case *TSIG:
|
||||||
|
compressionLenHelper(c, x.Algorithm)
|
||||||
|
case *KX:
|
||||||
|
compressionLenHelper(c, x.Exchanger)
|
||||||
|
case *MG:
|
||||||
|
compressionLenHelper(c, x.Mg)
|
||||||
|
case *NSAPPTR:
|
||||||
|
compressionLenHelper(c, x.Ptr)
|
||||||
|
case *PX:
|
||||||
|
compressionLenHelper(c, x.Map822)
|
||||||
|
compressionLenHelper(c, x.Mapx400)
|
||||||
|
case *DNAME:
|
||||||
|
compressionLenHelper(c, x.Target)
|
||||||
|
case *MR:
|
||||||
|
compressionLenHelper(c, x.Mr)
|
||||||
|
case *MX:
|
||||||
|
compressionLenHelper(c, x.Mx)
|
||||||
|
case *TKEY:
|
||||||
|
compressionLenHelper(c, x.Algorithm)
|
||||||
|
case *NSEC:
|
||||||
|
compressionLenHelper(c, x.NextDomain)
|
||||||
|
case *TALINK:
|
||||||
|
compressionLenHelper(c, x.PreviousName)
|
||||||
|
compressionLenHelper(c, x.NextName)
|
||||||
|
case *MD:
|
||||||
|
compressionLenHelper(c, x.Md)
|
||||||
|
case *NAPTR:
|
||||||
|
compressionLenHelper(c, x.Replacement)
|
||||||
|
case *NS:
|
||||||
|
compressionLenHelper(c, x.Ns)
|
||||||
|
case *RT:
|
||||||
|
compressionLenHelper(c, x.Host)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func compressionLenSearchType(c map[string]int, r RR) (int, bool) {
|
func compressionLenSearchType(c map[string]int, r RR) (int, bool) {
|
||||||
switch x := r.(type) {
|
switch x := r.(type) {
|
||||||
case *MF:
|
|
||||||
k1, ok1 := compressionLenSearch(c, x.Mf)
|
|
||||||
return k1, ok1
|
|
||||||
case *MG:
|
case *MG:
|
||||||
k1, ok1 := compressionLenSearch(c, x.Mg)
|
k1, ok1 := compressionLenSearch(c, x.Mg)
|
||||||
return k1, ok1
|
return k1, ok1
|
||||||
case *MINFO:
|
|
||||||
k1, ok1 := compressionLenSearch(c, x.Rmail)
|
|
||||||
k2, ok2 := compressionLenSearch(c, x.Email)
|
|
||||||
return k1 + k2, ok1 && ok2
|
|
||||||
case *MR:
|
|
||||||
k1, ok1 := compressionLenSearch(c, x.Mr)
|
|
||||||
return k1, ok1
|
|
||||||
case *PTR:
|
case *PTR:
|
||||||
k1, ok1 := compressionLenSearch(c, x.Ptr)
|
k1, ok1 := compressionLenSearch(c, x.Ptr)
|
||||||
return k1, ok1
|
return k1, ok1
|
||||||
case *AFSDB:
|
case *AFSDB:
|
||||||
k1, ok1 := compressionLenSearch(c, x.Hostname)
|
k1, ok1 := compressionLenSearch(c, x.Hostname)
|
||||||
return k1, ok1
|
return k1, ok1
|
||||||
case *CNAME:
|
case *MB:
|
||||||
k1, ok1 := compressionLenSearch(c, x.Target)
|
k1, ok1 := compressionLenSearch(c, x.Mb)
|
||||||
return k1, ok1
|
return k1, ok1
|
||||||
case *MD:
|
case *MD:
|
||||||
k1, ok1 := compressionLenSearch(c, x.Md)
|
k1, ok1 := compressionLenSearch(c, x.Md)
|
||||||
return k1, ok1
|
return k1, ok1
|
||||||
|
case *MF:
|
||||||
|
k1, ok1 := compressionLenSearch(c, x.Mf)
|
||||||
|
return k1, ok1
|
||||||
|
case *NS:
|
||||||
|
k1, ok1 := compressionLenSearch(c, x.Ns)
|
||||||
|
return k1, ok1
|
||||||
case *RT:
|
case *RT:
|
||||||
k1, ok1 := compressionLenSearch(c, x.Host)
|
k1, ok1 := compressionLenSearch(c, x.Host)
|
||||||
return k1, ok1
|
return k1, ok1
|
||||||
|
@ -105,15 +101,19 @@ func compressionLenSearchType(c map[string]int, r RR) (int, bool) {
|
||||||
k1, ok1 := compressionLenSearch(c, x.Ns)
|
k1, ok1 := compressionLenSearch(c, x.Ns)
|
||||||
k2, ok2 := compressionLenSearch(c, x.Mbox)
|
k2, ok2 := compressionLenSearch(c, x.Mbox)
|
||||||
return k1 + k2, ok1 && ok2
|
return k1 + k2, ok1 && ok2
|
||||||
case *MB:
|
case *CNAME:
|
||||||
k1, ok1 := compressionLenSearch(c, x.Mb)
|
k1, ok1 := compressionLenSearch(c, x.Target)
|
||||||
|
return k1, ok1
|
||||||
|
case *MINFO:
|
||||||
|
k1, ok1 := compressionLenSearch(c, x.Rmail)
|
||||||
|
k2, ok2 := compressionLenSearch(c, x.Email)
|
||||||
|
return k1 + k2, ok1 && ok2
|
||||||
|
case *MR:
|
||||||
|
k1, ok1 := compressionLenSearch(c, x.Mr)
|
||||||
return k1, ok1
|
return k1, ok1
|
||||||
case *MX:
|
case *MX:
|
||||||
k1, ok1 := compressionLenSearch(c, x.Mx)
|
k1, ok1 := compressionLenSearch(c, x.Mx)
|
||||||
return k1, ok1
|
return k1, ok1
|
||||||
case *NS:
|
|
||||||
k1, ok1 := compressionLenSearch(c, x.Ns)
|
|
||||||
return k1, ok1
|
|
||||||
}
|
}
|
||||||
return 0, false
|
return 0, false
|
||||||
}
|
}
|
||||||
|
|
32
zmsg.go
32
zmsg.go
|
@ -61,6 +61,20 @@ func (rr *ANY) pack(msg []byte, off int, compression map[string]int, compress bo
|
||||||
return off, nil
|
return off, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (rr *AVC) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
|
||||||
|
off, err := rr.Hdr.pack(msg, off, compression, compress)
|
||||||
|
if err != nil {
|
||||||
|
return off, err
|
||||||
|
}
|
||||||
|
headerEnd := off
|
||||||
|
off, err = packStringTxt(rr.Txt, msg, off)
|
||||||
|
if err != nil {
|
||||||
|
return off, err
|
||||||
|
}
|
||||||
|
rr.Header().Rdlength = uint16(off - headerEnd)
|
||||||
|
return off, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (rr *CAA) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
|
func (rr *CAA) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
|
||||||
off, err := rr.Hdr.pack(msg, off, compression, compress)
|
off, err := rr.Hdr.pack(msg, off, compression, compress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1528,6 +1542,23 @@ func unpackANY(h RR_Header, msg []byte, off int) (RR, int, error) {
|
||||||
return rr, off, err
|
return rr, off, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func unpackAVC(h RR_Header, msg []byte, off int) (RR, int, error) {
|
||||||
|
rr := new(AVC)
|
||||||
|
rr.Hdr = h
|
||||||
|
if noRdata(h) {
|
||||||
|
return rr, off, nil
|
||||||
|
}
|
||||||
|
var err error
|
||||||
|
rdStart := off
|
||||||
|
_ = rdStart
|
||||||
|
|
||||||
|
rr.Txt, off, err = unpackStringTxt(msg, off)
|
||||||
|
if err != nil {
|
||||||
|
return rr, off, err
|
||||||
|
}
|
||||||
|
return rr, off, err
|
||||||
|
}
|
||||||
|
|
||||||
func unpackCAA(h RR_Header, msg []byte, off int) (RR, int, error) {
|
func unpackCAA(h RR_Header, msg []byte, off int) (RR, int, error) {
|
||||||
rr := new(CAA)
|
rr := new(CAA)
|
||||||
rr.Hdr = h
|
rr.Hdr = h
|
||||||
|
@ -3467,6 +3498,7 @@ var typeToUnpack = map[uint16]func(RR_Header, []byte, int) (RR, int, error){
|
||||||
TypeAAAA: unpackAAAA,
|
TypeAAAA: unpackAAAA,
|
||||||
TypeAFSDB: unpackAFSDB,
|
TypeAFSDB: unpackAFSDB,
|
||||||
TypeANY: unpackANY,
|
TypeANY: unpackANY,
|
||||||
|
TypeAVC: unpackAVC,
|
||||||
TypeCAA: unpackCAA,
|
TypeCAA: unpackCAA,
|
||||||
TypeCDNSKEY: unpackCDNSKEY,
|
TypeCDNSKEY: unpackCDNSKEY,
|
||||||
TypeCDS: unpackCDS,
|
TypeCDS: unpackCDS,
|
||||||
|
|
15
ztypes.go
15
ztypes.go
|
@ -14,6 +14,7 @@ var TypeToRR = map[uint16]func() RR{
|
||||||
TypeAAAA: func() RR { return new(AAAA) },
|
TypeAAAA: func() RR { return new(AAAA) },
|
||||||
TypeAFSDB: func() RR { return new(AFSDB) },
|
TypeAFSDB: func() RR { return new(AFSDB) },
|
||||||
TypeANY: func() RR { return new(ANY) },
|
TypeANY: func() RR { return new(ANY) },
|
||||||
|
TypeAVC: func() RR { return new(AVC) },
|
||||||
TypeCAA: func() RR { return new(CAA) },
|
TypeCAA: func() RR { return new(CAA) },
|
||||||
TypeCDNSKEY: func() RR { return new(CDNSKEY) },
|
TypeCDNSKEY: func() RR { return new(CDNSKEY) },
|
||||||
TypeCDS: func() RR { return new(CDS) },
|
TypeCDS: func() RR { return new(CDS) },
|
||||||
|
@ -86,6 +87,7 @@ var TypeToString = map[uint16]string{
|
||||||
TypeAFSDB: "AFSDB",
|
TypeAFSDB: "AFSDB",
|
||||||
TypeANY: "ANY",
|
TypeANY: "ANY",
|
||||||
TypeATMA: "ATMA",
|
TypeATMA: "ATMA",
|
||||||
|
TypeAVC: "AVC",
|
||||||
TypeAXFR: "AXFR",
|
TypeAXFR: "AXFR",
|
||||||
TypeCAA: "CAA",
|
TypeCAA: "CAA",
|
||||||
TypeCDNSKEY: "CDNSKEY",
|
TypeCDNSKEY: "CDNSKEY",
|
||||||
|
@ -166,6 +168,7 @@ func (rr *A) Header() *RR_Header { return &rr.Hdr }
|
||||||
func (rr *AAAA) Header() *RR_Header { return &rr.Hdr }
|
func (rr *AAAA) Header() *RR_Header { return &rr.Hdr }
|
||||||
func (rr *AFSDB) Header() *RR_Header { return &rr.Hdr }
|
func (rr *AFSDB) Header() *RR_Header { return &rr.Hdr }
|
||||||
func (rr *ANY) Header() *RR_Header { return &rr.Hdr }
|
func (rr *ANY) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *AVC) Header() *RR_Header { return &rr.Hdr }
|
||||||
func (rr *CAA) Header() *RR_Header { return &rr.Hdr }
|
func (rr *CAA) Header() *RR_Header { return &rr.Hdr }
|
||||||
func (rr *CDNSKEY) Header() *RR_Header { return &rr.Hdr }
|
func (rr *CDNSKEY) Header() *RR_Header { return &rr.Hdr }
|
||||||
func (rr *CDS) Header() *RR_Header { return &rr.Hdr }
|
func (rr *CDS) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
@ -252,6 +255,13 @@ func (rr *ANY) len() int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len()
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
func (rr *AVC) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
for _, x := range rr.Txt {
|
||||||
|
l += len(x) + 1
|
||||||
|
}
|
||||||
|
return l
|
||||||
|
}
|
||||||
func (rr *CAA) len() int {
|
func (rr *CAA) len() int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len()
|
||||||
l++ // Flag
|
l++ // Flag
|
||||||
|
@ -649,6 +659,11 @@ func (rr *AFSDB) copy() RR {
|
||||||
func (rr *ANY) copy() RR {
|
func (rr *ANY) copy() RR {
|
||||||
return &ANY{*rr.Hdr.copyHeader()}
|
return &ANY{*rr.Hdr.copyHeader()}
|
||||||
}
|
}
|
||||||
|
func (rr *AVC) copy() RR {
|
||||||
|
Txt := make([]string, len(rr.Txt))
|
||||||
|
copy(Txt, rr.Txt)
|
||||||
|
return &AVC{*rr.Hdr.copyHeader(), Txt}
|
||||||
|
}
|
||||||
func (rr *CAA) copy() RR {
|
func (rr *CAA) copy() RR {
|
||||||
return &CAA{*rr.Hdr.copyHeader(), rr.Flag, rr.Tag, rr.Value}
|
return &CAA{*rr.Hdr.copyHeader(), rr.Flag, rr.Tag, rr.Value}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue