Update
This commit is contained in:
31
vendor/golang.org/x/net/dns/dnsmessage/message.go
generated
vendored
31
vendor/golang.org/x/net/dns/dnsmessage/message.go
generated
vendored
@@ -17,8 +17,21 @@ import (
|
||||
)
|
||||
|
||||
// Message formats
|
||||
//
|
||||
// To add a new Resource Record type:
|
||||
// 1. Create Resource Record types
|
||||
// 1.1. Add a Type constant named "Type<name>"
|
||||
// 1.2. Add the corresponding entry to the typeNames map
|
||||
// 1.3. Add a [ResourceBody] implementation named "<name>Resource"
|
||||
// 2. Implement packing
|
||||
// 2.1. Implement Builder.<name>Resource()
|
||||
// 3. Implement unpacking
|
||||
// 3.1. Add the unpacking code to unpackResourceBody()
|
||||
// 3.2. Implement Parser.<name>Resource()
|
||||
|
||||
// A Type is a type of DNS request and response.
|
||||
// A Type is the type of a DNS Resource Record, as defined in the [IANA registry].
|
||||
//
|
||||
// [IANA registry]: https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-4
|
||||
type Type uint16
|
||||
|
||||
const (
|
||||
@@ -33,6 +46,8 @@ const (
|
||||
TypeAAAA Type = 28
|
||||
TypeSRV Type = 33
|
||||
TypeOPT Type = 41
|
||||
TypeSVCB Type = 64
|
||||
TypeHTTPS Type = 65
|
||||
|
||||
// Question.Type
|
||||
TypeWKS Type = 11
|
||||
@@ -53,6 +68,8 @@ var typeNames = map[Type]string{
|
||||
TypeAAAA: "TypeAAAA",
|
||||
TypeSRV: "TypeSRV",
|
||||
TypeOPT: "TypeOPT",
|
||||
TypeSVCB: "TypeSVCB",
|
||||
TypeHTTPS: "TypeHTTPS",
|
||||
TypeWKS: "TypeWKS",
|
||||
TypeHINFO: "TypeHINFO",
|
||||
TypeMINFO: "TypeMINFO",
|
||||
@@ -273,6 +290,8 @@ var (
|
||||
errTooManyAdditionals = errors.New("too many Additionals to pack (>65535)")
|
||||
errNonCanonicalName = errors.New("name is not in canonical format (it must end with a .)")
|
||||
errStringTooLong = errors.New("character string exceeds maximum length (255)")
|
||||
errParamOutOfOrder = errors.New("parameter out of order")
|
||||
errTooLongSVCBValue = errors.New("value too long (>65535 bytes)")
|
||||
)
|
||||
|
||||
// Internal constants.
|
||||
@@ -2220,6 +2239,16 @@ func unpackResourceBody(msg []byte, off int, hdr ResourceHeader) (ResourceBody,
|
||||
rb, err = unpackSRVResource(msg, off)
|
||||
r = &rb
|
||||
name = "SRV"
|
||||
case TypeSVCB:
|
||||
var rb SVCBResource
|
||||
rb, err = unpackSVCBResource(msg, off, hdr.Length)
|
||||
r = &rb
|
||||
name = "SVCB"
|
||||
case TypeHTTPS:
|
||||
var rb HTTPSResource
|
||||
rb.SVCBResource, err = unpackSVCBResource(msg, off, hdr.Length)
|
||||
r = &rb
|
||||
name = "HTTPS"
|
||||
case TypeOPT:
|
||||
var rb OPTResource
|
||||
rb, err = unpackOPTResource(msg, off, hdr.Length)
|
||||
|
||||
326
vendor/golang.org/x/net/dns/dnsmessage/svcb.go
generated
vendored
Normal file
326
vendor/golang.org/x/net/dns/dnsmessage/svcb.go
generated
vendored
Normal file
@@ -0,0 +1,326 @@
|
||||
// Copyright 2025 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package dnsmessage
|
||||
|
||||
import (
|
||||
"slices"
|
||||
)
|
||||
|
||||
// An SVCBResource is an SVCB Resource record.
|
||||
type SVCBResource struct {
|
||||
Priority uint16
|
||||
Target Name
|
||||
Params []SVCParam // Must be in strict increasing order by Key.
|
||||
}
|
||||
|
||||
func (r *SVCBResource) realType() Type {
|
||||
return TypeSVCB
|
||||
}
|
||||
|
||||
// GoString implements fmt.GoStringer.GoString.
|
||||
func (r *SVCBResource) GoString() string {
|
||||
b := []byte("dnsmessage.SVCBResource{" +
|
||||
"Priority: " + printUint16(r.Priority) + ", " +
|
||||
"Target: " + r.Target.GoString() + ", " +
|
||||
"Params: []dnsmessage.SVCParam{")
|
||||
if len(r.Params) > 0 {
|
||||
b = append(b, r.Params[0].GoString()...)
|
||||
for _, p := range r.Params[1:] {
|
||||
b = append(b, ", "+p.GoString()...)
|
||||
}
|
||||
}
|
||||
b = append(b, "}}"...)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
// An HTTPSResource is an HTTPS Resource record.
|
||||
// It has the same format as the SVCB record.
|
||||
type HTTPSResource struct {
|
||||
// Alias for SVCB resource record.
|
||||
SVCBResource
|
||||
}
|
||||
|
||||
func (r *HTTPSResource) realType() Type {
|
||||
return TypeHTTPS
|
||||
}
|
||||
|
||||
// GoString implements fmt.GoStringer.GoString.
|
||||
func (r *HTTPSResource) GoString() string {
|
||||
return "dnsmessage.HTTPSResource{SVCBResource: " + r.SVCBResource.GoString() + "}"
|
||||
}
|
||||
|
||||
// GetParam returns a parameter value by key.
|
||||
func (r *SVCBResource) GetParam(key SVCParamKey) (value []byte, ok bool) {
|
||||
for i := range r.Params {
|
||||
if r.Params[i].Key == key {
|
||||
return r.Params[i].Value, true
|
||||
}
|
||||
if r.Params[i].Key > key {
|
||||
break
|
||||
}
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// SetParam sets a parameter value by key.
|
||||
// The Params list is kept sorted by key.
|
||||
func (r *SVCBResource) SetParam(key SVCParamKey, value []byte) {
|
||||
i := 0
|
||||
for i < len(r.Params) {
|
||||
if r.Params[i].Key >= key {
|
||||
break
|
||||
}
|
||||
i++
|
||||
}
|
||||
|
||||
if i < len(r.Params) && r.Params[i].Key == key {
|
||||
r.Params[i].Value = value
|
||||
return
|
||||
}
|
||||
|
||||
r.Params = slices.Insert(r.Params, i, SVCParam{Key: key, Value: value})
|
||||
}
|
||||
|
||||
// DeleteParam deletes a parameter by key.
|
||||
// It returns true if the parameter was present.
|
||||
func (r *SVCBResource) DeleteParam(key SVCParamKey) bool {
|
||||
for i := range r.Params {
|
||||
if r.Params[i].Key == key {
|
||||
r.Params = slices.Delete(r.Params, i, i+1)
|
||||
return true
|
||||
}
|
||||
if r.Params[i].Key > key {
|
||||
break
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// A SVCParam is a service parameter.
|
||||
type SVCParam struct {
|
||||
Key SVCParamKey
|
||||
Value []byte
|
||||
}
|
||||
|
||||
// GoString implements fmt.GoStringer.GoString.
|
||||
func (p SVCParam) GoString() string {
|
||||
return "dnsmessage.SVCParam{" +
|
||||
"Key: " + p.Key.GoString() + ", " +
|
||||
"Value: []byte{" + printByteSlice(p.Value) + "}}"
|
||||
}
|
||||
|
||||
// A SVCParamKey is a key for a service parameter.
|
||||
type SVCParamKey uint16
|
||||
|
||||
// Values defined at https://www.iana.org/assignments/dns-svcb/dns-svcb.xhtml#dns-svcparamkeys.
|
||||
const (
|
||||
SVCParamMandatory SVCParamKey = 0
|
||||
SVCParamALPN SVCParamKey = 1
|
||||
SVCParamNoDefaultALPN SVCParamKey = 2
|
||||
SVCParamPort SVCParamKey = 3
|
||||
SVCParamIPv4Hint SVCParamKey = 4
|
||||
SVCParamECH SVCParamKey = 5
|
||||
SVCParamIPv6Hint SVCParamKey = 6
|
||||
SVCParamDOHPath SVCParamKey = 7
|
||||
SVCParamOHTTP SVCParamKey = 8
|
||||
SVCParamTLSSupportedGroups SVCParamKey = 9
|
||||
)
|
||||
|
||||
var svcParamKeyNames = map[SVCParamKey]string{
|
||||
SVCParamMandatory: "Mandatory",
|
||||
SVCParamALPN: "ALPN",
|
||||
SVCParamNoDefaultALPN: "NoDefaultALPN",
|
||||
SVCParamPort: "Port",
|
||||
SVCParamIPv4Hint: "IPv4Hint",
|
||||
SVCParamECH: "ECH",
|
||||
SVCParamIPv6Hint: "IPv6Hint",
|
||||
SVCParamDOHPath: "DOHPath",
|
||||
SVCParamOHTTP: "OHTTP",
|
||||
SVCParamTLSSupportedGroups: "TLSSupportedGroups",
|
||||
}
|
||||
|
||||
// String implements fmt.Stringer.String.
|
||||
func (k SVCParamKey) String() string {
|
||||
if n, ok := svcParamKeyNames[k]; ok {
|
||||
return n
|
||||
}
|
||||
return printUint16(uint16(k))
|
||||
}
|
||||
|
||||
// GoString implements fmt.GoStringer.GoString.
|
||||
func (k SVCParamKey) GoString() string {
|
||||
if n, ok := svcParamKeyNames[k]; ok {
|
||||
return "dnsmessage.SVCParam" + n
|
||||
}
|
||||
return printUint16(uint16(k))
|
||||
}
|
||||
|
||||
func (r *SVCBResource) pack(msg []byte, _ map[string]uint16, _ int) ([]byte, error) {
|
||||
oldMsg := msg
|
||||
msg = packUint16(msg, r.Priority)
|
||||
// https://datatracker.ietf.org/doc/html/rfc3597#section-4 prohibits name
|
||||
// compression for RR types that are not "well-known".
|
||||
// https://datatracker.ietf.org/doc/html/rfc9460#section-2.2 explicitly states that
|
||||
// compression of the Target is prohibited, following RFC 3597.
|
||||
msg, err := r.Target.pack(msg, nil, 0)
|
||||
if err != nil {
|
||||
return oldMsg, &nestedError{"SVCBResource.Target", err}
|
||||
}
|
||||
var previousKey SVCParamKey
|
||||
for i, param := range r.Params {
|
||||
if i > 0 && param.Key <= previousKey {
|
||||
return oldMsg, &nestedError{"SVCBResource.Params", errParamOutOfOrder}
|
||||
}
|
||||
if len(param.Value) > (1<<16)-1 {
|
||||
return oldMsg, &nestedError{"SVCBResource.Params", errTooLongSVCBValue}
|
||||
}
|
||||
msg = packUint16(msg, uint16(param.Key))
|
||||
msg = packUint16(msg, uint16(len(param.Value)))
|
||||
msg = append(msg, param.Value...)
|
||||
}
|
||||
return msg, nil
|
||||
}
|
||||
|
||||
func unpackSVCBResource(msg []byte, off int, length uint16) (SVCBResource, error) {
|
||||
// Wire format reference: https://www.rfc-editor.org/rfc/rfc9460.html#section-2.2.
|
||||
r := SVCBResource{}
|
||||
paramsOff := off
|
||||
bodyEnd := off + int(length)
|
||||
|
||||
var err error
|
||||
if r.Priority, paramsOff, err = unpackUint16(msg, paramsOff); err != nil {
|
||||
return SVCBResource{}, &nestedError{"Priority", err}
|
||||
}
|
||||
|
||||
if paramsOff, err = r.Target.unpack(msg, paramsOff); err != nil {
|
||||
return SVCBResource{}, &nestedError{"Target", err}
|
||||
}
|
||||
|
||||
// Two-pass parsing to avoid allocations.
|
||||
// First, count the number of params.
|
||||
n := 0
|
||||
var totalValueLen uint16
|
||||
off = paramsOff
|
||||
var previousKey uint16
|
||||
for off < bodyEnd {
|
||||
var key, len uint16
|
||||
if key, off, err = unpackUint16(msg, off); err != nil {
|
||||
return SVCBResource{}, &nestedError{"Params key", err}
|
||||
}
|
||||
if n > 0 && key <= previousKey {
|
||||
// As per https://www.rfc-editor.org/rfc/rfc9460.html#section-2.2, clients MUST
|
||||
// consider the RR malformed if the SvcParamKeys are not in strictly increasing numeric order
|
||||
return SVCBResource{}, &nestedError{"Params", errParamOutOfOrder}
|
||||
}
|
||||
if len, off, err = unpackUint16(msg, off); err != nil {
|
||||
return SVCBResource{}, &nestedError{"Params value length", err}
|
||||
}
|
||||
if off+int(len) > bodyEnd {
|
||||
return SVCBResource{}, errResourceLen
|
||||
}
|
||||
totalValueLen += len
|
||||
off += int(len)
|
||||
n++
|
||||
}
|
||||
if off != bodyEnd {
|
||||
return SVCBResource{}, errResourceLen
|
||||
}
|
||||
|
||||
// Second, fill in the params.
|
||||
r.Params = make([]SVCParam, n)
|
||||
// valuesBuf is used to hold all param values to reduce allocations.
|
||||
// Each param's Value slice will point into this buffer.
|
||||
valuesBuf := make([]byte, totalValueLen)
|
||||
off = paramsOff
|
||||
for i := 0; i < n; i++ {
|
||||
p := &r.Params[i]
|
||||
var key, len uint16
|
||||
if key, off, err = unpackUint16(msg, off); err != nil {
|
||||
return SVCBResource{}, &nestedError{"param key", err}
|
||||
}
|
||||
p.Key = SVCParamKey(key)
|
||||
if len, off, err = unpackUint16(msg, off); err != nil {
|
||||
return SVCBResource{}, &nestedError{"param length", err}
|
||||
}
|
||||
if copy(valuesBuf, msg[off:off+int(len)]) != int(len) {
|
||||
return SVCBResource{}, &nestedError{"param value", errCalcLen}
|
||||
}
|
||||
p.Value = valuesBuf[:len:len]
|
||||
valuesBuf = valuesBuf[len:]
|
||||
off += int(len)
|
||||
}
|
||||
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// genericSVCBResource parses a single Resource Record compatible with SVCB.
|
||||
func (p *Parser) genericSVCBResource(svcbType Type) (SVCBResource, error) {
|
||||
if !p.resHeaderValid || p.resHeaderType != svcbType {
|
||||
return SVCBResource{}, ErrNotStarted
|
||||
}
|
||||
r, err := unpackSVCBResource(p.msg, p.off, p.resHeaderLength)
|
||||
if err != nil {
|
||||
return SVCBResource{}, err
|
||||
}
|
||||
p.off += int(p.resHeaderLength)
|
||||
p.resHeaderValid = false
|
||||
p.index++
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// SVCBResource parses a single SVCBResource.
|
||||
//
|
||||
// One of the XXXHeader methods must have been called before calling this
|
||||
// method.
|
||||
func (p *Parser) SVCBResource() (SVCBResource, error) {
|
||||
return p.genericSVCBResource(TypeSVCB)
|
||||
}
|
||||
|
||||
// HTTPSResource parses a single HTTPSResource.
|
||||
//
|
||||
// One of the XXXHeader methods must have been called before calling this
|
||||
// method.
|
||||
func (p *Parser) HTTPSResource() (HTTPSResource, error) {
|
||||
svcb, err := p.genericSVCBResource(TypeHTTPS)
|
||||
if err != nil {
|
||||
return HTTPSResource{}, err
|
||||
}
|
||||
return HTTPSResource{svcb}, nil
|
||||
}
|
||||
|
||||
// genericSVCBResource is the generic implementation for adding SVCB-like resources.
|
||||
func (b *Builder) genericSVCBResource(h ResourceHeader, r SVCBResource) error {
|
||||
if err := b.checkResourceSection(); err != nil {
|
||||
return err
|
||||
}
|
||||
msg, lenOff, err := h.pack(b.msg, b.compression, b.start)
|
||||
if err != nil {
|
||||
return &nestedError{"ResourceHeader", err}
|
||||
}
|
||||
preLen := len(msg)
|
||||
if msg, err = r.pack(msg, b.compression, b.start); err != nil {
|
||||
return &nestedError{"ResourceBody", err}
|
||||
}
|
||||
if err := h.fixLen(msg, lenOff, preLen); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := b.incrementSectionCount(); err != nil {
|
||||
return err
|
||||
}
|
||||
b.msg = msg
|
||||
return nil
|
||||
}
|
||||
|
||||
// SVCBResource adds a single SVCBResource.
|
||||
func (b *Builder) SVCBResource(h ResourceHeader, r SVCBResource) error {
|
||||
h.Type = r.realType()
|
||||
return b.genericSVCBResource(h, r)
|
||||
}
|
||||
|
||||
// HTTPSResource adds a single HTTPSResource.
|
||||
func (b *Builder) HTTPSResource(h ResourceHeader, r HTTPSResource) error {
|
||||
h.Type = r.realType()
|
||||
return b.genericSVCBResource(h, r.SVCBResource)
|
||||
}
|
||||
Reference in New Issue
Block a user