svcb: doc updates (#1178)

The SVBC record didn't have a class, so add that and use struct literal
to put it all on 1 one. Use `s` for SVCB records, and `h` for HTTPS to
be more consistent.

Signed-off-by: Miek Gieben <miek@miek.nl>
This commit is contained in:
Miek Gieben 2020-10-17 10:00:13 +02:00 committed by GitHub
parent 95dddd3867
commit 61a22d0ee6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 35 additions and 69 deletions

104
svcb.go
View File

@ -12,7 +12,7 @@ import (
type SVCBKey uint16 type SVCBKey uint16
// Keys defined in draft-ietf-dnsop-svcb-https-02 Section 11.1.2 // Keys defined in draft-ietf-dnsop-svcb-https-02 Section 11.1.2.
const ( const (
SVCB_MANDATORY SVCBKey = 0 SVCB_MANDATORY SVCBKey = 0
SVCB_ALPN SVCBKey = 1 SVCB_ALPN SVCBKey = 1
@ -173,8 +173,7 @@ func (rr *SVCB) parse(c *zlexer, o string) *ParseError {
return nil return nil
} }
// makeSVCBKeyValue returns an SVCBKeyValue struct with the key // makeSVCBKeyValue returns an SVCBKeyValue struct with the key or nil for reserved keys.
// or nil for reserved keys.
func makeSVCBKeyValue(key SVCBKey) SVCBKeyValue { func makeSVCBKeyValue(key SVCBKey) SVCBKeyValue {
switch key { switch key {
case SVCB_MANDATORY: case SVCB_MANDATORY:
@ -200,19 +199,16 @@ func makeSVCBKeyValue(key SVCBKey) SVCBKeyValue {
} }
} }
// SVCB RR. See RFC xxxx (https://tools.ietf.org/html/draft-ietf-dnsop-svcb-https-00) // SVCB RR. See RFC xxxx (https://tools.ietf.org/html/draft-ietf-dnsop-svcb-https-02).
// The one with the smallest priority should be given preference. Of those with
// equal priority, a random one should be preferred for load balancing.
type SVCB struct { type SVCB struct {
Hdr RR_Header Hdr RR_Header
Priority uint16 Priority uint16
Target string `dns:"domain-name"` Target string `dns:"domain-name"`
Value []SVCBKeyValue `dns:"pairs"` // This must be empty if Priority is non-zero Value []SVCBKeyValue `dns:"pairs"` // Value must be empty if Priority is non-zero.
} }
// HTTPS RR. Everything valid for SVCB applies to HTTPS as well // HTTPS RR. Everything valid for SVCB applies to HTTPS as well.
// except that the HTTPS record is intended for use with the HTTP and HTTPS protocols. // Except that the HTTPS record is intended for use with the HTTP and HTTPS protocols.
type HTTPS struct { type HTTPS struct {
SVCB SVCB
} }
@ -228,33 +224,23 @@ func (rr *HTTPS) parse(c *zlexer, o string) *ParseError {
// SVCBKeyValue defines a key=value pair for the SVCB RR type. // SVCBKeyValue defines a key=value pair for the SVCB RR type.
// An SVCB RR can have multiple SVCBKeyValues appended to it. // An SVCB RR can have multiple SVCBKeyValues appended to it.
type SVCBKeyValue interface { type SVCBKeyValue interface {
// Key returns the numerical key code. Key() SVCBKey // Key returns the numerical key code.
Key() SVCBKey pack() ([]byte, error) // pack returns the encoded value.
// pack returns the encoded value. unpack([]byte) error // unpack sets the value.
pack() ([]byte, error) String() string // String returns the string representation of the value.
// unpack sets the value. parse(string) error // parse sets the value to the given string representation of the value.
unpack([]byte) error copy() SVCBKeyValue // copy returns a deep-copy of the pair.
// String returns the string representation of the value. len() int // len returns the length of value in the wire format.
String() string
// parse sets the value to the given string representation of the value.
parse(string) error
// copy returns a deep-copy of the pair.
copy() SVCBKeyValue
// len returns the length of value in the wire format.
len() int
} }
// SVCBMandatory pair adds to required keys that must be interpreted for the RR // SVCBMandatory pair adds to required keys that must be interpreted for the RR
// to be functional. // to be functional.
// Basic use pattern for creating a mandatory option: // Basic use pattern for creating a mandatory option:
// //
// o := new(dns.SVCB) // s := &dns.SVCB{Hdr: dns.RR_Header{Name: ".", Rrtype: dns.TypeSVCB, Class: dns.ClassINET}}
// o.Hdr.Name = "."
// o.Hdr.Rrtype = dns.TypeSVCB
// e := new(dns.SVCBMandatory) // e := new(dns.SVCBMandatory)
// e.Code = []uint16{65403} // e.Code = []uint16{65403}
// o.Value = append(o.Value, e) // s.Value = append(s.Value, e)
// // Then add key-value pair for key65403
type SVCBMandatory struct { type SVCBMandatory struct {
Code []SVCBKey // Must not include mandatory Code []SVCBKey // Must not include mandatory
} }
@ -319,12 +305,10 @@ func (s *SVCBMandatory) copy() SVCBKeyValue {
// https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids // https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids
// Basic use pattern for creating an alpn option: // Basic use pattern for creating an alpn option:
// //
// o := new(dns.HTTPS) // h := &dns.HTTPS{Hdr: dns.RR_Header{Name: ".", Rrtype: dns.TypeHTTPS, Class: dns.ClassINET}}
// o.Hdr.Name = "."
// o.Hdr.Rrtype = dns.TypeHTTPS
// e := new(dns.SVCBAlpn) // e := new(dns.SVCBAlpn)
// e.Alpn = []string{"h2", "http/1.1"} // e.Alpn = []string{"h2", "http/1.1"}
// o.Value = append(o.Value, e) // h.Value = append(o.Value, e)
type SVCBAlpn struct { type SVCBAlpn struct {
Alpn []string Alpn []string
} }
@ -332,10 +316,6 @@ type SVCBAlpn struct {
func (*SVCBAlpn) Key() SVCBKey { return SVCB_ALPN } func (*SVCBAlpn) Key() SVCBKey { return SVCB_ALPN }
func (s *SVCBAlpn) String() string { return strings.Join(s.Alpn, ",") } func (s *SVCBAlpn) String() string { return strings.Join(s.Alpn, ",") }
// The spec requires the alpn keys including \ or , to be escaped.
// In practice, no standard key including those exists.
// Therefore those characters are not escaped.
func (s *SVCBAlpn) pack() ([]byte, error) { func (s *SVCBAlpn) pack() ([]byte, error) {
// Liberally estimate the size of an alpn as 10 octets // Liberally estimate the size of an alpn as 10 octets
b := make([]byte, 0, 10*len(s.Alpn)) b := make([]byte, 0, 10*len(s.Alpn))
@ -390,14 +370,10 @@ func (s *SVCBAlpn) copy() SVCBKeyValue {
// SVCBNoDefaultAlpn pair signifies no support for default connection protocols. // SVCBNoDefaultAlpn pair signifies no support for default connection protocols.
// Basic use pattern for creating a no-default-alpn option: // Basic use pattern for creating a no-default-alpn option:
// //
// o := new(dns.SVCB) // s := &dns.SVCB{Hdr: dns.RR_Header{Name: ".", Rrtype: dns.TypeSVCB, Class: dns.ClassINET}}
// o.Hdr.Name = "."
// o.Hdr.Rrtype = dns.SVCB
// e := new(dns.SVCBNoDefaultAlpn) // e := new(dns.SVCBNoDefaultAlpn)
// o.Value = append(o.Value, e) // s.Value = append(s.Value, e)
type SVCBNoDefaultAlpn struct { type SVCBNoDefaultAlpn struct{}
// Empty
}
func (*SVCBNoDefaultAlpn) Key() SVCBKey { return SVCB_NO_DEFAULT_ALPN } func (*SVCBNoDefaultAlpn) Key() SVCBKey { return SVCB_NO_DEFAULT_ALPN }
func (*SVCBNoDefaultAlpn) copy() SVCBKeyValue { return &SVCBNoDefaultAlpn{} } func (*SVCBNoDefaultAlpn) copy() SVCBKeyValue { return &SVCBNoDefaultAlpn{} }
@ -422,12 +398,10 @@ func (*SVCBNoDefaultAlpn) parse(b string) error {
// SVCBPort pair defines the port for connection. // SVCBPort pair defines the port for connection.
// Basic use pattern for creating a port option: // Basic use pattern for creating a port option:
// //
// o := new(dns.SVCB) // s := &dns.SVCB{Hdr: dns.RR_Header{Name: ".", Rrtype: dns.TypeSVCB, Class: dns.ClassINET}}
// o.Hdr.Name = "."
// o.Hdr.Rrtype = dns.SVCB
// e := new(dns.SVCBPort) // e := new(dns.SVCBPort)
// e.Port = 80 // e.Port = 80
// o.Value = append(o.Value, e) // s.Value = append(s.Value, e)
type SVCBPort struct { type SVCBPort struct {
Port uint16 Port uint16
} }
@ -466,14 +440,14 @@ func (s *SVCBPort) parse(b string) error {
// to the hinted IP address may be terminated and a new connection may be opened. // to the hinted IP address may be terminated and a new connection may be opened.
// Basic use pattern for creating an ipv4hint option: // Basic use pattern for creating an ipv4hint option:
// //
// o := new(dns.HTTPS) // h := &dns.HTTPS{Hdr: dns.RR_Header{Name: ".", Rrtype: dns.TypeHTTPS, Class: dns.ClassINET}}
// o.Hdr.Name = "."
// o.Hdr.Rrtype = dns.HTTPS
// e := new(dns.SVCBIPv4Hint) // e := new(dns.SVCBIPv4Hint)
// e.Hint = []net.IP{net.IPv4(1,1,1,1).To4()} // e.Hint = []net.IP{net.IPv4(1,1,1,1).To4()}
// // or //
// Or
//
// e.Hint = []net.IP{net.ParseIP("1.1.1.1").To4()} // e.Hint = []net.IP{net.ParseIP("1.1.1.1").To4()}
// o.Value = append(o.Value, e) // h.Value = append(h.Value, e)
type SVCBIPv4Hint struct { type SVCBIPv4Hint struct {
Hint []net.IP Hint []net.IP
} }
@ -505,7 +479,6 @@ func (s *SVCBIPv4Hint) unpack(b []byte) error {
return nil return nil
} }
// String returns the string form of s, it returns "<nil>" if s is invalid.
func (s *SVCBIPv4Hint) String() string { func (s *SVCBIPv4Hint) String() string {
str := make([]string, len(s.Hint)) str := make([]string, len(s.Hint))
for i, e := range s.Hint { for i, e := range s.Hint {
@ -544,12 +517,10 @@ func (s *SVCBIPv4Hint) copy() SVCBKeyValue {
// SVCBECHConfig pair contains the ECHConfig structure defined in draft-ietf-tls-esni [RFC xxxx]. // SVCBECHConfig pair contains the ECHConfig structure defined in draft-ietf-tls-esni [RFC xxxx].
// Basic use pattern for creating an echconfig option: // Basic use pattern for creating an echconfig option:
// //
// o := new(dns.HTTPS) // h := &dns.HTTPS{Hdr: dns.RR_Header{Name: ".", Rrtype: dns.TypeHTTPS, Class: dns.ClassINET}}
// o.Hdr.Name = "."
// o.Hdr.Rrtype = dns.HTTPS
// e := new(dns.SVCBECHConfig) // e := new(dns.SVCBECHConfig)
// e.ECH = "/wH...=" // e.ECH = "/wH...="
// o.Value = append(o.Value, e) // h.Value = append(h.Value, e)
type SVCBECHConfig struct { type SVCBECHConfig struct {
ECH []byte ECH []byte
} }
@ -587,12 +558,10 @@ func (s *SVCBECHConfig) parse(b string) error {
// connection to the hinted IP address may be terminated and a new connection may be opened. // connection to the hinted IP address may be terminated and a new connection may be opened.
// Basic use pattern for creating an ipv6hint option: // Basic use pattern for creating an ipv6hint option:
// //
// o := new(dns.HTTPS) // h := &dns.HTTPS{Hdr: dns.RR_Header{Name: ".", Rrtype: dns.TypeHTTPS, Class: dns.ClassINET}}
// o.Hdr.Name = "."
// o.Hdr.Rrtype = dns.HTTPS
// e := new(dns.SVCBIPv6Hint) // e := new(dns.SVCBIPv6Hint)
// e.Hint = []net.IP{net.ParseIP("2001:db8::1")} // e.Hint = []net.IP{net.ParseIP("2001:db8::1")}
// o.Value = append(o.Value, e) // h.Value = append(h.Value, e)
type SVCBIPv6Hint struct { type SVCBIPv6Hint struct {
Hint []net.IP Hint []net.IP
} }
@ -627,7 +596,6 @@ func (s *SVCBIPv6Hint) unpack(b []byte) error {
return nil return nil
} }
// String returns the string form of s, it returns "<nil>" if s is invalid.
func (s *SVCBIPv6Hint) String() string { func (s *SVCBIPv6Hint) String() string {
str := make([]string, len(s.Hint)) str := make([]string, len(s.Hint))
for i, e := range s.Hint { for i, e := range s.Hint {
@ -666,16 +634,14 @@ func (s *SVCBIPv6Hint) copy() SVCBKeyValue {
// to be in the range [SVCB_PRIVATE_LOWER, SVCB_PRIVATE_UPPER]. // to be in the range [SVCB_PRIVATE_LOWER, SVCB_PRIVATE_UPPER].
// Basic use pattern for creating a keyNNNNN option: // Basic use pattern for creating a keyNNNNN option:
// //
// o := new(dns.HTTPS) // h := &dns.HTTPS{Hdr: dns.RR_Header{Name: ".", Rrtype: dns.TypeHTTPS, Class: dns.ClassINET}}
// o.Hdr.Name = "."
// o.Hdr.Rrtype = dns.HTTPS
// e := new(dns.SVCBLocal) // e := new(dns.SVCBLocal)
// e.KeyCode = 65400 // e.KeyCode = 65400
// e.Data = []byte("abc") // e.Data = []byte("abc")
// o.Value = append(o.Value, e) // h.Value = append(h.Value, e)
type SVCBLocal struct { type SVCBLocal struct {
KeyCode SVCBKey // Never 65535 or any assigned keys KeyCode SVCBKey // Never 65535 or any assigned keys.
Data []byte // All byte sequences are allowed Data []byte // All byte sequences are allowed.
} }
func (s *SVCBLocal) Key() SVCBKey { return s.KeyCode } func (s *SVCBLocal) Key() SVCBKey { return s.KeyCode }