BIND: Improve SOA serial number handling (#651)

* github.com/miekg/dns
* Greatly simplify the logic for handling serial numbers. Related code was all over the place. Now it is abstracted into one testable method makeSoa. This simplifies code in many other places.
* Update docs/_providers/bind.md: Edit old text. Add SOA description.
* SOA records are now treated like any other record internally. You still can't specify them in dnsconfig.js, but that's by design.
* The URL for issue 491 was wrong in many places
* BIND: Clarify GENERATE_ZONEFILE message
This commit is contained in:
Tom Limoncelli 2020-02-23 13:58:49 -05:00 committed by GitHub
parent 3c41a39252
commit 9812ecd9ff
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
60 changed files with 708 additions and 254 deletions

View file

@ -83,7 +83,7 @@ func main() {
switch *flagOutfmt {
case "pretty":
prettyzone.WriteZoneFileRR(os.Stdout, recs, zonename, 0)
prettyzone.WriteZoneFileRR(os.Stdout, recs, zonename)
case "dsl":
fmt.Printf(`D("%s", %s, DnsProvider(%s)`, zonename, *flagRegText, *flagProviderText)
rrFormat(zonename, filename, recs, defTTL, true)

View file

@ -12,7 +12,8 @@ Both of those tasks are different at each site, so they are best done by a local
## Configuration
In your credentials file (`creds.json`), you can specify a `directory` where the provider will look for and create zone files. The default is the `zones` directory where dnscontrol is run.
The BIND provider does not require anything in `creds.json`. However
you can specify a `directory` where the provider will look for and create zone files. The default is the `zones` directory (in the current directory).
{% highlight json %}
{
@ -22,7 +23,9 @@ In your credentials file (`creds.json`), you can specify a `directory` where the
}
{% endhighlight %}
The BIND provider does not require anything in `creds.json`. It does accept some optional metadata via your DNS config when you create the provider:
The BIND accepts some optional metadata via your DNS config when you create the provider:
In this example we set the default SOA settings and NS records.
{% highlight javascript %}
var BIND = NewDnsProvider('bind', 'BIND', {
@ -43,4 +46,24 @@ var BIND = NewDnsProvider('bind', 'BIND', {
})
{% endhighlight %}
If you need to customize your SOA or NS records, you can do so with this setup.
## SOA Records
DNSControl assumes that SOA records are managed by the provider. Most
providers simply generate the SOA record for you and do not permit you
to control it at all. The BIND provider is unique in that it must emulate
what most DNS-as-a-service providers do.
When DNSControl reads a BIND zonefile:
* If there was no SOA record, one is created using the `default_soa`
settings listed above.
* When generating a new zonefile, the SOA serial number is
updated.
DNSControl ties to maintain the serial number as yyyymmddvv. If the
existing serial number is significantly higher it will simply
increment the value by 1.
If you need to edit the SOA fields, the best way is to edit the
zonefile directly, then run `dnscontrol preview` and `dnscontrol push`
as normal.

6
go.mod
View file

@ -48,11 +48,11 @@ require (
github.com/tiramiseb/go-gandi v0.0.0-20200128175142-df8b8e9d23a1
github.com/urfave/cli/v2 v2.1.1
github.com/vultr/govultr v0.2.0
golang.org/x/crypto v0.0.0-20200210222208-86ce3cb69678 // indirect
golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d // indirect
golang.org/x/mod v0.2.0 // indirect
golang.org/x/net v0.0.0-20200202094626-16171245cfb2
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4 // indirect
golang.org/x/sys v0.0.0-20200219091948-cb0a6d8edb6c // indirect
golang.org/x/tools v0.0.0-20200212213243-2ee7536ab1cc // indirect
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 // indirect
google.golang.org/api v0.17.0

10
go.sum
View file

@ -244,8 +244,8 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413 h1:ULYEB3JvPRE/IfO+9uO7vKV/xzVTO7XPAwm8xbf4w2g=
golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200210222208-86ce3cb69678 h1:wCWoJcFExDgyYx2m2hpHgwz8W3+FPdfldvIgzqDIhyg=
golang.org/x/crypto v0.0.0-20200210222208-86ce3cb69678/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d h1:1ZiEyfaQIg3Qh0EoqpwAakHVhecoE5wlSg5GjnafJGw=
golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
@ -273,6 +273,8 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2 h1:CCH4IOTTfewWjGOlSp+zGcjutRKlBEZQ6wTn8ozI/nI=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0 h1:MsuvTghUPjX762sGLnGsxC3HM0B5r83wEtYcYR8/vRs=
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -299,8 +301,8 @@ golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe h1:6fAMxZRR6sl1Uq8U61gxU+kPTs2tR8uOySCbBP7BN/M=
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4 h1:sfkvUWPNGwSV+8/fNqctR5lS2AqCSqYwXdrjCxp/dXo=
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200219091948-cb0a6d8edb6c h1:jceGD5YNJGgGMkJz79agzOln1K9TaZUjv5ird16qniQ=
golang.org/x/sys v0.0.0-20200219091948-cb0a6d8edb6c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=

View file

@ -44,7 +44,7 @@ type DNSProviderConfig struct {
// FIXME(tal): In hindsight, the Nameserver struct is overkill. We
// could have just used []string. Now every provider calls StringsToNameservers
// and ever user calls StringsToNameservers. We should refactor this
// some day. https://github.com/StackExchange/dnscontrol/v2/issues/577
// some day. https://github.com/StackExchange/dnscontrol/issues/577
// Nameserver describes a nameserver.
type Nameserver struct {

View file

@ -42,28 +42,20 @@ func (rc *RecordConfig) String() string {
// Conversions
// RRstoRCs converts []dns.RR to []RecordConfigs.
func RRstoRCs(rrs []dns.RR, origin string, replaceSerial uint32) Records {
func RRstoRCs(rrs []dns.RR, origin string) Records {
rcs := make(Records, 0, len(rrs))
var x uint32
for _, r := range rrs {
var rc RecordConfig
//fmt.Printf("CONVERT: %+v\n", r)
rc, x = RRtoRC(r, origin, replaceSerial)
replaceSerial = x
rc = RRtoRC(r, origin)
rcs = append(rcs, &rc)
}
return rcs
}
// RRtoRC converts dns.RR to RecordConfig
func RRtoRC(rr dns.RR, origin string, replaceSerial uint32) (RecordConfig, uint32) {
func RRtoRC(rr dns.RR, origin string) RecordConfig {
// Convert's dns.RR into our native data type (RecordConfig).
// Records are translated directly with no changes.
// If it is an SOA for the apex domain and
// replaceSerial != 0, change the serial to replaceSerial.
// WARNING(tlim): This assumes SOAs do not have serial=0.
// If one is found, we replace it with serial=1.
var oldSerial, newSerial uint32
header := rr.Header()
rc := new(RecordConfig)
rc.Type = dns.TypeToString[header.Rrtype]
@ -88,20 +80,7 @@ func RRtoRC(rr dns.RR, origin string, replaceSerial uint32) (RecordConfig, uint3
case *dns.NAPTR:
panicInvalid(rc.SetTargetNAPTR(v.Order, v.Preference, v.Flags, v.Service, v.Regexp, v.Replacement))
case *dns.SOA:
oldSerial = v.Serial
if oldSerial == 0 {
// For SOA records, we never return a 0 serial number.
oldSerial = 1
}
newSerial = v.Serial
if rc.GetLabel() == "@" && replaceSerial != 0 {
newSerial = replaceSerial
}
panicInvalid(rc.SetTarget(
fmt.Sprintf("%v %v %v %v %v %v %v",
v.Ns, v.Mbox, newSerial, v.Refresh, v.Retry, v.Expire, v.Minttl),
))
// FIXME(tlim): SOA should be handled by splitting out the fields.
panicInvalid(rc.SetTargetSOA(v.Ns, v.Mbox, v.Serial, v.Refresh, v.Retry, v.Expire, v.Minttl))
case *dns.SRV:
panicInvalid(rc.SetTargetSRV(v.Priority, v.Weight, v.Port, v.Target))
case *dns.SSHFP:
@ -113,7 +92,7 @@ func RRtoRC(rr dns.RR, origin string, replaceSerial uint32) (RecordConfig, uint3
default:
log.Fatalf("rrToRecord: Unimplemented zone record type=%s (%v)\n", rc.Type, rr)
}
return *rc, oldSerial
return *rc
}
func panicInvalid(err error) {

View file

@ -79,7 +79,7 @@ func (dc *DomainConfig) Punycode() error {
if err != nil {
return err
}
case "A", "AAAA", "CAA", "NAPTR", "SSHFP", "TXT", "TLSA":
case "A", "AAAA", "CAA", "NAPTR", "SOA", "SSHFP", "TXT", "TLSA":
// Nothing to do.
default:
msg := fmt.Sprintf("Punycode rtype %v unimplemented", rec.Type)

View file

@ -84,6 +84,12 @@ type RecordConfig struct {
NaptrRegexp string `json:"naptrregexp,omitempty"`
SshfpAlgorithm uint8 `json:"sshfpalgorithm,omitempty"`
SshfpFingerprint uint8 `json:"sshfpfingerprint,omitempty"`
SoaMbox string `json:"soambox,omitempty"`
SoaSerial uint32 `json:"soaserial,omitempty"`
SoaRefresh uint32 `json:"soarefresh,omitempty"`
SoaRetry uint32 `json:"soaretry,omitempty"`
SoaExpire uint32 `json:"soaexpire,omitempty"`
SoaMinttl uint32 `json:"soaminttl,omitempty"`
TlsaUsage uint8 `json:"tlsausage,omitempty"`
TlsaSelector uint8 `json:"tlsaselector,omitempty"`
TlsaMatchingType uint8 `json:"tlsamatchingtype,omitempty"`
@ -181,6 +187,10 @@ func (rc *RecordConfig) GetLabelFQDN() string {
// extraMaps: a list of maps that should be included in the comparison.
func (rc *RecordConfig) ToDiffable(extraMaps ...map[string]string) string {
content := fmt.Sprintf("%v ttl=%d", rc.GetTargetCombined(), rc.TTL)
if rc.Type == "SOA" {
content = fmt.Sprintf("%s %v %d %d %d %d ttl=%d", rc.Target, rc.SoaMbox, rc.SoaRefresh, rc.SoaRetry, rc.SoaExpire, rc.SoaMinttl, rc.TTL)
// SoaSerial is not used in comparison
}
for _, valueMap := range extraMaps {
// sort the extra values map keys to perform a deterministic
// comparison since Golang maps iteration order is not guaranteed
@ -246,15 +256,13 @@ func (rc *RecordConfig) ToRR() dns.RR {
case dns.TypeNS:
rr.(*dns.NS).Ns = rc.GetTargetField()
case dns.TypeSOA:
t := strings.Replace(rc.GetTargetField(), `\ `, ` `, -1)
parts := strings.Fields(t)
rr.(*dns.SOA).Ns = parts[0]
rr.(*dns.SOA).Mbox = parts[1]
rr.(*dns.SOA).Serial = atou32(parts[2])
rr.(*dns.SOA).Refresh = atou32(parts[3])
rr.(*dns.SOA).Retry = atou32(parts[4])
rr.(*dns.SOA).Expire = atou32(parts[5])
rr.(*dns.SOA).Minttl = atou32(parts[6])
rr.(*dns.SOA).Ns = rc.GetTargetField()
rr.(*dns.SOA).Mbox = rc.SoaMbox
rr.(*dns.SOA).Serial = rc.SoaSerial
rr.(*dns.SOA).Refresh = rc.SoaRefresh
rr.(*dns.SOA).Retry = rc.SoaRetry
rr.(*dns.SOA).Expire = rc.SoaExpire
rr.(*dns.SOA).Minttl = rc.SoaMinttl
case dns.TypeSRV:
rr.(*dns.SRV).Priority = rc.SrvPriority
rr.(*dns.SRV).Weight = rc.SrvWeight
@ -318,28 +326,28 @@ func (recs Records) HasRecordTypeName(rtype, name string) bool {
// FQDNMap returns a map of all LabelFQDNs. Useful for making a
// truthtable of labels that exist in Records.
func (r Records) FQDNMap() (m map[string]bool) {
func (recs Records) FQDNMap() (m map[string]bool) {
m = map[string]bool{}
for _, rec := range r {
for _, rec := range recs {
m[rec.GetLabelFQDN()] = true
}
return m
}
// Grouped returns a map of keys to records.
func (r Records) GroupedByKey() map[RecordKey]Records {
// GroupedByKey returns a map of keys to records.
func (recs Records) GroupedByKey() map[RecordKey]Records {
groups := map[RecordKey]Records{}
for _, rec := range r {
for _, rec := range recs {
groups[rec.Key()] = append(groups[rec.Key()], rec)
}
return groups
}
// GroupedByLabel returns a map of keys to records, and their original key order.
func (r Records) GroupedByLabel() ([]string, map[string]Records) {
func (recs Records) GroupedByLabel() ([]string, map[string]Records) {
order := []string{}
groups := map[string]Records{}
for _, rec := range r {
for _, rec := range recs {
if _, found := groups[rec.Name]; !found {
order = append(order, rec.Name)
}
@ -349,10 +357,10 @@ func (r Records) GroupedByLabel() ([]string, map[string]Records) {
}
// GroupedByFQDN returns a map of keys to records, grouped by FQDN.
func (r Records) GroupedByFQDN() ([]string, map[string]Records) {
func (recs Records) GroupedByFQDN() ([]string, map[string]Records) {
order := []string{}
groups := map[string]Records{}
for _, rec := range r {
for _, rec := range recs {
namefqdn := rec.GetLabelFQDN()
if _, found := groups[namefqdn]; !found {
order = append(order, namefqdn)
@ -376,9 +384,16 @@ func downcase(recs []*RecordConfig) {
case "ANAME", "CNAME", "MX", "NS", "PTR", "NAPTR", "SRV":
// These record types have a target that is case insensitive, so we downcase it.
r.Target = strings.ToLower(r.Target)
case "A", "AAAA", "ALIAS", "CAA", "IMPORT_TRANSFORM", "TLSA", "TXT", "SOA", "SSHFP", "CF_REDIRECT", "CF_TEMP_REDIRECT":
case "A", "AAAA", "ALIAS", "CAA", "IMPORT_TRANSFORM", "TLSA", "TXT", "SSHFP", "CF_REDIRECT", "CF_TEMP_REDIRECT":
// These record types have a target that is case sensitive, or is an IP address. We leave them alone.
// Do nothing.
case "SOA":
if r.Target != "DEFAULT_NOT_SET." {
r.Target = strings.ToLower(r.Target) // .Target stores the Ns
}
if r.SoaMbox != "DEFAULT_NOT_SET." {
r.SoaMbox = strings.ToLower(r.SoaMbox)
}
default:
// TODO: we'd like to panic here, but custom record types complicate things.
}

View file

@ -43,6 +43,8 @@ func (r *RecordConfig) PopulateFromString(rtype, contents, origin string) error
return r.SetTargetNAPTRString(contents)
case "SRV":
return r.SetTargetSRVString(contents)
case "SOA":
return r.SetTargetSOAString(contents)
case "SSHFP":
return r.SetTargetSSHFPString(contents)
case "TLSA":

78
models/t_soa.go Normal file
View file

@ -0,0 +1,78 @@
package models
import (
"fmt"
"strconv"
"strings"
)
/*
Providers are not expected to support this record.
Most providers do not support SOA records. They generate them
dynamically behind the scenes. Providers like BIND (which is
software, not SaaS), must handle SOA records and emulate the dynamic
work that providers do.
*/
// SetTargetSOA sets the SOA fields.
func (rc *RecordConfig) SetTargetSOA(ns, mbox string, serial, refresh, retry, expire, minttl uint32) error {
rc.SetTarget(ns) // The NS field is stored as the .Target
rc.SoaMbox = mbox
rc.SoaSerial = serial
rc.SoaRefresh = refresh
rc.SoaRetry = retry
rc.SoaExpire = expire
rc.SoaMinttl = minttl
if rc.Type == "" {
rc.Type = "SOA"
}
if rc.Type != "SOA" {
panic("assertion failed: SetTargetSOA called when .Type is not SOA")
}
return nil
}
// SetTargetSOAStrings is like SetTargetSOA but accepts strings.
func (rc *RecordConfig) SetTargetSOAStrings(ns, mbox, serial, refresh, retry, expire, minttl string) error {
u32serial, err := strconv.ParseUint(serial, 10, 32)
if err != nil {
return fmt.Errorf("SOA serial '%v' is invalid: %w", serial, err)
}
u32refresh, err := strconv.ParseUint(refresh, 10, 32)
if err != nil {
return fmt.Errorf("SOA refresh '%v' is invalid: %w", refresh, err)
}
u32retry, err := strconv.ParseUint(retry, 10, 32)
if err != nil {
return fmt.Errorf("SOA retry '%v' is invalid: %w", retry, err)
}
u32expire, err := strconv.ParseUint(expire, 10, 32)
if err != nil {
return fmt.Errorf("SOA expire '%v' is invalid: %w", expire, err)
}
u32minttl, err := strconv.ParseUint(minttl, 10, 32)
if err != nil {
return fmt.Errorf("SOA minttl '%v' is invalid: %w", minttl, err)
}
return rc.SetTargetSOA(ns, mbox, uint32(u32serial), uint32(u32refresh), uint32(u32retry), uint32(u32expire), uint32(u32minttl))
}
// SetTargetSOAString is like SetTargetSOA but accepts one big string.
func (rc *RecordConfig) SetTargetSOAString(s string) error {
part := strings.Fields(s)
if len(part) != 7 {
return fmt.Errorf("SOA value does not contain 7 fields: (%#v)", s)
}
return rc.SetTargetSOAStrings(part[0], part[1], part[2], part[3], part[4], part[5], part[6])
}

View file

@ -51,7 +51,9 @@ func (rc *RecordConfig) GetTargetCombined() string {
switch rc.Type { // #rtype_variations
case "R53_ALIAS":
// Differentiate between multiple R53_ALIASs on the same label.
return fmt.Sprintf("%s type=%s zone_id=%s", rc.Target, rc.R53Alias["type"], rc.R53Alias["zone_id"])
return fmt.Sprintf("%s atype=%s zone_id=%s", rc.Target, rc.R53Alias["type"], rc.R53Alias["zone_id"])
case "SOA":
return fmt.Sprintf("%s %v %d %d %d %d %d", rc.Target, rc.SoaMbox, rc.SoaSerial, rc.SoaRefresh, rc.SoaRetry, rc.SoaExpire, rc.SoaMinttl)
default:
// Just return the target.
return rc.Target
@ -88,7 +90,7 @@ func (rc *RecordConfig) GetTargetDebug() string {
case "MX":
content += fmt.Sprintf(" pref=%d", rc.MxPreference)
case "SOA":
content = fmt.Sprintf("%s %s %s %d", rc.Type, rc.Name, rc.Target, rc.TTL)
content = fmt.Sprintf("%s ns=%v mbox=%v serial=%v refresh=%v retry=%v expire=%v minttl=%v", rc.Type, rc.Target, rc.SoaMbox, rc.SoaSerial, rc.SoaRefresh, rc.SoaRetry, rc.SoaExpire, rc.SoaMinttl)
case "SRV":
content += fmt.Sprintf(" srvpriority=%d srvweight=%d srvport=%d", rc.SrvPriority, rc.SrvWeight, rc.SrvPort)
case "SSHFP":

View file

@ -3,8 +3,6 @@ package models
import (
"bytes"
"encoding/gob"
"fmt"
"strconv"
)
func copyObj(input interface{}, output interface{}) error {
@ -16,13 +14,3 @@ func copyObj(input interface{}, output interface{}) error {
}
return dec.Decode(output)
}
// atou32 converts a string to uint32 or panics.
// DEPRECATED: This will go away when SOA record handling is rewritten.
func atou32(s string) uint32 {
i64, err := strconv.ParseUint(s, 10, 32)
if err != nil {
panic(fmt.Errorf("atou32 failed (%v) (err=%v", s, err))
}
return uint32(i64)
}

View file

@ -35,7 +35,7 @@ func DetermineNameservers(dc *models.DomainConfig) ([]*models.Nameserver, error)
// FIXME(tlim): Rather than correct broken providers, we should print
// a warning that the provider should be updated to store the FQDN
// with no trailing dot. See also providers/namedotcom/nameservers.go
// Bug https://github.com/StackExchange/dnscontrol/v2/issues/491
// Bug https://github.com/StackExchange/dnscontrol/issues/491
ns = append(ns, nss[i])
}
}

View file

@ -175,6 +175,8 @@ func checkTargets(rec *models.RecordConfig, domain string) (errs []error) {
check(checkTarget(target))
case "ALIAS":
check(checkTarget(target))
case "SOA":
check(checkTarget(target))
case "SRV":
check(checkTarget(target))
case "TXT", "IMPORT_TRANSFORM", "CAA", "SSHFP", "TLSA":
@ -234,7 +236,7 @@ func importTransform(srcDomain, dstDomain *models.DomainConfig, transforms []tra
r := newRec()
r.SetTarget(transformCNAME(r.GetTargetField(), srcDomain.Name, dstDomain.Name))
dstDomain.Records = append(dstDomain.Records, r)
case "MX", "NAPTR", "NS", "SRV", "TXT", "CAA", "TLSA":
case "MX", "NAPTR", "NS", "SOA", "SRV", "TXT", "CAA", "TLSA":
// Not imported.
continue
default:

View file

@ -44,8 +44,8 @@ func mostCommonTTL(records models.Records) uint32 {
}
// WriteZoneFileRR is a helper for when you have []dns.RR instead of models.Records
func WriteZoneFileRR(w io.Writer, records []dns.RR, origin string, serial uint32) error {
return WriteZoneFileRC(w, models.RRstoRCs(records, origin, serial), origin, nil)
func WriteZoneFileRR(w io.Writer, records []dns.RR, origin string) error {
return WriteZoneFileRC(w, models.RRstoRCs(records, origin), origin, nil)
}
// WriteZoneFileRC writes a beautifully formatted zone file.

View file

@ -28,7 +28,7 @@ func parseAndRegen(t *testing.T, buf *bytes.Buffer, expected string) {
}
// Generate it back:
buf2 := &bytes.Buffer{}
WriteZoneFileRR(buf2, parsed, "bosun.org", 99)
WriteZoneFileRR(buf2, parsed, "bosun.org")
// Compare:
if buf2.String() != expected {
@ -48,7 +48,7 @@ func TestMostCommonTtl(t *testing.T) {
// All records are TTL=100
records = nil
records, e = append(records, r1, r1, r1), 100
x := models.RRstoRCs(records, "bosun.org", 99)
x := models.RRstoRCs(records, "bosun.org")
g = mostCommonTTL(x)
if e != g {
t.Fatalf("expected %d; got %d\n", e, g)
@ -57,7 +57,7 @@ func TestMostCommonTtl(t *testing.T) {
// Mixture of TTLs with an obvious winner.
records = nil
records, e = append(records, r1, r2, r2), 200
g = mostCommonTTL(models.RRstoRCs(records, "bosun.org", 99))
g = mostCommonTTL(models.RRstoRCs(records, "bosun.org"))
if e != g {
t.Fatalf("expected %d; got %d\n", e, g)
}
@ -65,7 +65,7 @@ func TestMostCommonTtl(t *testing.T) {
// 3-way tie. Largest TTL should be used.
records = nil
records, e = append(records, r1, r2, r3), 300
g = mostCommonTTL(models.RRstoRCs(records, "bosun.org", 99))
g = mostCommonTTL(models.RRstoRCs(records, "bosun.org"))
if e != g {
t.Fatalf("expected %d; got %d\n", e, g)
}
@ -73,7 +73,7 @@ func TestMostCommonTtl(t *testing.T) {
// NS records are ignored.
records = nil
records, e = append(records, r1, r4, r5), 100
g = mostCommonTTL(models.RRstoRCs(records, "bosun.org", 99))
g = mostCommonTTL(models.RRstoRCs(records, "bosun.org"))
if e != g {
t.Fatalf("expected %d; got %d\n", e, g)
}
@ -87,7 +87,7 @@ func TestWriteZoneFileSimple(t *testing.T) {
r2, _ := dns.NewRR("bosun.org. 300 IN A 192.30.252.154")
r3, _ := dns.NewRR("www.bosun.org. 300 IN CNAME bosun.org.")
buf := &bytes.Buffer{}
WriteZoneFileRR(buf, []dns.RR{r1, r2, r3}, "bosun.org", 99)
WriteZoneFileRR(buf, []dns.RR{r1, r2, r3}, "bosun.org")
expected := `$TTL 300
@ IN A 192.30.252.153
IN A 192.30.252.154
@ -108,7 +108,7 @@ func TestWriteZoneFileSimpleTtl(t *testing.T) {
r3, _ := dns.NewRR("bosun.org. 100 IN A 192.30.252.155")
r4, _ := dns.NewRR("www.bosun.org. 300 IN CNAME bosun.org.")
buf := &bytes.Buffer{}
WriteZoneFileRR(buf, []dns.RR{r1, r2, r3, r4}, "bosun.org", 99)
WriteZoneFileRR(buf, []dns.RR{r1, r2, r3, r4}, "bosun.org")
expected := `$TTL 100
@ IN A 192.30.252.153
IN A 192.30.252.154
@ -138,7 +138,7 @@ func TestWriteZoneFileMx(t *testing.T) {
r8, _ := dns.NewRR("ccc.bosun.org. IN MX 40 aaa.example.com.")
r9, _ := dns.NewRR("ccc.bosun.org. IN MX 1 ttt.example.com.")
buf := &bytes.Buffer{}
WriteZoneFileRR(buf, []dns.RR{r1, r2, r3, r4, r5, r6, r7, r8, r9}, "bosun.org", 99)
WriteZoneFileRR(buf, []dns.RR{r1, r2, r3, r4, r5, r6, r7, r8, r9}, "bosun.org")
if buf.String() != testdataZFMX {
t.Log(buf.String())
t.Log(testdataZFMX)
@ -167,7 +167,7 @@ func TestWriteZoneFileSrv(t *testing.T) {
r4, _ := dns.NewRR(`bosun.org. 300 IN SRV 20 10 5050 foo.com.`)
r5, _ := dns.NewRR(`bosun.org. 300 IN SRV 10 10 5050 foo.com.`)
buf := &bytes.Buffer{}
WriteZoneFileRR(buf, []dns.RR{r1, r2, r3, r4, r5}, "bosun.org", 99)
WriteZoneFileRR(buf, []dns.RR{r1, r2, r3, r4, r5}, "bosun.org")
if buf.String() != testdataZFSRV {
t.Log(buf.String())
t.Log(testdataZFSRV)
@ -190,7 +190,7 @@ func TestWriteZoneFilePtr(t *testing.T) {
r2, _ := dns.NewRR(`bosun.org. 300 IN PTR barney.bosun.org.`)
r3, _ := dns.NewRR(`bosun.org. 300 IN PTR alex.bosun.org.`)
buf := &bytes.Buffer{}
WriteZoneFileRR(buf, []dns.RR{r1, r2, r3}, "bosun.org", 99)
WriteZoneFileRR(buf, []dns.RR{r1, r2, r3}, "bosun.org")
if buf.String() != testdataZFPTR {
t.Log(buf.String())
t.Log(testdataZFPTR)
@ -214,7 +214,7 @@ func TestWriteZoneFileCaa(t *testing.T) {
r5, _ := dns.NewRR(`bosun.org. 300 IN CAA 0 iodef "https://example.net"`)
r6, _ := dns.NewRR(`bosun.org. 300 IN CAA 1 iodef "mailto:example.com"`)
buf := &bytes.Buffer{}
WriteZoneFileRR(buf, []dns.RR{r1, r2, r3, r4, r5, r6}, "bosun.org", 99)
WriteZoneFileRR(buf, []dns.RR{r1, r2, r3, r4, r5, r6}, "bosun.org")
if buf.String() != testdataZFCAA {
t.Log(buf.String())
t.Log(testdataZFCAA)
@ -258,7 +258,7 @@ func TestWriteZoneFileEach(t *testing.T) {
d = append(d, mustNewRR(`sub.bosun.org. 300 IN NS bosun.org.`)) // Must be a label with no other records.
d = append(d, mustNewRR(`x.bosun.org. 300 IN CNAME bosun.org.`)) // Must be a label with no other records.
buf := &bytes.Buffer{}
WriteZoneFileRR(buf, d, "bosun.org", 99)
WriteZoneFileRR(buf, d, "bosun.org")
if buf.String() != testdataZFEach {
t.Log(buf.String())
t.Log(testdataZFEach)
@ -289,7 +289,7 @@ func TestWriteZoneFileSynth(t *testing.T) {
rsynz := &models.RecordConfig{Type: "R53_ALIAS", TTL: 300}
rsynz.SetLabel("zalias", "bosun.org")
recs := models.RRstoRCs([]dns.RR{r1, r2, r3}, "bosun.org", 99)
recs := models.RRstoRCs([]dns.RR{r1, r2, r3}, "bosun.org")
recs = append(recs, rsynm)
recs = append(recs, rsynm)
recs = append(recs, rsynz)
@ -303,10 +303,10 @@ func TestWriteZoneFileSynth(t *testing.T) {
; c4
@ IN A 192.30.252.153
IN A 192.30.252.154
;myalias IN R53_ALIAS type= zone_id=
;myalias IN R53_ALIAS type= zone_id=
;myalias IN R53_ALIAS atype= zone_id=
;myalias IN R53_ALIAS atype= zone_id=
www IN CNAME bosun.org.
;zalias IN R53_ALIAS type= zone_id=
;zalias IN R53_ALIAS atype= zone_id=
`
if buf.String() != expected {
t.Log(buf.String())
@ -343,7 +343,7 @@ func TestWriteZoneFileOrder(t *testing.T) {
}
buf := &bytes.Buffer{}
WriteZoneFileRR(buf, records, "stackoverflow.com", 99)
WriteZoneFileRR(buf, records, "stackoverflow.com")
// Compare
if buf.String() != testdataOrder {
t.Log("Found:")
@ -363,7 +363,7 @@ func TestWriteZoneFileOrder(t *testing.T) {
}
// Generate
buf := &bytes.Buffer{}
WriteZoneFileRR(buf, records, "stackoverflow.com", 99)
WriteZoneFileRR(buf, records, "stackoverflow.com")
// Compare
if buf.String() != testdataOrder {
t.Log(buf.String())

View file

@ -17,7 +17,7 @@ import (
"bytes"
"encoding/json"
"fmt"
"log"
"io/ioutil"
"os"
"path/filepath"
"strings"
@ -70,7 +70,7 @@ func init() {
providers.RegisterDomainServiceProviderType("BIND", initBind, features)
}
// SoaInfo contains the parts of a SOA rtype.
// SoaInfo contains the parts of the default SOA settings.
type SoaInfo struct {
Ns string `json:"master"`
Mbox string `json:"mbox"`
@ -95,38 +95,6 @@ type Bind struct {
zoneFileFound bool // Did the zonefile exist?
}
func makeDefaultSOA(info SoaInfo, origin string) *models.RecordConfig {
// Make a default SOA record in case one isn't found:
soaRec := models.RecordConfig{
Type: "SOA",
}
soaRec.SetLabel("@", origin)
if len(info.Ns) == 0 {
info.Ns = "DEFAULT_NOT_SET."
}
if len(info.Mbox) == 0 {
info.Mbox = "DEFAULT_NOT_SET."
}
if info.Serial == 0 {
info.Serial = 1
}
if info.Refresh == 0 {
info.Refresh = 3600
}
if info.Retry == 0 {
info.Retry = 600
}
if info.Expire == 0 {
info.Expire = 604800
}
if info.Minttl == 0 {
info.Minttl = 1440
}
soaRec.SetTarget(info.String())
return &soaRec
}
// GetNameservers returns the nameservers for a domain.
func (c *Bind) GetNameservers(string) ([]*models.Nameserver, error) {
return c.nameservers, nil
@ -135,7 +103,7 @@ func (c *Bind) GetNameservers(string) ([]*models.Nameserver, error) {
// ListZones returns all the zones in an account
func (c *Bind) ListZones() ([]string, error) {
if _, err := os.Stat(c.directory); os.IsNotExist(err) {
return nil, fmt.Errorf("BIND directory %q does not exist!\n", c.directory)
return nil, fmt.Errorf("directory %q does not exist", c.directory)
}
filenames, err := filepath.Glob(filepath.Join(c.directory, "*.zone"))
@ -152,82 +120,81 @@ func (c *Bind) ListZones() ([]string, error) {
// GetZoneRecords gets the records of a zone and returns them in RecordConfig format.
func (c *Bind) GetZoneRecords(domain string) (models.Records, error) {
// Default SOA record. If we see one in the zone, this will be replaced.
soaRec := makeDefaultSOA(c.DefaultSoa, domain)
foundRecords := models.Records{}
var oldSerial, newSerial uint32
if _, err := os.Stat(c.directory); os.IsNotExist(err) {
fmt.Printf("\nWARNING: BIND directory %q does not exist!\n", c.directory)
}
zonefile := filepath.Join(c.directory, strings.Replace(strings.ToLower(domain), "/", "_", -1)+".zone")
c.zonefile = zonefile
foundFH, err := os.Open(zonefile)
c.zoneFileFound = err == nil
if err != nil && !os.IsNotExist(os.ErrNotExist) {
// Don't whine if the file doesn't exist. However all other
// errors will be reported.
fmt.Printf("Could not read zonefile: %v\n", err)
} else {
for x := range dns.ParseZone(foundFH, domain, zonefile) {
if x.Error != nil {
log.Println("Error in zonefile:", x.Error)
} else {
rec, serial := models.RRtoRC(x.RR, domain, oldSerial)
if serial != 0 && oldSerial != 0 {
log.Fatalf("Multiple SOA records in zonefile: %v\n", zonefile)
}
if serial != 0 {
// This was an SOA record. Update the serial.
oldSerial = serial
newSerial = generateSerial(oldSerial)
// Regenerate with new serial:
*soaRec, _ = models.RRtoRC(x.RR, domain, newSerial)
rec = *soaRec
}
foundRecords = append(foundRecords, &rec)
}
c.zonefile = filepath.Join(
c.directory,
strings.Replace(strings.ToLower(domain), "/", "_", -1)+".zone")
content, err := ioutil.ReadFile(c.zonefile)
if os.IsNotExist(err) {
// If the file doesn't exist, that's not an error. Just informational.
c.zoneFileFound = false
fmt.Fprintf(os.Stderr, "File not found: '%v'\n", c.zonefile)
return nil, nil
}
if err != nil {
return nil, fmt.Errorf("can't open %s: %w", c.zonefile, err)
}
c.zoneFileFound = true
zp := dns.NewZoneParser(strings.NewReader(string(content)), domain, c.zonefile)
for rr, ok := zp.Next(); ok; rr, ok = zp.Next() {
rec := models.RRtoRC(rr, domain)
if rec.Type == "SOA" {
}
foundRecords = append(foundRecords, &rec)
}
// Add SOA record to expected set:
if !foundRecords.HasRecordTypeName("SOA", "@") {
//foundRecords = append(foundRecords, soaRec)
if err := zp.Err(); err != nil {
return nil, fmt.Errorf("error while parsing '%v': %w", c.zonefile, err)
}
return foundRecords, nil
}
// GetDomainCorrections returns a list of corrections to update a domain.
func (c *Bind) GetDomainCorrections(dc *models.DomainConfig) ([]*models.Correction, error) {
dc.Punycode()
// Phase 1: Copy everything to []*models.RecordConfig:
// expectedRecords < dc.Records[i]
// foundRecords < zonefile
//
// Phase 2: Do any manipulations:
// add NS
// manipulate SOA
//
// Phase 3: Convert to []diff.Records and compare:
// expectedDiffRecords < expectedRecords
// foundDiffRecords < foundRecords
// diff.Inc...(foundDiffRecords, expectedDiffRecords )
comments := make([]string, 0, 5)
comments = append(comments,
fmt.Sprintf("generated with dnscontrol %s", time.Now().Format(time.RFC3339)),
)
if dc.AutoDNSSEC {
comments = append(comments, "Automatic DNSSEC signing requested")
}
foundRecords, err := c.GetZoneRecords(dc.Name)
if err != nil {
return nil, err
}
if dc.AutoDNSSEC {
comments = append(comments, "Automatic DNSSEC signing requested")
// Find the SOA records; use them to make or update the desired SOA.
var foundSoa *models.RecordConfig
for _, r := range foundRecords {
if r.Type == "SOA" && r.Name == "@" {
foundSoa = r
break
}
}
var desiredSoa *models.RecordConfig
for _, r := range dc.Records {
if r.Type == "SOA" && r.Name == "@" {
desiredSoa = r
break
}
}
soaRec, nextSerial := makeSoa(dc.Name, &c.DefaultSoa, foundSoa, desiredSoa)
if desiredSoa == nil {
dc.Records = append(dc.Records, soaRec)
desiredSoa = dc.Records[len(dc.Records)-1]
} else {
*desiredSoa = *soaRec
}
// Normalize
@ -257,21 +224,28 @@ func (c *Bind) GetDomainCorrections(dc *models.DomainConfig) ([]*models.Correcti
fmt.Fprintln(buf, i)
}
}
msg := fmt.Sprintf("GENERATE_ZONEFILE: %s\n", dc.Name)
if !c.zoneFileFound {
msg = msg + fmt.Sprintf(" (%d records)\n", len(create))
var msg string
if c.zoneFileFound {
msg = fmt.Sprintf("GENERATE_ZONEFILE: '%s'. Changes:\n%s", dc.Name, buf)
} else {
msg = fmt.Sprintf("GENERATE_ZONEFILE: '%s' (new file with %d records)\n", dc.Name, len(create))
}
msg += buf.String()
corrections := []*models.Correction{}
if changes {
// We only change the serial number if there is a change.
desiredSoa.SoaSerial = nextSerial
corrections = append(corrections,
&models.Correction{
Msg: msg,
F: func() error {
fmt.Printf("CREATING ZONEFILE: %v\n", c.zonefile)
fmt.Printf("WRITING ZONEFILE: %v\n", c.zonefile)
zf, err := os.Create(c.zonefile)
if err != nil {
log.Fatalf("Could not create zonefile: %v", err)
return fmt.Errorf("could not create zonefile: %w", err)
}
// Beware that if there are any fake types, then they will
// be commented out on write, but we don't reverse that when
@ -279,11 +253,11 @@ func (c *Bind) GetDomainCorrections(dc *models.DomainConfig) ([]*models.Correcti
err = prettyzone.WriteZoneFileRC(zf, dc.Records, dc.Name, comments)
if err != nil {
log.Fatalf("WriteZoneFile error: %v\n", err)
return fmt.Errorf("failed WriteZoneFile: %w", err)
}
err = zf.Close()
if err != nil {
log.Fatalf("Closing: %v", err)
return fmt.Errorf("closing: %w", err)
}
return nil
},

View file

@ -61,11 +61,14 @@ func generateSerial(oldSerial uint32) uint32 {
// We never return 0 as the serial number.
newSerial = 1
}
// Assertions that should never happen.
if oldSerial == newSerial {
log.Fatalf("%v: old_serial == new_serial (%v == %v) draft=%v method=%v", original, oldSerial, newSerial, draft, method)
}
if oldSerial > newSerial {
log.Fatalf("%v: old_serial > new_serial (%v > %v) draft=%v method=%v", original, oldSerial, newSerial, draft, method)
}
return newSerial
}

54
providers/bind/soa.go Normal file
View file

@ -0,0 +1,54 @@
package bind
import (
"github.com/StackExchange/dnscontrol/v2/models"
)
func makeSoa(origin string, defSoa *SoaInfo, existing, desired *models.RecordConfig) (*models.RecordConfig, uint32) {
// Create a SOA record. Take data from desired, existing, default,
// or hardcoded defaults.
soaRec := models.RecordConfig{}
soaRec.SetLabel("@", origin)
soaRec.TTL = models.DefaultTTL
if defSoa == nil {
defSoa = &SoaInfo{}
}
if existing == nil {
existing = &models.RecordConfig{}
}
if desired == nil {
desired = &models.RecordConfig{}
}
soaRec.SetTargetSOA(
firstNonNull(desired.GetTargetField(), existing.GetTargetField(), defSoa.Ns, "DEFAULT_NOT_SET."),
firstNonNull(desired.SoaMbox, existing.SoaMbox, defSoa.Mbox, "DEFAULT_NOT_SET."),
firstNonZero(desired.SoaSerial, existing.SoaSerial, defSoa.Serial, 1),
firstNonZero(desired.SoaRefresh, existing.SoaRefresh, defSoa.Refresh, 3600),
firstNonZero(desired.SoaRetry, existing.SoaRetry, defSoa.Retry, 600),
firstNonZero(desired.SoaExpire, existing.SoaExpire, defSoa.Expire, 604800),
firstNonZero(desired.SoaMinttl, existing.SoaMinttl, defSoa.Minttl, 1440),
)
return &soaRec, generateSerial(soaRec.SoaSerial)
}
func firstNonNull(items ...string) string {
for _, item := range items {
if item != "" {
return item
}
}
return "FAIL"
}
func firstNonZero(items ...uint32) uint32 {
for _, item := range items {
if item != 0 {
return item
}
}
return 999
}

147
providers/bind/soa_test.go Normal file
View file

@ -0,0 +1,147 @@
package bind
import (
"fmt"
"testing"
"time"
"github.com/StackExchange/dnscontrol/v2/models"
)
func Test_makeSoa(t *testing.T) {
origin := "example.com"
var tests = []struct {
def *SoaInfo
existing *models.RecordConfig
desired *models.RecordConfig
expectedSoa *models.RecordConfig
expectedSerial uint32
}{
{
// If everything is blank, the hard-coded defaults should kick in.
&SoaInfo{"", "", 0, 0, 0, 0, 0},
&models.RecordConfig{Target: "", SoaMbox: "", SoaSerial: 0, SoaRefresh: 0, SoaRetry: 0, SoaExpire: 0, SoaMinttl: 0},
&models.RecordConfig{Target: "", SoaMbox: "", SoaSerial: 0, SoaRefresh: 0, SoaRetry: 0, SoaExpire: 0, SoaMinttl: 0},
&models.RecordConfig{Target: "DEFAULT_NOT_SET.", SoaMbox: "DEFAULT_NOT_SET.", SoaSerial: 1, SoaRefresh: 3600, SoaRetry: 600, SoaExpire: 604800, SoaMinttl: 1440},
2019022301,
},
{
// If everything is filled, leave the desired values in place.
&SoaInfo{"ns.example.com", "root.example.com", 1, 2, 3, 4, 5},
&models.RecordConfig{Target: "a", SoaMbox: "aa", SoaSerial: 10, SoaRefresh: 11, SoaRetry: 12, SoaExpire: 13, SoaMinttl: 14},
&models.RecordConfig{Target: "b", SoaMbox: "bb", SoaSerial: 15, SoaRefresh: 16, SoaRetry: 17, SoaExpire: 18, SoaMinttl: 19},
&models.RecordConfig{Target: "b", SoaMbox: "bb", SoaSerial: 15, SoaRefresh: 16, SoaRetry: 17, SoaExpire: 18, SoaMinttl: 19},
2019022301,
},
{
// Test incrementing serial.
&SoaInfo{"ns.example.com", "root.example.com", 1, 2, 3, 4, 5},
&models.RecordConfig{Target: "a", SoaMbox: "aa", SoaSerial: 2019022301, SoaRefresh: 11, SoaRetry: 12, SoaExpire: 13, SoaMinttl: 14},
&models.RecordConfig{Target: "b", SoaMbox: "bb", SoaSerial: 0, SoaRefresh: 16, SoaRetry: 17, SoaExpire: 18, SoaMinttl: 19},
&models.RecordConfig{Target: "b", SoaMbox: "bb", SoaSerial: 2019022301, SoaRefresh: 16, SoaRetry: 17, SoaExpire: 18, SoaMinttl: 19},
2019022302,
},
{
// Test incrementing serial_2.
&SoaInfo{"ns.example.com", "root.example.com", 1, 2, 3, 4, 5},
&models.RecordConfig{Target: "a", SoaMbox: "aa", SoaSerial: 0, SoaRefresh: 11, SoaRetry: 12, SoaExpire: 13, SoaMinttl: 14},
&models.RecordConfig{Target: "b", SoaMbox: "bb", SoaSerial: 2019022304, SoaRefresh: 16, SoaRetry: 17, SoaExpire: 18, SoaMinttl: 19},
&models.RecordConfig{Target: "b", SoaMbox: "bb", SoaSerial: 2019022304, SoaRefresh: 16, SoaRetry: 17, SoaExpire: 18, SoaMinttl: 19},
2019022305,
},
{
// If there are gaps in existing or desired, fill in as appropriate.
&SoaInfo{"ns.example.com", "root.example.com", 1, 2, 3, 4, 5},
&models.RecordConfig{Target: "", SoaMbox: "aa", SoaSerial: 0, SoaRefresh: 11, SoaRetry: 0, SoaExpire: 13, SoaMinttl: 0},
&models.RecordConfig{Target: "b", SoaMbox: "", SoaSerial: 15, SoaRefresh: 0, SoaRetry: 17, SoaExpire: 0, SoaMinttl: 19},
&models.RecordConfig{Target: "b", SoaMbox: "aa", SoaSerial: 15, SoaRefresh: 11, SoaRetry: 17, SoaExpire: 13, SoaMinttl: 19},
2019022301,
},
{
// Gaps + existing==nil
&SoaInfo{"ns.example.com", "root.example.com", 1, 2, 3, 4, 5},
nil,
&models.RecordConfig{Target: "b", SoaMbox: "", SoaSerial: 15, SoaRefresh: 0, SoaRetry: 17, SoaExpire: 0, SoaMinttl: 19},
&models.RecordConfig{Target: "b", SoaMbox: "root.example.com", SoaSerial: 15, SoaRefresh: 2, SoaRetry: 17, SoaExpire: 4, SoaMinttl: 19},
2019022301,
},
{
// Gaps + desired==nil
// NB(tom): In the code as of 2020-02-23, desired will never be nil.
&SoaInfo{"ns.example.com", "root.example.com", 1, 2, 3, 4, 5},
&models.RecordConfig{Target: "", SoaMbox: "aa", SoaSerial: 0, SoaRefresh: 11, SoaRetry: 0, SoaExpire: 13, SoaMinttl: 0},
nil,
&models.RecordConfig{Target: "ns.example.com", SoaMbox: "aa", SoaSerial: 1, SoaRefresh: 11, SoaRetry: 3, SoaExpire: 13, SoaMinttl: 5},
2019022301,
},
}
// Fake out the tests so they think today is 2019-02-23
nowFunc = func() time.Time {
fakeToday, _ := time.Parse("20060102", "20190223")
return fakeToday
}
for i, tst := range tests {
if tst.existing != nil {
tst.existing.SetLabel("@", origin)
tst.existing.Type = "SOA"
}
if tst.desired != nil {
tst.desired.SetLabel("@", origin)
tst.desired.Type = "SOA"
}
tst.expectedSoa.SetLabel("@", origin)
tst.expectedSoa.Type = "SOA"
r1, r2 := makeSoa(origin, tst.def, tst.existing, tst.desired)
if !areEqualSoa(r1, tst.expectedSoa) {
t.Fatalf("Test %d soa:\nExpected (%v)\n got (%v)\n", i, tst.expectedSoa.String(), r1.String())
}
if r2 != tst.expectedSerial {
t.Fatalf("Test:%d soa: Expected (%v) got (%v)\n", i, tst.expectedSerial, r2)
}
}
}
func areEqualSoa(r1, r2 *models.RecordConfig) bool {
if r1.NameFQDN != r2.NameFQDN {
fmt.Printf("ERROR: fqdn %q != %q\n", r1.NameFQDN, r2.NameFQDN)
return false
}
if r1.Name != r2.Name {
fmt.Printf("ERROR: name %q != %q\n", r1.Name, r2.Name)
return false
}
if r1.Target != r2.Target {
fmt.Printf("ERROR: target %q != %q\n", r1.Target, r2.Target)
return false
}
if r1.SoaMbox != r2.SoaMbox {
fmt.Printf("ERROR: mbox %v != %v\n", r1.SoaMbox, r2.SoaMbox)
return false
}
if r1.SoaSerial != r2.SoaSerial {
fmt.Printf("ERROR: serial %v != %v\n", r1.SoaSerial, r2.SoaSerial)
return false
}
if r1.SoaRefresh != r2.SoaRefresh {
fmt.Printf("ERROR: refresh %v != %v\n", r1.SoaRefresh, r2.SoaRefresh)
return false
}
if r1.SoaRetry != r2.SoaRetry {
fmt.Printf("ERROR: retry %v != %v\n", r1.SoaRetry, r2.SoaRetry)
return false
}
if r1.SoaExpire != r2.SoaExpire {
fmt.Printf("ERROR: expire %v != %v\n", r1.SoaExpire, r2.SoaExpire)
return false
}
if r1.SoaMinttl != r2.SoaMinttl {
fmt.Printf("ERROR: minttl %v != %v\n", r1.SoaMinttl, r2.SoaMinttl)
return false
}
return true
}

View file

@ -550,7 +550,7 @@ func (c *cfRecord) nativeToRecord(domain string) *models.RecordConfig {
}
rc.SetLabelFromFQDN(c.Name, domain)
// workaround for https://github.com/StackExchange/dnscontrol/v2/issues/446
// workaround for https://github.com/StackExchange/dnscontrol/issues/446
if c.Type == "SPF" {
c.Type = "TXT"
}

View file

@ -54,6 +54,9 @@ func (d *differ) content(r *models.RecordConfig) string {
// its output with r.GetTargetDiffable() to make sure the same
// results are generated. Once we have confidence, this function will go away.
content := fmt.Sprintf("%v ttl=%d", r.GetTargetCombined(), r.TTL)
if r.Type == "SOA" {
content = fmt.Sprintf("%s %v %d %d %d %d ttl=%d", r.Target, r.SoaMbox, r.SoaRefresh, r.SoaRetry, r.SoaExpire, r.SoaMinttl, r.TTL) // SoaSerial is not used in comparison
}
var allMaps []map[string]string
for _, f := range d.extraValues {
// sort the extra values map keys to perform a deterministic
@ -72,6 +75,7 @@ func (d *differ) content(r *models.RecordConfig) string {
}
control := r.ToDiffable(allMaps...)
if control != content {
fmt.Printf("CONTROL=%q CONTENT=%q\n", control, content)
panic("OOPS! control != content")
}
return content

View file

@ -263,7 +263,7 @@ func TestInvalidGlobIgnoredRecord(t *testing.T) {
checkLengthsFull(t, existing, desired, 0, 1, 0, 0, false, []string{"www1", "www2", "[.www3"})
}
// from https://github.com/StackExchange/dnscontrol/v2/issues/552
// from https://github.com/StackExchange/dnscontrol/issues/552
func TestCaas(t *testing.T) {
existing := []*models.RecordConfig{
myRecord("test CAA 1 1.1.1.1"),

View file

@ -57,7 +57,7 @@ func (n *NameCom) GetRegistrarCorrections(dc *models.DomainConfig) ([]*models.Co
expected = append(expected, ns.Name)
// FIXME(tlim): This should store a FQDN with no trailing ".".
// See pkg/nameservers/nameservers.go for details.
// Bug https://github.com/StackExchange/dnscontrol/v2/issues/491
// Bug https://github.com/StackExchange/dnscontrol/issues/491
}
sort.Strings(expected)
expectedNameservers := strings.Join(expected, ",")

View file

@ -19,7 +19,6 @@ package http2 // import "golang.org/x/net/http2"
import (
"bufio"
"crypto/tls"
"errors"
"fmt"
"io"
"net/http"
@ -173,11 +172,6 @@ func (s SettingID) String() string {
return fmt.Sprintf("UNKNOWN_SETTING_%d", uint16(s))
}
var (
errInvalidHeaderFieldName = errors.New("http2: invalid header field name")
errInvalidHeaderFieldValue = errors.New("http2: invalid header field value")
)
// validWireHeaderFieldName reports whether v is a valid header field
// name (key). See httpguts.ValidHeaderName for the base rules.
//

View file

@ -581,13 +581,10 @@ type stream struct {
cancelCtx func()
// owned by serverConn's serve loop:
bodyBytes int64 // body bytes seen so far
declBodyBytes int64 // or -1 if undeclared
flow flow // limits writing from Handler to client
inflow flow // what the client is allowed to POST/etc to us
parent *stream // or nil
numTrailerValues int64
weight uint8
bodyBytes int64 // body bytes seen so far
declBodyBytes int64 // or -1 if undeclared
flow flow // limits writing from Handler to client
inflow flow // what the client is allowed to POST/etc to us
state streamState
resetQueued bool // RST_STREAM queued for write; set by sc.resetStream
gotTrailerHeader bool // HEADER frame for trailers was seen

View file

@ -2198,8 +2198,6 @@ func (rl *clientConnReadLoop) processData(f *DataFrame) error {
return nil
}
var errInvalidTrailers = errors.New("http2: invalid trailers")
func (rl *clientConnReadLoop) endStream(cs *clientStream) {
// TODO: check that any declared content-length matches, like
// server.go's (*stream).endStream method.
@ -2430,7 +2428,6 @@ func (cc *ClientConn) writeStreamReset(streamID uint32, code ErrCode, err error)
var (
errResponseHeaderListSize = errors.New("http2: response header list larger than advertised limit")
errRequestHeaderListSize = errors.New("http2: request header list larger than peer's advertised limit")
errPseudoTrailers = errors.New("http2: invalid pseudo header in trailers")
)
func (cc *ClientConn) logf(format string, args ...interface{}) {

View file

@ -13,16 +13,13 @@ import (
)
var (
errInvalidConn = errors.New("invalid connection")
errMissingAddress = errors.New("missing address")
errMissingHeader = errors.New("missing header")
errNilHeader = errors.New("nil header")
errHeaderTooShort = errors.New("header too short")
errExtHeaderTooShort = errors.New("extension header too short")
errInvalidConnType = errors.New("invalid conn type")
errNoSuchInterface = errors.New("no such interface")
errNoSuchMulticastInterface = errors.New("no such multicast interface")
errNotImplemented = errors.New("not implemented on " + runtime.GOOS + "/" + runtime.GOARCH)
errInvalidConn = errors.New("invalid connection")
errMissingAddress = errors.New("missing address")
errNilHeader = errors.New("nil header")
errHeaderTooShort = errors.New("header too short")
errExtHeaderTooShort = errors.New("extension header too short")
errInvalidConnType = errors.New("invalid conn type")
errNotImplemented = errors.New("not implemented on " + runtime.GOOS + "/" + runtime.GOARCH)
// See https://www.freebsd.org/doc/en/books/porters-handbook/versions.html.
freebsdVersion uint32

View file

@ -7,12 +7,15 @@
package ipv4
import (
"errors"
"net"
"unsafe"
"golang.org/x/net/internal/socket"
)
var errNoSuchInterface = errors.New("no such interface")
func (so *sockOpt) setIPMreq(c *socket.Conn, ifi *net.Interface, grp net.IP) error {
mreq := ipMreq{Multiaddr: [4]byte{grp[0], grp[1], grp[2], grp[3]}}
if err := setIPMreqInterface(&mreq, ifi); err != nil {

View file

@ -15,7 +15,6 @@ var (
errMissingAddress = errors.New("missing address")
errHeaderTooShort = errors.New("header too short")
errInvalidConnType = errors.New("invalid conn type")
errNoSuchInterface = errors.New("no such interface")
errNotImplemented = errors.New("not implemented on " + runtime.GOOS + "/" + runtime.GOARCH)
)

View file

@ -486,7 +486,7 @@ ccflags="$@"
$2 ~ /^TCSET/ ||
$2 ~ /^TC(FLSH|SBRKP?|XONC)$/ ||
$2 !~ "RTF_BITS" &&
$2 ~ /^(IFF|IFT|NET_RT|RTM|RTF|RTV|RTA|RTAX)_/ ||
$2 ~ /^(IFF|IFT|NET_RT|RTM(GRP)?|RTF|RTV|RTA|RTAX)_/ ||
$2 ~ /^BIOC/ ||
$2 ~ /^RUSAGE_(SELF|CHILDREN|THREAD)/ ||
$2 ~ /^RLIMIT_(AS|CORE|CPU|DATA|FSIZE|LOCKS|MEMLOCK|MSGQUEUE|NICE|NOFILE|NPROC|RSS|RTPRIO|RTTIME|SIGPENDING|STACK)|RLIM_INFINITY/ ||

View file

@ -1555,8 +1555,8 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
//sys Acct(path string) (err error)
//sys AddKey(keyType string, description string, payload []byte, ringid int) (id int, err error)
//sys Adjtimex(buf *Timex) (state int, err error)
//sys Capget(hdr *CapUserHeader, data *CapUserData) (err error)
//sys Capset(hdr *CapUserHeader, data *CapUserData) (err error)
//sysnb Capget(hdr *CapUserHeader, data *CapUserData) (err error)
//sysnb Capset(hdr *CapUserHeader, data *CapUserData) (err error)
//sys Chdir(path string) (err error)
//sys Chroot(path string) (err error)
//sys ClockGetres(clockid int32, res *Timespec) (err error)

View file

@ -216,6 +216,10 @@ func (cmsg *Cmsghdr) SetLen(length int) {
cmsg.Len = uint64(length)
}
func InotifyInit() (fd int, err error) {
return InotifyInit1(0)
}
//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error)
func Poll(fds []PollFd, timeout int) (n int, err error) {
@ -224,8 +228,3 @@ func Poll(fds []PollFd, timeout int) (n int, err error) {
}
return poll(&fds[0], len(fds), timeout)
}
func InotifyInit() (fd int, err error) {
return InotifyInit1(0)
}

View file

@ -1938,6 +1938,21 @@ const (
RTF_UP = 0x1
RTF_WINDOW = 0x80
RTF_XRESOLVE = 0x800
RTMGRP_DECnet_IFADDR = 0x1000
RTMGRP_DECnet_ROUTE = 0x4000
RTMGRP_IPV4_IFADDR = 0x10
RTMGRP_IPV4_MROUTE = 0x20
RTMGRP_IPV4_ROUTE = 0x40
RTMGRP_IPV4_RULE = 0x80
RTMGRP_IPV6_IFADDR = 0x100
RTMGRP_IPV6_IFINFO = 0x800
RTMGRP_IPV6_MROUTE = 0x200
RTMGRP_IPV6_PREFIX = 0x20000
RTMGRP_IPV6_ROUTE = 0x400
RTMGRP_LINK = 0x1
RTMGRP_NEIGH = 0x4
RTMGRP_NOTIFY = 0x2
RTMGRP_TC = 0x8
RTM_BASE = 0x10
RTM_DELACTION = 0x31
RTM_DELADDR = 0x15

View file

@ -1939,6 +1939,21 @@ const (
RTF_UP = 0x1
RTF_WINDOW = 0x80
RTF_XRESOLVE = 0x800
RTMGRP_DECnet_IFADDR = 0x1000
RTMGRP_DECnet_ROUTE = 0x4000
RTMGRP_IPV4_IFADDR = 0x10
RTMGRP_IPV4_MROUTE = 0x20
RTMGRP_IPV4_ROUTE = 0x40
RTMGRP_IPV4_RULE = 0x80
RTMGRP_IPV6_IFADDR = 0x100
RTMGRP_IPV6_IFINFO = 0x800
RTMGRP_IPV6_MROUTE = 0x200
RTMGRP_IPV6_PREFIX = 0x20000
RTMGRP_IPV6_ROUTE = 0x400
RTMGRP_LINK = 0x1
RTMGRP_NEIGH = 0x4
RTMGRP_NOTIFY = 0x2
RTMGRP_TC = 0x8
RTM_BASE = 0x10
RTM_DELACTION = 0x31
RTM_DELADDR = 0x15

View file

@ -1945,6 +1945,21 @@ const (
RTF_UP = 0x1
RTF_WINDOW = 0x80
RTF_XRESOLVE = 0x800
RTMGRP_DECnet_IFADDR = 0x1000
RTMGRP_DECnet_ROUTE = 0x4000
RTMGRP_IPV4_IFADDR = 0x10
RTMGRP_IPV4_MROUTE = 0x20
RTMGRP_IPV4_ROUTE = 0x40
RTMGRP_IPV4_RULE = 0x80
RTMGRP_IPV6_IFADDR = 0x100
RTMGRP_IPV6_IFINFO = 0x800
RTMGRP_IPV6_MROUTE = 0x200
RTMGRP_IPV6_PREFIX = 0x20000
RTMGRP_IPV6_ROUTE = 0x400
RTMGRP_LINK = 0x1
RTMGRP_NEIGH = 0x4
RTMGRP_NOTIFY = 0x2
RTMGRP_TC = 0x8
RTM_BASE = 0x10
RTM_DELACTION = 0x31
RTM_DELADDR = 0x15

View file

@ -1931,6 +1931,21 @@ const (
RTF_UP = 0x1
RTF_WINDOW = 0x80
RTF_XRESOLVE = 0x800
RTMGRP_DECnet_IFADDR = 0x1000
RTMGRP_DECnet_ROUTE = 0x4000
RTMGRP_IPV4_IFADDR = 0x10
RTMGRP_IPV4_MROUTE = 0x20
RTMGRP_IPV4_ROUTE = 0x40
RTMGRP_IPV4_RULE = 0x80
RTMGRP_IPV6_IFADDR = 0x100
RTMGRP_IPV6_IFINFO = 0x800
RTMGRP_IPV6_MROUTE = 0x200
RTMGRP_IPV6_PREFIX = 0x20000
RTMGRP_IPV6_ROUTE = 0x400
RTMGRP_LINK = 0x1
RTMGRP_NEIGH = 0x4
RTMGRP_NOTIFY = 0x2
RTMGRP_TC = 0x8
RTM_BASE = 0x10
RTM_DELACTION = 0x31
RTM_DELADDR = 0x15

View file

@ -1938,6 +1938,21 @@ const (
RTF_UP = 0x1
RTF_WINDOW = 0x80
RTF_XRESOLVE = 0x800
RTMGRP_DECnet_IFADDR = 0x1000
RTMGRP_DECnet_ROUTE = 0x4000
RTMGRP_IPV4_IFADDR = 0x10
RTMGRP_IPV4_MROUTE = 0x20
RTMGRP_IPV4_ROUTE = 0x40
RTMGRP_IPV4_RULE = 0x80
RTMGRP_IPV6_IFADDR = 0x100
RTMGRP_IPV6_IFINFO = 0x800
RTMGRP_IPV6_MROUTE = 0x200
RTMGRP_IPV6_PREFIX = 0x20000
RTMGRP_IPV6_ROUTE = 0x400
RTMGRP_LINK = 0x1
RTMGRP_NEIGH = 0x4
RTMGRP_NOTIFY = 0x2
RTMGRP_TC = 0x8
RTM_BASE = 0x10
RTM_DELACTION = 0x31
RTM_DELADDR = 0x15

View file

@ -1938,6 +1938,21 @@ const (
RTF_UP = 0x1
RTF_WINDOW = 0x80
RTF_XRESOLVE = 0x800
RTMGRP_DECnet_IFADDR = 0x1000
RTMGRP_DECnet_ROUTE = 0x4000
RTMGRP_IPV4_IFADDR = 0x10
RTMGRP_IPV4_MROUTE = 0x20
RTMGRP_IPV4_ROUTE = 0x40
RTMGRP_IPV4_RULE = 0x80
RTMGRP_IPV6_IFADDR = 0x100
RTMGRP_IPV6_IFINFO = 0x800
RTMGRP_IPV6_MROUTE = 0x200
RTMGRP_IPV6_PREFIX = 0x20000
RTMGRP_IPV6_ROUTE = 0x400
RTMGRP_LINK = 0x1
RTMGRP_NEIGH = 0x4
RTMGRP_NOTIFY = 0x2
RTMGRP_TC = 0x8
RTM_BASE = 0x10
RTM_DELACTION = 0x31
RTM_DELADDR = 0x15

View file

@ -1938,6 +1938,21 @@ const (
RTF_UP = 0x1
RTF_WINDOW = 0x80
RTF_XRESOLVE = 0x800
RTMGRP_DECnet_IFADDR = 0x1000
RTMGRP_DECnet_ROUTE = 0x4000
RTMGRP_IPV4_IFADDR = 0x10
RTMGRP_IPV4_MROUTE = 0x20
RTMGRP_IPV4_ROUTE = 0x40
RTMGRP_IPV4_RULE = 0x80
RTMGRP_IPV6_IFADDR = 0x100
RTMGRP_IPV6_IFINFO = 0x800
RTMGRP_IPV6_MROUTE = 0x200
RTMGRP_IPV6_PREFIX = 0x20000
RTMGRP_IPV6_ROUTE = 0x400
RTMGRP_LINK = 0x1
RTMGRP_NEIGH = 0x4
RTMGRP_NOTIFY = 0x2
RTMGRP_TC = 0x8
RTM_BASE = 0x10
RTM_DELACTION = 0x31
RTM_DELADDR = 0x15

View file

@ -1938,6 +1938,21 @@ const (
RTF_UP = 0x1
RTF_WINDOW = 0x80
RTF_XRESOLVE = 0x800
RTMGRP_DECnet_IFADDR = 0x1000
RTMGRP_DECnet_ROUTE = 0x4000
RTMGRP_IPV4_IFADDR = 0x10
RTMGRP_IPV4_MROUTE = 0x20
RTMGRP_IPV4_ROUTE = 0x40
RTMGRP_IPV4_RULE = 0x80
RTMGRP_IPV6_IFADDR = 0x100
RTMGRP_IPV6_IFINFO = 0x800
RTMGRP_IPV6_MROUTE = 0x200
RTMGRP_IPV6_PREFIX = 0x20000
RTMGRP_IPV6_ROUTE = 0x400
RTMGRP_LINK = 0x1
RTMGRP_NEIGH = 0x4
RTMGRP_NOTIFY = 0x2
RTMGRP_TC = 0x8
RTM_BASE = 0x10
RTM_DELACTION = 0x31
RTM_DELADDR = 0x15

View file

@ -1997,6 +1997,21 @@ const (
RTF_UP = 0x1
RTF_WINDOW = 0x80
RTF_XRESOLVE = 0x800
RTMGRP_DECnet_IFADDR = 0x1000
RTMGRP_DECnet_ROUTE = 0x4000
RTMGRP_IPV4_IFADDR = 0x10
RTMGRP_IPV4_MROUTE = 0x20
RTMGRP_IPV4_ROUTE = 0x40
RTMGRP_IPV4_RULE = 0x80
RTMGRP_IPV6_IFADDR = 0x100
RTMGRP_IPV6_IFINFO = 0x800
RTMGRP_IPV6_MROUTE = 0x200
RTMGRP_IPV6_PREFIX = 0x20000
RTMGRP_IPV6_ROUTE = 0x400
RTMGRP_LINK = 0x1
RTMGRP_NEIGH = 0x4
RTMGRP_NOTIFY = 0x2
RTMGRP_TC = 0x8
RTM_BASE = 0x10
RTM_DELACTION = 0x31
RTM_DELADDR = 0x15

View file

@ -1997,6 +1997,21 @@ const (
RTF_UP = 0x1
RTF_WINDOW = 0x80
RTF_XRESOLVE = 0x800
RTMGRP_DECnet_IFADDR = 0x1000
RTMGRP_DECnet_ROUTE = 0x4000
RTMGRP_IPV4_IFADDR = 0x10
RTMGRP_IPV4_MROUTE = 0x20
RTMGRP_IPV4_ROUTE = 0x40
RTMGRP_IPV4_RULE = 0x80
RTMGRP_IPV6_IFADDR = 0x100
RTMGRP_IPV6_IFINFO = 0x800
RTMGRP_IPV6_MROUTE = 0x200
RTMGRP_IPV6_PREFIX = 0x20000
RTMGRP_IPV6_ROUTE = 0x400
RTMGRP_LINK = 0x1
RTMGRP_NEIGH = 0x4
RTMGRP_NOTIFY = 0x2
RTMGRP_TC = 0x8
RTM_BASE = 0x10
RTM_DELACTION = 0x31
RTM_DELADDR = 0x15

View file

@ -1926,6 +1926,21 @@ const (
RTF_UP = 0x1
RTF_WINDOW = 0x80
RTF_XRESOLVE = 0x800
RTMGRP_DECnet_IFADDR = 0x1000
RTMGRP_DECnet_ROUTE = 0x4000
RTMGRP_IPV4_IFADDR = 0x10
RTMGRP_IPV4_MROUTE = 0x20
RTMGRP_IPV4_ROUTE = 0x40
RTMGRP_IPV4_RULE = 0x80
RTMGRP_IPV6_IFADDR = 0x100
RTMGRP_IPV6_IFINFO = 0x800
RTMGRP_IPV6_MROUTE = 0x200
RTMGRP_IPV6_PREFIX = 0x20000
RTMGRP_IPV6_ROUTE = 0x400
RTMGRP_LINK = 0x1
RTMGRP_NEIGH = 0x4
RTMGRP_NOTIFY = 0x2
RTMGRP_TC = 0x8
RTM_BASE = 0x10
RTM_DELACTION = 0x31
RTM_DELADDR = 0x15

View file

@ -1999,6 +1999,21 @@ const (
RTF_UP = 0x1
RTF_WINDOW = 0x80
RTF_XRESOLVE = 0x800
RTMGRP_DECnet_IFADDR = 0x1000
RTMGRP_DECnet_ROUTE = 0x4000
RTMGRP_IPV4_IFADDR = 0x10
RTMGRP_IPV4_MROUTE = 0x20
RTMGRP_IPV4_ROUTE = 0x40
RTMGRP_IPV4_RULE = 0x80
RTMGRP_IPV6_IFADDR = 0x100
RTMGRP_IPV6_IFINFO = 0x800
RTMGRP_IPV6_MROUTE = 0x200
RTMGRP_IPV6_PREFIX = 0x20000
RTMGRP_IPV6_ROUTE = 0x400
RTMGRP_LINK = 0x1
RTMGRP_NEIGH = 0x4
RTMGRP_NOTIFY = 0x2
RTMGRP_TC = 0x8
RTM_BASE = 0x10
RTM_DELACTION = 0x31
RTM_DELADDR = 0x15

View file

@ -1992,6 +1992,21 @@ const (
RTF_UP = 0x1
RTF_WINDOW = 0x80
RTF_XRESOLVE = 0x800
RTMGRP_DECnet_IFADDR = 0x1000
RTMGRP_DECnet_ROUTE = 0x4000
RTMGRP_IPV4_IFADDR = 0x10
RTMGRP_IPV4_MROUTE = 0x20
RTMGRP_IPV4_ROUTE = 0x40
RTMGRP_IPV4_RULE = 0x80
RTMGRP_IPV6_IFADDR = 0x100
RTMGRP_IPV6_IFINFO = 0x800
RTMGRP_IPV6_MROUTE = 0x200
RTMGRP_IPV6_PREFIX = 0x20000
RTMGRP_IPV6_ROUTE = 0x400
RTMGRP_LINK = 0x1
RTMGRP_NEIGH = 0x4
RTMGRP_NOTIFY = 0x2
RTMGRP_TC = 0x8
RTM_BASE = 0x10
RTM_DELACTION = 0x31
RTM_DELADDR = 0x15

View file

@ -439,7 +439,7 @@ func Adjtimex(buf *Timex) (state int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
_, _, e1 := Syscall(SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
_, _, e1 := RawSyscall(SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
@ -449,7 +449,7 @@ func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Capset(hdr *CapUserHeader, data *CapUserData) (err error) {
_, _, e1 := Syscall(SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
_, _, e1 := RawSyscall(SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
if e1 != 0 {
err = errnoErr(e1)
}

View file

@ -439,7 +439,7 @@ func Adjtimex(buf *Timex) (state int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
_, _, e1 := Syscall(SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
_, _, e1 := RawSyscall(SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
@ -449,7 +449,7 @@ func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Capset(hdr *CapUserHeader, data *CapUserData) (err error) {
_, _, e1 := Syscall(SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
_, _, e1 := RawSyscall(SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
if e1 != 0 {
err = errnoErr(e1)
}

View file

@ -439,7 +439,7 @@ func Adjtimex(buf *Timex) (state int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
_, _, e1 := Syscall(SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
_, _, e1 := RawSyscall(SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
@ -449,7 +449,7 @@ func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Capset(hdr *CapUserHeader, data *CapUserData) (err error) {
_, _, e1 := Syscall(SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
_, _, e1 := RawSyscall(SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
if e1 != 0 {
err = errnoErr(e1)
}

View file

@ -439,7 +439,7 @@ func Adjtimex(buf *Timex) (state int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
_, _, e1 := Syscall(SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
_, _, e1 := RawSyscall(SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
@ -449,7 +449,7 @@ func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Capset(hdr *CapUserHeader, data *CapUserData) (err error) {
_, _, e1 := Syscall(SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
_, _, e1 := RawSyscall(SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
if e1 != 0 {
err = errnoErr(e1)
}

View file

@ -439,7 +439,7 @@ func Adjtimex(buf *Timex) (state int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
_, _, e1 := Syscall(SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
_, _, e1 := RawSyscall(SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
@ -449,7 +449,7 @@ func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Capset(hdr *CapUserHeader, data *CapUserData) (err error) {
_, _, e1 := Syscall(SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
_, _, e1 := RawSyscall(SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
if e1 != 0 {
err = errnoErr(e1)
}

View file

@ -439,7 +439,7 @@ func Adjtimex(buf *Timex) (state int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
_, _, e1 := Syscall(SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
_, _, e1 := RawSyscall(SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
@ -449,7 +449,7 @@ func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Capset(hdr *CapUserHeader, data *CapUserData) (err error) {
_, _, e1 := Syscall(SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
_, _, e1 := RawSyscall(SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
if e1 != 0 {
err = errnoErr(e1)
}

View file

@ -439,7 +439,7 @@ func Adjtimex(buf *Timex) (state int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
_, _, e1 := Syscall(SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
_, _, e1 := RawSyscall(SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
@ -449,7 +449,7 @@ func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Capset(hdr *CapUserHeader, data *CapUserData) (err error) {
_, _, e1 := Syscall(SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
_, _, e1 := RawSyscall(SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
if e1 != 0 {
err = errnoErr(e1)
}

View file

@ -439,7 +439,7 @@ func Adjtimex(buf *Timex) (state int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
_, _, e1 := Syscall(SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
_, _, e1 := RawSyscall(SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
@ -449,7 +449,7 @@ func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Capset(hdr *CapUserHeader, data *CapUserData) (err error) {
_, _, e1 := Syscall(SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
_, _, e1 := RawSyscall(SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
if e1 != 0 {
err = errnoErr(e1)
}

View file

@ -439,7 +439,7 @@ func Adjtimex(buf *Timex) (state int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
_, _, e1 := Syscall(SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
_, _, e1 := RawSyscall(SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
@ -449,7 +449,7 @@ func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Capset(hdr *CapUserHeader, data *CapUserData) (err error) {
_, _, e1 := Syscall(SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
_, _, e1 := RawSyscall(SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
if e1 != 0 {
err = errnoErr(e1)
}

View file

@ -439,7 +439,7 @@ func Adjtimex(buf *Timex) (state int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
_, _, e1 := Syscall(SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
_, _, e1 := RawSyscall(SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
@ -449,7 +449,7 @@ func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Capset(hdr *CapUserHeader, data *CapUserData) (err error) {
_, _, e1 := Syscall(SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
_, _, e1 := RawSyscall(SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
if e1 != 0 {
err = errnoErr(e1)
}

View file

@ -439,7 +439,7 @@ func Adjtimex(buf *Timex) (state int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
_, _, e1 := Syscall(SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
_, _, e1 := RawSyscall(SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
@ -449,7 +449,7 @@ func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Capset(hdr *CapUserHeader, data *CapUserData) (err error) {
_, _, e1 := Syscall(SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
_, _, e1 := RawSyscall(SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
if e1 != 0 {
err = errnoErr(e1)
}

View file

@ -439,7 +439,7 @@ func Adjtimex(buf *Timex) (state int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
_, _, e1 := Syscall(SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
_, _, e1 := RawSyscall(SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
@ -449,7 +449,7 @@ func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Capset(hdr *CapUserHeader, data *CapUserData) (err error) {
_, _, e1 := Syscall(SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
_, _, e1 := RawSyscall(SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
if e1 != 0 {
err = errnoErr(e1)
}

View file

@ -439,7 +439,7 @@ func Adjtimex(buf *Timex) (state int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
_, _, e1 := Syscall(SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
_, _, e1 := RawSyscall(SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
@ -449,7 +449,7 @@ func Capget(hdr *CapUserHeader, data *CapUserData) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Capset(hdr *CapUserHeader, data *CapUserData) (err error) {
_, _, e1 := Syscall(SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
_, _, e1 := RawSyscall(SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
if e1 != 0 {
err = errnoErr(e1)
}

6
vendor/modules.txt vendored
View file

@ -265,7 +265,7 @@ go.opencensus.io/trace
go.opencensus.io/trace/internal
go.opencensus.io/trace/propagation
go.opencensus.io/trace/tracestate
# golang.org/x/crypto v0.0.0-20200210222208-86ce3cb69678
# golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d
golang.org/x/crypto/ed25519
golang.org/x/crypto/ed25519/internal/edwards25519
golang.org/x/crypto/ocsp
@ -275,7 +275,7 @@ golang.org/x/crypto/pkcs12/internal/rc2
# golang.org/x/mod v0.2.0
golang.org/x/mod/module
golang.org/x/mod/semver
# golang.org/x/net v0.0.0-20200202094626-16171245cfb2
# golang.org/x/net v0.0.0-20200222125558-5a598a2470a0
golang.org/x/net/bpf
golang.org/x/net/context
golang.org/x/net/context/ctxhttp
@ -296,7 +296,7 @@ golang.org/x/oauth2/google
golang.org/x/oauth2/internal
golang.org/x/oauth2/jws
golang.org/x/oauth2/jwt
# golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4
# golang.org/x/sys v0.0.0-20200219091948-cb0a6d8edb6c
golang.org/x/sys/unix
golang.org/x/sys/windows
# golang.org/x/text v0.3.2