Update
This commit is contained in:
1 parent
3530afb854
commit
6903fcff27
2146 files changed
+112256
-190703
No files matched your search
+7
@@ -49,6 +49,13 @@ to extensions, which are essentially calls to kernel utility
|
||||
functions. Currently, the only extensions supported by this package
|
||||
are the Linux packet filter extensions.
|
||||
|
||||
# Security Considerations
|
||||
|
||||
The implementation of the BPF VM in this package is suitable for
|
||||
testing BPF programs. It aims for consistency with other BPF VM
|
||||
implementations, but divergence in behavior is not considered a
|
||||
security issue.
|
||||
|
||||
# Examples
|
||||
|
||||
This packet filter selects all ARP packets.
|
||||
|
||||
+8
-16
@@ -751,10 +751,7 @@ func (p *Parser) AllAnswers() ([]Resource, error) {
|
||||
//
|
||||
// Pre-allocate up to a certain limit, since p.header is
|
||||
// untrusted data.
|
||||
n := int(p.header.answers)
|
||||
if n > 20 {
|
||||
n = 20
|
||||
}
|
||||
n := min(int(p.header.answers), 20)
|
||||
as := make([]Resource, 0, n)
|
||||
for {
|
||||
a, err := p.Answer()
|
||||
@@ -804,10 +801,7 @@ func (p *Parser) AllAuthorities() ([]Resource, error) {
|
||||
//
|
||||
// Pre-allocate up to a certain limit, since p.header is
|
||||
// untrusted data.
|
||||
n := int(p.header.authorities)
|
||||
if n > 10 {
|
||||
n = 10
|
||||
}
|
||||
n := min(int(p.header.authorities), 10)
|
||||
as := make([]Resource, 0, n)
|
||||
for {
|
||||
a, err := p.Authority()
|
||||
@@ -857,10 +851,7 @@ func (p *Parser) AllAdditionals() ([]Resource, error) {
|
||||
//
|
||||
// Pre-allocate up to a certain limit, since p.header is
|
||||
// untrusted data.
|
||||
n := int(p.header.additionals)
|
||||
if n > 10 {
|
||||
n = 10
|
||||
}
|
||||
n := min(int(p.header.additionals), 10)
|
||||
as := make([]Resource, 0, n)
|
||||
for {
|
||||
a, err := p.Additional()
|
||||
@@ -2085,7 +2076,11 @@ Loop:
|
||||
return off, errInvalidName
|
||||
}
|
||||
}
|
||||
|
||||
// Reject names that are too long while unpacking
|
||||
// See issue golang/go#77540
|
||||
if len(name)+(endOff-currOff) >= nonEncodedNameMax {
|
||||
return off, errNameTooLong
|
||||
}
|
||||
name = append(name, msg[currOff:endOff]...)
|
||||
name = append(name, '.')
|
||||
currOff = endOff
|
||||
@@ -2111,9 +2106,6 @@ Loop:
|
||||
if len(name) == 0 {
|
||||
name = append(name, '.')
|
||||
}
|
||||
if len(name) > nonEncodedNameMax {
|
||||
return off, errNameTooLong
|
||||
}
|
||||
n.Length = uint8(len(name))
|
||||
if ptr == 0 {
|
||||
newOff = currOff
|
||||
|
||||
+20
-13
@@ -168,9 +168,8 @@ func (r *SVCBResource) pack(msg []byte, _ map[string]uint16, _ int) ([]byte, err
|
||||
if err != nil {
|
||||
return oldMsg, &nestedError{"SVCBResource.Target", err}
|
||||
}
|
||||
var previousKey SVCParamKey
|
||||
for i, param := range r.Params {
|
||||
if i > 0 && param.Key <= previousKey {
|
||||
if i > 0 && param.Key <= r.Params[i-1].Key {
|
||||
return oldMsg, &nestedError{"SVCBResource.Params", errParamOutOfOrder}
|
||||
}
|
||||
if len(param.Value) > (1<<16)-1 {
|
||||
@@ -189,6 +188,10 @@ func unpackSVCBResource(msg []byte, off int, length uint16) (SVCBResource, error
|
||||
paramsOff := off
|
||||
bodyEnd := off + int(length)
|
||||
|
||||
if bodyEnd > len(msg) {
|
||||
return SVCBResource{}, errResourceLen
|
||||
}
|
||||
|
||||
var err error
|
||||
if r.Priority, paramsOff, err = unpackUint16(msg, paramsOff); err != nil {
|
||||
return SVCBResource{}, &nestedError{"Priority", err}
|
||||
@@ -205,7 +208,7 @@ func unpackSVCBResource(msg []byte, off int, length uint16) (SVCBResource, error
|
||||
off = paramsOff
|
||||
var previousKey uint16
|
||||
for off < bodyEnd {
|
||||
var key, len uint16
|
||||
var key, size uint16
|
||||
if key, off, err = unpackUint16(msg, off); err != nil {
|
||||
return SVCBResource{}, &nestedError{"Params key", err}
|
||||
}
|
||||
@@ -214,14 +217,15 @@ func unpackSVCBResource(msg []byte, off int, length uint16) (SVCBResource, error
|
||||
// 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 {
|
||||
if size, off, err = unpackUint16(msg, off); err != nil {
|
||||
return SVCBResource{}, &nestedError{"Params value length", err}
|
||||
}
|
||||
if off+int(len) > bodyEnd {
|
||||
if off+int(size) > bodyEnd {
|
||||
return SVCBResource{}, errResourceLen
|
||||
}
|
||||
totalValueLen += len
|
||||
off += int(len)
|
||||
previousKey = key
|
||||
totalValueLen += size
|
||||
off += int(size)
|
||||
n++
|
||||
}
|
||||
if off != bodyEnd {
|
||||
@@ -236,20 +240,23 @@ func unpackSVCBResource(msg []byte, off int, length uint16) (SVCBResource, error
|
||||
off = paramsOff
|
||||
for i := 0; i < n; i++ {
|
||||
p := &r.Params[i]
|
||||
var key, len uint16
|
||||
var key, size 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 {
|
||||
if size, off, err = unpackUint16(msg, off); err != nil {
|
||||
return SVCBResource{}, &nestedError{"param length", err}
|
||||
}
|
||||
if copy(valuesBuf, msg[off:off+int(len)]) != int(len) {
|
||||
if len(msg[off:]) < int(size) {
|
||||
return SVCBResource{}, &nestedError{"param value", errCalcLen}
|
||||
}
|
||||
p.Value = valuesBuf[:len:len]
|
||||
valuesBuf = valuesBuf[len:]
|
||||
off += int(len)
|
||||
if copy(valuesBuf, msg[off:][:int(size)]) != int(size) {
|
||||
return SVCBResource{}, &nestedError{"param value", errCalcLen}
|
||||
}
|
||||
p.Value = valuesBuf[:size:size]
|
||||
valuesBuf = valuesBuf[size:]
|
||||
off += int(size)
|
||||
}
|
||||
|
||||
return r, nil
|
||||
|
||||
+11
-10
@@ -3,8 +3,8 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package httpproxy provides support for HTTP proxy determination
|
||||
// based on environment variables, as provided by net/http's
|
||||
// ProxyFromEnvironment function.
|
||||
// based on environment variables, as provided by
|
||||
// [net/http.ProxyFromEnvironment] function.
|
||||
//
|
||||
// The API is not subject to the Go 1 compatibility promise and may change at
|
||||
// any time.
|
||||
@@ -56,7 +56,7 @@ type Config struct {
|
||||
// presence of a REQUEST_METHOD environment variable).
|
||||
// When this is set, ProxyForURL will return an error
|
||||
// when HTTPProxy applies, because a client could be
|
||||
// setting HTTP_PROXY maliciously. See https://golang.org/s/cgihttpproxy.
|
||||
// setting HTTP_PROXY maliciously. See https://go.dev/s/cgihttpproxy.
|
||||
CGI bool
|
||||
}
|
||||
|
||||
@@ -80,18 +80,19 @@ type config struct {
|
||||
domainMatchers []matcher
|
||||
}
|
||||
|
||||
// FromEnvironment returns a Config instance populated from the
|
||||
// environment variables HTTP_PROXY, HTTPS_PROXY and NO_PROXY (or the
|
||||
// lowercase versions thereof).
|
||||
// FromEnvironment returns a Config instance populated from the environment
|
||||
// variables HTTP_PROXY, HTTPS_PROXY and NO_PROXY (or the lowercase versions
|
||||
// thereof). When both the uppercase and lowercase versions are provided, the
|
||||
// lowercase versions are prioritized.
|
||||
//
|
||||
// The environment values may be either a complete URL or a
|
||||
// "host[:port]", in which case the "http" scheme is assumed. An error
|
||||
// is returned if the value is a different form.
|
||||
func FromEnvironment() *Config {
|
||||
return &Config{
|
||||
HTTPProxy: getEnvAny("HTTP_PROXY", "http_proxy"),
|
||||
HTTPSProxy: getEnvAny("HTTPS_PROXY", "https_proxy"),
|
||||
NoProxy: getEnvAny("NO_PROXY", "no_proxy"),
|
||||
HTTPProxy: getEnvAny("http_proxy", "HTTP_PROXY"),
|
||||
HTTPSProxy: getEnvAny("https_proxy", "HTTPS_PROXY"),
|
||||
NoProxy: getEnvAny("no_proxy", "NO_PROXY"),
|
||||
CGI: os.Getenv("REQUEST_METHOD") != "",
|
||||
}
|
||||
}
|
||||
@@ -113,7 +114,7 @@ func getEnvAny(names ...string) string {
|
||||
// environment, or a proxy should not be used for the given request, as
|
||||
// defined by NO_PROXY.
|
||||
//
|
||||
// As a special case, if req.URL.Host is "localhost" or a loopback address
|
||||
// As a special case, if reqURL.Host is "localhost" or a loopback address
|
||||
// (with or without a port number), then a nil URL and nil error will be returned.
|
||||
func (cfg *Config) ProxyFunc() func(reqURL *url.URL) (*url.URL, error) {
|
||||
// Preprocess the Config settings for more efficient evaluation.
|
||||
|
||||
+1
-4
@@ -253,10 +253,7 @@ type InterfaceIdent struct {
|
||||
func (ifi *InterfaceIdent) Len(_ int) int {
|
||||
switch ifi.Type {
|
||||
case typeInterfaceByName:
|
||||
l := len(ifi.Name)
|
||||
if l > 255 {
|
||||
l = 255
|
||||
}
|
||||
l := min(len(ifi.Name), 255)
|
||||
return 4 + (l+3)&^3
|
||||
case typeInterfaceByIndex:
|
||||
return 4 + 4
|
||||
|
||||
+2
-3
@@ -9,7 +9,6 @@ import (
|
||||
"net"
|
||||
"runtime"
|
||||
|
||||
"golang.org/x/net/internal/socket"
|
||||
"golang.org/x/net/ipv4"
|
||||
)
|
||||
|
||||
@@ -49,12 +48,12 @@ func ParseIPv4Header(b []byte) (*ipv4.Header, error) {
|
||||
}
|
||||
switch runtime.GOOS {
|
||||
case "darwin", "ios":
|
||||
h.TotalLen = int(socket.NativeEndian.Uint16(b[2:4]))
|
||||
h.TotalLen = int(binary.NativeEndian.Uint16(b[2:4]))
|
||||
case "freebsd":
|
||||
if freebsdVersion >= 1000000 {
|
||||
h.TotalLen = int(binary.BigEndian.Uint16(b[2:4]))
|
||||
} else {
|
||||
h.TotalLen = int(socket.NativeEndian.Uint16(b[2:4]))
|
||||
h.TotalLen = int(binary.NativeEndian.Uint16(b[2:4]))
|
||||
}
|
||||
default:
|
||||
h.TotalLen = int(binary.BigEndian.Uint16(b[2:4]))
|
||||
|
||||
-13
@@ -1,13 +0,0 @@
|
||||
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
|
||||
|
||||
// Copyright 2021 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.
|
||||
|
||||
//go:build go1.18
|
||||
|
||||
package idna
|
||||
|
||||
// Transitional processing is disabled by default in Go 1.18.
|
||||
// https://golang.org/issue/47510
|
||||
const transitionalLookup = false
|
||||
Generated
Vendored
+152
-37
@@ -4,8 +4,6 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build go1.10
|
||||
|
||||
// Package idna implements IDNA2008 using the compatibility processing
|
||||
// defined by UTS (Unicode Technical Standard) #46, which defines a standard to
|
||||
// deal with the transition from IDNA2003.
|
||||
@@ -20,6 +18,7 @@ package idna // import "golang.org/x/net/idna"
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
|
||||
"golang.org/x/text/secure/bidirule"
|
||||
@@ -27,6 +26,8 @@ import (
|
||||
"golang.org/x/text/unicode/norm"
|
||||
)
|
||||
|
||||
const unicode16 = unicode.Version >= "16.0.0"
|
||||
|
||||
// NOTE: Unlike common practice in Go APIs, the functions will return a
|
||||
// sanitized domain name in case of errors. Browsers sometimes use a partially
|
||||
// evaluated string as lookup.
|
||||
@@ -101,6 +102,11 @@ func ValidateLabels(enable bool) Option {
|
||||
}
|
||||
}
|
||||
|
||||
// validateLabels reports whether the ValidateLabels option is enabled.
|
||||
func (p *Profile) validateLabels() bool {
|
||||
return p.fromPuny != nil
|
||||
}
|
||||
|
||||
// CheckHyphens sets whether to check for correct use of hyphens ('-') in
|
||||
// labels. Most web browsers do not have this option set, since labels such as
|
||||
// "r3---sn-apo3qvuoxuxbt-j5pe" are in common use.
|
||||
@@ -263,6 +269,10 @@ func (p *Profile) String() string {
|
||||
return s
|
||||
}
|
||||
|
||||
// Transitional processing is disabled by default as of Go 1.18.
|
||||
// https://golang.org/issue/47510
|
||||
const transitionalLookup = false
|
||||
|
||||
var (
|
||||
// Punycode is a Profile that does raw punycode processing with a minimum
|
||||
// of validation.
|
||||
@@ -324,15 +334,30 @@ func (e labelError) Error() string {
|
||||
return fmt.Sprintf("idna: invalid label %q", e.label)
|
||||
}
|
||||
|
||||
type runeError rune
|
||||
|
||||
func (e runeError) code() string { return "P1" }
|
||||
func (e runeError) Error() string {
|
||||
return fmt.Sprintf("idna: disallowed rune %U", e)
|
||||
type runeError struct {
|
||||
r rune
|
||||
code_ string
|
||||
}
|
||||
|
||||
// process implements the algorithm described in section 4 of UTS #46,
|
||||
// see https://www.unicode.org/reports/tr46.
|
||||
func (e runeError) code() string { return e.code_ }
|
||||
func (e runeError) Error() string {
|
||||
return fmt.Sprintf("idna: disallowed rune %U", e.r)
|
||||
}
|
||||
|
||||
// code16 returns old for Unicode < 16, new for Unicode >= 16.
|
||||
func code16(old, new string) string {
|
||||
if unicode16 {
|
||||
return new
|
||||
}
|
||||
return old
|
||||
}
|
||||
|
||||
// process10 implements the algorithm described in section 4 of UTS #46.
|
||||
// It implements both the Unicode 10 algorithm
|
||||
// (https://www.unicode.org/reports/tr46/tr46-19.html)
|
||||
// and the Unicode 16 algorithm
|
||||
// (https://www.unicode.org/reports/tr46/tr46-35.html)
|
||||
// depending on unicode16, which in turn depends on unicode.Version.
|
||||
func (p *Profile) process(s string, toASCII bool) (string, error) {
|
||||
var err error
|
||||
var isBidi bool
|
||||
@@ -347,8 +372,12 @@ func (p *Profile) process(s string, toASCII bool) (string, error) {
|
||||
// TODO: allow for a quick check of the tables data.
|
||||
// It seems like we should only create this error on ToASCII, but the
|
||||
// UTS 46 conformance tests suggests we should always check this.
|
||||
labelCode := "X4_2"
|
||||
if !unicode16 || toASCII {
|
||||
labelCode = "A4"
|
||||
}
|
||||
if err == nil && p.verifyDNSLength && s == "" {
|
||||
err = &labelError{s, "A4"}
|
||||
err = labelError{s, labelCode}
|
||||
}
|
||||
labels := labelIter{orig: s}
|
||||
for ; !labels.done(); labels.next() {
|
||||
@@ -357,12 +386,13 @@ func (p *Profile) process(s string, toASCII bool) (string, error) {
|
||||
// Empty labels are not okay. The label iterator skips the last
|
||||
// label if it is empty.
|
||||
if err == nil && p.verifyDNSLength {
|
||||
err = &labelError{s, "A4"}
|
||||
err = labelError{s, labelCode}
|
||||
}
|
||||
continue
|
||||
}
|
||||
if strings.HasPrefix(label, acePrefix) {
|
||||
u, err2 := decode(label[len(acePrefix):])
|
||||
enc := label[len(acePrefix):]
|
||||
u, err2 := decode(enc)
|
||||
if err2 != nil {
|
||||
if err == nil {
|
||||
err = err2
|
||||
@@ -370,6 +400,13 @@ func (p *Profile) process(s string, toASCII bool) (string, error) {
|
||||
// Spec says keep the old label.
|
||||
continue
|
||||
}
|
||||
if err == nil && len(u) > 0 && isASCII(u) {
|
||||
// UTS 43 pre-revision 33 doesn't classify a xn-- label
|
||||
// which contains only ASCII characters as an error,
|
||||
// but that's a specification bug and a security issue.
|
||||
// Always return an error in this case.
|
||||
err = punyError(enc)
|
||||
}
|
||||
isBidi = isBidi || bidirule.DirectionString(u) != bidi.LeftToRight
|
||||
labels.set(u)
|
||||
if err == nil && p.fromPuny != nil {
|
||||
@@ -379,16 +416,16 @@ func (p *Profile) process(s string, toASCII bool) (string, error) {
|
||||
// This should be called on NonTransitional, according to the
|
||||
// spec, but that currently does not have any effect. Use the
|
||||
// original profile to preserve options.
|
||||
err = p.validateLabel(u)
|
||||
err = p.validateLabel(u, labelCode)
|
||||
}
|
||||
} else if err == nil {
|
||||
err = p.validateLabel(label)
|
||||
err = p.validateLabel(label, labelCode)
|
||||
}
|
||||
}
|
||||
if isBidi && p.bidirule != nil && err == nil {
|
||||
for labels.reset(); !labels.done(); labels.next() {
|
||||
if !p.bidirule(labels.label()) {
|
||||
err = &labelError{s, "B"}
|
||||
err = labelError{s, "B"}
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -406,24 +443,36 @@ func (p *Profile) process(s string, toASCII bool) (string, error) {
|
||||
}
|
||||
n := len(label)
|
||||
if p.verifyDNSLength && err == nil && (n == 0 || n > 63) {
|
||||
err = &labelError{label, "A4"}
|
||||
err = labelError{label, labelCode}
|
||||
}
|
||||
}
|
||||
}
|
||||
s = labels.result()
|
||||
if toASCII && p.verifyDNSLength && err == nil {
|
||||
if unicode16 && strings.HasSuffix(s, ".") {
|
||||
err = labelError{s, labelCode}
|
||||
}
|
||||
// Compute the length of the domain name minus the root label and its dot.
|
||||
n := len(s)
|
||||
if n > 0 && s[n-1] == '.' {
|
||||
n--
|
||||
}
|
||||
if len(s) < 1 || n > 253 {
|
||||
err = &labelError{s, "A4"}
|
||||
err = labelError{s, labelCode}
|
||||
}
|
||||
}
|
||||
return s, err
|
||||
}
|
||||
|
||||
func isASCII(s string) bool {
|
||||
for _, c := range []byte(s) {
|
||||
if c >= 0x80 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func normalize(p *Profile, s string) (mapped string, isBidi bool, err error) {
|
||||
// TODO: consider first doing a quick check to see if any of these checks
|
||||
// need to be done. This will make it slower in the general case, but
|
||||
@@ -436,12 +485,12 @@ func normalize(p *Profile, s string) (mapped string, isBidi bool, err error) {
|
||||
func validateRegistration(p *Profile, s string) (idem string, bidi bool, err error) {
|
||||
// TODO: filter need for normalization in loop below.
|
||||
if !norm.NFC.IsNormalString(s) {
|
||||
return s, false, &labelError{s, "V1"}
|
||||
return s, false, labelError{s, "V1"}
|
||||
}
|
||||
for i := 0; i < len(s); {
|
||||
v, sz := trie.lookupString(s[i:])
|
||||
if sz == 0 {
|
||||
return s, bidi, runeError(utf8.RuneError)
|
||||
return s, bidi, runeError{utf8.RuneError, "P1"}
|
||||
}
|
||||
bidi = bidi || info(v).isBidi(s[i:])
|
||||
// Copy bytes not copied so far.
|
||||
@@ -449,9 +498,12 @@ func validateRegistration(p *Profile, s string) (idem string, bidi bool, err err
|
||||
// TODO: handle the NV8 defined in the Unicode idna data set to allow
|
||||
// for strict conformance to IDNA2008.
|
||||
case valid, deviation:
|
||||
if sz == 1 && p.useSTD3Rules && !allowedSTD3(rune(s[i])) {
|
||||
return s, bidi, runeError{rune(s[i]), "P1"}
|
||||
}
|
||||
case disallowed, mapped, unknown, ignored:
|
||||
r, _ := utf8.DecodeRuneInString(s[i:])
|
||||
return s, bidi, runeError(r)
|
||||
return s, bidi, runeError{r, "P1"}
|
||||
}
|
||||
i += sz
|
||||
}
|
||||
@@ -489,7 +541,7 @@ func validateAndMap(p *Profile, s string) (vm string, bidi bool, err error) {
|
||||
b = append(b, "\ufffd"...)
|
||||
k = len(s)
|
||||
if err == nil {
|
||||
err = runeError(utf8.RuneError)
|
||||
err = runeError{utf8.RuneError, "P1"}
|
||||
}
|
||||
break
|
||||
}
|
||||
@@ -502,14 +554,26 @@ func validateAndMap(p *Profile, s string) (vm string, bidi bool, err error) {
|
||||
case valid:
|
||||
continue
|
||||
case disallowed:
|
||||
if err == nil {
|
||||
// Unicode 16 delays the error until validateLabels.
|
||||
// Unicode 10 gave an error now.
|
||||
if !unicode16 && err == nil {
|
||||
r, _ := utf8.DecodeRuneInString(s[start:])
|
||||
err = runeError(r)
|
||||
err = runeError{r, "P1"}
|
||||
}
|
||||
continue
|
||||
case mapped, deviation:
|
||||
case deviation:
|
||||
if unicode16 && !p.transitional {
|
||||
break
|
||||
}
|
||||
fallthrough
|
||||
case mapped:
|
||||
b = append(b, s[k:start]...)
|
||||
b = info(v).appendMapping(b, s[start:i])
|
||||
// Unicode 16 requires a special case to handle ẞ -> ss in transitional mode.
|
||||
if unicode16 && p.transitional && s[start:start+sz] == "ẞ" {
|
||||
b = append(b, "ss"...)
|
||||
} else {
|
||||
b = info(v).appendMapping(b, s[start:i])
|
||||
}
|
||||
case ignored:
|
||||
b = append(b, s[k:start]...)
|
||||
// drop the rune
|
||||
@@ -600,13 +664,13 @@ const acePrefix = "xn--"
|
||||
|
||||
func (p *Profile) simplify(cat category) category {
|
||||
switch cat {
|
||||
case disallowedSTD3Mapped:
|
||||
case disallowedSTD3Mapped: // only happens for pre-Unicode 16
|
||||
if p.useSTD3Rules {
|
||||
cat = disallowed
|
||||
} else {
|
||||
cat = mapped
|
||||
}
|
||||
case disallowedSTD3Valid:
|
||||
case disallowedSTD3Valid: // only happens for pre-Unicode 16
|
||||
if p.useSTD3Rules {
|
||||
cat = disallowed
|
||||
} else {
|
||||
@@ -625,17 +689,18 @@ func (p *Profile) simplify(cat category) category {
|
||||
|
||||
func validateFromPunycode(p *Profile, s string) error {
|
||||
if !norm.NFC.IsNormalString(s) {
|
||||
return &labelError{s, "V1"}
|
||||
return labelError{s, "V1"}
|
||||
}
|
||||
// TODO: detect whether string may have to be normalized in the following
|
||||
// loop.
|
||||
for i := 0; i < len(s); {
|
||||
v, sz := trie.lookupString(s[i:])
|
||||
if sz == 0 {
|
||||
return runeError(utf8.RuneError)
|
||||
return runeError{utf8.RuneError, "P1"}
|
||||
}
|
||||
if c := p.simplify(info(v).category()); c != valid && c != deviation {
|
||||
return &labelError{s, "V6"}
|
||||
cat := info(v).category()
|
||||
if c := p.simplify(cat); c != valid && c != deviation {
|
||||
return labelError{s, code16("V6", "V7")}
|
||||
}
|
||||
i += sz
|
||||
}
|
||||
@@ -704,23 +769,51 @@ var joinStates = [][numJoinTypes]joinState{
|
||||
},
|
||||
}
|
||||
|
||||
// allowedSTD3 reports whether r is a rune that can appear in a domain name
|
||||
// according to STD3. We allow all non-ASCII runes and then letters, digits, hyphens.
|
||||
// We also add dot so that this can be run against the whole name and not just
|
||||
// a single name element (label). The surrounding code checks dots well enough.
|
||||
func allowedSTD3(r rune) bool {
|
||||
return r >= 0x80 || 'a' <= r && r <= 'z' || '0' <= r && r <= '9' || r == '-' || r == '.'
|
||||
}
|
||||
|
||||
// validateLabel validates the criteria from Section 4.1. Item 1, 4, and 6 are
|
||||
// already implicitly satisfied by the overall implementation.
|
||||
func (p *Profile) validateLabel(s string) (err error) {
|
||||
func (p *Profile) validateLabel(s string, labelCode string) (err error) {
|
||||
if s == "" {
|
||||
if p.verifyDNSLength {
|
||||
return &labelError{s, "A4"}
|
||||
return labelError{s, labelCode}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if p.checkHyphens {
|
||||
if len(s) > 4 && s[2] == '-' && s[3] == '-' {
|
||||
return &labelError{s, "V2"}
|
||||
return labelError{s, "V2"}
|
||||
}
|
||||
if s[0] == '-' || s[len(s)-1] == '-' {
|
||||
return &labelError{s, "V3"}
|
||||
return labelError{s, "V3"}
|
||||
}
|
||||
}
|
||||
|
||||
// Unicode 16's TR 46 delays the rune validity checks until after the label is decoded.
|
||||
// (validateAndMap did not reject them earlier.)
|
||||
if unicode16 && p.validateLabels() {
|
||||
for i := 0; i < len(s); {
|
||||
v, sz := trie.lookupString(s[i:])
|
||||
if sz == 0 {
|
||||
return runeError{utf8.RuneError, "P1"}
|
||||
}
|
||||
cat := info(v).category()
|
||||
if c := p.simplify(cat); c != valid && (!p.transitional || c != deviation) {
|
||||
return labelError{s, "V7"}
|
||||
}
|
||||
if sz == 1 && p.useSTD3Rules && !allowedSTD3(rune(s[i])) {
|
||||
return runeError{rune(s[i]), "U1"}
|
||||
}
|
||||
i += sz
|
||||
}
|
||||
}
|
||||
|
||||
if !p.checkJoiners {
|
||||
return nil
|
||||
}
|
||||
@@ -729,7 +822,7 @@ func (p *Profile) validateLabel(s string) (err error) {
|
||||
v, sz := trie.lookupString(s)
|
||||
x := info(v)
|
||||
if x.isModifier() {
|
||||
return &labelError{s, "V5"}
|
||||
return labelError{s, code16("V5", "V6")}
|
||||
}
|
||||
// Quickly return in the absence of zero-width (non) joiners.
|
||||
if strings.Index(s, zwj) == -1 && strings.Index(s, zwnj) == -1 {
|
||||
@@ -754,8 +847,9 @@ func (p *Profile) validateLabel(s string) (err error) {
|
||||
x = info(v)
|
||||
}
|
||||
if st == stateFAIL || st == stateAfter {
|
||||
return &labelError{s, "C"}
|
||||
return labelError{s, "C"}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -767,3 +861,24 @@ func ascii(s string) bool {
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// appendMapping appends the mapping for the respective rune. isMapped must be
|
||||
// true. A mapping is a categorization of a rune as defined in UTS #46.
|
||||
func (c info) appendMapping(b []byte, s string) []byte {
|
||||
index := int(c >> indexShift)
|
||||
if c&xorBit == 0 {
|
||||
p := index
|
||||
return append(b, mappings[mappingIndex[p]:mappingIndex[p+1]]...)
|
||||
}
|
||||
b = append(b, s...)
|
||||
if c&inlineXOR == inlineXOR {
|
||||
// TODO: support and handle two-byte inline masks
|
||||
b[len(b)-1] ^= byte(index)
|
||||
} else {
|
||||
for p := len(b) - int(xorData[index]); p < len(b); p++ {
|
||||
index++
|
||||
b[p] ^= xorData[index]
|
||||
}
|
||||
}
|
||||
return b
|
||||
}
|
||||
-717
@@ -1,717 +0,0 @@
|
||||
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
|
||||
|
||||
// Copyright 2016 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.
|
||||
|
||||
//go:build !go1.10
|
||||
|
||||
// Package idna implements IDNA2008 using the compatibility processing
|
||||
// defined by UTS (Unicode Technical Standard) #46, which defines a standard to
|
||||
// deal with the transition from IDNA2003.
|
||||
//
|
||||
// IDNA2008 (Internationalized Domain Names for Applications), is defined in RFC
|
||||
// 5890, RFC 5891, RFC 5892, RFC 5893 and RFC 5894.
|
||||
// UTS #46 is defined in https://www.unicode.org/reports/tr46.
|
||||
// See https://unicode.org/cldr/utility/idna.jsp for a visualization of the
|
||||
// differences between these two standards.
|
||||
package idna // import "golang.org/x/net/idna"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
|
||||
"golang.org/x/text/secure/bidirule"
|
||||
"golang.org/x/text/unicode/norm"
|
||||
)
|
||||
|
||||
// NOTE: Unlike common practice in Go APIs, the functions will return a
|
||||
// sanitized domain name in case of errors. Browsers sometimes use a partially
|
||||
// evaluated string as lookup.
|
||||
// TODO: the current error handling is, in my opinion, the least opinionated.
|
||||
// Other strategies are also viable, though:
|
||||
// Option 1) Return an empty string in case of error, but allow the user to
|
||||
// specify explicitly which errors to ignore.
|
||||
// Option 2) Return the partially evaluated string if it is itself a valid
|
||||
// string, otherwise return the empty string in case of error.
|
||||
// Option 3) Option 1 and 2.
|
||||
// Option 4) Always return an empty string for now and implement Option 1 as
|
||||
// needed, and document that the return string may not be empty in case of
|
||||
// error in the future.
|
||||
// I think Option 1 is best, but it is quite opinionated.
|
||||
|
||||
// ToASCII is a wrapper for Punycode.ToASCII.
|
||||
func ToASCII(s string) (string, error) {
|
||||
return Punycode.process(s, true)
|
||||
}
|
||||
|
||||
// ToUnicode is a wrapper for Punycode.ToUnicode.
|
||||
func ToUnicode(s string) (string, error) {
|
||||
return Punycode.process(s, false)
|
||||
}
|
||||
|
||||
// An Option configures a Profile at creation time.
|
||||
type Option func(*options)
|
||||
|
||||
// Transitional sets a Profile to use the Transitional mapping as defined in UTS
|
||||
// #46. This will cause, for example, "ß" to be mapped to "ss". Using the
|
||||
// transitional mapping provides a compromise between IDNA2003 and IDNA2008
|
||||
// compatibility. It is used by some browsers when resolving domain names. This
|
||||
// option is only meaningful if combined with MapForLookup.
|
||||
func Transitional(transitional bool) Option {
|
||||
return func(o *options) { o.transitional = transitional }
|
||||
}
|
||||
|
||||
// VerifyDNSLength sets whether a Profile should fail if any of the IDN parts
|
||||
// are longer than allowed by the RFC.
|
||||
//
|
||||
// This option corresponds to the VerifyDnsLength flag in UTS #46.
|
||||
func VerifyDNSLength(verify bool) Option {
|
||||
return func(o *options) { o.verifyDNSLength = verify }
|
||||
}
|
||||
|
||||
// RemoveLeadingDots removes leading label separators. Leading runes that map to
|
||||
// dots, such as U+3002 IDEOGRAPHIC FULL STOP, are removed as well.
|
||||
func RemoveLeadingDots(remove bool) Option {
|
||||
return func(o *options) { o.removeLeadingDots = remove }
|
||||
}
|
||||
|
||||
// ValidateLabels sets whether to check the mandatory label validation criteria
|
||||
// as defined in Section 5.4 of RFC 5891. This includes testing for correct use
|
||||
// of hyphens ('-'), normalization, validity of runes, and the context rules.
|
||||
// In particular, ValidateLabels also sets the CheckHyphens and CheckJoiners flags
|
||||
// in UTS #46.
|
||||
func ValidateLabels(enable bool) Option {
|
||||
return func(o *options) {
|
||||
// Don't override existing mappings, but set one that at least checks
|
||||
// normalization if it is not set.
|
||||
if o.mapping == nil && enable {
|
||||
o.mapping = normalize
|
||||
}
|
||||
o.trie = trie
|
||||
o.checkJoiners = enable
|
||||
o.checkHyphens = enable
|
||||
if enable {
|
||||
o.fromPuny = validateFromPunycode
|
||||
} else {
|
||||
o.fromPuny = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// CheckHyphens sets whether to check for correct use of hyphens ('-') in
|
||||
// labels. Most web browsers do not have this option set, since labels such as
|
||||
// "r3---sn-apo3qvuoxuxbt-j5pe" are in common use.
|
||||
//
|
||||
// This option corresponds to the CheckHyphens flag in UTS #46.
|
||||
func CheckHyphens(enable bool) Option {
|
||||
return func(o *options) { o.checkHyphens = enable }
|
||||
}
|
||||
|
||||
// CheckJoiners sets whether to check the ContextJ rules as defined in Appendix
|
||||
// A of RFC 5892, concerning the use of joiner runes.
|
||||
//
|
||||
// This option corresponds to the CheckJoiners flag in UTS #46.
|
||||
func CheckJoiners(enable bool) Option {
|
||||
return func(o *options) {
|
||||
o.trie = trie
|
||||
o.checkJoiners = enable
|
||||
}
|
||||
}
|
||||
|
||||
// StrictDomainName limits the set of permissible ASCII characters to those
|
||||
// allowed in domain names as defined in RFC 1034 (A-Z, a-z, 0-9 and the
|
||||
// hyphen). This is set by default for MapForLookup and ValidateForRegistration,
|
||||
// but is only useful if ValidateLabels is set.
|
||||
//
|
||||
// This option is useful, for instance, for browsers that allow characters
|
||||
// outside this range, for example a '_' (U+005F LOW LINE). See
|
||||
// http://www.rfc-editor.org/std/std3.txt for more details.
|
||||
//
|
||||
// This option corresponds to the UseSTD3ASCIIRules flag in UTS #46.
|
||||
func StrictDomainName(use bool) Option {
|
||||
return func(o *options) { o.useSTD3Rules = use }
|
||||
}
|
||||
|
||||
// NOTE: the following options pull in tables. The tables should not be linked
|
||||
// in as long as the options are not used.
|
||||
|
||||
// BidiRule enables the Bidi rule as defined in RFC 5893. Any application
|
||||
// that relies on proper validation of labels should include this rule.
|
||||
//
|
||||
// This option corresponds to the CheckBidi flag in UTS #46.
|
||||
func BidiRule() Option {
|
||||
return func(o *options) { o.bidirule = bidirule.ValidString }
|
||||
}
|
||||
|
||||
// ValidateForRegistration sets validation options to verify that a given IDN is
|
||||
// properly formatted for registration as defined by Section 4 of RFC 5891.
|
||||
func ValidateForRegistration() Option {
|
||||
return func(o *options) {
|
||||
o.mapping = validateRegistration
|
||||
StrictDomainName(true)(o)
|
||||
ValidateLabels(true)(o)
|
||||
VerifyDNSLength(true)(o)
|
||||
BidiRule()(o)
|
||||
}
|
||||
}
|
||||
|
||||
// MapForLookup sets validation and mapping options such that a given IDN is
|
||||
// transformed for domain name lookup according to the requirements set out in
|
||||
// Section 5 of RFC 5891. The mappings follow the recommendations of RFC 5894,
|
||||
// RFC 5895 and UTS 46. It does not add the Bidi Rule. Use the BidiRule option
|
||||
// to add this check.
|
||||
//
|
||||
// The mappings include normalization and mapping case, width and other
|
||||
// compatibility mappings.
|
||||
func MapForLookup() Option {
|
||||
return func(o *options) {
|
||||
o.mapping = validateAndMap
|
||||
StrictDomainName(true)(o)
|
||||
ValidateLabels(true)(o)
|
||||
RemoveLeadingDots(true)(o)
|
||||
}
|
||||
}
|
||||
|
||||
type options struct {
|
||||
transitional bool
|
||||
useSTD3Rules bool
|
||||
checkHyphens bool
|
||||
checkJoiners bool
|
||||
verifyDNSLength bool
|
||||
removeLeadingDots bool
|
||||
|
||||
trie *idnaTrie
|
||||
|
||||
// fromPuny calls validation rules when converting A-labels to U-labels.
|
||||
fromPuny func(p *Profile, s string) error
|
||||
|
||||
// mapping implements a validation and mapping step as defined in RFC 5895
|
||||
// or UTS 46, tailored to, for example, domain registration or lookup.
|
||||
mapping func(p *Profile, s string) (string, error)
|
||||
|
||||
// bidirule, if specified, checks whether s conforms to the Bidi Rule
|
||||
// defined in RFC 5893.
|
||||
bidirule func(s string) bool
|
||||
}
|
||||
|
||||
// A Profile defines the configuration of a IDNA mapper.
|
||||
type Profile struct {
|
||||
options
|
||||
}
|
||||
|
||||
func apply(o *options, opts []Option) {
|
||||
for _, f := range opts {
|
||||
f(o)
|
||||
}
|
||||
}
|
||||
|
||||
// New creates a new Profile.
|
||||
//
|
||||
// With no options, the returned Profile is the most permissive and equals the
|
||||
// Punycode Profile. Options can be passed to further restrict the Profile. The
|
||||
// MapForLookup and ValidateForRegistration options set a collection of options,
|
||||
// for lookup and registration purposes respectively, which can be tailored by
|
||||
// adding more fine-grained options, where later options override earlier
|
||||
// options.
|
||||
func New(o ...Option) *Profile {
|
||||
p := &Profile{}
|
||||
apply(&p.options, o)
|
||||
return p
|
||||
}
|
||||
|
||||
// ToASCII converts a domain or domain label to its ASCII form. For example,
|
||||
// ToASCII("bücher.example.com") is "xn--bcher-kva.example.com", and
|
||||
// ToASCII("golang") is "golang". If an error is encountered it will return
|
||||
// an error and a (partially) processed result.
|
||||
func (p *Profile) ToASCII(s string) (string, error) {
|
||||
return p.process(s, true)
|
||||
}
|
||||
|
||||
// ToUnicode converts a domain or domain label to its Unicode form. For example,
|
||||
// ToUnicode("xn--bcher-kva.example.com") is "bücher.example.com", and
|
||||
// ToUnicode("golang") is "golang". If an error is encountered it will return
|
||||
// an error and a (partially) processed result.
|
||||
func (p *Profile) ToUnicode(s string) (string, error) {
|
||||
pp := *p
|
||||
pp.transitional = false
|
||||
return pp.process(s, false)
|
||||
}
|
||||
|
||||
// String reports a string with a description of the profile for debugging
|
||||
// purposes. The string format may change with different versions.
|
||||
func (p *Profile) String() string {
|
||||
s := ""
|
||||
if p.transitional {
|
||||
s = "Transitional"
|
||||
} else {
|
||||
s = "NonTransitional"
|
||||
}
|
||||
if p.useSTD3Rules {
|
||||
s += ":UseSTD3Rules"
|
||||
}
|
||||
if p.checkHyphens {
|
||||
s += ":CheckHyphens"
|
||||
}
|
||||
if p.checkJoiners {
|
||||
s += ":CheckJoiners"
|
||||
}
|
||||
if p.verifyDNSLength {
|
||||
s += ":VerifyDNSLength"
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
var (
|
||||
// Punycode is a Profile that does raw punycode processing with a minimum
|
||||
// of validation.
|
||||
Punycode *Profile = punycode
|
||||
|
||||
// Lookup is the recommended profile for looking up domain names, according
|
||||
// to Section 5 of RFC 5891. The exact configuration of this profile may
|
||||
// change over time.
|
||||
Lookup *Profile = lookup
|
||||
|
||||
// Display is the recommended profile for displaying domain names.
|
||||
// The configuration of this profile may change over time.
|
||||
Display *Profile = display
|
||||
|
||||
// Registration is the recommended profile for checking whether a given
|
||||
// IDN is valid for registration, according to Section 4 of RFC 5891.
|
||||
Registration *Profile = registration
|
||||
|
||||
punycode = &Profile{}
|
||||
lookup = &Profile{options{
|
||||
transitional: true,
|
||||
removeLeadingDots: true,
|
||||
useSTD3Rules: true,
|
||||
checkHyphens: true,
|
||||
checkJoiners: true,
|
||||
trie: trie,
|
||||
fromPuny: validateFromPunycode,
|
||||
mapping: validateAndMap,
|
||||
bidirule: bidirule.ValidString,
|
||||
}}
|
||||
display = &Profile{options{
|
||||
useSTD3Rules: true,
|
||||
removeLeadingDots: true,
|
||||
checkHyphens: true,
|
||||
checkJoiners: true,
|
||||
trie: trie,
|
||||
fromPuny: validateFromPunycode,
|
||||
mapping: validateAndMap,
|
||||
bidirule: bidirule.ValidString,
|
||||
}}
|
||||
registration = &Profile{options{
|
||||
useSTD3Rules: true,
|
||||
verifyDNSLength: true,
|
||||
checkHyphens: true,
|
||||
checkJoiners: true,
|
||||
trie: trie,
|
||||
fromPuny: validateFromPunycode,
|
||||
mapping: validateRegistration,
|
||||
bidirule: bidirule.ValidString,
|
||||
}}
|
||||
|
||||
// TODO: profiles
|
||||
// Register: recommended for approving domain names: don't do any mappings
|
||||
// but rather reject on invalid input. Bundle or block deviation characters.
|
||||
)
|
||||
|
||||
type labelError struct{ label, code_ string }
|
||||
|
||||
func (e labelError) code() string { return e.code_ }
|
||||
func (e labelError) Error() string {
|
||||
return fmt.Sprintf("idna: invalid label %q", e.label)
|
||||
}
|
||||
|
||||
type runeError rune
|
||||
|
||||
func (e runeError) code() string { return "P1" }
|
||||
func (e runeError) Error() string {
|
||||
return fmt.Sprintf("idna: disallowed rune %U", e)
|
||||
}
|
||||
|
||||
// process implements the algorithm described in section 4 of UTS #46,
|
||||
// see https://www.unicode.org/reports/tr46.
|
||||
func (p *Profile) process(s string, toASCII bool) (string, error) {
|
||||
var err error
|
||||
if p.mapping != nil {
|
||||
s, err = p.mapping(p, s)
|
||||
}
|
||||
// Remove leading empty labels.
|
||||
if p.removeLeadingDots {
|
||||
for ; len(s) > 0 && s[0] == '.'; s = s[1:] {
|
||||
}
|
||||
}
|
||||
// It seems like we should only create this error on ToASCII, but the
|
||||
// UTS 46 conformance tests suggests we should always check this.
|
||||
if err == nil && p.verifyDNSLength && s == "" {
|
||||
err = &labelError{s, "A4"}
|
||||
}
|
||||
labels := labelIter{orig: s}
|
||||
for ; !labels.done(); labels.next() {
|
||||
label := labels.label()
|
||||
if label == "" {
|
||||
// Empty labels are not okay. The label iterator skips the last
|
||||
// label if it is empty.
|
||||
if err == nil && p.verifyDNSLength {
|
||||
err = &labelError{s, "A4"}
|
||||
}
|
||||
continue
|
||||
}
|
||||
if strings.HasPrefix(label, acePrefix) {
|
||||
u, err2 := decode(label[len(acePrefix):])
|
||||
if err2 != nil {
|
||||
if err == nil {
|
||||
err = err2
|
||||
}
|
||||
// Spec says keep the old label.
|
||||
continue
|
||||
}
|
||||
labels.set(u)
|
||||
if err == nil && p.fromPuny != nil {
|
||||
err = p.fromPuny(p, u)
|
||||
}
|
||||
if err == nil {
|
||||
// This should be called on NonTransitional, according to the
|
||||
// spec, but that currently does not have any effect. Use the
|
||||
// original profile to preserve options.
|
||||
err = p.validateLabel(u)
|
||||
}
|
||||
} else if err == nil {
|
||||
err = p.validateLabel(label)
|
||||
}
|
||||
}
|
||||
if toASCII {
|
||||
for labels.reset(); !labels.done(); labels.next() {
|
||||
label := labels.label()
|
||||
if !ascii(label) {
|
||||
a, err2 := encode(acePrefix, label)
|
||||
if err == nil {
|
||||
err = err2
|
||||
}
|
||||
label = a
|
||||
labels.set(a)
|
||||
}
|
||||
n := len(label)
|
||||
if p.verifyDNSLength && err == nil && (n == 0 || n > 63) {
|
||||
err = &labelError{label, "A4"}
|
||||
}
|
||||
}
|
||||
}
|
||||
s = labels.result()
|
||||
if toASCII && p.verifyDNSLength && err == nil {
|
||||
// Compute the length of the domain name minus the root label and its dot.
|
||||
n := len(s)
|
||||
if n > 0 && s[n-1] == '.' {
|
||||
n--
|
||||
}
|
||||
if len(s) < 1 || n > 253 {
|
||||
err = &labelError{s, "A4"}
|
||||
}
|
||||
}
|
||||
return s, err
|
||||
}
|
||||
|
||||
func normalize(p *Profile, s string) (string, error) {
|
||||
return norm.NFC.String(s), nil
|
||||
}
|
||||
|
||||
func validateRegistration(p *Profile, s string) (string, error) {
|
||||
if !norm.NFC.IsNormalString(s) {
|
||||
return s, &labelError{s, "V1"}
|
||||
}
|
||||
for i := 0; i < len(s); {
|
||||
v, sz := trie.lookupString(s[i:])
|
||||
// Copy bytes not copied so far.
|
||||
switch p.simplify(info(v).category()) {
|
||||
// TODO: handle the NV8 defined in the Unicode idna data set to allow
|
||||
// for strict conformance to IDNA2008.
|
||||
case valid, deviation:
|
||||
case disallowed, mapped, unknown, ignored:
|
||||
r, _ := utf8.DecodeRuneInString(s[i:])
|
||||
return s, runeError(r)
|
||||
}
|
||||
i += sz
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func validateAndMap(p *Profile, s string) (string, error) {
|
||||
var (
|
||||
err error
|
||||
b []byte
|
||||
k int
|
||||
)
|
||||
for i := 0; i < len(s); {
|
||||
v, sz := trie.lookupString(s[i:])
|
||||
start := i
|
||||
i += sz
|
||||
// Copy bytes not copied so far.
|
||||
switch p.simplify(info(v).category()) {
|
||||
case valid:
|
||||
continue
|
||||
case disallowed:
|
||||
if err == nil {
|
||||
r, _ := utf8.DecodeRuneInString(s[start:])
|
||||
err = runeError(r)
|
||||
}
|
||||
continue
|
||||
case mapped, deviation:
|
||||
b = append(b, s[k:start]...)
|
||||
b = info(v).appendMapping(b, s[start:i])
|
||||
case ignored:
|
||||
b = append(b, s[k:start]...)
|
||||
// drop the rune
|
||||
case unknown:
|
||||
b = append(b, s[k:start]...)
|
||||
b = append(b, "\ufffd"...)
|
||||
}
|
||||
k = i
|
||||
}
|
||||
if k == 0 {
|
||||
// No changes so far.
|
||||
s = norm.NFC.String(s)
|
||||
} else {
|
||||
b = append(b, s[k:]...)
|
||||
if norm.NFC.QuickSpan(b) != len(b) {
|
||||
b = norm.NFC.Bytes(b)
|
||||
}
|
||||
// TODO: the punycode converters require strings as input.
|
||||
s = string(b)
|
||||
}
|
||||
return s, err
|
||||
}
|
||||
|
||||
// A labelIter allows iterating over domain name labels.
|
||||
type labelIter struct {
|
||||
orig string
|
||||
slice []string
|
||||
curStart int
|
||||
curEnd int
|
||||
i int
|
||||
}
|
||||
|
||||
func (l *labelIter) reset() {
|
||||
l.curStart = 0
|
||||
l.curEnd = 0
|
||||
l.i = 0
|
||||
}
|
||||
|
||||
func (l *labelIter) done() bool {
|
||||
return l.curStart >= len(l.orig)
|
||||
}
|
||||
|
||||
func (l *labelIter) result() string {
|
||||
if l.slice != nil {
|
||||
return strings.Join(l.slice, ".")
|
||||
}
|
||||
return l.orig
|
||||
}
|
||||
|
||||
func (l *labelIter) label() string {
|
||||
if l.slice != nil {
|
||||
return l.slice[l.i]
|
||||
}
|
||||
p := strings.IndexByte(l.orig[l.curStart:], '.')
|
||||
l.curEnd = l.curStart + p
|
||||
if p == -1 {
|
||||
l.curEnd = len(l.orig)
|
||||
}
|
||||
return l.orig[l.curStart:l.curEnd]
|
||||
}
|
||||
|
||||
// next sets the value to the next label. It skips the last label if it is empty.
|
||||
func (l *labelIter) next() {
|
||||
l.i++
|
||||
if l.slice != nil {
|
||||
if l.i >= len(l.slice) || l.i == len(l.slice)-1 && l.slice[l.i] == "" {
|
||||
l.curStart = len(l.orig)
|
||||
}
|
||||
} else {
|
||||
l.curStart = l.curEnd + 1
|
||||
if l.curStart == len(l.orig)-1 && l.orig[l.curStart] == '.' {
|
||||
l.curStart = len(l.orig)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (l *labelIter) set(s string) {
|
||||
if l.slice == nil {
|
||||
l.slice = strings.Split(l.orig, ".")
|
||||
}
|
||||
l.slice[l.i] = s
|
||||
}
|
||||
|
||||
// acePrefix is the ASCII Compatible Encoding prefix.
|
||||
const acePrefix = "xn--"
|
||||
|
||||
func (p *Profile) simplify(cat category) category {
|
||||
switch cat {
|
||||
case disallowedSTD3Mapped:
|
||||
if p.useSTD3Rules {
|
||||
cat = disallowed
|
||||
} else {
|
||||
cat = mapped
|
||||
}
|
||||
case disallowedSTD3Valid:
|
||||
if p.useSTD3Rules {
|
||||
cat = disallowed
|
||||
} else {
|
||||
cat = valid
|
||||
}
|
||||
case deviation:
|
||||
if !p.transitional {
|
||||
cat = valid
|
||||
}
|
||||
case validNV8, validXV8:
|
||||
// TODO: handle V2008
|
||||
cat = valid
|
||||
}
|
||||
return cat
|
||||
}
|
||||
|
||||
func validateFromPunycode(p *Profile, s string) error {
|
||||
if !norm.NFC.IsNormalString(s) {
|
||||
return &labelError{s, "V1"}
|
||||
}
|
||||
for i := 0; i < len(s); {
|
||||
v, sz := trie.lookupString(s[i:])
|
||||
if c := p.simplify(info(v).category()); c != valid && c != deviation {
|
||||
return &labelError{s, "V6"}
|
||||
}
|
||||
i += sz
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
const (
|
||||
zwnj = "\u200c"
|
||||
zwj = "\u200d"
|
||||
)
|
||||
|
||||
type joinState int8
|
||||
|
||||
const (
|
||||
stateStart joinState = iota
|
||||
stateVirama
|
||||
stateBefore
|
||||
stateBeforeVirama
|
||||
stateAfter
|
||||
stateFAIL
|
||||
)
|
||||
|
||||
var joinStates = [][numJoinTypes]joinState{
|
||||
stateStart: {
|
||||
joiningL: stateBefore,
|
||||
joiningD: stateBefore,
|
||||
joinZWNJ: stateFAIL,
|
||||
joinZWJ: stateFAIL,
|
||||
joinVirama: stateVirama,
|
||||
},
|
||||
stateVirama: {
|
||||
joiningL: stateBefore,
|
||||
joiningD: stateBefore,
|
||||
},
|
||||
stateBefore: {
|
||||
joiningL: stateBefore,
|
||||
joiningD: stateBefore,
|
||||
joiningT: stateBefore,
|
||||
joinZWNJ: stateAfter,
|
||||
joinZWJ: stateFAIL,
|
||||
joinVirama: stateBeforeVirama,
|
||||
},
|
||||
stateBeforeVirama: {
|
||||
joiningL: stateBefore,
|
||||
joiningD: stateBefore,
|
||||
joiningT: stateBefore,
|
||||
},
|
||||
stateAfter: {
|
||||
joiningL: stateFAIL,
|
||||
joiningD: stateBefore,
|
||||
joiningT: stateAfter,
|
||||
joiningR: stateStart,
|
||||
joinZWNJ: stateFAIL,
|
||||
joinZWJ: stateFAIL,
|
||||
joinVirama: stateAfter, // no-op as we can't accept joiners here
|
||||
},
|
||||
stateFAIL: {
|
||||
0: stateFAIL,
|
||||
joiningL: stateFAIL,
|
||||
joiningD: stateFAIL,
|
||||
joiningT: stateFAIL,
|
||||
joiningR: stateFAIL,
|
||||
joinZWNJ: stateFAIL,
|
||||
joinZWJ: stateFAIL,
|
||||
joinVirama: stateFAIL,
|
||||
},
|
||||
}
|
||||
|
||||
// validateLabel validates the criteria from Section 4.1. Item 1, 4, and 6 are
|
||||
// already implicitly satisfied by the overall implementation.
|
||||
func (p *Profile) validateLabel(s string) error {
|
||||
if s == "" {
|
||||
if p.verifyDNSLength {
|
||||
return &labelError{s, "A4"}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if p.bidirule != nil && !p.bidirule(s) {
|
||||
return &labelError{s, "B"}
|
||||
}
|
||||
if p.checkHyphens {
|
||||
if len(s) > 4 && s[2] == '-' && s[3] == '-' {
|
||||
return &labelError{s, "V2"}
|
||||
}
|
||||
if s[0] == '-' || s[len(s)-1] == '-' {
|
||||
return &labelError{s, "V3"}
|
||||
}
|
||||
}
|
||||
if !p.checkJoiners {
|
||||
return nil
|
||||
}
|
||||
trie := p.trie // p.checkJoiners is only set if trie is set.
|
||||
// TODO: merge the use of this in the trie.
|
||||
v, sz := trie.lookupString(s)
|
||||
x := info(v)
|
||||
if x.isModifier() {
|
||||
return &labelError{s, "V5"}
|
||||
}
|
||||
// Quickly return in the absence of zero-width (non) joiners.
|
||||
if strings.Index(s, zwj) == -1 && strings.Index(s, zwnj) == -1 {
|
||||
return nil
|
||||
}
|
||||
st := stateStart
|
||||
for i := 0; ; {
|
||||
jt := x.joinType()
|
||||
if s[i:i+sz] == zwj {
|
||||
jt = joinZWJ
|
||||
} else if s[i:i+sz] == zwnj {
|
||||
jt = joinZWNJ
|
||||
}
|
||||
st = joinStates[st][jt]
|
||||
if x.isViramaModifier() {
|
||||
st = joinStates[st][joinVirama]
|
||||
}
|
||||
if i += sz; i == len(s) {
|
||||
break
|
||||
}
|
||||
v, sz = trie.lookupString(s[i:])
|
||||
x = info(v)
|
||||
}
|
||||
if st == stateFAIL || st == stateAfter {
|
||||
return &labelError{s, "C"}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ascii(s string) bool {
|
||||
for i := 0; i < len(s); i++ {
|
||||
if s[i] >= utf8.RuneSelf {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
-11
@@ -1,11 +0,0 @@
|
||||
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
|
||||
|
||||
// Copyright 2021 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.
|
||||
|
||||
//go:build !go1.18
|
||||
|
||||
package idna
|
||||
|
||||
const transitionalLookup = true
|
||||
+4
-1
@@ -28,7 +28,7 @@ const (
|
||||
tmin int32 = 1
|
||||
)
|
||||
|
||||
func punyError(s string) error { return &labelError{s, "A3"} }
|
||||
func punyError(s string) error { return &labelError{s, code16("A3", "P4")} }
|
||||
|
||||
// decode decodes a string as specified in section 6.2.
|
||||
func decode(encoded string) (string, error) {
|
||||
@@ -108,6 +108,9 @@ func encode(prefix, s string) (string, error) {
|
||||
delta, n, bias := int32(0), initialN, initialBias
|
||||
b, remaining := int32(0), int32(0)
|
||||
for _, r := range s {
|
||||
if unicode16 && r == 0xfffd {
|
||||
return s, &labelError{s, "A3"}
|
||||
}
|
||||
if r < 0x80 {
|
||||
b++
|
||||
output = append(output, byte(r))
|
||||
|
||||
-4559
File diff suppressed because it is too large.
Load diff
-4653
File diff suppressed because it is too large.
Load diff
-4733
File diff suppressed because it is too large.
Load diff
-4959
File diff suppressed because it is too large.
Load diff
+1
-1
@@ -1,6 +1,6 @@
|
||||
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
|
||||
|
||||
//go:build go1.21
|
||||
//go:build !go1.27
|
||||
|
||||
package idna
|
||||
|
||||
|
||||
+5302
File diff suppressed because it is too large.
Load diff
-4486
File diff suppressed because it is too large.
Load diff
-30
@@ -1,30 +0,0 @@
|
||||
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
|
||||
|
||||
// Copyright 2016 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.
|
||||
|
||||
//go:build !go1.16
|
||||
|
||||
package idna
|
||||
|
||||
// appendMapping appends the mapping for the respective rune. isMapped must be
|
||||
// true. A mapping is a categorization of a rune as defined in UTS #46.
|
||||
func (c info) appendMapping(b []byte, s string) []byte {
|
||||
index := int(c >> indexShift)
|
||||
if c&xorBit == 0 {
|
||||
s := mappings[index:]
|
||||
return append(b, s[1:s[0]+1]...)
|
||||
}
|
||||
b = append(b, s...)
|
||||
if c&inlineXOR == inlineXOR {
|
||||
// TODO: support and handle two-byte inline masks
|
||||
b[len(b)-1] ^= byte(index)
|
||||
} else {
|
||||
for p := len(b) - int(xorData[index]); p < len(b); p++ {
|
||||
index++
|
||||
b[p] ^= xorData[index]
|
||||
}
|
||||
}
|
||||
return b
|
||||
}
|
||||
-30
@@ -1,30 +0,0 @@
|
||||
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
|
||||
|
||||
// Copyright 2016 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.
|
||||
|
||||
//go:build go1.16
|
||||
|
||||
package idna
|
||||
|
||||
// appendMapping appends the mapping for the respective rune. isMapped must be
|
||||
// true. A mapping is a categorization of a rune as defined in UTS #46.
|
||||
func (c info) appendMapping(b []byte, s string) []byte {
|
||||
index := int(c >> indexShift)
|
||||
if c&xorBit == 0 {
|
||||
p := index
|
||||
return append(b, mappings[mappingIndex[p]:mappingIndex[p+1]]...)
|
||||
}
|
||||
b = append(b, s...)
|
||||
if c&inlineXOR == inlineXOR {
|
||||
// TODO: support and handle two-byte inline masks
|
||||
b[len(b)-1] ^= byte(index)
|
||||
} else {
|
||||
for p := len(b) - int(xorData[index]); p < len(b); p++ {
|
||||
index++
|
||||
b[p] ^= xorData[index]
|
||||
}
|
||||
}
|
||||
return b
|
||||
}
|
||||
+1
-1
@@ -2,6 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build darwin && go1.12
|
||||
//go:build darwin
|
||||
|
||||
// This exists solely so we can linkname in symbols from syscall.
|
||||
+5
-2
@@ -6,7 +6,10 @@
|
||||
|
||||
package socket
|
||||
|
||||
import "unsafe"
|
||||
import (
|
||||
"encoding/binary"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func (h *msghdr) pack(vs []iovec, bs [][]byte, oob []byte, sa []byte) {
|
||||
for i := range vs {
|
||||
@@ -31,5 +34,5 @@ func (h *msghdr) controllen() int {
|
||||
}
|
||||
|
||||
func (h *msghdr) flags() int {
|
||||
return int(NativeEndian.Uint32(h.Pad_cgo_2[:]))
|
||||
return int(binary.NativeEndian.Uint32(h.Pad_cgo_2[:]))
|
||||
}
|
||||
+3
-2
@@ -7,6 +7,7 @@
|
||||
package socket // import "golang.org/x/net/internal/socket"
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"net"
|
||||
"runtime"
|
||||
@@ -58,7 +59,7 @@ func (o *Option) GetInt(c *Conn) (int, error) {
|
||||
if o.Len == 1 {
|
||||
return int(b[0]), nil
|
||||
}
|
||||
return int(NativeEndian.Uint32(b[:4])), nil
|
||||
return int(binary.NativeEndian.Uint32(b[:4])), nil
|
||||
}
|
||||
|
||||
// Set writes the option and value to the kernel.
|
||||
@@ -84,7 +85,7 @@ func (o *Option) SetInt(c *Conn, v int) error {
|
||||
b = []byte{byte(v)}
|
||||
} else {
|
||||
var bb [4]byte
|
||||
NativeEndian.PutUint32(bb[:o.Len], uint32(v))
|
||||
binary.NativeEndian.PutUint32(bb[:o.Len], uint32(v))
|
||||
b = bb[:4]
|
||||
}
|
||||
return o.set(c, b)
|
||||
|
||||
-23
@@ -1,23 +0,0 @@
|
||||
// Copyright 2017 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 socket
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// NativeEndian is the machine native endian implementation of ByteOrder.
|
||||
var NativeEndian binary.ByteOrder
|
||||
|
||||
func init() {
|
||||
i := uint32(1)
|
||||
b := (*[4]byte)(unsafe.Pointer(&i))
|
||||
if b[0] == 1 {
|
||||
NativeEndian = binary.LittleEndian
|
||||
} else {
|
||||
NativeEndian = binary.BigEndian
|
||||
}
|
||||
}
|
||||
+5
-5
@@ -36,7 +36,7 @@ func marshalSockaddr(ip net.IP, port int, zone string, b []byte) int {
|
||||
if ip4 := ip.To4(); ip4 != nil {
|
||||
switch runtime.GOOS {
|
||||
case "android", "illumos", "linux", "solaris", "windows":
|
||||
NativeEndian.PutUint16(b[:2], uint16(sysAF_INET))
|
||||
binary.NativeEndian.PutUint16(b[:2], uint16(sysAF_INET))
|
||||
default:
|
||||
b[0] = sizeofSockaddrInet4
|
||||
b[1] = sysAF_INET
|
||||
@@ -48,7 +48,7 @@ func marshalSockaddr(ip net.IP, port int, zone string, b []byte) int {
|
||||
if ip6 := ip.To16(); ip6 != nil && ip.To4() == nil {
|
||||
switch runtime.GOOS {
|
||||
case "android", "illumos", "linux", "solaris", "windows":
|
||||
NativeEndian.PutUint16(b[:2], uint16(sysAF_INET6))
|
||||
binary.NativeEndian.PutUint16(b[:2], uint16(sysAF_INET6))
|
||||
default:
|
||||
b[0] = sizeofSockaddrInet6
|
||||
b[1] = sysAF_INET6
|
||||
@@ -56,7 +56,7 @@ func marshalSockaddr(ip net.IP, port int, zone string, b []byte) int {
|
||||
binary.BigEndian.PutUint16(b[2:4], uint16(port))
|
||||
copy(b[8:24], ip6)
|
||||
if zone != "" {
|
||||
NativeEndian.PutUint32(b[24:28], uint32(zoneCache.index(zone)))
|
||||
binary.NativeEndian.PutUint32(b[24:28], uint32(zoneCache.index(zone)))
|
||||
}
|
||||
return sizeofSockaddrInet6
|
||||
}
|
||||
@@ -70,7 +70,7 @@ func parseInetAddr(b []byte, network string) (net.Addr, error) {
|
||||
var af int
|
||||
switch runtime.GOOS {
|
||||
case "android", "illumos", "linux", "solaris", "windows":
|
||||
af = int(NativeEndian.Uint16(b[:2]))
|
||||
af = int(binary.NativeEndian.Uint16(b[:2]))
|
||||
default:
|
||||
af = int(b[1])
|
||||
}
|
||||
@@ -89,7 +89,7 @@ func parseInetAddr(b []byte, network string) (net.Addr, error) {
|
||||
}
|
||||
ip = make(net.IP, net.IPv6len)
|
||||
copy(ip, b[8:24])
|
||||
if id := int(NativeEndian.Uint32(b[24:28])); id > 0 {
|
||||
if id := int(binary.NativeEndian.Uint32(b[24:28])); id > 0 {
|
||||
zone = zoneCache.name(id)
|
||||
}
|
||||
}
|
||||
|
||||
+8
-10
@@ -9,8 +9,6 @@ import (
|
||||
"fmt"
|
||||
"net"
|
||||
"runtime"
|
||||
|
||||
"golang.org/x/net/internal/socket"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -68,12 +66,12 @@ func (h *Header) Marshal() ([]byte, error) {
|
||||
flagsAndFragOff := (h.FragOff & 0x1fff) | int(h.Flags<<13)
|
||||
switch runtime.GOOS {
|
||||
case "darwin", "ios", "dragonfly", "netbsd":
|
||||
socket.NativeEndian.PutUint16(b[2:4], uint16(h.TotalLen))
|
||||
socket.NativeEndian.PutUint16(b[6:8], uint16(flagsAndFragOff))
|
||||
binary.NativeEndian.PutUint16(b[2:4], uint16(h.TotalLen))
|
||||
binary.NativeEndian.PutUint16(b[6:8], uint16(flagsAndFragOff))
|
||||
case "freebsd":
|
||||
if freebsdVersion < 1100000 {
|
||||
socket.NativeEndian.PutUint16(b[2:4], uint16(h.TotalLen))
|
||||
socket.NativeEndian.PutUint16(b[6:8], uint16(flagsAndFragOff))
|
||||
binary.NativeEndian.PutUint16(b[2:4], uint16(h.TotalLen))
|
||||
binary.NativeEndian.PutUint16(b[6:8], uint16(flagsAndFragOff))
|
||||
} else {
|
||||
binary.BigEndian.PutUint16(b[2:4], uint16(h.TotalLen))
|
||||
binary.BigEndian.PutUint16(b[6:8], uint16(flagsAndFragOff))
|
||||
@@ -127,15 +125,15 @@ func (h *Header) Parse(b []byte) error {
|
||||
h.Dst = net.IPv4(b[16], b[17], b[18], b[19])
|
||||
switch runtime.GOOS {
|
||||
case "darwin", "ios", "dragonfly", "netbsd":
|
||||
h.TotalLen = int(socket.NativeEndian.Uint16(b[2:4])) + hdrlen
|
||||
h.FragOff = int(socket.NativeEndian.Uint16(b[6:8]))
|
||||
h.TotalLen = int(binary.NativeEndian.Uint16(b[2:4])) + hdrlen
|
||||
h.FragOff = int(binary.NativeEndian.Uint16(b[6:8]))
|
||||
case "freebsd":
|
||||
if freebsdVersion < 1100000 {
|
||||
h.TotalLen = int(socket.NativeEndian.Uint16(b[2:4]))
|
||||
h.TotalLen = int(binary.NativeEndian.Uint16(b[2:4]))
|
||||
if freebsdVersion < 1000000 {
|
||||
h.TotalLen += hdrlen
|
||||
}
|
||||
h.FragOff = int(socket.NativeEndian.Uint16(b[6:8]))
|
||||
h.FragOff = int(binary.NativeEndian.Uint16(b[6:8]))
|
||||
} else {
|
||||
h.TotalLen = int(binary.BigEndian.Uint16(b[2:4]))
|
||||
h.FragOff = int(binary.BigEndian.Uint16(b[6:8]))
|
||||
|
||||
+2
-1
@@ -7,6 +7,7 @@
|
||||
package ipv6
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/net/internal/iana"
|
||||
@@ -19,7 +20,7 @@ func marshal2292HopLimit(b []byte, cm *ControlMessage) []byte {
|
||||
m := socket.ControlMessage(b)
|
||||
m.MarshalHeader(iana.ProtocolIPv6, unix.IPV6_2292HOPLIMIT, 4)
|
||||
if cm != nil {
|
||||
socket.NativeEndian.PutUint32(m.Data(4), uint32(cm.HopLimit))
|
||||
binary.NativeEndian.PutUint32(m.Data(4), uint32(cm.HopLimit))
|
||||
}
|
||||
return m.Next(4)
|
||||
}
|
||||
|
||||
+5
-4
@@ -7,6 +7,7 @@
|
||||
package ipv6
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"net"
|
||||
"unsafe"
|
||||
|
||||
@@ -20,26 +21,26 @@ func marshalTrafficClass(b []byte, cm *ControlMessage) []byte {
|
||||
m := socket.ControlMessage(b)
|
||||
m.MarshalHeader(iana.ProtocolIPv6, unix.IPV6_TCLASS, 4)
|
||||
if cm != nil {
|
||||
socket.NativeEndian.PutUint32(m.Data(4), uint32(cm.TrafficClass))
|
||||
binary.NativeEndian.PutUint32(m.Data(4), uint32(cm.TrafficClass))
|
||||
}
|
||||
return m.Next(4)
|
||||
}
|
||||
|
||||
func parseTrafficClass(cm *ControlMessage, b []byte) {
|
||||
cm.TrafficClass = int(socket.NativeEndian.Uint32(b[:4]))
|
||||
cm.TrafficClass = int(binary.NativeEndian.Uint32(b[:4]))
|
||||
}
|
||||
|
||||
func marshalHopLimit(b []byte, cm *ControlMessage) []byte {
|
||||
m := socket.ControlMessage(b)
|
||||
m.MarshalHeader(iana.ProtocolIPv6, unix.IPV6_HOPLIMIT, 4)
|
||||
if cm != nil {
|
||||
socket.NativeEndian.PutUint32(m.Data(4), uint32(cm.HopLimit))
|
||||
binary.NativeEndian.PutUint32(m.Data(4), uint32(cm.HopLimit))
|
||||
}
|
||||
return m.Next(4)
|
||||
}
|
||||
|
||||
func parseHopLimit(cm *ControlMessage, b []byte) {
|
||||
cm.HopLimit = int(socket.NativeEndian.Uint32(b[:4]))
|
||||
cm.HopLimit = int(binary.NativeEndian.Uint32(b[:4]))
|
||||
}
|
||||
|
||||
func marshalPacketInfo(b []byte, cm *ControlMessage) []byte {
|
||||
|
||||
+1
-1
@@ -248,7 +248,7 @@ func parseKernelInetAddr(af int, b []byte) (int, Addr, error) {
|
||||
// doesn't mean 0.0.0.0/0 or ::/0
|
||||
//
|
||||
// - The kernel form appends leading bytes to the prefix field
|
||||
// to make the <length, prefix> tuple to be conformed with
|
||||
// to make the <length, prefix> tuple conform to
|
||||
// the routing message boundary
|
||||
l := int(b[0])
|
||||
if runtime.GOOS == "darwin" || runtime.GOOS == "ios" {
|
||||
|
||||
+1
-1
@@ -2,6 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build darwin && go1.12
|
||||
//go:build darwin
|
||||
|
||||
// This exists solely so we can linkname in symbols from syscall.
|
||||
Reference in new issue
Block a user