1
0
mirror of https://github.com/StackExchange/dnscontrol.git synced 2024-05-11 05:55:12 +00:00

PopulateFromString is back to the original txt parser

This commit is contained in:
Tom Limoncelli
2023-11-17 15:52:26 -05:00
parent 24f72ddfd9
commit 654fcfd752
3 changed files with 75 additions and 33 deletions

View File

@ -97,9 +97,6 @@ func RRtoRC(rr dns.RR, origin string) (RecordConfig, error) {
case *dns.TLSA: case *dns.TLSA:
err = rc.SetTargetTLSA(v.Usage, v.Selector, v.MatchingType, v.Certificate) err = rc.SetTargetTLSA(v.Usage, v.Selector, v.MatchingType, v.Certificate)
case *dns.TXT: case *dns.TXT:
//fmt.Fprintf(os.Stdout, "DEBUG: RRtoRC TXT inbounds=%s q=%q\n", v.Txt, v.Txt)
//d := strings.ReplaceAll(strings.Join(v.Txt, ""), `\"`, `"`)
//fmt.Fprintf(os.Stdout, "DEBUG: RRtoRC TXT decodeds=%s q=%q\n", d, d)
err = rc.SetTargetTXTs(v.Txt) err = rc.SetTargetTXTs(v.Txt)
default: default:
return *rc, fmt.Errorf("rrToRecord: Unimplemented zone record type=%s (%v)", rc.Type, rr) return *rc, fmt.Errorf("rrToRecord: Unimplemented zone record type=%s (%v)", rc.Type, rr)

View File

@ -395,7 +395,7 @@ func (rc *RecordConfig) ToRR() dns.RR {
rr.(*dns.SOA).Expire = rc.SoaExpire rr.(*dns.SOA).Expire = rc.SoaExpire
rr.(*dns.SOA).Minttl = rc.SoaMinttl rr.(*dns.SOA).Minttl = rc.SoaMinttl
case dns.TypeSPF: case dns.TypeSPF:
rr.(*dns.SPF).Txt = []string{rc.target} rr.(*dns.SPF).Txt = rc.GetTargetTXTChunked255()
case dns.TypeSRV: case dns.TypeSRV:
rr.(*dns.SRV).Priority = rc.SrvPriority rr.(*dns.SRV).Priority = rc.SrvPriority
rr.(*dns.SRV).Weight = rc.SrvWeight rr.(*dns.SRV).Weight = rc.SrvWeight
@ -411,7 +411,7 @@ func (rc *RecordConfig) ToRR() dns.RR {
rr.(*dns.TLSA).Selector = rc.TlsaSelector rr.(*dns.TLSA).Selector = rc.TlsaSelector
rr.(*dns.TLSA).Certificate = rc.GetTargetField() rr.(*dns.TLSA).Certificate = rc.GetTargetField()
case dns.TypeTXT: case dns.TypeTXT:
rr.(*dns.TXT).Txt = []string{rc.target} rr.(*dns.TXT).Txt = rc.GetTargetTXTChunked255()
default: default:
panic(fmt.Sprintf("ToRR: Unimplemented rtype %v", rc.Type)) panic(fmt.Sprintf("ToRR: Unimplemented rtype %v", rc.Type))
// We panic so that we quickly find any switch statements // We panic so that we quickly find any switch statements

View File

@ -3,8 +3,6 @@ package models
import ( import (
"fmt" "fmt"
"net" "net"
"github.com/StackExchange/dnscontrol/v4/pkg/txtutil"
) )
// PopulateFromString populates a RecordConfig given a type and string. Many // PopulateFromString populates a RecordConfig given a type and string. Many
@ -17,27 +15,26 @@ import (
// Recommended calling convention: Process the exceptions first, then use the // Recommended calling convention: Process the exceptions first, then use the
// PopulateFromString function for everything else. // PopulateFromString function for everything else.
// //
// rtype := FILL_IN_TYPE // rtype := FILL_IN_TYPE
// var err error // var err error
// rc := &models.RecordConfig{Type: rtype} // rc := &models.RecordConfig{Type: rtype}
// rc.SetLabelFromFQDN(FILL_IN_NAME, origin) // rc.SetLabelFromFQDN(FILL_IN_NAME, origin)
// rc.TTL = uint32(FILL_IN_TTL) // rc.TTL = uint32(FILL_IN_TTL)
// rc.Original = FILL_IN_ORIGINAL // The raw data received from provider (if needed later) // rc.Original = FILL_IN_ORIGINAL // The raw data received from provider (if needed later)
// switch rtype { // switch rtype {
// case "MX": // case "MX":
// // MX priority in a separate field. // // MX priority in a separate field.
// err = rc.SetTargetMX(cr.Priority, target) // err = rc.SetTargetMX(cr.Priority, target)
// case "TXT": // case "TXT":
// // TXT records are stored verbatim; no quoting/escaping to parse. // // TXT records are stored verbatim; no quoting/escaping to parse.
// err = rc.SetTargetTXT(target) // err = rc.SetTargetTXT(target)
// default: // default:
// err = rc.PopulateFromString(rtype, target, origin) // err = rc.PopulateFromString(rtype, target, origin)
// } // }
// if err != nil { // if err != nil {
// return nil, fmt.Errorf("unparsable record type=%q received from PROVDER_NAME: %w", rtype, err) // return nil, fmt.Errorf("unparsable record type=%q received from PROVDER_NAME: %w", rtype, err)
// } // }
// return rc, nil // return rc, nil
func (rc *RecordConfig) PopulateFromString(rtype, contents, origin string) error { func (rc *RecordConfig) PopulateFromString(rtype, contents, origin string) error {
if rc.Type != "" && rc.Type != rtype { if rc.Type != "" && rc.Type != rtype {
panic(fmt.Errorf("assertion failed: rtype already set (%s) (%s)", rtype, rc.Type)) panic(fmt.Errorf("assertion failed: rtype already set (%s) (%s)", rtype, rc.Type))
@ -72,11 +69,59 @@ func (rc *RecordConfig) PopulateFromString(rtype, contents, origin string) error
case "SOA": case "SOA":
return rc.SetTargetSOAString(contents) return rc.SetTargetSOAString(contents)
case "SPF", "TXT": case "SPF", "TXT":
t, err := txtutil.ParseQuoted(contents) return rc.SetTargetTXTs(ParseQuotedTxt(contents))
if err != nil { case "SRV":
return err return rc.SetTargetSRVString(contents)
} case "SSHFP":
return rc.SetTargetTXT(t) return rc.SetTargetSSHFPString(contents)
case "TLSA":
return rc.SetTargetTLSAString(contents)
default:
return fmt.Errorf("unknown rtype (%s) when parsing (%s) domain=(%s)",
rtype, contents, origin)
}
}
func (rc *RecordConfig) PopulateFromStringFunc(rtype, contents, origin string, txtFn func(s string) string) error {
if rc.Type != "" && rc.Type != rtype {
return fmt.Errorf("assertion failed: rtype already set (%s) (%s)", rtype, rc.Type)
}
switch rc.Type = rtype; rtype { // #rtype_variations
case "A":
ip := net.ParseIP(contents)
if ip == nil || ip.To4() == nil {
return fmt.Errorf("invalid IP in A record: %s", contents)
}
return rc.SetTargetIP(ip) // Reformat to canonical form.
case "AAAA":
ip := net.ParseIP(contents)
if ip == nil || ip.To16() == nil {
return fmt.Errorf("invalid IP in AAAA record: %s", contents)
}
return rc.SetTargetIP(ip) // Reformat to canonical form.
case "AKAMAICDN", "ALIAS", "ANAME", "CNAME", "NS", "PTR":
return rc.SetTarget(contents)
case "CAA":
return rc.SetTargetCAAString(contents)
case "DS":
return rc.SetTargetDSString(contents)
case "DHCID":
return rc.SetTarget(contents)
case "LOC":
return rc.SetTargetLOCString(origin, contents)
case "MX":
return rc.SetTargetMXString(contents)
case "NAPTR":
return rc.SetTargetNAPTRString(contents)
case "SOA":
return rc.SetTargetSOAString(contents)
case "SPF", "TXT":
if txtFn == nil {
return rc.SetTargetTXT(contents)
} else {
return rc.SetTargetTXT(txtFn(contents))
}
case "SRV": case "SRV":
return rc.SetTargetSRVString(contents) return rc.SetTargetSRVString(contents)
case "SSHFP": case "SSHFP":